From afed5f3afc62431735b48a0ca6b5fb16ec598cf3 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 27 Jan 2016 11:30:12 +0100
Subject: [PATCH 001/273] Test code for the DFRN import

---
 include/import-dfrn.php | 376 ++++++++++++++++++++++++++++++++++++++++
 include/items.php       |   9 +
 2 files changed, 385 insertions(+)
 create mode 100644 include/import-dfrn.php

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
new file mode 100644
index 0000000000..7336946a7b
--- /dev/null
+++ b/include/import-dfrn.php
@@ -0,0 +1,376 @@
+<?php
+/*
+require_once("include/Contact.php");
+require_once("include/threads.php");
+require_once("include/html2bbcode.php");
+require_once("include/bbcode.php");
+require_once("include/items.php");
+require_once("mod/share.php");
+require_once("include/enotify.php");
+require_once("include/socgraph.php");
+require_once("include/Photo.php");
+require_once("include/Scrape.php");
+require_once("include/follow.php");
+require_once("include/api.php");
+require_once("mod/proxy.php");
+*/
+
+define("NS_ATOM", "http://www.w3.org/2005/Atom");
+define("NS_THR", "http://purl.org/syndication/thread/1.0");
+define("NS_GEORSS", "http://www.georss.org/georss");
+define("NS_ACTIVITY", "http://activitystrea.ms/spec/1.0/");
+define("NS_MEDIA", "http://purl.org/syndication/atommedia");
+define("NS_POCO", "http://portablecontacts.net/spec/1.0");
+define("NS_OSTATUS", "http://ostatus.org/schema/1.0");
+define("NS_STATUSNET", "http://status.net/schema/api/1/");
+
+class dfrn2 {
+	function fetchauthor($xpath, $context, $importer, $element, &$contact, $onlyfetch) {
+
+		$author = array();
+		$author["name"] = $xpath->evaluate($element.'/atom:name/text()', $context)->item(0)->nodeValue;
+		$author["link"] = $xpath->evaluate($element.'/atom:uri/text()', $context)->item(0)->nodeValue;
+
+		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'",
+			intval($importer["uid"]), dbesc(normalise_link($author["author-link"])),
+			dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET));
+		if ($r) {
+			$contact = $r[0];
+			$author["contact-id"] = $r[0]["id"];
+			$author["network"] = $r[0]["network"];
+		} else {
+			$author["contact-id"] = $contact["id"];
+			$author["network"] = $contact["network"];
+		}
+
+		// Until now we aren't serving different sizes - but maybe later
+		$avatarlist = array();
+		// @todo check if "avatar" or "photo" would be the best field in the specification
+		$avatars = $xpath->query($element."/atom:link[@rel='avatar']", $context);
+		foreach($avatars AS $avatar) {
+			$href = "";
+			$width = 0;
+			foreach($avatar->attributes AS $attributes) {
+				if ($attributes->name == "href")
+					$href = $attributes->textContent;
+				if ($attributes->name == "width")
+					$width = $attributes->textContent;
+			}
+			if (($width > 0) AND ($href != ""))
+				$avatarlist[$width] = $href;
+		}
+		if (count($avatarlist) > 0) {
+			krsort($avatarlist);
+			$author["avatar"] = current($avatarlist);
+		}
+
+		if ($r AND !$onlyfetch) {
+			// Update contact data
+
+			$value = $xpath->evaluate($element.'/poco:displayName/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["name"] = $value;
+
+			$value = $xpath->evaluate($element.'/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["nick"] = $value;
+
+			$value = $xpath->evaluate($element.'/poco:note/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["about"] = $value;
+
+			$value = $xpath->evaluate($element.'/poco:address/poco:formatted/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["location"] = $value;
+
+			/// @todo
+			/// poco:birthday
+			/// poco:utcOffset
+			/// poco:updated
+			/// poco:ims
+			/// poco:tags
+
+/*
+			if (($contact["name"] != $r[0]["name"]) OR ($contact["nick"] != $r[0]["nick"]) OR ($contact["about"] != $r[0]["about"]) OR ($contact["location"] != $r[0]["location"])) {
+
+				logger("Update contact data for contact ".$contact["id"], LOGGER_DEBUG);
+
+				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', `name-date` = '%s' WHERE `id` = %d AND `network` = '%s'",
+					dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
+					dbesc(datetime_convert()), intval($contact["id"]), dbesc(NETWORK_OSTATUS));
+
+			}
+
+			if (isset($author["author-avatar"]) AND ($author["author-avatar"] != $r[0]['photo'])) {
+				logger("Update profile picture for contact ".$contact["id"], LOGGER_DEBUG);
+
+				$photos = import_profile_photo($author["author-avatar"], $importer["uid"], $contact["id"]);
+
+				q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' WHERE `id` = %d AND `network` = '%s'",
+					dbesc($author["author-avatar"]), dbesc($photos[1]), dbesc($photos[2]),
+					dbesc(datetime_convert()), intval($contact["id"]), dbesc(NETWORK_OSTATUS));
+			}
+*/
+			/// @todo Add the "addr" field
+//			$contact["generation"] = 2;
+//			$contact["photo"] = $author["avatar"];
+//print_r($contact);
+			//update_gcontact($contact);
+		}
+
+		return($author);
+	}
+
+	function import($xml,$importer,&$contact, &$hub) {
+
+		$a = get_app();
+
+		logger("Import DFRN message", LOGGER_DEBUG);
+
+		if ($xml == "")
+			return;
+
+		$doc = new DOMDocument();
+		@$doc->loadXML($xml);
+
+		$xpath = new DomXPath($doc);
+		$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
+		$xpath->registerNamespace('thr', "http://purl.org/syndication/thread/1.0");
+		$xpath->registerNamespace('at', "http://purl.org/atompub/tombstones/1.0");
+		$xpath->registerNamespace('media', "http://purl.org/syndication/atommedia");
+		$xpath->registerNamespace('dfrn', "http://purl.org/macgirvin/dfrn/1.0");
+		$xpath->registerNamespace('activity', "http://activitystrea.ms/spec/1.0/");
+		$xpath->registerNamespace('georss', "http://www.georss.org/georss");
+		$xpath->registerNamespace('poco', "http://portablecontacts.net/spec/1.0");
+		$xpath->registerNamespace('ostatus', "http://ostatus.org/schema/1.0");
+		$xpath->registerNamespace('statusnet', "http://status.net/schema/api/1/");
+
+		$header = array();
+		$header["uid"] = $importer["uid"];
+		$header["network"] = NETWORK_DFRN;
+		$header["type"] = "remote";
+		$header["wall"] = 0;
+		$header["origin"] = 0;
+		$header["gravity"] = GRAVITY_PARENT;
+		$header["contact-id"] = $importer["id"];
+
+		// Update the contact table if the data has changed
+		// Only the "dfrn:owner" in the head section contains all data
+		self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", $contact, false);
+
+		$entries = $xpath->query('/atom:feed/atom:entry');
+
+		$item_id = 0;
+
+		// Reverse the order of the entries
+		$entrylist = array();
+
+		foreach ($entries AS $entry)
+			$entrylist[] = $entry;
+
+		foreach (array_reverse($entrylist) AS $entry) {
+
+			$item = $header;
+
+			$mention = false;
+
+			// Fetch the owner
+			$owner = self::fetchauthor($xpath, $entry, $importer, "dfrn:owner", $contact, true);
+
+			$item["owner-name"] = $owner["name"];
+			$item["owner-link"] = $owner["link"];
+			$item["owner-avatar"] = $owner["avatar"];
+
+			if ($header["contact-id"] != $owner["contact-id"])
+				$item["contact-id"] = $owner["contact-id"];
+
+			if (($header["network"] != $owner["network"]) AND ($owner["network"] != ""))
+				$item["network"] = $owner["network"];
+
+			// fetch the author
+			$author = self::fetchauthor($xpath, $entry, $importer, "atom:author", $contact, true);
+
+			$item["author-name"] = $author["name"];
+			$item["author-link"] = $author["link"];
+			$item["author-avatar"] = $author["avatar"];
+
+			if ($header["contact-id"] != $author["contact-id"])
+				$item["contact-id"] = $author["contact-id"];
+
+			if (($header["network"] != $author["network"]) AND ($author["network"] != ""))
+				$item["network"] = $author["network"];
+
+			// Now get the item
+			$item["uri"] = $xpath->query('atom:id/text()', $entry)->item(0)->nodeValue;
+
+			$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
+				intval($importer["uid"]), dbesc($item["uri"]));
+			if ($r) {
+				//logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
+				//continue;
+			}
+
+			// Is it a reply?
+			$inreplyto = $xpath->query('thr:in-reply-to', $entry);
+			if (is_object($inreplyto->item(0))) {
+				$objecttype = ACTIVITY_OBJ_COMMENT;
+				$item["type"] = 'remote-comment';
+				$item["gravity"] = GRAVITY_COMMENT;
+
+				foreach($inreplyto->item(0)->attributes AS $attributes) {
+					if ($attributes->name == "ref")
+						$item["parent-uri"] = $attributes->textContent;
+				}
+			} else {
+				$objecttype = ACTIVITY_OBJ_NOTE;
+				$item["parent-uri"] = $item["uri"];
+			}
+
+			$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
+
+			$item["created"] = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
+			$item["edited"] = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue;
+
+			$item["body"] = $xpath->query('dfrn:env/text()', $entry)->item(0)->nodeValue;
+			$item["body"] = str_replace(array(' ',"\t","\r","\n"), array('','','',''),$item["body"]);
+			// make sure nobody is trying to sneak some html tags by us
+			$item["body"] = notags(base64url_decode($item["body"]));
+
+			$item["body"] = limit_body_size($item["body"]);
+
+			/// @todo Do we need the old check for HTML elements?
+
+			// We don't need the content element since "dfrn:env" is always present
+			//$item["body"] = $xpath->query('atom:content/text()', $entry)->item(0)->nodeValue;
+
+			$item["last-child"] = $xpath->query('dfrn:comment-allow/text()', $entry)->item(0)->nodeValue;
+			$item["location"] = $xpath->query('dfrn:location/text()', $entry)->item(0)->nodeValue;
+
+			$georsspoint = $xpath->query('georss:point', $entry);
+			if ($georsspoint)
+				$item["coord"] = $georsspoint->item(0)->nodeValue;
+
+			$item["private"] = $xpath->query('dfrn:private/text()', $entry)->item(0)->nodeValue;
+
+			$item["extid"] = $xpath->query('dfrn:extid/text()', $entry)->item(0)->nodeValue;
+
+			if ($xpath->query('dfrn:extid/text()', $entry)->item(0)->nodeValue == "true")
+				$item["bookmark"] = true;
+
+			$notice_info = $xpath->query('statusnet:notice_info', $entry);
+			if ($notice_info AND ($notice_info->length > 0)) {
+				foreach($notice_info->item(0)->attributes AS $attributes) {
+					if ($attributes->name == "source")
+						$item["app"] = strip_tags($attributes->textContent);
+				}
+			}
+
+			$item["guid"] = $xpath->query('dfrn:diaspora_guid/text()', $entry)->item(0)->nodeValue;
+
+			// dfrn:diaspora_signature
+
+			$item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue;
+
+			if ($xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue != "")
+				$objecttype = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue;
+
+			$item["object-type"] = $objecttype;
+
+			// activity:object
+
+			// activity:target
+
+			$categories = $xpath->query('atom:category', $entry);
+			if ($categories) {
+				foreach ($categories AS $category) {
+					foreach($category->attributes AS $attributes)
+						if ($attributes->name == "term") {
+							$term = $attributes->textContent;
+							if(strlen($item["tag"]))
+							$item["tag"] .= ',';
+							$item["tag"] .= "#[url=".$a->get_baseurl()."/search?tag=".$term."]".$term."[/url]";
+						}
+				}
+			}
+
+			$enclosure = "";
+
+			$links = $xpath->query('atom:link', $entry);
+			if ($links) {
+				$rel = "";
+				$href = "";
+				$type = "";
+				$length = "0";
+				$title = "";
+				foreach ($links AS $link) {
+					foreach($link->attributes AS $attributes) {
+						if ($attributes->name == "href")
+							$href = $attributes->textContent;
+						if ($attributes->name == "rel")
+							$rel = $attributes->textContent;
+						if ($attributes->name == "type")
+							$type = $attributes->textContent;
+						if ($attributes->name == "length")
+							$length = $attributes->textContent;
+						if ($attributes->name == "title")
+							$title = $attributes->textContent;
+					}
+					if (($rel != "") AND ($href != ""))
+						switch($rel) {
+							case "alternate":
+								$item["plink"] = $href;
+								break;
+							case "enclosure":
+								$enclosure = $href;
+								if(strlen($item["attach"]))
+									$item["attach"] .= ',';
+
+								$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
+								break;
+							case "mentioned":
+								// Notification check
+								if ($importer["nurl"] == normalise_link($href))
+									$mention = true;
+								break;
+						}
+				}
+			}
+
+			print_r($item);
+/*
+			if (!$item_id) {
+				logger("Error storing item", LOGGER_DEBUG);
+				continue;
+			}
+
+			logger("Item was stored with id ".$item_id, LOGGER_DEBUG);
+			$item["id"] = $item_id;
+*/
+
+/*
+			if ($mention) {
+				$u = q("SELECT `notify-flags`, `language`, `username`, `email` FROM user WHERE uid = %d LIMIT 1", intval($item['uid']));
+				$r = q("SELECT `parent` FROM `item` WHERE `id` = %d", intval($item_id));
+
+				notification(array(
+					'type'         => NOTIFY_TAGSELF,
+					'notify_flags' => $u[0]["notify-flags"],
+					'language'     => $u[0]["language"],
+					'to_name'      => $u[0]["username"],
+					'to_email'     => $u[0]["email"],
+					'uid'          => $item["uid"],
+					'item'         => $item,
+					'link'         => $a->get_baseurl().'/display/'.urlencode(get_item_guid($item_id)),
+					'source_name'  => $item["author-name"],
+					'source_link'  => $item["author-link"],
+					'source_photo' => $item["author-avatar"],
+					'verb'         => ACTIVITY_TAG,
+					'otype'        => 'item',
+					'parent'       => $r[0]["parent"]
+				));
+			}
+*/
+		}
+	}
+}
+?>
diff --git a/include/items.php b/include/items.php
index cf044d8837..f52d46b7e2 100644
--- a/include/items.php
+++ b/include/items.php
@@ -1766,6 +1766,12 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
 		return;
 	}
 
+	// Test - remove before flight
+	//if ($pass < 2) {
+	//	$tempfile = tempnam(get_temppath(), "dfrn-consume-");
+	//	file_put_contents($tempfile, $xml);
+	//}
+
 	require_once('library/simplepie/simplepie.inc');
 	require_once('include/contact_selectors.php');
 
@@ -2471,6 +2477,9 @@ function local_delivery($importer,$data) {
 
 	logger(__function__, LOGGER_TRACE);
 
+	//$tempfile = tempnam(get_temppath(), "dfrn-local-");
+	//file_put_contents($tempfile, $data);
+
 	if($importer['readonly']) {
 		// We aren't receiving stuff from this person. But we will quietly ignore them
 		// rather than a blatant "go away" message.

From 1d4de969603906646de7a0015346f6fdadd39a89 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 27 Jan 2016 15:57:11 +0100
Subject: [PATCH 002/273] Next steps to add all fields

---
 include/dfrn.php        |  12 +++-
 include/import-dfrn.php | 125 +++++++++++++++++++++++++++++++++++-----
 2 files changed, 121 insertions(+), 16 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index 2c8e8ce38f..883afe15f7 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -396,7 +396,6 @@ class dfrn {
 		$root->setAttribute("xmlns:ostatus", NS_OSTATUS);
 		$root->setAttribute("xmlns:statusnet", NS_STATUSNET);
 
-		//xml_add_element($doc, $root, "id", app::get_baseurl()."/profile/".$owner["nick"]);
 		xml_add_element($doc, $root, "id", app::get_baseurl()."/profile/".$owner["nick"]);
 		xml_add_element($doc, $root, "title", $owner["name"]);
 
@@ -409,9 +408,11 @@ class dfrn {
 		$attributes = array("rel" => "alternate", "type" => "text/html", "href" => $alternatelink);
 		xml_add_element($doc, $root, "link", "", $attributes);
 
-		ostatus_hublinks($doc, $root);
 
 		if ($public) {
+			// DFRN itself doesn't uses this. But maybe someone else wants to subscribe to the public feed.
+			ostatus_hublinks($doc, $root);
+
 			$attributes = array("rel" => "salmon", "href" => app::get_baseurl()."/salmon/".$owner["nick"]);
 			xml_add_element($doc, $root, "link", "", $attributes);
 
@@ -425,6 +426,8 @@ class dfrn {
 		if ($owner['page-flags'] == PAGE_COMMUNITY)
 			xml_add_element($doc, $root, "dfrn:community", 1);
 
+		/// @todo We need a way to transmit the different page flags like "PAGE_PRVGROUP"
+
 		xml_add_element($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME));
 
 		$author = self::add_author($doc, $owner, $authorelement, $public);
@@ -727,9 +730,14 @@ class dfrn {
 		xml_add_element($doc, $entry, "published", datetime_convert("UTC","UTC",$item["created"]."+00:00",ATOM_TIME));
 		xml_add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME));
 
+		// "dfrn:env" is used to read the content
 		xml_add_element($doc, $entry, "dfrn:env", base64url_encode($body, true));
+
+		// The "content" field is not read by the receiver. We could remove it when the type is "text"
+		// We keep it at the moment, maybe there is some old version that doesn't read "dfrn:env"
 		xml_add_element($doc, $entry, "content", (($type === 'html') ? $htmlbody : $body), array("type" => $type));
 
+		// We save this value in "plink". Maybe we should read it from there as well?
 		xml_add_element($doc, $entry, "link", "", array("rel" => "alternate", "type" => "text/html",
 								"href" => app::get_baseurl()."/display/".$item["guid"]));
 
diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index 7336946a7b..5a35829263 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -25,7 +25,48 @@ define("NS_OSTATUS", "http://ostatus.org/schema/1.0");
 define("NS_STATUSNET", "http://status.net/schema/api/1/");
 
 class dfrn2 {
-	function fetchauthor($xpath, $context, $importer, $element, &$contact, $onlyfetch) {
+        /**
+         * @brief Add new birthday event for this person
+         *
+         * @param array $contact Contact record
+         * @param string $birthday Birthday of the contact
+         *
+         */
+	private function birthday_event($contact, $birthday) {
+
+		logger('updating birthday: '.$birthday.' for contact '.$contact['id']);
+
+		$bdtext = sprintf(t('%s\'s birthday'), $contact['name']);
+		$bdtext2 = sprintf(t('Happy Birthday %s'), ' [url=' . $contact['url'].']'.$contact['name'].'[/url]' ) ;
+
+
+		$r = q("INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`summary`,`desc`,`type`)
+			VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
+			intval($contact['uid']),
+			intval($contact['id']),
+			dbesc(datetime_convert()),
+			dbesc(datetime_convert()),
+			dbesc(datetime_convert('UTC','UTC', $birthday)),
+			dbesc(datetime_convert('UTC','UTC', $birthday.' + 1 day ')),
+			dbesc($bdtext),
+			dbesc($bdtext2),
+			dbesc('birthday')
+		);
+	}
+
+        /**
+         * @brief Fetch the author data from head or entry items
+         *
+         * @param object $xpath XPath object
+         * @param object $context In which context should the data be searched
+         * @param array $importer Record of the importer contact
+         * @param string $element Element name from which the data is fetched
+         * @param array $contact The updated contact record of the author
+         * @param bool $onlyfetch Should the data only be fetched or should it update the contact record as well
+         *
+	 * @return Returns an array with relevant data of the author
+         */
+	private function fetchauthor($xpath, $context, $importer, $element, &$contact, $onlyfetch) {
 
 		$author = array();
 		$author["name"] = $xpath->evaluate($element.'/atom:name/text()', $context)->item(0)->nodeValue;
@@ -55,6 +96,8 @@ class dfrn2 {
 					$href = $attributes->textContent;
 				if ($attributes->name == "width")
 					$width = $attributes->textContent;
+				if ($attributes->name == "updated")
+					$contact["avatar-date"] = $attributes->textContent;
 			}
 			if (($width > 0) AND ($href != ""))
 				$avatarlist[$width] = $href;
@@ -65,7 +108,26 @@ class dfrn2 {
 		}
 
 		if ($r AND !$onlyfetch) {
+
+			// When was the last change to name or uri?
+			$name_element = $xpath->query($element."/atom:name", $context)->item(0);
+			foreach($name_element->attributes AS $attributes)
+				if ($attributes->name == "updated")
+					$contact["name-date"] = $attributes->textContent;
+
+
+			$link_element = $xpath->query($element."/atom:link", $context)->item(0);
+			foreach($link_element->attributes AS $attributes)
+				if ($attributes->name == "updated")
+					$contact["uri-date"] = $attributes->textContent;
+
+			// is it a public forum? Private forums aren't supported by now with this method
+			$contact["forum"] = intval($xpath->evaluate($element.'/dfrn:community/text()', $context)->item(0)->nodeValue);
+
 			// Update contact data
+			$value = $xpath->evaluate($element.'/dfrn:handle/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["addr"] = $value;
 
 			$value = $xpath->evaluate($element.'/poco:displayName/text()', $context)->item(0)->nodeValue;
 			if ($value != "")
@@ -83,13 +145,54 @@ class dfrn2 {
 			if ($value != "")
 				$contact["location"] = $value;
 
-			/// @todo
-			/// poco:birthday
-			/// poco:utcOffset
-			/// poco:updated
-			/// poco:ims
-			/// poco:tags
+			/// @todo Add support for the following fields that we don't support by now in the contact table:
+			/// - poco:utcOffset
+			/// - poco:ims
+			/// - poco:urls
+			/// - poco:locality
+			/// - poco:region
+			/// - poco:country
 
+			// Save the keywords into the contact table
+			$tags = array();
+			$tagelements = $xpath->evaluate($element.'/poco:tags/text()', $context);
+			foreach($tagelements AS $tag)
+				$tags[$tag->nodeValue] = $tag->nodeValue;
+
+			if (count($tags))
+				$contact["keywords"] = implode(", ", $tags);
+
+			// "dfrn:birthday" contains the birthday converted to UTC
+			$old_bdyear = $contact["bdyear"];
+
+			$birthday = $xpath->evaluate($element.'/dfrn:birthday/text()', $context)->item(0)->nodeValue;
+
+			if (strtotime($birthday) > time()) {
+				$bd_timestamp = strtotime($birthday);
+
+				$contact["bdyear"] = date("Y", $bd_timestamp);
+			}
+
+			// "poco:birthday" is the birthday in the format "yyyy-mm-dd"
+			$value = $xpath->evaluate($element.'/poco:birthday/text()', $context)->item(0)->nodeValue;
+
+			if (!in_array($value, array("", "0000-00-00"))) {
+				$bdyear = date("Y");
+				$value = str_replace("0000", $bdyear, $value);
+
+				if (strtotime($value) < time()) {
+					$value = str_replace($bdyear, $bdyear + 1, $value);
+					$bdyear = $bdyear + 1;
+				}
+
+				$contact["bd"] = $value;
+			}
+
+			if ($old_bdyear != $contact["bdyear"])
+				self::birthday_event($contact, $birthday;
+
+print_r($contact);
+die();
 /*
 			if (($contact["name"] != $r[0]["name"]) OR ($contact["nick"] != $r[0]["nick"]) OR ($contact["about"] != $r[0]["about"]) OR ($contact["location"] != $r[0]["location"])) {
 
@@ -162,13 +265,7 @@ class dfrn2 {
 
 		$item_id = 0;
 
-		// Reverse the order of the entries
-		$entrylist = array();
-
-		foreach ($entries AS $entry)
-			$entrylist[] = $entry;
-
-		foreach (array_reverse($entrylist) AS $entry) {
+		foreach ($entries AS $entry) {
 
 			$item = $header;
 

From 613f6b9b32e5c8370bb236caba03a82c09625239 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 27 Jan 2016 20:06:23 +0100
Subject: [PATCH 003/273] Just some more code :-)

---
 include/import-dfrn.php | 97 +++++++++++++++++++++++------------------
 1 file changed, 55 insertions(+), 42 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index 5a35829263..b3a8dbaf86 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -25,13 +25,13 @@ define("NS_OSTATUS", "http://ostatus.org/schema/1.0");
 define("NS_STATUSNET", "http://status.net/schema/api/1/");
 
 class dfrn2 {
-        /**
-         * @brief Add new birthday event for this person
-         *
-         * @param array $contact Contact record
-         * @param string $birthday Birthday of the contact
-         *
-         */
+	/**
+	 * @brief Add new birthday event for this person
+	 *
+	 * @param array $contact Contact record
+	 * @param string $birthday Birthday of the contact
+	 *
+	 */
 	private function birthday_event($contact, $birthday) {
 
 		logger('updating birthday: '.$birthday.' for contact '.$contact['id']);
@@ -54,25 +54,27 @@ class dfrn2 {
 		);
 	}
 
-        /**
-         * @brief Fetch the author data from head or entry items
-         *
-         * @param object $xpath XPath object
-         * @param object $context In which context should the data be searched
-         * @param array $importer Record of the importer contact
-         * @param string $element Element name from which the data is fetched
-         * @param array $contact The updated contact record of the author
-         * @param bool $onlyfetch Should the data only be fetched or should it update the contact record as well
-         *
+	/**
+	 * @brief Fetch the author data from head or entry items
+	 *
+	 * @param object $xpath XPath object
+	 * @param object $context In which context should the data be searched
+	 * @param array $importer Record of the importer contact
+	 * @param string $element Element name from which the data is fetched
+	 * @param array $contact The updated contact record of the author
+	 * @param bool $onlyfetch Should the data only be fetched or should it update the contact record as well
+	 *
 	 * @return Returns an array with relevant data of the author
-         */
+	 */
 	private function fetchauthor($xpath, $context, $importer, $element, &$contact, $onlyfetch) {
 
 		$author = array();
 		$author["name"] = $xpath->evaluate($element.'/atom:name/text()', $context)->item(0)->nodeValue;
 		$author["link"] = $xpath->evaluate($element.'/atom:uri/text()', $context)->item(0)->nodeValue;
 
-		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'",
+		$r = q("SELECT `id`, `uid`, `network`, `avatar-date`, `name-date`, `uri-date`, `addr`,
+				`name`, `nick`, `about`, `location`, `keywords`, `bdyear`, `bd`
+				FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'",
 			intval($importer["uid"]), dbesc(normalise_link($author["author-link"])),
 			dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET));
 		if ($r) {
@@ -115,15 +117,11 @@ class dfrn2 {
 				if ($attributes->name == "updated")
 					$contact["name-date"] = $attributes->textContent;
 
-
 			$link_element = $xpath->query($element."/atom:link", $context)->item(0);
 			foreach($link_element->attributes AS $attributes)
 				if ($attributes->name == "updated")
 					$contact["uri-date"] = $attributes->textContent;
 
-			// is it a public forum? Private forums aren't supported by now with this method
-			$contact["forum"] = intval($xpath->evaluate($element.'/dfrn:community/text()', $context)->item(0)->nodeValue);
-
 			// Update contact data
 			$value = $xpath->evaluate($element.'/dfrn:handle/text()', $context)->item(0)->nodeValue;
 			if ($value != "")
@@ -188,37 +186,49 @@ class dfrn2 {
 				$contact["bd"] = $value;
 			}
 
-			if ($old_bdyear != $contact["bdyear"])
-				self::birthday_event($contact, $birthday;
+			//if ($old_bdyear != $contact["bdyear"])
+			//	self::birthday_event($contact, $birthday);
 
-print_r($contact);
-die();
-/*
-			if (($contact["name"] != $r[0]["name"]) OR ($contact["nick"] != $r[0]["nick"]) OR ($contact["about"] != $r[0]["about"]) OR ($contact["location"] != $r[0]["location"])) {
+			// Get all field names
+			$fields = array();
+			foreach ($r[0] AS $field => $data)
+				$fields[$field] = $data;
 
+			unset($fields["id"]);
+			unset($fields["uid"]);
+
+			foreach ($fields AS $field => $data)
+				if ($contact[$field] != $r[0][$field])
+					$update = true;
+
+			if ($update) {
 				logger("Update contact data for contact ".$contact["id"], LOGGER_DEBUG);
 
-				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', `name-date` = '%s' WHERE `id` = %d AND `network` = '%s'",
+				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s',
+					`addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s'
+					`avatar-date`  = '%s', `name-date`  = '%s', `uri-date` = '%s'
+					WHERE `id` = %d AND `network` = '%s'",
 					dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
-					dbesc(datetime_convert()), intval($contact["id"]), dbesc(NETWORK_OSTATUS));
-
+					dbesc($contact["addr"]), dbesc($contact["keywords"]), dbesc($contact["bdyear"]),
+					dbesc($contact["bd"]), dbesc($contact["avatar-date"]), dbesc($contact["name-date"]), dbesc($contact["uri-date"]),
+					intval($contact["id"]), dbesc($contact["network"]));
 			}
 
-			if (isset($author["author-avatar"]) AND ($author["author-avatar"] != $r[0]['photo'])) {
+			if ((isset($author["avatar"]) AND ($author["avatar"] != $r[0]["photo"])) OR
+				($contact["avatar-date"] != $r[0]["avatar-date"])) {
 				logger("Update profile picture for contact ".$contact["id"], LOGGER_DEBUG);
 
-				$photos = import_profile_photo($author["author-avatar"], $importer["uid"], $contact["id"]);
+				$photos = import_profile_photo($author["avatar"], $importer["uid"], $contact["id"]);
 
 				q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' WHERE `id` = %d AND `network` = '%s'",
-					dbesc($author["author-avatar"]), dbesc($photos[1]), dbesc($photos[2]),
-					dbesc(datetime_convert()), intval($contact["id"]), dbesc(NETWORK_OSTATUS));
+					dbesc($author["avatar"]), dbesc($photos[1]), dbesc($photos[2]),
+					dbesc($contact["avatar-date"]), intval($contact["id"]), dbesc($contact["network"]));
 			}
-*/
-			/// @todo Add the "addr" field
-//			$contact["generation"] = 2;
-//			$contact["photo"] = $author["avatar"];
-//print_r($contact);
-			//update_gcontact($contact);
+
+			$contact["generation"] = 2;
+			$contact["photo"] = $author["avatar"];
+			print_r($contact);
+			update_gcontact($contact);
 		}
 
 		return($author);
@@ -261,6 +271,9 @@ die();
 		// Only the "dfrn:owner" in the head section contains all data
 		self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", $contact, false);
 
+		// is it a public forum? Private forums aren't supported by now with this method
+		//$contact["forum"] = intval($xpath->evaluate($element.'/dfrn:community/text()', $context)->item(0)->nodeValue);
+
 		$entries = $xpath->query('/atom:feed/atom:entry');
 
 		$item_id = 0;

From 1cdcb9fc2e9abc97167a6b004d773172e4166eb7 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 29 Jan 2016 17:42:38 +0100
Subject: [PATCH 004/273] DFRN: Entry import could work now, first steps for
 mails

---
 include/Photo.php       |   5 +-
 include/import-dfrn.php | 533 +++++++++++++++++++++++-----------------
 2 files changed, 315 insertions(+), 223 deletions(-)

diff --git a/include/Photo.php b/include/Photo.php
index 3f1608d3ec..91fce55a86 100644
--- a/include/Photo.php
+++ b/include/Photo.php
@@ -726,10 +726,11 @@ function guess_image_type($filename, $fromcurl=false) {
  * @param string $avatar Link to avatar picture
  * @param int $uid User id of contact owner
  * @param int $cid Contact id
+ * @param bool $force force picture update
  *
  * @return array Returns array of the different avatar sizes
  */
-function update_contact_avatar($avatar,$uid,$cid) {
+function update_contact_avatar($avatar,$uid,$cid, $force = false) {
 
 	$r = q("SELECT `avatar`, `photo`, `thumb`, `micro` FROM `contact` WHERE `id` = %d LIMIT 1", intval($cid));
 	if (!$r)
@@ -737,7 +738,7 @@ function update_contact_avatar($avatar,$uid,$cid) {
 	else
 		$data = array($r[0]["photo"], $r[0]["thumb"], $r[0]["micro"]);
 
-	if ($r[0]["avatar"] != $avatar) {
+	if (($r[0]["avatar"] != $avatar) OR $force) {
 		$photos = import_profile_photo($avatar,$uid,$cid, true);
 
 		if ($photos) {
diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index b3a8dbaf86..c934380357 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -109,6 +109,8 @@ class dfrn2 {
 			$author["avatar"] = current($avatarlist);
 		}
 
+$onlyfetch = true; // Test
+
 		if ($r AND !$onlyfetch) {
 
 			// When was the last change to name or uri?
@@ -186,8 +188,8 @@ class dfrn2 {
 				$contact["bd"] = $value;
 			}
 
-			//if ($old_bdyear != $contact["bdyear"])
-			//	self::birthday_event($contact, $birthday);
+			if ($old_bdyear != $contact["bdyear"])
+				self::birthday_event($contact, $birthday);
 
 			// Get all field names
 			$fields = array();
@@ -214,26 +216,301 @@ class dfrn2 {
 					intval($contact["id"]), dbesc($contact["network"]));
 			}
 
-			if ((isset($author["avatar"]) AND ($author["avatar"] != $r[0]["photo"])) OR
-				($contact["avatar-date"] != $r[0]["avatar-date"])) {
-				logger("Update profile picture for contact ".$contact["id"], LOGGER_DEBUG);
-
-				$photos = import_profile_photo($author["avatar"], $importer["uid"], $contact["id"]);
-
-				q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' WHERE `id` = %d AND `network` = '%s'",
-					dbesc($author["avatar"]), dbesc($photos[1]), dbesc($photos[2]),
-					dbesc($contact["avatar-date"]), intval($contact["id"]), dbesc($contact["network"]));
-			}
+			update_contact_avatar($author["avatar"], $importer["uid"], $contact["id"], ($contact["avatar-date"] != $r[0]["avatar-date"]));
 
 			$contact["generation"] = 2;
 			$contact["photo"] = $author["avatar"];
-			print_r($contact);
 			update_gcontact($contact);
 		}
 
 		return($author);
 	}
 
+	private function transform_activity($xpath, $activity, $element) {
+		if (!is_object($activity))
+			return "";
+
+		$obj_doc = new DOMDocument('1.0', 'utf-8');
+		$obj_doc->formatOutput = true;
+
+		$obj_element = $obj_doc->createElementNS(NS_ATOM, $element);
+
+		$activity_type = $xpath->query('activity:object-type/text()', $activity)->item(0)->nodeValue;
+		xml_add_element($obj_doc, $obj_element, "type", $activity_type);
+
+		$id = $xpath->query('atom:id', $activity)->item(0);
+		if (is_object($id))
+			$obj_element->appendChild($obj_doc->importNode($id, true));
+
+		$title = $xpath->query('atom:title', $activity)->item(0);
+		if (is_object($title))
+			$obj_element->appendChild($obj_doc->importNode($title, true));
+
+		$link = $xpath->query('atom:link', $activity)->item(0);
+		if (is_object($link))
+			$obj_element->appendChild($obj_doc->importNode($link, true));
+
+		$content = $xpath->query('atom:content', $activity)->item(0);
+		if (is_object($content))
+			$obj_element->appendChild($obj_doc->importNode($content, true));
+
+		$obj_doc->appendChild($obj_element);
+
+		$objxml = $obj_doc->saveXML($obj_element);
+
+		// @todo This isn't totally clean. We should find a way to transform the namespaces
+		$objxml = str_replace('<'.$element.' xmlns="http://www.w3.org/2005/Atom">', "<".$element.">", $objxml);
+		return($objxml);
+	}
+
+	private function process_mail($header, $xpath, $mail, $importer, $contact) {
+
+		$msg = array();
+		$msg["uid"] = $importer['importer_uid'];
+		$msg["from-name"] = $xpath->query('dfrn:sender/dfrn:name/text()', $mail)->item(0)->nodeValue;
+		$msg["from-url"] = $xpath->query('dfrn:sender/dfrn:uri/text()', $mail)->item(0)->nodeValue;
+		$msg["from-photo"] = $xpath->query('dfrn:sender/dfrn:avatar/text()', $mail)->item(0)->nodeValue;
+                $msg["contact-id"] = $importer["id"];
+		$msg["uri"] = $xpath->query('dfrn:id/text()', $mail)->item(0)->nodeValue;
+		$msg["parent-uri"] = $xpath->query('dfrn:in-reply-to/text()', $mail)->item(0)->nodeValue;
+		$msg["created"] = $xpath->query('dfrn:sentdate/text()', $mail)->item(0)->nodeValue;
+		$msg["title"] = $xpath->query('dfrn:subject/text()', $mail)->item(0)->nodeValue;
+		$msg["body"] = $xpath->query('dfrn:content/text()', $mail)->item(0)->nodeValue;
+                $msg["seen"] = 0;
+                $msg["replied"] = 0;
+
+		dbesc_array($msg);
+
+                //$r = dbq("INSERT INTO `mail` (`" . implode("`, `", array_keys($msg))
+                //        . "`) VALUES ('" . implode("', '", array_values($msg)) . "')" );
+
+print_r($msg);
+
+                // send notifications.
+
+                require_once('include/enotify.php');
+
+                $notif_params = array(
+                        'type' => NOTIFY_MAIL,
+                        'notify_flags' => $importer['notify-flags'],
+                        'language' => $importer['language'],
+                        'to_name' => $importer['username'],
+                        'to_email' => $importer['email'],
+                        'uid' => $importer['importer_uid'],
+                        'item' => $msg,
+                        'source_name' => $msg['from-name'],
+                        'source_link' => $importer['url'],
+                        'source_photo' => $importer['thumb'],
+                        'verb' => ACTIVITY_POST,
+                        'otype' => 'mail'
+                );
+
+//                notification($notif_params);
+print_r($notif_params);
+
+	}
+
+	private function process_suggestion($header, $xpath, $suggestion, $importer, $contact) {
+	}
+
+	private function process_relocation($header, $xpath, $relocation, $importer, $contact) {
+	}
+
+	private function process_entry($header, $xpath, $entry, $importer, $contact) {
+		$item = $header;
+
+		// Fetch the owner
+		$owner = self::fetchauthor($xpath, $entry, $importer, "dfrn:owner", $contact, true);
+
+		$item["owner-name"] = $owner["name"];
+		$item["owner-link"] = $owner["link"];
+		$item["owner-avatar"] = $owner["avatar"];
+
+		if ($header["contact-id"] != $owner["contact-id"])
+			$item["contact-id"] = $owner["contact-id"];
+
+		if (($header["network"] != $owner["network"]) AND ($owner["network"] != ""))
+			$item["network"] = $owner["network"];
+
+		// fetch the author
+		$author = self::fetchauthor($xpath, $entry, $importer, "atom:author", $contact, true);
+
+		$item["author-name"] = $author["name"];
+		$item["author-link"] = $author["link"];
+		$item["author-avatar"] = $author["avatar"];
+
+		if ($header["contact-id"] != $author["contact-id"])
+			$item["contact-id"] = $author["contact-id"];
+
+		if (($header["network"] != $author["network"]) AND ($author["network"] != ""))
+			$item["network"] = $author["network"];
+
+		// Now get the item
+		$item["uri"] = $xpath->query('atom:id/text()', $entry)->item(0)->nodeValue;
+
+		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
+			intval($importer["uid"]), dbesc($item["uri"]));
+		if ($r) {
+			//logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
+			//return false;
+		}
+
+		// Is it a reply?
+		$inreplyto = $xpath->query('thr:in-reply-to', $entry);
+		if (is_object($inreplyto->item(0))) {
+			$objecttype = ACTIVITY_OBJ_COMMENT;
+			$item["type"] = 'remote-comment';
+			$item["gravity"] = GRAVITY_COMMENT;
+
+			foreach($inreplyto->item(0)->attributes AS $attributes) {
+				if ($attributes->name == "ref")
+					$item["parent-uri"] = $attributes->textContent;
+			}
+		} else {
+			$objecttype = ACTIVITY_OBJ_NOTE;
+			$item["parent-uri"] = $item["uri"];
+		}
+
+		$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
+
+		$item["created"] = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
+		$item["edited"] = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue;
+
+		$item["body"] = $xpath->query('dfrn:env/text()', $entry)->item(0)->nodeValue;
+		$item["body"] = str_replace(array(' ',"\t","\r","\n"), array('','','',''),$item["body"]);
+		// make sure nobody is trying to sneak some html tags by us
+		$item["body"] = notags(base64url_decode($item["body"]));
+
+		$item["body"] = limit_body_size($item["body"]);
+
+		/// @todo Do we need the old check for HTML elements?
+
+		// We don't need the content element since "dfrn:env" is always present
+		//$item["body"] = $xpath->query('atom:content/text()', $entry)->item(0)->nodeValue;
+
+		$item["last-child"] = $xpath->query('dfrn:comment-allow/text()', $entry)->item(0)->nodeValue;
+		$item["location"] = $xpath->query('dfrn:location/text()', $entry)->item(0)->nodeValue;
+
+		$georsspoint = $xpath->query('georss:point', $entry);
+		if ($georsspoint)
+			$item["coord"] = $georsspoint->item(0)->nodeValue;
+
+		$item["private"] = $xpath->query('dfrn:private/text()', $entry)->item(0)->nodeValue;
+
+		$item["extid"] = $xpath->query('dfrn:extid/text()', $entry)->item(0)->nodeValue;
+
+		if ($xpath->query('dfrn:extid/text()', $entry)->item(0)->nodeValue == "true")
+			$item["bookmark"] = true;
+
+		$notice_info = $xpath->query('statusnet:notice_info', $entry);
+		if ($notice_info AND ($notice_info->length > 0)) {
+			foreach($notice_info->item(0)->attributes AS $attributes) {
+				if ($attributes->name == "source")
+					$item["app"] = strip_tags($attributes->textContent);
+			}
+		}
+
+		$item["guid"] = $xpath->query('dfrn:diaspora_guid/text()', $entry)->item(0)->nodeValue;
+
+		// We store the data from "dfrn:diaspora_signature" in a later step. See some lines below
+		$signature = $xpath->query('dfrn:diaspora_signature/text()', $entry)->item(0)->nodeValue;
+
+		$item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue;
+
+		if ($xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue != "")
+			$objecttype = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue;
+
+		$item["object-type"] = $objecttype;
+
+		// I have the feeling that we don't do anything with this data
+		$object = $xpath->query('activity:object', $entry)->item(0);
+		$item["object"] = self::transform_activity($xpath, $object, "object");
+
+		// Could someone explain what this is for?
+		$target = $xpath->query('activity:target', $entry)->item(0);
+		$item["target"] = self::transform_activity($xpath, $target, "target");
+
+		$categories = $xpath->query('atom:category', $entry);
+		if ($categories) {
+			foreach ($categories AS $category) {
+				foreach($category->attributes AS $attributes)
+					if ($attributes->name == "term") {
+						$term = $attributes->textContent;
+						if(strlen($item["tag"]))
+							$item["tag"] .= ',';
+
+						$item["tag"] .= "#[url=".$a->get_baseurl()."/search?tag=".$term."]".$term."[/url]";
+					}
+			}
+		}
+
+		$enclosure = "";
+
+		$links = $xpath->query('atom:link', $entry);
+		if ($links) {
+			$rel = "";
+			$href = "";
+			$type = "";
+			$length = "0";
+			$title = "";
+			foreach ($links AS $link) {
+				foreach($link->attributes AS $attributes) {
+					if ($attributes->name == "href")
+						$href = $attributes->textContent;
+					if ($attributes->name == "rel")
+						$rel = $attributes->textContent;
+					if ($attributes->name == "type")
+						$type = $attributes->textContent;
+					if ($attributes->name == "length")
+						$length = $attributes->textContent;
+					if ($attributes->name == "title")
+						$title = $attributes->textContent;
+				}
+				if (($rel != "") AND ($href != ""))
+					switch($rel) {
+						case "alternate":
+							$item["plink"] = $href;
+							break;
+						case "enclosure":
+							$enclosure = $href;
+							if(strlen($item["attach"]))
+								$item["attach"] .= ',';
+
+							$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
+							break;
+					}
+			}
+		}
+
+		print_r($item);
+		//$item_id = item_store($item);
+
+		return;
+
+		if (!$item_id) {
+			logger("Error storing item", LOGGER_DEBUG);
+			return false;
+		} else {
+			logger("Item was stored with id ".$item_id, LOGGER_DEBUG);
+
+			if ($signature) {
+				$signature = json_decode(base64_decode($signature));
+
+				// Check for falsely double encoded signatures
+				$signature->signature = diaspora_repair_signature($signature->signature, $signature->signer);
+
+				// Store it in the "sign" table where we will read it for comments that we relay to Diaspora
+				q("INSERT INTO `sign` (`iid`,`signed_text`,`signature`,`signer`) VALUES (%d,'%s','%s','%s')",
+					intval($item_id),
+					dbesc($signature->signed_text),
+					dbesc($signature->signature),
+					dbesc($signature->signer)
+				);
+			}
+		}
+		return $item_id;
+	}
+
 	function import($xml,$importer,&$contact, &$hub) {
 
 		$a = get_app();
@@ -269,218 +546,32 @@ class dfrn2 {
 
 		// Update the contact table if the data has changed
 		// Only the "dfrn:owner" in the head section contains all data
-		self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", $contact, false);
+		$dfrn_owner = self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", $contact, false);
 
 		// is it a public forum? Private forums aren't supported by now with this method
-		//$contact["forum"] = intval($xpath->evaluate($element.'/dfrn:community/text()', $context)->item(0)->nodeValue);
+		$forum = intval($xpath->evaluate('/atom:feed/dfrn:community/text()', $context)->item(0)->nodeValue);
+
+		if ($forum AND ($dfrn_owner["contact-id"] != 0))
+			q("UPDATE `contact` SET `forum` = %d WHERE `forum` != %d AND `id` = %d",
+				intval($forum), intval($forum),
+				intval($dfrn_owner["contact-id"])
+			);
+
+		$mails = $xpath->query('/atom:feed/dfrn:mail');
+		foreach ($mails AS $mail)
+			self::process_mail($header, $xpath, $mail, $importer, $contact);
+
+		$suggestions = $xpath->query('/atom:feed/dfrn:suggest');
+		foreach ($suggestions AS $suggestion)
+			self::process_suggestion($header, $xpath, $suggestion, $importer, $contact);
+
+		$relocations = $xpath->query('/atom:feed/dfrn:relocate');
+		foreach ($relocations AS $relocation)
+			self::process_relocation($header, $xpath, $relocation, $importer, $contact);
 
 		$entries = $xpath->query('/atom:feed/atom:entry');
-
-		$item_id = 0;
-
-		foreach ($entries AS $entry) {
-
-			$item = $header;
-
-			$mention = false;
-
-			// Fetch the owner
-			$owner = self::fetchauthor($xpath, $entry, $importer, "dfrn:owner", $contact, true);
-
-			$item["owner-name"] = $owner["name"];
-			$item["owner-link"] = $owner["link"];
-			$item["owner-avatar"] = $owner["avatar"];
-
-			if ($header["contact-id"] != $owner["contact-id"])
-				$item["contact-id"] = $owner["contact-id"];
-
-			if (($header["network"] != $owner["network"]) AND ($owner["network"] != ""))
-				$item["network"] = $owner["network"];
-
-			// fetch the author
-			$author = self::fetchauthor($xpath, $entry, $importer, "atom:author", $contact, true);
-
-			$item["author-name"] = $author["name"];
-			$item["author-link"] = $author["link"];
-			$item["author-avatar"] = $author["avatar"];
-
-			if ($header["contact-id"] != $author["contact-id"])
-				$item["contact-id"] = $author["contact-id"];
-
-			if (($header["network"] != $author["network"]) AND ($author["network"] != ""))
-				$item["network"] = $author["network"];
-
-			// Now get the item
-			$item["uri"] = $xpath->query('atom:id/text()', $entry)->item(0)->nodeValue;
-
-			$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
-				intval($importer["uid"]), dbesc($item["uri"]));
-			if ($r) {
-				//logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
-				//continue;
-			}
-
-			// Is it a reply?
-			$inreplyto = $xpath->query('thr:in-reply-to', $entry);
-			if (is_object($inreplyto->item(0))) {
-				$objecttype = ACTIVITY_OBJ_COMMENT;
-				$item["type"] = 'remote-comment';
-				$item["gravity"] = GRAVITY_COMMENT;
-
-				foreach($inreplyto->item(0)->attributes AS $attributes) {
-					if ($attributes->name == "ref")
-						$item["parent-uri"] = $attributes->textContent;
-				}
-			} else {
-				$objecttype = ACTIVITY_OBJ_NOTE;
-				$item["parent-uri"] = $item["uri"];
-			}
-
-			$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
-
-			$item["created"] = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
-			$item["edited"] = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue;
-
-			$item["body"] = $xpath->query('dfrn:env/text()', $entry)->item(0)->nodeValue;
-			$item["body"] = str_replace(array(' ',"\t","\r","\n"), array('','','',''),$item["body"]);
-			// make sure nobody is trying to sneak some html tags by us
-			$item["body"] = notags(base64url_decode($item["body"]));
-
-			$item["body"] = limit_body_size($item["body"]);
-
-			/// @todo Do we need the old check for HTML elements?
-
-			// We don't need the content element since "dfrn:env" is always present
-			//$item["body"] = $xpath->query('atom:content/text()', $entry)->item(0)->nodeValue;
-
-			$item["last-child"] = $xpath->query('dfrn:comment-allow/text()', $entry)->item(0)->nodeValue;
-			$item["location"] = $xpath->query('dfrn:location/text()', $entry)->item(0)->nodeValue;
-
-			$georsspoint = $xpath->query('georss:point', $entry);
-			if ($georsspoint)
-				$item["coord"] = $georsspoint->item(0)->nodeValue;
-
-			$item["private"] = $xpath->query('dfrn:private/text()', $entry)->item(0)->nodeValue;
-
-			$item["extid"] = $xpath->query('dfrn:extid/text()', $entry)->item(0)->nodeValue;
-
-			if ($xpath->query('dfrn:extid/text()', $entry)->item(0)->nodeValue == "true")
-				$item["bookmark"] = true;
-
-			$notice_info = $xpath->query('statusnet:notice_info', $entry);
-			if ($notice_info AND ($notice_info->length > 0)) {
-				foreach($notice_info->item(0)->attributes AS $attributes) {
-					if ($attributes->name == "source")
-						$item["app"] = strip_tags($attributes->textContent);
-				}
-			}
-
-			$item["guid"] = $xpath->query('dfrn:diaspora_guid/text()', $entry)->item(0)->nodeValue;
-
-			// dfrn:diaspora_signature
-
-			$item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue;
-
-			if ($xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue != "")
-				$objecttype = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue;
-
-			$item["object-type"] = $objecttype;
-
-			// activity:object
-
-			// activity:target
-
-			$categories = $xpath->query('atom:category', $entry);
-			if ($categories) {
-				foreach ($categories AS $category) {
-					foreach($category->attributes AS $attributes)
-						if ($attributes->name == "term") {
-							$term = $attributes->textContent;
-							if(strlen($item["tag"]))
-							$item["tag"] .= ',';
-							$item["tag"] .= "#[url=".$a->get_baseurl()."/search?tag=".$term."]".$term."[/url]";
-						}
-				}
-			}
-
-			$enclosure = "";
-
-			$links = $xpath->query('atom:link', $entry);
-			if ($links) {
-				$rel = "";
-				$href = "";
-				$type = "";
-				$length = "0";
-				$title = "";
-				foreach ($links AS $link) {
-					foreach($link->attributes AS $attributes) {
-						if ($attributes->name == "href")
-							$href = $attributes->textContent;
-						if ($attributes->name == "rel")
-							$rel = $attributes->textContent;
-						if ($attributes->name == "type")
-							$type = $attributes->textContent;
-						if ($attributes->name == "length")
-							$length = $attributes->textContent;
-						if ($attributes->name == "title")
-							$title = $attributes->textContent;
-					}
-					if (($rel != "") AND ($href != ""))
-						switch($rel) {
-							case "alternate":
-								$item["plink"] = $href;
-								break;
-							case "enclosure":
-								$enclosure = $href;
-								if(strlen($item["attach"]))
-									$item["attach"] .= ',';
-
-								$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
-								break;
-							case "mentioned":
-								// Notification check
-								if ($importer["nurl"] == normalise_link($href))
-									$mention = true;
-								break;
-						}
-				}
-			}
-
-			print_r($item);
-/*
-			if (!$item_id) {
-				logger("Error storing item", LOGGER_DEBUG);
-				continue;
-			}
-
-			logger("Item was stored with id ".$item_id, LOGGER_DEBUG);
-			$item["id"] = $item_id;
-*/
-
-/*
-			if ($mention) {
-				$u = q("SELECT `notify-flags`, `language`, `username`, `email` FROM user WHERE uid = %d LIMIT 1", intval($item['uid']));
-				$r = q("SELECT `parent` FROM `item` WHERE `id` = %d", intval($item_id));
-
-				notification(array(
-					'type'         => NOTIFY_TAGSELF,
-					'notify_flags' => $u[0]["notify-flags"],
-					'language'     => $u[0]["language"],
-					'to_name'      => $u[0]["username"],
-					'to_email'     => $u[0]["email"],
-					'uid'          => $item["uid"],
-					'item'         => $item,
-					'link'         => $a->get_baseurl().'/display/'.urlencode(get_item_guid($item_id)),
-					'source_name'  => $item["author-name"],
-					'source_link'  => $item["author-link"],
-					'source_photo' => $item["author-avatar"],
-					'verb'         => ACTIVITY_TAG,
-					'otype'        => 'item',
-					'parent'       => $r[0]["parent"]
-				));
-			}
-*/
-		}
+		foreach ($entries AS $entry)
+			self::process_entry($header, $xpath, $entry, $importer, $contact);
 	}
 }
 ?>

From decaac6c31226fcbfd064f894e14f5c3b2405813 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 29 Jan 2016 23:14:01 +0100
Subject: [PATCH 005/273] DFRN-Import is now nearly complete, changed namespace
 constants

---
 include/dfrn.php        |  18 +--
 include/import-dfrn.php | 249 +++++++++++++++++++++++++++++++++-------
 include/ostatus.php     |  73 ++++++------
 3 files changed, 248 insertions(+), 92 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index 883afe15f7..50d78de3c4 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -386,15 +386,15 @@ class dfrn {
 		$root = $doc->createElementNS(NS_ATOM, 'feed');
 		$doc->appendChild($root);
 
-		$root->setAttribute("xmlns:thr", NS_THR);
-		$root->setAttribute("xmlns:at", "http://purl.org/atompub/tombstones/1.0");
-		$root->setAttribute("xmlns:media", NS_MEDIA);
-		$root->setAttribute("xmlns:dfrn", "http://purl.org/macgirvin/dfrn/1.0");
-		$root->setAttribute("xmlns:activity", NS_ACTIVITY);
-		$root->setAttribute("xmlns:georss", NS_GEORSS);
-		$root->setAttribute("xmlns:poco", NS_POCO);
-		$root->setAttribute("xmlns:ostatus", NS_OSTATUS);
-		$root->setAttribute("xmlns:statusnet", NS_STATUSNET);
+		$root->setAttribute("xmlns:thr", NAMESPACE_THREAD);
+		$root->setAttribute("xmlns:at", NAMESPACE_TOMB);
+		$root->setAttribute("xmlns:media", NAMESPACE_MEDIA);
+		$root->setAttribute("xmlns:dfrn", NAMESPACE_DFRN);
+		$root->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY);
+		$root->setAttribute("xmlns:georss", NAMESPACE_GEORSS);
+		$root->setAttribute("xmlns:poco", NAMESPACE_POCO);
+		$root->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
+		$root->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
 
 		xml_add_element($doc, $root, "id", app::get_baseurl()."/profile/".$owner["nick"]);
 		xml_add_element($doc, $root, "title", $owner["name"]);
diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index c934380357..3265eb6ff5 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -263,57 +263,215 @@ $onlyfetch = true; // Test
 		return($objxml);
 	}
 
-	private function process_mail($header, $xpath, $mail, $importer, $contact) {
+	private function process_mail($xpath, $mail, $importer) {
 
 		$msg = array();
 		$msg["uid"] = $importer['importer_uid'];
 		$msg["from-name"] = $xpath->query('dfrn:sender/dfrn:name/text()', $mail)->item(0)->nodeValue;
 		$msg["from-url"] = $xpath->query('dfrn:sender/dfrn:uri/text()', $mail)->item(0)->nodeValue;
 		$msg["from-photo"] = $xpath->query('dfrn:sender/dfrn:avatar/text()', $mail)->item(0)->nodeValue;
-                $msg["contact-id"] = $importer["id"];
+		$msg["contact-id"] = $importer["id"];
 		$msg["uri"] = $xpath->query('dfrn:id/text()', $mail)->item(0)->nodeValue;
 		$msg["parent-uri"] = $xpath->query('dfrn:in-reply-to/text()', $mail)->item(0)->nodeValue;
 		$msg["created"] = $xpath->query('dfrn:sentdate/text()', $mail)->item(0)->nodeValue;
 		$msg["title"] = $xpath->query('dfrn:subject/text()', $mail)->item(0)->nodeValue;
 		$msg["body"] = $xpath->query('dfrn:content/text()', $mail)->item(0)->nodeValue;
-                $msg["seen"] = 0;
-                $msg["replied"] = 0;
+		$msg["seen"] = 0;
+		$msg["replied"] = 0;
 
 		dbesc_array($msg);
 
-                //$r = dbq("INSERT INTO `mail` (`" . implode("`, `", array_keys($msg))
-                //        . "`) VALUES ('" . implode("', '", array_values($msg)) . "')" );
+		$r = dbq("INSERT INTO `mail` (`".implode("`, `", array_keys($msg))."`) VALUES ('".implode("', '", array_values($msg))."')");
 
-print_r($msg);
+		// send notifications.
 
-                // send notifications.
+		$notif_params = array(
+			'type' => NOTIFY_MAIL,
+			'notify_flags' => $importer['notify-flags'],
+			'language' => $importer['language'],
+			'to_name' => $importer['username'],
+			'to_email' => $importer['email'],
+			'uid' => $importer['importer_uid'],
+			'item' => $msg,
+			'source_name' => $msg['from-name'],
+			'source_link' => $importer['url'],
+			'source_photo' => $importer['thumb'],
+			'verb' => ACTIVITY_POST,
+			'otype' => 'mail'
+		);
 
-                require_once('include/enotify.php');
+		notification($notif_params);
+	}
 
-                $notif_params = array(
-                        'type' => NOTIFY_MAIL,
-                        'notify_flags' => $importer['notify-flags'],
-                        'language' => $importer['language'],
-                        'to_name' => $importer['username'],
-                        'to_email' => $importer['email'],
-                        'uid' => $importer['importer_uid'],
-                        'item' => $msg,
-                        'source_name' => $msg['from-name'],
-                        'source_link' => $importer['url'],
-                        'source_photo' => $importer['thumb'],
-                        'verb' => ACTIVITY_POST,
-                        'otype' => 'mail'
-                );
+	private function process_suggestion($xpath, $suggestion, $importer) {
 
-//                notification($notif_params);
-print_r($notif_params);
+		$suggest = array();
+		$suggest["uid"] = $importer["importer_uid"];
+		$suggest["cid"] = $importer["id"];
+		$suggest["url"] = $xpath->query('dfrn:url/text()', $suggestion)->item(0)->nodeValue;
+		$suggest["name"] = $xpath->query('dfrn:name/text()', $suggestion)->item(0)->nodeValue;
+		$suggest["photo"] = $xpath->query('dfrn:photo/text()', $suggestion)->item(0)->nodeValue;
+		$suggest["request"] = $xpath->query('dfrn:request/text()', $suggestion)->item(0)->nodeValue;
+		$suggest["note"] = $xpath->query('dfrn:note/text()', $suggestion)->item(0)->nodeValue;
+
+		// Does our member already have a friend matching this description?
+
+		$r = q("SELECT `id` FROM `contact` WHERE `name` = '%s' AND `nurl` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc($suggest["name"]),
+			dbesc(normalise_link($suggest["url"])),
+			intval($suggest["uid"])
+		);
+		if(count($r))
+			return false;
+
+		// Do we already have an fcontact record for this person?
+
+		$fid = 0;
+		$r = q("SELECT `id` FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1",
+			dbesc($suggest["url"]),
+			dbesc($suggest["name"]),
+			dbesc($suggest["request"])
+		);
+		if(count($r)) {
+			$fid = $r[0]["id"];
+
+			// OK, we do. Do we already have an introduction for this person ?
+			$r = q("SELECT `id` FROM `intro` WHERE `uid` = %d AND `fid` = %d LIMIT 1",
+				intval($suggest["uid"]),
+				intval($fid)
+			);
+			if(count($r))
+				return false;
+		}
+		if(!$fid)
+			$r = q("INSERT INTO `fcontact` (`name`,`url`,`photo`,`request`) VALUES ('%s', '%s', '%s', '%s')",
+			dbesc($suggest["name"]),
+			dbesc($suggest["url"]),
+			dbesc($suggest["photo"]),
+			dbesc($suggest["request"])
+		);
+		$r = q("SELECT `id` FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1",
+			dbesc($suggest["url"]),
+			dbesc($suggest["name"]),
+			dbesc($suggest["request"])
+		);
+		if(count($r))
+			$fid = $r[0]["id"];
+		else
+			// database record did not get created. Quietly give up.
+			return false;
+
+
+		$hash = random_string();
+
+		$r = q("INSERT INTO `intro` (`uid`, `fid`, `contact-id`, `note`, `hash`, `datetime`, `blocked`)
+			VALUES(%d, %d, %d, '%s', '%s', '%s', %d)",
+			intval($suggest["uid"]),
+			intval($fid),
+			intval($suggest["cid"]),
+			dbesc($suggest["body"]),
+			dbesc($hash),
+			dbesc(datetime_convert()),
+			intval(0)
+		);
+
+		notification(array(
+			'type'         => NOTIFY_SUGGEST,
+			'notify_flags' => $importer["notify-flags"],
+			'language'     => $importer["language"],
+			'to_name'      => $importer["username"],
+			'to_email'     => $importer["email"],
+			'uid'          => $importer["importer_uid"],
+			'item'         => $suggest,
+			'link'         => App::get_baseurl()."/notifications/intros",
+			'source_name'  => $importer["name"],
+			'source_link'  => $importer["url"],
+			'source_photo' => $importer["photo"],
+			'verb'         => ACTIVITY_REQ_FRIEND,
+			'otype'        => "intro"
+		));
+
+		return true;
 
 	}
 
-	private function process_suggestion($header, $xpath, $suggestion, $importer, $contact) {
-	}
+	private function process_relocation($xpath, $relocation, $importer) {
 
-	private function process_relocation($header, $xpath, $relocation, $importer, $contact) {
+		$relocate = array();
+		$relocate["uid"] = $importer["importer_uid"];
+		$relocate["cid"] = $importer["id"];
+		$relocate["url"] = $xpath->query('dfrn:url/text()', $relocation)->item(0)->nodeValue;
+		$relocate["name"] = $xpath->query('dfrn:name/text()', $relocation)->item(0)->nodeValue;
+		$relocate["photo"] = $xpath->query('dfrn:photo/text()', $relocation)->item(0)->nodeValue;
+		$relocate["thumb"] = $xpath->query('dfrn:thumb/text()', $relocation)->item(0)->nodeValue;
+		$relocate["micro"] = $xpath->query('dfrn:micro/text()', $relocation)->item(0)->nodeValue;
+		$relocate["request"] = $xpath->query('dfrn:request/text()', $relocation)->item(0)->nodeValue;
+		$relocate["confirm"] = $xpath->query('dfrn:confirm/text()', $relocation)->item(0)->nodeValue;
+		$relocate["notify"] = $xpath->query('dfrn:notify/text()', $relocation)->item(0)->nodeValue;
+		$relocate["poll"] = $xpath->query('dfrn:poll/text()', $relocation)->item(0)->nodeValue;
+		$relocate["sitepubkey"] = $xpath->query('dfrn:sitepubkey/text()', $relocation)->item(0)->nodeValue;
+
+		// update contact
+		$r = q("SELECT `photo`, `url` FROM `contact` WHERE `id` = %d AND `uid` = %d;",
+			intval($importer["id"]),
+			intval($importer["importer_uid"]));
+		if (!$r)
+			return false;
+
+		$old = $r[0];
+
+		$x = q("UPDATE `contact` SET
+					`name` = '%s',
+					`photo` = '%s',
+					`thumb` = '%s',
+					`micro` = '%s',
+					`url` = '%s',
+					`nurl` = '%s',
+					`request` = '%s',
+					`confirm` = '%s',
+					`notify` = '%s',
+					`poll` = '%s',
+					`site-pubkey` = '%s'
+			WHERE `id` = %d AND `uid` = %d;",
+					dbesc($relocate["name"]),
+					dbesc($relocate["photo"]),
+					dbesc($relocate["thumb"]),
+					dbesc($relocate["micro"]),
+					dbesc($relocate["url"]),
+					dbesc(normalise_link($relocate["url"])),
+					dbesc($relocate["request"]),
+					dbesc($relocate["confirm"]),
+					dbesc($relocate["notify"]),
+					dbesc($relocate["poll"]),
+					dbesc($relocate["sitepubkey"]),
+					intval($importer["id"]),
+					intval($importer["importer_uid"]));
+
+		if ($x === false)
+			return false;
+
+		// update items
+		$fields = array(
+			'owner-link' => array($old["url"], $relocate["url"]),
+			'author-link' => array($old["url"], $relocate["url"]),
+			'owner-avatar' => array($old["photo"], $relocate["photo"]),
+			'author-avatar' => array($old["photo"], $relocate["photo"]),
+			);
+		foreach ($fields as $n=>$f){
+			$x = q("UPDATE `item` SET `%s` = '%s' WHERE `%s` = '%s' AND `uid` = %d",
+					$n, dbesc($f[1]),
+					$n, dbesc($f[0]),
+					intval($importer["importer_uid"]));
+				if ($x === false)
+					return false;
+			}
+
+		/// @TODO
+		/// merge with current record, current contents have priority
+		/// update record, set url-updated
+		/// update profile photos
+		/// schedule a scan?
+		return true;
 	}
 
 	private function process_entry($header, $xpath, $entry, $importer, $contact) {
@@ -511,7 +669,11 @@ print_r($notif_params);
 		return $item_id;
 	}
 
-	function import($xml,$importer,&$contact, &$hub) {
+	private function process_deletion($header, $xpath, $entry, $importer, $contact) {
+		die("blubb");
+	}
+
+	function import($xml,$importer) {
 
 		$a = get_app();
 
@@ -524,16 +686,19 @@ print_r($notif_params);
 		@$doc->loadXML($xml);
 
 		$xpath = new DomXPath($doc);
-		$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
-		$xpath->registerNamespace('thr', "http://purl.org/syndication/thread/1.0");
-		$xpath->registerNamespace('at', "http://purl.org/atompub/tombstones/1.0");
-		$xpath->registerNamespace('media', "http://purl.org/syndication/atommedia");
-		$xpath->registerNamespace('dfrn', "http://purl.org/macgirvin/dfrn/1.0");
-		$xpath->registerNamespace('activity', "http://activitystrea.ms/spec/1.0/");
-		$xpath->registerNamespace('georss', "http://www.georss.org/georss");
-		$xpath->registerNamespace('poco', "http://portablecontacts.net/spec/1.0");
-		$xpath->registerNamespace('ostatus', "http://ostatus.org/schema/1.0");
-		$xpath->registerNamespace('statusnet', "http://status.net/schema/api/1/");
+		$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
+		$xpath->registerNamespace('thr', NAMESPACE_THREAD);
+		$xpath->registerNamespace('at', NAMESPACE_TOMB);
+		$xpath->registerNamespace('media', NAMESPACE_MEDIA);
+		$xpath->registerNamespace('dfrn', NAMESPACE_DFRN);
+		$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
+		$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
+		$xpath->registerNamespace('poco', NAMESPACE_POCO);
+		$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
+		$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
+
+		$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `self`", intval($importer["uid"]));
+		$contact = $r[0];
 
 		$header = array();
 		$header["uid"] = $importer["uid"];
@@ -559,15 +724,15 @@ print_r($notif_params);
 
 		$mails = $xpath->query('/atom:feed/dfrn:mail');
 		foreach ($mails AS $mail)
-			self::process_mail($header, $xpath, $mail, $importer, $contact);
+			self::process_mail($xpath, $mail, $importer);
 
 		$suggestions = $xpath->query('/atom:feed/dfrn:suggest');
 		foreach ($suggestions AS $suggestion)
-			self::process_suggestion($header, $xpath, $suggestion, $importer, $contact);
+			self::process_suggestion($xpath, $suggestion, $importer);
 
 		$relocations = $xpath->query('/atom:feed/dfrn:relocate');
 		foreach ($relocations AS $relocation)
-			self::process_relocation($header, $xpath, $relocation, $importer, $contact);
+			self::process_relocation($xpath, $relocation, $importer);
 
 		$entries = $xpath->query('/atom:feed/atom:entry');
 		foreach ($entries AS $entry)
diff --git a/include/ostatus.php b/include/ostatus.php
index 37b308db70..caaeec84f7 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -17,15 +17,6 @@ define('OSTATUS_DEFAULT_POLL_INTERVAL', 30); // given in minutes
 define('OSTATUS_DEFAULT_POLL_TIMEFRAME', 1440); // given in minutes
 define('OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS', 14400); // given in minutes
 
-define("NS_ATOM", "http://www.w3.org/2005/Atom");
-define("NS_THR", "http://purl.org/syndication/thread/1.0");
-define("NS_GEORSS", "http://www.georss.org/georss");
-define("NS_ACTIVITY", "http://activitystrea.ms/spec/1.0/");
-define("NS_MEDIA", "http://purl.org/syndication/atommedia");
-define("NS_POCO", "http://portablecontacts.net/spec/1.0");
-define("NS_OSTATUS", "http://ostatus.org/schema/1.0");
-define("NS_STATUSNET", "http://status.net/schema/api/1/");
-
 function ostatus_check_follow_friends() {
 	$r = q("SELECT `uid`,`v` FROM `pconfig` WHERE `cat`='system' AND `k`='ostatus_legacy_contact' AND `v` != ''");
 
@@ -193,14 +184,14 @@ function ostatus_salmon_author($xml, $importer) {
 	@$doc->loadXML($xml);
 
 	$xpath = new DomXPath($doc);
-	$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
-	$xpath->registerNamespace('thr', "http://purl.org/syndication/thread/1.0");
-	$xpath->registerNamespace('georss', "http://www.georss.org/georss");
-	$xpath->registerNamespace('activity', "http://activitystrea.ms/spec/1.0/");
-	$xpath->registerNamespace('media', "http://purl.org/syndication/atommedia");
-	$xpath->registerNamespace('poco', "http://portablecontacts.net/spec/1.0");
-	$xpath->registerNamespace('ostatus', "http://ostatus.org/schema/1.0");
-	$xpath->registerNamespace('statusnet', "http://status.net/schema/api/1/");
+	$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
+	$xpath->registerNamespace('thr', NAMESPACE_THREAD);
+	$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
+	$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
+	$xpath->registerNamespace('media', NAMESPACE_MEDIA);
+	$xpath->registerNamespace('poco', NAMESPACE_POCO);
+	$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
+	$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
 
 	$entries = $xpath->query('/atom:entry');
 
@@ -224,14 +215,14 @@ function ostatus_import($xml,$importer,&$contact, &$hub) {
 	@$doc->loadXML($xml);
 
 	$xpath = new DomXPath($doc);
-	$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
-	$xpath->registerNamespace('thr', "http://purl.org/syndication/thread/1.0");
-	$xpath->registerNamespace('georss', "http://www.georss.org/georss");
-	$xpath->registerNamespace('activity', "http://activitystrea.ms/spec/1.0/");
-	$xpath->registerNamespace('media', "http://purl.org/syndication/atommedia");
-	$xpath->registerNamespace('poco', "http://portablecontacts.net/spec/1.0");
-	$xpath->registerNamespace('ostatus', "http://ostatus.org/schema/1.0");
-	$xpath->registerNamespace('statusnet', "http://status.net/schema/api/1/");
+	$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
+	$xpath->registerNamespace('thr', NAMESPACE_THREAD);
+	$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
+	$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
+	$xpath->registerNamespace('media', NAMESPACE_MEDIA);
+	$xpath->registerNamespace('poco', NAMESPACE_POCO);
+	$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
+	$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
 
 	$gub = "";
 	$hub_attributes = $xpath->query("/atom:feed/atom:link[@rel='hub']")->item(0)->attributes;
@@ -1120,16 +1111,16 @@ function ostatus_format_picture_post($body) {
 function ostatus_add_header($doc, $owner) {
 	$a = get_app();
 
-	$root = $doc->createElementNS(NS_ATOM, 'feed');
+	$root = $doc->createElementNS(NAMESPACE_ATOM1, 'feed');
 	$doc->appendChild($root);
 
-	$root->setAttribute("xmlns:thr", NS_THR);
-	$root->setAttribute("xmlns:georss", NS_GEORSS);
-	$root->setAttribute("xmlns:activity", NS_ACTIVITY);
-	$root->setAttribute("xmlns:media", NS_MEDIA);
-	$root->setAttribute("xmlns:poco", NS_POCO);
-	$root->setAttribute("xmlns:ostatus", NS_OSTATUS);
-	$root->setAttribute("xmlns:statusnet", NS_STATUSNET);
+	$root->setAttribute("xmlns:thr", NAMESPACE_THREAD);
+	$root->setAttribute("xmlns:georss", NAMESPACE_GEORSS);
+	$root->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY);
+	$root->setAttribute("xmlns:media", NAMESPACE_MEDIA);
+	$root->setAttribute("xmlns:poco", NAMESPACE_POCO);
+	$root->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
+	$root->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
 
 	$attributes = array("uri" => "https://friendi.ca", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION);
 	xml_add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes);
@@ -1343,15 +1334,15 @@ function ostatus_entry($doc, $item, $owner, $toplevel = false, $repeat = false)
 		$entry = $doc->createElement("activity:object");
 		$title = sprintf("New note by %s", $owner["nick"]);
 	} else {
-		$entry = $doc->createElementNS(NS_ATOM, "entry");
+		$entry = $doc->createElementNS(NAMESPACE_ATOM1, "entry");
 
-		$entry->setAttribute("xmlns:thr", NS_THR);
-		$entry->setAttribute("xmlns:georss", NS_GEORSS);
-		$entry->setAttribute("xmlns:activity", NS_ACTIVITY);
-		$entry->setAttribute("xmlns:media", NS_MEDIA);
-		$entry->setAttribute("xmlns:poco", NS_POCO);
-		$entry->setAttribute("xmlns:ostatus", NS_OSTATUS);
-		$entry->setAttribute("xmlns:statusnet", NS_STATUSNET);
+		$entry->setAttribute("xmlns:thr", NAMESPACE_THREAD);
+		$entry->setAttribute("xmlns:georss", NAMESPACE_GEORSS);
+		$entry->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY);
+		$entry->setAttribute("xmlns:media", NAMESPACE_MEDIA);
+		$entry->setAttribute("xmlns:poco", NAMESPACE_POCO);
+		$entry->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
+		$entry->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
 
 		$author = ostatus_add_author($doc, $owner);
 		$entry->appendChild($author);

From cd1f3cde00612a4798fc0c42fd5daa37ff393964 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 30 Jan 2016 01:20:43 +0100
Subject: [PATCH 006/273] DFRN Deletions should now work too

---
 include/import-dfrn.php | 143 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 131 insertions(+), 12 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index 3265eb6ff5..fd5b71cadb 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -1,13 +1,9 @@
 <?php
 /*
 require_once("include/Contact.php");
-require_once("include/threads.php");
 require_once("include/html2bbcode.php");
 require_once("include/bbcode.php");
-require_once("include/items.php");
 require_once("mod/share.php");
-require_once("include/enotify.php");
-require_once("include/socgraph.php");
 require_once("include/Photo.php");
 require_once("include/Scrape.php");
 require_once("include/follow.php");
@@ -15,6 +11,13 @@ require_once("include/api.php");
 require_once("mod/proxy.php");
 */
 
+require_once("include/enotify.php");
+require_once("include/threads.php");
+require_once("include/socgraph.php");
+require_once("include/items.php");
+require_once("include/tags.php");
+require_once("include/files.php");
+
 define("NS_ATOM", "http://www.w3.org/2005/Atom");
 define("NS_THR", "http://purl.org/syndication/thread/1.0");
 define("NS_GEORSS", "http://www.georss.org/georss");
@@ -109,7 +112,7 @@ class dfrn2 {
 			$author["avatar"] = current($avatarlist);
 		}
 
-$onlyfetch = true; // Test
+		//$onlyfetch = true; // Test
 
 		if ($r AND !$onlyfetch) {
 
@@ -640,8 +643,8 @@ $onlyfetch = true; // Test
 			}
 		}
 
-		print_r($item);
-		//$item_id = item_store($item);
+		//print_r($item);
+		$item_id = item_store($item);
 
 		return;
 
@@ -669,11 +672,121 @@ $onlyfetch = true; // Test
 		return $item_id;
 	}
 
-	private function process_deletion($header, $xpath, $entry, $importer, $contact) {
-		die("blubb");
+	private function process_deletion($header, $xpath, $deletion, $importer, $contact) {
+		foreach($deletion->attributes AS $attributes) {
+			if ($attributes->name == "ref")
+				$uri = $attributes->textContent;
+			if ($attributes->name == "when")
+				$when = $attributes->textContent;
+		}
+		if ($when)
+			$when = datetime_convert('UTC','UTC', $when, 'Y-m-d H:i:s');
+		else
+			$when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s');
+
+		if (!$uri OR !is_array($contact))
+			return false;
+
+		$r = q("SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN `contact` on `item`.`contact-id` = `contact`.`id`
+				WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1",
+				dbesc($uri),
+				intval($importer["uid"]),
+				intval($contact["id"])
+			);
+		if(count($r)) {
+			$item = $r[0];
+
+			if(!$item["deleted"])
+				logger('deleting item '.$item["id"].' uri='.$item['uri'], LOGGER_DEBUG);
+
+			if($item["object-type"] === ACTIVITY_OBJ_EVENT) {
+				logger("Deleting event ".$item["event-id"], LOGGER_DEBUG);
+				event_delete($item["event-id"]);
+			}
+
+			if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
+				$xo = parse_xml_string($item["object"],false);
+				$xt = parse_xml_string($item["target"],false);
+				if($xt->type === ACTIVITY_OBJ_NOTE) {
+					$i = q("SELECT `id`, `contact-id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+						dbesc($xt->id),
+						intval($importer["importer_uid"])
+					);
+					if(count($i)) {
+
+						// For tags, the owner cannot remove the tag on the author's copy of the post.
+
+						$owner_remove = (($item['contact-id'] == $i[0]['contact-id']) ? true: false);
+						$author_remove = (($item['origin'] && $item['self']) ? true : false);
+						$author_copy = (($item['origin']) ? true : false);
+
+						if($owner_remove && $author_copy)
+							continue;
+						if($author_remove || $owner_remove) {
+							$tags = explode(',',$i[0]['tag']);
+							$newtags = array();
+							if(count($tags)) {
+								foreach($tags as $tag)
+									if(trim($tag) !== trim($xo->body))
+										$newtags[] = trim($tag);
+							}
+							q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
+								dbesc(implode(',',$newtags)),
+								intval($i[0]['id'])
+							);
+							create_tags_from_item($i[0]['id']);
+						}
+					}
+				}
+			}
+
+			if($item['uri'] == $item['parent-uri']) {
+				$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
+						`body` = '', `title` = ''
+					WHERE `parent-uri` = '%s' AND `uid` = %d",
+						dbesc($when),
+						dbesc(datetime_convert()),
+						dbesc($item['uri']),
+						intval($importer['uid'])
+					);
+					create_tags_from_itemuri($item['uri'], $importer['uid']);
+					create_files_from_itemuri($item['uri'], $importer['uid']);
+					update_thread_uri($item['uri'], $importer['uid']);
+			} else {
+				$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
+						`body` = '', `title` = ''
+					WHERE `uri` = '%s' AND `uid` = %d",
+						dbesc($when),
+						dbesc(datetime_convert()),
+						dbesc($uri),
+						intval($importer['uid'])
+					);
+				create_tags_from_itemuri($uri, $importer['uid']);
+				create_files_from_itemuri($uri, $importer['uid']);
+				if($item['last-child']) {
+					// ensure that last-child is set in case the comment that had it just got wiped.
+					q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ",
+						dbesc(datetime_convert()),
+						dbesc($item['parent-uri']),
+						intval($item['uid'])
+					);
+					// who is the last child now?
+					$r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `moderated` = 0 AND `uid` = %d
+						ORDER BY `created` DESC LIMIT 1",
+							dbesc($item['parent-uri']),
+							intval($importer['uid'])
+					);
+					if(count($r)) {
+						q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d",
+							intval($r[0]['id'])
+						);
+					}
+				}
+			}
+		}
 	}
 
-	function import($xml,$importer) {
+	function import($xml,$importer, &$contact) {
 
 		$a = get_app();
 
@@ -697,8 +810,10 @@ $onlyfetch = true; // Test
 		$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
 		$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
 
-		$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `self`", intval($importer["uid"]));
-		$contact = $r[0];
+		if (!$contact) {
+			$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `self`", intval($importer["uid"]));
+			$contact = $r[0];
+		}
 
 		$header = array();
 		$header["uid"] = $importer["uid"];
@@ -734,6 +849,10 @@ $onlyfetch = true; // Test
 		foreach ($relocations AS $relocation)
 			self::process_relocation($xpath, $relocation, $importer);
 
+		$deletions = $xpath->query('/atom:feed/at:deleted-entry');
+		foreach ($deletions AS $deletion)
+			self::process_deletion($header, $xpath, $deletion, $importer, $contact);
+
 		$entries = $xpath->query('/atom:feed/atom:entry');
 		foreach ($entries AS $entry)
 			self::process_entry($header, $xpath, $entry, $importer, $contact);

From 69457a4a5bf5058a3982ad88094b833ece3ced4a Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 30 Jan 2016 02:57:40 +0100
Subject: [PATCH 007/273] DFRN import seems to work. Improvements are possible
 :-)

---
 include/import-dfrn.php | 43 +++++++++++++++++++++++++++--------------
 include/items.php       | 10 ++++++++++
 mod/ping.php            |  6 +++++-
 3 files changed, 43 insertions(+), 16 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index fd5b71cadb..20735bd507 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -69,7 +69,7 @@ class dfrn2 {
 	 *
 	 * @return Returns an array with relevant data of the author
 	 */
-	private function fetchauthor($xpath, $context, $importer, $element, &$contact, $onlyfetch) {
+	private function fetchauthor($xpath, $context, $importer, $element, $contact, $onlyfetch) {
 
 		$author = array();
 		$author["name"] = $xpath->evaluate($element.'/atom:name/text()', $context)->item(0)->nodeValue;
@@ -77,9 +77,8 @@ class dfrn2 {
 
 		$r = q("SELECT `id`, `uid`, `network`, `avatar-date`, `name-date`, `uri-date`, `addr`,
 				`name`, `nick`, `about`, `location`, `keywords`, `bdyear`, `bd`
-				FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'",
-			intval($importer["uid"]), dbesc(normalise_link($author["author-link"])),
-			dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET));
+				FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
+			intval($importer["uid"]), dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET));
 		if ($r) {
 			$contact = $r[0];
 			$author["contact-id"] = $r[0]["id"];
@@ -87,6 +86,7 @@ class dfrn2 {
 		} else {
 			$author["contact-id"] = $contact["id"];
 			$author["network"] = $contact["network"];
+			$onlyfetch = true;
 		}
 
 		// Until now we aren't serving different sizes - but maybe later
@@ -268,6 +268,8 @@ class dfrn2 {
 
 	private function process_mail($xpath, $mail, $importer) {
 
+		logger("Processing mails");
+
 		$msg = array();
 		$msg["uid"] = $importer['importer_uid'];
 		$msg["from-name"] = $xpath->query('dfrn:sender/dfrn:name/text()', $mail)->item(0)->nodeValue;
@@ -308,6 +310,8 @@ class dfrn2 {
 
 	private function process_suggestion($xpath, $suggestion, $importer) {
 
+		logger("Processing suggestions");
+
 		$suggest = array();
 		$suggest["uid"] = $importer["importer_uid"];
 		$suggest["cid"] = $importer["id"];
@@ -400,6 +404,8 @@ class dfrn2 {
 
 	private function process_relocation($xpath, $relocation, $importer) {
 
+		logger("Processing relocations");
+
 		$relocate = array();
 		$relocate["uid"] = $importer["importer_uid"];
 		$relocate["cid"] = $importer["id"];
@@ -478,6 +484,9 @@ class dfrn2 {
 	}
 
 	private function process_entry($header, $xpath, $entry, $importer, $contact) {
+
+		logger("Processing entries");
+
 		$item = $header;
 
 		// Fetch the owner
@@ -600,7 +609,7 @@ class dfrn2 {
 						if(strlen($item["tag"]))
 							$item["tag"] .= ',';
 
-						$item["tag"] .= "#[url=".$a->get_baseurl()."/search?tag=".$term."]".$term."[/url]";
+						$item["tag"] .= "#[url=".App::get_baseurl()."/search?tag=".$term."]".$term."[/url]";
 					}
 			}
 		}
@@ -646,8 +655,6 @@ class dfrn2 {
 		//print_r($item);
 		$item_id = item_store($item);
 
-		return;
-
 		if (!$item_id) {
 			logger("Error storing item", LOGGER_DEBUG);
 			return false;
@@ -672,7 +679,10 @@ class dfrn2 {
 		return $item_id;
 	}
 
-	private function process_deletion($header, $xpath, $deletion, $importer, $contact) {
+	private function process_deletion($header, $xpath, $deletion, $importer, $contact_id) {
+
+		logger("Processing deletions");
+
 		foreach($deletion->attributes AS $attributes) {
 			if ($attributes->name == "ref")
 				$uri = $attributes->textContent;
@@ -684,14 +694,14 @@ class dfrn2 {
 		else
 			$when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s');
 
-		if (!$uri OR !is_array($contact))
+		if (!$uri OR !$contact)
 			return false;
 
 		$r = q("SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN `contact` on `item`.`contact-id` = `contact`.`id`
 				WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1",
 				dbesc($uri),
 				intval($importer["uid"]),
-				intval($contact["id"])
+				intval($contact_id)
 			);
 		if(count($r)) {
 			$item = $r[0];
@@ -788,10 +798,6 @@ class dfrn2 {
 
 	function import($xml,$importer, &$contact) {
 
-		$a = get_app();
-
-		logger("Import DFRN message", LOGGER_DEBUG);
-
 		if ($xml == "")
 			return;
 
@@ -828,6 +834,13 @@ class dfrn2 {
 		// Only the "dfrn:owner" in the head section contains all data
 		$dfrn_owner = self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", $contact, false);
 
+		logger("Import DFRN message for user ".$importer["uid"]." from contact ".$contact["id"]." ".print_r($dfrn_owner, true)." - ".print_r($contact, true), LOGGER_DEBUG);
+
+		//if (!$dfrn_owner["found"]) {
+		//	logger("Author doesn't seem to be known by us. UID: ".$importer["uid"]." Contact: ".$dfrn_owner["contact-id"]." - ".print_r($dfrn_owner, true));
+		//	return;
+		//}
+
 		// is it a public forum? Private forums aren't supported by now with this method
 		$forum = intval($xpath->evaluate('/atom:feed/dfrn:community/text()', $context)->item(0)->nodeValue);
 
@@ -851,7 +864,7 @@ class dfrn2 {
 
 		$deletions = $xpath->query('/atom:feed/at:deleted-entry');
 		foreach ($deletions AS $deletion)
-			self::process_deletion($header, $xpath, $deletion, $importer, $contact);
+			self::process_deletion($header, $xpath, $deletion, $importer, $dfrn_owner["contact-id"]);
 
 		$entries = $xpath->query('/atom:feed/atom:entry');
 		foreach ($entries AS $entry)
diff --git a/include/items.php b/include/items.php
index 65b274019c..7df4e0c78a 100644
--- a/include/items.php
+++ b/include/items.php
@@ -17,6 +17,7 @@ require_once('include/feed.php');
 require_once('include/Contact.php');
 require_once('mod/share.php');
 require_once('include/enotify.php');
+require_once('include/import-dfrn.php');
 
 require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
 
@@ -1693,6 +1694,13 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
 		}
 		return;
 	}
+	// dfrn-test
+//	if ($contact['network'] === NETWORK_DFRN) {
+//		logger("Consume DFRN messages", LOGGER_DEBUG);
+//		logger("dfrn-test");
+//		dfrn2::import($xml,$importer, $contact);
+//		return;
+//	}
 
 	// Test - remove before flight
 	//if ($pass < 2) {
@@ -2398,6 +2406,8 @@ function item_is_remote_self($contact, &$datarray) {
 }
 
 function local_delivery($importer,$data) {
+	// dfrn-Test
+	return dfrn2::import($data, $importer, $contact);
 
 	require_once('library/simplepie/simplepie.inc');
 
diff --git a/mod/ping.php b/mod/ping.php
index 57728d3294..e517f785e8 100644
--- a/mod/ping.php
+++ b/mod/ping.php
@@ -389,7 +389,11 @@ function ping_get_notifications($uid) {
 			// Replace the name with {0} but ensure to make that only once
 			// The {0} is used later and prints the name in bold.
 
-			$pos = strpos($notification["message"],$notification['name']);
+			if ($notification['name'] != "")
+				$pos = strpos($notification["message"],$notification['name']);
+			else
+				$pos = false;
+
 			if ($pos !== false)
 				$notification["message"] = substr_replace($notification["message"],"{0}",$pos,strlen($notification["name"]));
 

From 4e513d3885eb04119c785f4c15561e6c32568078 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 30 Jan 2016 03:17:46 +0100
Subject: [PATCH 008/273] DFRN: Deletions should work now as well

---
 include/import-dfrn.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index 20735bd507..b1a1c80e04 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -521,8 +521,8 @@ class dfrn2 {
 		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
 			intval($importer["uid"]), dbesc($item["uri"]));
 		if ($r) {
-			//logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
-			//return false;
+			logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
+			return false;
 		}
 
 		// Is it a reply?
@@ -694,7 +694,7 @@ class dfrn2 {
 		else
 			$when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s');
 
-		if (!$uri OR !$contact)
+		if (!$uri OR !$contact_id)
 			return false;
 
 		$r = q("SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN `contact` on `item`.`contact-id` = `contact`.`id`

From eb17fe7324507aa60d7227397cd98aa230aa3c26 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 30 Jan 2016 14:13:58 +0100
Subject: [PATCH 009/273] Some missing parts added

---
 include/import-dfrn.php | 252 ++++++++++++++++++++++++++++++++++++++--
 include/items.php       |   4 +-
 2 files changed, 247 insertions(+), 9 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index b1a1c80e04..9660d9209c 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -520,10 +520,10 @@ class dfrn2 {
 
 		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
 			intval($importer["uid"]), dbesc($item["uri"]));
-		if ($r) {
-			logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
-			return false;
-		}
+		//if ($r) {
+		//	logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
+		//	return false;
+		//}
 
 		// Is it a reply?
 		$inreplyto = $xpath->query('thr:in-reply-to', $entry);
@@ -652,8 +652,239 @@ class dfrn2 {
 			}
 		}
 
-		//print_r($item);
-		$item_id = item_store($item);
+/*
+// reply
+                                // not allowed to post
+
+                                if($contact['rel'] == CONTACT_IS_FOLLOWER)
+                                        continue;
+
+                                $r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                        dbesc($item_id),
+                                        intval($importer['uid'])
+                                );
+
+				// Update content if 'updated' changes
+
+                                if(count($r)) {
+                                        if (edited_timestamp_is_newer($r[0], $datarray)) {
+
+                                                // do not accept (ignore) an earlier edit than one we currently have.
+                                                if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
+                                                        continue;
+
+                                                $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` =
+ '%s' WHERE `uri` = '%s' AND `uid` = %d",
+                                                        dbesc($datarray['title']),
+                                                        dbesc($datarray['body']),
+                                                        dbesc($datarray['tag']),
+                                                        dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
+                                                        dbesc(datetime_convert()),
+                                                        dbesc($item_id),
+                                                        intval($importer['uid'])
+                                                );
+                                                create_tags_from_itemuri($item_id, $importer['uid']);
+                                                update_thread_uri($item_id, $importer['uid']);
+                                        }
+
+                                        // update last-child if it changes
+                                        // update last-child if it changes
+
+                                        $allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow');
+                                        if(($allow) && ($allow[0]['data'] != $r[0]['last-child'])) {
+                                                $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
+                                                        dbesc(datetime_convert()),
+                                                        dbesc($parent_uri),
+                                                        intval($importer['uid'])
+                                                );
+                                                $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s'  WHERE `uri` = '%s' AND `uid` = %d",
+                                                        intval($allow[0]['data']),
+                                                        dbesc(datetime_convert()),
+                                                        dbesc($item_id),
+                                                        intval($importer['uid'])
+                                                );
+                                                update_thread_uri($item_id, $importer['uid']);
+                                        }
+                                        continue;
+                                }
+                                if(($datarray['verb'] === ACTIVITY_LIKE)
+                                        || ($datarray['verb'] === ACTIVITY_DISLIKE)
+                                        || ($datarray['verb'] === ACTIVITY_ATTEND)
+                                        || ($datarray['verb'] === ACTIVITY_ATTENDNO)
+                                        || ($datarray['verb'] === ACTIVITY_ATTENDMAYBE)) {
+                                        $datarray['type'] = 'activity';
+                                        $datarray['gravity'] = GRAVITY_LIKE;
+                                        // only one like or dislike per person
+                                        // splitted into two queries for performance issues
+                                        $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1",
+                                                intval($datarray['uid']),
+                                                dbesc($datarray['author-link']),
+                                                dbesc($datarray['verb']),
+                                                dbesc($datarray['parent-uri'])
+                                        );
+                                        if($r && count($r))
+                                                continue;
+
+                                        $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1",
+                                                intval($datarray['uid']),
+                                                dbesc($datarray['author-link']),
+                                                dbesc($datarray['verb']),
+                                                dbesc($datarray['parent-uri'])
+                                        );
+                                        if($r && count($r))
+                                                continue;
+                                }
+                                if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
+                                        $xo = parse_xml_string($datarray['object'],false);
+                                        $xt = parse_xml_string($datarray['target'],false);
+
+                                        if($xt->type == ACTIVITY_OBJ_NOTE) {
+                                                $r = q("select * from item where `uri` = '%s' AND `uid` = %d limit 1",
+                                                        dbesc($xt->id),
+                                                        intval($importer['importer_uid'])
+                                                );
+                                                if(! count($r))
+                                                        continue;
+
+                                                // extract tag, if not duplicate, add to parent item
+                                                if($xo->id && $xo->content) {
+                                                        $newtag = '#[url=' . $xo->id . ']'. $xo->content . '[/url]';
+                                                        if(! (stristr($r[0]['tag'],$newtag))) {
+                                                                q("UPDATE item SET tag = '%s' WHERE id = %d",
+                                                                        dbesc($r[0]['tag'] . (strlen($r[0]['tag']) ? ',' : '') . $newtag),
+                                                                        intval($r[0]['id'])
+                                                                );
+                                                                create_tags_from_item($r[0]['id']);
+                                                        }
+                                                }
+                                        }
+                                }
+
+
+
+// toplevel
+                                // special handling for events
+
+                                if((x($datarray,'object-type')) && ($datarray['object-type'] === ACTIVITY_OBJ_EVENT)) {
+                                        $ev = bbtoevent($datarray['body']);
+                                        if((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) {
+                                                $ev['uid'] = $importer['uid'];
+                                                $ev['uri'] = $item_id;
+                                                $ev['edited'] = $datarray['edited'];
+                                                $ev['private'] = $datarray['private'];
+                                                $ev['guid'] = $datarray['guid'];
+
+                                                if(is_array($contact))
+                                                        $ev['cid'] = $contact['id'];
+                                                $r = q("SELECT * FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                                        dbesc($item_id),
+                                                        intval($importer['uid'])
+                                                );
+                                                if(count($r))
+                                                        $ev['id'] = $r[0]['id'];
+                                                $xyz = event_store($ev);
+                                                continue;
+                                        }
+                                }
+
+
+				$r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+                                        dbesc($item_id),
+                                        intval($importer['uid'])
+                                );
+
+                                // Update content if 'updated' changes
+
+                                if(count($r)) {
+                                        if (edited_timestamp_is_newer($r[0], $datarray)) {
+
+                                                // do not accept (ignore) an earlier edit than one we currently have.
+                                                if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
+                                                        continue;
+
+                                                $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` =
+ '%s' WHERE `uri` = '%s' AND `uid` = %d",
+                                                        dbesc($datarray['title']),
+                                                        dbesc($datarray['body']),
+                                                        dbesc($datarray['tag']),
+                                                        dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
+                                                        dbesc(datetime_convert()),
+                                                        dbesc($item_id),
+                                                        intval($importer['uid'])
+                                                );
+                                                create_tags_from_itemuri($item_id, $importer['uid']);
+                                                update_thread_uri($item_id, $importer['uid']);
+                                        }
+
+                                        // update last-child if it changes
+
+                                        $allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow');
+                                        if($allow && $allow[0]['data'] != $r[0]['last-child']) {
+                                                $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
+                                                        intval($allow[0]['data']),
+                                                        dbesc(datetime_convert()),
+                                                        dbesc($item_id),
+                                                        intval($importer['uid'])
+                                                );
+                                                update_thread_uri($item_id, $importer['uid']);
+                                        }
+                                        continue;
+                                }
+
+
+
+toplevel:
+
+                                if(activity_match($datarray['verb'],ACTIVITY_FOLLOW)) {
+                                        logger('consume-feed: New follower');
+                                        new_follower($importer,$contact,$datarray,$item);
+                                        return;
+                                }
+                                if(activity_match($datarray['verb'],ACTIVITY_UNFOLLOW))  {
+                                        lose_follower($importer,$contact,$datarray,$item);
+                                        return;
+                                }
+
+                                if(activity_match($datarray['verb'],ACTIVITY_REQ_FRIEND)) {
+                                        logger('consume-feed: New friend request');
+                                        new_follower($importer,$contact,$datarray,$item,true);
+                                        return;
+                                }
+                                if(activity_match($datarray['verb'],ACTIVITY_UNFRIEND))  {
+                                        lose_sharer($importer,$contact,$datarray,$item);
+                                        return;
+                                }
+
+
+                                if(! is_array($contact))
+                                        return;
+
+                                if(! link_compare($datarray['owner-link'],$contact['url'])) {
+                                        // The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
+                                        // but otherwise there's a possible data mixup on the sender's system.
+                                        // the tgroup delivery code called from item_store will correct it if it's a forum,
+                                        // but we're going to unconditionally correct it here so that the post will always be owned by our contact.
+                                        logger('consume_feed: Correcting item owner.', LOGGER_DEBUG);
+                                        $datarray['owner-name']   = $contact['name'];
+                                        $datarray['owner-link']   = $contact['url'];
+                                        $datarray['owner-avatar'] = $contact['thumb'];
+                                }
+
+                                // We've allowed "followers" to reach this point so we can decide if they are
+                                // posting an @-tag delivery, which followers are allowed to do for certain
+                                // page types. Now that we've parsed the post, let's check if it is legit. Otherwise ignore it.
+
+                                if(($contact['rel'] == CONTACT_IS_FOLLOWER) && (! tgroup_check($importer['uid'],$datarray)))
+                                        continue;
+
+                                // This is my contact on another system, but it's really me.
+                                // Turn this into a wall post.
+                                $notify = item_is_remote_self($contact, $datarray);
+
+*/
+		print_r($item);
+		return;
+		//$item_id = item_store($item);
 
 		if (!$item_id) {
 			logger("Error storing item", LOGGER_DEBUG);
@@ -703,7 +934,9 @@ class dfrn2 {
 				intval($importer["uid"]),
 				intval($contact_id)
 			);
-		if(count($r)) {
+		if(!count($r))
+			logger("Item with uri ".$uri." from contact ".$contact_id." for user ".$importer["uid"]." wasn't found.", LOGGER_DEBUG);
+		else {
 			$item = $r[0];
 
 			if(!$item["deleted"])
@@ -792,6 +1025,11 @@ class dfrn2 {
 						);
 					}
 				}
+				// if this is a relayed delete, propagate it to other recipients
+
+//                                                if($is_a_remote_delete)
+  //                                                      proc_run('php',"include/notifier.php","drop",$item['id']);
+
 			}
 		}
 	}
diff --git a/include/items.php b/include/items.php
index 7df4e0c78a..6ed53ffcd8 100644
--- a/include/items.php
+++ b/include/items.php
@@ -17,7 +17,7 @@ require_once('include/feed.php');
 require_once('include/Contact.php');
 require_once('mod/share.php');
 require_once('include/enotify.php');
-require_once('include/import-dfrn.php');
+//require_once('include/import-dfrn.php');
 
 require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
 
@@ -2407,7 +2407,7 @@ function item_is_remote_self($contact, &$datarray) {
 
 function local_delivery($importer,$data) {
 	// dfrn-Test
-	return dfrn2::import($data, $importer, $contact);
+	//return dfrn2::import($data, $importer, $contact);
 
 	require_once('library/simplepie/simplepie.inc');
 

From 3ea5706d167df8e576bbe6ced0a4caa836f644e0 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 30 Jan 2016 16:37:18 +0100
Subject: [PATCH 010/273] Resolved namespace trouble

---
 include/dfrn.php        |  2 +-
 include/import-dfrn.php | 11 +----------
 2 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index 50d78de3c4..4c1f21dd06 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -383,7 +383,7 @@ class dfrn {
 		if ($alternatelink == "")
 			$alternatelink = $owner['url'];
 
-		$root = $doc->createElementNS(NS_ATOM, 'feed');
+		$root = $doc->createElementNS(NAMESPACE_ATOM1, 'feed');
 		$doc->appendChild($root);
 
 		$root->setAttribute("xmlns:thr", NAMESPACE_THREAD);
diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index 9660d9209c..8a72e40060 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -18,15 +18,6 @@ require_once("include/items.php");
 require_once("include/tags.php");
 require_once("include/files.php");
 
-define("NS_ATOM", "http://www.w3.org/2005/Atom");
-define("NS_THR", "http://purl.org/syndication/thread/1.0");
-define("NS_GEORSS", "http://www.georss.org/georss");
-define("NS_ACTIVITY", "http://activitystrea.ms/spec/1.0/");
-define("NS_MEDIA", "http://purl.org/syndication/atommedia");
-define("NS_POCO", "http://portablecontacts.net/spec/1.0");
-define("NS_OSTATUS", "http://ostatus.org/schema/1.0");
-define("NS_STATUSNET", "http://status.net/schema/api/1/");
-
 class dfrn2 {
 	/**
 	 * @brief Add new birthday event for this person
@@ -236,7 +227,7 @@ class dfrn2 {
 		$obj_doc = new DOMDocument('1.0', 'utf-8');
 		$obj_doc->formatOutput = true;
 
-		$obj_element = $obj_doc->createElementNS(NS_ATOM, $element);
+		$obj_element = $obj_doc->createElementNS(NAMESPACE_ATOM1, $element);
 
 		$activity_type = $xpath->query('activity:object-type/text()', $activity)->item(0)->nodeValue;
 		xml_add_element($obj_doc, $obj_element, "type", $activity_type);

From 447ed7af53d25b080da630283757876b17600ded Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Sun, 31 Jan 2016 12:02:05 +0100
Subject: [PATCH 011/273] IT update to the strings

---
 view/it/messages.po | 2205 +++++++++++++++++++++----------------------
 view/it/strings.php |   77 +-
 2 files changed, 1120 insertions(+), 1162 deletions(-)

diff --git a/view/it/messages.po b/view/it/messages.po
index 5f0129fb0a..b2b88bc72f 100644
--- a/view/it/messages.po
+++ b/view/it/messages.po
@@ -9,15 +9,15 @@
 # fabrixxm <fabrix.xm@gmail.com>, 2011-2012
 # Francesco Apruzzese <cescoap@gmail.com>, 2012-2013
 # ufic <marco@carnazzo.it>, 2012
-# tuscanhobbit <pynolo@tarine.net>, 2012
-# Sandro Santilli <strk@keybit.net>, 2015
+# Paolo Wave <pynolo@tarine.net>, 2012
+# Sandro Santilli <strk@keybit.net>, 2015-2016
 msgid ""
 msgstr ""
 "Project-Id-Version: friendica\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-12-14 07:48+0100\n"
-"PO-Revision-Date: 2015-12-14 13:05+0000\n"
-"Last-Translator: fabrixxm <fabrix.xm@gmail.com>\n"
+"POT-Creation-Date: 2016-01-24 06:49+0100\n"
+"PO-Revision-Date: 2016-01-30 08:43+0000\n"
+"Last-Translator: Sandro Santilli <strk@keybit.net>\n"
 "Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -25,26 +25,26 @@ msgstr ""
 "Language: it\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: mod/contacts.php:50 include/identity.php:380
+#: mod/contacts.php:50 include/identity.php:395
 msgid "Network:"
 msgstr "Rete:"
 
-#: mod/contacts.php:51 mod/contacts.php:986 mod/videos.php:37
-#: mod/viewcontacts.php:105 mod/dirfind.php:208 mod/network.php:596
-#: mod/allfriends.php:72 mod/match.php:82 mod/directory.php:172
-#: mod/common.php:124 mod/suggest.php:95 mod/photos.php:41
-#: include/identity.php:295
+#: mod/contacts.php:51 mod/contacts.php:961 mod/videos.php:37
+#: mod/viewcontacts.php:105 mod/dirfind.php:214 mod/network.php:598
+#: mod/allfriends.php:77 mod/match.php:82 mod/directory.php:172
+#: mod/common.php:123 mod/suggest.php:95 mod/photos.php:41
+#: include/identity.php:298
 msgid "Forum"
 msgstr "Forum"
 
 #: mod/contacts.php:128
 #, php-format
 msgid "%d contact edited."
-msgid_plural "%d contacts edited"
-msgstr[0] "%d contatto modificato"
-msgstr[1] "%d contatti modificati"
+msgid_plural "%d contacts edited."
+msgstr[0] ""
+msgstr[1] ""
 
-#: mod/contacts.php:159 mod/contacts.php:382
+#: mod/contacts.php:159 mod/contacts.php:383
 msgid "Could not access contact record."
 msgstr "Non è possibile accedere al contatto."
 
@@ -56,15 +56,15 @@ msgstr "Non riesco a trovare il profilo selezionato."
 msgid "Contact updated."
 msgstr "Contatto aggiornato."
 
-#: mod/contacts.php:208 mod/dfrn_request.php:578
+#: mod/contacts.php:208 mod/dfrn_request.php:575
 msgid "Failed to update contact record."
 msgstr "Errore nell'aggiornamento del contatto."
 
-#: mod/contacts.php:364 mod/manage.php:96 mod/display.php:496
+#: mod/contacts.php:365 mod/manage.php:96 mod/display.php:509
 #: mod/profile_photo.php:19 mod/profile_photo.php:175
 #: mod/profile_photo.php:186 mod/profile_photo.php:199
-#: mod/ostatus_subscribe.php:9 mod/follow.php:10 mod/follow.php:72
-#: mod/follow.php:137 mod/item.php:169 mod/item.php:185 mod/group.php:19
+#: mod/ostatus_subscribe.php:9 mod/follow.php:11 mod/follow.php:73
+#: mod/follow.php:155 mod/item.php:180 mod/item.php:192 mod/group.php:19
 #: mod/dfrn_confirm.php:55 mod/fsuggest.php:78 mod/wall_upload.php:77
 #: mod/wall_upload.php:80 mod/viewcontacts.php:40 mod/notifications.php:69
 #: mod/message.php:45 mod/message.php:181 mod/crepair.php:117
@@ -72,129 +72,129 @@ msgstr "Errore nell'aggiornamento del contatto."
 #: mod/allfriends.php:12 mod/events.php:165 mod/wallmessage.php:9
 #: mod/wallmessage.php:33 mod/wallmessage.php:79 mod/wallmessage.php:103
 #: mod/wall_attach.php:67 mod/wall_attach.php:70 mod/settings.php:20
-#: mod/settings.php:116 mod/settings.php:637 mod/register.php:42
+#: mod/settings.php:126 mod/settings.php:646 mod/register.php:42
 #: mod/delegate.php:12 mod/common.php:18 mod/mood.php:114 mod/suggest.php:58
 #: mod/profiles.php:165 mod/profiles.php:615 mod/editpost.php:10
 #: mod/api.php:26 mod/api.php:31 mod/notes.php:22 mod/poke.php:149
 #: mod/repair_ostatus.php:9 mod/invite.php:15 mod/invite.php:101
 #: mod/photos.php:171 mod/photos.php:1105 mod/regmod.php:110
-#: mod/uimport.php:23 mod/attach.php:33 include/items.php:5067 index.php:382
+#: mod/uimport.php:23 mod/attach.php:33 include/items.php:5096 index.php:383
 msgid "Permission denied."
 msgstr "Permesso negato."
 
-#: mod/contacts.php:403
+#: mod/contacts.php:404
 msgid "Contact has been blocked"
 msgstr "Il contatto è stato bloccato"
 
-#: mod/contacts.php:403
+#: mod/contacts.php:404
 msgid "Contact has been unblocked"
 msgstr "Il contatto è stato sbloccato"
 
-#: mod/contacts.php:414
+#: mod/contacts.php:415
 msgid "Contact has been ignored"
 msgstr "Il contatto è ignorato"
 
-#: mod/contacts.php:414
+#: mod/contacts.php:415
 msgid "Contact has been unignored"
 msgstr "Il contatto non è più ignorato"
 
-#: mod/contacts.php:426
+#: mod/contacts.php:427
 msgid "Contact has been archived"
 msgstr "Il contatto è stato archiviato"
 
-#: mod/contacts.php:426
+#: mod/contacts.php:427
 msgid "Contact has been unarchived"
 msgstr "Il contatto è stato dearchiviato"
 
-#: mod/contacts.php:453 mod/contacts.php:801
+#: mod/contacts.php:454 mod/contacts.php:802
 msgid "Do you really want to delete this contact?"
 msgstr "Vuoi veramente cancellare questo contatto?"
 
-#: mod/contacts.php:455 mod/follow.php:105 mod/message.php:216
-#: mod/settings.php:1094 mod/settings.php:1100 mod/settings.php:1108
-#: mod/settings.php:1112 mod/settings.php:1117 mod/settings.php:1123
-#: mod/settings.php:1129 mod/settings.php:1135 mod/settings.php:1161
-#: mod/settings.php:1162 mod/settings.php:1163 mod/settings.php:1164
-#: mod/settings.php:1165 mod/dfrn_request.php:850 mod/register.php:238
+#: mod/contacts.php:456 mod/follow.php:110 mod/message.php:216
+#: mod/settings.php:1103 mod/settings.php:1109 mod/settings.php:1117
+#: mod/settings.php:1121 mod/settings.php:1126 mod/settings.php:1132
+#: mod/settings.php:1138 mod/settings.php:1144 mod/settings.php:1170
+#: mod/settings.php:1171 mod/settings.php:1172 mod/settings.php:1173
+#: mod/settings.php:1174 mod/dfrn_request.php:857 mod/register.php:238
 #: mod/suggest.php:29 mod/profiles.php:658 mod/profiles.php:661
-#: mod/profiles.php:687 mod/api.php:105 include/items.php:4899
+#: mod/profiles.php:687 mod/api.php:105 include/items.php:4928
 msgid "Yes"
 msgstr "Si"
 
-#: mod/contacts.php:458 mod/tagrm.php:11 mod/tagrm.php:94 mod/follow.php:116
+#: mod/contacts.php:459 mod/tagrm.php:11 mod/tagrm.php:94 mod/follow.php:121
 #: mod/videos.php:131 mod/message.php:219 mod/fbrowser.php:93
-#: mod/fbrowser.php:128 mod/settings.php:651 mod/settings.php:677
-#: mod/dfrn_request.php:864 mod/suggest.php:32 mod/editpost.php:148
-#: mod/photos.php:247 mod/photos.php:336 include/conversation.php:1221
-#: include/items.php:4902
+#: mod/fbrowser.php:128 mod/settings.php:660 mod/settings.php:686
+#: mod/dfrn_request.php:871 mod/suggest.php:32 mod/editpost.php:148
+#: mod/photos.php:247 mod/photos.php:336 include/conversation.php:1220
+#: include/items.php:4931
 msgid "Cancel"
 msgstr "Annulla"
 
-#: mod/contacts.php:470
+#: mod/contacts.php:471
 msgid "Contact has been removed."
 msgstr "Il contatto è stato rimosso."
 
-#: mod/contacts.php:511
+#: mod/contacts.php:512
 #, php-format
 msgid "You are mutual friends with %s"
 msgstr "Sei amico reciproco con %s"
 
-#: mod/contacts.php:515
+#: mod/contacts.php:516
 #, php-format
 msgid "You are sharing with %s"
 msgstr "Stai condividendo con %s"
 
-#: mod/contacts.php:520
+#: mod/contacts.php:521
 #, php-format
 msgid "%s is sharing with you"
 msgstr "%s sta condividendo con te"
 
-#: mod/contacts.php:540
+#: mod/contacts.php:541
 msgid "Private communications are not available for this contact."
 msgstr "Le comunicazioni private non sono disponibili per questo contatto."
 
-#: mod/contacts.php:543 mod/admin.php:645
+#: mod/contacts.php:544 mod/admin.php:822
 msgid "Never"
 msgstr "Mai"
 
-#: mod/contacts.php:547
+#: mod/contacts.php:548
 msgid "(Update was successful)"
 msgstr "(L'aggiornamento è stato completato)"
 
-#: mod/contacts.php:547
+#: mod/contacts.php:548
 msgid "(Update was not successful)"
 msgstr "(L'aggiornamento non è stato completato)"
 
-#: mod/contacts.php:549
+#: mod/contacts.php:550
 msgid "Suggest friends"
 msgstr "Suggerisci amici"
 
-#: mod/contacts.php:553
+#: mod/contacts.php:554
 #, php-format
 msgid "Network type: %s"
 msgstr "Tipo di rete: %s"
 
-#: mod/contacts.php:566
+#: mod/contacts.php:567
 msgid "Communications lost with this contact!"
 msgstr "Comunicazione con questo contatto persa!"
 
-#: mod/contacts.php:569
+#: mod/contacts.php:570
 msgid "Fetch further information for feeds"
 msgstr "Recupera maggiori infomazioni per i feed"
 
-#: mod/contacts.php:570 mod/admin.php:654
+#: mod/contacts.php:571 mod/admin.php:831
 msgid "Disabled"
 msgstr "Disabilitato"
 
-#: mod/contacts.php:570
+#: mod/contacts.php:571
 msgid "Fetch information"
 msgstr "Recupera informazioni"
 
-#: mod/contacts.php:570
+#: mod/contacts.php:571
 msgid "Fetch information and keywords"
 msgstr "Recupera informazioni e parole chiave"
 
-#: mod/contacts.php:586 mod/manage.php:143 mod/fsuggest.php:107
+#: mod/contacts.php:587 mod/manage.php:143 mod/fsuggest.php:107
 #: mod/message.php:342 mod/message.php:525 mod/crepair.php:196
 #: mod/events.php:574 mod/content.php:712 mod/install.php:261
 #: mod/install.php:299 mod/mood.php:137 mod/profiles.php:696
@@ -204,308 +204,308 @@ msgstr "Recupera informazioni e parole chiave"
 #: object/Item.php:710 view/theme/cleanzero/config.php:80
 #: view/theme/dispy/config.php:70 view/theme/quattro/config.php:64
 #: view/theme/diabook/config.php:148 view/theme/diabook/theme.php:633
-#: view/theme/clean/config.php:83 view/theme/vier/config.php:107
-#: view/theme/duepuntozero/config.php:59
+#: view/theme/vier/config.php:107 view/theme/duepuntozero/config.php:59
 msgid "Submit"
 msgstr "Invia"
 
-#: mod/contacts.php:587
+#: mod/contacts.php:588
 msgid "Profile Visibility"
 msgstr "Visibilità del profilo"
 
-#: mod/contacts.php:588
+#: mod/contacts.php:589
 #, php-format
 msgid ""
 "Please choose the profile you would like to display to %s when viewing your "
 "profile securely."
 msgstr "Seleziona il profilo che vuoi mostrare a %s quando visita il tuo profilo in modo sicuro."
 
-#: mod/contacts.php:589
+#: mod/contacts.php:590
 msgid "Contact Information / Notes"
 msgstr "Informazioni / Note sul contatto"
 
-#: mod/contacts.php:590
+#: mod/contacts.php:591
 msgid "Edit contact notes"
 msgstr "Modifica note contatto"
 
-#: mod/contacts.php:595 mod/contacts.php:977 mod/viewcontacts.php:97
+#: mod/contacts.php:596 mod/contacts.php:952 mod/viewcontacts.php:97
 #: mod/nogroup.php:41
 #, php-format
 msgid "Visit %s's profile [%s]"
 msgstr "Visita il profilo di %s [%s]"
 
-#: mod/contacts.php:596
+#: mod/contacts.php:597
 msgid "Block/Unblock contact"
 msgstr "Blocca/Sblocca contatto"
 
-#: mod/contacts.php:597
+#: mod/contacts.php:598
 msgid "Ignore contact"
 msgstr "Ignora il contatto"
 
-#: mod/contacts.php:598
+#: mod/contacts.php:599
 msgid "Repair URL settings"
 msgstr "Impostazioni riparazione URL"
 
-#: mod/contacts.php:599
+#: mod/contacts.php:600
 msgid "View conversations"
 msgstr "Vedi conversazioni"
 
-#: mod/contacts.php:601
+#: mod/contacts.php:602
 msgid "Delete contact"
 msgstr "Rimuovi contatto"
 
-#: mod/contacts.php:605
+#: mod/contacts.php:606
 msgid "Last update:"
 msgstr "Ultimo aggiornamento:"
 
-#: mod/contacts.php:607
+#: mod/contacts.php:608
 msgid "Update public posts"
 msgstr "Aggiorna messaggi pubblici"
 
-#: mod/contacts.php:609 mod/admin.php:1653
+#: mod/contacts.php:610
 msgid "Update now"
 msgstr "Aggiorna adesso"
 
-#: mod/contacts.php:611 mod/dirfind.php:190 mod/allfriends.php:60
-#: mod/match.php:71 mod/suggest.php:82 include/contact_widgets.php:32
-#: include/Contact.php:321 include/conversation.php:924
+#: mod/contacts.php:612 mod/follow.php:103 mod/dirfind.php:196
+#: mod/allfriends.php:65 mod/match.php:71 mod/suggest.php:82
+#: include/contact_widgets.php:32 include/Contact.php:297
+#: include/conversation.php:924
 msgid "Connect/Follow"
 msgstr "Connetti/segui"
 
-#: mod/contacts.php:614 mod/contacts.php:805 mod/contacts.php:864
-#: mod/admin.php:1117
+#: mod/contacts.php:615 mod/contacts.php:806 mod/contacts.php:865
+#: mod/admin.php:1312
 msgid "Unblock"
 msgstr "Sblocca"
 
-#: mod/contacts.php:614 mod/contacts.php:805 mod/contacts.php:864
-#: mod/admin.php:1116
+#: mod/contacts.php:615 mod/contacts.php:806 mod/contacts.php:865
+#: mod/admin.php:1311
 msgid "Block"
 msgstr "Blocca"
 
-#: mod/contacts.php:615 mod/contacts.php:806 mod/contacts.php:871
+#: mod/contacts.php:616 mod/contacts.php:807 mod/contacts.php:872
 msgid "Unignore"
 msgstr "Non ignorare"
 
-#: mod/contacts.php:615 mod/contacts.php:806 mod/contacts.php:871
+#: mod/contacts.php:616 mod/contacts.php:807 mod/contacts.php:872
 #: mod/notifications.php:54 mod/notifications.php:179
 #: mod/notifications.php:259
 msgid "Ignore"
 msgstr "Ignora"
 
-#: mod/contacts.php:618
+#: mod/contacts.php:619
 msgid "Currently blocked"
 msgstr "Bloccato"
 
-#: mod/contacts.php:619
+#: mod/contacts.php:620
 msgid "Currently ignored"
 msgstr "Ignorato"
 
-#: mod/contacts.php:620
+#: mod/contacts.php:621
 msgid "Currently archived"
 msgstr "Al momento archiviato"
 
-#: mod/contacts.php:621 mod/notifications.php:172 mod/notifications.php:251
+#: mod/contacts.php:622 mod/notifications.php:172 mod/notifications.php:251
 msgid "Hide this contact from others"
 msgstr "Nascondi questo contatto agli altri"
 
-#: mod/contacts.php:621
+#: mod/contacts.php:622
 msgid ""
 "Replies/likes to your public posts <strong>may</strong> still be visible"
 msgstr "Risposte ai tuoi post pubblici <strong>possono</strong> essere comunque visibili"
 
-#: mod/contacts.php:622
+#: mod/contacts.php:623
 msgid "Notification for new posts"
 msgstr "Notifica per i nuovi messaggi"
 
-#: mod/contacts.php:622
+#: mod/contacts.php:623
 msgid "Send a notification of every new post of this contact"
 msgstr "Invia una notifica per ogni nuovo messaggio di questo contatto"
 
-#: mod/contacts.php:625
+#: mod/contacts.php:626
 msgid "Blacklisted keywords"
 msgstr "Parole chiave in blacklist"
 
-#: mod/contacts.php:625
+#: mod/contacts.php:626
 msgid ""
 "Comma separated list of keywords that should not be converted to hashtags, "
 "when \"Fetch information and keywords\" is selected"
 msgstr "Lista separata da virgola di parole chiave che non dovranno essere convertite in hastag, quando \"Recupera informazioni e parole chiave\" è selezionato"
 
-#: mod/contacts.php:632 mod/follow.php:121 mod/notifications.php:255
+#: mod/contacts.php:633 mod/follow.php:126 mod/notifications.php:255
 msgid "Profile URL"
 msgstr "URL Profilo"
 
-#: mod/contacts.php:635 mod/follow.php:125 mod/notifications.php:244
-#: mod/events.php:566 mod/directory.php:145 include/identity.php:304
-#: include/bb2diaspora.php:170 include/event.php:36 include/event.php:60
+#: mod/contacts.php:636 mod/notifications.php:244 mod/events.php:566
+#: mod/directory.php:145 include/identity.php:308 include/bb2diaspora.php:170
+#: include/event.php:36 include/event.php:60
 msgid "Location:"
 msgstr "Posizione:"
 
-#: mod/contacts.php:637 mod/follow.php:127 mod/notifications.php:246
-#: mod/directory.php:153 include/identity.php:313 include/identity.php:621
+#: mod/contacts.php:638 mod/notifications.php:246 mod/directory.php:153
+#: include/identity.php:317 include/identity.php:631
 msgid "About:"
 msgstr "Informazioni:"
 
-#: mod/contacts.php:639 mod/follow.php:129 mod/notifications.php:248
-#: include/identity.php:615
+#: mod/contacts.php:640 mod/follow.php:134 mod/notifications.php:248
+#: include/identity.php:625
 msgid "Tags:"
 msgstr "Tag:"
 
-#: mod/contacts.php:684
+#: mod/contacts.php:685
 msgid "Suggestions"
 msgstr "Suggerimenti"
 
-#: mod/contacts.php:687
+#: mod/contacts.php:688
 msgid "Suggest potential friends"
 msgstr "Suggerisci potenziali amici"
 
-#: mod/contacts.php:692 mod/group.php:192
+#: mod/contacts.php:693 mod/group.php:192
 msgid "All Contacts"
 msgstr "Tutti i contatti"
 
-#: mod/contacts.php:695
+#: mod/contacts.php:696
 msgid "Show all contacts"
 msgstr "Mostra tutti i contatti"
 
-#: mod/contacts.php:700
+#: mod/contacts.php:701
 msgid "Unblocked"
 msgstr "Sbloccato"
 
-#: mod/contacts.php:703
+#: mod/contacts.php:704
 msgid "Only show unblocked contacts"
 msgstr "Mostra solo contatti non bloccati"
 
-#: mod/contacts.php:709
+#: mod/contacts.php:710
 msgid "Blocked"
 msgstr "Bloccato"
 
-#: mod/contacts.php:712
+#: mod/contacts.php:713
 msgid "Only show blocked contacts"
 msgstr "Mostra solo contatti bloccati"
 
-#: mod/contacts.php:718
+#: mod/contacts.php:719
 msgid "Ignored"
 msgstr "Ignorato"
 
-#: mod/contacts.php:721
+#: mod/contacts.php:722
 msgid "Only show ignored contacts"
 msgstr "Mostra solo contatti ignorati"
 
-#: mod/contacts.php:727
+#: mod/contacts.php:728
 msgid "Archived"
 msgstr "Achiviato"
 
-#: mod/contacts.php:730
+#: mod/contacts.php:731
 msgid "Only show archived contacts"
 msgstr "Mostra solo contatti archiviati"
 
-#: mod/contacts.php:736
+#: mod/contacts.php:737
 msgid "Hidden"
 msgstr "Nascosto"
 
-#: mod/contacts.php:739
+#: mod/contacts.php:740
 msgid "Only show hidden contacts"
 msgstr "Mostra solo contatti nascosti"
 
-#: mod/contacts.php:792 mod/contacts.php:840 mod/viewcontacts.php:116
-#: include/identity.php:732 include/identity.php:735 include/text.php:1012
+#: mod/contacts.php:793 mod/contacts.php:841 mod/viewcontacts.php:116
+#: include/identity.php:741 include/identity.php:744 include/text.php:1012
 #: include/nav.php:123 include/nav.php:187 view/theme/diabook/theme.php:125
 msgid "Contacts"
 msgstr "Contatti"
 
-#: mod/contacts.php:796
+#: mod/contacts.php:797
 msgid "Search your contacts"
 msgstr "Cerca nei tuoi contatti"
 
-#: mod/contacts.php:797
+#: mod/contacts.php:798
 msgid "Finding: "
 msgstr "Ricerca: "
 
-#: mod/contacts.php:798 mod/directory.php:210 include/contact_widgets.php:34
+#: mod/contacts.php:799 mod/directory.php:210 include/contact_widgets.php:34
 msgid "Find"
 msgstr "Trova"
 
-#: mod/contacts.php:804 mod/settings.php:146 mod/settings.php:676
+#: mod/contacts.php:805 mod/settings.php:156 mod/settings.php:685
 msgid "Update"
 msgstr "Aggiorna"
 
-#: mod/contacts.php:807 mod/contacts.php:878
+#: mod/contacts.php:808 mod/contacts.php:879
 msgid "Archive"
 msgstr "Archivia"
 
-#: mod/contacts.php:807 mod/contacts.php:878
+#: mod/contacts.php:808 mod/contacts.php:879
 msgid "Unarchive"
 msgstr "Dearchivia"
 
-#: mod/contacts.php:808 mod/group.php:171 mod/admin.php:1115
-#: mod/content.php:440 mod/content.php:743 mod/settings.php:713
+#: mod/contacts.php:809 mod/group.php:171 mod/admin.php:1310
+#: mod/content.php:440 mod/content.php:743 mod/settings.php:722
 #: mod/photos.php:1723 object/Item.php:134 include/conversation.php:635
 msgid "Delete"
 msgstr "Rimuovi"
 
-#: mod/contacts.php:821 include/identity.php:677 include/nav.php:75
+#: mod/contacts.php:822 include/identity.php:686 include/nav.php:75
 msgid "Status"
 msgstr "Stato"
 
-#: mod/contacts.php:824 include/identity.php:680
+#: mod/contacts.php:825 mod/follow.php:143 include/identity.php:689
 msgid "Status Messages and Posts"
 msgstr "Messaggi di stato e post"
 
-#: mod/contacts.php:829 mod/profperm.php:104 mod/newmember.php:32
-#: include/identity.php:569 include/identity.php:655 include/identity.php:685
+#: mod/contacts.php:830 mod/profperm.php:104 mod/newmember.php:32
+#: include/identity.php:579 include/identity.php:665 include/identity.php:694
 #: include/nav.php:76 view/theme/diabook/theme.php:124
 msgid "Profile"
 msgstr "Profilo"
 
-#: mod/contacts.php:832 include/identity.php:688
+#: mod/contacts.php:833 include/identity.php:697
 msgid "Profile Details"
 msgstr "Dettagli del profilo"
 
-#: mod/contacts.php:843
+#: mod/contacts.php:844
 msgid "View all contacts"
 msgstr "Vedi tutti i contatti"
 
-#: mod/contacts.php:849 mod/common.php:135
+#: mod/contacts.php:850 mod/common.php:134
 msgid "Common Friends"
 msgstr "Amici in comune"
 
-#: mod/contacts.php:852
+#: mod/contacts.php:853
 msgid "View all common friends"
 msgstr "Vedi tutti gli amici in comune"
 
-#: mod/contacts.php:856
+#: mod/contacts.php:857
 msgid "Repair"
 msgstr "Ripara"
 
-#: mod/contacts.php:859
+#: mod/contacts.php:860
 msgid "Advanced Contact Settings"
 msgstr "Impostazioni avanzate Contatto"
 
-#: mod/contacts.php:867
+#: mod/contacts.php:868
 msgid "Toggle Blocked status"
 msgstr "Inverti stato \"Blocca\""
 
-#: mod/contacts.php:874
+#: mod/contacts.php:875
 msgid "Toggle Ignored status"
 msgstr "Inverti stato \"Ignora\""
 
-#: mod/contacts.php:881
+#: mod/contacts.php:882
 msgid "Toggle Archive status"
 msgstr "Inverti stato \"Archiviato\""
 
-#: mod/contacts.php:949
+#: mod/contacts.php:924
 msgid "Mutual Friendship"
 msgstr "Amicizia reciproca"
 
-#: mod/contacts.php:953
+#: mod/contacts.php:928
 msgid "is a fan of yours"
 msgstr "è un tuo fan"
 
-#: mod/contacts.php:957
+#: mod/contacts.php:932
 msgid "you are a fan of"
 msgstr "sei un fan di"
 
-#: mod/contacts.php:978 mod/nogroup.php:42
+#: mod/contacts.php:953 mod/nogroup.php:42
 msgid "Edit contact"
 msgstr "Modifca contatto"
 
@@ -531,7 +531,7 @@ msgstr "Seleziona un'identità da gestire:"
 msgid "Post successful."
 msgstr "Inviato!"
 
-#: mod/profperm.php:19 mod/group.php:72 index.php:381
+#: mod/profperm.php:19 mod/group.php:72 index.php:382
 msgid "Permission denied"
 msgstr "Permesso negato"
 
@@ -555,23 +555,23 @@ msgstr "Visibile a"
 msgid "All Contacts (with secure profile access)"
 msgstr "Tutti i contatti (con profilo ad accesso sicuro)"
 
-#: mod/display.php:82 mod/display.php:283 mod/display.php:500
-#: mod/viewsrc.php:15 mod/admin.php:196 mod/admin.php:1160 mod/admin.php:1381
-#: mod/notice.php:15 include/items.php:4858
+#: mod/display.php:82 mod/display.php:291 mod/display.php:513
+#: mod/viewsrc.php:15 mod/admin.php:234 mod/admin.php:1365 mod/admin.php:1599
+#: mod/notice.php:15 include/items.php:4887
 msgid "Item not found."
 msgstr "Elemento non trovato."
 
-#: mod/display.php:211 mod/videos.php:197 mod/viewcontacts.php:35
-#: mod/community.php:18 mod/dfrn_request.php:779 mod/search.php:93
+#: mod/display.php:220 mod/videos.php:197 mod/viewcontacts.php:35
+#: mod/community.php:22 mod/dfrn_request.php:786 mod/search.php:93
 #: mod/search.php:99 mod/directory.php:37 mod/photos.php:976
 msgid "Public access denied."
 msgstr "Accesso negato."
 
-#: mod/display.php:331 mod/profile.php:155
+#: mod/display.php:339 mod/profile.php:155
 msgid "Access to this profile has been restricted."
 msgstr "L'accesso a questo profilo è stato limitato."
 
-#: mod/display.php:493
+#: mod/display.php:506
 msgid "Item has been removed."
 msgstr "L'oggetto è stato rimosso."
 
@@ -606,8 +606,8 @@ msgid ""
 " join."
 msgstr "Sulla tua pagina <em>Quick Start</em> - veloce introduzione alla tua pagina profilo e alla pagina Rete, fai qualche nuova amicizia, e trova qualche gruppo a cui unirti."
 
-#: mod/newmember.php:22 mod/admin.php:1212 mod/admin.php:1457
-#: mod/settings.php:99 include/nav.php:182 view/theme/diabook/theme.php:544
+#: mod/newmember.php:22 mod/admin.php:1418 mod/admin.php:1676
+#: mod/settings.php:109 include/nav.php:182 view/theme/diabook/theme.php:544
 #: view/theme/diabook/theme.php:648
 msgid "Settings"
 msgstr "Impostazioni"
@@ -668,60 +668,44 @@ msgstr "Inserisci qualche parola chiave pubblica nel tuo profilo predefinito che
 msgid "Connecting"
 msgstr "Collegarsi"
 
-#: mod/newmember.php:49 mod/newmember.php:51 include/contact_selectors.php:81
-msgid "Facebook"
-msgstr "Facebook"
-
-#: mod/newmember.php:49
-msgid ""
-"Authorise the Facebook Connector if you currently have a Facebook account "
-"and we will (optionally) import all your Facebook friends and conversations."
-msgstr "Autorizza il Facebook Connector se hai un account Facebook, e noi (opzionalmente) importeremo tuti i tuoi amici e le tue conversazioni da Facebook."
-
 #: mod/newmember.php:51
-msgid ""
-"<em>If</em> this is your own personal server, installing the Facebook addon "
-"may ease your transition to the free social web."
-msgstr "<em>Se</em questo è il tuo server personale, installare il plugin per Facebook puo' aiutarti nella transizione verso il web sociale libero."
-
-#: mod/newmember.php:56
 msgid "Importing Emails"
 msgstr "Importare le Email"
 
-#: mod/newmember.php:56
+#: mod/newmember.php:51
 msgid ""
 "Enter your email access information on your Connector Settings page if you "
 "wish to import and interact with friends or mailing lists from your email "
 "INBOX"
 msgstr "Inserisci i tuoi dati di accesso all'email nella tua pagina Impostazioni Connettori se vuoi importare e interagire con amici o mailing list dalla tua casella di posta in arrivo"
 
-#: mod/newmember.php:58
+#: mod/newmember.php:53
 msgid "Go to Your Contacts Page"
 msgstr "Vai alla tua pagina Contatti"
 
-#: mod/newmember.php:58
+#: mod/newmember.php:53
 msgid ""
 "Your Contacts page is your gateway to managing friendships and connecting "
 "with friends on other networks. Typically you enter their address or site "
 "URL in the <em>Add New Contact</em> dialog."
 msgstr "La tua pagina Contatti è il mezzo per gestire le amicizie e collegarsi con amici su altre reti. Di solito, basta inserire l'indirizzo nel campo <em>Aggiungi Nuovo Contatto</em>"
 
-#: mod/newmember.php:60
+#: mod/newmember.php:55
 msgid "Go to Your Site's Directory"
 msgstr "Vai all'Elenco del tuo sito"
 
-#: mod/newmember.php:60
+#: mod/newmember.php:55
 msgid ""
 "The Directory page lets you find other people in this network or other "
 "federated sites. Look for a <em>Connect</em> or <em>Follow</em> link on "
 "their profile page. Provide your own Identity Address if requested."
 msgstr "La pagina Elenco ti permette di trovare altre persone in questa rete o in altri siti. Cerca un link <em>Connetti</em> o <em>Segui</em> nella loro pagina del profilo. Inserisci il tuo Indirizzo Identità, se richiesto."
 
-#: mod/newmember.php:62
+#: mod/newmember.php:57
 msgid "Finding New People"
 msgstr "Trova nuove persone"
 
-#: mod/newmember.php:62
+#: mod/newmember.php:57
 msgid ""
 "On the side panel of the Contacts page are several tools to find new "
 "friends. We can match people by interest, look up people by name or "
@@ -730,41 +714,41 @@ msgid ""
 "hours."
 msgstr "Nel pannello laterale nella pagina \"Contatti\", ci sono diversi strumenti per trovare nuovi amici. Possiamo confrontare le persone per interessi, cercare le persone per nome e fornire suggerimenti basati sui tuoi contatti esistenti. Su un sito nuovo, i suggerimenti sono di solito presenti dopo 24 ore."
 
-#: mod/newmember.php:66 include/group.php:283
+#: mod/newmember.php:61 include/group.php:283
 msgid "Groups"
 msgstr "Gruppi"
 
-#: mod/newmember.php:70
+#: mod/newmember.php:65
 msgid "Group Your Contacts"
 msgstr "Raggruppa i tuoi contatti"
 
-#: mod/newmember.php:70
+#: mod/newmember.php:65
 msgid ""
 "Once you have made some friends, organize them into private conversation "
 "groups from the sidebar of your Contacts page and then you can interact with"
 " each group privately on your Network page."
 msgstr "Quando avrai alcuni amici, organizzali in gruppi di conversazioni private dalla barra laterale della tua pagina Contatti. Potrai interagire privatamente con ogni gruppo nella tua pagina Rete"
 
-#: mod/newmember.php:73
+#: mod/newmember.php:68
 msgid "Why Aren't My Posts Public?"
 msgstr "Perchè i miei post non sono pubblici?"
 
-#: mod/newmember.php:73
+#: mod/newmember.php:68
 msgid ""
 "Friendica respects your privacy. By default, your posts will only show up to"
 " people you've added as friends. For more information, see the help section "
 "from the link above."
 msgstr "Friendica rispetta la tua provacy. Per impostazione predefinita, i tuoi post sono mostrati solo alle persone che hai aggiunto come amici. Per maggiori informazioni guarda la sezione della guida dal link qui sopra."
 
-#: mod/newmember.php:78
+#: mod/newmember.php:73
 msgid "Getting Help"
 msgstr "Ottenere Aiuto"
 
-#: mod/newmember.php:82
+#: mod/newmember.php:77
 msgid "Go to the Help Section"
 msgstr "Vai alla sezione Guida"
 
-#: mod/newmember.php:82
+#: mod/newmember.php:77
 msgid ""
 "Our <strong>help</strong> pages may be consulted for detail on other program"
 " features and resources."
@@ -779,7 +763,7 @@ msgid ""
 "Account not found and OpenID registration is not permitted on this site."
 msgstr "L'account non è stato trovato, e la registrazione via OpenID non è permessa su questo sito."
 
-#: mod/openid.php:93 include/auth.php:112 include/auth.php:175
+#: mod/openid.php:93 include/auth.php:118 include/auth.php:181
 msgid "Login failed."
 msgstr "Accesso fallito."
 
@@ -865,18 +849,18 @@ msgstr "Immagine caricata con successo."
 msgid "Image upload failed."
 msgstr "Caricamento immagine fallito."
 
-#: mod/subthread.php:87 mod/tagger.php:62 mod/like.php:168
+#: mod/subthread.php:87 mod/tagger.php:62 include/like.php:165
 #: include/conversation.php:130 include/conversation.php:266
-#: include/text.php:1993 include/diaspora.php:2146
+#: include/text.php:2000 include/diaspora.php:2169
 #: view/theme/diabook/theme.php:471
 msgid "photo"
 msgstr "foto"
 
-#: mod/subthread.php:87 mod/tagger.php:62 mod/like.php:168 mod/like.php:346
-#: include/conversation.php:125 include/conversation.php:134
-#: include/conversation.php:261 include/conversation.php:270
-#: include/diaspora.php:2146 view/theme/diabook/theme.php:466
-#: view/theme/diabook/theme.php:475
+#: mod/subthread.php:87 mod/tagger.php:62 include/like.php:165
+#: include/like.php:334 include/conversation.php:125
+#: include/conversation.php:134 include/conversation.php:261
+#: include/conversation.php:270 include/diaspora.php:2169
+#: view/theme/diabook/theme.php:466 view/theme/diabook/theme.php:475
 msgid "status"
 msgstr "stato"
 
@@ -902,8 +886,8 @@ msgid "Remove"
 msgstr "Rimuovi"
 
 #: mod/ostatus_subscribe.php:14
-msgid "Subsribing to OStatus contacts"
-msgstr "Iscrizione a contatti OStatus"
+msgid "Subscribing to OStatus contacts"
+msgstr ""
 
 #: mod/ostatus_subscribe.php:25
 msgid "No contact provided."
@@ -937,8 +921,8 @@ msgstr "ignorato"
 msgid "Keep this window open until done."
 msgstr "Tieni questa finestra aperta fino a che ha finito."
 
-#: mod/filer.php:30 include/conversation.php:1133
-#: include/conversation.php:1151
+#: mod/filer.php:30 include/conversation.php:1132
+#: include/conversation.php:1150
 msgid "Save to Folder:"
 msgstr "Salva nella Cartella:"
 
@@ -951,54 +935,54 @@ msgstr "- seleziona -"
 msgid "Save"
 msgstr "Salva"
 
-#: mod/follow.php:18 mod/dfrn_request.php:863
+#: mod/follow.php:19 mod/dfrn_request.php:870
 msgid "Submit Request"
 msgstr "Invia richiesta"
 
-#: mod/follow.php:29
+#: mod/follow.php:30
 msgid "You already added this contact."
 msgstr "Hai già aggiunto questo contatto."
 
-#: mod/follow.php:38
+#: mod/follow.php:39
 msgid "Diaspora support isn't enabled. Contact can't be added."
 msgstr "Il supporto Diaspora non è abilitato. Il contatto non puo' essere aggiunto."
 
-#: mod/follow.php:45
+#: mod/follow.php:46
 msgid "OStatus support is disabled. Contact can't be added."
 msgstr "Il supporto OStatus non è abilitato. Il contatto non puo' essere aggiunto."
 
-#: mod/follow.php:52
+#: mod/follow.php:53
 msgid "The network type couldn't be detected. Contact can't be added."
 msgstr "Non è possibile rilevare il tipo di rete. Il contatto non puo' essere aggiunto."
 
-#: mod/follow.php:104 mod/dfrn_request.php:849
+#: mod/follow.php:109 mod/dfrn_request.php:856
 msgid "Please answer the following:"
 msgstr "Rispondi:"
 
-#: mod/follow.php:105 mod/dfrn_request.php:850
+#: mod/follow.php:110 mod/dfrn_request.php:857
 #, php-format
 msgid "Does %s know you?"
 msgstr "%s ti conosce?"
 
-#: mod/follow.php:105 mod/settings.php:1094 mod/settings.php:1100
-#: mod/settings.php:1108 mod/settings.php:1112 mod/settings.php:1117
-#: mod/settings.php:1123 mod/settings.php:1129 mod/settings.php:1135
-#: mod/settings.php:1161 mod/settings.php:1162 mod/settings.php:1163
-#: mod/settings.php:1164 mod/settings.php:1165 mod/dfrn_request.php:850
+#: mod/follow.php:110 mod/settings.php:1103 mod/settings.php:1109
+#: mod/settings.php:1117 mod/settings.php:1121 mod/settings.php:1126
+#: mod/settings.php:1132 mod/settings.php:1138 mod/settings.php:1144
+#: mod/settings.php:1170 mod/settings.php:1171 mod/settings.php:1172
+#: mod/settings.php:1173 mod/settings.php:1174 mod/dfrn_request.php:857
 #: mod/register.php:239 mod/profiles.php:658 mod/profiles.php:662
 #: mod/profiles.php:687 mod/api.php:106
 msgid "No"
 msgstr "No"
 
-#: mod/follow.php:106 mod/dfrn_request.php:854
+#: mod/follow.php:111 mod/dfrn_request.php:861
 msgid "Add a personal note:"
 msgstr "Aggiungi una nota personale:"
 
-#: mod/follow.php:112 mod/dfrn_request.php:860
+#: mod/follow.php:117 mod/dfrn_request.php:867
 msgid "Your Identity Address:"
 msgstr "L'indirizzo della tua identità:"
 
-#: mod/follow.php:162
+#: mod/follow.php:180
 msgid "Contact added"
 msgstr "Contatto aggiunto"
 
@@ -1006,39 +990,39 @@ msgstr "Contatto aggiunto"
 msgid "Unable to locate original post."
 msgstr "Impossibile trovare il messaggio originale."
 
-#: mod/item.php:322
+#: mod/item.php:329
 msgid "Empty post discarded."
 msgstr "Messaggio vuoto scartato."
 
-#: mod/item.php:460 mod/wall_upload.php:213 mod/wall_upload.php:227
-#: mod/wall_upload.php:234 include/Photo.php:954 include/Photo.php:969
-#: include/Photo.php:976 include/Photo.php:998 include/message.php:145
+#: mod/item.php:467 mod/wall_upload.php:213 mod/wall_upload.php:227
+#: mod/wall_upload.php:234 include/Photo.php:958 include/Photo.php:973
+#: include/Photo.php:980 include/Photo.php:1002 include/message.php:145
 msgid "Wall Photos"
 msgstr "Foto della bacheca"
 
-#: mod/item.php:834
+#: mod/item.php:842
 msgid "System error. Post not saved."
 msgstr "Errore di sistema. Messaggio non salvato."
 
-#: mod/item.php:963
+#: mod/item.php:971
 #, php-format
 msgid ""
 "This message was sent to you by %s, a member of the Friendica social "
 "network."
 msgstr "Questo messaggio ti è stato inviato da %s, un membro del social network Friendica."
 
-#: mod/item.php:965
+#: mod/item.php:973
 #, php-format
 msgid "You may visit them online at %s"
 msgstr "Puoi visitarli online su %s"
 
-#: mod/item.php:966
+#: mod/item.php:974
 msgid ""
 "Please contact the sender by replying to this post if you do not wish to "
 "receive these messages."
 msgstr "Contatta il mittente rispondendo a questo post se non vuoi ricevere questi messaggi."
 
-#: mod/item.php:970
+#: mod/item.php:978
 #, php-format
 msgid "%s posted an update."
 msgstr "%s ha inviato un aggiornamento."
@@ -1087,11 +1071,11 @@ msgstr "Modifica gruppo"
 msgid "Members"
 msgstr "Membri"
 
-#: mod/group.php:193 mod/network.php:563 mod/content.php:130
+#: mod/group.php:193 mod/network.php:576 mod/content.php:130
 msgid "Group is empty"
 msgstr "Il gruppo è vuoto"
 
-#: mod/apps.php:7 index.php:225
+#: mod/apps.php:7 index.php:226
 msgid "You must be logged in to use addons. "
 msgstr "Devi aver effettuato il login per usare gli addons."
 
@@ -1148,7 +1132,7 @@ msgid "Unable to set contact photo."
 msgstr "Impossibile impostare la foto del contatto."
 
 #: mod/dfrn_confirm.php:487 include/conversation.php:185
-#: include/diaspora.php:636
+#: include/diaspora.php:637
 #, php-format
 msgid "%1$s is now friends with %2$s"
 msgstr "%1$s e %2$s adesso sono amici"
@@ -1189,7 +1173,7 @@ msgstr "Impossibile impostare le credenziali del tuo contatto sul nostro sistema
 msgid "Unable to update your contact profile details on our system"
 msgstr "Impossibile aggiornare i dettagli del tuo contatto sul nostro sistema"
 
-#: mod/dfrn_confirm.php:753 mod/dfrn_request.php:734 include/items.php:4270
+#: mod/dfrn_confirm.php:753 mod/dfrn_request.php:741 include/items.php:4299
 msgid "[Name Withheld]"
 msgstr "[Nome Nascosto]"
 
@@ -1198,7 +1182,7 @@ msgstr "[Nome Nascosto]"
 msgid "%1$s has joined %2$s"
 msgstr "%1$s si è unito a %2$s"
 
-#: mod/profile.php:21 include/identity.php:52
+#: mod/profile.php:21 include/identity.php:51
 msgid "Requested profile is not available."
 msgstr "Profilo richiesto non disponibile."
 
@@ -1222,7 +1206,7 @@ msgstr "Nessun video selezionato"
 msgid "Access to this item is restricted."
 msgstr "Questo oggetto non è visibile a tutti."
 
-#: mod/videos.php:383 include/text.php:1465
+#: mod/videos.php:383 include/text.php:1472
 msgid "View Video"
 msgstr "Guarda Video"
 
@@ -1258,7 +1242,7 @@ msgstr "Suggerisci un amico a %s"
 
 #: mod/wall_upload.php:20 mod/wall_upload.php:33 mod/wall_upload.php:86
 #: mod/wall_upload.php:122 mod/wall_upload.php:125 mod/wall_attach.php:17
-#: mod/wall_attach.php:25 mod/wall_attach.php:76 include/api.php:1733
+#: mod/wall_attach.php:25 mod/wall_attach.php:76 include/api.php:1781
 msgid "Invalid request."
 msgstr "Richiesta non valida."
 
@@ -1314,7 +1298,7 @@ msgid ""
 "Password reset failed."
 msgstr "La richiesta non può essere verificata. (Puoi averla già richiesta precendentemente). Reimpostazione password fallita."
 
-#: mod/lostpass.php:109 boot.php:1307
+#: mod/lostpass.php:109 boot.php:1444
 msgid "Password Reset"
 msgstr "Reimpostazione password"
 
@@ -1388,37 +1372,6 @@ msgstr "Nome utente o email: "
 msgid "Reset"
 msgstr "Reimposta"
 
-#: mod/like.php:170 include/conversation.php:122 include/conversation.php:258
-#: include/text.php:1991 view/theme/diabook/theme.php:463
-msgid "event"
-msgstr "l'evento"
-
-#: mod/like.php:187 include/conversation.php:141 include/diaspora.php:2162
-#: view/theme/diabook/theme.php:480
-#, php-format
-msgid "%1$s likes %2$s's %3$s"
-msgstr "A %1$s piace %3$s di %2$s"
-
-#: mod/like.php:189 include/conversation.php:144
-#, php-format
-msgid "%1$s doesn't like %2$s's %3$s"
-msgstr "A %1$s non piace %3$s di %2$s"
-
-#: mod/like.php:191
-#, php-format
-msgid "%1$s is attending %2$s's %3$s"
-msgstr "%1$s parteciperà a %3$s di %2$s"
-
-#: mod/like.php:193
-#, php-format
-msgid "%1$s is not attending %2$s's %3$s"
-msgstr "%1$s non parteciperà a %3$s di %2$s"
-
-#: mod/like.php:195
-#, php-format
-msgid "%1$s may attend %2$s's %3$s"
-msgstr "%1$s forse parteciperà a %3$s di %2$s"
-
 #: mod/ping.php:265
 msgid "{0} wants to be your friend"
 msgstr "{0} vuole essere tuo amico"
@@ -1448,11 +1401,11 @@ msgstr "Scarta"
 msgid "System"
 msgstr "Sistema"
 
-#: mod/notifications.php:87 mod/admin.php:228 include/nav.php:154
+#: mod/notifications.php:87 mod/admin.php:390 include/nav.php:154
 msgid "Network"
 msgstr "Rete"
 
-#: mod/notifications.php:93 mod/network.php:381
+#: mod/notifications.php:93 mod/network.php:384
 msgid "Personal"
 msgstr "Personale"
 
@@ -1494,7 +1447,7 @@ msgstr "Invia una attività \"è ora amico con\""
 msgid "if applicable"
 msgstr "se applicabile"
 
-#: mod/notifications.php:176 mod/notifications.php:257 mod/admin.php:1113
+#: mod/notifications.php:176 mod/notifications.php:257 mod/admin.php:1308
 msgid "Approve"
 msgstr "Approva"
 
@@ -1544,8 +1497,8 @@ msgstr "Richiesta amicizia/connessione"
 msgid "New Follower"
 msgstr "Qualcuno inizia a seguirti"
 
-#: mod/notifications.php:250 mod/directory.php:147 include/identity.php:306
-#: include/identity.php:580
+#: mod/notifications.php:250 mod/directory.php:147 include/identity.php:310
+#: include/identity.php:590
 msgid "Gender:"
 msgstr "Genere:"
 
@@ -1716,7 +1669,7 @@ msgstr "Conversazione rimossa."
 
 #: mod/message.php:290 mod/message.php:298 mod/message.php:427
 #: mod/message.php:435 mod/wallmessage.php:127 mod/wallmessage.php:135
-#: include/conversation.php:1129 include/conversation.php:1147
+#: include/conversation.php:1128 include/conversation.php:1146
 msgid "Please enter a link URL:"
 msgstr "Inserisci l'indirizzo del link:"
 
@@ -1738,19 +1691,19 @@ msgid "Your message:"
 msgstr "Il tuo messaggio:"
 
 #: mod/message.php:339 mod/message.php:523 mod/wallmessage.php:154
-#: mod/editpost.php:110 include/conversation.php:1184
+#: mod/editpost.php:110 include/conversation.php:1183
 msgid "Upload photo"
 msgstr "Carica foto"
 
 #: mod/message.php:340 mod/message.php:524 mod/wallmessage.php:155
-#: mod/editpost.php:114 include/conversation.php:1188
+#: mod/editpost.php:114 include/conversation.php:1187
 msgid "Insert web link"
 msgstr "Inserisci link"
 
 #: mod/message.php:341 mod/message.php:526 mod/content.php:501
 #: mod/content.php:885 mod/wallmessage.php:156 mod/editpost.php:124
 #: mod/photos.php:1610 object/Item.php:396 include/conversation.php:713
-#: include/conversation.php:1202
+#: include/conversation.php:1201
 msgid "Please wait"
 msgstr "Attendi"
 
@@ -1766,7 +1719,7 @@ msgstr "Messaggio non disponibile."
 msgid "Delete message"
 msgstr "Elimina il messaggio"
 
-#: mod/message.php:507 mod/message.php:582
+#: mod/message.php:507 mod/message.php:584
 msgid "Delete conversation"
 msgstr "Elimina la conversazione"
 
@@ -1780,26 +1733,26 @@ msgstr "Nessuna comunicazione sicura disponibile, <strong>Potresti</strong> esse
 msgid "Send Reply"
 msgstr "Invia la risposta"
 
-#: mod/message.php:555
+#: mod/message.php:557
 #, php-format
 msgid "Unknown sender - %s"
 msgstr "Mittente sconosciuto - %s"
 
-#: mod/message.php:558
+#: mod/message.php:560
 #, php-format
 msgid "You and %s"
 msgstr "Tu e %s"
 
-#: mod/message.php:561
+#: mod/message.php:563
 #, php-format
 msgid "%s and You"
 msgstr "%s e Tu"
 
-#: mod/message.php:585
+#: mod/message.php:587
 msgid "D, d M Y - g:i A"
 msgstr "D d M Y - G:i"
 
-#: mod/message.php:588
+#: mod/message.php:590
 #, php-format
 msgid "%d message"
 msgid_plural "%d messages"
@@ -1851,9 +1804,9 @@ msgstr "Ritorna alla modifica contatto"
 msgid "Refetch contact data"
 msgstr "Ricarica dati contatto"
 
-#: mod/crepair.php:170 mod/admin.php:1111 mod/admin.php:1123
-#: mod/admin.php:1124 mod/admin.php:1137 mod/settings.php:652
-#: mod/settings.php:678
+#: mod/crepair.php:170 mod/admin.php:1306 mod/admin.php:1318
+#: mod/admin.php:1319 mod/admin.php:1332 mod/settings.php:661
+#: mod/settings.php:687
 msgid "Name"
 msgstr "Nome"
 
@@ -1903,7 +1856,7 @@ msgid ""
 "entries from this contact."
 msgstr "Imposta questo contatto come 'io remoto', questo farà si che friendica reinvii i nuovi messaggi da questo contatto."
 
-#: mod/bookmarklet.php:12 boot.php:1293 include/nav.php:91
+#: mod/bookmarklet.php:12 boot.php:1430 include/nav.php:91
 msgid "Login"
 msgstr "Accedi"
 
@@ -1915,28 +1868,28 @@ msgstr "Il messaggio è stato creato"
 msgid "Access denied."
 msgstr "Accesso negato."
 
-#: mod/dirfind.php:188 mod/allfriends.php:75 mod/match.php:85
-#: mod/suggest.php:98 include/contact_widgets.php:10 include/identity.php:209
+#: mod/dirfind.php:194 mod/allfriends.php:80 mod/match.php:85
+#: mod/suggest.php:98 include/contact_widgets.php:10 include/identity.php:212
 msgid "Connect"
 msgstr "Connetti"
 
-#: mod/dirfind.php:189 mod/allfriends.php:59 mod/match.php:70
-#: mod/directory.php:162 mod/suggest.php:81 include/Contact.php:307
-#: include/Contact.php:320 include/Contact.php:362
+#: mod/dirfind.php:195 mod/allfriends.php:64 mod/match.php:70
+#: mod/directory.php:162 mod/suggest.php:81 include/Contact.php:283
+#: include/Contact.php:296 include/Contact.php:338
 #: include/conversation.php:912 include/conversation.php:926
 msgid "View Profile"
 msgstr "Visualizza profilo"
 
-#: mod/dirfind.php:218
+#: mod/dirfind.php:224
 #, php-format
 msgid "People Search - %s"
 msgstr "Cerca persone - %s"
 
-#: mod/dirfind.php:225 mod/match.php:105
+#: mod/dirfind.php:231 mod/match.php:105
 msgid "No matches"
 msgstr "Nessun risultato"
 
-#: mod/fbrowser.php:32 include/identity.php:693 include/nav.php:77
+#: mod/fbrowser.php:32 include/identity.php:702 include/nav.php:77
 #: view/theme/diabook/theme.php:126
 msgid "Photos"
 msgstr "Foto"
@@ -1956,548 +1909,579 @@ msgstr "File"
 msgid "Contacts who are not members of a group"
 msgstr "Contatti che non sono membri di un gruppo"
 
-#: mod/admin.php:80
+#: mod/admin.php:92
 msgid "Theme settings updated."
 msgstr "Impostazioni del tema aggiornate."
 
-#: mod/admin.php:127 mod/admin.php:711
+#: mod/admin.php:156 mod/admin.php:888
 msgid "Site"
 msgstr "Sito"
 
-#: mod/admin.php:128 mod/admin.php:655 mod/admin.php:1106 mod/admin.php:1121
+#: mod/admin.php:157 mod/admin.php:832 mod/admin.php:1301 mod/admin.php:1316
 msgid "Users"
 msgstr "Utenti"
 
-#: mod/admin.php:129 mod/admin.php:1210 mod/admin.php:1270 mod/settings.php:66
+#: mod/admin.php:158 mod/admin.php:1416 mod/admin.php:1476 mod/settings.php:72
 msgid "Plugins"
 msgstr "Plugin"
 
-#: mod/admin.php:130 mod/admin.php:1455 mod/admin.php:1506
+#: mod/admin.php:159 mod/admin.php:1674 mod/admin.php:1724
 msgid "Themes"
 msgstr "Temi"
 
-#: mod/admin.php:131
+#: mod/admin.php:160 mod/settings.php:50
+msgid "Additional features"
+msgstr "Funzionalità aggiuntive"
+
+#: mod/admin.php:161
 msgid "DB updates"
 msgstr "Aggiornamenti Database"
 
-#: mod/admin.php:132 mod/admin.php:223
+#: mod/admin.php:162 mod/admin.php:385
 msgid "Inspect Queue"
 msgstr "Ispeziona Coda di invio"
 
-#: mod/admin.php:147 mod/admin.php:156 mod/admin.php:1594
+#: mod/admin.php:163 mod/admin.php:354
+msgid "Federation Statistics"
+msgstr ""
+
+#: mod/admin.php:177 mod/admin.php:188 mod/admin.php:1792
 msgid "Logs"
 msgstr "Log"
 
-#: mod/admin.php:148
+#: mod/admin.php:178 mod/admin.php:1859
+msgid "View Logs"
+msgstr ""
+
+#: mod/admin.php:179
 msgid "probe address"
 msgstr "controlla indirizzo"
 
-#: mod/admin.php:149
+#: mod/admin.php:180
 msgid "check webfinger"
 msgstr "verifica webfinger"
 
-#: mod/admin.php:154 include/nav.php:194
+#: mod/admin.php:186 include/nav.php:194
 msgid "Admin"
 msgstr "Amministrazione"
 
-#: mod/admin.php:155
+#: mod/admin.php:187
 msgid "Plugin Features"
 msgstr "Impostazioni Plugins"
 
-#: mod/admin.php:157
+#: mod/admin.php:189
 msgid "diagnostics"
 msgstr "diagnostiche"
 
-#: mod/admin.php:158
+#: mod/admin.php:190
 msgid "User registrations waiting for confirmation"
 msgstr "Utenti registrati in attesa di conferma"
 
-#: mod/admin.php:222 mod/admin.php:272 mod/admin.php:710 mod/admin.php:1105
-#: mod/admin.php:1209 mod/admin.php:1269 mod/admin.php:1454 mod/admin.php:1505
-#: mod/admin.php:1593
+#: mod/admin.php:347
+msgid ""
+"This page offers you some numbers to the known part of the federated social "
+"network your Friendica node is part of. These numbers are not complete but "
+"only reflect the part of the network your node is aware of."
+msgstr ""
+
+#: mod/admin.php:348
+msgid ""
+"The <em>Auto Discovered Contact Directory</em> feature is not enabled, it "
+"will improve the data displayed here."
+msgstr ""
+
+#: mod/admin.php:353 mod/admin.php:384 mod/admin.php:441 mod/admin.php:887
+#: mod/admin.php:1300 mod/admin.php:1415 mod/admin.php:1475 mod/admin.php:1673
+#: mod/admin.php:1723 mod/admin.php:1791 mod/admin.php:1858
 msgid "Administration"
 msgstr "Amministrazione"
 
-#: mod/admin.php:225
+#: mod/admin.php:360
+#, php-format
+msgid "Currently this node is aware of %d nodes from the following platforms:"
+msgstr ""
+
+#: mod/admin.php:387
 msgid "ID"
 msgstr "ID"
 
-#: mod/admin.php:226
+#: mod/admin.php:388
 msgid "Recipient Name"
 msgstr "Nome Destinatario"
 
-#: mod/admin.php:227
+#: mod/admin.php:389
 msgid "Recipient Profile"
 msgstr "Profilo Destinatario"
 
-#: mod/admin.php:229
+#: mod/admin.php:391
 msgid "Created"
 msgstr "Creato"
 
-#: mod/admin.php:230
+#: mod/admin.php:392
 msgid "Last Tried"
 msgstr "Ultimo Tentativo"
 
-#: mod/admin.php:231
+#: mod/admin.php:393
 msgid ""
 "This page lists the content of the queue for outgoing postings. These are "
 "postings the initial delivery failed for. They will be resend later and "
 "eventually deleted if the delivery fails permanently."
 msgstr "Questa pagina elenca il contenuto della coda di invo dei post. Questi sono post la cui consegna è fallita. Verranno reinviati più tardi ed eventualmente cancellati se la consegna continua a fallire."
 
-#: mod/admin.php:243 mod/admin.php:1059
+#: mod/admin.php:412 mod/admin.php:1254
 msgid "Normal Account"
 msgstr "Account normale"
 
-#: mod/admin.php:244 mod/admin.php:1060
+#: mod/admin.php:413 mod/admin.php:1255
 msgid "Soapbox Account"
 msgstr "Account per comunicati e annunci"
 
-#: mod/admin.php:245 mod/admin.php:1061
+#: mod/admin.php:414 mod/admin.php:1256
 msgid "Community/Celebrity Account"
 msgstr "Account per celebrità o per comunità"
 
-#: mod/admin.php:246 mod/admin.php:1062
+#: mod/admin.php:415 mod/admin.php:1257
 msgid "Automatic Friend Account"
 msgstr "Account per amicizia automatizzato"
 
-#: mod/admin.php:247
+#: mod/admin.php:416
 msgid "Blog Account"
 msgstr "Account Blog"
 
-#: mod/admin.php:248
+#: mod/admin.php:417
 msgid "Private Forum"
 msgstr "Forum Privato"
 
-#: mod/admin.php:267
+#: mod/admin.php:436
 msgid "Message queues"
 msgstr "Code messaggi"
 
-#: mod/admin.php:273
+#: mod/admin.php:442
 msgid "Summary"
 msgstr "Sommario"
 
-#: mod/admin.php:275
+#: mod/admin.php:444
 msgid "Registered users"
 msgstr "Utenti registrati"
 
-#: mod/admin.php:277
+#: mod/admin.php:446
 msgid "Pending registrations"
 msgstr "Registrazioni in attesa"
 
-#: mod/admin.php:278
+#: mod/admin.php:447
 msgid "Version"
 msgstr "Versione"
 
-#: mod/admin.php:283
+#: mod/admin.php:452
 msgid "Active plugins"
 msgstr "Plugin attivi"
 
-#: mod/admin.php:306
+#: mod/admin.php:475
 msgid "Can not parse base url. Must have at least <scheme>://<domain>"
 msgstr "Impossibile analizzare l'url base. Deve avere almeno [schema]://[dominio]"
 
-#: mod/admin.php:587
+#: mod/admin.php:760
 msgid "RINO2 needs mcrypt php extension to work."
 msgstr "RINO2 necessita dell'estensione php mcrypt per funzionare."
 
-#: mod/admin.php:595
+#: mod/admin.php:768
 msgid "Site settings updated."
 msgstr "Impostazioni del sito aggiornate."
 
-#: mod/admin.php:619 mod/settings.php:903
+#: mod/admin.php:796 mod/settings.php:912
 msgid "No special theme for mobile devices"
 msgstr "Nessun tema speciale per i dispositivi mobili"
 
-#: mod/admin.php:638
+#: mod/admin.php:815
 msgid "No community page"
 msgstr "Nessuna pagina Comunità"
 
-#: mod/admin.php:639
+#: mod/admin.php:816
 msgid "Public postings from users of this site"
 msgstr "Messaggi pubblici dagli utenti di questo sito"
 
-#: mod/admin.php:640
+#: mod/admin.php:817
 msgid "Global community page"
 msgstr "Pagina Comunità globale"
 
-#: mod/admin.php:646
+#: mod/admin.php:823
 msgid "At post arrival"
 msgstr "All'arrivo di un messaggio"
 
-#: mod/admin.php:647 include/contact_selectors.php:56
+#: mod/admin.php:824 include/contact_selectors.php:56
 msgid "Frequently"
 msgstr "Frequentemente"
 
-#: mod/admin.php:648 include/contact_selectors.php:57
+#: mod/admin.php:825 include/contact_selectors.php:57
 msgid "Hourly"
 msgstr "Ogni ora"
 
-#: mod/admin.php:649 include/contact_selectors.php:58
+#: mod/admin.php:826 include/contact_selectors.php:58
 msgid "Twice daily"
 msgstr "Due volte al dì"
 
-#: mod/admin.php:650 include/contact_selectors.php:59
+#: mod/admin.php:827 include/contact_selectors.php:59
 msgid "Daily"
 msgstr "Giornalmente"
 
-#: mod/admin.php:656
+#: mod/admin.php:833
 msgid "Users, Global Contacts"
 msgstr "Utenti, Contatti Globali"
 
-#: mod/admin.php:657
+#: mod/admin.php:834
 msgid "Users, Global Contacts/fallback"
 msgstr "Utenti, Contatti Globali/fallback"
 
-#: mod/admin.php:661
+#: mod/admin.php:838
 msgid "One month"
 msgstr "Un mese"
 
-#: mod/admin.php:662
+#: mod/admin.php:839
 msgid "Three months"
 msgstr "Tre mesi"
 
-#: mod/admin.php:663
+#: mod/admin.php:840
 msgid "Half a year"
 msgstr "Sei mesi"
 
-#: mod/admin.php:664
+#: mod/admin.php:841
 msgid "One year"
 msgstr "Un anno"
 
-#: mod/admin.php:669
+#: mod/admin.php:846
 msgid "Multi user instance"
 msgstr "Istanza multi utente"
 
-#: mod/admin.php:692
+#: mod/admin.php:869
 msgid "Closed"
 msgstr "Chiusa"
 
-#: mod/admin.php:693
+#: mod/admin.php:870
 msgid "Requires approval"
 msgstr "Richiede l'approvazione"
 
-#: mod/admin.php:694
+#: mod/admin.php:871
 msgid "Open"
 msgstr "Aperta"
 
-#: mod/admin.php:698
+#: mod/admin.php:875
 msgid "No SSL policy, links will track page SSL state"
 msgstr "Nessuna gestione SSL, i link seguiranno lo stato SSL della pagina"
 
-#: mod/admin.php:699
+#: mod/admin.php:876
 msgid "Force all links to use SSL"
 msgstr "Forza tutti i linki ad usare SSL"
 
-#: mod/admin.php:700
+#: mod/admin.php:877
 msgid "Self-signed certificate, use SSL for local links only (discouraged)"
 msgstr "Certificato auto-firmato, usa SSL solo per i link locali (sconsigliato)"
 
-#: mod/admin.php:712 mod/admin.php:1271 mod/admin.php:1507 mod/admin.php:1595
-#: mod/settings.php:650 mod/settings.php:760 mod/settings.php:804
-#: mod/settings.php:873 mod/settings.php:960 mod/settings.php:1195
+#: mod/admin.php:889 mod/admin.php:1477 mod/admin.php:1725 mod/admin.php:1793
+#: mod/admin.php:1942 mod/settings.php:659 mod/settings.php:769
+#: mod/settings.php:813 mod/settings.php:882 mod/settings.php:969
+#: mod/settings.php:1204
 msgid "Save Settings"
 msgstr "Salva Impostazioni"
 
-#: mod/admin.php:713 mod/register.php:263
+#: mod/admin.php:890 mod/register.php:263
 msgid "Registration"
 msgstr "Registrazione"
 
-#: mod/admin.php:714
+#: mod/admin.php:891
 msgid "File upload"
 msgstr "Caricamento file"
 
-#: mod/admin.php:715
+#: mod/admin.php:892
 msgid "Policies"
 msgstr "Politiche"
 
-#: mod/admin.php:716
+#: mod/admin.php:893
 msgid "Advanced"
 msgstr "Avanzate"
 
-#: mod/admin.php:717
+#: mod/admin.php:894
 msgid "Auto Discovered Contact Directory"
 msgstr "Elenco Contatti Scoperto Automaticamente"
 
-#: mod/admin.php:718
+#: mod/admin.php:895
 msgid "Performance"
 msgstr "Performance"
 
-#: mod/admin.php:719
+#: mod/admin.php:896
 msgid ""
 "Relocate - WARNING: advanced function. Could make this server unreachable."
 msgstr "Trasloca - ATTENZIONE: funzione avanzata! Puo' rendere questo server irraggiungibile."
 
-#: mod/admin.php:722
+#: mod/admin.php:899
 msgid "Site name"
 msgstr "Nome del sito"
 
-#: mod/admin.php:723
+#: mod/admin.php:900
 msgid "Host name"
 msgstr "Nome host"
 
-#: mod/admin.php:724
+#: mod/admin.php:901
 msgid "Sender Email"
 msgstr "Mittente email"
 
-#: mod/admin.php:724
+#: mod/admin.php:901
 msgid ""
 "The email address your server shall use to send notification emails from."
 msgstr "L'indirizzo email che il tuo server dovrà usare per inviare notifiche via email."
 
-#: mod/admin.php:725
+#: mod/admin.php:902
 msgid "Banner/Logo"
 msgstr "Banner/Logo"
 
-#: mod/admin.php:726
+#: mod/admin.php:903
 msgid "Shortcut icon"
 msgstr "Icona shortcut"
 
-#: mod/admin.php:726
+#: mod/admin.php:903
 msgid "Link to an icon that will be used for browsers."
 msgstr "Link verso un'icona che verrà usata dai browsers."
 
-#: mod/admin.php:727
+#: mod/admin.php:904
 msgid "Touch icon"
 msgstr "Icona touch"
 
-#: mod/admin.php:727
+#: mod/admin.php:904
 msgid "Link to an icon that will be used for tablets and mobiles."
 msgstr "Link verso un'icona che verrà usata dai tablet e i telefonini."
 
-#: mod/admin.php:728
+#: mod/admin.php:905
 msgid "Additional Info"
 msgstr "Informazioni aggiuntive"
 
-#: mod/admin.php:728
+#: mod/admin.php:905
 #, php-format
 msgid ""
 "For public servers: you can add additional information here that will be "
 "listed at %s/siteinfo."
 msgstr "Per server pubblici: puoi aggiungere informazioni extra che verrano mostrate su %s/siteinfo."
 
-#: mod/admin.php:729
+#: mod/admin.php:906
 msgid "System language"
 msgstr "Lingua di sistema"
 
-#: mod/admin.php:730
+#: mod/admin.php:907
 msgid "System theme"
 msgstr "Tema di sistema"
 
-#: mod/admin.php:730
+#: mod/admin.php:907
 msgid ""
 "Default system theme - may be over-ridden by user profiles - <a href='#' "
 "id='cnftheme'>change theme settings</a>"
 msgstr "Tema di sistema - puo' essere sovrascritto dalle impostazioni utente - <a href='#' id='cnftheme'>cambia le impostazioni del tema</a>"
 
-#: mod/admin.php:731
+#: mod/admin.php:908
 msgid "Mobile system theme"
 msgstr "Tema mobile di sistema"
 
-#: mod/admin.php:731
+#: mod/admin.php:908
 msgid "Theme for mobile devices"
 msgstr "Tema per dispositivi mobili"
 
-#: mod/admin.php:732
+#: mod/admin.php:909
 msgid "SSL link policy"
 msgstr "Gestione link SSL"
 
-#: mod/admin.php:732
+#: mod/admin.php:909
 msgid "Determines whether generated links should be forced to use SSL"
 msgstr "Determina se i link generati devono essere forzati a usare SSL"
 
-#: mod/admin.php:733
+#: mod/admin.php:910
 msgid "Force SSL"
 msgstr "Forza SSL"
 
-#: mod/admin.php:733
+#: mod/admin.php:910
 msgid ""
 "Force all Non-SSL requests to SSL - Attention: on some systems it could lead"
 " to endless loops."
 msgstr "Forza tutte le richieste non SSL su SSL - Attenzione: su alcuni sistemi puo' portare a loop senza fine"
 
-#: mod/admin.php:734
+#: mod/admin.php:911
 msgid "Old style 'Share'"
 msgstr "Ricondivisione vecchio stile"
 
-#: mod/admin.php:734
+#: mod/admin.php:911
 msgid "Deactivates the bbcode element 'share' for repeating items."
 msgstr "Disattiva l'elemento bbcode 'share' con elementi ripetuti"
 
-#: mod/admin.php:735
+#: mod/admin.php:912
 msgid "Hide help entry from navigation menu"
 msgstr "Nascondi la voce 'Guida' dal menu di navigazione"
 
-#: mod/admin.php:735
+#: mod/admin.php:912
 msgid ""
 "Hides the menu entry for the Help pages from the navigation menu. You can "
 "still access it calling /help directly."
 msgstr "Nasconde la voce per le pagine della guida dal menu di navigazione. E' comunque possibile accedervi richiamando /help direttamente."
 
-#: mod/admin.php:736
+#: mod/admin.php:913
 msgid "Single user instance"
 msgstr "Instanza a singolo utente"
 
-#: mod/admin.php:736
+#: mod/admin.php:913
 msgid "Make this instance multi-user or single-user for the named user"
 msgstr "Rendi questa istanza multi utente o a singolo utente per l'utente selezionato"
 
-#: mod/admin.php:737
+#: mod/admin.php:914
 msgid "Maximum image size"
 msgstr "Massima dimensione immagini"
 
-#: mod/admin.php:737
+#: mod/admin.php:914
 msgid ""
 "Maximum size in bytes of uploaded images. Default is 0, which means no "
 "limits."
 msgstr "Massima dimensione in byte delle immagini caricate. Il default è 0, cioè nessun limite."
 
-#: mod/admin.php:738
+#: mod/admin.php:915
 msgid "Maximum image length"
 msgstr "Massima lunghezza immagine"
 
-#: mod/admin.php:738
+#: mod/admin.php:915
 msgid ""
 "Maximum length in pixels of the longest side of uploaded images. Default is "
 "-1, which means no limits."
 msgstr "Massima lunghezza in pixel del lato più lungo delle immagini caricate. Predefinito a -1, ovvero nessun limite."
 
-#: mod/admin.php:739
+#: mod/admin.php:916
 msgid "JPEG image quality"
 msgstr "Qualità immagini JPEG"
 
-#: mod/admin.php:739
+#: mod/admin.php:916
 msgid ""
 "Uploaded JPEGS will be saved at this quality setting [0-100]. Default is "
 "100, which is full quality."
 msgstr "Le immagini JPEG caricate verranno salvate con questa qualità [0-100]. Predefinito è 100, ovvero qualità piena."
 
-#: mod/admin.php:741
+#: mod/admin.php:918
 msgid "Register policy"
 msgstr "Politica di registrazione"
 
-#: mod/admin.php:742
+#: mod/admin.php:919
 msgid "Maximum Daily Registrations"
 msgstr "Massime registrazioni giornaliere"
 
-#: mod/admin.php:742
+#: mod/admin.php:919
 msgid ""
 "If registration is permitted above, this sets the maximum number of new user"
 " registrations to accept per day.  If register is set to closed, this "
 "setting has no effect."
 msgstr "Se la registrazione è permessa, qui si definisce il massimo numero di nuovi utenti registrati da accettare giornalmente. Se la registrazione è chiusa, questa impostazione non ha effetto."
 
-#: mod/admin.php:743
+#: mod/admin.php:920
 msgid "Register text"
 msgstr "Testo registrazione"
 
-#: mod/admin.php:743
+#: mod/admin.php:920
 msgid "Will be displayed prominently on the registration page."
 msgstr "Sarà mostrato ben visibile nella pagina di registrazione."
 
-#: mod/admin.php:744
+#: mod/admin.php:921
 msgid "Accounts abandoned after x days"
 msgstr "Account abbandonati dopo x giorni"
 
-#: mod/admin.php:744
+#: mod/admin.php:921
 msgid ""
 "Will not waste system resources polling external sites for abandonded "
 "accounts. Enter 0 for no time limit."
 msgstr "Non spreca risorse di sistema controllando siti esterni per gli account abbandonati. Immettere 0 per nessun limite di tempo."
 
-#: mod/admin.php:745
+#: mod/admin.php:922
 msgid "Allowed friend domains"
 msgstr "Domini amici consentiti"
 
-#: mod/admin.php:745
+#: mod/admin.php:922
 msgid ""
 "Comma separated list of domains which are allowed to establish friendships "
 "with this site. Wildcards are accepted. Empty to allow any domains"
 msgstr "Elenco separato da virglola dei domini che possono stabilire amicizie con questo sito. Sono accettati caratteri jolly. Lascalo vuoto per accettare qualsiasi dominio."
 
-#: mod/admin.php:746
+#: mod/admin.php:923
 msgid "Allowed email domains"
 msgstr "Domini email consentiti"
 
-#: mod/admin.php:746
+#: mod/admin.php:923
 msgid ""
 "Comma separated list of domains which are allowed in email addresses for "
 "registrations to this site. Wildcards are accepted. Empty to allow any "
 "domains"
 msgstr "Elenco separato da virgola dei domini permessi come indirizzi email in fase di registrazione a questo sito. Sono accettati caratteri jolly. Lascalo vuoto per accettare qualsiasi dominio."
 
-#: mod/admin.php:747
+#: mod/admin.php:924
 msgid "Block public"
 msgstr "Blocca pagine pubbliche"
 
-#: mod/admin.php:747
+#: mod/admin.php:924
 msgid ""
 "Check to block public access to all otherwise public personal pages on this "
 "site unless you are currently logged in."
 msgstr "Seleziona per bloccare l'accesso pubblico a tutte le pagine personali di questo sito, a meno di essere loggato."
 
-#: mod/admin.php:748
+#: mod/admin.php:925
 msgid "Force publish"
 msgstr "Forza publicazione"
 
-#: mod/admin.php:748
+#: mod/admin.php:925
 msgid ""
 "Check to force all profiles on this site to be listed in the site directory."
 msgstr "Seleziona per forzare tutti i profili di questo sito ad essere compresi  nell'elenco di questo sito."
 
-#: mod/admin.php:749
+#: mod/admin.php:926
 msgid "Global directory URL"
 msgstr "URL della directory globale"
 
-#: mod/admin.php:749
+#: mod/admin.php:926
 msgid ""
 "URL to the global directory. If this is not set, the global directory is "
 "completely unavailable to the application."
 msgstr "URL dell'elenco globale. Se vuoto, l'elenco globale sarà completamente disabilitato."
 
-#: mod/admin.php:750
+#: mod/admin.php:927
 msgid "Allow threaded items"
 msgstr "Permetti commenti nidificati"
 
-#: mod/admin.php:750
+#: mod/admin.php:927
 msgid "Allow infinite level threading for items on this site."
 msgstr "Permette un infinito livello di nidificazione dei commenti su questo sito."
 
-#: mod/admin.php:751
+#: mod/admin.php:928
 msgid "Private posts by default for new users"
 msgstr "Post privati di default per i nuovi utenti"
 
-#: mod/admin.php:751
+#: mod/admin.php:928
 msgid ""
 "Set default post permissions for all new members to the default privacy "
 "group rather than public."
 msgstr "Imposta i permessi predefiniti dei post per tutti i nuovi utenti come privati per il gruppo predefinito, invece che pubblici."
 
-#: mod/admin.php:752
+#: mod/admin.php:929
 msgid "Don't include post content in email notifications"
 msgstr "Non includere il contenuto dei post nelle notifiche via email"
 
-#: mod/admin.php:752
+#: mod/admin.php:929
 msgid ""
 "Don't include the content of a post/comment/private message/etc. in the "
 "email notifications that are sent out from this site, as a privacy measure."
 msgstr "Non include il contenuti del post/commento/messaggio privato/etc. nelle notifiche email che sono inviate da questo sito, per privacy"
 
-#: mod/admin.php:753
+#: mod/admin.php:930
 msgid "Disallow public access to addons listed in the apps menu."
 msgstr "Disabilita l'accesso pubblico ai plugin raccolti nel menu apps."
 
-#: mod/admin.php:753
+#: mod/admin.php:930
 msgid ""
 "Checking this box will restrict addons listed in the apps menu to members "
 "only."
 msgstr "Selezionando questo box si limiterà ai soli membri l'accesso agli addon nel menu applicazioni"
 
-#: mod/admin.php:754
+#: mod/admin.php:931
 msgid "Don't embed private images in posts"
 msgstr "Non inglobare immagini private nei post"
 
-#: mod/admin.php:754
+#: mod/admin.php:931
 msgid ""
 "Don't replace locally-hosted private photos in posts with an embedded copy "
 "of the image. This means that contacts who receive posts containing private "
@@ -2505,218 +2489,228 @@ msgid ""
 "while."
 msgstr "Non sostituire le foto locali nei post con una copia incorporata dell'immagine. Questo significa che i contatti che riceveranno i post contenenti foto private dovranno autenticarsi e caricare ogni immagine, cosa che puo' richiedere un po' di tempo."
 
-#: mod/admin.php:755
+#: mod/admin.php:932
 msgid "Allow Users to set remote_self"
 msgstr "Permetti agli utenti di impostare 'io remoto'"
 
-#: mod/admin.php:755
+#: mod/admin.php:932
 msgid ""
 "With checking this, every user is allowed to mark every contact as a "
 "remote_self in the repair contact dialog. Setting this flag on a contact "
 "causes mirroring every posting of that contact in the users stream."
 msgstr "Selezionando questo, a tutti gli utenti sarà permesso di impostare qualsiasi contatto come 'io remoto' nella pagina di modifica del contatto. Impostare questa opzione fa si che tutti i messaggi di quel contatto vengano ripetuti nello stream del'utente."
 
-#: mod/admin.php:756
+#: mod/admin.php:933
 msgid "Block multiple registrations"
 msgstr "Blocca registrazioni multiple"
 
-#: mod/admin.php:756
+#: mod/admin.php:933
 msgid "Disallow users to register additional accounts for use as pages."
 msgstr "Non permette all'utente di registrare account extra da usare come pagine."
 
-#: mod/admin.php:757
+#: mod/admin.php:934
 msgid "OpenID support"
 msgstr "Supporto OpenID"
 
-#: mod/admin.php:757
+#: mod/admin.php:934
 msgid "OpenID support for registration and logins."
 msgstr "Supporta OpenID per la registrazione e il login"
 
-#: mod/admin.php:758
+#: mod/admin.php:935
 msgid "Fullname check"
 msgstr "Controllo nome completo"
 
-#: mod/admin.php:758
+#: mod/admin.php:935
 msgid ""
 "Force users to register with a space between firstname and lastname in Full "
 "name, as an antispam measure"
 msgstr "Forza gli utenti a registrarsi con uno spazio tra il nome e il cognome in \"Nome completo\", come misura antispam"
 
-#: mod/admin.php:759
+#: mod/admin.php:936
 msgid "UTF-8 Regular expressions"
 msgstr "Espressioni regolari UTF-8"
 
-#: mod/admin.php:759
+#: mod/admin.php:936
 msgid "Use PHP UTF8 regular expressions"
 msgstr "Usa le espressioni regolari PHP in UTF8"
 
-#: mod/admin.php:760
+#: mod/admin.php:937
 msgid "Community Page Style"
 msgstr "Stile pagina Comunità"
 
-#: mod/admin.php:760
+#: mod/admin.php:937
 msgid ""
 "Type of community page to show. 'Global community' shows every public "
 "posting from an open distributed network that arrived on this server."
 msgstr "Tipo di pagina Comunità da mostrare. 'Comunità Globale' mostra tutti i messaggi pubblici arrivati su questo server da network aperti distribuiti."
 
-#: mod/admin.php:761
+#: mod/admin.php:938
 msgid "Posts per user on community page"
 msgstr "Messaggi per utente nella pagina Comunità"
 
-#: mod/admin.php:761
+#: mod/admin.php:938
 msgid ""
 "The maximum number of posts per user on the community page. (Not valid for "
 "'Global Community')"
 msgstr "Il numero massimo di messaggi per utente mostrato nella pagina Comuntà (non valido per 'Comunità globale')"
 
-#: mod/admin.php:762
+#: mod/admin.php:939
 msgid "Enable OStatus support"
 msgstr "Abilita supporto OStatus"
 
-#: mod/admin.php:762
+#: mod/admin.php:939
 msgid ""
 "Provide built-in OStatus (StatusNet, GNU Social etc.) compatibility. All "
 "communications in OStatus are public, so privacy warnings will be "
 "occasionally displayed."
 msgstr "Fornisce la compatibilità integrata a OStatus (StatusNet, Gnu Social, etc.). Tutte le comunicazioni su OStatus sono pubbliche, quindi un avviso di privacy verrà mostrato occasionalmente."
 
-#: mod/admin.php:763
+#: mod/admin.php:940
 msgid "OStatus conversation completion interval"
 msgstr "Intervallo completamento conversazioni OStatus"
 
-#: mod/admin.php:763
+#: mod/admin.php:940
 msgid ""
 "How often shall the poller check for new entries in OStatus conversations? "
 "This can be a very ressource task."
 msgstr "quanto spesso il poller deve controllare se esistono nuovi commenti in una conversazione OStatus? Questo è un lavoro che puo' richiedere molte risorse."
 
-#: mod/admin.php:764
+#: mod/admin.php:941
 msgid "OStatus support can only be enabled if threading is enabled."
 msgstr "Il supporto OStatus puo' essere abilitato solo se è abilitato il threading."
 
-#: mod/admin.php:766
+#: mod/admin.php:943
 msgid ""
 "Diaspora support can't be enabled because Friendica was installed into a sub"
 " directory."
 msgstr "Il supporto a Diaspora non puo' essere abilitato perchè Friendica è stato installato in una sotto directory."
 
-#: mod/admin.php:767
+#: mod/admin.php:944
 msgid "Enable Diaspora support"
 msgstr "Abilita il supporto a Diaspora"
 
-#: mod/admin.php:767
+#: mod/admin.php:944
 msgid "Provide built-in Diaspora network compatibility."
 msgstr "Fornisce compatibilità con il network Diaspora."
 
-#: mod/admin.php:768
+#: mod/admin.php:945
 msgid "Only allow Friendica contacts"
 msgstr "Permetti solo contatti Friendica"
 
-#: mod/admin.php:768
+#: mod/admin.php:945
 msgid ""
 "All contacts must use Friendica protocols. All other built-in communication "
 "protocols disabled."
 msgstr "Tutti i contatti devono usare il protocollo di Friendica. Tutti gli altri protocolli sono disabilitati."
 
-#: mod/admin.php:769
+#: mod/admin.php:946
 msgid "Verify SSL"
 msgstr "Verifica SSL"
 
-#: mod/admin.php:769
+#: mod/admin.php:946
 msgid ""
 "If you wish, you can turn on strict certificate checking. This will mean you"
 " cannot connect (at all) to self-signed SSL sites."
 msgstr "Se vuoi, puoi abilitare il controllo rigoroso dei certificati.Questo significa che non potrai collegarti (del tutto) con siti con certificati SSL auto-firmati."
 
-#: mod/admin.php:770
+#: mod/admin.php:947
 msgid "Proxy user"
 msgstr "Utente Proxy"
 
-#: mod/admin.php:771
+#: mod/admin.php:948
 msgid "Proxy URL"
 msgstr "URL Proxy"
 
-#: mod/admin.php:772
+#: mod/admin.php:949
 msgid "Network timeout"
 msgstr "Timeout rete"
 
-#: mod/admin.php:772
+#: mod/admin.php:949
 msgid "Value is in seconds. Set to 0 for unlimited (not recommended)."
 msgstr "Valore in secondi. Imposta a 0 per illimitato (non raccomandato)."
 
-#: mod/admin.php:773
+#: mod/admin.php:950
 msgid "Delivery interval"
 msgstr "Intervallo di invio"
 
-#: mod/admin.php:773
+#: mod/admin.php:950
 msgid ""
 "Delay background delivery processes by this many seconds to reduce system "
 "load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 "
 "for large dedicated servers."
 msgstr "Ritarda il processo di invio in background  di n secondi per ridurre il carico di sistema. Raccomandato:  4-5 per host condivisit, 2-3 per VPS. 0-1 per grandi server dedicati."
 
-#: mod/admin.php:774
+#: mod/admin.php:951
 msgid "Poll interval"
 msgstr "Intervallo di poll"
 
-#: mod/admin.php:774
+#: mod/admin.php:951
 msgid ""
 "Delay background polling processes by this many seconds to reduce system "
 "load. If 0, use delivery interval."
 msgstr "Ritarda il processo di poll in background di n secondi per ridurre il carico di sistema. Se 0, usa l'intervallo di invio."
 
-#: mod/admin.php:775
+#: mod/admin.php:952
 msgid "Maximum Load Average"
 msgstr "Massimo carico medio"
 
-#: mod/admin.php:775
+#: mod/admin.php:952
 msgid ""
 "Maximum system load before delivery and poll processes are deferred - "
 "default 50."
 msgstr "Massimo carico di sistema prima che i processi di invio e di poll siano ritardati. Predefinito a 50."
 
-#: mod/admin.php:776
+#: mod/admin.php:953
 msgid "Maximum Load Average (Frontend)"
 msgstr "Media Massimo Carico (Frontend)"
 
-#: mod/admin.php:776
+#: mod/admin.php:953
 msgid "Maximum system load before the frontend quits service - default 50."
 msgstr "Massimo carico di sistema prima che il frontend fermi il servizio - default 50."
 
-#: mod/admin.php:777
+#: mod/admin.php:954
 msgid "Maximum table size for optimization"
 msgstr "Dimensione massima della tabella per l'ottimizzazione"
 
-#: mod/admin.php:777
+#: mod/admin.php:954
 msgid ""
 "Maximum table size (in MB) for the automatic optimization - default 100 MB. "
 "Enter -1 to disable it."
 msgstr "La dimensione massima (in MB) per l'ottimizzazione automatica - default 100 MB. Inserisci -1 per disabilitarlo."
 
-#: mod/admin.php:779
+#: mod/admin.php:955
+msgid "Minimum level of fragmentation"
+msgstr ""
+
+#: mod/admin.php:955
+msgid ""
+"Minimum fragmenation level to start the automatic optimization - default "
+"value is 30%."
+msgstr ""
+
+#: mod/admin.php:957
 msgid "Periodical check of global contacts"
 msgstr "Check periodico dei contatti globali"
 
-#: mod/admin.php:779
+#: mod/admin.php:957
 msgid ""
 "If enabled, the global contacts are checked periodically for missing or "
 "outdated data and the vitality of the contacts and servers."
 msgstr "Se abilitato, i contatti globali sono controllati periodicamente per verificare dati mancanti o sorpassati e la vitaltà dei contatti e dei server."
 
-#: mod/admin.php:780
+#: mod/admin.php:958
 msgid "Days between requery"
 msgstr "Giorni tra le richieste"
 
-#: mod/admin.php:780
+#: mod/admin.php:958
 msgid "Number of days after which a server is requeried for his contacts."
 msgstr "Numero di giorni dopo i quali al server vengono richiesti i suoi contatti."
 
-#: mod/admin.php:781
+#: mod/admin.php:959
 msgid "Discover contacts from other servers"
 msgstr "Trova contatti dagli altri server"
 
-#: mod/admin.php:781
+#: mod/admin.php:959
 msgid ""
 "Periodically query other servers for contacts. You can choose between "
 "'users': the users on the remote system, 'Global Contacts': active contacts "
@@ -2726,32 +2720,32 @@ msgid ""
 "Global Contacts'."
 msgstr "Richiede periodicamente contatti agli altri server. Puoi scegliere tra 'utenti', gli uenti sul sistema remoto, o 'contatti globali', i contatti attivi che sono conosciuti dal sistema. Il fallback è pensato per i server Redmatrix e i vecchi server Friendica, dove i contatti globali non sono disponibili. Il fallback incrementa il carico di sistema, per cui l'impostazione consigliata è \"Utenti, Contatti Globali\"."
 
-#: mod/admin.php:782
+#: mod/admin.php:960
 msgid "Timeframe for fetching global contacts"
 msgstr "Termine per il recupero contatti globali"
 
-#: mod/admin.php:782
+#: mod/admin.php:960
 msgid ""
 "When the discovery is activated, this value defines the timeframe for the "
 "activity of the global contacts that are fetched from other servers."
 msgstr "Quando si attiva la scoperta, questo valore definisce il periodo di tempo per l'attività dei contatti globali che vengono prelevati da altri server."
 
-#: mod/admin.php:783
+#: mod/admin.php:961
 msgid "Search the local directory"
 msgstr "Cerca la directory locale"
 
-#: mod/admin.php:783
+#: mod/admin.php:961
 msgid ""
 "Search the local directory instead of the global directory. When searching "
 "locally, every search will be executed on the global directory in the "
 "background. This improves the search results when the search is repeated."
 msgstr "Cerca nella directory locale invece che nella directory globale. Durante la ricerca a livello locale, ogni ricerca verrà eseguita sulla directory globale in background. Ciò migliora i risultati della ricerca quando la ricerca viene ripetuta."
 
-#: mod/admin.php:785
+#: mod/admin.php:963
 msgid "Publish server information"
 msgstr "Pubblica informazioni server"
 
-#: mod/admin.php:785
+#: mod/admin.php:963
 msgid ""
 "If enabled, general server and usage data will be published. The data "
 "contains the name and version of the server, number of users with public "
@@ -2759,205 +2753,205 @@ msgid ""
 " href='http://the-federation.info/'>the-federation.info</a> for details."
 msgstr "Se abilitata, saranno pubblicati i dati generali del server e i dati di utilizzo. I dati contengono il nome e la versione del server, il numero di utenti con profili pubblici, numero dei posti e dei protocolli e connettori attivati. Per informazioni, vedere <a href='http://the-federation.info/'> the-federation.info </a>."
 
-#: mod/admin.php:787
+#: mod/admin.php:965
 msgid "Use MySQL full text engine"
 msgstr "Usa il motore MySQL full text"
 
-#: mod/admin.php:787
+#: mod/admin.php:965
 msgid ""
 "Activates the full text engine. Speeds up search - but can only search for "
 "four and more characters."
 msgstr "Attiva il motore full text. Velocizza la ricerca, ma puo' cercare solo per quattro o più caratteri."
 
-#: mod/admin.php:788
+#: mod/admin.php:966
 msgid "Suppress Language"
 msgstr "Disattiva lingua"
 
-#: mod/admin.php:788
+#: mod/admin.php:966
 msgid "Suppress language information in meta information about a posting."
 msgstr "Disattiva le informazioni sulla lingua nei meta di un post."
 
-#: mod/admin.php:789
+#: mod/admin.php:967
 msgid "Suppress Tags"
 msgstr "Sopprimi Tags"
 
-#: mod/admin.php:789
+#: mod/admin.php:967
 msgid "Suppress showing a list of hashtags at the end of the posting."
 msgstr "Non mostra la lista di hashtag in coda al messaggio"
 
-#: mod/admin.php:790
+#: mod/admin.php:968
 msgid "Path to item cache"
 msgstr "Percorso cache elementi"
 
-#: mod/admin.php:790
+#: mod/admin.php:968
 msgid "The item caches buffers generated bbcode and external images."
 msgstr "La cache degli elementi memorizza il bbcode generato e le immagini esterne."
 
-#: mod/admin.php:791
+#: mod/admin.php:969
 msgid "Cache duration in seconds"
 msgstr "Durata della cache in secondi"
 
-#: mod/admin.php:791
+#: mod/admin.php:969
 msgid ""
 "How long should the cache files be hold? Default value is 86400 seconds (One"
 " day). To disable the item cache, set the value to -1."
 msgstr "Quanto a lungo devono essere mantenuti i file di cache? Il valore predefinito è 86400 secondi (un giorno). Per disabilitare la cache, imposta il valore a -1."
 
-#: mod/admin.php:792
+#: mod/admin.php:970
 msgid "Maximum numbers of comments per post"
 msgstr "Numero massimo di commenti per post"
 
-#: mod/admin.php:792
+#: mod/admin.php:970
 msgid "How much comments should be shown for each post? Default value is 100."
 msgstr "Quanti commenti devono essere mostrati per ogni post? Default : 100."
 
-#: mod/admin.php:793
+#: mod/admin.php:971
 msgid "Path for lock file"
 msgstr "Percorso al file di lock"
 
-#: mod/admin.php:793
+#: mod/admin.php:971
 msgid ""
 "The lock file is used to avoid multiple pollers at one time. Only define a "
 "folder here."
 msgstr "Il file di lock è usato per evitare l'avvio di poller multipli allo stesso tempo. Inserisci solo la cartella, qui."
 
-#: mod/admin.php:794
+#: mod/admin.php:972
 msgid "Temp path"
 msgstr "Percorso file temporanei"
 
-#: mod/admin.php:794
+#: mod/admin.php:972
 msgid ""
 "If you have a restricted system where the webserver can't access the system "
 "temp path, enter another path here."
 msgstr "Se si dispone di un sistema ristretto in cui il server web non può accedere al percorso temporaneo di sistema, inserire un altro percorso qui."
 
-#: mod/admin.php:795
+#: mod/admin.php:973
 msgid "Base path to installation"
 msgstr "Percorso base all'installazione"
 
-#: mod/admin.php:795
+#: mod/admin.php:973
 msgid ""
 "If the system cannot detect the correct path to your installation, enter the"
 " correct path here. This setting should only be set if you are using a "
 "restricted system and symbolic links to your webroot."
 msgstr "Se il sistema non è in grado di rilevare il percorso corretto per l'installazione, immettere il percorso corretto qui. Questa impostazione deve essere inserita solo se si utilizza un sistema limitato e/o collegamenti simbolici al tuo webroot."
 
-#: mod/admin.php:796
+#: mod/admin.php:974
 msgid "Disable picture proxy"
 msgstr "Disabilita il proxy immagini"
 
-#: mod/admin.php:796
+#: mod/admin.php:974
 msgid ""
 "The picture proxy increases performance and privacy. It shouldn't be used on"
 " systems with very low bandwith."
 msgstr "Il proxy immagini aumenta le performace e la privacy. Non dovrebbe essere usato su server con poca banda disponibile."
 
-#: mod/admin.php:797
+#: mod/admin.php:975
 msgid "Enable old style pager"
 msgstr "Abilita la paginazione vecchio stile"
 
-#: mod/admin.php:797
+#: mod/admin.php:975
 msgid ""
 "The old style pager has page numbers but slows down massively the page "
 "speed."
 msgstr "La paginazione vecchio stile mostra i numeri delle pagine, ma rallenta la velocità di caricamento della pagina."
 
-#: mod/admin.php:798
+#: mod/admin.php:976
 msgid "Only search in tags"
 msgstr "Cerca solo nei tag"
 
-#: mod/admin.php:798
+#: mod/admin.php:976
 msgid "On large systems the text search can slow down the system extremely."
 msgstr "Su server con molti dati, la ricerca nel testo può estremamente rallentare il sistema."
 
-#: mod/admin.php:800
+#: mod/admin.php:978
 msgid "New base url"
 msgstr "Nuovo url base"
 
-#: mod/admin.php:800
+#: mod/admin.php:978
 msgid ""
 "Change base url for this server. Sends relocate message to all DFRN contacts"
 " of all users."
 msgstr "Cambia l'url base di questo server. Invia il messaggio di trasloco a tutti i contatti DFRN di tutti gli utenti."
 
-#: mod/admin.php:802
+#: mod/admin.php:980
 msgid "RINO Encryption"
 msgstr "Crittografia RINO"
 
-#: mod/admin.php:802
+#: mod/admin.php:980
 msgid "Encryption layer between nodes."
 msgstr "Crittografia delle comunicazioni tra nodi."
 
-#: mod/admin.php:803
+#: mod/admin.php:981
 msgid "Embedly API key"
 msgstr "Embedly API key"
 
-#: mod/admin.php:803
+#: mod/admin.php:981
 msgid ""
 "<a href='http://embed.ly'>Embedly</a> is used to fetch additional data for "
 "web pages. This is an optional parameter."
 msgstr "<a href='http://embed.ly'>Embedly</a> è usato per recuperate informazioni addizionali dalle pagine web. Questo parametro è opzionale."
 
-#: mod/admin.php:821
+#: mod/admin.php:1010
 msgid "Update has been marked successful"
 msgstr "L'aggiornamento è stato segnato come  di successo"
 
-#: mod/admin.php:829
+#: mod/admin.php:1018
 #, php-format
 msgid "Database structure update %s was successfully applied."
 msgstr "Aggiornamento struttura database %s applicata con successo."
 
-#: mod/admin.php:832
+#: mod/admin.php:1021
 #, php-format
 msgid "Executing of database structure update %s failed with error: %s"
 msgstr "Aggiornamento struttura database %s fallita con errore: %s"
 
-#: mod/admin.php:844
+#: mod/admin.php:1033
 #, php-format
 msgid "Executing %s failed with error: %s"
 msgstr "Esecuzione di %s fallita con errore: %s"
 
-#: mod/admin.php:847
+#: mod/admin.php:1036
 #, php-format
 msgid "Update %s was successfully applied."
 msgstr "L'aggiornamento %s è stato applicato con successo"
 
-#: mod/admin.php:851
+#: mod/admin.php:1040
 #, php-format
 msgid "Update %s did not return a status. Unknown if it succeeded."
 msgstr "L'aggiornamento %s non ha riportato uno stato. Non so se è andato a buon fine."
 
-#: mod/admin.php:853
+#: mod/admin.php:1042
 #, php-format
 msgid "There was no additional update function %s that needed to be called."
 msgstr "Non ci sono altre funzioni di aggiornamento %s da richiamare."
 
-#: mod/admin.php:872
+#: mod/admin.php:1061
 msgid "No failed updates."
 msgstr "Nessun aggiornamento fallito."
 
-#: mod/admin.php:873
+#: mod/admin.php:1062
 msgid "Check database structure"
 msgstr "Controlla struttura database"
 
-#: mod/admin.php:878
+#: mod/admin.php:1067
 msgid "Failed Updates"
 msgstr "Aggiornamenti falliti"
 
-#: mod/admin.php:879
+#: mod/admin.php:1068
 msgid ""
 "This does not include updates prior to 1139, which did not return a status."
 msgstr "Questo non include gli aggiornamenti prima del 1139, che non ritornano lo stato."
 
-#: mod/admin.php:880
+#: mod/admin.php:1069
 msgid "Mark success (if update was manually applied)"
 msgstr "Segna completato (se l'update è stato applicato manualmente)"
 
-#: mod/admin.php:881
+#: mod/admin.php:1070
 msgid "Attempt to execute this update step automatically"
 msgstr "Cerco di eseguire questo aggiornamento in automatico"
 
-#: mod/admin.php:913
+#: mod/admin.php:1102
 #, php-format
 msgid ""
 "\n"
@@ -2965,7 +2959,7 @@ msgid ""
 "\t\t\t\tthe administrator of %2$s has set up an account for you."
 msgstr "\nGentile %1$s,\n    l'amministratore di %2$s ha impostato un account per te."
 
-#: mod/admin.php:916
+#: mod/admin.php:1105
 #, php-format
 msgid ""
 "\n"
@@ -2995,233 +2989,255 @@ msgid ""
 "\t\t\tThank you and welcome to %4$s."
 msgstr "\nI dettagli del tuo utente sono:\n    Indirizzo del sito: %1$s\n    Nome utente: %2$s\n    Password: %3$s\n\nPuoi cambiare la tua password dalla pagina delle impostazioni del tuo account dopo esserti autenticato.\n\nPer favore, prenditi qualche momento per esaminare tutte le impostazioni presenti.\n\nPotresti voler aggiungere qualche informazione di base al tuo profilo predefinito (nella pagina \"Profili\"), così che le altre persone possano trovarti più facilmente.\n\nTi raccomandiamo di inserire il tuo nome completo, aggiungere una foto, aggiungere qualche parola chiave del profilo (molto utili per trovare nuovi contatti), e magari in quale nazione vivi, se non vuoi essere più specifico di così.\n\nNoi rispettiamo appieno la tua privacy, e nessuna di queste informazioni è necessaria o obbligatoria.\nSe sei nuovo e non conosci nessuno qui, possono aiutarti a trovare qualche nuovo e interessante contatto.\n\nGrazie e benvenuto su %4$s"
 
-#: mod/admin.php:948 include/user.php:423
+#: mod/admin.php:1137 include/user.php:423
 #, php-format
 msgid "Registration details for %s"
 msgstr "Dettagli della registrazione di %s"
 
-#: mod/admin.php:960
+#: mod/admin.php:1149
 #, php-format
 msgid "%s user blocked/unblocked"
 msgid_plural "%s users blocked/unblocked"
 msgstr[0] "%s utente bloccato/sbloccato"
 msgstr[1] "%s utenti bloccati/sbloccati"
 
-#: mod/admin.php:967
+#: mod/admin.php:1156
 #, php-format
 msgid "%s user deleted"
 msgid_plural "%s users deleted"
 msgstr[0] "%s utente cancellato"
 msgstr[1] "%s utenti cancellati"
 
-#: mod/admin.php:1006
+#: mod/admin.php:1203
 #, php-format
 msgid "User '%s' deleted"
 msgstr "Utente '%s' cancellato"
 
-#: mod/admin.php:1014
+#: mod/admin.php:1211
 #, php-format
 msgid "User '%s' unblocked"
 msgstr "Utente '%s' sbloccato"
 
-#: mod/admin.php:1014
+#: mod/admin.php:1211
 #, php-format
 msgid "User '%s' blocked"
 msgstr "Utente '%s' bloccato"
 
-#: mod/admin.php:1107
+#: mod/admin.php:1302
 msgid "Add User"
 msgstr "Aggiungi utente"
 
-#: mod/admin.php:1108
+#: mod/admin.php:1303
 msgid "select all"
 msgstr "seleziona tutti"
 
-#: mod/admin.php:1109
+#: mod/admin.php:1304
 msgid "User registrations waiting for confirm"
 msgstr "Richieste di registrazione in attesa di conferma"
 
-#: mod/admin.php:1110
+#: mod/admin.php:1305
 msgid "User waiting for permanent deletion"
 msgstr "Utente in attesa di cancellazione definitiva"
 
-#: mod/admin.php:1111
+#: mod/admin.php:1306
 msgid "Request date"
 msgstr "Data richiesta"
 
-#: mod/admin.php:1111 mod/admin.php:1123 mod/admin.php:1124 mod/admin.php:1139
+#: mod/admin.php:1306 mod/admin.php:1318 mod/admin.php:1319 mod/admin.php:1334
 #: include/contact_selectors.php:79 include/contact_selectors.php:86
 msgid "Email"
 msgstr "Email"
 
-#: mod/admin.php:1112
+#: mod/admin.php:1307
 msgid "No registrations."
 msgstr "Nessuna registrazione."
 
-#: mod/admin.php:1114
+#: mod/admin.php:1309
 msgid "Deny"
 msgstr "Nega"
 
-#: mod/admin.php:1118
+#: mod/admin.php:1313
 msgid "Site admin"
 msgstr "Amministrazione sito"
 
-#: mod/admin.php:1119
+#: mod/admin.php:1314
 msgid "Account expired"
 msgstr "Account scaduto"
 
-#: mod/admin.php:1122
+#: mod/admin.php:1317
 msgid "New User"
 msgstr "Nuovo Utente"
 
-#: mod/admin.php:1123 mod/admin.php:1124
+#: mod/admin.php:1318 mod/admin.php:1319
 msgid "Register date"
 msgstr "Data registrazione"
 
-#: mod/admin.php:1123 mod/admin.php:1124
+#: mod/admin.php:1318 mod/admin.php:1319
 msgid "Last login"
 msgstr "Ultimo accesso"
 
-#: mod/admin.php:1123 mod/admin.php:1124
+#: mod/admin.php:1318 mod/admin.php:1319
 msgid "Last item"
 msgstr "Ultimo elemento"
 
-#: mod/admin.php:1123
+#: mod/admin.php:1318
 msgid "Deleted since"
 msgstr "Rimosso da"
 
-#: mod/admin.php:1124 mod/settings.php:41
+#: mod/admin.php:1319 mod/settings.php:41
 msgid "Account"
 msgstr "Account"
 
-#: mod/admin.php:1126
+#: mod/admin.php:1321
 msgid ""
 "Selected users will be deleted!\\n\\nEverything these users had posted on "
 "this site will be permanently deleted!\\n\\nAre you sure?"
 msgstr "Gli utenti selezionati saranno cancellati!\\n\\nTutto quello che gli utenti hanno inviato su questo sito sarà permanentemente canellato!\\n\\nSei sicuro?"
 
-#: mod/admin.php:1127
+#: mod/admin.php:1322
 msgid ""
 "The user {0} will be deleted!\\n\\nEverything this user has posted on this "
 "site will be permanently deleted!\\n\\nAre you sure?"
 msgstr "L'utente {0} sarà cancellato!\\n\\nTutto quello che ha inviato su questo sito sarà permanentemente cancellato!\\n\\nSei sicuro?"
 
-#: mod/admin.php:1137
+#: mod/admin.php:1332
 msgid "Name of the new user."
 msgstr "Nome del nuovo utente."
 
-#: mod/admin.php:1138
+#: mod/admin.php:1333
 msgid "Nickname"
 msgstr "Nome utente"
 
-#: mod/admin.php:1138
+#: mod/admin.php:1333
 msgid "Nickname of the new user."
 msgstr "Nome utente del nuovo utente."
 
-#: mod/admin.php:1139
+#: mod/admin.php:1334
 msgid "Email address of the new user."
 msgstr "Indirizzo Email del nuovo utente."
 
-#: mod/admin.php:1172
+#: mod/admin.php:1377
 #, php-format
 msgid "Plugin %s disabled."
 msgstr "Plugin %s disabilitato."
 
-#: mod/admin.php:1176
+#: mod/admin.php:1381
 #, php-format
 msgid "Plugin %s enabled."
 msgstr "Plugin %s abilitato."
 
-#: mod/admin.php:1186 mod/admin.php:1410
+#: mod/admin.php:1392 mod/admin.php:1628
 msgid "Disable"
 msgstr "Disabilita"
 
-#: mod/admin.php:1188 mod/admin.php:1412
+#: mod/admin.php:1394 mod/admin.php:1630
 msgid "Enable"
 msgstr "Abilita"
 
-#: mod/admin.php:1211 mod/admin.php:1456
+#: mod/admin.php:1417 mod/admin.php:1675
 msgid "Toggle"
 msgstr "Inverti"
 
-#: mod/admin.php:1219 mod/admin.php:1466
+#: mod/admin.php:1425 mod/admin.php:1684
 msgid "Author: "
 msgstr "Autore: "
 
-#: mod/admin.php:1220 mod/admin.php:1467
+#: mod/admin.php:1426 mod/admin.php:1685
 msgid "Maintainer: "
 msgstr "Manutentore: "
 
-#: mod/admin.php:1272
-#: view/smarty3/compiled/f835364006028b1061f37be121c9bd9db5fa50a9.file.admin_plugins.tpl.php:42
+#: mod/admin.php:1478
 msgid "Reload active plugins"
 msgstr "Ricarica i plugin attivi"
 
-#: mod/admin.php:1370
+#: mod/admin.php:1483
+#, php-format
+msgid ""
+"There are currently no plugins available on your node. You can find the "
+"official plugin repository at %1$s and might find other interesting plugins "
+"in the open plugin registry at %2$s"
+msgstr ""
+
+#: mod/admin.php:1588
 msgid "No themes found."
 msgstr "Nessun tema trovato."
 
-#: mod/admin.php:1448
+#: mod/admin.php:1666
 msgid "Screenshot"
 msgstr "Anteprima"
 
-#: mod/admin.php:1508
+#: mod/admin.php:1726
 msgid "Reload active themes"
 msgstr "Ricarica i temi attivi"
 
-#: mod/admin.php:1512
+#: mod/admin.php:1731
+#, php-format
+msgid "No themes found on the system. They should be paced in %1$s"
+msgstr ""
+
+#: mod/admin.php:1732
 msgid "[Experimental]"
 msgstr "[Sperimentale]"
 
-#: mod/admin.php:1513
+#: mod/admin.php:1733
 msgid "[Unsupported]"
 msgstr "[Non supportato]"
 
-#: mod/admin.php:1540
+#: mod/admin.php:1757
 msgid "Log settings updated."
 msgstr "Impostazioni Log aggiornate."
 
-#: mod/admin.php:1596
+#: mod/admin.php:1794
 msgid "Clear"
 msgstr "Pulisci"
 
-#: mod/admin.php:1602
+#: mod/admin.php:1799
 msgid "Enable Debugging"
 msgstr "Abilita Debugging"
 
-#: mod/admin.php:1603
+#: mod/admin.php:1800
 msgid "Log file"
 msgstr "File di Log"
 
-#: mod/admin.php:1603
+#: mod/admin.php:1800
 msgid ""
 "Must be writable by web server. Relative to your Friendica top-level "
 "directory."
 msgstr "Deve essere scrivibile dal server web. Relativo alla tua directory Friendica."
 
-#: mod/admin.php:1604
+#: mod/admin.php:1801
 msgid "Log level"
 msgstr "Livello di Log"
 
-#: mod/admin.php:1654 include/acl_selectors.php:348
-msgid "Close"
-msgstr "Chiudi"
+#: mod/admin.php:1804
+msgid "PHP logging"
+msgstr ""
 
-#: mod/admin.php:1660
-msgid "FTP Host"
-msgstr "Indirizzo FTP"
+#: mod/admin.php:1805
+msgid ""
+"To enable logging of PHP errors and warnings you can add the following to "
+"the .htconfig.php file of your installation. The filename set in the "
+"'error_log' line is relative to the friendica top-level directory and must "
+"be writeable by the web server. The option '1' for 'log_errors' and "
+"'display_errors' is to enable these options, set to '0' to disable them."
+msgstr ""
 
-#: mod/admin.php:1661
-msgid "FTP Path"
-msgstr "Percorso FTP"
+#: mod/admin.php:1931 mod/admin.php:1932 mod/settings.php:759
+msgid "Off"
+msgstr "Spento"
 
-#: mod/admin.php:1662
-msgid "FTP User"
-msgstr "Utente FTP"
+#: mod/admin.php:1931 mod/admin.php:1932 mod/settings.php:759
+msgid "On"
+msgstr "Acceso"
 
-#: mod/admin.php:1663
-msgid "FTP Password"
-msgstr "Pasword FTP"
+#: mod/admin.php:1932
+#, php-format
+msgid "Lock feature %s"
+msgstr ""
+
+#: mod/admin.php:1940
+msgid "Manage Additional Features"
+msgstr ""
 
 #: mod/network.php:146
 #, php-format
@@ -3232,7 +3248,7 @@ msgstr "Risultato della ricerca per: %s"
 msgid "Remove term"
 msgstr "Rimuovi termine"
 
-#: mod/network.php:200 mod/search.php:34 include/features.php:79
+#: mod/network.php:200 mod/search.php:34 include/features.php:84
 msgid "Saved Searches"
 msgstr "Ricerche salvate"
 
@@ -3240,51 +3256,51 @@ msgstr "Ricerche salvate"
 msgid "add"
 msgstr "aggiungi"
 
-#: mod/network.php:362
+#: mod/network.php:365
 msgid "Commented Order"
 msgstr "Ordina per commento"
 
-#: mod/network.php:365
+#: mod/network.php:368
 msgid "Sort by Comment Date"
 msgstr "Ordina per data commento"
 
-#: mod/network.php:370
+#: mod/network.php:373
 msgid "Posted Order"
 msgstr "Ordina per invio"
 
-#: mod/network.php:373
+#: mod/network.php:376
 msgid "Sort by Post Date"
 msgstr "Ordina per data messaggio"
 
-#: mod/network.php:384
+#: mod/network.php:387
 msgid "Posts that mention or involve you"
 msgstr "Messaggi che ti citano o coinvolgono"
 
-#: mod/network.php:392
+#: mod/network.php:395
 msgid "New"
 msgstr "Nuovo"
 
-#: mod/network.php:395
+#: mod/network.php:398
 msgid "Activity Stream - by date"
 msgstr "Activity Stream - per data"
 
-#: mod/network.php:403
+#: mod/network.php:406
 msgid "Shared Links"
 msgstr "Links condivisi"
 
-#: mod/network.php:406
+#: mod/network.php:409
 msgid "Interesting Links"
 msgstr "Link Interessanti"
 
-#: mod/network.php:414
+#: mod/network.php:417
 msgid "Starred"
 msgstr "Preferiti"
 
-#: mod/network.php:417
+#: mod/network.php:420
 msgid "Favourite Posts"
 msgstr "Messaggi preferiti"
 
-#: mod/network.php:476
+#: mod/network.php:479
 #, php-format
 msgid "Warning: This group contains %s member from an insecure network."
 msgid_plural ""
@@ -3292,28 +3308,28 @@ msgid_plural ""
 msgstr[0] "Attenzione: questo gruppo contiene %s membro da un network insicuro."
 msgstr[1] "Attenzione: questo gruppo contiene %s membri da un network insicuro."
 
-#: mod/network.php:479
+#: mod/network.php:482
 msgid "Private messages to this group are at risk of public disclosure."
 msgstr "I messaggi privati su questo gruppo potrebbero risultare visibili anche pubblicamente."
 
-#: mod/network.php:546 mod/content.php:119
+#: mod/network.php:549 mod/content.php:119
 msgid "No such group"
 msgstr "Nessun gruppo"
 
-#: mod/network.php:574 mod/content.php:135
+#: mod/network.php:580 mod/content.php:135
 #, php-format
 msgid "Group: %s"
 msgstr "Gruppo: %s"
 
-#: mod/network.php:606
+#: mod/network.php:608
 msgid "Private messages to this person are at risk of public disclosure."
 msgstr "I messaggi privati a questa persona potrebbero risultare visibili anche pubblicamente."
 
-#: mod/network.php:611
+#: mod/network.php:613
 msgid "Invalid contact."
 msgstr "Contatto non valido."
 
-#: mod/allfriends.php:38
+#: mod/allfriends.php:43
 msgid "No friends to display."
 msgstr "Nessun amico da visualizzare."
 
@@ -3353,11 +3369,11 @@ msgstr "Ven"
 msgid "Sat"
 msgstr "Sab"
 
-#: mod/events.php:208 mod/settings.php:939 include/text.php:1274
+#: mod/events.php:208 mod/settings.php:948 include/text.php:1274
 msgid "Sunday"
 msgstr "Domenica"
 
-#: mod/events.php:209 mod/settings.php:939 include/text.php:1274
+#: mod/events.php:209 mod/settings.php:948 include/text.php:1274
 msgid "Monday"
 msgstr "Lunedì"
 
@@ -3497,11 +3513,11 @@ msgstr "l j F"
 msgid "Edit event"
 msgstr "Modifca l'evento"
 
-#: mod/events.php:421 include/text.php:1721 include/text.php:1728
+#: mod/events.php:421 include/text.php:1728 include/text.php:1735
 msgid "link to source"
 msgstr "Collegamento all'originale"
 
-#: mod/events.php:456 include/identity.php:713 include/nav.php:79
+#: mod/events.php:456 include/identity.php:722 include/nav.php:79
 #: include/nav.php:140 view/theme/diabook/theme.php:127
 msgid "Events"
 msgstr "Eventi"
@@ -3560,7 +3576,7 @@ msgstr "Condividi questo evento"
 
 #: mod/events.php:572 mod/content.php:721 mod/editpost.php:145
 #: mod/photos.php:1631 mod/photos.php:1679 mod/photos.php:1767
-#: object/Item.php:719 include/conversation.php:1217
+#: object/Item.php:719 include/conversation.php:1216
 msgid "Preview"
 msgstr "Anteprima"
 
@@ -3604,15 +3620,15 @@ msgstr[0] "%d commento"
 msgstr[1] "%d commenti"
 
 #: mod/content.php:607 object/Item.php:421 object/Item.php:434
-#: include/text.php:1997
+#: include/text.php:2004
 msgid "comment"
 msgid_plural "comments"
 msgstr[0] ""
 msgstr[1] "commento"
 
-#: mod/content.php:608 boot.php:785 object/Item.php:422
+#: mod/content.php:608 boot.php:870 object/Item.php:422
 #: include/contact_widgets.php:242 include/forums.php:110
-#: include/items.php:5178 view/theme/vier/theme.php:264
+#: include/items.php:5207 view/theme/vier/theme.php:264
 msgid "show more"
 msgstr "mostra di più"
 
@@ -3650,7 +3666,7 @@ msgid "This is you"
 msgstr "Questo sei tu"
 
 #: mod/content.php:711 mod/photos.php:1629 mod/photos.php:1677
-#: mod/photos.php:1765 boot.php:784 object/Item.php:393 object/Item.php:709
+#: mod/photos.php:1765 boot.php:869 object/Item.php:393 object/Item.php:709
 msgid "Comment"
 msgstr "Commento"
 
@@ -3686,7 +3702,7 @@ msgstr "Link"
 msgid "Video"
 msgstr "Video"
 
-#: mod/content.php:730 mod/settings.php:712 object/Item.php:122
+#: mod/content.php:730 mod/settings.php:721 object/Item.php:122
 #: object/Item.php:124
 msgid "Edit"
 msgstr "Modifica"
@@ -4082,19 +4098,19 @@ msgid ""
 "your site allow private mail from unknown senders."
 msgstr "Se vuoi che %s ti risponda, controlla che le tue impostazioni di privacy permettano la ricezione di messaggi privati da mittenti sconosciuti."
 
-#: mod/help.php:31
+#: mod/help.php:41
 msgid "Help:"
 msgstr "Guida:"
 
-#: mod/help.php:36 include/nav.php:113 view/theme/vier/theme.php:302
+#: mod/help.php:47 include/nav.php:113 view/theme/vier/theme.php:302
 msgid "Help"
 msgstr "Guida"
 
-#: mod/help.php:42 mod/p.php:16 mod/p.php:25 index.php:269
+#: mod/help.php:53 mod/p.php:16 mod/p.php:25 index.php:270
 msgid "Not Found"
 msgstr "Non trovato"
 
-#: mod/help.php:45 index.php:272
+#: mod/help.php:56 index.php:273
 msgid "Page not found."
 msgstr "Pagina non trovata."
 
@@ -4141,16 +4157,16 @@ msgstr "Profili corrispondenti"
 msgid "link"
 msgstr "collegamento"
 
-#: mod/community.php:23
+#: mod/community.php:27
 msgid "Not available."
 msgstr "Non disponibile."
 
-#: mod/community.php:32 include/nav.php:136 include/nav.php:138
+#: mod/community.php:36 include/nav.php:136 include/nav.php:138
 #: view/theme/diabook/theme.php:129
 msgid "Community"
 msgstr "Comunità"
 
-#: mod/community.php:62 mod/community.php:71 mod/search.php:228
+#: mod/community.php:66 mod/community.php:75 mod/search.php:228
 msgid "No results."
 msgstr "Nessun risultato."
 
@@ -4158,822 +4174,812 @@ msgstr "Nessun risultato."
 msgid "everybody"
 msgstr "tutti"
 
-#: mod/settings.php:47
-msgid "Additional features"
-msgstr "Funzionalità aggiuntive"
-
-#: mod/settings.php:53
+#: mod/settings.php:58
 msgid "Display"
 msgstr "Visualizzazione"
 
-#: mod/settings.php:60 mod/settings.php:855
+#: mod/settings.php:65 mod/settings.php:864
 msgid "Social Networks"
 msgstr "Social Networks"
 
-#: mod/settings.php:72 include/nav.php:180
+#: mod/settings.php:79 include/nav.php:180
 msgid "Delegations"
 msgstr "Delegazioni"
 
-#: mod/settings.php:78
+#: mod/settings.php:86
 msgid "Connected apps"
 msgstr "Applicazioni collegate"
 
-#: mod/settings.php:84 mod/uexport.php:85
+#: mod/settings.php:93 mod/uexport.php:85
 msgid "Export personal data"
 msgstr "Esporta dati personali"
 
-#: mod/settings.php:90
+#: mod/settings.php:100
 msgid "Remove account"
 msgstr "Rimuovi account"
 
-#: mod/settings.php:143
+#: mod/settings.php:153
 msgid "Missing some important data!"
 msgstr "Mancano alcuni dati importanti!"
 
-#: mod/settings.php:256
+#: mod/settings.php:266
 msgid "Failed to connect with email account using the settings provided."
 msgstr "Impossibile collegarsi all'account email con i parametri forniti."
 
-#: mod/settings.php:261
+#: mod/settings.php:271
 msgid "Email settings updated."
 msgstr "Impostazioni e-mail aggiornate."
 
-#: mod/settings.php:276
+#: mod/settings.php:286
 msgid "Features updated"
 msgstr "Funzionalità aggiornate"
 
-#: mod/settings.php:343
+#: mod/settings.php:353
 msgid "Relocate message has been send to your contacts"
 msgstr "Il messaggio di trasloco è stato inviato ai tuoi contatti"
 
-#: mod/settings.php:357 include/user.php:39
+#: mod/settings.php:367 include/user.php:39
 msgid "Passwords do not match. Password unchanged."
 msgstr "Le password non corrispondono. Password non cambiata."
 
-#: mod/settings.php:362
+#: mod/settings.php:372
 msgid "Empty passwords are not allowed. Password unchanged."
 msgstr "Le password non possono essere vuote. Password non cambiata."
 
-#: mod/settings.php:370
+#: mod/settings.php:380
 msgid "Wrong password."
 msgstr "Password sbagliata."
 
-#: mod/settings.php:381
+#: mod/settings.php:391
 msgid "Password changed."
 msgstr "Password cambiata."
 
-#: mod/settings.php:383
+#: mod/settings.php:393
 msgid "Password update failed. Please try again."
 msgstr "Aggiornamento password fallito. Prova ancora."
 
-#: mod/settings.php:452
+#: mod/settings.php:462
 msgid " Please use a shorter name."
 msgstr " Usa un nome più corto."
 
-#: mod/settings.php:454
+#: mod/settings.php:464
 msgid " Name too short."
 msgstr " Nome troppo corto."
 
-#: mod/settings.php:463
+#: mod/settings.php:473
 msgid "Wrong Password"
 msgstr "Password Sbagliata"
 
-#: mod/settings.php:468
+#: mod/settings.php:478
 msgid " Not valid email."
 msgstr " Email non valida."
 
-#: mod/settings.php:474
+#: mod/settings.php:484
 msgid " Cannot change to that email."
 msgstr "Non puoi usare quella email."
 
-#: mod/settings.php:530
+#: mod/settings.php:540
 msgid "Private forum has no privacy permissions. Using default privacy group."
 msgstr "Il forum privato non ha permessi di privacy. Uso il gruppo di privacy predefinito."
 
-#: mod/settings.php:534
+#: mod/settings.php:544
 msgid "Private forum has no privacy permissions and no default privacy group."
 msgstr "Il gruppo privato non ha permessi di privacy e nessun gruppo di privacy predefinito."
 
-#: mod/settings.php:573
+#: mod/settings.php:583
 msgid "Settings updated."
 msgstr "Impostazioni aggiornate."
 
-#: mod/settings.php:649 mod/settings.php:675 mod/settings.php:711
+#: mod/settings.php:658 mod/settings.php:684 mod/settings.php:720
 msgid "Add application"
 msgstr "Aggiungi applicazione"
 
-#: mod/settings.php:653 mod/settings.php:679
+#: mod/settings.php:662 mod/settings.php:688
 msgid "Consumer Key"
 msgstr "Consumer Key"
 
-#: mod/settings.php:654 mod/settings.php:680
+#: mod/settings.php:663 mod/settings.php:689
 msgid "Consumer Secret"
 msgstr "Consumer Secret"
 
-#: mod/settings.php:655 mod/settings.php:681
+#: mod/settings.php:664 mod/settings.php:690
 msgid "Redirect"
 msgstr "Redirect"
 
-#: mod/settings.php:656 mod/settings.php:682
+#: mod/settings.php:665 mod/settings.php:691
 msgid "Icon url"
 msgstr "Url icona"
 
-#: mod/settings.php:667
+#: mod/settings.php:676
 msgid "You can't edit this application."
 msgstr "Non puoi modificare questa applicazione."
 
-#: mod/settings.php:710
+#: mod/settings.php:719
 msgid "Connected Apps"
 msgstr "Applicazioni Collegate"
 
-#: mod/settings.php:714
+#: mod/settings.php:723
 msgid "Client key starts with"
 msgstr "Chiave del client inizia con"
 
-#: mod/settings.php:715
+#: mod/settings.php:724
 msgid "No name"
 msgstr "Nessun nome"
 
-#: mod/settings.php:716
+#: mod/settings.php:725
 msgid "Remove authorization"
 msgstr "Rimuovi l'autorizzazione"
 
-#: mod/settings.php:728
+#: mod/settings.php:737
 msgid "No Plugin settings configured"
 msgstr "Nessun plugin ha impostazioni modificabili"
 
-#: mod/settings.php:736
+#: mod/settings.php:745
 msgid "Plugin Settings"
 msgstr "Impostazioni plugin"
 
-#: mod/settings.php:750
-msgid "Off"
-msgstr "Spento"
-
-#: mod/settings.php:750
-msgid "On"
-msgstr "Acceso"
-
-#: mod/settings.php:758
+#: mod/settings.php:767
 msgid "Additional Features"
 msgstr "Funzionalità aggiuntive"
 
-#: mod/settings.php:768 mod/settings.php:772
+#: mod/settings.php:777 mod/settings.php:781
 msgid "General Social Media Settings"
 msgstr "Impostazioni Media Sociali"
 
-#: mod/settings.php:778
+#: mod/settings.php:787
 msgid "Disable intelligent shortening"
 msgstr "Disabilita accorciamento intelligente"
 
-#: mod/settings.php:780
+#: mod/settings.php:789
 msgid ""
 "Normally the system tries to find the best link to add to shortened posts. "
 "If this option is enabled then every shortened post will always point to the"
 " original friendica post."
 msgstr "Normalmente il sistema tenta di trovare il migliore link da aggiungere a un post accorciato. Se questa opzione è abilitata, ogni post accorciato conterrà sempre un link al post originale su Friendica."
 
-#: mod/settings.php:786
+#: mod/settings.php:795
 msgid "Automatically follow any GNU Social (OStatus) followers/mentioners"
 msgstr "Segui automanticamente chiunque da GNU Social (OStatus)  ti segua o ti menzioni"
 
-#: mod/settings.php:788
+#: mod/settings.php:797
 msgid ""
 "If you receive a message from an unknown OStatus user, this option decides "
 "what to do. If it is checked, a new contact will be created for every "
 "unknown user."
 msgstr "Se ricevi un messaggio da un utente OStatus sconosciuto, questa opzione decide cosa fare. Se selezionato, un nuovo contatto verrà creato per ogni utente sconosciuto."
 
-#: mod/settings.php:797
+#: mod/settings.php:806
 msgid "Your legacy GNU Social account"
 msgstr "Il tuo vecchio account GNU Social"
 
-#: mod/settings.php:799
+#: mod/settings.php:808
 msgid ""
 "If you enter your old GNU Social/Statusnet account name here (in the format "
 "user@domain.tld), your contacts will be added automatically. The field will "
 "be emptied when done."
 msgstr "Se inserisci il nome del tuo vecchio account GNU Social/Statusnet qui (nel formato utente@dominio.tld), i tuoi contatti verranno automaticamente aggiunti. Il campo verrà svuotato una volta terminato."
 
-#: mod/settings.php:802
+#: mod/settings.php:811
 msgid "Repair OStatus subscriptions"
 msgstr "Ripara le iscrizioni OStatus"
 
-#: mod/settings.php:811 mod/settings.php:812
+#: mod/settings.php:820 mod/settings.php:821
 #, php-format
 msgid "Built-in support for %s connectivity is %s"
 msgstr "Il supporto integrato per la connettività con %s è %s"
 
-#: mod/settings.php:811 mod/dfrn_request.php:858
+#: mod/settings.php:820 mod/dfrn_request.php:865
 #: include/contact_selectors.php:80
 msgid "Diaspora"
 msgstr "Diaspora"
 
-#: mod/settings.php:811 mod/settings.php:812
+#: mod/settings.php:820 mod/settings.php:821
 msgid "enabled"
 msgstr "abilitato"
 
-#: mod/settings.php:811 mod/settings.php:812
+#: mod/settings.php:820 mod/settings.php:821
 msgid "disabled"
 msgstr "disabilitato"
 
-#: mod/settings.php:812
+#: mod/settings.php:821
 msgid "GNU Social (OStatus)"
 msgstr "GNU Social (OStatus)"
 
-#: mod/settings.php:848
+#: mod/settings.php:857
 msgid "Email access is disabled on this site."
 msgstr "L'accesso email è disabilitato su questo sito."
 
-#: mod/settings.php:860
+#: mod/settings.php:869
 msgid "Email/Mailbox Setup"
 msgstr "Impostazioni email"
 
-#: mod/settings.php:861
+#: mod/settings.php:870
 msgid ""
 "If you wish to communicate with email contacts using this service "
 "(optional), please specify how to connect to your mailbox."
 msgstr "Se vuoi comunicare con i contatti email usando questo servizio, specifica come collegarti alla tua casella di posta. (opzionale)"
 
-#: mod/settings.php:862
+#: mod/settings.php:871
 msgid "Last successful email check:"
 msgstr "Ultimo controllo email eseguito con successo:"
 
-#: mod/settings.php:864
+#: mod/settings.php:873
 msgid "IMAP server name:"
 msgstr "Nome server IMAP:"
 
-#: mod/settings.php:865
+#: mod/settings.php:874
 msgid "IMAP port:"
 msgstr "Porta IMAP:"
 
-#: mod/settings.php:866
+#: mod/settings.php:875
 msgid "Security:"
 msgstr "Sicurezza:"
 
-#: mod/settings.php:866 mod/settings.php:871
+#: mod/settings.php:875 mod/settings.php:880
 msgid "None"
 msgstr "Nessuna"
 
-#: mod/settings.php:867
+#: mod/settings.php:876
 msgid "Email login name:"
 msgstr "Nome utente email:"
 
-#: mod/settings.php:868
+#: mod/settings.php:877
 msgid "Email password:"
 msgstr "Password email:"
 
-#: mod/settings.php:869
+#: mod/settings.php:878
 msgid "Reply-to address:"
 msgstr "Indirizzo di risposta:"
 
-#: mod/settings.php:870
+#: mod/settings.php:879
 msgid "Send public posts to all email contacts:"
 msgstr "Invia i messaggi pubblici ai contatti email:"
 
-#: mod/settings.php:871
+#: mod/settings.php:880
 msgid "Action after import:"
 msgstr "Azione post importazione:"
 
-#: mod/settings.php:871
+#: mod/settings.php:880
 msgid "Mark as seen"
 msgstr "Segna come letto"
 
-#: mod/settings.php:871
+#: mod/settings.php:880
 msgid "Move to folder"
 msgstr "Sposta nella cartella"
 
-#: mod/settings.php:872
+#: mod/settings.php:881
 msgid "Move to folder:"
 msgstr "Sposta nella cartella:"
 
-#: mod/settings.php:958
+#: mod/settings.php:967
 msgid "Display Settings"
 msgstr "Impostazioni Grafiche"
 
-#: mod/settings.php:964 mod/settings.php:982
+#: mod/settings.php:973 mod/settings.php:991
 msgid "Display Theme:"
 msgstr "Tema:"
 
-#: mod/settings.php:965
+#: mod/settings.php:974
 msgid "Mobile Theme:"
 msgstr "Tema mobile:"
 
-#: mod/settings.php:966
+#: mod/settings.php:975
 msgid "Update browser every xx seconds"
 msgstr "Aggiorna il browser ogni x secondi"
 
-#: mod/settings.php:966
+#: mod/settings.php:975
 msgid "Minimum of 10 seconds. Enter -1 to disable it."
 msgstr "Minimo 10 secondi. Inserisci -1 per disabilitarlo"
 
-#: mod/settings.php:967
+#: mod/settings.php:976
 msgid "Number of items to display per page:"
 msgstr "Numero di elementi da mostrare per pagina:"
 
-#: mod/settings.php:967 mod/settings.php:968
+#: mod/settings.php:976 mod/settings.php:977
 msgid "Maximum of 100 items"
 msgstr "Massimo 100 voci"
 
-#: mod/settings.php:968
+#: mod/settings.php:977
 msgid "Number of items to display per page when viewed from mobile device:"
 msgstr "Numero di voci da visualizzare per pagina quando si utilizza un dispositivo mobile:"
 
-#: mod/settings.php:969
+#: mod/settings.php:978
 msgid "Don't show emoticons"
 msgstr "Non mostrare le emoticons"
 
-#: mod/settings.php:970
+#: mod/settings.php:979
 msgid "Calendar"
 msgstr "Calendario"
 
-#: mod/settings.php:971
+#: mod/settings.php:980
 msgid "Beginning of week:"
 msgstr "Inizio della settimana:"
 
-#: mod/settings.php:972
+#: mod/settings.php:981
 msgid "Don't show notices"
 msgstr "Non mostrare gli avvisi"
 
-#: mod/settings.php:973
+#: mod/settings.php:982
 msgid "Infinite scroll"
 msgstr "Scroll infinito"
 
-#: mod/settings.php:974
+#: mod/settings.php:983
 msgid "Automatic updates only at the top of the network page"
 msgstr "Aggiornamenti automatici solo in cima alla pagina \"rete\""
 
-#: mod/settings.php:976 view/theme/cleanzero/config.php:82
+#: mod/settings.php:985 view/theme/cleanzero/config.php:82
 #: view/theme/dispy/config.php:72 view/theme/quattro/config.php:66
-#: view/theme/diabook/config.php:150 view/theme/clean/config.php:85
-#: view/theme/vier/config.php:109 view/theme/duepuntozero/config.php:61
+#: view/theme/diabook/config.php:150 view/theme/vier/config.php:109
+#: view/theme/duepuntozero/config.php:61
 msgid "Theme settings"
 msgstr "Impostazioni tema"
 
-#: mod/settings.php:1053
+#: mod/settings.php:1062
 msgid "User Types"
 msgstr "Tipi di Utenti"
 
-#: mod/settings.php:1054
+#: mod/settings.php:1063
 msgid "Community Types"
 msgstr "Tipi di Comunità"
 
-#: mod/settings.php:1055
+#: mod/settings.php:1064
 msgid "Normal Account Page"
 msgstr "Pagina Account Normale"
 
-#: mod/settings.php:1056
+#: mod/settings.php:1065
 msgid "This account is a normal personal profile"
 msgstr "Questo account è un normale profilo personale"
 
-#: mod/settings.php:1059
+#: mod/settings.php:1068
 msgid "Soapbox Page"
 msgstr "Pagina Sandbox"
 
-#: mod/settings.php:1060
+#: mod/settings.php:1069
 msgid "Automatically approve all connection/friend requests as read-only fans"
 msgstr "Chi richiede la connessione/amicizia sarà accettato automaticamente come fan che potrà solamente leggere la bacheca"
 
-#: mod/settings.php:1063
+#: mod/settings.php:1072
 msgid "Community Forum/Celebrity Account"
 msgstr "Account Celebrità/Forum comunitario"
 
-#: mod/settings.php:1064
+#: mod/settings.php:1073
 msgid ""
 "Automatically approve all connection/friend requests as read-write fans"
 msgstr "Chi richiede la connessione/amicizia sarà accettato automaticamente come fan che potrà leggere e scrivere sulla bacheca"
 
-#: mod/settings.php:1067
+#: mod/settings.php:1076
 msgid "Automatic Friend Page"
 msgstr "Pagina con amicizia automatica"
 
-#: mod/settings.php:1068
+#: mod/settings.php:1077
 msgid "Automatically approve all connection/friend requests as friends"
 msgstr "Chi richiede la connessione/amicizia sarà accettato automaticamente come amico"
 
-#: mod/settings.php:1071
+#: mod/settings.php:1080
 msgid "Private Forum [Experimental]"
 msgstr "Forum privato [sperimentale]"
 
-#: mod/settings.php:1072
+#: mod/settings.php:1081
 msgid "Private forum - approved members only"
 msgstr "Forum privato - solo membri approvati"
 
-#: mod/settings.php:1084
+#: mod/settings.php:1093
 msgid "OpenID:"
 msgstr "OpenID:"
 
-#: mod/settings.php:1084
+#: mod/settings.php:1093
 msgid "(Optional) Allow this OpenID to login to this account."
 msgstr "(Opzionale) Consente di loggarti in questo account con questo OpenID"
 
-#: mod/settings.php:1094
+#: mod/settings.php:1103
 msgid "Publish your default profile in your local site directory?"
 msgstr "Pubblica il tuo profilo predefinito nell'elenco locale del sito"
 
-#: mod/settings.php:1100
+#: mod/settings.php:1109
 msgid "Publish your default profile in the global social directory?"
 msgstr "Pubblica il tuo profilo predefinito nell'elenco sociale globale"
 
-#: mod/settings.php:1108
+#: mod/settings.php:1117
 msgid "Hide your contact/friend list from viewers of your default profile?"
 msgstr "Nascondi la lista dei tuoi contatti/amici dai visitatori del tuo profilo predefinito"
 
-#: mod/settings.php:1112 include/acl_selectors.php:331
+#: mod/settings.php:1121 include/acl_selectors.php:331
 msgid "Hide your profile details from unknown viewers?"
 msgstr "Nascondi i dettagli del tuo profilo ai visitatori sconosciuti?"
 
-#: mod/settings.php:1112
+#: mod/settings.php:1121
 msgid ""
 "If enabled, posting public messages to Diaspora and other networks isn't "
 "possible."
 msgstr "Se abilitato, l'invio di messaggi pubblici verso Diaspora e altri network non sarà possibile"
 
-#: mod/settings.php:1117
+#: mod/settings.php:1126
 msgid "Allow friends to post to your profile page?"
 msgstr "Permetti agli amici di scrivere sulla tua pagina profilo?"
 
-#: mod/settings.php:1123
+#: mod/settings.php:1132
 msgid "Allow friends to tag your posts?"
 msgstr "Permetti agli amici di taggare i tuoi messaggi?"
 
-#: mod/settings.php:1129
+#: mod/settings.php:1138
 msgid "Allow us to suggest you as a potential friend to new members?"
 msgstr "Ci permetti di suggerirti come potenziale amico ai nuovi membri?"
 
-#: mod/settings.php:1135
+#: mod/settings.php:1144
 msgid "Permit unknown people to send you private mail?"
 msgstr "Permetti a utenti sconosciuti di inviarti messaggi privati?"
 
-#: mod/settings.php:1143
+#: mod/settings.php:1152
 msgid "Profile is <strong>not published</strong>."
 msgstr "Il profilo <strong>non è pubblicato</strong>."
 
-#: mod/settings.php:1151
+#: mod/settings.php:1160
 #, php-format
 msgid "Your Identity Address is <strong>'%s'</strong> or '%s'."
 msgstr "L'indirizzo della tua identità è <strong>'%s'</strong> or '%s'."
 
-#: mod/settings.php:1158
+#: mod/settings.php:1167
 msgid "Automatically expire posts after this many days:"
 msgstr "Fai scadere i post automaticamente dopo x giorni:"
 
-#: mod/settings.php:1158
+#: mod/settings.php:1167
 msgid "If empty, posts will not expire. Expired posts will be deleted"
 msgstr "Se lasciato vuoto, i messaggi non verranno cancellati."
 
-#: mod/settings.php:1159
+#: mod/settings.php:1168
 msgid "Advanced expiration settings"
 msgstr "Impostazioni avanzate di scandenza"
 
-#: mod/settings.php:1160
+#: mod/settings.php:1169
 msgid "Advanced Expiration"
 msgstr "Scadenza avanzata"
 
-#: mod/settings.php:1161
+#: mod/settings.php:1170
 msgid "Expire posts:"
 msgstr "Fai scadere i post:"
 
-#: mod/settings.php:1162
+#: mod/settings.php:1171
 msgid "Expire personal notes:"
 msgstr "Fai scadere le Note personali:"
 
-#: mod/settings.php:1163
+#: mod/settings.php:1172
 msgid "Expire starred posts:"
 msgstr "Fai scadere i post Speciali:"
 
-#: mod/settings.php:1164
+#: mod/settings.php:1173
 msgid "Expire photos:"
 msgstr "Fai scadere le foto:"
 
-#: mod/settings.php:1165
+#: mod/settings.php:1174
 msgid "Only expire posts by others:"
 msgstr "Fai scadere solo i post degli altri:"
 
-#: mod/settings.php:1193
+#: mod/settings.php:1202
 msgid "Account Settings"
 msgstr "Impostazioni account"
 
-#: mod/settings.php:1201
+#: mod/settings.php:1210
 msgid "Password Settings"
 msgstr "Impostazioni password"
 
-#: mod/settings.php:1202 mod/register.php:274
+#: mod/settings.php:1211 mod/register.php:274
 msgid "New Password:"
 msgstr "Nuova password:"
 
-#: mod/settings.php:1203 mod/register.php:275
+#: mod/settings.php:1212 mod/register.php:275
 msgid "Confirm:"
 msgstr "Conferma:"
 
-#: mod/settings.php:1203
+#: mod/settings.php:1212
 msgid "Leave password fields blank unless changing"
 msgstr "Lascia questi campi in bianco per non effettuare variazioni alla password"
 
-#: mod/settings.php:1204
+#: mod/settings.php:1213
 msgid "Current Password:"
 msgstr "Password Attuale:"
 
-#: mod/settings.php:1204 mod/settings.php:1205
+#: mod/settings.php:1213 mod/settings.php:1214
 msgid "Your current password to confirm the changes"
 msgstr "La tua password attuale per confermare le modifiche"
 
-#: mod/settings.php:1205
+#: mod/settings.php:1214
 msgid "Password:"
 msgstr "Password:"
 
-#: mod/settings.php:1209
+#: mod/settings.php:1218
 msgid "Basic Settings"
 msgstr "Impostazioni base"
 
-#: mod/settings.php:1210 include/identity.php:578
+#: mod/settings.php:1219 include/identity.php:588
 msgid "Full Name:"
 msgstr "Nome completo:"
 
-#: mod/settings.php:1211
+#: mod/settings.php:1220
 msgid "Email Address:"
 msgstr "Indirizzo Email:"
 
-#: mod/settings.php:1212
+#: mod/settings.php:1221
 msgid "Your Timezone:"
 msgstr "Il tuo fuso orario:"
 
-#: mod/settings.php:1213
+#: mod/settings.php:1222
 msgid "Your Language:"
 msgstr "La tua lingua:"
 
-#: mod/settings.php:1213
+#: mod/settings.php:1222
 msgid ""
 "Set the language we use to show you friendica interface and to send you "
 "emails"
 msgstr "Imposta la lingua che sarà usata per mostrarti l'interfaccia di Friendica e per inviarti le email"
 
-#: mod/settings.php:1214
+#: mod/settings.php:1223
 msgid "Default Post Location:"
 msgstr "Località predefinita:"
 
-#: mod/settings.php:1215
+#: mod/settings.php:1224
 msgid "Use Browser Location:"
 msgstr "Usa la località rilevata dal browser:"
 
-#: mod/settings.php:1218
+#: mod/settings.php:1227
 msgid "Security and Privacy Settings"
 msgstr "Impostazioni di sicurezza e privacy"
 
-#: mod/settings.php:1220
+#: mod/settings.php:1229
 msgid "Maximum Friend Requests/Day:"
 msgstr "Numero massimo di richieste di amicizia al giorno:"
 
-#: mod/settings.php:1220 mod/settings.php:1250
+#: mod/settings.php:1229 mod/settings.php:1259
 msgid "(to prevent spam abuse)"
 msgstr "(per prevenire lo spam)"
 
-#: mod/settings.php:1221
+#: mod/settings.php:1230
 msgid "Default Post Permissions"
 msgstr "Permessi predefiniti per i messaggi"
 
-#: mod/settings.php:1222
+#: mod/settings.php:1231
 msgid "(click to open/close)"
 msgstr "(clicca per aprire/chiudere)"
 
-#: mod/settings.php:1231 mod/photos.php:1199 mod/photos.php:1584
+#: mod/settings.php:1240 mod/photos.php:1199 mod/photos.php:1584
 msgid "Show to Groups"
 msgstr "Mostra ai gruppi"
 
-#: mod/settings.php:1232 mod/photos.php:1200 mod/photos.php:1585
+#: mod/settings.php:1241 mod/photos.php:1200 mod/photos.php:1585
 msgid "Show to Contacts"
 msgstr "Mostra ai contatti"
 
-#: mod/settings.php:1233
+#: mod/settings.php:1242
 msgid "Default Private Post"
 msgstr "Default Post Privato"
 
-#: mod/settings.php:1234
+#: mod/settings.php:1243
 msgid "Default Public Post"
 msgstr "Default Post Pubblico"
 
-#: mod/settings.php:1238
+#: mod/settings.php:1247
 msgid "Default Permissions for New Posts"
 msgstr "Permessi predefiniti per i nuovi post"
 
-#: mod/settings.php:1250
+#: mod/settings.php:1259
 msgid "Maximum private messages per day from unknown people:"
 msgstr "Numero massimo di messaggi privati da utenti sconosciuti per giorno:"
 
-#: mod/settings.php:1253
+#: mod/settings.php:1262
 msgid "Notification Settings"
 msgstr "Impostazioni notifiche"
 
-#: mod/settings.php:1254
+#: mod/settings.php:1263
 msgid "By default post a status message when:"
 msgstr "Invia un messaggio di stato quando:"
 
-#: mod/settings.php:1255
+#: mod/settings.php:1264
 msgid "accepting a friend request"
 msgstr "accetti una richiesta di amicizia"
 
-#: mod/settings.php:1256
+#: mod/settings.php:1265
 msgid "joining a forum/community"
 msgstr "ti unisci a un forum/comunità"
 
-#: mod/settings.php:1257
+#: mod/settings.php:1266
 msgid "making an <em>interesting</em> profile change"
 msgstr "fai un <em>interessante</em> modifica al profilo"
 
-#: mod/settings.php:1258
+#: mod/settings.php:1267
 msgid "Send a notification email when:"
 msgstr "Invia una mail di notifica quando:"
 
-#: mod/settings.php:1259
+#: mod/settings.php:1268
 msgid "You receive an introduction"
 msgstr "Ricevi una presentazione"
 
-#: mod/settings.php:1260
+#: mod/settings.php:1269
 msgid "Your introductions are confirmed"
 msgstr "Le tue presentazioni sono confermate"
 
-#: mod/settings.php:1261
+#: mod/settings.php:1270
 msgid "Someone writes on your profile wall"
 msgstr "Qualcuno scrive sulla bacheca del tuo profilo"
 
-#: mod/settings.php:1262
+#: mod/settings.php:1271
 msgid "Someone writes a followup comment"
 msgstr "Qualcuno scrive un commento a un tuo messaggio"
 
-#: mod/settings.php:1263
+#: mod/settings.php:1272
 msgid "You receive a private message"
 msgstr "Ricevi un messaggio privato"
 
-#: mod/settings.php:1264
+#: mod/settings.php:1273
 msgid "You receive a friend suggestion"
 msgstr "Hai ricevuto un suggerimento di amicizia"
 
-#: mod/settings.php:1265
+#: mod/settings.php:1274
 msgid "You are tagged in a post"
 msgstr "Sei stato taggato in un post"
 
-#: mod/settings.php:1266
+#: mod/settings.php:1275
 msgid "You are poked/prodded/etc. in a post"
 msgstr "Sei 'toccato'/'spronato'/ecc. in un post"
 
-#: mod/settings.php:1268
+#: mod/settings.php:1277
 msgid "Activate desktop notifications"
 msgstr "Attiva notifiche desktop"
 
-#: mod/settings.php:1268
+#: mod/settings.php:1277
 msgid "Show desktop popup on new notifications"
 msgstr "Mostra un popup di notifica sul desktop all'arrivo di nuove notifiche"
 
-#: mod/settings.php:1270
+#: mod/settings.php:1279
 msgid "Text-only notification emails"
 msgstr "Email di notifica in solo testo"
 
-#: mod/settings.php:1272
+#: mod/settings.php:1281
 msgid "Send text only notification emails, without the html part"
 msgstr "Invia le email di notifica in solo testo, senza la parte in html"
 
-#: mod/settings.php:1274
+#: mod/settings.php:1283
 msgid "Advanced Account/Page Type Settings"
 msgstr "Impostazioni avanzate Account/Tipo di pagina"
 
-#: mod/settings.php:1275
+#: mod/settings.php:1284
 msgid "Change the behaviour of this account for special situations"
 msgstr "Modifica il comportamento di questo account in situazioni speciali"
 
-#: mod/settings.php:1278
+#: mod/settings.php:1287
 msgid "Relocate"
 msgstr "Trasloca"
 
-#: mod/settings.php:1279
+#: mod/settings.php:1288
 msgid ""
 "If you have moved this profile from another server, and some of your "
 "contacts don't receive your updates, try pushing this button."
 msgstr "Se hai spostato questo profilo da un'altro server, e alcuni dei tuoi contatti non ricevono i tuoi aggiornamenti, prova a premere questo bottone."
 
-#: mod/settings.php:1280
+#: mod/settings.php:1289
 msgid "Resend relocate message to contacts"
 msgstr "Reinvia il messaggio di trasloco"
 
-#: mod/dfrn_request.php:95
+#: mod/dfrn_request.php:96
 msgid "This introduction has already been accepted."
 msgstr "Questa presentazione è già stata accettata."
 
-#: mod/dfrn_request.php:120 mod/dfrn_request.php:519
+#: mod/dfrn_request.php:119 mod/dfrn_request.php:516
 msgid "Profile location is not valid or does not contain profile information."
 msgstr "L'indirizzo del profilo non è valido o non contiene un profilo."
 
-#: mod/dfrn_request.php:125 mod/dfrn_request.php:524
+#: mod/dfrn_request.php:124 mod/dfrn_request.php:521
 msgid "Warning: profile location has no identifiable owner name."
 msgstr "Attenzione: l'indirizzo del profilo non riporta il nome del proprietario."
 
-#: mod/dfrn_request.php:127 mod/dfrn_request.php:526
+#: mod/dfrn_request.php:126 mod/dfrn_request.php:523
 msgid "Warning: profile location has no profile photo."
 msgstr "Attenzione: l'indirizzo del profilo non ha una foto."
 
-#: mod/dfrn_request.php:130 mod/dfrn_request.php:529
+#: mod/dfrn_request.php:129 mod/dfrn_request.php:526
 #, php-format
 msgid "%d required parameter was not found at the given location"
 msgid_plural "%d required parameters were not found at the given location"
 msgstr[0] "%d parametro richiesto non è stato trovato all'indirizzo dato"
 msgstr[1] "%d parametri richiesti non sono stati trovati all'indirizzo dato"
 
-#: mod/dfrn_request.php:173
+#: mod/dfrn_request.php:172
 msgid "Introduction complete."
 msgstr "Presentazione completa."
 
-#: mod/dfrn_request.php:215
+#: mod/dfrn_request.php:214
 msgid "Unrecoverable protocol error."
 msgstr "Errore di comunicazione."
 
-#: mod/dfrn_request.php:243
+#: mod/dfrn_request.php:242
 msgid "Profile unavailable."
 msgstr "Profilo non disponibile."
 
-#: mod/dfrn_request.php:268
+#: mod/dfrn_request.php:267
 #, php-format
 msgid "%s has received too many connection requests today."
 msgstr "%s ha ricevuto troppe richieste di connessione per oggi."
 
-#: mod/dfrn_request.php:269
+#: mod/dfrn_request.php:268
 msgid "Spam protection measures have been invoked."
 msgstr "Sono state attivate le misure di protezione contro lo spam."
 
-#: mod/dfrn_request.php:270
+#: mod/dfrn_request.php:269
 msgid "Friends are advised to please try again in 24 hours."
 msgstr "Gli amici sono pregati di riprovare tra 24 ore."
 
-#: mod/dfrn_request.php:332
+#: mod/dfrn_request.php:331
 msgid "Invalid locator"
 msgstr "Invalid locator"
 
-#: mod/dfrn_request.php:341
+#: mod/dfrn_request.php:340
 msgid "Invalid email address."
 msgstr "Indirizzo email non valido."
 
-#: mod/dfrn_request.php:368
+#: mod/dfrn_request.php:367
 msgid "This account has not been configured for email. Request failed."
 msgstr "Questo account non è stato configurato per l'email. Richiesta fallita."
 
-#: mod/dfrn_request.php:464
-msgid "Unable to resolve your name at the provided location."
-msgstr "Impossibile risolvere il tuo nome nella posizione indicata."
-
-#: mod/dfrn_request.php:477
+#: mod/dfrn_request.php:474
 msgid "You have already introduced yourself here."
 msgstr "Ti sei già presentato qui."
 
-#: mod/dfrn_request.php:481
+#: mod/dfrn_request.php:478
 #, php-format
 msgid "Apparently you are already friends with %s."
 msgstr "Pare che tu e %s siate già amici."
 
-#: mod/dfrn_request.php:502
+#: mod/dfrn_request.php:499
 msgid "Invalid profile URL."
 msgstr "Indirizzo profilo non valido."
 
-#: mod/dfrn_request.php:508 include/follow.php:72
+#: mod/dfrn_request.php:505 include/follow.php:72
 msgid "Disallowed profile URL."
 msgstr "Indirizzo profilo non permesso."
 
-#: mod/dfrn_request.php:599
+#: mod/dfrn_request.php:596
 msgid "Your introduction has been sent."
 msgstr "La tua presentazione è stata inviata."
 
-#: mod/dfrn_request.php:652
+#: mod/dfrn_request.php:636
+msgid ""
+"Remote subscription can't be done for your network. Please subscribe "
+"directly on your system."
+msgstr ""
+
+#: mod/dfrn_request.php:659
 msgid "Please login to confirm introduction."
 msgstr "Accedi per confermare la presentazione."
 
-#: mod/dfrn_request.php:662
+#: mod/dfrn_request.php:669
 msgid ""
 "Incorrect identity currently logged in. Please login to "
 "<strong>this</strong> profile."
 msgstr "Non hai fatto accesso con l'identità corretta. Accedi a <strong>questo</strong> profilo."
 
-#: mod/dfrn_request.php:676 mod/dfrn_request.php:693
+#: mod/dfrn_request.php:683 mod/dfrn_request.php:700
 msgid "Confirm"
 msgstr "Conferma"
 
-#: mod/dfrn_request.php:688
+#: mod/dfrn_request.php:695
 msgid "Hide this contact"
 msgstr "Nascondi questo contatto"
 
-#: mod/dfrn_request.php:691
+#: mod/dfrn_request.php:698
 #, php-format
 msgid "Welcome home %s."
 msgstr "Bentornato a casa %s."
 
-#: mod/dfrn_request.php:692
+#: mod/dfrn_request.php:699
 #, php-format
 msgid "Please confirm your introduction/connection request to %s."
 msgstr "Conferma la tua richiesta di connessione con %s."
 
-#: mod/dfrn_request.php:821
+#: mod/dfrn_request.php:828
 msgid ""
 "Please enter your 'Identity Address' from one of the following supported "
 "communications networks:"
 msgstr "Inserisci il tuo 'Indirizzo Identità' da uno dei seguenti network supportati:"
 
-#: mod/dfrn_request.php:842
+#: mod/dfrn_request.php:849
 #, php-format
 msgid ""
 "If you are not yet a member of the free social web, <a "
@@ -4981,25 +4987,25 @@ msgid ""
 "join us today</a>."
 msgstr "Se non sei un membro del web sociale libero,  <a href=\"%s/siteinfo\">segui questo link per trovare un sito Friendica pubblico e unisciti a noi oggi</a>"
 
-#: mod/dfrn_request.php:847
+#: mod/dfrn_request.php:854
 msgid "Friend/Connection Request"
 msgstr "Richieste di amicizia/connessione"
 
-#: mod/dfrn_request.php:848
+#: mod/dfrn_request.php:855
 msgid ""
 "Examples: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, "
 "testuser@identi.ca"
 msgstr "Esempi: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, testuser@identi.ca"
 
-#: mod/dfrn_request.php:856 include/contact_selectors.php:76
+#: mod/dfrn_request.php:863 include/contact_selectors.php:76
 msgid "Friendica"
 msgstr "Friendica"
 
-#: mod/dfrn_request.php:857
+#: mod/dfrn_request.php:864
 msgid "StatusNet/Federated Social Web"
 msgstr "StatusNet/Federated Social Web"
 
-#: mod/dfrn_request.php:859
+#: mod/dfrn_request.php:866
 #, php-format
 msgid ""
 " - please do not use this form.  Instead, enter %s into your Diaspora search"
@@ -5087,7 +5093,7 @@ msgstr "Scegli un nome utente. Deve cominciare con una lettera. L'indirizzo del
 msgid "Choose a nickname: "
 msgstr "Scegli un nome utente: "
 
-#: mod/register.php:280 boot.php:1268 include/nav.php:108
+#: mod/register.php:280 boot.php:1405 include/nav.php:108
 msgid "Register"
 msgstr "Registrati"
 
@@ -5129,11 +5135,11 @@ msgstr "Elementi taggati con: %s"
 msgid "Search results for: %s"
 msgstr "Risultato della ricerca per: %s"
 
-#: mod/directory.php:149 include/identity.php:309 include/identity.php:600
+#: mod/directory.php:149 include/identity.php:313 include/identity.php:610
 msgid "Status:"
 msgstr "Stato:"
 
-#: mod/directory.php:151 include/identity.php:311 include/identity.php:611
+#: mod/directory.php:151 include/identity.php:315 include/identity.php:621
 msgid "Homepage:"
 msgstr "Homepage:"
 
@@ -5193,7 +5199,7 @@ msgstr "Aggiungi"
 msgid "No entries."
 msgstr "Nessuna voce."
 
-#: mod/common.php:87
+#: mod/common.php:86
 msgid "No contacts in common."
 msgstr "Nessun contatto in comune."
 
@@ -5461,7 +5467,7 @@ msgstr "Esempio: cathy123, Cathy Williams, cathy@example.com"
 msgid "Since [date]:"
 msgstr "Dal [data]:"
 
-#: mod/profiles.php:724 include/identity.php:609
+#: mod/profiles.php:724 include/identity.php:619
 msgid "Sexual Preference:"
 msgstr "Preferenze sessuali:"
 
@@ -5469,11 +5475,11 @@ msgstr "Preferenze sessuali:"
 msgid "Homepage URL:"
 msgstr "Homepage:"
 
-#: mod/profiles.php:726 include/identity.php:613
+#: mod/profiles.php:726 include/identity.php:623
 msgid "Hometown:"
 msgstr "Paese natale:"
 
-#: mod/profiles.php:727 include/identity.php:617
+#: mod/profiles.php:727 include/identity.php:627
 msgid "Political Views:"
 msgstr "Orientamento politico:"
 
@@ -5489,11 +5495,11 @@ msgstr "Parole chiave visibili a tutti:"
 msgid "Private Keywords:"
 msgstr "Parole chiave private:"
 
-#: mod/profiles.php:731 include/identity.php:625
+#: mod/profiles.php:731 include/identity.php:635
 msgid "Likes:"
 msgstr "Mi piace:"
 
-#: mod/profiles.php:732 include/identity.php:627
+#: mod/profiles.php:732 include/identity.php:637
 msgid "Dislikes:"
 msgstr "Non mi piace:"
 
@@ -5563,23 +5569,23 @@ msgstr "Età : "
 msgid "Edit/Manage Profiles"
 msgstr "Modifica / Gestisci profili"
 
-#: mod/profiles.php:814 include/identity.php:257 include/identity.php:283
+#: mod/profiles.php:814 include/identity.php:260 include/identity.php:286
 msgid "Change profile photo"
 msgstr "Cambia la foto del profilo"
 
-#: mod/profiles.php:815 include/identity.php:258
+#: mod/profiles.php:815 include/identity.php:261
 msgid "Create New Profile"
 msgstr "Crea un nuovo profilo"
 
-#: mod/profiles.php:826 include/identity.php:268
+#: mod/profiles.php:826 include/identity.php:271
 msgid "Profile Image"
 msgstr "Immagine del Profilo"
 
-#: mod/profiles.php:828 include/identity.php:271
+#: mod/profiles.php:828 include/identity.php:274
 msgid "visible to everybody"
 msgstr "visibile a tutti"
 
-#: mod/profiles.php:829 include/identity.php:272
+#: mod/profiles.php:829 include/identity.php:275
 msgid "Edit visibility"
 msgstr "Modifica visibilità"
 
@@ -5591,55 +5597,55 @@ msgstr "Oggetto non trovato"
 msgid "Edit post"
 msgstr "Modifica messaggio"
 
-#: mod/editpost.php:111 include/conversation.php:1185
+#: mod/editpost.php:111 include/conversation.php:1184
 msgid "upload photo"
 msgstr "carica foto"
 
-#: mod/editpost.php:112 include/conversation.php:1186
+#: mod/editpost.php:112 include/conversation.php:1185
 msgid "Attach file"
 msgstr "Allega file"
 
-#: mod/editpost.php:113 include/conversation.php:1187
+#: mod/editpost.php:113 include/conversation.php:1186
 msgid "attach file"
 msgstr "allega file"
 
-#: mod/editpost.php:115 include/conversation.php:1189
+#: mod/editpost.php:115 include/conversation.php:1188
 msgid "web link"
 msgstr "link web"
 
-#: mod/editpost.php:116 include/conversation.php:1190
+#: mod/editpost.php:116 include/conversation.php:1189
 msgid "Insert video link"
 msgstr "Inserire collegamento video"
 
-#: mod/editpost.php:117 include/conversation.php:1191
+#: mod/editpost.php:117 include/conversation.php:1190
 msgid "video link"
 msgstr "link video"
 
-#: mod/editpost.php:118 include/conversation.php:1192
+#: mod/editpost.php:118 include/conversation.php:1191
 msgid "Insert audio link"
 msgstr "Inserisci collegamento audio"
 
-#: mod/editpost.php:119 include/conversation.php:1193
+#: mod/editpost.php:119 include/conversation.php:1192
 msgid "audio link"
 msgstr "link audio"
 
-#: mod/editpost.php:120 include/conversation.php:1194
+#: mod/editpost.php:120 include/conversation.php:1193
 msgid "Set your location"
 msgstr "La tua posizione"
 
-#: mod/editpost.php:121 include/conversation.php:1195
+#: mod/editpost.php:121 include/conversation.php:1194
 msgid "set location"
 msgstr "posizione"
 
-#: mod/editpost.php:122 include/conversation.php:1196
+#: mod/editpost.php:122 include/conversation.php:1195
 msgid "Clear browser location"
 msgstr "Rimuovi la localizzazione data dal browser"
 
-#: mod/editpost.php:123 include/conversation.php:1197
+#: mod/editpost.php:123 include/conversation.php:1196
 msgid "clear location"
 msgstr "canc. pos."
 
-#: mod/editpost.php:125 include/conversation.php:1203
+#: mod/editpost.php:125 include/conversation.php:1202
 msgid "Permission settings"
 msgstr "Impostazioni permessi"
 
@@ -5647,15 +5653,15 @@ msgstr "Impostazioni permessi"
 msgid "CC: email addresses"
 msgstr "CC: indirizzi email"
 
-#: mod/editpost.php:134 include/conversation.php:1212
+#: mod/editpost.php:134 include/conversation.php:1211
 msgid "Public post"
 msgstr "Messaggio pubblico"
 
-#: mod/editpost.php:137 include/conversation.php:1199
+#: mod/editpost.php:137 include/conversation.php:1198
 msgid "Set title"
 msgstr "Scegli un titolo"
 
-#: mod/editpost.php:139 include/conversation.php:1201
+#: mod/editpost.php:139 include/conversation.php:1200
 msgid "Categories (comma-separated list)"
 msgstr "Categorie (lista separata da virgola)"
 
@@ -5663,39 +5669,39 @@ msgstr "Categorie (lista separata da virgola)"
 msgid "Example: bob@example.com, mary@example.com"
 msgstr "Esempio: bob@example.com, mary@example.com"
 
-#: mod/friendica.php:59
+#: mod/friendica.php:70
 msgid "This is Friendica, version"
 msgstr "Questo è Friendica, versione"
 
-#: mod/friendica.php:60
+#: mod/friendica.php:71
 msgid "running at web location"
 msgstr "in esecuzione all'indirizzo web"
 
-#: mod/friendica.php:62
+#: mod/friendica.php:73
 msgid ""
 "Please visit <a href=\"http://friendica.com\">Friendica.com</a> to learn "
 "more about the Friendica project."
 msgstr "Visita <a href=\"http://friendica.com\">Friendica.com</a> per saperne di più sul progetto Friendica."
 
-#: mod/friendica.php:64
+#: mod/friendica.php:75
 msgid "Bug reports and issues: please visit"
 msgstr "Segnalazioni di bug e problemi: visita"
 
-#: mod/friendica.php:64
+#: mod/friendica.php:75
 msgid "the bugtracker at github"
 msgstr "il bugtracker su github"
 
-#: mod/friendica.php:65
+#: mod/friendica.php:76
 msgid ""
 "Suggestions, praise, donations, etc. - please email \"Info\" at Friendica - "
 "dot com"
 msgstr "Suggerimenti, lodi, donazioni, ecc -  e-mail a  \"Info\" at Friendica punto com"
 
-#: mod/friendica.php:79
+#: mod/friendica.php:90
 msgid "Installed plugins/addons/apps:"
 msgstr "Plugin/addon/applicazioni instalate"
 
-#: mod/friendica.php:92
+#: mod/friendica.php:103
 msgid "No installed plugins/addons/apps"
 msgstr "Nessun plugin/addons/applicazione installata"
 
@@ -5725,7 +5731,7 @@ msgstr "Informazioni remote sulla privacy non disponibili."
 msgid "Visible to:"
 msgstr "Visibile a:"
 
-#: mod/notes.php:46 include/identity.php:721
+#: mod/notes.php:46 include/identity.php:730
 msgid "Personal Notes"
 msgstr "Note personali"
 
@@ -5783,8 +5789,8 @@ msgid "Make this post private"
 msgstr "Rendi questo post privato"
 
 #: mod/repair_ostatus.php:14
-msgid "Resubsribing to OStatus contacts"
-msgstr "Reiscrizione a contatti OStatus"
+msgid "Resubscribing to OStatus contacts"
+msgstr ""
 
 #: mod/repair_ostatus.php:30
 msgid "Error"
@@ -5836,7 +5842,7 @@ msgstr "Visita %s per una lista di siti pubblici a cui puoi iscriverti. I membri
 msgid ""
 "To accept this invitation, please visit and register at %s or any other "
 "public Friendica website."
-msgstr "Per accettare questo invito, visita e resitrati su %s o su un'altro sito web Friendica aperto al pubblico."
+msgstr "Per accettare questo invito, visita e registrati su %s o su un'altro sito web Friendica aperto al pubblico."
 
 #: mod/invite.php:123
 #, php-format
@@ -5865,7 +5871,7 @@ msgstr "Inserisci gli indirizzi email, uno per riga:"
 msgid ""
 "You are cordially invited to join me and other close friends on Friendica - "
 "and help us to create a better social web."
-msgstr "Sei cordialmente invitato a unirti a me ed ad altri amici su Friendica, e ad aiutarci a creare una rete sociale migliore."
+msgstr "Sei cordialmente invitato/a ad unirti a me e ad altri amici su Friendica, e ad aiutarci a creare una rete sociale migliore."
 
 #: mod/invite.php:137
 msgid "You will need to supply this invitation code: $invite_code"
@@ -5882,7 +5888,7 @@ msgid ""
 "important, please visit http://friendica.com"
 msgstr "Per maggiori informazioni sul progetto Friendica e perchè pensiamo sia importante, visita http://friendica.com"
 
-#: mod/photos.php:99 include/identity.php:696
+#: mod/photos.php:99 include/identity.php:705
 msgid "Photo Albums"
 msgstr "Album foto"
 
@@ -6053,12 +6059,12 @@ msgstr "Foto privata"
 msgid "Public photo"
 msgstr "Foto pubblica"
 
-#: mod/photos.php:1609 include/conversation.php:1183
+#: mod/photos.php:1609 include/conversation.php:1182
 msgid "Share"
 msgstr "Condividi"
 
 #: mod/photos.php:1648 include/conversation.php:509
-#: include/conversation.php:1414
+#: include/conversation.php:1413
 msgid "Attending"
 msgid_plural "Attending"
 msgstr[0] "Partecipa"
@@ -6132,60 +6138,60 @@ msgstr "Oggetto non disponibile."
 msgid "Item was not found."
 msgstr "Oggetto non trovato."
 
-#: boot.php:783
+#: boot.php:868
 msgid "Delete this item?"
 msgstr "Cancellare questo elemento?"
 
-#: boot.php:786
+#: boot.php:871
 msgid "show fewer"
 msgstr "mostra di meno"
 
-#: boot.php:1160
+#: boot.php:1292
 #, php-format
 msgid "Update %s failed. See error logs."
 msgstr "aggiornamento %s fallito. Guarda i log di errore."
 
-#: boot.php:1267
+#: boot.php:1404
 msgid "Create a New Account"
 msgstr "Crea un nuovo account"
 
-#: boot.php:1292 include/nav.php:72
+#: boot.php:1429 include/nav.php:72
 msgid "Logout"
 msgstr "Esci"
 
-#: boot.php:1295
+#: boot.php:1432
 msgid "Nickname or Email address: "
 msgstr "Nome utente o indirizzo email: "
 
-#: boot.php:1296
+#: boot.php:1433
 msgid "Password: "
 msgstr "Password: "
 
-#: boot.php:1297
+#: boot.php:1434
 msgid "Remember me"
 msgstr "Ricordati di me"
 
-#: boot.php:1300
+#: boot.php:1437
 msgid "Or login using OpenID: "
 msgstr "O entra con OpenID:"
 
-#: boot.php:1306
+#: boot.php:1443
 msgid "Forgot your password?"
 msgstr "Hai dimenticato la password?"
 
-#: boot.php:1309
+#: boot.php:1446
 msgid "Website Terms of Service"
 msgstr "Condizioni di servizio del sito web "
 
-#: boot.php:1310
+#: boot.php:1447
 msgid "terms of service"
 msgstr "condizioni del servizio"
 
-#: boot.php:1312
+#: boot.php:1449
 msgid "Website Privacy Policy"
 msgstr "Politiche di privacy del sito"
 
-#: boot.php:1313
+#: boot.php:1450
 msgid "privacy policy"
 msgstr "politiche di privacy"
 
@@ -6246,25 +6252,25 @@ msgid ""
 "[pre]%s[/pre]"
 msgstr "Il messaggio di errore è\n[pre]%s[/pre]"
 
-#: include/dbstructure.php:151
+#: include/dbstructure.php:153
 msgid "Errors encountered creating database tables."
 msgstr "La creazione delle tabelle del database ha generato errori."
 
-#: include/dbstructure.php:209
+#: include/dbstructure.php:230
 msgid "Errors encountered performing database changes."
 msgstr "Riscontrati errori applicando le modifiche al database."
 
-#: include/auth.php:38
+#: include/auth.php:44
 msgid "Logged out."
 msgstr "Uscita effettuata."
 
-#: include/auth.php:128 include/user.php:75
+#: include/auth.php:134 include/user.php:75
 msgid ""
 "We encountered a problem while logging in with the OpenID you provided. "
 "Please check the correct spelling of the ID."
 msgstr "Abbiamo incontrato un problema mentre contattavamo il server OpenID che ci hai fornito. Controlla di averlo scritto giusto."
 
-#: include/auth.php:128 include/user.php:75
+#: include/auth.php:134 include/user.php:75
 msgid "The error message was:"
 msgstr "Il messaggio riportato era:"
 
@@ -6321,7 +6327,7 @@ msgstr "Reti"
 msgid "All Networks"
 msgstr "Tutte le Reti"
 
-#: include/contact_widgets.php:141 include/features.php:97
+#: include/contact_widgets.php:141 include/features.php:102
 msgid "Saved Folders"
 msgstr "Cartelle Salvate"
 
@@ -6340,194 +6346,194 @@ msgid_plural "%d contacts in common"
 msgstr[0] "%d contatto in comune"
 msgstr[1] "%d contatti in comune"
 
-#: include/features.php:58
+#: include/features.php:63
 msgid "General Features"
 msgstr "Funzionalità generali"
 
-#: include/features.php:60
+#: include/features.php:65
 msgid "Multiple Profiles"
 msgstr "Profili multipli"
 
-#: include/features.php:60
+#: include/features.php:65
 msgid "Ability to create multiple profiles"
 msgstr "Possibilità di creare profili multipli"
 
-#: include/features.php:61
+#: include/features.php:66
 msgid "Photo Location"
 msgstr "Località Foto"
 
-#: include/features.php:61
+#: include/features.php:66
 msgid ""
 "Photo metadata is normally stripped. This extracts the location (if present)"
 " prior to stripping metadata and links it to a map."
 msgstr "I metadati delle foto vengono rimossi. Questa opzione estrae la località (se presenta) prima di rimuovere i metadati e la collega a una mappa."
 
-#: include/features.php:66
+#: include/features.php:71
 msgid "Post Composition Features"
 msgstr "Funzionalità di composizione dei post"
 
-#: include/features.php:67
+#: include/features.php:72
 msgid "Richtext Editor"
 msgstr "Editor visuale"
 
-#: include/features.php:67
+#: include/features.php:72
 msgid "Enable richtext editor"
 msgstr "Abilita l'editor visuale"
 
-#: include/features.php:68
+#: include/features.php:73
 msgid "Post Preview"
 msgstr "Anteprima dei post"
 
-#: include/features.php:68
+#: include/features.php:73
 msgid "Allow previewing posts and comments before publishing them"
 msgstr "Permetti di avere un'anteprima di messaggi e commenti prima di pubblicarli"
 
-#: include/features.php:69
+#: include/features.php:74
 msgid "Auto-mention Forums"
 msgstr "Auto-cita i Forum"
 
-#: include/features.php:69
+#: include/features.php:74
 msgid ""
 "Add/remove mention when a fourm page is selected/deselected in ACL window."
 msgstr "Aggiunge o rimuove una citazione quando un forum è selezionato o deselezionato nella finestra dei permessi."
 
-#: include/features.php:74
+#: include/features.php:79
 msgid "Network Sidebar Widgets"
 msgstr "Widget della barra laterale nella pagina Rete"
 
-#: include/features.php:75
+#: include/features.php:80
 msgid "Search by Date"
 msgstr "Cerca per data"
 
-#: include/features.php:75
+#: include/features.php:80
 msgid "Ability to select posts by date ranges"
 msgstr "Permette di filtrare i post per data"
 
-#: include/features.php:76 include/features.php:106
+#: include/features.php:81 include/features.php:111
 msgid "List Forums"
 msgstr "Elenco forum"
 
-#: include/features.php:76
+#: include/features.php:81
 msgid "Enable widget to display the forums your are connected with"
 msgstr "Abilita il widget che mostra i forum ai quali sei connesso"
 
-#: include/features.php:77
+#: include/features.php:82
 msgid "Group Filter"
 msgstr "Filtra gruppi"
 
-#: include/features.php:77
+#: include/features.php:82
 msgid "Enable widget to display Network posts only from selected group"
 msgstr "Abilita il widget per filtrare i post solo per il gruppo selezionato"
 
-#: include/features.php:78
+#: include/features.php:83
 msgid "Network Filter"
 msgstr "Filtro reti"
 
-#: include/features.php:78
+#: include/features.php:83
 msgid "Enable widget to display Network posts only from selected network"
 msgstr "Abilita il widget per mostare i post solo per la rete selezionata"
 
-#: include/features.php:79
+#: include/features.php:84
 msgid "Save search terms for re-use"
 msgstr "Salva i termini cercati per riutilizzarli"
 
-#: include/features.php:84
+#: include/features.php:89
 msgid "Network Tabs"
 msgstr "Schede pagina Rete"
 
-#: include/features.php:85
+#: include/features.php:90
 msgid "Network Personal Tab"
 msgstr "Scheda Personali"
 
-#: include/features.php:85
+#: include/features.php:90
 msgid "Enable tab to display only Network posts that you've interacted on"
 msgstr "Abilita la scheda per mostrare solo i post a cui hai partecipato"
 
-#: include/features.php:86
+#: include/features.php:91
 msgid "Network New Tab"
 msgstr "Scheda Nuovi"
 
-#: include/features.php:86
+#: include/features.php:91
 msgid "Enable tab to display only new Network posts (from the last 12 hours)"
 msgstr "Abilita la scheda per mostrare solo i post nuovi (nelle ultime 12 ore)"
 
-#: include/features.php:87
+#: include/features.php:92
 msgid "Network Shared Links Tab"
 msgstr "Scheda Link Condivisi"
 
-#: include/features.php:87
+#: include/features.php:92
 msgid "Enable tab to display only Network posts with links in them"
 msgstr "Abilita la scheda per mostrare solo i post che contengono link"
 
-#: include/features.php:92
+#: include/features.php:97
 msgid "Post/Comment Tools"
 msgstr "Strumenti per messaggi/commenti"
 
-#: include/features.php:93
+#: include/features.php:98
 msgid "Multiple Deletion"
 msgstr "Eliminazione multipla"
 
-#: include/features.php:93
+#: include/features.php:98
 msgid "Select and delete multiple posts/comments at once"
 msgstr "Seleziona ed elimina vari messagi e commenti in una volta sola"
 
-#: include/features.php:94
+#: include/features.php:99
 msgid "Edit Sent Posts"
 msgstr "Modifica i post inviati"
 
-#: include/features.php:94
+#: include/features.php:99
 msgid "Edit and correct posts and comments after sending"
 msgstr "Modifica e correggi messaggi e commenti dopo averli inviati"
 
-#: include/features.php:95
+#: include/features.php:100
 msgid "Tagging"
 msgstr "Aggiunta tag"
 
-#: include/features.php:95
+#: include/features.php:100
 msgid "Ability to tag existing posts"
 msgstr "Permette di aggiungere tag ai post già esistenti"
 
-#: include/features.php:96
+#: include/features.php:101
 msgid "Post Categories"
 msgstr "Cateorie post"
 
-#: include/features.php:96
+#: include/features.php:101
 msgid "Add categories to your posts"
 msgstr "Aggiungi categorie ai tuoi post"
 
-#: include/features.php:97
+#: include/features.php:102
 msgid "Ability to file posts under folders"
 msgstr "Permette di archiviare i post in cartelle"
 
-#: include/features.php:98
+#: include/features.php:103
 msgid "Dislike Posts"
 msgstr "Non mi piace"
 
-#: include/features.php:98
+#: include/features.php:103
 msgid "Ability to dislike posts/comments"
 msgstr "Permetti di inviare \"non mi piace\" ai messaggi"
 
-#: include/features.php:99
+#: include/features.php:104
 msgid "Star Posts"
 msgstr "Post preferiti"
 
-#: include/features.php:99
+#: include/features.php:104
 msgid "Ability to mark special posts with a star indicator"
 msgstr "Permette di segnare i post preferiti con una stella"
 
-#: include/features.php:100
+#: include/features.php:105
 msgid "Mute Post Notifications"
 msgstr "Silenzia le notifiche di nuovi post"
 
-#: include/features.php:100
+#: include/features.php:105
 msgid "Ability to mute notifications for a thread"
 msgstr "Permette di silenziare le notifiche di nuovi post in una discussione"
 
-#: include/features.php:105
+#: include/features.php:110
 msgid "Advanced Profile Settings"
 msgstr "Impostazioni Avanzate Profilo"
 
-#: include/features.php:106
+#: include/features.php:111
 msgid "Show visitors public community forums at the Advanced Profile Page"
 msgstr "Mostra ai visitatori i forum nella pagina Profilo Avanzato"
 
@@ -6686,149 +6692,181 @@ msgstr "secondi"
 msgid "%1$d %2$s ago"
 msgstr "%1$d %2$s fa"
 
-#: include/datetime.php:474 include/items.php:2470
+#: include/datetime.php:474 include/items.php:2500
 #, php-format
 msgid "%s's birthday"
 msgstr "Compleanno di %s"
 
-#: include/datetime.php:475 include/items.php:2471
+#: include/datetime.php:475 include/items.php:2501
 #, php-format
 msgid "Happy Birthday %s"
 msgstr "Buon compleanno %s"
 
-#: include/identity.php:43
+#: include/identity.php:42
 msgid "Requested account is not available."
 msgstr "L'account richiesto non è disponibile."
 
-#: include/identity.php:96 include/identity.php:281 include/identity.php:652
+#: include/identity.php:95 include/identity.php:284 include/identity.php:662
 msgid "Edit profile"
 msgstr "Modifica il profilo"
 
-#: include/identity.php:241
+#: include/identity.php:244
 msgid "Atom feed"
 msgstr "Feed Atom"
 
-#: include/identity.php:246
+#: include/identity.php:249
 msgid "Message"
 msgstr "Messaggio"
 
-#: include/identity.php:252 include/nav.php:185
+#: include/identity.php:255 include/nav.php:185
 msgid "Profiles"
 msgstr "Profili"
 
-#: include/identity.php:252
+#: include/identity.php:255
 msgid "Manage/edit profiles"
 msgstr "Gestisci/modifica i profili"
 
-#: include/identity.php:412 include/identity.php:498
+#: include/identity.php:425 include/identity.php:509
 msgid "g A l F d"
 msgstr "g A l d F"
 
-#: include/identity.php:413 include/identity.php:499
+#: include/identity.php:426 include/identity.php:510
 msgid "F d"
 msgstr "d F"
 
-#: include/identity.php:458 include/identity.php:545
+#: include/identity.php:471 include/identity.php:556
 msgid "[today]"
 msgstr "[oggi]"
 
-#: include/identity.php:470
+#: include/identity.php:483
 msgid "Birthday Reminders"
 msgstr "Promemoria compleanni"
 
-#: include/identity.php:471
+#: include/identity.php:484
 msgid "Birthdays this week:"
 msgstr "Compleanni questa settimana:"
 
-#: include/identity.php:532
+#: include/identity.php:543
 msgid "[No description]"
 msgstr "[Nessuna descrizione]"
 
-#: include/identity.php:556
+#: include/identity.php:567
 msgid "Event Reminders"
 msgstr "Promemoria"
 
-#: include/identity.php:557
+#: include/identity.php:568
 msgid "Events this week:"
 msgstr "Eventi di questa settimana:"
 
-#: include/identity.php:585
+#: include/identity.php:595
 msgid "j F, Y"
 msgstr "j F Y"
 
-#: include/identity.php:586
+#: include/identity.php:596
 msgid "j F"
 msgstr "j F"
 
-#: include/identity.php:593
+#: include/identity.php:603
 msgid "Birthday:"
 msgstr "Compleanno:"
 
-#: include/identity.php:597
+#: include/identity.php:607
 msgid "Age:"
 msgstr "Età:"
 
-#: include/identity.php:606
+#: include/identity.php:616
 #, php-format
 msgid "for %1$d %2$s"
 msgstr "per %1$d %2$s"
 
-#: include/identity.php:619
+#: include/identity.php:629
 msgid "Religion:"
 msgstr "Religione:"
 
-#: include/identity.php:623
+#: include/identity.php:633
 msgid "Hobbies/Interests:"
 msgstr "Hobby/Interessi:"
 
-#: include/identity.php:630
+#: include/identity.php:640
 msgid "Contact information and Social Networks:"
 msgstr "Informazioni su contatti e social network:"
 
-#: include/identity.php:632
+#: include/identity.php:642
 msgid "Musical interests:"
 msgstr "Interessi musicali:"
 
-#: include/identity.php:634
+#: include/identity.php:644
 msgid "Books, literature:"
 msgstr "Libri, letteratura:"
 
-#: include/identity.php:636
+#: include/identity.php:646
 msgid "Television:"
 msgstr "Televisione:"
 
-#: include/identity.php:638
+#: include/identity.php:648
 msgid "Film/dance/culture/entertainment:"
 msgstr "Film/danza/cultura/intrattenimento:"
 
-#: include/identity.php:640
+#: include/identity.php:650
 msgid "Love/Romance:"
 msgstr "Amore:"
 
-#: include/identity.php:642
+#: include/identity.php:652
 msgid "Work/employment:"
 msgstr "Lavoro:"
 
-#: include/identity.php:644
+#: include/identity.php:654
 msgid "School/education:"
 msgstr "Scuola:"
 
-#: include/identity.php:648
+#: include/identity.php:658
 msgid "Forums:"
 msgstr "Forum:"
 
-#: include/identity.php:701 include/identity.php:704 include/nav.php:78
+#: include/identity.php:710 include/identity.php:713 include/nav.php:78
 msgid "Videos"
 msgstr "Video"
 
-#: include/identity.php:716 include/nav.php:140
+#: include/identity.php:725 include/nav.php:140
 msgid "Events and Calendar"
 msgstr "Eventi e calendario"
 
-#: include/identity.php:724
+#: include/identity.php:733
 msgid "Only You Can See This"
 msgstr "Solo tu puoi vedere questo"
 
+#: include/like.php:167 include/conversation.php:122
+#: include/conversation.php:258 include/text.php:1998
+#: view/theme/diabook/theme.php:463
+msgid "event"
+msgstr "l'evento"
+
+#: include/like.php:184 include/conversation.php:141 include/diaspora.php:2185
+#: view/theme/diabook/theme.php:480
+#, php-format
+msgid "%1$s likes %2$s's %3$s"
+msgstr "A %1$s piace %3$s di %2$s"
+
+#: include/like.php:186 include/conversation.php:144
+#, php-format
+msgid "%1$s doesn't like %2$s's %3$s"
+msgstr "A %1$s non piace %3$s di %2$s"
+
+#: include/like.php:188
+#, php-format
+msgid "%1$s is attending %2$s's %3$s"
+msgstr "%1$s parteciperà a %3$s di %2$s"
+
+#: include/like.php:190
+#, php-format
+msgid "%1$s is not attending %2$s's %3$s"
+msgstr "%1$s non parteciperà a %3$s di %2$s"
+
+#: include/like.php:192
+#, php-format
+msgid "%1$s may attend %2$s's %3$s"
+msgstr "%1$s forse parteciperà a %3$s di %2$s"
+
 #: include/acl_selectors.php:325
 msgid "Post to Email"
 msgstr "Invia a email"
@@ -6852,6 +6890,10 @@ msgstr "mostra"
 msgid "don't show"
 msgstr "non mostrare"
 
+#: include/acl_selectors.php:348
+msgid "Close"
+msgstr "Chiudi"
+
 #: include/message.php:15 include/message.php:173
 msgid "[no subject]"
 msgstr "[nessun oggetto]"
@@ -6860,31 +6902,31 @@ msgstr "[nessun oggetto]"
 msgid "stopped following"
 msgstr "tolto dai seguiti"
 
-#: include/Contact.php:361 include/conversation.php:911
+#: include/Contact.php:337 include/conversation.php:911
 msgid "View Status"
 msgstr "Visualizza stato"
 
-#: include/Contact.php:363 include/conversation.php:913
+#: include/Contact.php:339 include/conversation.php:913
 msgid "View Photos"
 msgstr "Visualizza foto"
 
-#: include/Contact.php:364 include/conversation.php:914
+#: include/Contact.php:340 include/conversation.php:914
 msgid "Network Posts"
 msgstr "Post della Rete"
 
-#: include/Contact.php:365 include/conversation.php:915
+#: include/Contact.php:341 include/conversation.php:915
 msgid "Edit Contact"
 msgstr "Modifica contatto"
 
-#: include/Contact.php:366
+#: include/Contact.php:342
 msgid "Drop Contact"
 msgstr "Rimuovi contatto"
 
-#: include/Contact.php:367 include/conversation.php:916
+#: include/Contact.php:343 include/conversation.php:916
 msgid "Send PM"
 msgstr "Invia messaggio privato"
 
-#: include/Contact.php:368 include/conversation.php:920
+#: include/Contact.php:344 include/conversation.php:920
 msgid "Poke"
 msgstr "Stuzzica"
 
@@ -6947,153 +6989,153 @@ msgstr "Cancella elementi selezionati"
 msgid "Follow Thread"
 msgstr "Segui la discussione"
 
-#: include/conversation.php:1035
+#: include/conversation.php:1034
 #, php-format
 msgid "%s likes this."
 msgstr "Piace a %s."
 
-#: include/conversation.php:1038
+#: include/conversation.php:1037
 #, php-format
 msgid "%s doesn't like this."
 msgstr "Non piace a %s."
 
-#: include/conversation.php:1041
+#: include/conversation.php:1040
 #, php-format
 msgid "%s attends."
 msgstr "%s partecipa."
 
-#: include/conversation.php:1044
+#: include/conversation.php:1043
 #, php-format
 msgid "%s doesn't attend."
 msgstr "%s non partecipa."
 
-#: include/conversation.php:1047
+#: include/conversation.php:1046
 #, php-format
 msgid "%s attends maybe."
 msgstr "%s forse partecipa."
 
-#: include/conversation.php:1057
+#: include/conversation.php:1056
 msgid "and"
 msgstr "e"
 
-#: include/conversation.php:1063
+#: include/conversation.php:1062
 #, php-format
 msgid ", and %d other people"
 msgstr "e altre %d persone"
 
-#: include/conversation.php:1072
+#: include/conversation.php:1071
 #, php-format
 msgid "<span  %1$s>%2$d people</span> like this"
 msgstr "Piace a <span %1$s>%2$d persone</span>."
 
-#: include/conversation.php:1073
+#: include/conversation.php:1072
 #, php-format
 msgid "%s like this."
 msgstr "a %s piace."
 
-#: include/conversation.php:1076
+#: include/conversation.php:1075
 #, php-format
 msgid "<span  %1$s>%2$d people</span> don't like this"
 msgstr "Non piace a <span %1$s>%2$d persone</span>."
 
-#: include/conversation.php:1077
+#: include/conversation.php:1076
 #, php-format
 msgid "%s don't like this."
 msgstr "a %s non piace."
 
-#: include/conversation.php:1080
+#: include/conversation.php:1079
 #, php-format
 msgid "<span  %1$s>%2$d people</span> attend"
 msgstr "<span  %1$s>%2$d persone</span> partecipano"
 
-#: include/conversation.php:1081
+#: include/conversation.php:1080
 #, php-format
 msgid "%s attend."
 msgstr "%s partecipa."
 
-#: include/conversation.php:1084
+#: include/conversation.php:1083
 #, php-format
 msgid "<span  %1$s>%2$d people</span> don't attend"
 msgstr "<span  %1$s>%2$d persone</span> non partecipano"
 
-#: include/conversation.php:1085
+#: include/conversation.php:1084
 #, php-format
 msgid "%s don't attend."
 msgstr "%s non partecipa."
 
-#: include/conversation.php:1088
+#: include/conversation.php:1087
 #, php-format
 msgid "<span  %1$s>%2$d people</span> anttend maybe"
 msgstr "<span  %1$s>%2$d persone</span> forse partecipano"
 
-#: include/conversation.php:1089
+#: include/conversation.php:1088
 #, php-format
 msgid "%s anttend maybe."
 msgstr "%s forse partecipano."
 
-#: include/conversation.php:1128 include/conversation.php:1146
+#: include/conversation.php:1127 include/conversation.php:1145
 msgid "Visible to <strong>everybody</strong>"
 msgstr "Visibile a <strong>tutti</strong>"
 
-#: include/conversation.php:1130 include/conversation.php:1148
+#: include/conversation.php:1129 include/conversation.php:1147
 msgid "Please enter a video link/URL:"
 msgstr "Inserisci un collegamento video / URL:"
 
-#: include/conversation.php:1131 include/conversation.php:1149
+#: include/conversation.php:1130 include/conversation.php:1148
 msgid "Please enter an audio link/URL:"
 msgstr "Inserisci un collegamento audio / URL:"
 
-#: include/conversation.php:1132 include/conversation.php:1150
+#: include/conversation.php:1131 include/conversation.php:1149
 msgid "Tag term:"
 msgstr "Tag:"
 
-#: include/conversation.php:1134 include/conversation.php:1152
+#: include/conversation.php:1133 include/conversation.php:1151
 msgid "Where are you right now?"
 msgstr "Dove sei ora?"
 
-#: include/conversation.php:1135
+#: include/conversation.php:1134
 msgid "Delete item(s)?"
 msgstr "Cancellare questo elemento/i?"
 
-#: include/conversation.php:1204
+#: include/conversation.php:1203
 msgid "permissions"
 msgstr "permessi"
 
-#: include/conversation.php:1227
+#: include/conversation.php:1226
 msgid "Post to Groups"
 msgstr "Invia ai Gruppi"
 
-#: include/conversation.php:1228
+#: include/conversation.php:1227
 msgid "Post to Contacts"
 msgstr "Invia ai Contatti"
 
-#: include/conversation.php:1229
+#: include/conversation.php:1228
 msgid "Private post"
 msgstr "Post privato"
 
-#: include/conversation.php:1386
+#: include/conversation.php:1385
 msgid "View all"
 msgstr "Mostra tutto"
 
-#: include/conversation.php:1408
+#: include/conversation.php:1407
 msgid "Like"
 msgid_plural "Likes"
 msgstr[0] "Mi piace"
 msgstr[1] "Mi piace"
 
-#: include/conversation.php:1411
+#: include/conversation.php:1410
 msgid "Dislike"
 msgid_plural "Dislikes"
 msgstr[0] "Non mi piace"
 msgstr[1] "Non mi piace"
 
-#: include/conversation.php:1417
+#: include/conversation.php:1416
 msgid "Not Attending"
 msgid_plural "Not Attending"
 msgstr[0] "Non partecipa"
 msgstr[1] "Non partecipano"
 
-#: include/conversation.php:1420 include/profile_selectors.php:6
+#: include/conversation.php:1419 include/profile_selectors.php:6
 msgid "Undecided"
 msgid_plural "Undecided"
 msgstr[0] "Indeciso"
@@ -7295,67 +7337,59 @@ msgstr "rilassato"
 msgid "surprised"
 msgstr "sorpreso"
 
-#: include/text.php:1497
+#: include/text.php:1504
 msgid "bytes"
 msgstr "bytes"
 
-#: include/text.php:1529 include/text.php:1541
+#: include/text.php:1536 include/text.php:1548
 msgid "Click to open/close"
 msgstr "Clicca per aprire/chiudere"
 
-#: include/text.php:1715
+#: include/text.php:1722
 msgid "View on separate page"
 msgstr "Vedi in una pagina separata"
 
-#: include/text.php:1716
+#: include/text.php:1723
 msgid "view on separate page"
 msgstr "vedi in una pagina separata"
 
-#: include/text.php:1995
+#: include/text.php:2002
 msgid "activity"
 msgstr "attività"
 
-#: include/text.php:1998
+#: include/text.php:2005
 msgid "post"
 msgstr "messaggio"
 
-#: include/text.php:2166
+#: include/text.php:2173
 msgid "Item filed"
 msgstr "Messaggio salvato"
 
-#: include/bbcode.php:483 include/bbcode.php:1143 include/bbcode.php:1144
+#: include/bbcode.php:482 include/bbcode.php:1157 include/bbcode.php:1158
 msgid "Image/photo"
 msgstr "Immagine/foto"
 
-#: include/bbcode.php:581
+#: include/bbcode.php:595
 #, php-format
 msgid "<a href=\"%1$s\" target=\"_blank\">%2$s</a> %3$s"
 msgstr "<a href=\"%1$s\" target=\"_blank\">%2$s</a> %3$s"
 
-#: include/bbcode.php:615
+#: include/bbcode.php:629
 #, php-format
 msgid ""
 "<span><a href=\"%s\" target=\"_blank\">%s</a> wrote the following <a "
 "href=\"%s\" target=\"_blank\">post</a>"
 msgstr "<span><a href=\"%s\" target=\"_blank\">%s</a> ha scritto il seguente <a href=\"%s\" target=\"_blank\">messaggio</a>"
 
-#: include/bbcode.php:1103 include/bbcode.php:1123
+#: include/bbcode.php:1117 include/bbcode.php:1137
 msgid "$1 wrote:"
 msgstr "$1 ha scritto:"
 
-#: include/bbcode.php:1152 include/bbcode.php:1153
+#: include/bbcode.php:1166 include/bbcode.php:1167
 msgid "Encrypted content"
 msgstr "Contenuto criptato"
 
-#: include/notifier.php:843 include/delivery.php:458
-msgid "(no subject)"
-msgstr "(nessun oggetto)"
-
-#: include/notifier.php:853 include/delivery.php:469 include/enotify.php:37
-msgid "noreply"
-msgstr "nessuna risposta"
-
-#: include/dba_pdo.php:72 include/dba.php:56
+#: include/dba_pdo.php:72 include/dba.php:55
 #, php-format
 msgid "Cannot locate DNS info for database server '%s'"
 msgstr "Non trovo le informazioni DNS per il database server '%s'"
@@ -7400,6 +7434,10 @@ msgstr "Ostatus"
 msgid "RSS/Atom"
 msgstr "RSS / Atom"
 
+#: include/contact_selectors.php:81
+msgid "Facebook"
+msgstr "Facebook"
+
 #: include/contact_selectors.php:82
 msgid "Zot!"
 msgstr "Zot!"
@@ -7444,7 +7482,7 @@ msgstr "App.net"
 msgid "Redmatrix"
 msgstr "Redmatrix"
 
-#: include/Scrape.php:610
+#: include/Scrape.php:624
 msgid " on Last.fm"
 msgstr "su Last.fm"
 
@@ -7620,46 +7658,21 @@ msgstr "Navigazione"
 msgid "Site map"
 msgstr "Mappa del sito"
 
-#: include/api.php:343 include/api.php:354 include/api.php:463
-#: include/api.php:1182 include/api.php:1184
-msgid "User not found."
-msgstr "Utente non trovato."
-
-#: include/api.php:830
+#: include/api.php:878
 #, php-format
 msgid "Daily posting limit of %d posts reached. The post was rejected."
 msgstr "Limite giornaliero di %d messaggi raggiunto. Il messaggio è stato rifiutato"
 
-#: include/api.php:849
+#: include/api.php:897
 #, php-format
 msgid "Weekly posting limit of %d posts reached. The post was rejected."
 msgstr "Limite settimanale di %d messaggi raggiunto. Il messaggio è stato rifiutato"
 
-#: include/api.php:868
+#: include/api.php:916
 #, php-format
 msgid "Monthly posting limit of %d posts reached. The post was rejected."
 msgstr "Limite mensile di %d messaggi raggiunto. Il messaggio è stato rifiutato"
 
-#: include/api.php:1391
-msgid "There is no status with this id."
-msgstr "Non c'è nessuno status con questo id."
-
-#: include/api.php:1465
-msgid "There is no conversation with this id."
-msgstr "Non c'è nessuna conversazione con questo id"
-
-#: include/api.php:1744
-msgid "Invalid item."
-msgstr "Elemento non valido."
-
-#: include/api.php:1754
-msgid "Invalid action. "
-msgstr "Azione non valida."
-
-#: include/api.php:1762
-msgid "DB error"
-msgstr "Errore database"
-
 #: include/user.php:48
 msgid "An invitation is required."
 msgstr "E' richiesto un invito."
@@ -7722,8 +7735,7 @@ msgstr "ERRORE GRAVE: La generazione delle chiavi di sicurezza è fallita."
 msgid "An error occurred during registration. Please try again."
 msgstr "C'è stato un errore durante la registrazione. Prova ancora."
 
-#: include/user.php:256 view/theme/clean/config.php:56
-#: view/theme/duepuntozero/config.php:44
+#: include/user.php:256 view/theme/duepuntozero/config.php:44
 msgid "default"
 msgstr "default"
 
@@ -7774,19 +7786,27 @@ msgid ""
 "\t\tThank you and welcome to %2$s."
 msgstr "\nI dettagli del tuo utente sono:\n    Indirizzo del sito: %3$s\n    Nome utente: %1$s\n    Password: %5$s\n\nPuoi cambiare la tua password dalla pagina delle impostazioni del tuo account dopo esserti autenticato.\n\nPer favore, prenditi qualche momento per esaminare tutte le impostazioni presenti.\n\nPotresti voler aggiungere qualche informazione di base al tuo profilo predefinito (nella pagina \"Profili\"), così che le altre persone possano trovarti più facilmente.\n\nTi raccomandiamo di inserire il tuo nome completo, aggiungere una foto, aggiungere qualche parola chiave del profilo (molto utili per trovare nuovi contatti), e magari in quale nazione vivi, se non vuoi essere più specifico di così.\n\nNoi rispettiamo appieno la tua privacy, e nessuna di queste informazioni è necessaria o obbligatoria.\nSe sei nuovo e non conosci nessuno qui, possono aiutarti a trovare qualche nuovo e interessante contatto.\n\nGrazie e benvenuto su %2$s"
 
-#: include/diaspora.php:719
+#: include/diaspora.php:720
 msgid "Sharing notification from Diaspora network"
 msgstr "Notifica di condivisione dal network Diaspora*"
 
-#: include/diaspora.php:2606
+#: include/diaspora.php:2625
 msgid "Attachments:"
 msgstr "Allegati:"
 
-#: include/items.php:4897
+#: include/delivery.php:533
+msgid "(no subject)"
+msgstr "(nessun oggetto)"
+
+#: include/delivery.php:544 include/enotify.php:37
+msgid "noreply"
+msgstr "nessuna risposta"
+
+#: include/items.php:4926
 msgid "Do you really want to delete this item?"
 msgstr "Vuoi veramente cancellare questo elemento?"
 
-#: include/items.php:5172
+#: include/items.php:5201
 msgid "Archives"
 msgstr "Archivi"
 
@@ -8302,11 +8322,11 @@ msgstr "Nome completo: %1$s\nIndirizzo del sito: %2$s\nNome utente: %3$s (%4$s)"
 msgid "Please visit %s to approve or reject the request."
 msgstr "Visita %s per approvare o rifiutare la richiesta."
 
-#: include/oembed.php:220
+#: include/oembed.php:226
 msgid "Embedded content"
 msgstr "Contenuto incorporato"
 
-#: include/oembed.php:229
+#: include/oembed.php:235
 msgid "Embedding disabled"
 msgstr "Embed disabilitato"
 
@@ -8346,7 +8366,7 @@ msgstr[1] "%d contatti non importati"
 msgid "Done. You can now login with your username and password"
 msgstr "Fatto. Ora puoi entrare con il tuo nome utente e la tua password"
 
-#: index.php:441
+#: index.php:442
 msgid "toggle mobile"
 msgstr "commuta tema mobile"
 
@@ -8364,7 +8384,6 @@ msgid "Set theme width"
 msgstr "Imposta la larghezza del tema"
 
 #: view/theme/cleanzero/config.php:86 view/theme/quattro/config.php:68
-#: view/theme/clean/config.php:88
 msgid "Color scheme"
 msgstr "Schema colori"
 
@@ -8486,56 +8505,6 @@ msgstr "Livello di zoom per Earth Layers"
 msgid "Show/hide boxes at right-hand column:"
 msgstr "Mostra/Nascondi riquadri nella colonna destra"
 
-#: view/theme/clean/config.php:57
-msgid "Midnight"
-msgstr "Mezzanotte"
-
-#: view/theme/clean/config.php:58
-msgid "Zenburn"
-msgstr "Zenburn"
-
-#: view/theme/clean/config.php:59
-msgid "Bootstrap"
-msgstr "Bootstrap"
-
-#: view/theme/clean/config.php:60
-msgid "Shades of Pink"
-msgstr "Sfumature di Rosa"
-
-#: view/theme/clean/config.php:61
-msgid "Lime and Orange"
-msgstr "Lime e Arancia"
-
-#: view/theme/clean/config.php:62
-msgid "GeoCities Retro"
-msgstr "GeoCities Retro"
-
-#: view/theme/clean/config.php:86
-msgid "Background Image"
-msgstr "Immagine di sfondo"
-
-#: view/theme/clean/config.php:86
-msgid ""
-"The URL to a picture (e.g. from your photo album) that should be used as "
-"background image."
-msgstr "L'URL a un'immagine (p.e. dal tuo album foto) che viene usata come immagine di sfondo."
-
-#: view/theme/clean/config.php:87
-msgid "Background Color"
-msgstr "Colore di sfondo"
-
-#: view/theme/clean/config.php:87
-msgid "HEX value for the background color. Don't include the #"
-msgstr "Valore esadecimale del colore di sfondo. Non includere il #"
-
-#: view/theme/clean/config.php:89
-msgid "font size"
-msgstr "dimensione font"
-
-#: view/theme/clean/config.php:89
-msgid "base font size for your interface"
-msgstr "dimensione di base dei font per la tua interfaccia"
-
 #: view/theme/vier/config.php:64
 msgid "Comma separated list of helper forums"
 msgstr "Lista separata da virgola di forum di aiuto"
diff --git a/view/it/strings.php b/view/it/strings.php
index fb30c73573..606ae1e16c 100644
--- a/view/it/strings.php
+++ b/view/it/strings.php
@@ -8,8 +8,8 @@ function string_plural_select_it($n){
 $a->strings["Network:"] = "Rete:";
 $a->strings["Forum"] = "Forum";
 $a->strings["%d contact edited."] = array(
-	0 => "%d contatto modificato",
-	1 => "%d contatti modificati",
+	0 => "",
+	1 => "",
 );
 $a->strings["Could not access contact record."] = "Non è possibile accedere al contatto.";
 $a->strings["Could not locate selected profile."] = "Non riesco a trovare il profilo selezionato.";
@@ -142,9 +142,6 @@ $a->strings["Edit your <strong>default</strong> profile to your liking. Review t
 $a->strings["Profile Keywords"] = "Parole chiave del profilo";
 $a->strings["Set some public keywords for your default profile which describe your interests. We may be able to find other people with similar interests and suggest friendships."] = "Inserisci qualche parola chiave pubblica nel tuo profilo predefinito che descriva i tuoi interessi. Potremmo essere in grado di trovare altre persone con interessi similari e suggerirti delle amicizie.";
 $a->strings["Connecting"] = "Collegarsi";
-$a->strings["Facebook"] = "Facebook";
-$a->strings["Authorise the Facebook Connector if you currently have a Facebook account and we will (optionally) import all your Facebook friends and conversations."] = "Autorizza il Facebook Connector se hai un account Facebook, e noi (opzionalmente) importeremo tuti i tuoi amici e le tue conversazioni da Facebook.";
-$a->strings["<em>If</em> this is your own personal server, installing the Facebook addon may ease your transition to the free social web."] = "<em>Se</em questo è il tuo server personale, installare il plugin per Facebook puo' aiutarti nella transizione verso il web sociale libero.";
 $a->strings["Importing Emails"] = "Importare le Email";
 $a->strings["Enter your email access information on your Connector Settings page if you wish to import and interact with friends or mailing lists from your email INBOX"] = "Inserisci i tuoi dati di accesso all'email nella tua pagina Impostazioni Connettori se vuoi importare e interagire con amici o mailing list dalla tua casella di posta in arrivo";
 $a->strings["Go to Your Contacts Page"] = "Vai alla tua pagina Contatti";
@@ -189,7 +186,7 @@ $a->strings["Tag removed"] = "Tag rimosso";
 $a->strings["Remove Item Tag"] = "Rimuovi il tag";
 $a->strings["Select a tag to remove: "] = "Seleziona un tag da rimuovere: ";
 $a->strings["Remove"] = "Rimuovi";
-$a->strings["Subsribing to OStatus contacts"] = "Iscrizione a contatti OStatus";
+$a->strings["Subscribing to OStatus contacts"] = "";
 $a->strings["No contact provided."] = "Nessun contatto disponibile.";
 $a->strings["Couldn't fetch information for contact."] = "Non è stato possibile recuperare le informazioni del contatto.";
 $a->strings["Couldn't fetch friends for contact."] = "Non è stato possibile recuperare gli amici del contatto.";
@@ -290,12 +287,6 @@ $a->strings["Forgot your Password?"] = "Hai dimenticato la password?";
 $a->strings["Enter your email address and submit to have your password reset. Then check your email for further instructions."] = "Inserisci il tuo indirizzo email per reimpostare la password.";
 $a->strings["Nickname or Email: "] = "Nome utente o email: ";
 $a->strings["Reset"] = "Reimposta";
-$a->strings["event"] = "l'evento";
-$a->strings["%1\$s likes %2\$s's %3\$s"] = "A %1\$s piace %3\$s di %2\$s";
-$a->strings["%1\$s doesn't like %2\$s's %3\$s"] = "A %1\$s non piace %3\$s di %2\$s";
-$a->strings["%1\$s is attending %2\$s's %3\$s"] = "%1\$s parteciperà a %3\$s di %2\$s";
-$a->strings["%1\$s is not attending %2\$s's %3\$s"] = "%1\$s non parteciperà a %3\$s di %2\$s";
-$a->strings["%1\$s may attend %2\$s's %3\$s"] = "%1\$s forse parteciperà a %3\$s di %2\$s";
 $a->strings["{0} wants to be your friend"] = "{0} vuole essere tuo amico";
 $a->strings["{0} sent you a message"] = "{0} ti ha inviato un messaggio";
 $a->strings["{0} requested registration"] = "{0} chiede la registrazione";
@@ -425,16 +416,22 @@ $a->strings["Site"] = "Sito";
 $a->strings["Users"] = "Utenti";
 $a->strings["Plugins"] = "Plugin";
 $a->strings["Themes"] = "Temi";
+$a->strings["Additional features"] = "Funzionalità aggiuntive";
 $a->strings["DB updates"] = "Aggiornamenti Database";
 $a->strings["Inspect Queue"] = "Ispeziona Coda di invio";
+$a->strings["Federation Statistics"] = "";
 $a->strings["Logs"] = "Log";
+$a->strings["View Logs"] = "";
 $a->strings["probe address"] = "controlla indirizzo";
 $a->strings["check webfinger"] = "verifica webfinger";
 $a->strings["Admin"] = "Amministrazione";
 $a->strings["Plugin Features"] = "Impostazioni Plugins";
 $a->strings["diagnostics"] = "diagnostiche";
 $a->strings["User registrations waiting for confirmation"] = "Utenti registrati in attesa di conferma";
+$a->strings["This page offers you some numbers to the known part of the federated social network your Friendica node is part of. These numbers are not complete but only reflect the part of the network your node is aware of."] = "";
+$a->strings["The <em>Auto Discovered Contact Directory</em> feature is not enabled, it will improve the data displayed here."] = "";
 $a->strings["Administration"] = "Amministrazione";
+$a->strings["Currently this node is aware of %d nodes from the following platforms:"] = "";
 $a->strings["ID"] = "ID";
 $a->strings["Recipient Name"] = "Nome Destinatario";
 $a->strings["Recipient Profile"] = "Profilo Destinatario";
@@ -585,6 +582,8 @@ $a->strings["Maximum Load Average (Frontend)"] = "Media Massimo Carico (Frontend
 $a->strings["Maximum system load before the frontend quits service - default 50."] = "Massimo carico di sistema prima che il frontend fermi il servizio - default 50.";
 $a->strings["Maximum table size for optimization"] = "Dimensione massima della tabella per l'ottimizzazione";
 $a->strings["Maximum table size (in MB) for the automatic optimization - default 100 MB. Enter -1 to disable it."] = "La dimensione massima (in MB) per l'ottimizzazione automatica - default 100 MB. Inserisci -1 per disabilitarlo.";
+$a->strings["Minimum level of fragmentation"] = "";
+$a->strings["Minimum fragmenation level to start the automatic optimization - default value is 30%."] = "";
 $a->strings["Periodical check of global contacts"] = "Check periodico dei contatti globali";
 $a->strings["If enabled, the global contacts are checked periodically for missing or outdated data and the vitality of the contacts and servers."] = "Se abilitato, i contatti globali sono controllati periodicamente per verificare dati mancanti o sorpassati e la vitaltà dei contatti e dei server.";
 $a->strings["Days between requery"] = "Giorni tra le richieste";
@@ -684,9 +683,11 @@ $a->strings["Toggle"] = "Inverti";
 $a->strings["Author: "] = "Autore: ";
 $a->strings["Maintainer: "] = "Manutentore: ";
 $a->strings["Reload active plugins"] = "Ricarica i plugin attivi";
+$a->strings["There are currently no plugins available on your node. You can find the official plugin repository at %1\$s and might find other interesting plugins in the open plugin registry at %2\$s"] = "";
 $a->strings["No themes found."] = "Nessun tema trovato.";
 $a->strings["Screenshot"] = "Anteprima";
 $a->strings["Reload active themes"] = "Ricarica i temi attivi";
+$a->strings["No themes found on the system. They should be paced in %1\$s"] = "";
 $a->strings["[Experimental]"] = "[Sperimentale]";
 $a->strings["[Unsupported]"] = "[Non supportato]";
 $a->strings["Log settings updated."] = "Impostazioni Log aggiornate.";
@@ -695,11 +696,12 @@ $a->strings["Enable Debugging"] = "Abilita Debugging";
 $a->strings["Log file"] = "File di Log";
 $a->strings["Must be writable by web server. Relative to your Friendica top-level directory."] = "Deve essere scrivibile dal server web. Relativo alla tua directory Friendica.";
 $a->strings["Log level"] = "Livello di Log";
-$a->strings["Close"] = "Chiudi";
-$a->strings["FTP Host"] = "Indirizzo FTP";
-$a->strings["FTP Path"] = "Percorso FTP";
-$a->strings["FTP User"] = "Utente FTP";
-$a->strings["FTP Password"] = "Pasword FTP";
+$a->strings["PHP logging"] = "";
+$a->strings["To enable logging of PHP errors and warnings you can add the following to the .htconfig.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."] = "";
+$a->strings["Off"] = "Spento";
+$a->strings["On"] = "Acceso";
+$a->strings["Lock feature %s"] = "";
+$a->strings["Manage Additional Features"] = "";
 $a->strings["Search Results For: %s"] = "Risultato della ricerca per: %s";
 $a->strings["Remove term"] = "Rimuovi termine";
 $a->strings["Saved Searches"] = "Ricerche salvate";
@@ -921,7 +923,6 @@ $a->strings["Not available."] = "Non disponibile.";
 $a->strings["Community"] = "Comunità";
 $a->strings["No results."] = "Nessun risultato.";
 $a->strings["everybody"] = "tutti";
-$a->strings["Additional features"] = "Funzionalità aggiuntive";
 $a->strings["Display"] = "Visualizzazione";
 $a->strings["Social Networks"] = "Social Networks";
 $a->strings["Delegations"] = "Delegazioni";
@@ -958,8 +959,6 @@ $a->strings["No name"] = "Nessun nome";
 $a->strings["Remove authorization"] = "Rimuovi l'autorizzazione";
 $a->strings["No Plugin settings configured"] = "Nessun plugin ha impostazioni modificabili";
 $a->strings["Plugin Settings"] = "Impostazioni plugin";
-$a->strings["Off"] = "Spento";
-$a->strings["On"] = "Acceso";
 $a->strings["Additional Features"] = "Funzionalità aggiuntive";
 $a->strings["General Social Media Settings"] = "Impostazioni Media Sociali";
 $a->strings["Disable intelligent shortening"] = "Disabilita accorciamento intelligente";
@@ -1106,12 +1105,12 @@ $a->strings["Friends are advised to please try again in 24 hours."] = "Gli amici
 $a->strings["Invalid locator"] = "Invalid locator";
 $a->strings["Invalid email address."] = "Indirizzo email non valido.";
 $a->strings["This account has not been configured for email. Request failed."] = "Questo account non è stato configurato per l'email. Richiesta fallita.";
-$a->strings["Unable to resolve your name at the provided location."] = "Impossibile risolvere il tuo nome nella posizione indicata.";
 $a->strings["You have already introduced yourself here."] = "Ti sei già presentato qui.";
 $a->strings["Apparently you are already friends with %s."] = "Pare che tu e %s siate già amici.";
 $a->strings["Invalid profile URL."] = "Indirizzo profilo non valido.";
 $a->strings["Disallowed profile URL."] = "Indirizzo profilo non permesso.";
 $a->strings["Your introduction has been sent."] = "La tua presentazione è stata inviata.";
+$a->strings["Remote subscription can't be done for your network. Please subscribe directly on your system."] = "";
 $a->strings["Please login to confirm introduction."] = "Accedi per confermare la presentazione.";
 $a->strings["Incorrect identity currently logged in. Please login to <strong>this</strong> profile."] = "Non hai fatto accesso con l'identità corretta. Accedi a <strong>questo</strong> profilo.";
 $a->strings["Confirm"] = "Conferma";
@@ -1308,7 +1307,7 @@ $a->strings["poke, prod or do other things to somebody"] = "tocca, pungola o fai
 $a->strings["Recipient"] = "Destinatario";
 $a->strings["Choose what you wish to do to recipient"] = "Scegli cosa vuoi fare al destinatario";
 $a->strings["Make this post private"] = "Rendi questo post privato";
-$a->strings["Resubsribing to OStatus contacts"] = "Reiscrizione a contatti OStatus";
+$a->strings["Resubscribing to OStatus contacts"] = "";
 $a->strings["Error"] = "Errore";
 $a->strings["Total invitation limit exceeded."] = "Limite totale degli inviti superato.";
 $a->strings["%s : Not a valid email address."] = "%s: non è un indirizzo email valido.";
@@ -1321,12 +1320,12 @@ $a->strings["%d message sent."] = array(
 );
 $a->strings["You have no more invitations available"] = "Non hai altri inviti disponibili";
 $a->strings["Visit %s for a list of public sites that you can join. Friendica members on other sites can all connect with each other, as well as with members of many other social networks."] = "Visita %s per una lista di siti pubblici a cui puoi iscriverti. I membri Friendica su altri siti possono collegarsi uno con l'altro, come con membri di molti altri social network.";
-$a->strings["To accept this invitation, please visit and register at %s or any other public Friendica website."] = "Per accettare questo invito, visita e resitrati su %s o su un'altro sito web Friendica aperto al pubblico.";
+$a->strings["To accept this invitation, please visit and register at %s or any other public Friendica website."] = "Per accettare questo invito, visita e registrati su %s o su un'altro sito web Friendica aperto al pubblico.";
 $a->strings["Friendica sites all inter-connect to create a huge privacy-enhanced social web that is owned and controlled by its members. They can also connect with many traditional social networks. See %s for a list of alternate Friendica sites you can join."] = "I siti Friendica son tutti collegati tra loro per creare una grossa rete sociale rispettosa della privacy, posseduta e controllata dai suoi membri. I siti Friendica possono anche collegarsi a molti altri social network tradizionali. Vai su %s per una lista di siti Friendica alternativi a cui puoi iscriverti.";
 $a->strings["Our apologies. This system is not currently configured to connect with other public sites or invite members."] = "Ci scusiamo, questo sistema non è configurato per collegarsi con altri siti pubblici o per invitare membri.";
 $a->strings["Send invitations"] = "Invia inviti";
 $a->strings["Enter email addresses, one per line:"] = "Inserisci gli indirizzi email, uno per riga:";
-$a->strings["You are cordially invited to join me and other close friends on Friendica - and help us to create a better social web."] = "Sei cordialmente invitato a unirti a me ed ad altri amici su Friendica, e ad aiutarci a creare una rete sociale migliore.";
+$a->strings["You are cordially invited to join me and other close friends on Friendica - and help us to create a better social web."] = "Sei cordialmente invitato/a ad unirti a me e ad altri amici su Friendica, e ad aiutarci a creare una rete sociale migliore.";
 $a->strings["You will need to supply this invitation code: \$invite_code"] = "Sarà necessario fornire questo codice invito: \$invite_code";
 $a->strings["Once you have registered, please connect with me via my profile page at:"] = "Una volta registrato, connettiti con me dal mio profilo:";
 $a->strings["For more information about the Friendica project and why we feel it is important, please visit http://friendica.com"] = "Per maggiori informazioni sul progetto Friendica e perchè pensiamo sia importante, visita http://friendica.com";
@@ -1563,11 +1562,18 @@ $a->strings["Forums:"] = "Forum:";
 $a->strings["Videos"] = "Video";
 $a->strings["Events and Calendar"] = "Eventi e calendario";
 $a->strings["Only You Can See This"] = "Solo tu puoi vedere questo";
+$a->strings["event"] = "l'evento";
+$a->strings["%1\$s likes %2\$s's %3\$s"] = "A %1\$s piace %3\$s di %2\$s";
+$a->strings["%1\$s doesn't like %2\$s's %3\$s"] = "A %1\$s non piace %3\$s di %2\$s";
+$a->strings["%1\$s is attending %2\$s's %3\$s"] = "%1\$s parteciperà a %3\$s di %2\$s";
+$a->strings["%1\$s is not attending %2\$s's %3\$s"] = "%1\$s non parteciperà a %3\$s di %2\$s";
+$a->strings["%1\$s may attend %2\$s's %3\$s"] = "%1\$s forse parteciperà a %3\$s di %2\$s";
 $a->strings["Post to Email"] = "Invia a email";
 $a->strings["Connectors disabled, since \"%s\" is enabled."] = "Connettore disabilitato, dato che \"%s\" è abilitato.";
 $a->strings["Visible to everybody"] = "Visibile a tutti";
 $a->strings["show"] = "mostra";
 $a->strings["don't show"] = "non mostrare";
+$a->strings["Close"] = "Chiudi";
 $a->strings["[no subject]"] = "[nessun oggetto]";
 $a->strings["stopped following"] = "tolto dai seguiti";
 $a->strings["View Status"] = "Visualizza stato";
@@ -1697,8 +1703,6 @@ $a->strings["<a href=\"%1\$s\" target=\"_blank\">%2\$s</a> %3\$s"] = "<a href=\"
 $a->strings["<span><a href=\"%s\" target=\"_blank\">%s</a> wrote the following <a href=\"%s\" target=\"_blank\">post</a>"] = "<span><a href=\"%s\" target=\"_blank\">%s</a> ha scritto il seguente <a href=\"%s\" target=\"_blank\">messaggio</a>";
 $a->strings["$1 wrote:"] = "$1 ha scritto:";
 $a->strings["Encrypted content"] = "Contenuto criptato";
-$a->strings["(no subject)"] = "(nessun oggetto)";
-$a->strings["noreply"] = "nessuna risposta";
 $a->strings["Cannot locate DNS info for database server '%s'"] = "Non trovo le informazioni DNS per il database server '%s'";
 $a->strings["Unknown | Not categorised"] = "Sconosciuto | non categorizzato";
 $a->strings["Block immediately"] = "Blocca immediatamente";
@@ -1710,6 +1714,7 @@ $a->strings["Weekly"] = "Settimanalmente";
 $a->strings["Monthly"] = "Mensilmente";
 $a->strings["OStatus"] = "Ostatus";
 $a->strings["RSS/Atom"] = "RSS / Atom";
+$a->strings["Facebook"] = "Facebook";
 $a->strings["Zot!"] = "Zot!";
 $a->strings["LinkedIn"] = "LinkedIn";
 $a->strings["XMPP/IM"] = "XMPP/IM";
@@ -1765,15 +1770,9 @@ $a->strings["Manage/edit friends and contacts"] = "Gestisci/modifica amici e con
 $a->strings["Site setup and configuration"] = "Configurazione del sito";
 $a->strings["Navigation"] = "Navigazione";
 $a->strings["Site map"] = "Mappa del sito";
-$a->strings["User not found."] = "Utente non trovato.";
 $a->strings["Daily posting limit of %d posts reached. The post was rejected."] = "Limite giornaliero di %d messaggi raggiunto. Il messaggio è stato rifiutato";
 $a->strings["Weekly posting limit of %d posts reached. The post was rejected."] = "Limite settimanale di %d messaggi raggiunto. Il messaggio è stato rifiutato";
 $a->strings["Monthly posting limit of %d posts reached. The post was rejected."] = "Limite mensile di %d messaggi raggiunto. Il messaggio è stato rifiutato";
-$a->strings["There is no status with this id."] = "Non c'è nessuno status con questo id.";
-$a->strings["There is no conversation with this id."] = "Non c'è nessuna conversazione con questo id";
-$a->strings["Invalid item."] = "Elemento non valido.";
-$a->strings["Invalid action. "] = "Azione non valida.";
-$a->strings["DB error"] = "Errore database";
 $a->strings["An invitation is required."] = "E' richiesto un invito.";
 $a->strings["Invitation could not be verified."] = "L'invito non puo' essere verificato.";
 $a->strings["Invalid OpenID url"] = "Url OpenID non valido";
@@ -1796,6 +1795,8 @@ $a->strings["\n\t\tDear %1\$s,\n\t\t\tThank you for registering at %2\$s. Your a
 $a->strings["\n\t\tThe login details are as follows:\n\t\t\tSite Location:\t%3\$s\n\t\t\tLogin Name:\t%1\$s\n\t\t\tPassword:\t%5\$s\n\n\t\tYou may change your password from your account \"Settings\" page after logging\n\t\tin.\n\n\t\tPlease take a few moments to review the other account settings on that page.\n\n\t\tYou may also wish to add some basic information to your default profile\n\t\t(on the \"Profiles\" page) so that other people can easily find you.\n\n\t\tWe recommend setting your full name, adding a profile photo,\n\t\tadding some profile \"keywords\" (very useful in making new friends) - and\n\t\tperhaps what country you live in; if you do not wish to be more specific\n\t\tthan that.\n\n\t\tWe fully respect your right to privacy, and none of these items are necessary.\n\t\tIf you are new and do not know anybody here, they may help\n\t\tyou to make some new and interesting friends.\n\n\n\t\tThank you and welcome to %2\$s."] = "\nI dettagli del tuo utente sono:\n    Indirizzo del sito: %3\$s\n    Nome utente: %1\$s\n    Password: %5\$s\n\nPuoi cambiare la tua password dalla pagina delle impostazioni del tuo account dopo esserti autenticato.\n\nPer favore, prenditi qualche momento per esaminare tutte le impostazioni presenti.\n\nPotresti voler aggiungere qualche informazione di base al tuo profilo predefinito (nella pagina \"Profili\"), così che le altre persone possano trovarti più facilmente.\n\nTi raccomandiamo di inserire il tuo nome completo, aggiungere una foto, aggiungere qualche parola chiave del profilo (molto utili per trovare nuovi contatti), e magari in quale nazione vivi, se non vuoi essere più specifico di così.\n\nNoi rispettiamo appieno la tua privacy, e nessuna di queste informazioni è necessaria o obbligatoria.\nSe sei nuovo e non conosci nessuno qui, possono aiutarti a trovare qualche nuovo e interessante contatto.\n\nGrazie e benvenuto su %2\$s";
 $a->strings["Sharing notification from Diaspora network"] = "Notifica di condivisione dal network Diaspora*";
 $a->strings["Attachments:"] = "Allegati:";
+$a->strings["(no subject)"] = "(nessun oggetto)";
+$a->strings["noreply"] = "nessuna risposta";
 $a->strings["Do you really want to delete this item?"] = "Vuoi veramente cancellare questo elemento?";
 $a->strings["Archives"] = "Archivi";
 $a->strings["Male"] = "Maschio";
@@ -1956,18 +1957,6 @@ $a->strings["Your personal photos"] = "Le tue foto personali";
 $a->strings["Local Directory"] = "Elenco Locale";
 $a->strings["Set zoomfactor for Earth Layers"] = "Livello di zoom per Earth Layers";
 $a->strings["Show/hide boxes at right-hand column:"] = "Mostra/Nascondi riquadri nella colonna destra";
-$a->strings["Midnight"] = "Mezzanotte";
-$a->strings["Zenburn"] = "Zenburn";
-$a->strings["Bootstrap"] = "Bootstrap";
-$a->strings["Shades of Pink"] = "Sfumature di Rosa";
-$a->strings["Lime and Orange"] = "Lime e Arancia";
-$a->strings["GeoCities Retro"] = "GeoCities Retro";
-$a->strings["Background Image"] = "Immagine di sfondo";
-$a->strings["The URL to a picture (e.g. from your photo album) that should be used as background image."] = "L'URL a un'immagine (p.e. dal tuo album foto) che viene usata come immagine di sfondo.";
-$a->strings["Background Color"] = "Colore di sfondo";
-$a->strings["HEX value for the background color. Don't include the #"] = "Valore esadecimale del colore di sfondo. Non includere il #";
-$a->strings["font size"] = "dimensione font";
-$a->strings["base font size for your interface"] = "dimensione di base dei font per la tua interfaccia";
 $a->strings["Comma separated list of helper forums"] = "Lista separata da virgola di forum di aiuto";
 $a->strings["Set style"] = "Imposta stile";
 $a->strings["Quick Start"] = "Quick Start";

From 8a9862c9cedcf0f05aea3ad892d4a7cb774beb1b Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 1 Feb 2016 00:09:03 +0100
Subject: [PATCH 012/273] Entry import could work but need clean up

---
 include/import-dfrn.php | 684 +++++++++++++++++++++++-----------------
 1 file changed, 396 insertions(+), 288 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index 8a72e40060..0e185d3f44 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -18,7 +18,12 @@ require_once("include/items.php");
 require_once("include/tags.php");
 require_once("include/files.php");
 
+define('DFRN_TOP_LEVEL', 0);
+define('DFRN_REPLY', 1);
+define('DFRN_REPLY_RC', 2);
+
 class dfrn2 {
+
 	/**
 	 * @brief Add new birthday event for this person
 	 *
@@ -31,11 +36,11 @@ class dfrn2 {
 		logger('updating birthday: '.$birthday.' for contact '.$contact['id']);
 
 		$bdtext = sprintf(t('%s\'s birthday'), $contact['name']);
-		$bdtext2 = sprintf(t('Happy Birthday %s'), ' [url=' . $contact['url'].']'.$contact['name'].'[/url]' ) ;
+		$bdtext2 = sprintf(t('Happy Birthday %s'), ' [url=' . $contact['url'].']'.$contact['name'].'[/url]') ;
 
 
 		$r = q("INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`summary`,`desc`,`type`)
-			VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
+			VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
 			intval($contact['uid']),
 			intval($contact['id']),
 			dbesc(datetime_convert()),
@@ -310,7 +315,7 @@ class dfrn2 {
 		$suggest["name"] = $xpath->query('dfrn:name/text()', $suggestion)->item(0)->nodeValue;
 		$suggest["photo"] = $xpath->query('dfrn:photo/text()', $suggestion)->item(0)->nodeValue;
 		$suggest["request"] = $xpath->query('dfrn:request/text()', $suggestion)->item(0)->nodeValue;
-		$suggest["note"] = $xpath->query('dfrn:note/text()', $suggestion)->item(0)->nodeValue;
+		$suggest["body"] = $xpath->query('dfrn:note/text()', $suggestion)->item(0)->nodeValue;
 
 		// Does our member already have a friend matching this description?
 
@@ -474,12 +479,115 @@ class dfrn2 {
 		return true;
 	}
 
+	private function upate_content($current, $item, $importer, $entrytype) {
+		if (edited_timestamp_is_newer($current, $item)) {
+
+			// do not accept (ignore) an earlier edit than one we currently have.
+			if(datetime_convert('UTC','UTC',$item['edited']) < $current['edited'])
+				return;
+
+			$r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
+				dbesc($item['title']),
+				dbesc($item['body']),
+				dbesc($item['tag']),
+				dbesc(datetime_convert('UTC','UTC',$item['edited'])),
+				dbesc(datetime_convert()),
+				dbesc($item["uri"]),
+				intval($importer['importer_uid'])
+			);
+			create_tags_from_itemuri($item["uri"], $importer['importer_uid']);
+			update_thread_uri($item["uri"], $importer['importer_uid']);
+
+			if ($entrytype == DFRN_REPLY_RC)
+				proc_run('php',"include/notifier.php","comment-import",$current["id"]);
+		}
+
+		// update last-child if it changes
+		if($item["last-child"] AND ($item["last-child"] != $current['last-child'])) {
+			$r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
+				dbesc(datetime_convert()),
+				dbesc($item["parent-uri"]),
+				intval($importer['importer_uid'])
+			);
+			$r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
+				intval($item["last-child"]),
+				dbesc(datetime_convert()),
+				dbesc($item["uri"]),
+				intval($importer['importer_uid'])
+			);
+		}
+	}
+
+	private function get_entry_type($is_reply, $importer, $item) {
+		if ($is_reply) {
+			$community = false;
+
+			if($importer['page-flags'] == PAGE_COMMUNITY || $importer['page-flags'] == PAGE_PRVGROUP) {
+				$sql_extra = '';
+				$community = true;
+				logger('possible community reply');
+			} else
+				$sql_extra = " and contact.self = 1 and item.wall = 1 ";
+
+			// was the top-level post for this reply written by somebody on this site?
+			// Specifically, the recipient?
+
+			$is_a_remote_comment = false;
+
+			$r = q("SELECT `item`.`parent-uri` FROM `item`
+				WHERE `item`.`uri` = '%s'
+				LIMIT 1",
+				dbesc($item["parent-uri"])
+			);
+			if($r && count($r)) {
+				$r = q("SELECT `item`.`forum_mode`, `item`.`wall` FROM `item`
+					INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
+					WHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' OR `item`.`thr-parent` = '%s')
+					AND `item`.`uid` = %d
+					$sql_extra
+					LIMIT 1",
+					dbesc($r[0]['parent-uri']),
+					dbesc($r[0]['parent-uri']),
+					dbesc($r[0]['parent-uri']),
+					intval($importer['importer_uid'])
+				);
+				if($r && count($r))
+					$is_a_remote_comment = true;
+			}
+
+			// Does this have the characteristics of a community or private group comment?
+			// If it's a reply to a wall post on a community/prvgroup page it's a
+			// valid community comment. Also forum_mode makes it valid for sure.
+			// If neither, it's not.
+
+			if($is_a_remote_comment && $community) {
+				if((!$r[0]['forum_mode']) && (!$r[0]['wall'])) {
+					$is_a_remote_comment = false;
+					logger('not a community reply');
+				}
+			}
+		} else {
+			$is_reply = false;
+			$is_a_remote_comment = false;
+		}
+
+		if ($is_a_remote_comment)
+			return DFRN_REPLY_RC;
+		elseif ($is_reply)
+			return DFRN_REPLY;
+		else
+			return DFRN_TOP_LEVEL;
+	}
+
 	private function process_entry($header, $xpath, $entry, $importer, $contact) {
 
 		logger("Processing entries");
 
 		$item = $header;
 
+		// Get the uri
+		$item["uri"] = $xpath->query('atom:id/text()', $entry)->item(0)->nodeValue;
+
 		// Fetch the owner
 		$owner = self::fetchauthor($xpath, $entry, $importer, "dfrn:owner", $contact, true);
 
@@ -506,32 +614,6 @@ class dfrn2 {
 		if (($header["network"] != $author["network"]) AND ($author["network"] != ""))
 			$item["network"] = $author["network"];
 
-		// Now get the item
-		$item["uri"] = $xpath->query('atom:id/text()', $entry)->item(0)->nodeValue;
-
-		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
-			intval($importer["uid"]), dbesc($item["uri"]));
-		//if ($r) {
-		//	logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
-		//	return false;
-		//}
-
-		// Is it a reply?
-		$inreplyto = $xpath->query('thr:in-reply-to', $entry);
-		if (is_object($inreplyto->item(0))) {
-			$objecttype = ACTIVITY_OBJ_COMMENT;
-			$item["type"] = 'remote-comment';
-			$item["gravity"] = GRAVITY_COMMENT;
-
-			foreach($inreplyto->item(0)->attributes AS $attributes) {
-				if ($attributes->name == "ref")
-					$item["parent-uri"] = $attributes->textContent;
-			}
-		} else {
-			$objecttype = ACTIVITY_OBJ_NOTE;
-			$item["parent-uri"] = $item["uri"];
-		}
-
 		$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
 
 		$item["created"] = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
@@ -574,14 +656,12 @@ class dfrn2 {
 		$item["guid"] = $xpath->query('dfrn:diaspora_guid/text()', $entry)->item(0)->nodeValue;
 
 		// We store the data from "dfrn:diaspora_signature" in a later step. See some lines below
-		$signature = $xpath->query('dfrn:diaspora_signature/text()', $entry)->item(0)->nodeValue;
+		$item["dsprsig"] = unxmlify($xpath->query('dfrn:diaspora_signature/text()', $entry)->item(0)->nodeValue);
 
 		$item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue;
 
 		if ($xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue != "")
-			$objecttype = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue;
-
-		$item["object-type"] = $objecttype;
+			$item["object-type"] = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue;
 
 		// I have the feeling that we don't do anything with this data
 		$object = $xpath->query('activity:object', $entry)->item(0);
@@ -643,262 +723,231 @@ class dfrn2 {
 			}
 		}
 
-/*
-// reply
-                                // not allowed to post
+		// Is it a reply or a top level posting?
+		$item["parent-uri"] = $item["uri"];
 
-                                if($contact['rel'] == CONTACT_IS_FOLLOWER)
-                                        continue;
+		$inreplyto = $xpath->query('thr:in-reply-to', $entry);
+		if (is_object($inreplyto->item(0)))
+			foreach($inreplyto->item(0)->attributes AS $attributes)
+				if ($attributes->name == "ref")
+					$item["parent-uri"] = $attributes->textContent;
 
-                                $r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-                                        dbesc($item_id),
-                                        intval($importer['uid'])
-                                );
+		$entrytype = get_entry_type(( $item["parent-uri"] != $item["uri"]),  $importer, $item);
 
-				// Update content if 'updated' changes
+		// Now assign the rest of the values that depend on the type of the message
+		if ($entrytype == DFRN_REPLY_RC) {
+			if (!isset($item["object-type"]))
+				$item["object-type"] = ACTIVITY_OBJ_COMMENT;
 
-                                if(count($r)) {
-                                        if (edited_timestamp_is_newer($r[0], $datarray)) {
-
-                                                // do not accept (ignore) an earlier edit than one we currently have.
-                                                if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
-                                                        continue;
-
-                                                $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` =
- '%s' WHERE `uri` = '%s' AND `uid` = %d",
-                                                        dbesc($datarray['title']),
-                                                        dbesc($datarray['body']),
-                                                        dbesc($datarray['tag']),
-                                                        dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
-                                                        dbesc(datetime_convert()),
-                                                        dbesc($item_id),
-                                                        intval($importer['uid'])
-                                                );
-                                                create_tags_from_itemuri($item_id, $importer['uid']);
-                                                update_thread_uri($item_id, $importer['uid']);
-                                        }
-
-                                        // update last-child if it changes
-                                        // update last-child if it changes
-
-                                        $allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow');
-                                        if(($allow) && ($allow[0]['data'] != $r[0]['last-child'])) {
-                                                $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
-                                                        dbesc(datetime_convert()),
-                                                        dbesc($parent_uri),
-                                                        intval($importer['uid'])
-                                                );
-                                                $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s'  WHERE `uri` = '%s' AND `uid` = %d",
-                                                        intval($allow[0]['data']),
-                                                        dbesc(datetime_convert()),
-                                                        dbesc($item_id),
-                                                        intval($importer['uid'])
-                                                );
-                                                update_thread_uri($item_id, $importer['uid']);
-                                        }
-                                        continue;
-                                }
-                                if(($datarray['verb'] === ACTIVITY_LIKE)
-                                        || ($datarray['verb'] === ACTIVITY_DISLIKE)
-                                        || ($datarray['verb'] === ACTIVITY_ATTEND)
-                                        || ($datarray['verb'] === ACTIVITY_ATTENDNO)
-                                        || ($datarray['verb'] === ACTIVITY_ATTENDMAYBE)) {
-                                        $datarray['type'] = 'activity';
-                                        $datarray['gravity'] = GRAVITY_LIKE;
-                                        // only one like or dislike per person
-                                        // splitted into two queries for performance issues
-                                        $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1",
-                                                intval($datarray['uid']),
-                                                dbesc($datarray['author-link']),
-                                                dbesc($datarray['verb']),
-                                                dbesc($datarray['parent-uri'])
-                                        );
-                                        if($r && count($r))
-                                                continue;
-
-                                        $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1",
-                                                intval($datarray['uid']),
-                                                dbesc($datarray['author-link']),
-                                                dbesc($datarray['verb']),
-                                                dbesc($datarray['parent-uri'])
-                                        );
-                                        if($r && count($r))
-                                                continue;
-                                }
-                                if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
-                                        $xo = parse_xml_string($datarray['object'],false);
-                                        $xt = parse_xml_string($datarray['target'],false);
-
-                                        if($xt->type == ACTIVITY_OBJ_NOTE) {
-                                                $r = q("select * from item where `uri` = '%s' AND `uid` = %d limit 1",
-                                                        dbesc($xt->id),
-                                                        intval($importer['importer_uid'])
-                                                );
-                                                if(! count($r))
-                                                        continue;
-
-                                                // extract tag, if not duplicate, add to parent item
-                                                if($xo->id && $xo->content) {
-                                                        $newtag = '#[url=' . $xo->id . ']'. $xo->content . '[/url]';
-                                                        if(! (stristr($r[0]['tag'],$newtag))) {
-                                                                q("UPDATE item SET tag = '%s' WHERE id = %d",
-                                                                        dbesc($r[0]['tag'] . (strlen($r[0]['tag']) ? ',' : '') . $newtag),
-                                                                        intval($r[0]['id'])
-                                                                );
-                                                                create_tags_from_item($r[0]['id']);
-                                                        }
-                                                }
-                                        }
-                                }
-
-
-
-// toplevel
-                                // special handling for events
-
-                                if((x($datarray,'object-type')) && ($datarray['object-type'] === ACTIVITY_OBJ_EVENT)) {
-                                        $ev = bbtoevent($datarray['body']);
-                                        if((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) {
-                                                $ev['uid'] = $importer['uid'];
-                                                $ev['uri'] = $item_id;
-                                                $ev['edited'] = $datarray['edited'];
-                                                $ev['private'] = $datarray['private'];
-                                                $ev['guid'] = $datarray['guid'];
-
-                                                if(is_array($contact))
-                                                        $ev['cid'] = $contact['id'];
-                                                $r = q("SELECT * FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-                                                        dbesc($item_id),
-                                                        intval($importer['uid'])
-                                                );
-                                                if(count($r))
-                                                        $ev['id'] = $r[0]['id'];
-                                                $xyz = event_store($ev);
-                                                continue;
-                                        }
-                                }
-
-
-				$r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-                                        dbesc($item_id),
-                                        intval($importer['uid'])
-                                );
-
-                                // Update content if 'updated' changes
-
-                                if(count($r)) {
-                                        if (edited_timestamp_is_newer($r[0], $datarray)) {
-
-                                                // do not accept (ignore) an earlier edit than one we currently have.
-                                                if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
-                                                        continue;
-
-                                                $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` =
- '%s' WHERE `uri` = '%s' AND `uid` = %d",
-                                                        dbesc($datarray['title']),
-                                                        dbesc($datarray['body']),
-                                                        dbesc($datarray['tag']),
-                                                        dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
-                                                        dbesc(datetime_convert()),
-                                                        dbesc($item_id),
-                                                        intval($importer['uid'])
-                                                );
-                                                create_tags_from_itemuri($item_id, $importer['uid']);
-                                                update_thread_uri($item_id, $importer['uid']);
-                                        }
-
-                                        // update last-child if it changes
-
-                                        $allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow');
-                                        if($allow && $allow[0]['data'] != $r[0]['last-child']) {
-                                                $r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
-                                                        intval($allow[0]['data']),
-                                                        dbesc(datetime_convert()),
-                                                        dbesc($item_id),
-                                                        intval($importer['uid'])
-                                                );
-                                                update_thread_uri($item_id, $importer['uid']);
-                                        }
-                                        continue;
-                                }
-
-
-
-toplevel:
-
-                                if(activity_match($datarray['verb'],ACTIVITY_FOLLOW)) {
-                                        logger('consume-feed: New follower');
-                                        new_follower($importer,$contact,$datarray,$item);
-                                        return;
-                                }
-                                if(activity_match($datarray['verb'],ACTIVITY_UNFOLLOW))  {
-                                        lose_follower($importer,$contact,$datarray,$item);
-                                        return;
-                                }
-
-                                if(activity_match($datarray['verb'],ACTIVITY_REQ_FRIEND)) {
-                                        logger('consume-feed: New friend request');
-                                        new_follower($importer,$contact,$datarray,$item,true);
-                                        return;
-                                }
-                                if(activity_match($datarray['verb'],ACTIVITY_UNFRIEND))  {
-                                        lose_sharer($importer,$contact,$datarray,$item);
-                                        return;
-                                }
-
-
-                                if(! is_array($contact))
-                                        return;
-
-                                if(! link_compare($datarray['owner-link'],$contact['url'])) {
-                                        // The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
-                                        // but otherwise there's a possible data mixup on the sender's system.
-                                        // the tgroup delivery code called from item_store will correct it if it's a forum,
-                                        // but we're going to unconditionally correct it here so that the post will always be owned by our contact.
-                                        logger('consume_feed: Correcting item owner.', LOGGER_DEBUG);
-                                        $datarray['owner-name']   = $contact['name'];
-                                        $datarray['owner-link']   = $contact['url'];
-                                        $datarray['owner-avatar'] = $contact['thumb'];
-                                }
-
-                                // We've allowed "followers" to reach this point so we can decide if they are
-                                // posting an @-tag delivery, which followers are allowed to do for certain
-                                // page types. Now that we've parsed the post, let's check if it is legit. Otherwise ignore it.
-
-                                if(($contact['rel'] == CONTACT_IS_FOLLOWER) && (! tgroup_check($importer['uid'],$datarray)))
-                                        continue;
-
-                                // This is my contact on another system, but it's really me.
-                                // Turn this into a wall post.
-                                $notify = item_is_remote_self($contact, $datarray);
-
-*/
-		print_r($item);
-		return;
-		//$item_id = item_store($item);
-
-		if (!$item_id) {
-			logger("Error storing item", LOGGER_DEBUG);
-			return false;
+			$item["type"] = 'remote-comment';
+			$item['wall'] = 1;
+		} elseif ($entrytype == DFRN_REPLY) {
+			if (!isset($item["object-type"]))
+				$item["object-type"] = ACTIVITY_OBJ_COMMENT;
 		} else {
-			logger("Item was stored with id ".$item_id, LOGGER_DEBUG);
+			if (!isset($item["object-type"]))
+				$item["object-type"] = ACTIVITY_OBJ_NOTE;
 
-			if ($signature) {
-				$signature = json_decode(base64_decode($signature));
+			if ($item["object-type"] === ACTIVITY_OBJ_EVENT) {
+				$ev = bbtoevent($item['body']);
+				if((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) {
+					$ev['cid'] = $importer['id'];
+					$ev['uid'] = $importer['uid'];
+					$ev['uri'] = $item["uri"];
+					$ev['edited'] = $item['edited'];
+					$ev['private'] = $item['private'];
+					$ev['guid'] = $item['guid'];
 
-				// Check for falsely double encoded signatures
-				$signature->signature = diaspora_repair_signature($signature->signature, $signature->signer);
-
-				// Store it in the "sign" table where we will read it for comments that we relay to Diaspora
-				q("INSERT INTO `sign` (`iid`,`signed_text`,`signature`,`signer`) VALUES (%d,'%s','%s','%s')",
-					intval($item_id),
-					dbesc($signature->signed_text),
-					dbesc($signature->signature),
-					dbesc($signature->signer)
-				);
+					$r = q("SELECT * FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+						dbesc($item["uri"]),
+						intval($importer['uid'])
+					);
+					if(count($r))
+						$ev['id'] = $r[0]['id'];
+						$xyz = event_store($ev);
+							return;
+				}
+			}
+		}
+
+		$r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc($item["uri"]),
+			intval($importer['importer_uid'])
+		);
+
+		// Update content if 'updated' changes
+		if(count($r)) {
+			self::upate_content($r[0], $item, $importer, $entrytype);
+			return;
+		}
+
+		if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) {
+			if($importer['rel'] == CONTACT_IS_FOLLOWER)
+				return;
+
+			if(($item['verb'] === ACTIVITY_LIKE)
+				|| ($item['verb'] === ACTIVITY_DISLIKE)
+				|| ($item['verb'] === ACTIVITY_ATTEND)
+				|| ($item['verb'] === ACTIVITY_ATTENDNO)
+				|| ($item['verb'] === ACTIVITY_ATTENDMAYBE)) {
+				$is_like = true;
+				$item['type'] = 'activity';
+				$item['gravity'] = GRAVITY_LIKE;
+				// only one like or dislike per person
+				// splitted into two queries for performance issues
+				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1",
+					intval($item['uid']),
+					dbesc($item['author-link']),
+					dbesc($item['verb']),
+					dbesc($item['parent-uri'])
+				);
+				if($r && count($r))
+					return;
+
+				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1",
+					intval($item['uid']),
+					dbesc($item['author-link']),
+					dbesc($item['verb']),
+					dbesc($item['parent-uri'])
+				);
+				if($r && count($r))
+					return;
+
+			} else
+				$is_like = false;
+
+			if(($item['verb'] === ACTIVITY_TAG) && ($item['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
+
+				$xo = parse_xml_string($item['object'],false);
+				$xt = parse_xml_string($item['target'],false);
+
+				if($xt->type == ACTIVITY_OBJ_NOTE) {
+					$r = q("SELECT `id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+						dbesc($xt->id),
+						intval($importer['importer_uid'])
+					);
+
+					if(!count($r))
+						return;
+
+					// extract tag, if not duplicate, add to parent item
+					if($xo->content) {
+						if(!(stristr($r[0]['tag'],trim($xo->content)))) {
+							q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
+								dbesc($r[0]['tag'] . (strlen($r[0]['tag']) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'),
+								intval($r[0]['id'])
+							);
+							create_tags_from_item($r[0]['id']);
+						}
+					}
+				}
+			}
+
+			$posted_id = item_store($item);
+			$parent = 0;
+
+			if($posted_id) {
+
+				$item["id"] = $posted_id;
+
+				$r = q("SELECT `parent`, `parent-uri` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+					intval($posted_id),
+					intval($importer['importer_uid'])
+				);
+				if(count($r)) {
+					$parent = $r[0]['parent'];
+					$parent_uri = $r[0]['parent-uri'];
+				}
+
+				if(!$is_like) {
+					$r1 = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `uid` = %d AND `parent` = %d",
+						dbesc(datetime_convert()),
+						intval($importer['importer_uid']),
+						intval($r[0]['parent'])
+					);
+
+					$r2 = q("UPDATE `item` SET `last-child` = 1, `changed` = '%s' WHERE `uid` = %d AND `id` = %d",
+						dbesc(datetime_convert()),
+						intval($importer['importer_uid']),
+						intval($posted_id)
+					);
+				}
+
+				if($posted_id AND $parent AND ($entrytype == DFRN_REPLY_RC)) {
+					proc_run('php',"include/notifier.php","comment-import","$posted_id");
+				}
+
+				return true;
+			}
+		} else {
+			if(!link_compare($item['owner-link'],$importer['url'])) {
+				// The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
+				// but otherwise there's a possible data mixup on the sender's system.
+				// the tgroup delivery code called from item_store will correct it if it's a forum,
+				// but we're going to unconditionally correct it here so that the post will always be owned by our contact.
+				logger('Correcting item owner.', LOGGER_DEBUG);
+				$item['owner-name']   = $importer['senderName'];
+				$item['owner-link']   = $importer['url'];
+				$item['owner-avatar'] = $importer['thumb'];
+			}
+
+			if(($importer['rel'] == CONTACT_IS_FOLLOWER) && (!tgroup_check($importer['importer_uid'],$item)))
+				return;
+
+			// This is my contact on another system, but it's really me.
+			// Turn this into a wall post.
+			$notify = item_is_remote_self($importer, $item);
+
+			$posted_id = item_store($item, false, $notify);
+
+			if(stristr($item['verb'],ACTIVITY_POKE)) {
+				$verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1));
+				if(!$verb)
+					return;
+				$xo = parse_xml_string($item['object'],false);
+
+				if(($xo->type == ACTIVITY_OBJ_PERSON) && ($xo->id)) {
+
+					// somebody was poked/prodded. Was it me?
+					$links = parse_xml_string("<links>".unxmlify($xo->link)."</links>",false);
+
+					foreach($links->link as $l) {
+						$atts = $l->attributes();
+						switch($atts['rel']) {
+							case "alternate":
+								$Blink = $atts['href'];
+								break;
+							default:
+								break;
+						}
+					}
+					if($Blink && link_compare($Blink,$a->get_baseurl() . '/profile/' . $importer['nickname'])) {
+
+						// send a notification
+						require_once('include/enotify.php');
+
+						notification(array(
+							'type'         => NOTIFY_POKE,
+							'notify_flags' => $importer['notify-flags'],
+							'language'     => $importer['language'],
+							'to_name'      => $importer['username'],
+							'to_email'     => $importer['email'],
+							'uid'          => $importer['importer_uid'],
+							'item'         => $item,
+							'link'             => $a->get_baseurl().'/display/'.urlencode(get_item_guid($posted_id)),
+							'source_name'  => stripslashes($item['author-name']),
+							'source_link'  => $item['author-link'],
+							'source_photo' => ((link_compare($item['author-link'],$importer['url']))
+								? $importer['thumb'] : $item['author-avatar']),
+							'verb'         => $item['verb'],
+							'otype'        => 'person',
+							'activity'     => $verb,
+							'parent'       => $item['parent']
+						));
+					}
+				}
 			}
 		}
-		return $item_id;
 	}
 
 	private function process_deletion($header, $xpath, $deletion, $importer, $contact_id) {
@@ -919,6 +968,64 @@ toplevel:
 		if (!$uri OR !$contact_id)
 			return false;
 
+
+		$is_reply = false;
+		$r = q("SELECT `id`, `parent-uri`, `parent` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc($uri),
+			intval($importer['importer_uid'])
+		);
+		if(count($r)) {
+			$parent_uri = $r[0]['parent-uri'];
+			if($r[0]['id'] != $r[0]['parent'])
+				$is_reply = true;
+		}
+
+		if($is_reply) {
+			$community = false;
+
+			if($importer['page-flags'] == PAGE_COMMUNITY || $importer['page-flags'] == PAGE_PRVGROUP) {
+				$sql_extra = '';
+				$community = true;
+				logger('possible community delete');
+			} else
+				$sql_extra = " AND `contact`.`self` AND `item`.`wall`";
+
+			// was the top-level post for this reply written by somebody on this site?
+			// Specifically, the recipient?
+
+			$is_a_remote_delete = false;
+
+			$r = q("SELECT `item`.`forum_mode`, `item`.`wall` FROM `item`
+				INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
+				WHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' or `item`.`thr-parent` = '%s')
+				AND `item`.`uid` = %d
+				$sql_extra
+				LIMIT 1",
+				dbesc($parent_uri),
+				dbesc($parent_uri),
+				dbesc($parent_uri),
+				intval($importer['importer_uid'])
+			);
+			if($r && count($r))
+				$is_a_remote_delete = true;
+
+			// Does this have the characteristics of a community or private group comment?
+			// If it's a reply to a wall post on a community/prvgroup page it's a
+			// valid community comment. Also forum_mode makes it valid for sure.
+			// If neither, it's not.
+
+			if($is_a_remote_delete && $community) {
+				if((!$r[0]['forum_mode']) && (!$r[0]['wall'])) {
+					$is_a_remote_delete = false;
+					logger('not a community delete');
+				}
+			}
+
+			if($is_a_remote_delete) {
+				logger('received remote delete');
+			}
+		}
+
 		$r = q("SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN `contact` on `item`.`contact-id` = `contact`.`id`
 				WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1",
 				dbesc($uri),
@@ -932,6 +1039,8 @@ toplevel:
 
 			if(!$item["deleted"])
 				logger('deleting item '.$item["id"].' uri='.$item['uri'], LOGGER_DEBUG);
+			else
+				return;
 
 			if($item["object-type"] === ACTIVITY_OBJ_EVENT) {
 				logger("Deleting event ".$item["event-id"], LOGGER_DEBUG);
@@ -955,7 +1064,7 @@ toplevel:
 						$author_copy = (($item['origin']) ? true : false);
 
 						if($owner_remove && $author_copy)
-							continue;
+							return;
 						if($author_remove || $owner_remove) {
 							$tags = explode(',',$i[0]['tag']);
 							$newtags = array();
@@ -983,9 +1092,9 @@ toplevel:
 						dbesc($item['uri']),
 						intval($importer['uid'])
 					);
-					create_tags_from_itemuri($item['uri'], $importer['uid']);
-					create_files_from_itemuri($item['uri'], $importer['uid']);
-					update_thread_uri($item['uri'], $importer['uid']);
+				create_tags_from_itemuri($item['uri'], $importer['uid']);
+				create_files_from_itemuri($item['uri'], $importer['uid']);
+				update_thread_uri($item['uri'], $importer['uid']);
 			} else {
 				$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
 						`body` = '', `title` = ''
@@ -997,6 +1106,7 @@ toplevel:
 					);
 				create_tags_from_itemuri($uri, $importer['uid']);
 				create_files_from_itemuri($uri, $importer['uid']);
+				update_thread_uri($uri, $importer['importer_uid']);
 				if($item['last-child']) {
 					// ensure that last-child is set in case the comment that had it just got wiped.
 					q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ",
@@ -1018,9 +1128,8 @@ toplevel:
 				}
 				// if this is a relayed delete, propagate it to other recipients
 
-//                                                if($is_a_remote_delete)
-  //                                                      proc_run('php',"include/notifier.php","drop",$item['id']);
-
+				if($is_a_remote_delete)
+					proc_run('php',"include/notifier.php","drop",$item['id']);
 			}
 		}
 	}
@@ -1056,7 +1165,6 @@ toplevel:
 		$header["type"] = "remote";
 		$header["wall"] = 0;
 		$header["origin"] = 0;
-		$header["gravity"] = GRAVITY_PARENT;
 		$header["contact-id"] = $importer["id"];
 
 		// Update the contact table if the data has changed

From 1aa225b03bc89e53cbaa5ec95e4c13b87587a926 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 1 Feb 2016 23:52:37 +0100
Subject: [PATCH 013/273] Code beautification

---
 include/import-dfrn.php | 642 ++++++++++++++++++----------------------
 1 file changed, 294 insertions(+), 348 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index 0e185d3f44..bfcb002bb1 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -18,9 +18,9 @@ require_once("include/items.php");
 require_once("include/tags.php");
 require_once("include/files.php");
 
-define('DFRN_TOP_LEVEL', 0);
-define('DFRN_REPLY', 1);
-define('DFRN_REPLY_RC', 2);
+define("DFRN_TOP_LEVEL", 0);
+define("DFRN_REPLY", 1);
+define("DFRN_REPLY_RC", 2);
 
 class dfrn2 {
 
@@ -33,23 +33,23 @@ class dfrn2 {
 	 */
 	private function birthday_event($contact, $birthday) {
 
-		logger('updating birthday: '.$birthday.' for contact '.$contact['id']);
+		logger("updating birthday: ".$birthday." for contact ".$contact["id"]);
 
-		$bdtext = sprintf(t('%s\'s birthday'), $contact['name']);
-		$bdtext2 = sprintf(t('Happy Birthday %s'), ' [url=' . $contact['url'].']'.$contact['name'].'[/url]') ;
+		$bdtext = sprintf(t("%s\'s birthday"), $contact["name"]);
+		$bdtext2 = sprintf(t("Happy Birthday %s"), " [url=".$contact["url"]."]".$contact["name"]."[/url]") ;
 
 
 		$r = q("INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`summary`,`desc`,`type`)
 			VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
-			intval($contact['uid']),
-			intval($contact['id']),
+			intval($contact["uid"]),
+			intval($contact["id"]),
 			dbesc(datetime_convert()),
 			dbesc(datetime_convert()),
-			dbesc(datetime_convert('UTC','UTC', $birthday)),
-			dbesc(datetime_convert('UTC','UTC', $birthday.' + 1 day ')),
+			dbesc(datetime_convert("UTC","UTC", $birthday)),
+			dbesc(datetime_convert("UTC","UTC", $birthday." + 1 day ")),
 			dbesc($bdtext),
 			dbesc($bdtext2),
-			dbesc('birthday')
+			dbesc("birthday")
 		);
 	}
 
@@ -68,8 +68,8 @@ class dfrn2 {
 	private function fetchauthor($xpath, $context, $importer, $element, $contact, $onlyfetch) {
 
 		$author = array();
-		$author["name"] = $xpath->evaluate($element.'/atom:name/text()', $context)->item(0)->nodeValue;
-		$author["link"] = $xpath->evaluate($element.'/atom:uri/text()', $context)->item(0)->nodeValue;
+		$author["name"] = $xpath->evaluate($element."/atom:name/text()", $context)->item(0)->nodeValue;
+		$author["link"] = $xpath->evaluate($element."/atom:uri/text()", $context)->item(0)->nodeValue;
 
 		$r = q("SELECT `id`, `uid`, `network`, `avatar-date`, `name-date`, `uri-date`, `addr`,
 				`name`, `nick`, `about`, `location`, `keywords`, `bdyear`, `bd`
@@ -124,23 +124,23 @@ class dfrn2 {
 					$contact["uri-date"] = $attributes->textContent;
 
 			// Update contact data
-			$value = $xpath->evaluate($element.'/dfrn:handle/text()', $context)->item(0)->nodeValue;
+			$value = $xpath->evaluate($element."/dfrn:handle/text()", $context)->item(0)->nodeValue;
 			if ($value != "")
 				$contact["addr"] = $value;
 
-			$value = $xpath->evaluate($element.'/poco:displayName/text()', $context)->item(0)->nodeValue;
+			$value = $xpath->evaluate($element."/poco:displayName/text()", $context)->item(0)->nodeValue;
 			if ($value != "")
 				$contact["name"] = $value;
 
-			$value = $xpath->evaluate($element.'/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
+			$value = $xpath->evaluate($element."/poco:preferredUsername/text()", $context)->item(0)->nodeValue;
 			if ($value != "")
 				$contact["nick"] = $value;
 
-			$value = $xpath->evaluate($element.'/poco:note/text()', $context)->item(0)->nodeValue;
+			$value = $xpath->evaluate($element."/poco:note/text()", $context)->item(0)->nodeValue;
 			if ($value != "")
 				$contact["about"] = $value;
 
-			$value = $xpath->evaluate($element.'/poco:address/poco:formatted/text()', $context)->item(0)->nodeValue;
+			$value = $xpath->evaluate($element."/poco:address/poco:formatted/text()", $context)->item(0)->nodeValue;
 			if ($value != "")
 				$contact["location"] = $value;
 
@@ -154,7 +154,7 @@ class dfrn2 {
 
 			// Save the keywords into the contact table
 			$tags = array();
-			$tagelements = $xpath->evaluate($element.'/poco:tags/text()', $context);
+			$tagelements = $xpath->evaluate($element."/poco:tags/text()", $context);
 			foreach($tagelements AS $tag)
 				$tags[$tag->nodeValue] = $tag->nodeValue;
 
@@ -164,7 +164,7 @@ class dfrn2 {
 			// "dfrn:birthday" contains the birthday converted to UTC
 			$old_bdyear = $contact["bdyear"];
 
-			$birthday = $xpath->evaluate($element.'/dfrn:birthday/text()', $context)->item(0)->nodeValue;
+			$birthday = $xpath->evaluate($element."/dfrn:birthday/text()", $context)->item(0)->nodeValue;
 
 			if (strtotime($birthday) > time()) {
 				$bd_timestamp = strtotime($birthday);
@@ -173,7 +173,7 @@ class dfrn2 {
 			}
 
 			// "poco:birthday" is the birthday in the format "yyyy-mm-dd"
-			$value = $xpath->evaluate($element.'/poco:birthday/text()', $context)->item(0)->nodeValue;
+			$value = $xpath->evaluate($element."/poco:birthday/text()", $context)->item(0)->nodeValue;
 
 			if (!in_array($value, array("", "0000-00-00"))) {
 				$bdyear = date("Y");
@@ -229,27 +229,27 @@ class dfrn2 {
 		if (!is_object($activity))
 			return "";
 
-		$obj_doc = new DOMDocument('1.0', 'utf-8');
+		$obj_doc = new DOMDocument("1.0", "utf-8");
 		$obj_doc->formatOutput = true;
 
 		$obj_element = $obj_doc->createElementNS(NAMESPACE_ATOM1, $element);
 
-		$activity_type = $xpath->query('activity:object-type/text()', $activity)->item(0)->nodeValue;
+		$activity_type = $xpath->query("activity:object-type/text()", $activity)->item(0)->nodeValue;
 		xml_add_element($obj_doc, $obj_element, "type", $activity_type);
 
-		$id = $xpath->query('atom:id', $activity)->item(0);
+		$id = $xpath->query("atom:id", $activity)->item(0);
 		if (is_object($id))
 			$obj_element->appendChild($obj_doc->importNode($id, true));
 
-		$title = $xpath->query('atom:title', $activity)->item(0);
+		$title = $xpath->query("atom:title", $activity)->item(0);
 		if (is_object($title))
 			$obj_element->appendChild($obj_doc->importNode($title, true));
 
-		$link = $xpath->query('atom:link', $activity)->item(0);
+		$link = $xpath->query("atom:link", $activity)->item(0);
 		if (is_object($link))
 			$obj_element->appendChild($obj_doc->importNode($link, true));
 
-		$content = $xpath->query('atom:content', $activity)->item(0);
+		$content = $xpath->query("atom:content", $activity)->item(0);
 		if (is_object($content))
 			$obj_element->appendChild($obj_doc->importNode($content, true));
 
@@ -258,7 +258,7 @@ class dfrn2 {
 		$objxml = $obj_doc->saveXML($obj_element);
 
 		// @todo This isn't totally clean. We should find a way to transform the namespaces
-		$objxml = str_replace('<'.$element.' xmlns="http://www.w3.org/2005/Atom">', "<".$element.">", $objxml);
+		$objxml = str_replace("<".$element.' xmlns="http://www.w3.org/2005/Atom">', "<".$element.">", $objxml);
 		return($objxml);
 	}
 
@@ -267,16 +267,16 @@ class dfrn2 {
 		logger("Processing mails");
 
 		$msg = array();
-		$msg["uid"] = $importer['importer_uid'];
-		$msg["from-name"] = $xpath->query('dfrn:sender/dfrn:name/text()', $mail)->item(0)->nodeValue;
-		$msg["from-url"] = $xpath->query('dfrn:sender/dfrn:uri/text()', $mail)->item(0)->nodeValue;
-		$msg["from-photo"] = $xpath->query('dfrn:sender/dfrn:avatar/text()', $mail)->item(0)->nodeValue;
+		$msg["uid"] = $importer["importer_uid"];
+		$msg["from-name"] = $xpath->query("dfrn:sender/dfrn:name/text()", $mail)->item(0)->nodeValue;
+		$msg["from-url"] = $xpath->query("dfrn:sender/dfrn:uri/text()", $mail)->item(0)->nodeValue;
+		$msg["from-photo"] = $xpath->query("dfrn:sender/dfrn:avatar/text()", $mail)->item(0)->nodeValue;
 		$msg["contact-id"] = $importer["id"];
-		$msg["uri"] = $xpath->query('dfrn:id/text()', $mail)->item(0)->nodeValue;
-		$msg["parent-uri"] = $xpath->query('dfrn:in-reply-to/text()', $mail)->item(0)->nodeValue;
-		$msg["created"] = $xpath->query('dfrn:sentdate/text()', $mail)->item(0)->nodeValue;
-		$msg["title"] = $xpath->query('dfrn:subject/text()', $mail)->item(0)->nodeValue;
-		$msg["body"] = $xpath->query('dfrn:content/text()', $mail)->item(0)->nodeValue;
+		$msg["uri"] = $xpath->query("dfrn:id/text()", $mail)->item(0)->nodeValue;
+		$msg["parent-uri"] = $xpath->query("dfrn:in-reply-to/text()", $mail)->item(0)->nodeValue;
+		$msg["created"] = $xpath->query("dfrn:sentdate/text()", $mail)->item(0)->nodeValue;
+		$msg["title"] = $xpath->query("dfrn:subject/text()", $mail)->item(0)->nodeValue;
+		$msg["body"] = $xpath->query("dfrn:content/text()", $mail)->item(0)->nodeValue;
 		$msg["seen"] = 0;
 		$msg["replied"] = 0;
 
@@ -287,18 +287,18 @@ class dfrn2 {
 		// send notifications.
 
 		$notif_params = array(
-			'type' => NOTIFY_MAIL,
-			'notify_flags' => $importer['notify-flags'],
-			'language' => $importer['language'],
-			'to_name' => $importer['username'],
-			'to_email' => $importer['email'],
-			'uid' => $importer['importer_uid'],
-			'item' => $msg,
-			'source_name' => $msg['from-name'],
-			'source_link' => $importer['url'],
-			'source_photo' => $importer['thumb'],
-			'verb' => ACTIVITY_POST,
-			'otype' => 'mail'
+			"type" => NOTIFY_MAIL,
+			"notify_flags" => $importer["notify-flags"],
+			"language" => $importer["language"],
+			"to_name" => $importer["username"],
+			"to_email" => $importer["email"],
+			"uid" => $importer["importer_uid"],
+			"item" => $msg,
+			"source_name" => $msg["from-name"],
+			"source_link" => $importer["url"],
+			"source_photo" => $importer["thumb"],
+			"verb" => ACTIVITY_POST,
+			"otype" => "mail"
 		);
 
 		notification($notif_params);
@@ -311,11 +311,11 @@ class dfrn2 {
 		$suggest = array();
 		$suggest["uid"] = $importer["importer_uid"];
 		$suggest["cid"] = $importer["id"];
-		$suggest["url"] = $xpath->query('dfrn:url/text()', $suggestion)->item(0)->nodeValue;
-		$suggest["name"] = $xpath->query('dfrn:name/text()', $suggestion)->item(0)->nodeValue;
-		$suggest["photo"] = $xpath->query('dfrn:photo/text()', $suggestion)->item(0)->nodeValue;
-		$suggest["request"] = $xpath->query('dfrn:request/text()', $suggestion)->item(0)->nodeValue;
-		$suggest["body"] = $xpath->query('dfrn:note/text()', $suggestion)->item(0)->nodeValue;
+		$suggest["url"] = $xpath->query("dfrn:url/text()", $suggestion)->item(0)->nodeValue;
+		$suggest["name"] = $xpath->query("dfrn:name/text()", $suggestion)->item(0)->nodeValue;
+		$suggest["photo"] = $xpath->query("dfrn:photo/text()", $suggestion)->item(0)->nodeValue;
+		$suggest["request"] = $xpath->query("dfrn:request/text()", $suggestion)->item(0)->nodeValue;
+		$suggest["body"] = $xpath->query("dfrn:note/text()", $suggestion)->item(0)->nodeValue;
 
 		// Does our member already have a friend matching this description?
 
@@ -379,19 +379,19 @@ class dfrn2 {
 		);
 
 		notification(array(
-			'type'         => NOTIFY_SUGGEST,
-			'notify_flags' => $importer["notify-flags"],
-			'language'     => $importer["language"],
-			'to_name'      => $importer["username"],
-			'to_email'     => $importer["email"],
-			'uid'          => $importer["importer_uid"],
-			'item'         => $suggest,
-			'link'         => App::get_baseurl()."/notifications/intros",
-			'source_name'  => $importer["name"],
-			'source_link'  => $importer["url"],
-			'source_photo' => $importer["photo"],
-			'verb'         => ACTIVITY_REQ_FRIEND,
-			'otype'        => "intro"
+			"type"         => NOTIFY_SUGGEST,
+			"notify_flags" => $importer["notify-flags"],
+			"language"     => $importer["language"],
+			"to_name"      => $importer["username"],
+			"to_email"     => $importer["email"],
+			"uid"          => $importer["importer_uid"],
+			"item"         => $suggest,
+			"link"         => App::get_baseurl()."/notifications/intros",
+			"source_name"  => $importer["name"],
+			"source_link"  => $importer["url"],
+			"source_photo" => $importer["photo"],
+			"verb"         => ACTIVITY_REQ_FRIEND,
+			"otype"        => "intro"
 		));
 
 		return true;
@@ -405,16 +405,16 @@ class dfrn2 {
 		$relocate = array();
 		$relocate["uid"] = $importer["importer_uid"];
 		$relocate["cid"] = $importer["id"];
-		$relocate["url"] = $xpath->query('dfrn:url/text()', $relocation)->item(0)->nodeValue;
-		$relocate["name"] = $xpath->query('dfrn:name/text()', $relocation)->item(0)->nodeValue;
-		$relocate["photo"] = $xpath->query('dfrn:photo/text()', $relocation)->item(0)->nodeValue;
-		$relocate["thumb"] = $xpath->query('dfrn:thumb/text()', $relocation)->item(0)->nodeValue;
-		$relocate["micro"] = $xpath->query('dfrn:micro/text()', $relocation)->item(0)->nodeValue;
-		$relocate["request"] = $xpath->query('dfrn:request/text()', $relocation)->item(0)->nodeValue;
-		$relocate["confirm"] = $xpath->query('dfrn:confirm/text()', $relocation)->item(0)->nodeValue;
-		$relocate["notify"] = $xpath->query('dfrn:notify/text()', $relocation)->item(0)->nodeValue;
-		$relocate["poll"] = $xpath->query('dfrn:poll/text()', $relocation)->item(0)->nodeValue;
-		$relocate["sitepubkey"] = $xpath->query('dfrn:sitepubkey/text()', $relocation)->item(0)->nodeValue;
+		$relocate["url"] = $xpath->query("dfrn:url/text()", $relocation)->item(0)->nodeValue;
+		$relocate["name"] = $xpath->query("dfrn:name/text()", $relocation)->item(0)->nodeValue;
+		$relocate["photo"] = $xpath->query("dfrn:photo/text()", $relocation)->item(0)->nodeValue;
+		$relocate["thumb"] = $xpath->query("dfrn:thumb/text()", $relocation)->item(0)->nodeValue;
+		$relocate["micro"] = $xpath->query("dfrn:micro/text()", $relocation)->item(0)->nodeValue;
+		$relocate["request"] = $xpath->query("dfrn:request/text()", $relocation)->item(0)->nodeValue;
+		$relocate["confirm"] = $xpath->query("dfrn:confirm/text()", $relocation)->item(0)->nodeValue;
+		$relocate["notify"] = $xpath->query("dfrn:notify/text()", $relocation)->item(0)->nodeValue;
+		$relocate["poll"] = $xpath->query("dfrn:poll/text()", $relocation)->item(0)->nodeValue;
+		$relocate["sitepubkey"] = $xpath->query("dfrn:sitepubkey/text()", $relocation)->item(0)->nodeValue;
 
 		// update contact
 		$r = q("SELECT `photo`, `url` FROM `contact` WHERE `id` = %d AND `uid` = %d;",
@@ -479,60 +479,60 @@ class dfrn2 {
 		return true;
 	}
 
-	private function upate_content($current, $item, $importer, $entrytype) {
+	private function update_content($current, $item, $importer, $entrytype) {
 		if (edited_timestamp_is_newer($current, $item)) {
 
 			// do not accept (ignore) an earlier edit than one we currently have.
-			if(datetime_convert('UTC','UTC',$item['edited']) < $current['edited'])
+			if(datetime_convert("UTC","UTC",$item["edited"]) < $current["edited"])
 				return;
 
 			$r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
-				dbesc($item['title']),
-				dbesc($item['body']),
-				dbesc($item['tag']),
-				dbesc(datetime_convert('UTC','UTC',$item['edited'])),
+				dbesc($item["title"]),
+				dbesc($item["body"]),
+				dbesc($item["tag"]),
+				dbesc(datetime_convert("UTC","UTC",$item["edited"])),
 				dbesc(datetime_convert()),
 				dbesc($item["uri"]),
-				intval($importer['importer_uid'])
+				intval($importer["importer_uid"])
 			);
-			create_tags_from_itemuri($item["uri"], $importer['importer_uid']);
-			update_thread_uri($item["uri"], $importer['importer_uid']);
+			create_tags_from_itemuri($item["uri"], $importer["importer_uid"]);
+			update_thread_uri($item["uri"], $importer["importer_uid"]);
 
 			if ($entrytype == DFRN_REPLY_RC)
-				proc_run('php',"include/notifier.php","comment-import",$current["id"]);
+				proc_run("php", "include/notifier.php","comment-import", $current["id"]);
 		}
 
 		// update last-child if it changes
-		if($item["last-child"] AND ($item["last-child"] != $current['last-child'])) {
+		if($item["last-child"] AND ($item["last-child"] != $current["last-child"])) {
 			$r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
 				dbesc(datetime_convert()),
 				dbesc($item["parent-uri"]),
-				intval($importer['importer_uid'])
+				intval($importer["importer_uid"])
 			);
 			$r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
 				intval($item["last-child"]),
 				dbesc(datetime_convert()),
 				dbesc($item["uri"]),
-				intval($importer['importer_uid'])
+				intval($importer["importer_uid"])
 			);
 		}
 	}
 
-	private function get_entry_type($is_reply, $importer, $item) {
-		if ($is_reply) {
+	private function get_entry_type($importer, $item) {
+		if ($item["parent-uri"] != $item["uri"]) {
 			$community = false;
 
-			if($importer['page-flags'] == PAGE_COMMUNITY || $importer['page-flags'] == PAGE_PRVGROUP) {
-				$sql_extra = '';
+			if($importer["page-flags"] == PAGE_COMMUNITY || $importer["page-flags"] == PAGE_PRVGROUP) {
+				$sql_extra = "";
 				$community = true;
-				logger('possible community reply');
+				logger("possible community action");
 			} else
-				$sql_extra = " and contact.self = 1 and item.wall = 1 ";
+				$sql_extra = " AND `contact`.`self` AND `item`.`wall` ";
 
-			// was the top-level post for this reply written by somebody on this site?
+			// was the top-level post for this action written by somebody on this site?
 			// Specifically, the recipient?
 
-			$is_a_remote_comment = false;
+			$is_a_remote_action = false;
 
 			$r = q("SELECT `item`.`parent-uri` FROM `item`
 				WHERE `item`.`uri` = '%s'
@@ -546,37 +546,81 @@ class dfrn2 {
 					AND `item`.`uid` = %d
 					$sql_extra
 					LIMIT 1",
-					dbesc($r[0]['parent-uri']),
-					dbesc($r[0]['parent-uri']),
-					dbesc($r[0]['parent-uri']),
-					intval($importer['importer_uid'])
+					dbesc($r[0]["parent-uri"]),
+					dbesc($r[0]["parent-uri"]),
+					dbesc($r[0]["parent-uri"]),
+					intval($importer["importer_uid"])
 				);
 				if($r && count($r))
-					$is_a_remote_comment = true;
+					$is_a_remote_action = true;
 			}
 
-			// Does this have the characteristics of a community or private group comment?
-			// If it's a reply to a wall post on a community/prvgroup page it's a
-			// valid community comment. Also forum_mode makes it valid for sure.
+			// Does this have the characteristics of a community or private group action?
+			// If it's an action to a wall post on a community/prvgroup page it's a
+			// valid community action. Also forum_mode makes it valid for sure.
 			// If neither, it's not.
 
-			if($is_a_remote_comment && $community) {
-				if((!$r[0]['forum_mode']) && (!$r[0]['wall'])) {
-					$is_a_remote_comment = false;
-					logger('not a community reply');
+			if($is_a_remote_action && $community) {
+				if((!$r[0]["forum_mode"]) && (!$r[0]["wall"])) {
+					$is_a_remote_action = false;
+					logger("not a community action");
 				}
 			}
-		} else {
-			$is_reply = false;
-			$is_a_remote_comment = false;
-		}
 
-		if ($is_a_remote_comment)
-			return DFRN_REPLY_RC;
-		elseif ($is_reply)
-			return DFRN_REPLY;
-		else
+			if ($is_a_remote_action)
+				return DFRN_REPLY_RC;
+			else
+				return DFRN_REPLY;
+
+		} else
 			return DFRN_TOP_LEVEL;
+
+	}
+
+	private function do_poke($item, $importer, $posted_id) {
+		$verb = urldecode(substr($item["verb"],strpos($item["verb"], "#")+1));
+		if(!$verb)
+			return;
+		$xo = parse_xml_string($item["object"],false);
+
+		if(($xo->type == ACTIVITY_OBJ_PERSON) && ($xo->id)) {
+
+			// somebody was poked/prodded. Was it me?
+			$links = parse_xml_string("<links>".unxmlify($xo->link)."</links>",false);
+
+			foreach($links->link as $l) {
+				$atts = $l->attributes();
+				switch($atts["rel"]) {
+					case "alternate":
+						$Blink = $atts["href"];
+						break;
+					default:
+						break;
+				}
+			}
+			if($Blink && link_compare($Blink,$a->get_baseurl()."/profile/".$importer["nickname"])) {
+
+				// send a notification
+				notification(array(
+					"type"         => NOTIFY_POKE,
+					"notify_flags" => $importer["notify-flags"],
+					"language"     => $importer["language"],
+					"to_name"      => $importer["username"],
+					"to_email"     => $importer["email"],
+					"uid"          => $importer["importer_uid"],
+					"item"         => $item,
+					"link"         => $a->get_baseurl()."/display/".urlencode(get_item_guid($posted_id)),
+					"source_name"  => stripslashes($item["author-name"]),
+					"source_link"  => $item["author-link"],
+					"source_photo" => ((link_compare($item["author-link"],$importer["url"]))
+						? $importer["thumb"] : $item["author-avatar"]),
+					"verb"         => $item["verb"],
+					"otype"        => "person",
+					"activity"     => $verb,
+					"parent"       => $item["parent"]
+				));
+			}
+		}
 	}
 
 	private function process_entry($header, $xpath, $entry, $importer, $contact) {
@@ -586,7 +630,7 @@ class dfrn2 {
 		$item = $header;
 
 		// Get the uri
-		$item["uri"] = $xpath->query('atom:id/text()', $entry)->item(0)->nodeValue;
+		$item["uri"] = $xpath->query("atom:id/text()", $entry)->item(0)->nodeValue;
 
 		// Fetch the owner
 		$owner = self::fetchauthor($xpath, $entry, $importer, "dfrn:owner", $contact, true);
@@ -614,12 +658,12 @@ class dfrn2 {
 		if (($header["network"] != $author["network"]) AND ($author["network"] != ""))
 			$item["network"] = $author["network"];
 
-		$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
+		$item["title"] = $xpath->query("atom:title/text()", $entry)->item(0)->nodeValue;
 
-		$item["created"] = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
-		$item["edited"] = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue;
+		$item["created"] = $xpath->query("atom:published/text()", $entry)->item(0)->nodeValue;
+		$item["edited"] = $xpath->query("atom:updated/text()", $entry)->item(0)->nodeValue;
 
-		$item["body"] = $xpath->query('dfrn:env/text()', $entry)->item(0)->nodeValue;
+		$item["body"] = $xpath->query("dfrn:env/text()", $entry)->item(0)->nodeValue;
 		$item["body"] = str_replace(array(' ',"\t","\r","\n"), array('','','',''),$item["body"]);
 		// make sure nobody is trying to sneak some html tags by us
 		$item["body"] = notags(base64url_decode($item["body"]));
@@ -629,23 +673,23 @@ class dfrn2 {
 		/// @todo Do we need the old check for HTML elements?
 
 		// We don't need the content element since "dfrn:env" is always present
-		//$item["body"] = $xpath->query('atom:content/text()', $entry)->item(0)->nodeValue;
+		//$item["body"] = $xpath->query("atom:content/text()", $entry)->item(0)->nodeValue;
 
-		$item["last-child"] = $xpath->query('dfrn:comment-allow/text()', $entry)->item(0)->nodeValue;
-		$item["location"] = $xpath->query('dfrn:location/text()', $entry)->item(0)->nodeValue;
+		$item["last-child"] = $xpath->query("dfrn:comment-allow/text()", $entry)->item(0)->nodeValue;
+		$item["location"] = $xpath->query("dfrn:location/text()", $entry)->item(0)->nodeValue;
 
-		$georsspoint = $xpath->query('georss:point', $entry);
+		$georsspoint = $xpath->query("georss:point", $entry);
 		if ($georsspoint)
 			$item["coord"] = $georsspoint->item(0)->nodeValue;
 
-		$item["private"] = $xpath->query('dfrn:private/text()', $entry)->item(0)->nodeValue;
+		$item["private"] = $xpath->query("dfrn:private/text()", $entry)->item(0)->nodeValue;
 
-		$item["extid"] = $xpath->query('dfrn:extid/text()', $entry)->item(0)->nodeValue;
+		$item["extid"] = $xpath->query("dfrn:extid/text()", $entry)->item(0)->nodeValue;
 
-		if ($xpath->query('dfrn:extid/text()', $entry)->item(0)->nodeValue == "true")
+		if ($xpath->query("dfrn:extid/text()", $entry)->item(0)->nodeValue == "true")
 			$item["bookmark"] = true;
 
-		$notice_info = $xpath->query('statusnet:notice_info', $entry);
+		$notice_info = $xpath->query("statusnet:notice_info", $entry);
 		if ($notice_info AND ($notice_info->length > 0)) {
 			foreach($notice_info->item(0)->attributes AS $attributes) {
 				if ($attributes->name == "source")
@@ -653,32 +697,30 @@ class dfrn2 {
 			}
 		}
 
-		$item["guid"] = $xpath->query('dfrn:diaspora_guid/text()', $entry)->item(0)->nodeValue;
+		$item["guid"] = $xpath->query("dfrn:diaspora_guid/text()", $entry)->item(0)->nodeValue;
 
-		// We store the data from "dfrn:diaspora_signature" in a later step. See some lines below
-		$item["dsprsig"] = unxmlify($xpath->query('dfrn:diaspora_signature/text()', $entry)->item(0)->nodeValue);
+		// We store the data from "dfrn:diaspora_signature" in a different table, this is done in "item_store"
+		$item["dsprsig"] = unxmlify($xpath->query("dfrn:diaspora_signature/text()", $entry)->item(0)->nodeValue);
 
-		$item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue;
+		$item["verb"] = $xpath->query("activity:verb/text()", $entry)->item(0)->nodeValue;
 
-		if ($xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue != "")
-			$item["object-type"] = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue;
+		if ($xpath->query("activity:object-type/text()", $entry)->item(0)->nodeValue != "")
+			$item["object-type"] = $xpath->query("activity:object-type/text()", $entry)->item(0)->nodeValue;
 
-		// I have the feeling that we don't do anything with this data
-		$object = $xpath->query('activity:object', $entry)->item(0);
+		$object = $xpath->query("activity:object", $entry)->item(0);
 		$item["object"] = self::transform_activity($xpath, $object, "object");
 
-		// Could someone explain what this is for?
-		$target = $xpath->query('activity:target', $entry)->item(0);
+		$target = $xpath->query("activity:target", $entry)->item(0);
 		$item["target"] = self::transform_activity($xpath, $target, "target");
 
-		$categories = $xpath->query('atom:category', $entry);
+		$categories = $xpath->query("atom:category", $entry);
 		if ($categories) {
 			foreach ($categories AS $category) {
 				foreach($category->attributes AS $attributes)
 					if ($attributes->name == "term") {
 						$term = $attributes->textContent;
 						if(strlen($item["tag"]))
-							$item["tag"] .= ',';
+							$item["tag"] .= ",";
 
 						$item["tag"] .= "#[url=".App::get_baseurl()."/search?tag=".$term."]".$term."[/url]";
 					}
@@ -687,7 +729,7 @@ class dfrn2 {
 
 		$enclosure = "";
 
-		$links = $xpath->query('atom:link', $entry);
+		$links = $xpath->query("atom:link", $entry);
 		if ($links) {
 			$rel = "";
 			$href = "";
@@ -715,7 +757,7 @@ class dfrn2 {
 						case "enclosure":
 							$enclosure = $href;
 							if(strlen($item["attach"]))
-								$item["attach"] .= ',';
+								$item["attach"] .= ",";
 
 							$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
 							break;
@@ -726,21 +768,22 @@ class dfrn2 {
 		// Is it a reply or a top level posting?
 		$item["parent-uri"] = $item["uri"];
 
-		$inreplyto = $xpath->query('thr:in-reply-to', $entry);
+		$inreplyto = $xpath->query("thr:in-reply-to", $entry);
 		if (is_object($inreplyto->item(0)))
 			foreach($inreplyto->item(0)->attributes AS $attributes)
 				if ($attributes->name == "ref")
 					$item["parent-uri"] = $attributes->textContent;
 
-		$entrytype = get_entry_type(( $item["parent-uri"] != $item["uri"]),  $importer, $item);
+		// Get the type of the item (Top level post, reply or remote reply)
+		$entrytype = get_entry_type($importer, $item);
 
 		// Now assign the rest of the values that depend on the type of the message
 		if ($entrytype == DFRN_REPLY_RC) {
 			if (!isset($item["object-type"]))
 				$item["object-type"] = ACTIVITY_OBJ_COMMENT;
 
-			$item["type"] = 'remote-comment';
-			$item['wall'] = 1;
+			$item["type"] = "remote-comment";
+			$item["wall"] = 1;
 		} elseif ($entrytype == DFRN_REPLY) {
 			if (!isset($item["object-type"]))
 				$item["object-type"] = ACTIVITY_OBJ_COMMENT;
@@ -749,21 +792,21 @@ class dfrn2 {
 				$item["object-type"] = ACTIVITY_OBJ_NOTE;
 
 			if ($item["object-type"] === ACTIVITY_OBJ_EVENT) {
-				$ev = bbtoevent($item['body']);
-				if((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) {
-					$ev['cid'] = $importer['id'];
-					$ev['uid'] = $importer['uid'];
-					$ev['uri'] = $item["uri"];
-					$ev['edited'] = $item['edited'];
+				$ev = bbtoevent($item["body"]);
+				if((x($ev, "desc") || x($ev, "summary")) && x($ev, "start")) {
+					$ev["cid"] = $importer["id"];
+					$ev["uid"] = $importer["uid"];
+					$ev["uri"] = $item["uri"];
+					$ev["edited"] = $item["edited"];
 					$ev['private'] = $item['private'];
-					$ev['guid'] = $item['guid'];
+					$ev["guid"] = $item["guid"];
 
-					$r = q("SELECT * FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+					$r = q("SELECT `id` FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
 						dbesc($item["uri"]),
-						intval($importer['uid'])
+						intval($importer["uid"])
 					);
 					if(count($r))
-						$ev['id'] = $r[0]['id'];
+						$ev["id"] = $r[0]["id"];
 						$xyz = event_store($ev);
 							return;
 				}
@@ -772,43 +815,43 @@ class dfrn2 {
 
 		$r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
 			dbesc($item["uri"]),
-			intval($importer['importer_uid'])
+			intval($importer["importer_uid"])
 		);
 
 		// Update content if 'updated' changes
 		if(count($r)) {
-			self::upate_content($r[0], $item, $importer, $entrytype);
+			self::update_content($r[0], $item, $importer, $entrytype);
 			return;
 		}
 
 		if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) {
-			if($importer['rel'] == CONTACT_IS_FOLLOWER)
+			if($importer["rel"] == CONTACT_IS_FOLLOWER)
 				return;
 
-			if(($item['verb'] === ACTIVITY_LIKE)
-				|| ($item['verb'] === ACTIVITY_DISLIKE)
-				|| ($item['verb'] === ACTIVITY_ATTEND)
-				|| ($item['verb'] === ACTIVITY_ATTENDNO)
-				|| ($item['verb'] === ACTIVITY_ATTENDMAYBE)) {
+			if(($item["verb"] === ACTIVITY_LIKE)
+				|| ($item["verb"] === ACTIVITY_DISLIKE)
+				|| ($item["verb"] === ACTIVITY_ATTEND)
+				|| ($item["verb"] === ACTIVITY_ATTENDNO)
+				|| ($item["verb"] === ACTIVITY_ATTENDMAYBE)) {
 				$is_like = true;
-				$item['type'] = 'activity';
-				$item['gravity'] = GRAVITY_LIKE;
+				$item["type"] = "activity";
+				$item["gravity"] = GRAVITY_LIKE;
 				// only one like or dislike per person
 				// splitted into two queries for performance issues
 				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1",
-					intval($item['uid']),
-					dbesc($item['author-link']),
-					dbesc($item['verb']),
-					dbesc($item['parent-uri'])
+					intval($item["uid"]),
+					dbesc($item["author-link"]),
+					dbesc($item["verb"]),
+					dbesc($item["parent-uri"])
 				);
 				if($r && count($r))
 					return;
 
 				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1",
-					intval($item['uid']),
-					dbesc($item['author-link']),
-					dbesc($item['verb']),
-					dbesc($item['parent-uri'])
+					intval($item["uid"]),
+					dbesc($item["author-link"]),
+					dbesc($item["verb"]),
+					dbesc($item["parent-uri"])
 				);
 				if($r && count($r))
 					return;
@@ -816,15 +859,15 @@ class dfrn2 {
 			} else
 				$is_like = false;
 
-			if(($item['verb'] === ACTIVITY_TAG) && ($item['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
+			if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
 
-				$xo = parse_xml_string($item['object'],false);
-				$xt = parse_xml_string($item['target'],false);
+				$xo = parse_xml_string($item["object"],false);
+				$xt = parse_xml_string($item["target"],false);
 
 				if($xt->type == ACTIVITY_OBJ_NOTE) {
 					$r = q("SELECT `id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
 						dbesc($xt->id),
-						intval($importer['importer_uid'])
+						intval($importer["importer_uid"])
 					);
 
 					if(!count($r))
@@ -832,12 +875,12 @@ class dfrn2 {
 
 					// extract tag, if not duplicate, add to parent item
 					if($xo->content) {
-						if(!(stristr($r[0]['tag'],trim($xo->content)))) {
+						if(!(stristr($r[0]["tag"],trim($xo->content)))) {
 							q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
-								dbesc($r[0]['tag'] . (strlen($r[0]['tag']) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'),
-								intval($r[0]['id'])
+								dbesc($r[0]["tag"] . (strlen($r[0]["tag"]) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'),
+								intval($r[0]["id"])
 							);
-							create_tags_from_item($r[0]['id']);
+							create_tags_from_item($r[0]["id"]);
 						}
 					}
 				}
@@ -852,46 +895,46 @@ class dfrn2 {
 
 				$r = q("SELECT `parent`, `parent-uri` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
 					intval($posted_id),
-					intval($importer['importer_uid'])
+					intval($importer["importer_uid"])
 				);
 				if(count($r)) {
-					$parent = $r[0]['parent'];
-					$parent_uri = $r[0]['parent-uri'];
+					$parent = $r[0]["parent"];
+					$parent_uri = $r[0]["parent-uri"];
 				}
 
 				if(!$is_like) {
 					$r1 = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `uid` = %d AND `parent` = %d",
 						dbesc(datetime_convert()),
-						intval($importer['importer_uid']),
-						intval($r[0]['parent'])
+						intval($importer["importer_uid"]),
+						intval($r[0]["parent"])
 					);
 
 					$r2 = q("UPDATE `item` SET `last-child` = 1, `changed` = '%s' WHERE `uid` = %d AND `id` = %d",
 						dbesc(datetime_convert()),
-						intval($importer['importer_uid']),
+						intval($importer["importer_uid"]),
 						intval($posted_id)
 					);
 				}
 
 				if($posted_id AND $parent AND ($entrytype == DFRN_REPLY_RC)) {
-					proc_run('php',"include/notifier.php","comment-import","$posted_id");
+					proc_run("php", "include/notifier.php", "comment-import", $posted_id);
 				}
 
 				return true;
 			}
 		} else {
-			if(!link_compare($item['owner-link'],$importer['url'])) {
+			if(!link_compare($item["owner-link"],$importer["url"])) {
 				// The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
 				// but otherwise there's a possible data mixup on the sender's system.
 				// the tgroup delivery code called from item_store will correct it if it's a forum,
 				// but we're going to unconditionally correct it here so that the post will always be owned by our contact.
 				logger('Correcting item owner.', LOGGER_DEBUG);
-				$item['owner-name']   = $importer['senderName'];
-				$item['owner-link']   = $importer['url'];
-				$item['owner-avatar'] = $importer['thumb'];
+				$item["owner-name"]   = $importer["senderName"];
+				$item["owner-link"]   = $importer["url"];
+				$item["owner-avatar"] = $importer["thumb"];
 			}
 
-			if(($importer['rel'] == CONTACT_IS_FOLLOWER) && (!tgroup_check($importer['importer_uid'],$item)))
+			if(($importer["rel"] == CONTACT_IS_FOLLOWER) && (!tgroup_check($importer["importer_uid"], $item)))
 				return;
 
 			// This is my contact on another system, but it's really me.
@@ -900,53 +943,8 @@ class dfrn2 {
 
 			$posted_id = item_store($item, false, $notify);
 
-			if(stristr($item['verb'],ACTIVITY_POKE)) {
-				$verb = urldecode(substr($item['verb'],strpos($item['verb'],'#')+1));
-				if(!$verb)
-					return;
-				$xo = parse_xml_string($item['object'],false);
-
-				if(($xo->type == ACTIVITY_OBJ_PERSON) && ($xo->id)) {
-
-					// somebody was poked/prodded. Was it me?
-					$links = parse_xml_string("<links>".unxmlify($xo->link)."</links>",false);
-
-					foreach($links->link as $l) {
-						$atts = $l->attributes();
-						switch($atts['rel']) {
-							case "alternate":
-								$Blink = $atts['href'];
-								break;
-							default:
-								break;
-						}
-					}
-					if($Blink && link_compare($Blink,$a->get_baseurl() . '/profile/' . $importer['nickname'])) {
-
-						// send a notification
-						require_once('include/enotify.php');
-
-						notification(array(
-							'type'         => NOTIFY_POKE,
-							'notify_flags' => $importer['notify-flags'],
-							'language'     => $importer['language'],
-							'to_name'      => $importer['username'],
-							'to_email'     => $importer['email'],
-							'uid'          => $importer['importer_uid'],
-							'item'         => $item,
-							'link'             => $a->get_baseurl().'/display/'.urlencode(get_item_guid($posted_id)),
-							'source_name'  => stripslashes($item['author-name']),
-							'source_link'  => $item['author-link'],
-							'source_photo' => ((link_compare($item['author-link'],$importer['url']))
-								? $importer['thumb'] : $item['author-avatar']),
-							'verb'         => $item['verb'],
-							'otype'        => 'person',
-							'activity'     => $verb,
-							'parent'       => $item['parent']
-						));
-					}
-				}
-			}
+			if(stristr($item["verb"],ACTIVITY_POKE))
+				self::do_poke($item, $importer, $posted_id);
 		}
 	}
 
@@ -961,84 +959,31 @@ class dfrn2 {
 				$when = $attributes->textContent;
 		}
 		if ($when)
-			$when = datetime_convert('UTC','UTC', $when, 'Y-m-d H:i:s');
+			$when = datetime_convert("UTC", "UTC", $when, "Y-m-d H:i:s");
 		else
-			$when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s');
+			$when = datetime_convert("UTC", "UTC", "now", "Y-m-d H:i:s");
 
 		if (!$uri OR !$contact_id)
 			return false;
 
-
-		$is_reply = false;
-		$r = q("SELECT `id`, `parent-uri`, `parent` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-			dbesc($uri),
-			intval($importer['importer_uid'])
-		);
-		if(count($r)) {
-			$parent_uri = $r[0]['parent-uri'];
-			if($r[0]['id'] != $r[0]['parent'])
-				$is_reply = true;
-		}
-
-		if($is_reply) {
-			$community = false;
-
-			if($importer['page-flags'] == PAGE_COMMUNITY || $importer['page-flags'] == PAGE_PRVGROUP) {
-				$sql_extra = '';
-				$community = true;
-				logger('possible community delete');
-			} else
-				$sql_extra = " AND `contact`.`self` AND `item`.`wall`";
-
-			// was the top-level post for this reply written by somebody on this site?
-			// Specifically, the recipient?
-
-			$is_a_remote_delete = false;
-
-			$r = q("SELECT `item`.`forum_mode`, `item`.`wall` FROM `item`
-				INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
-				WHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' or `item`.`thr-parent` = '%s')
-				AND `item`.`uid` = %d
-				$sql_extra
-				LIMIT 1",
-				dbesc($parent_uri),
-				dbesc($parent_uri),
-				dbesc($parent_uri),
-				intval($importer['importer_uid'])
-			);
-			if($r && count($r))
-				$is_a_remote_delete = true;
-
-			// Does this have the characteristics of a community or private group comment?
-			// If it's a reply to a wall post on a community/prvgroup page it's a
-			// valid community comment. Also forum_mode makes it valid for sure.
-			// If neither, it's not.
-
-			if($is_a_remote_delete && $community) {
-				if((!$r[0]['forum_mode']) && (!$r[0]['wall'])) {
-					$is_a_remote_delete = false;
-					logger('not a community delete');
-				}
-			}
-
-			if($is_a_remote_delete) {
-				logger('received remote delete');
-			}
-		}
-
+		/// @todo Only select the used fields
 		$r = q("SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN `contact` on `item`.`contact-id` = `contact`.`id`
 				WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1",
 				dbesc($uri),
 				intval($importer["uid"]),
 				intval($contact_id)
 			);
-		if(!count($r))
+		if(!count($r)) {
 			logger("Item with uri ".$uri." from contact ".$contact_id." for user ".$importer["uid"]." wasn't found.", LOGGER_DEBUG);
-		else {
+			return;
+		} else {
+
 			$item = $r[0];
 
+			$entrytype = get_entry_type($importer, $item);
+
 			if(!$item["deleted"])
-				logger('deleting item '.$item["id"].' uri='.$item['uri'], LOGGER_DEBUG);
+				logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG);
 			else
 				return;
 
@@ -1059,14 +1004,14 @@ class dfrn2 {
 
 						// For tags, the owner cannot remove the tag on the author's copy of the post.
 
-						$owner_remove = (($item['contact-id'] == $i[0]['contact-id']) ? true: false);
-						$author_remove = (($item['origin'] && $item['self']) ? true : false);
-						$author_copy = (($item['origin']) ? true : false);
+						$owner_remove = (($item["contact-id"] == $i[0]["contact-id"]) ? true: false);
+						$author_remove = (($item["origin"] && $item["self"]) ? true : false);
+						$author_copy = (($item["origin"]) ? true : false);
 
 						if($owner_remove && $author_copy)
 							return;
 						if($author_remove || $owner_remove) {
-							$tags = explode(',',$i[0]['tag']);
+							$tags = explode(',',$i[0]["tag"]);
 							$newtags = array();
 							if(count($tags)) {
 								foreach($tags as $tag)
@@ -1075,26 +1020,26 @@ class dfrn2 {
 							}
 							q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
 								dbesc(implode(',',$newtags)),
-								intval($i[0]['id'])
+								intval($i[0]["id"])
 							);
-							create_tags_from_item($i[0]['id']);
+							create_tags_from_item($i[0]["id"]);
 						}
 					}
 				}
 			}
 
-			if($item['uri'] == $item['parent-uri']) {
+			if($entrytype == DFRN_TOP_LEVEL) {
 				$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
 						`body` = '', `title` = ''
 					WHERE `parent-uri` = '%s' AND `uid` = %d",
 						dbesc($when),
 						dbesc(datetime_convert()),
-						dbesc($item['uri']),
-						intval($importer['uid'])
+						dbesc($uri),
+						intval($importer["uid"])
 					);
-				create_tags_from_itemuri($item['uri'], $importer['uid']);
-				create_files_from_itemuri($item['uri'], $importer['uid']);
-				update_thread_uri($item['uri'], $importer['uid']);
+				create_tags_from_itemuri($uri, $importer["uid"]);
+				create_files_from_itemuri($uri, $importer["uid"]);
+				update_thread_uri($uri, $importer["uid"]);
 			} else {
 				$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
 						`body` = '', `title` = ''
@@ -1102,34 +1047,34 @@ class dfrn2 {
 						dbesc($when),
 						dbesc(datetime_convert()),
 						dbesc($uri),
-						intval($importer['uid'])
+						intval($importer["uid"])
 					);
-				create_tags_from_itemuri($uri, $importer['uid']);
-				create_files_from_itemuri($uri, $importer['uid']);
-				update_thread_uri($uri, $importer['importer_uid']);
-				if($item['last-child']) {
+				create_tags_from_itemuri($uri, $importer["uid"]);
+				create_files_from_itemuri($uri, $importer["uid"]);
+				update_thread_uri($uri, $importer["importer_uid"]);
+				if($item["last-child"]) {
 					// ensure that last-child is set in case the comment that had it just got wiped.
 					q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ",
 						dbesc(datetime_convert()),
-						dbesc($item['parent-uri']),
-						intval($item['uid'])
+						dbesc($item["parent-uri"]),
+						intval($item["uid"])
 					);
 					// who is the last child now?
 					$r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `moderated` = 0 AND `uid` = %d
 						ORDER BY `created` DESC LIMIT 1",
-							dbesc($item['parent-uri']),
-							intval($importer['uid'])
+							dbesc($item["parent-uri"]),
+							intval($importer["uid"])
 					);
 					if(count($r)) {
 						q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d",
-							intval($r[0]['id'])
+							intval($r[0]["id"])
 						);
 					}
 				}
 				// if this is a relayed delete, propagate it to other recipients
 
-				if($is_a_remote_delete)
-					proc_run('php',"include/notifier.php","drop",$item['id']);
+				if($entrytype == DFRN_REPLY_RC)
+					proc_run("php", "include/notifier.php","drop", $item["id"]);
 			}
 		}
 	}
@@ -1143,17 +1088,18 @@ class dfrn2 {
 		@$doc->loadXML($xml);
 
 		$xpath = new DomXPath($doc);
-		$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
-		$xpath->registerNamespace('thr', NAMESPACE_THREAD);
-		$xpath->registerNamespace('at', NAMESPACE_TOMB);
-		$xpath->registerNamespace('media', NAMESPACE_MEDIA);
-		$xpath->registerNamespace('dfrn', NAMESPACE_DFRN);
-		$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
-		$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
-		$xpath->registerNamespace('poco', NAMESPACE_POCO);
-		$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
-		$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
+		$xpath->registerNamespace("atom", NAMESPACE_ATOM1);
+		$xpath->registerNamespace("thr", NAMESPACE_THREAD);
+		$xpath->registerNamespace("at", NAMESPACE_TOMB);
+		$xpath->registerNamespace("media", NAMESPACE_MEDIA);
+		$xpath->registerNamespace("dfrn", NAMESPACE_DFRN);
+		$xpath->registerNamespace("activity", NAMESPACE_ACTIVITY);
+		$xpath->registerNamespace("georss", NAMESPACE_GEORSS);
+		$xpath->registerNamespace("poco", NAMESPACE_POCO);
+		$xpath->registerNamespace("ostatus", NAMESPACE_OSTATUS);
+		$xpath->registerNamespace("statusnet", NAMESPACE_STATUSNET);
 
+		/// @todo Do we need this?
 		if (!$contact) {
 			$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `self`", intval($importer["uid"]));
 			$contact = $r[0];
@@ -1179,7 +1125,7 @@ class dfrn2 {
 		//}
 
 		// is it a public forum? Private forums aren't supported by now with this method
-		$forum = intval($xpath->evaluate('/atom:feed/dfrn:community/text()', $context)->item(0)->nodeValue);
+		$forum = intval($xpath->evaluate("/atom:feed/dfrn:community/text()", $context)->item(0)->nodeValue);
 
 		if ($forum AND ($dfrn_owner["contact-id"] != 0))
 			q("UPDATE `contact` SET `forum` = %d WHERE `forum` != %d AND `id` = %d",
@@ -1187,23 +1133,23 @@ class dfrn2 {
 				intval($dfrn_owner["contact-id"])
 			);
 
-		$mails = $xpath->query('/atom:feed/dfrn:mail');
+		$mails = $xpath->query("/atom:feed/dfrn:mail");
 		foreach ($mails AS $mail)
 			self::process_mail($xpath, $mail, $importer);
 
-		$suggestions = $xpath->query('/atom:feed/dfrn:suggest');
+		$suggestions = $xpath->query("/atom:feed/dfrn:suggest");
 		foreach ($suggestions AS $suggestion)
 			self::process_suggestion($xpath, $suggestion, $importer);
 
-		$relocations = $xpath->query('/atom:feed/dfrn:relocate');
+		$relocations = $xpath->query("/atom:feed/dfrn:relocate");
 		foreach ($relocations AS $relocation)
 			self::process_relocation($xpath, $relocation, $importer);
 
-		$deletions = $xpath->query('/atom:feed/at:deleted-entry');
+		$deletions = $xpath->query("/atom:feed/at:deleted-entry");
 		foreach ($deletions AS $deletion)
 			self::process_deletion($header, $xpath, $deletion, $importer, $dfrn_owner["contact-id"]);
 
-		$entries = $xpath->query('/atom:feed/atom:entry');
+		$entries = $xpath->query("/atom:feed/atom:entry");
 		foreach ($entries AS $entry)
 			self::process_entry($header, $xpath, $entry, $importer, $contact);
 	}

From 24d471620404e56105671b00f32738881e5af24b Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Tue, 2 Feb 2016 15:56:06 +0100
Subject: [PATCH 014/273] perfect-scrollbar: update to 0.6.10

---
 js/main.js                                    |   5 +-
 .../perfect-scrollbar/perfect-scrollbar.css   |  51 ++++----
 .../perfect-scrollbar.jquery.js               | 109 ++++++------------
 .../perfect-scrollbar.min.css                 |   4 +-
 4 files changed, 65 insertions(+), 104 deletions(-)

diff --git a/js/main.js b/js/main.js
index d1fd3765fb..bba5e92969 100644
--- a/js/main.js
+++ b/js/main.js
@@ -170,9 +170,8 @@
 		var notifications_mark = unescape($('<div>').append( $("#nav-notifications-mark-all").clone() ).html()); //outerHtml hack
 		var notifications_empty = unescape($("#nav-notifications-menu").html());
 
-		/* enable perfect-scrollbars for nav-notivications-menu */
-		$('#nav-notifications-menu').perfectScrollbar();
-		$('aside').perfectScrollbar();
+		/* enable perfect-scrollbars for different elements */
+		$('#nav-notifications-menu, aside').perfectScrollbar();
 
 		/* nav update event  */
 		$('nav').bind('nav-update', function(e,data){
diff --git a/library/perfect-scrollbar/perfect-scrollbar.css b/library/perfect-scrollbar/perfect-scrollbar.css
index 32cf99b0a3..354705dd57 100644
--- a/library/perfect-scrollbar/perfect-scrollbar.css
+++ b/library/perfect-scrollbar/perfect-scrollbar.css
@@ -1,10 +1,19 @@
-/* perfect-scrollbar v0.6.8 */
+/* perfect-scrollbar v0.6.10 */
 .ps-container {
   -ms-touch-action: none;
-  overflow: hidden !important; }
+  touch-action: none;
+  overflow: hidden !important;
+  -ms-overflow-style: none; }
+  @supports (-ms-overflow-style: none) {
+    .ps-container {
+      overflow: auto !important; } }
+  @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
+    .ps-container {
+      overflow: auto !important; } }
   .ps-container.ps-active-x > .ps-scrollbar-x-rail,
   .ps-container.ps-active-y > .ps-scrollbar-y-rail {
-    display: block; }
+    display: block;
+    background-color: transparent; }
   .ps-container.ps-in-scrolling {
     pointer-events: none; }
     .ps-container.ps-in-scrolling.ps-x > .ps-scrollbar-x-rail {
@@ -23,13 +32,12 @@
     /* please don't change 'position' */
     -webkit-border-radius: 4px;
     -moz-border-radius: 4px;
-    -ms-border-radius: 4px;
     border-radius: 4px;
     opacity: 0;
-    -webkit-transition: background-color 0.2s linear, opacity 0.2s linear;
-    -moz-transition: background-color 0.2s linear, opacity 0.2s linear;
-    -o-transition: background-color 0.2s linear, opacity 0.2s linear;
-    transition: background-color 0.2s linear, opacity 0.2s linear;
+    -webkit-transition: background-color .2s linear, opacity .2s linear;
+    -moz-transition: background-color .2s linear, opacity .2s linear;
+    -o-transition: background-color .2s linear, opacity .2s linear;
+    transition: background-color .2s linear, opacity .2s linear;
     bottom: 3px;
     /* there must be 'bottom' for ps-scrollbar-x-rail */
     height: 8px; }
@@ -39,12 +47,11 @@
       background-color: #aaa;
       -webkit-border-radius: 4px;
       -moz-border-radius: 4px;
-      -ms-border-radius: 4px;
       border-radius: 4px;
-      -webkit-transition: background-color 0.2s linear;
-      -moz-transition: background-color 0.2s linear;
-      -o-transition: background-color 0.2s linear;
-      transition: background-color 0.2s linear;
+      -webkit-transition: background-color .2s linear;
+      -moz-transition: background-color .2s linear;
+      -o-transition: background-color .2s linear;
+      transition: background-color .2s linear;
       bottom: 0;
       /* there must be 'bottom' for ps-scrollbar-x */
       height: 8px; }
@@ -54,13 +61,12 @@
     /* please don't change 'position' */
     -webkit-border-radius: 4px;
     -moz-border-radius: 4px;
-    -ms-border-radius: 4px;
     border-radius: 4px;
     opacity: 0;
-    -webkit-transition: background-color 0.2s linear, opacity 0.2s linear;
-    -moz-transition: background-color 0.2s linear, opacity 0.2s linear;
-    -o-transition: background-color 0.2s linear, opacity 0.2s linear;
-    transition: background-color 0.2s linear, opacity 0.2s linear;
+    -webkit-transition: background-color .2s linear, opacity .2s linear;
+    -moz-transition: background-color .2s linear, opacity .2s linear;
+    -o-transition: background-color .2s linear, opacity .2s linear;
+    transition: background-color .2s linear, opacity .2s linear;
     right: 3px;
     /* there must be 'right' for ps-scrollbar-y-rail */
     width: 8px; }
@@ -70,12 +76,11 @@
       background-color: #aaa;
       -webkit-border-radius: 4px;
       -moz-border-radius: 4px;
-      -ms-border-radius: 4px;
       border-radius: 4px;
-      -webkit-transition: background-color 0.2s linear;
-      -moz-transition: background-color 0.2s linear;
-      -o-transition: background-color 0.2s linear;
-      transition: background-color 0.2s linear;
+      -webkit-transition: background-color .2s linear;
+      -moz-transition: background-color .2s linear;
+      -o-transition: background-color .2s linear;
+      transition: background-color .2s linear;
       right: 0;
       /* there must be 'right' for ps-scrollbar-y */
       width: 8px; }
diff --git a/library/perfect-scrollbar/perfect-scrollbar.jquery.js b/library/perfect-scrollbar/perfect-scrollbar.jquery.js
index 2bc3b2f939..d94ed91bcd 100644
--- a/library/perfect-scrollbar/perfect-scrollbar.jquery.js
+++ b/library/perfect-scrollbar/perfect-scrollbar.jquery.js
@@ -1,10 +1,12 @@
-/* perfect-scrollbar v0.6.8 */
-(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
+/* perfect-scrollbar v0.6.10
+ * 
+ * Copyright (c) 2015 Hyunje Alex Jun and other contributors
  * Licensed under the MIT License
  * 
  * Source: https://github.com/noraesae/perfect-scrollbar
  */
+
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
 'use strict';
 
 var ps = require('../main')
@@ -50,9 +52,6 @@ if (typeof define === 'function' && define.amd) {
 module.exports = mountJQuery;
 
 },{"../main":7,"../plugin/instances":18}],2:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 function oldAdd(element, className) {
@@ -97,9 +96,6 @@ exports.list = function (element) {
 };
 
 },{}],3:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var DOM = {};
@@ -186,9 +182,6 @@ DOM.queryChildren = function (element, selector) {
 module.exports = DOM;
 
 },{}],4:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var EventElement = function (element) {
@@ -262,9 +255,6 @@ EventManager.prototype.once = function (element, eventName, handler) {
 module.exports = EventManager;
 
 },{}],5:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 module.exports = (function () {
@@ -280,9 +270,6 @@ module.exports = (function () {
 })();
 
 },{}],6:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var cls = require('./class')
@@ -366,9 +353,6 @@ exports.env = {
 };
 
 },{"./class":2,"./dom":3}],7:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var destroy = require('./plugin/destroy')
@@ -382,9 +366,6 @@ module.exports = {
 };
 
 },{"./plugin/destroy":9,"./plugin/initialize":17,"./plugin/update":21}],8:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 module.exports = {
@@ -400,13 +381,11 @@ module.exports = {
   useKeyboard: true,
   useSelectionScroll: false,
   wheelPropagation: false,
-  wheelSpeed: 1
+  wheelSpeed: 1,
+  theme: 'default'
 };
 
 },{}],9:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var d = require('../lib/dom')
@@ -431,9 +410,6 @@ module.exports = function (element) {
 };
 
 },{"../lib/dom":3,"../lib/helper":6,"./instances":18}],10:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var h = require('../../lib/helper')
@@ -496,9 +472,6 @@ module.exports = function (element) {
 };
 
 },{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],11:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var d = require('../../lib/dom')
@@ -604,12 +577,10 @@ module.exports = function (element) {
 };
 
 },{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],12:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var h = require('../../lib/helper')
+  , d = require('../../lib/dom')
   , instances = require('../instances')
   , updateGeometry = require('../update-geometry')
   , updateScroll = require('../update-scroll');
@@ -652,7 +623,10 @@ function bindKeyboardHandler(element, i) {
       return;
     }
 
-    if (!hovered) {
+    var focused = d.matches(i.scrollbarX, ':focus') ||
+                  d.matches(i.scrollbarY, ':focus');
+
+    if (!hovered && !focused) {
       return;
     }
 
@@ -730,10 +704,7 @@ module.exports = function (element) {
   bindKeyboardHandler(element, i);
 };
 
-},{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],13:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
+},{"../../lib/dom":3,"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],13:[function(require,module,exports){
 'use strict';
 
 var instances = require('../instances')
@@ -870,9 +841,6 @@ module.exports = function (element) {
 };
 
 },{"../instances":18,"../update-geometry":19,"../update-scroll":20}],14:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var instances = require('../instances')
@@ -890,9 +858,6 @@ module.exports = function (element) {
 };
 
 },{"../instances":18,"../update-geometry":19}],15:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var h = require('../../lib/helper')
@@ -1004,9 +969,6 @@ module.exports = function (element) {
 };
 
 },{"../../lib/helper":6,"../instances":18,"../update-geometry":19,"../update-scroll":20}],16:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var instances = require('../instances')
@@ -1177,9 +1139,6 @@ module.exports = function (element, supportsTouch, supportsIePointer) {
 };
 
 },{"../instances":18,"../update-geometry":19,"../update-scroll":20}],17:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var cls = require('../lib/class')
@@ -1205,6 +1164,7 @@ module.exports = function (element, userSettings) {
   var i = instances.add(element);
 
   i.settings = h.extend(i.settings, userSettings);
+  cls.add(element, 'ps-theme-' + i.settings.theme);
 
   clickRailHandler(element);
   dragScrollbarHandler(element);
@@ -1226,12 +1186,10 @@ module.exports = function (element, userSettings) {
 };
 
 },{"../lib/class":2,"../lib/helper":6,"./handler/click-rail":10,"./handler/drag-scrollbar":11,"./handler/keyboard":12,"./handler/mouse-wheel":13,"./handler/native-scroll":14,"./handler/selection":15,"./handler/touch":16,"./instances":18,"./update-geometry":19}],18:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
-var d = require('../lib/dom')
+var cls = require('../lib/class')
+  , d = require('../lib/dom')
   , defaultSettings = require('./default-setting')
   , EventManager = require('../lib/event-manager')
   , guid = require('../lib/guid')
@@ -1261,9 +1219,19 @@ function Instance(element) {
   i.event = new EventManager();
   i.ownerDocument = element.ownerDocument || document;
 
+  function focus() {
+    cls.add(element, 'ps-focus');
+  }
+
+  function blur() {
+    cls.remove(element, 'ps-focus');
+  }
+
   i.scrollbarXRail = d.appendTo(d.e('div', 'ps-scrollbar-x-rail'), element);
   i.scrollbarX = d.appendTo(d.e('div', 'ps-scrollbar-x'), i.scrollbarXRail);
   i.scrollbarX.setAttribute('tabindex', 0);
+  i.event.bind(i.scrollbarX, 'focus', focus);
+  i.event.bind(i.scrollbarX, 'blur', blur);
   i.scrollbarXActive = null;
   i.scrollbarXWidth = null;
   i.scrollbarXLeft = null;
@@ -1281,6 +1249,8 @@ function Instance(element) {
   i.scrollbarYRail = d.appendTo(d.e('div', 'ps-scrollbar-y-rail'), element);
   i.scrollbarY = d.appendTo(d.e('div', 'ps-scrollbar-y'), i.scrollbarYRail);
   i.scrollbarY.setAttribute('tabindex', 0);
+  i.event.bind(i.scrollbarY, 'focus', focus);
+  i.event.bind(i.scrollbarY, 'blur', blur);
   i.scrollbarYActive = null;
   i.scrollbarYHeight = null;
   i.scrollbarYTop = null;
@@ -1336,10 +1306,7 @@ exports.get = function (element) {
   return instances[getId(element)];
 };
 
-},{"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
+},{"../lib/class":2,"../lib/dom":3,"../lib/event-manager":4,"../lib/guid":5,"../lib/helper":6,"./default-setting":8}],19:[function(require,module,exports){
 'use strict';
 
 var cls = require('../lib/class')
@@ -1468,9 +1435,6 @@ module.exports = function (element) {
 };
 
 },{"../lib/class":2,"../lib/dom":3,"../lib/helper":6,"./instances":18,"./update-scroll":20}],20:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var instances = require('./instances');
@@ -1513,29 +1477,25 @@ module.exports = function (element, axis, value) {
   }
 
   if (axis === 'top' && value <= 0) {
-    element.scrollTop = 0;
+    element.scrollTop = value = 0; // don't allow negative scroll
     element.dispatchEvent(yStartEvent);
-    return; // don't allow negative scroll
   }
 
   if (axis === 'left' && value <= 0) {
-    element.scrollLeft = 0;
+    element.scrollLeft = value = 0; // don't allow negative scroll
     element.dispatchEvent(xStartEvent);
-    return; // don't allow negative scroll
   }
 
   var i = instances.get(element);
 
   if (axis === 'top' && value >= i.contentHeight - i.containerHeight) {
-    element.scrollTop = i.contentHeight - i.containerHeight;
+    element.scrollTop = value = i.contentHeight - i.containerHeight; // don't allow scroll past container
     element.dispatchEvent(yEndEvent);
-    return; // don't allow scroll past container
   }
 
   if (axis === 'left' && value >= i.contentWidth - i.containerWidth) {
-    element.scrollLeft = i.contentWidth - i.containerWidth;
+    element.scrollLeft = value = i.contentWidth - i.containerWidth; // don't allow scroll past container
     element.dispatchEvent(xEndEvent);
-    return; // don't allow scroll past container
   }
 
   if (!lastTop) {
@@ -1575,9 +1535,6 @@ module.exports = function (element, axis, value) {
 };
 
 },{"./instances":18}],21:[function(require,module,exports){
-/* Copyright (c) 2015 Hyunje Alex Jun and other contributors
- * Licensed under the MIT License
- */
 'use strict';
 
 var d = require('../lib/dom')
diff --git a/library/perfect-scrollbar/perfect-scrollbar.min.css b/library/perfect-scrollbar/perfect-scrollbar.min.css
index 288671cfcc..e8d2f37d9c 100644
--- a/library/perfect-scrollbar/perfect-scrollbar.min.css
+++ b/library/perfect-scrollbar/perfect-scrollbar.min.css
@@ -1,2 +1,2 @@
-/* perfect-scrollbar v0.6.8 */
-.ps-container{-ms-touch-action:none;overflow:hidden !important}.ps-container.ps-active-x>.ps-scrollbar-x-rail,.ps-container.ps-active-y>.ps-scrollbar-y-rail{display:block}.ps-container.ps-in-scrolling{pointer-events:none}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:0.9}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:0.9}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999}.ps-container>.ps-scrollbar-x-rail{display:none;position:absolute;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;border-radius:4px;opacity:0;-webkit-transition:background-color 0.2s linear,opacity 0.2s linear;-moz-transition:background-color 0.2s linear,opacity 0.2s linear;-o-transition:background-color 0.2s linear,opacity 0.2s linear;transition:background-color 0.2s linear,opacity 0.2s linear;bottom:3px;height:8px}.ps-container>.ps-scrollbar-x-rail>.ps-scrollbar-x{position:absolute;background-color:#aaa;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;border-radius:4px;-webkit-transition:background-color 0.2s linear;-moz-transition:background-color 0.2s linear;-o-transition:background-color 0.2s linear;transition:background-color 0.2s linear;bottom:0;height:8px}.ps-container>.ps-scrollbar-y-rail{display:none;position:absolute;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;border-radius:4px;opacity:0;-webkit-transition:background-color 0.2s linear,opacity 0.2s linear;-moz-transition:background-color 0.2s linear,opacity 0.2s linear;-o-transition:background-color 0.2s linear,opacity 0.2s linear;transition:background-color 0.2s linear,opacity 0.2s linear;right:3px;width:8px}.ps-container>.ps-scrollbar-y-rail>.ps-scrollbar-y{position:absolute;background-color:#aaa;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;border-radius:4px;-webkit-transition:background-color 0.2s linear;-moz-transition:background-color 0.2s linear;-o-transition:background-color 0.2s linear;transition:background-color 0.2s linear;right:0;width:8px}.ps-container:hover.ps-in-scrolling{pointer-events:none}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:0.9}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:0.9}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999}.ps-container:hover>.ps-scrollbar-x-rail,.ps-container:hover>.ps-scrollbar-y-rail{opacity:0.6}.ps-container:hover>.ps-scrollbar-x-rail:hover{background-color:#eee;opacity:0.9}.ps-container:hover>.ps-scrollbar-x-rail:hover>.ps-scrollbar-x{background-color:#999}.ps-container:hover>.ps-scrollbar-y-rail:hover{background-color:#eee;opacity:0.9}.ps-container:hover>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y{background-color:#999}
+/* perfect-scrollbar v0.6.10 */
+.ps-container{-ms-touch-action:none;touch-action:none;overflow:hidden !important;-ms-overflow-style:none}@supports (-ms-overflow-style: none){.ps-container{overflow:auto !important}}@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none){.ps-container{overflow:auto !important}}.ps-container.ps-active-x>.ps-scrollbar-x-rail,.ps-container.ps-active-y>.ps-scrollbar-y-rail{display:block;background-color:transparent}.ps-container.ps-in-scrolling{pointer-events:none}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:0.9}.ps-container.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:0.9}.ps-container.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999}.ps-container>.ps-scrollbar-x-rail{display:none;position:absolute;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;opacity:0;-webkit-transition:background-color .2s linear, opacity .2s linear;-moz-transition:background-color .2s linear, opacity .2s linear;-o-transition:background-color .2s linear, opacity .2s linear;transition:background-color .2s linear, opacity .2s linear;bottom:3px;height:8px}.ps-container>.ps-scrollbar-x-rail>.ps-scrollbar-x{position:absolute;background-color:#aaa;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-transition:background-color .2s linear;-moz-transition:background-color .2s linear;-o-transition:background-color .2s linear;transition:background-color .2s linear;bottom:0;height:8px}.ps-container>.ps-scrollbar-y-rail{display:none;position:absolute;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;opacity:0;-webkit-transition:background-color .2s linear, opacity .2s linear;-moz-transition:background-color .2s linear, opacity .2s linear;-o-transition:background-color .2s linear, opacity .2s linear;transition:background-color .2s linear, opacity .2s linear;right:3px;width:8px}.ps-container>.ps-scrollbar-y-rail>.ps-scrollbar-y{position:absolute;background-color:#aaa;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-transition:background-color .2s linear;-moz-transition:background-color .2s linear;-o-transition:background-color .2s linear;transition:background-color .2s linear;right:0;width:8px}.ps-container:hover.ps-in-scrolling{pointer-events:none}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail{background-color:#eee;opacity:0.9}.ps-container:hover.ps-in-scrolling.ps-x>.ps-scrollbar-x-rail>.ps-scrollbar-x{background-color:#999}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail{background-color:#eee;opacity:0.9}.ps-container:hover.ps-in-scrolling.ps-y>.ps-scrollbar-y-rail>.ps-scrollbar-y{background-color:#999}.ps-container:hover>.ps-scrollbar-x-rail,.ps-container:hover>.ps-scrollbar-y-rail{opacity:0.6}.ps-container:hover>.ps-scrollbar-x-rail:hover{background-color:#eee;opacity:0.9}.ps-container:hover>.ps-scrollbar-x-rail:hover>.ps-scrollbar-x{background-color:#999}.ps-container:hover>.ps-scrollbar-y-rail:hover{background-color:#eee;opacity:0.9}.ps-container:hover>.ps-scrollbar-y-rail:hover>.ps-scrollbar-y{background-color:#999}

From f604f13d7da004b52c5858091aeecc678ee54082 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 2 Feb 2016 20:57:19 +0100
Subject: [PATCH 015/273] New method to create a guid if none was given

---
 include/items.php | 43 ++++++++++++++++---------------------------
 1 file changed, 16 insertions(+), 27 deletions(-)

diff --git a/include/items.php b/include/items.php
index 21a0c414dc..ff5d919c9e 100644
--- a/include/items.php
+++ b/include/items.php
@@ -773,6 +773,18 @@ function item_add_language_opt(&$arr) {
 	}
 }
 
+function uri_to_guid($uri) {
+	$parsed = parse_url($uri);
+	$guid_prefix = hash("crc32", $parsed["host"]);
+
+	unset($parsed["scheme"]);
+
+	$host_id = implode("/", $parsed);
+	$host_hash = hash("ripemd128", $host_id);
+
+	return $guid_prefix.$host_hash;
+}
+
 function item_store($arr,$force_parent = false, $notify = false, $dontcache = false) {
 
 	// If it is a posting where users should get notifications, then define it as wall posting
@@ -848,33 +860,6 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
 		}
 	}
 
-	// If there is no guid then take the same guid that was taken before for the same uri
-	if ((trim($arr['guid']) == "") AND (trim($arr['uri']) != "") AND (trim($arr['network']) != "")) {
-		logger('item_store: checking for an existing guid for uri '.$arr['uri'], LOGGER_DEBUG);
-		$r = q("SELECT `guid` FROM `guid` WHERE `uri` = '%s' AND `network` = '%s' LIMIT 1",
-			dbesc(trim($arr['uri'])), dbesc(trim($arr['network'])));
-
-		if(count($r)) {
-			$arr['guid'] = $r[0]["guid"];
-			logger('item_store: found guid '.$arr['guid'].' for uri '.$arr['uri'], LOGGER_DEBUG);
-		}
-	}
-
-	// If there is no guid then take the same guid that was taken before for the same plink
-	if ((trim($arr['guid']) == "") AND (trim($arr['plink']) != "") AND (trim($arr['network']) != "")) {
-		logger('item_store: checking for an existing guid for plink '.$arr['plink'], LOGGER_DEBUG);
-		$r = q("SELECT `guid`, `uri` FROM `guid` WHERE `plink` = '%s' AND `network` = '%s' LIMIT 1",
-			dbesc(trim($arr['plink'])), dbesc(trim($arr['network'])));
-
-		if(count($r)) {
-			$arr['guid'] = $r[0]["guid"];
-			logger('item_store: found guid '.$arr['guid'].' for plink '.$arr['plink'], LOGGER_DEBUG);
-
-			if ($r[0]["uri"] != $arr['uri'])
-			logger('Different uri for same guid: '.$arr['uri'].' and '.$r[0]["uri"].' - this shouldnt happen!', LOGGER_DEBUG);
-		}
-	}
-
 	// Shouldn't happen but we want to make absolutely sure it doesn't leak from a plugin.
 	// Deactivated, since the bbcode parser can handle with it - and it destroys posts with some smileys that contain "<"
 	//if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false))
@@ -884,6 +869,10 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
 
 	if ($notify)
 		$guid_prefix = "";
+	elseif ((trim($arr['guid']) == "") AND (trim($arr['plink']) != ""))
+		$arr['guid'] = uri_to_guid($arr['plink']);
+	elseif ((trim($arr['guid']) == "") AND (trim($arr['uri']) != ""))
+		$arr['guid'] = uri_to_guid($arr['uri']);
 	else {
 		$parsed = parse_url($arr["author-link"]);
 		$guid_prefix = hash("crc32", $parsed["host"]);

From 58c1f9a60f951b5dad39f33cce5fd7d5e2538ef6 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Wed, 3 Feb 2016 03:59:42 +0100
Subject: [PATCH 016/273] vier: use object-fit: cover for recent photos view

---
 view/theme/vier/style.css | 42 ++++++++++++++++++++++-----------------
 1 file changed, 24 insertions(+), 18 deletions(-)

diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css
index 16685e55ef..e0abee837c 100644
--- a/view/theme/vier/style.css
+++ b/view/theme/vier/style.css
@@ -2947,35 +2947,41 @@ a.mail-list-link {
   color: #999999;
 }
 
+/* photo album page */
 .photo-top-image-wrapper {
-        position: relative;
-        float: left;
-        margin-top: 15px;
-        margin-right: 15px;
-        width: 200px; height: 200px;
-        overflow: hidden;
+  position: relative;
+  float: left;
+  margin-top: 15px;
+  margin-right: 15px;
+  width: 200px; height: 200px;
+  overflow: hidden;
 }
 .photo-top-album-name {
-        width: 100%;
-        min-height: 2em;
-        position: absolute;
-        bottom: 0px;
-        padding: 0px 3px;
-        padding-top: 0.5em;
-        background-color: rgb(255, 255, 255);
+  width: 100%;
+  min-height: 2em;
+  position: absolute;
+  bottom: 0px;
+  padding: 0px 3px;
+  padding-top: 0.5em;
+  background-color: rgb(255, 255, 255);
 }
 #photo-top-end {
-        clear: both;
+  clear: both;
 }
 
 #photo-top-links {
-        margin-bottom: 30px;
-        margin-left: 30px;
+  margin-bottom: 30px;
+  margin-left: 30px;
 }
 
 #photos-upload-newalbum-div {
-        float: left;
-        width: 175px;
+  float: left;
+  width: 175px;
+}
+img.photo-top-photo {
+  width: 100%;
+  height: 100%;
+  object-fit: cover;
 }
 
 .menu-profile-list{

From 47d2e3b1424bdbc903a84ea94b9d3c7dfe4b5c9f Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 3 Feb 2016 05:00:26 +0100
Subject: [PATCH 017/273] Added some documentation

---
 include/items.php | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/items.php b/include/items.php
index ff5d919c9e..c149660fac 100644
--- a/include/items.php
+++ b/include/items.php
@@ -773,13 +773,25 @@ function item_add_language_opt(&$arr) {
 	}
 }
 
+/**
+ * @brief Creates an unique guid out of a given uri
+ *
+ * @param string $uri uri of an item entry
+ * @return string unique guid
+ */
 function uri_to_guid($uri) {
+
+	// Our regular guid routine is using this kind of prefix as well
+	// We have to avoid that different routines could accidentally create the same value
 	$parsed = parse_url($uri);
 	$guid_prefix = hash("crc32", $parsed["host"]);
 
+	// Remove the scheme to make sure that "https" and "http" doesn't make a difference
 	unset($parsed["scheme"]);
 
 	$host_id = implode("/", $parsed);
+
+	// We could use any hash algorithm since it isn't a security issue
 	$host_hash = hash("ripemd128", $host_id);
 
 	return $guid_prefix.$host_hash;

From 9fcd74f470f596fb85727af561d86404b59dfc93 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Wed, 3 Feb 2016 14:01:37 +0100
Subject: [PATCH 018/273] Pass App class instace to all templates via "$APP"
 variable

---
 include/friendica_smarty.php | 2 ++
 include/text.php             | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/friendica_smarty.php b/include/friendica_smarty.php
index 99dc12bf8d..9ba2d2a744 100644
--- a/include/friendica_smarty.php
+++ b/include/friendica_smarty.php
@@ -60,6 +60,8 @@ class FriendicaSmartyEngine implements ITemplateEngine {
 			$template = $s;
 			$s = new FriendicaSmarty();
 		}
+		
+		$r['$APP'] = get_app();
 
 		// "middleware": inject variables into templates
 		$arr = array(
diff --git a/include/text.php b/include/text.php
index 4f3af5aee8..c7681a4d58 100644
--- a/include/text.php
+++ b/include/text.php
@@ -22,7 +22,7 @@ function replace_macros($s,$r) {
 	$a = get_app();
 
 	// pass $baseurl to all templates
-	$r['$baseurl'] = z_root();
+	$r['$baseurl'] = $a->get_baseurl();
 
 
 	$t = $a->template_engine();

From 3c6ebfa5a9055c71502324aa4c4b93c3d5857cc1 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Wed, 3 Feb 2016 14:03:00 +0100
Subject: [PATCH 019/273] Vier - mobile friendly ACL window and form fields

---
 js/acl.js                       | 207 +++++++++++++++++---------------
 js/main.js                      |   2 +-
 view/templates/acl_selector.tpl |   3 +-
 view/templates/jot-header.tpl   |  21 ++--
 view/theme/vier/mobile.css      |  74 ++++++++++++
 5 files changed, 197 insertions(+), 110 deletions(-)

diff --git a/js/acl.js b/js/acl.js
index 487ffafc77..8e4e06c83c 100644
--- a/js/acl.js
+++ b/js/acl.js
@@ -1,49 +1,56 @@
-function ACL(backend_url, preset, automention){
-	that = this;
+function ACL(backend_url, preset, automention, is_mobile){
 	
-	that.url = backend_url;
-	that.automention = automention;
+	this.url = backend_url;
+	this.automention = automention;
+	this.is_mobile = is_mobile;
 	
-	that.kp_timer = null;
+	
+	this.kp_timer = null;
 	
 	if (preset==undefined) preset = [];
-	that.allow_cid = (preset[0] || []);
-	that.allow_gid = (preset[1] || []);
-	that.deny_cid  = (preset[2] || []);
-	that.deny_gid  = (preset[3] || []);
-	that.group_uids = [];
-	that.nw = 4; //items per row. should be calulated from #acl-list.width
-	
-	that.list_content = $("#acl-list-content");
-	that.item_tpl = unescape($(".acl-list-item[rel=acl-template]").html());
-	that.showall = $("#acl-showall");
+	this.allow_cid = (preset[0] || []);
+	this.allow_gid = (preset[1] || []);
+	this.deny_cid  = (preset[2] || []);
+	this.deny_gid  = (preset[3] || []);
+	this.group_uids = [];
 
-	if (preset.length==0) that.showall.addClass("selected");
+	if (this.is_mobile) {
+		this.nw = 1;
+	} else {
+		this.nw = 4;
+	}
+	
+	
+	this.list_content = $("#acl-list-content");
+	this.item_tpl = unescape($(".acl-list-item[rel=acl-template]").html());
+	this.showall = $("#acl-showall");
+
+	if (preset.length==0) this.showall.addClass("selected");
 	
 	/*events*/
-	that.showall.click(that.on_showall);
-	$(document).on("click", ".acl-button-show", that.on_button_show);
-	$(document).on("click", ".acl-button-hide", that.on_button_hide);
-	$("#acl-search").keypress(that.on_search);
-	$("#acl-wrapper").parents("form").submit(that.on_submit);
+	this.showall.click(this.on_showall);
+	$(document).on("click", ".acl-button-show", this.on_button_show.bind(this));
+	$(document).on("click", ".acl-button-hide", this.on_button_hide.bind(this));
+	$("#acl-search").keypress(this.on_search.bind(this));
+	$("#acl-wrapper").parents("form").submit(this.on_submit.bind(this));
 	
 	/* add/remove mentions  */
-	that.element = $("#profile-jot-text");
-	that.htmlelm = that.element.get()[0];
+	this.element = $("#profile-jot-text");
+	this.htmlelm = this.element.get()[0];
 	
 	/* startup! */
-	that.get(0,100);
+	this.get(0,100);
 }
 
 ACL.prototype.remove_mention = function(id) {
-	if (!that.automention) return;
-	var nick = that.data[id].nick;
+	if (!this.automention) return;
+	var nick = this.data[id].nick;
 	var searchText = "@"+nick+"+"+id+" ";
 	if (tinyMCE.activeEditor===null) {
-		start = that.element.val().indexOf(searchText); 
+		start = this.element.val().indexOf(searchText); 
 		if ( start<0) return;
 		end = start+searchText.length;
-		that.element.setSelection(start,end).replaceSelectedText('').collapseSelection(false);
+		this.element.setSelection(start,end).replaceSelectedText('').collapseSelection(false);
 	} else {
 		start =  tinyMCE.activeEditor.getContent({format : 'raw'}).search( searchText );
 		if ( start<0 ) return;
@@ -54,12 +61,12 @@ ACL.prototype.remove_mention = function(id) {
 }
 
 ACL.prototype.add_mention = function(id) {
-	if (!that.automention) return;
-	var nick = that.data[id].nick;
+	if (!this.automention) return;
+	var nick = this.data[id].nick;
 	var searchText =  "@"+nick+"+"+id+" ";
 	if (tinyMCE.activeEditor===null) {
-		if ( that.element.val().indexOf( searchText) >= 0 ) return;
-		that.element.val( searchText + that.element.val() );
+		if ( this.element.val().indexOf( searchText) >= 0 ) return;
+		this.element.val( searchText + this.element.val() );
 	} else {
 		if ( tinyMCE.activeEditor.getContent({format : 'raw'}).search(searchText) >= 0 ) return;
 		tinyMCE.activeEditor.dom.add(tinyMCE.activeEditor.getBody(), 'dummy', {}, searchText);
@@ -68,46 +75,46 @@ ACL.prototype.add_mention = function(id) {
 
 ACL.prototype.on_submit = function(){
 	aclfileds = $("#acl-fields").html("");
-	$(that.allow_gid).each(function(i,v){
+	$(this.allow_gid).each(function(i,v){
 		aclfileds.append("<input type='hidden' name='group_allow[]' value='"+v+"'>");
 	});
-	$(that.allow_cid).each(function(i,v){
+	$(this.allow_cid).each(function(i,v){
 		aclfileds.append("<input type='hidden' name='contact_allow[]' value='"+v+"'>");
 	});
-	$(that.deny_gid).each(function(i,v){
+	$(this.deny_gid).each(function(i,v){
 		aclfileds.append("<input type='hidden' name='group_deny[]' value='"+v+"'>");
 	});
-	$(that.deny_cid).each(function(i,v){
+	$(this.deny_cid).each(function(i,v){
 		aclfileds.append("<input type='hidden' name='contact_deny[]' value='"+v+"'>");
 	});	
 }
 
 ACL.prototype.search = function(){
 	var srcstr = $("#acl-search").val();
-	that.list_content.html("");
-	that.get(0,100, srcstr);
+	this.list_content.html("");
+	this.get(0,100, srcstr);
 }
 
 ACL.prototype.on_search = function(event){
-	if (that.kp_timer) clearTimeout(that.kp_timer);
-	that.kp_timer = setTimeout( that.search, 1000);
+	if (this.kp_timer) clearTimeout(this.kp_timer);
+	this.kp_timer = setTimeout( this.search.bind(this), 1000);
 }
 
 ACL.prototype.on_showall = function(event){
 	event.preventDefault()
 	event.stopPropagation();
 	
-	if (that.showall.hasClass("selected")){
+	if (this.showall.hasClass("selected")){
 		return false;
 	}
-	that.showall.addClass("selected");
+	this.showall.addClass("selected");
 	
-	that.allow_cid = [];
-	that.allow_gid = [];
-	that.deny_cid  = [];
-	that.deny_gid  = [];
+	this.allow_cid = [];
+	this.allow_gid = [];
+	this.deny_cid  = [];
+	this.deny_gid  = [];
 	
-	that.update_view();
+	this.update_view();
 	
 	return false;
 }
@@ -117,11 +124,11 @@ ACL.prototype.on_button_show = function(event){
 	event.stopImmediatePropagation()
 	event.stopPropagation();
 
-	/*that.showall.removeClass("selected");
+	/*this.showall.removeClass("selected");
 	$(this).siblings(".acl-button-hide").removeClass("selected");
 	$(this).toggleClass("selected");*/
 
-	that.set_allow($(this).parent().attr('id'));
+	this.set_allow($(this).parent().attr('id'));
 
 	return false;
 }
@@ -130,11 +137,11 @@ ACL.prototype.on_button_hide = function(event){
 	event.stopImmediatePropagation()
 	event.stopPropagation();
 
-	/*that.showall.removeClass("selected");
+	/*this.showall.removeClass("selected");
 	$(this).siblings(".acl-button-show").removeClass("selected");
 	$(this).toggleClass("selected");*/
 
-	that.set_deny($(this).parent().attr('id'));
+	this.set_deny($(this).parent().attr('id'));
 
 	return false;
 }
@@ -145,25 +152,25 @@ ACL.prototype.set_allow = function(itemid){
 	
 	switch(type){
 		case "g":
-			if (that.allow_gid.indexOf(id)<0){
-				that.allow_gid.push(id)
+			if (this.allow_gid.indexOf(id)<0){
+				this.allow_gid.push(id)
 			}else {
-				that.allow_gid.remove(id);
+				this.allow_gid.remove(id);
 			}
-			if (that.deny_gid.indexOf(id)>=0) that.deny_gid.remove(id);
+			if (this.deny_gid.indexOf(id)>=0) this.deny_gid.remove(id);
 			break;
 		case "c":
-			if (that.allow_cid.indexOf(id)<0){
-				that.allow_cid.push(id)
-				if (that.data[id].forum=="1") that.add_mention(id);
+			if (this.allow_cid.indexOf(id)<0){
+				this.allow_cid.push(id)
+				if (this.data[id].forum=="1") this.add_mention(id);
 			} else {
-				that.allow_cid.remove(id);
-				if (that.data[id].forum=="1") that.remove_mention(id);
+				this.allow_cid.remove(id);
+				if (this.data[id].forum=="1") this.remove_mention(id);
 			}
-			if (that.deny_cid.indexOf(id)>=0) that.deny_cid.remove(id);			
+			if (this.deny_cid.indexOf(id)>=0) this.deny_cid.remove(id);			
 			break;
 	}
-	that.update_view();
+	this.update_view();
 }
 
 ACL.prototype.set_deny = function(itemid){
@@ -172,34 +179,34 @@ ACL.prototype.set_deny = function(itemid){
 	
 	switch(type){
 		case "g":
-			if (that.deny_gid.indexOf(id)<0){
-				that.deny_gid.push(id)
+			if (this.deny_gid.indexOf(id)<0){
+				this.deny_gid.push(id)
 			} else {
-				that.deny_gid.remove(id);
+				this.deny_gid.remove(id);
 			}
-			if (that.allow_gid.indexOf(id)>=0) that.allow_gid.remove(id);
+			if (this.allow_gid.indexOf(id)>=0) this.allow_gid.remove(id);
 			break;
 		case "c":
-			if (that.data[id].forum=="1") that.remove_mention(id);
-			if (that.deny_cid.indexOf(id)<0){
-				that.deny_cid.push(id)
+			if (this.data[id].forum=="1") this.remove_mention(id);
+			if (this.deny_cid.indexOf(id)<0){
+				this.deny_cid.push(id)
 			} else {
-				that.deny_cid.remove(id);
+				this.deny_cid.remove(id);
 			}
-			if (that.allow_cid.indexOf(id)>=0) that.allow_cid.remove(id);
+			if (this.allow_cid.indexOf(id)>=0) this.allow_cid.remove(id);
 			break;
 	}
-	that.update_view();
+	this.update_view();
 }
 
 ACL.prototype.is_show_all = function() {
-	return (that.allow_gid.length==0 && that.allow_cid.length==0 &&
-		that.deny_gid.length==0 && that.deny_cid.length==0);
+	return (this.allow_gid.length==0 && this.allow_cid.length==0 &&
+		this.deny_gid.length==0 && this.deny_cid.length==0);
 }
 
 ACL.prototype.update_view = function(){
 	if (this.is_show_all()){
-			that.showall.addClass("selected");
+			this.showall.addClass("selected");
 			/* jot acl */
 				$('#jot-perms-icon').removeClass('lock').addClass('unlock');
 				$('#jot-public').show();
@@ -209,7 +216,7 @@ ACL.prototype.update_view = function(){
 				}
 			
 	} else {
-			that.showall.removeClass("selected");
+			this.showall.removeClass("selected");
 			/* jot acl */
 				$('#jot-perms-icon').removeClass('unlock').addClass('lock');
 				$('#jot-public').hide();
@@ -220,29 +227,29 @@ ACL.prototype.update_view = function(){
 		$(this).removeClass("groupshow grouphide");
 	});
 	
-	$("#acl-list-content .acl-list-item").each(function(){
-		itemid = $(this).attr('id');
+	$("#acl-list-content .acl-list-item").each(function(index, element){
+		itemid = $(element).attr('id');
 		type = itemid[0];
 		id 	 = parseInt(itemid.substr(1));
 		
-		btshow = $(this).children(".acl-button-show").removeClass("selected");
-		bthide = $(this).children(".acl-button-hide").removeClass("selected");	
+		btshow = $(element).children(".acl-button-show").removeClass("selected");
+		bthide = $(element).children(".acl-button-hide").removeClass("selected");	
 		
 		switch(type){
 			case "g":
 				var uclass = "";
-				if (that.allow_gid.indexOf(id)>=0){
+				if (this.allow_gid.indexOf(id)>=0){
 					btshow.addClass("selected");
 					bthide.removeClass("selected");
 					uclass="groupshow";
 				}
-				if (that.deny_gid.indexOf(id)>=0){
+				if (this.deny_gid.indexOf(id)>=0){
 					btshow.removeClass("selected");
 					bthide.addClass("selected");
 					uclass="grouphide";
 				}
 				
-				$(that.group_uids[id]).each(function(i,v) {
+				$(this.group_uids[id]).each(function(i,v) {
 					if(uclass == "grouphide")
 						$("#c"+v).removeClass("groupshow");
 					if(uclass != "") {
@@ -257,17 +264,17 @@ ACL.prototype.update_view = function(){
 				
 				break;
 			case "c":
-				if (that.allow_cid.indexOf(id)>=0){
+				if (this.allow_cid.indexOf(id)>=0){
 					btshow.addClass("selected");
 					bthide.removeClass("selected");
 				}
-				if (that.deny_cid.indexOf(id)>=0){
+				if (this.deny_cid.indexOf(id)>=0){
 					btshow.removeClass("selected");
 					bthide.addClass("selected");
 				}			
 		}
 		
-	});
+	}.bind(this));
 	
 }
 
@@ -281,30 +288,30 @@ ACL.prototype.get = function(start,count, search){
 	
 	$.ajax({
 		type:'POST',
-		url: that.url,
+		url: this.url,
 		data: postdata,
 		dataType: 'json',
-		success:that.populate
+		success:this.populate.bind(this)
 	});
 }
 
 ACL.prototype.populate = function(data){
-	var height = Math.ceil(data.tot / that.nw) * 42;
-	that.list_content.height(height);
-	that.data = {};
-	$(data.items).each(function(){
-		html = "<div class='acl-list-item {4} {5} type{2}' title='{6}' id='{2}{3}'>"+that.item_tpl+"</div>";
-		html = html.format(this.photo, this.name, this.type, this.id, (this.forum=='1'?'forum':''), this.network, this.link);
-		if (this.uids!=undefined) that.group_uids[this.id] = this.uids;
+	var height = Math.ceil(data.tot / this.nw) * 42;
+	this.list_content.height(height);
+	this.data = {};
+	$(data.items).each(function(index, item){
+		html = "<div class='acl-list-item {4} {5} type{2}' title='{6}' id='{2}{3}'>"+this.item_tpl+"</div>";
+		html = html.format(item.photo, item.name, item.type, item.id, (item.forum=='1'?'forum':''), item.network, item.link);
+		if (item.uids!=undefined) this.group_uids[item.id] = item.uids;
 		//console.log(html);
-		that.list_content.append(html);
-		that.data[this.id] = this;
-	});
-	$(".acl-list-item img[data-src]", that.list_content).each(function(i, el){
+		this.list_content.append(html);
+		this.data[item.id] = item;
+	}.bind(this));
+	$(".acl-list-item img[data-src]", this.list_content).each(function(i, el){
 		// Add src attribute for images with a data-src attribute
 		$(el).attr('src', $(el).data("src"));
 	});
 	
-	that.update_view();
+	this.update_view();
 }
 
diff --git a/js/main.js b/js/main.js
index bba5e92969..5a1affe3cb 100644
--- a/js/main.js
+++ b/js/main.js
@@ -9,7 +9,7 @@
 		if (h==ch) {
 			return;
 		}
-		console.log("_resizeIframe", obj, desth, ch);
+		//console.log("_resizeIframe", obj, desth, ch);
 		if (desth!=ch) {
 			setTimeout(_resizeIframe, 500, obj, ch);
 		} else {
diff --git a/view/templates/acl_selector.tpl b/view/templates/acl_selector.tpl
index bf9470b64e..bb76135067 100644
--- a/view/templates/acl_selector.tpl
+++ b/view/templates/acl_selector.tpl
@@ -29,7 +29,8 @@ $(document).ready(function() {
 		acl = new ACL(
 			baseurl+"/acl",
 			[ {{$allowcid}},{{$allowgid}},{{$denycid}},{{$denygid}} ],
-			{{$features.aclautomention}}
+			{{$features.aclautomention}},
+			{{$APP->is_mobile}}
 		);
 	}
 });
diff --git a/view/templates/jot-header.tpl b/view/templates/jot-header.tpl
index 647f261c45..b06f6032c3 100644
--- a/view/templates/jot-header.tpl
+++ b/view/templates/jot-header.tpl
@@ -8,16 +8,24 @@ var plaintext = '{{$editselect}}';
 
 function initEditor(cb){
 	if (editor==false){
+		var  colorbox_options = {
+			{{if $APP->is_mobile}}
+			'width' : '100%',
+			'height' : '100%',
+			{{/if}}
+			'inline' : true,
+			'transition' : 'elastic'
+		}
+		
+		
+		
 		$("#profile-jot-text-loading").show();
 		if(plaintext == 'none') {
 			$("#profile-jot-text-loading").hide();
 			$("#profile-jot-text").css({ 'height': 200, 'color': '#000' });
 			$("#profile-jot-text").contact_autocomplete(baseurl+"/acl");
 			editor = true;
-			$("a#jot-perms-icon").colorbox({
-				'inline' : true,
-				'transition' : 'elastic'
-			});
+			$("a#jot-perms-icon").colorbox(colorbox_options);
 			$(".jothidden").show();
 			if (typeof cb!="undefined") cb();
 			return;
@@ -107,10 +115,7 @@ function initEditor(cb){
 		});
 		editor = true;
 		// setup acl popup
-		$("a#jot-perms-icon").colorbox({
-			'inline' : true,
-			'transition' : 'elastic'
-		});
+		$("a#jot-perms-icon").colorbox(colorbox_options);
 	} else {
 		if (typeof cb!="undefined") cb();
 	}
diff --git a/view/theme/vier/mobile.css b/view/theme/vier/mobile.css
index f6ec2b8ccb..128fb469c6 100644
--- a/view/theme/vier/mobile.css
+++ b/view/theme/vier/mobile.css
@@ -161,3 +161,77 @@ aside.show {
 }
 .tabs.show::after { display: none; }
 .tabs.show .tab { display: block; }
+
+/* ACL window */
+#profile-jot-acl-wrapper, #profile-jot-acl-wrapper * { box-sizing: border-box; }
+#acl-wrapper { width: 100%; float: none; }
+#acl-search { width: 100%; float: none; padding-right: 0px; margin-bottom: 1em; }
+#acl-showall { width: 100%; height: 48px; margin-bottom: 1em; }
+.acl-list-item { width: auto; float: none; height: auto; overflow: hidden; position: relative;}
+.acl-list-item img { width: 48px; height: 48px; }
+.acl-list-item p { height: auto; font-size: inherit; }
+.acl-list-item a {
+  float: none;
+  position: absolute;
+  top: 5px;
+  right: 5px;
+  height: 48px;
+  padding: 10px 2px 2px 2px;
+  font-size: 12px;
+  width: 20%;
+  text-align: center;
+  background-position: center 5px;
+}
+.acl-list-item a.acl-button-hide { right: 25%; }
+/* flexbox for ACL window */
+#cboxLoadedContent,
+#cboxLoadedContent > div,
+#acl-wrapper {
+  display: -ms-Flexbox !important;
+  -ms-box-orient: vertival;
+
+  display: -webkit-flex !important;
+  display: -moz-flex !important;
+  display: -ms-flex !important;
+  display: flex !important;
+
+  -webkit-flex-flow: column;
+  -moz-flex-flow: column;
+  -ms-flex-flow: column;
+  flex-flow: column;
+  
+  -webkit-flex: 1 100%;
+  -moz-flex: 1 100%;
+  -ms-flex: 1 100%;
+  flex: 1 100%;
+}
+#acl-list {
+  -webkit-flex: 1 1 auto;
+  -moz-flex: 1 1 auto;
+  -ms-flex: 1 1 auto;
+  flex: 1 1 auto;  
+}
+
+/** input elements **/
+input,
+textarea,
+select {
+    font-size: 18px;
+    border: 1px solid #888;
+    padding: 0.2em;
+}
+input:focus,
+textarea:focus,
+select:focus {
+    box-shadow: 1px 1px 10px rgba(46, 151, 255, 0.62);
+}
+
+.field, .field > * {  box-sizing: border-box; }
+.field label { width: 100%; float: none; display: block; }
+.field input, .field textarea, .field select { max-width: 100%; width: 100%; }
+.field.yesno .onoff,
+.field.checkbox input { width: auto; float: right; }
+.field.yesno label,
+.field.checkbox label { width: 70%; float: left; }
+.field .field_help { margin: 0; }
+

From 1ddae21cff0a75e4801eac146435069edf96ae51 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Wed, 3 Feb 2016 14:48:46 +0100
Subject: [PATCH 020/273] Vier mobile: fix content width, events style, oembed

---
 view/theme/vier/mobile.css | 40 +++++++++++++++++++++++++++++++++-----
 view/theme/vier/style.css  |  4 +++-
 2 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/view/theme/vier/mobile.css b/view/theme/vier/mobile.css
index 128fb469c6..edba28e5af 100644
--- a/view/theme/vier/mobile.css
+++ b/view/theme/vier/mobile.css
@@ -8,11 +8,11 @@ aside, header, #nav-events-link, #search-box, #nav-admin-link, #activitiy-by-dat
 }
 
 section {
-  /* left: calc((100% - (784px)) / 2); */
+  box-sizing: border-box;
   left: 0px;
-  width: calc(100% - 20px);
+  width: 100%;
   max-width: 100%;
-  padding: 10px;
+  padding: 5px;
 }
 
 body, section, nav .nav-menu, div.pager, ul.tabs {
@@ -92,8 +92,8 @@ nav ul {
 .wall-item-container.thread_level_5,
 .wall-item-container.thread_level_6,
 .wall-item-container.thread_level_7 {
-  margin-left: 60px;
-  width: calc(100% - 70px);
+  margin-left: 0;
+  width: calc(100% - 10px);
 }
 
 .wall-item-container.thread_level_2 .wall-item-content,
@@ -105,6 +105,10 @@ nav ul {
   max-width: 100%;
 }
 
+.wall-item-container .wall-item-info { width: auto; }
+.contact-photo-wrapper { width: 55px; }
+.wwto { left: 0px; }
+
 /* aside in/out */
 .mobile-aside-toggle {
 	display: block !important;
@@ -235,3 +239,29 @@ select:focus {
 .field.checkbox label { width: 70%; float: left; }
 .field .field_help { margin: 0; }
 
+/** event **/
+.event-start, .event-end { width: auto; }
+.event-start .dtstart, .event-end .dtend { float: none; display: block; }
+
+/** oembed **/
+.embed_video {
+  float: none;
+  margin: 0px;
+  height: 120px;
+  width: 100%;
+  overflow: hidden;
+  display: block;
+}
+.embed_video > img {
+  display: block;
+  width: 100% !important;
+  height: auto !important;
+  max-width: 100% !important;
+}
+.embed_video > div {
+  background-image: none !important; background-color: transparent !important;
+  width: 100% !important; height: 110px !important;
+}
+
+.type-link > a { height: 120px; width: 100%; overflow: hidden; display: block; }
+.type-link > a > img { display: block; max-width: 100%!important; width: 100% !important; height: auto !important; }
\ No newline at end of file
diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css
index e0abee837c..cdbda71fda 100644
--- a/view/theme/vier/style.css
+++ b/view/theme/vier/style.css
@@ -2748,7 +2748,9 @@ a.mail-list-link {
         margin-bottom: 15px;
 }
 
-.vevent .event-description, .vevent .event-location {
+.vevent .event-summary,
+.vevent .event-description,
+.vevent .event-location {
         margin-left: 10px;
         margin-right: 10px;
 }

From f21e3e46c7f7258ba237dfa5002b9b07624a5c57 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Wed, 3 Feb 2016 15:01:24 +0100
Subject: [PATCH 021/273] Vier mobile: better jot buttons on small screens

---
 view/theme/vier/mobile.css | 13 +++++++++++++
 view/theme/vier/style.css  |  4 ++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/view/theme/vier/mobile.css b/view/theme/vier/mobile.css
index edba28e5af..b67dc5f771 100644
--- a/view/theme/vier/mobile.css
+++ b/view/theme/vier/mobile.css
@@ -166,6 +166,19 @@ aside.show {
 .tabs.show::after { display: none; }
 .tabs.show .tab { display: block; }
 
+/* jot buttons */
+#profile-jot-submit,
+#jot-preview-link {
+    float: none;
+    display: block;
+    width: 100%;
+    margin: 0 0 1em 0;
+}
+#profile-jot-submit-wrapper > div {
+    margin: 0 1em 1em 0;
+}
+#profile-jot-submit-wrapper > div#profile-jot-perms { margin: 0; }
+ 
 /* ACL window */
 #profile-jot-acl-wrapper, #profile-jot-acl-wrapper * { box-sizing: border-box; }
 #acl-wrapper { width: 100%; float: none; }
diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css
index cdbda71fda..7d7e2683a4 100644
--- a/view/theme/vier/style.css
+++ b/view/theme/vier/style.css
@@ -127,8 +127,8 @@ img {
 .icon {
   background-color: transparent ;
   background-repeat: no-repeat;
-  width: 18px;
-  height: 18px;
+  width: 20px;
+  height: 20px;
   /* display: block; */
   display: inline-block;
   overflow: hidden;

From c1070e4655996e047951dada992b65abebf74834 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Wed, 3 Feb 2016 18:05:26 +0100
Subject: [PATCH 022/273] forums.php is now forum.php and providing class forum

---
 include/forum.php         | 190 ++++++++++++++++++++++++++++++++++++++
 include/forums.php        | 185 -------------------------------------
 include/identity.php      |   4 +-
 mod/network.php           |   4 +-
 mod/ping.php              |   4 +-
 view/theme/vier/theme.php |   4 +-
 6 files changed, 198 insertions(+), 193 deletions(-)
 create mode 100644 include/forum.php
 delete mode 100644 include/forums.php

diff --git a/include/forum.php b/include/forum.php
new file mode 100644
index 0000000000..290f0134a1
--- /dev/null
+++ b/include/forum.php
@@ -0,0 +1,190 @@
+<?php
+
+/**
+ * @file include/forum.php
+ * @brief Functions related to forum functionality *
+ */
+
+/**
+ * @brief This class handles functions related to the forum functionality
+ */
+class forum {
+
+	/**
+	 * @brief Function to list all forums a user is connected with
+	 *
+	 * @param int $uid of the profile owner
+	 * @param boolean $showhidden
+	 *	Show frorums which are not hidden
+	 * @param boolean $lastitem
+	 *	Sort by lastitem
+	 * @param boolean $showprivate
+	 *	Show private groups
+	 *
+	 * @returns array
+	 *	'url'	=> forum url
+	 *	'name'	=> forum name
+	 *	'id'	=> number of the key from the array
+	 *	'micro' => contact photo in format micro
+	 */
+	public static function get_forumlist($uid, $showhidden = true, $lastitem, $showprivate = false) {
+
+		$forumlist = array();
+
+		$order = (($showhidden) ? '' : ' AND NOT `hidden` ');
+		$order .= (($lastitem) ? ' ORDER BY `last-item` DESC ' : ' ORDER BY `name` ASC ');
+		$select = '`forum` ';
+		if ($showprivate) {
+			$select = '(`forum` OR `prv`)';
+		}
+
+		$contacts = q("SELECT `contact`.`id`, `contact`.`url`, `contact`.`name`, `contact`.`micro` FROM `contact`
+				WHERE `network`= 'dfrn' AND $select AND `uid` = %d
+				AND NOT `blocked` AND NOT `hidden` AND NOT `pending` AND NOT `archive`
+				AND `success_update` > `failure_update`
+				$order ",
+				intval($uid)
+		);
+
+		if (!$contacts)
+			return($forumlist);
+
+		foreach($contacts as $contact) {
+			$forumlist[] = array(
+				'url'	=> $contact['url'],
+				'name'	=> $contact['name'],
+				'id'	=> $contact['id'],
+				'micro' => $contact['micro'],
+			);
+		}
+		return($forumlist);
+	}
+
+
+	/**
+	 * @brief Forumlist widget
+	 *
+	 * Sidebar widget to show subcribed friendica forums. If activated
+	 * in the settings, it appears at the notwork page sidebar
+	 *
+	 * @param int $uid The ID of the User
+	 * @param int $cid
+	 *	The contact id which is used to mark a forum as "selected"
+	 * @return string
+	 */
+	public static function widget_forumlist($uid,$cid = 0) {
+
+		if(! intval(feature_enabled(local_user(),'forumlist_widget')))
+			return;
+
+		$o = '';
+
+		//sort by last updated item
+		$lastitem = true;
+
+		$contacts = self::get_forumlist($uid,true,$lastitem, true);
+		$total = count($contacts);
+		$visible_forums = 10;
+
+		if(count($contacts)) {
+
+			$id = 0;
+
+			foreach($contacts as $contact) {
+
+				$selected = (($cid == $contact['id']) ? ' forum-selected' : '');
+
+				$entry = array(
+					'url' => z_root() . '/network?f=&cid=' . $contact['id'],
+					'external_url' => z_root() . '/redir/' . $contact['id'],
+					'name' => $contact['name'],
+					'cid' => $contact['id'],
+					'selected' 	=> $selected,
+					'micro' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO),
+					'id' => ++$id,
+				);
+				$entries[] = $entry;
+			}
+
+			$tpl = get_markup_template('widget_forumlist.tpl');
+
+			$o .= replace_macros($tpl,array(
+				'$title'	=> t('Forums'),
+				'$forums'	=> $entries,
+				'$link_desc'	=> t('External link to forum'),
+				'$total'	=> $total,
+				'$visible_forums' => $visible_forums,
+				'$showmore'	=> t('show more'),
+			));
+		}
+
+		return $o;
+	}
+
+	/**
+	 * @brief Format forumlist as contact block
+	 *
+	 * This function is used to show the forumlist in
+	 * the advanced profile.
+	 *
+	 * @param int $uid The ID of the User
+	 * @return string
+	 *
+	 */
+	public static function forumlist_profile_advanced($uid) {
+
+		$profile = intval(feature_enabled($uid,'forumlist_profile'));
+		if(! $profile)
+			return;
+
+		$o = '';
+
+		// place holder in case somebody wants configurability
+		$show_total = 9999;
+
+		//don't sort by last updated item
+		$lastitem = false;
+
+		$contacts = self::get_forumlist($uid,false,$lastitem,false);
+
+		$total_shown = 0;
+
+		foreach($contacts as $contact) {
+			$forumlist .= micropro($contact,false,'forumlist-profile-advanced');
+			$total_shown ++;
+			if($total_shown == $show_total)
+				break;
+		}
+
+		if(count($contacts) > 0)
+			$o .= $forumlist;
+			return $o;
+	}
+
+	/**
+	 * @brief count unread forum items
+	 *
+	 * Count unread items of connected forums and private groups
+	 *
+	 * @return array
+	 *	'id' => contact id
+	 *	'name' => contact/forum name
+	 *	'count' => counted unseen forum items
+	 *
+	 */
+	public static function count_unseen_items() {
+		$r = q("SELECT `contact`.`id`, `contact`.`name`, COUNT(*) AS `count` FROM `item`
+				INNER JOIN `contact` ON `item`.`contact-id` = `contact`.`id`
+				WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted` AND `item`.`unseen`
+				AND `contact`.`network`= 'dfrn' AND (`contact`.`forum` OR `contact`.`prv`)
+				AND NOT `contact`.`blocked` AND NOT `contact`.`hidden`
+				AND NOT `contact`.`pending` AND NOT `contact`.`archive`
+				AND `contact`.`success_update` > `failure_update`
+				GROUP BY `contact`.`id` ",
+			intval(local_user())
+		);
+
+		return $r;
+	}
+
+}
\ No newline at end of file
diff --git a/include/forums.php b/include/forums.php
deleted file mode 100644
index 952d09a494..0000000000
--- a/include/forums.php
+++ /dev/null
@@ -1,185 +0,0 @@
-<?php
-
-/**
- * @file include/forums.php
- * @brief Functions related to forum functionality *
- */
-
-
-/**
- * @brief Function to list all forums a user is connected with
- *
- * @param int $uid of the profile owner
- * @param boolean $showhidden
- *	Show frorums which are not hidden
- * @param boolean $lastitem
- *	Sort by lastitem
- * @param boolean $showprivate
- *	Show private groups
- *
- * @returns array
- *	'url'	=> forum url
- *	'name'	=> forum name
- *	'id'	=> number of the key from the array
- *	'micro' => contact photo in format micro
- */
-function get_forumlist($uid, $showhidden = true, $lastitem, $showprivate = false) {
-
-	$forumlist = array();
-
-	$order = (($showhidden) ? '' : ' AND NOT `hidden` ');
-	$order .= (($lastitem) ? ' ORDER BY `last-item` DESC ' : ' ORDER BY `name` ASC ');
-	$select = '`forum` ';
-	if ($showprivate) {
-		$select = '(`forum` OR `prv`)';
-	}
-
-	$contacts = q("SELECT `contact`.`id`, `contact`.`url`, `contact`.`name`, `contact`.`micro` FROM `contact`
-			WHERE `network`= 'dfrn' AND $select AND `uid` = %d
-			AND NOT `blocked` AND NOT `hidden` AND NOT `pending` AND NOT `archive`
-			AND `success_update` > `failure_update`
-			$order ",
-			intval($uid)
-	);
-
-	if (!$contacts)
-		return($forumlist);
-
-	foreach($contacts as $contact) {
-		$forumlist[] = array(
-			'url'	=> $contact['url'],
-			'name'	=> $contact['name'],
-			'id'	=> $contact['id'],
-			'micro' => $contact['micro'],
-		);
-	}
-	return($forumlist);
-}
-
-
-/**
- * @brief Forumlist widget
- *
- * Sidebar widget to show subcribed friendica forums. If activated
- * in the settings, it appears at the notwork page sidebar
- *
- * @param int $uid
- * @param int $cid
- *	The contact id which is used to mark a forum as "selected"
- * @return string
- */
-function widget_forumlist($uid,$cid = 0) {
-
-	if(! intval(feature_enabled(local_user(),'forumlist_widget')))
-		return;
-
-	$o = '';
-
-	//sort by last updated item
-	$lastitem = true;
-
-	$contacts = get_forumlist($uid,true,$lastitem, true);
-	$total = count($contacts);
-	$visible_forums = 10;
-
-	if(count($contacts)) {
-
-		$id = 0;
-
-		foreach($contacts as $contact) {
-
-			$selected = (($cid == $contact['id']) ? ' forum-selected' : '');
-
-			$entry = array(
-				'url' => z_root() . '/network?f=&cid=' . $contact['id'],
-				'external_url' => z_root() . '/redir/' . $contact['id'],
-				'name' => $contact['name'],
-				'cid' => $contact['id'],
-				'selected' 	=> $selected,
-				'micro' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO),
-				'id' => ++$id,
-			);
-			$entries[] = $entry;
-		}
-
-		$tpl = get_markup_template('widget_forumlist.tpl');
-
-		$o .= replace_macros($tpl,array(
-			'$title'	=> t('Forums'),
-			'$forums'	=> $entries,
-			'$link_desc'	=> t('External link to forum'),
-			'$total'	=> $total,
-			'$visible_forums' => $visible_forums,
-			'$showmore'	=> t('show more'),
-		));
-	}
-
-	return $o;
-}
-
-/**
- * @brief Format forumlist as contact block
- *
- * This function is used to show the forumlist in
- * the advanced profile.
- *
- * @param int $uid
- * @return string
- *
- */
-function forumlist_profile_advanced($uid) {
-
-	$profile = intval(feature_enabled($uid,'forumlist_profile'));
-	if(! $profile)
-		return;
-
-	$o = '';
-
-	// place holder in case somebody wants configurability
-	$show_total = 9999;
-
-	//don't sort by last updated item
-	$lastitem = false;
-
-	$contacts = get_forumlist($uid,false,$lastitem,false);
-
-	$total_shown = 0;
-
-	foreach($contacts as $contact) {
-		$forumlist .= micropro($contact,false,'forumlist-profile-advanced');
-		$total_shown ++;
-		if($total_shown == $show_total)
-			break;
-	}
-
-	if(count($contacts) > 0)
-		$o .= $forumlist;
-		return $o;
-}
-
-/**
- * @brief count unread forum items
- *
- * Count unread items of connected forums and private groups
- *
- * @return array
- *	'id' => contact id
- *	'name' => contact/forum name
- *	'count' => counted unseen forum items
- *
- */
-
-function forums_count_unseen() {
-	$r = q("SELECT `contact`.`id`, `contact`.`name`, COUNT(*) AS `count` FROM `item`
-			INNER JOIN `contact` ON `item`.`contact-id` = `contact`.`id`
-			WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted` AND `item`.`unseen`
-			AND `contact`.`network`= 'dfrn' AND (`contact`.`forum` OR `contact`.`prv`)
-			AND NOT `contact`.`blocked` AND NOT `contact`.`hidden`
-			AND NOT `contact`.`pending` AND NOT `contact`.`archive`
-			AND `contact`.`success_update` > `failure_update`
-			GROUP BY `contact`.`id` ",
-		intval(local_user())
-	);
-
-	return $r;
-}
diff --git a/include/identity.php b/include/identity.php
index fdd28f81ce..87c91e6dcc 100644
--- a/include/identity.php
+++ b/include/identity.php
@@ -3,7 +3,7 @@
  * @file include/identity.php
  */
 
-require_once('include/forums.php');
+require_once('include/forum.php');
 require_once('include/bbcode.php');
 require_once("mod/proxy.php");
 
@@ -655,7 +655,7 @@ function advanced_profile(&$a) {
 	
 		//show subcribed forum if it is enabled in the usersettings
 		if (feature_enabled($uid,'forumlist_profile')) {
-			$profile['forumlist'] = array( t('Forums:'), forumlist_profile_advanced($uid));
+			$profile['forumlist'] = array( t('Forums:'), forum::forumlist_profile_advanced($uid));
 		}
 
 		if ($a->profile['uid'] == local_user())
diff --git a/mod/network.php b/mod/network.php
index a07c5868ec..151384cd67 100644
--- a/mod/network.php
+++ b/mod/network.php
@@ -114,7 +114,7 @@ function network_init(&$a) {
 	require_once('include/group.php');
 	require_once('include/contact_widgets.php');
 	require_once('include/items.php');
-	require_once('include/forums.php');
+	require_once('include/forum.php');
 
 	if(! x($a->page,'aside'))
 		$a->page['aside'] = '';
@@ -148,7 +148,7 @@ function network_init(&$a) {
 	}
 
 	$a->page['aside'] .= (feature_enabled(local_user(),'groups') ? group_side('network/0','network','standard',$group_id) : '');
-	$a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? widget_forumlist(local_user(),$cid) : '');
+	$a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? forum::widget_forumlist(local_user(),$cid) : '');
 	$a->page['aside'] .= posted_date_widget($a->get_baseurl() . '/network',local_user(),false);
 	$a->page['aside'] .= networks_widget($a->get_baseurl(true) . '/network',(x($_GET, 'nets') ? $_GET['nets'] : ''));
 	$a->page['aside'] .= saved_searches($search);
diff --git a/mod/ping.php b/mod/ping.php
index 57728d3294..3d34e2fe62 100644
--- a/mod/ping.php
+++ b/mod/ping.php
@@ -1,7 +1,7 @@
 <?php
 require_once("include/datetime.php");
 require_once('include/bbcode.php');
-require_once('include/forums.php');
+require_once('include/forum.php');
 require_once('include/group.php');
 require_once("mod/proxy.php");
 
@@ -96,7 +96,7 @@ function ping_init(&$a) {
 			}
 
 			if(intval(feature_enabled(local_user(),'forumlist_widget'))) {
-				$forums_unseen = forums_count_unseen();
+				$forums_unseen = forum::count_unseen_items();
 			}
 		}
 
diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php
index 4afc5409c0..93a6d5ce08 100644
--- a/view/theme/vier/theme.php
+++ b/view/theme/vier/theme.php
@@ -220,7 +220,7 @@ function vier_community_info() {
 	//Community_Pages at right_aside
 	if($show_pages AND local_user()) {
 
-		require_once('include/forums.php');
+		require_once('include/forum.php');
 
 		if(x($_GET['cid']) && intval($_GET['cid']) != 0)
 			$cid = $_GET['cid'];
@@ -228,7 +228,7 @@ function vier_community_info() {
 		//sort by last updated item
 		$lastitem = true;
 
-		$contacts = get_forumlist($a->user['uid'],true,$lastitem, true);
+		$contacts = forum::get_forumlist($a->user['uid'],true,$lastitem, true);
 		$total = count($contacts);
 		$visible_forums = 10;
 

From 811ed4e1c0bad71c29af927267dbc85b57dc6027 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Wed, 3 Feb 2016 19:48:09 +0100
Subject: [PATCH 023/273] datetime.php cleanup

---
 include/datetime.php | 407 ++++++++++++++++++++++++++-----------------
 1 file changed, 247 insertions(+), 160 deletions(-)

diff --git a/include/datetime.php b/include/datetime.php
index a05af5e38f..3a75690d22 100644
--- a/include/datetime.php
+++ b/include/datetime.php
@@ -1,8 +1,17 @@
 <?php
+/**
+ * @file include/datetime.php
+ * @brief Some functions for date and time related tasks.
+ */
 
-// two-level sort for timezones.
 
-if(! function_exists('timezone_cmp')) {
+/**
+ * @brief Two-level sort for timezones.
+ *
+ * @param string $a
+ * @param string $b
+ * @return int
+ */
 function timezone_cmp($a, $b) {
 	if(strstr($a,'/') && strstr($b,'/')) {
 		if ( t($a) == t($b)) return 0;
@@ -11,11 +20,16 @@ function timezone_cmp($a, $b) {
 	if(strstr($a,'/')) return -1;
 	if(strstr($b,'/')) return  1;
 	if ( t($a) == t($b)) return 0;
-	return ( t($a) < t($b)) ? -1 : 1;
-}}
 
-// emit a timezone selector grouped (primarily) by continent
-if(! function_exists('select_timezone')) {
+	return ( t($a) < t($b)) ? -1 : 1;
+}
+
+/**
+ * @brief Emit a timezone selector grouped (primarily) by continent
+ * 
+ * @param string $current Timezone
+ * @return string Parsed HTML output
+ */
 function select_timezone($current = 'America/Los_Angeles') {
 
 	$timezone_identifiers = DateTimeZone::listIdentifiers();
@@ -52,13 +66,25 @@ function select_timezone($current = 'America/Los_Angeles') {
 	}
 	$o .= '</optgroup></select>';
 	return $o;
-}}
+}
 
-// return a select using 'field_select_raw' template, with timezones
-// groupped (primarily) by continent
-// arguments follow convetion as other field_* template array:
-// 'name', 'label', $value, 'help'
-if (!function_exists('field_timezone')){
+
+
+/**
+ * @brief Generating a Timezone selector
+ * 
+ * Return a select using 'field_select_raw' template, with timezones
+ * groupped (primarily) by continent
+.* arguments follow convetion as other field_* template array:
+.* 'name', 'label', $value, 'help'
+ * 
+ * @param string $name Name of the selector
+ * @param string $label Label for the selector
+ * @param string $current Timezone
+ * @param string $help Help text
+ * 
+ * @return string Parsed HTML
+ */
 function field_timezone($name='timezone', $label='', $current = 'America/Los_Angeles', $help){
 	$options = select_timezone($current);
 	$options = str_replace('<select id="timezone_select" name="timezone">','', $options);
@@ -69,15 +95,19 @@ function field_timezone($name='timezone', $label='', $current = 'America/Los_Ang
 		'$field' => array($name, $label, $current, $help, $options),
 	));
 
-}}
+}
 
-// General purpose date parse/convert function.
-// $from = source timezone
-// $to   = dest timezone
-// $s    = some parseable date/time string
-// $fmt  = output format
-
-if(! function_exists('datetime_convert')) {
+/**
+ * @brief General purpose date parse/convert function.
+ *
+ * @param string $from Source timezone
+ * @param string $to Dest timezone
+ * @param string $s Some parseable date/time string
+ * @param string $fmt Output format recognised from php's DateTime class
+ *   http://www.php.net/manual/en/datetime.format.php
+ * 
+ * @return string
+ */
 function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d H:i:s") {
 
 	// Defaults to UTC if nothing is set, but throws an exception if set to empty string.
@@ -124,13 +154,18 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
 
 	$d->setTimeZone($to_obj);
 	return($d->format($fmt));
-}}
+}
 
 
-// wrapper for date selector, tailored for use in birthday fields
-
+/**
+ * @brief Wrapper for date selector, tailored for use in birthday fields.
+ *
+ * @param string $dob Date of Birth
+ * @return string
+ */
 function dob($dob) {
 	list($year,$month,$day) = sscanf($dob,'%4d-%2d-%2d');
+
 	$f = get_config('system','birthday_input_format');
 	if(! $f)
 		$f = 'ymd';
@@ -138,62 +173,69 @@ function dob($dob) {
 		$value = '';
 	else
 		$value = (($year) ? datetime_convert('UTC','UTC',$dob,'Y-m-d') : datetime_convert('UTC','UTC',$dob,'m-d'));
+
 	$o = '<input type="text" name="dob" value="' . $value . '" placeholder="' . t('YYYY-MM-DD or MM-DD') . '" />';
+
 //	if ($dob && $dob != '0000-00-00')
 //		$o = datesel($f,mktime(0,0,0,0,0,1900),mktime(),mktime(0,0,0,$month,$day,$year),'dob');
 //	else
 //		$o = datesel($f,mktime(0,0,0,0,0,1900),mktime(),false,'dob');
+
 	return $o;
 }
 
 /**
- * returns a date selector
- * @param $format
- *  format string, e.g. 'ymd' or 'mdy'. Not currently supported
- * @param $min
- *  unix timestamp of minimum date
- * @param $max
- *  unix timestap of maximum date
- * @param $default
- *  unix timestamp of default date
- * @param $id
- *  id and name of datetimepicker (defaults to "datetimepicker")
+ * @brief Returns a date selector
+ * 
+ * @param string $format
+ *  Format string, e.g. 'ymd' or 'mdy'. Not currently supported
+ * @param string $min
+ *  Unix timestamp of minimum date
+ * @param string $max
+ *  Unix timestap of maximum date
+ * @param string $default
+ *  Unix timestamp of default date
+ * @param string $id
+ *  ID and name of datetimepicker (defaults to "datetimepicker")
+ * 
+ * @return string Parsed HTML output.
  */
-if(! function_exists('datesel')) {
 function datesel($format, $min, $max, $default, $id = 'datepicker') {
 	return datetimesel($format,$min,$max,$default,$id,true,false, '','');
-}}
+}
 
 /**
- * returns a time selector
- * @param $format
- *  format string, e.g. 'ymd' or 'mdy'. Not currently supported
+ * @brief Returns a time selector
+ * 
+ * @param string $format
+ *  Format string, e.g. 'ymd' or 'mdy'. Not currently supported
  * @param $h
- *  already selected hour
+ *  Already selected hour
  * @param $m
- *  already selected minute
- * @param $id
- *  id and name of datetimepicker (defaults to "timepicker")
+ *  Already selected minute
+ * @param string $id
+ *  ID and name of datetimepicker (defaults to "timepicker")
+ * 
+ * @return string Parsed HTML output.
  */
-if(! function_exists('timesel')) {
 function timesel($format, $h, $m, $id='timepicker') {
 	return datetimesel($format,new DateTime(),new DateTime(),new DateTime("$h:$m"),$id,false,true);
-}}
+}
 
 /**
  * @brief Returns a datetime selector.
  *
- * @param $format
+ * @param string $format
  *  format string, e.g. 'ymd' or 'mdy'. Not currently supported
- * @param $min
+ * @param string $min
  *  unix timestamp of minimum date
- * @param $max
+ * @param string $max
  *  unix timestap of maximum date
- * @param $default
+ * @param string $default
  *  unix timestamp of default date
  * @param string $id
  *  id and name of datetimepicker (defaults to "datetimepicker")
- * @param boolean $pickdate
+ * @param bool $pickdate
  *  true to show date picker (default)
  * @param boolean $picktime
  *  true to show time picker (default)
@@ -201,17 +243,15 @@ function timesel($format, $h, $m, $id='timepicker') {
  *  set minimum date from picker with id $minfrom (none by default)
  * @param $maxfrom
  *  set maximum date from picker with id $maxfrom (none by default)
- * @param boolean $required default false
+ * @param bool $required default false
+ * 
  * @return string Parsed HTML output.
  *
  * @todo Once browser support is better this could probably be replaced with
  * native HTML5 date picker.
  */
-if(! function_exists('datetimesel')) {
 function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pickdate = true, $picktime = true, $minfrom = '', $maxfrom = '', $required = false) {
 
-	$a = get_app();
-
 	// First day of the week (0 = Sunday)
 	$firstDay = get_pconfig(local_user(),'system','first_day_of_week');
 	if ($firstDay === false) $firstDay=0;
@@ -224,43 +264,58 @@ function datetimesel($format, $min, $max, $default, $id = 'datetimepicker', $pic
 
 	$o = '';
 	$dateformat = '';
+
 	if($pickdate) $dateformat .= 'Y-m-d';
 	if($pickdate && $picktime) $dateformat .= ' ';
 	if($picktime) $dateformat .= 'H:i';
+
 	$minjs = $min ? ",minDate: new Date({$min->getTimestamp()}*1000), yearStart: " . $min->format('Y') : '';
 	$maxjs = $max ? ",maxDate: new Date({$max->getTimestamp()}*1000), yearEnd: " . $max->format('Y') : '';
 
 	$input_text = $default ? 'value="' . date($dateformat, $default->getTimestamp()) . '"' : '';
 	$defaultdatejs = $default ? ",defaultDate: new Date({$default->getTimestamp()}*1000)" : '';
+
 	$pickers = '';
 	if(!$pickdate) $pickers .= ',datepicker: false';
 	if(!$picktime) $pickers .= ',timepicker: false';
+
 	$extra_js = '';
 	$pickers .= ",dayOfWeekStart: ".$firstDay.",lang:'".$lang."'";
 	if($minfrom != '')
 		$extra_js .= "\$('#$minfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#$id').data('xdsoft_datetimepicker').setOptions({minDate: currentDateTime})}})";
 	if($maxfrom != '')
 		$extra_js .= "\$('#$maxfrom').data('xdsoft_datetimepicker').setOptions({onChangeDateTime: function (currentDateTime) { \$('#$id').data('xdsoft_datetimepicker').setOptions({maxDate: currentDateTime})}})";
+
 	$readable_format = $dateformat;
 	$readable_format = str_replace('Y','yyyy',$readable_format);
 	$readable_format = str_replace('m','mm',$readable_format);
 	$readable_format = str_replace('d','dd',$readable_format);
 	$readable_format = str_replace('H','HH',$readable_format);
 	$readable_format = str_replace('i','MM',$readable_format);
+
 	$o .= "<div class='date'><input type='text' placeholder='$readable_format' name='$id' id='$id' $input_text />";
 	$o .= '</div>';
 	$o .= "<script type='text/javascript'>";
 	$o .= "\$(function () {var picker = \$('#$id').datetimepicker({step:5,format:'$dateformat' $minjs $maxjs $pickers $defaultdatejs}); $extra_js})";
 	$o .= "</script>";
+
 	return $o;
-}}
+}
 
-// implements "3 seconds ago" etc.
-// based on $posted_date, (UTC).
-// Results relative to current timezone
-// Limited to range of timestamps
-
-if(! function_exists('relative_date')) {
+/**
+ * @brief Returns a relative date string.
+ *
+ * Implements "3 seconds ago" etc.
+ * Based on $posted_date, (UTC).
+ * Results relative to current timezone.
+ * Limited to range of timestamps.
+ *
+ * @param string $posted_date
+ * @param string $format (optional) Parsed with sprintf()
+ *    <tt>%1$d %2$s ago</tt>, e.g. 22 hours ago, 1 minute ago
+ * 
+ * @return string with relative date
+ */
 function relative_date($posted_date,$format = null) {
 
 	$localtime = datetime_convert('UTC',date_default_timezone_get(),$posted_date);
@@ -300,23 +355,33 @@ function relative_date($posted_date,$format = null) {
 			// translators - e.g. 22 hours ago, 1 minute ago
 			if(! $format)
 				$format = t('%1$d %2$s ago');
+
 			return sprintf( $format,$r, (($r == 1) ? $str[0] : $str[1]));
-        }
-    }
-}}
-
-
-
-// Returns age in years, given a date of birth,
-// the timezone of the person whose date of birth is provided,
-// and the timezone of the person viewing the result.
-// Why? Bear with me. Let's say I live in Mittagong, Australia, and my
-// birthday is on New Year's. You live in San Bruno, California.
-// When exactly are you going to see my age increase?
-// A: 5:00 AM Dec 31 San Bruno time. That's precisely when I start
-// celebrating and become a year older. If you wish me happy birthday
-// on January 1 (San Bruno time), you'll be a day late.
+		}
+	}
+}
 
+/**
+ * @brief Returns timezone correct age in years.
+ *
+ * Returns the age in years, given a date of birth, the timezone of the person
+ * whose date of birth is provided, and the timezone of the person viewing the
+ * result.
+ *
+ * Why? Bear with me. Let's say I live in Mittagong, Australia, and my birthday
+ * is on New Year's. You live in San Bruno, California.
+ * When exactly are you going to see my age increase?
+ *
+ * A: 5:00 AM Dec 31 San Bruno time. That's precisely when I start celebrating
+ * and become a year older. If you wish me happy birthday on January 1
+ * (San Bruno time), you'll be a day late.
+ *
+ * @param string $dob Date of Birth
+ * @param string $owner_tz (optional) Timezone of the person of interest
+ * @param string $viewer_tz (optional) Timezone of the person viewing
+ * 
+ * @return int
+ */
 function age($dob,$owner_tz = '',$viewer_tz = '') {
 	if(! intval($dob))
 		return 0;
@@ -333,64 +398,79 @@ function age($dob,$owner_tz = '',$viewer_tz = '') {
 
 	if(($curr_month < $month) || (($curr_month == $month) && ($curr_day < $day)))
 		$year_diff--;
+
 	return $year_diff;
 }
 
-
-
-// Get days in month
-// get_dim($year, $month);
-// returns number of days.
-// $month[1] = 'January'; 
-//   to match human usage.
-
-if(! function_exists('get_dim')) {
+/**
+ * @brief Get days of a month in a given year.
+ *
+ * Returns number of days in the month of the given year.
+ * $m = 1 is 'January' to match human usage.
+ *
+ * @param int $y Year
+ * @param int $m Month (1=January, 12=December)
+ * 
+ * @return int Number of days in the given month
+ */
 function get_dim($y,$m) {
 
-  $dim = array( 0,
-    31, 28, 31, 30, 31, 30,
-    31, 31, 30, 31, 30, 31);
- 
-  if($m != 2)
-    return $dim[$m];
-  if(((($y % 4) == 0) && (($y % 100) != 0)) || (($y % 400) == 0))
-    return 29;
-  return $dim[2];
-}}
+	$dim = array( 0,
+		31, 28, 31, 30, 31, 30,
+		31, 31, 30, 31, 30, 31);
 
+	if($m != 2)
+		return $dim[$m];
 
-// Returns the first day in month for a given month, year
-// get_first_dim($year,$month)
-// returns 0 = Sunday through 6 = Saturday
-// Months start at 1.
+	if(((($y % 4) == 0) && (($y % 100) != 0)) || (($y % 400) == 0))
+		return 29;
 
-if(! function_exists('get_first_dim')) {
+	return $dim[2];
+}
+
+/**
+ * @brief Returns the first day in month for a given month, year.
+ *
+ * Months start at 1.
+ *
+ * @param int $y Year
+ * @param int $m Month (1=January, 12=December)
+ * 
+ * @return string day 0 = Sunday through 6 = Saturday
+ */
 function get_first_dim($y,$m) {
-  $d = sprintf('%04d-%02d-01 00:00', intval($y), intval($m));
-  return datetime_convert('UTC','UTC',$d,'w');
-}}
+	$d = sprintf('%04d-%02d-01 00:00', intval($y), intval($m));
 
-// output a calendar for the given month, year.
-// if $links are provided (array), e.g. $links[12] => 'http://mylink' , 
-// date 12 will be linked appropriately. Today's date is also noted by
-// altering td class.
-// Months count from 1.
+	return datetime_convert('UTC','UTC',$d,'w');
+}
 
-
-/// @TODO Provide (prev,next) links, define class variations for different size calendars
-
-
-if(! function_exists('cal')) {
+/**
+ * @brief Output a calendar for the given month, year.
+ *
+ * If $links are provided (array), e.g. $links[12] => 'http://mylink' ,
+ * date 12 will be linked appropriately. Today's date is also noted by
+ * altering td class.
+ * Months count from 1.
+ *
+ * @param int $y Year
+ * @param int $m Month
+ * @param bool $links (default false)
+ * @param string $class
+ * 
+ * @return string
+ *
+ * @todo Provide (prev,next) links, define class variations for different size calendars
+ */
 function cal($y = 0,$m = 0, $links = false, $class='') {
 
 
 	// month table - start at 1 to match human usage.
 
 	$mtab = array(' ',
-	  'January','February','March',
-	  'April','May','June',
-	  'July','August','September',
-	  'October','November','December'
+		'January','February','March',
+		'April','May','June',
+		'July','August','September',
+		'October','November','December'
 	);
 
 	$thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
@@ -400,54 +480,63 @@ function cal($y = 0,$m = 0, $links = false, $class='') {
 	if(! $m)
 		$m = intval($thismonth);
 
-  $dn = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
-  $f = get_first_dim($y,$m);
-  $l = get_dim($y,$m);
-  $d = 1;
-  $dow = 0;
-  $started = false;
+	$dn = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
+	$f = get_first_dim($y,$m);
+	$l = get_dim($y,$m);
+	$d = 1;
+	$dow = 0;
+	$started = false;
 
-  if(($y == $thisyear) && ($m == $thismonth))
-    $tddate = intval(datetime_convert('UTC',date_default_timezone_get(),'now','j'));
+	if(($y == $thisyear) && ($m == $thismonth))
+		$tddate = intval(datetime_convert('UTC',date_default_timezone_get(),'now','j'));
 
 	$str_month = day_translate($mtab[$m]);
-  $o = '<table class="calendar' . $class . '">';
-  $o .= "<caption>$str_month $y</caption><tr>";
-  for($a = 0; $a < 7; $a ++)
-     $o .= '<th>' . mb_substr(day_translate($dn[$a]),0,3,'UTF-8') . '</th>';
-  $o .= '</tr><tr>';
+	$o = '<table class="calendar' . $class . '">';
+	$o .= "<caption>$str_month $y</caption><tr>";
+	for($a = 0; $a < 7; $a ++)
+		$o .= '<th>' . mb_substr(day_translate($dn[$a]),0,3,'UTF-8') . '</th>';
 
-  while($d <= $l) {
-    if(($dow == $f) && (! $started))
-      $started = true;
-    $today = (((isset($tddate)) && ($tddate == $d)) ? "class=\"today\" " : '');
-    $o .= "<td $today>";
-	$day = str_replace(' ','&nbsp;',sprintf('%2.2d', $d));
-    if($started) {
-      if(is_array($links) && isset($links[$d]))
-        $o .=  "<a href=\"{$links[$d]}\">$day</a>";
-      else
-        $o .= $day;
-      $d ++;
-    }
-    else
-      $o .= '&nbsp;';
-    $o .= '</td>';
-    $dow ++;
-    if(($dow == 7) && ($d <= $l)) {
-      $dow = 0;
-      $o .= '</tr><tr>';
-    }
-  }
-  if($dow)
-    for($a = $dow; $a < 7; $a ++)
-       $o .= '<td>&nbsp;</td>';
-  $o .= '</tr></table>'."\r\n";
+	$o .= '</tr><tr>';
 
-  return $o;
-}}
+	while($d <= $l) {
+		if(($dow == $f) && (! $started))
+			$started = true;
 
+		$today = (((isset($tddate)) && ($tddate == $d)) ? "class=\"today\" " : '');
+		$o .= "<td $today>";
+		$day = str_replace(' ','&nbsp;',sprintf('%2.2d', $d));
+		if($started) {
+			if(is_array($links) && isset($links[$d]))
+				$o .=  "<a href=\"{$links[$d]}\">$day</a>";
+			else
+				$o .= $day;
 
+			$d ++;
+		} else {
+			$o .= '&nbsp;';
+		}
+
+		$o .= '</td>';
+		$dow ++;
+		if(($dow == 7) && ($d <= $l)) {
+			$dow = 0;
+			$o .= '</tr><tr>';
+		}
+	}
+	if($dow)
+		for($a = $dow; $a < 7; $a ++)
+			$o .= '<td>&nbsp;</td>';
+
+	$o .= '</tr></table>'."\r\n";
+
+	return $o;
+}
+
+/**
+ * @brief Create a birthday event.
+ *
+ * Update the year and the birthday.
+ */
 function update_contact_birthdays() {
 
 	// This only handles foreign or alien networks where a birthday has been provided.
@@ -474,8 +563,6 @@ function update_contact_birthdays() {
 			$bdtext = sprintf( t('%s\'s birthday'), $rr['name']);
 			$bdtext2 = sprintf( t('Happy Birthday %s'), ' [url=' . $rr['url'] . ']' . $rr['name'] . '[/url]') ;
 
-
-
 			$r = q("INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`summary`,`desc`,`type`,`adjust`)
 				VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%d' ) ",
 				intval($rr['uid']),

From c7158772619f2b38a55b22c7639ee3fd58bc0db0 Mon Sep 17 00:00:00 2001
From: Silke Meyer <silke@silkemeyer.net>
Date: Wed, 3 Feb 2016 20:47:41 +0100
Subject: [PATCH 024/273] Slightly updated docs about Let's Encrypt

---
 doc/SSL.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/doc/SSL.md b/doc/SSL.md
index a72eec2a16..bcff929fe5 100644
--- a/doc/SSL.md
+++ b/doc/SSL.md
@@ -90,8 +90,8 @@ If you run your own server, upload the files and check out the Mozilla wiki link
 Let's encrypt
 ---
 
-If you run your own server and you control your name server, the "Let's encrypt" initiative might become an interesting alternative.
-Their offer is not ready, yet.
+If you run your own server, the "Let's encrypt" initiative might become an interesting alternative.
+Their offer is in public beta right now.
 Check out [their website](https://letsencrypt.org/) for status updates.
 
 Web server settings

From 2d0c2990ea13a756578b3117efeee788413648b6 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 3 Feb 2016 23:04:52 +0100
Subject: [PATCH 025/273] Differences fixed between old and new code

---
 include/import-dfrn.php | 80 +++++++++++++++++++++--------------------
 include/items.php       | 30 ++++++++++++----
 2 files changed, 65 insertions(+), 45 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index bfcb002bb1..981e596432 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -18,12 +18,12 @@ require_once("include/items.php");
 require_once("include/tags.php");
 require_once("include/files.php");
 
-define("DFRN_TOP_LEVEL", 0);
-define("DFRN_REPLY", 1);
-define("DFRN_REPLY_RC", 2);
-
 class dfrn2 {
 
+	const DFRN_TOP_LEVEL = 0;
+	const DFRN_REPLY = 1;
+	const DFRN_REPLY_RC = 2;
+
 	/**
 	 * @brief Add new birthday event for this person
 	 *
@@ -58,14 +58,13 @@ class dfrn2 {
 	 *
 	 * @param object $xpath XPath object
 	 * @param object $context In which context should the data be searched
-	 * @param array $importer Record of the importer contact
+	 * @param array $importer Record of the importer user mixed with contact of the content
 	 * @param string $element Element name from which the data is fetched
-	 * @param array $contact The updated contact record of the author
 	 * @param bool $onlyfetch Should the data only be fetched or should it update the contact record as well
 	 *
 	 * @return Returns an array with relevant data of the author
 	 */
-	private function fetchauthor($xpath, $context, $importer, $element, $contact, $onlyfetch) {
+	private function fetchauthor($xpath, $context, $importer, $element, $onlyfetch) {
 
 		$author = array();
 		$author["name"] = $xpath->evaluate($element."/atom:name/text()", $context)->item(0)->nodeValue;
@@ -80,8 +79,8 @@ class dfrn2 {
 			$author["contact-id"] = $r[0]["id"];
 			$author["network"] = $r[0]["network"];
 		} else {
-			$author["contact-id"] = $contact["id"];
-			$author["network"] = $contact["network"];
+			$author["contact-id"] = $importer["id"];
+			$author["network"] = $importer["network"];
 			$onlyfetch = true;
 		}
 
@@ -623,7 +622,7 @@ class dfrn2 {
 		}
 	}
 
-	private function process_entry($header, $xpath, $entry, $importer, $contact) {
+	private function process_entry($header, $xpath, $entry, $importer) {
 
 		logger("Processing entries");
 
@@ -633,27 +632,29 @@ class dfrn2 {
 		$item["uri"] = $xpath->query("atom:id/text()", $entry)->item(0)->nodeValue;
 
 		// Fetch the owner
-		$owner = self::fetchauthor($xpath, $entry, $importer, "dfrn:owner", $contact, true);
+		$owner = self::fetchauthor($xpath, $entry, $importer, "dfrn:owner", true);
 
 		$item["owner-name"] = $owner["name"];
 		$item["owner-link"] = $owner["link"];
 		$item["owner-avatar"] = $owner["avatar"];
 
-		if ($header["contact-id"] != $owner["contact-id"])
-			$item["contact-id"] = $owner["contact-id"];
+		// At the moment we trust the importer array
+		//if ($header["contact-id"] != $owner["contact-id"])
+		//	$item["contact-id"] = $owner["contact-id"];
 
 		if (($header["network"] != $owner["network"]) AND ($owner["network"] != ""))
 			$item["network"] = $owner["network"];
 
 		// fetch the author
-		$author = self::fetchauthor($xpath, $entry, $importer, "atom:author", $contact, true);
+		$author = self::fetchauthor($xpath, $entry, $importer, "atom:author", true);
 
 		$item["author-name"] = $author["name"];
 		$item["author-link"] = $author["link"];
 		$item["author-avatar"] = $author["avatar"];
 
-		if ($header["contact-id"] != $author["contact-id"])
-			$item["contact-id"] = $author["contact-id"];
+		// At the moment we trust the importer array
+		//if ($header["contact-id"] != $author["contact-id"])
+		//	$item["contact-id"] = $author["contact-id"];
 
 		if (($header["network"] != $author["network"]) AND ($author["network"] != ""))
 			$item["network"] = $author["network"];
@@ -948,7 +949,7 @@ class dfrn2 {
 		}
 	}
 
-	private function process_deletion($header, $xpath, $deletion, $importer, $contact_id) {
+	private function process_deletion($header, $xpath, $deletion, $importer) {
 
 		logger("Processing deletions");
 
@@ -963,7 +964,7 @@ class dfrn2 {
 		else
 			$when = datetime_convert("UTC", "UTC", "now", "Y-m-d H:i:s");
 
-		if (!$uri OR !$contact_id)
+		if (!$uri OR !$importer["id"])
 			return false;
 
 		/// @todo Only select the used fields
@@ -971,10 +972,10 @@ class dfrn2 {
 				WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1",
 				dbesc($uri),
 				intval($importer["uid"]),
-				intval($contact_id)
+				intval($importer["id"])
 			);
 		if(!count($r)) {
-			logger("Item with uri ".$uri." from contact ".$contact_id." for user ".$importer["uid"]." wasn't found.", LOGGER_DEBUG);
+			logger("Item with uri ".$uri." from contact ".$importer["id"]." for user ".$importer["uid"]." wasn't found.", LOGGER_DEBUG);
 			return;
 		} else {
 
@@ -1079,11 +1080,25 @@ class dfrn2 {
 		}
 	}
 
-	function import($xml,$importer, &$contact) {
+	/**
+	 * @brief Imports a DFRN message
+	 *
+	 * @param text $xml The DFRN message
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 * @param bool $sort_by_date Is used when feeds are polled
+	 */
+	function import($xml,$importer, $sort_by_date = false) {
 
 		if ($xml == "")
 			return;
 
+		if($importer["readonly"]) {
+	                // We aren't receiving stuff from this person. But we will quietly ignore them
+	                // rather than a blatant "go away" message.
+	                logger('ignoring contact '.$importer["id"]);
+	                return;
+	        }
+
 		$doc = new DOMDocument();
 		@$doc->loadXML($xml);
 
@@ -1099,12 +1114,6 @@ class dfrn2 {
 		$xpath->registerNamespace("ostatus", NAMESPACE_OSTATUS);
 		$xpath->registerNamespace("statusnet", NAMESPACE_STATUSNET);
 
-		/// @todo Do we need this?
-		if (!$contact) {
-			$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `self`", intval($importer["uid"]));
-			$contact = $r[0];
-		}
-
 		$header = array();
 		$header["uid"] = $importer["uid"];
 		$header["network"] = NETWORK_DFRN;
@@ -1115,22 +1124,17 @@ class dfrn2 {
 
 		// Update the contact table if the data has changed
 		// Only the "dfrn:owner" in the head section contains all data
-		$dfrn_owner = self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", $contact, false);
+		self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", false);
 
-		logger("Import DFRN message for user ".$importer["uid"]." from contact ".$contact["id"]." ".print_r($dfrn_owner, true)." - ".print_r($contact, true), LOGGER_DEBUG);
-
-		//if (!$dfrn_owner["found"]) {
-		//	logger("Author doesn't seem to be known by us. UID: ".$importer["uid"]." Contact: ".$dfrn_owner["contact-id"]." - ".print_r($dfrn_owner, true));
-		//	return;
-		//}
+		logger("Import DFRN message for user ".$importer["uid"]." from contact ".$importer["id"], LOGGER_DEBUG);
 
 		// is it a public forum? Private forums aren't supported by now with this method
 		$forum = intval($xpath->evaluate("/atom:feed/dfrn:community/text()", $context)->item(0)->nodeValue);
 
-		if ($forum AND ($dfrn_owner["contact-id"] != 0))
+		if ($forum)
 			q("UPDATE `contact` SET `forum` = %d WHERE `forum` != %d AND `id` = %d",
 				intval($forum), intval($forum),
-				intval($dfrn_owner["contact-id"])
+				intval($importer["id"])
 			);
 
 		$mails = $xpath->query("/atom:feed/dfrn:mail");
@@ -1147,11 +1151,11 @@ class dfrn2 {
 
 		$deletions = $xpath->query("/atom:feed/at:deleted-entry");
 		foreach ($deletions AS $deletion)
-			self::process_deletion($header, $xpath, $deletion, $importer, $dfrn_owner["contact-id"]);
+			self::process_deletion($header, $xpath, $deletion, $importer);
 
 		$entries = $xpath->query("/atom:feed/atom:entry");
 		foreach ($entries AS $entry)
-			self::process_entry($header, $xpath, $entry, $importer, $contact);
+			self::process_entry($header, $xpath, $entry, $importer);
 	}
 }
 ?>
diff --git a/include/items.php b/include/items.php
index 0e98e8f19e..f1291d6490 100644
--- a/include/items.php
+++ b/include/items.php
@@ -1696,13 +1696,29 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
 		return;
 	}
 	// dfrn-test
-//	if ($contact['network'] === NETWORK_DFRN) {
-//		logger("Consume DFRN messages", LOGGER_DEBUG);
-//		logger("dfrn-test");
-//		dfrn2::import($xml,$importer, $contact);
-//		return;
-//	}
+/*
+	if ($contact['network'] === NETWORK_DFRN) {
+		logger("Consume DFRN messages", LOGGER_DEBUG);
+		logger("dfrn-test");
 
+		$r = q("SELECT  `contact`.*, `contact`.`uid` AS `importer_uid`,
+                                        `contact`.`pubkey` AS `cpubkey`,
+                                        `contact`.`prvkey` AS `cprvkey`,
+                                        `contact`.`thumb` AS `thumb`,
+                                        `contact`.`url` as `url`,
+                                        `contact`.`name` as `senderName`,
+                                        `user`.*
+                        FROM `contact`
+                        LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
+                        WHERE `contact`.`id` = %d AND `user`.`uid` = %d",
+	                dbesc($contact["id"], $importer["uid"]);
+	        );
+		if ($r) {
+			dfrn2::import($xml,$r[0], true);
+			return;
+		}
+	}
+*/
 	// Test - remove before flight
 	//if ($pass < 2) {
 	//	$tempfile = tempnam(get_temppath(), "dfrn-consume-");
@@ -2408,7 +2424,7 @@ function item_is_remote_self($contact, &$datarray) {
 
 function local_delivery($importer,$data) {
 	// dfrn-Test
-	//return dfrn2::import($data, $importer, $contact);
+	//return dfrn2::import($data, $importer);
 
 	require_once('library/simplepie/simplepie.inc');
 

From e11ff25de2122fd619a68152af8f7a66cfb11ca1 Mon Sep 17 00:00:00 2001
From: fabrixxm <fabrix.xm@gmail.com>
Date: Wed, 3 Feb 2016 23:22:45 +0100
Subject: [PATCH 026/273] fix empty ACL window on desktop

---
 view/templates/acl_selector.tpl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/view/templates/acl_selector.tpl b/view/templates/acl_selector.tpl
index bb76135067..7c68a73064 100644
--- a/view/templates/acl_selector.tpl
+++ b/view/templates/acl_selector.tpl
@@ -30,7 +30,7 @@ $(document).ready(function() {
 			baseurl+"/acl",
 			[ {{$allowcid}},{{$allowgid}},{{$denycid}},{{$denygid}} ],
 			{{$features.aclautomention}},
-			{{$APP->is_mobile}}
+			{{if $APP->is_mobile}}true{{else}}false{{/if}}
 		);
 	}
 });

From 5f6ba00408ca0f28b2d36d799fa62d37c72333a8 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 4 Feb 2016 10:19:13 +0100
Subject: [PATCH 027/273] Added documentation, fixed some bug

---
 include/import-dfrn.php | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index 981e596432..0abf92feb4 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -776,7 +776,7 @@ class dfrn2 {
 					$item["parent-uri"] = $attributes->textContent;
 
 		// Get the type of the item (Top level post, reply or remote reply)
-		$entrytype = get_entry_type($importer, $item);
+		$entrytype = self::get_entry_type($importer, $item);
 
 		// Now assign the rest of the values that depend on the type of the message
 		if ($entrytype == DFRN_REPLY_RC) {
@@ -892,6 +892,8 @@ class dfrn2 {
 
 			if($posted_id) {
 
+				logger("Reply was stored with id ".$posted_id, LOGGER_DEBUG);
+
 				$item["id"] = $posted_id;
 
 				$r = q("SELECT `parent`, `parent-uri` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
@@ -918,6 +920,7 @@ class dfrn2 {
 				}
 
 				if($posted_id AND $parent AND ($entrytype == DFRN_REPLY_RC)) {
+					logger("Notifying followers about comment ".$posted_id, LOGGER_DEBUG);
 					proc_run("php", "include/notifier.php", "comment-import", $posted_id);
 				}
 
@@ -944,6 +947,8 @@ class dfrn2 {
 
 			$posted_id = item_store($item, false, $notify);
 
+			logger("Item was stored with id ".$posted_id, LOGGER_DEBUG);
+
 			if(stristr($item["verb"],ACTIVITY_POKE))
 				self::do_poke($item, $importer, $posted_id);
 		}
@@ -981,7 +986,7 @@ class dfrn2 {
 
 			$item = $r[0];
 
-			$entrytype = get_entry_type($importer, $item);
+			$entrytype = self::get_entry_type($importer, $item);
 
 			if(!$item["deleted"])
 				logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG);
@@ -1074,8 +1079,10 @@ class dfrn2 {
 				}
 				// if this is a relayed delete, propagate it to other recipients
 
-				if($entrytype == DFRN_REPLY_RC)
+				if($entrytype == DFRN_REPLY_RC) {
+					logger("Notifying followers about deletion of post ".$item["id"], LOGGER_DEBUG);
 					proc_run("php", "include/notifier.php","drop", $item["id"]);
+				}
 			}
 		}
 	}

From 3a649047df15c5edad55572c62c2e3b6a35084db Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 4 Feb 2016 12:51:34 +0100
Subject: [PATCH 028/273] DFRN: Contact-id is now stored depending on the
 author/Some more bugfixes

---
 include/import-dfrn.php | 75 +++++++++++++++++++++--------------------
 include/items.php       |  4 +--
 2 files changed, 41 insertions(+), 38 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index 0abf92feb4..87b2273ef4 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -1,16 +1,4 @@
 <?php
-/*
-require_once("include/Contact.php");
-require_once("include/html2bbcode.php");
-require_once("include/bbcode.php");
-require_once("mod/share.php");
-require_once("include/Photo.php");
-require_once("include/Scrape.php");
-require_once("include/follow.php");
-require_once("include/api.php");
-require_once("mod/proxy.php");
-*/
-
 require_once("include/enotify.php");
 require_once("include/threads.php");
 require_once("include/socgraph.php");
@@ -196,25 +184,37 @@ class dfrn2 {
 
 			unset($fields["id"]);
 			unset($fields["uid"]);
+			unset($fields["avatar-date"]);
+			unset($fields["name-date"]);
+			unset($fields["uri-date"]);
+
+			 // Update check for this field has to be done differently
+			$datefields = array("name-date", "uri-date");
+			foreach ($datefields AS $field)
+				if (strtotime($contact[$field]) > strtotime($r[0][$field]))
+					$update = true;
 
 			foreach ($fields AS $field => $data)
-				if ($contact[$field] != $r[0][$field])
+				if ($contact[$field] != $r[0][$field]) {
+					logger("Difference for contact ".$contact["id"]." in field '".$field."'. Old value: '".$contact[$field]."', new value '".$r[0][$field]."'", LOGGER_DEBUG);
 					$update = true;
+				}
 
 			if ($update) {
 				logger("Update contact data for contact ".$contact["id"], LOGGER_DEBUG);
 
 				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s',
-					`addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s'
-					`avatar-date`  = '%s', `name-date`  = '%s', `uri-date` = '%s'
+					`addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s',
+					`name-date`  = '%s', `uri-date` = '%s'
 					WHERE `id` = %d AND `network` = '%s'",
 					dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
 					dbesc($contact["addr"]), dbesc($contact["keywords"]), dbesc($contact["bdyear"]),
-					dbesc($contact["bd"]), dbesc($contact["avatar-date"]), dbesc($contact["name-date"]), dbesc($contact["uri-date"]),
+					dbesc($contact["bd"]), dbesc($contact["name-date"]), dbesc($contact["uri-date"]),
 					intval($contact["id"]), dbesc($contact["network"]));
 			}
 
-			update_contact_avatar($author["avatar"], $importer["uid"], $contact["id"], ($contact["avatar-date"] != $r[0]["avatar-date"]));
+			update_contact_avatar($author["avatar"], $importer["uid"], $contact["id"],
+						(strtotime($contact["avatar-date"]) > strtotime($r[0]["avatar-date"])));
 
 			$contact["generation"] = 2;
 			$contact["photo"] = $author["avatar"];
@@ -301,6 +301,8 @@ class dfrn2 {
 		);
 
 		notification($notif_params);
+
+		logger("Mail is processed, notification was sent.");
 	}
 
 	private function process_suggestion($xpath, $suggestion, $importer) {
@@ -638,13 +640,6 @@ class dfrn2 {
 		$item["owner-link"] = $owner["link"];
 		$item["owner-avatar"] = $owner["avatar"];
 
-		// At the moment we trust the importer array
-		//if ($header["contact-id"] != $owner["contact-id"])
-		//	$item["contact-id"] = $owner["contact-id"];
-
-		if (($header["network"] != $owner["network"]) AND ($owner["network"] != ""))
-			$item["network"] = $owner["network"];
-
 		// fetch the author
 		$author = self::fetchauthor($xpath, $entry, $importer, "atom:author", true);
 
@@ -652,13 +647,6 @@ class dfrn2 {
 		$item["author-link"] = $author["link"];
 		$item["author-avatar"] = $author["avatar"];
 
-		// At the moment we trust the importer array
-		//if ($header["contact-id"] != $author["contact-id"])
-		//	$item["contact-id"] = $author["contact-id"];
-
-		if (($header["network"] != $author["network"]) AND ($author["network"] != ""))
-			$item["network"] = $author["network"];
-
 		$item["title"] = $xpath->query("atom:title/text()", $entry)->item(0)->nodeValue;
 
 		$item["created"] = $xpath->query("atom:published/text()", $entry)->item(0)->nodeValue;
@@ -779,16 +767,31 @@ class dfrn2 {
 		$entrytype = self::get_entry_type($importer, $item);
 
 		// Now assign the rest of the values that depend on the type of the message
-		if ($entrytype == DFRN_REPLY_RC) {
+		if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) {
 			if (!isset($item["object-type"]))
 				$item["object-type"] = ACTIVITY_OBJ_COMMENT;
 
+			if ($item["contact-id"] != $owner["contact-id"])
+				$item["contact-id"] = $owner["contact-id"];
+
+			if (($item["network"] != $owner["network"]) AND ($owner["network"] != ""))
+				$item["network"] = $owner["network"];
+
+			if ($item["contact-id"] != $author["contact-id"])
+				$item["contact-id"] = $author["contact-id"];
+
+			if (($item["network"] != $author["network"]) AND ($author["network"] != ""))
+				$item["network"] = $author["network"];
+		}
+
+		if ($entrytype == DFRN_REPLY_RC) {
 			$item["type"] = "remote-comment";
 			$item["wall"] = 1;
-		} elseif ($entrytype == DFRN_REPLY) {
-			if (!isset($item["object-type"]))
-				$item["object-type"] = ACTIVITY_OBJ_COMMENT;
 		} else {
+			// The Diaspora signature is only stored in replies
+			// Since this isn't a field in the item table this would create a bug when inserting this in the item table
+			unset($item["dsprsig"]);
+
 			if (!isset($item["object-type"]))
 				$item["object-type"] = ACTIVITY_OBJ_NOTE;
 
@@ -892,7 +895,7 @@ class dfrn2 {
 
 			if($posted_id) {
 
-				logger("Reply was stored with id ".$posted_id, LOGGER_DEBUG);
+				logger("Reply from contact ".$item["contact-id"]." was stored with id ".$posted_id, LOGGER_DEBUG);
 
 				$item["id"] = $posted_id;
 
diff --git a/include/items.php b/include/items.php
index f1291d6490..0ec645cc7a 100644
--- a/include/items.php
+++ b/include/items.php
@@ -17,7 +17,7 @@ require_once('include/feed.php');
 require_once('include/Contact.php');
 require_once('mod/share.php');
 require_once('include/enotify.php');
-//require_once('include/import-dfrn.php');
+require_once('include/import-dfrn.php');
 
 require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
 
@@ -2424,7 +2424,7 @@ function item_is_remote_self($contact, &$datarray) {
 
 function local_delivery($importer,$data) {
 	// dfrn-Test
-	//return dfrn2::import($data, $importer);
+	return dfrn2::import($data, $importer);
 
 	require_once('library/simplepie/simplepie.inc');
 

From 9a54afa629acc58a8e1df9dd48a2dd1f718b8a77 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Thu, 4 Feb 2016 14:47:20 +0100
Subject: [PATCH 029/273] Forum class - rename Class CamelCase and rename some
 methods

---
 include/{forum.php => Forum.php} | 12 ++++++------
 include/identity.php             |  4 ++--
 mod/network.php                  |  4 ++--
 mod/ping.php                     |  4 ++--
 view/theme/vier/theme.php        |  4 ++--
 5 files changed, 14 insertions(+), 14 deletions(-)
 rename include/{forum.php => Forum.php} (92%)

diff --git a/include/forum.php b/include/Forum.php
similarity index 92%
rename from include/forum.php
rename to include/Forum.php
index 290f0134a1..847affa875 100644
--- a/include/forum.php
+++ b/include/Forum.php
@@ -8,7 +8,7 @@
 /**
  * @brief This class handles functions related to the forum functionality
  */
-class forum {
+class Forum {
 
 	/**
 	 * @brief Function to list all forums a user is connected with
@@ -27,7 +27,7 @@ class forum {
 	 *	'id'	=> number of the key from the array
 	 *	'micro' => contact photo in format micro
 	 */
-	public static function get_forumlist($uid, $showhidden = true, $lastitem, $showprivate = false) {
+	public static function get_list($uid, $showhidden = true, $lastitem, $showprivate = false) {
 
 		$forumlist = array();
 
@@ -72,7 +72,7 @@ class forum {
 	 *	The contact id which is used to mark a forum as "selected"
 	 * @return string
 	 */
-	public static function widget_forumlist($uid,$cid = 0) {
+	public static function widget($uid,$cid = 0) {
 
 		if(! intval(feature_enabled(local_user(),'forumlist_widget')))
 			return;
@@ -82,7 +82,7 @@ class forum {
 		//sort by last updated item
 		$lastitem = true;
 
-		$contacts = self::get_forumlist($uid,true,$lastitem, true);
+		$contacts = self::get_list($uid,true,$lastitem, true);
 		$total = count($contacts);
 		$visible_forums = 10;
 
@@ -131,7 +131,7 @@ class forum {
 	 * @return string
 	 *
 	 */
-	public static function forumlist_profile_advanced($uid) {
+	public static function profile_advanced($uid) {
 
 		$profile = intval(feature_enabled($uid,'forumlist_profile'));
 		if(! $profile)
@@ -145,7 +145,7 @@ class forum {
 		//don't sort by last updated item
 		$lastitem = false;
 
-		$contacts = self::get_forumlist($uid,false,$lastitem,false);
+		$contacts = self::get_list($uid,false,$lastitem,false);
 
 		$total_shown = 0;
 
diff --git a/include/identity.php b/include/identity.php
index 87c91e6dcc..a6932f0911 100644
--- a/include/identity.php
+++ b/include/identity.php
@@ -3,7 +3,7 @@
  * @file include/identity.php
  */
 
-require_once('include/forum.php');
+require_once('include/Forum.php');
 require_once('include/bbcode.php');
 require_once("mod/proxy.php");
 
@@ -655,7 +655,7 @@ function advanced_profile(&$a) {
 	
 		//show subcribed forum if it is enabled in the usersettings
 		if (feature_enabled($uid,'forumlist_profile')) {
-			$profile['forumlist'] = array( t('Forums:'), forum::forumlist_profile_advanced($uid));
+			$profile['forumlist'] = array( t('Forums:'), Forum::profile_advanced($uid));
 		}
 
 		if ($a->profile['uid'] == local_user())
diff --git a/mod/network.php b/mod/network.php
index 151384cd67..b72d72d78f 100644
--- a/mod/network.php
+++ b/mod/network.php
@@ -114,7 +114,7 @@ function network_init(&$a) {
 	require_once('include/group.php');
 	require_once('include/contact_widgets.php');
 	require_once('include/items.php');
-	require_once('include/forum.php');
+	require_once('include/Forum.php');
 
 	if(! x($a->page,'aside'))
 		$a->page['aside'] = '';
@@ -148,7 +148,7 @@ function network_init(&$a) {
 	}
 
 	$a->page['aside'] .= (feature_enabled(local_user(),'groups') ? group_side('network/0','network','standard',$group_id) : '');
-	$a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? forum::widget_forumlist(local_user(),$cid) : '');
+	$a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? Forum::widget(local_user(),$cid) : '');
 	$a->page['aside'] .= posted_date_widget($a->get_baseurl() . '/network',local_user(),false);
 	$a->page['aside'] .= networks_widget($a->get_baseurl(true) . '/network',(x($_GET, 'nets') ? $_GET['nets'] : ''));
 	$a->page['aside'] .= saved_searches($search);
diff --git a/mod/ping.php b/mod/ping.php
index 3d34e2fe62..2abad13b0b 100644
--- a/mod/ping.php
+++ b/mod/ping.php
@@ -1,7 +1,7 @@
 <?php
 require_once("include/datetime.php");
 require_once('include/bbcode.php');
-require_once('include/forum.php');
+require_once('include/Forum.php');
 require_once('include/group.php');
 require_once("mod/proxy.php");
 
@@ -96,7 +96,7 @@ function ping_init(&$a) {
 			}
 
 			if(intval(feature_enabled(local_user(),'forumlist_widget'))) {
-				$forums_unseen = forum::count_unseen_items();
+				$forums_unseen = Forum::count_unseen_items();
 			}
 		}
 
diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php
index 93a6d5ce08..cd2c31f188 100644
--- a/view/theme/vier/theme.php
+++ b/view/theme/vier/theme.php
@@ -220,7 +220,7 @@ function vier_community_info() {
 	//Community_Pages at right_aside
 	if($show_pages AND local_user()) {
 
-		require_once('include/forum.php');
+		require_once('include/Forum.php');
 
 		if(x($_GET['cid']) && intval($_GET['cid']) != 0)
 			$cid = $_GET['cid'];
@@ -228,7 +228,7 @@ function vier_community_info() {
 		//sort by last updated item
 		$lastitem = true;
 
-		$contacts = forum::get_forumlist($a->user['uid'],true,$lastitem, true);
+		$contacts = Forum::get_list($a->user['uid'],true,$lastitem, true);
 		$total = count($contacts);
 		$visible_forums = 10;
 

From 52dbb0b4a2fd4aa4d747605e329002334a26dd72 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Thu, 4 Feb 2016 14:51:54 +0100
Subject: [PATCH 030/273] Forum class - rename Class CamelCase and rename some
 methods

---
 include/{Forum.php => ForumManager.php} | 2 +-
 include/identity.php                    | 4 ++--
 mod/network.php                         | 4 ++--
 mod/ping.php                            | 4 ++--
 view/theme/vier/theme.php               | 4 ++--
 5 files changed, 9 insertions(+), 9 deletions(-)
 rename include/{Forum.php => ForumManager.php} (99%)

diff --git a/include/Forum.php b/include/ForumManager.php
similarity index 99%
rename from include/Forum.php
rename to include/ForumManager.php
index 847affa875..49417d1831 100644
--- a/include/Forum.php
+++ b/include/ForumManager.php
@@ -8,7 +8,7 @@
 /**
  * @brief This class handles functions related to the forum functionality
  */
-class Forum {
+class ForumManager {
 
 	/**
 	 * @brief Function to list all forums a user is connected with
diff --git a/include/identity.php b/include/identity.php
index a6932f0911..ec66225d0f 100644
--- a/include/identity.php
+++ b/include/identity.php
@@ -3,7 +3,7 @@
  * @file include/identity.php
  */
 
-require_once('include/Forum.php');
+require_once('include/ForumManager.php');
 require_once('include/bbcode.php');
 require_once("mod/proxy.php");
 
@@ -655,7 +655,7 @@ function advanced_profile(&$a) {
 	
 		//show subcribed forum if it is enabled in the usersettings
 		if (feature_enabled($uid,'forumlist_profile')) {
-			$profile['forumlist'] = array( t('Forums:'), Forum::profile_advanced($uid));
+			$profile['forumlist'] = array( t('Forums:'), ForumManager::profile_advanced($uid));
 		}
 
 		if ($a->profile['uid'] == local_user())
diff --git a/mod/network.php b/mod/network.php
index b72d72d78f..0010a3d824 100644
--- a/mod/network.php
+++ b/mod/network.php
@@ -114,7 +114,7 @@ function network_init(&$a) {
 	require_once('include/group.php');
 	require_once('include/contact_widgets.php');
 	require_once('include/items.php');
-	require_once('include/Forum.php');
+	require_once('include/ForumManager.php');
 
 	if(! x($a->page,'aside'))
 		$a->page['aside'] = '';
@@ -148,7 +148,7 @@ function network_init(&$a) {
 	}
 
 	$a->page['aside'] .= (feature_enabled(local_user(),'groups') ? group_side('network/0','network','standard',$group_id) : '');
-	$a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? Forum::widget(local_user(),$cid) : '');
+	$a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? ForumManager::widget(local_user(),$cid) : '');
 	$a->page['aside'] .= posted_date_widget($a->get_baseurl() . '/network',local_user(),false);
 	$a->page['aside'] .= networks_widget($a->get_baseurl(true) . '/network',(x($_GET, 'nets') ? $_GET['nets'] : ''));
 	$a->page['aside'] .= saved_searches($search);
diff --git a/mod/ping.php b/mod/ping.php
index 2abad13b0b..577a2c6c82 100644
--- a/mod/ping.php
+++ b/mod/ping.php
@@ -1,7 +1,7 @@
 <?php
 require_once("include/datetime.php");
 require_once('include/bbcode.php');
-require_once('include/Forum.php');
+require_once('include/ForumManager.php');
 require_once('include/group.php');
 require_once("mod/proxy.php");
 
@@ -96,7 +96,7 @@ function ping_init(&$a) {
 			}
 
 			if(intval(feature_enabled(local_user(),'forumlist_widget'))) {
-				$forums_unseen = Forum::count_unseen_items();
+				$forums_unseen = ForumManager::count_unseen_items();
 			}
 		}
 
diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php
index cd2c31f188..c2669f5a93 100644
--- a/view/theme/vier/theme.php
+++ b/view/theme/vier/theme.php
@@ -220,7 +220,7 @@ function vier_community_info() {
 	//Community_Pages at right_aside
 	if($show_pages AND local_user()) {
 
-		require_once('include/Forum.php');
+		require_once('include/ForumManager.php');
 
 		if(x($_GET['cid']) && intval($_GET['cid']) != 0)
 			$cid = $_GET['cid'];
@@ -228,7 +228,7 @@ function vier_community_info() {
 		//sort by last updated item
 		$lastitem = true;
 
-		$contacts = Forum::get_list($a->user['uid'],true,$lastitem, true);
+		$contacts = ForumManager::get_list($a->user['uid'],true,$lastitem, true);
 		$total = count($contacts);
 		$visible_forums = 10;
 

From 0390001d4e9244f114e3021c6ae243cdd77d99c9 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 4 Feb 2016 15:53:22 +0100
Subject: [PATCH 031/273] Added some more logging

---
 include/import-dfrn.php | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index 87b2273ef4..c4b3fed361 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -95,8 +95,6 @@ class dfrn2 {
 			$author["avatar"] = current($avatarlist);
 		}
 
-		//$onlyfetch = true; // Test
-
 		if ($r AND !$onlyfetch) {
 
 			// When was the last change to name or uri?
@@ -481,11 +479,13 @@ class dfrn2 {
 	}
 
 	private function update_content($current, $item, $importer, $entrytype) {
+		$changed = false;
+
 		if (edited_timestamp_is_newer($current, $item)) {
 
 			// do not accept (ignore) an earlier edit than one we currently have.
 			if(datetime_convert("UTC","UTC",$item["edited"]) < $current["edited"])
-				return;
+				return(false);
 
 			$r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
 				dbesc($item["title"]),
@@ -499,6 +499,8 @@ class dfrn2 {
 			create_tags_from_itemuri($item["uri"], $importer["importer_uid"]);
 			update_thread_uri($item["uri"], $importer["importer_uid"]);
 
+			$changed = true;
+
 			if ($entrytype == DFRN_REPLY_RC)
 				proc_run("php", "include/notifier.php","comment-import", $current["id"]);
 		}
@@ -517,6 +519,7 @@ class dfrn2 {
 				intval($importer["importer_uid"])
 			);
 		}
+		return $changed;
 	}
 
 	private function get_entry_type($importer, $item) {
@@ -812,7 +815,8 @@ class dfrn2 {
 					if(count($r))
 						$ev["id"] = $r[0]["id"];
 						$xyz = event_store($ev);
-							return;
+						logger("Event ".$ev["id"]." was stored", LOGGER_DEBUG);
+						return;
 				}
 			}
 		}
@@ -824,13 +828,18 @@ class dfrn2 {
 
 		// Update content if 'updated' changes
 		if(count($r)) {
-			self::update_content($r[0], $item, $importer, $entrytype);
+			if (self::update_content($r[0], $item, $importer, $entrytype))
+				logger("Item ".$item["uri"]." was updated.", LOGGER_DEBUG);
+			else
+				logger("Item ".$item["uri"]." already existed.", LOGGER_DEBUG);
 			return;
 		}
 
 		if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) {
-			if($importer["rel"] == CONTACT_IS_FOLLOWER)
+			if($importer["rel"] == CONTACT_IS_FOLLOWER) {
+				logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG);
 				return;
+			}
 
 			if(($item["verb"] === ACTIVITY_LIKE)
 				|| ($item["verb"] === ACTIVITY_DISLIKE)
@@ -931,6 +940,7 @@ class dfrn2 {
 			}
 		} else {
 			if(!link_compare($item["owner-link"],$importer["url"])) {
+				/// @todo Check if this is really used
 				// The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
 				// but otherwise there's a possible data mixup on the sender's system.
 				// the tgroup delivery code called from item_store will correct it if it's a forum,

From 12c6ba9081e05ecb2b9ebcbb16aeb0b7dfc0eb55 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Thu, 4 Feb 2016 16:21:40 +0100
Subject: [PATCH 032/273] vier: remove some hardcoded css to be more mobile
 friendly

---
 view/theme/vier/style.css | 67 +++++++++++----------------------------
 1 file changed, 19 insertions(+), 48 deletions(-)

diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css
index 7d7e2683a4..8c03277976 100644
--- a/view/theme/vier/style.css
+++ b/view/theme/vier/style.css
@@ -1583,63 +1583,34 @@ section.minimal {
   width: calc(100% - 165px);
 }
 
-.wall-item-container.comment .wall-item-content {
-  max-width: 585px;
-}
-.wall-item-container.thread_level_3 .wall-item-content {
-  max-width: 570px;
-}
-.wall-item-container.thread_level_4 .wall-item-content {
-  max-width: 555px;
-}
-.wall-item-container.thread_level_5 .wall-item-content {
-  max-width: 540px;
-}
-.wall-item-container.thread_level_6 .wall-item-content {
-  max-width: 525px;
-}
+.wall-item-container.comment .wall-item-content,
+.wall-item-container.thread_level_3 .wall-item-content,
+.wall-item-container.thread_level_4 .wall-item-content,
+.wall-item-container.thread_level_5 .wall-item-content,
+.wall-item-container.thread_level_6 .wall-item-content,
 .wall-item-container.thread_level_7 .wall-item-content {
-  max-width: 510px;
+  max-width: calc(100% - 1px);
 }
 
-.children .wall-item-comment-wrapper textarea {
-  width: 570px;
-}
-.wall-item-container.thread_level_3 .wall-item-comment-wrapper textarea {
-  width: 555px;
-}
-.wall-item-container.thread_level_4 .wall-item-comment-wrapper textarea {
-  width: 540px;
-}
-.wall-item-container.thread_level_5 .wall-item-comment-wrapper textarea {
-  width: 525px;
-}
-.wall-item-container.thread_level_6 .wall-item-comment-wrapper textarea {
-  width: 510px;
-}
+.children .wall-item-comment-wrapper textarea, 
+.wall-item-container.thread_level_3 .wall-item-comment-wrapper textarea,
+.wall-item-container.thread_level_4 .wall-item-comment-wrapper textarea,
+.wall-item-container.thread_level_5 .wall-item-comment-wrapper textarea,
+.wall-item-container.thread_level_6 .wall-item-comment-wrapper textarea,
 .wall-item-container.thread_level_7 .wall-item-comment-wrapper textarea {
-  width: 495px;
+  width: calc(100% - 11px);
 }
 
-.children .wall-item-bottom .comment-edit-preview {
-  width: 575px;
-}
-.wall-item-container.thread_level_3 .wall-item-bottom .comment-edit-preview {
-  width: 560px;
-}
-.wall-item-container.thread_level_4 .wall-item-bottom .comment-edit-preview {
-  width: 545px;
-}
-.wall-item-container.thread_level_5 .wall-item-bottom .comment-edit-preview {
-  width: 530px;
-}
-.wall-item-container.thread_level_6 .wall-item-bottom .comment-edit-preview {
-  width: 515px;
-}
+.children .wall-item-bottom .comment-edit-preview,
+.wall-item-container.thread_level_3 .wall-item-bottom .comment-edit-preview,
+.wall-item-container.thread_level_4 .wall-item-bottom .comment-edit-preview,
+.wall-item-container.thread_level_5 .wall-item-bottom .comment-edit-preview,
+.wall-item-container.thread_level_6 .wall-item-bottom .comment-edit-preview,
 .wall-item-container.thread_level_7 .wall-item-bottom .comment-edit-preview {
-  width: 500px;
+  width: calc(100% - 6px);
 }
 
+
 .wall-item-container.comment .contact-photo {
   width: 32px;
   height: 32px;

From a75be65860391ea81e91ba28d2b4047c8b3bcc02 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Thu, 4 Feb 2016 16:45:39 +0100
Subject: [PATCH 033/273] vier: little float fix

---
 view/theme/vier/style.css | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css
index 8c03277976..39d2af680b 100644
--- a/view/theme/vier/style.css
+++ b/view/theme/vier/style.css
@@ -1042,6 +1042,9 @@ aside {
   box-shadow: 1px 2px 0px 0px #D8D8D8;
   color: #737373;
 }
+aside .vcard .tool {
+  clear: both;
+}
 aside .vcard .fn {
   font-size: 18px;
   font-weight: bold;
@@ -1050,7 +1053,6 @@ aside .vcard .fn {
 }
 aside .vcard .title {
   margin-bottom: 5px;
-  float: left;
 }
 aside .vcard dl {
   height: auto;

From b85369a03bcc10c8f6860be11e129c03dd49c141 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 4 Feb 2016 18:58:33 +0100
Subject: [PATCH 034/273] Vier: The font "system" can make the system look ugly

---
 view/theme/vier/style.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css
index e0abee837c..7d56f6c402 100644
--- a/view/theme/vier/style.css
+++ b/view/theme/vier/style.css
@@ -269,7 +269,7 @@ div.pager {
 /* global */
 body {
 /*  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; */
-  font-family: system,-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Helvetica,Arial,sans-serif;
+  font-family: -apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Helvetica,Arial,sans-serif;
   font-size: 14px;
   /* font-size: 13px;
   line-height: 19.5px; */

From acefb846810434a77335862bfb9bd1294c079a9c Mon Sep 17 00:00:00 2001
From: Andrej Stieben <e-mail@stieben.de>
Date: Thu, 4 Feb 2016 19:37:06 +0100
Subject: [PATCH 035/273] Improved documentation formatting (of Plugins.md)

---
 doc/Plugins.md    | 101 +++++++++++++++++++++++-----------------------
 doc/de/Plugins.md |  75 ++++++++++++++++++----------------
 2 files changed, 92 insertions(+), 84 deletions(-)

diff --git a/doc/Plugins.md b/doc/Plugins.md
index 24d403e1f6..a30a3f4a71 100644
--- a/doc/Plugins.md
+++ b/doc/Plugins.md
@@ -1,5 +1,7 @@
 Friendica Addon/Plugin development
-==========================
+==============
+
+* [Home](help)
 
 Please see the sample addon 'randplace' for a working example of using some of these features.
 Addons work by intercepting event hooks - which must be registered.
@@ -16,12 +18,12 @@ Future extensions may provide for "setup" amd "remove".
 
 Plugins should contain a comment block with the four following parameters:
 
-	/*
-	* Name: My Great Plugin
- 	* Description: This is what my plugin does. It's really cool
- 	* Version: 1.0
- 	* Author: John Q. Public <john@myfriendicasite.com>
-	*/
+    /*
+     * Name: My Great Plugin
+     * Description: This is what my plugin does. It's really cool.
+     * Version: 1.0
+     * Author: John Q. Public <john@myfriendicasite.com>
+     */
 
 Register your plugin hooks during installation.
 
@@ -45,7 +47,7 @@ Your hook callback functions will be called with at least one and possibly two a
 
 If you wish to make changes to the calling data, you must declare them as reference variables (with '&') during function declaration.
 
-###$a
+#### $a
 $a is the Friendica 'App' class.
 It contains a wealth of information about the current state of Friendica:
 
@@ -56,13 +58,13 @@ It contains a wealth of information about the current state of Friendica:
 
 It is recommeded you call this '$a' to match its usage elsewhere.
 
-###$b
+#### $b
 $b can be called anything you like.
 This is information specific to the hook currently being processed, and generally contains information that is being immediately processed or acted on that you can use, display, or alter.
 Remember to declare it with '&' if you wish to alter it.
 
 Modules
---------
+---
 
 Plugins/addons may also act as "modules" and intercept all page requests for a given URL path.
 In order for a plugin to act as a module it needs to define a function "plugin_name_module()" which takes no arguments and needs not do anything.
@@ -72,15 +74,15 @@ These are parsed into an array $a->argv, with a corresponding $a->argc indicatin
 So http://my.web.site/plugin/arg1/arg2 would look for a module named "plugin" and pass its module functions the $a App structure (which is available to many components).
 This will include:
 
-     $a->argc = 3
-     $a->argv = array(0 => 'plugin', 1 => 'arg1', 2 => 'arg2');
+    $a->argc = 3
+    $a->argv = array(0 => 'plugin', 1 => 'arg1', 2 => 'arg2');
 
 Your module functions will often contain the function plugin_name_content(&$a), which defines and returns the page body content.
 They may also contain plugin_name_post(&$a) which is called before the _content function and typically handles the results of POST forms.
 You may also have plugin_name_init(&$a) which is called very early on and often does module initialisation.
 
 Templates
-----------
+---
 
 If your plugin needs some template, you can use the Friendica template system.
 Friendica uses [smarty3](http://www.smarty.net/) as a template engine.
@@ -104,140 +106,140 @@ See also the wiki page [Quick Template Guide](https://github.com/friendica/frien
 Current hooks
 -------------
 
-###'authenticate'
+### 'authenticate'
 'authenticate' is called when a user attempts to login.
 $b is an array containing:
 
-	'username' => the supplied username
-	'password' => the supplied password
+    'username' => the supplied username
+    'password' => the supplied password
     'authenticated' => set this to non-zero to authenticate the user.
     'user_record' => successful authentication must also return a valid user record from the database
 
-###'logged_in'
+### 'logged_in'
 'logged_in' is called after a user has successfully logged in.
 $b contains the $a->user array.
 
-###'display_item'
+### 'display_item'
 'display_item' is called when formatting a post for display.
 $b is an array:
 
 	'item' => The item (array) details pulled from the database
 	'output' => the (string) HTML representation of this item prior to adding it to the page
 
-###'post_local'
+### 'post_local'
 * called when a status post or comment is entered on the local system
 * $b is the item array of the information to be stored in the database
 * Please note: body contents are bbcode - not HTML
 
-###'post_local_end'
+### 'post_local_end'
 * called when a local status post or comment has been stored on the local system
 * $b is the item array of the information which has just been stored in the database
 * Please note: body contents are bbcode - not HTML
 
-###'post_remote'
+### 'post_remote'
 * called when receiving a post from another source. This may also be used to post local activity or system generated messages.
 * $b is the item array of information to be stored in the database and the item body is bbcode.
 
-###'settings_form'
+### 'settings_form'
 * called when generating the HTML for the user Settings page
 * $b is the (string) HTML of the settings page before the final '</form>' tag.
 
-###'settings_post'
+### 'settings_post'
 * called when the Settings pages are submitted
 * $b is the $_POST array
 
-###'plugin_settings'
+### 'plugin_settings'
 * called when generating the HTML for the addon settings page
 * $b is the (string) HTML of the addon settings page before the final '</form>' tag.
 
-###'plugin_settings_post'
+### 'plugin_settings_post'
 * called when the Addon Settings pages are submitted
 * $b is the $_POST array
 
-###'profile_post'
+### 'profile_post'
 * called when posting a profile page
 * $b is the $_POST array
 
-###'profile_edit'
+### 'profile_edit'
 'profile_edit' is called prior to output of profile edit page.
 $b is an array containing:
 
 	'profile' => profile (array) record from the database
 	'entry' => the (string) HTML of the generated entry
 
-###'profile_advanced'
+### 'profile_advanced'
 * called when the HTML is generated for the 'Advanced profile', corresponding to the 'Profile' tab within a person's profile page
 * $b is the (string) HTML representation of the generated profile
 * The profile array details are in $a->profile.
 
-###'directory_item'
+### 'directory_item'
 'directory_item' is called from the Directory page when formatting an item for display.
 $b is an array:
 
 	'contact' => contact (array) record for the person from the database
     'entry' => the (string) HTML of the generated entry
 
-###'profile_sidebar_enter'
+### 'profile_sidebar_enter'
 * called prior to generating the sidebar "short" profile for a page
 * $b is the person's profile array
 
-###'profile_sidebar'
+### 'profile_sidebar'
 'profile_sidebar is called when generating the sidebar "short" profile for a page.
 $b is an array:
 
 	'profile' => profile (array) record for the person from the database
 	'entry' => the (string) HTML of the generated entry
 
-###'contact_block_end'
+### 'contact_block_end'
 is called when formatting the block of contacts/friends on a profile sidebar has completed.
 $b is an array:
 
 	'contacts' => array of contacts
 	'output' => the (string) generated HTML of the contact block
 
-###'bbcode'
+### 'bbcode'
 * called during conversion of bbcode to html
 * $b is a string converted text
 
-###'html2bbcode'
+### 'html2bbcode'
 * called during conversion of html to bbcode (e.g. remote message posting)
 * $b is a string converted text
 
-###'page_header'
+### 'page_header'
 * called after building the page navigation section
 * $b is a string HTML of nav region
 
-###'personal_xrd'
+### 'personal_xrd'
 'personal_xrd' is called prior to output of personal XRD file.
 $b is an array:
 
 	'user' => the user record for the person
 	'xml' => the complete XML to be output
 
-###'home_content'
+### 'home_content'
 * called prior to output home page content, shown to unlogged users
 * $b is (string) HTML of section region
 
-###'contact_edit'
+### 'contact_edit'
 is called when editing contact details on an individual from the Contacts page.
 $b is an array:
 
 	'contact' => contact record (array) of target contact
 	'output' => the (string) generated HTML of the contact edit page
 
-###'contact_edit_post'
+### 'contact_edit_post'
 * called when posting the contact edit page.
 * $b is the $_POST array
 
-###'init_1'
+### 'init_1'
 * called just after DB has been opened and before session start
 * $b is not used or passed
 
-###'page_end'
+### 'page_end'
 * called after HTML content functions have completed
 * $b is (string) HTML of content div
 
-###'avatar_lookup'
+### 'avatar_lookup'
 'avatar_lookup' is called when looking up the avatar.
 $b is an array:
 
@@ -245,11 +247,11 @@ $b is an array:
 	'email' => email to look up the avatar for
 	'url' => the (string) generated URL of the avatar
 
-###'emailer_send_prepare'
+### 'emailer_send_prepare'
 'emailer_send_prepare' called from Emailer::send() before building the mime message.
 $b is an array, params to Emailer::send()
 
-	'fromName' => name of the sender
+    'fromName' => name of the sender
     'fromEmail' => email fo the sender
     'replyTo' => replyTo address to direct responses
     'toEmail' => destination email address
@@ -258,20 +260,20 @@ $b is an array, params to Emailer::send()
     'textVersion' => text only version of the message
     'additionalMailHeader' => additions to the smtp mail header
 
-###'emailer_send'
+### 'emailer_send'
 is called before calling PHP's mail().
 $b is an array, params to mail()
 
-	'to'
-	'subject'
+    'to'
+    'subject'
     'body'
     'headers'
 
-###'nav_info'
+### 'nav_info'
 is called after the navigational menu is build in include/nav.php.
 $b is an array containing $nav from nav.php.
 
-###'template_vars'
+### 'template_vars'
 is called before vars are passed to the template engine to render the page.
 The registered function can add,change or remove variables passed to template.
 $b is an array with:
@@ -463,4 +465,3 @@ mod/cb.php:	call_hooks('cb_afterpost');
 mod/cb.php:	call_hooks('cb_content', $o);
 
 mod/directory.php:			call_hooks('directory_item', $arr);
-
diff --git a/doc/de/Plugins.md b/doc/de/Plugins.md
index dcff41a4b6..11113843bb 100644
--- a/doc/de/Plugins.md
+++ b/doc/de/Plugins.md
@@ -1,27 +1,27 @@
-**Friendica Addon/Plugin-Entwicklung**
+Friendica Addon/Plugin-Entwicklung
 ==============
 
 * [Zur Startseite der Hilfe](help)
 
-Bitte schau dir das Beispiel-Addon "randplace" für ein funktionierendes Beispiel für manche der hier aufgeführten Funktionen an. 
-Das Facebook-Addon bietet ein Beispiel dafür, die "addon"- und "module"-Funktion gemeinsam zu integrieren. 
-Addons arbeiten, indem sie Event Hooks abfangen. Module arbeiten, indem bestimmte Seitenanfragen (durch den URL-Pfad) abgefangen werden 
+Bitte schau dir das Beispiel-Addon "randplace" für ein funktionierendes Beispiel für manche der hier aufgeführten Funktionen an.
+Das Facebook-Addon bietet ein Beispiel dafür, die "addon"- und "module"-Funktion gemeinsam zu integrieren.
+Addons arbeiten, indem sie Event Hooks abfangen. Module arbeiten, indem bestimmte Seitenanfragen (durch den URL-Pfad) abgefangen werden
 
-Plugin-Namen können keine Leerstellen oder andere Interpunktionen enthalten und werden als Datei- und Funktionsnamen genutzt. 
-Du kannst einen lesbaren Namen im Kommentarblock eintragen. 
-Jedes Addon muss beides beinhalten - eine Installations- und eine Deinstallationsfunktion, die auf dem Addon-/Plugin-Namen basieren; z.B. "plugin1name_install()". 
-Diese beiden Funktionen haben keine Argumente und sind dafür verantwortlich, Event Hooks zu registrieren und abzumelden (unregistering), die dein Plugin benötigt. 
-Die Installations- und Deinstallationsfunktionfunktionen werden auch ausgeführt (z.B. neu installiert), wenn sich das Plugin nach der Installation ändert - somit sollte deine Deinstallationsfunktion keine Daten zerstört und deine Installationsfunktion sollte bestehende Daten berücksichtigen. 
+Plugin-Namen können keine Leerstellen oder andere Interpunktionen enthalten und werden als Datei- und Funktionsnamen genutzt.
+Du kannst einen lesbaren Namen im Kommentarblock eintragen.
+Jedes Addon muss beides beinhalten - eine Installations- und eine Deinstallationsfunktion, die auf dem Addon-/Plugin-Namen basieren; z.B. "plugin1name_install()".
+Diese beiden Funktionen haben keine Argumente und sind dafür verantwortlich, Event Hooks zu registrieren und abzumelden (unregistering), die dein Plugin benötigt.
+Die Installations- und Deinstallationsfunktionfunktionen werden auch ausgeführt (z.B. neu installiert), wenn sich das Plugin nach der Installation ändert - somit sollte deine Deinstallationsfunktion keine Daten zerstört und deine Installationsfunktion sollte bestehende Daten berücksichtigen.
 Zukünftige Extensions werden möglicherweise "Setup" und "Entfernen" anbieten.
 
 Plugins sollten einen Kommentarblock mit den folgenden vier Parametern enthalten:
 
-	/*
-	* Name: My Great Plugin 
- 	* Description: This is what my plugin does. It's really cool
- 	* Version: 1.0
- 	* Author: John Q. Public <john@myfriendicasite.com>
-	*/
+    /*
+     * Name: My Great Plugin
+     * Description: This is what my plugin does. It's really cool
+     * Version: 1.0
+     * Author: John Q. Public <john@myfriendicasite.com>
+     */
 
 Registriere deine Plugin-Hooks während der Installation.
 
@@ -29,45 +29,50 @@ Registriere deine Plugin-Hooks während der Installation.
 
 $hookname ist ein String und entspricht einem bekannten Friendica-Hook.
 
-$file steht für den Pfadnamen, der relativ zum Top-Level-Friendicaverzeichnis liegt. 
+$file steht für den Pfadnamen, der relativ zum Top-Level-Friendicaverzeichnis liegt.
 Das *sollte* "addon/plugin_name/plugin_name.php' sein.
 
 $function ist ein String und der Name der Funktion, die ausgeführt wird, wenn der Hook aufgerufen wird.
 
+Argumente
+---
+
 Deine Hook-Callback-Funktion wird mit mindestens einem und bis zu zwei Argumenten aufgerufen
 
     function myhook_function(&$a, &$b) {
 
     }
 
-Wenn du Änderungen an den aufgerufenen Daten vornehmen willst, musst du diese als Referenzvariable (mit "&") während der Funktionsdeklaration deklarieren. 
+Wenn du Änderungen an den aufgerufenen Daten vornehmen willst, musst du diese als Referenzvariable (mit "&") während der Funktionsdeklaration deklarieren.
 
-$a ist die Friendica "App"-Klasse, die eine Menge an Informationen über den aktuellen Friendica-Status beinhaltet, u.a. welche Module genutzt werden, Konfigurationsinformationen, Inhalte der Seite zum Zeitpunkt des Hook-Aufrufs. 
-Es ist empfohlen, diese Funktion "$a" zu nennen, um seine Nutzung an den Gebrauch an anderer Stelle anzugleichen. 
+$a ist die Friendica "App"-Klasse, die eine Menge an Informationen über den aktuellen Friendica-Status beinhaltet, u.a. welche Module genutzt werden, Konfigurationsinformationen, Inhalte der Seite zum Zeitpunkt des Hook-Aufrufs.
+Es ist empfohlen, diese Funktion "$a" zu nennen, um seine Nutzung an den Gebrauch an anderer Stelle anzugleichen.
 
-$b kann frei benannt werden. 
-Diese Information ist speziell auf den Hook bezogen, der aktuell bearbeitet wird, und beinhaltet normalerweise Daten, die du sofort nutzen, anzeigen oder bearbeiten kannst. 
-Achte darauf, diese mit "&" zu deklarieren, wenn du sie bearbeiten willst. 
+$b kann frei benannt werden.
+Diese Information ist speziell auf den Hook bezogen, der aktuell bearbeitet wird, und beinhaltet normalerweise Daten, die du sofort nutzen, anzeigen oder bearbeiten kannst.
+Achte darauf, diese mit "&" zu deklarieren, wenn du sie bearbeiten willst.
 
 
-**Module**
+Module
+---
 
-Plugins/Addons können auch als "Module" agieren und alle Seitenanfragen für eine bestimte URL abfangen. 
-Um ein Plugin als Modul zu nutzen, ist es nötig, die Funktion "plugin_name_module()" zu definieren, die keine Argumente benötigt und nichts weiter machen muss. 
+Plugins/Addons können auch als "Module" agieren und alle Seitenanfragen für eine bestimte URL abfangen.
+Um ein Plugin als Modul zu nutzen, ist es nötig, die Funktion "plugin_name_module()" zu definieren, die keine Argumente benötigt und nichts weiter machen muss.
 
-Wenn diese Funktion existiert, wirst du nun alle Seitenanfragen für "http://my.web.site/plugin_name" erhalten - mit allen URL-Komponenten als zusätzliche Argumente. 
-Diese werden in ein Array $a->argv geparst und stimmen mit $a->argc überein, wobei sie die Anzahl der URL-Komponenten abbilden. 
+Wenn diese Funktion existiert, wirst du nun alle Seitenanfragen für "http://my.web.site/plugin_name" erhalten - mit allen URL-Komponenten als zusätzliche Argumente.
+Diese werden in ein Array $a->argv geparst und stimmen mit $a->argc überein, wobei sie die Anzahl der URL-Komponenten abbilden.
 So würde http://my.web.site/plugin/arg1/arg2 nach einem Modul "plugin" suchen und seiner Modulfunktion die $a-App-Strukur übergeben (dies ist für viele Komponenten verfügbar). Das umfasst:
 
-     $a->argc = 3
-     $a->argv = array(0 => 'plugin', 1 => 'arg1', 2 => 'arg2');
+    $a->argc = 3
+    $a->argv = array(0 => 'plugin', 1 => 'arg1', 2 => 'arg2');
 
-Deine Modulfunktionen umfassen oft die Funktion plugin_name_content(&$a), welche den Seiteninhalt definiert und zurückgibt. 
-Sie können auch plugin_name_post(&$a) umfassen, welches vor der content-Funktion aufgerufen wird und normalerweise die Resultate der POST-Formulare handhabt. 
+Deine Modulfunktionen umfassen oft die Funktion plugin_name_content(&$a), welche den Seiteninhalt definiert und zurückgibt.
+Sie können auch plugin_name_post(&$a) umfassen, welches vor der content-Funktion aufgerufen wird und normalerweise die Resultate der POST-Formulare handhabt.
 Du kannst ebenso plugin_name_init(&$a) nutzen, was oft frühzeitig aufgerufen wird und das Modul initialisert.
 
 
-**Derzeitige Hooks:**
+Derzeitige Hooks
+---
 
 **'authenticate'** - wird aufgerufen, wenn sich der User einloggt.
     $b ist ein Array
@@ -180,6 +185,9 @@ Du kannst ebenso plugin_name_init(&$a) nutzen, was oft frühzeitig aufgerufen wi
  - wird aufgerufen nachdem in include/nav,php der Inhalt des Navigations Menüs erzeugt wurde.
  - $b ist ein Array, das $nav wiederspiegelt.
 
+Komplette Liste der Hook-Callbacks
+---
+
 Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 14-Feb-2012 generiert): Bitte schau in die Quellcodes für Details zu Hooks, die oben nicht dokumentiert sind.
 
 boot.php:			call_hooks('login_hook',$o);
@@ -204,7 +212,7 @@ include/text.php:		call_hooks('contact_block_end', $arr);
 
 include/text.php:		call_hooks('smilie', $s);
 
-include/text.php:		call_hooks('prepare_body_init', $item); 
+include/text.php:		call_hooks('prepare_body_init', $item);
 
 include/text.php:		call_hooks('prepare_body', $prep_arr);
 
@@ -359,4 +367,3 @@ mod/cb.php:			call_hooks('cb_afterpost');
 mod/cb.php:			call_hooks('cb_content', $o);
 
 mod/directory.php:		call_hooks('directory_item', $arr);
-

From 92a31344b5e8e0c01aec325874a86808f7bba8e5 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 4 Feb 2016 20:34:18 +0100
Subject: [PATCH 036/273] Events do work now.

---
 include/import-dfrn.php | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index c4b3fed361..edbbde98a0 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -5,6 +5,7 @@ require_once("include/socgraph.php");
 require_once("include/items.php");
 require_once("include/tags.php");
 require_once("include/files.php");
+require_once("include/event.php");
 
 class dfrn2 {
 
@@ -702,6 +703,12 @@ class dfrn2 {
 		$object = $xpath->query("activity:object", $entry)->item(0);
 		$item["object"] = self::transform_activity($xpath, $object, "object");
 
+		if (trim($item["object"]) != "") {
+			$r = parse_xml_string($item["object"], false);
+			if (isset($r->type))
+				$item["object-type"] = $r->type;
+		}
+
 		$target = $xpath->query("activity:target", $entry)->item(0);
 		$item["target"] = self::transform_activity($xpath, $target, "target");
 
@@ -790,7 +797,7 @@ class dfrn2 {
 		if ($entrytype == DFRN_REPLY_RC) {
 			$item["type"] = "remote-comment";
 			$item["wall"] = 1;
-		} else {
+		} elseif ($entrytype == DFRN_TOP_LEVEL) {
 			// The Diaspora signature is only stored in replies
 			// Since this isn't a field in the item table this would create a bug when inserting this in the item table
 			unset($item["dsprsig"]);
@@ -798,9 +805,11 @@ class dfrn2 {
 			if (!isset($item["object-type"]))
 				$item["object-type"] = ACTIVITY_OBJ_NOTE;
 
-			if ($item["object-type"] === ACTIVITY_OBJ_EVENT) {
+			if ($item["object-type"] == ACTIVITY_OBJ_EVENT) {
+				logger("Item ".$item["uri"]." seems to contain an event.", LOGGER_DEBUG);
 				$ev = bbtoevent($item["body"]);
 				if((x($ev, "desc") || x($ev, "summary")) && x($ev, "start")) {
+					logger("Event in item ".$item["uri"]." was found.", LOGGER_DEBUG);
 					$ev["cid"] = $importer["id"];
 					$ev["uid"] = $importer["uid"];
 					$ev["uri"] = $item["uri"];
@@ -814,9 +823,10 @@ class dfrn2 {
 					);
 					if(count($r))
 						$ev["id"] = $r[0]["id"];
-						$xyz = event_store($ev);
-						logger("Event ".$ev["id"]." was stored", LOGGER_DEBUG);
-						return;
+
+					$event_id = event_store($ev);
+					logger("Event ".$event_id." was stored", LOGGER_DEBUG);
+					return;
 				}
 			}
 		}

From 48e6ff21aa50b428a970c53f1f6618c4794fa043 Mon Sep 17 00:00:00 2001
From: Andrej Stieben <e-mail@stieben.de>
Date: Thu, 4 Feb 2016 21:45:21 +0100
Subject: [PATCH 037/273] Added the possibility for themes to override core
 module functions

---
 doc/themes.md | 16 ++++++++++++++--
 index.php     | 11 ++++++++++-
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/doc/themes.md b/doc/themes.md
index add44c776b..ec3a76ac28 100644
--- a/doc/themes.md
+++ b/doc/themes.md
@@ -59,7 +59,19 @@ The same rule applies to the JavaScript files found in
 
 they will be overwritten by files in
 
-    /view/theme/**your-theme-name**/js.
+    /view/theme/**your-theme-name**/js
+
+### Modules
+
+You have the freedom to override core modules found in
+
+    /mod
+
+They will be overwritten by files in
+
+    /view/theme/**your-theme-name**/mod
+
+Be aware that you can break things easily here if you don't know what you do. Also notice that you can override parts of the module – functions not defined in your theme module will be loaded from the core module.
 
 ## Expand an existing Theme
 
@@ -288,4 +300,4 @@ The default file is in
     /view/default.php
 
 if you want to change it, say adding a 4th column for banners of your favourite FLOSS projects, place a new default.php file in your theme directory.
-As with the theme.php file, you can use the properties of the $a variable with holds the friendica application to decide what content is displayed.
\ No newline at end of file
+As with the theme.php file, you can use the properties of the $a variable with holds the friendica application to decide what content is displayed.
diff --git a/index.php b/index.php
index bf926d1fe7..2b1053cc1b 100644
--- a/index.php
+++ b/index.php
@@ -233,7 +233,16 @@ if(strlen($a->module)) {
 	}
 
 	/**
-	 * If not, next look for a 'standard' program module in the 'mod' directory
+	 * If not, next look for module overrides by the theme
+	 */
+
+	if((! $a->module_loaded) && (file_exists("view/theme/" . current_theme() . "/mod/{$a->module}.php"))) {
+		include_once("view/theme/" . current_theme() . "/mod/{$a->module}.php");
+		// We will not set module_loaded to true to allow for partial overrides.
+	}
+
+	/**
+	 * Finally, look for a 'standard' program module in the 'mod' directory
 	 */
 
 	if((! $a->module_loaded) && (file_exists("mod/{$a->module}.php"))) {

From 2bd36e562889803841588a276232ef5fa819730a Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 4 Feb 2016 23:52:06 +0100
Subject: [PATCH 038/273] Feed should work now as well

---
 include/import-dfrn.php | 25 +++++++++++++++++++++----
 include/items.php       |  9 ++++-----
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index edbbde98a0..72d507bbf1 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -961,8 +961,10 @@ class dfrn2 {
 				$item["owner-avatar"] = $importer["thumb"];
 			}
 
-			if(($importer["rel"] == CONTACT_IS_FOLLOWER) && (!tgroup_check($importer["importer_uid"], $item)))
+			if(($importer["rel"] == CONTACT_IS_FOLLOWER) && (!tgroup_check($importer["importer_uid"], $item))) {
+				logger("Contact ".$importer["id"]." is only follower and tgroup check was negative.", LOGGER_DEBUG);
 				return;
+			}
 
 			// This is my contact on another system, but it's really me.
 			// Turn this into a wall post.
@@ -1183,9 +1185,24 @@ class dfrn2 {
 		foreach ($deletions AS $deletion)
 			self::process_deletion($header, $xpath, $deletion, $importer);
 
-		$entries = $xpath->query("/atom:feed/atom:entry");
-		foreach ($entries AS $entry)
-			self::process_entry($header, $xpath, $entry, $importer);
+		if (!$sort_by_date) {
+			$entries = $xpath->query("/atom:feed/atom:entry");
+			foreach ($entries AS $entry)
+				self::process_entry($header, $xpath, $entry, $importer);
+		} else {
+			$newentries = array();
+			$entries = $xpath->query("/atom:feed/atom:entry");
+			foreach ($entries AS $entry) {
+				$created = $xpath->query("atom:published/text()", $entry)->item(0)->nodeValue;
+				$newentries[strtotime($created)] = $entry;
+			}
+
+			// Now sort after the publishing date
+			ksort($newentries);
+
+			foreach ($newentries AS $entry)
+				self::process_entry($header, $xpath, $entry, $importer);
+		}
 	}
 }
 ?>
diff --git a/include/items.php b/include/items.php
index 0ec645cc7a..52a1071f2d 100644
--- a/include/items.php
+++ b/include/items.php
@@ -1695,11 +1695,9 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
 		}
 		return;
 	}
-	// dfrn-test
-/*
+
 	if ($contact['network'] === NETWORK_DFRN) {
 		logger("Consume DFRN messages", LOGGER_DEBUG);
-		logger("dfrn-test");
 
 		$r = q("SELECT  `contact`.*, `contact`.`uid` AS `importer_uid`,
                                         `contact`.`pubkey` AS `cpubkey`,
@@ -1711,14 +1709,15 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
                         FROM `contact`
                         LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
                         WHERE `contact`.`id` = %d AND `user`.`uid` = %d",
-	                dbesc($contact["id"], $importer["uid"]);
+	                dbesc($contact["id"]), dbesc($importer["uid"])
 	        );
 		if ($r) {
+			logger("Now import the DFRN feed");
 			dfrn2::import($xml,$r[0], true);
 			return;
 		}
 	}
-*/
+
 	// Test - remove before flight
 	//if ($pass < 2) {
 	//	$tempfile = tempnam(get_temppath(), "dfrn-consume-");

From e2a8146307123f638d035d6c34bde16c96444e88 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 5 Feb 2016 09:03:17 +0100
Subject: [PATCH 039/273] Added some to-do points

---
 include/import-dfrn.php | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/include/import-dfrn.php b/include/import-dfrn.php
index 72d507bbf1..244018887b 100644
--- a/include/import-dfrn.php
+++ b/include/import-dfrn.php
@@ -829,6 +829,26 @@ class dfrn2 {
 					return;
 				}
 			}
+/*
+			if(activity_match($item['verb'],ACTIVITY_FOLLOW)) {
+				logger('consume-feed: New follower');
+				new_follower($importer,$contact,$item);
+				return;
+			}
+			if(activity_match($item['verb'],ACTIVITY_UNFOLLOW))  {
+				lose_follower($importer,$contact,$item);
+				return;
+			}
+			if(activity_match($item['verb'],ACTIVITY_REQ_FRIEND)) {
+				logger('consume-feed: New friend request');
+				new_follower($importer,$contact,$item,(?),true);
+				return;
+			}
+			if(activity_match($item['verb'],ACTIVITY_UNFRIEND))  {
+				lose_sharer($importer,$contact,$item);
+				return;
+			}
+*/
 		}
 
 		$r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
@@ -1125,11 +1145,11 @@ class dfrn2 {
 			return;
 
 		if($importer["readonly"]) {
-	                // We aren't receiving stuff from this person. But we will quietly ignore them
-	                // rather than a blatant "go away" message.
-	                logger('ignoring contact '.$importer["id"]);
-	                return;
-	        }
+			// We aren't receiving stuff from this person. But we will quietly ignore them
+			// rather than a blatant "go away" message.
+			logger('ignoring contact '.$importer["id"]);
+			return;
+		}
 
 		$doc = new DOMDocument();
 		@$doc->loadXML($xml);
@@ -1163,6 +1183,7 @@ class dfrn2 {
 		// is it a public forum? Private forums aren't supported by now with this method
 		$forum = intval($xpath->evaluate("/atom:feed/dfrn:community/text()", $context)->item(0)->nodeValue);
 
+		/// @todo Check the opposite as well (forum changed to non-forum)
 		if ($forum)
 			q("UPDATE `contact` SET `forum` = %d WHERE `forum` != %d AND `id` = %d",
 				intval($forum), intval($forum),

From a81d929cdf223ac0ecf5407a3696db788cd705c4 Mon Sep 17 00:00:00 2001
From: Andrej Stieben <e-mail@stieben.de>
Date: Fri, 5 Feb 2016 14:11:10 +0100
Subject: [PATCH 040/273] Minor documentation update, as requested by @tobiasd

---
 doc/de/Plugins.md | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/doc/de/Plugins.md b/doc/de/Plugins.md
index 11113843bb..40be4a0695 100644
--- a/doc/de/Plugins.md
+++ b/doc/de/Plugins.md
@@ -5,7 +5,8 @@ Friendica Addon/Plugin-Entwicklung
 
 Bitte schau dir das Beispiel-Addon "randplace" für ein funktionierendes Beispiel für manche der hier aufgeführten Funktionen an.
 Das Facebook-Addon bietet ein Beispiel dafür, die "addon"- und "module"-Funktion gemeinsam zu integrieren.
-Addons arbeiten, indem sie Event Hooks abfangen. Module arbeiten, indem bestimmte Seitenanfragen (durch den URL-Pfad) abgefangen werden
+Addons arbeiten, indem sie Event Hooks abfangen.
+Module arbeiten, indem bestimmte Seitenanfragen (durch den URL-Pfad) abgefangen werden.
 
 Plugin-Namen können keine Leerstellen oder andere Interpunktionen enthalten und werden als Datei- und Funktionsnamen genutzt.
 Du kannst einen lesbaren Namen im Kommentarblock eintragen.
@@ -18,7 +19,7 @@ Plugins sollten einen Kommentarblock mit den folgenden vier Parametern enthalten
 
     /*
      * Name: My Great Plugin
-     * Description: This is what my plugin does. It's really cool
+     * Description: This is what my plugin does. It's really cool.
      * Version: 1.0
      * Author: John Q. Public <john@myfriendicasite.com>
      */
@@ -59,9 +60,9 @@ Module
 Plugins/Addons können auch als "Module" agieren und alle Seitenanfragen für eine bestimte URL abfangen.
 Um ein Plugin als Modul zu nutzen, ist es nötig, die Funktion "plugin_name_module()" zu definieren, die keine Argumente benötigt und nichts weiter machen muss.
 
-Wenn diese Funktion existiert, wirst du nun alle Seitenanfragen für "http://my.web.site/plugin_name" erhalten - mit allen URL-Komponenten als zusätzliche Argumente.
+Wenn diese Funktion existiert, wirst du nun alle Seitenanfragen für "http://example.com/plugin_name" erhalten - mit allen URL-Komponenten als zusätzliche Argumente.
 Diese werden in ein Array $a->argv geparst und stimmen mit $a->argc überein, wobei sie die Anzahl der URL-Komponenten abbilden.
-So würde http://my.web.site/plugin/arg1/arg2 nach einem Modul "plugin" suchen und seiner Modulfunktion die $a-App-Strukur übergeben (dies ist für viele Komponenten verfügbar). Das umfasst:
+So würde http://example.com/plugin/arg1/arg2 nach einem Modul "plugin" suchen und seiner Modulfunktion die $a-App-Strukur übergeben (dies ist für viele Komponenten verfügbar). Das umfasst:
 
     $a->argc = 3
     $a->argv = array(0 => 'plugin', 1 => 'arg1', 2 => 'arg2');

From f70f4bb89937d3056f71d8a2d5ba32836946186e Mon Sep 17 00:00:00 2001
From: fabrixxm <fabrix.xm@gmail.com>
Date: Fri, 5 Feb 2016 18:43:46 +0100
Subject: [PATCH 041/273] ACL: fix TypeError when selecting permissions

---
 js/acl.js | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/js/acl.js b/js/acl.js
index 8e4e06c83c..3c96d13469 100644
--- a/js/acl.js
+++ b/js/acl.js
@@ -28,7 +28,7 @@ function ACL(backend_url, preset, automention, is_mobile){
 	if (preset.length==0) this.showall.addClass("selected");
 	
 	/*events*/
-	this.showall.click(this.on_showall);
+	this.showall.click(this.on_showall.bind(this));
 	$(document).on("click", ".acl-button-show", this.on_button_show.bind(this));
 	$(document).on("click", ".acl-button-hide", this.on_button_hide.bind(this));
 	$("#acl-search").keypress(this.on_search.bind(this));
@@ -123,12 +123,8 @@ ACL.prototype.on_button_show = function(event){
 	event.preventDefault()
 	event.stopImmediatePropagation()
 	event.stopPropagation();
-
-	/*this.showall.removeClass("selected");
-	$(this).siblings(".acl-button-hide").removeClass("selected");
-	$(this).toggleClass("selected");*/
-
-	this.set_allow($(this).parent().attr('id'));
+	
+	this.set_allow($(event.target).parent().attr('id'));
 
 	return false;
 }
@@ -137,11 +133,7 @@ ACL.prototype.on_button_hide = function(event){
 	event.stopImmediatePropagation()
 	event.stopPropagation();
 
-	/*this.showall.removeClass("selected");
-	$(this).siblings(".acl-button-show").removeClass("selected");
-	$(this).toggleClass("selected");*/
-
-	this.set_deny($(this).parent().attr('id'));
+	this.set_deny($(event.target).parent().attr('id'));
 
 	return false;
 }
@@ -303,7 +295,7 @@ ACL.prototype.populate = function(data){
 		html = "<div class='acl-list-item {4} {5} type{2}' title='{6}' id='{2}{3}'>"+this.item_tpl+"</div>";
 		html = html.format(item.photo, item.name, item.type, item.id, (item.forum=='1'?'forum':''), item.network, item.link);
 		if (item.uids!=undefined) this.group_uids[item.id] = item.uids;
-		//console.log(html);
+		
 		this.list_content.append(html);
 		this.data[item.id] = item;
 	}.bind(this));

From 41405ed0f2ff24dff89e11e5ecd695fb4cf11066 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Fri, 5 Feb 2016 21:24:01 +0100
Subject: [PATCH 042/273] vier: display smiley-preview as inline-block - needs
 addons update

---
 view/theme/vier/dark.css  | 5 +++++
 view/theme/vier/style.css | 9 +++++++++
 2 files changed, 14 insertions(+)

diff --git a/view/theme/vier/dark.css b/view/theme/vier/dark.css
index 8e128ae27f..7c671e4b7d 100644
--- a/view/theme/vier/dark.css
+++ b/view/theme/vier/dark.css
@@ -63,3 +63,8 @@ li :hover {
 #viewcontact_wrapper-network {
 	background-color: #343434;
 }
+
+table.smiley-preview{
+  background-color: #252C33 !important;
+  box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.7);
+}
\ No newline at end of file
diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css
index 0b52b50960..2b78d25d7f 100644
--- a/view/theme/vier/style.css
+++ b/view/theme/vier/style.css
@@ -2024,6 +2024,15 @@ section.minimal {
   cursor: pointer;
   margin-top: 3px;
   height: 10px;
+  display: inline-block;
+}
+#smileybutton {
+  position: absolute;
+  z-index: 99;
+}
+table.smiley-preview{
+  background-color: #FFF;
+  box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.7);
 }
 #jot-perms-icon {
   float: right;

From d408cea871e00a7f3c5e58b466395802eba523f7 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 5 Feb 2016 21:25:20 +0100
Subject: [PATCH 043/273] DFRN import has now gone live

---
 include/delivery.php |    2 +-
 include/items.php    | 2145 +-----------------------------------------
 mod/dfrn_notify.php  |    3 +-
 3 files changed, 7 insertions(+), 2143 deletions(-)

diff --git a/include/delivery.php b/include/delivery.php
index 5ef942dd06..021ceb9968 100644
--- a/include/delivery.php
+++ b/include/delivery.php
@@ -374,7 +374,7 @@ function delivery_run(&$argv, &$argc){
 							break;
 
 						logger('mod-delivery: local delivery');
-						local_delivery($x[0],$atom);
+						dfrn::import($atom, $x[0]);
 						break;
 					}
 				}
diff --git a/include/items.php b/include/items.php
index 52a1071f2d..798ee56958 100644
--- a/include/items.php
+++ b/include/items.php
@@ -17,7 +17,7 @@ require_once('include/feed.php');
 require_once('include/Contact.php');
 require_once('mod/share.php');
 require_once('include/enotify.php');
-require_once('include/import-dfrn.php');
+require_once('include/dfrn.php');
 
 require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
 
@@ -145,413 +145,6 @@ function title_is_body($title, $body) {
 	return($title == $body);
 }
 
-function get_atom_elements($feed, $item, $contact = array()) {
-
-	require_once('library/HTMLPurifier.auto.php');
-	require_once('include/html2bbcode.php');
-
-	$best_photo = array();
-
-	$res = array();
-
-	$author = $item->get_author();
-	if($author) {
-		$res['author-name'] = unxmlify($author->get_name());
-		$res['author-link'] = unxmlify($author->get_link());
-	}
-	else {
-		$res['author-name'] = unxmlify($feed->get_title());
-		$res['author-link'] = unxmlify($feed->get_permalink());
-	}
-	$res['uri'] = unxmlify($item->get_id());
-	$res['title'] = unxmlify($item->get_title());
-	$res['body'] = unxmlify($item->get_content());
-	$res['plink'] = unxmlify($item->get_link(0));
-
-	if($res['plink'])
-		$base_url = implode('/', array_slice(explode('/',$res['plink']),0,3));
-	else
-		$base_url = '';
-
-	// look for a photo. We should check media size and find the best one,
-	// but for now let's just find any author photo
-	// Additionally we look for an alternate author link. On OStatus this one is the one we want.
-
-	$authorlinks = $item->feed->data["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["feed"][0]["child"][SIMPLEPIE_NAMESPACE_ATOM_10]["author"][0]["child"]["http://www.w3.org/2005/Atom"]["link"];
-	if (is_array($authorlinks)) {
-		foreach ($authorlinks as $link) {
-			$linkdata = array_shift($link["attribs"]);
-
-			if ($linkdata["rel"] == "alternate")
-				$res["author-link"] = $linkdata["href"];
-		};
-	}
-
-	$rawauthor = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
-
-	if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
-		$base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
-		foreach($base as $link) {
-			if($link['attribs']['']['rel'] === 'alternate')
-				$res['author-link'] = unxmlify($link['attribs']['']['href']);
-
-			if(!x($res, 'author-avatar') || !$res['author-avatar']) {
-				if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
-					$res['author-avatar'] = unxmlify($link['attribs']['']['href']);
-			}
-		}
-	}
-
-	$rawactor = $item->get_item_tags(NAMESPACE_ACTIVITY, 'actor');
-
-	if($rawactor && activity_match($rawactor[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'],ACTIVITY_OBJ_PERSON)) {
-		$base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
-		if($base && count($base)) {
-			foreach($base as $link) {
-				if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
-					$res['author-link'] = unxmlify($link['attribs']['']['href']);
-				if(!x($res, 'author-avatar') || !$res['author-avatar']) {
-					if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
-						$res['author-avatar'] = unxmlify($link['attribs']['']['href']);
-				}
-			}
-		}
-	}
-
-	// No photo/profile-link on the item - look at the feed level
-
-	if((! (x($res,'author-link'))) || (! (x($res,'author-avatar')))) {
-		$rawauthor = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'author');
-		if($rawauthor && $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
-			$base = $rawauthor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
-			foreach($base as $link) {
-				if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
-					$res['author-link'] = unxmlify($link['attribs']['']['href']);
-				if(! $res['author-avatar']) {
-					if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
-						$res['author-avatar'] = unxmlify($link['attribs']['']['href']);
-				}
-			}
-		}
-
-		$rawactor = $feed->get_feed_tags(NAMESPACE_ACTIVITY, 'subject');
-
-		if($rawactor && activity_match($rawactor[0]['child'][NAMESPACE_ACTIVITY]['object-type'][0]['data'],ACTIVITY_OBJ_PERSON)) {
-			$base = $rawactor[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
-
-			if($base && count($base)) {
-				foreach($base as $link) {
-					if($link['attribs']['']['rel'] === 'alternate' && (! $res['author-link']))
-						$res['author-link'] = unxmlify($link['attribs']['']['href']);
-					if(! (x($res,'author-avatar'))) {
-						if($link['attribs']['']['rel'] === 'avatar' || $link['attribs']['']['rel'] === 'photo')
-							$res['author-avatar'] = unxmlify($link['attribs']['']['href']);
-					}
-				}
-			}
-		}
-	}
-
-	$apps = $item->get_item_tags(NAMESPACE_STATUSNET,'notice_info');
-	if($apps && $apps[0]['attribs']['']['source']) {
-		$res['app'] = strip_tags(unxmlify($apps[0]['attribs']['']['source']));
-		if($res['app'] === 'web')
-			$res['app'] = 'OStatus';
-	}
-
-	// base64 encoded json structure representing Diaspora signature
-
-	$dsig = $item->get_item_tags(NAMESPACE_DFRN,'diaspora_signature');
-	if($dsig) {
-		$res['dsprsig'] = unxmlify($dsig[0]['data']);
-	}
-
-	$dguid = $item->get_item_tags(NAMESPACE_DFRN,'diaspora_guid');
-	if($dguid)
-		$res['guid'] = unxmlify($dguid[0]['data']);
-
-	$bm = $item->get_item_tags(NAMESPACE_DFRN,'bookmark');
-	if($bm)
-		$res['bookmark'] = ((unxmlify($bm[0]['data']) === 'true') ? 1 : 0);
-
-
-	/**
-	 * If there's a copy of the body content which is guaranteed to have survived mangling in transit, use it.
-	 */
-
-	$have_real_body = false;
-
-	$rawenv = $item->get_item_tags(NAMESPACE_DFRN, 'env');
-	if($rawenv) {
-		$have_real_body = true;
-		$res['body'] = $rawenv[0]['data'];
-		$res['body'] = str_replace(array(' ',"\t","\r","\n"), array('','','',''),$res['body']);
-		// make sure nobody is trying to sneak some html tags by us
-		$res['body'] = notags(base64url_decode($res['body']));
-	}
-
-
-	$res['body'] = limit_body_size($res['body']);
-
-	// It isn't certain at this point whether our content is plaintext or html and we'd be foolish to trust
-	// the content type. Our own network only emits text normally, though it might have been converted to
-	// html if we used a pubsubhubbub transport. But if we see even one html tag in our text, we will
-	// have to assume it is all html and needs to be purified.
-
-	// It doesn't matter all that much security wise - because before this content is used anywhere, we are
-	// going to escape any tags we find regardless, but this lets us import a limited subset of html from
-	// the wild, by sanitising it and converting supported tags to bbcode before we rip out any remaining
-	// html.
-
-	if((strpos($res['body'],'<') !== false) && (strpos($res['body'],'>') !== false)) {
-
-		$res['body'] = reltoabs($res['body'],$base_url);
-
-		$res['body'] = html2bb_video($res['body']);
-
-		$res['body'] = oembed_html2bbcode($res['body']);
-
-		$config = HTMLPurifier_Config::createDefault();
-		$config->set('Cache.DefinitionImpl', null);
-
-		// we shouldn't need a whitelist, because the bbcode converter
-		// will strip out any unsupported tags.
-
-		$purifier = new HTMLPurifier($config);
-		$res['body'] = $purifier->purify($res['body']);
-
-		$res['body'] = @html2bbcode($res['body']);
-
-
-	}
-	elseif(! $have_real_body) {
-
-		// it's not one of our messages and it has no tags
-		// so it's probably just text. We'll escape it just to be safe.
-
-		$res['body'] = escape_tags($res['body']);
-	}
-
-
-	// this tag is obsolete but we keep it for really old sites
-
-	$allow = $item->get_item_tags(NAMESPACE_DFRN,'comment-allow');
-	if($allow && $allow[0]['data'] == 1)
-		$res['last-child'] = 1;
-	else
-		$res['last-child'] = 0;
-
-	$private = $item->get_item_tags(NAMESPACE_DFRN,'private');
-	if($private && intval($private[0]['data']) > 0)
-		$res['private'] = intval($private[0]['data']);
-	else
-		$res['private'] = 0;
-
-	$extid = $item->get_item_tags(NAMESPACE_DFRN,'extid');
-	if($extid && $extid[0]['data'])
-		$res['extid'] = $extid[0]['data'];
-
-	$rawlocation = $item->get_item_tags(NAMESPACE_DFRN, 'location');
-	if($rawlocation)
-		$res['location'] = unxmlify($rawlocation[0]['data']);
-
-
-	$rawcreated = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'published');
-	if($rawcreated)
-		$res['created'] = unxmlify($rawcreated[0]['data']);
-
-
-	$rawedited = $item->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10,'updated');
-	if($rawedited)
-		$res['edited'] = unxmlify($rawedited[0]['data']);
-
-	if((x($res,'edited')) && (! (x($res,'created'))))
-		$res['created'] = $res['edited'];
-
-	if(! $res['created'])
-		$res['created'] = $item->get_date('c');
-
-	if(! $res['edited'])
-		$res['edited'] = $item->get_date('c');
-
-
-	// Disallow time travelling posts
-
-	$d1 = strtotime($res['created']);
-	$d2 = strtotime($res['edited']);
-	$d3 = strtotime('now');
-
-	if($d1 > $d3)
-		$res['created'] = datetime_convert();
-	if($d2 > $d3)
-		$res['edited'] = datetime_convert();
-
-	$rawowner = $item->get_item_tags(NAMESPACE_DFRN, 'owner');
-	if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'])
-		$res['owner-name'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']);
-	elseif($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data'])
-		$res['owner-name'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['name'][0]['data']);
-	if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'])
-		$res['owner-link'] = unxmlify($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']);
-	elseif($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data'])
-		$res['owner-link'] = unxmlify($rawowner[0]['child'][NAMESPACE_DFRN]['uri'][0]['data']);
-
-	if($rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link']) {
-		$base = $rawowner[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['link'];
-
-		foreach($base as $link) {
-			if(!x($res, 'owner-avatar') || !$res['owner-avatar']) {
-				if($link['attribs']['']['rel'] === 'photo' || $link['attribs']['']['rel'] === 'avatar')
-					$res['owner-avatar'] = unxmlify($link['attribs']['']['href']);
-			}
-		}
-	}
-
-	$rawgeo = $item->get_item_tags(NAMESPACE_GEORSS,'point');
-	if($rawgeo)
-		$res['coord'] = unxmlify($rawgeo[0]['data']);
-
-	if ($contact["network"] == NETWORK_FEED) {
-		$res['verb'] = ACTIVITY_POST;
-		$res['object-type'] = ACTIVITY_OBJ_NOTE;
-	}
-
-	$rawverb = $item->get_item_tags(NAMESPACE_ACTIVITY, 'verb');
-
-	// select between supported verbs
-
-	if($rawverb) {
-		$res['verb'] = unxmlify($rawverb[0]['data']);
-	}
-
-	// translate OStatus unfollow to activity streams if it happened to get selected
-
-	if((x($res,'verb')) && ($res['verb'] === 'http://ostatus.org/schema/1.0/unfollow'))
-		$res['verb'] = ACTIVITY_UNFOLLOW;
-
-	$cats = $item->get_categories();
-	if($cats) {
-		$tag_arr = array();
-		foreach($cats as $cat) {
-			$term = $cat->get_term();
-			if(! $term)
-				$term = $cat->get_label();
-			$scheme = $cat->get_scheme();
-			if($scheme && $term && stristr($scheme,'X-DFRN:'))
-				$tag_arr[] = substr($scheme,7,1) . '[url=' . unxmlify(substr($scheme,9)) . ']' . unxmlify($term) . '[/url]';
-			elseif($term)
-				$tag_arr[] = notags(trim($term));
-		}
-		$res['tag'] =  implode(',', $tag_arr);
-	}
-
-	$attach = $item->get_enclosures();
-	if($attach) {
-		$att_arr = array();
-		foreach($attach as $att) {
-			$len   = intval($att->get_length());
-			$link  = str_replace(array(',','"'),array('%2D','%22'),notags(trim(unxmlify($att->get_link()))));
-			$title = str_replace(array(',','"'),array('%2D','%22'),notags(trim(unxmlify($att->get_title()))));
-			$type  = str_replace(array(',','"'),array('%2D','%22'),notags(trim(unxmlify($att->get_type()))));
-			if(strpos($type,';'))
-				$type = substr($type,0,strpos($type,';'));
-			if((! $link) || (strpos($link,'http') !== 0))
-				continue;
-
-			if(! $title)
-				$title = ' ';
-			if(! $type)
-				$type = 'application/octet-stream';
-
-			$att_arr[] = '[attach]href="' . $link . '" length="' . $len . '" type="' . $type . '" title="' . $title . '"[/attach]';
-		}
-		$res['attach'] = implode(',', $att_arr);
-	}
-
-	$rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'object');
-
-	if($rawobj) {
-		$res['object'] = '<object>' . "\n";
-		$child = $rawobj[0]['child'];
-		if($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
-			$res['object-type'] = $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'];
-			$res['object'] .= '<type>' . $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'] . '</type>' . "\n";
-		}
-		if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'])
-			$res['object'] .= '<id>' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'] . '</id>' . "\n";
-		if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link'])
-			$res['object'] .= '<link>' . encode_rel_links($child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']) . '</link>' . "\n";
-		if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'title') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'])
-			$res['object'] .= '<title>' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'] . '</title>' . "\n";
-		if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'content') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']) {
-			$body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data'];
-			if(! $body)
-				$body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data'];
-			// preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events
-			$res['object'] .= '<orig>' . xmlify($body) . '</orig>' . "\n";
-			if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) {
-
-				$body = html2bb_video($body);
-
-				$config = HTMLPurifier_Config::createDefault();
-				$config->set('Cache.DefinitionImpl', null);
-
-				$purifier = new HTMLPurifier($config);
-				$body = $purifier->purify($body);
-				$body = html2bbcode($body);
-			}
-
-			$res['object'] .= '<content>' . $body . '</content>' . "\n";
-		}
-
-		$res['object'] .= '</object>' . "\n";
-	}
-
-	$rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'target');
-
-	if($rawobj) {
-		$res['target'] = '<target>' . "\n";
-		$child = $rawobj[0]['child'];
-		if($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) {
-			$res['target'] .= '<type>' . $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'] . '</type>' . "\n";
-		}
-		if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'])
-			$res['target'] .= '<id>' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'] . '</id>' . "\n";
-		if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link'])
-			$res['target'] .= '<link>' . encode_rel_links($child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']) . '</link>' . "\n";
-		if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'data') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'])
-			$res['target'] .= '<title>' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'] . '</title>' . "\n";
-		if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'data') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data']) {
-			$body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['content'][0]['data'];
-			if(! $body)
-				$body = $child[SIMPLEPIE_NAMESPACE_ATOM_10]['summary'][0]['data'];
-			// preserve a copy of the original body content in case we later need to parse out any microformat information, e.g. events
-			$res['target'] .= '<orig>' . xmlify($body) . '</orig>' . "\n";
-			if((strpos($body,'<') !== false) || (strpos($body,'>') !== false)) {
-
-				$body = html2bb_video($body);
-
-				$config = HTMLPurifier_Config::createDefault();
-				$config->set('Cache.DefinitionImpl', null);
-
-				$purifier = new HTMLPurifier($config);
-				$body = $purifier->purify($body);
-				$body = html2bbcode($body);
-			}
-
-			$res['target'] .= '<content>' . $body . '</content>' . "\n";
-		}
-
-		$res['target'] .= '</target>' . "\n";
-	}
-
-	$arr = array('feed' => $feed, 'item' => $item, 'result' => $res);
-
-	call_hooks('parse_atom', $arr);
-
-	return $res;
-}
-
 function add_page_info_data($data) {
 	call_hooks('page_info_data', $data);
 
@@ -698,27 +291,6 @@ function add_page_info_to_body($body, $texturl = false, $no_photos = false) {
 	return $body;
 }
 
-function encode_rel_links($links) {
-	$o = '';
-	if(! ((is_array($links)) && (count($links))))
-		return $o;
-	foreach($links as $link) {
-		$o .= '<link ';
-		if($link['attribs']['']['rel'])
-			$o .= 'rel="' . $link['attribs']['']['rel'] . '" ';
-		if($link['attribs']['']['type'])
-			$o .= 'type="' . $link['attribs']['']['type'] . '" ';
-		if($link['attribs']['']['href'])
-			$o .= 'href="' . $link['attribs']['']['href'] . '" ';
-		if( (x($link['attribs'],NAMESPACE_MEDIA)) && $link['attribs'][NAMESPACE_MEDIA]['width'])
-			$o .= 'media:width="' . $link['attribs'][NAMESPACE_MEDIA]['width'] . '" ';
-		if( (x($link['attribs'],NAMESPACE_MEDIA)) && $link['attribs'][NAMESPACE_MEDIA]['height'])
-			$o .= 'media:height="' . $link['attribs'][NAMESPACE_MEDIA]['height'] . '" ';
-		$o .= ' />' . "\n" ;
-	}
-	return xmlify($o);
-}
-
 function add_guid($item) {
 	$r = q("SELECT `guid` FROM `guid` WHERE `guid` = '%s' LIMIT 1", dbesc($item["guid"]));
 	if ($r)
@@ -1713,652 +1285,10 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
 	        );
 		if ($r) {
 			logger("Now import the DFRN feed");
-			dfrn2::import($xml,$r[0], true);
+			dfrn::import($xml,$r[0], true);
 			return;
 		}
 	}
-
-	// Test - remove before flight
-	//if ($pass < 2) {
-	//	$tempfile = tempnam(get_temppath(), "dfrn-consume-");
-	//	file_put_contents($tempfile, $xml);
-	//}
-
-	require_once('library/simplepie/simplepie.inc');
-	require_once('include/contact_selectors.php');
-
-	if(! strlen($xml)) {
-		logger('consume_feed: empty input');
-		return;
-	}
-
-	$feed = new SimplePie();
-	$feed->set_raw_data($xml);
-	if($datedir)
-		$feed->enable_order_by_date(true);
-	else
-		$feed->enable_order_by_date(false);
-	$feed->init();
-
-	if($feed->error())
-		logger('consume_feed: Error parsing XML: ' . $feed->error());
-
-	$permalink = $feed->get_permalink();
-
-	// Check at the feed level for updated contact name and/or photo
-
-	$name_updated  = '';
-	$new_name = '';
-	$photo_timestamp = '';
-	$photo_url = '';
-	$birthday = '';
-	$contact_updated = '';
-
-	$hubs = $feed->get_links('hub');
-	logger('consume_feed: hubs: ' . print_r($hubs,true), LOGGER_DATA);
-
-	if(count($hubs))
-		$hub = implode(',', $hubs);
-
-	$rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'owner');
-	if(! $rawtags)
-		$rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author');
-	if($rawtags) {
-		$elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10];
-		if($elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']) {
-			$name_updated = $elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated'];
-			$new_name = $elems['name'][0]['data'];
-
-			// Manually checking for changed contact names
-			if (($new_name != $contact['name']) AND ($new_name != "") AND ($name_updated <= $contact['name-date'])) {
-				$name_updated = date("c");
-				$photo_timestamp = date("c");
-			}
-		}
-		if((x($elems,'link')) && ($elems['link'][0]['attribs']['']['rel'] === 'photo') && ($elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated'])) {
-			if ($photo_timestamp == "")
-				$photo_timestamp = datetime_convert('UTC','UTC',$elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']);
-			$photo_url = $elems['link'][0]['attribs']['']['href'];
-		}
-
-		if((x($rawtags[0]['child'], NAMESPACE_DFRN)) && (x($rawtags[0]['child'][NAMESPACE_DFRN],'birthday'))) {
-			$birthday = datetime_convert('UTC','UTC', $rawtags[0]['child'][NAMESPACE_DFRN]['birthday'][0]['data']);
-		}
-	}
-
-	if((is_array($contact)) && ($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $contact['avatar-date'])) {
-		logger('consume_feed: Updating photo for '.$contact['name'].' from '.$photo_url.' uid: '.$contact['uid']);
-
-		$contact_updated = $photo_timestamp;
-
-		require_once("include/Photo.php");
-		$photos = import_profile_photo($photo_url,$contact['uid'],$contact['id']);
-
-		q("UPDATE `contact` SET `avatar-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s'
-			WHERE `uid` = %d AND `id` = %d AND NOT `self`",
-			dbesc(datetime_convert()),
-			dbesc($photos[0]),
-			dbesc($photos[1]),
-			dbesc($photos[2]),
-			intval($contact['uid']),
-			intval($contact['id'])
-		);
-	}
-
-	if((is_array($contact)) && ($name_updated) && (strlen($new_name)) && ($name_updated > $contact['name-date'])) {
-		if ($name_updated > $contact_updated)
-			$contact_updated = $name_updated;
-
-		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `id` = %d LIMIT 1",
-			intval($contact['uid']),
-			intval($contact['id'])
-		);
-
-		$x = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d AND `name` != '%s' AND NOT `self`",
-			dbesc(notags(trim($new_name))),
-			dbesc(datetime_convert()),
-			intval($contact['uid']),
-			intval($contact['id']),
-			dbesc(notags(trim($new_name)))
-		);
-
-		// do our best to update the name on content items
-
-		if(count($r) AND (notags(trim($new_name)) != $r[0]['name'])) {
-			q("UPDATE `item` SET `author-name` = '%s' WHERE `author-name` = '%s' AND `author-link` = '%s' AND `uid` = %d AND `author-name` != '%s'",
-				dbesc(notags(trim($new_name))),
-				dbesc($r[0]['name']),
-				dbesc($r[0]['url']),
-				intval($contact['uid']),
-				dbesc(notags(trim($new_name)))
-			);
-		}
-	}
-
-	if ($contact_updated AND $new_name AND $photo_url)
-		poco_check($contact['url'], $new_name, NETWORK_DFRN, $photo_url, "", "", "", "", "", $contact_updated, 2, $contact['id'], $contact['uid']);
-
-	if(strlen($birthday)) {
-		if(substr($birthday,0,4) != $contact['bdyear']) {
-			logger('consume_feed: updating birthday: ' . $birthday);
-
-			/**
-			 *
-			 * Add new birthday event for this person
-			 *
-			 * $bdtext is just a readable placeholder in case the event is shared
-			 * with others. We will replace it during presentation to our $importer
-			 * to contain a sparkle link and perhaps a photo.
-			 *
-			 */
-
-			$bdtext = sprintf( t('%s\'s birthday'), $contact['name']);
-			$bdtext2 = sprintf( t('Happy Birthday %s'), ' [url=' . $contact['url'] . ']' . $contact['name'] . '[/url]' ) ;
-
-
-			$r = q("INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`summary`,`desc`,`type`)
-				VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
-				intval($contact['uid']),
-				intval($contact['id']),
-				dbesc(datetime_convert()),
-				dbesc(datetime_convert()),
-				dbesc(datetime_convert('UTC','UTC', $birthday)),
-				dbesc(datetime_convert('UTC','UTC', $birthday . ' + 1 day ')),
-				dbesc($bdtext),
-				dbesc($bdtext2),
-				dbesc('birthday')
-			);
-
-
-			// update bdyear
-
-			q("UPDATE `contact` SET `bdyear` = '%s' WHERE `uid` = %d AND `id` = %d",
-				dbesc(substr($birthday,0,4)),
-				intval($contact['uid']),
-				intval($contact['id'])
-			);
-
-			// This function is called twice without reloading the contact
-			// Make sure we only create one event. This is why &$contact
-			// is a reference var in this function
-
-			$contact['bdyear'] = substr($birthday,0,4);
-		}
-	}
-
-	$community_page = 0;
-	$rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'community');
-	if($rawtags) {
-		$community_page = intval($rawtags[0]['data']);
-	}
-	if(is_array($contact) && intval($contact['forum']) != $community_page) {
-		q("update contact set forum = %d where id = %d",
-			intval($community_page),
-			intval($contact['id'])
-		);
-		$contact['forum'] = (string) $community_page;
-	}
-
-
-	// process any deleted entries
-
-	$del_entries = $feed->get_feed_tags(NAMESPACE_TOMB, 'deleted-entry');
-	if(is_array($del_entries) && count($del_entries) && $pass != 2) {
-		foreach($del_entries as $dentry) {
-			$deleted = false;
-			if(isset($dentry['attribs']['']['ref'])) {
-				$uri = $dentry['attribs']['']['ref'];
-				$deleted = true;
-				if(isset($dentry['attribs']['']['when'])) {
-					$when = $dentry['attribs']['']['when'];
-					$when = datetime_convert('UTC','UTC', $when, 'Y-m-d H:i:s');
-				}
-				else
-					$when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s');
-			}
-			if($deleted && is_array($contact)) {
-				$r = q("SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN `contact` on `item`.`contact-id` = `contact`.`id`
-					WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1",
-					dbesc($uri),
-					intval($importer['uid']),
-					intval($contact['id'])
-				);
-				if(count($r)) {
-					$item = $r[0];
-
-					if(! $item['deleted'])
-						logger('consume_feed: deleting item ' . $item['id'] . ' uri=' . $item['uri'], LOGGER_DEBUG);
-
-					if($item['object-type'] === ACTIVITY_OBJ_EVENT) {
-						logger("Deleting event ".$item['event-id'], LOGGER_DEBUG);
-						event_delete($item['event-id']);
-					}
-
-					if(($item['verb'] === ACTIVITY_TAG) && ($item['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
-						$xo = parse_xml_string($item['object'],false);
-						$xt = parse_xml_string($item['target'],false);
-						if($xt->type === ACTIVITY_OBJ_NOTE) {
-							$i = q("select * from `item` where uri = '%s' and uid = %d limit 1",
-								dbesc($xt->id),
-								intval($importer['importer_uid'])
-							);
-							if(count($i)) {
-
-								// For tags, the owner cannot remove the tag on the author's copy of the post.
-
-								$owner_remove = (($item['contact-id'] == $i[0]['contact-id']) ? true: false);
-								$author_remove = (($item['origin'] && $item['self']) ? true : false);
-								$author_copy = (($item['origin']) ? true : false);
-
-								if($owner_remove && $author_copy)
-									continue;
-								if($author_remove || $owner_remove) {
-									$tags = explode(',',$i[0]['tag']);
-									$newtags = array();
-									if(count($tags)) {
-										foreach($tags as $tag)
-											if(trim($tag) !== trim($xo->body))
-												$newtags[] = trim($tag);
-									}
-									q("update item set tag = '%s' where id = %d",
-										dbesc(implode(',',$newtags)),
-										intval($i[0]['id'])
-									);
-									create_tags_from_item($i[0]['id']);
-								}
-							}
-						}
-					}
-
-					if($item['uri'] == $item['parent-uri']) {
-						$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
-							`body` = '', `title` = ''
-							WHERE `parent-uri` = '%s' AND `uid` = %d",
-							dbesc($when),
-							dbesc(datetime_convert()),
-							dbesc($item['uri']),
-							intval($importer['uid'])
-						);
-						create_tags_from_itemuri($item['uri'], $importer['uid']);
-						create_files_from_itemuri($item['uri'], $importer['uid']);
-						update_thread_uri($item['uri'], $importer['uid']);
-					}
-					else {
-						$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
-							`body` = '', `title` = ''
-							WHERE `uri` = '%s' AND `uid` = %d",
-							dbesc($when),
-							dbesc(datetime_convert()),
-							dbesc($uri),
-							intval($importer['uid'])
-						);
-						create_tags_from_itemuri($uri, $importer['uid']);
-						create_files_from_itemuri($uri, $importer['uid']);
-						if($item['last-child']) {
-							// ensure that last-child is set in case the comment that had it just got wiped.
-							q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ",
-								dbesc(datetime_convert()),
-								dbesc($item['parent-uri']),
-								intval($item['uid'])
-							);
-							// who is the last child now?
-							$r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `moderated` = 0 AND `uid` = %d
-								ORDER BY `created` DESC LIMIT 1",
-									dbesc($item['parent-uri']),
-									intval($importer['uid'])
-							);
-							if(count($r)) {
-								q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d",
-									intval($r[0]['id'])
-								);
-							}
-						}
-					}
-				}
-			}
-		}
-	}
-
-	// Now process the feed
-
-	if($feed->get_item_quantity()) {
-
-		logger('consume_feed: feed item count = ' . $feed->get_item_quantity());
-
-		// in inverse date order
-		if ($datedir)
-			$items = array_reverse($feed->get_items());
-		else
-			$items = $feed->get_items();
-
-
-		foreach($items as $item) {
-
-			$is_reply = false;
-			$item_id = $item->get_id();
-			$rawthread = $item->get_item_tags( NAMESPACE_THREAD,'in-reply-to');
-			if(isset($rawthread[0]['attribs']['']['ref'])) {
-				$is_reply = true;
-				$parent_uri = $rawthread[0]['attribs']['']['ref'];
-			}
-
-			if(($is_reply) && is_array($contact)) {
-
-				if($pass == 1)
-					continue;
-
-				// not allowed to post
-
-				if($contact['rel'] == CONTACT_IS_FOLLOWER)
-					continue;
-
-
-				// Have we seen it? If not, import it.
-
-				$item_id  = $item->get_id();
-				$datarray = get_atom_elements($feed, $item, $contact);
-
-				if((! x($datarray,'author-name')) && ($contact['network'] != NETWORK_DFRN))
-					$datarray['author-name'] = $contact['name'];
-				if((! x($datarray,'author-link')) && ($contact['network'] != NETWORK_DFRN))
-					$datarray['author-link'] = $contact['url'];
-				if((! x($datarray,'author-avatar')) && ($contact['network'] != NETWORK_DFRN))
-					$datarray['author-avatar'] = $contact['thumb'];
-
-				if((! x($datarray,'author-name')) || (! x($datarray,'author-link'))) {
-					logger('consume_feed: no author information! ' . print_r($datarray,true));
-					continue;
-				}
-
-				$force_parent = false;
-				if($contact['network'] === NETWORK_OSTATUS || stristr($contact['url'],'twitter.com')) {
-					if($contact['network'] === NETWORK_OSTATUS)
-						$force_parent = true;
-					if(strlen($datarray['title']))
-						unset($datarray['title']);
-					$r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
-						dbesc(datetime_convert()),
-						dbesc($parent_uri),
-						intval($importer['uid'])
-					);
-					$datarray['last-child'] = 1;
-					update_thread_uri($parent_uri, $importer['uid']);
-				}
-
-
-				$r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-					dbesc($item_id),
-					intval($importer['uid'])
-				);
-
-				// Update content if 'updated' changes
-
-				if(count($r)) {
-					if (edited_timestamp_is_newer($r[0], $datarray)) {
-
-						// do not accept (ignore) an earlier edit than one we currently have.
-						if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
-							continue;
-
-						$r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
-							dbesc($datarray['title']),
-							dbesc($datarray['body']),
-							dbesc($datarray['tag']),
-							dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
-							dbesc(datetime_convert()),
-							dbesc($item_id),
-							intval($importer['uid'])
-						);
-						create_tags_from_itemuri($item_id, $importer['uid']);
-						update_thread_uri($item_id, $importer['uid']);
-					}
-
-					// update last-child if it changes
-
-					$allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow');
-					if(($allow) && ($allow[0]['data'] != $r[0]['last-child'])) {
-						$r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
-							dbesc(datetime_convert()),
-							dbesc($parent_uri),
-							intval($importer['uid'])
-						);
-						$r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s'  WHERE `uri` = '%s' AND `uid` = %d",
-							intval($allow[0]['data']),
-							dbesc(datetime_convert()),
-							dbesc($item_id),
-							intval($importer['uid'])
-						);
-						update_thread_uri($item_id, $importer['uid']);
-					}
-					continue;
-				}
-
-
-				if(($contact['network'] === NETWORK_FEED) || (! strlen($contact['notify']))) {
-					// one way feed - no remote comment ability
-					$datarray['last-child'] = 0;
-				}
-				$datarray['parent-uri'] = $parent_uri;
-				$datarray['uid'] = $importer['uid'];
-				$datarray['contact-id'] = $contact['id'];
-				if(($datarray['verb'] === ACTIVITY_LIKE)
-					|| ($datarray['verb'] === ACTIVITY_DISLIKE)
-					|| ($datarray['verb'] === ACTIVITY_ATTEND)
-					|| ($datarray['verb'] === ACTIVITY_ATTENDNO)
-					|| ($datarray['verb'] === ACTIVITY_ATTENDMAYBE)) {
-					$datarray['type'] = 'activity';
-					$datarray['gravity'] = GRAVITY_LIKE;
-					// only one like or dislike per person
-					// splitted into two queries for performance issues
-					$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1",
-						intval($datarray['uid']),
-						dbesc($datarray['author-link']),
-						dbesc($datarray['verb']),
-						dbesc($datarray['parent-uri'])
-					);
-					if($r && count($r))
-						continue;
-
-					$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1",
-						intval($datarray['uid']),
-						dbesc($datarray['author-link']),
-						dbesc($datarray['verb']),
-						dbesc($datarray['parent-uri'])
-					);
-					if($r && count($r))
-						continue;
-				}
-
-				if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
-					$xo = parse_xml_string($datarray['object'],false);
-					$xt = parse_xml_string($datarray['target'],false);
-
-					if($xt->type == ACTIVITY_OBJ_NOTE) {
-						$r = q("select * from item where `uri` = '%s' AND `uid` = %d limit 1",
-							dbesc($xt->id),
-							intval($importer['importer_uid'])
-						);
-						if(! count($r))
-							continue;
-
-						// extract tag, if not duplicate, add to parent item
-						if($xo->id && $xo->content) {
-							$newtag = '#[url=' . $xo->id . ']'. $xo->content . '[/url]';
-							if(! (stristr($r[0]['tag'],$newtag))) {
-								q("UPDATE item SET tag = '%s' WHERE id = %d",
-									dbesc($r[0]['tag'] . (strlen($r[0]['tag']) ? ',' : '') . $newtag),
-									intval($r[0]['id'])
-								);
-								create_tags_from_item($r[0]['id']);
-							}
-						}
-					}
-				}
-
-				$r = item_store($datarray,$force_parent);
-				continue;
-			}
-
-			else {
-
-				// Head post of a conversation. Have we seen it? If not, import it.
-
-				$item_id  = $item->get_id();
-
-				$datarray = get_atom_elements($feed, $item, $contact);
-
-				if(is_array($contact)) {
-					if((! x($datarray,'author-name')) && ($contact['network'] != NETWORK_DFRN))
-						$datarray['author-name'] = $contact['name'];
-					if((! x($datarray,'author-link')) && ($contact['network'] != NETWORK_DFRN))
-						$datarray['author-link'] = $contact['url'];
-					if((! x($datarray,'author-avatar')) && ($contact['network'] != NETWORK_DFRN))
-						$datarray['author-avatar'] = $contact['thumb'];
-				}
-
-				if((! x($datarray,'author-name')) || (! x($datarray,'author-link'))) {
-					logger('consume_feed: no author information! ' . print_r($datarray,true));
-					continue;
-				}
-
-				// special handling for events
-
-				if((x($datarray,'object-type')) && ($datarray['object-type'] === ACTIVITY_OBJ_EVENT)) {
-					$ev = bbtoevent($datarray['body']);
-					if((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) {
-						$ev['uid'] = $importer['uid'];
-						$ev['uri'] = $item_id;
-						$ev['edited'] = $datarray['edited'];
-						$ev['private'] = $datarray['private'];
-						$ev['guid'] = $datarray['guid'];
-
-						if(is_array($contact))
-							$ev['cid'] = $contact['id'];
-						$r = q("SELECT * FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-							dbesc($item_id),
-							intval($importer['uid'])
-						);
-						if(count($r))
-							$ev['id'] = $r[0]['id'];
-						$xyz = event_store($ev);
-						continue;
-					}
-				}
-
-				if($contact['network'] === NETWORK_OSTATUS || stristr($contact['url'],'twitter.com')) {
-					if(strlen($datarray['title']))
-						unset($datarray['title']);
-					$datarray['last-child'] = 1;
-				}
-
-
-				$r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-					dbesc($item_id),
-					intval($importer['uid'])
-				);
-
-				// Update content if 'updated' changes
-
-				if(count($r)) {
-					if (edited_timestamp_is_newer($r[0], $datarray)) {
-
-						// do not accept (ignore) an earlier edit than one we currently have.
-						if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
-							continue;
-
-						$r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
-							dbesc($datarray['title']),
-							dbesc($datarray['body']),
-							dbesc($datarray['tag']),
-							dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
-							dbesc(datetime_convert()),
-							dbesc($item_id),
-							intval($importer['uid'])
-						);
-						create_tags_from_itemuri($item_id, $importer['uid']);
-						update_thread_uri($item_id, $importer['uid']);
-					}
-
-					// update last-child if it changes
-
-					$allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow');
-					if($allow && $allow[0]['data'] != $r[0]['last-child']) {
-						$r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
-							intval($allow[0]['data']),
-							dbesc(datetime_convert()),
-							dbesc($item_id),
-							intval($importer['uid'])
-						);
-						update_thread_uri($item_id, $importer['uid']);
-					}
-					continue;
-				}
-
-				if(activity_match($datarray['verb'],ACTIVITY_FOLLOW)) {
-					logger('consume-feed: New follower');
-					new_follower($importer,$contact,$datarray,$item);
-					return;
-				}
-				if(activity_match($datarray['verb'],ACTIVITY_UNFOLLOW))  {
-					lose_follower($importer,$contact,$datarray,$item);
-					return;
-				}
-
-				if(activity_match($datarray['verb'],ACTIVITY_REQ_FRIEND)) {
-					logger('consume-feed: New friend request');
-					new_follower($importer,$contact,$datarray,$item,true);
-					return;
-				}
-				if(activity_match($datarray['verb'],ACTIVITY_UNFRIEND))  {
-					lose_sharer($importer,$contact,$datarray,$item);
-					return;
-				}
-
-
-				if(! is_array($contact))
-					return;
-
-
-				if(($contact['network'] === NETWORK_FEED) || (! strlen($contact['notify']))) {
-						// one way feed - no remote comment ability
-						$datarray['last-child'] = 0;
-				}
-				if($contact['network'] === NETWORK_FEED)
-					$datarray['private'] = 2;
-
-				$datarray['parent-uri'] = $item_id;
-				$datarray['uid'] = $importer['uid'];
-				$datarray['contact-id'] = $contact['id'];
-
-				if(! link_compare($datarray['owner-link'],$contact['url'])) {
-					// The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
-					// but otherwise there's a possible data mixup on the sender's system.
-					// the tgroup delivery code called from item_store will correct it if it's a forum,
-					// but we're going to unconditionally correct it here so that the post will always be owned by our contact.
-					logger('consume_feed: Correcting item owner.', LOGGER_DEBUG);
-					$datarray['owner-name']   = $contact['name'];
-					$datarray['owner-link']   = $contact['url'];
-					$datarray['owner-avatar'] = $contact['thumb'];
-				}
-
-				// We've allowed "followers" to reach this point so we can decide if they are
-				// posting an @-tag delivery, which followers are allowed to do for certain
-				// page types. Now that we've parsed the post, let's check if it is legit. Otherwise ignore it.
-
-				if(($contact['rel'] == CONTACT_IS_FOLLOWER) && (! tgroup_check($importer['uid'],$datarray)))
-					continue;
-
-				// This is my contact on another system, but it's really me.
-				// Turn this into a wall post.
-				$notify = item_is_remote_self($contact, $datarray);
-
-				$r = item_store($datarray, false, $notify);
-				logger('Stored - Contact '.$contact['url'].' Notify '.$notify.' return '.$r.' Item '.print_r($datarray, true), LOGGER_DEBUG);
-				continue;
-
-			}
-		}
-	}
 }
 
 function item_is_remote_self($contact, &$datarray) {
@@ -2421,1073 +1351,6 @@ function item_is_remote_self($contact, &$datarray) {
 	return true;
 }
 
-function local_delivery($importer,$data) {
-	// dfrn-Test
-	return dfrn2::import($data, $importer);
-
-	require_once('library/simplepie/simplepie.inc');
-
-	$a = get_app();
-
-	logger(__function__, LOGGER_TRACE);
-
-	//$tempfile = tempnam(get_temppath(), "dfrn-local-");
-	//file_put_contents($tempfile, $data);
-
-	if($importer['readonly']) {
-		// We aren't receiving stuff from this person. But we will quietly ignore them
-		// rather than a blatant "go away" message.
-		logger('local_delivery: ignoring');
-		return 0;
-		//NOTREACHED
-	}
-
-	// Consume notification feed. This may differ from consuming a public feed in several ways
-	// - might contain email or friend suggestions
-	// - might contain remote followup to our message
-	//		- in which case we need to accept it and then notify other conversants
-	// - we may need to send various email notifications
-
-	$feed = new SimplePie();
-	$feed->set_raw_data($data);
-	$feed->enable_order_by_date(false);
-	$feed->init();
-
-
-	if($feed->error())
-		logger('local_delivery: Error parsing XML: ' . $feed->error());
-
-
-	// Check at the feed level for updated contact name and/or photo
-
-	$name_updated  = '';
-	$new_name = '';
-	$photo_timestamp = '';
-	$photo_url = '';
-	$contact_updated = '';
-
-
-	$rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'owner');
-
-// Fallback should not be needed here. If it isn't DFRN it won't have DFRN updated tags
-//	if(! $rawtags)
-//		$rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author');
-
-	if($rawtags) {
-		$elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10];
-		if($elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated']) {
-			$name_updated = $elems['name'][0]['attribs'][NAMESPACE_DFRN]['updated'];
-			$new_name = $elems['name'][0]['data'];
-
-			// Manually checking for changed contact names
-			if (($new_name != $importer['name']) AND ($new_name != "") AND ($name_updated <= $importer['name-date'])) {
-				$name_updated = date("c");
-				$photo_timestamp = date("c");
-			}
-		}
-		if((x($elems,'link')) && ($elems['link'][0]['attribs']['']['rel'] === 'photo') && ($elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated'])) {
-			if ($photo_timestamp == "")
-				$photo_timestamp = datetime_convert('UTC','UTC',$elems['link'][0]['attribs'][NAMESPACE_DFRN]['updated']);
-			$photo_url = $elems['link'][0]['attribs']['']['href'];
-		}
-	}
-
-	if(($photo_timestamp) && (strlen($photo_url)) && ($photo_timestamp > $importer['avatar-date'])) {
-
-		$contact_updated = $photo_timestamp;
-
-		logger('local_delivery: Updating photo for ' . $importer['name']);
-		require_once("include/Photo.php");
-
-		$photos = import_profile_photo($photo_url,$importer['importer_uid'],$importer['id']);
-
-		q("UPDATE `contact` SET `avatar-date` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s'
-			WHERE `uid` = %d AND `id` = %d AND NOT `self`",
-			dbesc(datetime_convert()),
-			dbesc($photos[0]),
-			dbesc($photos[1]),
-			dbesc($photos[2]),
-			intval($importer['importer_uid']),
-			intval($importer['id'])
-		);
-	}
-
-	if(($name_updated) && (strlen($new_name)) && ($name_updated > $importer['name-date'])) {
-		if ($name_updated > $contact_updated)
-			$contact_updated = $name_updated;
-
-		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `id` = %d LIMIT 1",
-			intval($importer['importer_uid']),
-			intval($importer['id'])
-		);
-
-		$x = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `id` = %d AND `name` != '%s' AND NOT `self`",
-			dbesc(notags(trim($new_name))),
-			dbesc(datetime_convert()),
-			intval($importer['importer_uid']),
-			intval($importer['id']),
-			dbesc(notags(trim($new_name)))
-		);
-
-		// do our best to update the name on content items
-
-		if(count($r) AND (notags(trim($new_name)) != $r[0]['name'])) {
-			q("UPDATE `item` SET `author-name` = '%s' WHERE `author-name` = '%s' AND `author-link` = '%s' AND `uid` = %d AND `author-name` != '%s'",
-				dbesc(notags(trim($new_name))),
-				dbesc($r[0]['name']),
-				dbesc($r[0]['url']),
-				intval($importer['importer_uid']),
-				dbesc(notags(trim($new_name)))
-			);
-		}
-	}
-
-	if ($contact_updated AND $new_name AND $photo_url)
-		poco_check($importer['url'], $new_name, NETWORK_DFRN, $photo_url, "", "", "", "", "", $contact_updated, 2, $importer['id'], $importer['importer_uid']);
-
-	// Currently unsupported - needs a lot of work
-	$reloc = $feed->get_feed_tags( NAMESPACE_DFRN, 'relocate' );
-	if(isset($reloc[0]['child'][NAMESPACE_DFRN])) {
-		$base = $reloc[0]['child'][NAMESPACE_DFRN];
-		$newloc = array();
-		$newloc['uid'] = $importer['importer_uid'];
-		$newloc['cid'] = $importer['id'];
-		$newloc['name'] = notags(unxmlify($base['name'][0]['data']));
-		$newloc['photo'] = notags(unxmlify($base['photo'][0]['data']));
-		$newloc['thumb'] = notags(unxmlify($base['thumb'][0]['data']));
-		$newloc['micro'] = notags(unxmlify($base['micro'][0]['data']));
-		$newloc['url'] = notags(unxmlify($base['url'][0]['data']));
-		$newloc['request'] = notags(unxmlify($base['request'][0]['data']));
-		$newloc['confirm'] = notags(unxmlify($base['confirm'][0]['data']));
-		$newloc['notify'] = notags(unxmlify($base['notify'][0]['data']));
-		$newloc['poll'] = notags(unxmlify($base['poll'][0]['data']));
-		$newloc['sitepubkey'] = notags(unxmlify($base['sitepubkey'][0]['data']));
-		/** relocated user must have original key pair */
-		/*$newloc['pubkey'] = notags(unxmlify($base['pubkey'][0]['data']));
-		$newloc['prvkey'] = notags(unxmlify($base['prvkey'][0]['data']));*/
-
-		logger("items:relocate contact ".print_r($newloc, true).print_r($importer, true), LOGGER_DEBUG);
-
-		// update contact
-		$r = q("SELECT photo, url FROM contact WHERE id=%d AND uid=%d;",
-			intval($importer['id']),
-			intval($importer['importer_uid']));
-		if ($r === false)
-			return 1;
-		$old = $r[0];
-
-		$x = q("UPDATE contact SET
-					name = '%s',
-					photo = '%s',
-					thumb = '%s',
-					micro = '%s',
-					url = '%s',
-					nurl = '%s',
-					request = '%s',
-					confirm = '%s',
-					notify = '%s',
-					poll = '%s',
-					`site-pubkey` = '%s'
-			WHERE id=%d AND uid=%d;",
-					dbesc($newloc['name']),
-					dbesc($newloc['photo']),
-					dbesc($newloc['thumb']),
-					dbesc($newloc['micro']),
-					dbesc($newloc['url']),
-					dbesc(normalise_link($newloc['url'])),
-					dbesc($newloc['request']),
-					dbesc($newloc['confirm']),
-					dbesc($newloc['notify']),
-					dbesc($newloc['poll']),
-					dbesc($newloc['sitepubkey']),
-					intval($importer['id']),
-					intval($importer['importer_uid']));
-
-		if ($x === false)
-			return 1;
-		// update items
-		$fields = array(
-			'owner-link' => array($old['url'], $newloc['url']),
-			'author-link' => array($old['url'], $newloc['url']),
-			'owner-avatar' => array($old['photo'], $newloc['photo']),
-			'author-avatar' => array($old['photo'], $newloc['photo']),
-			);
-		foreach ($fields as $n=>$f){
-			$x = q("UPDATE `item` SET `%s`='%s' WHERE `%s`='%s' AND uid=%d",
-					$n, dbesc($f[1]),
-					$n, dbesc($f[0]),
-					intval($importer['importer_uid']));
-				if ($x === false)
-					return 1;
-			}
-
-		/// @TODO
-		/// merge with current record, current contents have priority
-		/// update record, set url-updated
-		/// update profile photos
-		/// schedule a scan?
-		return 0;
-	}
-
-
-	// handle friend suggestion notification
-
-	$sugg = $feed->get_feed_tags( NAMESPACE_DFRN, 'suggest' );
-	if(isset($sugg[0]['child'][NAMESPACE_DFRN])) {
-		$base = $sugg[0]['child'][NAMESPACE_DFRN];
-		$fsugg = array();
-		$fsugg['uid'] = $importer['importer_uid'];
-		$fsugg['cid'] = $importer['id'];
-		$fsugg['name'] = notags(unxmlify($base['name'][0]['data']));
-		$fsugg['photo'] = notags(unxmlify($base['photo'][0]['data']));
-		$fsugg['url'] = notags(unxmlify($base['url'][0]['data']));
-		$fsugg['request'] = notags(unxmlify($base['request'][0]['data']));
-		$fsugg['body'] = escape_tags(unxmlify($base['note'][0]['data']));
-
-		// Does our member already have a friend matching this description?
-
-		$r = q("SELECT * FROM `contact` WHERE `name` = '%s' AND `nurl` = '%s' AND `uid` = %d LIMIT 1",
-			dbesc($fsugg['name']),
-			dbesc(normalise_link($fsugg['url'])),
-			intval($fsugg['uid'])
-		);
-		if(count($r))
-			return 0;
-
-		// Do we already have an fcontact record for this person?
-
-		$fid = 0;
-		$r = q("SELECT * FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1",
-			dbesc($fsugg['url']),
-			dbesc($fsugg['name']),
-			dbesc($fsugg['request'])
-		);
-		if(count($r)) {
-			$fid = $r[0]['id'];
-
-			// OK, we do. Do we already have an introduction for this person ?
-			$r = q("select id from intro where uid = %d and fid = %d limit 1",
-				intval($fsugg['uid']),
-				intval($fid)
-			);
-			if(count($r))
-				return 0;
-		}
-		if(! $fid)
-			$r = q("INSERT INTO `fcontact` ( `name`,`url`,`photo`,`request` ) VALUES ( '%s', '%s', '%s', '%s' ) ",
-			dbesc($fsugg['name']),
-			dbesc($fsugg['url']),
-			dbesc($fsugg['photo']),
-			dbesc($fsugg['request'])
-		);
-		$r = q("SELECT * FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1",
-			dbesc($fsugg['url']),
-			dbesc($fsugg['name']),
-			dbesc($fsugg['request'])
-		);
-		if(count($r)) {
-			$fid = $r[0]['id'];
-		}
-		// database record did not get created. Quietly give up.
-		else
-			return 0;
-
-
-		$hash = random_string();
-
-		$r = q("INSERT INTO `intro` ( `uid`, `fid`, `contact-id`, `note`, `hash`, `datetime`, `blocked` )
-			VALUES( %d, %d, %d, '%s', '%s', '%s', %d )",
-			intval($fsugg['uid']),
-			intval($fid),
-			intval($fsugg['cid']),
-			dbesc($fsugg['body']),
-			dbesc($hash),
-			dbesc(datetime_convert()),
-			intval(0)
-		);
-
-		notification(array(
-			'type'         => NOTIFY_SUGGEST,
-			'notify_flags' => $importer['notify-flags'],
-			'language'     => $importer['language'],
-			'to_name'      => $importer['username'],
-			'to_email'     => $importer['email'],
-			'uid'          => $importer['importer_uid'],
-			'item'         => $fsugg,
-			'link'         => $a->get_baseurl() . '/notifications/intros',
-			'source_name'  => $importer['name'],
-			'source_link'  => $importer['url'],
-			'source_photo' => $importer['photo'],
-			'verb'         => ACTIVITY_REQ_FRIEND,
-			'otype'        => 'intro'
-		));
-
-		return 0;
-	}
-
-	$ismail = false;
-
-	$rawmail = $feed->get_feed_tags( NAMESPACE_DFRN, 'mail' );
-	if(isset($rawmail[0]['child'][NAMESPACE_DFRN])) {
-
-		logger('local_delivery: private message received');
-
-		$ismail = true;
-		$base = $rawmail[0]['child'][NAMESPACE_DFRN];
-
-		$msg = array();
-		$msg['uid'] = $importer['importer_uid'];
-		$msg['from-name'] = notags(unxmlify($base['sender'][0]['child'][NAMESPACE_DFRN]['name'][0]['data']));
-		$msg['from-photo'] = notags(unxmlify($base['sender'][0]['child'][NAMESPACE_DFRN]['avatar'][0]['data']));
-		$msg['from-url'] = notags(unxmlify($base['sender'][0]['child'][NAMESPACE_DFRN]['uri'][0]['data']));
-		$msg['contact-id'] = $importer['id'];
-		$msg['title'] = notags(unxmlify($base['subject'][0]['data']));
-		$msg['body'] = escape_tags(unxmlify($base['content'][0]['data']));
-		$msg['seen'] = 0;
-		$msg['replied'] = 0;
-		$msg['uri'] = notags(unxmlify($base['id'][0]['data']));
-		$msg['parent-uri'] = notags(unxmlify($base['in-reply-to'][0]['data']));
-		$msg['created'] = datetime_convert(notags(unxmlify('UTC','UTC',$base['sentdate'][0]['data'])));
-
-		dbesc_array($msg);
-
-		$r = dbq("INSERT INTO `mail` (`" . implode("`, `", array_keys($msg))
-			. "`) VALUES ('" . implode("', '", array_values($msg)) . "')" );
-
-		// send notifications.
-
-		require_once('include/enotify.php');
-
-		$notif_params = array(
-			'type' => NOTIFY_MAIL,
-			'notify_flags' => $importer['notify-flags'],
-			'language' => $importer['language'],
-			'to_name' => $importer['username'],
-			'to_email' => $importer['email'],
-			'uid' => $importer['importer_uid'],
-			'item' => $msg,
-			'source_name' => $msg['from-name'],
-			'source_link' => $importer['url'],
-			'source_photo' => $importer['thumb'],
-			'verb' => ACTIVITY_POST,
-			'otype' => 'mail'
-		);
-
-		notification($notif_params);
-		return 0;
-
-		// NOTREACHED
-	}
-
-	$community_page = 0;
-	$rawtags = $feed->get_feed_tags( NAMESPACE_DFRN, 'community');
-	if($rawtags) {
-		$community_page = intval($rawtags[0]['data']);
-	}
-	if(intval($importer['forum']) != $community_page) {
-		q("update contact set forum = %d where id = %d",
-			intval($community_page),
-			intval($importer['id'])
-		);
-		$importer['forum'] = (string) $community_page;
-	}
-
-	logger('local_delivery: feed item count = ' . $feed->get_item_quantity());
-
-	// process any deleted entries
-
-	$del_entries = $feed->get_feed_tags(NAMESPACE_TOMB, 'deleted-entry');
-	if(is_array($del_entries) && count($del_entries)) {
-		foreach($del_entries as $dentry) {
-			$deleted = false;
-			if(isset($dentry['attribs']['']['ref'])) {
-				$uri = $dentry['attribs']['']['ref'];
-				$deleted = true;
-				if(isset($dentry['attribs']['']['when'])) {
-					$when = $dentry['attribs']['']['when'];
-					$when = datetime_convert('UTC','UTC', $when, 'Y-m-d H:i:s');
-				}
-				else
-					$when = datetime_convert('UTC','UTC','now','Y-m-d H:i:s');
-			}
-			if($deleted) {
-
-				// check for relayed deletes to our conversation
-
-				$is_reply = false;
-				$r = q("select * from item where uri = '%s' and uid = %d limit 1",
-					dbesc($uri),
-					intval($importer['importer_uid'])
-				);
-				if(count($r)) {
-					$parent_uri = $r[0]['parent-uri'];
-					if($r[0]['id'] != $r[0]['parent'])
-						$is_reply = true;
-				}
-
-				if($is_reply) {
-					$community = false;
-
-					if($importer['page-flags'] == PAGE_COMMUNITY || $importer['page-flags'] == PAGE_PRVGROUP ) {
-						$sql_extra = '';
-						$community = true;
-						logger('local_delivery: possible community delete');
-					}
-					else
-						$sql_extra = " and contact.self = 1 and item.wall = 1 ";
-
-					// was the top-level post for this reply written by somebody on this site?
-					// Specifically, the recipient?
-
-					$is_a_remote_delete = false;
-
-					// POSSIBLE CLEANUP --> Why select so many fields when only forum_mode and wall are used?
-					$r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, `item`.`forum_mode`,`item`.`origin`,`item`.`wall`,
-						`contact`.`name`, `contact`.`url`, `contact`.`thumb` from `item`
-						INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
-						WHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' or `item`.`thr-parent` = '%s')
-						AND `item`.`uid` = %d
-						$sql_extra
-						LIMIT 1",
-						dbesc($parent_uri),
-						dbesc($parent_uri),
-						dbesc($parent_uri),
-						intval($importer['importer_uid'])
-					);
-					if($r && count($r))
-						$is_a_remote_delete = true;
-
-					// Does this have the characteristics of a community or private group comment?
-					// If it's a reply to a wall post on a community/prvgroup page it's a
-					// valid community comment. Also forum_mode makes it valid for sure.
-					// If neither, it's not.
-
-					if($is_a_remote_delete && $community) {
-						if((! $r[0]['forum_mode']) && (! $r[0]['wall'])) {
-							$is_a_remote_delete = false;
-							logger('local_delivery: not a community delete');
-						}
-					}
-
-					if($is_a_remote_delete) {
-						logger('local_delivery: received remote delete');
-					}
-				}
-
-				$r = q("SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN contact on `item`.`contact-id` = `contact`.`id`
-					WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1",
-					dbesc($uri),
-					intval($importer['importer_uid']),
-					intval($importer['id'])
-				);
-
-				if(count($r)) {
-					$item = $r[0];
-
-					if($item['deleted'])
-						continue;
-
-					logger('local_delivery: deleting item ' . $item['id'] . ' uri=' . $item['uri'], LOGGER_DEBUG);
-
-					if($item['object-type'] === ACTIVITY_OBJ_EVENT) {
-						logger("Deleting event ".$item['event-id'], LOGGER_DEBUG);
-						event_delete($item['event-id']);
-					}
-
-					if(($item['verb'] === ACTIVITY_TAG) && ($item['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
-						$xo = parse_xml_string($item['object'],false);
-						$xt = parse_xml_string($item['target'],false);
-
-						if($xt->type === ACTIVITY_OBJ_NOTE) {
-							$i = q("select * from `item` where uri = '%s' and uid = %d limit 1",
-								dbesc($xt->id),
-								intval($importer['importer_uid'])
-							);
-							if(count($i)) {
-
-								// For tags, the owner cannot remove the tag on the author's copy of the post.
-
-								$owner_remove = (($item['contact-id'] == $i[0]['contact-id']) ? true: false);
-								$author_remove = (($item['origin'] && $item['self']) ? true : false);
-								$author_copy = (($item['origin']) ? true : false);
-
-								if($owner_remove && $author_copy)
-									continue;
-								if($author_remove || $owner_remove) {
-									$tags = explode(',',$i[0]['tag']);
-									$newtags = array();
-									if(count($tags)) {
-										foreach($tags as $tag)
-											if(trim($tag) !== trim($xo->body))
-												$newtags[] = trim($tag);
-									}
-									q("update item set tag = '%s' where id = %d",
-										dbesc(implode(',',$newtags)),
-										intval($i[0]['id'])
-									);
-									create_tags_from_item($i[0]['id']);
-								}
-							}
-						}
-					}
-
-					if($item['uri'] == $item['parent-uri']) {
-						$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
-							`body` = '', `title` = ''
-							WHERE `parent-uri` = '%s' AND `uid` = %d",
-							dbesc($when),
-							dbesc(datetime_convert()),
-							dbesc($item['uri']),
-							intval($importer['importer_uid'])
-						);
-						create_tags_from_itemuri($item['uri'], $importer['importer_uid']);
-						create_files_from_itemuri($item['uri'], $importer['importer_uid']);
-						update_thread_uri($item['uri'], $importer['importer_uid']);
-					}
-					else {
-						$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
-							`body` = '', `title` = ''
-							WHERE `uri` = '%s' AND `uid` = %d",
-							dbesc($when),
-							dbesc(datetime_convert()),
-							dbesc($uri),
-							intval($importer['importer_uid'])
-						);
-						create_tags_from_itemuri($uri, $importer['importer_uid']);
-						create_files_from_itemuri($uri, $importer['importer_uid']);
-						update_thread_uri($uri, $importer['importer_uid']);
-						if($item['last-child']) {
-							// ensure that last-child is set in case the comment that had it just got wiped.
-							q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ",
-								dbesc(datetime_convert()),
-								dbesc($item['parent-uri']),
-								intval($item['uid'])
-							);
-							// who is the last child now?
-							$r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `uid` = %d
-								ORDER BY `created` DESC LIMIT 1",
-									dbesc($item['parent-uri']),
-									intval($importer['importer_uid'])
-							);
-							if(count($r)) {
-								q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d",
-									intval($r[0]['id'])
-								);
-							}
-						}
-						// if this is a relayed delete, propagate it to other recipients
-
-						if($is_a_remote_delete)
-							proc_run('php',"include/notifier.php","drop",$item['id']);
-					}
-				}
-			}
-		}
-	}
-
-
-	foreach($feed->get_items() as $item) {
-
-		$is_reply = false;
-		$item_id = $item->get_id();
-		$rawthread = $item->get_item_tags( NAMESPACE_THREAD, 'in-reply-to');
-		if(isset($rawthread[0]['attribs']['']['ref'])) {
-			$is_reply = true;
-			$parent_uri = $rawthread[0]['attribs']['']['ref'];
-		}
-
-		if($is_reply) {
-			$community = false;
-
-			if($importer['page-flags'] == PAGE_COMMUNITY || $importer['page-flags'] == PAGE_PRVGROUP ) {
-				$sql_extra = '';
-				$community = true;
-				logger('local_delivery: possible community reply');
-			}
-			else
-				$sql_extra = " and contact.self = 1 and item.wall = 1 ";
-
-			// was the top-level post for this reply written by somebody on this site?
-			// Specifically, the recipient?
-
-			$is_a_remote_comment = false;
-			$top_uri = $parent_uri;
-
-			$r = q("select `item`.`parent-uri` from `item`
-				WHERE `item`.`uri` = '%s'
-				LIMIT 1",
-				dbesc($parent_uri)
-			);
-			if($r && count($r)) {
-				$top_uri = $r[0]['parent-uri'];
-
-				// POSSIBLE CLEANUP --> Why select so many fields when only forum_mode and wall are used?
-				$r = q("select `item`.`id`, `item`.`uri`, `item`.`tag`, `item`.`forum_mode`,`item`.`origin`,`item`.`wall`,
-					`contact`.`name`, `contact`.`url`, `contact`.`thumb` from `item`
-					INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
-					WHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' or `item`.`thr-parent` = '%s')
-					AND `item`.`uid` = %d
-					$sql_extra
-					LIMIT 1",
-					dbesc($top_uri),
-					dbesc($top_uri),
-					dbesc($top_uri),
-					intval($importer['importer_uid'])
-				);
-				if($r && count($r))
-					$is_a_remote_comment = true;
-			}
-
-			// Does this have the characteristics of a community or private group comment?
-			// If it's a reply to a wall post on a community/prvgroup page it's a
-			// valid community comment. Also forum_mode makes it valid for sure.
-			// If neither, it's not.
-
-			if($is_a_remote_comment && $community) {
-				if((! $r[0]['forum_mode']) && (! $r[0]['wall'])) {
-					$is_a_remote_comment = false;
-					logger('local_delivery: not a community reply');
-				}
-			}
-
-			if($is_a_remote_comment) {
-				logger('local_delivery: received remote comment');
-				$is_like = false;
-				// remote reply to our post. Import and then notify everybody else.
-
-				$datarray = get_atom_elements($feed, $item);
-
-				$r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body`  FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-					dbesc($item_id),
-					intval($importer['importer_uid'])
-				);
-
-				// Update content if 'updated' changes
-
-				if(count($r)) {
-					$iid = $r[0]['id'];
-					if (edited_timestamp_is_newer($r[0], $datarray)) {
-
-						// do not accept (ignore) an earlier edit than one we currently have.
-						if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
-							continue;
-
-						logger('received updated comment' , LOGGER_DEBUG);
-						$r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
-							dbesc($datarray['title']),
-							dbesc($datarray['body']),
-							dbesc($datarray['tag']),
-							dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
-							dbesc(datetime_convert()),
-							dbesc($item_id),
-							intval($importer['importer_uid'])
-						);
-						create_tags_from_itemuri($item_id, $importer['importer_uid']);
-
-						proc_run('php',"include/notifier.php","comment-import",$iid);
-
-					}
-
-					continue;
-				}
-
-
-
-				$own = q("select name,url,thumb from contact where uid = %d and self = 1 limit 1",
-					intval($importer['importer_uid'])
-				);
-
-
-				$datarray['type'] = 'remote-comment';
-				$datarray['wall'] = 1;
-				$datarray['parent-uri'] = $parent_uri;
-				$datarray['uid'] = $importer['importer_uid'];
-				$datarray['owner-name'] = $own[0]['name'];
-				$datarray['owner-link'] = $own[0]['url'];
-				$datarray['owner-avatar'] = $own[0]['thumb'];
-				$datarray['contact-id'] = $importer['id'];
-
-				if(($datarray['verb'] === ACTIVITY_LIKE)
-					|| ($datarray['verb'] === ACTIVITY_DISLIKE)
-					|| ($datarray['verb'] === ACTIVITY_ATTEND)
-					|| ($datarray['verb'] === ACTIVITY_ATTENDNO)
-					|| ($datarray['verb'] === ACTIVITY_ATTENDMAYBE)) {
-					$is_like = true;
-					$datarray['type'] = 'activity';
-					$datarray['gravity'] = GRAVITY_LIKE;
-					$datarray['last-child'] = 0;
-					// only one like or dislike per person
-					// splitted into two queries for performance issues
-					$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1",
-						intval($datarray['uid']),
-						dbesc($datarray['author-link']),
-						dbesc($datarray['verb']),
-						dbesc($datarray['parent-uri'])
-					);
-					if($r && count($r))
-						continue;
-
-					$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1",
-						intval($datarray['uid']),
-						dbesc($datarray['author-link']),
-						dbesc($datarray['verb']),
-						dbesc($datarray['parent-uri'])
-
-					);
-					if($r && count($r))
-						continue;
-				}
-
-				if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
-
-					$xo = parse_xml_string($datarray['object'],false);
-					$xt = parse_xml_string($datarray['target'],false);
-
-					if(($xt->type == ACTIVITY_OBJ_NOTE) && ($xt->id)) {
-
-						// fetch the parent item
-
-						$tagp = q("select * from item where uri = '%s' and uid = %d limit 1",
-							dbesc($xt->id),
-							intval($importer['importer_uid'])
-						);
-						if(! count($tagp))
-							continue;
-
-						// extract tag, if not duplicate, and this user allows tags, add to parent item
-
-						if($xo->id && $xo->content) {
-							$newtag = '#[url=' . $xo->id . ']'. $xo->content . '[/url]';
-							if(! (stristr($tagp[0]['tag'],$newtag))) {
-								$i = q("SELECT `blocktags` FROM `user` where `uid` = %d LIMIT 1",
-									intval($importer['importer_uid'])
-								);
-								if(count($i) && ! intval($i[0]['blocktags'])) {
-									q("UPDATE item SET tag = '%s', `edited` = '%s', `changed` = '%s' WHERE id = %d",
-										dbesc($tagp[0]['tag'] . (strlen($tagp[0]['tag']) ? ',' : '') . $newtag),
-										intval($tagp[0]['id']),
-										dbesc(datetime_convert()),
-										dbesc(datetime_convert())
-									);
-									create_tags_from_item($tagp[0]['id']);
-								}
-							}
-						}
-					}
-				}
-
-
-				$posted_id = item_store($datarray);
-				$parent = 0;
-
-				if($posted_id) {
-
-					$datarray["id"] = $posted_id;
-
-					$r = q("SELECT `parent`, `parent-uri` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
-						intval($posted_id),
-						intval($importer['importer_uid'])
-					);
-					if(count($r)) {
-						$parent = $r[0]['parent'];
-						$parent_uri = $r[0]['parent-uri'];
-					}
-
-					if(! $is_like) {
-						$r1 = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `uid` = %d AND `parent` = %d",
-							dbesc(datetime_convert()),
-							intval($importer['importer_uid']),
-							intval($r[0]['parent'])
-						);
-
-						$r2 = q("UPDATE `item` SET `last-child` = 1, `changed` = '%s' WHERE `uid` = %d AND `id` = %d",
-							dbesc(datetime_convert()),
-							intval($importer['importer_uid']),
-							intval($posted_id)
-						);
-					}
-
-					if($posted_id && $parent) {
-						proc_run('php',"include/notifier.php","comment-import","$posted_id");
-					}
-
-					return 0;
-					// NOTREACHED
-				}
-			}
-			else {
-
-				// regular comment that is part of this total conversation. Have we seen it? If not, import it.
-
-				$item_id  = $item->get_id();
-				$datarray = get_atom_elements($feed,$item);
-
-				if($importer['rel'] == CONTACT_IS_FOLLOWER)
-					continue;
-
-				$r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-					dbesc($item_id),
-					intval($importer['importer_uid'])
-				);
-
-				// Update content if 'updated' changes
-
-				if(count($r)) {
-					if (edited_timestamp_is_newer($r[0], $datarray)) {
-
-						// do not accept (ignore) an earlier edit than one we currently have.
-						if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
-							continue;
-
-						$r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
-							dbesc($datarray['title']),
-							dbesc($datarray['body']),
-							dbesc($datarray['tag']),
-							dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
-							dbesc(datetime_convert()),
-							dbesc($item_id),
-							intval($importer['importer_uid'])
-						);
-						create_tags_from_itemuri($item_id, $importer['importer_uid']);
-					}
-
-					// update last-child if it changes
-
-					$allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow');
-					if(($allow) && ($allow[0]['data'] != $r[0]['last-child'])) {
-						$r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
-							dbesc(datetime_convert()),
-							dbesc($parent_uri),
-							intval($importer['importer_uid'])
-						);
-						$r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s'  WHERE `uri` = '%s' AND `uid` = %d",
-							intval($allow[0]['data']),
-							dbesc(datetime_convert()),
-							dbesc($item_id),
-							intval($importer['importer_uid'])
-						);
-					}
-					continue;
-				}
-
-				$datarray['parent-uri'] = $parent_uri;
-				$datarray['uid'] = $importer['importer_uid'];
-				$datarray['contact-id'] = $importer['id'];
-				if(($datarray['verb'] === ACTIVITY_LIKE)
-					|| ($datarray['verb'] === ACTIVITY_DISLIKE)
-					|| ($datarray['verb'] === ACTIVITY_ATTEND)
-					|| ($datarray['verb'] === ACTIVITY_ATTENDNO)
-					|| ($datarray['verb'] === ACTIVITY_ATTENDMAYBE)) {
-					$datarray['type'] = 'activity';
-					$datarray['gravity'] = GRAVITY_LIKE;
-					// only one like or dislike per person
-					// splitted into two queries for performance issues
-					$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1",
-						intval($datarray['uid']),
-						dbesc($datarray['author-link']),
-						dbesc($datarray['verb']),
-						dbesc($datarray['parent-uri'])
-					);
-					if($r && count($r))
-						continue;
-
-					$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1",
-						intval($datarray['uid']),
-						dbesc($datarray['author-link']),
-						dbesc($datarray['verb']),
-						dbesc($datarray['parent-uri'])
-					);
-					if($r && count($r))
-						continue;
-
-				}
-
-				if(($datarray['verb'] === ACTIVITY_TAG) && ($datarray['object-type'] === ACTIVITY_OBJ_TAGTERM)) {
-
-					$xo = parse_xml_string($datarray['object'],false);
-					$xt = parse_xml_string($datarray['target'],false);
-
-					if($xt->type == ACTIVITY_OBJ_NOTE) {
-						$r = q("select * from item where `uri` = '%s' AND `uid` = %d limit 1",
-							dbesc($xt->id),
-							intval($importer['importer_uid'])
-						);
-						if(! count($r))
-							continue;
-
-						// extract tag, if not duplicate, add to parent item
-						if($xo->content) {
-							if(! (stristr($r[0]['tag'],trim($xo->content)))) {
-								q("UPDATE item SET tag = '%s' WHERE id = %d",
-									dbesc($r[0]['tag'] . (strlen($r[0]['tag']) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'),
-									intval($r[0]['id'])
-								);
-								create_tags_from_item($r[0]['id']);
-							}
-						}
-					}
-				}
-
-				$posted_id = item_store($datarray);
-
-				continue;
-			}
-		}
-
-		else {
-
-			// Head post of a conversation. Have we seen it? If not, import it.
-
-
-			$item_id  = $item->get_id();
-			$datarray = get_atom_elements($feed,$item);
-
-			if((x($datarray,'object-type')) && ($datarray['object-type'] === ACTIVITY_OBJ_EVENT)) {
-				$ev = bbtoevent($datarray['body']);
-				if((x($ev,'desc') || x($ev,'summary')) && x($ev,'start')) {
-					$ev['cid'] = $importer['id'];
-					$ev['uid'] = $importer['uid'];
-					$ev['uri'] = $item_id;
-					$ev['edited'] = $datarray['edited'];
-					$ev['private'] = $datarray['private'];
-					$ev['guid'] = $datarray['guid'];
-
-					$r = q("SELECT * FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-						dbesc($item_id),
-						intval($importer['uid'])
-					);
-					if(count($r))
-						$ev['id'] = $r[0]['id'];
-					$xyz = event_store($ev);
-					continue;
-				}
-			}
-
-			$r = q("SELECT `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-				dbesc($item_id),
-				intval($importer['importer_uid'])
-			);
-
-			// Update content if 'updated' changes
-
-			if(count($r)) {
-				if (edited_timestamp_is_newer($r[0], $datarray)) {
-
-					// do not accept (ignore) an earlier edit than one we currently have.
-					if(datetime_convert('UTC','UTC',$datarray['edited']) < $r[0]['edited'])
-						continue;
-
-					$r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
-						dbesc($datarray['title']),
-						dbesc($datarray['body']),
-						dbesc($datarray['tag']),
-						dbesc(datetime_convert('UTC','UTC',$datarray['edited'])),
-						dbesc(datetime_convert()),
-						dbesc($item_id),
-						intval($importer['importer_uid'])
-					);
-					create_tags_from_itemuri($item_id, $importer['importer_uid']);
-					update_thread_uri($item_id, $importer['importer_uid']);
-				}
-
-				// update last-child if it changes
-
-				$allow = $item->get_item_tags( NAMESPACE_DFRN, 'comment-allow');
-				if($allow && $allow[0]['data'] != $r[0]['last-child']) {
-					$r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
-						intval($allow[0]['data']),
-						dbesc(datetime_convert()),
-						dbesc($item_id),
-						intval($importer['importer_uid'])
-					);
-				}
-				continue;
-			}
-
-			$datarray['parent-uri'] = $item_id;
-			$datarray['uid'] = $importer['importer_uid'];
-			$datarray['contact-id'] = $importer['id'];
-
-
-			if(! link_compare($datarray['owner-link'],$importer['url'])) {
-				// The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
-				// but otherwise there's a possible data mixup on the sender's system.
-				// the tgroup delivery code called from item_store will correct it if it's a forum,
-				// but we're going to unconditionally correct it here so that the post will always be owned by our contact.
-				logger('local_delivery: Correcting item owner.', LOGGER_DEBUG);
-				$datarray['owner-name']   = $importer['senderName'];
-				$datarray['owner-link']   = $importer['url'];
-				$datarray['owner-avatar'] = $importer['thumb'];
-			}
-
-			if(($importer['rel'] == CONTACT_IS_FOLLOWER) && (! tgroup_check($importer['importer_uid'],$datarray)))
-				continue;
-
-			// This is my contact on another system, but it's really me.
-			// Turn this into a wall post.
-			$notify = item_is_remote_self($importer, $datarray);
-
-			$posted_id = item_store($datarray, false, $notify);
-
-			if(stristr($datarray['verb'],ACTIVITY_POKE)) {
-				$verb = urldecode(substr($datarray['verb'],strpos($datarray['verb'],'#')+1));
-				if(! $verb)
-					continue;
-				$xo = parse_xml_string($datarray['object'],false);
-
-				if(($xo->type == ACTIVITY_OBJ_PERSON) && ($xo->id)) {
-
-					// somebody was poked/prodded. Was it me?
-
-					$links = parse_xml_string("<links>".unxmlify($xo->link)."</links>",false);
-
-				foreach($links->link as $l) {
-				$atts = $l->attributes();
-				switch($atts['rel']) {
-					case "alternate":
-								$Blink = $atts['href'];
-								break;
-							default:
-								break;
-				    }
-				}
-					if($Blink && link_compare($Blink,$a->get_baseurl() . '/profile/' . $importer['nickname'])) {
-
-						// send a notification
-						require_once('include/enotify.php');
-
-						notification(array(
-							'type'         => NOTIFY_POKE,
-							'notify_flags' => $importer['notify-flags'],
-							'language'     => $importer['language'],
-							'to_name'      => $importer['username'],
-							'to_email'     => $importer['email'],
-							'uid'          => $importer['importer_uid'],
-							'item'         => $datarray,
-							'link'		   => $a->get_baseurl().'/display/'.urlencode(get_item_guid($posted_id)),
-							'source_name'  => stripslashes($datarray['author-name']),
-							'source_link'  => $datarray['author-link'],
-							'source_photo' => ((link_compare($datarray['author-link'],$importer['url']))
-								? $importer['thumb'] : $datarray['author-avatar']),
-							'verb'         => $datarray['verb'],
-							'otype'        => 'person',
-							'activity'     => $verb,
-							'parent'       => $datarray['parent']
-						));
-					}
-				}
-			}
-
-			continue;
-		}
-	}
-
-	return 0;
-	// NOTREACHED
-
-}
-
-
 function new_follower($importer,$contact,$datarray,$item,$sharing = false) {
 	$url = notags(trim($datarray['author-link']));
 	$name = notags(trim($datarray['author-name']));
@@ -3598,7 +1461,7 @@ function new_follower($importer,$contact,$datarray,$item,$sharing = false) {
 	}
 }
 
-function lose_follower($importer,$contact,$datarray,$item) {
+function lose_follower($importer,$contact,$datarray = array(),$item = "") {
 
 	if(($contact['rel'] == CONTACT_IS_FRIEND) || ($contact['rel'] == CONTACT_IS_SHARING)) {
 		q("UPDATE `contact` SET `rel` = %d WHERE `id` = %d",
@@ -3611,7 +1474,7 @@ function lose_follower($importer,$contact,$datarray,$item) {
 	}
 }
 
-function lose_sharer($importer,$contact,$datarray,$item) {
+function lose_sharer($importer,$contact,$datarray = array(),$item = "") {
 
 	if(($contact['rel'] == CONTACT_IS_FRIEND) || ($contact['rel'] == CONTACT_IS_FOLLOWER)) {
 		q("UPDATE `contact` SET `rel` = %d WHERE `id` = %d",
diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php
index 4aa777b550..780fb456f5 100644
--- a/mod/dfrn_notify.php
+++ b/mod/dfrn_notify.php
@@ -1,6 +1,7 @@
 <?php
 
 require_once('include/items.php');
+require_once('include/dfrn.php');
 require_once('include/event.php');
 
 require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
@@ -208,7 +209,7 @@ function dfrn_notify_post(&$a) {
 		logger('rino: decrypted data: ' . $data, LOGGER_DATA);
 	}
 
-	$ret = local_delivery($importer,$data);
+	$ret = dfrn::import($data, $importer);
 	xml_status($ret);
 
 	// NOTREACHED

From 9fd3d8116bee7ff6ede2477f6a1b5ca163257fc7 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Fri, 5 Feb 2016 21:30:31 +0100
Subject: [PATCH 044/273] vier smileybutton: little polish in dark.css

---
 view/theme/vier/dark.css | 1 -
 1 file changed, 1 deletion(-)

diff --git a/view/theme/vier/dark.css b/view/theme/vier/dark.css
index 7c671e4b7d..5ddaf71a2f 100644
--- a/view/theme/vier/dark.css
+++ b/view/theme/vier/dark.css
@@ -66,5 +66,4 @@ li :hover {
 
 table.smiley-preview{
   background-color: #252C33 !important;
-  box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.7);
 }
\ No newline at end of file

From 1c82e9f209eb72a7ed8d0fc1ee6a66b8d02d4110 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 5 Feb 2016 21:31:11 +0100
Subject: [PATCH 045/273] Bugfix for OStatus to prevent sending messages from
 wrong senders

---
 include/dfrn.php        | 1259 ++++++++++++++++++++++++++++++++++++++-
 include/import-dfrn.php | 1229 --------------------------------------
 include/ostatus.php     |    4 +
 3 files changed, 1260 insertions(+), 1232 deletions(-)
 delete mode 100644 include/import-dfrn.php

diff --git a/include/dfrn.php b/include/dfrn.php
index 4c1f21dd06..e286b75cce 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -6,9 +6,19 @@
  * https://github.com/friendica/friendica/wiki/Protocol
  */
 
-require_once('include/items.php');
-require_once('include/Contact.php');
-require_once('include/ostatus.php');
+require_once("include/Contact.php");
+require_once("include/ostatus.php");
+require_once("include/enotify.php");
+require_once("include/threads.php");
+require_once("include/socgraph.php");
+require_once("include/items.php");
+require_once("include/tags.php");
+require_once("include/files.php");
+require_once("include/event.php");
+require_once("include/text.php");
+require_once("include/oembed.php");
+require_once("include/html2bbcode.php");
+require_once("library/HTMLPurifier.auto.php");
 
 /**
  * @brief This class contain functions to create and send DFRN XML files
@@ -16,6 +26,10 @@ require_once('include/ostatus.php');
  */
 class dfrn {
 
+	const DFRN_TOP_LEVEL = 0;
+	const DFRN_REPLY = 1;
+	const DFRN_REPLY_RC = 2;
+
 	/**
 	 * @brief Generates the atom entries for delivery.php
 	 *
@@ -1053,4 +1067,1243 @@ class dfrn {
 
 		return $res->status;
 	}
+
+	/**
+	 * @brief Add new birthday event for this person
+	 *
+	 * @param array $contact Contact record
+	 * @param string $birthday Birthday of the contact
+	 *
+	 */
+	private function birthday_event($contact, $birthday) {
+
+		logger("updating birthday: ".$birthday." for contact ".$contact["id"]);
+
+		$bdtext = sprintf(t("%s\'s birthday"), $contact["name"]);
+		$bdtext2 = sprintf(t("Happy Birthday %s"), " [url=".$contact["url"]."]".$contact["name"]."[/url]") ;
+
+
+		$r = q("INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`summary`,`desc`,`type`)
+			VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
+			intval($contact["uid"]),
+			intval($contact["id"]),
+			dbesc(datetime_convert()),
+			dbesc(datetime_convert()),
+			dbesc(datetime_convert("UTC","UTC", $birthday)),
+			dbesc(datetime_convert("UTC","UTC", $birthday." + 1 day ")),
+			dbesc($bdtext),
+			dbesc($bdtext2),
+			dbesc("birthday")
+		);
+	}
+
+	/**
+	 * @brief Fetch the author data from head or entry items
+	 *
+	 * @param object $xpath XPath object
+	 * @param object $context In which context should the data be searched
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 * @param string $element Element name from which the data is fetched
+	 * @param bool $onlyfetch Should the data only be fetched or should it update the contact record as well
+	 *
+	 * @return Returns an array with relevant data of the author
+	 */
+	private function fetchauthor($xpath, $context, $importer, $element, $onlyfetch) {
+
+		$author = array();
+		$author["name"] = $xpath->evaluate($element."/atom:name/text()", $context)->item(0)->nodeValue;
+		$author["link"] = $xpath->evaluate($element."/atom:uri/text()", $context)->item(0)->nodeValue;
+
+		$r = q("SELECT `id`, `uid`, `network`, `avatar-date`, `name-date`, `uri-date`, `addr`,
+				`name`, `nick`, `about`, `location`, `keywords`, `bdyear`, `bd`
+				FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
+			intval($importer["uid"]), dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET));
+		if ($r) {
+			$contact = $r[0];
+			$author["contact-id"] = $r[0]["id"];
+			$author["network"] = $r[0]["network"];
+		} else {
+			$author["contact-id"] = $importer["id"];
+			$author["network"] = $importer["network"];
+			$onlyfetch = true;
+		}
+
+		// Until now we aren't serving different sizes - but maybe later
+		$avatarlist = array();
+		// @todo check if "avatar" or "photo" would be the best field in the specification
+		$avatars = $xpath->query($element."/atom:link[@rel='avatar']", $context);
+		foreach($avatars AS $avatar) {
+			$href = "";
+			$width = 0;
+			foreach($avatar->attributes AS $attributes) {
+				if ($attributes->name == "href")
+					$href = $attributes->textContent;
+				if ($attributes->name == "width")
+					$width = $attributes->textContent;
+				if ($attributes->name == "updated")
+					$contact["avatar-date"] = $attributes->textContent;
+			}
+			if (($width > 0) AND ($href != ""))
+				$avatarlist[$width] = $href;
+		}
+		if (count($avatarlist) > 0) {
+			krsort($avatarlist);
+			$author["avatar"] = current($avatarlist);
+		}
+
+		if ($r AND !$onlyfetch) {
+
+			// When was the last change to name or uri?
+			$name_element = $xpath->query($element."/atom:name", $context)->item(0);
+			foreach($name_element->attributes AS $attributes)
+				if ($attributes->name == "updated")
+					$contact["name-date"] = $attributes->textContent;
+
+			$link_element = $xpath->query($element."/atom:link", $context)->item(0);
+			foreach($link_element->attributes AS $attributes)
+				if ($attributes->name == "updated")
+					$contact["uri-date"] = $attributes->textContent;
+
+			// Update contact data
+			$value = $xpath->evaluate($element."/dfrn:handle/text()", $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["addr"] = $value;
+
+			$value = $xpath->evaluate($element."/poco:displayName/text()", $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["name"] = $value;
+
+			$value = $xpath->evaluate($element."/poco:preferredUsername/text()", $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["nick"] = $value;
+
+			$value = $xpath->evaluate($element."/poco:note/text()", $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["about"] = $value;
+
+			$value = $xpath->evaluate($element."/poco:address/poco:formatted/text()", $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["location"] = $value;
+
+			/// @todo Add support for the following fields that we don't support by now in the contact table:
+			/// - poco:utcOffset
+			/// - poco:ims
+			/// - poco:urls
+			/// - poco:locality
+			/// - poco:region
+			/// - poco:country
+
+			// Save the keywords into the contact table
+			$tags = array();
+			$tagelements = $xpath->evaluate($element."/poco:tags/text()", $context);
+			foreach($tagelements AS $tag)
+				$tags[$tag->nodeValue] = $tag->nodeValue;
+
+			if (count($tags))
+				$contact["keywords"] = implode(", ", $tags);
+
+			// "dfrn:birthday" contains the birthday converted to UTC
+			$old_bdyear = $contact["bdyear"];
+
+			$birthday = $xpath->evaluate($element."/dfrn:birthday/text()", $context)->item(0)->nodeValue;
+
+			if (strtotime($birthday) > time()) {
+				$bd_timestamp = strtotime($birthday);
+
+				$contact["bdyear"] = date("Y", $bd_timestamp);
+			}
+
+			// "poco:birthday" is the birthday in the format "yyyy-mm-dd"
+			$value = $xpath->evaluate($element."/poco:birthday/text()", $context)->item(0)->nodeValue;
+
+			if (!in_array($value, array("", "0000-00-00"))) {
+				$bdyear = date("Y");
+				$value = str_replace("0000", $bdyear, $value);
+
+				if (strtotime($value) < time()) {
+					$value = str_replace($bdyear, $bdyear + 1, $value);
+					$bdyear = $bdyear + 1;
+				}
+
+				$contact["bd"] = $value;
+			}
+
+			if ($old_bdyear != $contact["bdyear"])
+				self::birthday_event($contact, $birthday);
+
+			// Get all field names
+			$fields = array();
+			foreach ($r[0] AS $field => $data)
+				$fields[$field] = $data;
+
+			unset($fields["id"]);
+			unset($fields["uid"]);
+			unset($fields["avatar-date"]);
+			unset($fields["name-date"]);
+			unset($fields["uri-date"]);
+
+			 // Update check for this field has to be done differently
+			$datefields = array("name-date", "uri-date");
+			foreach ($datefields AS $field)
+				if (strtotime($contact[$field]) > strtotime($r[0][$field]))
+					$update = true;
+
+			foreach ($fields AS $field => $data)
+				if ($contact[$field] != $r[0][$field]) {
+					logger("Difference for contact ".$contact["id"]." in field '".$field."'. Old value: '".$contact[$field]."', new value '".$r[0][$field]."'", LOGGER_DEBUG);
+					$update = true;
+				}
+
+			if ($update) {
+				logger("Update contact data for contact ".$contact["id"], LOGGER_DEBUG);
+
+				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s',
+					`addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s',
+					`name-date`  = '%s', `uri-date` = '%s'
+					WHERE `id` = %d AND `network` = '%s'",
+					dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
+					dbesc($contact["addr"]), dbesc($contact["keywords"]), dbesc($contact["bdyear"]),
+					dbesc($contact["bd"]), dbesc($contact["name-date"]), dbesc($contact["uri-date"]),
+					intval($contact["id"]), dbesc($contact["network"]));
+			}
+
+			update_contact_avatar($author["avatar"], $importer["uid"], $contact["id"],
+						(strtotime($contact["avatar-date"]) > strtotime($r[0]["avatar-date"])));
+
+			$contact["generation"] = 2;
+			$contact["photo"] = $author["avatar"];
+			update_gcontact($contact);
+		}
+
+		return($author);
+	}
+
+	private function transform_activity($xpath, $activity, $element) {
+		if (!is_object($activity))
+			return "";
+
+		$obj_doc = new DOMDocument("1.0", "utf-8");
+		$obj_doc->formatOutput = true;
+
+		$obj_element = $obj_doc->createElementNS(NAMESPACE_ATOM1, $element);
+
+		$activity_type = $xpath->query("activity:object-type/text()", $activity)->item(0)->nodeValue;
+		xml_add_element($obj_doc, $obj_element, "type", $activity_type);
+
+		$id = $xpath->query("atom:id", $activity)->item(0);
+		if (is_object($id))
+			$obj_element->appendChild($obj_doc->importNode($id, true));
+
+		$title = $xpath->query("atom:title", $activity)->item(0);
+		if (is_object($title))
+			$obj_element->appendChild($obj_doc->importNode($title, true));
+
+		$link = $xpath->query("atom:link", $activity)->item(0);
+		if (is_object($link))
+			$obj_element->appendChild($obj_doc->importNode($link, true));
+
+		$content = $xpath->query("atom:content", $activity)->item(0);
+		if (is_object($content))
+			$obj_element->appendChild($obj_doc->importNode($content, true));
+
+		$obj_doc->appendChild($obj_element);
+
+		$objxml = $obj_doc->saveXML($obj_element);
+
+		// @todo This isn't totally clean. We should find a way to transform the namespaces
+		$objxml = str_replace("<".$element.' xmlns="http://www.w3.org/2005/Atom">', "<".$element.">", $objxml);
+		return($objxml);
+	}
+
+	private function process_mail($xpath, $mail, $importer) {
+
+		logger("Processing mails");
+
+		$msg = array();
+		$msg["uid"] = $importer["importer_uid"];
+		$msg["from-name"] = $xpath->query("dfrn:sender/dfrn:name/text()", $mail)->item(0)->nodeValue;
+		$msg["from-url"] = $xpath->query("dfrn:sender/dfrn:uri/text()", $mail)->item(0)->nodeValue;
+		$msg["from-photo"] = $xpath->query("dfrn:sender/dfrn:avatar/text()", $mail)->item(0)->nodeValue;
+		$msg["contact-id"] = $importer["id"];
+		$msg["uri"] = $xpath->query("dfrn:id/text()", $mail)->item(0)->nodeValue;
+		$msg["parent-uri"] = $xpath->query("dfrn:in-reply-to/text()", $mail)->item(0)->nodeValue;
+		$msg["created"] = $xpath->query("dfrn:sentdate/text()", $mail)->item(0)->nodeValue;
+		$msg["title"] = $xpath->query("dfrn:subject/text()", $mail)->item(0)->nodeValue;
+		$msg["body"] = $xpath->query("dfrn:content/text()", $mail)->item(0)->nodeValue;
+		$msg["seen"] = 0;
+		$msg["replied"] = 0;
+
+		dbesc_array($msg);
+
+		$r = dbq("INSERT INTO `mail` (`".implode("`, `", array_keys($msg))."`) VALUES ('".implode("', '", array_values($msg))."')");
+
+		// send notifications.
+
+		$notif_params = array(
+			"type" => NOTIFY_MAIL,
+			"notify_flags" => $importer["notify-flags"],
+			"language" => $importer["language"],
+			"to_name" => $importer["username"],
+			"to_email" => $importer["email"],
+			"uid" => $importer["importer_uid"],
+			"item" => $msg,
+			"source_name" => $msg["from-name"],
+			"source_link" => $importer["url"],
+			"source_photo" => $importer["thumb"],
+			"verb" => ACTIVITY_POST,
+			"otype" => "mail"
+		);
+
+		notification($notif_params);
+
+		logger("Mail is processed, notification was sent.");
+	}
+
+	private function process_suggestion($xpath, $suggestion, $importer) {
+
+		logger("Processing suggestions");
+
+		$suggest = array();
+		$suggest["uid"] = $importer["importer_uid"];
+		$suggest["cid"] = $importer["id"];
+		$suggest["url"] = $xpath->query("dfrn:url/text()", $suggestion)->item(0)->nodeValue;
+		$suggest["name"] = $xpath->query("dfrn:name/text()", $suggestion)->item(0)->nodeValue;
+		$suggest["photo"] = $xpath->query("dfrn:photo/text()", $suggestion)->item(0)->nodeValue;
+		$suggest["request"] = $xpath->query("dfrn:request/text()", $suggestion)->item(0)->nodeValue;
+		$suggest["body"] = $xpath->query("dfrn:note/text()", $suggestion)->item(0)->nodeValue;
+
+		// Does our member already have a friend matching this description?
+
+		$r = q("SELECT `id` FROM `contact` WHERE `name` = '%s' AND `nurl` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc($suggest["name"]),
+			dbesc(normalise_link($suggest["url"])),
+			intval($suggest["uid"])
+		);
+		if(count($r))
+			return false;
+
+		// Do we already have an fcontact record for this person?
+
+		$fid = 0;
+		$r = q("SELECT `id` FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1",
+			dbesc($suggest["url"]),
+			dbesc($suggest["name"]),
+			dbesc($suggest["request"])
+		);
+		if(count($r)) {
+			$fid = $r[0]["id"];
+
+			// OK, we do. Do we already have an introduction for this person ?
+			$r = q("SELECT `id` FROM `intro` WHERE `uid` = %d AND `fid` = %d LIMIT 1",
+				intval($suggest["uid"]),
+				intval($fid)
+			);
+			if(count($r))
+				return false;
+		}
+		if(!$fid)
+			$r = q("INSERT INTO `fcontact` (`name`,`url`,`photo`,`request`) VALUES ('%s', '%s', '%s', '%s')",
+			dbesc($suggest["name"]),
+			dbesc($suggest["url"]),
+			dbesc($suggest["photo"]),
+			dbesc($suggest["request"])
+		);
+		$r = q("SELECT `id` FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1",
+			dbesc($suggest["url"]),
+			dbesc($suggest["name"]),
+			dbesc($suggest["request"])
+		);
+		if(count($r))
+			$fid = $r[0]["id"];
+		else
+			// database record did not get created. Quietly give up.
+			return false;
+
+
+		$hash = random_string();
+
+		$r = q("INSERT INTO `intro` (`uid`, `fid`, `contact-id`, `note`, `hash`, `datetime`, `blocked`)
+			VALUES(%d, %d, %d, '%s', '%s', '%s', %d)",
+			intval($suggest["uid"]),
+			intval($fid),
+			intval($suggest["cid"]),
+			dbesc($suggest["body"]),
+			dbesc($hash),
+			dbesc(datetime_convert()),
+			intval(0)
+		);
+
+		notification(array(
+			"type"         => NOTIFY_SUGGEST,
+			"notify_flags" => $importer["notify-flags"],
+			"language"     => $importer["language"],
+			"to_name"      => $importer["username"],
+			"to_email"     => $importer["email"],
+			"uid"          => $importer["importer_uid"],
+			"item"         => $suggest,
+			"link"         => App::get_baseurl()."/notifications/intros",
+			"source_name"  => $importer["name"],
+			"source_link"  => $importer["url"],
+			"source_photo" => $importer["photo"],
+			"verb"         => ACTIVITY_REQ_FRIEND,
+			"otype"        => "intro"
+		));
+
+		return true;
+
+	}
+
+	private function process_relocation($xpath, $relocation, $importer) {
+
+		logger("Processing relocations");
+
+		$relocate = array();
+		$relocate["uid"] = $importer["importer_uid"];
+		$relocate["cid"] = $importer["id"];
+		$relocate["url"] = $xpath->query("dfrn:url/text()", $relocation)->item(0)->nodeValue;
+		$relocate["name"] = $xpath->query("dfrn:name/text()", $relocation)->item(0)->nodeValue;
+		$relocate["photo"] = $xpath->query("dfrn:photo/text()", $relocation)->item(0)->nodeValue;
+		$relocate["thumb"] = $xpath->query("dfrn:thumb/text()", $relocation)->item(0)->nodeValue;
+		$relocate["micro"] = $xpath->query("dfrn:micro/text()", $relocation)->item(0)->nodeValue;
+		$relocate["request"] = $xpath->query("dfrn:request/text()", $relocation)->item(0)->nodeValue;
+		$relocate["confirm"] = $xpath->query("dfrn:confirm/text()", $relocation)->item(0)->nodeValue;
+		$relocate["notify"] = $xpath->query("dfrn:notify/text()", $relocation)->item(0)->nodeValue;
+		$relocate["poll"] = $xpath->query("dfrn:poll/text()", $relocation)->item(0)->nodeValue;
+		$relocate["sitepubkey"] = $xpath->query("dfrn:sitepubkey/text()", $relocation)->item(0)->nodeValue;
+
+		// update contact
+		$r = q("SELECT `photo`, `url` FROM `contact` WHERE `id` = %d AND `uid` = %d;",
+			intval($importer["id"]),
+			intval($importer["importer_uid"]));
+		if (!$r)
+			return false;
+
+		$old = $r[0];
+
+		$x = q("UPDATE `contact` SET
+					`name` = '%s',
+					`photo` = '%s',
+					`thumb` = '%s',
+					`micro` = '%s',
+					`url` = '%s',
+					`nurl` = '%s',
+					`request` = '%s',
+					`confirm` = '%s',
+					`notify` = '%s',
+					`poll` = '%s',
+					`site-pubkey` = '%s'
+			WHERE `id` = %d AND `uid` = %d;",
+					dbesc($relocate["name"]),
+					dbesc($relocate["photo"]),
+					dbesc($relocate["thumb"]),
+					dbesc($relocate["micro"]),
+					dbesc($relocate["url"]),
+					dbesc(normalise_link($relocate["url"])),
+					dbesc($relocate["request"]),
+					dbesc($relocate["confirm"]),
+					dbesc($relocate["notify"]),
+					dbesc($relocate["poll"]),
+					dbesc($relocate["sitepubkey"]),
+					intval($importer["id"]),
+					intval($importer["importer_uid"]));
+
+		if ($x === false)
+			return false;
+
+		// update items
+		$fields = array(
+			'owner-link' => array($old["url"], $relocate["url"]),
+			'author-link' => array($old["url"], $relocate["url"]),
+			'owner-avatar' => array($old["photo"], $relocate["photo"]),
+			'author-avatar' => array($old["photo"], $relocate["photo"]),
+			);
+		foreach ($fields as $n=>$f){
+			$x = q("UPDATE `item` SET `%s` = '%s' WHERE `%s` = '%s' AND `uid` = %d",
+					$n, dbesc($f[1]),
+					$n, dbesc($f[0]),
+					intval($importer["importer_uid"]));
+				if ($x === false)
+					return false;
+			}
+
+		/// @TODO
+		/// merge with current record, current contents have priority
+		/// update record, set url-updated
+		/// update profile photos
+		/// schedule a scan?
+		return true;
+	}
+
+	private function update_content($current, $item, $importer, $entrytype) {
+		$changed = false;
+
+		if (edited_timestamp_is_newer($current, $item)) {
+
+			// do not accept (ignore) an earlier edit than one we currently have.
+			if(datetime_convert("UTC","UTC",$item["edited"]) < $current["edited"])
+				return(false);
+
+			$r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
+				dbesc($item["title"]),
+				dbesc($item["body"]),
+				dbesc($item["tag"]),
+				dbesc(datetime_convert("UTC","UTC",$item["edited"])),
+				dbesc(datetime_convert()),
+				dbesc($item["uri"]),
+				intval($importer["importer_uid"])
+			);
+			create_tags_from_itemuri($item["uri"], $importer["importer_uid"]);
+			update_thread_uri($item["uri"], $importer["importer_uid"]);
+
+			$changed = true;
+
+			if ($entrytype == DFRN_REPLY_RC)
+				proc_run("php", "include/notifier.php","comment-import", $current["id"]);
+		}
+
+		// update last-child if it changes
+		if($item["last-child"] AND ($item["last-child"] != $current["last-child"])) {
+			$r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
+				dbesc(datetime_convert()),
+				dbesc($item["parent-uri"]),
+				intval($importer["importer_uid"])
+			);
+			$r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
+				intval($item["last-child"]),
+				dbesc(datetime_convert()),
+				dbesc($item["uri"]),
+				intval($importer["importer_uid"])
+			);
+		}
+		return $changed;
+	}
+
+	private function get_entry_type($importer, $item) {
+		if ($item["parent-uri"] != $item["uri"]) {
+			$community = false;
+
+			if($importer["page-flags"] == PAGE_COMMUNITY || $importer["page-flags"] == PAGE_PRVGROUP) {
+				$sql_extra = "";
+				$community = true;
+				logger("possible community action");
+			} else
+				$sql_extra = " AND `contact`.`self` AND `item`.`wall` ";
+
+			// was the top-level post for this action written by somebody on this site?
+			// Specifically, the recipient?
+
+			$is_a_remote_action = false;
+
+			$r = q("SELECT `item`.`parent-uri` FROM `item`
+				WHERE `item`.`uri` = '%s'
+				LIMIT 1",
+				dbesc($item["parent-uri"])
+			);
+			if($r && count($r)) {
+				$r = q("SELECT `item`.`forum_mode`, `item`.`wall` FROM `item`
+					INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
+					WHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' OR `item`.`thr-parent` = '%s')
+					AND `item`.`uid` = %d
+					$sql_extra
+					LIMIT 1",
+					dbesc($r[0]["parent-uri"]),
+					dbesc($r[0]["parent-uri"]),
+					dbesc($r[0]["parent-uri"]),
+					intval($importer["importer_uid"])
+				);
+				if($r && count($r))
+					$is_a_remote_action = true;
+			}
+
+			// Does this have the characteristics of a community or private group action?
+			// If it's an action to a wall post on a community/prvgroup page it's a
+			// valid community action. Also forum_mode makes it valid for sure.
+			// If neither, it's not.
+
+			if($is_a_remote_action && $community) {
+				if((!$r[0]["forum_mode"]) && (!$r[0]["wall"])) {
+					$is_a_remote_action = false;
+					logger("not a community action");
+				}
+			}
+
+			if ($is_a_remote_action)
+				return DFRN_REPLY_RC;
+			else
+				return DFRN_REPLY;
+
+		} else
+			return DFRN_TOP_LEVEL;
+
+	}
+
+	private function do_poke($item, $importer, $posted_id) {
+		$verb = urldecode(substr($item["verb"],strpos($item["verb"], "#")+1));
+		if(!$verb)
+			return;
+		$xo = parse_xml_string($item["object"],false);
+
+		if(($xo->type == ACTIVITY_OBJ_PERSON) && ($xo->id)) {
+
+			// somebody was poked/prodded. Was it me?
+			$links = parse_xml_string("<links>".unxmlify($xo->link)."</links>",false);
+
+			foreach($links->link as $l) {
+				$atts = $l->attributes();
+				switch($atts["rel"]) {
+					case "alternate":
+						$Blink = $atts["href"];
+						break;
+					default:
+						break;
+				}
+			}
+			if($Blink && link_compare($Blink,$a->get_baseurl()."/profile/".$importer["nickname"])) {
+
+				// send a notification
+				notification(array(
+					"type"         => NOTIFY_POKE,
+					"notify_flags" => $importer["notify-flags"],
+					"language"     => $importer["language"],
+					"to_name"      => $importer["username"],
+					"to_email"     => $importer["email"],
+					"uid"          => $importer["importer_uid"],
+					"item"         => $item,
+					"link"         => $a->get_baseurl()."/display/".urlencode(get_item_guid($posted_id)),
+					"source_name"  => stripslashes($item["author-name"]),
+					"source_link"  => $item["author-link"],
+					"source_photo" => ((link_compare($item["author-link"],$importer["url"]))
+						? $importer["thumb"] : $item["author-avatar"]),
+					"verb"         => $item["verb"],
+					"otype"        => "person",
+					"activity"     => $verb,
+					"parent"       => $item["parent"]
+				));
+			}
+		}
+	}
+
+	private function process_entry($header, $xpath, $entry, $importer) {
+
+		logger("Processing entries");
+
+		$item = $header;
+
+		// Get the uri
+		$item["uri"] = $xpath->query("atom:id/text()", $entry)->item(0)->nodeValue;
+
+		// Fetch the owner
+		$owner = self::fetchauthor($xpath, $entry, $importer, "dfrn:owner", true);
+
+		$item["owner-name"] = $owner["name"];
+		$item["owner-link"] = $owner["link"];
+		$item["owner-avatar"] = $owner["avatar"];
+
+		// fetch the author
+		$author = self::fetchauthor($xpath, $entry, $importer, "atom:author", true);
+
+		$item["author-name"] = $author["name"];
+		$item["author-link"] = $author["link"];
+		$item["author-avatar"] = $author["avatar"];
+
+		$item["title"] = $xpath->query("atom:title/text()", $entry)->item(0)->nodeValue;
+
+		$item["created"] = $xpath->query("atom:published/text()", $entry)->item(0)->nodeValue;
+		$item["edited"] = $xpath->query("atom:updated/text()", $entry)->item(0)->nodeValue;
+
+		$item["body"] = $xpath->query("dfrn:env/text()", $entry)->item(0)->nodeValue;
+		$item["body"] = str_replace(array(' ',"\t","\r","\n"), array('','','',''),$item["body"]);
+		// make sure nobody is trying to sneak some html tags by us
+		$item["body"] = notags(base64url_decode($item["body"]));
+
+		$item["body"] = limit_body_size($item["body"]);
+
+		/// @todo Do we really need this check for HTML elements? (It was copied from the old function)
+		if((strpos($item['body'],'<') !== false) && (strpos($item['body'],'>') !== false)) {
+
+			$item['body'] = reltoabs($item['body'],$base_url);
+
+			$item['body'] = html2bb_video($item['body']);
+
+			$item['body'] = oembed_html2bbcode($item['body']);
+
+			$config = HTMLPurifier_Config::createDefault();
+			$config->set('Cache.DefinitionImpl', null);
+
+			// we shouldn't need a whitelist, because the bbcode converter
+			// will strip out any unsupported tags.
+
+			$purifier = new HTMLPurifier($config);
+			$item['body'] = $purifier->purify($item['body']);
+
+			$item['body'] = @html2bbcode($item['body']);
+		}
+
+		// We don't need the content element since "dfrn:env" is always present
+		//$item["body"] = $xpath->query("atom:content/text()", $entry)->item(0)->nodeValue;
+
+		$item["last-child"] = $xpath->query("dfrn:comment-allow/text()", $entry)->item(0)->nodeValue;
+		$item["location"] = $xpath->query("dfrn:location/text()", $entry)->item(0)->nodeValue;
+
+		$georsspoint = $xpath->query("georss:point", $entry);
+		if ($georsspoint)
+			$item["coord"] = $georsspoint->item(0)->nodeValue;
+
+		$item["private"] = $xpath->query("dfrn:private/text()", $entry)->item(0)->nodeValue;
+
+		$item["extid"] = $xpath->query("dfrn:extid/text()", $entry)->item(0)->nodeValue;
+
+		if ($xpath->query("dfrn:extid/text()", $entry)->item(0)->nodeValue == "true")
+			$item["bookmark"] = true;
+
+		$notice_info = $xpath->query("statusnet:notice_info", $entry);
+		if ($notice_info AND ($notice_info->length > 0)) {
+			foreach($notice_info->item(0)->attributes AS $attributes) {
+				if ($attributes->name == "source")
+					$item["app"] = strip_tags($attributes->textContent);
+			}
+		}
+
+		$item["guid"] = $xpath->query("dfrn:diaspora_guid/text()", $entry)->item(0)->nodeValue;
+
+		// We store the data from "dfrn:diaspora_signature" in a different table, this is done in "item_store"
+		$dsprsig = unxmlify($xpath->query("dfrn:diaspora_signature/text()", $entry)->item(0)->nodeValue);
+		if ($dsprsig != "")
+			$item["dsprsig"] = $dsprsig;
+
+		$item["verb"] = $xpath->query("activity:verb/text()", $entry)->item(0)->nodeValue;
+
+		if ($xpath->query("activity:object-type/text()", $entry)->item(0)->nodeValue != "")
+			$item["object-type"] = $xpath->query("activity:object-type/text()", $entry)->item(0)->nodeValue;
+
+		$object = $xpath->query("activity:object", $entry)->item(0);
+		$item["object"] = self::transform_activity($xpath, $object, "object");
+
+		if (trim($item["object"]) != "") {
+			$r = parse_xml_string($item["object"], false);
+			if (isset($r->type))
+				$item["object-type"] = $r->type;
+		}
+
+		$target = $xpath->query("activity:target", $entry)->item(0);
+		$item["target"] = self::transform_activity($xpath, $target, "target");
+
+		$categories = $xpath->query("atom:category", $entry);
+		if ($categories) {
+			foreach ($categories AS $category) {
+				foreach($category->attributes AS $attributes)
+					if ($attributes->name == "term") {
+						$term = $attributes->textContent;
+						if(strlen($item["tag"]))
+							$item["tag"] .= ",";
+
+						$item["tag"] .= "#[url=".App::get_baseurl()."/search?tag=".$term."]".$term."[/url]";
+					}
+			}
+		}
+
+		$enclosure = "";
+
+		$links = $xpath->query("atom:link", $entry);
+		if ($links) {
+			$rel = "";
+			$href = "";
+			$type = "";
+			$length = "0";
+			$title = "";
+			foreach ($links AS $link) {
+				foreach($link->attributes AS $attributes) {
+					if ($attributes->name == "href")
+						$href = $attributes->textContent;
+					if ($attributes->name == "rel")
+						$rel = $attributes->textContent;
+					if ($attributes->name == "type")
+						$type = $attributes->textContent;
+					if ($attributes->name == "length")
+						$length = $attributes->textContent;
+					if ($attributes->name == "title")
+						$title = $attributes->textContent;
+				}
+				if (($rel != "") AND ($href != ""))
+					switch($rel) {
+						case "alternate":
+							$item["plink"] = $href;
+							break;
+						case "enclosure":
+							$enclosure = $href;
+							if(strlen($item["attach"]))
+								$item["attach"] .= ",";
+
+							$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
+							break;
+					}
+			}
+		}
+
+		// Is it a reply or a top level posting?
+		$item["parent-uri"] = $item["uri"];
+
+		$inreplyto = $xpath->query("thr:in-reply-to", $entry);
+		if (is_object($inreplyto->item(0)))
+			foreach($inreplyto->item(0)->attributes AS $attributes)
+				if ($attributes->name == "ref")
+					$item["parent-uri"] = $attributes->textContent;
+
+		// Get the type of the item (Top level post, reply or remote reply)
+		$entrytype = self::get_entry_type($importer, $item);
+
+		// Now assign the rest of the values that depend on the type of the message
+		if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) {
+			if (!isset($item["object-type"]))
+				$item["object-type"] = ACTIVITY_OBJ_COMMENT;
+
+			if ($item["contact-id"] != $owner["contact-id"])
+				$item["contact-id"] = $owner["contact-id"];
+
+			if (($item["network"] != $owner["network"]) AND ($owner["network"] != ""))
+				$item["network"] = $owner["network"];
+
+			if ($item["contact-id"] != $author["contact-id"])
+				$item["contact-id"] = $author["contact-id"];
+
+			if (($item["network"] != $author["network"]) AND ($author["network"] != ""))
+				$item["network"] = $author["network"];
+		}
+
+		if ($entrytype == DFRN_REPLY_RC) {
+			$item["type"] = "remote-comment";
+			$item["wall"] = 1;
+		} elseif ($entrytype == DFRN_TOP_LEVEL) {
+			if (!isset($item["object-type"]))
+				$item["object-type"] = ACTIVITY_OBJ_NOTE;
+
+			if ($item["object-type"] == ACTIVITY_OBJ_EVENT) {
+				logger("Item ".$item["uri"]." seems to contain an event.", LOGGER_DEBUG);
+				$ev = bbtoevent($item["body"]);
+				if((x($ev, "desc") || x($ev, "summary")) && x($ev, "start")) {
+					logger("Event in item ".$item["uri"]." was found.", LOGGER_DEBUG);
+					$ev["cid"] = $importer["id"];
+					$ev["uid"] = $importer["uid"];
+					$ev["uri"] = $item["uri"];
+					$ev["edited"] = $item["edited"];
+					$ev['private'] = $item['private'];
+					$ev["guid"] = $item["guid"];
+
+					$r = q("SELECT `id` FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+						dbesc($item["uri"]),
+						intval($importer["uid"])
+					);
+					if(count($r))
+						$ev["id"] = $r[0]["id"];
+
+					$event_id = event_store($ev);
+					logger("Event ".$event_id." was stored", LOGGER_DEBUG);
+					return;
+				}
+			}
+
+			// The filling of the the "contact" variable is done for legcy reasons
+			// The functions below are partly used by ostatus.php as well - where we have this variable
+			$r = q("SELECT * FROM `contact` WHERE `id` = %d", intval($importer["id"]));
+			$contact = $r[0];
+			$nickname = $contact["nick"];
+
+			// Big question: Do we need these functions? They were part of the "consume_feed" function.
+			// This function once was responsible for DFRN and OStatus.
+			if(activity_match($item['verb'],ACTIVITY_FOLLOW)) {
+				logger('New follower');
+				new_follower($importer, $contact, $item, $nickname);
+				return;
+			}
+			if(activity_match($item['verb'],ACTIVITY_UNFOLLOW))  {
+				logger('Lost follower');
+				lose_follower($importer, $contact, $item);
+				return;
+			}
+			if(activity_match($item['verb'],ACTIVITY_REQ_FRIEND)) {
+				logger('New friend request');
+				new_follower($importer, $contact, $item, $nickname, true);
+				return;
+			}
+			if(activity_match($item['verb'],ACTIVITY_UNFRIEND))  {
+				logger('Lost sharer');
+				lose_sharer($importer, $contact, $item);
+				return;
+			}
+		}
+
+		$r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc($item["uri"]),
+			intval($importer["importer_uid"])
+		);
+
+		// Update content if 'updated' changes
+		if(count($r)) {
+			if (self::update_content($r[0], $item, $importer, $entrytype))
+				logger("Item ".$item["uri"]." was updated.", LOGGER_DEBUG);
+			else
+				logger("Item ".$item["uri"]." already existed.", LOGGER_DEBUG);
+			return;
+		}
+
+		if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) {
+			if($importer["rel"] == CONTACT_IS_FOLLOWER) {
+				logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG);
+				return;
+			}
+
+			if(($item["verb"] === ACTIVITY_LIKE)
+				|| ($item["verb"] === ACTIVITY_DISLIKE)
+				|| ($item["verb"] === ACTIVITY_ATTEND)
+				|| ($item["verb"] === ACTIVITY_ATTENDNO)
+				|| ($item["verb"] === ACTIVITY_ATTENDMAYBE)) {
+				$is_like = true;
+				$item["type"] = "activity";
+				$item["gravity"] = GRAVITY_LIKE;
+				// only one like or dislike per person
+				// splitted into two queries for performance issues
+				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1",
+					intval($item["uid"]),
+					dbesc($item["author-link"]),
+					dbesc($item["verb"]),
+					dbesc($item["parent-uri"])
+				);
+				if($r && count($r))
+					return;
+
+				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1",
+					intval($item["uid"]),
+					dbesc($item["author-link"]),
+					dbesc($item["verb"]),
+					dbesc($item["parent-uri"])
+				);
+				if($r && count($r))
+					return;
+
+			} else
+				$is_like = false;
+
+			if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
+
+				$xo = parse_xml_string($item["object"],false);
+				$xt = parse_xml_string($item["target"],false);
+
+				if($xt->type == ACTIVITY_OBJ_NOTE) {
+					$r = q("SELECT `id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+						dbesc($xt->id),
+						intval($importer["importer_uid"])
+					);
+
+					if(!count($r))
+						return;
+
+					// extract tag, if not duplicate, add to parent item
+					if($xo->content) {
+						if(!(stristr($r[0]["tag"],trim($xo->content)))) {
+							q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
+								dbesc($r[0]["tag"] . (strlen($r[0]["tag"]) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'),
+								intval($r[0]["id"])
+							);
+							create_tags_from_item($r[0]["id"]);
+						}
+					}
+				}
+			}
+
+			$posted_id = item_store($item);
+			$parent = 0;
+
+			if($posted_id) {
+
+				logger("Reply from contact ".$item["contact-id"]." was stored with id ".$posted_id, LOGGER_DEBUG);
+
+				$item["id"] = $posted_id;
+
+				$r = q("SELECT `parent`, `parent-uri` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+					intval($posted_id),
+					intval($importer["importer_uid"])
+				);
+				if(count($r)) {
+					$parent = $r[0]["parent"];
+					$parent_uri = $r[0]["parent-uri"];
+				}
+
+				if(!$is_like) {
+					$r1 = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `uid` = %d AND `parent` = %d",
+						dbesc(datetime_convert()),
+						intval($importer["importer_uid"]),
+						intval($r[0]["parent"])
+					);
+
+					$r2 = q("UPDATE `item` SET `last-child` = 1, `changed` = '%s' WHERE `uid` = %d AND `id` = %d",
+						dbesc(datetime_convert()),
+						intval($importer["importer_uid"]),
+						intval($posted_id)
+					);
+				}
+
+				if($posted_id AND $parent AND ($entrytype == DFRN_REPLY_RC)) {
+					logger("Notifying followers about comment ".$posted_id, LOGGER_DEBUG);
+					proc_run("php", "include/notifier.php", "comment-import", $posted_id);
+				}
+
+				return true;
+			}
+		} else {
+			if(!link_compare($item["owner-link"],$importer["url"])) {
+				// The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
+				// but otherwise there's a possible data mixup on the sender's system.
+				// the tgroup delivery code called from item_store will correct it if it's a forum,
+				// but we're going to unconditionally correct it here so that the post will always be owned by our contact.
+				logger('Correcting item owner.', LOGGER_DEBUG);
+				$item["owner-name"]   = $importer["senderName"];
+				$item["owner-link"]   = $importer["url"];
+				$item["owner-avatar"] = $importer["thumb"];
+			}
+
+			if(($importer["rel"] == CONTACT_IS_FOLLOWER) && (!tgroup_check($importer["importer_uid"], $item))) {
+				logger("Contact ".$importer["id"]." is only follower and tgroup check was negative.", LOGGER_DEBUG);
+				return;
+			}
+
+			// This is my contact on another system, but it's really me.
+			// Turn this into a wall post.
+			$notify = item_is_remote_self($importer, $item);
+
+			$posted_id = item_store($item, false, $notify);
+
+			logger("Item was stored with id ".$posted_id, LOGGER_DEBUG);
+
+			if(stristr($item["verb"],ACTIVITY_POKE))
+				self::do_poke($item, $importer, $posted_id);
+		}
+	}
+
+	private function process_deletion($header, $xpath, $deletion, $importer) {
+
+		logger("Processing deletions");
+
+		foreach($deletion->attributes AS $attributes) {
+			if ($attributes->name == "ref")
+				$uri = $attributes->textContent;
+			if ($attributes->name == "when")
+				$when = $attributes->textContent;
+		}
+		if ($when)
+			$when = datetime_convert("UTC", "UTC", $when, "Y-m-d H:i:s");
+		else
+			$when = datetime_convert("UTC", "UTC", "now", "Y-m-d H:i:s");
+
+		if (!$uri OR !$importer["id"])
+			return false;
+
+		/// @todo Only select the used fields
+		$r = q("SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN `contact` on `item`.`contact-id` = `contact`.`id`
+				WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1",
+				dbesc($uri),
+				intval($importer["uid"]),
+				intval($importer["id"])
+			);
+		if(!count($r)) {
+			logger("Item with uri ".$uri." from contact ".$importer["id"]." for user ".$importer["uid"]." wasn't found.", LOGGER_DEBUG);
+			return;
+		} else {
+
+			$item = $r[0];
+
+			$entrytype = self::get_entry_type($importer, $item);
+
+			if(!$item["deleted"])
+				logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG);
+			else
+				return;
+
+			if($item["object-type"] === ACTIVITY_OBJ_EVENT) {
+				logger("Deleting event ".$item["event-id"], LOGGER_DEBUG);
+				event_delete($item["event-id"]);
+			}
+
+			if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
+				$xo = parse_xml_string($item["object"],false);
+				$xt = parse_xml_string($item["target"],false);
+				if($xt->type === ACTIVITY_OBJ_NOTE) {
+					$i = q("SELECT `id`, `contact-id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+						dbesc($xt->id),
+						intval($importer["importer_uid"])
+					);
+					if(count($i)) {
+
+						// For tags, the owner cannot remove the tag on the author's copy of the post.
+
+						$owner_remove = (($item["contact-id"] == $i[0]["contact-id"]) ? true: false);
+						$author_remove = (($item["origin"] && $item["self"]) ? true : false);
+						$author_copy = (($item["origin"]) ? true : false);
+
+						if($owner_remove && $author_copy)
+							return;
+						if($author_remove || $owner_remove) {
+							$tags = explode(',',$i[0]["tag"]);
+							$newtags = array();
+							if(count($tags)) {
+								foreach($tags as $tag)
+									if(trim($tag) !== trim($xo->body))
+										$newtags[] = trim($tag);
+							}
+							q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
+								dbesc(implode(',',$newtags)),
+								intval($i[0]["id"])
+							);
+							create_tags_from_item($i[0]["id"]);
+						}
+					}
+				}
+			}
+
+			if($entrytype == DFRN_TOP_LEVEL) {
+				$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
+						`body` = '', `title` = ''
+					WHERE `parent-uri` = '%s' AND `uid` = %d",
+						dbesc($when),
+						dbesc(datetime_convert()),
+						dbesc($uri),
+						intval($importer["uid"])
+					);
+				create_tags_from_itemuri($uri, $importer["uid"]);
+				create_files_from_itemuri($uri, $importer["uid"]);
+				update_thread_uri($uri, $importer["uid"]);
+			} else {
+				$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
+						`body` = '', `title` = ''
+					WHERE `uri` = '%s' AND `uid` = %d",
+						dbesc($when),
+						dbesc(datetime_convert()),
+						dbesc($uri),
+						intval($importer["uid"])
+					);
+				create_tags_from_itemuri($uri, $importer["uid"]);
+				create_files_from_itemuri($uri, $importer["uid"]);
+				update_thread_uri($uri, $importer["importer_uid"]);
+				if($item["last-child"]) {
+					// ensure that last-child is set in case the comment that had it just got wiped.
+					q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ",
+						dbesc(datetime_convert()),
+						dbesc($item["parent-uri"]),
+						intval($item["uid"])
+					);
+					// who is the last child now?
+					$r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `moderated` = 0 AND `uid` = %d
+						ORDER BY `created` DESC LIMIT 1",
+							dbesc($item["parent-uri"]),
+							intval($importer["uid"])
+					);
+					if(count($r)) {
+						q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d",
+							intval($r[0]["id"])
+						);
+					}
+				}
+				// if this is a relayed delete, propagate it to other recipients
+
+				if($entrytype == DFRN_REPLY_RC) {
+					logger("Notifying followers about deletion of post ".$item["id"], LOGGER_DEBUG);
+					proc_run("php", "include/notifier.php","drop", $item["id"]);
+				}
+			}
+		}
+	}
+
+	/**
+	 * @brief Imports a DFRN message
+	 *
+	 * @param text $xml The DFRN message
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 * @param bool $sort_by_date Is used when feeds are polled
+	 */
+	function import($xml,$importer, $sort_by_date = false) {
+
+		if ($xml == "")
+			return;
+
+		if($importer["readonly"]) {
+			// We aren't receiving stuff from this person. But we will quietly ignore them
+			// rather than a blatant "go away" message.
+			logger('ignoring contact '.$importer["id"]);
+			return;
+		}
+
+		$doc = new DOMDocument();
+		@$doc->loadXML($xml);
+
+		$xpath = new DomXPath($doc);
+		$xpath->registerNamespace("atom", NAMESPACE_ATOM1);
+		$xpath->registerNamespace("thr", NAMESPACE_THREAD);
+		$xpath->registerNamespace("at", NAMESPACE_TOMB);
+		$xpath->registerNamespace("media", NAMESPACE_MEDIA);
+		$xpath->registerNamespace("dfrn", NAMESPACE_DFRN);
+		$xpath->registerNamespace("activity", NAMESPACE_ACTIVITY);
+		$xpath->registerNamespace("georss", NAMESPACE_GEORSS);
+		$xpath->registerNamespace("poco", NAMESPACE_POCO);
+		$xpath->registerNamespace("ostatus", NAMESPACE_OSTATUS);
+		$xpath->registerNamespace("statusnet", NAMESPACE_STATUSNET);
+
+		$header = array();
+		$header["uid"] = $importer["uid"];
+		$header["network"] = NETWORK_DFRN;
+		$header["type"] = "remote";
+		$header["wall"] = 0;
+		$header["origin"] = 0;
+		$header["contact-id"] = $importer["id"];
+
+		// Update the contact table if the data has changed
+		// Only the "dfrn:owner" in the head section contains all data
+		self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", false);
+
+		logger("Import DFRN message for user ".$importer["uid"]." from contact ".$importer["id"], LOGGER_DEBUG);
+
+		// is it a public forum? Private forums aren't supported by now with this method
+		$forum = intval($xpath->evaluate("/atom:feed/dfrn:community/text()", $context)->item(0)->nodeValue);
+
+		if ($forum != $importer["forum"])
+			q("UPDATE `contact` SET `forum` = %d WHERE `forum` != %d AND `id` = %d",
+				intval($forum), intval($forum),
+				intval($importer["id"])
+			);
+
+		$mails = $xpath->query("/atom:feed/dfrn:mail");
+		foreach ($mails AS $mail)
+			self::process_mail($xpath, $mail, $importer);
+
+		$suggestions = $xpath->query("/atom:feed/dfrn:suggest");
+		foreach ($suggestions AS $suggestion)
+			self::process_suggestion($xpath, $suggestion, $importer);
+
+		$relocations = $xpath->query("/atom:feed/dfrn:relocate");
+		foreach ($relocations AS $relocation)
+			self::process_relocation($xpath, $relocation, $importer);
+
+		$deletions = $xpath->query("/atom:feed/at:deleted-entry");
+		foreach ($deletions AS $deletion)
+			self::process_deletion($header, $xpath, $deletion, $importer);
+
+		if (!$sort_by_date) {
+			$entries = $xpath->query("/atom:feed/atom:entry");
+			foreach ($entries AS $entry)
+				self::process_entry($header, $xpath, $entry, $importer);
+		} else {
+			$newentries = array();
+			$entries = $xpath->query("/atom:feed/atom:entry");
+			foreach ($entries AS $entry) {
+				$created = $xpath->query("atom:published/text()", $entry)->item(0)->nodeValue;
+				$newentries[strtotime($created)] = $entry;
+			}
+
+			// Now sort after the publishing date
+			ksort($newentries);
+
+			foreach ($newentries AS $entry)
+				self::process_entry($header, $xpath, $entry, $importer);
+		}
+		logger("Import done for user ".$importer["uid"]." from contact ".$importer["id"], LOGGER_DEBUG);
+	}
 }
+?>
diff --git a/include/import-dfrn.php b/include/import-dfrn.php
deleted file mode 100644
index 244018887b..0000000000
--- a/include/import-dfrn.php
+++ /dev/null
@@ -1,1229 +0,0 @@
-<?php
-require_once("include/enotify.php");
-require_once("include/threads.php");
-require_once("include/socgraph.php");
-require_once("include/items.php");
-require_once("include/tags.php");
-require_once("include/files.php");
-require_once("include/event.php");
-
-class dfrn2 {
-
-	const DFRN_TOP_LEVEL = 0;
-	const DFRN_REPLY = 1;
-	const DFRN_REPLY_RC = 2;
-
-	/**
-	 * @brief Add new birthday event for this person
-	 *
-	 * @param array $contact Contact record
-	 * @param string $birthday Birthday of the contact
-	 *
-	 */
-	private function birthday_event($contact, $birthday) {
-
-		logger("updating birthday: ".$birthday." for contact ".$contact["id"]);
-
-		$bdtext = sprintf(t("%s\'s birthday"), $contact["name"]);
-		$bdtext2 = sprintf(t("Happy Birthday %s"), " [url=".$contact["url"]."]".$contact["name"]."[/url]") ;
-
-
-		$r = q("INSERT INTO `event` (`uid`,`cid`,`created`,`edited`,`start`,`finish`,`summary`,`desc`,`type`)
-			VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
-			intval($contact["uid"]),
-			intval($contact["id"]),
-			dbesc(datetime_convert()),
-			dbesc(datetime_convert()),
-			dbesc(datetime_convert("UTC","UTC", $birthday)),
-			dbesc(datetime_convert("UTC","UTC", $birthday." + 1 day ")),
-			dbesc($bdtext),
-			dbesc($bdtext2),
-			dbesc("birthday")
-		);
-	}
-
-	/**
-	 * @brief Fetch the author data from head or entry items
-	 *
-	 * @param object $xpath XPath object
-	 * @param object $context In which context should the data be searched
-	 * @param array $importer Record of the importer user mixed with contact of the content
-	 * @param string $element Element name from which the data is fetched
-	 * @param bool $onlyfetch Should the data only be fetched or should it update the contact record as well
-	 *
-	 * @return Returns an array with relevant data of the author
-	 */
-	private function fetchauthor($xpath, $context, $importer, $element, $onlyfetch) {
-
-		$author = array();
-		$author["name"] = $xpath->evaluate($element."/atom:name/text()", $context)->item(0)->nodeValue;
-		$author["link"] = $xpath->evaluate($element."/atom:uri/text()", $context)->item(0)->nodeValue;
-
-		$r = q("SELECT `id`, `uid`, `network`, `avatar-date`, `name-date`, `uri-date`, `addr`,
-				`name`, `nick`, `about`, `location`, `keywords`, `bdyear`, `bd`
-				FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
-			intval($importer["uid"]), dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET));
-		if ($r) {
-			$contact = $r[0];
-			$author["contact-id"] = $r[0]["id"];
-			$author["network"] = $r[0]["network"];
-		} else {
-			$author["contact-id"] = $importer["id"];
-			$author["network"] = $importer["network"];
-			$onlyfetch = true;
-		}
-
-		// Until now we aren't serving different sizes - but maybe later
-		$avatarlist = array();
-		// @todo check if "avatar" or "photo" would be the best field in the specification
-		$avatars = $xpath->query($element."/atom:link[@rel='avatar']", $context);
-		foreach($avatars AS $avatar) {
-			$href = "";
-			$width = 0;
-			foreach($avatar->attributes AS $attributes) {
-				if ($attributes->name == "href")
-					$href = $attributes->textContent;
-				if ($attributes->name == "width")
-					$width = $attributes->textContent;
-				if ($attributes->name == "updated")
-					$contact["avatar-date"] = $attributes->textContent;
-			}
-			if (($width > 0) AND ($href != ""))
-				$avatarlist[$width] = $href;
-		}
-		if (count($avatarlist) > 0) {
-			krsort($avatarlist);
-			$author["avatar"] = current($avatarlist);
-		}
-
-		if ($r AND !$onlyfetch) {
-
-			// When was the last change to name or uri?
-			$name_element = $xpath->query($element."/atom:name", $context)->item(0);
-			foreach($name_element->attributes AS $attributes)
-				if ($attributes->name == "updated")
-					$contact["name-date"] = $attributes->textContent;
-
-			$link_element = $xpath->query($element."/atom:link", $context)->item(0);
-			foreach($link_element->attributes AS $attributes)
-				if ($attributes->name == "updated")
-					$contact["uri-date"] = $attributes->textContent;
-
-			// Update contact data
-			$value = $xpath->evaluate($element."/dfrn:handle/text()", $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["addr"] = $value;
-
-			$value = $xpath->evaluate($element."/poco:displayName/text()", $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["name"] = $value;
-
-			$value = $xpath->evaluate($element."/poco:preferredUsername/text()", $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["nick"] = $value;
-
-			$value = $xpath->evaluate($element."/poco:note/text()", $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["about"] = $value;
-
-			$value = $xpath->evaluate($element."/poco:address/poco:formatted/text()", $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["location"] = $value;
-
-			/// @todo Add support for the following fields that we don't support by now in the contact table:
-			/// - poco:utcOffset
-			/// - poco:ims
-			/// - poco:urls
-			/// - poco:locality
-			/// - poco:region
-			/// - poco:country
-
-			// Save the keywords into the contact table
-			$tags = array();
-			$tagelements = $xpath->evaluate($element."/poco:tags/text()", $context);
-			foreach($tagelements AS $tag)
-				$tags[$tag->nodeValue] = $tag->nodeValue;
-
-			if (count($tags))
-				$contact["keywords"] = implode(", ", $tags);
-
-			// "dfrn:birthday" contains the birthday converted to UTC
-			$old_bdyear = $contact["bdyear"];
-
-			$birthday = $xpath->evaluate($element."/dfrn:birthday/text()", $context)->item(0)->nodeValue;
-
-			if (strtotime($birthday) > time()) {
-				$bd_timestamp = strtotime($birthday);
-
-				$contact["bdyear"] = date("Y", $bd_timestamp);
-			}
-
-			// "poco:birthday" is the birthday in the format "yyyy-mm-dd"
-			$value = $xpath->evaluate($element."/poco:birthday/text()", $context)->item(0)->nodeValue;
-
-			if (!in_array($value, array("", "0000-00-00"))) {
-				$bdyear = date("Y");
-				$value = str_replace("0000", $bdyear, $value);
-
-				if (strtotime($value) < time()) {
-					$value = str_replace($bdyear, $bdyear + 1, $value);
-					$bdyear = $bdyear + 1;
-				}
-
-				$contact["bd"] = $value;
-			}
-
-			if ($old_bdyear != $contact["bdyear"])
-				self::birthday_event($contact, $birthday);
-
-			// Get all field names
-			$fields = array();
-			foreach ($r[0] AS $field => $data)
-				$fields[$field] = $data;
-
-			unset($fields["id"]);
-			unset($fields["uid"]);
-			unset($fields["avatar-date"]);
-			unset($fields["name-date"]);
-			unset($fields["uri-date"]);
-
-			 // Update check for this field has to be done differently
-			$datefields = array("name-date", "uri-date");
-			foreach ($datefields AS $field)
-				if (strtotime($contact[$field]) > strtotime($r[0][$field]))
-					$update = true;
-
-			foreach ($fields AS $field => $data)
-				if ($contact[$field] != $r[0][$field]) {
-					logger("Difference for contact ".$contact["id"]." in field '".$field."'. Old value: '".$contact[$field]."', new value '".$r[0][$field]."'", LOGGER_DEBUG);
-					$update = true;
-				}
-
-			if ($update) {
-				logger("Update contact data for contact ".$contact["id"], LOGGER_DEBUG);
-
-				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s',
-					`addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s',
-					`name-date`  = '%s', `uri-date` = '%s'
-					WHERE `id` = %d AND `network` = '%s'",
-					dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
-					dbesc($contact["addr"]), dbesc($contact["keywords"]), dbesc($contact["bdyear"]),
-					dbesc($contact["bd"]), dbesc($contact["name-date"]), dbesc($contact["uri-date"]),
-					intval($contact["id"]), dbesc($contact["network"]));
-			}
-
-			update_contact_avatar($author["avatar"], $importer["uid"], $contact["id"],
-						(strtotime($contact["avatar-date"]) > strtotime($r[0]["avatar-date"])));
-
-			$contact["generation"] = 2;
-			$contact["photo"] = $author["avatar"];
-			update_gcontact($contact);
-		}
-
-		return($author);
-	}
-
-	private function transform_activity($xpath, $activity, $element) {
-		if (!is_object($activity))
-			return "";
-
-		$obj_doc = new DOMDocument("1.0", "utf-8");
-		$obj_doc->formatOutput = true;
-
-		$obj_element = $obj_doc->createElementNS(NAMESPACE_ATOM1, $element);
-
-		$activity_type = $xpath->query("activity:object-type/text()", $activity)->item(0)->nodeValue;
-		xml_add_element($obj_doc, $obj_element, "type", $activity_type);
-
-		$id = $xpath->query("atom:id", $activity)->item(0);
-		if (is_object($id))
-			$obj_element->appendChild($obj_doc->importNode($id, true));
-
-		$title = $xpath->query("atom:title", $activity)->item(0);
-		if (is_object($title))
-			$obj_element->appendChild($obj_doc->importNode($title, true));
-
-		$link = $xpath->query("atom:link", $activity)->item(0);
-		if (is_object($link))
-			$obj_element->appendChild($obj_doc->importNode($link, true));
-
-		$content = $xpath->query("atom:content", $activity)->item(0);
-		if (is_object($content))
-			$obj_element->appendChild($obj_doc->importNode($content, true));
-
-		$obj_doc->appendChild($obj_element);
-
-		$objxml = $obj_doc->saveXML($obj_element);
-
-		// @todo This isn't totally clean. We should find a way to transform the namespaces
-		$objxml = str_replace("<".$element.' xmlns="http://www.w3.org/2005/Atom">', "<".$element.">", $objxml);
-		return($objxml);
-	}
-
-	private function process_mail($xpath, $mail, $importer) {
-
-		logger("Processing mails");
-
-		$msg = array();
-		$msg["uid"] = $importer["importer_uid"];
-		$msg["from-name"] = $xpath->query("dfrn:sender/dfrn:name/text()", $mail)->item(0)->nodeValue;
-		$msg["from-url"] = $xpath->query("dfrn:sender/dfrn:uri/text()", $mail)->item(0)->nodeValue;
-		$msg["from-photo"] = $xpath->query("dfrn:sender/dfrn:avatar/text()", $mail)->item(0)->nodeValue;
-		$msg["contact-id"] = $importer["id"];
-		$msg["uri"] = $xpath->query("dfrn:id/text()", $mail)->item(0)->nodeValue;
-		$msg["parent-uri"] = $xpath->query("dfrn:in-reply-to/text()", $mail)->item(0)->nodeValue;
-		$msg["created"] = $xpath->query("dfrn:sentdate/text()", $mail)->item(0)->nodeValue;
-		$msg["title"] = $xpath->query("dfrn:subject/text()", $mail)->item(0)->nodeValue;
-		$msg["body"] = $xpath->query("dfrn:content/text()", $mail)->item(0)->nodeValue;
-		$msg["seen"] = 0;
-		$msg["replied"] = 0;
-
-		dbesc_array($msg);
-
-		$r = dbq("INSERT INTO `mail` (`".implode("`, `", array_keys($msg))."`) VALUES ('".implode("', '", array_values($msg))."')");
-
-		// send notifications.
-
-		$notif_params = array(
-			"type" => NOTIFY_MAIL,
-			"notify_flags" => $importer["notify-flags"],
-			"language" => $importer["language"],
-			"to_name" => $importer["username"],
-			"to_email" => $importer["email"],
-			"uid" => $importer["importer_uid"],
-			"item" => $msg,
-			"source_name" => $msg["from-name"],
-			"source_link" => $importer["url"],
-			"source_photo" => $importer["thumb"],
-			"verb" => ACTIVITY_POST,
-			"otype" => "mail"
-		);
-
-		notification($notif_params);
-
-		logger("Mail is processed, notification was sent.");
-	}
-
-	private function process_suggestion($xpath, $suggestion, $importer) {
-
-		logger("Processing suggestions");
-
-		$suggest = array();
-		$suggest["uid"] = $importer["importer_uid"];
-		$suggest["cid"] = $importer["id"];
-		$suggest["url"] = $xpath->query("dfrn:url/text()", $suggestion)->item(0)->nodeValue;
-		$suggest["name"] = $xpath->query("dfrn:name/text()", $suggestion)->item(0)->nodeValue;
-		$suggest["photo"] = $xpath->query("dfrn:photo/text()", $suggestion)->item(0)->nodeValue;
-		$suggest["request"] = $xpath->query("dfrn:request/text()", $suggestion)->item(0)->nodeValue;
-		$suggest["body"] = $xpath->query("dfrn:note/text()", $suggestion)->item(0)->nodeValue;
-
-		// Does our member already have a friend matching this description?
-
-		$r = q("SELECT `id` FROM `contact` WHERE `name` = '%s' AND `nurl` = '%s' AND `uid` = %d LIMIT 1",
-			dbesc($suggest["name"]),
-			dbesc(normalise_link($suggest["url"])),
-			intval($suggest["uid"])
-		);
-		if(count($r))
-			return false;
-
-		// Do we already have an fcontact record for this person?
-
-		$fid = 0;
-		$r = q("SELECT `id` FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1",
-			dbesc($suggest["url"]),
-			dbesc($suggest["name"]),
-			dbesc($suggest["request"])
-		);
-		if(count($r)) {
-			$fid = $r[0]["id"];
-
-			// OK, we do. Do we already have an introduction for this person ?
-			$r = q("SELECT `id` FROM `intro` WHERE `uid` = %d AND `fid` = %d LIMIT 1",
-				intval($suggest["uid"]),
-				intval($fid)
-			);
-			if(count($r))
-				return false;
-		}
-		if(!$fid)
-			$r = q("INSERT INTO `fcontact` (`name`,`url`,`photo`,`request`) VALUES ('%s', '%s', '%s', '%s')",
-			dbesc($suggest["name"]),
-			dbesc($suggest["url"]),
-			dbesc($suggest["photo"]),
-			dbesc($suggest["request"])
-		);
-		$r = q("SELECT `id` FROM `fcontact` WHERE `url` = '%s' AND `name` = '%s' AND `request` = '%s' LIMIT 1",
-			dbesc($suggest["url"]),
-			dbesc($suggest["name"]),
-			dbesc($suggest["request"])
-		);
-		if(count($r))
-			$fid = $r[0]["id"];
-		else
-			// database record did not get created. Quietly give up.
-			return false;
-
-
-		$hash = random_string();
-
-		$r = q("INSERT INTO `intro` (`uid`, `fid`, `contact-id`, `note`, `hash`, `datetime`, `blocked`)
-			VALUES(%d, %d, %d, '%s', '%s', '%s', %d)",
-			intval($suggest["uid"]),
-			intval($fid),
-			intval($suggest["cid"]),
-			dbesc($suggest["body"]),
-			dbesc($hash),
-			dbesc(datetime_convert()),
-			intval(0)
-		);
-
-		notification(array(
-			"type"         => NOTIFY_SUGGEST,
-			"notify_flags" => $importer["notify-flags"],
-			"language"     => $importer["language"],
-			"to_name"      => $importer["username"],
-			"to_email"     => $importer["email"],
-			"uid"          => $importer["importer_uid"],
-			"item"         => $suggest,
-			"link"         => App::get_baseurl()."/notifications/intros",
-			"source_name"  => $importer["name"],
-			"source_link"  => $importer["url"],
-			"source_photo" => $importer["photo"],
-			"verb"         => ACTIVITY_REQ_FRIEND,
-			"otype"        => "intro"
-		));
-
-		return true;
-
-	}
-
-	private function process_relocation($xpath, $relocation, $importer) {
-
-		logger("Processing relocations");
-
-		$relocate = array();
-		$relocate["uid"] = $importer["importer_uid"];
-		$relocate["cid"] = $importer["id"];
-		$relocate["url"] = $xpath->query("dfrn:url/text()", $relocation)->item(0)->nodeValue;
-		$relocate["name"] = $xpath->query("dfrn:name/text()", $relocation)->item(0)->nodeValue;
-		$relocate["photo"] = $xpath->query("dfrn:photo/text()", $relocation)->item(0)->nodeValue;
-		$relocate["thumb"] = $xpath->query("dfrn:thumb/text()", $relocation)->item(0)->nodeValue;
-		$relocate["micro"] = $xpath->query("dfrn:micro/text()", $relocation)->item(0)->nodeValue;
-		$relocate["request"] = $xpath->query("dfrn:request/text()", $relocation)->item(0)->nodeValue;
-		$relocate["confirm"] = $xpath->query("dfrn:confirm/text()", $relocation)->item(0)->nodeValue;
-		$relocate["notify"] = $xpath->query("dfrn:notify/text()", $relocation)->item(0)->nodeValue;
-		$relocate["poll"] = $xpath->query("dfrn:poll/text()", $relocation)->item(0)->nodeValue;
-		$relocate["sitepubkey"] = $xpath->query("dfrn:sitepubkey/text()", $relocation)->item(0)->nodeValue;
-
-		// update contact
-		$r = q("SELECT `photo`, `url` FROM `contact` WHERE `id` = %d AND `uid` = %d;",
-			intval($importer["id"]),
-			intval($importer["importer_uid"]));
-		if (!$r)
-			return false;
-
-		$old = $r[0];
-
-		$x = q("UPDATE `contact` SET
-					`name` = '%s',
-					`photo` = '%s',
-					`thumb` = '%s',
-					`micro` = '%s',
-					`url` = '%s',
-					`nurl` = '%s',
-					`request` = '%s',
-					`confirm` = '%s',
-					`notify` = '%s',
-					`poll` = '%s',
-					`site-pubkey` = '%s'
-			WHERE `id` = %d AND `uid` = %d;",
-					dbesc($relocate["name"]),
-					dbesc($relocate["photo"]),
-					dbesc($relocate["thumb"]),
-					dbesc($relocate["micro"]),
-					dbesc($relocate["url"]),
-					dbesc(normalise_link($relocate["url"])),
-					dbesc($relocate["request"]),
-					dbesc($relocate["confirm"]),
-					dbesc($relocate["notify"]),
-					dbesc($relocate["poll"]),
-					dbesc($relocate["sitepubkey"]),
-					intval($importer["id"]),
-					intval($importer["importer_uid"]));
-
-		if ($x === false)
-			return false;
-
-		// update items
-		$fields = array(
-			'owner-link' => array($old["url"], $relocate["url"]),
-			'author-link' => array($old["url"], $relocate["url"]),
-			'owner-avatar' => array($old["photo"], $relocate["photo"]),
-			'author-avatar' => array($old["photo"], $relocate["photo"]),
-			);
-		foreach ($fields as $n=>$f){
-			$x = q("UPDATE `item` SET `%s` = '%s' WHERE `%s` = '%s' AND `uid` = %d",
-					$n, dbesc($f[1]),
-					$n, dbesc($f[0]),
-					intval($importer["importer_uid"]));
-				if ($x === false)
-					return false;
-			}
-
-		/// @TODO
-		/// merge with current record, current contents have priority
-		/// update record, set url-updated
-		/// update profile photos
-		/// schedule a scan?
-		return true;
-	}
-
-	private function update_content($current, $item, $importer, $entrytype) {
-		$changed = false;
-
-		if (edited_timestamp_is_newer($current, $item)) {
-
-			// do not accept (ignore) an earlier edit than one we currently have.
-			if(datetime_convert("UTC","UTC",$item["edited"]) < $current["edited"])
-				return(false);
-
-			$r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
-				dbesc($item["title"]),
-				dbesc($item["body"]),
-				dbesc($item["tag"]),
-				dbesc(datetime_convert("UTC","UTC",$item["edited"])),
-				dbesc(datetime_convert()),
-				dbesc($item["uri"]),
-				intval($importer["importer_uid"])
-			);
-			create_tags_from_itemuri($item["uri"], $importer["importer_uid"]);
-			update_thread_uri($item["uri"], $importer["importer_uid"]);
-
-			$changed = true;
-
-			if ($entrytype == DFRN_REPLY_RC)
-				proc_run("php", "include/notifier.php","comment-import", $current["id"]);
-		}
-
-		// update last-child if it changes
-		if($item["last-child"] AND ($item["last-child"] != $current["last-child"])) {
-			$r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
-				dbesc(datetime_convert()),
-				dbesc($item["parent-uri"]),
-				intval($importer["importer_uid"])
-			);
-			$r = q("UPDATE `item` SET `last-child` = %d , `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d",
-				intval($item["last-child"]),
-				dbesc(datetime_convert()),
-				dbesc($item["uri"]),
-				intval($importer["importer_uid"])
-			);
-		}
-		return $changed;
-	}
-
-	private function get_entry_type($importer, $item) {
-		if ($item["parent-uri"] != $item["uri"]) {
-			$community = false;
-
-			if($importer["page-flags"] == PAGE_COMMUNITY || $importer["page-flags"] == PAGE_PRVGROUP) {
-				$sql_extra = "";
-				$community = true;
-				logger("possible community action");
-			} else
-				$sql_extra = " AND `contact`.`self` AND `item`.`wall` ";
-
-			// was the top-level post for this action written by somebody on this site?
-			// Specifically, the recipient?
-
-			$is_a_remote_action = false;
-
-			$r = q("SELECT `item`.`parent-uri` FROM `item`
-				WHERE `item`.`uri` = '%s'
-				LIMIT 1",
-				dbesc($item["parent-uri"])
-			);
-			if($r && count($r)) {
-				$r = q("SELECT `item`.`forum_mode`, `item`.`wall` FROM `item`
-					INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
-					WHERE `item`.`uri` = '%s' AND (`item`.`parent-uri` = '%s' OR `item`.`thr-parent` = '%s')
-					AND `item`.`uid` = %d
-					$sql_extra
-					LIMIT 1",
-					dbesc($r[0]["parent-uri"]),
-					dbesc($r[0]["parent-uri"]),
-					dbesc($r[0]["parent-uri"]),
-					intval($importer["importer_uid"])
-				);
-				if($r && count($r))
-					$is_a_remote_action = true;
-			}
-
-			// Does this have the characteristics of a community or private group action?
-			// If it's an action to a wall post on a community/prvgroup page it's a
-			// valid community action. Also forum_mode makes it valid for sure.
-			// If neither, it's not.
-
-			if($is_a_remote_action && $community) {
-				if((!$r[0]["forum_mode"]) && (!$r[0]["wall"])) {
-					$is_a_remote_action = false;
-					logger("not a community action");
-				}
-			}
-
-			if ($is_a_remote_action)
-				return DFRN_REPLY_RC;
-			else
-				return DFRN_REPLY;
-
-		} else
-			return DFRN_TOP_LEVEL;
-
-	}
-
-	private function do_poke($item, $importer, $posted_id) {
-		$verb = urldecode(substr($item["verb"],strpos($item["verb"], "#")+1));
-		if(!$verb)
-			return;
-		$xo = parse_xml_string($item["object"],false);
-
-		if(($xo->type == ACTIVITY_OBJ_PERSON) && ($xo->id)) {
-
-			// somebody was poked/prodded. Was it me?
-			$links = parse_xml_string("<links>".unxmlify($xo->link)."</links>",false);
-
-			foreach($links->link as $l) {
-				$atts = $l->attributes();
-				switch($atts["rel"]) {
-					case "alternate":
-						$Blink = $atts["href"];
-						break;
-					default:
-						break;
-				}
-			}
-			if($Blink && link_compare($Blink,$a->get_baseurl()."/profile/".$importer["nickname"])) {
-
-				// send a notification
-				notification(array(
-					"type"         => NOTIFY_POKE,
-					"notify_flags" => $importer["notify-flags"],
-					"language"     => $importer["language"],
-					"to_name"      => $importer["username"],
-					"to_email"     => $importer["email"],
-					"uid"          => $importer["importer_uid"],
-					"item"         => $item,
-					"link"         => $a->get_baseurl()."/display/".urlencode(get_item_guid($posted_id)),
-					"source_name"  => stripslashes($item["author-name"]),
-					"source_link"  => $item["author-link"],
-					"source_photo" => ((link_compare($item["author-link"],$importer["url"]))
-						? $importer["thumb"] : $item["author-avatar"]),
-					"verb"         => $item["verb"],
-					"otype"        => "person",
-					"activity"     => $verb,
-					"parent"       => $item["parent"]
-				));
-			}
-		}
-	}
-
-	private function process_entry($header, $xpath, $entry, $importer) {
-
-		logger("Processing entries");
-
-		$item = $header;
-
-		// Get the uri
-		$item["uri"] = $xpath->query("atom:id/text()", $entry)->item(0)->nodeValue;
-
-		// Fetch the owner
-		$owner = self::fetchauthor($xpath, $entry, $importer, "dfrn:owner", true);
-
-		$item["owner-name"] = $owner["name"];
-		$item["owner-link"] = $owner["link"];
-		$item["owner-avatar"] = $owner["avatar"];
-
-		// fetch the author
-		$author = self::fetchauthor($xpath, $entry, $importer, "atom:author", true);
-
-		$item["author-name"] = $author["name"];
-		$item["author-link"] = $author["link"];
-		$item["author-avatar"] = $author["avatar"];
-
-		$item["title"] = $xpath->query("atom:title/text()", $entry)->item(0)->nodeValue;
-
-		$item["created"] = $xpath->query("atom:published/text()", $entry)->item(0)->nodeValue;
-		$item["edited"] = $xpath->query("atom:updated/text()", $entry)->item(0)->nodeValue;
-
-		$item["body"] = $xpath->query("dfrn:env/text()", $entry)->item(0)->nodeValue;
-		$item["body"] = str_replace(array(' ',"\t","\r","\n"), array('','','',''),$item["body"]);
-		// make sure nobody is trying to sneak some html tags by us
-		$item["body"] = notags(base64url_decode($item["body"]));
-
-		$item["body"] = limit_body_size($item["body"]);
-
-		/// @todo Do we need the old check for HTML elements?
-
-		// We don't need the content element since "dfrn:env" is always present
-		//$item["body"] = $xpath->query("atom:content/text()", $entry)->item(0)->nodeValue;
-
-		$item["last-child"] = $xpath->query("dfrn:comment-allow/text()", $entry)->item(0)->nodeValue;
-		$item["location"] = $xpath->query("dfrn:location/text()", $entry)->item(0)->nodeValue;
-
-		$georsspoint = $xpath->query("georss:point", $entry);
-		if ($georsspoint)
-			$item["coord"] = $georsspoint->item(0)->nodeValue;
-
-		$item["private"] = $xpath->query("dfrn:private/text()", $entry)->item(0)->nodeValue;
-
-		$item["extid"] = $xpath->query("dfrn:extid/text()", $entry)->item(0)->nodeValue;
-
-		if ($xpath->query("dfrn:extid/text()", $entry)->item(0)->nodeValue == "true")
-			$item["bookmark"] = true;
-
-		$notice_info = $xpath->query("statusnet:notice_info", $entry);
-		if ($notice_info AND ($notice_info->length > 0)) {
-			foreach($notice_info->item(0)->attributes AS $attributes) {
-				if ($attributes->name == "source")
-					$item["app"] = strip_tags($attributes->textContent);
-			}
-		}
-
-		$item["guid"] = $xpath->query("dfrn:diaspora_guid/text()", $entry)->item(0)->nodeValue;
-
-		// We store the data from "dfrn:diaspora_signature" in a different table, this is done in "item_store"
-		$item["dsprsig"] = unxmlify($xpath->query("dfrn:diaspora_signature/text()", $entry)->item(0)->nodeValue);
-
-		$item["verb"] = $xpath->query("activity:verb/text()", $entry)->item(0)->nodeValue;
-
-		if ($xpath->query("activity:object-type/text()", $entry)->item(0)->nodeValue != "")
-			$item["object-type"] = $xpath->query("activity:object-type/text()", $entry)->item(0)->nodeValue;
-
-		$object = $xpath->query("activity:object", $entry)->item(0);
-		$item["object"] = self::transform_activity($xpath, $object, "object");
-
-		if (trim($item["object"]) != "") {
-			$r = parse_xml_string($item["object"], false);
-			if (isset($r->type))
-				$item["object-type"] = $r->type;
-		}
-
-		$target = $xpath->query("activity:target", $entry)->item(0);
-		$item["target"] = self::transform_activity($xpath, $target, "target");
-
-		$categories = $xpath->query("atom:category", $entry);
-		if ($categories) {
-			foreach ($categories AS $category) {
-				foreach($category->attributes AS $attributes)
-					if ($attributes->name == "term") {
-						$term = $attributes->textContent;
-						if(strlen($item["tag"]))
-							$item["tag"] .= ",";
-
-						$item["tag"] .= "#[url=".App::get_baseurl()."/search?tag=".$term."]".$term."[/url]";
-					}
-			}
-		}
-
-		$enclosure = "";
-
-		$links = $xpath->query("atom:link", $entry);
-		if ($links) {
-			$rel = "";
-			$href = "";
-			$type = "";
-			$length = "0";
-			$title = "";
-			foreach ($links AS $link) {
-				foreach($link->attributes AS $attributes) {
-					if ($attributes->name == "href")
-						$href = $attributes->textContent;
-					if ($attributes->name == "rel")
-						$rel = $attributes->textContent;
-					if ($attributes->name == "type")
-						$type = $attributes->textContent;
-					if ($attributes->name == "length")
-						$length = $attributes->textContent;
-					if ($attributes->name == "title")
-						$title = $attributes->textContent;
-				}
-				if (($rel != "") AND ($href != ""))
-					switch($rel) {
-						case "alternate":
-							$item["plink"] = $href;
-							break;
-						case "enclosure":
-							$enclosure = $href;
-							if(strlen($item["attach"]))
-								$item["attach"] .= ",";
-
-							$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
-							break;
-					}
-			}
-		}
-
-		// Is it a reply or a top level posting?
-		$item["parent-uri"] = $item["uri"];
-
-		$inreplyto = $xpath->query("thr:in-reply-to", $entry);
-		if (is_object($inreplyto->item(0)))
-			foreach($inreplyto->item(0)->attributes AS $attributes)
-				if ($attributes->name == "ref")
-					$item["parent-uri"] = $attributes->textContent;
-
-		// Get the type of the item (Top level post, reply or remote reply)
-		$entrytype = self::get_entry_type($importer, $item);
-
-		// Now assign the rest of the values that depend on the type of the message
-		if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) {
-			if (!isset($item["object-type"]))
-				$item["object-type"] = ACTIVITY_OBJ_COMMENT;
-
-			if ($item["contact-id"] != $owner["contact-id"])
-				$item["contact-id"] = $owner["contact-id"];
-
-			if (($item["network"] != $owner["network"]) AND ($owner["network"] != ""))
-				$item["network"] = $owner["network"];
-
-			if ($item["contact-id"] != $author["contact-id"])
-				$item["contact-id"] = $author["contact-id"];
-
-			if (($item["network"] != $author["network"]) AND ($author["network"] != ""))
-				$item["network"] = $author["network"];
-		}
-
-		if ($entrytype == DFRN_REPLY_RC) {
-			$item["type"] = "remote-comment";
-			$item["wall"] = 1;
-		} elseif ($entrytype == DFRN_TOP_LEVEL) {
-			// The Diaspora signature is only stored in replies
-			// Since this isn't a field in the item table this would create a bug when inserting this in the item table
-			unset($item["dsprsig"]);
-
-			if (!isset($item["object-type"]))
-				$item["object-type"] = ACTIVITY_OBJ_NOTE;
-
-			if ($item["object-type"] == ACTIVITY_OBJ_EVENT) {
-				logger("Item ".$item["uri"]." seems to contain an event.", LOGGER_DEBUG);
-				$ev = bbtoevent($item["body"]);
-				if((x($ev, "desc") || x($ev, "summary")) && x($ev, "start")) {
-					logger("Event in item ".$item["uri"]." was found.", LOGGER_DEBUG);
-					$ev["cid"] = $importer["id"];
-					$ev["uid"] = $importer["uid"];
-					$ev["uri"] = $item["uri"];
-					$ev["edited"] = $item["edited"];
-					$ev['private'] = $item['private'];
-					$ev["guid"] = $item["guid"];
-
-					$r = q("SELECT `id` FROM `event` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-						dbesc($item["uri"]),
-						intval($importer["uid"])
-					);
-					if(count($r))
-						$ev["id"] = $r[0]["id"];
-
-					$event_id = event_store($ev);
-					logger("Event ".$event_id." was stored", LOGGER_DEBUG);
-					return;
-				}
-			}
-/*
-			if(activity_match($item['verb'],ACTIVITY_FOLLOW)) {
-				logger('consume-feed: New follower');
-				new_follower($importer,$contact,$item);
-				return;
-			}
-			if(activity_match($item['verb'],ACTIVITY_UNFOLLOW))  {
-				lose_follower($importer,$contact,$item);
-				return;
-			}
-			if(activity_match($item['verb'],ACTIVITY_REQ_FRIEND)) {
-				logger('consume-feed: New friend request');
-				new_follower($importer,$contact,$item,(?),true);
-				return;
-			}
-			if(activity_match($item['verb'],ACTIVITY_UNFRIEND))  {
-				lose_sharer($importer,$contact,$item);
-				return;
-			}
-*/
-		}
-
-		$r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-			dbesc($item["uri"]),
-			intval($importer["importer_uid"])
-		);
-
-		// Update content if 'updated' changes
-		if(count($r)) {
-			if (self::update_content($r[0], $item, $importer, $entrytype))
-				logger("Item ".$item["uri"]." was updated.", LOGGER_DEBUG);
-			else
-				logger("Item ".$item["uri"]." already existed.", LOGGER_DEBUG);
-			return;
-		}
-
-		if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) {
-			if($importer["rel"] == CONTACT_IS_FOLLOWER) {
-				logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG);
-				return;
-			}
-
-			if(($item["verb"] === ACTIVITY_LIKE)
-				|| ($item["verb"] === ACTIVITY_DISLIKE)
-				|| ($item["verb"] === ACTIVITY_ATTEND)
-				|| ($item["verb"] === ACTIVITY_ATTENDNO)
-				|| ($item["verb"] === ACTIVITY_ATTENDMAYBE)) {
-				$is_like = true;
-				$item["type"] = "activity";
-				$item["gravity"] = GRAVITY_LIKE;
-				// only one like or dislike per person
-				// splitted into two queries for performance issues
-				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1",
-					intval($item["uid"]),
-					dbesc($item["author-link"]),
-					dbesc($item["verb"]),
-					dbesc($item["parent-uri"])
-				);
-				if($r && count($r))
-					return;
-
-				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1",
-					intval($item["uid"]),
-					dbesc($item["author-link"]),
-					dbesc($item["verb"]),
-					dbesc($item["parent-uri"])
-				);
-				if($r && count($r))
-					return;
-
-			} else
-				$is_like = false;
-
-			if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
-
-				$xo = parse_xml_string($item["object"],false);
-				$xt = parse_xml_string($item["target"],false);
-
-				if($xt->type == ACTIVITY_OBJ_NOTE) {
-					$r = q("SELECT `id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-						dbesc($xt->id),
-						intval($importer["importer_uid"])
-					);
-
-					if(!count($r))
-						return;
-
-					// extract tag, if not duplicate, add to parent item
-					if($xo->content) {
-						if(!(stristr($r[0]["tag"],trim($xo->content)))) {
-							q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
-								dbesc($r[0]["tag"] . (strlen($r[0]["tag"]) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'),
-								intval($r[0]["id"])
-							);
-							create_tags_from_item($r[0]["id"]);
-						}
-					}
-				}
-			}
-
-			$posted_id = item_store($item);
-			$parent = 0;
-
-			if($posted_id) {
-
-				logger("Reply from contact ".$item["contact-id"]." was stored with id ".$posted_id, LOGGER_DEBUG);
-
-				$item["id"] = $posted_id;
-
-				$r = q("SELECT `parent`, `parent-uri` FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
-					intval($posted_id),
-					intval($importer["importer_uid"])
-				);
-				if(count($r)) {
-					$parent = $r[0]["parent"];
-					$parent_uri = $r[0]["parent-uri"];
-				}
-
-				if(!$is_like) {
-					$r1 = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `uid` = %d AND `parent` = %d",
-						dbesc(datetime_convert()),
-						intval($importer["importer_uid"]),
-						intval($r[0]["parent"])
-					);
-
-					$r2 = q("UPDATE `item` SET `last-child` = 1, `changed` = '%s' WHERE `uid` = %d AND `id` = %d",
-						dbesc(datetime_convert()),
-						intval($importer["importer_uid"]),
-						intval($posted_id)
-					);
-				}
-
-				if($posted_id AND $parent AND ($entrytype == DFRN_REPLY_RC)) {
-					logger("Notifying followers about comment ".$posted_id, LOGGER_DEBUG);
-					proc_run("php", "include/notifier.php", "comment-import", $posted_id);
-				}
-
-				return true;
-			}
-		} else {
-			if(!link_compare($item["owner-link"],$importer["url"])) {
-				/// @todo Check if this is really used
-				// The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
-				// but otherwise there's a possible data mixup on the sender's system.
-				// the tgroup delivery code called from item_store will correct it if it's a forum,
-				// but we're going to unconditionally correct it here so that the post will always be owned by our contact.
-				logger('Correcting item owner.', LOGGER_DEBUG);
-				$item["owner-name"]   = $importer["senderName"];
-				$item["owner-link"]   = $importer["url"];
-				$item["owner-avatar"] = $importer["thumb"];
-			}
-
-			if(($importer["rel"] == CONTACT_IS_FOLLOWER) && (!tgroup_check($importer["importer_uid"], $item))) {
-				logger("Contact ".$importer["id"]." is only follower and tgroup check was negative.", LOGGER_DEBUG);
-				return;
-			}
-
-			// This is my contact on another system, but it's really me.
-			// Turn this into a wall post.
-			$notify = item_is_remote_self($importer, $item);
-
-			$posted_id = item_store($item, false, $notify);
-
-			logger("Item was stored with id ".$posted_id, LOGGER_DEBUG);
-
-			if(stristr($item["verb"],ACTIVITY_POKE))
-				self::do_poke($item, $importer, $posted_id);
-		}
-	}
-
-	private function process_deletion($header, $xpath, $deletion, $importer) {
-
-		logger("Processing deletions");
-
-		foreach($deletion->attributes AS $attributes) {
-			if ($attributes->name == "ref")
-				$uri = $attributes->textContent;
-			if ($attributes->name == "when")
-				$when = $attributes->textContent;
-		}
-		if ($when)
-			$when = datetime_convert("UTC", "UTC", $when, "Y-m-d H:i:s");
-		else
-			$when = datetime_convert("UTC", "UTC", "now", "Y-m-d H:i:s");
-
-		if (!$uri OR !$importer["id"])
-			return false;
-
-		/// @todo Only select the used fields
-		$r = q("SELECT `item`.*, `contact`.`self` FROM `item` INNER JOIN `contact` on `item`.`contact-id` = `contact`.`id`
-				WHERE `uri` = '%s' AND `item`.`uid` = %d AND `contact-id` = %d AND NOT `item`.`file` LIKE '%%[%%' LIMIT 1",
-				dbesc($uri),
-				intval($importer["uid"]),
-				intval($importer["id"])
-			);
-		if(!count($r)) {
-			logger("Item with uri ".$uri." from contact ".$importer["id"]." for user ".$importer["uid"]." wasn't found.", LOGGER_DEBUG);
-			return;
-		} else {
-
-			$item = $r[0];
-
-			$entrytype = self::get_entry_type($importer, $item);
-
-			if(!$item["deleted"])
-				logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG);
-			else
-				return;
-
-			if($item["object-type"] === ACTIVITY_OBJ_EVENT) {
-				logger("Deleting event ".$item["event-id"], LOGGER_DEBUG);
-				event_delete($item["event-id"]);
-			}
-
-			if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
-				$xo = parse_xml_string($item["object"],false);
-				$xt = parse_xml_string($item["target"],false);
-				if($xt->type === ACTIVITY_OBJ_NOTE) {
-					$i = q("SELECT `id`, `contact-id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-						dbesc($xt->id),
-						intval($importer["importer_uid"])
-					);
-					if(count($i)) {
-
-						// For tags, the owner cannot remove the tag on the author's copy of the post.
-
-						$owner_remove = (($item["contact-id"] == $i[0]["contact-id"]) ? true: false);
-						$author_remove = (($item["origin"] && $item["self"]) ? true : false);
-						$author_copy = (($item["origin"]) ? true : false);
-
-						if($owner_remove && $author_copy)
-							return;
-						if($author_remove || $owner_remove) {
-							$tags = explode(',',$i[0]["tag"]);
-							$newtags = array();
-							if(count($tags)) {
-								foreach($tags as $tag)
-									if(trim($tag) !== trim($xo->body))
-										$newtags[] = trim($tag);
-							}
-							q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
-								dbesc(implode(',',$newtags)),
-								intval($i[0]["id"])
-							);
-							create_tags_from_item($i[0]["id"]);
-						}
-					}
-				}
-			}
-
-			if($entrytype == DFRN_TOP_LEVEL) {
-				$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
-						`body` = '', `title` = ''
-					WHERE `parent-uri` = '%s' AND `uid` = %d",
-						dbesc($when),
-						dbesc(datetime_convert()),
-						dbesc($uri),
-						intval($importer["uid"])
-					);
-				create_tags_from_itemuri($uri, $importer["uid"]);
-				create_files_from_itemuri($uri, $importer["uid"]);
-				update_thread_uri($uri, $importer["uid"]);
-			} else {
-				$r = q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s',
-						`body` = '', `title` = ''
-					WHERE `uri` = '%s' AND `uid` = %d",
-						dbesc($when),
-						dbesc(datetime_convert()),
-						dbesc($uri),
-						intval($importer["uid"])
-					);
-				create_tags_from_itemuri($uri, $importer["uid"]);
-				create_files_from_itemuri($uri, $importer["uid"]);
-				update_thread_uri($uri, $importer["importer_uid"]);
-				if($item["last-child"]) {
-					// ensure that last-child is set in case the comment that had it just got wiped.
-					q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d ",
-						dbesc(datetime_convert()),
-						dbesc($item["parent-uri"]),
-						intval($item["uid"])
-					);
-					// who is the last child now?
-					$r = q("SELECT `id` FROM `item` WHERE `parent-uri` = '%s' AND `type` != 'activity' AND `deleted` = 0 AND `moderated` = 0 AND `uid` = %d
-						ORDER BY `created` DESC LIMIT 1",
-							dbesc($item["parent-uri"]),
-							intval($importer["uid"])
-					);
-					if(count($r)) {
-						q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d",
-							intval($r[0]["id"])
-						);
-					}
-				}
-				// if this is a relayed delete, propagate it to other recipients
-
-				if($entrytype == DFRN_REPLY_RC) {
-					logger("Notifying followers about deletion of post ".$item["id"], LOGGER_DEBUG);
-					proc_run("php", "include/notifier.php","drop", $item["id"]);
-				}
-			}
-		}
-	}
-
-	/**
-	 * @brief Imports a DFRN message
-	 *
-	 * @param text $xml The DFRN message
-	 * @param array $importer Record of the importer user mixed with contact of the content
-	 * @param bool $sort_by_date Is used when feeds are polled
-	 */
-	function import($xml,$importer, $sort_by_date = false) {
-
-		if ($xml == "")
-			return;
-
-		if($importer["readonly"]) {
-			// We aren't receiving stuff from this person. But we will quietly ignore them
-			// rather than a blatant "go away" message.
-			logger('ignoring contact '.$importer["id"]);
-			return;
-		}
-
-		$doc = new DOMDocument();
-		@$doc->loadXML($xml);
-
-		$xpath = new DomXPath($doc);
-		$xpath->registerNamespace("atom", NAMESPACE_ATOM1);
-		$xpath->registerNamespace("thr", NAMESPACE_THREAD);
-		$xpath->registerNamespace("at", NAMESPACE_TOMB);
-		$xpath->registerNamespace("media", NAMESPACE_MEDIA);
-		$xpath->registerNamespace("dfrn", NAMESPACE_DFRN);
-		$xpath->registerNamespace("activity", NAMESPACE_ACTIVITY);
-		$xpath->registerNamespace("georss", NAMESPACE_GEORSS);
-		$xpath->registerNamespace("poco", NAMESPACE_POCO);
-		$xpath->registerNamespace("ostatus", NAMESPACE_OSTATUS);
-		$xpath->registerNamespace("statusnet", NAMESPACE_STATUSNET);
-
-		$header = array();
-		$header["uid"] = $importer["uid"];
-		$header["network"] = NETWORK_DFRN;
-		$header["type"] = "remote";
-		$header["wall"] = 0;
-		$header["origin"] = 0;
-		$header["contact-id"] = $importer["id"];
-
-		// Update the contact table if the data has changed
-		// Only the "dfrn:owner" in the head section contains all data
-		self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", false);
-
-		logger("Import DFRN message for user ".$importer["uid"]." from contact ".$importer["id"], LOGGER_DEBUG);
-
-		// is it a public forum? Private forums aren't supported by now with this method
-		$forum = intval($xpath->evaluate("/atom:feed/dfrn:community/text()", $context)->item(0)->nodeValue);
-
-		/// @todo Check the opposite as well (forum changed to non-forum)
-		if ($forum)
-			q("UPDATE `contact` SET `forum` = %d WHERE `forum` != %d AND `id` = %d",
-				intval($forum), intval($forum),
-				intval($importer["id"])
-			);
-
-		$mails = $xpath->query("/atom:feed/dfrn:mail");
-		foreach ($mails AS $mail)
-			self::process_mail($xpath, $mail, $importer);
-
-		$suggestions = $xpath->query("/atom:feed/dfrn:suggest");
-		foreach ($suggestions AS $suggestion)
-			self::process_suggestion($xpath, $suggestion, $importer);
-
-		$relocations = $xpath->query("/atom:feed/dfrn:relocate");
-		foreach ($relocations AS $relocation)
-			self::process_relocation($xpath, $relocation, $importer);
-
-		$deletions = $xpath->query("/atom:feed/at:deleted-entry");
-		foreach ($deletions AS $deletion)
-			self::process_deletion($header, $xpath, $deletion, $importer);
-
-		if (!$sort_by_date) {
-			$entries = $xpath->query("/atom:feed/atom:entry");
-			foreach ($entries AS $entry)
-				self::process_entry($header, $xpath, $entry, $importer);
-		} else {
-			$newentries = array();
-			$entries = $xpath->query("/atom:feed/atom:entry");
-			foreach ($entries AS $entry) {
-				$created = $xpath->query("atom:published/text()", $entry)->item(0)->nodeValue;
-				$newentries[strtotime($created)] = $entry;
-			}
-
-			// Now sort after the publishing date
-			ksort($newentries);
-
-			foreach ($newentries AS $entry)
-				self::process_entry($header, $xpath, $entry, $importer);
-		}
-	}
-}
-?>
diff --git a/include/ostatus.php b/include/ostatus.php
index caaeec84f7..00022f8c6c 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -1312,6 +1312,10 @@ function ostatus_add_author($doc, $owner) {
 function ostatus_entry($doc, $item, $owner, $toplevel = false, $repeat = false) {
 	$a = get_app();
 
+	if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
+		logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
+	}
+
 	$is_repeat = false;
 
 /*	if (!$repeat) {

From bcf10206359ee610c3a3f19c53d54563ae7dd8ca Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Fri, 5 Feb 2016 21:38:55 +0100
Subject: [PATCH 046/273] vier smileybutton: dark.css insert new line at the
 end of the file

---
 view/theme/vier/dark.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/view/theme/vier/dark.css b/view/theme/vier/dark.css
index 5ddaf71a2f..d9b419e18a 100644
--- a/view/theme/vier/dark.css
+++ b/view/theme/vier/dark.css
@@ -66,4 +66,4 @@ li :hover {
 
 table.smiley-preview{
   background-color: #252C33 !important;
-}
\ No newline at end of file
+}

From db949bb802448184bfe5164d8d3dd86ddf51b187 Mon Sep 17 00:00:00 2001
From: Andrej Stieben <e-mail@stieben.de>
Date: Fri, 5 Feb 2016 21:52:39 +0100
Subject: [PATCH 047/273] Updated modules to allow for partial overrides
 without errors

Only define functions if they have not been defined before, e.g. in themes. This makes it possible to override parts of a module and still use the other functions.
---
 mod/_well_known.php       |  4 ++
 mod/acctlink.php          |  3 +-
 mod/acl.php               |  4 +-
 mod/admin.php             | 78 ++++++++++++++++++++++++++++-----------
 mod/allfriends.php        |  2 +
 mod/amcd.php              |  5 ++-
 mod/api.php               | 11 +++---
 mod/apps.php              | 40 ++++++++++----------
 mod/attach.php            |  3 +-
 mod/babel.php             | 46 ++++++++++++-----------
 mod/bookmarklet.php       |  5 ++-
 mod/cb.php                | 11 +++++-
 mod/common.php            |  2 +
 mod/community.php         | 13 ++++---
 mod/contactgroup.php      |  4 +-
 mod/contacts.php          | 38 +++++++++++++++----
 mod/content.php           | 48 ++++++++++++------------
 mod/credits.php           |  2 +
 mod/crepair.php           | 10 +++--
 mod/delegate.php          | 10 +++--
 mod/dfrn_confirm.php      |  3 +-
 mod/dfrn_notify.php       |  6 ++-
 mod/dfrn_poll.php         | 13 ++++---
 mod/directory.php         | 19 +++++-----
 mod/dirfind.php           |  6 ++-
 mod/display.php           |  9 +++--
 mod/editpost.php          |  5 +--
 mod/events.php            |  6 ++-
 mod/fbrowser.php          |  3 +-
 mod/filer.php             |  5 ++-
 mod/filerm.php            |  2 +
 mod/follow.php            |  4 ++
 mod/friendica.php         | 11 +++---
 mod/fsuggest.php          | 19 +++++-----
 mod/group.php             | 11 ++++--
 mod/hcard.php             | 10 ++---
 mod/help.php              |  3 +-
 mod/hostxrd.php           |  3 +-
 mod/ignored.php           |  3 +-
 mod/install.php           | 55 ++++++++++++++++++---------
 mod/invite.php            | 13 ++++---
 mod/item.php              | 13 +++++--
 mod/like.php              |  7 ++--
 mod/localtime.php         | 11 +++---
 mod/lockview.php          | 20 +++++-----
 mod/login.php             |  4 +-
 mod/lostpass.php          |  7 ++--
 mod/maintenance.php       |  3 +-
 mod/manage.php            |  8 ++--
 mod/match.php             |  2 +
 mod/message.php           | 13 +++++--
 mod/modexp.php            |  4 +-
 mod/mood.php              | 10 ++---
 mod/msearch.php           |  9 +++--
 mod/navigation.php        |  3 +-
 mod/network.php           | 17 +++++++--
 mod/newmember.php         | 10 +++--
 mod/nodeinfo.php          | 11 ++++--
 mod/nogroup.php           |  6 ++-
 mod/noscrape.php          |  3 +-
 mod/notes.php             | 20 +++++-----
 mod/notice.php            |  9 +++--
 mod/notifications.php     |  6 ++-
 mod/notify.php            |  8 ++--
 mod/oembed.php            |  4 +-
 mod/oexchange.php         | 17 ++++-----
 mod/openid.php            | 10 ++---
 mod/opensearch.php        | 16 ++++----
 mod/ostatus_subscribe.php |  2 +
 mod/p.php                 |  4 +-
 mod/parse_url.php         | 18 +++++++--
 mod/photo.php             |  2 +
 mod/photos.php            | 15 ++++----
 mod/ping.php              |  4 ++
 mod/poco.php              |  3 +-
 mod/poke.php              | 12 +++---
 mod/post.php              |  7 ++--
 mod/pretheme.php          |  4 +-
 mod/probe.php             |  4 +-
 mod/profile.php           |  7 ++--
 mod/profile_photo.php     | 26 ++++++-------
 mod/profiles.php          | 14 +++++--
 mod/profperm.php          | 12 +++---
 mod/proxy.php             | 12 ++++++
 mod/pubsub.php            | 20 +++++-----
 mod/pubsubhubbub.php      |  5 ++-
 mod/qsearch.php           |  3 +-
 mod/randprof.php          |  3 +-
 mod/receive.php           |  4 +-
 mod/redir.php             |  6 ++-
 mod/regmod.php            |  9 +++--
 mod/removeme.php          |  6 ++-
 mod/repair_ostatus.php    |  2 +
 mod/rsd_xml.php           |  6 +--
 mod/salmon.php            |  7 +++-
 mod/search.php            | 14 ++++---
 mod/session.php           |  3 +-
 mod/settings.php          | 16 ++++----
 mod/share.php             |  9 ++++-
 mod/smilies.php           |  6 ++-
 mod/starred.php           |  3 +-
 mod/statistics_json.php   |  2 +
 mod/subthread.php         | 12 +++---
 mod/suggest.php           |  9 +++--
 mod/tagger.php            |  8 ++--
 mod/tagrm.php             |  9 +++--
 mod/toggle_mobile.php     |  3 +-
 mod/uexport.php           | 30 +++++++++------
 mod/uimport.php           | 12 ++++--
 mod/update_community.php  |  5 ++-
 mod/update_display.php    |  3 +-
 mod/update_network.php    |  3 +-
 mod/update_notes.php      |  9 +++--
 mod/update_profile.php    |  9 +++--
 mod/videos.php            | 12 +++---
 mod/view.php              | 10 +++--
 mod/viewcontacts.php      |  5 ++-
 mod/viewsrc.php           |  6 +--
 mod/wall_attach.php       |  2 +
 mod/wall_upload.php       |  2 +
 mod/wallmessage.php       | 12 +++---
 mod/webfinger.php         |  6 +--
 mod/xrd.php               |  3 +-
 123 files changed, 768 insertions(+), 471 deletions(-)

diff --git a/mod/_well_known.php b/mod/_well_known.php
index 33070a1ecd..6c33136f95 100644
--- a/mod/_well_known.php
+++ b/mod/_well_known.php
@@ -2,6 +2,7 @@
 require_once("mod/hostxrd.php");
 require_once("mod/nodeinfo.php");
 
+if(! function_exists('_well_known_init')) {
 function _well_known_init(&$a){
 	if ($a->argc > 1) {
 		switch($a->argv[1]) {
@@ -19,7 +20,9 @@ function _well_known_init(&$a){
 	http_status_exit(404);
 	killme();
 }
+}
 
+if(! function_exists('wk_social_relay')) {
 function wk_social_relay(&$a) {
 
 	define('SR_SCOPE_ALL', 'all');
@@ -64,3 +67,4 @@ function wk_social_relay(&$a) {
 	echo json_encode($relay, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
 	exit;
 }
+}
diff --git a/mod/acctlink.php b/mod/acctlink.php
index a2365803ac..a551e3dbd6 100644
--- a/mod/acctlink.php
+++ b/mod/acctlink.php
@@ -2,8 +2,8 @@
 
 require_once('include/Scrape.php');
 
+if(! function_exists('acctlink_init')) {
 function acctlink_init(&$a) {
-
 	if(x($_GET,'addr')) {
 		$addr = trim($_GET['addr']);
 		$res = probe_url($addr);
@@ -14,3 +14,4 @@ function acctlink_init(&$a) {
 		}
 	}
 }
+}
diff --git a/mod/acl.php b/mod/acl.php
index f5e04b96a7..5666ccabb8 100644
--- a/mod/acl.php
+++ b/mod/acl.php
@@ -3,8 +3,8 @@
 
 require_once("include/acl_selectors.php");
 
+if(! function_exists('acl_init')) {
 function acl_init(&$a){
 	acl_lookup($a);
 }
-
-
+}
diff --git a/mod/admin.php b/mod/admin.php
index 7f9000807b..ff17c0b8c4 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -2,7 +2,7 @@
 
  /**
  * @file mod/admin.php
- * 
+ *
  * @brief Friendica admin
  */
 
@@ -23,6 +23,7 @@ require_once("include/text.php");
  * @param App $a
  *
  */
+if(! function_exists('admin_post')) {
 function admin_post(&$a){
 
 
@@ -110,6 +111,7 @@ function admin_post(&$a){
 	goaway($a->get_baseurl(true) . '/admin' );
 	return; // NOTREACHED
 }
+}
 
 /**
  * @brief Generates content of the admin panel pages
@@ -128,6 +130,7 @@ function admin_post(&$a){
  * @param App $a
  * @return string
  */
+if(! function_exists('admin_content')) {
 function admin_content(&$a) {
 
 	if(!is_site_admin()) {
@@ -245,6 +248,7 @@ function admin_content(&$a) {
 		return $o;
 	}
 }
+}
 
 /**
  * @brief Subpage with some stats about "the federation" network
@@ -260,6 +264,7 @@ function admin_content(&$a) {
  * @param App $a
  * @return string
  */
+if(! function_exists('admin_page_federation')) {
 function admin_page_federation(&$a) {
 	// get counts on active friendica, diaspora, redmatrix, hubzilla, gnu
 	// social and statusnet nodes this node is knowing
@@ -284,7 +289,7 @@ function admin_page_federation(&$a) {
 		// what versions for that platform do we know at all?
 		// again only the active nodes
 		$v = q('SELECT count(*) AS total, version FROM gserver
-			WHERE last_contact > last_failure AND platform LIKE "%s" 
+			WHERE last_contact > last_failure AND platform LIKE "%s"
 			GROUP BY version
 			ORDER BY version;', $p);
 
@@ -301,12 +306,12 @@ function admin_page_federation(&$a) {
 				$newVC = $vv['total'];
 				$newVV = $vv['version'];
 				$posDash = strpos($newVV, '-');
-				if($posDash) 
+				if($posDash)
 					$newVV = substr($newVV, 0, $posDash);
 				if(isset($newV[$newVV]))
-					$newV[$newVV] += $newVC; 
+					$newV[$newVV] += $newVC;
 				else
-					$newV[$newVV] = $newVC; 
+					$newV[$newVV] = $newVC;
 			}
 			foreach ($newV as $key => $value) {
 				array_push($newVv, array('total'=>$value, 'version'=>$key));
@@ -361,6 +366,7 @@ function admin_page_federation(&$a) {
 		'$baseurl' => $a->get_baseurl(),
 	));
 }
+}
 
 /**
  * @brief Admin Inspect Queue Page
@@ -375,6 +381,7 @@ function admin_page_federation(&$a) {
  * @param App $a
  * @return string
  */
+if(! function_exists('admin_page_queue')) {
 function admin_page_queue(&$a) {
 	// get content from the queue table
 	$r = q("SELECT c.name,c.nurl,q.id,q.network,q.created,q.last from queue as q, contact as c where c.id=q.cid order by q.cid, q.created;");
@@ -394,6 +401,7 @@ function admin_page_queue(&$a) {
 		'$entries' => $r,
 	));
 }
+}
 
 /**
  * @brief Admin Summary Page
@@ -406,6 +414,7 @@ function admin_page_queue(&$a) {
  * @param App $a
  * @return string
  */
+if(! function_exists('admin_page_summary')) {
 function admin_page_summary(&$a) {
 	$r = q("SELECT `page-flags`, COUNT(uid) as `count` FROM `user` GROUP BY `page-flags`");
 	$accounts = array(
@@ -452,12 +461,14 @@ function admin_page_summary(&$a) {
 		'$plugins' => array( t('Active plugins'), $a->plugins )
 	));
 }
+}
 
 /**
  * @brief Process send data from Admin Site Page
- * 
+ *
  * @param App $a
  */
+if(! function_exists('admin_page_site_post')) {
 function admin_page_site_post(&$a) {
 	if(!x($_POST,"page_site")) {
 		return;
@@ -770,6 +781,7 @@ function admin_page_site_post(&$a) {
 	return; // NOTREACHED
 
 }
+}
 
 /**
  * @brief Generate Admin Site subpage
@@ -779,6 +791,7 @@ function admin_page_site_post(&$a) {
  * @param  App $a
  * @return string
  */
+if(! function_exists('admin_page_site')) {
 function admin_page_site(&$a) {
 
 	/* Installed langs */
@@ -983,7 +996,7 @@ function admin_page_site(&$a) {
 		'$form_security_token'	=> get_form_security_token("admin_site")
 
 	));
-
+}
 }
 
 /**
@@ -998,6 +1011,7 @@ function admin_page_site(&$a) {
  * @param App $a
  * @return string
  **/
+if(! function_exists('admin_page_dbsync')) {
 function admin_page_dbsync(&$a) {
 
 	$o = '';
@@ -1073,14 +1087,15 @@ function admin_page_dbsync(&$a) {
 	}
 
 	return $o;
-
+}
 }
 
 /**
  * @brief Process data send by Users admin page
- * 
+ *
  * @param App $a
  */
+if(! function_exists('admin_page_users_post')) {
 function admin_page_users_post(&$a){
 	$pending	=	( x($_POST, 'pending')			? $_POST['pending']		: array() );
 	$users		=	( x($_POST, 'user')			? $_POST['user']		: array() );
@@ -1171,6 +1186,7 @@ function admin_page_users_post(&$a){
 	goaway($a->get_baseurl(true) . '/admin/users' );
 	return; // NOTREACHED
 }
+}
 
 /**
  * @brief Admin panel subpage for User management
@@ -1184,6 +1200,7 @@ function admin_page_users_post(&$a){
  * @param App $a
  * @return string
  */
+if(! function_exists('admin_page_users')) {
 function admin_page_users(&$a){
 	if($a->argc>2) {
 		$uid = $a->argv[3];
@@ -1336,7 +1353,7 @@ function admin_page_users(&$a){
 	$o .= paginate($a);
 	return $o;
 }
-
+}
 
 /**
  * @brief Plugins admin page
@@ -1354,6 +1371,7 @@ function admin_page_users(&$a){
  * @param App $a
  * @return string
  */
+if(! function_exists('admin_page_plugins')) {
 function admin_page_plugins(&$a){
 
 	/*
@@ -1479,17 +1497,19 @@ function admin_page_plugins(&$a){
 		'$baseurl' => $a->get_baseurl(true),
 		'$function' => 'plugins',
 		'$plugins' => $plugins,
-		'$pcount' => count($plugins), 
+		'$pcount' => count($plugins),
 		'$noplugshint' => sprintf( t('There are currently no plugins available on your node. You can find the official plugin repository at %1$s and might find other interesting plugins in the open plugin registry at %2$s'), 'https://github.com/friendica/friendica-addons', 'http://addons.friendi.ca'),
 		'$form_security_token' => get_form_security_token("admin_themes"),
 	));
 }
+}
 
 /**
  * @param array $themes
  * @param string $th
  * @param int $result
  */
+if(! function_exists('toggle_theme')) {
 function toggle_theme(&$themes,$th,&$result) {
 	for($x = 0; $x < count($themes); $x ++) {
 		if($themes[$x]['name'] === $th) {
@@ -1504,12 +1524,14 @@ function toggle_theme(&$themes,$th,&$result) {
 		}
 	}
 }
+}
 
 /**
  * @param array $themes
  * @param string $th
  * @return int
  */
+if(! function_exists('theme_status')) {
 function theme_status($themes,$th) {
 	for($x = 0; $x < count($themes); $x ++) {
 		if($themes[$x]['name'] === $th) {
@@ -1523,12 +1545,13 @@ function theme_status($themes,$th) {
 	}
 	return 0;
 }
-
+}
 
 /**
  * @param array $themes
  * @return string
  */
+if(! function_exists('rebuild_theme_table')) {
 function rebuild_theme_table($themes) {
 	$o = '';
 	if(count($themes)) {
@@ -1542,7 +1565,7 @@ function rebuild_theme_table($themes) {
 	}
 	return $o;
 }
-
+}
 
 /**
  * @brief Themes admin page
@@ -1560,6 +1583,7 @@ function rebuild_theme_table($themes) {
  * @param App $a
  * @return string
  */
+if(! function_exists('admin_page_themes')) {
 function admin_page_themes(&$a){
 
 	$allowed_themes_str = get_config('system','allowed_themes');
@@ -1734,13 +1758,14 @@ function admin_page_themes(&$a){
 		'$form_security_token' => get_form_security_token("admin_themes"),
 	));
 }
-
+}
 
 /**
  * @brief Prosesses data send by Logs admin page
- * 
+ *
  * @param App $a
  */
+if(! function_exists('admin_page_logs_post')) {
 function admin_page_logs_post(&$a) {
 	if(x($_POST,"page_logs")) {
 		check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs');
@@ -1758,6 +1783,7 @@ function admin_page_logs_post(&$a) {
 	goaway($a->get_baseurl(true) . '/admin/logs' );
 	return; // NOTREACHED
 }
+}
 
 /**
  * @brief Generates admin panel subpage for configuration of the logs
@@ -1775,6 +1801,7 @@ function admin_page_logs_post(&$a) {
  * @param App $a
  * @return string
  */
+if(! function_exists('admin_page_logs')) {
 function admin_page_logs(&$a){
 
 	$log_choices = array(
@@ -1806,6 +1833,7 @@ function admin_page_logs(&$a){
 		'$phplogcode' => "error_reporting(E_ERROR | E_WARNING | E_PARSE );\nini_set('error_log','php.out');\nini_set('log_errors','1');\nini_set('display_errors', '1');",
 	));
 }
+}
 
 /**
  * @brief Generates admin panel subpage to view the Friendica log
@@ -1825,6 +1853,7 @@ function admin_page_logs(&$a){
  * @param App $a
  * @return string
  */
+if(! function_exists('admin_page_viewlogs')) {
 function admin_page_viewlogs(&$a){
 	$t = get_markup_template("admin_viewlogs.tpl");
 	$f = get_config('system','logfile');
@@ -1861,12 +1890,14 @@ function admin_page_viewlogs(&$a){
 		'$logname' =>  get_config('system','logfile')
 	));
 }
+}
 
 /**
  * @brief Prosesses data send by the features admin page
- * 
+ *
  * @param App $a
  */
+if(! function_exists('admin_page_features_post')) {
 function admin_page_features_post(&$a) {
 
 	check_form_security_token_redirectOnErr('/admin/features', 'admin_manage_features');
@@ -1898,23 +1929,25 @@ function admin_page_features_post(&$a) {
 	goaway($a->get_baseurl(true) . '/admin/features' );
 	return; // NOTREACHED
 }
+}
 
 /**
  * @brief Subpage for global additional feature management
- * 
+ *
  * This functin generates the subpage 'Manage Additional Features'
  * for the admin panel. At this page the admin can set preferences
- * for the user settings of the 'additional features'. If needed this 
+ * for the user settings of the 'additional features'. If needed this
  * preferences can be locked through the admin.
- * 
+ *
  * The returned string contains the HTML code of the subpage 'Manage
  * Additional Features'
- * 
+ *
  * @param App $a
  * @return string
  */
+if(! function_exists('admin_page_features')) {
 function admin_page_features(&$a) {
-	
+
 	if((argc() > 1) && (argv(1) === 'features')) {
 		$arr = array();
 		$features = get_features(false);
@@ -1933,7 +1966,7 @@ function admin_page_features(&$a) {
 				);
 			}
 		}
-		
+
 		$tpl = get_markup_template("admin_settings_features.tpl");
 		$o .= replace_macros($tpl, array(
 			'$form_security_token' => get_form_security_token("admin_manage_features"),
@@ -1945,3 +1978,4 @@ function admin_page_features(&$a) {
 		return $o;
 	}
 }
+}
diff --git a/mod/allfriends.php b/mod/allfriends.php
index 356a389b83..8843265a99 100644
--- a/mod/allfriends.php
+++ b/mod/allfriends.php
@@ -5,6 +5,7 @@ require_once('include/Contact.php');
 require_once('include/contact_selectors.php');
 require_once('mod/contacts.php');
 
+if(! function_exists('allfriends_content')) {
 function allfriends_content(&$a) {
 
 	$o = '';
@@ -97,3 +98,4 @@ function allfriends_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/amcd.php b/mod/amcd.php
index a2a1327e6d..141a804298 100644
--- a/mod/amcd.php
+++ b/mod/amcd.php
@@ -1,5 +1,5 @@
 <?php
-
+if(! function_exists('amcd_content')) {
 function amcd_content(&$a) {
 //header("Content-type: text/json");
 echo <<< EOT
@@ -46,4 +46,5 @@ echo <<< EOT
 }
 EOT;
 killme();
-}
\ No newline at end of file
+}
+}
diff --git a/mod/api.php b/mod/api.php
index da2c40c305..67564836e8 100644
--- a/mod/api.php
+++ b/mod/api.php
@@ -1,10 +1,8 @@
 <?php
-
 require_once('include/api.php');
 
+if(! function_exists('oauth_get_client')) {
 function oauth_get_client($request){
-
-
 	$params = $request->get_parameters();
 	$token = $params['oauth_token'];
 
@@ -19,9 +17,10 @@ function oauth_get_client($request){
 
 	return $r[0];
 }
+}
 
+if(! function_exists('api_post')) {
 function api_post(&$a) {
-
 	if(! local_user()) {
 		notice( t('Permission denied.') . EOL);
 		return;
@@ -31,9 +30,10 @@ function api_post(&$a) {
 		notice( t('Permission denied.') . EOL);
 		return;
 	}
-
+}
 }
 
+if(! function_exists('api_content')) {
 function api_content(&$a) {
 	if ($a->cmd=='api/oauth/authorize'){
 		/*
@@ -114,3 +114,4 @@ function api_content(&$a) {
 	echo api_call($a);
 	killme();
 }
+}
diff --git a/mod/apps.php b/mod/apps.php
index a821ef5d5b..e807feae74 100644
--- a/mod/apps.php
+++ b/mod/apps.php
@@ -1,25 +1,23 @@
 <?php
-
+if(! function_exists('apps_content')) {
 function apps_content(&$a) {
-    $privateaddons = get_config('config','private_addons');
-      if ($privateaddons === "1") {
-	if((! (local_user())))  {
-	info( t("You must be logged in to use addons. "));
-      return;};
+  $privateaddons = get_config('config','private_addons');
+  if ($privateaddons === "1") {
+    if((! (local_user()))) {
+      info( t("You must be logged in to use addons. "));
+      return;
+    }
+  }
+
+  $title = t('Applications');
+
+  if(count($a->apps)==0)
+    notice( t('No installed applications.') . EOL);
+
+  $tpl = get_markup_template("apps.tpl");
+  return replace_macros($tpl, array(
+    '$title' => $title,
+    '$apps' => $a->apps,
+  ));
 }
-
-      $title = t('Applications');
-
-	if(count($a->apps)==0)
-		notice( t('No installed applications.') . EOL);
-
-
-	$tpl = get_markup_template("apps.tpl");
-	return replace_macros($tpl, array(
-		'$title' => $title,
-		'$apps' => $a->apps,
-	));
-
-	
-
 }
diff --git a/mod/attach.php b/mod/attach.php
index 03f850f0d1..849faa26ec 100644
--- a/mod/attach.php
+++ b/mod/attach.php
@@ -1,7 +1,7 @@
 <?php
-
 require_once('include/security.php');
 
+if(! function_exists('attach_init')) {
 function attach_init(&$a) {
 
 	if($a->argc != 2) {
@@ -47,3 +47,4 @@ function attach_init(&$a) {
 	killme();
 	// NOTREACHED
 }
+}
diff --git a/mod/babel.php b/mod/babel.php
index d31e090c55..56455bdb21 100644
--- a/mod/babel.php
+++ b/mod/babel.php
@@ -9,55 +9,56 @@ function visible_lf($s) {
 	return str_replace("\n",'<br />', $s);
 }
 
+if(! function_exists('babel_content')) {
 function babel_content(&$a) {
 
 	$o .= '<h1>Babel Diagnostic</h1>';
 
 	$o .= '<form action="babel" method="post">';
 	$o .= t('Source (bbcode) text:') . EOL . '<textarea name="text" >' . htmlspecialchars($_REQUEST['text']) .'</textarea>' . EOL;
-	$o .= '<input type="submit" name="submit" value="Submit" /></form>'; 
+	$o .= '<input type="submit" name="submit" value="Submit" /></form>';
 
 	$o .= '<br /><br />';
 
 	$o .= '<form action="babel" method="post">';
 	$o .= t('Source (Diaspora) text to convert to BBcode:') . EOL . '<textarea name="d2bbtext" >' . htmlspecialchars($_REQUEST['d2bbtext']) .'</textarea>' . EOL;
-	$o .= '<input type="submit" name="submit" value="Submit" /></form>'; 
+	$o .= '<input type="submit" name="submit" value="Submit" /></form>';
 
 	$o .= '<br /><br />';
 
 	if(x($_REQUEST,'text')) {
 
 		$text = trim($_REQUEST['text']);
-		$o .= "<h2>" . t("Source input: ") . "</h2>" . EOL. EOL; 
-		$o .= visible_lf($text) . EOL. EOL; 
+		$o .= "<h2>" . t("Source input: ") . "</h2>" . EOL. EOL;
+		$o .= visible_lf($text) . EOL. EOL;
 
 		$html = bbcode($text);
-		$o .= "<h2>" . t("bb2html (raw HTML): ") . "</h2>" . EOL. EOL; 
-		$o .= htmlspecialchars($html). EOL. EOL; 
+		$o .= "<h2>" . t("bb2html (raw HTML): ") . "</h2>" . EOL. EOL;
+		$o .= htmlspecialchars($html). EOL. EOL;
 
 		//$html = bbcode($text);
-		$o .= "<h2>" . t("bb2html: ") . "</h2>" . EOL. EOL; 
-		$o .= $html. EOL. EOL; 
+		$o .= "<h2>" . t("bb2html: ") . "</h2>" . EOL. EOL;
+		$o .= $html. EOL. EOL;
 
 		$bbcode = html2bbcode($html);
-		$o .= "<h2>" . t("bb2html2bb: ") . "</h2>" . EOL. EOL; 
-		$o .= visible_lf($bbcode) . EOL. EOL; 
+		$o .= "<h2>" . t("bb2html2bb: ") . "</h2>" . EOL. EOL;
+		$o .= visible_lf($bbcode) . EOL. EOL;
 
 		$diaspora = bb2diaspora($text);
-		$o .= "<h2>" . t("bb2md: ") . "</h2>" . EOL. EOL; 
-		$o .= visible_lf($diaspora) . EOL. EOL; 
+		$o .= "<h2>" . t("bb2md: ") . "</h2>" . EOL. EOL;
+		$o .= visible_lf($diaspora) . EOL. EOL;
 
 		$html = Markdown($diaspora);
-		$o .= "<h2>" . t("bb2md2html: ") . "</h2>" . EOL. EOL; 
-		$o .= $html. EOL. EOL; 
+		$o .= "<h2>" . t("bb2md2html: ") . "</h2>" . EOL. EOL;
+		$o .= $html. EOL. EOL;
 
 		$bbcode = diaspora2bb($diaspora);
-		$o .= "<h2>" . t("bb2dia2bb: ") . "</h2>" . EOL. EOL; 
-		$o .= visible_lf($bbcode) . EOL. EOL; 
+		$o .= "<h2>" . t("bb2dia2bb: ") . "</h2>" . EOL. EOL;
+		$o .= visible_lf($bbcode) . EOL. EOL;
 
 		$bbcode = html2bbcode($html);
-		$o .= "<h2>" . t("bb2md2html2bb: ") . "</h2>" . EOL. EOL; 
-		$o .= visible_lf($bbcode) . EOL. EOL; 
+		$o .= "<h2>" . t("bb2md2html2bb: ") . "</h2>" . EOL. EOL;
+		$o .= visible_lf($bbcode) . EOL. EOL;
 
 
 
@@ -66,14 +67,15 @@ function babel_content(&$a) {
 	if(x($_REQUEST,'d2bbtext')) {
 
 		$d2bbtext = trim($_REQUEST['d2bbtext']);
-		$o .= "<h2>" . t("Source input (Diaspora format): ") . "</h2>" . EOL. EOL; 
-		$o .= visible_lf($d2bbtext) . EOL. EOL; 
+		$o .= "<h2>" . t("Source input (Diaspora format): ") . "</h2>" . EOL. EOL;
+		$o .= visible_lf($d2bbtext) . EOL. EOL;
 
 
 		$bb = diaspora2bb($d2bbtext);
-		$o .= "<h2>" . t("diaspora2bb: ") . "</h2>" . EOL. EOL; 
-		$o .= visible_lf($bb) . EOL. EOL; 
+		$o .= "<h2>" . t("diaspora2bb: ") . "</h2>" . EOL. EOL;
+		$o .= visible_lf($bb) . EOL. EOL;
 	}
 
 	return $o;
 }
+}
diff --git a/mod/bookmarklet.php b/mod/bookmarklet.php
index be8645c1fd..4db6bf401e 100644
--- a/mod/bookmarklet.php
+++ b/mod/bookmarklet.php
@@ -1,12 +1,14 @@
 <?php
-
 require_once('include/conversation.php');
 require_once('include/items.php');
 
+if(! function_exists('bookmarklet_init')) {
 function bookmarklet_init(&$a) {
 	$_GET["mode"] = "minimal";
 }
+}
 
+if(! function_exists('bookmarklet_content')) {
 function bookmarklet_content(&$a) {
 	if(!local_user()) {
 		$o = '<h2>'.t('Login').'</h2>';
@@ -44,3 +46,4 @@ function bookmarklet_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/cb.php b/mod/cb.php
index 6375d23984..04d01302c1 100644
--- a/mod/cb.php
+++ b/mod/cb.php
@@ -4,21 +4,28 @@
  * General purpose landing page for plugins/addons
  */
 
-
+if(! function_exists('cb_init')) {
 function cb_init(&$a) {
 	call_hooks('cb_init');
 }
+}
 
+if(! function_exists('cb_post')) {
 function cb_post(&$a) {
 	call_hooks('cb_post', $_POST);
 }
+}
 
+if(! function_exists('cb_afterpost')) {
 function cb_afterpost(&$a) {
 	call_hooks('cb_afterpost');
 }
+}
 
+if(! function_exists('cb_content')) {
 function cb_content(&$a) {
 	$o = '';
 	call_hooks('cb_content', $o);
 	return $o;
-}
\ No newline at end of file
+}
+}
diff --git a/mod/common.php b/mod/common.php
index c9409b3ef1..4cdbe9641b 100644
--- a/mod/common.php
+++ b/mod/common.php
@@ -5,6 +5,7 @@ require_once('include/Contact.php');
 require_once('include/contact_selectors.php');
 require_once('mod/contacts.php');
 
+if(! function_exists('common_content')) {
 function common_content(&$a) {
 
 	$o = '';
@@ -144,3 +145,4 @@ function common_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/community.php b/mod/community.php
index b6d72a3555..c64c6216b1 100644
--- a/mod/community.php
+++ b/mod/community.php
@@ -1,15 +1,14 @@
 <?php
-
+if(! function_exists('community_init')) {
 function community_init(&$a) {
 	if(! local_user()) {
 		unset($_SESSION['theme']);
 		unset($_SESSION['mobile-theme']);
 	}
-
-
+}
 }
 
-
+if(! function_exists('community_content')) {
 function community_content(&$a, $update = 0) {
 
 	$o = '';
@@ -115,7 +114,9 @@ function community_content(&$a, $update = 0) {
 
 	return $o;
 }
+}
 
+if(! function_exists('community_getitems')) {
 function community_getitems($start, $itemspage) {
 	if (get_config('system','community_page_style') == CP_GLOBAL_COMMUNITY)
 		return(community_getpublicitems($start, $itemspage));
@@ -140,9 +141,10 @@ function community_getitems($start, $itemspage) {
 	);
 
 	return($r);
-
+}
 }
 
+if(! function_exists('community_getpublicitems')) {
 function community_getpublicitems($start, $itemspage) {
 	$r = q("SELECT `item`.`uri`, `item`.*, `item`.`id` AS `item_id`,
 			`author-name` AS `name`, `owner-avatar` AS `photo`,
@@ -157,3 +159,4 @@ function community_getpublicitems($start, $itemspage) {
 
 	return($r);
 }
+}
diff --git a/mod/contactgroup.php b/mod/contactgroup.php
index bf81afe079..0291350b21 100644
--- a/mod/contactgroup.php
+++ b/mod/contactgroup.php
@@ -2,6 +2,7 @@
 
 require_once('include/group.php');
 
+if(! function_exists('contactgroup_content')) {
 function contactgroup_content(&$a) {
 
 
@@ -47,4 +48,5 @@ function contactgroup_content(&$a) {
 	}
 
 	killme();
-}
\ No newline at end of file
+}
+}
diff --git a/mod/contacts.php b/mod/contacts.php
index 0b421433e0..cef8bdb897 100644
--- a/mod/contacts.php
+++ b/mod/contacts.php
@@ -7,6 +7,7 @@ require_once('include/Scrape.php');
 require_once('mod/proxy.php');
 require_once('include/Photo.php');
 
+if(! function_exists('contacts_init')) {
 function contacts_init(&$a) {
 	if(! local_user())
 		return;
@@ -38,7 +39,7 @@ function contacts_init(&$a) {
 
 			if (($a->data['contact']['network'] != "") AND ($a->data['contact']['network'] != NETWORK_DFRN)) {
 				$networkname = format_network_name($a->data['contact']['network'],$a->data['contact']['url']);
-			} else 
+			} else
 				$networkname = '';
 
 			$vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"),array(
@@ -88,9 +89,10 @@ function contacts_init(&$a) {
 		'$base' => $base
 	));
 
-
+}
 }
 
+if(! function_exists('contacts_batch_actions')) {
 function contacts_batch_actions(&$a){
 	$contacts_id = $_POST['contact_batch'];
 	if (!is_array($contacts_id)) return;
@@ -132,10 +134,10 @@ function contacts_batch_actions(&$a){
 		goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']);
 	else
 		goaway($a->get_baseurl(true) . '/contacts');
-
+}
 }
 
-
+if(! function_exists('contacts_post')) {
 function contacts_post(&$a) {
 
 	if(! local_user())
@@ -215,10 +217,11 @@ function contacts_post(&$a) {
 		$a->data['contact'] = $r[0];
 
 	return;
-
+}
 }
 
 /*contact actions*/
+if(! function_exists('_contact_update')) {
 function _contact_update($contact_id) {
 	$r = q("SELECT `uid`, `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id));
 	if (!$r)
@@ -239,7 +242,9 @@ function _contact_update($contact_id) {
 		// pull feed and consume it, which should subscribe to the hub.
 		proc_run('php',"include/onepoll.php","$contact_id", "force");
 }
+}
 
+if(! function_exists('_contact_update_profile')) {
 function _contact_update_profile($contact_id) {
 	$r = q("SELECT `uid`, `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id));
 	if (!$r)
@@ -299,7 +304,9 @@ function _contact_update_profile($contact_id) {
 	// Update the entry in the gcontact table
 	update_gcontact_from_probe($data["url"]);
 }
+}
 
+if(! function_exists('_contact_block')) {
 function _contact_block($contact_id, $orig_record) {
 	$blocked = (($orig_record['blocked']) ? 0 : 1);
 	$r = q("UPDATE `contact` SET `blocked` = %d WHERE `id` = %d AND `uid` = %d",
@@ -308,8 +315,10 @@ function _contact_block($contact_id, $orig_record) {
 		intval(local_user())
 	);
 	return $r;
-
 }
+}
+
+if(! function_exists('_contact_ignore')) {
 function _contact_ignore($contact_id, $orig_record) {
 	$readonly = (($orig_record['readonly']) ? 0 : 1);
 	$r = q("UPDATE `contact` SET `readonly` = %d WHERE `id` = %d AND `uid` = %d",
@@ -319,6 +328,9 @@ function _contact_ignore($contact_id, $orig_record) {
 	);
 	return $r;
 }
+}
+
+if(! function_exists('_contact_archive')) {
 function _contact_archive($contact_id, $orig_record) {
 	$archived = (($orig_record['archive']) ? 0 : 1);
 	$r = q("UPDATE `contact` SET `archive` = %d WHERE `id` = %d AND `uid` = %d",
@@ -331,14 +343,18 @@ function _contact_archive($contact_id, $orig_record) {
 	}
 	return $r;
 }
+}
+
+if(! function_exists('_contact_drop')) {
 function _contact_drop($contact_id, $orig_record) {
 	$a = get_app();
 
 	terminate_friendship($a->user,$a->contact,$orig_record);
 	contact_remove($orig_record['id']);
 }
+}
 
-
+if(! function_exists('contacts_content')) {
 function contacts_content(&$a) {
 
 	$sort_type = 0;
@@ -799,7 +815,9 @@ function contacts_content(&$a) {
 
 	return $o;
 }
+}
 
+if(! function_exists('contacts_tab')) {
 function contacts_tab($a, $contact_id, $active_tab) {
 	// tabs
 	$tabs = array(
@@ -873,7 +891,9 @@ function contacts_tab($a, $contact_id, $active_tab) {
 
 	return $tab_str;
 }
+}
 
+if(! function_exists('contact_posts')) {
 function contact_posts($a, $contact_id) {
 
 	$r = q("SELECT `url` FROM `contact` WHERE `id` = %d", intval($contact_id));
@@ -901,7 +921,9 @@ function contact_posts($a, $contact_id) {
 
 	return $o;
 }
+}
 
+if(! function_exists('_contact_detail_for_template')) {
 function _contact_detail_for_template($rr){
 
 	$community = '';
@@ -952,5 +974,5 @@ function _contact_detail_for_template($rr){
 		'url' => $url,
 		'network' => network_to_name($rr['network'], $rr['url']),
 	);
-
+}
 }
diff --git a/mod/content.php b/mod/content.php
index c5a5556116..ab0fe7e4bf 100644
--- a/mod/content.php
+++ b/mod/content.php
@@ -15,7 +15,7 @@
 // fast - e.g. one or two milliseconds to fetch parent items for the current content,
 // and 10-20 milliseconds to fetch all the child items.
 
-
+if(! function_exists('content_content')) {
 function content_content(&$a, $update = 0) {
 
 	require_once('include/conversation.php');
@@ -61,7 +61,7 @@ function content_content(&$a, $update = 0) {
 
 	$o = '';
 
-	
+
 
 	$contact_id = $a->cid;
 
@@ -100,7 +100,7 @@ function content_content(&$a, $update = 0) {
 			$def_acl = array('allow_cid' => $str);
 	}
 
-	
+
 	$sql_options  = (($star) ? " and starred = 1 " : '');
 	$sql_options .= (($bmark) ? " and bookmark = 1 " : '');
 
@@ -137,7 +137,7 @@ function content_content(&$a, $update = 0) {
 	}
 	elseif($cid) {
 
-		$r = q("SELECT `id`,`name`,`network`,`writable`,`nurl` FROM `contact` WHERE `id` = %d 
+		$r = q("SELECT `id`,`name`,`network`,`writable`,`nurl` FROM `contact` WHERE `id` = %d
 				AND `blocked` = 0 AND `pending` = 0 LIMIT 1",
 			intval($cid)
 		);
@@ -304,9 +304,9 @@ function content_content(&$a, $update = 0) {
 	echo json_encode($o);
 	killme();
 }
+}
 
-
-
+if(! function_exists('render_content')) {
 function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 	require_once('include/bbcode.php');
@@ -373,7 +373,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 		if($mode === 'network-new' || $mode === 'search' || $mode === 'community') {
 
-			// "New Item View" on network page or search page results 
+			// "New Item View" on network page or search page results
 			// - just loop through the items and format them minimally for display
 
 			//$tpl = get_markup_template('search_item.tpl');
@@ -389,7 +389,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 				$sparkle     = '';
 
 				if($mode === 'search' || $mode === 'community') {
-					if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) 
+					if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE)))
 						&& ($item['id'] != $item['parent']))
 						continue;
 					$nickname = $item['nickname'];
@@ -436,7 +436,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 				$drop = array(
 					'dropping' => $dropping,
-					'select' => t('Select'), 
+					'select' => t('Select'),
 					'delete' => t('Delete'),
 				);
 
@@ -526,11 +526,11 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 						$comments[$item['parent']] = 1;
 					else
 						$comments[$item['parent']] += 1;
-				} elseif(! x($comments,$item['parent'])) 
+				} elseif(! x($comments,$item['parent']))
 					$comments[$item['parent']] = 0; // avoid notices later on
 			}
 
-			// map all the like/dislike activities for each parent item 
+			// map all the like/dislike activities for each parent item
 			// Store these in the $alike and $dlike arrays
 
 			foreach($items as $item) {
@@ -617,14 +617,14 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 				$redirect_url = $a->get_baseurl($ssl_state) . '/redir/' . $item['cid'] ;
 
-				$lock = ((($item['private'] == 1) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid']) 
+				$lock = ((($item['private'] == 1) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
 					|| strlen($item['deny_cid']) || strlen($item['deny_gid']))))
 					? t('Private Message')
 					: false);
 
 
 				// Top-level wall post not written by the wall owner (wall-to-wall)
-				// First figure out who owns it. 
+				// First figure out who owns it.
 
 				$osparkle = '';
 
@@ -651,13 +651,13 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 						if((! $owner_linkmatch) && (! $alias_linkmatch) && (! $owner_namematch)) {
 
 							// The author url doesn't match the owner (typically the contact)
-							// and also doesn't match the contact alias. 
-							// The name match is a hack to catch several weird cases where URLs are 
+							// and also doesn't match the contact alias.
+							// The name match is a hack to catch several weird cases where URLs are
 							// all over the park. It can be tricked, but this prevents you from
 							// seeing "Bob Smith to Bob Smith via Wall-to-wall" and you know darn
-							// well that it's the same Bob Smith. 
+							// well that it's the same Bob Smith.
 
-							// But it could be somebody else with the same name. It just isn't highly likely. 
+							// But it could be somebody else with the same name. It just isn't highly likely.
 
 
 							$owner_url = $item['owner-link'];
@@ -666,7 +666,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 							$template = $wallwall;
 							$commentww = 'ww';
 							// If it is our contact, use a friendly redirect link
-							if((link_compare($item['owner-link'],$item['url'])) 
+							if((link_compare($item['owner-link'],$item['url']))
 								&& ($item['network'] === NETWORK_DFRN)) {
 								$owner_url = $redirect_url;
 								$osparkle = ' sparkle';
@@ -678,7 +678,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 				}
 
 				$likebuttons = '';
-				$shareable = ((($profile_owner == local_user()) && ($item['private'] != 1)) ? true : false); 
+				$shareable = ((($profile_owner == local_user()) && ($item['private'] != 1)) ? true : false);
 
 				if($page_writeable) {
 /*					if($toplevelpost) {  */
@@ -698,7 +698,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 					if(($show_comment_box) || (($show_comment_box == false) && ($override_comment_box == false) && ($item['last-child']))) {
 						$comment = replace_macros($cmnt_tpl,array(
-							'$return_path' => '', 
+							'$return_path' => '',
 							'$jsreload' => (($mode === 'display') ? $_SESSION['return_url'] : ''),
 							'$type' => (($mode === 'profile') ? 'wall-comment' : 'net-comment'),
 							'$id' => $item['item_id'],
@@ -739,7 +739,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 				$drop = array(
 					'dropping' => $dropping,
-					'select' => t('Select'), 
+					'select' => t('Select'),
 					'delete' => t('Delete'),
 				);
 
@@ -805,9 +805,9 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 				$shiny = "";
 				if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
-					$shiny = 'shiny'; 
+					$shiny = 'shiny';
 
-				// 
+				//
 				localize_item($item);
 
 
@@ -897,5 +897,5 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 
 	return $threads;
-
+}
 }
diff --git a/mod/credits.php b/mod/credits.php
index f8cfb03f37..8e6321760b 100644
--- a/mod/credits.php
+++ b/mod/credits.php
@@ -5,6 +5,7 @@
  * addons repository will be listed though ATM)
  */
 
+if(! function_exists('credits_content')) {
 function credits_content (&$a) {
     /* fill the page with credits */
     $f = fopen('util/credits.txt','r');
@@ -18,3 +19,4 @@ function credits_content (&$a) {
        '$names'         => $arr,
     ));
 }
+}
diff --git a/mod/crepair.php b/mod/crepair.php
index 5b4db09dac..50502b4987 100644
--- a/mod/crepair.php
+++ b/mod/crepair.php
@@ -2,6 +2,7 @@
 require_once("include/contact_selectors.php");
 require_once("mod/contacts.php");
 
+if(! function_exists('crepair_init')) {
 function crepair_init(&$a) {
 	if(! local_user())
 		return;
@@ -28,8 +29,9 @@ function crepair_init(&$a) {
 		profile_load($a, "", 0, get_contact_details_by_url($contact["url"]));
 	}
 }
+}
 
-
+if(! function_exists('crepair_post')) {
 function crepair_post(&$a) {
 	if(! local_user())
 		return;
@@ -91,9 +93,9 @@ function crepair_post(&$a) {
 
 	return;
 }
+}
 
-
-
+if(! function_exists('crepair_content')) {
 function crepair_content(&$a) {
 
 	if(! local_user()) {
@@ -180,5 +182,5 @@ function crepair_content(&$a) {
 	));
 
 	return $o;
-
+}
 }
diff --git a/mod/delegate.php b/mod/delegate.php
index 20d2e605e0..d421de3764 100644
--- a/mod/delegate.php
+++ b/mod/delegate.php
@@ -1,11 +1,13 @@
 <?php
 require_once('mod/settings.php');
 
+if(! function_exists('delegate_init')) {
 function delegate_init(&$a) {
 	return settings_init($a);
 }
+}
 
-
+if(! function_exists('delegate_content')) {
 function delegate_content(&$a) {
 
 	if(! local_user()) {
@@ -90,12 +92,12 @@ function delegate_content(&$a) {
 
 	// find every contact who might be a candidate for delegation
 
-	$r = q("select nurl from contact where substring_index(contact.nurl,'/',3) = '%s' 
+	$r = q("select nurl from contact where substring_index(contact.nurl,'/',3) = '%s'
 		and contact.uid = %d and contact.self = 0 and network = '%s' ",
 		dbesc(normalise_link($a->get_baseurl())),
 		intval(local_user()),
 		dbesc(NETWORK_DFRN)
-	); 
+	);
 
 	if(! count($r)) {
 		notice( t('No potential page delegates located.') . EOL);
@@ -144,5 +146,5 @@ function delegate_content(&$a) {
 
 	return $o;
 
-
+}
 }
diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php
index 27c04a908d..00e215e334 100644
--- a/mod/dfrn_confirm.php
+++ b/mod/dfrn_confirm.php
@@ -16,6 +16,7 @@
 
 require_once('include/enotify.php');
 
+if(! function_exists('dfrn_confirm_post')) {
 function dfrn_confirm_post(&$a,$handsfree = null) {
 
 	if(is_array($handsfree)) {
@@ -801,5 +802,5 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
 
 	goaway(z_root());
 	// NOTREACHED
-
+}
 }
diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php
index 4aa777b550..04500e89ad 100644
--- a/mod/dfrn_notify.php
+++ b/mod/dfrn_notify.php
@@ -5,6 +5,7 @@ require_once('include/event.php');
 
 require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
 
+if(! function_exists('dfrn_notify_post')) {
 function dfrn_notify_post(&$a) {
     logger(__function__, LOGGER_TRACE);
 	$dfrn_id      = ((x($_POST,'dfrn_id'))      ? notags(trim($_POST['dfrn_id']))   : '');
@@ -213,8 +214,9 @@ function dfrn_notify_post(&$a) {
 
 	// NOTREACHED
 }
+}
 
-
+if(! function_exists('dfrn_notify_content')) {
 function dfrn_notify_content(&$a) {
 
 	if(x($_GET,'dfrn_id')) {
@@ -338,5 +340,5 @@ function dfrn_notify_content(&$a) {
 
 		killme();
 	}
-
+}
 }
diff --git a/mod/dfrn_poll.php b/mod/dfrn_poll.php
index ab6637607e..82c75d28cf 100644
--- a/mod/dfrn_poll.php
+++ b/mod/dfrn_poll.php
@@ -3,7 +3,7 @@ require_once('include/items.php');
 require_once('include/auth.php');
 require_once('include/dfrn.php');
 
-
+if(! function_exists('dfrn_poll_init')) {
 function dfrn_poll_init(&$a) {
 
 
@@ -160,7 +160,7 @@ function dfrn_poll_init(&$a) {
 
 			if($final_dfrn_id != $orig_id) {
 				logger('profile_check: ' . $final_dfrn_id . ' != ' . $orig_id, LOGGER_DEBUG);
-				// did not decode properly - cannot trust this site 
+				// did not decode properly - cannot trust this site
 				xml_status(3, 'Bad decryption');
 			}
 
@@ -195,11 +195,11 @@ function dfrn_poll_init(&$a) {
 			return; // NOTREACHED
 		}
 	}
-
+}
 }
 
 
-
+if(! function_exists('dfrn_poll_post')) {
 function dfrn_poll_post(&$a) {
 
 	$dfrn_id      = ((x($_POST,'dfrn_id'))      ? $_POST['dfrn_id']              : '');
@@ -257,7 +257,7 @@ function dfrn_poll_post(&$a) {
 
 			if($final_dfrn_id != $orig_id) {
 				logger('profile_check: ' . $final_dfrn_id . ' != ' . $orig_id, LOGGER_DEBUG);
-				// did not decode properly - cannot trust this site 
+				// did not decode properly - cannot trust this site
 				xml_status(3, 'Bad decryption');
 			}
 
@@ -377,7 +377,9 @@ function dfrn_poll_post(&$a) {
 
 	}
 }
+}
 
+if(! function_exists('dfrn_poll_content')) {
 function dfrn_poll_content(&$a) {
 
 	$dfrn_id         = ((x($_GET,'dfrn_id'))         ? $_GET['dfrn_id']              : '');
@@ -562,3 +564,4 @@ function dfrn_poll_content(&$a) {
 		}
 	}
 }
+}
diff --git a/mod/directory.php b/mod/directory.php
index 294a55585d..7ce1530efc 100644
--- a/mod/directory.php
+++ b/mod/directory.php
@@ -1,5 +1,5 @@
 <?php
-
+if(! function_exists('directory_init')) {
 function directory_init(&$a) {
 	$a->set_pager_itemspage(60);
 
@@ -16,23 +16,23 @@ function directory_init(&$a) {
 		unset($_SESSION['mobile-theme']);
 	}
 
-
+}
 }
 
-
+if(! function_exists('directory_post')) {
 function directory_post(&$a) {
 	if(x($_POST,'search'))
 		$a->data['search'] = $_POST['search'];
 }
+}
 
-
-
+if(! function_exists('directory_content')) {
 function directory_content(&$a) {
 	global $db;
 
 	require_once("mod/proxy.php");
 
-	if((get_config('system','block_public')) && (! local_user()) && (! remote_user()) || 
+	if((get_config('system','block_public')) && (! local_user()) && (! remote_user()) ||
 		(get_config('system','block_local_dir')) && (! local_user()) && (! remote_user())) {
 		notice( t('Public access denied.') . EOL);
 		return;
@@ -123,14 +123,14 @@ function directory_content(&$a) {
 			}
 //			if(strlen($rr['dob'])) {
 //				if(($years = age($rr['dob'],$rr['timezone'],'')) != 0)
-//					$details .= '<br />' . t('Age: ') . $years ; 
+//					$details .= '<br />' . t('Age: ') . $years ;
 //			}
 //			if(strlen($rr['gender']))
 //				$details .= '<br />' . t('Gender: ') . $rr['gender'];
 
 
 			// show if account is a community account
-			/// @TODO The other page types should be also respected, but first we need a good 
+			/// @TODO The other page types should be also respected, but first we need a good
 			/// translatiion and systemwide consistency for displaying the page type
 			if((intval($rr['page-flags']) == PAGE_COMMUNITY) OR (intval($rr['page-flags']) == PAGE_PRVGROUP))
 				$community = true;
@@ -158,7 +158,7 @@ function directory_content(&$a) {
 			else {
 				$location_e = $location;
 			}
-			
+
 			$photo_menu = array(array(t("View Profile"), zrl($profile_link)));
 
 			$entry = array(
@@ -217,3 +217,4 @@ function directory_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/dirfind.php b/mod/dirfind.php
index 0dfe4d67a9..f5e90705b7 100644
--- a/mod/dirfind.php
+++ b/mod/dirfind.php
@@ -5,6 +5,7 @@ require_once('include/Contact.php');
 require_once('include/contact_selectors.php');
 require_once('mod/contacts.php');
 
+if(! function_exists('dirfind_init')) {
 function dirfind_init(&$a) {
 
 	if(! local_user()) {
@@ -19,9 +20,9 @@ function dirfind_init(&$a) {
 
 	$a->page['aside'] .= follow_widget();
 }
+}
 
-
-
+if(! function_exists('dirfind_content')) {
 function dirfind_content(&$a, $prefix = "") {
 
 	$community = false;
@@ -235,3 +236,4 @@ function dirfind_content(&$a, $prefix = "") {
 
 	return $o;
 }
+}
diff --git a/mod/display.php b/mod/display.php
index 4e33927072..9995a2b3ef 100644
--- a/mod/display.php
+++ b/mod/display.php
@@ -1,5 +1,5 @@
 <?php
-
+if(! function_exists('display_init')) {
 function display_init(&$a) {
 
 	if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
@@ -85,9 +85,10 @@ function display_init(&$a) {
 	}
 
 	profile_load($a, $nick, 0, $profiledata);
-
+}
 }
 
+if(! function_exists('display_fetchauthor')) {
 function display_fetchauthor($a, $item) {
 
 	$profiledata = array();
@@ -220,7 +221,9 @@ function display_fetchauthor($a, $item) {
 
 	return($profiledata);
 }
+}
 
+if(! function_exists('display_content')) {
 function display_content(&$a, $update = 0) {
 
 	if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
@@ -522,4 +525,4 @@ function display_content(&$a, $update = 0) {
 
 	return $o;
 }
-
+}
diff --git a/mod/editpost.php b/mod/editpost.php
index 9a80d0b2f4..ee4d61e60a 100644
--- a/mod/editpost.php
+++ b/mod/editpost.php
@@ -2,6 +2,7 @@
 
 require_once('include/acl_selectors.php');
 
+if(! function_exists('editpost_content')) {
 function editpost_content(&$a) {
 
 	$o = '';
@@ -150,7 +151,5 @@ function editpost_content(&$a) {
 	));
 
 	return $o;
-
 }
-
-
+}
diff --git a/mod/events.php b/mod/events.php
index 653ae489b8..3dc20e535a 100644
--- a/mod/events.php
+++ b/mod/events.php
@@ -5,6 +5,7 @@ require_once('include/datetime.php');
 require_once('include/event.php');
 require_once('include/items.php');
 
+if(! function_exists('events_post')) {
 function events_post(&$a) {
 
 	logger('post: ' . print_r($_REQUEST,true));
@@ -156,9 +157,9 @@ function events_post(&$a) {
 
 	goaway($_SESSION['return_url']);
 }
+}
 
-
-
+if(! function_exists('events_content')) {
 function events_content(&$a) {
 
 	if(! local_user()) {
@@ -578,3 +579,4 @@ function events_content(&$a) {
 		return $o;
 	}
 }
+}
diff --git a/mod/fbrowser.php b/mod/fbrowser.php
index 0a2a7dead5..73510ef58a 100644
--- a/mod/fbrowser.php
+++ b/mod/fbrowser.php
@@ -10,6 +10,7 @@ require_once('include/Photo.php');
 /**
  * @param App $a
  */
+if(! function_exists('fbrowser_content')) {
 function fbrowser_content($a){
 
 	if (!local_user())
@@ -141,5 +142,5 @@ function fbrowser_content($a){
 		killme();
 	}
 
-
+}
 }
diff --git a/mod/filer.php b/mod/filer.php
index 4e79f337dc..02b8d68978 100644
--- a/mod/filer.php
+++ b/mod/filer.php
@@ -4,7 +4,7 @@ require_once('include/security.php');
 require_once('include/bbcode.php');
 require_once('include/items.php');
 
-
+if(! function_exists('filer_content')) {
 function filer_content(&$a) {
 
 	if(! local_user()) {
@@ -30,8 +30,9 @@ function filer_content(&$a) {
 			'$field' => array('term', t("Save to Folder:"), '', '', $filetags, t('- select -')),
 			'$submit' => t('Save'),
 		));
-		
+
 		echo $o;
 	}
 	killme();
 }
+}
diff --git a/mod/filerm.php b/mod/filerm.php
index c266082c8f..be3456b58d 100644
--- a/mod/filerm.php
+++ b/mod/filerm.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('filerm_content')) {
 function filerm_content(&$a) {
 
 	if(! local_user()) {
@@ -25,3 +26,4 @@ function filerm_content(&$a) {
 
 	killme();
 }
+}
diff --git a/mod/follow.php b/mod/follow.php
index b92a0d980f..a8fdc31b5a 100644
--- a/mod/follow.php
+++ b/mod/follow.php
@@ -5,6 +5,7 @@ require_once('include/follow.php');
 require_once('include/Contact.php');
 require_once('include/contact_selectors.php');
 
+if(! function_exists('follow_content')) {
 function follow_content(&$a) {
 
 	if(! local_user()) {
@@ -148,7 +149,9 @@ function follow_content(&$a) {
 
 	return $o;
 }
+}
 
+if(! function_exists('follow_post')) {
 function follow_post(&$a) {
 
 	if(! local_user()) {
@@ -185,3 +188,4 @@ function follow_post(&$a) {
 	goaway($return_url);
 	// NOTREACHED
 }
+}
diff --git a/mod/friendica.php b/mod/friendica.php
index aad5964baf..18d045f2d5 100644
--- a/mod/friendica.php
+++ b/mod/friendica.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('friendica_init')) {
 function friendica_init(&$a) {
 	if ($a->argv[1]=="json"){
 		$register_policy = Array('REGISTER_CLOSED', 'REGISTER_APPROVE', 'REGISTER_OPEN');
@@ -56,9 +57,9 @@ function friendica_init(&$a) {
 		killme();
 	}
 }
+}
 
-
-
+if(! function_exists('friendica_content')) {
 function friendica_content(&$a) {
 
 	$o = '';
@@ -70,7 +71,7 @@ function friendica_content(&$a) {
 	$o .= t('This is Friendica, version') . ' ' . FRIENDICA_VERSION . ' ';
 	$o .= t('running at web location') . ' ' . z_root() . '</p><p>';
 
-	$o .= t('Please visit <a href="http://friendica.com">Friendica.com</a> to learn more about the Friendica project.') . '</p><p>';	
+	$o .= t('Please visit <a href="http://friendica.com">Friendica.com</a> to learn more about the Friendica project.') . '</p><p>';
 
 	$o .= t('Bug reports and issues: please visit') . ' ' . '<a href="https://github.com/friendica/friendica/issues?state=open">'.t('the bugtracker at github').'</a></p><p>';
 	$o .= t('Suggestions, praise, donations, etc. - please email "Info" at Friendica - dot com') . '</p>';
@@ -102,8 +103,8 @@ function friendica_content(&$a) {
 	else
 		$o .= '<p>' . t('No installed plugins/addons/apps') . '</p>';
 
-	call_hooks('about_hook', $o); 	
+	call_hooks('about_hook', $o);
 
 	return $o;
-
+}
 }
diff --git a/mod/fsuggest.php b/mod/fsuggest.php
index 6b1cbd7533..26a5e98063 100644
--- a/mod/fsuggest.php
+++ b/mod/fsuggest.php
@@ -1,6 +1,6 @@
 <?php
 
-
+if(! function_exists('fsuggest_post')) {
 function fsuggest_post(&$a) {
 
 	if(! local_user()) {
@@ -39,11 +39,11 @@ function fsuggest_post(&$a) {
 				VALUES ( %d, %d, '%s','%s','%s','%s','%s','%s')",
 				intval(local_user()),
 				intval($contact_id),
-				dbesc($r[0]['name']), 
-				dbesc($r[0]['url']), 
-				dbesc($r[0]['request']), 
-				dbesc($r[0]['photo']), 
-				dbesc($hash), 
+				dbesc($r[0]['name']),
+				dbesc($r[0]['url']),
+				dbesc($r[0]['request']),
+				dbesc($r[0]['photo']),
+				dbesc($hash),
 				dbesc(datetime_convert())
 			);
 			$r = q("SELECT `id` FROM `fsuggest` WHERE `note` = '%s' AND `uid` = %d LIMIT 1",
@@ -65,11 +65,11 @@ function fsuggest_post(&$a) {
 
 	}
 
-
+}
 }
 
 
-
+if(! function_exists('fsuggest_content')) {
 function fsuggest_content(&$a) {
 
 	require_once('include/acl_selectors.php');
@@ -100,7 +100,7 @@ function fsuggest_content(&$a) {
 
 	$o .= '<form id="fsuggest-form" action="fsuggest/' . $contact_id . '" method="post" >';
 
-	$o .= contact_selector('suggest','suggest-select', false, 
+	$o .= contact_selector('suggest','suggest-select', false,
 		array('size' => 4, 'exclude' => $contact_id, 'networks' => 'DFRN_ONLY', 'single' => true));
 
 
@@ -109,3 +109,4 @@ function fsuggest_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/group.php b/mod/group.php
index 5b28784f56..2f8053eefb 100644
--- a/mod/group.php
+++ b/mod/group.php
@@ -1,18 +1,21 @@
 <?php
 
+if(! function_exists('validate_members')) {
 function validate_members(&$item) {
 	$item = intval($item);
 }
+}
 
+if(! function_exists('group_init')) {
 function group_init(&$a) {
 	if(local_user()) {
 		require_once('include/group.php');
 		$a->page['aside'] = group_side('contacts','group','extended',(($a->argc > 1) ? intval($a->argv[1]) : 0));
 	}
 }
+}
 
-
-
+if(! function_exists('group_post')) {
 function group_post(&$a) {
 
 	if(! local_user()) {
@@ -64,7 +67,9 @@ function group_post(&$a) {
 	}
 	return;
 }
+}
 
+if(! function_exists('group_content')) {
 function group_content(&$a) {
 	$change = false;
 
@@ -229,5 +234,5 @@ function group_content(&$a) {
 	}
 
 	return replace_macros($tpl, $context);
-
+}
 }
diff --git a/mod/hcard.php b/mod/hcard.php
index 6d2d9e2ebf..af49423de3 100644
--- a/mod/hcard.php
+++ b/mod/hcard.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('hcard_init')) {
 function hcard_init(&$a) {
 
 	$blocked = (((get_config('system','block_public')) && (! local_user()) && (! remote_user())) ? true : false);
@@ -15,7 +16,7 @@ function hcard_init(&$a) {
 	$profile = 0;
 	if((local_user()) && ($a->argc > 2) && ($a->argv[2] === 'view')) {
 		$which = $a->user['nickname'];
-		$profile = $a->argv[1];		
+		$profile = $a->argv[1];
 	}
 
 	profile_load($a,$which,$profile);
@@ -23,7 +24,7 @@ function hcard_init(&$a) {
 	if((x($a->profile,'page-flags')) && ($a->profile['page-flags'] == PAGE_COMMUNITY)) {
 		$a->page['htmlhead'] .= '<meta name="friendica.community" content="true" />';
 	}
-	if(x($a->profile,'openidserver'))				
+	if(x($a->profile,'openidserver'))
 		$a->page['htmlhead'] .= '<link rel="openid.server" href="' . $a->profile['openidserver'] . '" />' . "\r\n";
 	if(x($a->profile,'openid')) {
 		$delegate = ((strstr($a->profile['openid'],'://')) ? $a->profile['openid'] : 'http://' . $a->profile['openid']);
@@ -42,10 +43,9 @@ function hcard_init(&$a) {
 	$uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->get_hostname() . (($a->path) ? '/' . $a->path : ''));
 	$a->page['htmlhead'] .= '<link rel="lrdd" type="application/xrd+xml" href="' . $a->get_baseurl() . '/xrd/?uri=' . $uri . '" />' . "\r\n";
 	header('Link: <' . $a->get_baseurl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false);
-  	
+
 	$dfrn_pages = array('request', 'confirm', 'notify', 'poll');
 	foreach($dfrn_pages as $dfrn)
 		$a->page['htmlhead'] .= "<link rel=\"dfrn-{$dfrn}\" href=\"".$a->get_baseurl()."/dfrn_{$dfrn}/{$which}\" />\r\n";
-
 }
-
+}
diff --git a/mod/help.php b/mod/help.php
index 5465d3e900..320e622fa5 100644
--- a/mod/help.php
+++ b/mod/help.php
@@ -18,6 +18,7 @@ if (!function_exists('load_doc_file')) {
 
 }
 
+if(! function_exists('help_content')) {
 function help_content(&$a) {
 
 	nav_set_selected('help');
@@ -98,5 +99,5 @@ function help_content(&$a) {
 		}
 		</style>".$html;
 	return $html;
-
+}
 }
diff --git a/mod/hostxrd.php b/mod/hostxrd.php
index 4121764f1a..5b178e9b8f 100644
--- a/mod/hostxrd.php
+++ b/mod/hostxrd.php
@@ -2,6 +2,7 @@
 
 require_once('include/crypto.php');
 
+if(! function_exists('hostxrd_init')) {
 function hostxrd_init(&$a) {
 	header('Access-Control-Allow-Origin: *');
 	header("Content-type: text/xml");
@@ -27,5 +28,5 @@ function hostxrd_init(&$a) {
 	));
 	session_write_close();
 	exit();
-
+}
 }
diff --git a/mod/ignored.php b/mod/ignored.php
index e876b4ef8b..8a681a1154 100644
--- a/mod/ignored.php
+++ b/mod/ignored.php
@@ -1,6 +1,6 @@
 <?php
 
-
+if(! function_exists('ignored_init')) {
 function ignored_init(&$a) {
 
 	$ignored = 0;
@@ -43,3 +43,4 @@ function ignored_init(&$a) {
 	echo json_encode($ignored);
 	killme();
 }
+}
diff --git a/mod/install.php b/mod/install.php
index 8434b38e38..be90acba10 100755
--- a/mod/install.php
+++ b/mod/install.php
@@ -3,7 +3,7 @@ require_once "include/Photo.php";
 
 $install_wizard_pass=1;
 
-
+if(! function_exists('install_init')) {
 function install_init(&$a){
 
 	// $baseurl/install/testrwrite to test if rewite in .htaccess is working
@@ -11,20 +11,21 @@ function install_init(&$a){
 		echo "ok";
 		killme();
 	}
-	
+
 	// We overwrite current theme css, because during install we could not have a working mod_rewrite
 	// so we could not have a css at all. Here we set a static css file for the install procedure pages
 	$a->config['system']['theme'] = "../install";
 	$a->theme['stylesheet'] = $a->get_baseurl()."/view/install/style.css";
-	
-	
-	
+
+
+
 	global $install_wizard_pass;
 	if (x($_POST,'pass'))
 		$install_wizard_pass = intval($_POST['pass']);
-
+}
 }
 
+if(! function_exists('install_post')) {
 function install_post(&$a) {
 	global $install_wizard_pass, $db;
 
@@ -112,14 +113,18 @@ function install_post(&$a) {
 		break;
 	}
 }
+}
 
+if(! function_exists('get_db_errno')) {
 function get_db_errno() {
 	if(class_exists('mysqli'))
 		return mysqli_connect_errno();
 	else
 		return mysql_errno();
 }
+}
 
+if(! function_exists('install_content')) {
 function install_content(&$a) {
 
 	global $install_wizard_pass, $db;
@@ -304,6 +309,7 @@ function install_content(&$a) {
 
 	}
 }
+}
 
 /**
  * checks   : array passed to template
@@ -312,7 +318,8 @@ function install_content(&$a) {
  * required : boolean
  * help		: string optional
  */
-function check_add(&$checks, $title, $status, $required, $help){
+if(! function_exists('check_add')) {
+function check_add(&$checks, $title, $status, $required, $help) {
 	$checks[] = array(
 		'title' => $title,
 		'status' => $status,
@@ -320,7 +327,9 @@ function check_add(&$checks, $title, $status, $required, $help){
 		'help'	=> $help,
 	);
 }
+}
 
+if(! function_exists('check_php')) {
 function check_php(&$phpath, &$checks) {
 	$passed = $passed2 = $passed3 = false;
 	if (strlen($phpath)){
@@ -370,9 +379,10 @@ function check_php(&$phpath, &$checks) {
 		check_add($checks, t('PHP register_argc_argv'), $passed3, true, $help);
 	}
 
-
+}
 }
 
+if(! function_exists('check_keys')) {
 function check_keys(&$checks) {
 
 	$help = '';
@@ -392,10 +402,10 @@ function check_keys(&$checks) {
 		$help .= t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
 	}
 	check_add($checks, t('Generate encryption keys'), $res, true, $help);
-
+}
 }
 
-
+if(! function_exists('check_funcs')) {
 function check_funcs(&$checks) {
 	$ck_funcs = array();
 	check_add($ck_funcs, t('libCurl PHP module'), true, true, "");
@@ -457,8 +467,9 @@ function check_funcs(&$checks) {
 	/*if((x($_SESSION,'sysmsg')) && is_array($_SESSION['sysmsg']) && count($_SESSION['sysmsg']))
 		notice( t('Please see the file "INSTALL.txt".') . EOL);*/
 }
+}
 
-
+if(! function_exists('check_htconfig')) {
 function check_htconfig(&$checks) {
 	$status = true;
 	$help = "";
@@ -473,9 +484,10 @@ function check_htconfig(&$checks) {
 	}
 
 	check_add($checks, t('.htconfig.php is writable'), $status, false, $help);
-
+}
 }
 
+if(! function_exists('check_smarty3')) {
 function check_smarty3(&$checks) {
 	$status = true;
 	$help = "";
@@ -489,9 +501,10 @@ function check_smarty3(&$checks) {
 	}
 
 	check_add($checks, t('view/smarty3 is writable'), $status, true, $help);
-
+}
 }
 
+if(! function_exists('check_htaccess')) {
 function check_htaccess(&$checks) {
 	$a = get_app();
 	$status = true;
@@ -511,7 +524,9 @@ function check_htaccess(&$checks) {
 		// cannot check modrewrite if libcurl is not installed
 	}
 }
+}
 
+if(! function_exists('check_imagik')) {
 function check_imagik(&$checks) {
 	$imagick = false;
 	$gif = false;
@@ -528,16 +543,18 @@ function check_imagik(&$checks) {
 		check_add($checks, t('ImageMagick supports GIF'), $gif, false, "");
 	}
 }
+}
 
-
-
+if(! function_exists('manual_config')) {
 function manual_config(&$a) {
 	$data = htmlentities($a->data['txt'],ENT_COMPAT,'UTF-8');
 	$o = t('The database configuration file ".htconfig.php" could not be written. Please use the enclosed text to create a configuration file in your web server root.');
 	$o .= "<textarea rows=\"24\" cols=\"80\" >$data</textarea>";
 	return $o;
 }
+}
 
+if(! function_exists('load_database_rem')) {
 function load_database_rem($v, $i){
 	$l = trim($i);
 	if (strlen($l)>1 && ($l[0]=="-" || ($l[0]=="/" && $l[1]=="*"))){
@@ -546,8 +563,9 @@ function load_database_rem($v, $i){
 		return $v."\n".$i;
 	}
 }
+}
 
-
+if(! function_exists('load_database')) {
 function load_database($db) {
 
 	require_once("include/dbstructure.php");
@@ -567,7 +585,9 @@ function load_database($db) {
 
 	return $errors;
 }
+}
 
+if(! function_exists('what_next')) {
 function what_next() {
 	$a = get_app();
 	$baseurl = $a->get_baseurl();
@@ -579,5 +599,4 @@ function what_next() {
 		.t("Go to your new Friendica node <a href='$baseurl/register'>registration page</a> and register as new user. Remember to use the same email you have entered as administrator email. This will allow you to enter the site admin panel.")
 		."</p>";
 }
-
-
+}
diff --git a/mod/invite.php b/mod/invite.php
index ccf876c7c0..1f559dabc0 100644
--- a/mod/invite.php
+++ b/mod/invite.php
@@ -9,6 +9,7 @@
 
 require_once('include/email.php');
 
+if(! function_exists('invite_post')) {
 function invite_post(&$a) {
 
 	if(! local_user()) {
@@ -49,7 +50,7 @@ function invite_post(&$a) {
 			notice(  sprintf( t('%s : Not a valid email address.'), $recip) . EOL);
 			continue;
 		}
-		
+
 		if($invonly && ($x || is_site_admin())) {
 			$code = autoname(8) . srand(1000,9999);
 			$nmessage = str_replace('$invite_code',$code,$message);
@@ -70,8 +71,8 @@ function invite_post(&$a) {
 		else
 			$nmessage = $message;
 
-		$res = mail($recip, email_header_encode( t('Please join us on Friendica'),'UTF-8'), 
-			$nmessage, 
+		$res = mail($recip, email_header_encode( t('Please join us on Friendica'),'UTF-8'),
+			$nmessage,
 			"From: " . $a->user['email'] . "\n"
 			. 'Content-type: text/plain; charset=UTF-8' . "\n"
 			. 'Content-transfer-encoding: 8bit' );
@@ -93,8 +94,9 @@ function invite_post(&$a) {
 	notice( sprintf( tt("%d message sent.", "%d messages sent.", $total) , $total) . EOL);
 	return;
 }
+}
 
-
+if(! function_exists('invite_content')) {
 function invite_content(&$a) {
 
 	if(! local_user()) {
@@ -134,7 +136,7 @@ function invite_content(&$a) {
 		'$msg_text' => t('Your message:'),
 		'$default_message' => t('You are cordially invited to join me and other close friends on Friendica - and help us to create a better social web.') . "\r\n" . "\r\n"
 			. $linktxt
-			. "\r\n" . "\r\n" . (($invonly) ? t('You will need to supply this invitation code: $invite_code') . "\r\n" . "\r\n" : '') .t('Once you have registered, please connect with me via my profile page at:') 
+			. "\r\n" . "\r\n" . (($invonly) ? t('You will need to supply this invitation code: $invite_code') . "\r\n" . "\r\n" : '') .t('Once you have registered, please connect with me via my profile page at:')
 			. "\r\n" . "\r\n" . $a->get_baseurl() . '/profile/' . $a->user['nickname']
 			. "\r\n" . "\r\n" . t('For more information about the Friendica project and why we feel it is important, please visit http://friendica.com') . "\r\n" . "\r\n"  ,
 		'$submit' => t('Submit')
@@ -142,3 +144,4 @@ function invite_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/item.php b/mod/item.php
index 8c5a479646..f8f2e0fafe 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -25,6 +25,7 @@ require_once('include/text.php');
 require_once('include/items.php');
 require_once('include/Scrape.php');
 
+if(! function_exists('item_post')) {
 function item_post(&$a) {
 
 	if((! local_user()) && (! remote_user()) && (! x($_REQUEST,'commenter')))
@@ -1017,7 +1018,9 @@ function item_post(&$a) {
 	item_post_return($a->get_baseurl(), $api_source, $return_path);
 	// NOTREACHED
 }
+}
 
+if(! function_exists('item_post_return')) {
 function item_post_return($baseurl, $api_source, $return_path) {
 	// figure out how to return, depending on from whence we came
 
@@ -1037,9 +1040,9 @@ function item_post_return($baseurl, $api_source, $return_path) {
 	echo json_encode($json);
 	killme();
 }
+}
 
-
-
+if(! function_exists('item_content')) {
 function item_content(&$a) {
 
 	if((! local_user()) && (! remote_user()))
@@ -1058,6 +1061,7 @@ function item_content(&$a) {
 	}
 	return $o;
 }
+}
 
 /**
  * This function removes the tag $tag from the text $body and replaces it with
@@ -1071,6 +1075,7 @@ function item_content(&$a) {
  *
  * @return boolean true if replaced, false if not replaced
  */
+if(! function_exists('handle_tag')) {
 function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $network = "") {
 	require_once("include/Scrape.php");
 	require_once("include/socgraph.php");
@@ -1245,8 +1250,9 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
 
 	return array('replaced' => $replaced, 'contact' => $r[0]);
 }
+}
 
-
+if(! function_exists('store_diaspora_comment_sig')) {
 function store_diaspora_comment_sig($datarray, $author, $uprvkey, $parent_item, $post_id) {
 	// We won't be able to sign Diaspora comments for authenticated visitors - we don't have their private key
 
@@ -1284,3 +1290,4 @@ function store_diaspora_comment_sig($datarray, $author, $uprvkey, $parent_item,
 
 	return;
 }
+}
diff --git a/mod/like.php b/mod/like.php
index 8d383b9abe..ef483a1f9e 100755
--- a/mod/like.php
+++ b/mod/like.php
@@ -5,6 +5,7 @@ require_once('include/bbcode.php');
 require_once('include/items.php');
 require_once('include/like.php');
 
+if(! function_exists('like_content')) {
 function like_content(&$a) {
 	if(! local_user() && ! remote_user()) {
 		return false;
@@ -28,11 +29,11 @@ function like_content(&$a) {
 	killme(); // NOTREACHED
 //	return; // NOTREACHED
 }
-
+}
 
 // Decide how to return. If we were called with a 'return' argument,
 // then redirect back to the calling page. If not, just quietly end
-
+if(! function_exists('like_content_return')) {
 function like_content_return($baseurl, $return_path) {
 
 	if($return_path) {
@@ -45,4 +46,4 @@ function like_content_return($baseurl, $return_path) {
 
 	killme();
 }
-
+}
diff --git a/mod/localtime.php b/mod/localtime.php
index d1453bc527..fc500f4dd9 100644
--- a/mod/localtime.php
+++ b/mod/localtime.php
@@ -2,7 +2,7 @@
 
 require_once('include/datetime.php');
 
-
+if(! function_exists('localtime_post')) {
 function localtime_post(&$a) {
 
 	$t = $_REQUEST['time'];
@@ -13,9 +13,10 @@ function localtime_post(&$a) {
 
 	if($_POST['timezone'])
 		$a->data['mod-localtime'] = datetime_convert('UTC',$_POST['timezone'],$t,$bd_format);
-
+}
 }
 
+if(! function_exists('localtime_content')) {
 function localtime_content(&$a) {
 	$t = $_REQUEST['time'];
 	if(! $t)
@@ -38,12 +39,12 @@ function localtime_content(&$a) {
 
 	$o .= '<form action ="' . $a->get_baseurl() . '/localtime?f=&time=' . $t . '" method="post" >';
 
-	$o .= '<p>' . t('Please select your timezone:') . '</p>'; 
+	$o .= '<p>' . t('Please select your timezone:') . '</p>';
 
 	$o .= select_timezone(($_REQUEST['timezone']) ? $_REQUEST['timezone'] : 'America/Los_Angeles');
 
 	$o .= '<input type="submit" name="submit" value="' . t('Submit') . '" /></form>';
 
 	return $o;
-
-}
\ No newline at end of file
+}
+}
diff --git a/mod/lockview.php b/mod/lockview.php
index 0ae54c8c12..82f93f4985 100644
--- a/mod/lockview.php
+++ b/mod/lockview.php
@@ -1,8 +1,8 @@
 <?php
 
-
+if(! function_exists('lockview_content')) {
 function lockview_content(&$a) {
-  
+
 	$type = (($a->argc > 1) ? $a->argv[1] : 0);
 	if (is_numeric($type)) {
 		$item_id = intval($type);
@@ -10,13 +10,13 @@ function lockview_content(&$a) {
 	} else {
 		$item_id = (($a->argc > 2) ? intval($a->argv[2]) : 0);
 	}
-  
+
 	if(! $item_id)
 		killme();
 
 	if (!in_array($type, array('item','photo','event')))
 		killme();
-     
+
 	$r = q("SELECT * FROM `%s` WHERE `id` = %d LIMIT 1",
 		dbesc($type),
 		intval($item_id)
@@ -33,7 +33,7 @@ function lockview_content(&$a) {
 	}
 
 
-	if(($item['private'] == 1) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid'])) 
+	if(($item['private'] == 1) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
 		&& (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) {
 
 		echo t('Remote privacy information not available.') . '<br />';
@@ -53,7 +53,7 @@ function lockview_content(&$a) {
 			dbesc(implode(', ', $allowed_groups))
 		);
 		if(count($r))
-			foreach($r as $rr) 
+			foreach($r as $rr)
 				$l[] = '<b>' . $rr['name'] . '</b>';
 	}
 	if(count($allowed_users)) {
@@ -61,7 +61,7 @@ function lockview_content(&$a) {
 			dbesc(implode(', ',$allowed_users))
 		);
 		if(count($r))
-			foreach($r as $rr) 
+			foreach($r as $rr)
 				$l[] = $rr['name'];
 
 	}
@@ -71,7 +71,7 @@ function lockview_content(&$a) {
 			dbesc(implode(', ', $deny_groups))
 		);
 		if(count($r))
-			foreach($r as $rr) 
+			foreach($r as $rr)
 				$l[] = '<b><strike>' . $rr['name'] . '</strike></b>';
 	}
 	if(count($deny_users)) {
@@ -79,12 +79,12 @@ function lockview_content(&$a) {
 			dbesc(implode(', ',$deny_users))
 		);
 		if(count($r))
-			foreach($r as $rr) 
+			foreach($r as $rr)
 				$l[] = '<strike>' . $rr['name'] . '</strike>';
 
 	}
 
 	echo $o . implode(', ', $l);
 	killme();
-
+}
 }
diff --git a/mod/login.php b/mod/login.php
index d09fc1868f..47c329eb63 100644
--- a/mod/login.php
+++ b/mod/login.php
@@ -1,5 +1,5 @@
 <?php
-
+if(! function_exists('login_content')) {
 function login_content(&$a) {
 	if(x($_SESSION,'theme'))
 		unset($_SESSION['theme']);
@@ -9,5 +9,5 @@ function login_content(&$a) {
 	if(local_user())
 		goaway(z_root());
 	return login(($a->config['register_policy'] == REGISTER_CLOSED) ? false : true);
-
+}
 }
diff --git a/mod/lostpass.php b/mod/lostpass.php
index 938d1cbb00..0c4bb1a833 100644
--- a/mod/lostpass.php
+++ b/mod/lostpass.php
@@ -4,6 +4,7 @@ require_once('include/email.php');
 require_once('include/enotify.php');
 require_once('include/text.php');
 
+if(! function_exists('lostpass_post')) {
 function lostpass_post(&$a) {
 
 	$loginame = notags(trim($_POST['login-name']));
@@ -74,10 +75,10 @@ function lostpass_post(&$a) {
 		'body' => $body));
 
 	goaway(z_root());
-
+}
 }
 
-
+if(! function_exists('lostpass_content')) {
 function lostpass_content(&$a) {
 
 
@@ -164,5 +165,5 @@ function lostpass_content(&$a) {
 
 		return $o;
 	}
-
+}
 }
diff --git a/mod/maintenance.php b/mod/maintenance.php
index b50c94c9b9..02de29108f 100644
--- a/mod/maintenance.php
+++ b/mod/maintenance.php
@@ -1,7 +1,8 @@
 <?php
-
+if(! function_exists('maintenance_content')) {
 function maintenance_content(&$a) {
 	return replace_macros(get_markup_template('maintenance.tpl'), array(
 		'$sysdown' => t('System down for maintenance')
 	));
 }
+}
diff --git a/mod/manage.php b/mod/manage.php
index adcc3d787a..6af3db9971 100644
--- a/mod/manage.php
+++ b/mod/manage.php
@@ -2,7 +2,7 @@
 
 require_once("include/text.php");
 
-
+if(! function_exists('manage_post')) {
 function manage_post(&$a) {
 
 	if(! local_user())
@@ -87,9 +87,9 @@ function manage_post(&$a) {
 	goaway( $a->get_baseurl() . "/profile/" . $a->user['nickname'] );
 	// NOTREACHED
 }
+}
 
-
-
+if(! function_exists('manage_content')) {
 function manage_content(&$a) {
 
 	if(! local_user()) {
@@ -144,5 +144,5 @@ function manage_content(&$a) {
 	));
 
 	return $o;
-
+}
 }
diff --git a/mod/match.php b/mod/match.php
index 3b0367b429..f4936b28dc 100644
--- a/mod/match.php
+++ b/mod/match.php
@@ -13,6 +13,7 @@ require_once('mod/proxy.php');
  * @param App &$a
  * @return void|string
  */
+if(! function_exists('match_content')) {
 function match_content(&$a) {
 
 	$o = '';
@@ -109,3 +110,4 @@ function match_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/message.php b/mod/message.php
index 1724ebc424..1f11797d8b 100644
--- a/mod/message.php
+++ b/mod/message.php
@@ -3,6 +3,7 @@
 require_once('include/acl_selectors.php');
 require_once('include/message.php');
 
+if(! function_exists('message_init')) {
 function message_init(&$a) {
 
 	$tabs = '';
@@ -36,9 +37,10 @@ function message_init(&$a) {
 		'$baseurl' => $a->get_baseurl(true),
 		'$base' => $base
 	));
-
+}
 }
 
+if(! function_exists('message_post')) {
 function message_post(&$a) {
 
 	if(! local_user()) {
@@ -91,7 +93,7 @@ function message_post(&$a) {
 	}
 	else
 		goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']);
-
+}
 }
 
 // Note: the code in 'item_extract_images' and 'item_redir_and_replace_images'
@@ -171,7 +173,7 @@ function item_redir_and_replace_images($body, $images, $cid) {
 }}
 
 
-
+if(! function_exists('message_content')) {
 function message_content(&$a) {
 
 	$o = '';
@@ -530,7 +532,9 @@ function message_content(&$a) {
 		return $o;
 	}
 }
+}
 
+if(! function_exists('get_messages')) {
 function get_messages($user, $lstart, $lend) {
 
 	return q("SELECT max(`mail`.`created`) AS `mailcreated`, min(`mail`.`seen`) AS `mailseen`,
@@ -541,7 +545,9 @@ function get_messages($user, $lstart, $lend) {
 		intval($user), intval($lstart), intval($lend)
 	);
 }
+}
 
+if(! function_exists('render_messages')) {
 function render_messages($msg, $t) {
 
 	$a = get_app();
@@ -593,3 +599,4 @@ function render_messages($msg, $t) {
 
 	return $rslt;
 }
+}
diff --git a/mod/modexp.php b/mod/modexp.php
index bba2c2882d..282d55a24b 100644
--- a/mod/modexp.php
+++ b/mod/modexp.php
@@ -2,6 +2,7 @@
 
 require_once('library/asn1.php');
 
+if(! function_exists('modexp_init')) {
 function modexp_init(&$a) {
 
 	if($a->argc != 2)
@@ -29,6 +30,5 @@ function modexp_init(&$a) {
 	echo 'RSA' . '.' . $m . '.' . $e ;
 
 	killme();
-
 }
-
+}
diff --git a/mod/mood.php b/mod/mood.php
index eee11e20c5..2476f06562 100644
--- a/mod/mood.php
+++ b/mod/mood.php
@@ -4,7 +4,7 @@ require_once('include/security.php');
 require_once('include/bbcode.php');
 require_once('include/items.php');
 
-
+if(! function_exists('mood_init')) {
 function mood_init(&$a) {
 
 	if(! local_user())
@@ -59,7 +59,7 @@ function mood_init(&$a) {
 
 	$uri = item_new_uri($a->get_hostname(),$uid);
 
-	$action = sprintf( t('%1$s is currently %2$s'), '[url=' . $poster['url'] . ']' . $poster['name'] . '[/url]' , $verbs[$verb]); 
+	$action = sprintf( t('%1$s is currently %2$s'), '[url=' . $poster['url'] . ']' . $poster['name'] . '[/url]' , $verbs[$verb]);
 
 	$arr = array();
 
@@ -105,9 +105,9 @@ function mood_init(&$a) {
 
 	return;
 }
+}
 
-
-
+if(! function_exists('mood_content')) {
 function mood_content(&$a) {
 
 	if(! local_user()) {
@@ -138,5 +138,5 @@ function mood_content(&$a) {
 	));
 
 	return $o;
-
+}
 }
diff --git a/mod/msearch.php b/mod/msearch.php
index 89de5b7057..3b1b0b617a 100644
--- a/mod/msearch.php
+++ b/mod/msearch.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('msearch_post')) {
 function msearch_post(&$a) {
 
 	$perpage = (($_POST['n']) ? $_POST['n'] : 80);
@@ -26,8 +27,8 @@ function msearch_post(&$a) {
 	if(count($r)) {
 		foreach($r as $rr)
 			$results[] = array(
-				'name' => $rr['name'], 
-				'url' => $a->get_baseurl() . '/profile/' . $rr['nickname'], 
+				'name' => $rr['name'],
+				'url' => $a->get_baseurl() . '/profile/' . $rr['nickname'],
 				'photo' => $a->get_baseurl() . '/photo/avatar/' . $rr['uid'] . '.jpg',
 				'tags' => str_replace(array(',','  '),array(' ',' '),$rr['pub_keywords'])
 			);
@@ -38,5 +39,5 @@ function msearch_post(&$a) {
 	echo json_encode($output);
 
 	killme();
-
-}
\ No newline at end of file
+}
+}
diff --git a/mod/navigation.php b/mod/navigation.php
index 5db69b171e..8fbabfda96 100644
--- a/mod/navigation.php
+++ b/mod/navigation.php
@@ -2,6 +2,7 @@
 
 require_once("include/nav.php");
 
+if(! function_exists('navigation_content')) {
 function navigation_content(&$a) {
 
 	$nav_info = nav_info($a);
@@ -22,5 +23,5 @@ function navigation_content(&$a) {
 		'$apps' => $a->apps,
 		'$clear_notifs' => t('Clear notifications')
 	));
-
+}
 }
diff --git a/mod/network.php b/mod/network.php
index a07c5868ec..9b07384e1b 100644
--- a/mod/network.php
+++ b/mod/network.php
@@ -1,4 +1,6 @@
 <?php
+
+if(! function_exists('network_init')) {
 function network_init(&$a) {
 	if(! local_user()) {
 		notice( t('Permission denied.') . EOL);
@@ -153,9 +155,10 @@ function network_init(&$a) {
 	$a->page['aside'] .= networks_widget($a->get_baseurl(true) . '/network',(x($_GET, 'nets') ? $_GET['nets'] : ''));
 	$a->page['aside'] .= saved_searches($search);
 	$a->page['aside'] .= fileas_widget($a->get_baseurl(true) . '/network',(x($_GET, 'file') ? $_GET['file'] : ''));
-
+}
 }
 
+if(! function_exists('saved_searches')) {
 function saved_searches($search) {
 
 	if(! feature_enabled(local_user(),'savedsearch'))
@@ -204,7 +207,7 @@ function saved_searches($search) {
 	));
 
 	return $o;
-
+}
 }
 
 /**
@@ -222,6 +225,7 @@ function saved_searches($search) {
  *
  * @return Array ( $no_active, $comment_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active );
  */
+if(! function_exists('network_query_get_sel_tab')) {
 function network_query_get_sel_tab($a) {
 	$no_active='';
 	$starred_active = '';
@@ -278,10 +282,12 @@ function network_query_get_sel_tab($a) {
 
 	return array($no_active, $all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active);
 }
+}
 
 /**
  * Return selected network from query
  */
+if(! function_exists('network_query_get_sel_net')) {
 function network_query_get_sel_net() {
 	$network = false;
 
@@ -291,7 +297,9 @@ function network_query_get_sel_net() {
 
 	return $network;
 }
+}
 
+if(! function_exists('network_query_get_sel_group')) {
 function network_query_get_sel_group($a) {
 	$group = false;
 
@@ -301,8 +309,9 @@ function network_query_get_sel_group($a) {
 
 	return $group;
 }
+}
 
-
+if(! function_exists('network_content')) {
 function network_content(&$a, $update = 0) {
 
 	require_once('include/conversation.php');
@@ -886,4 +895,4 @@ function network_content(&$a, $update = 0) {
 
 	return $o;
 }
-
+}
diff --git a/mod/newmember.php b/mod/newmember.php
index aa55c3a098..ef25333302 100644
--- a/mod/newmember.php
+++ b/mod/newmember.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('newmember_content')) {
 function newmember_content(&$a) {
 
 
@@ -15,7 +16,7 @@ function newmember_content(&$a) {
 
 	$o .= '<ul>';
 
-	$o .= '<li> ' . '<a target="newmember" href="help/guide">' . t('Friendica Walk-Through') . '</a><br />' . t('On your <em>Quick Start</em> page - find a brief introduction to your profile and network tabs, make some new connections, and find some groups to join.') . '</li>' . EOL; 
+	$o .= '<li> ' . '<a target="newmember" href="help/guide">' . t('Friendica Walk-Through') . '</a><br />' . t('On your <em>Quick Start</em> page - find a brief introduction to your profile and network tabs, make some new connections, and find some groups to join.') . '</li>' . EOL;
 
 	$o .= '</ul>';
 
@@ -23,7 +24,7 @@ function newmember_content(&$a) {
 
 	$o .= '<ul>';
 
-	$o .= '<li>' . '<a target="newmember" href="settings">' . t('Go to Your Settings') . '</a><br />' . t('On your <em>Settings</em> page -  change your initial password. Also make a note of your Identity Address. This looks just like an email address - and will be useful in making friends on the free social web.') . '</li>' . EOL; 
+	$o .= '<li>' . '<a target="newmember" href="settings">' . t('Go to Your Settings') . '</a><br />' . t('On your <em>Settings</em> page -  change your initial password. Also make a note of your Identity Address. This looks just like an email address - and will be useful in making friends on the free social web.') . '</li>' . EOL;
 
 	$o .= '<li>' . t('Review the other settings, particularly the privacy settings. An unpublished directory listing is like having an unlisted phone number. In general, you should probably publish your listing - unless all of your friends and potential friends know exactly how to find you.') . '</li>' . EOL;
 
@@ -33,7 +34,7 @@ function newmember_content(&$a) {
 
 	$o .= '<ul>';
 
-	$o .= '<li>' . '<a target="newmember" href="profile_photo">' . t('Upload Profile Photo') . '</a><br />' . t('Upload a profile photo if you have not done so already. Studies have shown that people with real photos of themselves are ten times more likely to make friends than people who do not.') . '</li>' . EOL;  
+	$o .= '<li>' . '<a target="newmember" href="profile_photo">' . t('Upload Profile Photo') . '</a><br />' . t('Upload a profile photo if you have not done so already. Studies have shown that people with real photos of themselves are ten times more likely to make friends than people who do not.') . '</li>' . EOL;
 
 	$o .= '<li>' . '<a target="newmember" href="profiles">' . t('Edit Your Profile') . '</a><br />' . t('Edit your <strong>default</strong> profile to your liking. Review the settings for hiding your list of friends and hiding the profile from unknown visitors.') . '</li>' . EOL;
 
@@ -46,7 +47,7 @@ function newmember_content(&$a) {
 	$o .= '<ul>';
 
     $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1);
-	
+
 	if(! $mail_disabled)
 		$o .= '<li>' . '<a target="newmember" href="settings/connectors">' . t('Importing Emails') . '</a><br />' . t('Enter your email access information on your Connector Settings page if you wish to import and interact with friends or mailing lists from your email INBOX') . '</li>' . EOL;
 
@@ -82,3 +83,4 @@ function newmember_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/nodeinfo.php b/mod/nodeinfo.php
index ba310a1051..7f8939182e 100644
--- a/mod/nodeinfo.php
+++ b/mod/nodeinfo.php
@@ -1,12 +1,13 @@
 <?php
 /**
  * @file mod/nodeinfo.php
- * 
+ *
  * Documentation: http://nodeinfo.diaspora.software/schema.html
 */
 
 require_once("include/plugin.php");
 
+if(! function_exists('nodeinfo_wellknown')) {
 function nodeinfo_wellknown(&$a) {
 	if (!get_config("system", "nodeinfo")) {
 		http_status_exit(404);
@@ -19,7 +20,9 @@ function nodeinfo_wellknown(&$a) {
 	echo json_encode($nodeinfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
 	exit;
 }
+}
 
+if(! function_exists('nodeinfo_init')) {
 function nodeinfo_init(&$a){
 	if (!get_config("system", "nodeinfo")) {
 		http_status_exit(404);
@@ -143,9 +146,9 @@ function nodeinfo_init(&$a){
 	echo json_encode($nodeinfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
 	exit;
 }
+}
 
-
-
+if(! function_exists('nodeinfo_cron')) {
 function nodeinfo_cron() {
 
 	$a = get_app();
@@ -260,5 +263,5 @@ function nodeinfo_cron() {
         logger("cron_end");
 	set_config('nodeinfo','last_calucation', time());
 }
-
+}
 ?>
diff --git a/mod/nogroup.php b/mod/nogroup.php
index 9f6e978433..818b0da77a 100644
--- a/mod/nogroup.php
+++ b/mod/nogroup.php
@@ -4,6 +4,7 @@ require_once('include/Contact.php');
 require_once('include/socgraph.php');
 require_once('include/contact_selectors.php');
 
+if(! function_exists('nogroup_init')) {
 function nogroup_init(&$a) {
 
 	if(! local_user())
@@ -17,8 +18,9 @@ function nogroup_init(&$a) {
 
 	$a->page['aside'] .= group_side('contacts','group','extended',0,$contact_id);
 }
+}
 
-
+if(! function_exists('nogroup_content')) {
 function nogroup_content(&$a) {
 
 	if(! local_user()) {
@@ -66,5 +68,5 @@ function nogroup_content(&$a) {
 	));
 
 	return $o;
-
+}
 }
diff --git a/mod/noscrape.php b/mod/noscrape.php
index 51bd7234cf..49fe2b9a37 100644
--- a/mod/noscrape.php
+++ b/mod/noscrape.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('noscrape_init')) {
 function noscrape_init(&$a) {
 
 	if($a->argc > 1)
@@ -62,5 +63,5 @@ function noscrape_init(&$a) {
 	header('Content-type: application/json; charset=utf-8');
 	echo json_encode($json_info);
 	exit;
-
+}
 }
diff --git a/mod/notes.php b/mod/notes.php
index 73c1507e3e..7817e25547 100644
--- a/mod/notes.php
+++ b/mod/notes.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('notes_init')) {
 function notes_init(&$a) {
 
 	if(! local_user())
@@ -12,10 +13,10 @@ function notes_init(&$a) {
 	nav_set_selected('home');
 
 //	profile_load($a,$which,$profile);
-
+}
 }
 
-
+if(! function_exists('notes_content')) {
 function notes_content(&$a,$update = false) {
 
 	if(! local_user()) {
@@ -69,12 +70,12 @@ function notes_content(&$a,$update = false) {
 	// Construct permissions
 
 	// default permissions - anonymous user
-	
+
 	$sql_extra = " AND `allow_cid` = '<" . $a->contact['id'] . ">' ";
 
 	$r = q("SELECT COUNT(*) AS `total`
 		FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
-		WHERE `item`.`uid` = %d AND `item`.`visible` = 1 and `item`.`moderated` = 0 
+		WHERE `item`.`uid` = %d AND `item`.`visible` = 1 and `item`.`moderated` = 0
 		AND `item`.`deleted` = 0 AND `item`.`type` = 'note'
 		AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 AND `contact`.`self` = 1
 		AND `item`.`id` = `item`.`parent` AND `item`.`wall` = 0
@@ -90,7 +91,7 @@ function notes_content(&$a,$update = false) {
 
 	$r = q("SELECT `item`.`id` AS `item_id`, `contact`.`uid` AS `contact-uid`
 		FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
-		WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0 
+		WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
 		and `item`.`moderated` = 0 AND `item`.`type` = 'note'
 		AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 AND `contact`.`self` = 1
 		AND `item`.`id` = `item`.`parent` AND `item`.`wall` = 0
@@ -109,10 +110,10 @@ function notes_content(&$a,$update = false) {
 		foreach($r as $rr)
 			$parents_arr[] = $rr['item_id'];
 		$parents_str = implode(', ', $parents_arr);
- 
-		$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, 
-			`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`alias`, `contact`.`network`, `contact`.`rel`, 
-			`contact`.`thumb`, `contact`.`self`, `contact`.`writable`, 
+
+		$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
+			`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`alias`, `contact`.`network`, `contact`.`rel`,
+			`contact`.`thumb`, `contact`.`self`, `contact`.`writable`,
 			`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
 			FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
 			WHERE `item`.`uid` = %d AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
@@ -135,3 +136,4 @@ function notes_content(&$a,$update = false) {
 	$o .= paginate($a);
 	return $o;
 }
+}
diff --git a/mod/notice.php b/mod/notice.php
index 19cf53189a..a42d60dd40 100644
--- a/mod/notice.php
+++ b/mod/notice.php
@@ -1,7 +1,8 @@
 <?php
-	/* identi.ca -> friendica items permanent-url compatibility */
-	
-	function notice_init(&$a){
+/* identi.ca -> friendica items permanent-url compatibility */
+
+if(! function_exists('notice_init')) {
+	function notice_init(&$a) {
 		$id = $a->argv[1];
 		$r = q("SELECT user.nickname FROM user LEFT JOIN item ON item.uid=user.uid WHERE item.id=%d",
 				intval($id)
@@ -16,5 +17,5 @@
 
 		}
 		return;
-
 	}
+}
diff --git a/mod/notifications.php b/mod/notifications.php
index a267b7c958..c7421b2d42 100644
--- a/mod/notifications.php
+++ b/mod/notifications.php
@@ -3,6 +3,7 @@ include_once("include/bbcode.php");
 include_once("include/contact_selectors.php");
 include_once("include/Scrape.php");
 
+if(! function_exists('notifications_post')) {
 function notifications_post(&$a) {
 
 	if(! local_user()) {
@@ -58,11 +59,11 @@ function notifications_post(&$a) {
 		}
 	}
 }
+}
 
 
 
-
-
+if(! function_exists('notifications_content')) {
 function notifications_content(&$a) {
 
 	if(! local_user()) {
@@ -579,3 +580,4 @@ function notifications_content(&$a) {
 	$o .= paginate($a);
 	return $o;
 }
+}
diff --git a/mod/notify.php b/mod/notify.php
index 02260514af..7acac1084a 100644
--- a/mod/notify.php
+++ b/mod/notify.php
@@ -1,6 +1,6 @@
 <?php
 
-
+if(! function_exists('notify_init')) {
 function notify_init(&$a) {
 	if(! local_user())
 		return;
@@ -42,10 +42,10 @@ function notify_init(&$a) {
 		echo $j;
 		killme();
 	}
-
+}
 }
 
-
+if(! function_exists('notify_content')) {
 function notify_content(&$a) {
 	if(! local_user())
 		return login();
@@ -80,5 +80,5 @@ function notify_content(&$a) {
 
 	return $o;
 
-
+}
 }
diff --git a/mod/oembed.php b/mod/oembed.php
index cb478cb860..021cbab6fd 100644
--- a/mod/oembed.php
+++ b/mod/oembed.php
@@ -1,7 +1,8 @@
 <?php
 require_once("include/oembed.php");
 
-function oembed_content(&$a){
+if(! function_exists('oembed_content')) {
+function oembed_content(&$a) {
 	// logger('mod_oembed ' . $a->query_string, LOGGER_ALL);
 
 	if ($a->argv[1]=='b2h'){
@@ -33,3 +34,4 @@ function oembed_content(&$a){
 	}
 	killme();
 }
+}
diff --git a/mod/oexchange.php b/mod/oexchange.php
index bbb436e702..1e7c9b23c9 100644
--- a/mod/oexchange.php
+++ b/mod/oexchange.php
@@ -1,6 +1,6 @@
 <?php
 
-
+if(! function_exists('oexchange_init')) {
 function oexchange_init(&$a) {
 
 	if(($a->argc > 1) && ($a->argv[1] === 'xrd')) {
@@ -11,9 +11,10 @@ function oexchange_init(&$a) {
 		killme();
 	}
 
-
+}
 }
 
+if(! function_exists('oexchange_content')) {
 function oexchange_content(&$a) {
 
 	if(! local_user()) {
@@ -26,13 +27,13 @@ function oexchange_content(&$a) {
 		return;
 	}
 
-	$url = (((x($_REQUEST,'url')) && strlen($_REQUEST['url'])) 
+	$url = (((x($_REQUEST,'url')) && strlen($_REQUEST['url']))
 		? urlencode(notags(trim($_REQUEST['url']))) : '');
-	$title = (((x($_REQUEST,'title')) && strlen($_REQUEST['title'])) 
+	$title = (((x($_REQUEST,'title')) && strlen($_REQUEST['title']))
 		? '&title=' . urlencode(notags(trim($_REQUEST['title']))) : '');
-	$description = (((x($_REQUEST,'description')) && strlen($_REQUEST['description'])) 
+	$description = (((x($_REQUEST,'description')) && strlen($_REQUEST['description']))
 		? '&description=' . urlencode(notags(trim($_REQUEST['description']))) : '');
-	$tags = (((x($_REQUEST,'tags')) && strlen($_REQUEST['tags'])) 
+	$tags = (((x($_REQUEST,'tags')) && strlen($_REQUEST['tags']))
 		? '&tags=' . urlencode(notags(trim($_REQUEST['tags']))) : '');
 
 	$s = fetch_url($a->get_baseurl() . '/parse_url?f=&url=' . $url . $title . $description . $tags);
@@ -52,7 +53,5 @@ function oexchange_content(&$a) {
 	$_REQUEST = $post;
 	require_once('mod/item.php');
 	item_post($a);
-
 }
-
-
+}
diff --git a/mod/openid.php b/mod/openid.php
index 5d5539f00e..a92a124c0d 100644
--- a/mod/openid.php
+++ b/mod/openid.php
@@ -1,9 +1,8 @@
 <?php
 
-
 require_once('library/openid.php');
 
-
+if(! function_exists('openid_content')) {
 function openid_content(&$a) {
 
 	$noid = get_config('system','no_openid');
@@ -25,8 +24,8 @@ function openid_content(&$a) {
 				goaway(z_root());
 			}
 
-			$r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey` 
-				FROM `user` WHERE `openid` = '%s' AND `blocked` = 0 
+			$r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey`
+				FROM `user` WHERE `openid` = '%s' AND `blocked` = 0
 				AND `account_expired` = 0 AND `account_removed` = 0 AND `verified` = 1 LIMIT 1",
 				dbesc($authid)
 			);
@@ -40,7 +39,7 @@ function openid_content(&$a) {
 				require_once('include/security.php');
 				authenticate_success($r[0],true,true);
 
-				// just in case there was no return url set 
+				// just in case there was no return url set
 				// and we fell through
 
 				goaway(z_root());
@@ -94,3 +93,4 @@ function openid_content(&$a) {
 	goaway(z_root());
 	// NOTREACHED
 }
+}
diff --git a/mod/opensearch.php b/mod/opensearch.php
index ff748d1c53..f3d55a1029 100644
--- a/mod/opensearch.php
+++ b/mod/opensearch.php
@@ -1,18 +1,18 @@
 <?php
-    function opensearch_content(&$a) {
-    	
+if(! function_exists('opensearch_content')) {
+  function opensearch_content(&$a) {
 		$tpl = get_markup_template('opensearch.tpl');
-	
+
 		header("Content-type: application/opensearchdescription+xml");
-	
+
 		$o = replace_macros($tpl, array(
 			'$baseurl' => $a->get_baseurl(),
 			'$nodename' => $a->get_hostname(),
 		));
-		
+
 		echo $o;
-		
+
 		killme();
-		
 	}
-?>
\ No newline at end of file
+}
+?>
diff --git a/mod/ostatus_subscribe.php b/mod/ostatus_subscribe.php
index 6cca0bf679..a21436db49 100644
--- a/mod/ostatus_subscribe.php
+++ b/mod/ostatus_subscribe.php
@@ -3,6 +3,7 @@
 require_once('include/Scrape.php');
 require_once('include/follow.php');
 
+if(! function_exists('ostatus_subscribe_content')) {
 function ostatus_subscribe_content(&$a) {
 
 	if(! local_user()) {
@@ -76,3 +77,4 @@ function ostatus_subscribe_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/p.php b/mod/p.php
index 92b72dc1ce..225b831fea 100644
--- a/mod/p.php
+++ b/mod/p.php
@@ -4,7 +4,8 @@ This file is part of the Diaspora protocol. It is used for fetching single publi
 */
 require_once("include/diaspora.php");
 
-function p_init($a){
+if(! function_exists('p_init')) {
+function p_init($a) {
 	if ($a->argc != 2) {
 		header($_SERVER["SERVER_PROTOCOL"].' 510 '.t('Not Extended'));
 		killme();
@@ -79,3 +80,4 @@ function p_init($a){
 
 	killme();
 }
+}
diff --git a/mod/parse_url.php b/mod/parse_url.php
index a1ca5a3db5..481cb89361 100644
--- a/mod/parse_url.php
+++ b/mod/parse_url.php
@@ -1,14 +1,14 @@
 <?php
-/** 
+/**
  * @file mod/parse_url.php
- * 
+ *
  * @todo https://developers.google.com/+/plugins/snippet/
- * 
+ *
  * @verbatim
  * <meta itemprop="name" content="Toller Titel">
  * <meta itemprop="description" content="Eine tolle Beschreibung">
  * <meta itemprop="image" content="http://maple.libertreeproject.org/images/tree-icon.png">
- * 
+ *
  * <body itemscope itemtype="http://schema.org/Product">
  *   <h1 itemprop="name">Shiny Trinket</h1>
  *   <img itemprop="image" src="{image-url}" />
@@ -27,6 +27,7 @@ if(!function_exists('deletenode')) {
 	}
 }
 
+if(! function_exists('completeurl')) {
 function completeurl($url, $scheme) {
 	$urlarr = parse_url($url);
 
@@ -53,7 +54,9 @@ function completeurl($url, $scheme) {
 
 	return($complete);
 }
+}
 
+if(! function_exists('parseurl_getsiteinfo_cached')) {
 function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = true) {
 
 	if ($url == "")
@@ -77,7 +80,9 @@ function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = tr
 
 	return $data;
 }
+}
 
+if(! function_exists('parseurl_getsiteinfo')) {
 function parseurl_getsiteinfo($url, $no_guessing = false, $do_oembed = true, $count = 1) {
 	require_once("include/network.php");
 	require_once("include/Photo.php");
@@ -400,11 +405,15 @@ function parseurl_getsiteinfo($url, $no_guessing = false, $do_oembed = true, $co
 
 	return($siteinfo);
 }
+}
 
+if(! function_exists('arr_add_hashes')) {
 function arr_add_hashes(&$item,$k) {
 	$item = '#' . $item;
 }
+}
 
+if(! function_exists('parse_url_content')) {
 function parse_url_content(&$a) {
 
 	$text = null;
@@ -558,4 +567,5 @@ function parse_url_content(&$a) {
 
 	killme();
 }
+}
 ?>
diff --git a/mod/photo.php b/mod/photo.php
index 4166b4d539..3baff13db5 100644
--- a/mod/photo.php
+++ b/mod/photo.php
@@ -3,6 +3,7 @@
 require_once('include/security.php');
 require_once('include/Photo.php');
 
+if(! function_exists('photo_init')) {
 function photo_init(&$a) {
 	global $_SERVER;
 
@@ -209,3 +210,4 @@ function photo_init(&$a) {
 	killme();
 	// NOTREACHED
 }
+}
diff --git a/mod/photos.php b/mod/photos.php
index a9dade6a81..9821918e5e 100644
--- a/mod/photos.php
+++ b/mod/photos.php
@@ -9,6 +9,7 @@ require_once('include/redir.php');
 require_once('include/tags.php');
 require_once('include/threads.php');
 
+if(! function_exists('photos_init')) {
 function photos_init(&$a) {
 
 	if($a->argc > 1)
@@ -121,9 +122,9 @@ function photos_init(&$a) {
 
 	return;
 }
+}
 
-
-
+if(! function_exists('photos_post')) {
 function photos_post(&$a) {
 
 	logger('mod-photos: photos_post: begin' , LOGGER_DEBUG);
@@ -957,9 +958,9 @@ function photos_post(&$a) {
 	goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
 	// NOTREACHED
 }
+}
 
-
-
+if(! function_exists('photos_content')) {
 function photos_content(&$a) {
 
 	// URLs:
@@ -1328,7 +1329,7 @@ function photos_content(&$a) {
 
 	}
 
-	/** 
+	/**
 	 * Display one photo
 	 */
 
@@ -1861,7 +1862,7 @@ function photos_content(&$a) {
 			//hide profile photos to others
 			if((! $is_owner) && (! remote_user()) && ($rr['album'] == t('Profile Photos')))
 					continue;
-			
+
 			if($twist == 'rotright')
 				$twist = 'rotleft';
 			else
@@ -1906,4 +1907,4 @@ function photos_content(&$a) {
 	$o .= paginate($a);
 	return $o;
 }
-
+}
diff --git a/mod/ping.php b/mod/ping.php
index 57728d3294..dbc000a8a5 100644
--- a/mod/ping.php
+++ b/mod/ping.php
@@ -5,6 +5,7 @@ require_once('include/forums.php');
 require_once('include/group.php');
 require_once("mod/proxy.php");
 
+if(! function_exists('ping_init')) {
 function ping_init(&$a) {
 
 	header("Content-type: text/xml");
@@ -338,7 +339,9 @@ function ping_init(&$a) {
 
 	killme();
 }
+}
 
+if(! function_exists('ping_get_notifications')) {
 function ping_get_notifications($uid) {
 
 	$result = array();
@@ -406,3 +409,4 @@ function ping_get_notifications($uid) {
 
 	return($result);
 }
+}
diff --git a/mod/poco.php b/mod/poco.php
index 0a1b392169..4b04d70138 100644
--- a/mod/poco.php
+++ b/mod/poco.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('poco_init')) {
 function poco_init(&$a) {
 	require_once("include/bbcode.php");
 
@@ -324,5 +325,5 @@ function poco_init(&$a) {
 	else
 		http_status_exit(500);
 
-
+}
 }
diff --git a/mod/poke.php b/mod/poke.php
index 45a577cda6..1af78b68ed 100644
--- a/mod/poke.php
+++ b/mod/poke.php
@@ -4,11 +4,11 @@
  *
  * Poke, prod, finger, or otherwise do unspeakable things to somebody - who must be a connection in your address book
  * This function can be invoked with the required arguments (verb and cid and private and possibly parent) silently via ajax or
- * other web request. You must be logged in and connected to a profile. 
+ * other web request. You must be logged in and connected to a profile.
  * If the required arguments aren't present, we'll display a simple form to choose a recipient and a verb.
  * parent is a special argument which let's you attach this activity as a comment to an existing conversation, which
  * may have started with somebody else poking (etc.) somebody, but this isn't necessary. This can be used in the more pokes
- * plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.  
+ * plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.
  *
  * private creates a private conversation with the recipient. Otherwise your profile's default post privacy is used.
  *
@@ -18,7 +18,7 @@ require_once('include/security.php');
 require_once('include/bbcode.php');
 require_once('include/items.php');
 
-
+if(! function_exists('poke_init')) {
 function poke_init(&$a) {
 
 	if(! local_user())
@@ -140,9 +140,9 @@ function poke_init(&$a) {
 
 	return;
 }
+}
 
-
-
+if(! function_exists('poke_content')) {
 function poke_content(&$a) {
 
 	if(! local_user()) {
@@ -201,5 +201,5 @@ function poke_content(&$a) {
 	));
 
 	return $o;
-
+}
 }
diff --git a/mod/post.php b/mod/post.php
index c0e783a6aa..631bf0eba6 100644
--- a/mod/post.php
+++ b/mod/post.php
@@ -9,7 +9,8 @@ require_once('include/salmon.php');
 require_once('include/crypto.php');
 // not yet ready for prime time
 //require_once('include/zot.php');
-	
+
+if(! function_exists('post_post')) {
 function post_post(&$a) {
 
 	$bulk_delivery = false;
@@ -19,7 +20,7 @@ function post_post(&$a) {
 	}
 	else {
 		$nickname = $a->argv[2];
-		$r = q("SELECT * FROM `user` WHERE `nickname` = '%s' 
+		$r = q("SELECT * FROM `user` WHERE `nickname` = '%s'
 				AND `account_expired` = 0 AND `account_removed` = 0 LIMIT 1",
 			dbesc($nickname)
 		);
@@ -48,4 +49,4 @@ function post_post(&$a) {
 	http_status_exit(($ret) ? $ret : 200);
 	// NOTREACHED
 }
-
+}
diff --git a/mod/pretheme.php b/mod/pretheme.php
index 4584cb29e2..5d1c261fcb 100644
--- a/mod/pretheme.php
+++ b/mod/pretheme.php
@@ -1,7 +1,8 @@
 <?php
 
+if(! function_exists('pretheme_init')) {
 function pretheme_init(&$a) {
-	
+
 	if($_REQUEST['theme']) {
 		$theme = $_REQUEST['theme'];
 		$info = get_theme_info($theme);
@@ -20,3 +21,4 @@ function pretheme_init(&$a) {
 	}
 	killme();
 }
+}
diff --git a/mod/probe.php b/mod/probe.php
index c95db291b3..fcf83e7603 100644
--- a/mod/probe.php
+++ b/mod/probe.php
@@ -2,13 +2,14 @@
 
 require_once('include/Scrape.php');
 
+if(! function_exists('probe_content')) {
 function probe_content(&$a) {
 
 	$o .= '<h3>Probe Diagnostic</h3>';
 
 	$o .= '<form action="probe" method="get">';
 	$o .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />';
-	$o .= '<input type="submit" name="submit" value="Submit" /></form>'; 
+	$o .= '<input type="submit" name="submit" value="Submit" /></form>';
 
 	$o .= '<br /><br />';
 
@@ -22,3 +23,4 @@ function probe_content(&$a) {
 	}
 	return $o;
 }
+}
diff --git a/mod/profile.php b/mod/profile.php
index 26bd395230..b02570d5af 100644
--- a/mod/profile.php
+++ b/mod/profile.php
@@ -3,7 +3,7 @@
 require_once('include/contact_widgets.php');
 require_once('include/redir.php');
 
-
+if(! function_exists('profile_init')) {
 function profile_init(&$a) {
 
 	if(! x($a->page,'aside'))
@@ -65,10 +65,10 @@ function profile_init(&$a) {
 	foreach($dfrn_pages as $dfrn)
 		$a->page['htmlhead'] .= "<link rel=\"dfrn-{$dfrn}\" href=\"".$a->get_baseurl()."/dfrn_{$dfrn}/{$which}\" />\r\n";
 	$a->page['htmlhead'] .= "<link rel=\"dfrn-poco\" href=\"".$a->get_baseurl()."/poco/{$which}\" />\r\n";
-
+}
 }
 
-
+if(! function_exists('profile_content')) {
 function profile_content(&$a, $update = 0) {
 
 	$category = $datequery = $datequery2 = '';
@@ -350,3 +350,4 @@ function profile_content(&$a, $update = 0) {
 
 	return $o;
 }
+}
diff --git a/mod/profile_photo.php b/mod/profile_photo.php
index 4e8d279a97..e3d6adb491 100644
--- a/mod/profile_photo.php
+++ b/mod/profile_photo.php
@@ -2,6 +2,7 @@
 
 require_once("include/Photo.php");
 
+if(! function_exists('profile_photo_init')) {
 function profile_photo_init(&$a) {
 
 	if(! local_user()) {
@@ -9,10 +10,10 @@ function profile_photo_init(&$a) {
 	}
 
 	profile_load($a,$a->user['nickname']);
-
+}
 }
 
-
+if(! function_exists('profile_photo_post')) {
 function profile_photo_post(&$a) {
 
 	if(! local_user()) {
@@ -143,7 +144,7 @@ function profile_photo_post(&$a) {
 	$filesize = intval($_FILES['userfile']['size']);
 	$filetype = $_FILES['userfile']['type'];
     if ($filetype=="") $filetype=guess_image_type($filename);
-    
+
 	$maximagesize = get_config('system','maximagesize');
 
 	if(($maximagesize) && ($filesize > $maximagesize)) {
@@ -164,7 +165,7 @@ function profile_photo_post(&$a) {
 	$ph->orient($src);
 	@unlink($src);
 	return profile_photo_crop_ui_head($a, $ph);
-	
+}
 }
 
 
@@ -175,7 +176,7 @@ function profile_photo_content(&$a) {
 		notice( t('Permission denied.') . EOL );
 		return;
 	}
-	
+
 	$newuser = false;
 
 	if($a->argc == 2 && $a->argv[1] === 'new')
@@ -186,9 +187,9 @@ function profile_photo_content(&$a) {
 			notice( t('Permission denied.') . EOL );
 			return;
 		};
-		
+
 //		check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
-        
+
 		$resource_id = $a->argv[2];
 		//die(":".local_user());
 		$r=q("SELECT * FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' ORDER BY `scale` ASC",
@@ -240,7 +241,7 @@ function profile_photo_content(&$a) {
 
 
 	if(! x($a->config,'imagecrop')) {
-	
+
 		$tpl = get_markup_template('profile_photo.tpl');
 
 		$o .= replace_macros($tpl,array(
@@ -295,11 +296,11 @@ function profile_photo_crop_ui_head(&$a, $ph){
 	}
 
 	$hash = photo_new_resource();
-	
+
 
 	$smallest = 0;
 
-	$r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 0 );	
+	$r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 0 );
 
 	if($r)
 		info( t('Image uploaded successfully.') . EOL );
@@ -308,8 +309,8 @@ function profile_photo_crop_ui_head(&$a, $ph){
 
 	if($width > 640 || $height > 640) {
 		$ph->scaleImage(640);
-		$r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 1 );	
-		
+		$r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 1 );
+
 		if($r === false)
 			notice( sprintf(t('Image size reduction [%s] failed.'),"640") . EOL );
 		else
@@ -323,4 +324,3 @@ function profile_photo_crop_ui_head(&$a, $ph){
 	$a->page['end'] .= replace_macros(get_markup_template("cropend.tpl"), array());
 	return;
 }}
-
diff --git a/mod/profiles.php b/mod/profiles.php
index 5c372de8ee..9ce478ba19 100644
--- a/mod/profiles.php
+++ b/mod/profiles.php
@@ -1,6 +1,7 @@
 <?php
 require_once("include/Contact.php");
 
+if(! function_exists('profiles_init')) {
 function profiles_init(&$a) {
 
 	nav_set_selected('profiles');
@@ -139,9 +140,10 @@ function profiles_init(&$a) {
 	}
 
 
-
+}
 }
 
+if(! function_exists('profile_clean_keywords')) {
 function profile_clean_keywords($keywords) {
 	$keywords = str_replace(","," ",$keywords);
 	$keywords = explode(" ", $keywords);
@@ -158,7 +160,9 @@ function profile_clean_keywords($keywords) {
 
 	return $keywords;
 }
+}
 
+if(! function_exists('profiles_post')) {
 function profiles_post(&$a) {
 
 	if(! local_user()) {
@@ -502,8 +506,9 @@ function profiles_post(&$a) {
 		}
 	}
 }
+}
 
-
+if(! function_exists('profile_activity')) {
 function profile_activity($changed, $value) {
 	$a = get_app();
 
@@ -593,8 +598,9 @@ function profile_activity($changed, $value) {
 
 	}
 }
+}
 
-
+if(! function_exists('profiles_content')) {
 function profiles_content(&$a) {
 
 	if(! local_user()) {
@@ -818,5 +824,5 @@ function profiles_content(&$a) {
 		}
 		return $o;
 	}
-
+}
 }
diff --git a/mod/profperm.php b/mod/profperm.php
index 077f695bea..6fb7172949 100644
--- a/mod/profperm.php
+++ b/mod/profperm.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('profperm_init')) {
 function profperm_init(&$a) {
 
 	if(! local_user())
@@ -9,10 +10,10 @@ function profperm_init(&$a) {
 	$profile = $a->argv[1];
 
 	profile_load($a,$which,$profile);
-
+}
 }
 
-
+if(! function_exists('profperm_content')) {
 function profperm_content(&$a) {
 
 	if(! local_user()) {
@@ -108,9 +109,9 @@ function profperm_content(&$a) {
 	}
 
 	$o .= '<div id="prof-update-wrapper">';
-	if($change) 
+	if($change)
 		$o = '';
-	
+
 	$o .= '<div id="prof-members-title">';
 	$o .= '<h3>' . t('Visible To') . '</h3>';
 	$o .= '</div>';
@@ -156,6 +157,5 @@ function profperm_content(&$a) {
 	}
 	$o .= '</div>';
 	return $o;
-
 }
-
+}
diff --git a/mod/proxy.php b/mod/proxy.php
index abcaf49127..8e2a389254 100644
--- a/mod/proxy.php
+++ b/mod/proxy.php
@@ -12,6 +12,7 @@ define("PROXY_SIZE_LARGE", "large");
 require_once('include/security.php');
 require_once("include/Photo.php");
 
+if(! function_exists('proxy_init')) {
 function proxy_init() {
 	global $a, $_SERVER;
 
@@ -232,7 +233,9 @@ function proxy_init() {
 
 	killme();
 }
+}
 
+if(! function_exists('proxy_url')) {
 function proxy_url($url, $writemode = false, $size = "") {
 	global $_SERVER;
 
@@ -294,11 +297,13 @@ function proxy_url($url, $writemode = false, $size = "") {
 	else
 		return ($proxypath.$size);
 }
+}
 
 /**
  * @param $url string
  * @return boolean
  */
+if(! function_exists('proxy_is_local_image')) {
 function proxy_is_local_image($url) {
 	if ($url[0] == '/') return true;
 
@@ -309,7 +314,9 @@ function proxy_is_local_image($url) {
 	$url = normalise_link($url);
 	return (substr($url, 0, strlen($baseurl)) == $baseurl);
 }
+}
 
+if(! function_exists('proxy_parse_query')) {
 function proxy_parse_query($var) {
         /**
          *  Use this function to parse out the query array element from
@@ -328,7 +335,9 @@ function proxy_parse_query($var) {
         unset($val, $x, $var);
         return $arr;
 }
+}
 
+if(! function_exists('proxy_img_cb')) {
 function proxy_img_cb($matches) {
 
 	// if the picture seems to be from another picture cache then take the original source
@@ -342,10 +351,13 @@ function proxy_img_cb($matches) {
 
 	return $matches[1].proxy_url(htmlspecialchars_decode($matches[2])).$matches[3];
 }
+}
 
+if(! function_exists('proxy_parse_html')) {
 function proxy_parse_html($html) {
 	$a = get_app();
 	$html = str_replace(normalise_link($a->get_baseurl())."/", $a->get_baseurl()."/", $html);
 
 	return preg_replace_callback("/(<img [^>]*src *= *[\"'])([^\"']+)([\"'][^>]*>)/siU", "proxy_img_cb", $html);
 }
+}
diff --git a/mod/pubsub.php b/mod/pubsub.php
index beb73b4e2c..15523e637a 100644
--- a/mod/pubsub.php
+++ b/mod/pubsub.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('hub_return')) {
 function hub_return($valid,$body) {
 
 	if($valid) {
@@ -14,18 +15,18 @@ function hub_return($valid,$body) {
 
 	// NOTREACHED
 }
+}
 
 // when receiving an XML feed, always return OK
-
+if(! function_exists('hub_post_return')) {
 function hub_post_return() {
-
 	header($_SERVER["SERVER_PROTOCOL"] . ' 200 ' . 'OK');
 	killme();
-
+}
 }
 
 
-
+if(! function_exists('pubsub_init')) {
 function pubsub_init(&$a) {
 
 	$nick       = (($a->argc > 1) ? notags(trim($a->argv[1])) : '');
@@ -57,7 +58,7 @@ function pubsub_init(&$a) {
 
 		$sql_extra = ((strlen($hub_verify)) ? sprintf(" AND `hub-verify` = '%s' ", dbesc($hub_verify)) : '');
 
-		$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d 
+		$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d
 			AND `blocked` = 0 AND `pending` = 0 $sql_extra LIMIT 1",
 			intval($contact_id),
 			intval($owner['uid'])
@@ -75,7 +76,7 @@ function pubsub_init(&$a) {
 
 		$contact = $r[0];
 
-		// We must initiate an unsubscribe request with a verify_token. 
+		// We must initiate an unsubscribe request with a verify_token.
 		// Don't allow outsiders to unsubscribe us.
 
 		if($hub_mode === 'unsubscribe') {
@@ -95,9 +96,11 @@ function pubsub_init(&$a) {
  		hub_return(true, $hub_challenge);
 	}
 }
+}
 
 require_once('include/security.php');
 
+if(! function_exists('pubsub_post')) {
 function pubsub_post(&$a) {
 
 	$xml = file_get_contents('php://input');
@@ -155,8 +158,5 @@ function pubsub_post(&$a) {
 	consume_feed($xml,$importer,$contact,$feedhub,1,2);
 
 	hub_post_return();
-
 }
-
-
-
+}
diff --git a/mod/pubsubhubbub.php b/mod/pubsubhubbub.php
index 5d7621cc74..b0e3ef3099 100644
--- a/mod/pubsubhubbub.php
+++ b/mod/pubsubhubbub.php
@@ -1,9 +1,12 @@
 <?php
 
+if(! function_exists('post_var')) {
 function post_var($name) {
 	return (x($_POST, $name)) ? notags(trim($_POST[$name])) : '';
 }
+}
 
+if(! function_exists('pubsubhubbub_init')) {
 function pubsubhubbub_init(&$a) {
 	// PuSH subscription must be considered "public" so just block it
 	// if public access isn't enabled.
@@ -158,5 +161,5 @@ function pubsubhubbub_init(&$a) {
 
 	killme();
 }
-
+}
 ?>
diff --git a/mod/qsearch.php b/mod/qsearch.php
index c35e253b67..cffc3e50ba 100644
--- a/mod/qsearch.php
+++ b/mod/qsearch.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('qsearch_init')) {
 function qsearch_init(&$a) {
 
 	if(! local_user())
@@ -47,4 +48,4 @@ function qsearch_init(&$a) {
 	echo json_encode((object) $results);
 	killme();
 }
-
+}
diff --git a/mod/randprof.php b/mod/randprof.php
index 6713a81d9e..e9e0a8e7bb 100644
--- a/mod/randprof.php
+++ b/mod/randprof.php
@@ -1,6 +1,6 @@
 <?php
 
-
+if(! function_exists('randprof_init')) {
 function randprof_init(&$a) {
 	require_once('include/Contact.php');
 	$x = random_profile();
@@ -8,3 +8,4 @@ function randprof_init(&$a) {
 		goaway(zrl($x));
 	goaway($a->get_baseurl() . '/profile');
 }
+}
diff --git a/mod/receive.php b/mod/receive.php
index 95a5101675..3a30058cdc 100644
--- a/mod/receive.php
+++ b/mod/receive.php
@@ -9,7 +9,7 @@ require_once('include/salmon.php');
 require_once('include/crypto.php');
 require_once('include/diaspora.php');
 
-
+if(! function_exists('receive_post')) {
 function receive_post(&$a) {
 
 
@@ -73,4 +73,4 @@ function receive_post(&$a) {
 	http_status_exit(($ret) ? $ret : 200);
 	// NOTREACHED
 }
-
+}
diff --git a/mod/redir.php b/mod/redir.php
index 632c395786..2dda0571b2 100644
--- a/mod/redir.php
+++ b/mod/redir.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('redir_init')) {
 function redir_init(&$a) {
 
 	$url = ((x($_GET,'url')) ? $_GET['url'] : '');
@@ -57,9 +58,9 @@ function redir_init(&$a) {
 			intval(time() + 45)
 		);
 
-		logger('mod_redir: ' . $r[0]['name'] . ' ' . $sec, LOGGER_DEBUG); 
+		logger('mod_redir: ' . $r[0]['name'] . ' ' . $sec, LOGGER_DEBUG);
 		$dest = (($url) ? '&destination_url=' . $url : '');
-		goaway ($r[0]['poll'] . '?dfrn_id=' . $dfrn_id 
+		goaway ($r[0]['poll'] . '?dfrn_id=' . $dfrn_id
 			. '&dfrn_version=' . DFRN_PROTOCOL_VERSION . '&type=profile&sec=' . $sec . $dest . $quiet );
 	}
 
@@ -75,3 +76,4 @@ function redir_init(&$a) {
 
 	goaway(z_root());
 }
+}
diff --git a/mod/regmod.php b/mod/regmod.php
index 5a90db1f90..2e3ca414e3 100644
--- a/mod/regmod.php
+++ b/mod/regmod.php
@@ -3,6 +3,7 @@
 require_once('include/enotify.php');
 require_once('include/user.php');
 
+if(! function_exists('user_allow')) {
 function user_allow($hash) {
 
 	$a = get_app();
@@ -55,14 +56,14 @@ function user_allow($hash) {
 		info( t('Account approved.') . EOL );
 		return true;
 	}
-
+}
 }
 
 
 // This does not have to go through user_remove() and save the nickname
 // permanently against re-registration, as the person was not yet
 // allowed to have friends on this system
-
+if(! function_exists('user_deny')) {
 function user_deny($hash) {
 
 	$register = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1",
@@ -91,9 +92,10 @@ function user_deny($hash) {
 	);
 	notice( sprintf(t('Registration revoked for %s'), $user[0]['username']) . EOL);
 	return true;
-
+}
 }
 
+if(! function_exists('regmod_content')) {
 function regmod_content(&$a) {
 
 	global $lang;
@@ -131,3 +133,4 @@ function regmod_content(&$a) {
 		killme();
 	}
 }
+}
diff --git a/mod/removeme.php b/mod/removeme.php
index 904606fd57..6c84c41892 100644
--- a/mod/removeme.php
+++ b/mod/removeme.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('removeme_post')) {
 function removeme_post(&$a) {
 
 	if(! local_user())
@@ -24,9 +25,10 @@ function removeme_post(&$a) {
 		user_remove($a->user['uid']);
 		// NOTREACHED
 	}
-
+}
 }
 
+if(! function_exists('removeme_content')) {
 function removeme_content(&$a) {
 
 	if(! local_user())
@@ -50,5 +52,5 @@ function removeme_content(&$a) {
 	));
 
 	return $o;
-
+}
 }
diff --git a/mod/repair_ostatus.php b/mod/repair_ostatus.php
index 2b1224f423..e3956ba8cb 100755
--- a/mod/repair_ostatus.php
+++ b/mod/repair_ostatus.php
@@ -3,6 +3,7 @@
 require_once('include/Scrape.php');
 require_once('include/follow.php');
 
+if(! function_exists('repair_ostatus_content')) {
 function repair_ostatus_content(&$a) {
 
 	if(! local_user()) {
@@ -55,3 +56,4 @@ function repair_ostatus_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/rsd_xml.php b/mod/rsd_xml.php
index f4984f0f0f..6f9c209fab 100644
--- a/mod/rsd_xml.php
+++ b/mod/rsd_xml.php
@@ -1,7 +1,6 @@
 <?php
 
-
-
+if(! function_exists('rsd_xml_content')) {
 function rsd_xml_content(&$a) {
 	header ("Content-Type: text/xml");
 	echo '<?xml version="1.0" encoding="UTF-8"?>
@@ -21,4 +20,5 @@ function rsd_xml_content(&$a) {
  </rsd>
 	';
 die();
-}
\ No newline at end of file
+}
+}
diff --git a/mod/salmon.php b/mod/salmon.php
index 9c22e42d11..ee3826d8a8 100644
--- a/mod/salmon.php
+++ b/mod/salmon.php
@@ -6,6 +6,7 @@ require_once('include/crypto.php');
 require_once('include/items.php');
 require_once('include/follow.php');
 
+if(! function_exists('salmon_return')) {
 function salmon_return($val) {
 
 	if($val >= 400)
@@ -16,9 +17,10 @@ function salmon_return($val) {
 	logger('mod-salmon returns ' . $val);
 	header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $err);
 	killme();
-
+}
 }
 
+if(! function_exists('salmon_post')) {
 function salmon_post(&$a) {
 
 	$xml = file_get_contents('php://input');
@@ -155,7 +157,7 @@ function salmon_post(&$a) {
 		if(get_pconfig($importer['uid'],'system','ostatus_autofriend')) {
 			$result = new_contact($importer['uid'],$author_link);
 			if($result['success']) {
-				$r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND ( `url` = '%s' OR `alias` = '%s') 
+				$r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND ( `url` = '%s' OR `alias` = '%s')
 					AND `uid` = %d LIMIT 1",
 					dbesc(NETWORK_OSTATUS),
 					dbesc($author_link),
@@ -185,3 +187,4 @@ function salmon_post(&$a) {
 
 	http_status_exit(200);
 }
+}
diff --git a/mod/search.php b/mod/search.php
index 7c78339c70..431bd821d6 100644
--- a/mod/search.php
+++ b/mod/search.php
@@ -4,6 +4,7 @@ require_once('include/security.php');
 require_once('include/conversation.php');
 require_once('mod/dirfind.php');
 
+if(! function_exists('search_saved_searches')) {
 function search_saved_searches() {
 
 	$o = '';
@@ -39,10 +40,10 @@ function search_saved_searches() {
 	}
 
 	return $o;
-
+}
 }
 
-
+if(! function_exists('search_init')) {
 function search_init(&$a) {
 
 	$search = ((x($_GET,'search')) ? notags(trim(rawurldecode($_GET['search']))) : '');
@@ -76,17 +77,18 @@ function search_init(&$a) {
 	}
 
 
-
+}
 }
 
 
-
+if(! function_exists('search_post')) {
 function search_post(&$a) {
 	if(x($_POST,'search'))
 		$a->data['search'] = $_POST['search'];
 }
+}
 
-
+if(! function_exists('search_content')) {
 function search_content(&$a) {
 
 	if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
@@ -248,4 +250,4 @@ function search_content(&$a) {
 
 	return $o;
 }
-
+}
diff --git a/mod/session.php b/mod/session.php
index 22c855edba..ac3d885b63 100644
--- a/mod/session.php
+++ b/mod/session.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('session_content')) {
 function session_content(&$a) {
-
+}
 }
diff --git a/mod/settings.php b/mod/settings.php
index 3efdbf6bde..1b62499c22 100644
--- a/mod/settings.php
+++ b/mod/settings.php
@@ -1,7 +1,7 @@
 <?php
 
-
-function get_theme_config_file($theme){
+if(! function_exists('get_theme_config_file')) {
+function get_theme_config_file($theme) {
 	$a = get_app();
 	$base_theme = $a->theme_info['extends'];
 
@@ -13,7 +13,9 @@ function get_theme_config_file($theme){
 	}
 	return null;
 }
+}
 
+if(! function_exists('settings_init')) {
 function settings_init(&$a) {
 
 	if(! local_user()) {
@@ -110,10 +112,10 @@ function settings_init(&$a) {
 		'$class' => 'settings-widget',
 		'$items' => $tabs,
 	));
-
+}
 }
 
-
+if(! function_exists('settings_post')) {
 function settings_post(&$a) {
 
 	if(! local_user())
@@ -630,8 +632,9 @@ function settings_post(&$a) {
 	goaway($a->get_baseurl(true) . '/settings' );
 	return; // NOTREACHED
 }
+}
 
-
+if(! function_exists('settings_content')) {
 function settings_content(&$a) {
 
 	$o = '';
@@ -1295,6 +1298,5 @@ function settings_content(&$a) {
 	$o .= '</form>' . "\r\n";
 
 	return $o;
-
 }
-
+}
diff --git a/mod/share.php b/mod/share.php
index 085da4e30d..f3a221eb8e 100644
--- a/mod/share.php
+++ b/mod/share.php
@@ -1,12 +1,14 @@
 <?php
+
+if(! function_exists('share_init')) {
 function share_init(&$a) {
 
 	$post_id = (($a->argc > 1) ? intval($a->argv[1]) : 0);
 	if((! $post_id) || (! local_user()))
 		killme();
 
-	$r = q("SELECT item.*, contact.network FROM `item` 
-		inner join contact on `item`.`contact-id` = `contact`.`id` 
+	$r = q("SELECT item.*, contact.network FROM `item`
+		inner join contact on `item`.`contact-id` = `contact`.`id`
 		WHERE `item`.`id` = %d AND `item`.`uid` = %d LIMIT 1",
 
 		intval($post_id),
@@ -40,7 +42,9 @@ function share_init(&$a) {
 	echo $o;
 	killme();
 }
+}
 
+if(! function_exists('share_header')) {
 function share_header($author, $profile, $avatar, $guid, $posted, $link) {
 	$header = "[share author='".str_replace(array("'", "[", "]"), array("&#x27;", "&#x5B;", "&#x5D;"),$author).
 		"' profile='".str_replace(array("'", "[", "]"), array("&#x27;", "&#x5B;", "&#x5D;"),$profile).
@@ -56,3 +60,4 @@ function share_header($author, $profile, $avatar, $guid, $posted, $link) {
 
 	return $header;
 }
+}
diff --git a/mod/smilies.php b/mod/smilies.php
index c47f95da76..4d498b6746 100644
--- a/mod/smilies.php
+++ b/mod/smilies.php
@@ -1,3 +1,7 @@
 <?php
 
-function smilies_content(&$a) { return smilies('',true); }
+if(! function_exists('smilies_content')) {
+function smilies_content(&$a) {
+  return smilies('',true);
+}
+}
diff --git a/mod/starred.php b/mod/starred.php
index 2a89ac768b..b4cc326787 100644
--- a/mod/starred.php
+++ b/mod/starred.php
@@ -1,6 +1,6 @@
 <?php
 
-
+if(! function_exists('starred_init')) {
 function starred_init(&$a) {
 
 	require_once("include/threads.php");
@@ -47,3 +47,4 @@ function starred_init(&$a) {
 	echo json_encode($starred);
 	killme();
 }
+}
diff --git a/mod/statistics_json.php b/mod/statistics_json.php
index 21a9a0521c..98cc708d26 100644
--- a/mod/statistics_json.php
+++ b/mod/statistics_json.php
@@ -5,6 +5,7 @@
 
 require_once("include/plugin.php");
 
+if(! function_exists('statistics_json_init')) {
 function statistics_json_init(&$a) {
 
         if (!get_config("system", "nodeinfo")) {
@@ -57,3 +58,4 @@ function statistics_json_init(&$a) {
 	logger("statistics_init: printed ".print_r($statistics, true), LOGGER_DATA);
 	killme();
 }
+}
diff --git a/mod/subthread.php b/mod/subthread.php
index 1486a33b42..6cbaa1d2a7 100644
--- a/mod/subthread.php
+++ b/mod/subthread.php
@@ -4,7 +4,7 @@ require_once('include/security.php');
 require_once('include/bbcode.php');
 require_once('include/items.php');
 
-
+if(! function_exists('subthread_content')) {
 function subthread_content(&$a) {
 
 	if(! local_user() && ! remote_user()) {
@@ -47,7 +47,7 @@ function subthread_content(&$a) {
 			$remote_owner = $r[0];
 	}
 
-	// this represents the post owner on this system. 
+	// this represents the post owner on this system.
 
 	$r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
 		WHERE `contact`.`self` = 1 AND `contact`.`uid` = %d LIMIT 1",
@@ -103,7 +103,7 @@ EOT;
 	$bodyverb = t('%1$s is following %2$s\'s %3$s');
 
 	if(! isset($bodyverb))
-			return; 
+			return;
 
 	$arr = array();
 
@@ -123,7 +123,7 @@ EOT;
 	$arr['author-name'] = $contact['name'];
 	$arr['author-link'] = $contact['url'];
 	$arr['author-avatar'] = $contact['thumb'];
-	
+
 	$ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
 	$alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]';
 	$plink = '[url=' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . ']' . $post_type . '[/url]';
@@ -154,7 +154,5 @@ EOT;
 	call_hooks('post_local_end', $arr);
 
 	killme();
-
 }
-
-
+}
diff --git a/mod/suggest.php b/mod/suggest.php
index b73c2cd1b6..8f5f4f6a12 100644
--- a/mod/suggest.php
+++ b/mod/suggest.php
@@ -3,7 +3,7 @@
 require_once('include/socgraph.php');
 require_once('include/contact_widgets.php');
 
-
+if(! function_exists('suggest_init')) {
 function suggest_init(&$a) {
 	if(! local_user())
 		return;
@@ -42,13 +42,13 @@ function suggest_init(&$a) {
 			);
 		}
 	}
-
+}
 }
 
 
 
 
-
+if(! function_exists('suggest_content')) {
 function suggest_content(&$a) {
 
 	require_once("mod/proxy.php");
@@ -110,8 +110,9 @@ function suggest_content(&$a) {
 	$o .= replace_macros($tpl,array(
 		'$title' => t('Friend Suggestions'),
 		'$contacts' => $entries,
-		
+
 	));
 
 	return $o;
 }
+}
diff --git a/mod/tagger.php b/mod/tagger.php
index 2c469a58bb..bee37015ea 100644
--- a/mod/tagger.php
+++ b/mod/tagger.php
@@ -4,7 +4,7 @@ require_once('include/security.php');
 require_once('include/bbcode.php');
 require_once('include/items.php');
 
-
+if(! function_exists('tagger_content')) {
 function tagger_content(&$a) {
 
 	if(! local_user() && ! remote_user()) {
@@ -95,7 +95,7 @@ EOT;
 	$bodyverb = t('%1$s tagged %2$s\'s %3$s with %4$s');
 
 	if(! isset($bodyverb))
-			return; 
+			return;
 
 	$termlink = html_entity_decode('&#x2317;') . '[url=' . $a->get_baseurl() . '/search?tag=' . urlencode($term) . ']'. $term . '[/url]';
 
@@ -115,7 +115,7 @@ EOT;
 	$arr['author-name'] = $contact['name'];
 	$arr['author-link'] = $contact['url'];
 	$arr['author-avatar'] = $contact['thumb'];
-	
+
 	$ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
 	$alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]';
 	$plink = '[url=' . $item['plink'] . ']' . $post_type . '[/url]';
@@ -216,5 +216,5 @@ EOT;
 
 	return; // NOTREACHED
 
-
+}
 }
diff --git a/mod/tagrm.php b/mod/tagrm.php
index 176986bc38..70b3ef048f 100644
--- a/mod/tagrm.php
+++ b/mod/tagrm.php
@@ -2,6 +2,7 @@
 
 require_once('include/bbcode.php');
 
+if(! function_exists('tagrm_post')) {
 function tagrm_post(&$a) {
 
 	if(! local_user())
@@ -40,13 +41,13 @@ function tagrm_post(&$a) {
 
 	info( t('Tag removed') . EOL );
 	goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
-	
-	// NOTREACHED
 
+	// NOTREACHED
+}
 }
 
 
-
+if(! function_exists('tagrm_content')) {
 function tagrm_content(&$a) {
 
 	$o = '';
@@ -95,5 +96,5 @@ function tagrm_content(&$a) {
 	$o .= '</form>';
 
 	return $o;
-	
+}
 }
diff --git a/mod/toggle_mobile.php b/mod/toggle_mobile.php
index 00991e44ca..dbf0996bba 100644
--- a/mod/toggle_mobile.php
+++ b/mod/toggle_mobile.php
@@ -1,5 +1,6 @@
 <?php
 
+if(! function_exists('toggle_mobile_init')) {
 function toggle_mobile_init(&$a) {
 
 	if(isset($_GET['off']))
@@ -14,4 +15,4 @@ function toggle_mobile_init(&$a) {
 
 	goaway($address);
 }
-
+}
diff --git a/mod/uexport.php b/mod/uexport.php
index a44620a976..eacf300f3f 100644
--- a/mod/uexport.php
+++ b/mod/uexport.php
@@ -1,6 +1,7 @@
 <?php
 
-function uexport_init(&$a){
+if(! function_exists('uexport_init')) {
+function uexport_init(&$a) {
 	if(! local_user())
 		killme();
 
@@ -55,8 +56,10 @@ function uexport_init(&$a){
 	));
 */
 }
+}
 
-function uexport_content(&$a){
+if(! function_exists('uexport_content')) {
+function uexport_content(&$a) {
 
     if ($a->argc > 1) {
         header("Content-type: application/json");
@@ -86,9 +89,10 @@ function uexport_content(&$a){
         '$options' => $options
     ));
 
-
+}
 }
 
+if(! function_exists('_uexport_multirow')) {
 function _uexport_multirow($query) {
 	$result = array();
 	$r = q($query);
@@ -103,7 +107,9 @@ function _uexport_multirow($query) {
 	}
     return $result;
 }
+}
 
+if(! function_exists('_uexport_row')) {
 function _uexport_row($query) {
 	$result = array();
 	$r = q($query);
@@ -115,9 +121,10 @@ function _uexport_row($query) {
 	}
     return $result;
 }
+}
 
-
-function uexport_account($a){
+if(! function_exists('uexport_account')) {
+function uexport_account($a) {
 
 	$user = _uexport_row(
         sprintf( "SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval(local_user()) )
@@ -153,9 +160,9 @@ function uexport_account($a){
         'version' => FRIENDICA_VERSION,
         'schema' => DB_UPDATE_VERSION,
         'baseurl' => $a->get_baseurl(),
-        'user' => $user, 
-        'contact' => $contact, 
-        'profile' => $profile, 
+        'user' => $user,
+        'contact' => $contact,
+        'profile' => $profile,
         'photo' => $photo,
         'pconfig' => $pconfig,
         'group' => $group,
@@ -164,14 +171,15 @@ function uexport_account($a){
 
     //echo "<pre>"; var_dump(json_encode($output)); killme();
 	echo json_encode($output);
-
+}
 }
 
 /**
  * echoes account data and items as separated json, one per line
  */
+if(! function_exists('uexport_all')) {
 function uexport_all(&$a) {
-    
+
     uexport_account($a);
 	echo "\n";
 
@@ -199,5 +207,5 @@ function uexport_all(&$a) {
 		$output = array('item' => $r);
 		echo json_encode($output)."\n";
 	}
-
+}
 }
diff --git a/mod/uimport.php b/mod/uimport.php
index 7ed5648d9e..942268b0ef 100644
--- a/mod/uimport.php
+++ b/mod/uimport.php
@@ -5,6 +5,7 @@
 
 require_once("include/uimport.php");
 
+if(! function_exists('uimport_post')) {
 function uimport_post(&$a) {
 	switch($a->config['register_policy']) {
         case REGISTER_OPEN:
@@ -27,16 +28,18 @@ function uimport_post(&$a) {
             $verified = 0;
             break;
 	}
-    
+
     if (x($_FILES,'accountfile')){
         /// @TODO Pass $blocked / $verified, send email to admin on REGISTER_APPROVE
         import_account($a, $_FILES['accountfile']);
         return;
     }
 }
+}
 
+if(! function_exists('uimport_content')) {
 function uimport_content(&$a) {
-	
+
 	if((! local_user()) && ($a->config['register_policy'] == REGISTER_CLOSED)) {
 		notice("Permission denied." . EOL);
 		return;
@@ -51,8 +54,8 @@ function uimport_content(&$a) {
 			return;
 		}
 	}
-	
-	
+
+
 	if(x($_SESSION,'theme'))
 		unset($_SESSION['theme']);
 	if(x($_SESSION,'mobile-theme'))
@@ -71,3 +74,4 @@ function uimport_content(&$a) {
         ),
     ));
 }
+}
diff --git a/mod/update_community.php b/mod/update_community.php
index 512629b005..396f4234c0 100644
--- a/mod/update_community.php
+++ b/mod/update_community.php
@@ -4,6 +4,7 @@
 
 require_once('mod/community.php');
 
+if(! function_exists('update_community_content')) {
 function update_community_content(&$a) {
 
 	header("Content-type: text/html");
@@ -29,5 +30,5 @@ function update_community_content(&$a) {
 	echo "</section>";
 	echo "</body></html>\r\n";
 	killme();
-
-}
\ No newline at end of file
+}
+}
diff --git a/mod/update_display.php b/mod/update_display.php
index 25b0f77926..9400cb39a6 100644
--- a/mod/update_display.php
+++ b/mod/update_display.php
@@ -5,6 +5,7 @@
 require_once('mod/display.php');
 require_once('include/group.php');
 
+if(! function_exists('update_display_content')) {
 function update_display_content(&$a) {
 
 	$profile_uid = intval($_GET['p']);
@@ -34,5 +35,5 @@ function update_display_content(&$a) {
 	echo "</section>";
 	echo "</body></html>\r\n";
 	killme();
-
+}
 }
diff --git a/mod/update_network.php b/mod/update_network.php
index 1bf3746575..b2e7abc90c 100644
--- a/mod/update_network.php
+++ b/mod/update_network.php
@@ -5,6 +5,7 @@
 require_once('mod/network.php');
 require_once('include/group.php');
 
+if(! function_exists('update_network_content')) {
 function update_network_content(&$a) {
 
 	$profile_uid = intval($_GET['p']);
@@ -37,5 +38,5 @@ function update_network_content(&$a) {
 	echo "</section>";
 	echo "</body></html>\r\n";
 	killme();
-
+}
 }
diff --git a/mod/update_notes.php b/mod/update_notes.php
index 6b8fff5115..e1e4f1d795 100644
--- a/mod/update_notes.php
+++ b/mod/update_notes.php
@@ -9,6 +9,7 @@
 
 require_once('mod/notes.php');
 
+if(! function_exists('update_notes_content')) {
 function update_notes_content(&$a) {
 
 	$profile_uid = intval($_GET['p']);
@@ -20,8 +21,8 @@ function update_notes_content(&$a) {
 
 	/**
 	 *
-	 * Grab the page inner contents by calling the content function from the profile module directly, 
-	 * but move any image src attributes to another attribute name. This is because 
+	 * Grab the page inner contents by calling the content function from the profile module directly,
+	 * but move any image src attributes to another attribute name. This is because
 	 * some browsers will prefetch all the images for the page even if we don't need them.
 	 * The only ones we need to fetch are those for new page additions, which we'll discover
 	 * on the client side and then swap the image back.
@@ -52,5 +53,5 @@ function update_notes_content(&$a) {
 	echo "</section>";
 	echo "</body></html>\r\n";
 	killme();
-
-}
\ No newline at end of file
+}
+}
diff --git a/mod/update_profile.php b/mod/update_profile.php
index 2492a48ee4..93a94ae0d8 100644
--- a/mod/update_profile.php
+++ b/mod/update_profile.php
@@ -9,6 +9,7 @@
 
 require_once('mod/profile.php');
 
+if(! function_exists('update_profile_content')) {
 function update_profile_content(&$a) {
 
 	$profile_uid = intval($_GET['p']);
@@ -24,8 +25,8 @@ function update_profile_content(&$a) {
 
 	/**
 	 *
-	 * Grab the page inner contents by calling the content function from the profile module directly, 
-	 * but move any image src attributes to another attribute name. This is because 
+	 * Grab the page inner contents by calling the content function from the profile module directly,
+	 * but move any image src attributes to another attribute name. This is because
 	 * some browsers will prefetch all the images for the page even if we don't need them.
 	 * The only ones we need to fetch are those for new page additions, which we'll discover
 	 * on the client side and then swap the image back.
@@ -56,5 +57,5 @@ function update_profile_content(&$a) {
 	echo "</section>";
 	echo "</body></html>\r\n";
 	killme();
-
-}
\ No newline at end of file
+}
+}
diff --git a/mod/videos.php b/mod/videos.php
index bf8d696b60..f9db7b05b1 100644
--- a/mod/videos.php
+++ b/mod/videos.php
@@ -5,7 +5,7 @@ require_once('include/bbcode.php');
 require_once('include/security.php');
 require_once('include/redir.php');
 
-
+if(! function_exists('videos_init')) {
 function videos_init(&$a) {
 
 	if($a->argc > 1)
@@ -102,9 +102,9 @@ function videos_init(&$a) {
 
 	return;
 }
+}
 
-
-
+if(! function_exists('videos_post')) {
 function videos_post(&$a) {
 
 	$owner_uid = $a->data['user']['uid'];
@@ -176,11 +176,11 @@ function videos_post(&$a) {
 	}
 
     goaway($a->get_baseurl() . '/videos/' . $a->data['user']['nickname']);
-
+}
 }
 
 
-
+if(! function_exists('videos_content')) {
 function videos_content(&$a) {
 
 	// URLs (most aren't currently implemented):
@@ -407,4 +407,4 @@ function videos_content(&$a) {
 	$o .= paginate($a);
 	return $o;
 }
-
+}
diff --git a/mod/view.php b/mod/view.php
index 15b3733b3f..a270baeaa1 100644
--- a/mod/view.php
+++ b/mod/view.php
@@ -2,16 +2,18 @@
 /**
  * load view/theme/$current_theme/style.php with friendica contex
  */
- 
-function view_init($a){
+
+if(! function_exists('view_init')) {
+function view_init($a) {
 	header("Content-Type: text/css");
-		
+
 	if ($a->argc == 4){
 		$theme = $a->argv[2];
 		$THEMEPATH = "view/theme/$theme";
 		if(file_exists("view/theme/$theme/style.php"))
 			require_once("view/theme/$theme/style.php");
 	}
-	
+
 	killme();
 }
+}
diff --git a/mod/viewcontacts.php b/mod/viewcontacts.php
index 04520e0d93..acb51f0cb4 100644
--- a/mod/viewcontacts.php
+++ b/mod/viewcontacts.php
@@ -2,6 +2,7 @@
 require_once('include/Contact.php');
 require_once('include/contact_selectors.php');
 
+if(! function_exists('viewcontacts_init')) {
 function viewcontacts_init(&$a) {
 
 	if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
@@ -26,8 +27,9 @@ function viewcontacts_init(&$a) {
 		profile_load($a,$a->argv[1]);
 	}
 }
+}
 
-
+if(! function_exists('viewcontacts_content')) {
 function viewcontacts_content(&$a) {
 	require_once("mod/proxy.php");
 
@@ -121,3 +123,4 @@ function viewcontacts_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/viewsrc.php b/mod/viewsrc.php
index 3fa4eaed53..1203d18fc9 100644
--- a/mod/viewsrc.php
+++ b/mod/viewsrc.php
@@ -1,6 +1,6 @@
 <?php
 
-
+if(! function_exists('viewsrc_content')) {
 function viewsrc_content(&$a) {
 
 	if(! local_user()) {
@@ -16,7 +16,7 @@ function viewsrc_content(&$a) {
 		return;
 	}
 
-	$r = q("SELECT `item`.`body` FROM `item` 
+	$r = q("SELECT `item`.`body` FROM `item`
 		WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
 		and `item`.`moderated` = 0
 		AND `item`.`id` = '%s' LIMIT 1",
@@ -33,4 +33,4 @@ function viewsrc_content(&$a) {
 		}
 	return $o;
 }
-
+}
diff --git a/mod/wall_attach.php b/mod/wall_attach.php
index 68752a0e1f..20e646cb9a 100644
--- a/mod/wall_attach.php
+++ b/mod/wall_attach.php
@@ -3,6 +3,7 @@
 require_once('include/attach.php');
 require_once('include/datetime.php');
 
+if(! function_exists('wall_attach_post')) {
 function wall_attach_post(&$a) {
 
 	$r_json = (x($_GET,'response') && $_GET['response']=='json');
@@ -190,3 +191,4 @@ function wall_attach_post(&$a) {
 	killme();
 	// NOTREACHED
 }
+}
diff --git a/mod/wall_upload.php b/mod/wall_upload.php
index b815348c70..2851807d57 100644
--- a/mod/wall_upload.php
+++ b/mod/wall_upload.php
@@ -2,6 +2,7 @@
 
 require_once('include/Photo.php');
 
+if(! function_exists('wall_upload_post')) {
 function wall_upload_post(&$a, $desktopmode = true) {
 
 	logger("wall upload: starting new upload", LOGGER_DEBUG);
@@ -297,3 +298,4 @@ function wall_upload_post(&$a, $desktopmode = true) {
 	killme();
 	// NOTREACHED
 }
+}
diff --git a/mod/wallmessage.php b/mod/wallmessage.php
index b8859badd3..a01dfd2b9f 100644
--- a/mod/wallmessage.php
+++ b/mod/wallmessage.php
@@ -2,6 +2,7 @@
 
 require_once('include/message.php');
 
+if(! function_exists('wallmessage_post')) {
 function wallmessage_post(&$a) {
 
 	$replyto = get_my_url();
@@ -48,7 +49,7 @@ function wallmessage_post(&$a) {
 	$body = str_replace("\r\n","\n",$body);
 	$body = str_replace("\n\n","\n",$body);
 
-	
+
 	$ret = send_wallmessage($user, $body, $subject, $replyto);
 
 	switch($ret){
@@ -69,10 +70,10 @@ function wallmessage_post(&$a) {
 	}
 
 //	goaway($a->get_baseurl() . '/profile/' . $user['nickname']);
-	
+}
 }
 
-
+if(! function_exists('wallmessage_content')) {
 function wallmessage_content(&$a) {
 
 	if(! get_my_url()) {
@@ -134,9 +135,9 @@ function wallmessage_content(&$a) {
 		'$nickname' => $user['nickname'],
 		'$linkurl' => t('Please enter a link URL:')
 	));
-	
 
-	
+
+
 	$tpl = get_markup_template('wallmessage.tpl');
 	$o .= replace_macros($tpl,array(
 		'$header' => t('Send Private Message'),
@@ -158,3 +159,4 @@ function wallmessage_content(&$a) {
 
 	return $o;
 }
+}
diff --git a/mod/webfinger.php b/mod/webfinger.php
index 74bd2c9543..4024671b02 100644
--- a/mod/webfinger.php
+++ b/mod/webfinger.php
@@ -1,14 +1,13 @@
 <?php
 
-
-
+if(! function_exists('webfinger_content')) {
 function webfinger_content(&$a) {
 
 	$o .= '<h3>Webfinger Diagnostic</h3>';
 
 	$o .= '<form action="webfinger" method="get">';
 	$o .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />';
-	$o .= '<input type="submit" name="submit" value="Submit" /></form>'; 
+	$o .= '<input type="submit" name="submit" value="Submit" /></form>';
 
 	$o .= '<br /><br />';
 
@@ -24,3 +23,4 @@ function webfinger_content(&$a) {
 	}
 	return $o;
 }
+}
diff --git a/mod/xrd.php b/mod/xrd.php
index c23119145c..f8e0a9c409 100644
--- a/mod/xrd.php
+++ b/mod/xrd.php
@@ -2,6 +2,7 @@
 
 require_once('include/crypto.php');
 
+if(! function_exists('xrd_init')) {
 function xrd_init(&$a) {
 
 	$uri = urldecode(notags(trim($_GET['uri'])));
@@ -77,5 +78,5 @@ function xrd_init(&$a) {
 
 	echo $arr['xml'];
 	killme();
-
+}
 }

From 9e3f849e89ce1fdbd195660878f1b10cdeea8248 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 5 Feb 2016 22:12:54 +0100
Subject: [PATCH 048/273] Added documentation

---
 include/dfrn.php | 72 ++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 70 insertions(+), 2 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index e286b75cce..d62d1d57fb 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -1278,6 +1278,15 @@ class dfrn {
 		return($author);
 	}
 
+	/**
+	 * @brief Transforms activity objects into an XML string
+	 *
+	 * @param object $xpath XPath object
+	 * @param object $activity Activity object
+	 * @param text $element element name
+	 *
+	 * @return string XML string
+	 */
 	private function transform_activity($xpath, $activity, $element) {
 		if (!is_object($activity))
 			return "";
@@ -1315,6 +1324,13 @@ class dfrn {
 		return($objxml);
 	}
 
+	/**
+	 * @brief Processes the mail elements
+	 *
+	 * @param object $xpath XPath object
+	 * @param object $mail mail elements
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 */
 	private function process_mail($xpath, $mail, $importer) {
 
 		logger("Processing mails");
@@ -1359,6 +1375,13 @@ class dfrn {
 		logger("Mail is processed, notification was sent.");
 	}
 
+	/**
+	 * @brief Processes the suggestion elements
+	 *
+	 * @param object $xpath XPath object
+	 * @param object $suggestion suggestion elements
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 */
 	private function process_suggestion($xpath, $suggestion, $importer) {
 
 		logger("Processing suggestions");
@@ -1453,6 +1476,13 @@ class dfrn {
 
 	}
 
+	/**
+	 * @brief Processes the relocation elements
+	 *
+	 * @param object $xpath XPath object
+	 * @param object $relocation relocation elements
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 */
 	private function process_relocation($xpath, $relocation, $importer) {
 
 		logger("Processing relocations");
@@ -1534,6 +1564,14 @@ class dfrn {
 		return true;
 	}
 
+	/**
+	 * @brief Updates an item
+	 *
+	 * @param array $current the current item record
+	 * @param array $item the new item record
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 * @param int $entrytype Is it a toplevel entry, a comment or a relayed comment?
+	 */
 	private function update_content($current, $item, $importer, $entrytype) {
 		$changed = false;
 
@@ -1578,6 +1616,14 @@ class dfrn {
 		return $changed;
 	}
 
+	/**
+	 * @brief Detects the entry type of the item
+	 *
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 * @param array $item the new item record
+	 *
+	 * @return int Is it a toplevel entry, a comment or a relayed comment?
+	 */
 	private function get_entry_type($importer, $item) {
 		if ($item["parent-uri"] != $item["uri"]) {
 			$community = false;
@@ -1637,6 +1683,13 @@ class dfrn {
 
 	}
 
+	/**
+	 * @brief Send a "poke"
+	 *
+	 * @param array $item the new item record
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 * @param int $posted_id The record number of item record that was just posted
+	 */
 	private function do_poke($item, $importer, $posted_id) {
 		$verb = urldecode(substr($item["verb"],strpos($item["verb"], "#")+1));
 		if(!$verb)
@@ -1683,6 +1736,14 @@ class dfrn {
 		}
 	}
 
+	/**
+	 * @brief Processes the entry elements which contain the items and comments
+	 *
+	 * @param array $header Array of the header elements that always stay the same
+	 * @param object $xpath XPath object
+	 * @param object $entry entry elements
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 */
 	private function process_entry($header, $xpath, $entry, $importer) {
 
 		logger("Processing entries");
@@ -2079,7 +2140,14 @@ class dfrn {
 		}
 	}
 
-	private function process_deletion($header, $xpath, $deletion, $importer) {
+	/**
+	 * @brief Deletes items
+	 *
+	 * @param object $xpath XPath object
+	 * @param object $deletion deletion elements
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 */
+	private function process_deletion($xpath, $deletion, $importer) {
 
 		logger("Processing deletions");
 
@@ -2283,7 +2351,7 @@ class dfrn {
 
 		$deletions = $xpath->query("/atom:feed/at:deleted-entry");
 		foreach ($deletions AS $deletion)
-			self::process_deletion($header, $xpath, $deletion, $importer);
+			self::process_deletion($xpath, $deletion, $importer);
 
 		if (!$sort_by_date) {
 			$entries = $xpath->query("/atom:feed/atom:entry");

From 0bccfea5968c5195a253bb7f2066145e0f539144 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Sat, 6 Feb 2016 00:54:50 +0100
Subject: [PATCH 049/273] vier: some consistency fixes for the dark scheme

---
 view/theme/vier/dark.css | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/view/theme/vier/dark.css b/view/theme/vier/dark.css
index 8e128ae27f..d34330010e 100644
--- a/view/theme/vier/dark.css
+++ b/view/theme/vier/dark.css
@@ -35,6 +35,11 @@ body, section, blockquote, blockquote.shared_content, #profile-jot-form,
 	background-color: #171B1F !important;
 }
 
+#profile-jot-acl-wrapper, #event-notice, #event-wrapper,
+#cboxLoadedContent, .contact-photo-menu {
+	background-color: #252C33 !important;
+}
+
 div.rte, .mceContentBody {
 background:none repeat scroll 0 0 #333333!important;
 color:#FFF!important;
@@ -63,3 +68,31 @@ li :hover {
 #viewcontact_wrapper-network {
 	background-color: #343434;
 }
+
+/* ACL permission popup */
+ .acl-list-item.groupshow {
+	border-color: #9ade00 !important;
+}
+
+.acl-list-item.grouphide {
+	border-color: #ff4141 !important;
+}
+
+/* Notifications */
+li.notify-unseen {
+	background-color: #252C33;
+}
+
+li.notify-seen {
+	background-color: #1C2126;
+}
+
+.photo-top-album-name {
+	background-color: #252C33;
+}
+
+#panel {
+	background-color: #252C33;
+	border: 3px solid #364e59;
+	color: #989898;
+}

From 4896517385f3b4484564bf675a5342f74d70f48a Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Sat, 6 Feb 2016 01:08:10 +0100
Subject: [PATCH 050/273] datetime.php: little more docu

---
 include/datetime.php | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/datetime.php b/include/datetime.php
index 3a75690d22..6983b6431d 100644
--- a/include/datetime.php
+++ b/include/datetime.php
@@ -106,7 +106,7 @@ function field_timezone($name='timezone', $label='', $current = 'America/Los_Ang
  * @param string $fmt Output format recognised from php's DateTime class
  *   http://www.php.net/manual/en/datetime.format.php
  * 
- * @return string
+ * @return string Formatted date according to given format
  */
 function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d H:i:s") {
 
@@ -153,6 +153,7 @@ function datetime_convert($from = 'UTC', $to = 'UTC', $s = 'now', $fmt = "Y-m-d
 	}
 
 	$d->setTimeZone($to_obj);
+
 	return($d->format($fmt));
 }
 
@@ -380,7 +381,7 @@ function relative_date($posted_date,$format = null) {
  * @param string $owner_tz (optional) Timezone of the person of interest
  * @param string $viewer_tz (optional) Timezone of the person viewing
  * 
- * @return int
+ * @return int Age in years
  */
 function age($dob,$owner_tz = '',$viewer_tz = '') {
 	if(! intval($dob))

From bd3e10b132ae95aaa34eb7ba6f618f5d9ac2612c Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 6 Feb 2016 10:16:16 +0100
Subject: [PATCH 051/273] Bugfix in the poke function / added documentation.

---
 include/dfrn.php | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index d62d1d57fb..eaf4341f03 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -1270,6 +1270,10 @@ class dfrn {
 			update_contact_avatar($author["avatar"], $importer["uid"], $contact["id"],
 						(strtotime($contact["avatar-date"]) > strtotime($r[0]["avatar-date"])));
 
+			// The generation is a sign for the reliability of the provided data.
+			// It is used in the socgraph.php to prevent that old contact data
+			// that was relayed over several servers can overwrite contact
+			// data that we received directly.
 			$contact["generation"] = 2;
 			$contact["photo"] = $author["avatar"];
 			update_gcontact($contact);
@@ -1711,7 +1715,7 @@ class dfrn {
 						break;
 				}
 			}
-			if($Blink && link_compare($Blink,$a->get_baseurl()."/profile/".$importer["nickname"])) {
+			if($Blink && link_compare($Blink,App::get_baseurl()."/profile/".$importer["nickname"])) {
 
 				// send a notification
 				notification(array(
@@ -1722,7 +1726,7 @@ class dfrn {
 					"to_email"     => $importer["email"],
 					"uid"          => $importer["importer_uid"],
 					"item"         => $item,
-					"link"         => $a->get_baseurl()."/display/".urlencode(get_item_guid($posted_id)),
+					"link"         => App::get_baseurl()."/display/".urlencode(get_item_guid($posted_id)),
 					"source_name"  => stripslashes($item["author-name"]),
 					"source_link"  => $item["author-link"],
 					"source_photo" => ((link_compare($item["author-link"],$importer["url"]))

From 3890415767aa687cf7a2e566e0f07b9c663f3de1 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 6 Feb 2016 11:16:00 +0100
Subject: [PATCH 052/273] Receiving pokes work now

---
 include/dfrn.php | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index eaf4341f03..90370694ec 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -1703,9 +1703,7 @@ class dfrn {
 		if(($xo->type == ACTIVITY_OBJ_PERSON) && ($xo->id)) {
 
 			// somebody was poked/prodded. Was it me?
-			$links = parse_xml_string("<links>".unxmlify($xo->link)."</links>",false);
-
-			foreach($links->link as $l) {
+			foreach($xo->link as $l) {
 				$atts = $l->attributes();
 				switch($atts["rel"]) {
 					case "alternate":
@@ -1715,6 +1713,7 @@ class dfrn {
 						break;
 				}
 			}
+
 			if($Blink && link_compare($Blink,App::get_baseurl()."/profile/".$importer["nickname"])) {
 
 				// send a notification

From 8ea4659031c28256332c69ae6ec88559b225b5b1 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 6 Feb 2016 17:48:03 +0100
Subject: [PATCH 053/273] The code was rearranged to improve readability

---
 include/dfrn.php | 206 ++++++++++++++++++++++++++---------------------
 1 file changed, 113 insertions(+), 93 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index 90370694ec..043f02cc2f 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -1739,6 +1739,107 @@ class dfrn {
 		}
 	}
 
+	/**
+	 * @brief Processes several actions, depending on the verb
+	 *
+	 * @param int $entrytype Is it a toplevel entry, a comment or a relayed comment?
+	 * @param array $importer Record of the importer user mixed with contact of the content
+	 * @param array $item the new item record
+	 * @param bool $is_like Is the verb a "like"?
+	 *
+	 * @return bool Should the processing of the entries be continued?
+	 */
+	private function process_verbs($entrytype, $importer, &$item, &$is_like) {
+		if (($entrytype == DFRN_TOP_LEVEL)) {
+			// The filling of the the "contact" variable is done for legcy reasons
+			// The functions below are partly used by ostatus.php as well - where we have this variable
+			$r = q("SELECT * FROM `contact` WHERE `id` = %d", intval($importer["id"]));
+			$contact = $r[0];
+			$nickname = $contact["nick"];
+
+			// Big question: Do we need these functions? They were part of the "consume_feed" function.
+			// This function once was responsible for DFRN and OStatus.
+			if(activity_match($item["verb"],ACTIVITY_FOLLOW)) {
+				logger("New follower");
+				new_follower($importer, $contact, $item, $nickname);
+				return false;
+			}
+			if(activity_match($item["verb"],ACTIVITY_UNFOLLOW))  {
+				logger("Lost follower");
+				lose_follower($importer, $contact, $item);
+				return false;
+			}
+			if(activity_match($item["verb"],ACTIVITY_REQ_FRIEND)) {
+				logger("New friend request");
+				new_follower($importer, $contact, $item, $nickname, true);
+				return false;
+			}
+			if(activity_match($item["verb"],ACTIVITY_UNFRIEND))  {
+				logger("Lost sharer");
+				lose_sharer($importer, $contact, $item);
+				return false;
+			}
+		} else {
+			if(($item["verb"] === ACTIVITY_LIKE)
+				|| ($item["verb"] === ACTIVITY_DISLIKE)
+				|| ($item["verb"] === ACTIVITY_ATTEND)
+				|| ($item["verb"] === ACTIVITY_ATTENDNO)
+				|| ($item["verb"] === ACTIVITY_ATTENDMAYBE)) {
+				$is_like = true;
+				$item["type"] = "activity";
+				$item["gravity"] = GRAVITY_LIKE;
+				// only one like or dislike per person
+				// splitted into two queries for performance issues
+				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1",
+					intval($item["uid"]),
+					dbesc($item["author-link"]),
+					dbesc($item["verb"]),
+					dbesc($item["parent-uri"])
+				);
+				if($r && count($r))
+					return false;
+
+				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1",
+					intval($item["uid"]),
+					dbesc($item["author-link"]),
+					dbesc($item["verb"]),
+					dbesc($item["parent-uri"])
+				);
+				if($r && count($r))
+					return false;
+			} else
+				$is_like = false;
+
+			if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
+
+				$xo = parse_xml_string($item["object"],false);
+				$xt = parse_xml_string($item["target"],false);
+
+				if($xt->type == ACTIVITY_OBJ_NOTE) {
+					$r = q("SELECT `id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+						dbesc($xt->id),
+						intval($importer["importer_uid"])
+					);
+
+					if(!count($r))
+						return false;
+
+					// extract tag, if not duplicate, add to parent item
+					if($xo->content) {
+						if(!(stristr($r[0]["tag"],trim($xo->content)))) {
+							q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
+								dbesc($r[0]["tag"] . (strlen($r[0]["tag"]) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'),
+								intval($r[0]["id"])
+							);
+							create_tags_from_item($r[0]["id"]);
+						}
+					}
+				}
+			}
+		}
+		return true;
+	}
+
 	/**
 	 * @brief Processes the entry elements which contain the items and comments
 	 *
@@ -1932,6 +2033,11 @@ class dfrn {
 
 			if (($item["network"] != $author["network"]) AND ($author["network"] != ""))
 				$item["network"] = $author["network"];
+
+			if($importer["rel"] == CONTACT_IS_FOLLOWER) {
+				logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG);
+				return;
+			}
 		}
 
 		if ($entrytype == DFRN_REPLY_RC) {
@@ -1941,6 +2047,7 @@ class dfrn {
 			if (!isset($item["object-type"]))
 				$item["object-type"] = ACTIVITY_OBJ_NOTE;
 
+			// Is it an event?
 			if ($item["object-type"] == ACTIVITY_OBJ_EVENT) {
 				logger("Item ".$item["uri"]." seems to contain an event.", LOGGER_DEBUG);
 				$ev = bbtoevent($item["body"]);
@@ -1965,35 +2072,6 @@ class dfrn {
 					return;
 				}
 			}
-
-			// The filling of the the "contact" variable is done for legcy reasons
-			// The functions below are partly used by ostatus.php as well - where we have this variable
-			$r = q("SELECT * FROM `contact` WHERE `id` = %d", intval($importer["id"]));
-			$contact = $r[0];
-			$nickname = $contact["nick"];
-
-			// Big question: Do we need these functions? They were part of the "consume_feed" function.
-			// This function once was responsible for DFRN and OStatus.
-			if(activity_match($item['verb'],ACTIVITY_FOLLOW)) {
-				logger('New follower');
-				new_follower($importer, $contact, $item, $nickname);
-				return;
-			}
-			if(activity_match($item['verb'],ACTIVITY_UNFOLLOW))  {
-				logger('Lost follower');
-				lose_follower($importer, $contact, $item);
-				return;
-			}
-			if(activity_match($item['verb'],ACTIVITY_REQ_FRIEND)) {
-				logger('New friend request');
-				new_follower($importer, $contact, $item, $nickname, true);
-				return;
-			}
-			if(activity_match($item['verb'],ACTIVITY_UNFRIEND))  {
-				logger('Lost sharer');
-				lose_sharer($importer, $contact, $item);
-				return;
-			}
 		}
 
 		$r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
@@ -2001,6 +2079,11 @@ class dfrn {
 			intval($importer["importer_uid"])
 		);
 
+		if (!self::process_verbs($entrytype, $importer, $item, $is_like)) {
+			logger("Exiting because 'process_verbs' told us so", LOGGER_DEBUG);
+			return;
+		}
+
 		// Update content if 'updated' changes
 		if(count($r)) {
 			if (self::update_content($r[0], $item, $importer, $entrytype))
@@ -2011,69 +2094,6 @@ class dfrn {
 		}
 
 		if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) {
-			if($importer["rel"] == CONTACT_IS_FOLLOWER) {
-				logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG);
-				return;
-			}
-
-			if(($item["verb"] === ACTIVITY_LIKE)
-				|| ($item["verb"] === ACTIVITY_DISLIKE)
-				|| ($item["verb"] === ACTIVITY_ATTEND)
-				|| ($item["verb"] === ACTIVITY_ATTENDNO)
-				|| ($item["verb"] === ACTIVITY_ATTENDMAYBE)) {
-				$is_like = true;
-				$item["type"] = "activity";
-				$item["gravity"] = GRAVITY_LIKE;
-				// only one like or dislike per person
-				// splitted into two queries for performance issues
-				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1",
-					intval($item["uid"]),
-					dbesc($item["author-link"]),
-					dbesc($item["verb"]),
-					dbesc($item["parent-uri"])
-				);
-				if($r && count($r))
-					return;
-
-				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1",
-					intval($item["uid"]),
-					dbesc($item["author-link"]),
-					dbesc($item["verb"]),
-					dbesc($item["parent-uri"])
-				);
-				if($r && count($r))
-					return;
-
-			} else
-				$is_like = false;
-
-			if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
-
-				$xo = parse_xml_string($item["object"],false);
-				$xt = parse_xml_string($item["target"],false);
-
-				if($xt->type == ACTIVITY_OBJ_NOTE) {
-					$r = q("SELECT `id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-						dbesc($xt->id),
-						intval($importer["importer_uid"])
-					);
-
-					if(!count($r))
-						return;
-
-					// extract tag, if not duplicate, add to parent item
-					if($xo->content) {
-						if(!(stristr($r[0]["tag"],trim($xo->content)))) {
-							q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d",
-								dbesc($r[0]["tag"] . (strlen($r[0]["tag"]) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'),
-								intval($r[0]["id"])
-							);
-							create_tags_from_item($r[0]["id"]);
-						}
-					}
-				}
-			}
-
 			$posted_id = item_store($item);
 			$parent = 0;
 
@@ -2113,7 +2133,7 @@ class dfrn {
 
 				return true;
 			}
-		} else {
+		} else { // $entrytype == DFRN_TOP_LEVEL
 			if(!link_compare($item["owner-link"],$importer["url"])) {
 				// The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery,
 				// but otherwise there's a possible data mixup on the sender's system.

From af219ac9ec547595fbc2b5b19ac402041f35dcf5 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 6 Feb 2016 21:44:10 +0100
Subject: [PATCH 054/273] Just some more code cleanup and documentation.

---
 include/dfrn.php | 83 +++++++++++++++++++++++++++---------------------
 1 file changed, 46 insertions(+), 37 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index 043f02cc2f..84660a0d18 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -26,9 +26,9 @@ require_once("library/HTMLPurifier.auto.php");
  */
 class dfrn {
 
-	const DFRN_TOP_LEVEL = 0;
-	const DFRN_REPLY = 1;
-	const DFRN_REPLY_RC = 2;
+	const DFRN_TOP_LEVEL = 0;	// Top level posting
+	const DFRN_REPLY = 1;		// Regular reply that is stored locally
+	const DFRN_REPLY_RC = 2;	// Reply that will be relayed
 
 	/**
 	 * @brief Generates the atom entries for delivery.php
@@ -1840,6 +1840,47 @@ class dfrn {
 		return true;
 	}
 
+	/**
+	 * @brief Processes the link elements
+	 *
+	 * @param object $links link elements
+	 * @param array $item the item record
+	 */
+	private function parse_links($links, &$item) {
+		$rel = "";
+		$href = "";
+		$type = "";
+		$length = "0";
+		$title = "";
+		foreach ($links AS $link) {
+			foreach($link->attributes AS $attributes) {
+				if ($attributes->name == "href")
+					$href = $attributes->textContent;
+				if ($attributes->name == "rel")
+					$rel = $attributes->textContent;
+				if ($attributes->name == "type")
+					$type = $attributes->textContent;
+				if ($attributes->name == "length")
+					$length = $attributes->textContent;
+				if ($attributes->name == "title")
+					$title = $attributes->textContent;
+			}
+			if (($rel != "") AND ($href != ""))
+				switch($rel) {
+					case "alternate":
+						$item["plink"] = $href;
+						break;
+					case "enclosure":
+						$enclosure = $href;
+						if(strlen($item["attach"]))
+							$item["attach"] .= ",";
+
+						$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
+						break;
+				}
+		}
+	}
+
 	/**
 	 * @brief Processes the entry elements which contain the items and comments
 	 *
@@ -1970,40 +2011,8 @@ class dfrn {
 		$enclosure = "";
 
 		$links = $xpath->query("atom:link", $entry);
-		if ($links) {
-			$rel = "";
-			$href = "";
-			$type = "";
-			$length = "0";
-			$title = "";
-			foreach ($links AS $link) {
-				foreach($link->attributes AS $attributes) {
-					if ($attributes->name == "href")
-						$href = $attributes->textContent;
-					if ($attributes->name == "rel")
-						$rel = $attributes->textContent;
-					if ($attributes->name == "type")
-						$type = $attributes->textContent;
-					if ($attributes->name == "length")
-						$length = $attributes->textContent;
-					if ($attributes->name == "title")
-						$title = $attributes->textContent;
-				}
-				if (($rel != "") AND ($href != ""))
-					switch($rel) {
-						case "alternate":
-							$item["plink"] = $href;
-							break;
-						case "enclosure":
-							$enclosure = $href;
-							if(strlen($item["attach"]))
-								$item["attach"] .= ",";
-
-							$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
-							break;
-					}
-			}
-		}
+		if ($links)
+			self::parse_links($links, $item);
 
 		// Is it a reply or a top level posting?
 		$item["parent-uri"] = $item["uri"];

From 44592611e1582fd97ae1988343418a0dae1ae2a0 Mon Sep 17 00:00:00 2001
From: fabrixxm <fabrix.xm@gmail.com>
Date: Sun, 7 Feb 2016 14:27:13 +0100
Subject: [PATCH 055/273] new api for notifications

/api/friendica/notification
returns first 50 notifications for current user

/api/friendica&notification/<id>
set note <id> as seen and return item object if possible

new class NotificationsManager to query for notifications and set seen
state
---
 include/NotificationsManager.php | 113 +++++++++++++++++++++++++++++++
 include/api.php                  |  79 +++++++++++++++++++--
 mod/notify.php                   |  82 ++++++++++------------
 mod/ping.php                     |   4 +-
 4 files changed, 223 insertions(+), 55 deletions(-)
 create mode 100644 include/NotificationsManager.php

diff --git a/include/NotificationsManager.php b/include/NotificationsManager.php
new file mode 100644
index 0000000000..8b0ca9e13d
--- /dev/null
+++ b/include/NotificationsManager.php
@@ -0,0 +1,113 @@
+<?php
+require_once("include/datetime.php");
+
+class NotificationsManager {
+    private $a;
+    
+    public function __construct() {
+        $this->a = get_app();
+    }
+    
+    private function _set_extra($notes) {
+        $rets = array();
+        foreach($notes as $n) {
+            $local_time = datetime_convert('UTC',date_default_timezone_get(),$n['date']);
+            $n['timestamp'] = strtotime($local_time);
+            $n['date_rel'] = relative_date($n['date']);
+            $rets[] = $n;
+        }
+        return $rets;
+    }
+
+
+    /**
+     * @brief get all notifications for local_user()
+     *
+     * @param array $filter optional Array "column name"=>value: filter query by columns values
+     * @param string $order optional Space separated list of column to sort by. prepend name with "+" to sort ASC, "-" to sort DESC. Default to "-date"
+     * @param string $limit optional Query limits
+     *
+     * @return array of results or false on errors
+     */
+    public function getAll($filter = array(), $order="-date", $limit="") {
+        $filter_str = array();
+        $filter_sql = "";
+        foreach($filter as $column => $value) {
+            $filter_str[] = sprintf("`%s` = '%s'", $column, dbesc($value));
+        }
+        if (count($filter_str)>0) {
+            $filter_sql = "AND ".implode(" AND ", $filter_str);
+        }
+        
+        $aOrder = explode(" ", $order);
+        $asOrder = array();
+        foreach($aOrder as $o) {
+            $dir = "asc";
+            if ($o[0]==="-") {
+                $dir = "desc";
+                $o = substr($o,1);
+            }
+            if ($o[0]==="+") {
+                $dir = "asc";
+                $o = substr($o,1);
+            }
+            $asOrder[] = "$o $dir";
+        }
+        $order_sql = implode(", ", $asOrder);
+        
+        if ($limit!="") $limit = " LIMIT ".$limit;
+        
+		$r = q("SELECT * from notify where uid = %d $filter_sql order by $order_sql $limit",
+			intval(local_user())
+		);
+        if ($r!==false && count($r)>0) return $this->_set_extra($r);
+        return false;
+    }
+    
+    /**
+     * @brief get one note for local_user() by $id value
+     *
+     * @param int $id
+     * @return array note values or null if not found
+     */
+    public function getByID($id) {
+        $r = q("select * from notify where id = %d and uid = %d limit 1",
+                intval($id),
+                intval(local_user())
+        );
+        if($r!==false && count($r)>0) {
+            return $this->_set_extra($r)[0];
+        }
+        return null;
+    }
+    
+    /**
+     * @brief set seen state of $note of local_user()
+     *
+     * @param array $note
+     * @param bool $seen optional true or false, default true
+     * @return bool true on success, false on errors
+     */
+    public function setSeen($note, $seen = true) {
+        return q("update notify set seen = %d where ( link = '%s' or ( parent != 0 and parent = %d and otype = '%s' )) and uid = %d",
+            intval($seen),
+            dbesc($note['link']),
+            intval($note['parent']),
+            dbesc($note['otype']),
+            intval(local_user())
+        );
+    }
+       
+    /**
+     * @brief set seen state of all notifications of local_user()
+     *
+     * @param bool $seen optional true or false. default true
+     * @return bool true on success, false on error
+     */
+    public function setAllSeen($seen = true) {
+    	return q("update notify set seen = %d where uid = %d",
+            intval($seen),
+			intval(local_user())
+		);
+    }
+}
diff --git a/include/api.php b/include/api.php
index 4d206da28e..5acc816575 100644
--- a/include/api.php
+++ b/include/api.php
@@ -23,6 +23,7 @@
 	require_once('include/message.php');
 	require_once('include/group.php');
 	require_once('include/like.php');
+	require_once('include/NotificationsManager.php');
 
 
 	define('API_METHOD_ANY','*');
@@ -250,7 +251,7 @@
 	 */
 	function api_call(&$a){
 		GLOBAL $API, $called_api;
-
+		
 		$type="json";
 		if (strpos($a->query_string, ".xml")>0) $type="xml";
 		if (strpos($a->query_string, ".json")>0) $type="json";
@@ -680,6 +681,29 @@
 	}
 
 
+	/**
+	 * @brief transform $data array in xml without a template
+	 *
+	 * @param array $data
+	 * @return string xml string
+	 */
+	function api_array_to_xml($data, $ename="") {
+		$attrs="";
+		$childs="";
+		foreach($data as $k=>$v) {
+			$k=trim($k,'$');
+			if (!is_array($v)) {
+				$attrs .= sprintf('%s="%s" ', $k, $v);
+			} else {
+				if (is_numeric($k)) $k=trim($ename,'s');
+				$childs.=api_array_to_xml($v, $k);
+			}
+		}
+		$res = $childs;
+		if ($ename!="") $res = "<$ename $attrs>$res</$ename>";
+		return $res;
+	}
+
 	/**
 	 *  load api $templatename for $type and replace $data array
 	 */
@@ -692,13 +716,17 @@
 			case "rss":
 			case "xml":
 				$data = array_xmlify($data);
-				$tpl = get_markup_template("api_".$templatename."_".$type.".tpl");
-				if(! $tpl) {
-					header ("Content-Type: text/xml");
-					echo '<?xml version="1.0" encoding="UTF-8"?>'."\n".'<status><error>not implemented</error></status>';
-					killme();
+				if ($templatename==="<auto>") {
+					$ret = api_array_to_xml($data); 
+				} else {
+					$tpl = get_markup_template("api_".$templatename."_".$type.".tpl");
+					if(! $tpl) {
+						header ("Content-Type: text/xml");
+						echo '<?xml version="1.0" encoding="UTF-8"?>'."\n".'<status><error>not implemented</error></status>';
+						killme();
+					}
+					$ret = replace_macros($tpl, $data);
 				}
-				$ret = replace_macros($tpl, $data);
 				break;
 			case "json":
 				$ret = $data;
@@ -3386,6 +3414,43 @@
 	api_register_func('api/friendica/activity/unattendno', 'api_friendica_activity', true, API_METHOD_POST);
 	api_register_func('api/friendica/activity/unattendmaybe', 'api_friendica_activity', true, API_METHOD_POST);
 
+	/**
+	 * returns notifications
+	 * if called with note id set note seen and returns associated item (if possible)
+	 */
+	function api_friendica_notification(&$a, $type) {
+		if (api_user()===false) throw new ForbiddenException();
+		
+		$nm = new NotificationsManager();
+		
+		if ($a->argc==3) {
+			$notes = $nm->getAll(array(), "+seen -date", 50);
+			return api_apply_template("<auto>", $type, array('$notes' => $notes));
+		}
+		if ($a->argc==4) {
+			$note = $nm->getByID(intval($a->argv[3]));
+			if (is_null($note)) throw new BadRequestException("Invalid argument");
+			$nm->setSeen($note);
+			if ($note['otype']=='item') {
+				// would be really better with a ItemsManager and $im->getByID() :-P
+				$r = q("SELECT * FROM item WHERE id=%d AND uid=%d",
+					intval($note['iid']),
+					intval(local_user())
+				);
+				if ($r===false) throw new NotFoundException();
+				$user_info = api_get_user($a);
+				$ret = api_format_items($r,$user_info);
+				$data = array('$statuses' => $ret);
+				return api_apply_template("timeline", $type, $data);
+			} else {
+				return api_apply_template('test', $type, array('ok' => $ok));
+			}
+			
+		}
+		throw new BadRequestException("Invalid argument count");
+	}
+	api_register_func('api/friendica/notification', 'api_friendica_notification', true, API_METHOD_GET);
+
 /*
 To.Do:
     [pagename] => api/1.1/statuses/lookup.json
diff --git a/mod/notify.php b/mod/notify.php
index 7acac1084a..7c367708bb 100644
--- a/mod/notify.php
+++ b/mod/notify.php
@@ -1,43 +1,34 @@
 <?php
-
+require_once('include/NotificationsManager.php');
 if(! function_exists('notify_init')) {
 function notify_init(&$a) {
-	if(! local_user())
-		return;
+	if(! local_user()) return;
 
+	$nm = new NotificationsManager();
+		
 	if($a->argc > 2 && $a->argv[1] === 'view' && intval($a->argv[2])) {
-		$r = q("select * from notify where id = %d and uid = %d limit 1",
-			intval($a->argv[2]),
-			intval(local_user())
-		);
-		if(count($r)) {
-			q("update notify set seen = 1 where ( link = '%s' or ( parent != 0 and parent = %d and otype = '%s' )) and uid = %d",
-				dbesc($r[0]['link']),
-				intval($r[0]['parent']),
-				dbesc($r[0]['otype']),
-				intval(local_user())
-			);
-
+		$note = $nm->getByID($a->argv[2]);
+		if ($note) {
+			$nm->setSeen($note);
+		
 			// The friendica client has problems with the GUID. this is some workaround
 			if ($a->is_friendica_app()) {
 				require_once("include/items.php");
-				$urldata = parse_url($r[0]['link']);
+				$urldata = parse_url($note['link']);
 				$guid = basename($urldata["path"]);
 				$itemdata = get_item_id($guid, local_user());
 				if ($itemdata["id"] != 0)
-					$r[0]['link'] = $a->get_baseurl().'/display/'.$itemdata["nick"].'/'.$itemdata["id"];
+					$note['link'] = $a->get_baseurl().'/display/'.$itemdata["nick"].'/'.$itemdata["id"];
 			}
 
-			goaway($r[0]['link']);
+			goaway($note['link']);
 		}
 
 		goaway($a->get_baseurl(true));
 	}
 
 	if($a->argc > 2 && $a->argv[1] === 'mark' && $a->argv[2] === 'all' ) {
-		$r = q("update notify set seen = 1 where uid = %d",
-			intval(local_user())
-		);
+		$r = $nm->setAllSeen();
 		$j = json_encode(array('result' => ($r) ? 'success' : 'fail'));
 		echo $j;
 		killme();
@@ -47,38 +38,37 @@ function notify_init(&$a) {
 
 if(! function_exists('notify_content')) {
 function notify_content(&$a) {
-	if(! local_user())
-		return login();
+	if(! local_user()) return login();
 
-		$notif_tpl = get_markup_template('notifications.tpl');
+	$nm = new NotificationsManager();
+	
+	$notif_tpl = get_markup_template('notifications.tpl');
 
-		$not_tpl = get_markup_template('notify.tpl');
-		require_once('include/bbcode.php');
+	$not_tpl = get_markup_template('notify.tpl');
+	require_once('include/bbcode.php');
 
-		$r = q("SELECT * from notify where uid = %d and seen = 0 order by date desc",
-			intval(local_user())
-		);
-
-		if (count($r) > 0) {
-			foreach ($r as $it) {
-				$notif_content .= replace_macros($not_tpl,array(
-					'$item_link' => $a->get_baseurl(true).'/notify/view/'. $it['id'],
-					'$item_image' => $it['photo'],
-					'$item_text' => strip_tags(bbcode($it['msg'])),
-					'$item_when' => relative_date($it['date'])
-				));
-			}
-		} else {
-			$notif_content .= t('No more system notifications.');
+	$r = $nm->getAll(array('seen'=>0));
+	if ($r!==false && count($r) > 0) {
+		foreach ($r as $it) {
+			$notif_content .= replace_macros($not_tpl,array(
+				'$item_link' => $a->get_baseurl(true).'/notify/view/'. $it['id'],
+				'$item_image' => $it['photo'],
+				'$item_text' => strip_tags(bbcode($it['msg'])),
+				'$item_when' => relative_date($it['date'])
+			));
 		}
+	} else {
+		$notif_content .= t('No more system notifications.');
+	}
 
-		$o .= replace_macros($notif_tpl, array(
-			'$notif_header' => t('System Notifications'),
-			'$tabs' => '', // $tabs,
-			'$notif_content' => $notif_content,
-		));
+	$o .= replace_macros($notif_tpl, array(
+		'$notif_header' => t('System Notifications'),
+		'$tabs' => false, // $tabs,
+		'$notif_content' => $notif_content,
+	));
 
 	return $o;
 
 }
 }
+
diff --git a/mod/ping.php b/mod/ping.php
index 0d1659a763..adff0912f4 100644
--- a/mod/ping.php
+++ b/mod/ping.php
@@ -206,8 +206,8 @@ function ping_init(&$a) {
 			$local_time = datetime_convert('UTC',date_default_timezone_get(),$n['date']);
 
 			call_hooks('ping_xmlize', $n);
-			$notsxml = '<note href="%s" name="%s" url="%s" photo="%s" date="%s" seen="%s" timestamp="%s" >%s</note>'."\n";
-			return sprintf ( $notsxml,
+			$notsxml = '<note id="%d" href="%s" name="%s" url="%s" photo="%s" date="%s" seen="%s" timestamp="%s" >%s</note>'."\n";
+			return sprintf ( $notsxml, intval($n['id']),
 				xmlify($n['href']), xmlify($n['name']), xmlify($n['url']), xmlify($n['photo']),
 				xmlify(relative_date($n['date'])), xmlify($n['seen']), xmlify(strtotime($local_time)),
 				xmlify($n['message'])

From 102c06a41f3fb6308a75a748a347ebc84b7362dd Mon Sep 17 00:00:00 2001
From: fabrixxm <fabrix.xm@gmail.com>
Date: Sun, 7 Feb 2016 14:29:07 +0100
Subject: [PATCH 056/273] fix error in template in notifications page

---
 view/templates/notifications.tpl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/view/templates/notifications.tpl b/view/templates/notifications.tpl
index 0b7e77a07b..54f9de0c7a 100644
--- a/view/templates/notifications.tpl
+++ b/view/templates/notifications.tpl
@@ -2,7 +2,7 @@
 
 <h1>{{$notif_header}}</h1>
 
-{{include file="common_tabs.tpl"}}
+{{if $tabs }}{{include file="common_tabs.tpl"}}{{/if}}
 
 <div class="notif-network-wrapper">
 	{{$notif_content}}

From b202e02fbf09859c06ed21cc3b6bec1530ccf1f1 Mon Sep 17 00:00:00 2001
From: fabrixxm <fabrix.xm@gmail.com>
Date: Sun, 7 Feb 2016 15:11:34 +0100
Subject: [PATCH 057/273] Revert "Updated modules to allow for partial
 overrides without errors"

This reverts commit db949bb802448184bfe5164d8d3dd86ddf51b187.
---
 mod/_well_known.php       |  4 --
 mod/acctlink.php          |  3 +-
 mod/acl.php               |  4 +-
 mod/admin.php             | 78 +++++++++++----------------------------
 mod/allfriends.php        |  2 -
 mod/amcd.php              |  5 +--
 mod/api.php               | 11 +++---
 mod/apps.php              | 40 ++++++++++----------
 mod/attach.php            |  3 +-
 mod/babel.php             | 46 +++++++++++------------
 mod/bookmarklet.php       |  5 +--
 mod/cb.php                | 11 +-----
 mod/common.php            |  2 -
 mod/community.php         | 13 +++----
 mod/contactgroup.php      |  4 +-
 mod/contacts.php          | 38 ++++---------------
 mod/content.php           | 48 ++++++++++++------------
 mod/credits.php           |  2 -
 mod/crepair.php           | 10 ++---
 mod/delegate.php          | 10 ++---
 mod/dfrn_confirm.php      |  3 +-
 mod/dfrn_notify.php       |  6 +--
 mod/dfrn_poll.php         | 13 +++----
 mod/directory.php         | 19 +++++-----
 mod/dirfind.php           |  6 +--
 mod/display.php           |  9 ++---
 mod/editpost.php          |  5 ++-
 mod/events.php            |  6 +--
 mod/fbrowser.php          |  3 +-
 mod/filer.php             |  5 +--
 mod/filerm.php            |  2 -
 mod/follow.php            |  4 --
 mod/friendica.php         | 11 +++---
 mod/fsuggest.php          | 19 +++++-----
 mod/group.php             | 11 ++----
 mod/hcard.php             | 10 ++---
 mod/help.php              |  3 +-
 mod/hostxrd.php           |  3 +-
 mod/ignored.php           |  3 +-
 mod/install.php           | 55 +++++++++------------------
 mod/invite.php            | 13 +++----
 mod/item.php              | 13 ++-----
 mod/like.php              |  7 ++--
 mod/localtime.php         | 11 +++---
 mod/lockview.php          | 20 +++++-----
 mod/login.php             |  4 +-
 mod/lostpass.php          |  7 ++--
 mod/maintenance.php       |  3 +-
 mod/manage.php            |  8 ++--
 mod/match.php             |  2 -
 mod/message.php           | 13 ++-----
 mod/modexp.php            |  4 +-
 mod/mood.php              | 10 ++---
 mod/msearch.php           |  9 ++---
 mod/navigation.php        |  3 +-
 mod/network.php           | 17 ++-------
 mod/newmember.php         | 10 ++---
 mod/nodeinfo.php          | 11 ++----
 mod/nogroup.php           |  6 +--
 mod/noscrape.php          |  3 +-
 mod/notes.php             | 20 +++++-----
 mod/notice.php            |  9 ++---
 mod/notifications.php     |  6 +--
 mod/notify.php            |  8 ++--
 mod/oembed.php            |  4 +-
 mod/oexchange.php         | 17 +++++----
 mod/openid.php            | 10 ++---
 mod/opensearch.php        | 16 ++++----
 mod/ostatus_subscribe.php |  2 -
 mod/p.php                 |  4 +-
 mod/parse_url.php         | 18 ++-------
 mod/photo.php             |  2 -
 mod/photos.php            | 15 ++++----
 mod/ping.php              |  4 --
 mod/poco.php              |  3 +-
 mod/poke.php              | 12 +++---
 mod/post.php              |  7 ++--
 mod/pretheme.php          |  4 +-
 mod/probe.php             |  4 +-
 mod/profile.php           |  7 ++--
 mod/profile_photo.php     | 26 ++++++-------
 mod/profiles.php          | 14 ++-----
 mod/profperm.php          | 12 +++---
 mod/proxy.php             | 12 ------
 mod/pubsub.php            | 20 +++++-----
 mod/pubsubhubbub.php      |  5 +--
 mod/qsearch.php           |  3 +-
 mod/randprof.php          |  3 +-
 mod/receive.php           |  4 +-
 mod/redir.php             |  6 +--
 mod/regmod.php            |  9 ++---
 mod/removeme.php          |  6 +--
 mod/repair_ostatus.php    |  2 -
 mod/rsd_xml.php           |  6 +--
 mod/salmon.php            |  7 +---
 mod/search.php            | 14 +++----
 mod/session.php           |  3 +-
 mod/settings.php          | 16 ++++----
 mod/share.php             |  9 +----
 mod/smilies.php           |  6 +--
 mod/starred.php           |  3 +-
 mod/statistics_json.php   |  2 -
 mod/subthread.php         | 12 +++---
 mod/suggest.php           |  9 ++---
 mod/tagger.php            |  8 ++--
 mod/tagrm.php             |  9 ++---
 mod/toggle_mobile.php     |  3 +-
 mod/uexport.php           | 30 ++++++---------
 mod/uimport.php           | 12 ++----
 mod/update_community.php  |  5 +--
 mod/update_display.php    |  3 +-
 mod/update_network.php    |  3 +-
 mod/update_notes.php      |  9 ++---
 mod/update_profile.php    |  9 ++---
 mod/videos.php            | 12 +++---
 mod/view.php              | 10 ++---
 mod/viewcontacts.php      |  5 +--
 mod/viewsrc.php           |  6 +--
 mod/wall_attach.php       |  2 -
 mod/wall_upload.php       |  2 -
 mod/wallmessage.php       | 12 +++---
 mod/webfinger.php         |  6 +--
 mod/xrd.php               |  3 +-
 123 files changed, 471 insertions(+), 768 deletions(-)

diff --git a/mod/_well_known.php b/mod/_well_known.php
index 6c33136f95..33070a1ecd 100644
--- a/mod/_well_known.php
+++ b/mod/_well_known.php
@@ -2,7 +2,6 @@
 require_once("mod/hostxrd.php");
 require_once("mod/nodeinfo.php");
 
-if(! function_exists('_well_known_init')) {
 function _well_known_init(&$a){
 	if ($a->argc > 1) {
 		switch($a->argv[1]) {
@@ -20,9 +19,7 @@ function _well_known_init(&$a){
 	http_status_exit(404);
 	killme();
 }
-}
 
-if(! function_exists('wk_social_relay')) {
 function wk_social_relay(&$a) {
 
 	define('SR_SCOPE_ALL', 'all');
@@ -67,4 +64,3 @@ function wk_social_relay(&$a) {
 	echo json_encode($relay, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
 	exit;
 }
-}
diff --git a/mod/acctlink.php b/mod/acctlink.php
index a551e3dbd6..a2365803ac 100644
--- a/mod/acctlink.php
+++ b/mod/acctlink.php
@@ -2,8 +2,8 @@
 
 require_once('include/Scrape.php');
 
-if(! function_exists('acctlink_init')) {
 function acctlink_init(&$a) {
+
 	if(x($_GET,'addr')) {
 		$addr = trim($_GET['addr']);
 		$res = probe_url($addr);
@@ -14,4 +14,3 @@ function acctlink_init(&$a) {
 		}
 	}
 }
-}
diff --git a/mod/acl.php b/mod/acl.php
index 5666ccabb8..f5e04b96a7 100644
--- a/mod/acl.php
+++ b/mod/acl.php
@@ -3,8 +3,8 @@
 
 require_once("include/acl_selectors.php");
 
-if(! function_exists('acl_init')) {
 function acl_init(&$a){
 	acl_lookup($a);
 }
-}
+
+
diff --git a/mod/admin.php b/mod/admin.php
index ff17c0b8c4..7f9000807b 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -2,7 +2,7 @@
 
  /**
  * @file mod/admin.php
- *
+ * 
  * @brief Friendica admin
  */
 
@@ -23,7 +23,6 @@ require_once("include/text.php");
  * @param App $a
  *
  */
-if(! function_exists('admin_post')) {
 function admin_post(&$a){
 
 
@@ -111,7 +110,6 @@ function admin_post(&$a){
 	goaway($a->get_baseurl(true) . '/admin' );
 	return; // NOTREACHED
 }
-}
 
 /**
  * @brief Generates content of the admin panel pages
@@ -130,7 +128,6 @@ function admin_post(&$a){
  * @param App $a
  * @return string
  */
-if(! function_exists('admin_content')) {
 function admin_content(&$a) {
 
 	if(!is_site_admin()) {
@@ -248,7 +245,6 @@ function admin_content(&$a) {
 		return $o;
 	}
 }
-}
 
 /**
  * @brief Subpage with some stats about "the federation" network
@@ -264,7 +260,6 @@ function admin_content(&$a) {
  * @param App $a
  * @return string
  */
-if(! function_exists('admin_page_federation')) {
 function admin_page_federation(&$a) {
 	// get counts on active friendica, diaspora, redmatrix, hubzilla, gnu
 	// social and statusnet nodes this node is knowing
@@ -289,7 +284,7 @@ function admin_page_federation(&$a) {
 		// what versions for that platform do we know at all?
 		// again only the active nodes
 		$v = q('SELECT count(*) AS total, version FROM gserver
-			WHERE last_contact > last_failure AND platform LIKE "%s"
+			WHERE last_contact > last_failure AND platform LIKE "%s" 
 			GROUP BY version
 			ORDER BY version;', $p);
 
@@ -306,12 +301,12 @@ function admin_page_federation(&$a) {
 				$newVC = $vv['total'];
 				$newVV = $vv['version'];
 				$posDash = strpos($newVV, '-');
-				if($posDash)
+				if($posDash) 
 					$newVV = substr($newVV, 0, $posDash);
 				if(isset($newV[$newVV]))
-					$newV[$newVV] += $newVC;
+					$newV[$newVV] += $newVC; 
 				else
-					$newV[$newVV] = $newVC;
+					$newV[$newVV] = $newVC; 
 			}
 			foreach ($newV as $key => $value) {
 				array_push($newVv, array('total'=>$value, 'version'=>$key));
@@ -366,7 +361,6 @@ function admin_page_federation(&$a) {
 		'$baseurl' => $a->get_baseurl(),
 	));
 }
-}
 
 /**
  * @brief Admin Inspect Queue Page
@@ -381,7 +375,6 @@ function admin_page_federation(&$a) {
  * @param App $a
  * @return string
  */
-if(! function_exists('admin_page_queue')) {
 function admin_page_queue(&$a) {
 	// get content from the queue table
 	$r = q("SELECT c.name,c.nurl,q.id,q.network,q.created,q.last from queue as q, contact as c where c.id=q.cid order by q.cid, q.created;");
@@ -401,7 +394,6 @@ function admin_page_queue(&$a) {
 		'$entries' => $r,
 	));
 }
-}
 
 /**
  * @brief Admin Summary Page
@@ -414,7 +406,6 @@ function admin_page_queue(&$a) {
  * @param App $a
  * @return string
  */
-if(! function_exists('admin_page_summary')) {
 function admin_page_summary(&$a) {
 	$r = q("SELECT `page-flags`, COUNT(uid) as `count` FROM `user` GROUP BY `page-flags`");
 	$accounts = array(
@@ -461,14 +452,12 @@ function admin_page_summary(&$a) {
 		'$plugins' => array( t('Active plugins'), $a->plugins )
 	));
 }
-}
 
 /**
  * @brief Process send data from Admin Site Page
- *
+ * 
  * @param App $a
  */
-if(! function_exists('admin_page_site_post')) {
 function admin_page_site_post(&$a) {
 	if(!x($_POST,"page_site")) {
 		return;
@@ -781,7 +770,6 @@ function admin_page_site_post(&$a) {
 	return; // NOTREACHED
 
 }
-}
 
 /**
  * @brief Generate Admin Site subpage
@@ -791,7 +779,6 @@ function admin_page_site_post(&$a) {
  * @param  App $a
  * @return string
  */
-if(! function_exists('admin_page_site')) {
 function admin_page_site(&$a) {
 
 	/* Installed langs */
@@ -996,7 +983,7 @@ function admin_page_site(&$a) {
 		'$form_security_token'	=> get_form_security_token("admin_site")
 
 	));
-}
+
 }
 
 /**
@@ -1011,7 +998,6 @@ function admin_page_site(&$a) {
  * @param App $a
  * @return string
  **/
-if(! function_exists('admin_page_dbsync')) {
 function admin_page_dbsync(&$a) {
 
 	$o = '';
@@ -1087,15 +1073,14 @@ function admin_page_dbsync(&$a) {
 	}
 
 	return $o;
-}
+
 }
 
 /**
  * @brief Process data send by Users admin page
- *
+ * 
  * @param App $a
  */
-if(! function_exists('admin_page_users_post')) {
 function admin_page_users_post(&$a){
 	$pending	=	( x($_POST, 'pending')			? $_POST['pending']		: array() );
 	$users		=	( x($_POST, 'user')			? $_POST['user']		: array() );
@@ -1186,7 +1171,6 @@ function admin_page_users_post(&$a){
 	goaway($a->get_baseurl(true) . '/admin/users' );
 	return; // NOTREACHED
 }
-}
 
 /**
  * @brief Admin panel subpage for User management
@@ -1200,7 +1184,6 @@ function admin_page_users_post(&$a){
  * @param App $a
  * @return string
  */
-if(! function_exists('admin_page_users')) {
 function admin_page_users(&$a){
 	if($a->argc>2) {
 		$uid = $a->argv[3];
@@ -1353,7 +1336,7 @@ function admin_page_users(&$a){
 	$o .= paginate($a);
 	return $o;
 }
-}
+
 
 /**
  * @brief Plugins admin page
@@ -1371,7 +1354,6 @@ function admin_page_users(&$a){
  * @param App $a
  * @return string
  */
-if(! function_exists('admin_page_plugins')) {
 function admin_page_plugins(&$a){
 
 	/*
@@ -1497,19 +1479,17 @@ function admin_page_plugins(&$a){
 		'$baseurl' => $a->get_baseurl(true),
 		'$function' => 'plugins',
 		'$plugins' => $plugins,
-		'$pcount' => count($plugins),
+		'$pcount' => count($plugins), 
 		'$noplugshint' => sprintf( t('There are currently no plugins available on your node. You can find the official plugin repository at %1$s and might find other interesting plugins in the open plugin registry at %2$s'), 'https://github.com/friendica/friendica-addons', 'http://addons.friendi.ca'),
 		'$form_security_token' => get_form_security_token("admin_themes"),
 	));
 }
-}
 
 /**
  * @param array $themes
  * @param string $th
  * @param int $result
  */
-if(! function_exists('toggle_theme')) {
 function toggle_theme(&$themes,$th,&$result) {
 	for($x = 0; $x < count($themes); $x ++) {
 		if($themes[$x]['name'] === $th) {
@@ -1524,14 +1504,12 @@ function toggle_theme(&$themes,$th,&$result) {
 		}
 	}
 }
-}
 
 /**
  * @param array $themes
  * @param string $th
  * @return int
  */
-if(! function_exists('theme_status')) {
 function theme_status($themes,$th) {
 	for($x = 0; $x < count($themes); $x ++) {
 		if($themes[$x]['name'] === $th) {
@@ -1545,13 +1523,12 @@ function theme_status($themes,$th) {
 	}
 	return 0;
 }
-}
+
 
 /**
  * @param array $themes
  * @return string
  */
-if(! function_exists('rebuild_theme_table')) {
 function rebuild_theme_table($themes) {
 	$o = '';
 	if(count($themes)) {
@@ -1565,7 +1542,7 @@ function rebuild_theme_table($themes) {
 	}
 	return $o;
 }
-}
+
 
 /**
  * @brief Themes admin page
@@ -1583,7 +1560,6 @@ function rebuild_theme_table($themes) {
  * @param App $a
  * @return string
  */
-if(! function_exists('admin_page_themes')) {
 function admin_page_themes(&$a){
 
 	$allowed_themes_str = get_config('system','allowed_themes');
@@ -1758,14 +1734,13 @@ function admin_page_themes(&$a){
 		'$form_security_token' => get_form_security_token("admin_themes"),
 	));
 }
-}
+
 
 /**
  * @brief Prosesses data send by Logs admin page
- *
+ * 
  * @param App $a
  */
-if(! function_exists('admin_page_logs_post')) {
 function admin_page_logs_post(&$a) {
 	if(x($_POST,"page_logs")) {
 		check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs');
@@ -1783,7 +1758,6 @@ function admin_page_logs_post(&$a) {
 	goaway($a->get_baseurl(true) . '/admin/logs' );
 	return; // NOTREACHED
 }
-}
 
 /**
  * @brief Generates admin panel subpage for configuration of the logs
@@ -1801,7 +1775,6 @@ function admin_page_logs_post(&$a) {
  * @param App $a
  * @return string
  */
-if(! function_exists('admin_page_logs')) {
 function admin_page_logs(&$a){
 
 	$log_choices = array(
@@ -1833,7 +1806,6 @@ function admin_page_logs(&$a){
 		'$phplogcode' => "error_reporting(E_ERROR | E_WARNING | E_PARSE );\nini_set('error_log','php.out');\nini_set('log_errors','1');\nini_set('display_errors', '1');",
 	));
 }
-}
 
 /**
  * @brief Generates admin panel subpage to view the Friendica log
@@ -1853,7 +1825,6 @@ function admin_page_logs(&$a){
  * @param App $a
  * @return string
  */
-if(! function_exists('admin_page_viewlogs')) {
 function admin_page_viewlogs(&$a){
 	$t = get_markup_template("admin_viewlogs.tpl");
 	$f = get_config('system','logfile');
@@ -1890,14 +1861,12 @@ function admin_page_viewlogs(&$a){
 		'$logname' =>  get_config('system','logfile')
 	));
 }
-}
 
 /**
  * @brief Prosesses data send by the features admin page
- *
+ * 
  * @param App $a
  */
-if(! function_exists('admin_page_features_post')) {
 function admin_page_features_post(&$a) {
 
 	check_form_security_token_redirectOnErr('/admin/features', 'admin_manage_features');
@@ -1929,25 +1898,23 @@ function admin_page_features_post(&$a) {
 	goaway($a->get_baseurl(true) . '/admin/features' );
 	return; // NOTREACHED
 }
-}
 
 /**
  * @brief Subpage for global additional feature management
- *
+ * 
  * This functin generates the subpage 'Manage Additional Features'
  * for the admin panel. At this page the admin can set preferences
- * for the user settings of the 'additional features'. If needed this
+ * for the user settings of the 'additional features'. If needed this 
  * preferences can be locked through the admin.
- *
+ * 
  * The returned string contains the HTML code of the subpage 'Manage
  * Additional Features'
- *
+ * 
  * @param App $a
  * @return string
  */
-if(! function_exists('admin_page_features')) {
 function admin_page_features(&$a) {
-
+	
 	if((argc() > 1) && (argv(1) === 'features')) {
 		$arr = array();
 		$features = get_features(false);
@@ -1966,7 +1933,7 @@ function admin_page_features(&$a) {
 				);
 			}
 		}
-
+		
 		$tpl = get_markup_template("admin_settings_features.tpl");
 		$o .= replace_macros($tpl, array(
 			'$form_security_token' => get_form_security_token("admin_manage_features"),
@@ -1978,4 +1945,3 @@ function admin_page_features(&$a) {
 		return $o;
 	}
 }
-}
diff --git a/mod/allfriends.php b/mod/allfriends.php
index 8843265a99..356a389b83 100644
--- a/mod/allfriends.php
+++ b/mod/allfriends.php
@@ -5,7 +5,6 @@ require_once('include/Contact.php');
 require_once('include/contact_selectors.php');
 require_once('mod/contacts.php');
 
-if(! function_exists('allfriends_content')) {
 function allfriends_content(&$a) {
 
 	$o = '';
@@ -98,4 +97,3 @@ function allfriends_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/amcd.php b/mod/amcd.php
index 141a804298..a2a1327e6d 100644
--- a/mod/amcd.php
+++ b/mod/amcd.php
@@ -1,5 +1,5 @@
 <?php
-if(! function_exists('amcd_content')) {
+
 function amcd_content(&$a) {
 //header("Content-type: text/json");
 echo <<< EOT
@@ -46,5 +46,4 @@ echo <<< EOT
 }
 EOT;
 killme();
-}
-}
+}
\ No newline at end of file
diff --git a/mod/api.php b/mod/api.php
index 67564836e8..da2c40c305 100644
--- a/mod/api.php
+++ b/mod/api.php
@@ -1,8 +1,10 @@
 <?php
+
 require_once('include/api.php');
 
-if(! function_exists('oauth_get_client')) {
 function oauth_get_client($request){
+
+
 	$params = $request->get_parameters();
 	$token = $params['oauth_token'];
 
@@ -17,10 +19,9 @@ function oauth_get_client($request){
 
 	return $r[0];
 }
-}
 
-if(! function_exists('api_post')) {
 function api_post(&$a) {
+
 	if(! local_user()) {
 		notice( t('Permission denied.') . EOL);
 		return;
@@ -30,10 +31,9 @@ function api_post(&$a) {
 		notice( t('Permission denied.') . EOL);
 		return;
 	}
-}
+
 }
 
-if(! function_exists('api_content')) {
 function api_content(&$a) {
 	if ($a->cmd=='api/oauth/authorize'){
 		/*
@@ -114,4 +114,3 @@ function api_content(&$a) {
 	echo api_call($a);
 	killme();
 }
-}
diff --git a/mod/apps.php b/mod/apps.php
index e807feae74..a821ef5d5b 100644
--- a/mod/apps.php
+++ b/mod/apps.php
@@ -1,23 +1,25 @@
 <?php
-if(! function_exists('apps_content')) {
+
 function apps_content(&$a) {
-  $privateaddons = get_config('config','private_addons');
-  if ($privateaddons === "1") {
-    if((! (local_user()))) {
-      info( t("You must be logged in to use addons. "));
-      return;
-    }
-  }
-
-  $title = t('Applications');
-
-  if(count($a->apps)==0)
-    notice( t('No installed applications.') . EOL);
-
-  $tpl = get_markup_template("apps.tpl");
-  return replace_macros($tpl, array(
-    '$title' => $title,
-    '$apps' => $a->apps,
-  ));
+    $privateaddons = get_config('config','private_addons');
+      if ($privateaddons === "1") {
+	if((! (local_user())))  {
+	info( t("You must be logged in to use addons. "));
+      return;};
 }
+
+      $title = t('Applications');
+
+	if(count($a->apps)==0)
+		notice( t('No installed applications.') . EOL);
+
+
+	$tpl = get_markup_template("apps.tpl");
+	return replace_macros($tpl, array(
+		'$title' => $title,
+		'$apps' => $a->apps,
+	));
+
+	
+
 }
diff --git a/mod/attach.php b/mod/attach.php
index 849faa26ec..03f850f0d1 100644
--- a/mod/attach.php
+++ b/mod/attach.php
@@ -1,7 +1,7 @@
 <?php
+
 require_once('include/security.php');
 
-if(! function_exists('attach_init')) {
 function attach_init(&$a) {
 
 	if($a->argc != 2) {
@@ -47,4 +47,3 @@ function attach_init(&$a) {
 	killme();
 	// NOTREACHED
 }
-}
diff --git a/mod/babel.php b/mod/babel.php
index 56455bdb21..d31e090c55 100644
--- a/mod/babel.php
+++ b/mod/babel.php
@@ -9,56 +9,55 @@ function visible_lf($s) {
 	return str_replace("\n",'<br />', $s);
 }
 
-if(! function_exists('babel_content')) {
 function babel_content(&$a) {
 
 	$o .= '<h1>Babel Diagnostic</h1>';
 
 	$o .= '<form action="babel" method="post">';
 	$o .= t('Source (bbcode) text:') . EOL . '<textarea name="text" >' . htmlspecialchars($_REQUEST['text']) .'</textarea>' . EOL;
-	$o .= '<input type="submit" name="submit" value="Submit" /></form>';
+	$o .= '<input type="submit" name="submit" value="Submit" /></form>'; 
 
 	$o .= '<br /><br />';
 
 	$o .= '<form action="babel" method="post">';
 	$o .= t('Source (Diaspora) text to convert to BBcode:') . EOL . '<textarea name="d2bbtext" >' . htmlspecialchars($_REQUEST['d2bbtext']) .'</textarea>' . EOL;
-	$o .= '<input type="submit" name="submit" value="Submit" /></form>';
+	$o .= '<input type="submit" name="submit" value="Submit" /></form>'; 
 
 	$o .= '<br /><br />';
 
 	if(x($_REQUEST,'text')) {
 
 		$text = trim($_REQUEST['text']);
-		$o .= "<h2>" . t("Source input: ") . "</h2>" . EOL. EOL;
-		$o .= visible_lf($text) . EOL. EOL;
+		$o .= "<h2>" . t("Source input: ") . "</h2>" . EOL. EOL; 
+		$o .= visible_lf($text) . EOL. EOL; 
 
 		$html = bbcode($text);
-		$o .= "<h2>" . t("bb2html (raw HTML): ") . "</h2>" . EOL. EOL;
-		$o .= htmlspecialchars($html). EOL. EOL;
+		$o .= "<h2>" . t("bb2html (raw HTML): ") . "</h2>" . EOL. EOL; 
+		$o .= htmlspecialchars($html). EOL. EOL; 
 
 		//$html = bbcode($text);
-		$o .= "<h2>" . t("bb2html: ") . "</h2>" . EOL. EOL;
-		$o .= $html. EOL. EOL;
+		$o .= "<h2>" . t("bb2html: ") . "</h2>" . EOL. EOL; 
+		$o .= $html. EOL. EOL; 
 
 		$bbcode = html2bbcode($html);
-		$o .= "<h2>" . t("bb2html2bb: ") . "</h2>" . EOL. EOL;
-		$o .= visible_lf($bbcode) . EOL. EOL;
+		$o .= "<h2>" . t("bb2html2bb: ") . "</h2>" . EOL. EOL; 
+		$o .= visible_lf($bbcode) . EOL. EOL; 
 
 		$diaspora = bb2diaspora($text);
-		$o .= "<h2>" . t("bb2md: ") . "</h2>" . EOL. EOL;
-		$o .= visible_lf($diaspora) . EOL. EOL;
+		$o .= "<h2>" . t("bb2md: ") . "</h2>" . EOL. EOL; 
+		$o .= visible_lf($diaspora) . EOL. EOL; 
 
 		$html = Markdown($diaspora);
-		$o .= "<h2>" . t("bb2md2html: ") . "</h2>" . EOL. EOL;
-		$o .= $html. EOL. EOL;
+		$o .= "<h2>" . t("bb2md2html: ") . "</h2>" . EOL. EOL; 
+		$o .= $html. EOL. EOL; 
 
 		$bbcode = diaspora2bb($diaspora);
-		$o .= "<h2>" . t("bb2dia2bb: ") . "</h2>" . EOL. EOL;
-		$o .= visible_lf($bbcode) . EOL. EOL;
+		$o .= "<h2>" . t("bb2dia2bb: ") . "</h2>" . EOL. EOL; 
+		$o .= visible_lf($bbcode) . EOL. EOL; 
 
 		$bbcode = html2bbcode($html);
-		$o .= "<h2>" . t("bb2md2html2bb: ") . "</h2>" . EOL. EOL;
-		$o .= visible_lf($bbcode) . EOL. EOL;
+		$o .= "<h2>" . t("bb2md2html2bb: ") . "</h2>" . EOL. EOL; 
+		$o .= visible_lf($bbcode) . EOL. EOL; 
 
 
 
@@ -67,15 +66,14 @@ function babel_content(&$a) {
 	if(x($_REQUEST,'d2bbtext')) {
 
 		$d2bbtext = trim($_REQUEST['d2bbtext']);
-		$o .= "<h2>" . t("Source input (Diaspora format): ") . "</h2>" . EOL. EOL;
-		$o .= visible_lf($d2bbtext) . EOL. EOL;
+		$o .= "<h2>" . t("Source input (Diaspora format): ") . "</h2>" . EOL. EOL; 
+		$o .= visible_lf($d2bbtext) . EOL. EOL; 
 
 
 		$bb = diaspora2bb($d2bbtext);
-		$o .= "<h2>" . t("diaspora2bb: ") . "</h2>" . EOL. EOL;
-		$o .= visible_lf($bb) . EOL. EOL;
+		$o .= "<h2>" . t("diaspora2bb: ") . "</h2>" . EOL. EOL; 
+		$o .= visible_lf($bb) . EOL. EOL; 
 	}
 
 	return $o;
 }
-}
diff --git a/mod/bookmarklet.php b/mod/bookmarklet.php
index 4db6bf401e..be8645c1fd 100644
--- a/mod/bookmarklet.php
+++ b/mod/bookmarklet.php
@@ -1,14 +1,12 @@
 <?php
+
 require_once('include/conversation.php');
 require_once('include/items.php');
 
-if(! function_exists('bookmarklet_init')) {
 function bookmarklet_init(&$a) {
 	$_GET["mode"] = "minimal";
 }
-}
 
-if(! function_exists('bookmarklet_content')) {
 function bookmarklet_content(&$a) {
 	if(!local_user()) {
 		$o = '<h2>'.t('Login').'</h2>';
@@ -46,4 +44,3 @@ function bookmarklet_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/cb.php b/mod/cb.php
index 04d01302c1..6375d23984 100644
--- a/mod/cb.php
+++ b/mod/cb.php
@@ -4,28 +4,21 @@
  * General purpose landing page for plugins/addons
  */
 
-if(! function_exists('cb_init')) {
+
 function cb_init(&$a) {
 	call_hooks('cb_init');
 }
-}
 
-if(! function_exists('cb_post')) {
 function cb_post(&$a) {
 	call_hooks('cb_post', $_POST);
 }
-}
 
-if(! function_exists('cb_afterpost')) {
 function cb_afterpost(&$a) {
 	call_hooks('cb_afterpost');
 }
-}
 
-if(! function_exists('cb_content')) {
 function cb_content(&$a) {
 	$o = '';
 	call_hooks('cb_content', $o);
 	return $o;
-}
-}
+}
\ No newline at end of file
diff --git a/mod/common.php b/mod/common.php
index 4cdbe9641b..c9409b3ef1 100644
--- a/mod/common.php
+++ b/mod/common.php
@@ -5,7 +5,6 @@ require_once('include/Contact.php');
 require_once('include/contact_selectors.php');
 require_once('mod/contacts.php');
 
-if(! function_exists('common_content')) {
 function common_content(&$a) {
 
 	$o = '';
@@ -145,4 +144,3 @@ function common_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/community.php b/mod/community.php
index c64c6216b1..b6d72a3555 100644
--- a/mod/community.php
+++ b/mod/community.php
@@ -1,14 +1,15 @@
 <?php
-if(! function_exists('community_init')) {
+
 function community_init(&$a) {
 	if(! local_user()) {
 		unset($_SESSION['theme']);
 		unset($_SESSION['mobile-theme']);
 	}
-}
+
+
 }
 
-if(! function_exists('community_content')) {
+
 function community_content(&$a, $update = 0) {
 
 	$o = '';
@@ -114,9 +115,7 @@ function community_content(&$a, $update = 0) {
 
 	return $o;
 }
-}
 
-if(! function_exists('community_getitems')) {
 function community_getitems($start, $itemspage) {
 	if (get_config('system','community_page_style') == CP_GLOBAL_COMMUNITY)
 		return(community_getpublicitems($start, $itemspage));
@@ -141,10 +140,9 @@ function community_getitems($start, $itemspage) {
 	);
 
 	return($r);
-}
+
 }
 
-if(! function_exists('community_getpublicitems')) {
 function community_getpublicitems($start, $itemspage) {
 	$r = q("SELECT `item`.`uri`, `item`.*, `item`.`id` AS `item_id`,
 			`author-name` AS `name`, `owner-avatar` AS `photo`,
@@ -159,4 +157,3 @@ function community_getpublicitems($start, $itemspage) {
 
 	return($r);
 }
-}
diff --git a/mod/contactgroup.php b/mod/contactgroup.php
index 0291350b21..bf81afe079 100644
--- a/mod/contactgroup.php
+++ b/mod/contactgroup.php
@@ -2,7 +2,6 @@
 
 require_once('include/group.php');
 
-if(! function_exists('contactgroup_content')) {
 function contactgroup_content(&$a) {
 
 
@@ -48,5 +47,4 @@ function contactgroup_content(&$a) {
 	}
 
 	killme();
-}
-}
+}
\ No newline at end of file
diff --git a/mod/contacts.php b/mod/contacts.php
index cef8bdb897..0b421433e0 100644
--- a/mod/contacts.php
+++ b/mod/contacts.php
@@ -7,7 +7,6 @@ require_once('include/Scrape.php');
 require_once('mod/proxy.php');
 require_once('include/Photo.php');
 
-if(! function_exists('contacts_init')) {
 function contacts_init(&$a) {
 	if(! local_user())
 		return;
@@ -39,7 +38,7 @@ function contacts_init(&$a) {
 
 			if (($a->data['contact']['network'] != "") AND ($a->data['contact']['network'] != NETWORK_DFRN)) {
 				$networkname = format_network_name($a->data['contact']['network'],$a->data['contact']['url']);
-			} else
+			} else 
 				$networkname = '';
 
 			$vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"),array(
@@ -89,10 +88,9 @@ function contacts_init(&$a) {
 		'$base' => $base
 	));
 
-}
+
 }
 
-if(! function_exists('contacts_batch_actions')) {
 function contacts_batch_actions(&$a){
 	$contacts_id = $_POST['contact_batch'];
 	if (!is_array($contacts_id)) return;
@@ -134,10 +132,10 @@ function contacts_batch_actions(&$a){
 		goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']);
 	else
 		goaway($a->get_baseurl(true) . '/contacts');
-}
+
 }
 
-if(! function_exists('contacts_post')) {
+
 function contacts_post(&$a) {
 
 	if(! local_user())
@@ -217,11 +215,10 @@ function contacts_post(&$a) {
 		$a->data['contact'] = $r[0];
 
 	return;
-}
+
 }
 
 /*contact actions*/
-if(! function_exists('_contact_update')) {
 function _contact_update($contact_id) {
 	$r = q("SELECT `uid`, `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id));
 	if (!$r)
@@ -242,9 +239,7 @@ function _contact_update($contact_id) {
 		// pull feed and consume it, which should subscribe to the hub.
 		proc_run('php',"include/onepoll.php","$contact_id", "force");
 }
-}
 
-if(! function_exists('_contact_update_profile')) {
 function _contact_update_profile($contact_id) {
 	$r = q("SELECT `uid`, `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id));
 	if (!$r)
@@ -304,9 +299,7 @@ function _contact_update_profile($contact_id) {
 	// Update the entry in the gcontact table
 	update_gcontact_from_probe($data["url"]);
 }
-}
 
-if(! function_exists('_contact_block')) {
 function _contact_block($contact_id, $orig_record) {
 	$blocked = (($orig_record['blocked']) ? 0 : 1);
 	$r = q("UPDATE `contact` SET `blocked` = %d WHERE `id` = %d AND `uid` = %d",
@@ -315,10 +308,8 @@ function _contact_block($contact_id, $orig_record) {
 		intval(local_user())
 	);
 	return $r;
-}
-}
 
-if(! function_exists('_contact_ignore')) {
+}
 function _contact_ignore($contact_id, $orig_record) {
 	$readonly = (($orig_record['readonly']) ? 0 : 1);
 	$r = q("UPDATE `contact` SET `readonly` = %d WHERE `id` = %d AND `uid` = %d",
@@ -328,9 +319,6 @@ function _contact_ignore($contact_id, $orig_record) {
 	);
 	return $r;
 }
-}
-
-if(! function_exists('_contact_archive')) {
 function _contact_archive($contact_id, $orig_record) {
 	$archived = (($orig_record['archive']) ? 0 : 1);
 	$r = q("UPDATE `contact` SET `archive` = %d WHERE `id` = %d AND `uid` = %d",
@@ -343,18 +331,14 @@ function _contact_archive($contact_id, $orig_record) {
 	}
 	return $r;
 }
-}
-
-if(! function_exists('_contact_drop')) {
 function _contact_drop($contact_id, $orig_record) {
 	$a = get_app();
 
 	terminate_friendship($a->user,$a->contact,$orig_record);
 	contact_remove($orig_record['id']);
 }
-}
 
-if(! function_exists('contacts_content')) {
+
 function contacts_content(&$a) {
 
 	$sort_type = 0;
@@ -815,9 +799,7 @@ function contacts_content(&$a) {
 
 	return $o;
 }
-}
 
-if(! function_exists('contacts_tab')) {
 function contacts_tab($a, $contact_id, $active_tab) {
 	// tabs
 	$tabs = array(
@@ -891,9 +873,7 @@ function contacts_tab($a, $contact_id, $active_tab) {
 
 	return $tab_str;
 }
-}
 
-if(! function_exists('contact_posts')) {
 function contact_posts($a, $contact_id) {
 
 	$r = q("SELECT `url` FROM `contact` WHERE `id` = %d", intval($contact_id));
@@ -921,9 +901,7 @@ function contact_posts($a, $contact_id) {
 
 	return $o;
 }
-}
 
-if(! function_exists('_contact_detail_for_template')) {
 function _contact_detail_for_template($rr){
 
 	$community = '';
@@ -974,5 +952,5 @@ function _contact_detail_for_template($rr){
 		'url' => $url,
 		'network' => network_to_name($rr['network'], $rr['url']),
 	);
-}
+
 }
diff --git a/mod/content.php b/mod/content.php
index ab0fe7e4bf..c5a5556116 100644
--- a/mod/content.php
+++ b/mod/content.php
@@ -15,7 +15,7 @@
 // fast - e.g. one or two milliseconds to fetch parent items for the current content,
 // and 10-20 milliseconds to fetch all the child items.
 
-if(! function_exists('content_content')) {
+
 function content_content(&$a, $update = 0) {
 
 	require_once('include/conversation.php');
@@ -61,7 +61,7 @@ function content_content(&$a, $update = 0) {
 
 	$o = '';
 
-
+	
 
 	$contact_id = $a->cid;
 
@@ -100,7 +100,7 @@ function content_content(&$a, $update = 0) {
 			$def_acl = array('allow_cid' => $str);
 	}
 
-
+	
 	$sql_options  = (($star) ? " and starred = 1 " : '');
 	$sql_options .= (($bmark) ? " and bookmark = 1 " : '');
 
@@ -137,7 +137,7 @@ function content_content(&$a, $update = 0) {
 	}
 	elseif($cid) {
 
-		$r = q("SELECT `id`,`name`,`network`,`writable`,`nurl` FROM `contact` WHERE `id` = %d
+		$r = q("SELECT `id`,`name`,`network`,`writable`,`nurl` FROM `contact` WHERE `id` = %d 
 				AND `blocked` = 0 AND `pending` = 0 LIMIT 1",
 			intval($cid)
 		);
@@ -304,9 +304,9 @@ function content_content(&$a, $update = 0) {
 	echo json_encode($o);
 	killme();
 }
-}
 
-if(! function_exists('render_content')) {
+
+
 function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 	require_once('include/bbcode.php');
@@ -373,7 +373,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 		if($mode === 'network-new' || $mode === 'search' || $mode === 'community') {
 
-			// "New Item View" on network page or search page results
+			// "New Item View" on network page or search page results 
 			// - just loop through the items and format them minimally for display
 
 			//$tpl = get_markup_template('search_item.tpl');
@@ -389,7 +389,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 				$sparkle     = '';
 
 				if($mode === 'search' || $mode === 'community') {
-					if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE)))
+					if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) 
 						&& ($item['id'] != $item['parent']))
 						continue;
 					$nickname = $item['nickname'];
@@ -436,7 +436,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 				$drop = array(
 					'dropping' => $dropping,
-					'select' => t('Select'),
+					'select' => t('Select'), 
 					'delete' => t('Delete'),
 				);
 
@@ -526,11 +526,11 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 						$comments[$item['parent']] = 1;
 					else
 						$comments[$item['parent']] += 1;
-				} elseif(! x($comments,$item['parent']))
+				} elseif(! x($comments,$item['parent'])) 
 					$comments[$item['parent']] = 0; // avoid notices later on
 			}
 
-			// map all the like/dislike activities for each parent item
+			// map all the like/dislike activities for each parent item 
 			// Store these in the $alike and $dlike arrays
 
 			foreach($items as $item) {
@@ -617,14 +617,14 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 				$redirect_url = $a->get_baseurl($ssl_state) . '/redir/' . $item['cid'] ;
 
-				$lock = ((($item['private'] == 1) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
+				$lock = ((($item['private'] == 1) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid']) 
 					|| strlen($item['deny_cid']) || strlen($item['deny_gid']))))
 					? t('Private Message')
 					: false);
 
 
 				// Top-level wall post not written by the wall owner (wall-to-wall)
-				// First figure out who owns it.
+				// First figure out who owns it. 
 
 				$osparkle = '';
 
@@ -651,13 +651,13 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 						if((! $owner_linkmatch) && (! $alias_linkmatch) && (! $owner_namematch)) {
 
 							// The author url doesn't match the owner (typically the contact)
-							// and also doesn't match the contact alias.
-							// The name match is a hack to catch several weird cases where URLs are
+							// and also doesn't match the contact alias. 
+							// The name match is a hack to catch several weird cases where URLs are 
 							// all over the park. It can be tricked, but this prevents you from
 							// seeing "Bob Smith to Bob Smith via Wall-to-wall" and you know darn
-							// well that it's the same Bob Smith.
+							// well that it's the same Bob Smith. 
 
-							// But it could be somebody else with the same name. It just isn't highly likely.
+							// But it could be somebody else with the same name. It just isn't highly likely. 
 
 
 							$owner_url = $item['owner-link'];
@@ -666,7 +666,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 							$template = $wallwall;
 							$commentww = 'ww';
 							// If it is our contact, use a friendly redirect link
-							if((link_compare($item['owner-link'],$item['url']))
+							if((link_compare($item['owner-link'],$item['url'])) 
 								&& ($item['network'] === NETWORK_DFRN)) {
 								$owner_url = $redirect_url;
 								$osparkle = ' sparkle';
@@ -678,7 +678,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 				}
 
 				$likebuttons = '';
-				$shareable = ((($profile_owner == local_user()) && ($item['private'] != 1)) ? true : false);
+				$shareable = ((($profile_owner == local_user()) && ($item['private'] != 1)) ? true : false); 
 
 				if($page_writeable) {
 /*					if($toplevelpost) {  */
@@ -698,7 +698,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 					if(($show_comment_box) || (($show_comment_box == false) && ($override_comment_box == false) && ($item['last-child']))) {
 						$comment = replace_macros($cmnt_tpl,array(
-							'$return_path' => '',
+							'$return_path' => '', 
 							'$jsreload' => (($mode === 'display') ? $_SESSION['return_url'] : ''),
 							'$type' => (($mode === 'profile') ? 'wall-comment' : 'net-comment'),
 							'$id' => $item['item_id'],
@@ -739,7 +739,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 				$drop = array(
 					'dropping' => $dropping,
-					'select' => t('Select'),
+					'select' => t('Select'), 
 					'delete' => t('Delete'),
 				);
 
@@ -805,9 +805,9 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 				$shiny = "";
 				if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
-					$shiny = 'shiny';
+					$shiny = 'shiny'; 
 
-				//
+				// 
 				localize_item($item);
 
 
@@ -897,5 +897,5 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 
 
 	return $threads;
-}
+
 }
diff --git a/mod/credits.php b/mod/credits.php
index 8e6321760b..f8cfb03f37 100644
--- a/mod/credits.php
+++ b/mod/credits.php
@@ -5,7 +5,6 @@
  * addons repository will be listed though ATM)
  */
 
-if(! function_exists('credits_content')) {
 function credits_content (&$a) {
     /* fill the page with credits */
     $f = fopen('util/credits.txt','r');
@@ -19,4 +18,3 @@ function credits_content (&$a) {
        '$names'         => $arr,
     ));
 }
-}
diff --git a/mod/crepair.php b/mod/crepair.php
index 50502b4987..5b4db09dac 100644
--- a/mod/crepair.php
+++ b/mod/crepair.php
@@ -2,7 +2,6 @@
 require_once("include/contact_selectors.php");
 require_once("mod/contacts.php");
 
-if(! function_exists('crepair_init')) {
 function crepair_init(&$a) {
 	if(! local_user())
 		return;
@@ -29,9 +28,8 @@ function crepair_init(&$a) {
 		profile_load($a, "", 0, get_contact_details_by_url($contact["url"]));
 	}
 }
-}
 
-if(! function_exists('crepair_post')) {
+
 function crepair_post(&$a) {
 	if(! local_user())
 		return;
@@ -93,9 +91,9 @@ function crepair_post(&$a) {
 
 	return;
 }
-}
 
-if(! function_exists('crepair_content')) {
+
+
 function crepair_content(&$a) {
 
 	if(! local_user()) {
@@ -182,5 +180,5 @@ function crepair_content(&$a) {
 	));
 
 	return $o;
-}
+
 }
diff --git a/mod/delegate.php b/mod/delegate.php
index d421de3764..20d2e605e0 100644
--- a/mod/delegate.php
+++ b/mod/delegate.php
@@ -1,13 +1,11 @@
 <?php
 require_once('mod/settings.php');
 
-if(! function_exists('delegate_init')) {
 function delegate_init(&$a) {
 	return settings_init($a);
 }
-}
 
-if(! function_exists('delegate_content')) {
+
 function delegate_content(&$a) {
 
 	if(! local_user()) {
@@ -92,12 +90,12 @@ function delegate_content(&$a) {
 
 	// find every contact who might be a candidate for delegation
 
-	$r = q("select nurl from contact where substring_index(contact.nurl,'/',3) = '%s'
+	$r = q("select nurl from contact where substring_index(contact.nurl,'/',3) = '%s' 
 		and contact.uid = %d and contact.self = 0 and network = '%s' ",
 		dbesc(normalise_link($a->get_baseurl())),
 		intval(local_user()),
 		dbesc(NETWORK_DFRN)
-	);
+	); 
 
 	if(! count($r)) {
 		notice( t('No potential page delegates located.') . EOL);
@@ -146,5 +144,5 @@ function delegate_content(&$a) {
 
 	return $o;
 
-}
+
 }
diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php
index 00e215e334..27c04a908d 100644
--- a/mod/dfrn_confirm.php
+++ b/mod/dfrn_confirm.php
@@ -16,7 +16,6 @@
 
 require_once('include/enotify.php');
 
-if(! function_exists('dfrn_confirm_post')) {
 function dfrn_confirm_post(&$a,$handsfree = null) {
 
 	if(is_array($handsfree)) {
@@ -802,5 +801,5 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
 
 	goaway(z_root());
 	// NOTREACHED
-}
+
 }
diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php
index 04500e89ad..4aa777b550 100644
--- a/mod/dfrn_notify.php
+++ b/mod/dfrn_notify.php
@@ -5,7 +5,6 @@ require_once('include/event.php');
 
 require_once('library/defuse/php-encryption-1.2.1/Crypto.php');
 
-if(! function_exists('dfrn_notify_post')) {
 function dfrn_notify_post(&$a) {
     logger(__function__, LOGGER_TRACE);
 	$dfrn_id      = ((x($_POST,'dfrn_id'))      ? notags(trim($_POST['dfrn_id']))   : '');
@@ -214,9 +213,8 @@ function dfrn_notify_post(&$a) {
 
 	// NOTREACHED
 }
-}
 
-if(! function_exists('dfrn_notify_content')) {
+
 function dfrn_notify_content(&$a) {
 
 	if(x($_GET,'dfrn_id')) {
@@ -340,5 +338,5 @@ function dfrn_notify_content(&$a) {
 
 		killme();
 	}
-}
+
 }
diff --git a/mod/dfrn_poll.php b/mod/dfrn_poll.php
index 82c75d28cf..ab6637607e 100644
--- a/mod/dfrn_poll.php
+++ b/mod/dfrn_poll.php
@@ -3,7 +3,7 @@ require_once('include/items.php');
 require_once('include/auth.php');
 require_once('include/dfrn.php');
 
-if(! function_exists('dfrn_poll_init')) {
+
 function dfrn_poll_init(&$a) {
 
 
@@ -160,7 +160,7 @@ function dfrn_poll_init(&$a) {
 
 			if($final_dfrn_id != $orig_id) {
 				logger('profile_check: ' . $final_dfrn_id . ' != ' . $orig_id, LOGGER_DEBUG);
-				// did not decode properly - cannot trust this site
+				// did not decode properly - cannot trust this site 
 				xml_status(3, 'Bad decryption');
 			}
 
@@ -195,11 +195,11 @@ function dfrn_poll_init(&$a) {
 			return; // NOTREACHED
 		}
 	}
-}
+
 }
 
 
-if(! function_exists('dfrn_poll_post')) {
+
 function dfrn_poll_post(&$a) {
 
 	$dfrn_id      = ((x($_POST,'dfrn_id'))      ? $_POST['dfrn_id']              : '');
@@ -257,7 +257,7 @@ function dfrn_poll_post(&$a) {
 
 			if($final_dfrn_id != $orig_id) {
 				logger('profile_check: ' . $final_dfrn_id . ' != ' . $orig_id, LOGGER_DEBUG);
-				// did not decode properly - cannot trust this site
+				// did not decode properly - cannot trust this site 
 				xml_status(3, 'Bad decryption');
 			}
 
@@ -377,9 +377,7 @@ function dfrn_poll_post(&$a) {
 
 	}
 }
-}
 
-if(! function_exists('dfrn_poll_content')) {
 function dfrn_poll_content(&$a) {
 
 	$dfrn_id         = ((x($_GET,'dfrn_id'))         ? $_GET['dfrn_id']              : '');
@@ -564,4 +562,3 @@ function dfrn_poll_content(&$a) {
 		}
 	}
 }
-}
diff --git a/mod/directory.php b/mod/directory.php
index 7ce1530efc..294a55585d 100644
--- a/mod/directory.php
+++ b/mod/directory.php
@@ -1,5 +1,5 @@
 <?php
-if(! function_exists('directory_init')) {
+
 function directory_init(&$a) {
 	$a->set_pager_itemspage(60);
 
@@ -16,23 +16,23 @@ function directory_init(&$a) {
 		unset($_SESSION['mobile-theme']);
 	}
 
-}
+
 }
 
-if(! function_exists('directory_post')) {
+
 function directory_post(&$a) {
 	if(x($_POST,'search'))
 		$a->data['search'] = $_POST['search'];
 }
-}
 
-if(! function_exists('directory_content')) {
+
+
 function directory_content(&$a) {
 	global $db;
 
 	require_once("mod/proxy.php");
 
-	if((get_config('system','block_public')) && (! local_user()) && (! remote_user()) ||
+	if((get_config('system','block_public')) && (! local_user()) && (! remote_user()) || 
 		(get_config('system','block_local_dir')) && (! local_user()) && (! remote_user())) {
 		notice( t('Public access denied.') . EOL);
 		return;
@@ -123,14 +123,14 @@ function directory_content(&$a) {
 			}
 //			if(strlen($rr['dob'])) {
 //				if(($years = age($rr['dob'],$rr['timezone'],'')) != 0)
-//					$details .= '<br />' . t('Age: ') . $years ;
+//					$details .= '<br />' . t('Age: ') . $years ; 
 //			}
 //			if(strlen($rr['gender']))
 //				$details .= '<br />' . t('Gender: ') . $rr['gender'];
 
 
 			// show if account is a community account
-			/// @TODO The other page types should be also respected, but first we need a good
+			/// @TODO The other page types should be also respected, but first we need a good 
 			/// translatiion and systemwide consistency for displaying the page type
 			if((intval($rr['page-flags']) == PAGE_COMMUNITY) OR (intval($rr['page-flags']) == PAGE_PRVGROUP))
 				$community = true;
@@ -158,7 +158,7 @@ function directory_content(&$a) {
 			else {
 				$location_e = $location;
 			}
-
+			
 			$photo_menu = array(array(t("View Profile"), zrl($profile_link)));
 
 			$entry = array(
@@ -217,4 +217,3 @@ function directory_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/dirfind.php b/mod/dirfind.php
index f5e90705b7..0dfe4d67a9 100644
--- a/mod/dirfind.php
+++ b/mod/dirfind.php
@@ -5,7 +5,6 @@ require_once('include/Contact.php');
 require_once('include/contact_selectors.php');
 require_once('mod/contacts.php');
 
-if(! function_exists('dirfind_init')) {
 function dirfind_init(&$a) {
 
 	if(! local_user()) {
@@ -20,9 +19,9 @@ function dirfind_init(&$a) {
 
 	$a->page['aside'] .= follow_widget();
 }
-}
 
-if(! function_exists('dirfind_content')) {
+
+
 function dirfind_content(&$a, $prefix = "") {
 
 	$community = false;
@@ -236,4 +235,3 @@ function dirfind_content(&$a, $prefix = "") {
 
 	return $o;
 }
-}
diff --git a/mod/display.php b/mod/display.php
index 9995a2b3ef..4e33927072 100644
--- a/mod/display.php
+++ b/mod/display.php
@@ -1,5 +1,5 @@
 <?php
-if(! function_exists('display_init')) {
+
 function display_init(&$a) {
 
 	if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
@@ -85,10 +85,9 @@ function display_init(&$a) {
 	}
 
 	profile_load($a, $nick, 0, $profiledata);
-}
+
 }
 
-if(! function_exists('display_fetchauthor')) {
 function display_fetchauthor($a, $item) {
 
 	$profiledata = array();
@@ -221,9 +220,7 @@ function display_fetchauthor($a, $item) {
 
 	return($profiledata);
 }
-}
 
-if(! function_exists('display_content')) {
 function display_content(&$a, $update = 0) {
 
 	if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
@@ -525,4 +522,4 @@ function display_content(&$a, $update = 0) {
 
 	return $o;
 }
-}
+
diff --git a/mod/editpost.php b/mod/editpost.php
index ee4d61e60a..9a80d0b2f4 100644
--- a/mod/editpost.php
+++ b/mod/editpost.php
@@ -2,7 +2,6 @@
 
 require_once('include/acl_selectors.php');
 
-if(! function_exists('editpost_content')) {
 function editpost_content(&$a) {
 
 	$o = '';
@@ -151,5 +150,7 @@ function editpost_content(&$a) {
 	));
 
 	return $o;
+
 }
-}
+
+
diff --git a/mod/events.php b/mod/events.php
index 3dc20e535a..653ae489b8 100644
--- a/mod/events.php
+++ b/mod/events.php
@@ -5,7 +5,6 @@ require_once('include/datetime.php');
 require_once('include/event.php');
 require_once('include/items.php');
 
-if(! function_exists('events_post')) {
 function events_post(&$a) {
 
 	logger('post: ' . print_r($_REQUEST,true));
@@ -157,9 +156,9 @@ function events_post(&$a) {
 
 	goaway($_SESSION['return_url']);
 }
-}
 
-if(! function_exists('events_content')) {
+
+
 function events_content(&$a) {
 
 	if(! local_user()) {
@@ -579,4 +578,3 @@ function events_content(&$a) {
 		return $o;
 	}
 }
-}
diff --git a/mod/fbrowser.php b/mod/fbrowser.php
index 73510ef58a..0a2a7dead5 100644
--- a/mod/fbrowser.php
+++ b/mod/fbrowser.php
@@ -10,7 +10,6 @@ require_once('include/Photo.php');
 /**
  * @param App $a
  */
-if(! function_exists('fbrowser_content')) {
 function fbrowser_content($a){
 
 	if (!local_user())
@@ -142,5 +141,5 @@ function fbrowser_content($a){
 		killme();
 	}
 
-}
+
 }
diff --git a/mod/filer.php b/mod/filer.php
index 02b8d68978..4e79f337dc 100644
--- a/mod/filer.php
+++ b/mod/filer.php
@@ -4,7 +4,7 @@ require_once('include/security.php');
 require_once('include/bbcode.php');
 require_once('include/items.php');
 
-if(! function_exists('filer_content')) {
+
 function filer_content(&$a) {
 
 	if(! local_user()) {
@@ -30,9 +30,8 @@ function filer_content(&$a) {
 			'$field' => array('term', t("Save to Folder:"), '', '', $filetags, t('- select -')),
 			'$submit' => t('Save'),
 		));
-
+		
 		echo $o;
 	}
 	killme();
 }
-}
diff --git a/mod/filerm.php b/mod/filerm.php
index be3456b58d..c266082c8f 100644
--- a/mod/filerm.php
+++ b/mod/filerm.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('filerm_content')) {
 function filerm_content(&$a) {
 
 	if(! local_user()) {
@@ -26,4 +25,3 @@ function filerm_content(&$a) {
 
 	killme();
 }
-}
diff --git a/mod/follow.php b/mod/follow.php
index a8fdc31b5a..b92a0d980f 100644
--- a/mod/follow.php
+++ b/mod/follow.php
@@ -5,7 +5,6 @@ require_once('include/follow.php');
 require_once('include/Contact.php');
 require_once('include/contact_selectors.php');
 
-if(! function_exists('follow_content')) {
 function follow_content(&$a) {
 
 	if(! local_user()) {
@@ -149,9 +148,7 @@ function follow_content(&$a) {
 
 	return $o;
 }
-}
 
-if(! function_exists('follow_post')) {
 function follow_post(&$a) {
 
 	if(! local_user()) {
@@ -188,4 +185,3 @@ function follow_post(&$a) {
 	goaway($return_url);
 	// NOTREACHED
 }
-}
diff --git a/mod/friendica.php b/mod/friendica.php
index 18d045f2d5..aad5964baf 100644
--- a/mod/friendica.php
+++ b/mod/friendica.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('friendica_init')) {
 function friendica_init(&$a) {
 	if ($a->argv[1]=="json"){
 		$register_policy = Array('REGISTER_CLOSED', 'REGISTER_APPROVE', 'REGISTER_OPEN');
@@ -57,9 +56,9 @@ function friendica_init(&$a) {
 		killme();
 	}
 }
-}
 
-if(! function_exists('friendica_content')) {
+
+
 function friendica_content(&$a) {
 
 	$o = '';
@@ -71,7 +70,7 @@ function friendica_content(&$a) {
 	$o .= t('This is Friendica, version') . ' ' . FRIENDICA_VERSION . ' ';
 	$o .= t('running at web location') . ' ' . z_root() . '</p><p>';
 
-	$o .= t('Please visit <a href="http://friendica.com">Friendica.com</a> to learn more about the Friendica project.') . '</p><p>';
+	$o .= t('Please visit <a href="http://friendica.com">Friendica.com</a> to learn more about the Friendica project.') . '</p><p>';	
 
 	$o .= t('Bug reports and issues: please visit') . ' ' . '<a href="https://github.com/friendica/friendica/issues?state=open">'.t('the bugtracker at github').'</a></p><p>';
 	$o .= t('Suggestions, praise, donations, etc. - please email "Info" at Friendica - dot com') . '</p>';
@@ -103,8 +102,8 @@ function friendica_content(&$a) {
 	else
 		$o .= '<p>' . t('No installed plugins/addons/apps') . '</p>';
 
-	call_hooks('about_hook', $o);
+	call_hooks('about_hook', $o); 	
 
 	return $o;
-}
+
 }
diff --git a/mod/fsuggest.php b/mod/fsuggest.php
index 26a5e98063..6b1cbd7533 100644
--- a/mod/fsuggest.php
+++ b/mod/fsuggest.php
@@ -1,6 +1,6 @@
 <?php
 
-if(! function_exists('fsuggest_post')) {
+
 function fsuggest_post(&$a) {
 
 	if(! local_user()) {
@@ -39,11 +39,11 @@ function fsuggest_post(&$a) {
 				VALUES ( %d, %d, '%s','%s','%s','%s','%s','%s')",
 				intval(local_user()),
 				intval($contact_id),
-				dbesc($r[0]['name']),
-				dbesc($r[0]['url']),
-				dbesc($r[0]['request']),
-				dbesc($r[0]['photo']),
-				dbesc($hash),
+				dbesc($r[0]['name']), 
+				dbesc($r[0]['url']), 
+				dbesc($r[0]['request']), 
+				dbesc($r[0]['photo']), 
+				dbesc($hash), 
 				dbesc(datetime_convert())
 			);
 			$r = q("SELECT `id` FROM `fsuggest` WHERE `note` = '%s' AND `uid` = %d LIMIT 1",
@@ -65,11 +65,11 @@ function fsuggest_post(&$a) {
 
 	}
 
-}
+
 }
 
 
-if(! function_exists('fsuggest_content')) {
+
 function fsuggest_content(&$a) {
 
 	require_once('include/acl_selectors.php');
@@ -100,7 +100,7 @@ function fsuggest_content(&$a) {
 
 	$o .= '<form id="fsuggest-form" action="fsuggest/' . $contact_id . '" method="post" >';
 
-	$o .= contact_selector('suggest','suggest-select', false,
+	$o .= contact_selector('suggest','suggest-select', false, 
 		array('size' => 4, 'exclude' => $contact_id, 'networks' => 'DFRN_ONLY', 'single' => true));
 
 
@@ -109,4 +109,3 @@ function fsuggest_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/group.php b/mod/group.php
index 2f8053eefb..5b28784f56 100644
--- a/mod/group.php
+++ b/mod/group.php
@@ -1,21 +1,18 @@
 <?php
 
-if(! function_exists('validate_members')) {
 function validate_members(&$item) {
 	$item = intval($item);
 }
-}
 
-if(! function_exists('group_init')) {
 function group_init(&$a) {
 	if(local_user()) {
 		require_once('include/group.php');
 		$a->page['aside'] = group_side('contacts','group','extended',(($a->argc > 1) ? intval($a->argv[1]) : 0));
 	}
 }
-}
 
-if(! function_exists('group_post')) {
+
+
 function group_post(&$a) {
 
 	if(! local_user()) {
@@ -67,9 +64,7 @@ function group_post(&$a) {
 	}
 	return;
 }
-}
 
-if(! function_exists('group_content')) {
 function group_content(&$a) {
 	$change = false;
 
@@ -234,5 +229,5 @@ function group_content(&$a) {
 	}
 
 	return replace_macros($tpl, $context);
-}
+
 }
diff --git a/mod/hcard.php b/mod/hcard.php
index af49423de3..6d2d9e2ebf 100644
--- a/mod/hcard.php
+++ b/mod/hcard.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('hcard_init')) {
 function hcard_init(&$a) {
 
 	$blocked = (((get_config('system','block_public')) && (! local_user()) && (! remote_user())) ? true : false);
@@ -16,7 +15,7 @@ function hcard_init(&$a) {
 	$profile = 0;
 	if((local_user()) && ($a->argc > 2) && ($a->argv[2] === 'view')) {
 		$which = $a->user['nickname'];
-		$profile = $a->argv[1];
+		$profile = $a->argv[1];		
 	}
 
 	profile_load($a,$which,$profile);
@@ -24,7 +23,7 @@ function hcard_init(&$a) {
 	if((x($a->profile,'page-flags')) && ($a->profile['page-flags'] == PAGE_COMMUNITY)) {
 		$a->page['htmlhead'] .= '<meta name="friendica.community" content="true" />';
 	}
-	if(x($a->profile,'openidserver'))
+	if(x($a->profile,'openidserver'))				
 		$a->page['htmlhead'] .= '<link rel="openid.server" href="' . $a->profile['openidserver'] . '" />' . "\r\n";
 	if(x($a->profile,'openid')) {
 		$delegate = ((strstr($a->profile['openid'],'://')) ? $a->profile['openid'] : 'http://' . $a->profile['openid']);
@@ -43,9 +42,10 @@ function hcard_init(&$a) {
 	$uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->get_hostname() . (($a->path) ? '/' . $a->path : ''));
 	$a->page['htmlhead'] .= '<link rel="lrdd" type="application/xrd+xml" href="' . $a->get_baseurl() . '/xrd/?uri=' . $uri . '" />' . "\r\n";
 	header('Link: <' . $a->get_baseurl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false);
-
+  	
 	$dfrn_pages = array('request', 'confirm', 'notify', 'poll');
 	foreach($dfrn_pages as $dfrn)
 		$a->page['htmlhead'] .= "<link rel=\"dfrn-{$dfrn}\" href=\"".$a->get_baseurl()."/dfrn_{$dfrn}/{$which}\" />\r\n";
+
 }
-}
+
diff --git a/mod/help.php b/mod/help.php
index 320e622fa5..5465d3e900 100644
--- a/mod/help.php
+++ b/mod/help.php
@@ -18,7 +18,6 @@ if (!function_exists('load_doc_file')) {
 
 }
 
-if(! function_exists('help_content')) {
 function help_content(&$a) {
 
 	nav_set_selected('help');
@@ -99,5 +98,5 @@ function help_content(&$a) {
 		}
 		</style>".$html;
 	return $html;
-}
+
 }
diff --git a/mod/hostxrd.php b/mod/hostxrd.php
index 5b178e9b8f..4121764f1a 100644
--- a/mod/hostxrd.php
+++ b/mod/hostxrd.php
@@ -2,7 +2,6 @@
 
 require_once('include/crypto.php');
 
-if(! function_exists('hostxrd_init')) {
 function hostxrd_init(&$a) {
 	header('Access-Control-Allow-Origin: *');
 	header("Content-type: text/xml");
@@ -28,5 +27,5 @@ function hostxrd_init(&$a) {
 	));
 	session_write_close();
 	exit();
-}
+
 }
diff --git a/mod/ignored.php b/mod/ignored.php
index 8a681a1154..e876b4ef8b 100644
--- a/mod/ignored.php
+++ b/mod/ignored.php
@@ -1,6 +1,6 @@
 <?php
 
-if(! function_exists('ignored_init')) {
+
 function ignored_init(&$a) {
 
 	$ignored = 0;
@@ -43,4 +43,3 @@ function ignored_init(&$a) {
 	echo json_encode($ignored);
 	killme();
 }
-}
diff --git a/mod/install.php b/mod/install.php
index be90acba10..8434b38e38 100755
--- a/mod/install.php
+++ b/mod/install.php
@@ -3,7 +3,7 @@ require_once "include/Photo.php";
 
 $install_wizard_pass=1;
 
-if(! function_exists('install_init')) {
+
 function install_init(&$a){
 
 	// $baseurl/install/testrwrite to test if rewite in .htaccess is working
@@ -11,21 +11,20 @@ function install_init(&$a){
 		echo "ok";
 		killme();
 	}
-
+	
 	// We overwrite current theme css, because during install we could not have a working mod_rewrite
 	// so we could not have a css at all. Here we set a static css file for the install procedure pages
 	$a->config['system']['theme'] = "../install";
 	$a->theme['stylesheet'] = $a->get_baseurl()."/view/install/style.css";
-
-
-
+	
+	
+	
 	global $install_wizard_pass;
 	if (x($_POST,'pass'))
 		$install_wizard_pass = intval($_POST['pass']);
-}
+
 }
 
-if(! function_exists('install_post')) {
 function install_post(&$a) {
 	global $install_wizard_pass, $db;
 
@@ -113,18 +112,14 @@ function install_post(&$a) {
 		break;
 	}
 }
-}
 
-if(! function_exists('get_db_errno')) {
 function get_db_errno() {
 	if(class_exists('mysqli'))
 		return mysqli_connect_errno();
 	else
 		return mysql_errno();
 }
-}
 
-if(! function_exists('install_content')) {
 function install_content(&$a) {
 
 	global $install_wizard_pass, $db;
@@ -309,7 +304,6 @@ function install_content(&$a) {
 
 	}
 }
-}
 
 /**
  * checks   : array passed to template
@@ -318,8 +312,7 @@ function install_content(&$a) {
  * required : boolean
  * help		: string optional
  */
-if(! function_exists('check_add')) {
-function check_add(&$checks, $title, $status, $required, $help) {
+function check_add(&$checks, $title, $status, $required, $help){
 	$checks[] = array(
 		'title' => $title,
 		'status' => $status,
@@ -327,9 +320,7 @@ function check_add(&$checks, $title, $status, $required, $help) {
 		'help'	=> $help,
 	);
 }
-}
 
-if(! function_exists('check_php')) {
 function check_php(&$phpath, &$checks) {
 	$passed = $passed2 = $passed3 = false;
 	if (strlen($phpath)){
@@ -379,10 +370,9 @@ function check_php(&$phpath, &$checks) {
 		check_add($checks, t('PHP register_argc_argv'), $passed3, true, $help);
 	}
 
-}
+
 }
 
-if(! function_exists('check_keys')) {
 function check_keys(&$checks) {
 
 	$help = '';
@@ -402,10 +392,10 @@ function check_keys(&$checks) {
 		$help .= t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".');
 	}
 	check_add($checks, t('Generate encryption keys'), $res, true, $help);
-}
+
 }
 
-if(! function_exists('check_funcs')) {
+
 function check_funcs(&$checks) {
 	$ck_funcs = array();
 	check_add($ck_funcs, t('libCurl PHP module'), true, true, "");
@@ -467,9 +457,8 @@ function check_funcs(&$checks) {
 	/*if((x($_SESSION,'sysmsg')) && is_array($_SESSION['sysmsg']) && count($_SESSION['sysmsg']))
 		notice( t('Please see the file "INSTALL.txt".') . EOL);*/
 }
-}
 
-if(! function_exists('check_htconfig')) {
+
 function check_htconfig(&$checks) {
 	$status = true;
 	$help = "";
@@ -484,10 +473,9 @@ function check_htconfig(&$checks) {
 	}
 
 	check_add($checks, t('.htconfig.php is writable'), $status, false, $help);
-}
+
 }
 
-if(! function_exists('check_smarty3')) {
 function check_smarty3(&$checks) {
 	$status = true;
 	$help = "";
@@ -501,10 +489,9 @@ function check_smarty3(&$checks) {
 	}
 
 	check_add($checks, t('view/smarty3 is writable'), $status, true, $help);
-}
+
 }
 
-if(! function_exists('check_htaccess')) {
 function check_htaccess(&$checks) {
 	$a = get_app();
 	$status = true;
@@ -524,9 +511,7 @@ function check_htaccess(&$checks) {
 		// cannot check modrewrite if libcurl is not installed
 	}
 }
-}
 
-if(! function_exists('check_imagik')) {
 function check_imagik(&$checks) {
 	$imagick = false;
 	$gif = false;
@@ -543,18 +528,16 @@ function check_imagik(&$checks) {
 		check_add($checks, t('ImageMagick supports GIF'), $gif, false, "");
 	}
 }
-}
 
-if(! function_exists('manual_config')) {
+
+
 function manual_config(&$a) {
 	$data = htmlentities($a->data['txt'],ENT_COMPAT,'UTF-8');
 	$o = t('The database configuration file ".htconfig.php" could not be written. Please use the enclosed text to create a configuration file in your web server root.');
 	$o .= "<textarea rows=\"24\" cols=\"80\" >$data</textarea>";
 	return $o;
 }
-}
 
-if(! function_exists('load_database_rem')) {
 function load_database_rem($v, $i){
 	$l = trim($i);
 	if (strlen($l)>1 && ($l[0]=="-" || ($l[0]=="/" && $l[1]=="*"))){
@@ -563,9 +546,8 @@ function load_database_rem($v, $i){
 		return $v."\n".$i;
 	}
 }
-}
 
-if(! function_exists('load_database')) {
+
 function load_database($db) {
 
 	require_once("include/dbstructure.php");
@@ -585,9 +567,7 @@ function load_database($db) {
 
 	return $errors;
 }
-}
 
-if(! function_exists('what_next')) {
 function what_next() {
 	$a = get_app();
 	$baseurl = $a->get_baseurl();
@@ -599,4 +579,5 @@ function what_next() {
 		.t("Go to your new Friendica node <a href='$baseurl/register'>registration page</a> and register as new user. Remember to use the same email you have entered as administrator email. This will allow you to enter the site admin panel.")
 		."</p>";
 }
-}
+
+
diff --git a/mod/invite.php b/mod/invite.php
index 1f559dabc0..ccf876c7c0 100644
--- a/mod/invite.php
+++ b/mod/invite.php
@@ -9,7 +9,6 @@
 
 require_once('include/email.php');
 
-if(! function_exists('invite_post')) {
 function invite_post(&$a) {
 
 	if(! local_user()) {
@@ -50,7 +49,7 @@ function invite_post(&$a) {
 			notice(  sprintf( t('%s : Not a valid email address.'), $recip) . EOL);
 			continue;
 		}
-
+		
 		if($invonly && ($x || is_site_admin())) {
 			$code = autoname(8) . srand(1000,9999);
 			$nmessage = str_replace('$invite_code',$code,$message);
@@ -71,8 +70,8 @@ function invite_post(&$a) {
 		else
 			$nmessage = $message;
 
-		$res = mail($recip, email_header_encode( t('Please join us on Friendica'),'UTF-8'),
-			$nmessage,
+		$res = mail($recip, email_header_encode( t('Please join us on Friendica'),'UTF-8'), 
+			$nmessage, 
 			"From: " . $a->user['email'] . "\n"
 			. 'Content-type: text/plain; charset=UTF-8' . "\n"
 			. 'Content-transfer-encoding: 8bit' );
@@ -94,9 +93,8 @@ function invite_post(&$a) {
 	notice( sprintf( tt("%d message sent.", "%d messages sent.", $total) , $total) . EOL);
 	return;
 }
-}
 
-if(! function_exists('invite_content')) {
+
 function invite_content(&$a) {
 
 	if(! local_user()) {
@@ -136,7 +134,7 @@ function invite_content(&$a) {
 		'$msg_text' => t('Your message:'),
 		'$default_message' => t('You are cordially invited to join me and other close friends on Friendica - and help us to create a better social web.') . "\r\n" . "\r\n"
 			. $linktxt
-			. "\r\n" . "\r\n" . (($invonly) ? t('You will need to supply this invitation code: $invite_code') . "\r\n" . "\r\n" : '') .t('Once you have registered, please connect with me via my profile page at:')
+			. "\r\n" . "\r\n" . (($invonly) ? t('You will need to supply this invitation code: $invite_code') . "\r\n" . "\r\n" : '') .t('Once you have registered, please connect with me via my profile page at:') 
 			. "\r\n" . "\r\n" . $a->get_baseurl() . '/profile/' . $a->user['nickname']
 			. "\r\n" . "\r\n" . t('For more information about the Friendica project and why we feel it is important, please visit http://friendica.com') . "\r\n" . "\r\n"  ,
 		'$submit' => t('Submit')
@@ -144,4 +142,3 @@ function invite_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/item.php b/mod/item.php
index f8f2e0fafe..8c5a479646 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -25,7 +25,6 @@ require_once('include/text.php');
 require_once('include/items.php');
 require_once('include/Scrape.php');
 
-if(! function_exists('item_post')) {
 function item_post(&$a) {
 
 	if((! local_user()) && (! remote_user()) && (! x($_REQUEST,'commenter')))
@@ -1018,9 +1017,7 @@ function item_post(&$a) {
 	item_post_return($a->get_baseurl(), $api_source, $return_path);
 	// NOTREACHED
 }
-}
 
-if(! function_exists('item_post_return')) {
 function item_post_return($baseurl, $api_source, $return_path) {
 	// figure out how to return, depending on from whence we came
 
@@ -1040,9 +1037,9 @@ function item_post_return($baseurl, $api_source, $return_path) {
 	echo json_encode($json);
 	killme();
 }
-}
 
-if(! function_exists('item_content')) {
+
+
 function item_content(&$a) {
 
 	if((! local_user()) && (! remote_user()))
@@ -1061,7 +1058,6 @@ function item_content(&$a) {
 	}
 	return $o;
 }
-}
 
 /**
  * This function removes the tag $tag from the text $body and replaces it with
@@ -1075,7 +1071,6 @@ function item_content(&$a) {
  *
  * @return boolean true if replaced, false if not replaced
  */
-if(! function_exists('handle_tag')) {
 function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $network = "") {
 	require_once("include/Scrape.php");
 	require_once("include/socgraph.php");
@@ -1250,9 +1245,8 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
 
 	return array('replaced' => $replaced, 'contact' => $r[0]);
 }
-}
 
-if(! function_exists('store_diaspora_comment_sig')) {
+
 function store_diaspora_comment_sig($datarray, $author, $uprvkey, $parent_item, $post_id) {
 	// We won't be able to sign Diaspora comments for authenticated visitors - we don't have their private key
 
@@ -1290,4 +1284,3 @@ function store_diaspora_comment_sig($datarray, $author, $uprvkey, $parent_item,
 
 	return;
 }
-}
diff --git a/mod/like.php b/mod/like.php
index ef483a1f9e..8d383b9abe 100755
--- a/mod/like.php
+++ b/mod/like.php
@@ -5,7 +5,6 @@ require_once('include/bbcode.php');
 require_once('include/items.php');
 require_once('include/like.php');
 
-if(! function_exists('like_content')) {
 function like_content(&$a) {
 	if(! local_user() && ! remote_user()) {
 		return false;
@@ -29,11 +28,11 @@ function like_content(&$a) {
 	killme(); // NOTREACHED
 //	return; // NOTREACHED
 }
-}
+
 
 // Decide how to return. If we were called with a 'return' argument,
 // then redirect back to the calling page. If not, just quietly end
-if(! function_exists('like_content_return')) {
+
 function like_content_return($baseurl, $return_path) {
 
 	if($return_path) {
@@ -46,4 +45,4 @@ function like_content_return($baseurl, $return_path) {
 
 	killme();
 }
-}
+
diff --git a/mod/localtime.php b/mod/localtime.php
index fc500f4dd9..d1453bc527 100644
--- a/mod/localtime.php
+++ b/mod/localtime.php
@@ -2,7 +2,7 @@
 
 require_once('include/datetime.php');
 
-if(! function_exists('localtime_post')) {
+
 function localtime_post(&$a) {
 
 	$t = $_REQUEST['time'];
@@ -13,10 +13,9 @@ function localtime_post(&$a) {
 
 	if($_POST['timezone'])
 		$a->data['mod-localtime'] = datetime_convert('UTC',$_POST['timezone'],$t,$bd_format);
-}
+
 }
 
-if(! function_exists('localtime_content')) {
 function localtime_content(&$a) {
 	$t = $_REQUEST['time'];
 	if(! $t)
@@ -39,12 +38,12 @@ function localtime_content(&$a) {
 
 	$o .= '<form action ="' . $a->get_baseurl() . '/localtime?f=&time=' . $t . '" method="post" >';
 
-	$o .= '<p>' . t('Please select your timezone:') . '</p>';
+	$o .= '<p>' . t('Please select your timezone:') . '</p>'; 
 
 	$o .= select_timezone(($_REQUEST['timezone']) ? $_REQUEST['timezone'] : 'America/Los_Angeles');
 
 	$o .= '<input type="submit" name="submit" value="' . t('Submit') . '" /></form>';
 
 	return $o;
-}
-}
+
+}
\ No newline at end of file
diff --git a/mod/lockview.php b/mod/lockview.php
index 82f93f4985..0ae54c8c12 100644
--- a/mod/lockview.php
+++ b/mod/lockview.php
@@ -1,8 +1,8 @@
 <?php
 
-if(! function_exists('lockview_content')) {
-function lockview_content(&$a) {
 
+function lockview_content(&$a) {
+  
 	$type = (($a->argc > 1) ? $a->argv[1] : 0);
 	if (is_numeric($type)) {
 		$item_id = intval($type);
@@ -10,13 +10,13 @@ function lockview_content(&$a) {
 	} else {
 		$item_id = (($a->argc > 2) ? intval($a->argv[2]) : 0);
 	}
-
+  
 	if(! $item_id)
 		killme();
 
 	if (!in_array($type, array('item','photo','event')))
 		killme();
-
+     
 	$r = q("SELECT * FROM `%s` WHERE `id` = %d LIMIT 1",
 		dbesc($type),
 		intval($item_id)
@@ -33,7 +33,7 @@ function lockview_content(&$a) {
 	}
 
 
-	if(($item['private'] == 1) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid']))
+	if(($item['private'] == 1) && (! strlen($item['allow_cid'])) && (! strlen($item['allow_gid'])) 
 		&& (! strlen($item['deny_cid'])) && (! strlen($item['deny_gid']))) {
 
 		echo t('Remote privacy information not available.') . '<br />';
@@ -53,7 +53,7 @@ function lockview_content(&$a) {
 			dbesc(implode(', ', $allowed_groups))
 		);
 		if(count($r))
-			foreach($r as $rr)
+			foreach($r as $rr) 
 				$l[] = '<b>' . $rr['name'] . '</b>';
 	}
 	if(count($allowed_users)) {
@@ -61,7 +61,7 @@ function lockview_content(&$a) {
 			dbesc(implode(', ',$allowed_users))
 		);
 		if(count($r))
-			foreach($r as $rr)
+			foreach($r as $rr) 
 				$l[] = $rr['name'];
 
 	}
@@ -71,7 +71,7 @@ function lockview_content(&$a) {
 			dbesc(implode(', ', $deny_groups))
 		);
 		if(count($r))
-			foreach($r as $rr)
+			foreach($r as $rr) 
 				$l[] = '<b><strike>' . $rr['name'] . '</strike></b>';
 	}
 	if(count($deny_users)) {
@@ -79,12 +79,12 @@ function lockview_content(&$a) {
 			dbesc(implode(', ',$deny_users))
 		);
 		if(count($r))
-			foreach($r as $rr)
+			foreach($r as $rr) 
 				$l[] = '<strike>' . $rr['name'] . '</strike>';
 
 	}
 
 	echo $o . implode(', ', $l);
 	killme();
-}
+
 }
diff --git a/mod/login.php b/mod/login.php
index 47c329eb63..d09fc1868f 100644
--- a/mod/login.php
+++ b/mod/login.php
@@ -1,5 +1,5 @@
 <?php
-if(! function_exists('login_content')) {
+
 function login_content(&$a) {
 	if(x($_SESSION,'theme'))
 		unset($_SESSION['theme']);
@@ -9,5 +9,5 @@ function login_content(&$a) {
 	if(local_user())
 		goaway(z_root());
 	return login(($a->config['register_policy'] == REGISTER_CLOSED) ? false : true);
-}
+
 }
diff --git a/mod/lostpass.php b/mod/lostpass.php
index 0c4bb1a833..938d1cbb00 100644
--- a/mod/lostpass.php
+++ b/mod/lostpass.php
@@ -4,7 +4,6 @@ require_once('include/email.php');
 require_once('include/enotify.php');
 require_once('include/text.php');
 
-if(! function_exists('lostpass_post')) {
 function lostpass_post(&$a) {
 
 	$loginame = notags(trim($_POST['login-name']));
@@ -75,10 +74,10 @@ function lostpass_post(&$a) {
 		'body' => $body));
 
 	goaway(z_root());
-}
+
 }
 
-if(! function_exists('lostpass_content')) {
+
 function lostpass_content(&$a) {
 
 
@@ -165,5 +164,5 @@ function lostpass_content(&$a) {
 
 		return $o;
 	}
-}
+
 }
diff --git a/mod/maintenance.php b/mod/maintenance.php
index 02de29108f..b50c94c9b9 100644
--- a/mod/maintenance.php
+++ b/mod/maintenance.php
@@ -1,8 +1,7 @@
 <?php
-if(! function_exists('maintenance_content')) {
+
 function maintenance_content(&$a) {
 	return replace_macros(get_markup_template('maintenance.tpl'), array(
 		'$sysdown' => t('System down for maintenance')
 	));
 }
-}
diff --git a/mod/manage.php b/mod/manage.php
index 6af3db9971..adcc3d787a 100644
--- a/mod/manage.php
+++ b/mod/manage.php
@@ -2,7 +2,7 @@
 
 require_once("include/text.php");
 
-if(! function_exists('manage_post')) {
+
 function manage_post(&$a) {
 
 	if(! local_user())
@@ -87,9 +87,9 @@ function manage_post(&$a) {
 	goaway( $a->get_baseurl() . "/profile/" . $a->user['nickname'] );
 	// NOTREACHED
 }
-}
 
-if(! function_exists('manage_content')) {
+
+
 function manage_content(&$a) {
 
 	if(! local_user()) {
@@ -144,5 +144,5 @@ function manage_content(&$a) {
 	));
 
 	return $o;
-}
+
 }
diff --git a/mod/match.php b/mod/match.php
index f4936b28dc..3b0367b429 100644
--- a/mod/match.php
+++ b/mod/match.php
@@ -13,7 +13,6 @@ require_once('mod/proxy.php');
  * @param App &$a
  * @return void|string
  */
-if(! function_exists('match_content')) {
 function match_content(&$a) {
 
 	$o = '';
@@ -110,4 +109,3 @@ function match_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/message.php b/mod/message.php
index 1f11797d8b..1724ebc424 100644
--- a/mod/message.php
+++ b/mod/message.php
@@ -3,7 +3,6 @@
 require_once('include/acl_selectors.php');
 require_once('include/message.php');
 
-if(! function_exists('message_init')) {
 function message_init(&$a) {
 
 	$tabs = '';
@@ -37,10 +36,9 @@ function message_init(&$a) {
 		'$baseurl' => $a->get_baseurl(true),
 		'$base' => $base
 	));
-}
+
 }
 
-if(! function_exists('message_post')) {
 function message_post(&$a) {
 
 	if(! local_user()) {
@@ -93,7 +91,7 @@ function message_post(&$a) {
 	}
 	else
 		goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']);
-}
+
 }
 
 // Note: the code in 'item_extract_images' and 'item_redir_and_replace_images'
@@ -173,7 +171,7 @@ function item_redir_and_replace_images($body, $images, $cid) {
 }}
 
 
-if(! function_exists('message_content')) {
+
 function message_content(&$a) {
 
 	$o = '';
@@ -532,9 +530,7 @@ function message_content(&$a) {
 		return $o;
 	}
 }
-}
 
-if(! function_exists('get_messages')) {
 function get_messages($user, $lstart, $lend) {
 
 	return q("SELECT max(`mail`.`created`) AS `mailcreated`, min(`mail`.`seen`) AS `mailseen`,
@@ -545,9 +541,7 @@ function get_messages($user, $lstart, $lend) {
 		intval($user), intval($lstart), intval($lend)
 	);
 }
-}
 
-if(! function_exists('render_messages')) {
 function render_messages($msg, $t) {
 
 	$a = get_app();
@@ -599,4 +593,3 @@ function render_messages($msg, $t) {
 
 	return $rslt;
 }
-}
diff --git a/mod/modexp.php b/mod/modexp.php
index 282d55a24b..bba2c2882d 100644
--- a/mod/modexp.php
+++ b/mod/modexp.php
@@ -2,7 +2,6 @@
 
 require_once('library/asn1.php');
 
-if(! function_exists('modexp_init')) {
 function modexp_init(&$a) {
 
 	if($a->argc != 2)
@@ -30,5 +29,6 @@ function modexp_init(&$a) {
 	echo 'RSA' . '.' . $m . '.' . $e ;
 
 	killme();
+
 }
-}
+
diff --git a/mod/mood.php b/mod/mood.php
index 2476f06562..eee11e20c5 100644
--- a/mod/mood.php
+++ b/mod/mood.php
@@ -4,7 +4,7 @@ require_once('include/security.php');
 require_once('include/bbcode.php');
 require_once('include/items.php');
 
-if(! function_exists('mood_init')) {
+
 function mood_init(&$a) {
 
 	if(! local_user())
@@ -59,7 +59,7 @@ function mood_init(&$a) {
 
 	$uri = item_new_uri($a->get_hostname(),$uid);
 
-	$action = sprintf( t('%1$s is currently %2$s'), '[url=' . $poster['url'] . ']' . $poster['name'] . '[/url]' , $verbs[$verb]);
+	$action = sprintf( t('%1$s is currently %2$s'), '[url=' . $poster['url'] . ']' . $poster['name'] . '[/url]' , $verbs[$verb]); 
 
 	$arr = array();
 
@@ -105,9 +105,9 @@ function mood_init(&$a) {
 
 	return;
 }
-}
 
-if(! function_exists('mood_content')) {
+
+
 function mood_content(&$a) {
 
 	if(! local_user()) {
@@ -138,5 +138,5 @@ function mood_content(&$a) {
 	));
 
 	return $o;
-}
+
 }
diff --git a/mod/msearch.php b/mod/msearch.php
index 3b1b0b617a..89de5b7057 100644
--- a/mod/msearch.php
+++ b/mod/msearch.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('msearch_post')) {
 function msearch_post(&$a) {
 
 	$perpage = (($_POST['n']) ? $_POST['n'] : 80);
@@ -27,8 +26,8 @@ function msearch_post(&$a) {
 	if(count($r)) {
 		foreach($r as $rr)
 			$results[] = array(
-				'name' => $rr['name'],
-				'url' => $a->get_baseurl() . '/profile/' . $rr['nickname'],
+				'name' => $rr['name'], 
+				'url' => $a->get_baseurl() . '/profile/' . $rr['nickname'], 
 				'photo' => $a->get_baseurl() . '/photo/avatar/' . $rr['uid'] . '.jpg',
 				'tags' => str_replace(array(',','  '),array(' ',' '),$rr['pub_keywords'])
 			);
@@ -39,5 +38,5 @@ function msearch_post(&$a) {
 	echo json_encode($output);
 
 	killme();
-}
-}
+
+}
\ No newline at end of file
diff --git a/mod/navigation.php b/mod/navigation.php
index 8fbabfda96..5db69b171e 100644
--- a/mod/navigation.php
+++ b/mod/navigation.php
@@ -2,7 +2,6 @@
 
 require_once("include/nav.php");
 
-if(! function_exists('navigation_content')) {
 function navigation_content(&$a) {
 
 	$nav_info = nav_info($a);
@@ -23,5 +22,5 @@ function navigation_content(&$a) {
 		'$apps' => $a->apps,
 		'$clear_notifs' => t('Clear notifications')
 	));
-}
+
 }
diff --git a/mod/network.php b/mod/network.php
index f9a0bec238..0010a3d824 100644
--- a/mod/network.php
+++ b/mod/network.php
@@ -1,6 +1,4 @@
 <?php
-
-if(! function_exists('network_init')) {
 function network_init(&$a) {
 	if(! local_user()) {
 		notice( t('Permission denied.') . EOL);
@@ -155,10 +153,9 @@ function network_init(&$a) {
 	$a->page['aside'] .= networks_widget($a->get_baseurl(true) . '/network',(x($_GET, 'nets') ? $_GET['nets'] : ''));
 	$a->page['aside'] .= saved_searches($search);
 	$a->page['aside'] .= fileas_widget($a->get_baseurl(true) . '/network',(x($_GET, 'file') ? $_GET['file'] : ''));
-}
+
 }
 
-if(! function_exists('saved_searches')) {
 function saved_searches($search) {
 
 	if(! feature_enabled(local_user(),'savedsearch'))
@@ -207,7 +204,7 @@ function saved_searches($search) {
 	));
 
 	return $o;
-}
+
 }
 
 /**
@@ -225,7 +222,6 @@ function saved_searches($search) {
  *
  * @return Array ( $no_active, $comment_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active );
  */
-if(! function_exists('network_query_get_sel_tab')) {
 function network_query_get_sel_tab($a) {
 	$no_active='';
 	$starred_active = '';
@@ -282,12 +278,10 @@ function network_query_get_sel_tab($a) {
 
 	return array($no_active, $all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active);
 }
-}
 
 /**
  * Return selected network from query
  */
-if(! function_exists('network_query_get_sel_net')) {
 function network_query_get_sel_net() {
 	$network = false;
 
@@ -297,9 +291,7 @@ function network_query_get_sel_net() {
 
 	return $network;
 }
-}
 
-if(! function_exists('network_query_get_sel_group')) {
 function network_query_get_sel_group($a) {
 	$group = false;
 
@@ -309,9 +301,8 @@ function network_query_get_sel_group($a) {
 
 	return $group;
 }
-}
 
-if(! function_exists('network_content')) {
+
 function network_content(&$a, $update = 0) {
 
 	require_once('include/conversation.php');
@@ -895,4 +886,4 @@ function network_content(&$a, $update = 0) {
 
 	return $o;
 }
-}
+
diff --git a/mod/newmember.php b/mod/newmember.php
index ef25333302..aa55c3a098 100644
--- a/mod/newmember.php
+++ b/mod/newmember.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('newmember_content')) {
 function newmember_content(&$a) {
 
 
@@ -16,7 +15,7 @@ function newmember_content(&$a) {
 
 	$o .= '<ul>';
 
-	$o .= '<li> ' . '<a target="newmember" href="help/guide">' . t('Friendica Walk-Through') . '</a><br />' . t('On your <em>Quick Start</em> page - find a brief introduction to your profile and network tabs, make some new connections, and find some groups to join.') . '</li>' . EOL;
+	$o .= '<li> ' . '<a target="newmember" href="help/guide">' . t('Friendica Walk-Through') . '</a><br />' . t('On your <em>Quick Start</em> page - find a brief introduction to your profile and network tabs, make some new connections, and find some groups to join.') . '</li>' . EOL; 
 
 	$o .= '</ul>';
 
@@ -24,7 +23,7 @@ function newmember_content(&$a) {
 
 	$o .= '<ul>';
 
-	$o .= '<li>' . '<a target="newmember" href="settings">' . t('Go to Your Settings') . '</a><br />' . t('On your <em>Settings</em> page -  change your initial password. Also make a note of your Identity Address. This looks just like an email address - and will be useful in making friends on the free social web.') . '</li>' . EOL;
+	$o .= '<li>' . '<a target="newmember" href="settings">' . t('Go to Your Settings') . '</a><br />' . t('On your <em>Settings</em> page -  change your initial password. Also make a note of your Identity Address. This looks just like an email address - and will be useful in making friends on the free social web.') . '</li>' . EOL; 
 
 	$o .= '<li>' . t('Review the other settings, particularly the privacy settings. An unpublished directory listing is like having an unlisted phone number. In general, you should probably publish your listing - unless all of your friends and potential friends know exactly how to find you.') . '</li>' . EOL;
 
@@ -34,7 +33,7 @@ function newmember_content(&$a) {
 
 	$o .= '<ul>';
 
-	$o .= '<li>' . '<a target="newmember" href="profile_photo">' . t('Upload Profile Photo') . '</a><br />' . t('Upload a profile photo if you have not done so already. Studies have shown that people with real photos of themselves are ten times more likely to make friends than people who do not.') . '</li>' . EOL;
+	$o .= '<li>' . '<a target="newmember" href="profile_photo">' . t('Upload Profile Photo') . '</a><br />' . t('Upload a profile photo if you have not done so already. Studies have shown that people with real photos of themselves are ten times more likely to make friends than people who do not.') . '</li>' . EOL;  
 
 	$o .= '<li>' . '<a target="newmember" href="profiles">' . t('Edit Your Profile') . '</a><br />' . t('Edit your <strong>default</strong> profile to your liking. Review the settings for hiding your list of friends and hiding the profile from unknown visitors.') . '</li>' . EOL;
 
@@ -47,7 +46,7 @@ function newmember_content(&$a) {
 	$o .= '<ul>';
 
     $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1);
-
+	
 	if(! $mail_disabled)
 		$o .= '<li>' . '<a target="newmember" href="settings/connectors">' . t('Importing Emails') . '</a><br />' . t('Enter your email access information on your Connector Settings page if you wish to import and interact with friends or mailing lists from your email INBOX') . '</li>' . EOL;
 
@@ -83,4 +82,3 @@ function newmember_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/nodeinfo.php b/mod/nodeinfo.php
index 7f8939182e..ba310a1051 100644
--- a/mod/nodeinfo.php
+++ b/mod/nodeinfo.php
@@ -1,13 +1,12 @@
 <?php
 /**
  * @file mod/nodeinfo.php
- *
+ * 
  * Documentation: http://nodeinfo.diaspora.software/schema.html
 */
 
 require_once("include/plugin.php");
 
-if(! function_exists('nodeinfo_wellknown')) {
 function nodeinfo_wellknown(&$a) {
 	if (!get_config("system", "nodeinfo")) {
 		http_status_exit(404);
@@ -20,9 +19,7 @@ function nodeinfo_wellknown(&$a) {
 	echo json_encode($nodeinfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
 	exit;
 }
-}
 
-if(! function_exists('nodeinfo_init')) {
 function nodeinfo_init(&$a){
 	if (!get_config("system", "nodeinfo")) {
 		http_status_exit(404);
@@ -146,9 +143,9 @@ function nodeinfo_init(&$a){
 	echo json_encode($nodeinfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES);
 	exit;
 }
-}
 
-if(! function_exists('nodeinfo_cron')) {
+
+
 function nodeinfo_cron() {
 
 	$a = get_app();
@@ -263,5 +260,5 @@ function nodeinfo_cron() {
         logger("cron_end");
 	set_config('nodeinfo','last_calucation', time());
 }
-}
+
 ?>
diff --git a/mod/nogroup.php b/mod/nogroup.php
index 818b0da77a..9f6e978433 100644
--- a/mod/nogroup.php
+++ b/mod/nogroup.php
@@ -4,7 +4,6 @@ require_once('include/Contact.php');
 require_once('include/socgraph.php');
 require_once('include/contact_selectors.php');
 
-if(! function_exists('nogroup_init')) {
 function nogroup_init(&$a) {
 
 	if(! local_user())
@@ -18,9 +17,8 @@ function nogroup_init(&$a) {
 
 	$a->page['aside'] .= group_side('contacts','group','extended',0,$contact_id);
 }
-}
 
-if(! function_exists('nogroup_content')) {
+
 function nogroup_content(&$a) {
 
 	if(! local_user()) {
@@ -68,5 +66,5 @@ function nogroup_content(&$a) {
 	));
 
 	return $o;
-}
+
 }
diff --git a/mod/noscrape.php b/mod/noscrape.php
index 49fe2b9a37..51bd7234cf 100644
--- a/mod/noscrape.php
+++ b/mod/noscrape.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('noscrape_init')) {
 function noscrape_init(&$a) {
 
 	if($a->argc > 1)
@@ -63,5 +62,5 @@ function noscrape_init(&$a) {
 	header('Content-type: application/json; charset=utf-8');
 	echo json_encode($json_info);
 	exit;
-}
+
 }
diff --git a/mod/notes.php b/mod/notes.php
index 7817e25547..73c1507e3e 100644
--- a/mod/notes.php
+++ b/mod/notes.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('notes_init')) {
 function notes_init(&$a) {
 
 	if(! local_user())
@@ -13,10 +12,10 @@ function notes_init(&$a) {
 	nav_set_selected('home');
 
 //	profile_load($a,$which,$profile);
-}
+
 }
 
-if(! function_exists('notes_content')) {
+
 function notes_content(&$a,$update = false) {
 
 	if(! local_user()) {
@@ -70,12 +69,12 @@ function notes_content(&$a,$update = false) {
 	// Construct permissions
 
 	// default permissions - anonymous user
-
+	
 	$sql_extra = " AND `allow_cid` = '<" . $a->contact['id'] . ">' ";
 
 	$r = q("SELECT COUNT(*) AS `total`
 		FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
-		WHERE `item`.`uid` = %d AND `item`.`visible` = 1 and `item`.`moderated` = 0
+		WHERE `item`.`uid` = %d AND `item`.`visible` = 1 and `item`.`moderated` = 0 
 		AND `item`.`deleted` = 0 AND `item`.`type` = 'note'
 		AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 AND `contact`.`self` = 1
 		AND `item`.`id` = `item`.`parent` AND `item`.`wall` = 0
@@ -91,7 +90,7 @@ function notes_content(&$a,$update = false) {
 
 	$r = q("SELECT `item`.`id` AS `item_id`, `contact`.`uid` AS `contact-uid`
 		FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
-		WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
+		WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0 
 		and `item`.`moderated` = 0 AND `item`.`type` = 'note'
 		AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 AND `contact`.`self` = 1
 		AND `item`.`id` = `item`.`parent` AND `item`.`wall` = 0
@@ -110,10 +109,10 @@ function notes_content(&$a,$update = false) {
 		foreach($r as $rr)
 			$parents_arr[] = $rr['item_id'];
 		$parents_str = implode(', ', $parents_arr);
-
-		$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,
-			`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`alias`, `contact`.`network`, `contact`.`rel`,
-			`contact`.`thumb`, `contact`.`self`, `contact`.`writable`,
+ 
+		$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, 
+			`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`alias`, `contact`.`network`, `contact`.`rel`, 
+			`contact`.`thumb`, `contact`.`self`, `contact`.`writable`, 
 			`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
 			FROM `item` LEFT JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
 			WHERE `item`.`uid` = %d AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
@@ -136,4 +135,3 @@ function notes_content(&$a,$update = false) {
 	$o .= paginate($a);
 	return $o;
 }
-}
diff --git a/mod/notice.php b/mod/notice.php
index a42d60dd40..19cf53189a 100644
--- a/mod/notice.php
+++ b/mod/notice.php
@@ -1,8 +1,7 @@
 <?php
-/* identi.ca -> friendica items permanent-url compatibility */
-
-if(! function_exists('notice_init')) {
-	function notice_init(&$a) {
+	/* identi.ca -> friendica items permanent-url compatibility */
+	
+	function notice_init(&$a){
 		$id = $a->argv[1];
 		$r = q("SELECT user.nickname FROM user LEFT JOIN item ON item.uid=user.uid WHERE item.id=%d",
 				intval($id)
@@ -17,5 +16,5 @@ if(! function_exists('notice_init')) {
 
 		}
 		return;
+
 	}
-}
diff --git a/mod/notifications.php b/mod/notifications.php
index c7421b2d42..a267b7c958 100644
--- a/mod/notifications.php
+++ b/mod/notifications.php
@@ -3,7 +3,6 @@ include_once("include/bbcode.php");
 include_once("include/contact_selectors.php");
 include_once("include/Scrape.php");
 
-if(! function_exists('notifications_post')) {
 function notifications_post(&$a) {
 
 	if(! local_user()) {
@@ -59,11 +58,11 @@ function notifications_post(&$a) {
 		}
 	}
 }
-}
 
 
 
-if(! function_exists('notifications_content')) {
+
+
 function notifications_content(&$a) {
 
 	if(! local_user()) {
@@ -580,4 +579,3 @@ function notifications_content(&$a) {
 	$o .= paginate($a);
 	return $o;
 }
-}
diff --git a/mod/notify.php b/mod/notify.php
index 7acac1084a..02260514af 100644
--- a/mod/notify.php
+++ b/mod/notify.php
@@ -1,6 +1,6 @@
 <?php
 
-if(! function_exists('notify_init')) {
+
 function notify_init(&$a) {
 	if(! local_user())
 		return;
@@ -42,10 +42,10 @@ function notify_init(&$a) {
 		echo $j;
 		killme();
 	}
-}
+
 }
 
-if(! function_exists('notify_content')) {
+
 function notify_content(&$a) {
 	if(! local_user())
 		return login();
@@ -80,5 +80,5 @@ function notify_content(&$a) {
 
 	return $o;
 
-}
+
 }
diff --git a/mod/oembed.php b/mod/oembed.php
index 021cbab6fd..cb478cb860 100644
--- a/mod/oembed.php
+++ b/mod/oembed.php
@@ -1,8 +1,7 @@
 <?php
 require_once("include/oembed.php");
 
-if(! function_exists('oembed_content')) {
-function oembed_content(&$a) {
+function oembed_content(&$a){
 	// logger('mod_oembed ' . $a->query_string, LOGGER_ALL);
 
 	if ($a->argv[1]=='b2h'){
@@ -34,4 +33,3 @@ function oembed_content(&$a) {
 	}
 	killme();
 }
-}
diff --git a/mod/oexchange.php b/mod/oexchange.php
index 1e7c9b23c9..bbb436e702 100644
--- a/mod/oexchange.php
+++ b/mod/oexchange.php
@@ -1,6 +1,6 @@
 <?php
 
-if(! function_exists('oexchange_init')) {
+
 function oexchange_init(&$a) {
 
 	if(($a->argc > 1) && ($a->argv[1] === 'xrd')) {
@@ -11,10 +11,9 @@ function oexchange_init(&$a) {
 		killme();
 	}
 
-}
+
 }
 
-if(! function_exists('oexchange_content')) {
 function oexchange_content(&$a) {
 
 	if(! local_user()) {
@@ -27,13 +26,13 @@ function oexchange_content(&$a) {
 		return;
 	}
 
-	$url = (((x($_REQUEST,'url')) && strlen($_REQUEST['url']))
+	$url = (((x($_REQUEST,'url')) && strlen($_REQUEST['url'])) 
 		? urlencode(notags(trim($_REQUEST['url']))) : '');
-	$title = (((x($_REQUEST,'title')) && strlen($_REQUEST['title']))
+	$title = (((x($_REQUEST,'title')) && strlen($_REQUEST['title'])) 
 		? '&title=' . urlencode(notags(trim($_REQUEST['title']))) : '');
-	$description = (((x($_REQUEST,'description')) && strlen($_REQUEST['description']))
+	$description = (((x($_REQUEST,'description')) && strlen($_REQUEST['description'])) 
 		? '&description=' . urlencode(notags(trim($_REQUEST['description']))) : '');
-	$tags = (((x($_REQUEST,'tags')) && strlen($_REQUEST['tags']))
+	$tags = (((x($_REQUEST,'tags')) && strlen($_REQUEST['tags'])) 
 		? '&tags=' . urlencode(notags(trim($_REQUEST['tags']))) : '');
 
 	$s = fetch_url($a->get_baseurl() . '/parse_url?f=&url=' . $url . $title . $description . $tags);
@@ -53,5 +52,7 @@ function oexchange_content(&$a) {
 	$_REQUEST = $post;
 	require_once('mod/item.php');
 	item_post($a);
+
 }
-}
+
+
diff --git a/mod/openid.php b/mod/openid.php
index a92a124c0d..5d5539f00e 100644
--- a/mod/openid.php
+++ b/mod/openid.php
@@ -1,8 +1,9 @@
 <?php
 
+
 require_once('library/openid.php');
 
-if(! function_exists('openid_content')) {
+
 function openid_content(&$a) {
 
 	$noid = get_config('system','no_openid');
@@ -24,8 +25,8 @@ function openid_content(&$a) {
 				goaway(z_root());
 			}
 
-			$r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey`
-				FROM `user` WHERE `openid` = '%s' AND `blocked` = 0
+			$r = q("SELECT `user`.*, `user`.`pubkey` as `upubkey`, `user`.`prvkey` as `uprvkey` 
+				FROM `user` WHERE `openid` = '%s' AND `blocked` = 0 
 				AND `account_expired` = 0 AND `account_removed` = 0 AND `verified` = 1 LIMIT 1",
 				dbesc($authid)
 			);
@@ -39,7 +40,7 @@ function openid_content(&$a) {
 				require_once('include/security.php');
 				authenticate_success($r[0],true,true);
 
-				// just in case there was no return url set
+				// just in case there was no return url set 
 				// and we fell through
 
 				goaway(z_root());
@@ -93,4 +94,3 @@ function openid_content(&$a) {
 	goaway(z_root());
 	// NOTREACHED
 }
-}
diff --git a/mod/opensearch.php b/mod/opensearch.php
index f3d55a1029..ff748d1c53 100644
--- a/mod/opensearch.php
+++ b/mod/opensearch.php
@@ -1,18 +1,18 @@
 <?php
-if(! function_exists('opensearch_content')) {
-  function opensearch_content(&$a) {
+    function opensearch_content(&$a) {
+    	
 		$tpl = get_markup_template('opensearch.tpl');
-
+	
 		header("Content-type: application/opensearchdescription+xml");
-
+	
 		$o = replace_macros($tpl, array(
 			'$baseurl' => $a->get_baseurl(),
 			'$nodename' => $a->get_hostname(),
 		));
-
+		
 		echo $o;
-
+		
 		killme();
+		
 	}
-}
-?>
+?>
\ No newline at end of file
diff --git a/mod/ostatus_subscribe.php b/mod/ostatus_subscribe.php
index a21436db49..6cca0bf679 100644
--- a/mod/ostatus_subscribe.php
+++ b/mod/ostatus_subscribe.php
@@ -3,7 +3,6 @@
 require_once('include/Scrape.php');
 require_once('include/follow.php');
 
-if(! function_exists('ostatus_subscribe_content')) {
 function ostatus_subscribe_content(&$a) {
 
 	if(! local_user()) {
@@ -77,4 +76,3 @@ function ostatus_subscribe_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/p.php b/mod/p.php
index 225b831fea..92b72dc1ce 100644
--- a/mod/p.php
+++ b/mod/p.php
@@ -4,8 +4,7 @@ This file is part of the Diaspora protocol. It is used for fetching single publi
 */
 require_once("include/diaspora.php");
 
-if(! function_exists('p_init')) {
-function p_init($a) {
+function p_init($a){
 	if ($a->argc != 2) {
 		header($_SERVER["SERVER_PROTOCOL"].' 510 '.t('Not Extended'));
 		killme();
@@ -80,4 +79,3 @@ function p_init($a) {
 
 	killme();
 }
-}
diff --git a/mod/parse_url.php b/mod/parse_url.php
index 481cb89361..a1ca5a3db5 100644
--- a/mod/parse_url.php
+++ b/mod/parse_url.php
@@ -1,14 +1,14 @@
 <?php
-/**
+/** 
  * @file mod/parse_url.php
- *
+ * 
  * @todo https://developers.google.com/+/plugins/snippet/
- *
+ * 
  * @verbatim
  * <meta itemprop="name" content="Toller Titel">
  * <meta itemprop="description" content="Eine tolle Beschreibung">
  * <meta itemprop="image" content="http://maple.libertreeproject.org/images/tree-icon.png">
- *
+ * 
  * <body itemscope itemtype="http://schema.org/Product">
  *   <h1 itemprop="name">Shiny Trinket</h1>
  *   <img itemprop="image" src="{image-url}" />
@@ -27,7 +27,6 @@ if(!function_exists('deletenode')) {
 	}
 }
 
-if(! function_exists('completeurl')) {
 function completeurl($url, $scheme) {
 	$urlarr = parse_url($url);
 
@@ -54,9 +53,7 @@ function completeurl($url, $scheme) {
 
 	return($complete);
 }
-}
 
-if(! function_exists('parseurl_getsiteinfo_cached')) {
 function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = true) {
 
 	if ($url == "")
@@ -80,9 +77,7 @@ function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = tr
 
 	return $data;
 }
-}
 
-if(! function_exists('parseurl_getsiteinfo')) {
 function parseurl_getsiteinfo($url, $no_guessing = false, $do_oembed = true, $count = 1) {
 	require_once("include/network.php");
 	require_once("include/Photo.php");
@@ -405,15 +400,11 @@ function parseurl_getsiteinfo($url, $no_guessing = false, $do_oembed = true, $co
 
 	return($siteinfo);
 }
-}
 
-if(! function_exists('arr_add_hashes')) {
 function arr_add_hashes(&$item,$k) {
 	$item = '#' . $item;
 }
-}
 
-if(! function_exists('parse_url_content')) {
 function parse_url_content(&$a) {
 
 	$text = null;
@@ -567,5 +558,4 @@ function parse_url_content(&$a) {
 
 	killme();
 }
-}
 ?>
diff --git a/mod/photo.php b/mod/photo.php
index 3baff13db5..4166b4d539 100644
--- a/mod/photo.php
+++ b/mod/photo.php
@@ -3,7 +3,6 @@
 require_once('include/security.php');
 require_once('include/Photo.php');
 
-if(! function_exists('photo_init')) {
 function photo_init(&$a) {
 	global $_SERVER;
 
@@ -210,4 +209,3 @@ function photo_init(&$a) {
 	killme();
 	// NOTREACHED
 }
-}
diff --git a/mod/photos.php b/mod/photos.php
index 9821918e5e..a9dade6a81 100644
--- a/mod/photos.php
+++ b/mod/photos.php
@@ -9,7 +9,6 @@ require_once('include/redir.php');
 require_once('include/tags.php');
 require_once('include/threads.php');
 
-if(! function_exists('photos_init')) {
 function photos_init(&$a) {
 
 	if($a->argc > 1)
@@ -122,9 +121,9 @@ function photos_init(&$a) {
 
 	return;
 }
-}
 
-if(! function_exists('photos_post')) {
+
+
 function photos_post(&$a) {
 
 	logger('mod-photos: photos_post: begin' , LOGGER_DEBUG);
@@ -958,9 +957,9 @@ function photos_post(&$a) {
 	goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
 	// NOTREACHED
 }
-}
 
-if(! function_exists('photos_content')) {
+
+
 function photos_content(&$a) {
 
 	// URLs:
@@ -1329,7 +1328,7 @@ function photos_content(&$a) {
 
 	}
 
-	/**
+	/** 
 	 * Display one photo
 	 */
 
@@ -1862,7 +1861,7 @@ function photos_content(&$a) {
 			//hide profile photos to others
 			if((! $is_owner) && (! remote_user()) && ($rr['album'] == t('Profile Photos')))
 					continue;
-
+			
 			if($twist == 'rotright')
 				$twist = 'rotleft';
 			else
@@ -1907,4 +1906,4 @@ function photos_content(&$a) {
 	$o .= paginate($a);
 	return $o;
 }
-}
+
diff --git a/mod/ping.php b/mod/ping.php
index 0d1659a763..577a2c6c82 100644
--- a/mod/ping.php
+++ b/mod/ping.php
@@ -5,7 +5,6 @@ require_once('include/ForumManager.php');
 require_once('include/group.php');
 require_once("mod/proxy.php");
 
-if(! function_exists('ping_init')) {
 function ping_init(&$a) {
 
 	header("Content-type: text/xml");
@@ -339,9 +338,7 @@ function ping_init(&$a) {
 
 	killme();
 }
-}
 
-if(! function_exists('ping_get_notifications')) {
 function ping_get_notifications($uid) {
 
 	$result = array();
@@ -409,4 +406,3 @@ function ping_get_notifications($uid) {
 
 	return($result);
 }
-}
diff --git a/mod/poco.php b/mod/poco.php
index 4b04d70138..0a1b392169 100644
--- a/mod/poco.php
+++ b/mod/poco.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('poco_init')) {
 function poco_init(&$a) {
 	require_once("include/bbcode.php");
 
@@ -325,5 +324,5 @@ function poco_init(&$a) {
 	else
 		http_status_exit(500);
 
-}
+
 }
diff --git a/mod/poke.php b/mod/poke.php
index 1af78b68ed..45a577cda6 100644
--- a/mod/poke.php
+++ b/mod/poke.php
@@ -4,11 +4,11 @@
  *
  * Poke, prod, finger, or otherwise do unspeakable things to somebody - who must be a connection in your address book
  * This function can be invoked with the required arguments (verb and cid and private and possibly parent) silently via ajax or
- * other web request. You must be logged in and connected to a profile.
+ * other web request. You must be logged in and connected to a profile. 
  * If the required arguments aren't present, we'll display a simple form to choose a recipient and a verb.
  * parent is a special argument which let's you attach this activity as a comment to an existing conversation, which
  * may have started with somebody else poking (etc.) somebody, but this isn't necessary. This can be used in the more pokes
- * plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.
+ * plugin version to have entire conversations where Alice poked Bob, Bob fingered Alice, Alice hugged Bob, etc.  
  *
  * private creates a private conversation with the recipient. Otherwise your profile's default post privacy is used.
  *
@@ -18,7 +18,7 @@ require_once('include/security.php');
 require_once('include/bbcode.php');
 require_once('include/items.php');
 
-if(! function_exists('poke_init')) {
+
 function poke_init(&$a) {
 
 	if(! local_user())
@@ -140,9 +140,9 @@ function poke_init(&$a) {
 
 	return;
 }
-}
 
-if(! function_exists('poke_content')) {
+
+
 function poke_content(&$a) {
 
 	if(! local_user()) {
@@ -201,5 +201,5 @@ function poke_content(&$a) {
 	));
 
 	return $o;
-}
+
 }
diff --git a/mod/post.php b/mod/post.php
index 631bf0eba6..c0e783a6aa 100644
--- a/mod/post.php
+++ b/mod/post.php
@@ -9,8 +9,7 @@ require_once('include/salmon.php');
 require_once('include/crypto.php');
 // not yet ready for prime time
 //require_once('include/zot.php');
-
-if(! function_exists('post_post')) {
+	
 function post_post(&$a) {
 
 	$bulk_delivery = false;
@@ -20,7 +19,7 @@ function post_post(&$a) {
 	}
 	else {
 		$nickname = $a->argv[2];
-		$r = q("SELECT * FROM `user` WHERE `nickname` = '%s'
+		$r = q("SELECT * FROM `user` WHERE `nickname` = '%s' 
 				AND `account_expired` = 0 AND `account_removed` = 0 LIMIT 1",
 			dbesc($nickname)
 		);
@@ -49,4 +48,4 @@ function post_post(&$a) {
 	http_status_exit(($ret) ? $ret : 200);
 	// NOTREACHED
 }
-}
+
diff --git a/mod/pretheme.php b/mod/pretheme.php
index 5d1c261fcb..4584cb29e2 100644
--- a/mod/pretheme.php
+++ b/mod/pretheme.php
@@ -1,8 +1,7 @@
 <?php
 
-if(! function_exists('pretheme_init')) {
 function pretheme_init(&$a) {
-
+	
 	if($_REQUEST['theme']) {
 		$theme = $_REQUEST['theme'];
 		$info = get_theme_info($theme);
@@ -21,4 +20,3 @@ function pretheme_init(&$a) {
 	}
 	killme();
 }
-}
diff --git a/mod/probe.php b/mod/probe.php
index fcf83e7603..c95db291b3 100644
--- a/mod/probe.php
+++ b/mod/probe.php
@@ -2,14 +2,13 @@
 
 require_once('include/Scrape.php');
 
-if(! function_exists('probe_content')) {
 function probe_content(&$a) {
 
 	$o .= '<h3>Probe Diagnostic</h3>';
 
 	$o .= '<form action="probe" method="get">';
 	$o .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />';
-	$o .= '<input type="submit" name="submit" value="Submit" /></form>';
+	$o .= '<input type="submit" name="submit" value="Submit" /></form>'; 
 
 	$o .= '<br /><br />';
 
@@ -23,4 +22,3 @@ function probe_content(&$a) {
 	}
 	return $o;
 }
-}
diff --git a/mod/profile.php b/mod/profile.php
index b02570d5af..26bd395230 100644
--- a/mod/profile.php
+++ b/mod/profile.php
@@ -3,7 +3,7 @@
 require_once('include/contact_widgets.php');
 require_once('include/redir.php');
 
-if(! function_exists('profile_init')) {
+
 function profile_init(&$a) {
 
 	if(! x($a->page,'aside'))
@@ -65,10 +65,10 @@ function profile_init(&$a) {
 	foreach($dfrn_pages as $dfrn)
 		$a->page['htmlhead'] .= "<link rel=\"dfrn-{$dfrn}\" href=\"".$a->get_baseurl()."/dfrn_{$dfrn}/{$which}\" />\r\n";
 	$a->page['htmlhead'] .= "<link rel=\"dfrn-poco\" href=\"".$a->get_baseurl()."/poco/{$which}\" />\r\n";
-}
+
 }
 
-if(! function_exists('profile_content')) {
+
 function profile_content(&$a, $update = 0) {
 
 	$category = $datequery = $datequery2 = '';
@@ -350,4 +350,3 @@ function profile_content(&$a, $update = 0) {
 
 	return $o;
 }
-}
diff --git a/mod/profile_photo.php b/mod/profile_photo.php
index e3d6adb491..4e8d279a97 100644
--- a/mod/profile_photo.php
+++ b/mod/profile_photo.php
@@ -2,7 +2,6 @@
 
 require_once("include/Photo.php");
 
-if(! function_exists('profile_photo_init')) {
 function profile_photo_init(&$a) {
 
 	if(! local_user()) {
@@ -10,10 +9,10 @@ function profile_photo_init(&$a) {
 	}
 
 	profile_load($a,$a->user['nickname']);
-}
+
 }
 
-if(! function_exists('profile_photo_post')) {
+
 function profile_photo_post(&$a) {
 
 	if(! local_user()) {
@@ -144,7 +143,7 @@ function profile_photo_post(&$a) {
 	$filesize = intval($_FILES['userfile']['size']);
 	$filetype = $_FILES['userfile']['type'];
     if ($filetype=="") $filetype=guess_image_type($filename);
-
+    
 	$maximagesize = get_config('system','maximagesize');
 
 	if(($maximagesize) && ($filesize > $maximagesize)) {
@@ -165,7 +164,7 @@ function profile_photo_post(&$a) {
 	$ph->orient($src);
 	@unlink($src);
 	return profile_photo_crop_ui_head($a, $ph);
-}
+	
 }
 
 
@@ -176,7 +175,7 @@ function profile_photo_content(&$a) {
 		notice( t('Permission denied.') . EOL );
 		return;
 	}
-
+	
 	$newuser = false;
 
 	if($a->argc == 2 && $a->argv[1] === 'new')
@@ -187,9 +186,9 @@ function profile_photo_content(&$a) {
 			notice( t('Permission denied.') . EOL );
 			return;
 		};
-
+		
 //		check_form_security_token_redirectOnErr('/profile_photo', 'profile_photo');
-
+        
 		$resource_id = $a->argv[2];
 		//die(":".local_user());
 		$r=q("SELECT * FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' ORDER BY `scale` ASC",
@@ -241,7 +240,7 @@ function profile_photo_content(&$a) {
 
 
 	if(! x($a->config,'imagecrop')) {
-
+	
 		$tpl = get_markup_template('profile_photo.tpl');
 
 		$o .= replace_macros($tpl,array(
@@ -296,11 +295,11 @@ function profile_photo_crop_ui_head(&$a, $ph){
 	}
 
 	$hash = photo_new_resource();
-
+	
 
 	$smallest = 0;
 
-	$r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 0 );
+	$r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 0 );	
 
 	if($r)
 		info( t('Image uploaded successfully.') . EOL );
@@ -309,8 +308,8 @@ function profile_photo_crop_ui_head(&$a, $ph){
 
 	if($width > 640 || $height > 640) {
 		$ph->scaleImage(640);
-		$r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 1 );
-
+		$r = $ph->store(local_user(), 0 , $hash, $filename, t('Profile Photos'), 1 );	
+		
 		if($r === false)
 			notice( sprintf(t('Image size reduction [%s] failed.'),"640") . EOL );
 		else
@@ -324,3 +323,4 @@ function profile_photo_crop_ui_head(&$a, $ph){
 	$a->page['end'] .= replace_macros(get_markup_template("cropend.tpl"), array());
 	return;
 }}
+
diff --git a/mod/profiles.php b/mod/profiles.php
index 9ce478ba19..5c372de8ee 100644
--- a/mod/profiles.php
+++ b/mod/profiles.php
@@ -1,7 +1,6 @@
 <?php
 require_once("include/Contact.php");
 
-if(! function_exists('profiles_init')) {
 function profiles_init(&$a) {
 
 	nav_set_selected('profiles');
@@ -140,10 +139,9 @@ function profiles_init(&$a) {
 	}
 
 
-}
+
 }
 
-if(! function_exists('profile_clean_keywords')) {
 function profile_clean_keywords($keywords) {
 	$keywords = str_replace(","," ",$keywords);
 	$keywords = explode(" ", $keywords);
@@ -160,9 +158,7 @@ function profile_clean_keywords($keywords) {
 
 	return $keywords;
 }
-}
 
-if(! function_exists('profiles_post')) {
 function profiles_post(&$a) {
 
 	if(! local_user()) {
@@ -506,9 +502,8 @@ function profiles_post(&$a) {
 		}
 	}
 }
-}
 
-if(! function_exists('profile_activity')) {
+
 function profile_activity($changed, $value) {
 	$a = get_app();
 
@@ -598,9 +593,8 @@ function profile_activity($changed, $value) {
 
 	}
 }
-}
 
-if(! function_exists('profiles_content')) {
+
 function profiles_content(&$a) {
 
 	if(! local_user()) {
@@ -824,5 +818,5 @@ function profiles_content(&$a) {
 		}
 		return $o;
 	}
-}
+
 }
diff --git a/mod/profperm.php b/mod/profperm.php
index 6fb7172949..077f695bea 100644
--- a/mod/profperm.php
+++ b/mod/profperm.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('profperm_init')) {
 function profperm_init(&$a) {
 
 	if(! local_user())
@@ -10,10 +9,10 @@ function profperm_init(&$a) {
 	$profile = $a->argv[1];
 
 	profile_load($a,$which,$profile);
-}
+
 }
 
-if(! function_exists('profperm_content')) {
+
 function profperm_content(&$a) {
 
 	if(! local_user()) {
@@ -109,9 +108,9 @@ function profperm_content(&$a) {
 	}
 
 	$o .= '<div id="prof-update-wrapper">';
-	if($change)
+	if($change) 
 		$o = '';
-
+	
 	$o .= '<div id="prof-members-title">';
 	$o .= '<h3>' . t('Visible To') . '</h3>';
 	$o .= '</div>';
@@ -157,5 +156,6 @@ function profperm_content(&$a) {
 	}
 	$o .= '</div>';
 	return $o;
+
 }
-}
+
diff --git a/mod/proxy.php b/mod/proxy.php
index 8e2a389254..abcaf49127 100644
--- a/mod/proxy.php
+++ b/mod/proxy.php
@@ -12,7 +12,6 @@ define("PROXY_SIZE_LARGE", "large");
 require_once('include/security.php');
 require_once("include/Photo.php");
 
-if(! function_exists('proxy_init')) {
 function proxy_init() {
 	global $a, $_SERVER;
 
@@ -233,9 +232,7 @@ function proxy_init() {
 
 	killme();
 }
-}
 
-if(! function_exists('proxy_url')) {
 function proxy_url($url, $writemode = false, $size = "") {
 	global $_SERVER;
 
@@ -297,13 +294,11 @@ function proxy_url($url, $writemode = false, $size = "") {
 	else
 		return ($proxypath.$size);
 }
-}
 
 /**
  * @param $url string
  * @return boolean
  */
-if(! function_exists('proxy_is_local_image')) {
 function proxy_is_local_image($url) {
 	if ($url[0] == '/') return true;
 
@@ -314,9 +309,7 @@ function proxy_is_local_image($url) {
 	$url = normalise_link($url);
 	return (substr($url, 0, strlen($baseurl)) == $baseurl);
 }
-}
 
-if(! function_exists('proxy_parse_query')) {
 function proxy_parse_query($var) {
         /**
          *  Use this function to parse out the query array element from
@@ -335,9 +328,7 @@ function proxy_parse_query($var) {
         unset($val, $x, $var);
         return $arr;
 }
-}
 
-if(! function_exists('proxy_img_cb')) {
 function proxy_img_cb($matches) {
 
 	// if the picture seems to be from another picture cache then take the original source
@@ -351,13 +342,10 @@ function proxy_img_cb($matches) {
 
 	return $matches[1].proxy_url(htmlspecialchars_decode($matches[2])).$matches[3];
 }
-}
 
-if(! function_exists('proxy_parse_html')) {
 function proxy_parse_html($html) {
 	$a = get_app();
 	$html = str_replace(normalise_link($a->get_baseurl())."/", $a->get_baseurl()."/", $html);
 
 	return preg_replace_callback("/(<img [^>]*src *= *[\"'])([^\"']+)([\"'][^>]*>)/siU", "proxy_img_cb", $html);
 }
-}
diff --git a/mod/pubsub.php b/mod/pubsub.php
index 15523e637a..beb73b4e2c 100644
--- a/mod/pubsub.php
+++ b/mod/pubsub.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('hub_return')) {
 function hub_return($valid,$body) {
 
 	if($valid) {
@@ -15,18 +14,18 @@ function hub_return($valid,$body) {
 
 	// NOTREACHED
 }
-}
 
 // when receiving an XML feed, always return OK
-if(! function_exists('hub_post_return')) {
+
 function hub_post_return() {
+
 	header($_SERVER["SERVER_PROTOCOL"] . ' 200 ' . 'OK');
 	killme();
-}
+
 }
 
 
-if(! function_exists('pubsub_init')) {
+
 function pubsub_init(&$a) {
 
 	$nick       = (($a->argc > 1) ? notags(trim($a->argv[1])) : '');
@@ -58,7 +57,7 @@ function pubsub_init(&$a) {
 
 		$sql_extra = ((strlen($hub_verify)) ? sprintf(" AND `hub-verify` = '%s' ", dbesc($hub_verify)) : '');
 
-		$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d
+		$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d 
 			AND `blocked` = 0 AND `pending` = 0 $sql_extra LIMIT 1",
 			intval($contact_id),
 			intval($owner['uid'])
@@ -76,7 +75,7 @@ function pubsub_init(&$a) {
 
 		$contact = $r[0];
 
-		// We must initiate an unsubscribe request with a verify_token.
+		// We must initiate an unsubscribe request with a verify_token. 
 		// Don't allow outsiders to unsubscribe us.
 
 		if($hub_mode === 'unsubscribe') {
@@ -96,11 +95,9 @@ function pubsub_init(&$a) {
  		hub_return(true, $hub_challenge);
 	}
 }
-}
 
 require_once('include/security.php');
 
-if(! function_exists('pubsub_post')) {
 function pubsub_post(&$a) {
 
 	$xml = file_get_contents('php://input');
@@ -158,5 +155,8 @@ function pubsub_post(&$a) {
 	consume_feed($xml,$importer,$contact,$feedhub,1,2);
 
 	hub_post_return();
+
 }
-}
+
+
+
diff --git a/mod/pubsubhubbub.php b/mod/pubsubhubbub.php
index b0e3ef3099..5d7621cc74 100644
--- a/mod/pubsubhubbub.php
+++ b/mod/pubsubhubbub.php
@@ -1,12 +1,9 @@
 <?php
 
-if(! function_exists('post_var')) {
 function post_var($name) {
 	return (x($_POST, $name)) ? notags(trim($_POST[$name])) : '';
 }
-}
 
-if(! function_exists('pubsubhubbub_init')) {
 function pubsubhubbub_init(&$a) {
 	// PuSH subscription must be considered "public" so just block it
 	// if public access isn't enabled.
@@ -161,5 +158,5 @@ function pubsubhubbub_init(&$a) {
 
 	killme();
 }
-}
+
 ?>
diff --git a/mod/qsearch.php b/mod/qsearch.php
index cffc3e50ba..c35e253b67 100644
--- a/mod/qsearch.php
+++ b/mod/qsearch.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('qsearch_init')) {
 function qsearch_init(&$a) {
 
 	if(! local_user())
@@ -48,4 +47,4 @@ function qsearch_init(&$a) {
 	echo json_encode((object) $results);
 	killme();
 }
-}
+
diff --git a/mod/randprof.php b/mod/randprof.php
index e9e0a8e7bb..6713a81d9e 100644
--- a/mod/randprof.php
+++ b/mod/randprof.php
@@ -1,6 +1,6 @@
 <?php
 
-if(! function_exists('randprof_init')) {
+
 function randprof_init(&$a) {
 	require_once('include/Contact.php');
 	$x = random_profile();
@@ -8,4 +8,3 @@ function randprof_init(&$a) {
 		goaway(zrl($x));
 	goaway($a->get_baseurl() . '/profile');
 }
-}
diff --git a/mod/receive.php b/mod/receive.php
index 3a30058cdc..95a5101675 100644
--- a/mod/receive.php
+++ b/mod/receive.php
@@ -9,7 +9,7 @@ require_once('include/salmon.php');
 require_once('include/crypto.php');
 require_once('include/diaspora.php');
 
-if(! function_exists('receive_post')) {
+
 function receive_post(&$a) {
 
 
@@ -73,4 +73,4 @@ function receive_post(&$a) {
 	http_status_exit(($ret) ? $ret : 200);
 	// NOTREACHED
 }
-}
+
diff --git a/mod/redir.php b/mod/redir.php
index 2dda0571b2..632c395786 100644
--- a/mod/redir.php
+++ b/mod/redir.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('redir_init')) {
 function redir_init(&$a) {
 
 	$url = ((x($_GET,'url')) ? $_GET['url'] : '');
@@ -58,9 +57,9 @@ function redir_init(&$a) {
 			intval(time() + 45)
 		);
 
-		logger('mod_redir: ' . $r[0]['name'] . ' ' . $sec, LOGGER_DEBUG);
+		logger('mod_redir: ' . $r[0]['name'] . ' ' . $sec, LOGGER_DEBUG); 
 		$dest = (($url) ? '&destination_url=' . $url : '');
-		goaway ($r[0]['poll'] . '?dfrn_id=' . $dfrn_id
+		goaway ($r[0]['poll'] . '?dfrn_id=' . $dfrn_id 
 			. '&dfrn_version=' . DFRN_PROTOCOL_VERSION . '&type=profile&sec=' . $sec . $dest . $quiet );
 	}
 
@@ -76,4 +75,3 @@ function redir_init(&$a) {
 
 	goaway(z_root());
 }
-}
diff --git a/mod/regmod.php b/mod/regmod.php
index 2e3ca414e3..5a90db1f90 100644
--- a/mod/regmod.php
+++ b/mod/regmod.php
@@ -3,7 +3,6 @@
 require_once('include/enotify.php');
 require_once('include/user.php');
 
-if(! function_exists('user_allow')) {
 function user_allow($hash) {
 
 	$a = get_app();
@@ -56,14 +55,14 @@ function user_allow($hash) {
 		info( t('Account approved.') . EOL );
 		return true;
 	}
-}
+
 }
 
 
 // This does not have to go through user_remove() and save the nickname
 // permanently against re-registration, as the person was not yet
 // allowed to have friends on this system
-if(! function_exists('user_deny')) {
+
 function user_deny($hash) {
 
 	$register = q("SELECT * FROM `register` WHERE `hash` = '%s' LIMIT 1",
@@ -92,10 +91,9 @@ function user_deny($hash) {
 	);
 	notice( sprintf(t('Registration revoked for %s'), $user[0]['username']) . EOL);
 	return true;
-}
+
 }
 
-if(! function_exists('regmod_content')) {
 function regmod_content(&$a) {
 
 	global $lang;
@@ -133,4 +131,3 @@ function regmod_content(&$a) {
 		killme();
 	}
 }
-}
diff --git a/mod/removeme.php b/mod/removeme.php
index 6c84c41892..904606fd57 100644
--- a/mod/removeme.php
+++ b/mod/removeme.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('removeme_post')) {
 function removeme_post(&$a) {
 
 	if(! local_user())
@@ -25,10 +24,9 @@ function removeme_post(&$a) {
 		user_remove($a->user['uid']);
 		// NOTREACHED
 	}
-}
+
 }
 
-if(! function_exists('removeme_content')) {
 function removeme_content(&$a) {
 
 	if(! local_user())
@@ -52,5 +50,5 @@ function removeme_content(&$a) {
 	));
 
 	return $o;
-}
+
 }
diff --git a/mod/repair_ostatus.php b/mod/repair_ostatus.php
index e3956ba8cb..2b1224f423 100755
--- a/mod/repair_ostatus.php
+++ b/mod/repair_ostatus.php
@@ -3,7 +3,6 @@
 require_once('include/Scrape.php');
 require_once('include/follow.php');
 
-if(! function_exists('repair_ostatus_content')) {
 function repair_ostatus_content(&$a) {
 
 	if(! local_user()) {
@@ -56,4 +55,3 @@ function repair_ostatus_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/rsd_xml.php b/mod/rsd_xml.php
index 6f9c209fab..f4984f0f0f 100644
--- a/mod/rsd_xml.php
+++ b/mod/rsd_xml.php
@@ -1,6 +1,7 @@
 <?php
 
-if(! function_exists('rsd_xml_content')) {
+
+
 function rsd_xml_content(&$a) {
 	header ("Content-Type: text/xml");
 	echo '<?xml version="1.0" encoding="UTF-8"?>
@@ -20,5 +21,4 @@ function rsd_xml_content(&$a) {
  </rsd>
 	';
 die();
-}
-}
+}
\ No newline at end of file
diff --git a/mod/salmon.php b/mod/salmon.php
index ee3826d8a8..9c22e42d11 100644
--- a/mod/salmon.php
+++ b/mod/salmon.php
@@ -6,7 +6,6 @@ require_once('include/crypto.php');
 require_once('include/items.php');
 require_once('include/follow.php');
 
-if(! function_exists('salmon_return')) {
 function salmon_return($val) {
 
 	if($val >= 400)
@@ -17,10 +16,9 @@ function salmon_return($val) {
 	logger('mod-salmon returns ' . $val);
 	header($_SERVER["SERVER_PROTOCOL"] . ' ' . $val . ' ' . $err);
 	killme();
-}
+
 }
 
-if(! function_exists('salmon_post')) {
 function salmon_post(&$a) {
 
 	$xml = file_get_contents('php://input');
@@ -157,7 +155,7 @@ function salmon_post(&$a) {
 		if(get_pconfig($importer['uid'],'system','ostatus_autofriend')) {
 			$result = new_contact($importer['uid'],$author_link);
 			if($result['success']) {
-				$r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND ( `url` = '%s' OR `alias` = '%s')
+				$r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND ( `url` = '%s' OR `alias` = '%s') 
 					AND `uid` = %d LIMIT 1",
 					dbesc(NETWORK_OSTATUS),
 					dbesc($author_link),
@@ -187,4 +185,3 @@ function salmon_post(&$a) {
 
 	http_status_exit(200);
 }
-}
diff --git a/mod/search.php b/mod/search.php
index 431bd821d6..7c78339c70 100644
--- a/mod/search.php
+++ b/mod/search.php
@@ -4,7 +4,6 @@ require_once('include/security.php');
 require_once('include/conversation.php');
 require_once('mod/dirfind.php');
 
-if(! function_exists('search_saved_searches')) {
 function search_saved_searches() {
 
 	$o = '';
@@ -40,10 +39,10 @@ function search_saved_searches() {
 	}
 
 	return $o;
-}
+
 }
 
-if(! function_exists('search_init')) {
+
 function search_init(&$a) {
 
 	$search = ((x($_GET,'search')) ? notags(trim(rawurldecode($_GET['search']))) : '');
@@ -77,18 +76,17 @@ function search_init(&$a) {
 	}
 
 
-}
+
 }
 
 
-if(! function_exists('search_post')) {
+
 function search_post(&$a) {
 	if(x($_POST,'search'))
 		$a->data['search'] = $_POST['search'];
 }
-}
 
-if(! function_exists('search_content')) {
+
 function search_content(&$a) {
 
 	if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
@@ -250,4 +248,4 @@ function search_content(&$a) {
 
 	return $o;
 }
-}
+
diff --git a/mod/session.php b/mod/session.php
index ac3d885b63..22c855edba 100644
--- a/mod/session.php
+++ b/mod/session.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('session_content')) {
 function session_content(&$a) {
-}
+
 }
diff --git a/mod/settings.php b/mod/settings.php
index 1b62499c22..3efdbf6bde 100644
--- a/mod/settings.php
+++ b/mod/settings.php
@@ -1,7 +1,7 @@
 <?php
 
-if(! function_exists('get_theme_config_file')) {
-function get_theme_config_file($theme) {
+
+function get_theme_config_file($theme){
 	$a = get_app();
 	$base_theme = $a->theme_info['extends'];
 
@@ -13,9 +13,7 @@ function get_theme_config_file($theme) {
 	}
 	return null;
 }
-}
 
-if(! function_exists('settings_init')) {
 function settings_init(&$a) {
 
 	if(! local_user()) {
@@ -112,10 +110,10 @@ function settings_init(&$a) {
 		'$class' => 'settings-widget',
 		'$items' => $tabs,
 	));
-}
+
 }
 
-if(! function_exists('settings_post')) {
+
 function settings_post(&$a) {
 
 	if(! local_user())
@@ -632,9 +630,8 @@ function settings_post(&$a) {
 	goaway($a->get_baseurl(true) . '/settings' );
 	return; // NOTREACHED
 }
-}
 
-if(! function_exists('settings_content')) {
+
 function settings_content(&$a) {
 
 	$o = '';
@@ -1298,5 +1295,6 @@ function settings_content(&$a) {
 	$o .= '</form>' . "\r\n";
 
 	return $o;
+
 }
-}
+
diff --git a/mod/share.php b/mod/share.php
index f3a221eb8e..085da4e30d 100644
--- a/mod/share.php
+++ b/mod/share.php
@@ -1,14 +1,12 @@
 <?php
-
-if(! function_exists('share_init')) {
 function share_init(&$a) {
 
 	$post_id = (($a->argc > 1) ? intval($a->argv[1]) : 0);
 	if((! $post_id) || (! local_user()))
 		killme();
 
-	$r = q("SELECT item.*, contact.network FROM `item`
-		inner join contact on `item`.`contact-id` = `contact`.`id`
+	$r = q("SELECT item.*, contact.network FROM `item` 
+		inner join contact on `item`.`contact-id` = `contact`.`id` 
 		WHERE `item`.`id` = %d AND `item`.`uid` = %d LIMIT 1",
 
 		intval($post_id),
@@ -42,9 +40,7 @@ function share_init(&$a) {
 	echo $o;
 	killme();
 }
-}
 
-if(! function_exists('share_header')) {
 function share_header($author, $profile, $avatar, $guid, $posted, $link) {
 	$header = "[share author='".str_replace(array("'", "[", "]"), array("&#x27;", "&#x5B;", "&#x5D;"),$author).
 		"' profile='".str_replace(array("'", "[", "]"), array("&#x27;", "&#x5B;", "&#x5D;"),$profile).
@@ -60,4 +56,3 @@ function share_header($author, $profile, $avatar, $guid, $posted, $link) {
 
 	return $header;
 }
-}
diff --git a/mod/smilies.php b/mod/smilies.php
index 4d498b6746..c47f95da76 100644
--- a/mod/smilies.php
+++ b/mod/smilies.php
@@ -1,7 +1,3 @@
 <?php
 
-if(! function_exists('smilies_content')) {
-function smilies_content(&$a) {
-  return smilies('',true);
-}
-}
+function smilies_content(&$a) { return smilies('',true); }
diff --git a/mod/starred.php b/mod/starred.php
index b4cc326787..2a89ac768b 100644
--- a/mod/starred.php
+++ b/mod/starred.php
@@ -1,6 +1,6 @@
 <?php
 
-if(! function_exists('starred_init')) {
+
 function starred_init(&$a) {
 
 	require_once("include/threads.php");
@@ -47,4 +47,3 @@ function starred_init(&$a) {
 	echo json_encode($starred);
 	killme();
 }
-}
diff --git a/mod/statistics_json.php b/mod/statistics_json.php
index 98cc708d26..21a9a0521c 100644
--- a/mod/statistics_json.php
+++ b/mod/statistics_json.php
@@ -5,7 +5,6 @@
 
 require_once("include/plugin.php");
 
-if(! function_exists('statistics_json_init')) {
 function statistics_json_init(&$a) {
 
         if (!get_config("system", "nodeinfo")) {
@@ -58,4 +57,3 @@ function statistics_json_init(&$a) {
 	logger("statistics_init: printed ".print_r($statistics, true), LOGGER_DATA);
 	killme();
 }
-}
diff --git a/mod/subthread.php b/mod/subthread.php
index 6cbaa1d2a7..1486a33b42 100644
--- a/mod/subthread.php
+++ b/mod/subthread.php
@@ -4,7 +4,7 @@ require_once('include/security.php');
 require_once('include/bbcode.php');
 require_once('include/items.php');
 
-if(! function_exists('subthread_content')) {
+
 function subthread_content(&$a) {
 
 	if(! local_user() && ! remote_user()) {
@@ -47,7 +47,7 @@ function subthread_content(&$a) {
 			$remote_owner = $r[0];
 	}
 
-	// this represents the post owner on this system.
+	// this represents the post owner on this system. 
 
 	$r = q("SELECT `contact`.*, `user`.`nickname` FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid`
 		WHERE `contact`.`self` = 1 AND `contact`.`uid` = %d LIMIT 1",
@@ -103,7 +103,7 @@ EOT;
 	$bodyverb = t('%1$s is following %2$s\'s %3$s');
 
 	if(! isset($bodyverb))
-			return;
+			return; 
 
 	$arr = array();
 
@@ -123,7 +123,7 @@ EOT;
 	$arr['author-name'] = $contact['name'];
 	$arr['author-link'] = $contact['url'];
 	$arr['author-avatar'] = $contact['thumb'];
-
+	
 	$ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
 	$alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]';
 	$plink = '[url=' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . ']' . $post_type . '[/url]';
@@ -154,5 +154,7 @@ EOT;
 	call_hooks('post_local_end', $arr);
 
 	killme();
+
 }
-}
+
+
diff --git a/mod/suggest.php b/mod/suggest.php
index 8f5f4f6a12..b73c2cd1b6 100644
--- a/mod/suggest.php
+++ b/mod/suggest.php
@@ -3,7 +3,7 @@
 require_once('include/socgraph.php');
 require_once('include/contact_widgets.php');
 
-if(! function_exists('suggest_init')) {
+
 function suggest_init(&$a) {
 	if(! local_user())
 		return;
@@ -42,13 +42,13 @@ function suggest_init(&$a) {
 			);
 		}
 	}
-}
+
 }
 
 
 
 
-if(! function_exists('suggest_content')) {
+
 function suggest_content(&$a) {
 
 	require_once("mod/proxy.php");
@@ -110,9 +110,8 @@ function suggest_content(&$a) {
 	$o .= replace_macros($tpl,array(
 		'$title' => t('Friend Suggestions'),
 		'$contacts' => $entries,
-
+		
 	));
 
 	return $o;
 }
-}
diff --git a/mod/tagger.php b/mod/tagger.php
index bee37015ea..2c469a58bb 100644
--- a/mod/tagger.php
+++ b/mod/tagger.php
@@ -4,7 +4,7 @@ require_once('include/security.php');
 require_once('include/bbcode.php');
 require_once('include/items.php');
 
-if(! function_exists('tagger_content')) {
+
 function tagger_content(&$a) {
 
 	if(! local_user() && ! remote_user()) {
@@ -95,7 +95,7 @@ EOT;
 	$bodyverb = t('%1$s tagged %2$s\'s %3$s with %4$s');
 
 	if(! isset($bodyverb))
-			return;
+			return; 
 
 	$termlink = html_entity_decode('&#x2317;') . '[url=' . $a->get_baseurl() . '/search?tag=' . urlencode($term) . ']'. $term . '[/url]';
 
@@ -115,7 +115,7 @@ EOT;
 	$arr['author-name'] = $contact['name'];
 	$arr['author-link'] = $contact['url'];
 	$arr['author-avatar'] = $contact['thumb'];
-
+	
 	$ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
 	$alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]';
 	$plink = '[url=' . $item['plink'] . ']' . $post_type . '[/url]';
@@ -216,5 +216,5 @@ EOT;
 
 	return; // NOTREACHED
 
-}
+
 }
diff --git a/mod/tagrm.php b/mod/tagrm.php
index 70b3ef048f..176986bc38 100644
--- a/mod/tagrm.php
+++ b/mod/tagrm.php
@@ -2,7 +2,6 @@
 
 require_once('include/bbcode.php');
 
-if(! function_exists('tagrm_post')) {
 function tagrm_post(&$a) {
 
 	if(! local_user())
@@ -41,13 +40,13 @@ function tagrm_post(&$a) {
 
 	info( t('Tag removed') . EOL );
 	goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
-
+	
 	// NOTREACHED
-}
+
 }
 
 
-if(! function_exists('tagrm_content')) {
+
 function tagrm_content(&$a) {
 
 	$o = '';
@@ -96,5 +95,5 @@ function tagrm_content(&$a) {
 	$o .= '</form>';
 
 	return $o;
-}
+	
 }
diff --git a/mod/toggle_mobile.php b/mod/toggle_mobile.php
index dbf0996bba..00991e44ca 100644
--- a/mod/toggle_mobile.php
+++ b/mod/toggle_mobile.php
@@ -1,6 +1,5 @@
 <?php
 
-if(! function_exists('toggle_mobile_init')) {
 function toggle_mobile_init(&$a) {
 
 	if(isset($_GET['off']))
@@ -15,4 +14,4 @@ function toggle_mobile_init(&$a) {
 
 	goaway($address);
 }
-}
+
diff --git a/mod/uexport.php b/mod/uexport.php
index eacf300f3f..a44620a976 100644
--- a/mod/uexport.php
+++ b/mod/uexport.php
@@ -1,7 +1,6 @@
 <?php
 
-if(! function_exists('uexport_init')) {
-function uexport_init(&$a) {
+function uexport_init(&$a){
 	if(! local_user())
 		killme();
 
@@ -56,10 +55,8 @@ function uexport_init(&$a) {
 	));
 */
 }
-}
 
-if(! function_exists('uexport_content')) {
-function uexport_content(&$a) {
+function uexport_content(&$a){
 
     if ($a->argc > 1) {
         header("Content-type: application/json");
@@ -89,10 +86,9 @@ function uexport_content(&$a) {
         '$options' => $options
     ));
 
-}
+
 }
 
-if(! function_exists('_uexport_multirow')) {
 function _uexport_multirow($query) {
 	$result = array();
 	$r = q($query);
@@ -107,9 +103,7 @@ function _uexport_multirow($query) {
 	}
     return $result;
 }
-}
 
-if(! function_exists('_uexport_row')) {
 function _uexport_row($query) {
 	$result = array();
 	$r = q($query);
@@ -121,10 +115,9 @@ function _uexport_row($query) {
 	}
     return $result;
 }
-}
 
-if(! function_exists('uexport_account')) {
-function uexport_account($a) {
+
+function uexport_account($a){
 
 	$user = _uexport_row(
         sprintf( "SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval(local_user()) )
@@ -160,9 +153,9 @@ function uexport_account($a) {
         'version' => FRIENDICA_VERSION,
         'schema' => DB_UPDATE_VERSION,
         'baseurl' => $a->get_baseurl(),
-        'user' => $user,
-        'contact' => $contact,
-        'profile' => $profile,
+        'user' => $user, 
+        'contact' => $contact, 
+        'profile' => $profile, 
         'photo' => $photo,
         'pconfig' => $pconfig,
         'group' => $group,
@@ -171,15 +164,14 @@ function uexport_account($a) {
 
     //echo "<pre>"; var_dump(json_encode($output)); killme();
 	echo json_encode($output);
-}
+
 }
 
 /**
  * echoes account data and items as separated json, one per line
  */
-if(! function_exists('uexport_all')) {
 function uexport_all(&$a) {
-
+    
     uexport_account($a);
 	echo "\n";
 
@@ -207,5 +199,5 @@ function uexport_all(&$a) {
 		$output = array('item' => $r);
 		echo json_encode($output)."\n";
 	}
-}
+
 }
diff --git a/mod/uimport.php b/mod/uimport.php
index 942268b0ef..7ed5648d9e 100644
--- a/mod/uimport.php
+++ b/mod/uimport.php
@@ -5,7 +5,6 @@
 
 require_once("include/uimport.php");
 
-if(! function_exists('uimport_post')) {
 function uimport_post(&$a) {
 	switch($a->config['register_policy']) {
         case REGISTER_OPEN:
@@ -28,18 +27,16 @@ function uimport_post(&$a) {
             $verified = 0;
             break;
 	}
-
+    
     if (x($_FILES,'accountfile')){
         /// @TODO Pass $blocked / $verified, send email to admin on REGISTER_APPROVE
         import_account($a, $_FILES['accountfile']);
         return;
     }
 }
-}
 
-if(! function_exists('uimport_content')) {
 function uimport_content(&$a) {
-
+	
 	if((! local_user()) && ($a->config['register_policy'] == REGISTER_CLOSED)) {
 		notice("Permission denied." . EOL);
 		return;
@@ -54,8 +51,8 @@ function uimport_content(&$a) {
 			return;
 		}
 	}
-
-
+	
+	
 	if(x($_SESSION,'theme'))
 		unset($_SESSION['theme']);
 	if(x($_SESSION,'mobile-theme'))
@@ -74,4 +71,3 @@ function uimport_content(&$a) {
         ),
     ));
 }
-}
diff --git a/mod/update_community.php b/mod/update_community.php
index 396f4234c0..512629b005 100644
--- a/mod/update_community.php
+++ b/mod/update_community.php
@@ -4,7 +4,6 @@
 
 require_once('mod/community.php');
 
-if(! function_exists('update_community_content')) {
 function update_community_content(&$a) {
 
 	header("Content-type: text/html");
@@ -30,5 +29,5 @@ function update_community_content(&$a) {
 	echo "</section>";
 	echo "</body></html>\r\n";
 	killme();
-}
-}
+
+}
\ No newline at end of file
diff --git a/mod/update_display.php b/mod/update_display.php
index 9400cb39a6..25b0f77926 100644
--- a/mod/update_display.php
+++ b/mod/update_display.php
@@ -5,7 +5,6 @@
 require_once('mod/display.php');
 require_once('include/group.php');
 
-if(! function_exists('update_display_content')) {
 function update_display_content(&$a) {
 
 	$profile_uid = intval($_GET['p']);
@@ -35,5 +34,5 @@ function update_display_content(&$a) {
 	echo "</section>";
 	echo "</body></html>\r\n";
 	killme();
-}
+
 }
diff --git a/mod/update_network.php b/mod/update_network.php
index b2e7abc90c..1bf3746575 100644
--- a/mod/update_network.php
+++ b/mod/update_network.php
@@ -5,7 +5,6 @@
 require_once('mod/network.php');
 require_once('include/group.php');
 
-if(! function_exists('update_network_content')) {
 function update_network_content(&$a) {
 
 	$profile_uid = intval($_GET['p']);
@@ -38,5 +37,5 @@ function update_network_content(&$a) {
 	echo "</section>";
 	echo "</body></html>\r\n";
 	killme();
-}
+
 }
diff --git a/mod/update_notes.php b/mod/update_notes.php
index e1e4f1d795..6b8fff5115 100644
--- a/mod/update_notes.php
+++ b/mod/update_notes.php
@@ -9,7 +9,6 @@
 
 require_once('mod/notes.php');
 
-if(! function_exists('update_notes_content')) {
 function update_notes_content(&$a) {
 
 	$profile_uid = intval($_GET['p']);
@@ -21,8 +20,8 @@ function update_notes_content(&$a) {
 
 	/**
 	 *
-	 * Grab the page inner contents by calling the content function from the profile module directly,
-	 * but move any image src attributes to another attribute name. This is because
+	 * Grab the page inner contents by calling the content function from the profile module directly, 
+	 * but move any image src attributes to another attribute name. This is because 
 	 * some browsers will prefetch all the images for the page even if we don't need them.
 	 * The only ones we need to fetch are those for new page additions, which we'll discover
 	 * on the client side and then swap the image back.
@@ -53,5 +52,5 @@ function update_notes_content(&$a) {
 	echo "</section>";
 	echo "</body></html>\r\n";
 	killme();
-}
-}
+
+}
\ No newline at end of file
diff --git a/mod/update_profile.php b/mod/update_profile.php
index 93a94ae0d8..2492a48ee4 100644
--- a/mod/update_profile.php
+++ b/mod/update_profile.php
@@ -9,7 +9,6 @@
 
 require_once('mod/profile.php');
 
-if(! function_exists('update_profile_content')) {
 function update_profile_content(&$a) {
 
 	$profile_uid = intval($_GET['p']);
@@ -25,8 +24,8 @@ function update_profile_content(&$a) {
 
 	/**
 	 *
-	 * Grab the page inner contents by calling the content function from the profile module directly,
-	 * but move any image src attributes to another attribute name. This is because
+	 * Grab the page inner contents by calling the content function from the profile module directly, 
+	 * but move any image src attributes to another attribute name. This is because 
 	 * some browsers will prefetch all the images for the page even if we don't need them.
 	 * The only ones we need to fetch are those for new page additions, which we'll discover
 	 * on the client side and then swap the image back.
@@ -57,5 +56,5 @@ function update_profile_content(&$a) {
 	echo "</section>";
 	echo "</body></html>\r\n";
 	killme();
-}
-}
+
+}
\ No newline at end of file
diff --git a/mod/videos.php b/mod/videos.php
index f9db7b05b1..bf8d696b60 100644
--- a/mod/videos.php
+++ b/mod/videos.php
@@ -5,7 +5,7 @@ require_once('include/bbcode.php');
 require_once('include/security.php');
 require_once('include/redir.php');
 
-if(! function_exists('videos_init')) {
+
 function videos_init(&$a) {
 
 	if($a->argc > 1)
@@ -102,9 +102,9 @@ function videos_init(&$a) {
 
 	return;
 }
-}
 
-if(! function_exists('videos_post')) {
+
+
 function videos_post(&$a) {
 
 	$owner_uid = $a->data['user']['uid'];
@@ -176,11 +176,11 @@ function videos_post(&$a) {
 	}
 
     goaway($a->get_baseurl() . '/videos/' . $a->data['user']['nickname']);
-}
+
 }
 
 
-if(! function_exists('videos_content')) {
+
 function videos_content(&$a) {
 
 	// URLs (most aren't currently implemented):
@@ -407,4 +407,4 @@ function videos_content(&$a) {
 	$o .= paginate($a);
 	return $o;
 }
-}
+
diff --git a/mod/view.php b/mod/view.php
index a270baeaa1..15b3733b3f 100644
--- a/mod/view.php
+++ b/mod/view.php
@@ -2,18 +2,16 @@
 /**
  * load view/theme/$current_theme/style.php with friendica contex
  */
-
-if(! function_exists('view_init')) {
-function view_init($a) {
+ 
+function view_init($a){
 	header("Content-Type: text/css");
-
+		
 	if ($a->argc == 4){
 		$theme = $a->argv[2];
 		$THEMEPATH = "view/theme/$theme";
 		if(file_exists("view/theme/$theme/style.php"))
 			require_once("view/theme/$theme/style.php");
 	}
-
+	
 	killme();
 }
-}
diff --git a/mod/viewcontacts.php b/mod/viewcontacts.php
index acb51f0cb4..04520e0d93 100644
--- a/mod/viewcontacts.php
+++ b/mod/viewcontacts.php
@@ -2,7 +2,6 @@
 require_once('include/Contact.php');
 require_once('include/contact_selectors.php');
 
-if(! function_exists('viewcontacts_init')) {
 function viewcontacts_init(&$a) {
 
 	if((get_config('system','block_public')) && (! local_user()) && (! remote_user())) {
@@ -27,9 +26,8 @@ function viewcontacts_init(&$a) {
 		profile_load($a,$a->argv[1]);
 	}
 }
-}
 
-if(! function_exists('viewcontacts_content')) {
+
 function viewcontacts_content(&$a) {
 	require_once("mod/proxy.php");
 
@@ -123,4 +121,3 @@ function viewcontacts_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/viewsrc.php b/mod/viewsrc.php
index 1203d18fc9..3fa4eaed53 100644
--- a/mod/viewsrc.php
+++ b/mod/viewsrc.php
@@ -1,6 +1,6 @@
 <?php
 
-if(! function_exists('viewsrc_content')) {
+
 function viewsrc_content(&$a) {
 
 	if(! local_user()) {
@@ -16,7 +16,7 @@ function viewsrc_content(&$a) {
 		return;
 	}
 
-	$r = q("SELECT `item`.`body` FROM `item`
+	$r = q("SELECT `item`.`body` FROM `item` 
 		WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
 		and `item`.`moderated` = 0
 		AND `item`.`id` = '%s' LIMIT 1",
@@ -33,4 +33,4 @@ function viewsrc_content(&$a) {
 		}
 	return $o;
 }
-}
+
diff --git a/mod/wall_attach.php b/mod/wall_attach.php
index 20e646cb9a..68752a0e1f 100644
--- a/mod/wall_attach.php
+++ b/mod/wall_attach.php
@@ -3,7 +3,6 @@
 require_once('include/attach.php');
 require_once('include/datetime.php');
 
-if(! function_exists('wall_attach_post')) {
 function wall_attach_post(&$a) {
 
 	$r_json = (x($_GET,'response') && $_GET['response']=='json');
@@ -191,4 +190,3 @@ function wall_attach_post(&$a) {
 	killme();
 	// NOTREACHED
 }
-}
diff --git a/mod/wall_upload.php b/mod/wall_upload.php
index 2851807d57..b815348c70 100644
--- a/mod/wall_upload.php
+++ b/mod/wall_upload.php
@@ -2,7 +2,6 @@
 
 require_once('include/Photo.php');
 
-if(! function_exists('wall_upload_post')) {
 function wall_upload_post(&$a, $desktopmode = true) {
 
 	logger("wall upload: starting new upload", LOGGER_DEBUG);
@@ -298,4 +297,3 @@ function wall_upload_post(&$a, $desktopmode = true) {
 	killme();
 	// NOTREACHED
 }
-}
diff --git a/mod/wallmessage.php b/mod/wallmessage.php
index a01dfd2b9f..b8859badd3 100644
--- a/mod/wallmessage.php
+++ b/mod/wallmessage.php
@@ -2,7 +2,6 @@
 
 require_once('include/message.php');
 
-if(! function_exists('wallmessage_post')) {
 function wallmessage_post(&$a) {
 
 	$replyto = get_my_url();
@@ -49,7 +48,7 @@ function wallmessage_post(&$a) {
 	$body = str_replace("\r\n","\n",$body);
 	$body = str_replace("\n\n","\n",$body);
 
-
+	
 	$ret = send_wallmessage($user, $body, $subject, $replyto);
 
 	switch($ret){
@@ -70,10 +69,10 @@ function wallmessage_post(&$a) {
 	}
 
 //	goaway($a->get_baseurl() . '/profile/' . $user['nickname']);
-}
+	
 }
 
-if(! function_exists('wallmessage_content')) {
+
 function wallmessage_content(&$a) {
 
 	if(! get_my_url()) {
@@ -135,9 +134,9 @@ function wallmessage_content(&$a) {
 		'$nickname' => $user['nickname'],
 		'$linkurl' => t('Please enter a link URL:')
 	));
+	
 
-
-
+	
 	$tpl = get_markup_template('wallmessage.tpl');
 	$o .= replace_macros($tpl,array(
 		'$header' => t('Send Private Message'),
@@ -159,4 +158,3 @@ function wallmessage_content(&$a) {
 
 	return $o;
 }
-}
diff --git a/mod/webfinger.php b/mod/webfinger.php
index 4024671b02..74bd2c9543 100644
--- a/mod/webfinger.php
+++ b/mod/webfinger.php
@@ -1,13 +1,14 @@
 <?php
 
-if(! function_exists('webfinger_content')) {
+
+
 function webfinger_content(&$a) {
 
 	$o .= '<h3>Webfinger Diagnostic</h3>';
 
 	$o .= '<form action="webfinger" method="get">';
 	$o .= 'Lookup address: <input type="text" style="width: 250px;" name="addr" value="' . $_GET['addr'] .'" />';
-	$o .= '<input type="submit" name="submit" value="Submit" /></form>';
+	$o .= '<input type="submit" name="submit" value="Submit" /></form>'; 
 
 	$o .= '<br /><br />';
 
@@ -23,4 +24,3 @@ function webfinger_content(&$a) {
 	}
 	return $o;
 }
-}
diff --git a/mod/xrd.php b/mod/xrd.php
index f8e0a9c409..c23119145c 100644
--- a/mod/xrd.php
+++ b/mod/xrd.php
@@ -2,7 +2,6 @@
 
 require_once('include/crypto.php');
 
-if(! function_exists('xrd_init')) {
 function xrd_init(&$a) {
 
 	$uri = urldecode(notags(trim($_GET['uri'])));
@@ -78,5 +77,5 @@ function xrd_init(&$a) {
 
 	echo $arr['xml'];
 	killme();
-}
+
 }

From 991cbd604a588e676bf316aa120f223071bdff94 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Mon, 8 Feb 2016 01:56:15 +0100
Subject: [PATCH 058/273] contact-edit-actions-button: initial commit

---
 mod/contacts.php                | 71 ++++++++++++++++++++++++++++++++-
 view/global.css                 | 69 ++++++++++++++++++++++----------
 view/templates/contact_edit.tpl | 24 ++++++-----
 3 files changed, 132 insertions(+), 32 deletions(-)

diff --git a/mod/contacts.php b/mod/contacts.php
index 0b421433e0..248ed47ab3 100644
--- a/mod/contacts.php
+++ b/mod/contacts.php
@@ -565,6 +565,8 @@ function contacts_content(&$a) {
 			($contact['rel'] == CONTACT_IS_FOLLOWER))
 			$follow = $a->get_baseurl(true)."/follow?url=".urlencode($contact["url"]);
 
+		$contact_actions = contact_action_menu($contact);
+
 
 		$o .= replace_macros($tpl, array(
 			//'$header' => t('Contact Editor'),
@@ -574,7 +576,7 @@ function contacts_content(&$a) {
 			'$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['name']),
 			'$lbl_info1' => t('Contact Information / Notes'),
 			'$infedit' => t('Edit contact notes'),
-			'$common_text' => $common_text,
+			//'$common_text' => $common_text,
 			'$common_link' => $a->get_baseurl(true) . '/common/loc/' . local_user() . '/' . $contact['id'],
 			'$all_friends' => $all_friends,
 			'$relation_text' => $relation_text,
@@ -622,7 +624,9 @@ function contacts_content(&$a) {
 			'$about' => bbcode($contact["about"], false, false),
 			'$about_label' => t("About:"),
 			'$keywords' => $contact["keywords"],
-			'$keywords_label' => t("Tags:")
+			'$keywords_label' => t("Tags:"),
+			'$contact_action_button' => t("Actions"),
+			'$contact_actions' => $contact_actions,
 
 		));
 
@@ -954,3 +958,66 @@ function _contact_detail_for_template($rr){
 	);
 
 }
+
+function contact_action_menu($contact) {
+
+	$contact_action_menu = array(
+				'suggest' => array(
+					'label' => t('Suggest friends'),
+					'url'	=> app::get_baseurl(true) . '/fsuggest/' . $contact['id'],
+					'title'	=> '',
+					'sel'	=> '',
+					'id'	=>  'suggest',
+				),
+
+				'update' => array(
+					'label'	=> t('Update now'),
+					'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/update',
+					'title'	=> '',
+					'sel'	=> '',
+					'id'	=> 'update',
+				),
+
+				'repair' => array(
+					'label'	=> t('Repair'),
+					'url'	=> app::get_baseurl(true) . '/crepair/' . $contact['id'],
+					'title' => t('Advanced Contact Settings'),
+					'sel'	=> '',
+					'id'	=> 'repair',
+				),
+
+				'block' => array(
+					'label'	=> (intval($contact['blocked']) ? t('Unblock') : t('Block') ),
+					'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/block',
+					'title' => t('Toggle Blocked status'),
+					'sel'	=> (intval($contact['blocked']) ? 'active' : ''),
+					'id'	=> 'toggle-block',
+				),
+
+				'ignore' => array(
+					'label'	=> (intval($contact['readonly']) ? t('Unignore') : t('Ignore') ),
+					'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/ignore',
+					'title' => t('Toggle Ignored status'),
+					'sel'	=> (intval($contact['readonly']) ? 'active' : ''),
+					'id'	=> 'toggle-ignore',
+				),
+
+				'archive' => array(
+					'label'	=> (intval($contact['archive']) ? t('Unarchive') : t('Archive') ),
+					'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/archive',
+					'title' => t('Toggle Archive status'),
+					'sel'	=> (intval($contact['archive']) ? 'active' : ''),
+					'id'	=> 'toggle-archive',
+				),
+
+				'delete' => array(
+					'label'	=> t('Delete'),
+					'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/drop', 
+					'title'	=> t('Delete contact'),
+					'sel'	=> '',
+					'id'	=> 'delete',
+				)
+	);
+
+	return $contact_action_menu;
+}
diff --git a/view/global.css b/view/global.css
index 8646bf8e44..df001ed362 100644
--- a/view/global.css
+++ b/view/global.css
@@ -1,6 +1,28 @@
 /* General style rules .*/
 .pull-right { float: right }
 
+/* General designing elements */
+.btn {
+  outline: none;
+  -moz-box-shadow: inset 0px 1px 0px 0px #ffffff;
+  -webkit-box-shadow: inset 0px 1px 0px 0px #ffffff;
+  box-shadow: inset 0px 1px 0px 0px #ffffff;
+  background-color: #ededed;
+  text-indent: 0;
+  border: 1px solid #dcdcdc;
+  display: inline-block;
+  color: #777777;
+  padding: 5px 10px;
+  text-align: center;
+}
+
+ul.menu-popup li.divider {
+  height: 1px;
+  margin: 3px 0;
+  overflow: hidden;
+  background-color: #2d2d2d;;
+}
+
 /* List of social Networks */
 img.connector, img.connector-disabled {
   height: 40px;
@@ -277,20 +299,20 @@ a {
   margin: 10px 0 10px;
 }
 .version-match {
-    font-weight: bold;
-    color: #00a700;
+  font-weight: bold;
+  color: #00a700;
 }
 .federation-graph {
-    width: 400px; 
-    height: 400px; 
-    float: right; 
-    margin: 20px;
+  width: 400px; 
+  height: 400px; 
+  float: right; 
+  margin: 20px;
 }
 .federation-network-graph {
-    width: 240px; 
-    height: 240px; 
-    float: left; 
-    margin: 20px;
+  width: 240px; 
+  height: 240px; 
+  float: left; 
+  margin: 20px;
 }
 ul.federation-stats,
 ul.credits {
@@ -302,10 +324,10 @@ ul.credits li {
   width: 240px;
 }
 table#federation-stats {
-    width: 100%;
+  width: 100%;
 }
 td.federation-data {
-    border-bottom: 1px solid #000;
+  border-bottom: 1px solid #000;
 }
 
 .contact-entry-photo img {
@@ -329,25 +351,30 @@ td.federation-data {
 }
 
 .crepair-label {
-        margin-top: 10px;
-        float: left;
-        width: 250px;
+  margin-top: 10px;
+  float: left;
+  width: 250px;
 }
 
 .crepair-input {
-        margin-top: 10px;
-        float: left;
-        width: 200px;
+  margin-top: 10px;
+  float: left;
+  width: 200px;
 }
 
 .renderinfo {
-	clear: both;
+  clear: both;
 }
 
 .p-addr {
-	clear: both;	
+  clear: both;	
 }
 
 #live-community {
-	clear: both;
+  clear: both;
 }
+
+/* contact-edit */
+#contact-edit-actions {
+    float: right;
+}
\ No newline at end of file
diff --git a/view/templates/contact_edit.tpl b/view/templates/contact_edit.tpl
index 15863b6a27..682ebfa36a 100644
--- a/view/templates/contact_edit.tpl
+++ b/view/templates/contact_edit.tpl
@@ -4,6 +4,21 @@
 
 	{{$tab_str}}
 
+	<div id="contact-edit-actions">
+		<a class="btn" rel="#contact-actions-menu" href="#" id="contact-edit-actions-button">{{$contact_action_button}}</a>
+
+		<ul role="menu" aria-haspopup="true" id="contact-actions-menu" class="menu-popup" >
+			{{if $lblsuggest}}<li><a  href="#" title="{{$contact_actions.suggest.title}}" onclick="window.location.href='{{$contact_actions.suggest.url}}'; return false;">{{$contact_actions.suggest.label}}</a></li>{{/if}}
+			{{if $poll_enabled}}<li><a  href="#" title="{{$contact_actions.update.title}}" onclick="window.location.href='{{$contact_actions.update.url}}'; return false;">{{$contact_actions.update.label}}</a></li>{{/if}}
+			<li><a  href="#" title="{{$contact_actions.repair.title}}" onclick="window.location.href='{{$contact_actions.repair.url}}'; return false;">{{$contact_actions.repair.label}}</a></li>
+			<li class="divider"></li>
+			<li><a  href="#" title="{{$contact_actions.block.title}}" onclick="window.location.href='{{$contact_actions.block.url}}'; return false;">{{$contact_actions.block.label}}</a></li>
+			<li><a  href="#" title="{{$contact_actions.ignore.title}}" onclick="window.location.href='{{$contact_actions.ignore.url}}'; return false;">{{$contact_actions.ignore.label}}</a></li>
+			<li><a  href="#" title="{{$contact_actions.archive.title}}" onclick="window.location.href='{{$contact_actions.archive.url}}'; return false;">{{$contact_actions.archive.label}}</a></li>
+			<li><a  href="#" title="{{$contact_actions.delete.title}}" onclick="return confirmDelete();">{{$contact_actions.delete.label}}</a></li>
+		</ul>
+	</div>
+
 	<div id="contact-edit-drop-link" >
 		<a href="contacts/{{$contact_id}}/drop" class="icon drophide" id="contact-edit-drop-link" onclick="return confirmDelete();"  title="{{$delete}}" onmouseover="imgbright(this);" onmouseout="imgdull(this);"></a>
 	</div>
@@ -35,15 +50,6 @@
 			</ul>
 
 			<ul>
-
-				{{if $common_text}}
-					<li><div id="contact-edit-common"><a href="{{$common_link}}">{{$common_text}}</a></div></li>
-				{{/if}}
-				{{if $all_friends}}
-					<li><div id="contact-edit-allfriends"><a href="allfriends/{{$contact_id}}">{{$all_friends}}</a></div></li>
-				{{/if}}
-
-
 				<!-- <li><a href="network/0?nets=all&cid={{$contact_id}}" id="contact-edit-view-recent">{{$lblrecent}}</a></li> -->
 				{{if $lblsuggest}}
 					<li><a href="fsuggest/{{$contact_id}}" id="contact-edit-suggest">{{$lblsuggest}}</a></li>

From e267630c546190b2a2cf437d98bbd415d48c4de2 Mon Sep 17 00:00:00 2001
From: rabuzarus <trebor@central-unit>
Date: Mon, 8 Feb 2016 01:59:05 +0100
Subject: [PATCH 059/273] datetime.php: cleanup - delete some dots which
 shouldn't be there

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

diff --git a/include/datetime.php b/include/datetime.php
index 6983b6431d..89305a2406 100644
--- a/include/datetime.php
+++ b/include/datetime.php
@@ -75,8 +75,8 @@ function select_timezone($current = 'America/Los_Angeles') {
  * 
  * Return a select using 'field_select_raw' template, with timezones
  * groupped (primarily) by continent
-.* arguments follow convetion as other field_* template array:
-.* 'name', 'label', $value, 'help'
+ * arguments follow convetion as other field_* template array:
+ * 'name', 'label', $value, 'help'
  * 
  * @param string $name Name of the selector
  * @param string $label Label for the selector

From 756b90a4e073c5f1e7cfb0314262b90f408b8f83 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Mon, 8 Feb 2016 09:47:59 +0100
Subject: [PATCH 060/273] add docs, rewrite part of the notification api

list notifications and set note as seen functionalities are now
splitted in two functions, with correct http method requirement.

Fixed returned value from `notification/seen`
---
 include/NotificationsManager.php | 30 +++++++++++--
 include/api.php                  | 74 +++++++++++++++++++++-----------
 2 files changed, 76 insertions(+), 28 deletions(-)

diff --git a/include/NotificationsManager.php b/include/NotificationsManager.php
index 8b0ca9e13d..b7e31d4f65 100644
--- a/include/NotificationsManager.php
+++ b/include/NotificationsManager.php
@@ -1,6 +1,13 @@
 <?php
+/**
+ * @file include/NotificationsManager.php
+ */
 require_once("include/datetime.php");
+require_once("include/bbcode.php");
 
+/**
+ * @brief Read and write notifications from/to database
+ */
 class NotificationsManager {
     private $a;
     
@@ -8,12 +15,27 @@ class NotificationsManager {
         $this->a = get_app();
     }
     
+	/**
+	 * @brief set some extra note properties
+	 *
+	 * @param array $notes array of note arrays from db
+	 * @return array Copy of input array with added properties
+	 * 
+	 * Set some extra properties to note array from db:
+	 *  - timestamp as int in default TZ
+	 *  - date_rel : relative date string
+	 *  - msg_html: message as html string
+	 *  - msg_plain: message as plain text string
+	 */
     private function _set_extra($notes) {
         $rets = array();
         foreach($notes as $n) {
             $local_time = datetime_convert('UTC',date_default_timezone_get(),$n['date']);
             $n['timestamp'] = strtotime($local_time);
             $n['date_rel'] = relative_date($n['date']);
+			$n['msg_html'] = bbcode($n['msg'], false, false, false, false);
+			$n['msg_plain'] = explode("\n",trim(html2plain($n['msg_html'], 0)))[0];
+			
             $rets[] = $n;
         }
         return $rets;
@@ -57,7 +79,7 @@ class NotificationsManager {
         
         if ($limit!="") $limit = " LIMIT ".$limit;
         
-		$r = q("SELECT * from notify where uid = %d $filter_sql order by $order_sql $limit",
+		$r = q("SELECT * FROM notify WHERE uid = %d $filter_sql ORDER BY $order_sql $limit",
 			intval(local_user())
 		);
         if ($r!==false && count($r)>0) return $this->_set_extra($r);
@@ -71,7 +93,7 @@ class NotificationsManager {
      * @return array note values or null if not found
      */
     public function getByID($id) {
-        $r = q("select * from notify where id = %d and uid = %d limit 1",
+        $r = q("SELECT * FROM notify WHERE id = %d AND uid = %d LIMIT 1",
                 intval($id),
                 intval(local_user())
         );
@@ -89,7 +111,7 @@ class NotificationsManager {
      * @return bool true on success, false on errors
      */
     public function setSeen($note, $seen = true) {
-        return q("update notify set seen = %d where ( link = '%s' or ( parent != 0 and parent = %d and otype = '%s' )) and uid = %d",
+        return q("UPDATE notify SET seen = %d WHERE ( link = '%s' OR ( parent != 0 AND parent = %d AND otype = '%s' )) AND uid = %d",
             intval($seen),
             dbesc($note['link']),
             intval($note['parent']),
@@ -105,7 +127,7 @@ class NotificationsManager {
      * @return bool true on success, false on error
      */
     public function setAllSeen($seen = true) {
-    	return q("update notify set seen = %d where uid = %d",
+    	return q("UPDATE notify SET seen = %d WHERE uid = %d",
             intval($seen),
 			intval(local_user())
 		);
diff --git a/include/api.php b/include/api.php
index 5acc816575..16481201e3 100644
--- a/include/api.php
+++ b/include/api.php
@@ -690,6 +690,11 @@
 	function api_array_to_xml($data, $ename="") {
 		$attrs="";
 		$childs="";
+		if (count($data)==1 && !is_array($data[0])) {
+			$ename = array_keys($data)[0];
+			$v = $data[$ename];
+			return "<$ename>$v</$ename>";
+		}
 		foreach($data as $k=>$v) {
 			$k=trim($k,'$');
 			if (!is_array($v)) {
@@ -3415,41 +3420,62 @@
 	api_register_func('api/friendica/activity/unattendmaybe', 'api_friendica_activity', true, API_METHOD_POST);
 
 	/**
-	 * returns notifications
-	 * if called with note id set note seen and returns associated item (if possible)
-	 */
+	 * @brief Returns notifications
+	 *
+	 * @param App $a
+	 * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+	 * @return string
+	*/
 	function api_friendica_notification(&$a, $type) {
 		if (api_user()===false) throw new ForbiddenException();
-		
+		if ($a->argc!==3) throw new BadRequestException("Invalid argument count");
 		$nm = new NotificationsManager();
 		
-		if ($a->argc==3) {
-			$notes = $nm->getAll(array(), "+seen -date", 50);
-			return api_apply_template("<auto>", $type, array('$notes' => $notes));
-		}
-		if ($a->argc==4) {
-			$note = $nm->getByID(intval($a->argv[3]));
-			if (is_null($note)) throw new BadRequestException("Invalid argument");
-			$nm->setSeen($note);
-			if ($note['otype']=='item') {
-				// would be really better with a ItemsManager and $im->getByID() :-P
-				$r = q("SELECT * FROM item WHERE id=%d AND uid=%d",
-					intval($note['iid']),
-					intval(local_user())
-				);
-				if ($r===false) throw new NotFoundException();
+		$notes = $nm->getAll(array(), "+seen -date", 50);
+		return api_apply_template("<auto>", $type, array('$notes' => $notes));
+	}
+	
+	/**
+	 * @brief Set notification as seen and returns associated item (if possible)
+	 *
+	 * POST request with 'id' param as notification id
+	 * 
+	 * @param App $a
+	 * @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
+	 * @return string
+	 */
+	function api_friendica_notification_seen(&$a, $type){
+		if (api_user()===false) throw new ForbiddenException();
+		if ($a->argc!==4) throw new BadRequestException("Invalid argument count");
+		
+		$id = (x($_REQUEST, 'id') ? intval($_REQUEST['id']) : 0);
+		
+		$nm = new NotificationsManager();		
+		$note = $nm->getByID($id);
+		if (is_null($note)) throw new BadRequestException("Invalid argument");
+		
+		$nm->setSeen($note);
+		if ($note['otype']=='item') {
+			// would be really better with an ItemsManager and $im->getByID() :-P
+			$r = q("SELECT * FROM item WHERE id=%d AND uid=%d",
+				intval($note['iid']),
+				intval(local_user())
+			);
+			if ($r!==false) {
+				// we found the item, return it to the user
 				$user_info = api_get_user($a);
 				$ret = api_format_items($r,$user_info);
 				$data = array('$statuses' => $ret);
 				return api_apply_template("timeline", $type, $data);
-			} else {
-				return api_apply_template('test', $type, array('ok' => $ok));
 			}
-			
-		}
-		throw new BadRequestException("Invalid argument count");
+			// the item can't be found, but we set the note as seen, so we count this as a success
+		} 
+		return api_apply_template('<auto>', $type, array('status' => "success"));
 	}
+	
+	api_register_func('api/friendica/notification/seen', 'api_friendica_notification_seen', true, API_METHOD_POST);
 	api_register_func('api/friendica/notification', 'api_friendica_notification', true, API_METHOD_GET);
+	
 
 /*
 To.Do:

From 870d2f844d83741c7fc1878dda72807dab92d992 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Mon, 8 Feb 2016 10:22:12 +0100
Subject: [PATCH 061/273] Update API docs

Add `friendica/notification` and `friendica/notification/seen` endpoints

Fix some list rendering issues

Move all `friendica/*` endpoints under "Implemented API calls (not compatible with other APIs)" section

Add info about permitted HTTP methods and required auth
---
 doc/api.md | 450 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 263 insertions(+), 187 deletions(-)

diff --git a/doc/api.md b/doc/api.md
index ced078f556..f050ae4304 100644
--- a/doc/api.md
+++ b/doc/api.md
@@ -7,6 +7,21 @@ Please refer to the linked documentation for further information.
 ## Implemented API calls
 
 ### General
+#### HTTP Method
+
+API endpoints can restrict the method used to request them.
+Using an invalid method results in HTTP error 405 "Method Not Allowed".
+
+In this document, the required method is listed after the endpoint name. "*" means every method can be used.
+
+#### Auth
+
+Friendica supports basic http auth and OAuth 1 to authenticate the user to the api.
+
+OAuth settings can be added by the user in web UI under /settings/oauth/
+
+In this document, endpoints which requires auth are marked with "AUTH" after endpoint name
+
 #### Unsupported parameters
 * cursor: Not implemented in GNU Social
 * trim_user: Not implemented in GNU Social
@@ -37,36 +52,37 @@ Error body is
 
 json:
 ```
-	{
-	  "error": "Specific error message",
-	  "request": "API path requested",
-	  "code": "HTTP error code"
-	}
+{
+"error": "Specific error message",
+"request": "API path requested",
+"code": "HTTP error code"
+}
 ```
 
 xml:
 ```
-	<status>
-		<error>Specific error message</error>
-		<request>API path requested</request>
-		<code>HTTP error code</code>
-	</status>
+<status>
+<error>Specific error message</error>
+<request>API path requested</request>
+<code>HTTP error code</code>
+</status>
 ```
 
 ---
-### account/rate_limit_status
+### account/rate_limit_status (*; AUTH)
 
 ---
-### account/verify_credentials
+### account/verify_credentials (*; AUTH)
 #### Parameters
+
 * skip_status: Don't show the "status" field. (Default: false)
 * include_entities: "true" shows entities for pictures and links (Default: false)
 
 ---
-### conversation/show
+### conversation/show (*; AUTH)
 Unofficial Twitter command. It shows all direct answers (excluding the original post) to a given id.
 
-#### Parameters
+#### Parameter
 * id: id of the post
 * count: Items per page (default: 20)
 * page: page number
@@ -80,7 +96,7 @@ Unofficial Twitter command. It shows all direct answers (excluding the original
 * contributor_details
 
 ---
-### direct_messages
+### direct_messages (*; AUTH)
 #### Parameters
 * count: Items per page (default: 20)
 * page: page number
@@ -93,7 +109,7 @@ Unofficial Twitter command. It shows all direct answers (excluding the original
 * skip_status
 
 ---
-### direct_messages/all
+### direct_messages/all (*; AUTH)
 #### Parameters
 * count: Items per page (default: 20)
 * page: page number
@@ -102,7 +118,7 @@ Unofficial Twitter command. It shows all direct answers (excluding the original
 * getText: Defines the format of the status field. Can be "html" or "plain"
 
 ---
-### direct_messages/conversation
+### direct_messages/conversation (*; AUTH)
 Shows all direct messages of a conversation
 #### Parameters
 * count: Items per page (default: 20)
@@ -113,7 +129,7 @@ Shows all direct messages of a conversation
 * uri: URI of the conversation
 
 ---
-### direct_messages/new
+### direct_messages/new (POST,PUT; AUTH)
 #### Parameters
 * user_id: id of the user
 * screen_name: screen name (for technical reasons, this value is not unique!)
@@ -122,7 +138,7 @@ Shows all direct messages of a conversation
 * title: Title of the direct message
 
 ---
-### direct_messages/sent
+### direct_messages/sent (*; AUTH)
 #### Parameters
 * count: Items per page (default: 20)
 * page: page number
@@ -132,7 +148,7 @@ Shows all direct messages of a conversation
 * include_entities: "true" shows entities for pictures and links (Default: false)
 
 ---
-### favorites
+### favorites (*; AUTH)
 #### Parameters
 * count: Items per page (default: 20)
 * page: page number
@@ -144,22 +160,23 @@ Shows all direct messages of a conversation
 * user_id
 * screen_name
 
-Favorites aren't displayed to other users, so "user_id" and "screen_name". So setting this value will result in an empty array.
+Favorites aren't displayed to other users, so "user_id" and "screen_name" are unsupported.
+Set this values will result in an empty array.
 
 ---
-### favorites/create
+### favorites/create (POST,PUT; AUTH)
 #### Parameters
 * id
 * include_entities: "true" shows entities for pictures and links (Default: false)
 
 ---
-### favorites/destroy
+### favorites/destroy (POST,DELETE; AUTH)
 #### Parameters
 * id
 * include_entities: "true" shows entities for pictures and links (Default: false)
 
 ---
-### followers/ids
+### followers/ids (*; AUTH)
 #### Parameters
 * stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
 
@@ -171,139 +188,7 @@ Favorites aren't displayed to other users, so "user_id" and "screen_name". So se
 Friendica doesn't allow showing followers of other users.
 
 ---
-### friendica/activity/<verb>
-#### parameters
-* id: item id
-
-Add or remove an activity from an item.
-'verb' can be one of:
-- like
-- dislike
-- attendyes
-- attendno
-- attendmaybe
-
-To remove an activity, prepend the verb with "un", eg. "unlike" or "undislike"
-Attend verbs disable eachother: that means that if "attendyes" was added to an item, adding "attendno" remove previous "attendyes".
-Attend verbs should be used only with event-related items (there is no check at the moment)
-
-#### Return values
-
-On success:
-json
-```"ok"```
-
-xml
-```<ok>true</ok>```
-
-On error:
-HTTP 400 BadRequest
-
----
-### friendica/photo
-#### Parameters
-* photo_id: Resource id of a photo.
-* scale: (optional) scale value of the photo
-
-Returns data of a picture with the given resource.
-If 'scale' isn't provided, returned data include full url to each scale of the photo.
-If 'scale' is set, returned data include image data base64 encoded.
-
-possibile scale value are:
-0: original or max size by server settings
-1: image with or height at <= 640
-2: image with or height at <= 320
-3: thumbnail 160x160
-
-4: Profile image at 175x175
-5: Profile image at 80x80
-6: Profile image at 48x48
-
-An image used as profile image has only scale 4-6, other images only 0-3
-
-#### Return values
-
-json
-```
-	{
-	  "id": "photo id"
-	  "created": "date(YYYY-MM-GG HH:MM:SS)",
-	  "edited": "date(YYYY-MM-GG HH:MM:SS)",
-	  "title": "photo title",
-	  "desc": "photo description",
-	  "album": "album name",
-	  "filename": "original file name",
-	  "type": "mime type",
-	  "height": "number",
-	  "width": "number",
-	  "profile": "1 if is profile photo",
-	  "link": {
-		"<scale>": "url to image"
-		...
-	  },
-	  // if 'scale' is set
-	  "datasize": "size in byte",
-	  "data": "base64 encoded image data"
-	}
-```
-
-xml
-```
-	<photo>
-		<id>photo id</id>
-		<created>date(YYYY-MM-GG HH:MM:SS)</created>
-		<edited>date(YYYY-MM-GG HH:MM:SS)</edited>
-		<title>photo title</title>
-		<desc>photo description</desc>
-		<album>album name</album>
-		<filename>original file name</filename>
-		<type>mime type</type>
-		<height>number</height>
-		<width>number</width>
-		<profile>1 if is profile photo</profile>
-		<links type="array">
-			<link type="mime type" scale="scale number" href="image url"/>
-			...
-		</links>
-	</photo>
-```
-
----
-### friendica/photos/list
-
-Returns a list of all photo resources of the logged in user.
-
-#### Return values
-
-json
-```
-	[
-		{
-			id: "resource_id",
-			album: "album name",
-			filename: "original file name",
-			type: "image mime type",
-			thumb: "url to thumb sized image"
-		},
-		...
-	]
-```
-
-xml
-```
-	<photos type="array">
-		<photo id="resource_id"
-			album="album name"
-			filename="original file name"
-			type="image mime type">
-				"url to thumb sized image"
-		</photo>
-		...
-	</photos>
-```
-
----
-### friends/ids
+### friends/ids (*; AUTH)
 #### Parameters
 * stringify_ids: Should the id numbers be sent as text (true) or number (false)? (default: false)
 
@@ -315,15 +200,15 @@ xml
 Friendica doesn't allow showing friends of other users.
 
 ---
-### help/test
+### help/test (*)
 
 ---
-### media/upload
+### media/upload (POST,PUT; AUTH)
 #### Parameters
 * media: image data
 
 ---
-### oauth/request_token
+### oauth/request_token (*)
 #### Parameters
 * oauth_callback
 
@@ -331,7 +216,7 @@ Friendica doesn't allow showing friends of other users.
 * x_auth_access_type
 
 ---
-### oauth/access_token
+### oauth/access_token (*)
 #### Parameters
 * oauth_verifier
 
@@ -341,7 +226,7 @@ Friendica doesn't allow showing friends of other users.
 * x_auth_mode
 
 ---
-### statuses/destroy
+### statuses/destroy (POST,DELETE; AUTH)
 #### Parameters
 * id: message number
 * include_entities: "true" shows entities for pictures and links (Default: false)
@@ -350,15 +235,21 @@ Friendica doesn't allow showing friends of other users.
 * trim_user
 
 ---
-### statuses/followers
+### statuses/followers (*; AUTH)
+
+#### Parameters
+
 * include_entities: "true" shows entities for pictures and links (Default: false)
 
 ---
-### statuses/friends
+### statuses/friends (*; AUTH)
+
+#### Parameters
+
 * include_entities: "true" shows entities for pictures and links (Default: false)
 
 ---
-### statuses/friends_timeline
+### statuses/friends_timeline (*; AUTH)
 #### Parameters
 * count: Items per page (default: 20)
 * page: page number
@@ -374,7 +265,7 @@ Friendica doesn't allow showing friends of other users.
 * contributor_details
 
 ---
-### statuses/home_timeline
+### statuses/home_timeline (*; AUTH)
 #### Parameters
 * count: Items per page (default: 20)
 * page: page number
@@ -390,7 +281,7 @@ Friendica doesn't allow showing friends of other users.
 * contributor_details
 
 ---
-### statuses/mentions
+### statuses/mentions (*; AUTH)
 #### Parameters
 * count: Items per page (default: 20)
 * page: page number
@@ -404,7 +295,7 @@ Friendica doesn't allow showing friends of other users.
 * contributor_details
 
 ---
-### statuses/public_timeline
+### statuses/public_timeline (*; AUTH)
 #### Parameters
 * count: Items per page (default: 20)
 * page: page number
@@ -418,7 +309,7 @@ Friendica doesn't allow showing friends of other users.
 * trim_user
 
 ---
-### statuses/replies
+### statuses/replies (*; AUTH)
 #### Parameters
 * count: Items per page (default: 20)
 * page: page number
@@ -432,7 +323,7 @@ Friendica doesn't allow showing friends of other users.
 * contributor_details
 
 ---
-### statuses/retweet
+### statuses/retweet (POST,PUT; AUTH)
 #### Parameters
 * id: message number
 * include_entities: "true" shows entities for pictures and links (Default: false)
@@ -441,7 +332,7 @@ Friendica doesn't allow showing friends of other users.
 * trim_user
 
 ---
-### statuses/show
+### statuses/show (*; AUTH)
 #### Parameters
 * id: message number
 * conversation: if set to "1" show all messages of the conversation with the given id
@@ -476,7 +367,7 @@ Friendica doesn't allow showing friends of other users.
 * display_coordinates
 
 ---
-### statuses/user_timeline
+### statuses/user_timeline (*; AUTH)
 #### Parameters
 * user_id: id of the user
 * screen_name: screen name (for technical reasons, this value is not unique!)
@@ -489,15 +380,16 @@ Friendica doesn't allow showing friends of other users.
 * include_entities: "true" shows entities for pictures and links (Default: false)
 
 #### Unsupported parameters
+
 * include_rts
 * trim_user
 * contributor_details
 
 ---
-### statusnet/config
+### statusnet/config (*)
 
 ---
-### statusnet/version
+### statusnet/version (*)
 
 #### Unsupported parameters
 * user_id
@@ -507,7 +399,7 @@ Friendica doesn't allow showing friends of other users.
 Friendica doesn't allow showing followers of other users.
 
 ---
-### users/search
+### users/search (*)
 #### Parameters
 * q: name of the user
 
@@ -517,7 +409,7 @@ Friendica doesn't allow showing followers of other users.
 * include_entities
 
 ---
-### users/show
+### users/show (*)
 #### Parameters
 * user_id: id of the user
 * screen_name: screen name (for technical reasons, this value is not unique!)
@@ -533,8 +425,39 @@ Friendica doesn't allow showing friends of other users.
 
 ## Implemented API calls (not compatible with other APIs)
 
+
 ---
-### friendica/group_show
+### friendica/activity/<verb>
+#### parameters
+* id: item id
+
+Add or remove an activity from an item.
+'verb' can be one of:
+
+- like
+- dislike
+- attendyes
+- attendno
+- attendmaybe
+
+To remove an activity, prepend the verb with "un", eg. "unlike" or "undislike"
+Attend verbs disable eachother: that means that if "attendyes" was added to an item, adding "attendno" remove previous "attendyes".
+Attend verbs should be used only with event-related items (there is no check at the moment)
+
+#### Return values
+
+On success:
+json
+```"ok"```
+
+xml
+```<ok>true</ok>```
+
+On error:
+HTTP 400 BadRequest
+
+---
+### friendica/group_show (*; AUTH)
 Return all or a specified group of the user with the containing contacts as array.
 
 #### Parameters
@@ -542,22 +465,23 @@ Return all or a specified group of the user with the containing contacts as arra
 
 #### Return values
 Array of:
+
 * name: name of the group
 * gid: id of the group
 * user: array of group members (return from api_get_user() function for each member)
 
 
 ---
-### friendica/group_delete
+### friendica/group_delete (POST,DELETE; AUTH)
 delete the specified group of contacts; API call need to include the correct gid AND name of the group to be deleted.
 
----
-### Parameters
+#### Parameters
 * gid: id of the group to be deleted
 * name: name of the group to be deleted
 
 #### Return values
 Array of:
+
 * success: true if successfully deleted
 * gid: gid of the deleted group
 * name: name of the deleted group
@@ -566,19 +490,22 @@ Array of:
 
 
 ---
-### friendica/group_create
+### friendica/group_create (POST,PUT; AUTH)
 Create the group with the posted array of contacts as members.
+
 #### Parameters
 * name: name of the group to be created
 
 #### POST data
-JSON data as Array like the result of „users/group_show“:
+JSON data as Array like the result of "users/group_show":
+
 * gid
 * name
 * array of users
 
 #### Return values
 Array of:
+
 * success: true if successfully created or reactivated
 * gid: gid of the created group
 * name: name of the created group
@@ -587,26 +514,175 @@ Array of:
 
 
 ---
-### friendica/group_update
+### friendica/group_update (POST)
 Update the group with the posted array of contacts as members (post all members of the group to the call; function will remove members not posted).
+
 #### Parameters
 * gid: id of the group to be changed
 * name: name of the group to be changed
 
 #### POST data
 JSON data as array like the result of „users/group_show“:
+
 * gid
 * name
 * array of users
 
 #### Return values
 Array of:
+
 * success: true if successfully updated
 * gid: gid of the changed group
 * name: name of the changed group
 * status: „missing user“ | „ok“
 * wrong users: array of users, which were not available in the contact table
 
+
+
+---
+### friendica/notifications (GET)
+Return last 50 notification for current user, ordered by date with unseen item on top
+
+#### Parameters
+none
+
+#### Return values
+Array of:
+
+* id: id of the note
+* type: type of notification as int (see NOTIFY_* constants in boot.php)
+* name: full name of the contact subject of the note
+* url: contact's profile url
+* photo: contact's profile photo
+* date: datetime string of the note
+* timestamp: timestamp of the node
+* date_rel: relative date of the note (eg. "1 hour ago")
+* msg: note message in bbcode
+* msg_html: note message in html
+* msg_plain: note message in plain text
+* link: link to note
+* seen: seen state: 0 or 1
+
+
+---
+### friendica/notifications/seen (POST)
+Set note as seen, returns item object if possible
+
+#### Parameters
+id: id of the note to set seen
+
+#### Return values
+If the note is linked to an item, the item is returned, just like one of the "statuses/*_timeline" api.
+
+If the note is not linked to an item, a success status is returned:
+
+* "success" (json) | "&lt;status&gt;success&lt;/status&gt;" (xml)
+
+
+---
+### friendica/photo (*; AUTH)
+#### Parameters
+* photo_id: Resource id of a photo.
+* scale: (optional) scale value of the photo
+
+Returns data of a picture with the given resource.
+If 'scale' isn't provided, returned data include full url to each scale of the photo.
+If 'scale' is set, returned data include image data base64 encoded.
+
+possibile scale value are:
+
+* 0: original or max size by server settings
+* 1: image with or height at <= 640
+* 2: image with or height at <= 320
+* 3: thumbnail 160x160
+* 4: Profile image at 175x175
+* 5: Profile image at 80x80
+* 6: Profile image at 48x48
+
+An image used as profile image has only scale 4-6, other images only 0-3
+
+#### Return values
+
+json
+```
+{
+"id": "photo id"
+"created": "date(YYYY-MM-GG HH:MM:SS)",
+"edited": "date(YYYY-MM-GG HH:MM:SS)",
+"title": "photo title",
+"desc": "photo description",
+"album": "album name",
+"filename": "original file name",
+"type": "mime type",
+"height": "number",
+"width": "number",
+"profile": "1 if is profile photo",
+"link": {
+"<scale>": "url to image"
+...
+},
+// if 'scale' is set
+"datasize": "size in byte",
+"data": "base64 encoded image data"
+}
+```
+
+xml
+```
+<photo>
+<id>photo id</id>
+<created>date(YYYY-MM-GG HH:MM:SS)</created>
+<edited>date(YYYY-MM-GG HH:MM:SS)</edited>
+<title>photo title</title>
+<desc>photo description</desc>
+<album>album name</album>
+<filename>original file name</filename>
+<type>mime type</type>
+<height>number</height>
+<width>number</width>
+<profile>1 if is profile photo</profile>
+<links type="array">
+<link type="mime type" scale="scale number" href="image url"/>
+...
+</links>
+</photo>
+```
+
+---
+### friendica/photos/list (*; AUTH)
+
+Returns a list of all photo resources of the logged in user.
+
+#### Return values
+
+json
+```
+[
+{
+id: "resource_id",
+album: "album name",
+filename: "original file name",
+type: "image mime type",
+thumb: "url to thumb sized image"
+},
+...
+]
+```
+
+xml
+```
+<photos type="array">
+<photo id="resource_id"
+album="album name"
+filename="original file name"
+type="image mime type">
+"url to thumb sized image"
+</photo>
+...
+</photos>
+```
+
+
 ---
 ## Not Implemented API calls
 The following API calls are implemented in GNU Social but not in Friendica: (incomplete)
@@ -702,13 +778,13 @@ The following API calls from the Twitter API aren't implemented neither in Frien
 ### BASH / cURL
 Betamax has documentated some example API usage from a [bash script](https://en.wikipedia.org/wiki/Bash_(Unix_shell) employing [curl](https://en.wikipedia.org/wiki/CURL) (see [his posting](https://betamax65.de/display/betamax65/43539)).
 
-    /usr/bin/curl -u USER:PASS https://YOUR.FRIENDICA.TLD/api/statuses/update.xml -d source="some source id" -d status="the status you want to post"
+/usr/bin/curl -u USER:PASS https://YOUR.FRIENDICA.TLD/api/statuses/update.xml -d source="some source id" -d status="the status you want to post"
 
 ### Python
 The [RSStoFriedika](https://github.com/pafcu/RSStoFriendika) code can be used as an example of how to use the API with python. The lines for posting are located at [line 21](https://github.com/pafcu/RSStoFriendika/blob/master/RSStoFriendika.py#L21) and following.
 
-    def tweet(server, message, group_allow=None):
-        url = server + '/api/statuses/update'
-        urllib2.urlopen(url, urllib.urlencode({'status': message,'group_allow[]':group_allow}, doseq=True))
+def tweet(server, message, group_allow=None):
+url = server + '/api/statuses/update'
+urllib2.urlopen(url, urllib.urlencode({'status': message,'group_allow[]':group_allow}, doseq=True))
 
 There is also a [module for python 3](https://bitbucket.org/tobiasd/python-friendica) for using the API.

From a283691149fa9224be8b7ba8edc4dcdef88c3612 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Mon, 8 Feb 2016 10:34:27 +0100
Subject: [PATCH 062/273] api docs: fix indentation

---
 doc/api.md | 132 ++++++++++++++++++++++++++---------------------------
 1 file changed, 66 insertions(+), 66 deletions(-)

diff --git a/doc/api.md b/doc/api.md
index f050ae4304..c020f403ff 100644
--- a/doc/api.md
+++ b/doc/api.md
@@ -52,20 +52,20 @@ Error body is
 
 json:
 ```
-{
-"error": "Specific error message",
-"request": "API path requested",
-"code": "HTTP error code"
-}
+	{
+		"error": "Specific error message",
+		"request": "API path requested",
+		"code": "HTTP error code"
+	}
 ```
 
 xml:
 ```
-<status>
-<error>Specific error message</error>
-<request>API path requested</request>
-<code>HTTP error code</code>
-</status>
+	<status>
+		<error>Specific error message</error>
+		<request>API path requested</request>
+		<code>HTTP error code</code>
+	</status>
 ```
 
 ---
@@ -605,47 +605,47 @@ An image used as profile image has only scale 4-6, other images only 0-3
 
 json
 ```
-{
-"id": "photo id"
-"created": "date(YYYY-MM-GG HH:MM:SS)",
-"edited": "date(YYYY-MM-GG HH:MM:SS)",
-"title": "photo title",
-"desc": "photo description",
-"album": "album name",
-"filename": "original file name",
-"type": "mime type",
-"height": "number",
-"width": "number",
-"profile": "1 if is profile photo",
-"link": {
-"<scale>": "url to image"
-...
-},
-// if 'scale' is set
-"datasize": "size in byte",
-"data": "base64 encoded image data"
-}
+	{
+		"id": "photo id"
+		"created": "date(YYYY-MM-GG HH:MM:SS)",
+		"edited": "date(YYYY-MM-GG HH:MM:SS)",
+		"title": "photo title",
+		"desc": "photo description",
+		"album": "album name",
+		"filename": "original file name",
+		"type": "mime type",
+		"height": "number",
+		"width": "number",
+		"profile": "1 if is profile photo",
+		"link": {
+			"<scale>": "url to image"
+			...
+		},
+		// if 'scale' is set
+		"datasize": "size in byte",
+		"data": "base64 encoded image data"
+	}
 ```
 
 xml
 ```
-<photo>
-<id>photo id</id>
-<created>date(YYYY-MM-GG HH:MM:SS)</created>
-<edited>date(YYYY-MM-GG HH:MM:SS)</edited>
-<title>photo title</title>
-<desc>photo description</desc>
-<album>album name</album>
-<filename>original file name</filename>
-<type>mime type</type>
-<height>number</height>
-<width>number</width>
-<profile>1 if is profile photo</profile>
-<links type="array">
-<link type="mime type" scale="scale number" href="image url"/>
-...
-</links>
-</photo>
+	<photo>
+		<id>photo id</id>
+		<created>date(YYYY-MM-GG HH:MM:SS)</created>
+		<edited>date(YYYY-MM-GG HH:MM:SS)</edited>
+		<title>photo title</title>
+		<desc>photo description</desc>
+		<album>album name</album>
+		<filename>original file name</filename>
+		<type>mime type</type>
+		<height>number</height>
+		<width>number</width>
+		<profile>1 if is profile photo</profile>
+		<links type="array">
+		<link type="mime type" scale="scale number" href="image url"/>
+			...
+		</links>
+	</photo>
 ```
 
 ---
@@ -657,29 +657,29 @@ Returns a list of all photo resources of the logged in user.
 
 json
 ```
-[
-{
-id: "resource_id",
-album: "album name",
-filename: "original file name",
-type: "image mime type",
-thumb: "url to thumb sized image"
-},
-...
-]
+	[
+		{
+			id: "resource_id",
+			album: "album name",
+			filename: "original file name",
+			type: "image mime type",
+			thumb: "url to thumb sized image"
+		},
+		...
+	]
 ```
 
 xml
 ```
-<photos type="array">
-<photo id="resource_id"
-album="album name"
-filename="original file name"
-type="image mime type">
-"url to thumb sized image"
-</photo>
-...
-</photos>
+	<photos type="array">
+		<photo id="resource_id"
+		album="album name"
+		filename="original file name"
+		type="image mime type">
+			"url to thumb sized image"
+		</photo>
+		...
+	</photos>
 ```
 
 

From 9ff0fc92dd1525450ea99347895fbbe5e367d56b Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Mon, 8 Feb 2016 13:42:06 +0100
Subject: [PATCH 063/273] NotificationsManager: add backtick to queries

---
 include/NotificationsManager.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/NotificationsManager.php b/include/NotificationsManager.php
index b7e31d4f65..c99d00742c 100644
--- a/include/NotificationsManager.php
+++ b/include/NotificationsManager.php
@@ -79,7 +79,7 @@ class NotificationsManager {
         
         if ($limit!="") $limit = " LIMIT ".$limit;
         
-		$r = q("SELECT * FROM notify WHERE uid = %d $filter_sql ORDER BY $order_sql $limit",
+		$r = q("SELECT * FROM `notify` WHERE `uid` = %d $filter_sql ORDER BY $order_sql $limit",
 			intval(local_user())
 		);
         if ($r!==false && count($r)>0) return $this->_set_extra($r);
@@ -93,7 +93,7 @@ class NotificationsManager {
      * @return array note values or null if not found
      */
     public function getByID($id) {
-        $r = q("SELECT * FROM notify WHERE id = %d AND uid = %d LIMIT 1",
+        $r = q("SELECT * FROM `notify` WHERE `id` = %d AND `uid` = %d LIMIT 1",
                 intval($id),
                 intval(local_user())
         );
@@ -111,7 +111,7 @@ class NotificationsManager {
      * @return bool true on success, false on errors
      */
     public function setSeen($note, $seen = true) {
-        return q("UPDATE notify SET seen = %d WHERE ( link = '%s' OR ( parent != 0 AND parent = %d AND otype = '%s' )) AND uid = %d",
+        return q("UPDATE `notify` SET `seen` = %d WHERE ( `link` = '%s' OR ( `parent` != 0 AND `parent` = %d AND `otype` = '%s' )) AND `uid` = %d",
             intval($seen),
             dbesc($note['link']),
             intval($note['parent']),
@@ -127,7 +127,7 @@ class NotificationsManager {
      * @return bool true on success, false on error
      */
     public function setAllSeen($seen = true) {
-    	return q("UPDATE notify SET seen = %d WHERE uid = %d",
+    	return q("UPDATE `notify` SET `seen` = %d WHERE `uid` = %d",
             intval($seen),
 			intval(local_user())
 		);

From 2a016e7685e76b29641dce09172058f716f4ee4b Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Mon, 8 Feb 2016 14:35:41 +0100
Subject: [PATCH 064/273] add missing query backticks

---
 include/api.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/api.php b/include/api.php
index 16481201e3..d205451e5e 100644
--- a/include/api.php
+++ b/include/api.php
@@ -3457,7 +3457,7 @@
 		$nm->setSeen($note);
 		if ($note['otype']=='item') {
 			// would be really better with an ItemsManager and $im->getByID() :-P
-			$r = q("SELECT * FROM item WHERE id=%d AND uid=%d",
+			$r = q("SELECT * FROM `item` WHERE `id`=%d AND `uid`=%d",
 				intval($note['iid']),
 				intval(local_user())
 			);

From cc18fd7ad90ed34c2dda33492d3e9b6c0cbd44a3 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Mon, 8 Feb 2016 15:00:53 +0100
Subject: [PATCH 065/273] contactedit-actions-button: doing some availability
 checks for the actions

---
 mod/contacts.php | 119 ++++++++++++++++++++++++++---------------------
 1 file changed, 66 insertions(+), 53 deletions(-)

diff --git a/mod/contacts.php b/mod/contacts.php
index 248ed47ab3..53fb96c5b1 100644
--- a/mod/contacts.php
+++ b/mod/contacts.php
@@ -565,7 +565,7 @@ function contacts_content(&$a) {
 			($contact['rel'] == CONTACT_IS_FOLLOWER))
 			$follow = $a->get_baseurl(true)."/follow?url=".urlencode($contact["url"]);
 
-		$contact_actions = contact_action_menu($contact);
+		$contact_actions = contact_actions($contact);
 
 
 		$o .= replace_macros($tpl, array(
@@ -959,65 +959,78 @@ function _contact_detail_for_template($rr){
 
 }
 
-function contact_action_menu($contact) {
+/**
+ * @brief Gives a array with actions which can performed to a given contact
+ * 
+ * This includes actions like e.g. 'block', 'hide', 'archive', 'delete' and others
+ * 
+ * @param array $contact Data about the Contact
+ * @return array with actions related actions
+ */
+function contact_actions($contact) {
 
-	$contact_action_menu = array(
-				'suggest' => array(
-					'label' => t('Suggest friends'),
-					'url'	=> app::get_baseurl(true) . '/fsuggest/' . $contact['id'],
-					'title'	=> '',
-					'sel'	=> '',
-					'id'	=>  'suggest',
-				),
+	$poll_enabled = in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2));
+	$contact_action_menu = array();
 
-				'update' => array(
-					'label'	=> t('Update now'),
-					'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/update',
-					'title'	=> '',
-					'sel'	=> '',
-					'id'	=> 'update',
-				),
+	if($contact['network'] === NETWORK_DFRN) {
+		$contact_actions['suggest'] = array(
+							'label' => t('Suggest friends'),
+							'url'	=> app::get_baseurl(true) . '/fsuggest/' . $contact['id'],
+							'title'	=> '',
+							'sel'	=> '',
+							'id'	=>  'suggest',
+					);
+	}
 
-				'repair' => array(
-					'label'	=> t('Repair'),
-					'url'	=> app::get_baseurl(true) . '/crepair/' . $contact['id'],
-					'title' => t('Advanced Contact Settings'),
-					'sel'	=> '',
-					'id'	=> 'repair',
-				),
+	if($poll_enabled) {
+		$contact_actions['update'] = array(
+							'label'	=> t('Update now'),
+							'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/update',
+							'title'	=> '',
+							'sel'	=> '',
+							'id'	=> 'update',
+					);
+	}
 
-				'block' => array(
-					'label'	=> (intval($contact['blocked']) ? t('Unblock') : t('Block') ),
-					'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/block',
-					'title' => t('Toggle Blocked status'),
-					'sel'	=> (intval($contact['blocked']) ? 'active' : ''),
-					'id'	=> 'toggle-block',
-				),
+	$contact_actions['repair'] = array(
+						'label'	=> t('Repair'),
+						'url'	=> app::get_baseurl(true) . '/crepair/' . $contact['id'],
+						'title' => t('Advanced Contact Settings'),
+						'sel'	=> '',
+						'id'	=> 'repair',
+				);
 
-				'ignore' => array(
-					'label'	=> (intval($contact['readonly']) ? t('Unignore') : t('Ignore') ),
-					'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/ignore',
-					'title' => t('Toggle Ignored status'),
-					'sel'	=> (intval($contact['readonly']) ? 'active' : ''),
-					'id'	=> 'toggle-ignore',
-				),
+	$contact_actions['block'] = array(
+						'label'	=> (intval($contact['blocked']) ? t('Unblock') : t('Block') ),
+						'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/block',
+						'title' => t('Toggle Blocked status'),
+						'sel'	=> (intval($contact['blocked']) ? 'active' : ''),
+						'id'	=> 'toggle-block',
+				);
 
-				'archive' => array(
-					'label'	=> (intval($contact['archive']) ? t('Unarchive') : t('Archive') ),
-					'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/archive',
-					'title' => t('Toggle Archive status'),
-					'sel'	=> (intval($contact['archive']) ? 'active' : ''),
-					'id'	=> 'toggle-archive',
-				),
+	$contact_actions['ignore'] = array(
+						'label'	=> (intval($contact['readonly']) ? t('Unignore') : t('Ignore') ),
+						'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/ignore',
+						'title' => t('Toggle Ignored status'),
+						'sel'	=> (intval($contact['readonly']) ? 'active' : ''),
+						'id'	=> 'toggle-ignore',
+				);
 
-				'delete' => array(
-					'label'	=> t('Delete'),
-					'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/drop', 
-					'title'	=> t('Delete contact'),
-					'sel'	=> '',
-					'id'	=> 'delete',
-				)
-	);
+	$contact_actions['archive'] = array(
+						'label'	=> (intval($contact['archive']) ? t('Unarchive') : t('Archive') ),
+						'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/archive',
+						'title' => t('Toggle Archive status'),
+						'sel'	=> (intval($contact['archive']) ? 'active' : ''),
+						'id'	=> 'toggle-archive',
+				);
+
+	$contact_actions['delete'] = array(
+						'label'	=> t('Delete'),
+						'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/drop', 
+						'title'	=> t('Delete contact'),
+						'sel'	=> '',
+						'id'	=> 'delete',
+				);
 
 	return $contact_action_menu;
 }

From b3f7e8d38808080a181f24720951842c0c76485e Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 8 Feb 2016 15:26:24 +0100
Subject: [PATCH 066/273] Now the public static functions are public static
 functions

---
 include/dfrn.php | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index 84660a0d18..c6c8deef58 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -40,7 +40,7 @@ class dfrn {
 	 *
 	 * @return string DFRN entries
 	 */
-	function entries($items,$owner) {
+	public static function entries($items,$owner) {
 
 		$doc = new DOMDocument('1.0', 'utf-8');
 		$doc->formatOutput = true;
@@ -70,7 +70,7 @@ class dfrn {
 	 *
 	 * @return string DFRN feed entries
 	 */
-	function feed($dfrn_id, $owner_nick, $last_update, $direction = 0) {
+	public static function feed($dfrn_id, $owner_nick, $last_update, $direction = 0) {
 
 		$a = get_app();
 
@@ -277,7 +277,7 @@ class dfrn {
 	 *
 	 * @return string DFRN mail
 	 */
-	function mail($item, $owner) {
+	public static function mail($item, $owner) {
 		$doc = new DOMDocument('1.0', 'utf-8');
 		$doc->formatOutput = true;
 
@@ -311,7 +311,7 @@ class dfrn {
 	 *
 	 * @return string DFRN suggestions
 	 */
-	function fsuggest($item, $owner) {
+	public static function fsuggest($item, $owner) {
 		$doc = new DOMDocument('1.0', 'utf-8');
 		$doc->formatOutput = true;
 
@@ -338,7 +338,7 @@ class dfrn {
 	 *
 	 * @return string DFRN relocations
 	 */
-	function relocate($owner, $uid) {
+	public static function relocate($owner, $uid) {
 
 		/* get site pubkey. this could be a new installation with no site keys*/
 		$pubkey = get_config('system','site_pubkey');
@@ -846,7 +846,7 @@ class dfrn {
 	 *
 	 * @return int Deliver status. -1 means an error.
 	 */
-	function deliver($owner,$contact,$atom, $dissolve = false) {
+	public static function deliver($owner,$contact,$atom, $dissolve = false) {
 
 		$a = get_app();
 
@@ -2319,7 +2319,7 @@ class dfrn {
 	 * @param array $importer Record of the importer user mixed with contact of the content
 	 * @param bool $sort_by_date Is used when feeds are polled
 	 */
-	function import($xml,$importer, $sort_by_date = false) {
+	public static function import($xml,$importer, $sort_by_date = false) {
 
 		if ($xml == "")
 			return;

From 981aad46d3fd926ff118bc63e7eb66451cac766f Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 8 Feb 2016 22:37:29 +0100
Subject: [PATCH 067/273] DFRN: Sending pokes does work now again

---
 include/dfrn.php | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index c6c8deef58..c4999a08e1 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -634,13 +634,20 @@ class dfrn {
 
 					$r->link = preg_replace('/\<link(.*?)\"\>/','<link$1"/>',$r->link);
 
-					$data = parse_xml_string($r->link, false);
-					foreach ($data->attributes() AS $parameter => $value)
-						$attributes[$parameter] = $value;
-				} else
+					// XML does need a single element as root element so we add a dummy element here
+					$data = parse_xml_string("<dummy>".$r->link."</dummy>", false);
+					if (is_object($data)) {
+						foreach ($data->link AS $link) {
+							$attributes = array();
+							foreach ($link->attributes() AS $parameter => $value)
+								$attributes[$parameter] = $value;
+							xml_add_element($doc, $entry, "link", "", $attributes);
+						}
+					}
+				} else {
 					$attributes = array("rel" => "alternate", "type" => "text/html", "href" => $r->link);
-
-				xml_add_element($doc, $entry, "link", "", $attributes);
+					xml_add_element($doc, $entry, "link", "", $attributes);
+				}
 			}
 			if($r->content)
 				xml_add_element($doc, $entry, "content", bbcode($r->content), array("type" => "html"));
@@ -1311,9 +1318,10 @@ class dfrn {
 		if (is_object($title))
 			$obj_element->appendChild($obj_doc->importNode($title, true));
 
-		$link = $xpath->query("atom:link", $activity)->item(0);
-		if (is_object($link))
-			$obj_element->appendChild($obj_doc->importNode($link, true));
+		$links = $xpath->query("atom:link", $activity);
+		if (is_object($links))
+			foreach ($links AS $link)
+				$obj_element->appendChild($obj_doc->importNode($link, true));
 
 		$content = $xpath->query("atom:content", $activity)->item(0);
 		if (is_object($content))

From 0b5d7b300e90324d0931837550cac5a9ed348f97 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Mon, 8 Feb 2016 23:15:20 +0100
Subject: [PATCH 068/273] contactedit-actions-button: adjust the themes and
 template polishing

---
 mod/contacts.php                              |   9 +-
 view/global.css                               |  30 +++-
 view/templates/contact_edit.tpl               | 167 ++++++++----------
 view/theme/duepuntozero/style.css             |  43 +++--
 view/theme/frost-mobile/js/main.js            |   1 -
 view/theme/frost-mobile/style.css             |  58 +++++-
 .../frost-mobile/templates/contact_edit.tpl   |  83 +++++----
 view/theme/frost/style.css                    |  64 ++++++-
 view/theme/frost/templates/contact_edit.tpl   |  84 +++++----
 view/theme/quattro/dark/style.css             |   5 +-
 view/theme/quattro/green/style.css            |   5 +-
 view/theme/quattro/lilac/style.css            |  11 +-
 view/theme/quattro/quattro.less               |  29 +--
 view/theme/smoothly/style.css                 |  48 +++--
 view/theme/vier/style.css                     | 132 +++++++++-----
 view/theme/vier/templates/contact_edit.tpl    |  99 +++++++++++
 16 files changed, 584 insertions(+), 284 deletions(-)
 create mode 100644 view/theme/vier/templates/contact_edit.tpl

diff --git a/mod/contacts.php b/mod/contacts.php
index 53fb96c5b1..77176f6ca6 100644
--- a/mod/contacts.php
+++ b/mod/contacts.php
@@ -565,6 +565,7 @@ function contacts_content(&$a) {
 			($contact['rel'] == CONTACT_IS_FOLLOWER))
 			$follow = $a->get_baseurl(true)."/follow?url=".urlencode($contact["url"]);
 
+		// Load contactact related actions like hide, suggest, delete and others
 		$contact_actions = contact_actions($contact);
 
 
@@ -586,7 +587,7 @@ function contacts_content(&$a) {
 			'$lblcrepair' => t("Repair URL settings"),
 			'$lblrecent' => t('View conversations'),
 			'$lblsuggest' => $lblsuggest,
-			'$delete' => t('Delete contact'),
+			//'$delete' => t('Delete contact'),
 			'$nettype' => $nettype,
 			'$poll_interval' => $poll_interval,
 			'$poll_enabled' => $poll_enabled,
@@ -627,6 +628,8 @@ function contacts_content(&$a) {
 			'$keywords_label' => t("Tags:"),
 			'$contact_action_button' => t("Actions"),
 			'$contact_actions' => $contact_actions,
+			'$contact_status' => t("Status"),
+			'$contact_settings_label' => t('Contact Settings'),
 
 		));
 
@@ -970,7 +973,7 @@ function _contact_detail_for_template($rr){
 function contact_actions($contact) {
 
 	$poll_enabled = in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2));
-	$contact_action_menu = array();
+	$contact_action = array();
 
 	if($contact['network'] === NETWORK_DFRN) {
 		$contact_actions['suggest'] = array(
@@ -1032,5 +1035,5 @@ function contact_actions($contact) {
 						'id'	=> 'delete',
 				);
 
-	return $contact_action_menu;
+	return $contact_actions;
 }
diff --git a/view/global.css b/view/global.css
index df001ed362..41af643ecc 100644
--- a/view/global.css
+++ b/view/global.css
@@ -15,12 +15,16 @@
   padding: 5px 10px;
   text-align: center;
 }
+a.btn, a.btn:hover {
+  text-decoration: none;
+  color: inherit;
+}
 
-ul.menu-popup li.divider {
+.menu-popup .divider {
   height: 1px;
   margin: 3px 0;
   overflow: hidden;
-  background-color: #2d2d2d;;
+  background-color: #2d2d2d;
 }
 
 /* List of social Networks */
@@ -375,6 +379,24 @@ td.federation-data {
 }
 
 /* contact-edit */
+#contact-edit-status-wrapper {
+  border: 1px solid;
+  padding: 10px;
+}
 #contact-edit-actions {
-    float: right;
-}
\ No newline at end of file
+  float: right;
+  display: inline-block;
+  position: relative;
+}
+#contact-edit-actions > .menu-popup {
+  right: 0;
+  left: auto;
+}
+
+#contact-edit-settings-label:after {
+  content: ' »';
+}
+
+#contact-edit-settings {
+  display: none;
+}
diff --git a/view/templates/contact_edit.tpl b/view/templates/contact_edit.tpl
index 682ebfa36a..91ef451278 100644
--- a/view/templates/contact_edit.tpl
+++ b/view/templates/contact_edit.tpl
@@ -1,110 +1,99 @@
+
 {{if $header}}<h2>{{$header}}</h2>{{/if}}
 
 <div id="contact-edit-wrapper" >
 
+	{{* Insert Tab-Nav *}}
 	{{$tab_str}}
 
-	<div id="contact-edit-actions">
-		<a class="btn" rel="#contact-actions-menu" href="#" id="contact-edit-actions-button">{{$contact_action_button}}</a>
-
-		<ul role="menu" aria-haspopup="true" id="contact-actions-menu" class="menu-popup" >
-			{{if $lblsuggest}}<li><a  href="#" title="{{$contact_actions.suggest.title}}" onclick="window.location.href='{{$contact_actions.suggest.url}}'; return false;">{{$contact_actions.suggest.label}}</a></li>{{/if}}
-			{{if $poll_enabled}}<li><a  href="#" title="{{$contact_actions.update.title}}" onclick="window.location.href='{{$contact_actions.update.url}}'; return false;">{{$contact_actions.update.label}}</a></li>{{/if}}
-			<li><a  href="#" title="{{$contact_actions.repair.title}}" onclick="window.location.href='{{$contact_actions.repair.url}}'; return false;">{{$contact_actions.repair.label}}</a></li>
-			<li class="divider"></li>
-			<li><a  href="#" title="{{$contact_actions.block.title}}" onclick="window.location.href='{{$contact_actions.block.url}}'; return false;">{{$contact_actions.block.label}}</a></li>
-			<li><a  href="#" title="{{$contact_actions.ignore.title}}" onclick="window.location.href='{{$contact_actions.ignore.url}}'; return false;">{{$contact_actions.ignore.label}}</a></li>
-			<li><a  href="#" title="{{$contact_actions.archive.title}}" onclick="window.location.href='{{$contact_actions.archive.url}}'; return false;">{{$contact_actions.archive.label}}</a></li>
-			<li><a  href="#" title="{{$contact_actions.delete.title}}" onclick="return confirmDelete();">{{$contact_actions.delete.label}}</a></li>
-		</ul>
-	</div>
-
-	<div id="contact-edit-drop-link" >
-		<a href="contacts/{{$contact_id}}/drop" class="icon drophide" id="contact-edit-drop-link" onclick="return confirmDelete();"  title="{{$delete}}" onmouseover="imgbright(this);" onmouseout="imgdull(this);"></a>
-	</div>
-
-	<div id="contact-edit-drop-link-end"></div>
-
 
 	<div id="contact-edit-nav-wrapper" >
 		<div id="contact-edit-links">
-			<ul>
-				{{if $relation_text}}
-					<li><div id="contact-edit-rel">{{$relation_text}}</div></li>
-				{{/if}}
-				{{if $lost_contact}}
-					<li><div id="lost-contact-message">{{$lost_contact}}</div></li>
-				{{/if}}
-				{{if $insecure}}
-					<li><div id="insecure-message">{{$insecure}}</div></li>
-				{{/if}}
-				{{if $blocked}}
-					<li><div id="block-message">{{$blocked}}</div></li>
-				{{/if}}
-				{{if $ignored}}
-					<li><div id="ignore-message">{{$ignored}}</div></li>
-				{{/if}}
-				{{if $archived}}
-					<li><div id="archive-message">{{$archived}}</div></li>
-				{{/if}}
-			</ul>
+			<div id="contact-edit-status-wrapper">
+				<span id="contact-edit-contact-status">{{$contact_status}}</span>
 
-			<ul>
-				<!-- <li><a href="network/0?nets=all&cid={{$contact_id}}" id="contact-edit-view-recent">{{$lblrecent}}</a></li> -->
-				{{if $lblsuggest}}
-					<li><a href="fsuggest/{{$contact_id}}" id="contact-edit-suggest">{{$lblsuggest}}</a></li>
-				{{/if}}
-				{{if $follow}}
-					<li><div id="contact-edit-follow"><a href="{{$follow}}">{{$follow_text}}</a></div></li>
-				{{/if}}
+				{{* This is the Action menu where contact related actions like 'ignore', 'hide' can be performed *}}
+				<div id="contact-edit-actions">
+					<a class="btn" rel="#contact-actions-menu" href="#" id="contact-edit-actions-button">{{$contact_action_button}}</a>
 
-			</ul>
+					<ul role="menu" aria-haspopup="true" id="contact-actions-menu" class="menu-popup" >
+						{{if $lblsuggest}}<li role="menuitem"><a  href="#" title="{{$contact_actions.suggest.title}}" onclick="window.location.href='{{$contact_actions.suggest.url}}'; return false;">{{$contact_actions.suggest.label}}</a></li>{{/if}}
+						{{if $poll_enabled}}<li role="menuitem"><a  href="#" title="{{$contact_actions.update.title}}" onclick="window.location.href='{{$contact_actions.update.url}}'; return false;">{{$contact_actions.update.label}}</a></li>{{/if}}
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.repair.title}}" onclick="window.location.href='{{$contact_actions.repair.url}}'; return false;">{{$contact_actions.repair.label}}</a></li>
+						<li class="divider"></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.block.title}}" onclick="window.location.href='{{$contact_actions.block.url}}'; return false;">{{$contact_actions.block.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.ignore.title}}" onclick="window.location.href='{{$contact_actions.ignore.url}}'; return false;">{{$contact_actions.ignore.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.archive.title}}" onclick="window.location.href='{{$contact_actions.archive.url}}'; return false;">{{$contact_actions.archive.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.delete.title}}" onclick="return confirmDelete();">{{$contact_actions.delete.label}}</a></li>
+					</ul>
+				</div>
 
+				{{* Block with status information about the contact *}}
+				<ul>
+					{{if $relation_text}}<li><div id="contact-edit-rel">{{$relation_text}}</div></li>{{/if}}
+
+					{{if $poll_enabled}}
+						<li><div id="contact-edit-last-update-text">{{$lastupdtext}} <span id="contact-edit-last-updated">{{$last_update}}</span></div>
+						{{if $poll_interval}}
+							<span id="contact-edit-poll-text">{{$updpub}}</span> {{$poll_interval}}
+						{{/if}}
+						</li>
+					{{/if}}
+
+					{{if $lost_contact}}<li><div id="lost-contact-message">{{$lost_contact}}</div></li>{{/if}}
+					{{if $insecure}}<li><div id="insecure-message">{{$insecure}}</div></li>	{{/if}}
+					{{if $blocked}}<li><div id="block-message">{{$blocked}}</div></li>{{/if}}
+					{{if $ignored}}<li><div id="ignore-message">{{$ignored}}</div></li>{{/if}}
+					{{if $archived}}<li><div id="archive-message">{{$archived}}</div></li>{{/if}}
+				</ul>
+
+				<ul>
+					<!-- <li><a href="network/0?nets=all&cid={{$contact_id}}" id="contact-edit-view-recent">{{$lblrecent}}</a></li> -->
+					{{if $follow}}<li><div id="contact-edit-follow"><a href="{{$follow}}">{{$follow_text}}</a></div></li>{{/if}}
+				</ul>
+			</div> {{* End of contact-edit-status-wrapper *}}
+
+			{{* Some information about the contact from the profile *}}
 			<dl><dt>{{$profileurllabel}}</dt><dd><a target="blank" href="{{$url}}">{{$profileurl}}</a></dd></dl>
 			{{if $location}}<dl><dt>{{$location_label}}</dt><dd>{{$location}}</dd></dl>{{/if}}
 			{{if $keywords}}<dl><dt>{{$keywords_label}}</dt><dd>{{$keywords}}</dd></dl>{{/if}}
 			{{if $about}}<dl><dt>{{$about_label}}</dt><dd>{{$about}}</dd></dl>{{/if}}
-		</div>
-	</div>
-	<div id="contact-edit-nav-end"></div>
+		</div>{{* End of contact-edit-links *}}
 
-<hr />
+		<div id="contact-edit-links-end"></div>
 
-<form action="contacts/{{$contact_id}}" method="post" >
-<input type="hidden" name="contact_id" value="{{$contact_id}}">
+		<hr />
 
-	<div id="contact-edit-poll-wrapper">
-		{{if $poll_enabled}}
-			<div id="contact-edit-last-update-text">{{$lastupdtext}} <span id="contact-edit-last-updated">{{$last_update}}</span></div>
-			{{if $poll_interval}}
-				<span id="contact-edit-poll-text">{{$updpub}}</span> {{$poll_interval}}
+		<h4 id="contact-edit-settings-label" class="fakelink" onclick="openClose('contact-edit-settings')">{{$contact_settings_label}}</h4>
+		<div id="contact-edit-settings">
+			<form action="contacts/{{$contact_id}}" method="post" >
+			<input type="hidden" name="contact_id" value="{{$contact_id}}">
+
+				<div id="contact-edit-end" ></div>
+				{{include file="field_checkbox.tpl" field=$notify}}
+				{{if $fetch_further_information}}
+					{{include file="field_select.tpl" field=$fetch_further_information}}
+					{{if $fetch_further_information.2 == 2 }} {{include file="field_textarea.tpl" field=$ffi_keyword_blacklist}} {{/if}}
+				{{/if}}
+				{{include file="field_checkbox.tpl" field=$hidden}}
+
+			<div id="contact-edit-info-wrapper">
+				<h4>{{$lbl_info1}}</h4>
+				<textarea id="contact-edit-info" rows="8" cols="60" name="info">{{$info}}</textarea>
+				<input class="contact-edit-submit" type="submit" name="submit" value="{{$submit|escape:'html'}}" />
+			</div>
+			<div id="contact-edit-info-end"></div>
+
+			{{if $profile_select}}
+				<div id="contact-edit-profile-select-text">
+				<h4>{{$lbl_vis1}}</h4>
+				<p>{{$lbl_vis2}}</p> 
+				</div>
+				{{$profile_select}}
+				<div id="contact-edit-profile-select-end"></div>
+				<input class="contact-edit-submit" type="submit" name="submit" value="{{$submit|escape:'html'}}" />
 			{{/if}}
-			<span id="contact-edit-update-now" class="button"><a href="contacts/{{$contact_id}}/update" >{{$udnow}}</a></span>
-		{{/if}}
-	</div>
-	<div id="contact-edit-end" ></div>
-	{{include file="field_checkbox.tpl" field=$notify}}
-	{{if $fetch_further_information}}
-		{{include file="field_select.tpl" field=$fetch_further_information}}
-		{{if $fetch_further_information.2 == 2 }} {{include file="field_textarea.tpl" field=$ffi_keyword_blacklist}} {{/if}}
-	{{/if}}
-	{{include file="field_checkbox.tpl" field=$hidden}}
-
-<div id="contact-edit-info-wrapper">
-<h4>{{$lbl_info1}}</h4>
-	<textarea id="contact-edit-info" rows="8" cols="60" name="info">{{$info}}</textarea>
-	<input class="contact-edit-submit" type="submit" name="submit" value="{{$submit|escape:'html'}}" />
-</div>
-<div id="contact-edit-info-end"></div>
-
-{{if $profile_select}}
-	<div id="contact-edit-profile-select-text">
-	<h4>{{$lbl_vis1}}</h4>
-	<p>{{$lbl_vis2}}</p> 
-	</div>
-	{{$profile_select}}
-	<div id="contact-edit-profile-select-end"></div>
-	<input class="contact-edit-submit" type="submit" name="submit" value="{{$submit|escape:'html'}}" />
-{{/if}}
-</form>
+			</form>
+		</div>
+	</div>{{* End of contact-edit-nav-wrapper *}}
 </div>
diff --git a/view/theme/duepuntozero/style.css b/view/theme/duepuntozero/style.css
index c004eb53d0..787e52600c 100644
--- a/view/theme/duepuntozero/style.css
+++ b/view/theme/duepuntozero/style.css
@@ -83,6 +83,26 @@ blockquote {
 	margin-right: 5px;
 }
 
+ul.menu-popup {
+	position: absolute;
+	display: none;
+	width: auto;
+	margin: 2px 0 0;
+	padding: 0px;
+	list-style: none;
+	z-index: 100000;
+	border: 2px solid #444444;
+	background: #FFFFFF;
+}
+.menu-popup li a {
+	padding: 2px;
+	white-space: nowrap;
+}
+
+a.btn, a.btn:hover {
+	text-decoration: none;
+	color: inherit;
+}
 
 
 /* nav */
@@ -140,12 +160,12 @@ nav #banner #logo-text a:hover { text-decoration: none; }
 
 
 .nav-commlink, .nav-login-link {
-    display: block;
-    height: 15px;
+	display: block;
+	height: 15px;
 	margin-top: 67px;
 	margin-right: 2px;
-	//padding: 6px 10px;
-       padding: 6px 3px;
+	/*padding: 6px 10px;*/
+	padding: 6px 3px;
 	float: left;
 	bottom: 140px;
 	border: 1px solid #babdb6;
@@ -244,7 +264,7 @@ section {
 	display:block;
 	float:left;
 	padding: 0.4em;
-	//margin-right: 1em;
+	/*margin-right: 1em;*/
 	margin-right: 3px ;
 }
 .tab.active {
@@ -3371,17 +3391,6 @@ div.jGrowl div.info {
 .nav-notify.show {
 	display: block;
 }
-ul.menu-popup {
-	position: absolute;
-	display: none;
-	width: 10em;
-	margin: 0px;
-	padding: 0px;
-	list-style: none;
-	z-index: 100000;
-	top: 90px;
-	left: 200px;
-}
 #nav-notifications-menu {
 	width: 320px;
 	max-height: 400px;
@@ -3391,6 +3400,8 @@ ul.menu-popup {
 	-webkit-border-radius: 5px;
 	border-radius:5px;
 	border: 1px solid #888;
+	top: 90px;
+	left: 200px;
 }
 #nav-notifications-menu .contactname { font-weight: bold; font-size: 0.9em; }
 #nav-notifications-menu img { float: left; margin-right: 5px; }
diff --git a/view/theme/frost-mobile/js/main.js b/view/theme/frost-mobile/js/main.js
index 9eac71be83..7e2880594d 100644
--- a/view/theme/frost-mobile/js/main.js
+++ b/view/theme/frost-mobile/js/main.js
@@ -13,7 +13,6 @@
 		if($(listID).is(":visible")) {
 			$(listID).hide();
 			$(listID+"-wrapper").show();
-			alert($(listID+"-wrapper").attr("id"));
 		}
 		else {
 			$(listID).show();
diff --git a/view/theme/frost-mobile/style.css b/view/theme/frost-mobile/style.css
index 400b23c10b..a99cc17a91 100644
--- a/view/theme/frost-mobile/style.css
+++ b/view/theme/frost-mobile/style.css
@@ -139,6 +139,47 @@ blockquote {
 	margin-right: 5px;
 }
 
+.btn {
+	outline: none;
+	-moz-box-shadow: inset 0px 1px 0px 0px #ffffff;
+	-webkit-box-shadow: inset 0px 1px 0px 0px #ffffff;
+	box-shadow: inset 0px 1px 0px 0px #ffffff;
+	background-color: #ededed;
+	text-indent: 0;
+	border: 1px solid #dcdcdc;
+	display: inline-block;
+	color: #777777;
+	padding: 5px 10px;
+	text-align: center;
+	border-radius: 8px;
+}
+
+.menu-popup {
+	width: auto;
+	border: 2px solid #444444;
+	background: #FFFFFF;
+	position: absolute;
+	margin: 2px 0 0;
+	display: none;
+	z-index: 10000;
+}
+
+.menu-popup li a {
+	display: block;
+	padding: 2px;
+}
+
+.menu-popup li a:hover {
+	color: #FFFFFF;
+	background: #3465A4;
+	text-decoration: none;
+}
+ul.menu-popup li.divider {
+	height: 1px;
+	margin: 3px 0;
+	overflow: hidden;
+	background-color: #2d2d2d;
+}
 
 
 /* nav */
@@ -2045,6 +2086,19 @@ input#profile-jot-email {
 	margin-left: 15px;
 }
 
+#contact-edit-status-wrapper {
+	padding: 10px;
+	border: 1px solid #aaa;
+	border-radius: 8px;
+}
+
+#contact-edit-contact-status {
+	font-weight: bold;
+}
+#contact-edit-actions {
+	float: right;
+	display: inline-block;
+}
 #contact-edit-wrapper {
 	margin-top: 10px;
 }
@@ -2059,14 +2113,10 @@ input#profile-jot-email {
 }
 
 #contact-edit-last-update-text {
-	float: left;
-	clear: left;
 	margin-top: 30px;
 }
 
 #contact-edit-poll-text {
-	float: left;
-	clear: left;
 	margin-top: 15px;
 	margin-bottom: 0px;
 }
diff --git a/view/theme/frost-mobile/templates/contact_edit.tpl b/view/theme/frost-mobile/templates/contact_edit.tpl
index e6401de606..48df4a0286 100644
--- a/view/theme/frost-mobile/templates/contact_edit.tpl
+++ b/view/theme/frost-mobile/templates/contact_edit.tpl
@@ -6,12 +6,6 @@
 
 	{{$tab_str}}
 
-	<div id="contact-edit-drop-link" >
-		<a href="contacts/{{$contact_id}}/drop" class="icon drophide" id="contact-edit-drop-link" onclick="return confirmDelete();"  title="{{$delete}}" {{*onmouseover="imgbright(this);" onmouseout="imgdull(this);"*}}></a>
-	</div>
-
-	<div id="contact-edit-drop-link-end"></div>
-
 	<div class="vcard">
 		<div class="fn">{{$name}}</div>
 		<div id="profile-photo-wrapper"><img class="photo" style="width: 175px; height: 175px;" src="{{$photo}}" alt="{{$name}}" /></div>
@@ -20,41 +14,50 @@
 
 	<div id="contact-edit-nav-wrapper" >
 		<div id="contact-edit-links">
-			<ul>
-				<li><div id="contact-edit-rel">{{$relation_text}}</div></li>
-				<li><div id="contact-edit-nettype">{{$nettype}}</div></li>
-				{{if $lost_contact}}
-					<li><div id="lost-contact-message">{{$lost_contact}}</div></li>
-				{{/if}}
-				{{if $insecure}}
-					<li><div id="insecure-message">{{$insecure}}</div></li>
-				{{/if}}
-				{{if $blocked}}
-					<li><div id="block-message">{{$blocked}}</div></li>
-				{{/if}}
-				{{if $ignored}}
-					<li><div id="ignore-message">{{$ignored}}</div></li>
-				{{/if}}
-				{{if $archived}}
-					<li><div id="archive-message">{{$archived}}</div></li>
-				{{/if}}
+			<div id="contact-edit-status-wrapper">
+				<span id="contact-edit-contact-status">{{$contact_status}}</span>
 
-				<li>&nbsp;</li>
+				<div id="contact-edit-actions">
+					<div class="btn" id="contact-edit-actions-button" onclick="openClose('contact-actions-menu')">{{$contact_action_button}}</div>
 
-				{{if $common_text}}
-					<li><div id="contact-edit-common"><a href="{{$common_link}}">{{$common_text}}</a></div></li>
-				{{/if}}
-				{{if $all_friends}}
-					<li><div id="contact-edit-allfriends"><a href="allfriends/{{$contact_id}}">{{$all_friends}}</a></div></li>
-				{{/if}}
+					<ul role="menu" aria-haspopup="true" id="contact-actions-menu" class="menu-popup" >
+						{{if $lblsuggest}}<li role="menuitem"><a  href="#" title="{{$contact_actions.suggest.title}}" onclick="window.location.href='{{$contact_actions.suggest.url}}'; return false;">{{$contact_actions.suggest.label}}</a></li>{{/if}}
+						{{if $poll_enabled}}<li role="menuitem"><a  href="#" title="{{$contact_actions.update.title}}" onclick="window.location.href='{{$contact_actions.update.url}}'; return false;">{{$contact_actions.update.label}}</a></li>{{/if}}
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.repair.title}}" onclick="window.location.href='{{$contact_actions.repair.url}}'; return false;">{{$contact_actions.repair.label}}</a></li>
+						<li class="divider"></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.block.title}}" onclick="window.location.href='{{$contact_actions.block.url}}'; return false;">{{$contact_actions.block.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.ignore.title}}" onclick="window.location.href='{{$contact_actions.ignore.url}}'; return false;">{{$contact_actions.ignore.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.archive.title}}" onclick="window.location.href='{{$contact_actions.archive.url}}'; return false;">{{$contact_actions.archive.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.delete.title}}" onclick="return confirmDelete();">{{$contact_actions.delete.label}}</a></li>
+					</ul>
+				</div>
 
+				<ul>
+					<li><div id="contact-edit-rel">{{$relation_text}}</div></li>
+					<li><div id="contact-edit-nettype">{{$nettype}}</div></li>
+					{{if $poll_enabled}}
+						<div id="contact-edit-poll-wrapper">
+							<div id="contact-edit-last-update-text">{{$lastupdtext}} <span id="contact-edit-last-updated">{{$last_update}}</span></div>
+						</div>
+					{{/if}}
+					{{if $lost_contact}}
+						<li><div id="lost-contact-message">{{$lost_contact}}</div></li>
+					{{/if}}
+					{{if $insecure}}
+						<li><div id="insecure-message">{{$insecure}}</div></li>
+					{{/if}}
+					{{if $blocked}}
+						<li><div id="block-message">{{$blocked}}</div></li>
+					{{/if}}
+					{{if $ignored}}
+						<li><div id="ignore-message">{{$ignored}}</div></li>
+					{{/if}}
+					{{if $archived}}
+						<li><div id="archive-message">{{$archived}}</div></li>
+					{{/if}}
 
-				<li><a href="network/0?nets=all&cid={{$contact_id}}" id="contact-edit-view-recent">{{$lblrecent}}</a></li>
-				{{if $lblsuggest}}
-					<li><a href="fsuggest/{{$contact_id}}" id="contact-edit-suggest">{{$lblsuggest}}</a></li>
-				{{/if}}
-
-			</ul>
+				</ul>
+			</div>
 		</div>
 	</div>
 	<div id="contact-edit-nav-end"></div>
@@ -63,12 +66,6 @@
 <form action="contacts/{{$contact_id}}" method="post" >
 <input type="hidden" name="contact_id" value="{{$contact_id}}">
 
-	{{if $poll_enabled}}
-		<div id="contact-edit-poll-wrapper">
-			<div id="contact-edit-last-update-text">{{$lastupdtext}} <span id="contact-edit-last-updated">{{$last_update}}</span></div>
-			<span id="contact-edit-poll-text">{{$updpub}} {{$poll_interval}}</span> <span id="contact-edit-update-now" class="button"><a id="update_now_link" href="contacts/{{$contact_id}}/update" >{{$udnow}}</a></span>
-		</div>
-	{{/if}}
 	<div id="contact-edit-end" ></div>
 
 	{{include file="field_checkbox.tpl" field=$hidden}}
diff --git a/view/theme/frost/style.css b/view/theme/frost/style.css
index 3dd400c76b..1054b55c11 100644
--- a/view/theme/frost/style.css
+++ b/view/theme/frost/style.css
@@ -113,6 +113,51 @@ blockquote {
 
 .pull-right { float: right }
 
+.btn {
+	outline: none;
+	-moz-box-shadow: inset 0px 1px 0px 0px #ffffff;
+	-webkit-box-shadow: inset 0px 1px 0px 0px #ffffff;
+	box-shadow: inset 0px 1px 0px 0px #ffffff;
+	background-color: #ededed;
+	text-indent: 0;
+	border: 1px solid #dcdcdc;
+	display: inline-block;
+	color: #777777;
+	padding: 5px 10px;
+	text-align: center;
+	border-radius: 8px;
+}
+a.btn {
+	text-decoration: none;
+	color: inherit;
+}
+
+.menu-popup {
+	width: auto;
+	border: 2px solid #444444;
+	background: #FFFFFF;
+	position: absolute;
+	margin: 2px 0 0;
+	display: none;
+	z-index: 10000;
+}
+
+.menu-popup li a {
+	display: block;
+	padding: 2px;
+}
+
+.menu-popup li a:hover {
+	color: #FFFFFF;
+	background: #3465A4;
+	text-decoration: none;
+}
+ul.menu-popup li.divider {
+	height: 1px;
+	margin: 3px 0;
+	overflow: hidden;
+	background-color: #2d2d2d;
+}
 
 
 /* nav */
@@ -1952,6 +1997,20 @@ input#dfrn-url {
 	margin-left: 15px;
 }
 
+#contact-edit-status-wrapper {
+	padding: 10px;
+	border: 1px solid #aaa;
+	border-radius: 8px;
+}
+
+#contact-edit-contact-status {
+	font-weight: bold;
+}
+#contact-edit-actions {
+	float: right;
+	display: inline-block;
+}
+
 #contact-edit-wrapper {
 	margin-top: 10px;
 }
@@ -1989,11 +2048,6 @@ input#dfrn-url {
 	margin-top: 5px;
 }
 
-#contact-edit-drop-link {
-	float: right;
-	margin-right: 20px;
-}
-
 #contact-edit-nav-end {
 	clear: both;
 }
diff --git a/view/theme/frost/templates/contact_edit.tpl b/view/theme/frost/templates/contact_edit.tpl
index 731c5e0d4c..76cfd77924 100644
--- a/view/theme/frost/templates/contact_edit.tpl
+++ b/view/theme/frost/templates/contact_edit.tpl
@@ -6,50 +6,52 @@
 
 	{{$tab_str}}
 
-	<div id="contact-edit-drop-link" >
-		<a href="contacts/{{$contact_id}}/drop" class="icon drophide" id="contact-edit-drop-link" onclick="return confirmDelete();"  title="{{$delete}}" {{*onmouseover="imgbright(this);" onmouseout="imgdull(this);"*}}></a>
-	</div>
-
-	<div id="contact-edit-drop-link-end"></div>
-
-
 	<div id="contact-edit-nav-wrapper" >
 		<div id="contact-edit-links">
-			<ul>
-				<li><div id="contact-edit-rel">{{$relation_text}}</div></li>
-				<li><div id="contact-edit-nettype">{{$nettype}}</div></li>
-				{{if $lost_contact}}
-					<li><div id="lost-contact-message">{{$lost_contact}}</div></li>
-				{{/if}}
-				{{if $insecure}}
-					<li><div id="insecure-message">{{$insecure}}</div></li>
-				{{/if}}
-				{{if $blocked}}
-					<li><div id="block-message">{{$blocked}}</div></li>
-				{{/if}}
-				{{if $ignored}}
-					<li><div id="ignore-message">{{$ignored}}</div></li>
-				{{/if}}
-				{{if $archived}}
-					<li><div id="archive-message">{{$archived}}</div></li>
-				{{/if}}
+			<div id="contact-edit-status-wrapper">
+				<span id="contact-edit-contact-status">{{$contact_status}}</span>
 
-				<li>&nbsp;</li>
+				<div id="contact-edit-actions">
+					<a class="btn" rel="#contact-actions-menu" href="#" id="contact-edit-actions-button">{{$contact_action_button}}</a>
 
-				{{if $common_text}}
-					<li><div id="contact-edit-common"><a href="{{$common_link}}">{{$common_text}}</a></div></li>
-				{{/if}}
-				{{if $all_friends}}
-					<li><div id="contact-edit-allfriends"><a href="allfriends/{{$contact_id}}">{{$all_friends}}</a></div></li>
-				{{/if}}
+					<ul role="menu" aria-haspopup="true" id="contact-actions-menu" class="menu-popup" >
+						{{if $lblsuggest}}<li role="menuitem"><a  href="#" title="{{$contact_actions.suggest.title}}" onclick="window.location.href='{{$contact_actions.suggest.url}}'; return false;">{{$contact_actions.suggest.label}}</a></li>{{/if}}
+						{{if $poll_enabled}}<li role="menuitem"><a  href="#" title="{{$contact_actions.update.title}}" onclick="window.location.href='{{$contact_actions.update.url}}'; return false;">{{$contact_actions.update.label}}</a></li>{{/if}}
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.repair.title}}" onclick="window.location.href='{{$contact_actions.repair.url}}'; return false;">{{$contact_actions.repair.label}}</a></li>
+						<li class="divider"></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.block.title}}" onclick="window.location.href='{{$contact_actions.block.url}}'; return false;">{{$contact_actions.block.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.ignore.title}}" onclick="window.location.href='{{$contact_actions.ignore.url}}'; return false;">{{$contact_actions.ignore.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.archive.title}}" onclick="window.location.href='{{$contact_actions.archive.url}}'; return false;">{{$contact_actions.archive.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.delete.title}}" onclick="return confirmDelete();">{{$contact_actions.delete.label}}</a></li>
+					</ul>
+				</div>
 
+				<ul>
+					<li><div id="contact-edit-rel">{{$relation_text}}</div></li>
+					<li><div id="contact-edit-nettype">{{$nettype}}</div></li>
+					{{if $poll_enabled}}
+						<div id="contact-edit-poll-wrapper">
+							<div id="contact-edit-last-update-text">{{$lastupdtext}} <span id="contact-edit-last-updated">{{$last_update}}</span></div>
+						</div>
+					{{/if}}
+					{{if $lost_contact}}
+						<li><div id="lost-contact-message">{{$lost_contact}}</div></li>
+					{{/if}}
+					{{if $insecure}}
+						<li><div id="insecure-message">{{$insecure}}</div></li>
+					{{/if}}
+					{{if $blocked}}
+						<li><div id="block-message">{{$blocked}}</div></li>
+					{{/if}}
+					{{if $ignored}}
+						<li><div id="ignore-message">{{$ignored}}</div></li>
+					{{/if}}
+					{{if $archived}}
+						<li><div id="archive-message">{{$archived}}</div></li>
+					{{/if}}
 
-				<li><a href="network/?cid={{$contact_id}}" id="contact-edit-view-recent">{{$lblrecent}}</a></li>
-				{{if $lblsuggest}}
-					<li><a href="fsuggest/{{$contact_id}}" id="contact-edit-suggest">{{$lblsuggest}}</a></li>
-				{{/if}}
-
-			</ul>
+				</ul>
+			</div>
 		</div>
 	</div>
 	<div id="contact-edit-nav-end"></div>
@@ -58,12 +60,6 @@
 <form action="contacts/{{$contact_id}}" method="post" >
 <input type="hidden" name="contact_id" value="{{$contact_id}}">
 
-	{{if $poll_enabled}}
-		<div id="contact-edit-poll-wrapper">
-			<div id="contact-edit-last-update-text">{{$lastupdtext}} <span id="contact-edit-last-updated">{{$last_update}}</span></div>
-			<span id="contact-edit-poll-text">{{$updpub}}</span> {{$poll_interval}} <span id="contact-edit-update-now" class="button"><a href="contacts/{{$contact_id}}/update" >{{$udnow}}</a></span>
-		</div>
-	{{/if}}
 	<div id="contact-edit-end" ></div>
 
 	{{include file="field_checkbox.tpl" field=$hidden}}
diff --git a/view/theme/quattro/dark/style.css b/view/theme/quattro/dark/style.css
index 847017ee5b..aed53fdac6 100644
--- a/view/theme/quattro/dark/style.css
+++ b/view/theme/quattro/dark/style.css
@@ -463,7 +463,7 @@ a:hover {
   text-decoration: underline;
 }
 blockquote {
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 1em;
   margin-left: 1em;
   border-left: 1em solid #e6e6e6;
@@ -1655,6 +1655,9 @@ span[id^="showmore-wrap"] {
   overflow: hidden;
   text-overflow: ellipsis;
 }
+#contact-edit-status-wrapper {
+  border-color: #364e59;
+}
 /* editor */
 .jothidden {
   display: none;
diff --git a/view/theme/quattro/green/style.css b/view/theme/quattro/green/style.css
index 4cfcb59273..74ab5b9cd0 100644
--- a/view/theme/quattro/green/style.css
+++ b/view/theme/quattro/green/style.css
@@ -463,7 +463,7 @@ a:hover {
   text-decoration: underline;
 }
 blockquote {
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 1em;
   margin-left: 1em;
   border-left: 1em solid #e6e6e6;
@@ -1655,6 +1655,9 @@ span[id^="showmore-wrap"] {
   overflow: hidden;
   text-overflow: ellipsis;
 }
+#contact-edit-status-wrapper {
+  border-color: #9ade00;
+}
 /* editor */
 .jothidden {
   display: none;
diff --git a/view/theme/quattro/lilac/style.css b/view/theme/quattro/lilac/style.css
index 2ff7cfcb0c..327309fa5e 100644
--- a/view/theme/quattro/lilac/style.css
+++ b/view/theme/quattro/lilac/style.css
@@ -420,7 +420,7 @@
 body {
   font-family: Liberation Sans, helvetica, arial, clean, sans-serif;
   font-size: 11px;
-  background-color: #F6ECF9;
+  background-color: #f6ecf9;
   color: #2d2d2d;
   margin: 50px 0 0 0;
   display: table;
@@ -463,7 +463,7 @@ a:hover {
   text-decoration: underline;
 }
 blockquote {
-  background: #FFFFFF;
+  background: #ffffff;
   padding: 1em;
   margin-left: 1em;
   border-left: 1em solid #e6e6e6;
@@ -1655,6 +1655,9 @@ span[id^="showmore-wrap"] {
   overflow: hidden;
   text-overflow: ellipsis;
 }
+#contact-edit-status-wrapper {
+  border-color: #86608e;
+}
 /* editor */
 .jothidden {
   display: none;
@@ -1753,7 +1756,7 @@ span[id^="showmore-wrap"] {
   height: 20px;
   width: 500px;
   font-weight: bold;
-  border: 1px solid #F6ECF9;
+  border: 1px solid #f6ecf9;
 }
 #jot #jot-title:-webkit-input-placeholder {
   font-weight: normal;
@@ -1780,7 +1783,7 @@ span[id^="showmore-wrap"] {
   margin: 0;
   height: 20px;
   width: 200px;
-  border: 1px solid #F6ECF9;
+  border: 1px solid #f6ecf9;
 }
 #jot #jot-category:hover {
   border: 1px solid #999999;
diff --git a/view/theme/quattro/quattro.less b/view/theme/quattro/quattro.less
index 681cfcc374..d81aedf41a 100644
--- a/view/theme/quattro/quattro.less
+++ b/view/theme/quattro/quattro.less
@@ -408,19 +408,19 @@ aside {
 .group-delete-wrapper {
 	float: right;
 	margin-right: 50px;
-        .drophide {
-            background-image: url('../../../images/icons/22/delete.png');
-            display: block; width: 22px; height: 22px;
-            opacity: 0.3;
-            position: relative;
-            top: -50px;
-        }
-        .drop {
-            background-image: url('../../../images/icons/22/delete.png');
-            display: block; width: 22px; height: 22px;
-            position: relative;
-            top: -50px;
-        }
+	.drophide {
+		background-image: url('../../../images/icons/22/delete.png');
+		display: block; width: 22px; height: 22px;
+		opacity: 0.3;
+		position: relative;
+		top: -50px;
+	}
+	.drop {
+		background-image: url('../../../images/icons/22/delete.png');
+		display: block; width: 22px; height: 22px;
+		position: relative;
+		top: -50px;
+	}
 }
 /*
 #group-members {
@@ -502,7 +502,7 @@ section {
 }
 
 .sparkle {
-  cursor: url('icons/lock.cur'), pointer;
+	cursor: url('icons/lock.cur'), pointer;
 }
 
 /* wall item */
@@ -959,6 +959,7 @@ span[id^="showmore-wrap"] {
 	text-overflow: ellipsis;
 }
 
+#contact-edit-status-wrapper { border-color: @JotToolsOverBackgroundColor;}
 /* editor */
 .jothidden { display: none; }
 #jot {
diff --git a/view/theme/smoothly/style.css b/view/theme/smoothly/style.css
index b9f094932d..87c7342c9d 100644
--- a/view/theme/smoothly/style.css
+++ b/view/theme/smoothly/style.css
@@ -236,6 +236,39 @@ section {
 	color: #efefef;
 }
 
+ul.menu-popup {
+	position: absolute;
+	display: none;
+	width: auto;
+	margin: 2px 0 0;
+	padding: 0px;
+	list-style: none;
+	z-index: 100000;
+	color: #2e3436;
+	border-top: 1px;
+	background: #eeeeee;
+	border: 1px solid #7C7D7B;
+	border-radius: 0px 0px 5px 5px;
+	-webkit-border-radius: 0px 0px 5px 5px;
+	-moz-border-radius: 0px 0px 5px 5px;
+	box-shadow: 5px 5px 10px #242424;
+	-moz-box-shadow: 5px 5px 10px #242424;
+	-webkit-box-shadow: 5px 5px 10px #242424;
+}
+ul.menu-popup li a {
+	white-space: nowrap;
+	display: block;
+	padding: 5px 2px;
+	color: #2e3436;
+}
+ul.menu-popup li a:hover {
+	color: #efefef;
+	background: -webkit-gradient( linear, left top, left bottom, color-stop(0.05, #1873a2), color-stop(1, #6da6c4) );
+	background: -moz-linear-gradient( center top, #1873a2 5%, #6da6c4 100% );
+	filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#1873a2', endColorstr='#6da6c4');
+	background-color: #1873a2;
+}
+
 /* ========= */
 /* = Login = */
 /* ========= */
@@ -4271,16 +4304,6 @@ a.active {
 .nav-notify.show {
 	display: block;
 }
-ul.menu-popup {
-	position: absolute;
-	display: none;
-	width: 10em;
-	margin: 0px;
-	padding: 0px;
-	list-style: none;
-	z-index: 100000;
-	top: 40px;
-}
 #nav-notifications-menu {
 	width: 320px;
 	max-height: 400px;
@@ -4298,6 +4321,7 @@ ul.menu-popup {
 	box-shadow: 5px 5px 10px #242424;
 		-moz-box-shadow: 5px 5px 10px #242424;
 		-webkit-box-shadow: 5px 5px 10px #242424;
+	top: 40px;
 }
 
 #nav-notifications-menu .contactname {
@@ -4406,6 +4430,10 @@ ul.menu-popup {
 	background: #000000;
 }
 
+.notify-seen a {
+	color: #efefef !important;
+}
+
 /* Pages profile widget ----------------------------------------------------------- */
 
 #page-profile,
diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css
index 2b78d25d7f..5b084567b6 100644
--- a/view/theme/vier/style.css
+++ b/view/theme/vier/style.css
@@ -24,72 +24,72 @@ img {
 }
 
 #pending-update {
-        float:right;
-        color: #ffffff;
-        font-weight: bold;
-        background-color: #FF0000;
-        padding: 0em 0.3em;
+  float:right;
+  color: #ffffff;
+  font-weight: bold;
+  background-color: #FF0000;
+  padding: 0em 0.3em;
 }
 
 .admin.linklist {
-        border: 0px;
-	padding: 0px;
-	list-style: none;
-	margin-top: 0px;
+  border: 0px;
+  padding: 0px;
+  list-style: none;
+  margin-top: 0px;
 }
 
 .admin.link {
-        list-style-position: inside;
-        font-size: 1em;
-/*        padding-left: 5px;
-        margin: 5px; */
+  list-style-position: inside;
+  font-size: 1em;
+/*  padding-left: 5px;
+    margin: 5px; */
 }
 
 #adminpage dl {
-        clear: left;
-        margin-bottom: 2px;
-        padding-bottom: 2px;
-        border-bottom: 1px solid black;
+  clear: left;
+  margin-bottom: 2px;
+  padding-bottom: 2px;
+  border-bottom: 1px solid black;
 }
 
 #adminpage dt {
-        width: 200px;
-        float: left;
-        font-weight: bold;
+  width: 200px;
+  float: left;
+  font-weight: bold;
 }
 
 #adminpage dd {
-        margin-left: 200px;
+  margin-left: 200px;
 }
 #adminpage h3 {
-        border-bottom: 1px solid #898989;
-        margin-bottom: 5px;
-        margin-top: 10px;
+  border-bottom: 1px solid #898989;
+  margin-bottom: 5px;
+  margin-top: 10px;
 }
 
 #adminpage .submit {
-        clear:left;
+  clear:left;
 }
 
 #adminpage #pluginslist {
-        margin: 0px; padding: 0px;
+  margin: 0px; padding: 0px;
 }
 
 #adminpage .plugin {
-        list-style: none;
-        display: block;
-	/* border: 1px solid #888888; */
-        padding: 1em;
-        margin-bottom: 5px;
-        clear: left;
+  list-style: none;
+  display: block;
+  /* border: 1px solid #888888; */
+  padding: 1em;
+  margin-bottom: 5px;
+  clear: left;
 }
 
 #adminpage .toggleplugin {
-        float:left;
-        margin-right: 1em;
+  float:left;
+  margin-right: 1em;
 }
 
-#adminpage table {width:100%; border-bottom: 1p solid #000000; margin: 5px 0px;}
+#adminpage table {width:100%; border-bottom: 1px solid #000000; margin: 5px 0px;}
 #adminpage table th { text-align: left;}
 #adminpage td .icon { float: left;}
 #adminpage table#users img { width: 16px; height: 16px; }
@@ -247,15 +247,6 @@ div.pager {
   float: left;
 }
 
-#contact-edit-drop-link-end {
-  /* clear: both; */
-}
-
-#contact-edit-links ul {
-  list-style: none;
-  list-style-type: none;
-}
-
 .hide-comments-outer {
   margin-left: 80px;
   margin-bottom: 5px;
@@ -385,6 +376,14 @@ code {
   overflow: auto;
   padding: 0px;
 }
+.menu-popup .divider {
+  width: 90%;
+  height: 1px;
+  margin: 3px auto;
+  overflow: hidden;
+  background-color: #737373;
+  opacity: 0.4;
+}
 #saved-search-ul .tool:hover,
 #nets-sidebar .tool:hover,
 #sidebar-group-list .tool:hover {
@@ -793,7 +792,8 @@ nav #nav-user-linklabel:hover #nav-user-menu,
 nav #nav-user-linkmenu:hover #nav-user-menu,
 nav #nav-apps-link:hover #nav-apps-menu,
 nav #nav-site-linkmenu:hover #nav-site-menu,
-nav #nav-notifications-linkmenu:hover #nav-notifications-menu {
+nav #nav-notifications-linkmenu:hover #nav-notifications-menu,
+#contact-edit-actions:hover #contact-actions-menu {
   display:block;
   visibility:visible;
   opacity:1;
@@ -2931,6 +2931,48 @@ a.mail-list-link {
   color: #999999;
 }
 
+/* contact edit page */
+#contact-edit-nav-wrapper {
+  margin-top: 24px;
+}
+#contact-edit-status-wrapper {
+  border-color: #c9d8f6;
+  background-color: #e0e8fa;
+  border-radius: 3px;
+}
+
+#contact-edit-contact-status {
+  font-weight: bold;
+}
+
+#contact-edit-drop-link-end {
+  /* clear: both; */
+}
+
+#contact-edit-links ul {
+  list-style: none;
+  list-style-type: none;
+}
+
+#contact-edit-settings {
+  margin-top: 10px;
+}
+
+a.btn#contact-edit-actions-button {
+  cursor: pointer;
+  border-radius: 3px;
+  font-size: inherit;
+  font-weight: normal;
+  height: auto;
+  line-height: inherit;
+  padding: 5px 10px;
+}
+
+#lost-contact-message, #insecure-message,
+#block-message, #ignore-message, #archive-message {
+  color: #CB4437;
+}
+
 /* photo album page */
 .photo-top-image-wrapper {
   position: relative;
diff --git a/view/theme/vier/templates/contact_edit.tpl b/view/theme/vier/templates/contact_edit.tpl
new file mode 100644
index 0000000000..df0053fb68
--- /dev/null
+++ b/view/theme/vier/templates/contact_edit.tpl
@@ -0,0 +1,99 @@
+
+{{if $header}}<h2>{{$header}}</h2>{{/if}}
+
+<div id="contact-edit-wrapper" >
+
+	{{* Insert Tab-Nav *}}
+	{{$tab_str}}
+
+
+	<div id="contact-edit-nav-wrapper" >
+		<div id="contact-edit-links">
+			<div id="contact-edit-status-wrapper">
+				<span id="contact-edit-contact-status">{{$contact_status}}</span>
+
+				{{* This is the Action menu where contact related actions like 'ignore', 'hide' can be performed *}}
+				<div id="contact-edit-actions">
+					<a class="btn" id="contact-edit-actions-button">{{$contact_action_button}}</a>
+
+					<ul role="menu" aria-haspopup="true" id="contact-actions-menu" class="menu-popup" >
+						{{if $lblsuggest}}<li role="menuitem"><a  href="#" title="{{$contact_actions.suggest.title}}" onclick="window.location.href='{{$contact_actions.suggest.url}}'; return false;">{{$contact_actions.suggest.label}}</a></li>{{/if}}
+						{{if $poll_enabled}}<li role="menuitem"><a  href="#" title="{{$contact_actions.update.title}}" onclick="window.location.href='{{$contact_actions.update.url}}'; return false;">{{$contact_actions.update.label}}</a></li>{{/if}}
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.repair.title}}" onclick="window.location.href='{{$contact_actions.repair.url}}'; return false;">{{$contact_actions.repair.label}}</a></li>
+						<li class="divider"></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.block.title}}" onclick="window.location.href='{{$contact_actions.block.url}}'; return false;">{{$contact_actions.block.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.ignore.title}}" onclick="window.location.href='{{$contact_actions.ignore.url}}'; return false;">{{$contact_actions.ignore.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.archive.title}}" onclick="window.location.href='{{$contact_actions.archive.url}}'; return false;">{{$contact_actions.archive.label}}</a></li>
+						<li role="menuitem"><a  href="#" title="{{$contact_actions.delete.title}}" onclick="return confirmDelete();">{{$contact_actions.delete.label}}</a></li>
+					</ul>
+				</div>
+
+				{{* Block with status information about the contact *}}
+				<ul>
+					{{if $relation_text}}<li><div id="contact-edit-rel">{{$relation_text}}</div></li>{{/if}}
+
+					{{if $poll_enabled}}
+						<li><div id="contact-edit-last-update-text">{{$lastupdtext}} <span id="contact-edit-last-updated">{{$last_update}}</span></div>
+						{{if $poll_interval}}
+							<span id="contact-edit-poll-text">{{$updpub}}</span> {{$poll_interval}}
+						{{/if}}
+						</li>
+					{{/if}}
+
+					{{if $lost_contact}}<li><div id="lost-contact-message">{{$lost_contact}}</div></li>{{/if}}
+					{{if $insecure}}<li><div id="insecure-message">{{$insecure}}</div></li>	{{/if}}
+					{{if $blocked}}<li><div id="block-message">{{$blocked}}</div></li>{{/if}}
+					{{if $ignored}}<li><div id="ignore-message">{{$ignored}}</div></li>{{/if}}
+					{{if $archived}}<li><div id="archive-message">{{$archived}}</div></li>{{/if}}
+				</ul>
+
+				<ul>
+					<!-- <li><a href="network/0?nets=all&cid={{$contact_id}}" id="contact-edit-view-recent">{{$lblrecent}}</a></li> -->
+					{{if $follow}}<li><div id="contact-edit-follow"><a href="{{$follow}}">{{$follow_text}}</a></div></li>{{/if}}
+				</ul>
+			</div> {{* End of contact-edit-status-wrapper *}}
+
+			{{* Some information about the contact from the profile *}}
+			<dl><dt>{{$profileurllabel}}</dt><dd><a target="blank" href="{{$url}}">{{$profileurl}}</a></dd></dl>
+			{{if $location}}<dl><dt>{{$location_label}}</dt><dd>{{$location}}</dd></dl>{{/if}}
+			{{if $keywords}}<dl><dt>{{$keywords_label}}</dt><dd>{{$keywords}}</dd></dl>{{/if}}
+			{{if $about}}<dl><dt>{{$about_label}}</dt><dd>{{$about}}</dd></dl>{{/if}}
+		</div>{{* End of contact-edit-links *}}
+
+		<div id="contact-edit-links-end"></div>
+
+		<hr />
+
+		<h4 id="contact-edit-settings-label" class="fakelink" onclick="openClose('contact-edit-settings')">{{$contact_settings_label}}</h4>
+		<div id="contact-edit-settings">
+			<form action="contacts/{{$contact_id}}" method="post" >
+			<input type="hidden" name="contact_id" value="{{$contact_id}}">
+
+				<div id="contact-edit-end" ></div>
+				{{include file="field_checkbox.tpl" field=$notify}}
+				{{if $fetch_further_information}}
+					{{include file="field_select.tpl" field=$fetch_further_information}}
+					{{if $fetch_further_information.2 == 2 }} {{include file="field_textarea.tpl" field=$ffi_keyword_blacklist}} {{/if}}
+				{{/if}}
+				{{include file="field_checkbox.tpl" field=$hidden}}
+
+			<div id="contact-edit-info-wrapper">
+				<h4>{{$lbl_info1}}</h4>
+				<textarea id="contact-edit-info" rows="8" cols="60" name="info">{{$info}}</textarea>
+				<input class="contact-edit-submit" type="submit" name="submit" value="{{$submit|escape:'html'}}" />
+			</div>
+			<div id="contact-edit-info-end"></div>
+
+			{{if $profile_select}}
+				<div id="contact-edit-profile-select-text">
+				<h4>{{$lbl_vis1}}</h4>
+				<p>{{$lbl_vis2}}</p> 
+				</div>
+				{{$profile_select}}
+				<div id="contact-edit-profile-select-end"></div>
+				<input class="contact-edit-submit" type="submit" name="submit" value="{{$submit|escape:'html'}}" />
+			{{/if}}
+			</form>
+		</div>
+	</div>{{* End of contact-edit-nav-wrapper *}}
+</div>

From 2e04a00d3044f600b29118e9a309c1192e62ead1 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Mon, 8 Feb 2016 23:25:48 +0100
Subject: [PATCH 069/273] contactedit-actions-button: some adjustment for vier
 dark scheme

---
 view/theme/vier/dark.css | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/view/theme/vier/dark.css b/view/theme/vier/dark.css
index 023e419464..99850f2826 100644
--- a/view/theme/vier/dark.css
+++ b/view/theme/vier/dark.css
@@ -8,6 +8,12 @@ hr { background-color: #343434 !important; }
 a, .wall-item-name, .fakelink { 
 	color: #989898 !important; 
 }
+.btn, .btn:hover{
+	color: #989898;
+	border: 2px solid #0C1116;
+	background-color: #0C1116;
+	text-shadow: none;
+}
 
 nav { 
 	color: #989898 !important;
@@ -36,7 +42,7 @@ body, section, blockquote, blockquote.shared_content, #profile-jot-form,
 }
 
 #profile-jot-acl-wrapper, #event-notice, #event-wrapper,
-#cboxLoadedContent, .contact-photo-menu {
+#cboxLoadedContent, .contact-photo-menu, #contact-edit-status-wrapper {
 	background-color: #252C33 !important;
 }
 

From c1c21ada0a9a728f18108168e0a324f7d84bd31c Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Mon, 8 Feb 2016 23:51:51 +0100
Subject: [PATCH 070/273] contactedit-actions-button: remove contact tabs which
 aren't needed anymore

---
 doc/Accesskeys.md |  4 ----
 mod/contacts.php  | 47 +++++++++++++++--------------------------------
 2 files changed, 15 insertions(+), 36 deletions(-)

diff --git a/doc/Accesskeys.md b/doc/Accesskeys.md
index c49e79c0ab..57de221c83 100644
--- a/doc/Accesskeys.md
+++ b/doc/Accesskeys.md
@@ -37,10 +37,6 @@ General
 * o: Profile
 * t: Contacts
 * d: Common friends
-* b: Toggle Blocked status
-* i: Toggle Ignored status
-* v: Toggle Archive status
-* r: Repair
 
 /message
 --------
diff --git a/mod/contacts.php b/mod/contacts.php
index a2287382a4..f5289cf03a 100644
--- a/mod/contacts.php
+++ b/mod/contacts.php
@@ -824,7 +824,17 @@ function contacts_content(&$a) {
 }
 }
 
-if(! function_exists('contacts_tab')) {
+/**
+ * @brief List of pages for the Contact TabBar
+ * 
+ * Available Pages are 'Status', 'Profile', 'Contacts' and 'Common Friends'
+ * 
+ * @param app $a
+ * @param int $contact_id The ID of the contact
+ * @param int $active_tab 1 if tab should be marked as active
+ * 
+ * @return array with with contact TabBar data
+ */
 function contacts_tab($a, $contact_id, $active_tab) {
 	// tabs
 	$tabs = array(
@@ -846,6 +856,7 @@ function contacts_tab($a, $contact_id, $active_tab) {
 		)
 	);
 
+	// Show this tab only if there is visible friend list
 	$x = count_all_friends(local_user(), $contact_id);
 	if ($x)
 		$tabs[] = array('label'=>t('Contacts'),
@@ -855,6 +866,7 @@ function contacts_tab($a, $contact_id, $active_tab) {
 				'id' => 'allfriends-tab',
 				'accesskey' => 't');
 
+	// Show this tab only if there is visible common friend list
 	$common = count_common_friends(local_user(),$contact_id);
 	if ($common)
 		$tabs[] = array('label'=>t('Common Friends'),
@@ -864,41 +876,11 @@ function contacts_tab($a, $contact_id, $active_tab) {
 				'id' => 'common-loc-tab',
 				'accesskey' => 'd');
 
-	$tabs[] = array('label' => t('Repair'),
-			'url'   => $a->get_baseurl(true) . '/crepair/' . $contact_id,
-			'sel' => (($active_tab == 5)?'active':''),
-			'title' => t('Advanced Contact Settings'),
-			'id'	=> 'repair-tab',
-			'accesskey' => 'r');
-
-
-	$tabs[] = array('label' => (($contact['blocked']) ? t('Unblock') : t('Block') ),
-			'url'   => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/block',
-			'sel'   => '',
-			'title' => t('Toggle Blocked status'),
-			'id'	=> 'toggle-block-tab',
-			'accesskey' => 'b');
-
-	$tabs[] = array('label' => (($contact['readonly']) ? t('Unignore') : t('Ignore') ),
-			'url'   => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/ignore',
-			'sel'   => '',
-			'title' => t('Toggle Ignored status'),
-			'id'	=> 'toggle-ignore-tab',
-			'accesskey' => 'i');
-
-	$tabs[] = array('label' => (($contact['archive']) ? t('Unarchive') : t('Archive') ),
-			'url'   => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/archive',
-			'sel'   => '',
-			'title' => t('Toggle Archive status'),
-			'id'	=> 'toggle-archive-tab',
-			'accesskey' => 'v');
-
 	$tab_tpl = get_markup_template('common_tabs.tpl');
 	$tab_str = replace_macros($tab_tpl, array('$tabs' => $tabs));
 
 	return $tab_str;
 }
-}
 
 if(! function_exists('contact_posts')) {
 function contact_posts($a, $contact_id) {
@@ -990,13 +972,14 @@ function _contact_detail_for_template($rr){
  * This includes actions like e.g. 'block', 'hide', 'archive', 'delete' and others
  * 
  * @param array $contact Data about the Contact
- * @return array with actions related actions
+ * @return array with contact related actions
  */
 function contact_actions($contact) {
 
 	$poll_enabled = in_array($contact['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_FEED, NETWORK_MAIL, NETWORK_MAIL2));
 	$contact_action = array();
 
+	// Provide friend suggestion only for Friendica contacts
 	if($contact['network'] === NETWORK_DFRN) {
 		$contact_actions['suggest'] = array(
 							'label' => t('Suggest friends'),

From 7af3dd01d808c99a5d7d02d152fe3399625b41e0 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 9 Feb 2016 06:42:00 +0100
Subject: [PATCH 071/273] Poller: Check the number of used database connections

---
 include/items.php  | 10 ++++++++++
 include/poller.php | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/include/items.php b/include/items.php
index 798ee56958..90c39a9889 100644
--- a/include/items.php
+++ b/include/items.php
@@ -509,6 +509,16 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
 	$arr['inform']        = ((x($arr,'inform'))        ? trim($arr['inform'])                : '');
 	$arr['file']          = ((x($arr,'file'))          ? trim($arr['file'])                  : '');
 
+
+	if (($arr['author-link'] == "") AND ($arr['owner-link'] == "")) {
+		$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
+		foreach ($trace AS $func)
+		        $function[] = $func["function"];
+
+		$function = implode(", ", $function);
+		logger("Both author-link and owner-link are empty. Called by: ".$function, LOGGER_DEBUG);
+	}
+
 	if ($arr['plink'] == "") {
 		$a = get_app();
 		$arr['plink'] = $a->get_baseurl().'/display/'.urlencode($arr['guid']);
diff --git a/include/poller.php b/include/poller.php
index 190f3fb1ad..712f6d5788 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -26,6 +26,9 @@ function poller_run(&$argv, &$argc){
 		unset($db_host, $db_user, $db_pass, $db_data);
 	};
 
+	if (poller_max_connections_reached())
+		return;
+
 	$load = current_load();
 	if($load) {
 		$maxsysload = intval(get_config('system','maxloadavg'));
@@ -117,6 +120,40 @@ function poller_run(&$argv, &$argc){
 
 }
 
+/**
+ * @brief Checks if the number of database connections has reached a critical limit.
+ *
+ * @return bool Are more than 3/4 of the maximum connections used?
+ */
+function poller_max_connections_reached() {
+	$r = q("SHOW VARIABLES WHERE `variable_name` = 'max_connections'");
+	if (!$r)
+		return false;
+
+	$max = intval($r[0]["Value"]);
+	if ($max == 0)
+		return false;
+
+	$r = q("SHOW STATUS WHERE `variable_name` = 'Threads_connected'");
+	if (!$r)
+		return false;
+
+	$connected = intval($r[0]["Value"]);
+	if ($connected == 0)
+		return false;
+
+	$level = $connected / $max;
+
+	logger("Connection usage: ".$connected."/".$max, LOGGER_DEBUG);
+
+	if ($level < (3/4))
+		return false;
+
+	logger("Maximum level (3/4) of connections reached: ".$connected."/".$max);
+	return true;
+
+}
+
 /**
  * @brief fix the queue entry if the worker process died
  *

From 5250fed44797a48dbddf7d2b5025f7a7c1b8da11 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Tue, 9 Feb 2016 09:39:29 +0100
Subject: [PATCH 072/273] Revert "Merge pull request #2319 from
 stieben/develop"

This reverts commit 9330a6994c1b9aee49a482efe32e84ca1a944c9b, reversing
changes made to ecfb6ec92460e3cd401789e44cd48a8bc503d762.

But it keeps changes to doc/Plugins.md and doc/de/Plugins.md
---
 doc/themes.md | 16 ++--------------
 index.php     | 11 +----------
 2 files changed, 3 insertions(+), 24 deletions(-)

diff --git a/doc/themes.md b/doc/themes.md
index ec3a76ac28..add44c776b 100644
--- a/doc/themes.md
+++ b/doc/themes.md
@@ -59,19 +59,7 @@ The same rule applies to the JavaScript files found in
 
 they will be overwritten by files in
 
-    /view/theme/**your-theme-name**/js
-
-### Modules
-
-You have the freedom to override core modules found in
-
-    /mod
-
-They will be overwritten by files in
-
-    /view/theme/**your-theme-name**/mod
-
-Be aware that you can break things easily here if you don't know what you do. Also notice that you can override parts of the module – functions not defined in your theme module will be loaded from the core module.
+    /view/theme/**your-theme-name**/js.
 
 ## Expand an existing Theme
 
@@ -300,4 +288,4 @@ The default file is in
     /view/default.php
 
 if you want to change it, say adding a 4th column for banners of your favourite FLOSS projects, place a new default.php file in your theme directory.
-As with the theme.php file, you can use the properties of the $a variable with holds the friendica application to decide what content is displayed.
+As with the theme.php file, you can use the properties of the $a variable with holds the friendica application to decide what content is displayed.
\ No newline at end of file
diff --git a/index.php b/index.php
index 2b1053cc1b..bf926d1fe7 100644
--- a/index.php
+++ b/index.php
@@ -233,16 +233,7 @@ if(strlen($a->module)) {
 	}
 
 	/**
-	 * If not, next look for module overrides by the theme
-	 */
-
-	if((! $a->module_loaded) && (file_exists("view/theme/" . current_theme() . "/mod/{$a->module}.php"))) {
-		include_once("view/theme/" . current_theme() . "/mod/{$a->module}.php");
-		// We will not set module_loaded to true to allow for partial overrides.
-	}
-
-	/**
-	 * Finally, look for a 'standard' program module in the 'mod' directory
+	 * If not, next look for a 'standard' program module in the 'mod' directory
 	 */
 
 	if((! $a->module_loaded) && (file_exists("mod/{$a->module}.php"))) {

From 7b2fadcf4330b47ffedddf6892b94fd0dd4ae86f Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 9 Feb 2016 10:21:10 +0100
Subject: [PATCH 073/273] Get rid of the "guid" table. We don't need it
 anymore.

---
 doc/database.md         |  1 -
 doc/database/db_guid.md | 12 ------------
 include/dbstructure.php | 15 ---------------
 include/items.php       | 13 -------------
 mod/item.php            |  3 ---
 5 files changed, 44 deletions(-)
 delete mode 100644 doc/database/db_guid.md

diff --git a/doc/database.md b/doc/database.md
index a0b28f4e84..e37df05e09 100644
--- a/doc/database.md
+++ b/doc/database.md
@@ -27,7 +27,6 @@ Database Tables
 | [group](help/database/db_group)                      | privacy groups, group info                       |
 | [group_member](help/database/db_group_member)        | privacy groups, member info                      |
 | [gserver](help/database/db_gserver)                  |                                                  |
-| [guid](help/database/db_guid)                        |                                                  |
 | [hook](help/database/db_hook)                        | plugin hook registry                             |
 | [intro](help/database/db_intro)                      |                                                  |
 | [item](help/database/db_item)                        | all posts                                        |
diff --git a/doc/database/db_guid.md b/doc/database/db_guid.md
deleted file mode 100644
index f607597a21..0000000000
--- a/doc/database/db_guid.md
+++ /dev/null
@@ -1,12 +0,0 @@
-Table guid
-==========
-
-| Field   | Description      | Type             | Null | Key | Default | Extra          |
-|---------|------------------|------------------|------|-----|---------|----------------|
-| id      | sequential ID    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
-| guid    |                  | varchar(255)     | NO   | MUL |         |                |
-| plink   |                  | varchar(255)     | NO   | MUL |         |                |
-| uri     |                  | varchar(255)     | NO   | MUL |         |                |
-| network |                  | varchar(32)      | NO   |     |         |                |
-
-Return to [database documentation](help/database)
diff --git a/include/dbstructure.php b/include/dbstructure.php
index 96d18cd789..ddf036f2c1 100644
--- a/include/dbstructure.php
+++ b/include/dbstructure.php
@@ -748,21 +748,6 @@ function db_definition() {
 					"nurl" => array("nurl"),
 					)
 			);
-	$database["guid"] = array(
-			"fields" => array(
-					"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
-					"guid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
-					"plink" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
-					"uri" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
-					"network" => array("type" => "varchar(32)", "not null" => "1", "default" => ""),
-					),
-			"indexes" => array(
-					"PRIMARY" => array("id"),
-					"guid" => array("guid"),
-					"plink" => array("plink"),
-					"uri" => array("uri"),
-					)
-			);
 	$database["hook"] = array(
 			"fields" => array(
 					"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
diff --git a/include/items.php b/include/items.php
index 90c39a9889..1af6fe1b52 100644
--- a/include/items.php
+++ b/include/items.php
@@ -291,16 +291,6 @@ function add_page_info_to_body($body, $texturl = false, $no_photos = false) {
 	return $body;
 }
 
-function add_guid($item) {
-	$r = q("SELECT `guid` FROM `guid` WHERE `guid` = '%s' LIMIT 1", dbesc($item["guid"]));
-	if ($r)
-		return;
-
-	q("INSERT INTO `guid` (`guid`,`plink`,`uri`,`network`) VALUES ('%s','%s','%s','%s')",
-		dbesc($item["guid"]), dbesc($item["plink"]),
-		dbesc($item["uri"]), dbesc($item["network"]));
-}
-
 /**
  * Adds a "lang" specification in a "postopts" element of given $arr,
  * if possible and not already present.
@@ -778,9 +768,6 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
 		return 0;
 	} elseif(count($r)) {
 
-		// Store the guid and other relevant data
-		add_guid($arr);
-
 		$current_post = $r[0]['id'];
 		logger('item_store: created item ' . $current_post);
 
diff --git a/mod/item.php b/mod/item.php
index 8c5a479646..7e575a17e4 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -844,9 +844,6 @@ function item_post(&$a) {
 		// NOTREACHED
 	}
 
-	// Store the guid and other relevant data
-	add_guid($datarray);
-
 	$post_id = $r[0]['id'];
 	logger('mod_item: saved item ' . $post_id);
 

From c28109ca947b5c5867ec052058dd2115f82aa0ff Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Tue, 9 Feb 2016 11:06:17 +0100
Subject: [PATCH 074/273] Update HTMLPurifier to v4.7.0

---
 .../HTMLPurifier/AttrDef/CSS/AlphaValue.php   |   21 -
 .../AttrDef/CSS/DenyElementDecorator.php      |   28 -
 .../HTMLPurifier/AttrDef/CSS/FontFamily.php   |   72 -
 library/HTMLPurifier/AttrDef/CSS/Length.php   |   47 -
 .../HTMLPurifier/AttrDef/CSS/ListStyle.php    |   78 -
 .../HTMLPurifier/AttrDef/CSS/Percentage.php   |   40 -
 library/HTMLPurifier/AttrDef/HTML/Bool.php    |   28 -
 library/HTMLPurifier/AttrDef/HTML/Color.php   |   32 -
 .../HTMLPurifier/AttrDef/HTML/FrameTarget.php |   21 -
 library/HTMLPurifier/AttrDef/HTML/ID.php      |   70 -
 library/HTMLPurifier/AttrDef/HTML/Length.php  |   41 -
 .../HTMLPurifier/AttrDef/HTML/MultiLength.php |   41 -
 library/HTMLPurifier/AttrDef/HTML/Pixels.php  |   48 -
 library/HTMLPurifier/AttrDef/Text.php         |   15 -
 library/HTMLPurifier/AttrDef/URI/Host.php     |   62 -
 library/HTMLPurifier/AttrDef/URI/IPv6.php     |   99 -
 .../HTMLPurifier/AttrTransform/BoolToCSS.php  |   36 -
 .../HTMLPurifier/AttrTransform/EnumToCSS.php  |   58 -
 library/HTMLPurifier/AttrTransform/Length.php |   27 -
 library/HTMLPurifier/AttrTransform/Name.php   |   21 -
 .../HTMLPurifier/AttrTransform/NameSync.php   |   27 -
 .../HTMLPurifier/AttrTransform/SafeObject.php |   16 -
 .../HTMLPurifier/AttrTransform/Textarea.php   |   18 -
 library/HTMLPurifier/Bootstrap.php            |   98 -
 library/HTMLPurifier/CSSDefinition.php        |  292 -
 library/HTMLPurifier/ChildDef/Optional.php    |   26 -
 library/HTMLPurifier/ChildDef/Required.php    |  117 -
 .../ChildDef/StrictBlockquote.php             |   88 -
 library/HTMLPurifier/ChildDef/Table.php       |  142 -
 library/HTMLPurifier/Config.php               |  580 --
 .../ConfigSchema/ValidatorAtom.php            |   66 -
 library/HTMLPurifier/ConfigSchema/schema.ser  |  Bin 13244 -> 0 bytes
 .../schema/HTML.AllowedElements.txt           |   18 -
 library/HTMLPurifier/Context.php              |   82 -
 library/HTMLPurifier/Definition.php           |   39 -
 .../DefinitionCache/Decorator.php             |   62 -
 .../DefinitionCache/Decorator/Cleanup.php     |   43 -
 .../DefinitionCache/Decorator/Memory.php      |   46 -
 .../DefinitionCache/Decorator/Template.php.in |   47 -
 library/HTMLPurifier/DefinitionCache/Null.php |   39 -
 .../DefinitionCache/Serializer.php            |  172 -
 .../HTMLPurifier/EntityLookup/entities.ser    |    1 -
 .../Filter/ExtractStyleBlocks.php             |  135 -
 library/HTMLPurifier/Filter/YouTube.php       |   39 -
 library/HTMLPurifier/HTMLModule/Forms.php     |  118 -
 .../HTMLPurifier/HTMLModule/Tidy/Strict.php   |   21 -
 library/HTMLPurifier/Injector/RemoveEmpty.php |   51 -
 library/HTMLPurifier/Language/messages/en.php |   63 -
 library/HTMLPurifier/Lexer/PEARSax3.php       |  139 -
 library/HTMLPurifier/Lexer/PH5P.php           | 3906 --------------
 library/HTMLPurifier/Strategy/FixNesting.php  |  328 --
 library/HTMLPurifier/Token.php                |   57 -
 library/HTMLPurifier/Token/Comment.php        |   22 -
 library/HTMLPurifier/TokenFactory.php         |   94 -
 library/HTMLPurifier/URI.php                  |  173 -
 library/HTMLPurifier/URIFilter.php            |   45 -
 .../URIFilter/DisableExternal.php             |   23 -
 .../URIFilter/DisableExternalResources.php    |   12 -
 .../HTMLPurifier/URIFilter/HostBlacklist.php  |   21 -
 library/HTMLPurifier/URIFilter/Munge.php      |   58 -
 library/HTMLPurifier/URIScheme.php            |   42 -
 library/HTMLPurifier/URIScheme/news.php       |   22 -
 library/HTMLPurifier/URIScheme/nntp.php       |   20 -
 library/HTMLPurifier/VarParser.php            |  154 -
 library/ezyang/htmlpurifier/CREDITS           |    9 +
 library/ezyang/htmlpurifier/INSTALL           |  374 ++
 library/ezyang/htmlpurifier/INSTALL.fr.utf8   |   60 +
 library/ezyang/htmlpurifier/LICENSE           |  504 ++
 library/ezyang/htmlpurifier/NEWS              | 1094 ++++
 library/ezyang/htmlpurifier/README            |   24 +
 library/ezyang/htmlpurifier/TODO              |  150 +
 library/ezyang/htmlpurifier/VERSION           |    1 +
 library/ezyang/htmlpurifier/WHATSNEW          |    4 +
 library/ezyang/htmlpurifier/WYSIWYG           |   20 +
 library/ezyang/htmlpurifier/composer.json     |   22 +
 .../extras/ConfigDoc/HTMLXSLTProcessor.php    |   91 +
 .../ezyang/htmlpurifier/extras/FSTools.php    |  164 +
 .../htmlpurifier/extras/FSTools/File.php      |  141 +
 .../extras/HTMLPurifierExtras.auto.php        |   11 +
 .../extras/HTMLPurifierExtras.autoload.php    |   26 +
 .../extras/HTMLPurifierExtras.php             |   31 +
 library/ezyang/htmlpurifier/extras/README     |   32 +
 .../library}/HTMLPurifier.auto.php            |    0
 .../library}/HTMLPurifier.autoload.php        |    8 +-
 .../library/HTMLPurifier.composer.php         |    4 +
 .../library}/HTMLPurifier.func.php            |    8 +-
 .../library}/HTMLPurifier.includes.php        |   21 +-
 .../library}/HTMLPurifier.kses.php            |    4 +-
 .../library}/HTMLPurifier.path.php            |    0
 .../htmlpurifier/library}/HTMLPurifier.php    |  153 +-
 .../library}/HTMLPurifier.safe-includes.php   |   19 +
 .../library/HTMLPurifier/Arborize.php         |   71 +
 .../library}/HTMLPurifier/AttrCollections.php |   53 +-
 .../library}/HTMLPurifier/AttrDef.php         |   53 +-
 .../library}/HTMLPurifier/AttrDef/CSS.php     |   39 +-
 .../HTMLPurifier/AttrDef/CSS/AlphaValue.php   |   34 +
 .../HTMLPurifier/AttrDef/CSS/Background.php   |   60 +-
 .../AttrDef/CSS/BackgroundPosition.php        |   54 +-
 .../HTMLPurifier/AttrDef/CSS/Border.php       |   21 +-
 .../HTMLPurifier/AttrDef/CSS/Color.php        |   67 +-
 .../HTMLPurifier/AttrDef/CSS/Composite.php    |   22 +-
 .../AttrDef/CSS/DenyElementDecorator.php      |   44 +
 .../HTMLPurifier/AttrDef/CSS/Filter.php       |   49 +-
 .../HTMLPurifier/AttrDef/CSS/Font.php         |   89 +-
 .../HTMLPurifier/AttrDef/CSS/FontFamily.php   |  219 +
 .../HTMLPurifier/AttrDef/CSS/Ident.php        |   32 +
 .../AttrDef/CSS/ImportantDecorator.php        |   28 +-
 .../HTMLPurifier/AttrDef/CSS/Length.php       |   77 +
 .../HTMLPurifier/AttrDef/CSS/ListStyle.php    |  112 +
 .../HTMLPurifier/AttrDef/CSS/Multiple.php     |   33 +-
 .../HTMLPurifier/AttrDef/CSS/Number.php       |   45 +-
 .../HTMLPurifier/AttrDef/CSS/Percentage.php   |   54 +
 .../AttrDef/CSS/TextDecoration.php            |   20 +-
 .../library}/HTMLPurifier/AttrDef/CSS/URI.php |   38 +-
 .../library/HTMLPurifier/AttrDef/Clone.php    |   44 +
 .../library}/HTMLPurifier/AttrDef/Enum.php    |   28 +-
 .../HTMLPurifier/AttrDef/HTML/Bool.php        |   48 +
 .../HTMLPurifier/AttrDef/HTML/Class.php       |   22 +-
 .../HTMLPurifier/AttrDef/HTML/Color.php       |   51 +
 .../HTMLPurifier/AttrDef/HTML/FrameTarget.php |   38 +
 .../library/HTMLPurifier/AttrDef/HTML/ID.php  |  105 +
 .../HTMLPurifier/AttrDef/HTML/Length.php      |   56 +
 .../HTMLPurifier/AttrDef/HTML/LinkTypes.php   |   43 +-
 .../HTMLPurifier/AttrDef/HTML/MultiLength.php |   60 +
 .../HTMLPurifier/AttrDef/HTML/Nmtokens.php    |   40 +-
 .../HTMLPurifier/AttrDef/HTML/Pixels.php      |   76 +
 .../library}/HTMLPurifier/AttrDef/Integer.php |   56 +-
 .../library}/HTMLPurifier/AttrDef/Lang.php    |   39 +-
 .../library}/HTMLPurifier/AttrDef/Switch.php  |   27 +-
 .../library/HTMLPurifier/AttrDef/Text.php     |   21 +
 .../library}/HTMLPurifier/AttrDef/URI.php     |   72 +-
 .../HTMLPurifier/AttrDef/URI/Email.php        |    5 +-
 .../AttrDef/URI/Email/SimpleCheck.php         |   14 +-
 .../library/HTMLPurifier/AttrDef/URI/Host.php |  128 +
 .../HTMLPurifier/AttrDef/URI/IPv4.php         |   28 +-
 .../library/HTMLPurifier/AttrDef/URI/IPv6.php |   89 +
 .../library}/HTMLPurifier/AttrTransform.php   |   28 +-
 .../HTMLPurifier/AttrTransform/Background.php |   21 +-
 .../HTMLPurifier/AttrTransform/BdoDir.php     |   14 +-
 .../HTMLPurifier/AttrTransform/BgColor.php    |   21 +-
 .../HTMLPurifier/AttrTransform/BoolToCSS.php  |   47 +
 .../HTMLPurifier/AttrTransform/Border.php     |   18 +-
 .../HTMLPurifier/AttrTransform/EnumToCSS.php  |   68 +
 .../AttrTransform/ImgRequired.php             |   19 +-
 .../HTMLPurifier/AttrTransform/ImgSpace.php   |   39 +-
 .../HTMLPurifier/AttrTransform/Input.php      |   34 +-
 .../HTMLPurifier/AttrTransform/Lang.php       |   15 +-
 .../HTMLPurifier/AttrTransform/Length.php     |   45 +
 .../HTMLPurifier/AttrTransform/Name.php       |   33 +
 .../HTMLPurifier/AttrTransform/NameSync.php   |   41 +
 .../HTMLPurifier/AttrTransform/Nofollow.php   |   52 +
 .../HTMLPurifier/AttrTransform/SafeEmbed.php  |   12 +-
 .../HTMLPurifier/AttrTransform/SafeObject.php |   28 +
 .../HTMLPurifier/AttrTransform/SafeParam.php  |   29 +-
 .../AttrTransform/ScriptRequired.php          |    9 +-
 .../AttrTransform/TargetBlank.php             |   45 +
 .../HTMLPurifier/AttrTransform/Textarea.php   |   27 +
 .../library}/HTMLPurifier/AttrTypes.php       |   45 +-
 .../library}/HTMLPurifier/AttrValidator.php   |   66 +-
 .../library/HTMLPurifier/Bootstrap.php        |  124 +
 .../library/HTMLPurifier/CSSDefinition.php    |  474 ++
 .../library}/HTMLPurifier/ChildDef.php        |   26 +-
 .../HTMLPurifier/ChildDef/Chameleon.php       |   33 +-
 .../library}/HTMLPurifier/ChildDef/Custom.php |   60 +-
 .../library}/HTMLPurifier/ChildDef/Empty.php  |   22 +-
 .../library/HTMLPurifier/ChildDef/List.php    |   86 +
 .../HTMLPurifier/ChildDef/Optional.php        |   45 +
 .../HTMLPurifier/ChildDef/Required.php        |  118 +
 .../ChildDef/StrictBlockquote.php             |  110 +
 .../library/HTMLPurifier/ChildDef/Table.php   |  224 +
 .../library/HTMLPurifier/Config.php           |  920 ++++
 .../library}/HTMLPurifier/ConfigSchema.php    |   78 +-
 .../ConfigSchema/Builder/ConfigSchema.php     |    8 +-
 .../HTMLPurifier/ConfigSchema/Builder/Xml.php |   94 +-
 .../HTMLPurifier/ConfigSchema/Exception.php   |    0
 .../HTMLPurifier/ConfigSchema/Interchange.php |   11 +-
 .../ConfigSchema/Interchange/Directive.php    |   28 +-
 .../ConfigSchema/Interchange/Id.php           |   33 +-
 .../ConfigSchema/InterchangeBuilder.php       |   90 +-
 .../HTMLPurifier/ConfigSchema/Validator.php   |   90 +-
 .../ConfigSchema/ValidatorAtom.php            |  130 +
 .../HTMLPurifier/ConfigSchema/schema.ser      |  Bin 0 -> 15305 bytes
 .../schema/Attr.AllowedClasses.txt            |    0
 .../schema/Attr.AllowedFrameTargets.txt       |    0
 .../ConfigSchema/schema/Attr.AllowedRel.txt   |    0
 .../ConfigSchema/schema/Attr.AllowedRev.txt   |    0
 .../schema/Attr.ClassUseCDATA.txt             |    0
 .../schema/Attr.DefaultImageAlt.txt           |    0
 .../schema/Attr.DefaultInvalidImage.txt       |    0
 .../schema/Attr.DefaultInvalidImageAlt.txt    |    0
 .../schema/Attr.DefaultTextDir.txt            |    0
 .../ConfigSchema/schema/Attr.EnableID.txt     |    0
 .../schema/Attr.ForbiddenClasses.txt          |    0
 .../ConfigSchema/schema/Attr.IDBlacklist.txt  |    0
 .../schema/Attr.IDBlacklistRegexp.txt         |    0
 .../ConfigSchema/schema/Attr.IDPrefix.txt     |    0
 .../schema/Attr.IDPrefixLocal.txt             |    0
 .../schema/AutoFormat.AutoParagraph.txt       |    0
 .../ConfigSchema/schema/AutoFormat.Custom.txt |    0
 .../schema/AutoFormat.DisplayLinkURI.txt      |    0
 .../schema/AutoFormat.Linkify.txt             |    0
 .../AutoFormat.PurifierLinkify.DocURL.txt     |    0
 .../schema/AutoFormat.PurifierLinkify.txt     |    0
 .../AutoFormat.RemoveEmpty.Predicate.txt      |   14 +
 ...rmat.RemoveEmpty.RemoveNbsp.Exceptions.txt |    0
 .../AutoFormat.RemoveEmpty.RemoveNbsp.txt     |    0
 .../schema/AutoFormat.RemoveEmpty.txt         |    0
 ...utoFormat.RemoveSpansWithoutAttributes.txt |    0
 .../schema/CSS.AllowImportant.txt             |    0
 .../ConfigSchema/schema/CSS.AllowTricky.txt   |    0
 .../ConfigSchema/schema/CSS.AllowedFonts.txt  |   12 +
 .../schema/CSS.AllowedProperties.txt          |    0
 .../ConfigSchema/schema/CSS.DefinitionRev.txt |    0
 .../schema/CSS.ForbiddenProperties.txt        |   13 +
 .../ConfigSchema/schema/CSS.MaxImgLength.txt  |    0
 .../ConfigSchema/schema/CSS.Proprietary.txt   |    0
 .../ConfigSchema/schema/CSS.Trusted.txt       |    9 +
 .../schema/Cache.DefinitionImpl.txt           |    0
 .../schema/Cache.SerializerPath.txt           |    0
 .../schema/Cache.SerializerPermissions.txt    |   11 +
 .../schema/Core.AggressivelyFixLt.txt         |    0
 .../schema/Core.AllowHostnameUnderscore.txt   |   16 +
 .../schema/Core.CollectErrors.txt             |    0
 .../schema/Core.ColorKeywords.txt             |    3 +-
 .../schema/Core.ConvertDocumentToFragment.txt |    0
 .../Core.DirectLexLineNumberSyncInterval.txt  |    0
 .../schema/Core.DisableExcludes.txt           |   14 +
 .../ConfigSchema/schema/Core.EnableIDNA.txt   |    9 +
 .../ConfigSchema/schema/Core.Encoding.txt     |    0
 .../schema/Core.EscapeInvalidChildren.txt     |    6 +-
 .../schema/Core.EscapeInvalidTags.txt         |    0
 .../schema/Core.EscapeNonASCIICharacters.txt  |    0
 .../schema/Core.HiddenElements.txt            |    0
 .../ConfigSchema/schema/Core.Language.txt     |    0
 .../ConfigSchema/schema/Core.LexerImpl.txt    |    0
 .../schema/Core.MaintainLineNumbers.txt       |    0
 .../schema/Core.NormalizeNewlines.txt         |   11 +
 .../schema/Core.RemoveInvalidImg.txt          |    0
 .../Core.RemoveProcessingInstructions.txt     |   11 +
 .../schema/Core.RemoveScriptContents.txt      |    0
 .../ConfigSchema/schema/Filter.Custom.txt     |    0
 .../Filter.ExtractStyleBlocks.Escaping.txt    |    0
 .../Filter.ExtractStyleBlocks.Scope.txt       |    0
 .../Filter.ExtractStyleBlocks.TidyImpl.txt    |    0
 .../schema/Filter.ExtractStyleBlocks.txt      |    0
 .../ConfigSchema/schema/Filter.YouTube.txt    |    5 +
 .../ConfigSchema/schema/HTML.Allowed.txt      |   11 +-
 .../schema/HTML.AllowedAttributes.txt         |    0
 .../schema/HTML.AllowedComments.txt           |   10 +
 .../schema/HTML.AllowedCommentsRegexp.txt     |   15 +
 .../schema/HTML.AllowedElements.txt           |   23 +
 .../schema/HTML.AllowedModules.txt            |    0
 .../schema/HTML.Attr.Name.UseCDATA.txt        |    0
 .../ConfigSchema/schema/HTML.BlockWrapper.txt |    0
 .../ConfigSchema/schema/HTML.CoreModules.txt  |    0
 .../schema/HTML.CustomDoctype.txt             |    2 +-
 .../ConfigSchema/schema/HTML.DefinitionID.txt |    0
 .../schema/HTML.DefinitionRev.txt             |    0
 .../ConfigSchema/schema/HTML.Doctype.txt      |    0
 .../schema/HTML.FlashAllowFullScreen.txt      |   11 +
 .../schema/HTML.ForbiddenAttributes.txt       |    0
 .../schema/HTML.ForbiddenElements.txt         |    0
 .../ConfigSchema/schema/HTML.MaxImgLength.txt |    0
 .../ConfigSchema/schema/HTML.Nofollow.txt     |    7 +
 .../ConfigSchema/schema/HTML.Parent.txt       |    0
 .../ConfigSchema/schema/HTML.Proprietary.txt  |    0
 .../ConfigSchema/schema/HTML.SafeEmbed.txt    |    0
 .../ConfigSchema/schema/HTML.SafeIframe.txt   |   13 +
 .../ConfigSchema/schema/HTML.SafeObject.txt   |    0
 .../schema/HTML.SafeScripting.txt             |   10 +
 .../ConfigSchema/schema/HTML.Strict.txt       |    0
 .../ConfigSchema/schema/HTML.TargetBlank.txt  |    8 +
 .../ConfigSchema/schema/HTML.TidyAdd.txt      |    0
 .../ConfigSchema/schema/HTML.TidyLevel.txt    |    0
 .../ConfigSchema/schema/HTML.TidyRemove.txt   |    0
 .../ConfigSchema/schema/HTML.Trusted.txt      |    1 +
 .../ConfigSchema/schema/HTML.XHTML.txt        |    0
 .../schema/Output.CommentScriptContents.txt   |    0
 .../schema/Output.FixInnerHTML.txt            |   15 +
 .../schema/Output.FlashCompat.txt             |    0
 .../ConfigSchema/schema/Output.Newline.txt    |    0
 .../ConfigSchema/schema/Output.SortAttr.txt   |    0
 .../ConfigSchema/schema/Output.TidyFormat.txt |    0
 .../ConfigSchema/schema/Test.ForceNoIconv.txt |    0
 .../schema/URI.AllowedSchemes.txt             |    4 +-
 .../ConfigSchema/schema/URI.Base.txt          |    0
 .../ConfigSchema/schema/URI.DefaultScheme.txt |    0
 .../ConfigSchema/schema/URI.DefinitionID.txt  |    0
 .../ConfigSchema/schema/URI.DefinitionRev.txt |    0
 .../ConfigSchema/schema/URI.Disable.txt       |    0
 .../schema/URI.DisableExternal.txt            |    0
 .../schema/URI.DisableExternalResources.txt   |    0
 .../schema/URI.DisableResources.txt           |    7 +-
 .../ConfigSchema/schema/URI.Host.txt          |    0
 .../ConfigSchema/schema/URI.HostBlacklist.txt |    0
 .../ConfigSchema/schema/URI.MakeAbsolute.txt  |    0
 .../ConfigSchema/schema/URI.Munge.txt         |    0
 .../schema/URI.MungeResources.txt             |    0
 .../schema/URI.MungeSecretKey.txt             |    2 +-
 .../schema/URI.OverrideAllowedSchemes.txt     |    0
 .../schema/URI.SafeIframeRegexp.txt           |   22 +
 .../HTMLPurifier/ConfigSchema/schema/info.ini |    0
 .../library}/HTMLPurifier/ContentSets.php     |   55 +-
 .../library/HTMLPurifier/Context.php          |   95 +
 .../library/HTMLPurifier/Definition.php       |   55 +
 .../library}/HTMLPurifier/DefinitionCache.php |   57 +-
 .../DefinitionCache/Decorator.php             |  112 +
 .../DefinitionCache/Decorator/Cleanup.php     |   78 +
 .../DefinitionCache/Decorator/Memory.php      |   85 +
 .../DefinitionCache/Decorator/Template.php.in |   82 +
 .../HTMLPurifier/DefinitionCache/Null.php     |   76 +
 .../DefinitionCache/Serializer.php            |  291 +
 .../DefinitionCache/Serializer/README         |    0
 .../HTMLPurifier/DefinitionCacheFactory.php   |   47 +-
 .../library}/HTMLPurifier/Doctype.php         |   17 +-
 .../library}/HTMLPurifier/DoctypeRegistry.php |   87 +-
 .../library}/HTMLPurifier/ElementDef.php      |   85 +-
 .../library}/HTMLPurifier/Encoder.php         |  303 +-
 .../library}/HTMLPurifier/EntityLookup.php    |   16 +-
 .../HTMLPurifier/EntityLookup/entities.ser    |    1 +
 .../library}/HTMLPurifier/EntityParser.php    |   53 +-
 .../library}/HTMLPurifier/ErrorCollector.php  |   87 +-
 .../library}/HTMLPurifier/ErrorStruct.php     |   20 +-
 .../library}/HTMLPurifier/Exception.php       |    0
 .../library}/HTMLPurifier/Filter.php          |   18 +-
 .../Filter/ExtractStyleBlocks.php             |  338 ++
 .../library/HTMLPurifier/Filter/YouTube.php   |   65 +
 .../library}/HTMLPurifier/Generator.php       |  164 +-
 .../library}/HTMLPurifier/HTMLDefinition.php  |  211 +-
 .../library}/HTMLPurifier/HTMLModule.php      |  122 +-
 .../library}/HTMLPurifier/HTMLModule/Bdo.php  |   21 +-
 .../HTMLModule/CommonAttributes.php           |    7 +-
 .../library}/HTMLPurifier/HTMLModule/Edit.php |   25 +-
 .../library/HTMLPurifier/HTMLModule/Forms.php |  190 +
 .../HTMLPurifier/HTMLModule/Hypertext.php     |   15 +-
 .../HTMLPurifier/HTMLModule/Iframe.php        |   51 +
 .../HTMLPurifier/HTMLModule/Image.php         |   17 +-
 .../HTMLPurifier/HTMLModule/Legacy.php        |   89 +-
 .../library}/HTMLPurifier/HTMLModule/List.php |   28 +-
 .../library}/HTMLPurifier/HTMLModule/Name.php |   13 +-
 .../HTMLPurifier/HTMLModule/Nofollow.php      |   25 +
 .../HTMLModule/NonXMLCommonAttributes.php     |    6 +
 .../HTMLPurifier/HTMLModule/Object.php        |   31 +-
 .../HTMLPurifier/HTMLModule/Presentation.php  |   26 +-
 .../HTMLPurifier/HTMLModule/Proprietary.php   |   19 +-
 .../library}/HTMLPurifier/HTMLModule/Ruby.php |   17 +-
 .../HTMLPurifier/HTMLModule/SafeEmbed.php     |   20 +-
 .../HTMLPurifier/HTMLModule/SafeObject.php    |   33 +-
 .../HTMLPurifier/HTMLModule/SafeScripting.php |   40 +
 .../HTMLPurifier/HTMLModule/Scripting.php     |   31 +-
 .../HTMLModule/StyleAttribute.php             |   15 +-
 .../HTMLPurifier/HTMLModule/Tables.php        |   29 +-
 .../HTMLPurifier/HTMLModule/Target.php        |   11 +-
 .../HTMLPurifier/HTMLModule/TargetBlank.php   |   24 +
 .../library}/HTMLPurifier/HTMLModule/Text.php |   56 +-
 .../library}/HTMLPurifier/HTMLModule/Tidy.php |   85 +-
 .../HTMLPurifier/HTMLModule/Tidy/Name.php     |   15 +-
 .../HTMLModule/Tidy/Proprietary.php           |   14 +-
 .../HTMLPurifier/HTMLModule/Tidy/Strict.php   |   43 +
 .../HTMLModule/Tidy/Transitional.php          |    7 +
 .../HTMLPurifier/HTMLModule/Tidy/XHTML.php    |   15 +-
 .../HTMLModule/Tidy/XHTMLAndHTML4.php         |  146 +-
 .../HTMLModule/XMLCommonAttributes.php        |    6 +
 .../HTMLPurifier/HTMLModuleManager.php        |  166 +-
 .../library}/HTMLPurifier/IDAccumulator.php   |   24 +-
 .../library}/HTMLPurifier/Injector.php        |  194 +-
 .../HTMLPurifier/Injector/AutoParagraph.php   |   99 +-
 .../HTMLPurifier/Injector/DisplayLinkURI.php  |   22 +-
 .../HTMLPurifier/Injector/Linkify.php         |   27 +-
 .../HTMLPurifier/Injector/PurifierLinkify.php |   46 +-
 .../HTMLPurifier/Injector/RemoveEmpty.php     |  106 +
 .../Injector/RemoveSpansWithoutAttributes.php |   36 +-
 .../HTMLPurifier/Injector/SafeObject.php      |   53 +-
 .../library}/HTMLPurifier/Language.php        |   97 +-
 .../Language/classes/en-x-test.php            |    3 -
 .../Language/messages/en-x-test.php           |    0
 .../Language/messages/en-x-testmini.php       |    0
 .../HTMLPurifier/Language/messages/en.php     |   55 +
 .../library}/HTMLPurifier/LanguageFactory.php |   81 +-
 .../library}/HTMLPurifier/Length.php          |   91 +-
 .../library}/HTMLPurifier/Lexer.php           |  189 +-
 .../library}/HTMLPurifier/Lexer/DOMLex.php    |  162 +-
 .../library}/HTMLPurifier/Lexer/DirectLex.php |  217 +-
 .../library/HTMLPurifier/Lexer/PH5P.php       | 4787 +++++++++++++++++
 .../library/HTMLPurifier/Node.php             |   49 +
 .../library/HTMLPurifier/Node/Comment.php     |   36 +
 .../library/HTMLPurifier/Node/Element.php     |   59 +
 .../library/HTMLPurifier/Node/Text.php        |   54 +
 .../library}/HTMLPurifier/PercentEncoder.php  |   37 +-
 .../library}/HTMLPurifier/Printer.php         |  134 +-
 .../HTMLPurifier/Printer/CSSDefinition.php    |   12 +-
 .../HTMLPurifier/Printer/ConfigForm.css       |    0
 .../HTMLPurifier/Printer/ConfigForm.js        |    0
 .../HTMLPurifier/Printer/ConfigForm.php       |  255 +-
 .../HTMLPurifier/Printer/HTMLDefinition.php   |  208 +-
 .../library}/HTMLPurifier/PropertyList.php    |   68 +-
 .../HTMLPurifier/PropertyListIterator.php     |   22 +-
 .../library/HTMLPurifier/Queue.php            |   56 +
 .../library}/HTMLPurifier/Strategy.php        |    8 +-
 .../HTMLPurifier/Strategy/Composite.php       |   13 +-
 .../library}/HTMLPurifier/Strategy/Core.php   |    5 +-
 .../HTMLPurifier/Strategy/FixNesting.php      |  181 +
 .../HTMLPurifier/Strategy/MakeWellFormed.php  |  383 +-
 .../Strategy/RemoveForeignElements.php        |   94 +-
 .../Strategy/ValidateAttributes.php           |   22 +-
 .../library}/HTMLPurifier/StringHash.php      |   16 +-
 .../HTMLPurifier/StringHashParser.php         |   52 +-
 .../library}/HTMLPurifier/TagTransform.php    |   15 +-
 .../HTMLPurifier/TagTransform/Font.php        |   42 +-
 .../HTMLPurifier/TagTransform/Simple.php      |   21 +-
 .../library/HTMLPurifier/Token.php            |  100 +
 .../library/HTMLPurifier/Token/Comment.php    |   38 +
 .../library}/HTMLPurifier/Token/Empty.php     |    6 +-
 .../library}/HTMLPurifier/Token/End.php       |    9 +-
 .../library}/HTMLPurifier/Token/Start.php     |    1 -
 .../library}/HTMLPurifier/Token/Tag.php       |   22 +-
 .../library}/HTMLPurifier/Token/Text.php      |   34 +-
 .../library/HTMLPurifier/TokenFactory.php     |  118 +
 .../htmlpurifier/library/HTMLPurifier/URI.php |  314 ++
 .../library}/HTMLPurifier/URIDefinition.php   |   39 +-
 .../library/HTMLPurifier/URIFilter.php        |   74 +
 .../URIFilter/DisableExternal.php             |   54 +
 .../URIFilter/DisableExternalResources.php    |   25 +
 .../URIFilter/DisableResources.php            |   22 +
 .../HTMLPurifier/URIFilter/HostBlacklist.php  |   46 +
 .../HTMLPurifier/URIFilter/MakeAbsolute.php   |   74 +-
 .../library/HTMLPurifier/URIFilter/Munge.php  |  115 +
 .../HTMLPurifier/URIFilter/SafeIframe.php     |   68 +
 .../library}/HTMLPurifier/URIParser.php       |    9 +-
 .../library/HTMLPurifier/URIScheme.php        |  102 +
 .../library}/HTMLPurifier/URIScheme/data.php  |   58 +-
 .../library/HTMLPurifier/URIScheme/file.php   |   44 +
 .../library}/HTMLPurifier/URIScheme/ftp.php   |   29 +-
 .../library}/HTMLPurifier/URIScheme/http.php  |   26 +-
 .../library}/HTMLPurifier/URIScheme/https.php |   12 +-
 .../HTMLPurifier/URIScheme/mailto.php         |   23 +-
 .../library/HTMLPurifier/URIScheme/news.php   |   35 +
 .../library/HTMLPurifier/URIScheme/nntp.php   |   32 +
 .../HTMLPurifier/URISchemeRegistry.php        |   41 +-
 .../library}/HTMLPurifier/UnitConverter.php   |  117 +-
 .../library/HTMLPurifier/VarParser.php        |  198 +
 .../HTMLPurifier/VarParser/Flexible.php       |   88 +-
 .../HTMLPurifier/VarParser/Native.php         |   18 +-
 .../HTMLPurifier/VarParserException.php       |    0
 .../library/HTMLPurifier/Zipper.php           |  157 +
 library/ezyang/htmlpurifier/package.php       |   61 +
 library/ezyang/htmlpurifier/phpdoc.ini        |  102 +
 library/ezyang/htmlpurifier/plugins/modx.txt  |  112 +
 .../htmlpurifier/plugins/phorum/.gitignore    |    2 +
 .../htmlpurifier/plugins/phorum/Changelog     |   27 +
 .../htmlpurifier/plugins/phorum/INSTALL       |   84 +
 .../ezyang/htmlpurifier/plugins/phorum/README |   45 +
 .../plugins/phorum/config.default.php         |   57 +
 .../plugins/phorum/htmlpurifier.php           |  316 ++
 .../htmlpurifier/plugins/phorum/info.txt      |   18 +
 .../plugins/phorum/init-config.php            |   30 +
 .../plugins/phorum/migrate.bbcode.php         |   31 +
 .../htmlpurifier/plugins/phorum/settings.php  |   64 +
 .../plugins/phorum/settings/form.php          |   95 +
 .../phorum/settings/migrate-sigs-form.php     |   22 +
 .../plugins/phorum/settings/migrate-sigs.php  |   79 +
 .../plugins/phorum/settings/save.php          |   29 +
 .../ezyang/htmlpurifier/release1-update.php   |  110 +
 library/ezyang/htmlpurifier/release2-tag.php  |   22 +
 .../htmlpurifier/test-settings.sample.php     |   76 +
 465 files changed, 22433 insertions(+), 10865 deletions(-)
 delete mode 100644 library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
 delete mode 100644 library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
 delete mode 100644 library/HTMLPurifier/AttrDef/CSS/FontFamily.php
 delete mode 100644 library/HTMLPurifier/AttrDef/CSS/Length.php
 delete mode 100644 library/HTMLPurifier/AttrDef/CSS/ListStyle.php
 delete mode 100644 library/HTMLPurifier/AttrDef/CSS/Percentage.php
 delete mode 100644 library/HTMLPurifier/AttrDef/HTML/Bool.php
 delete mode 100644 library/HTMLPurifier/AttrDef/HTML/Color.php
 delete mode 100644 library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
 delete mode 100644 library/HTMLPurifier/AttrDef/HTML/ID.php
 delete mode 100644 library/HTMLPurifier/AttrDef/HTML/Length.php
 delete mode 100644 library/HTMLPurifier/AttrDef/HTML/MultiLength.php
 delete mode 100644 library/HTMLPurifier/AttrDef/HTML/Pixels.php
 delete mode 100644 library/HTMLPurifier/AttrDef/Text.php
 delete mode 100644 library/HTMLPurifier/AttrDef/URI/Host.php
 delete mode 100644 library/HTMLPurifier/AttrDef/URI/IPv6.php
 delete mode 100644 library/HTMLPurifier/AttrTransform/BoolToCSS.php
 delete mode 100644 library/HTMLPurifier/AttrTransform/EnumToCSS.php
 delete mode 100644 library/HTMLPurifier/AttrTransform/Length.php
 delete mode 100644 library/HTMLPurifier/AttrTransform/Name.php
 delete mode 100644 library/HTMLPurifier/AttrTransform/NameSync.php
 delete mode 100644 library/HTMLPurifier/AttrTransform/SafeObject.php
 delete mode 100644 library/HTMLPurifier/AttrTransform/Textarea.php
 delete mode 100644 library/HTMLPurifier/Bootstrap.php
 delete mode 100644 library/HTMLPurifier/CSSDefinition.php
 delete mode 100644 library/HTMLPurifier/ChildDef/Optional.php
 delete mode 100644 library/HTMLPurifier/ChildDef/Required.php
 delete mode 100644 library/HTMLPurifier/ChildDef/StrictBlockquote.php
 delete mode 100644 library/HTMLPurifier/ChildDef/Table.php
 delete mode 100644 library/HTMLPurifier/Config.php
 delete mode 100644 library/HTMLPurifier/ConfigSchema/ValidatorAtom.php
 delete mode 100644 library/HTMLPurifier/ConfigSchema/schema.ser
 delete mode 100644 library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt
 delete mode 100644 library/HTMLPurifier/Context.php
 delete mode 100644 library/HTMLPurifier/Definition.php
 delete mode 100644 library/HTMLPurifier/DefinitionCache/Decorator.php
 delete mode 100644 library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php
 delete mode 100644 library/HTMLPurifier/DefinitionCache/Decorator/Memory.php
 delete mode 100644 library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in
 delete mode 100644 library/HTMLPurifier/DefinitionCache/Null.php
 delete mode 100644 library/HTMLPurifier/DefinitionCache/Serializer.php
 delete mode 100644 library/HTMLPurifier/EntityLookup/entities.ser
 delete mode 100644 library/HTMLPurifier/Filter/ExtractStyleBlocks.php
 delete mode 100644 library/HTMLPurifier/Filter/YouTube.php
 delete mode 100644 library/HTMLPurifier/HTMLModule/Forms.php
 delete mode 100644 library/HTMLPurifier/HTMLModule/Tidy/Strict.php
 delete mode 100644 library/HTMLPurifier/Injector/RemoveEmpty.php
 delete mode 100644 library/HTMLPurifier/Language/messages/en.php
 delete mode 100644 library/HTMLPurifier/Lexer/PEARSax3.php
 delete mode 100644 library/HTMLPurifier/Lexer/PH5P.php
 delete mode 100644 library/HTMLPurifier/Strategy/FixNesting.php
 delete mode 100644 library/HTMLPurifier/Token.php
 delete mode 100644 library/HTMLPurifier/Token/Comment.php
 delete mode 100644 library/HTMLPurifier/TokenFactory.php
 delete mode 100644 library/HTMLPurifier/URI.php
 delete mode 100644 library/HTMLPurifier/URIFilter.php
 delete mode 100644 library/HTMLPurifier/URIFilter/DisableExternal.php
 delete mode 100644 library/HTMLPurifier/URIFilter/DisableExternalResources.php
 delete mode 100644 library/HTMLPurifier/URIFilter/HostBlacklist.php
 delete mode 100644 library/HTMLPurifier/URIFilter/Munge.php
 delete mode 100644 library/HTMLPurifier/URIScheme.php
 delete mode 100644 library/HTMLPurifier/URIScheme/news.php
 delete mode 100644 library/HTMLPurifier/URIScheme/nntp.php
 delete mode 100644 library/HTMLPurifier/VarParser.php
 create mode 100644 library/ezyang/htmlpurifier/CREDITS
 create mode 100644 library/ezyang/htmlpurifier/INSTALL
 create mode 100644 library/ezyang/htmlpurifier/INSTALL.fr.utf8
 create mode 100644 library/ezyang/htmlpurifier/LICENSE
 create mode 100644 library/ezyang/htmlpurifier/NEWS
 create mode 100644 library/ezyang/htmlpurifier/README
 create mode 100644 library/ezyang/htmlpurifier/TODO
 create mode 100644 library/ezyang/htmlpurifier/VERSION
 create mode 100644 library/ezyang/htmlpurifier/WHATSNEW
 create mode 100644 library/ezyang/htmlpurifier/WYSIWYG
 create mode 100644 library/ezyang/htmlpurifier/composer.json
 create mode 100644 library/ezyang/htmlpurifier/extras/ConfigDoc/HTMLXSLTProcessor.php
 create mode 100644 library/ezyang/htmlpurifier/extras/FSTools.php
 create mode 100644 library/ezyang/htmlpurifier/extras/FSTools/File.php
 create mode 100644 library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.auto.php
 create mode 100644 library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.autoload.php
 create mode 100644 library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.php
 create mode 100644 library/ezyang/htmlpurifier/extras/README
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier.auto.php (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier.autoload.php (70%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier.composer.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier.func.php (67%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier.includes.php (91%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier.kses.php (96%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier.path.php (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier.php (66%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier.safe-includes.php (91%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Arborize.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrCollections.php (74%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef.php (74%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS.php (77%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/Background.php (63%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php (73%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/Border.php (71%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/Color.php (54%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/Composite.php (61%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/Filter.php (62%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/Font.php (67%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php (62%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/Multiple.php (65%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/Number.php (55%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/TextDecoration.php (69%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/CSS/URI.php (58%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/Enum.php (70%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/HTML/Class.php (66%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/HTML/LinkTypes.php (56%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/HTML/Nmtokens.php (55%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/Integer.php (55%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/Lang.php (67%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/Switch.php (62%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/URI.php (53%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/URI/Email.php (73%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php (65%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrDef/URI/IPv4.php (51%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform.php (63%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform/Background.php (55%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform/BdoDir.php (55%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform/BgColor.php (55%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform/Border.php (55%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform/ImgRequired.php (77%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform/ImgSpace.php (60%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform/Input.php (61%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform/Lang.php (68%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Length.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform/SafeEmbed.php (56%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform/SafeParam.php (67%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTransform/ScriptRequired.php (59%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Textarea.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrTypes.php (64%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/AttrValidator.php (74%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ChildDef.php (52%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ChildDef/Chameleon.php (57%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ChildDef/Custom.php (71%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ChildDef/Empty.php (58%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/List.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Config.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema.php (69%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php (86%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/Builder/Xml.php (52%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/Exception.php (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/Interchange.php (76%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/Interchange/Directive.php (65%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/Interchange/Id.php (54%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/InterchangeBuilder.php (67%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/Validator.php (73%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.Predicate.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt (84%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt (62%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.Language.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt (65%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt (54%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt (72%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt (91%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Output.FlashCompat.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt (74%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.Base.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt (64%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.Host.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt (93%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.SafeIframeRegexp.txt
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ConfigSchema/schema/info.ini (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ContentSets.php (76%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Context.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Definition.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/DefinitionCache.php (66%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Null.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/DefinitionCache/Serializer/README (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/DefinitionCacheFactory.php (67%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Doctype.php (77%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/DoctypeRegistry.php (51%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ElementDef.php (69%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Encoder.php (63%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/EntityLookup.php (75%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup/entities.ser
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/EntityParser.php (75%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ErrorCollector.php (82%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/ErrorStruct.php (81%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Exception.php (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Filter.php (71%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Generator.php (56%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLDefinition.php (70%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule.php (71%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Bdo.php (66%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/CommonAttributes.php (89%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Edit.php (71%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Hypertext.php (78%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Image.php (80%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Legacy.php (67%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/List.php (57%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Name.php (65%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Nofollow.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php (79%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Object.php (71%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Presentation.php (52%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Proprietary.php (74%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Ruby.php (77%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/SafeEmbed.php (74%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/SafeObject.php (67%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeScripting.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Scripting.php (76%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/StyleAttribute.php (78%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Tables.php (75%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Target.php (77%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetBlank.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Text.php (58%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Tidy.php (78%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Tidy/Name.php (80%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Tidy/Proprietary.php (85%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Strict.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Tidy/Transitional.php (74%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Tidy/XHTML.php (66%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php (50%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModule/XMLCommonAttributes.php (79%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/HTMLModuleManager.php (75%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/IDAccumulator.php (66%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Injector.php (55%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Injector/AutoParagraph.php (88%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Injector/DisplayLinkURI.php (64%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Injector/Linkify.php (72%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Injector/PurifierLinkify.php (58%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php (74%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Injector/SafeObject.php (78%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Language.php (67%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Language/classes/en-x-test.php (97%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Language/messages/en-x-test.php (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Language/messages/en-x-testmini.php (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/LanguageFactory.php (75%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Length.php (56%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Lexer.php (63%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Lexer/DOMLex.php (58%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Lexer/DirectLex.php (76%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/PH5P.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Node.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Comment.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Element.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Text.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/PercentEncoder.php (78%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Printer.php (54%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Printer/CSSDefinition.php (85%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Printer/ConfigForm.css (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Printer/ConfigForm.js (100%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Printer/ConfigForm.php (60%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Printer/HTMLDefinition.php (53%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/PropertyList.php (50%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/PropertyListIterator.php (60%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Queue.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Strategy.php (66%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Strategy/Composite.php (61%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Strategy/Core.php (92%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/FixNesting.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Strategy/MakeWellFormed.php (52%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Strategy/RemoveForeignElements.php (64%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Strategy/ValidateAttributes.php (65%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/StringHash.php (75%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/StringHashParser.php (73%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/TagTransform.php (62%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/TagTransform/Font.php (71%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/TagTransform/Simple.php (61%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Token.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Comment.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Token/Empty.php (54%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Token/End.php (58%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Token/Start.php (99%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Token/Tag.php (72%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/Token/Text.php (54%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/TokenFactory.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URI.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/URIDefinition.php (70%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternal.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternalResources.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableResources.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/HostBlacklist.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/URIFilter/MakeAbsolute.php (71%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/Munge.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/SafeIframe.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/URIParser.php (94%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/URIScheme/data.php (74%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/file.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/URIScheme/ftp.php (74%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/URIScheme/http.php (50%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/URIScheme/https.php (65%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/URIScheme/mailto.php (63%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/news.php
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/nntp.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/URISchemeRegistry.php (58%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/UnitConverter.php (75%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/VarParser.php
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/VarParser/Flexible.php (56%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/VarParser/Native.php (67%)
 rename library/{ => ezyang/htmlpurifier/library}/HTMLPurifier/VarParserException.php (100%)
 create mode 100644 library/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php
 create mode 100644 library/ezyang/htmlpurifier/package.php
 create mode 100644 library/ezyang/htmlpurifier/phpdoc.ini
 create mode 100644 library/ezyang/htmlpurifier/plugins/modx.txt
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/.gitignore
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/Changelog
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/INSTALL
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/README
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/config.default.php
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/htmlpurifier.php
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/info.txt
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/init-config.php
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/migrate.bbcode.php
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/settings.php
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/settings/form.php
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs-form.php
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs.php
 create mode 100644 library/ezyang/htmlpurifier/plugins/phorum/settings/save.php
 create mode 100644 library/ezyang/htmlpurifier/release1-update.php
 create mode 100644 library/ezyang/htmlpurifier/release2-tag.php
 create mode 100644 library/ezyang/htmlpurifier/test-settings.sample.php

diff --git a/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php b/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
deleted file mode 100644
index 292c040d4b..0000000000
--- a/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-class HTMLPurifier_AttrDef_CSS_AlphaValue extends HTMLPurifier_AttrDef_CSS_Number
-{
-
-    public function __construct() {
-        parent::__construct(false); // opacity is non-negative, but we will clamp it
-    }
-
-    public function validate($number, $config, $context) {
-        $result = parent::validate($number, $config, $context);
-        if ($result === false) return $result;
-        $float = (float) $result;
-        if ($float < 0.0) $result = '0';
-        if ($float > 1.0) $result = '1';
-        return $result;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php b/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
deleted file mode 100644
index 6599c5b2dd..0000000000
--- a/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-
-/**
- * Decorator which enables CSS properties to be disabled for specific elements.
- */
-class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef
-{
-    public $def, $element;
-
-    /**
-     * @param $def Definition to wrap
-     * @param $element Element to deny
-     */
-    public function __construct($def, $element) {
-        $this->def = $def;
-        $this->element = $element;
-    }
-    /**
-     * Checks if CurrentToken is set and equal to $this->element
-     */
-    public function validate($string, $config, $context) {
-        $token = $context->get('CurrentToken', true);
-        if ($token && $token->name == $this->element) return false;
-        return $this->def->validate($string, $config, $context);
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/FontFamily.php b/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
deleted file mode 100644
index 42c2054c2a..0000000000
--- a/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-
-/**
- * Validates a font family list according to CSS spec
- * @todo whitelisting allowed fonts would be nice
- */
-class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
-{
-
-    public function validate($string, $config, $context) {
-        static $generic_names = array(
-            'serif' => true,
-            'sans-serif' => true,
-            'monospace' => true,
-            'fantasy' => true,
-            'cursive' => true
-        );
-
-        // assume that no font names contain commas in them
-        $fonts = explode(',', $string);
-        $final = '';
-        foreach($fonts as $font) {
-            $font = trim($font);
-            if ($font === '') continue;
-            // match a generic name
-            if (isset($generic_names[$font])) {
-                $final .= $font . ', ';
-                continue;
-            }
-            // match a quoted name
-            if ($font[0] === '"' || $font[0] === "'") {
-                $length = strlen($font);
-                if ($length <= 2) continue;
-                $quote = $font[0];
-                if ($font[$length - 1] !== $quote) continue;
-                $font = substr($font, 1, $length - 2);
-            }
-
-            $font = $this->expandCSSEscape($font);
-
-            // $font is a pure representation of the font name
-
-            if (ctype_alnum($font) && $font !== '') {
-                // very simple font, allow it in unharmed
-                $final .= $font . ', ';
-                continue;
-            }
-
-            // bugger out on whitespace.  form feed (0C) really
-            // shouldn't show up regardless
-            $font = str_replace(array("\n", "\t", "\r", "\x0C"), ' ', $font);
-
-            // These ugly transforms don't pose a security
-            // risk (as \\ and \" might).  We could try to be clever and
-            // use single-quote wrapping when there is a double quote
-            // present, but I have choosen not to implement that.
-            // (warning: this code relies on the selection of quotation
-            // mark below)
-            $font = str_replace('\\', '\\5C ', $font);
-            $font = str_replace('"',  '\\22 ', $font);
-
-            // complicated font, requires quoting
-            $final .= "\"$font\", "; // note that this will later get turned into &quot;
-        }
-        $final = rtrim($final, ', ');
-        if ($final === '') return false;
-        return $final;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Length.php b/library/HTMLPurifier/AttrDef/CSS/Length.php
deleted file mode 100644
index a07ec58135..0000000000
--- a/library/HTMLPurifier/AttrDef/CSS/Length.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-/**
- * Represents a Length as defined by CSS.
- */
-class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
-{
-
-    protected $min, $max;
-
-    /**
-     * @param HTMLPurifier_Length $max Minimum length, or null for no bound. String is also acceptable.
-     * @param HTMLPurifier_Length $max Maximum length, or null for no bound. String is also acceptable.
-     */
-    public function __construct($min = null, $max = null) {
-        $this->min = $min !== null ? HTMLPurifier_Length::make($min) : null;
-        $this->max = $max !== null ? HTMLPurifier_Length::make($max) : null;
-    }
-
-    public function validate($string, $config, $context) {
-        $string = $this->parseCDATA($string);
-
-        // Optimizations
-        if ($string === '') return false;
-        if ($string === '0') return '0';
-        if (strlen($string) === 1) return false;
-
-        $length = HTMLPurifier_Length::make($string);
-        if (!$length->isValid()) return false;
-
-        if ($this->min) {
-            $c = $length->compareTo($this->min);
-            if ($c === false) return false;
-            if ($c < 0) return false;
-        }
-        if ($this->max) {
-            $c = $length->compareTo($this->max);
-            if ($c === false) return false;
-            if ($c > 0) return false;
-        }
-
-        return $length->toString();
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/ListStyle.php b/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
deleted file mode 100644
index 4406868c08..0000000000
--- a/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
+++ /dev/null
@@ -1,78 +0,0 @@
-<?php
-
-/**
- * Validates shorthand CSS property list-style.
- * @warning Does not support url tokens that have internal spaces.
- */
-class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
-{
-
-    /**
-     * Local copy of component validators.
-     * @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl.
-     */
-    protected $info;
-
-    public function __construct($config) {
-        $def = $config->getCSSDefinition();
-        $this->info['list-style-type']     = $def->info['list-style-type'];
-        $this->info['list-style-position'] = $def->info['list-style-position'];
-        $this->info['list-style-image'] = $def->info['list-style-image'];
-    }
-
-    public function validate($string, $config, $context) {
-
-        // regular pre-processing
-        $string = $this->parseCDATA($string);
-        if ($string === '') return false;
-
-        // assumes URI doesn't have spaces in it
-        $bits = explode(' ', strtolower($string)); // bits to process
-
-        $caught = array();
-        $caught['type']     = false;
-        $caught['position'] = false;
-        $caught['image']    = false;
-
-        $i = 0; // number of catches
-        $none = false;
-
-        foreach ($bits as $bit) {
-            if ($i >= 3) return; // optimization bit
-            if ($bit === '') continue;
-            foreach ($caught as $key => $status) {
-                if ($status !== false) continue;
-                $r = $this->info['list-style-' . $key]->validate($bit, $config, $context);
-                if ($r === false) continue;
-                if ($r === 'none') {
-                    if ($none) continue;
-                    else $none = true;
-                    if ($key == 'image') continue;
-                }
-                $caught[$key] = $r;
-                $i++;
-                break;
-            }
-        }
-
-        if (!$i) return false;
-
-        $ret = array();
-
-        // construct type
-        if ($caught['type']) $ret[] = $caught['type'];
-
-        // construct image
-        if ($caught['image']) $ret[] = $caught['image'];
-
-        // construct position
-        if ($caught['position']) $ret[] = $caught['position'];
-
-        if (empty($ret)) return false;
-        return implode(' ', $ret);
-
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Percentage.php b/library/HTMLPurifier/AttrDef/CSS/Percentage.php
deleted file mode 100644
index c34b8fc3c3..0000000000
--- a/library/HTMLPurifier/AttrDef/CSS/Percentage.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-
-/**
- * Validates a Percentage as defined by the CSS spec.
- */
-class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
-{
-
-    /**
-     * Instance of HTMLPurifier_AttrDef_CSS_Number to defer number validation
-     */
-    protected $number_def;
-
-    /**
-     * @param Bool indicating whether to forbid negative values
-     */
-    public function __construct($non_negative = false) {
-        $this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
-    }
-
-    public function validate($string, $config, $context) {
-
-        $string = $this->parseCDATA($string);
-
-        if ($string === '') return false;
-        $length = strlen($string);
-        if ($length === 1) return false;
-        if ($string[$length - 1] !== '%') return false;
-
-        $number = substr($string, 0, $length - 1);
-        $number = $this->number_def->validate($number, $config, $context);
-
-        if ($number === false) return false;
-        return "$number%";
-
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/HTML/Bool.php b/library/HTMLPurifier/AttrDef/HTML/Bool.php
deleted file mode 100644
index e06987eb8d..0000000000
--- a/library/HTMLPurifier/AttrDef/HTML/Bool.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-
-/**
- * Validates a boolean attribute
- */
-class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef
-{
-
-    protected $name;
-    public $minimized = true;
-
-    public function __construct($name = false) {$this->name = $name;}
-
-    public function validate($string, $config, $context) {
-        if (empty($string)) return false;
-        return $this->name;
-    }
-
-    /**
-     * @param $string Name of attribute
-     */
-    public function make($string) {
-        return new HTMLPurifier_AttrDef_HTML_Bool($string);
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/HTML/Color.php b/library/HTMLPurifier/AttrDef/HTML/Color.php
deleted file mode 100644
index d01e20454e..0000000000
--- a/library/HTMLPurifier/AttrDef/HTML/Color.php
+++ /dev/null
@@ -1,32 +0,0 @@
-<?php
-
-/**
- * Validates a color according to the HTML spec.
- */
-class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
-{
-
-    public function validate($string, $config, $context) {
-
-        static $colors = null;
-        if ($colors === null) $colors = $config->get('Core.ColorKeywords');
-
-        $string = trim($string);
-
-        if (empty($string)) return false;
-        if (isset($colors[$string])) return $colors[$string];
-        if ($string[0] === '#') $hex = substr($string, 1);
-        else $hex = $string;
-
-        $length = strlen($hex);
-        if ($length !== 3 && $length !== 6) return false;
-        if (!ctype_xdigit($hex)) return false;
-        if ($length === 3) $hex = $hex[0].$hex[0].$hex[1].$hex[1].$hex[2].$hex[2];
-
-        return "#$hex";
-
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php b/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
deleted file mode 100644
index ae6ea7c01d..0000000000
--- a/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-/**
- * Special-case enum attribute definition that lazy loads allowed frame targets
- */
-class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
-{
-
-    public $valid_values = false; // uninitialized value
-    protected $case_sensitive = false;
-
-    public function __construct() {}
-
-    public function validate($string, $config, $context) {
-        if ($this->valid_values === false) $this->valid_values = $config->get('Attr.AllowedFrameTargets');
-        return parent::validate($string, $config, $context);
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/HTML/ID.php b/library/HTMLPurifier/AttrDef/HTML/ID.php
deleted file mode 100644
index 81d03762de..0000000000
--- a/library/HTMLPurifier/AttrDef/HTML/ID.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-
-/**
- * Validates the HTML attribute ID.
- * @warning Even though this is the id processor, it
- *          will ignore the directive Attr:IDBlacklist, since it will only
- *          go according to the ID accumulator. Since the accumulator is
- *          automatically generated, it will have already absorbed the
- *          blacklist. If you're hacking around, make sure you use load()!
- */
-
-class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
-{
-
-    // ref functionality disabled, since we also have to verify
-    // whether or not the ID it refers to exists
-
-    public function validate($id, $config, $context) {
-
-        if (!$config->get('Attr.EnableID')) return false;
-
-        $id = trim($id); // trim it first
-
-        if ($id === '') return false;
-
-        $prefix = $config->get('Attr.IDPrefix');
-        if ($prefix !== '') {
-            $prefix .= $config->get('Attr.IDPrefixLocal');
-            // prevent re-appending the prefix
-            if (strpos($id, $prefix) !== 0) $id = $prefix . $id;
-        } elseif ($config->get('Attr.IDPrefixLocal') !== '') {
-            trigger_error('%Attr.IDPrefixLocal cannot be used unless '.
-                '%Attr.IDPrefix is set', E_USER_WARNING);
-        }
-
-        //if (!$this->ref) {
-            $id_accumulator =& $context->get('IDAccumulator');
-            if (isset($id_accumulator->ids[$id])) return false;
-        //}
-
-        // we purposely avoid using regex, hopefully this is faster
-
-        if (ctype_alpha($id)) {
-            $result = true;
-        } else {
-            if (!ctype_alpha(@$id[0])) return false;
-            $trim = trim( // primitive style of regexps, I suppose
-                $id,
-                'A..Za..z0..9:-._'
-              );
-            $result = ($trim === '');
-        }
-
-        $regexp = $config->get('Attr.IDBlacklistRegexp');
-        if ($regexp && preg_match($regexp, $id)) {
-            return false;
-        }
-
-        if (/*!$this->ref && */$result) $id_accumulator->add($id);
-
-        // if no change was made to the ID, return the result
-        // else, return the new id if stripping whitespace made it
-        //     valid, or return false.
-        return $result ? $id : false;
-
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/HTML/Length.php b/library/HTMLPurifier/AttrDef/HTML/Length.php
deleted file mode 100644
index a242f9c238..0000000000
--- a/library/HTMLPurifier/AttrDef/HTML/Length.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-/**
- * Validates the HTML type length (not to be confused with CSS's length).
- *
- * This accepts integer pixels or percentages as lengths for certain
- * HTML attributes.
- */
-
-class HTMLPurifier_AttrDef_HTML_Length extends HTMLPurifier_AttrDef_HTML_Pixels
-{
-
-    public function validate($string, $config, $context) {
-
-        $string = trim($string);
-        if ($string === '') return false;
-
-        $parent_result = parent::validate($string, $config, $context);
-        if ($parent_result !== false) return $parent_result;
-
-        $length = strlen($string);
-        $last_char = $string[$length - 1];
-
-        if ($last_char !== '%') return false;
-
-        $points = substr($string, 0, $length - 1);
-
-        if (!is_numeric($points)) return false;
-
-        $points = (int) $points;
-
-        if ($points < 0) return '0%';
-        if ($points > 100) return '100%';
-
-        return ((string) $points) . '%';
-
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/HTML/MultiLength.php b/library/HTMLPurifier/AttrDef/HTML/MultiLength.php
deleted file mode 100644
index c72fc76e4d..0000000000
--- a/library/HTMLPurifier/AttrDef/HTML/MultiLength.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-/**
- * Validates a MultiLength as defined by the HTML spec.
- *
- * A multilength is either a integer (pixel count), a percentage, or
- * a relative number.
- */
-class HTMLPurifier_AttrDef_HTML_MultiLength extends HTMLPurifier_AttrDef_HTML_Length
-{
-
-    public function validate($string, $config, $context) {
-
-        $string = trim($string);
-        if ($string === '') return false;
-
-        $parent_result = parent::validate($string, $config, $context);
-        if ($parent_result !== false) return $parent_result;
-
-        $length = strlen($string);
-        $last_char = $string[$length - 1];
-
-        if ($last_char !== '*') return false;
-
-        $int = substr($string, 0, $length - 1);
-
-        if ($int == '') return '*';
-        if (!is_numeric($int)) return false;
-
-        $int = (int) $int;
-
-        if ($int < 0) return false;
-        if ($int == 0) return '0';
-        if ($int == 1) return '*';
-        return ((string) $int) . '*';
-
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/HTML/Pixels.php b/library/HTMLPurifier/AttrDef/HTML/Pixels.php
deleted file mode 100644
index 4cb2c1b857..0000000000
--- a/library/HTMLPurifier/AttrDef/HTML/Pixels.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-
-/**
- * Validates an integer representation of pixels according to the HTML spec.
- */
-class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
-{
-
-    protected $max;
-
-    public function __construct($max = null) {
-        $this->max = $max;
-    }
-
-    public function validate($string, $config, $context) {
-
-        $string = trim($string);
-        if ($string === '0') return $string;
-        if ($string === '')  return false;
-        $length = strlen($string);
-        if (substr($string, $length - 2) == 'px') {
-            $string = substr($string, 0, $length - 2);
-        }
-        if (!is_numeric($string)) return false;
-        $int = (int) $string;
-
-        if ($int < 0) return '0';
-
-        // upper-bound value, extremely high values can
-        // crash operating systems, see <http://ha.ckers.org/imagecrash.html>
-        // WARNING, above link WILL crash you if you're using Windows
-
-        if ($this->max !== null && $int > $this->max) return (string) $this->max;
-
-        return (string) $int;
-
-    }
-
-    public function make($string) {
-        if ($string === '') $max = null;
-        else $max = (int) $string;
-        $class = get_class($this);
-        return new $class($max);
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/Text.php b/library/HTMLPurifier/AttrDef/Text.php
deleted file mode 100644
index c6216cc531..0000000000
--- a/library/HTMLPurifier/AttrDef/Text.php
+++ /dev/null
@@ -1,15 +0,0 @@
-<?php
-
-/**
- * Validates arbitrary text according to the HTML spec.
- */
-class HTMLPurifier_AttrDef_Text extends HTMLPurifier_AttrDef
-{
-
-    public function validate($string, $config, $context) {
-        return $this->parseCDATA($string);
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/URI/Host.php b/library/HTMLPurifier/AttrDef/URI/Host.php
deleted file mode 100644
index 2156c10c66..0000000000
--- a/library/HTMLPurifier/AttrDef/URI/Host.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-/**
- * Validates a host according to the IPv4, IPv6 and DNS (future) specifications.
- */
-class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
-{
-
-    /**
-     * Instance of HTMLPurifier_AttrDef_URI_IPv4 sub-validator
-     */
-    protected $ipv4;
-
-    /**
-     * Instance of HTMLPurifier_AttrDef_URI_IPv6 sub-validator
-     */
-    protected $ipv6;
-
-    public function __construct() {
-        $this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4();
-        $this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6();
-    }
-
-    public function validate($string, $config, $context) {
-        $length = strlen($string);
-        if ($string === '') return '';
-        if ($length > 1 && $string[0] === '[' && $string[$length-1] === ']') {
-            //IPv6
-            $ip = substr($string, 1, $length - 2);
-            $valid = $this->ipv6->validate($ip, $config, $context);
-            if ($valid === false) return false;
-            return '['. $valid . ']';
-        }
-
-        // need to do checks on unusual encodings too
-        $ipv4 = $this->ipv4->validate($string, $config, $context);
-        if ($ipv4 !== false) return $ipv4;
-
-        // A regular domain name.
-
-        // This breaks I18N domain names, but we don't have proper IRI support,
-        // so force users to insert Punycode. If there's complaining we'll
-        // try to fix things into an international friendly form.
-
-        // The productions describing this are:
-        $a   = '[a-z]';     // alpha
-        $an  = '[a-z0-9]';  // alphanum
-        $and = '[a-z0-9-]'; // alphanum | "-"
-        // domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
-        $domainlabel   = "$an($and*$an)?";
-        // toplabel    = alpha | alpha *( alphanum | "-" ) alphanum
-        $toplabel      = "$a($and*$an)?";
-        // hostname    = *( domainlabel "." ) toplabel [ "." ]
-        $match = preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string);
-        if (!$match) return false;
-
-        return $string;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/URI/IPv6.php b/library/HTMLPurifier/AttrDef/URI/IPv6.php
deleted file mode 100644
index 9454e9be50..0000000000
--- a/library/HTMLPurifier/AttrDef/URI/IPv6.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-
-/**
- * Validates an IPv6 address.
- * @author Feyd @ forums.devnetwork.net (public domain)
- * @note This function requires brackets to have been removed from address
- *       in URI.
- */
-class HTMLPurifier_AttrDef_URI_IPv6 extends HTMLPurifier_AttrDef_URI_IPv4
-{
-
-    public function validate($aIP, $config, $context) {
-
-        if (!$this->ip4) $this->_loadRegex();
-
-        $original = $aIP;
-
-        $hex = '[0-9a-fA-F]';
-        $blk = '(?:' . $hex . '{1,4})';
-        $pre = '(?:/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))';   // /0 - /128
-
-        //      prefix check
-        if (strpos($aIP, '/') !== false)
-        {
-                if (preg_match('#' . $pre . '$#s', $aIP, $find))
-                {
-                        $aIP = substr($aIP, 0, 0-strlen($find[0]));
-                        unset($find);
-                }
-                else
-                {
-                        return false;
-                }
-        }
-
-        //      IPv4-compatiblity check
-        if (preg_match('#(?<=:'.')' . $this->ip4 . '$#s', $aIP, $find))
-        {
-                $aIP = substr($aIP, 0, 0-strlen($find[0]));
-                $ip = explode('.', $find[0]);
-                $ip = array_map('dechex', $ip);
-                $aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3];
-                unset($find, $ip);
-        }
-
-        //      compression check
-        $aIP = explode('::', $aIP);
-        $c = count($aIP);
-        if ($c > 2)
-        {
-                return false;
-        }
-        elseif ($c == 2)
-        {
-                list($first, $second) = $aIP;
-                $first = explode(':', $first);
-                $second = explode(':', $second);
-
-                if (count($first) + count($second) > 8)
-                {
-                        return false;
-                }
-
-                while(count($first) < 8)
-                {
-                        array_push($first, '0');
-                }
-
-                array_splice($first, 8 - count($second), 8, $second);
-                $aIP = $first;
-                unset($first,$second);
-        }
-        else
-        {
-                $aIP = explode(':', $aIP[0]);
-        }
-        $c = count($aIP);
-
-        if ($c != 8)
-        {
-                return false;
-        }
-
-        //      All the pieces should be 16-bit hex strings. Are they?
-        foreach ($aIP as $piece)
-        {
-                if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece)))
-                {
-                        return false;
-                }
-        }
-
-        return $original;
-
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/BoolToCSS.php b/library/HTMLPurifier/AttrTransform/BoolToCSS.php
deleted file mode 100644
index 51159b6715..0000000000
--- a/library/HTMLPurifier/AttrTransform/BoolToCSS.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-/**
- * Pre-transform that changes converts a boolean attribute to fixed CSS
- */
-class HTMLPurifier_AttrTransform_BoolToCSS extends HTMLPurifier_AttrTransform {
-
-    /**
-     * Name of boolean attribute that is trigger
-     */
-    protected $attr;
-
-    /**
-     * CSS declarations to add to style, needs trailing semicolon
-     */
-    protected $css;
-
-    /**
-     * @param $attr string attribute name to convert from
-     * @param $css string CSS declarations to add to style (needs semicolon)
-     */
-    public function __construct($attr, $css) {
-        $this->attr = $attr;
-        $this->css  = $css;
-    }
-
-    public function transform($attr, $config, $context) {
-        if (!isset($attr[$this->attr])) return $attr;
-        unset($attr[$this->attr]);
-        $this->prependCSS($attr, $this->css);
-        return $attr;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/EnumToCSS.php b/library/HTMLPurifier/AttrTransform/EnumToCSS.php
deleted file mode 100644
index 2a5b4514ab..0000000000
--- a/library/HTMLPurifier/AttrTransform/EnumToCSS.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-/**
- * Generic pre-transform that converts an attribute with a fixed number of
- * values (enumerated) to CSS.
- */
-class HTMLPurifier_AttrTransform_EnumToCSS extends HTMLPurifier_AttrTransform {
-
-    /**
-     * Name of attribute to transform from
-     */
-    protected $attr;
-
-    /**
-     * Lookup array of attribute values to CSS
-     */
-    protected $enumToCSS = array();
-
-    /**
-     * Case sensitivity of the matching
-     * @warning Currently can only be guaranteed to work with ASCII
-     *          values.
-     */
-    protected $caseSensitive = false;
-
-    /**
-     * @param $attr String attribute name to transform from
-     * @param $enumToCSS Lookup array of attribute values to CSS
-     * @param $case_sensitive Boolean case sensitivity indicator, default false
-     */
-    public function __construct($attr, $enum_to_css, $case_sensitive = false) {
-        $this->attr = $attr;
-        $this->enumToCSS = $enum_to_css;
-        $this->caseSensitive = (bool) $case_sensitive;
-    }
-
-    public function transform($attr, $config, $context) {
-
-        if (!isset($attr[$this->attr])) return $attr;
-
-        $value = trim($attr[$this->attr]);
-        unset($attr[$this->attr]);
-
-        if (!$this->caseSensitive) $value = strtolower($value);
-
-        if (!isset($this->enumToCSS[$value])) {
-            return $attr;
-        }
-
-        $this->prependCSS($attr, $this->enumToCSS[$value]);
-
-        return $attr;
-
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/Length.php b/library/HTMLPurifier/AttrTransform/Length.php
deleted file mode 100644
index ea2f30473d..0000000000
--- a/library/HTMLPurifier/AttrTransform/Length.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-/**
- * Class for handling width/height length attribute transformations to CSS
- */
-class HTMLPurifier_AttrTransform_Length extends HTMLPurifier_AttrTransform
-{
-
-    protected $name;
-    protected $cssName;
-
-    public function __construct($name, $css_name = null) {
-        $this->name = $name;
-        $this->cssName = $css_name ? $css_name : $name;
-    }
-
-    public function transform($attr, $config, $context) {
-        if (!isset($attr[$this->name])) return $attr;
-        $length = $this->confiscateAttr($attr, $this->name);
-        if(ctype_digit($length)) $length .= 'px';
-        $this->prependCSS($attr, $this->cssName . ":$length;");
-        return $attr;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/Name.php b/library/HTMLPurifier/AttrTransform/Name.php
deleted file mode 100644
index 15315bc735..0000000000
--- a/library/HTMLPurifier/AttrTransform/Name.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-/**
- * Pre-transform that changes deprecated name attribute to ID if necessary
- */
-class HTMLPurifier_AttrTransform_Name extends HTMLPurifier_AttrTransform
-{
-
-    public function transform($attr, $config, $context) {
-        // Abort early if we're using relaxed definition of name
-        if ($config->get('HTML.Attr.Name.UseCDATA')) return $attr;
-        if (!isset($attr['name'])) return $attr;
-        $id = $this->confiscateAttr($attr, 'name');
-        if ( isset($attr['id']))   return $attr;
-        $attr['id'] = $id;
-        return $attr;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/NameSync.php b/library/HTMLPurifier/AttrTransform/NameSync.php
deleted file mode 100644
index a95638c140..0000000000
--- a/library/HTMLPurifier/AttrTransform/NameSync.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php
-
-/**
- * Post-transform that performs validation to the name attribute; if
- * it is present with an equivalent id attribute, it is passed through;
- * otherwise validation is performed.
- */
-class HTMLPurifier_AttrTransform_NameSync extends HTMLPurifier_AttrTransform
-{
-
-    public function __construct() {
-        $this->idDef = new HTMLPurifier_AttrDef_HTML_ID();
-    }
-
-    public function transform($attr, $config, $context) {
-        if (!isset($attr['name'])) return $attr;
-        $name = $attr['name'];
-        if (isset($attr['id']) && $attr['id'] === $name) return $attr;
-        $result = $this->idDef->validate($name, $config, $context);
-        if ($result === false) unset($attr['name']);
-        else $attr['name'] = $result;
-        return $attr;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/SafeObject.php b/library/HTMLPurifier/AttrTransform/SafeObject.php
deleted file mode 100644
index 1ed74898ba..0000000000
--- a/library/HTMLPurifier/AttrTransform/SafeObject.php
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php
-
-/**
- * Writes default type for all objects. Currently only supports flash.
- */
-class HTMLPurifier_AttrTransform_SafeObject extends HTMLPurifier_AttrTransform
-{
-    public $name = "SafeObject";
-
-    function transform($attr, $config, $context) {
-        if (!isset($attr['type'])) $attr['type'] = 'application/x-shockwave-flash';
-        return $attr;
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/Textarea.php b/library/HTMLPurifier/AttrTransform/Textarea.php
deleted file mode 100644
index 81ac3488ba..0000000000
--- a/library/HTMLPurifier/AttrTransform/Textarea.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php
-
-/**
- * Sets height/width defaults for <textarea>
- */
-class HTMLPurifier_AttrTransform_Textarea extends HTMLPurifier_AttrTransform
-{
-
-    public function transform($attr, $config, $context) {
-        // Calculated from Firefox
-        if (!isset($attr['cols'])) $attr['cols'] = '22';
-        if (!isset($attr['rows'])) $attr['rows'] = '3';
-        return $attr;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Bootstrap.php b/library/HTMLPurifier/Bootstrap.php
deleted file mode 100644
index 559f61a232..0000000000
--- a/library/HTMLPurifier/Bootstrap.php
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-
-// constants are slow, so we use as few as possible
-if (!defined('HTMLPURIFIER_PREFIX')) {
-    define('HTMLPURIFIER_PREFIX', realpath(dirname(__FILE__) . '/..'));
-}
-
-// accomodations for versions earlier than 5.0.2
-// borrowed from PHP_Compat, LGPL licensed, by Aidan Lister <aidan@php.net>
-if (!defined('PHP_EOL')) {
-    switch (strtoupper(substr(PHP_OS, 0, 3))) {
-        case 'WIN':
-            define('PHP_EOL', "\r\n");
-            break;
-        case 'DAR':
-            define('PHP_EOL', "\r");
-            break;
-        default:
-            define('PHP_EOL', "\n");
-    }
-}
-
-/**
- * Bootstrap class that contains meta-functionality for HTML Purifier such as
- * the autoload function.
- *
- * @note
- *      This class may be used without any other files from HTML Purifier.
- */
-class HTMLPurifier_Bootstrap
-{
-
-    /**
-     * Autoload function for HTML Purifier
-     * @param $class Class to load
-     */
-    public static function autoload($class) {
-        $file = HTMLPurifier_Bootstrap::getPath($class);
-        if (!$file) return false;
-        require HTMLPURIFIER_PREFIX . '/' . $file;
-        return true;
-    }
-
-    /**
-     * Returns the path for a specific class.
-     */
-    public static function getPath($class) {
-        if (strncmp('HTMLPurifier', $class, 12) !== 0) return false;
-        // Custom implementations
-        if (strncmp('HTMLPurifier_Language_', $class, 22) === 0) {
-            $code = str_replace('_', '-', substr($class, 22));
-            $file = 'HTMLPurifier/Language/classes/' . $code . '.php';
-        } else {
-            $file = str_replace('_', '/', $class) . '.php';
-        }
-        if (!file_exists(HTMLPURIFIER_PREFIX . '/' . $file)) return false;
-        return $file;
-    }
-
-    /**
-     * "Pre-registers" our autoloader on the SPL stack.
-     */
-    public static function registerAutoload() {
-        $autoload = array('HTMLPurifier_Bootstrap', 'autoload');
-        if ( ($funcs = spl_autoload_functions()) === false ) {
-            spl_autoload_register($autoload);
-        } elseif (function_exists('spl_autoload_unregister')) {
-            $compat = version_compare(PHP_VERSION, '5.1.2', '<=') &&
-                      version_compare(PHP_VERSION, '5.1.0', '>=');
-            foreach ($funcs as $func) {
-                if (is_array($func)) {
-                    // :TRICKY: There are some compatibility issues and some
-                    // places where we need to error out
-                    $reflector = new ReflectionMethod($func[0], $func[1]);
-                    if (!$reflector->isStatic()) {
-                        throw new Exception('
-                            HTML Purifier autoloader registrar is not compatible
-                            with non-static object methods due to PHP Bug #44144;
-                            Please do not use HTMLPurifier.autoload.php (or any
-                            file that includes this file); instead, place the code:
-                            spl_autoload_register(array(\'HTMLPurifier_Bootstrap\', \'autoload\'))
-                            after your own autoloaders.
-                        ');
-                    }
-                    // Suprisingly, spl_autoload_register supports the
-                    // Class::staticMethod callback format, although call_user_func doesn't
-                    if ($compat) $func = implode('::', $func);
-                }
-                spl_autoload_unregister($func);
-            }
-            spl_autoload_register($autoload);
-            foreach ($funcs as $func) spl_autoload_register($func);
-        }
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/CSSDefinition.php b/library/HTMLPurifier/CSSDefinition.php
deleted file mode 100644
index 6a2e6f56d9..0000000000
--- a/library/HTMLPurifier/CSSDefinition.php
+++ /dev/null
@@ -1,292 +0,0 @@
-<?php
-
-/**
- * Defines allowed CSS attributes and what their values are.
- * @see HTMLPurifier_HTMLDefinition
- */
-class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
-{
-
-    public $type = 'CSS';
-
-    /**
-     * Assoc array of attribute name to definition object.
-     */
-    public $info = array();
-
-    /**
-     * Constructs the info array.  The meat of this class.
-     */
-    protected function doSetup($config) {
-
-        $this->info['text-align'] = new HTMLPurifier_AttrDef_Enum(
-            array('left', 'right', 'center', 'justify'), false);
-
-        $border_style =
-        $this->info['border-bottom-style'] =
-        $this->info['border-right-style'] =
-        $this->info['border-left-style'] =
-        $this->info['border-top-style'] =  new HTMLPurifier_AttrDef_Enum(
-            array('none', 'hidden', 'dotted', 'dashed', 'solid', 'double',
-            'groove', 'ridge', 'inset', 'outset'), false);
-
-        $this->info['border-style'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_style);
-
-        $this->info['clear'] = new HTMLPurifier_AttrDef_Enum(
-            array('none', 'left', 'right', 'both'), false);
-        $this->info['float'] = new HTMLPurifier_AttrDef_Enum(
-            array('none', 'left', 'right'), false);
-        $this->info['font-style'] = new HTMLPurifier_AttrDef_Enum(
-            array('normal', 'italic', 'oblique'), false);
-        $this->info['font-variant'] = new HTMLPurifier_AttrDef_Enum(
-            array('normal', 'small-caps'), false);
-
-        $uri_or_none = new HTMLPurifier_AttrDef_CSS_Composite(
-            array(
-                new HTMLPurifier_AttrDef_Enum(array('none')),
-                new HTMLPurifier_AttrDef_CSS_URI()
-            )
-        );
-
-        $this->info['list-style-position'] = new HTMLPurifier_AttrDef_Enum(
-            array('inside', 'outside'), false);
-        $this->info['list-style-type'] = new HTMLPurifier_AttrDef_Enum(
-            array('disc', 'circle', 'square', 'decimal', 'lower-roman',
-            'upper-roman', 'lower-alpha', 'upper-alpha', 'none'), false);
-        $this->info['list-style-image'] = $uri_or_none;
-
-        $this->info['list-style'] = new HTMLPurifier_AttrDef_CSS_ListStyle($config);
-
-        $this->info['text-transform'] = new HTMLPurifier_AttrDef_Enum(
-            array('capitalize', 'uppercase', 'lowercase', 'none'), false);
-        $this->info['color'] = new HTMLPurifier_AttrDef_CSS_Color();
-
-        $this->info['background-image'] = $uri_or_none;
-        $this->info['background-repeat'] = new HTMLPurifier_AttrDef_Enum(
-            array('repeat', 'repeat-x', 'repeat-y', 'no-repeat')
-        );
-        $this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum(
-            array('scroll', 'fixed')
-        );
-        $this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_BackgroundPosition();
-
-        $border_color =
-        $this->info['border-top-color'] =
-        $this->info['border-bottom-color'] =
-        $this->info['border-left-color'] =
-        $this->info['border-right-color'] =
-        $this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
-            new HTMLPurifier_AttrDef_Enum(array('transparent')),
-            new HTMLPurifier_AttrDef_CSS_Color()
-        ));
-
-        $this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($config);
-
-        $this->info['border-color'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_color);
-
-        $border_width =
-        $this->info['border-top-width'] =
-        $this->info['border-bottom-width'] =
-        $this->info['border-left-width'] =
-        $this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
-            new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick')),
-            new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative
-        ));
-
-        $this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width);
-
-        $this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
-            new HTMLPurifier_AttrDef_Enum(array('normal')),
-            new HTMLPurifier_AttrDef_CSS_Length()
-        ));
-
-        $this->info['word-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
-            new HTMLPurifier_AttrDef_Enum(array('normal')),
-            new HTMLPurifier_AttrDef_CSS_Length()
-        ));
-
-        $this->info['font-size'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
-            new HTMLPurifier_AttrDef_Enum(array('xx-small', 'x-small',
-                'small', 'medium', 'large', 'x-large', 'xx-large',
-                'larger', 'smaller')),
-            new HTMLPurifier_AttrDef_CSS_Percentage(),
-            new HTMLPurifier_AttrDef_CSS_Length()
-        ));
-
-        $this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
-            new HTMLPurifier_AttrDef_Enum(array('normal')),
-            new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives
-            new HTMLPurifier_AttrDef_CSS_Length('0'),
-            new HTMLPurifier_AttrDef_CSS_Percentage(true)
-        ));
-
-        $margin =
-        $this->info['margin-top'] =
-        $this->info['margin-bottom'] =
-        $this->info['margin-left'] =
-        $this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
-            new HTMLPurifier_AttrDef_CSS_Length(),
-            new HTMLPurifier_AttrDef_CSS_Percentage(),
-            new HTMLPurifier_AttrDef_Enum(array('auto'))
-        ));
-
-        $this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin);
-
-        // non-negative
-        $padding =
-        $this->info['padding-top'] =
-        $this->info['padding-bottom'] =
-        $this->info['padding-left'] =
-        $this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
-            new HTMLPurifier_AttrDef_CSS_Length('0'),
-            new HTMLPurifier_AttrDef_CSS_Percentage(true)
-        ));
-
-        $this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding);
-
-        $this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
-            new HTMLPurifier_AttrDef_CSS_Length(),
-            new HTMLPurifier_AttrDef_CSS_Percentage()
-        ));
-
-        $trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite(array(
-            new HTMLPurifier_AttrDef_CSS_Length('0'),
-            new HTMLPurifier_AttrDef_CSS_Percentage(true),
-            new HTMLPurifier_AttrDef_Enum(array('auto'))
-        ));
-        $max = $config->get('CSS.MaxImgLength');
-
-        $this->info['width'] =
-        $this->info['height'] =
-            $max === null ?
-            $trusted_wh :
-            new HTMLPurifier_AttrDef_Switch('img',
-                // For img tags:
-                new HTMLPurifier_AttrDef_CSS_Composite(array(
-                    new HTMLPurifier_AttrDef_CSS_Length('0', $max),
-                    new HTMLPurifier_AttrDef_Enum(array('auto'))
-                )),
-                // For everyone else:
-                $trusted_wh
-            );
-
-        $this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration();
-
-        $this->info['font-family'] = new HTMLPurifier_AttrDef_CSS_FontFamily();
-
-        // this could use specialized code
-        $this->info['font-weight'] = new HTMLPurifier_AttrDef_Enum(
-            array('normal', 'bold', 'bolder', 'lighter', '100', '200', '300',
-            '400', '500', '600', '700', '800', '900'), false);
-
-        // MUST be called after other font properties, as it references
-        // a CSSDefinition object
-        $this->info['font'] = new HTMLPurifier_AttrDef_CSS_Font($config);
-
-        // same here
-        $this->info['border'] =
-        $this->info['border-bottom'] =
-        $this->info['border-top'] =
-        $this->info['border-left'] =
-        $this->info['border-right'] = new HTMLPurifier_AttrDef_CSS_Border($config);
-
-        $this->info['border-collapse'] = new HTMLPurifier_AttrDef_Enum(array(
-            'collapse', 'separate'));
-
-        $this->info['caption-side'] = new HTMLPurifier_AttrDef_Enum(array(
-            'top', 'bottom'));
-
-        $this->info['table-layout'] = new HTMLPurifier_AttrDef_Enum(array(
-            'auto', 'fixed'));
-
-        $this->info['vertical-align'] = new HTMLPurifier_AttrDef_CSS_Composite(array(
-            new HTMLPurifier_AttrDef_Enum(array('baseline', 'sub', 'super',
-                'top', 'text-top', 'middle', 'bottom', 'text-bottom')),
-            new HTMLPurifier_AttrDef_CSS_Length(),
-            new HTMLPurifier_AttrDef_CSS_Percentage()
-        ));
-
-        $this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2);
-
-        // partial support
-        $this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(array('nowrap'));
-
-        if ($config->get('CSS.Proprietary')) {
-            $this->doSetupProprietary($config);
-        }
-
-        if ($config->get('CSS.AllowTricky')) {
-            $this->doSetupTricky($config);
-        }
-
-        $allow_important = $config->get('CSS.AllowImportant');
-        // wrap all attr-defs with decorator that handles !important
-        foreach ($this->info as $k => $v) {
-            $this->info[$k] = new HTMLPurifier_AttrDef_CSS_ImportantDecorator($v, $allow_important);
-        }
-
-        $this->setupConfigStuff($config);
-    }
-
-    protected function doSetupProprietary($config) {
-        // Internet Explorer only scrollbar colors
-        $this->info['scrollbar-arrow-color']        = new HTMLPurifier_AttrDef_CSS_Color();
-        $this->info['scrollbar-base-color']         = new HTMLPurifier_AttrDef_CSS_Color();
-        $this->info['scrollbar-darkshadow-color']   = new HTMLPurifier_AttrDef_CSS_Color();
-        $this->info['scrollbar-face-color']         = new HTMLPurifier_AttrDef_CSS_Color();
-        $this->info['scrollbar-highlight-color']    = new HTMLPurifier_AttrDef_CSS_Color();
-        $this->info['scrollbar-shadow-color']       = new HTMLPurifier_AttrDef_CSS_Color();
-
-        // technically not proprietary, but CSS3, and no one supports it
-        $this->info['opacity']          = new HTMLPurifier_AttrDef_CSS_AlphaValue();
-        $this->info['-moz-opacity']     = new HTMLPurifier_AttrDef_CSS_AlphaValue();
-        $this->info['-khtml-opacity']   = new HTMLPurifier_AttrDef_CSS_AlphaValue();
-
-        // only opacity, for now
-        $this->info['filter'] = new HTMLPurifier_AttrDef_CSS_Filter();
-
-    }
-
-    protected function doSetupTricky($config) {
-        $this->info['display'] = new HTMLPurifier_AttrDef_Enum(array(
-            'inline', 'block', 'list-item', 'run-in', 'compact',
-            'marker', 'table', 'inline-table', 'table-row-group',
-            'table-header-group', 'table-footer-group', 'table-row',
-            'table-column-group', 'table-column', 'table-cell', 'table-caption', 'none'
-        ));
-        $this->info['visibility'] = new HTMLPurifier_AttrDef_Enum(array(
-            'visible', 'hidden', 'collapse'
-        ));
-        $this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(array('visible', 'hidden', 'auto', 'scroll'));
-    }
-
-
-    /**
-     * Performs extra config-based processing. Based off of
-     * HTMLPurifier_HTMLDefinition.
-     * @todo Refactor duplicate elements into common class (probably using
-     *       composition, not inheritance).
-     */
-    protected function setupConfigStuff($config) {
-
-        // setup allowed elements
-        $support = "(for information on implementing this, see the ".
-                   "support forums) ";
-        $allowed_attributes = $config->get('CSS.AllowedProperties');
-        if ($allowed_attributes !== null) {
-            foreach ($this->info as $name => $d) {
-                if(!isset($allowed_attributes[$name])) unset($this->info[$name]);
-                unset($allowed_attributes[$name]);
-            }
-            // emit errors
-            foreach ($allowed_attributes as $name => $d) {
-                // :TODO: Is this htmlspecialchars() call really necessary?
-                $name = htmlspecialchars($name);
-                trigger_error("Style attribute '$name' is not supported $support", E_USER_WARNING);
-            }
-        }
-
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ChildDef/Optional.php b/library/HTMLPurifier/ChildDef/Optional.php
deleted file mode 100644
index 32bcb9898e..0000000000
--- a/library/HTMLPurifier/ChildDef/Optional.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-
-/**
- * Definition that allows a set of elements, and allows no children.
- * @note This is a hack to reuse code from HTMLPurifier_ChildDef_Required,
- *       really, one shouldn't inherit from the other.  Only altered behavior
- *       is to overload a returned false with an array.  Thus, it will never
- *       return false.
- */
-class HTMLPurifier_ChildDef_Optional extends HTMLPurifier_ChildDef_Required
-{
-    public $allow_empty = true;
-    public $type = 'optional';
-    public function validateChildren($tokens_of_children, $config, $context) {
-        $result = parent::validateChildren($tokens_of_children, $config, $context);
-        // we assume that $tokens_of_children is not modified
-        if ($result === false) {
-            if (empty($tokens_of_children)) return true;
-            elseif ($this->whitespace) return $tokens_of_children;
-            else return array();
-        }
-        return $result;
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ChildDef/Required.php b/library/HTMLPurifier/ChildDef/Required.php
deleted file mode 100644
index 4889f249b8..0000000000
--- a/library/HTMLPurifier/ChildDef/Required.php
+++ /dev/null
@@ -1,117 +0,0 @@
-<?php
-
-/**
- * Definition that allows a set of elements, but disallows empty children.
- */
-class HTMLPurifier_ChildDef_Required extends HTMLPurifier_ChildDef
-{
-    /**
-     * Lookup table of allowed elements.
-     * @public
-     */
-    public $elements = array();
-    /**
-     * Whether or not the last passed node was all whitespace.
-     */
-    protected $whitespace = false;
-    /**
-     * @param $elements List of allowed element names (lowercase).
-     */
-    public function __construct($elements) {
-        if (is_string($elements)) {
-            $elements = str_replace(' ', '', $elements);
-            $elements = explode('|', $elements);
-        }
-        $keys = array_keys($elements);
-        if ($keys == array_keys($keys)) {
-            $elements = array_flip($elements);
-            foreach ($elements as $i => $x) {
-                $elements[$i] = true;
-                if (empty($i)) unset($elements[$i]); // remove blank
-            }
-        }
-        $this->elements = $elements;
-    }
-    public $allow_empty = false;
-    public $type = 'required';
-    public function validateChildren($tokens_of_children, $config, $context) {
-        // Flag for subclasses
-        $this->whitespace = false;
-
-        // if there are no tokens, delete parent node
-        if (empty($tokens_of_children)) return false;
-
-        // the new set of children
-        $result = array();
-
-        // current depth into the nest
-        $nesting = 0;
-
-        // whether or not we're deleting a node
-        $is_deleting = false;
-
-        // whether or not parsed character data is allowed
-        // this controls whether or not we silently drop a tag
-        // or generate escaped HTML from it
-        $pcdata_allowed = isset($this->elements['#PCDATA']);
-
-        // a little sanity check to make sure it's not ALL whitespace
-        $all_whitespace = true;
-
-        // some configuration
-        $escape_invalid_children = $config->get('Core.EscapeInvalidChildren');
-
-        // generator
-        $gen = new HTMLPurifier_Generator($config, $context);
-
-        foreach ($tokens_of_children as $token) {
-            if (!empty($token->is_whitespace)) {
-                $result[] = $token;
-                continue;
-            }
-            $all_whitespace = false; // phew, we're not talking about whitespace
-
-            $is_child = ($nesting == 0);
-
-            if ($token instanceof HTMLPurifier_Token_Start) {
-                $nesting++;
-            } elseif ($token instanceof HTMLPurifier_Token_End) {
-                $nesting--;
-            }
-
-            if ($is_child) {
-                $is_deleting = false;
-                if (!isset($this->elements[$token->name])) {
-                    $is_deleting = true;
-                    if ($pcdata_allowed && $token instanceof HTMLPurifier_Token_Text) {
-                        $result[] = $token;
-                    } elseif ($pcdata_allowed && $escape_invalid_children) {
-                        $result[] = new HTMLPurifier_Token_Text(
-                            $gen->generateFromToken($token)
-                        );
-                    }
-                    continue;
-                }
-            }
-            if (!$is_deleting || ($pcdata_allowed && $token instanceof HTMLPurifier_Token_Text)) {
-                $result[] = $token;
-            } elseif ($pcdata_allowed && $escape_invalid_children) {
-                $result[] =
-                    new HTMLPurifier_Token_Text(
-                        $gen->generateFromToken($token)
-                    );
-            } else {
-                // drop silently
-            }
-        }
-        if (empty($result)) return false;
-        if ($all_whitespace) {
-            $this->whitespace = true;
-            return false;
-        }
-        if ($tokens_of_children == $result) return true;
-        return $result;
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ChildDef/StrictBlockquote.php b/library/HTMLPurifier/ChildDef/StrictBlockquote.php
deleted file mode 100644
index dfae8a6e5e..0000000000
--- a/library/HTMLPurifier/ChildDef/StrictBlockquote.php
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php
-
-/**
- * Takes the contents of blockquote when in strict and reformats for validation.
- */
-class HTMLPurifier_ChildDef_StrictBlockquote extends HTMLPurifier_ChildDef_Required
-{
-    protected $real_elements;
-    protected $fake_elements;
-    public $allow_empty = true;
-    public $type = 'strictblockquote';
-    protected $init = false;
-
-    /**
-     * @note We don't want MakeWellFormed to auto-close inline elements since
-     *       they might be allowed.
-     */
-    public function getAllowedElements($config) {
-        $this->init($config);
-        return $this->fake_elements;
-    }
-
-    public function validateChildren($tokens_of_children, $config, $context) {
-
-        $this->init($config);
-
-        // trick the parent class into thinking it allows more
-        $this->elements = $this->fake_elements;
-        $result = parent::validateChildren($tokens_of_children, $config, $context);
-        $this->elements = $this->real_elements;
-
-        if ($result === false) return array();
-        if ($result === true) $result = $tokens_of_children;
-
-        $def = $config->getHTMLDefinition();
-        $block_wrap_start = new HTMLPurifier_Token_Start($def->info_block_wrapper);
-        $block_wrap_end   = new HTMLPurifier_Token_End(  $def->info_block_wrapper);
-        $is_inline = false;
-        $depth = 0;
-        $ret = array();
-
-        // assuming that there are no comment tokens
-        foreach ($result as $i => $token) {
-            $token = $result[$i];
-            // ifs are nested for readability
-            if (!$is_inline) {
-                if (!$depth) {
-                     if (
-                        ($token instanceof HTMLPurifier_Token_Text && !$token->is_whitespace) ||
-                        (!$token instanceof HTMLPurifier_Token_Text && !isset($this->elements[$token->name]))
-                     ) {
-                        $is_inline = true;
-                        $ret[] = $block_wrap_start;
-                     }
-                }
-            } else {
-                if (!$depth) {
-                    // starting tokens have been inline text / empty
-                    if ($token instanceof HTMLPurifier_Token_Start || $token instanceof HTMLPurifier_Token_Empty) {
-                        if (isset($this->elements[$token->name])) {
-                            // ended
-                            $ret[] = $block_wrap_end;
-                            $is_inline = false;
-                        }
-                    }
-                }
-            }
-            $ret[] = $token;
-            if ($token instanceof HTMLPurifier_Token_Start) $depth++;
-            if ($token instanceof HTMLPurifier_Token_End)   $depth--;
-        }
-        if ($is_inline) $ret[] = $block_wrap_end;
-        return $ret;
-    }
-
-    private function init($config) {
-        if (!$this->init) {
-            $def = $config->getHTMLDefinition();
-            // allow all inline elements
-            $this->real_elements = $this->elements;
-            $this->fake_elements = $def->info_content_sets['Flow'];
-            $this->fake_elements['#PCDATA'] = true;
-            $this->init = true;
-        }
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ChildDef/Table.php b/library/HTMLPurifier/ChildDef/Table.php
deleted file mode 100644
index 34f0227dd2..0000000000
--- a/library/HTMLPurifier/ChildDef/Table.php
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-
-/**
- * Definition for tables
- */
-class HTMLPurifier_ChildDef_Table extends HTMLPurifier_ChildDef
-{
-    public $allow_empty = false;
-    public $type = 'table';
-    public $elements = array('tr' => true, 'tbody' => true, 'thead' => true,
-        'tfoot' => true, 'caption' => true, 'colgroup' => true, 'col' => true);
-    public function __construct() {}
-    public function validateChildren($tokens_of_children, $config, $context) {
-        if (empty($tokens_of_children)) return false;
-
-        // this ensures that the loop gets run one last time before closing
-        // up. It's a little bit of a hack, but it works! Just make sure you
-        // get rid of the token later.
-        $tokens_of_children[] = false;
-
-        // only one of these elements is allowed in a table
-        $caption = false;
-        $thead   = false;
-        $tfoot   = false;
-
-        // as many of these as you want
-        $cols    = array();
-        $content = array();
-
-        $nesting = 0; // current depth so we can determine nodes
-        $is_collecting = false; // are we globbing together tokens to package
-                                // into one of the collectors?
-        $collection = array(); // collected nodes
-        $tag_index = 0; // the first node might be whitespace,
-                            // so this tells us where the start tag is
-
-        foreach ($tokens_of_children as $token) {
-            $is_child = ($nesting == 0);
-
-            if ($token === false) {
-                // terminating sequence started
-            } elseif ($token instanceof HTMLPurifier_Token_Start) {
-                $nesting++;
-            } elseif ($token instanceof HTMLPurifier_Token_End) {
-                $nesting--;
-            }
-
-            // handle node collection
-            if ($is_collecting) {
-                if ($is_child) {
-                    // okay, let's stash the tokens away
-                    // first token tells us the type of the collection
-                    switch ($collection[$tag_index]->name) {
-                        case 'tr':
-                        case 'tbody':
-                            $content[] = $collection;
-                            break;
-                        case 'caption':
-                            if ($caption !== false) break;
-                            $caption = $collection;
-                            break;
-                        case 'thead':
-                        case 'tfoot':
-                            // access the appropriate variable, $thead or $tfoot
-                            $var = $collection[$tag_index]->name;
-                            if ($$var === false) {
-                                $$var = $collection;
-                            } else {
-                                // transmutate the first and less entries into
-                                // tbody tags, and then put into content
-                                $collection[$tag_index]->name = 'tbody';
-                                $collection[count($collection)-1]->name = 'tbody';
-                                $content[] = $collection;
-                            }
-                            break;
-                         case 'colgroup':
-                            $cols[] = $collection;
-                            break;
-                    }
-                    $collection = array();
-                    $is_collecting = false;
-                    $tag_index = 0;
-                } else {
-                    // add the node to the collection
-                    $collection[] = $token;
-                }
-            }
-
-            // terminate
-            if ($token === false) break;
-
-            if ($is_child) {
-                // determine what we're dealing with
-                if ($token->name == 'col') {
-                    // the only empty tag in the possie, we can handle it
-                    // immediately
-                    $cols[] = array_merge($collection, array($token));
-                    $collection = array();
-                    $tag_index = 0;
-                    continue;
-                }
-                switch($token->name) {
-                    case 'caption':
-                    case 'colgroup':
-                    case 'thead':
-                    case 'tfoot':
-                    case 'tbody':
-                    case 'tr':
-                        $is_collecting = true;
-                        $collection[] = $token;
-                        continue;
-                    default:
-                        if (!empty($token->is_whitespace)) {
-                            $collection[] = $token;
-                            $tag_index++;
-                        }
-                        continue;
-                }
-            }
-        }
-
-        if (empty($content)) return false;
-
-        $ret = array();
-        if ($caption !== false) $ret = array_merge($ret, $caption);
-        if ($cols !== false)    foreach ($cols as $token_array) $ret = array_merge($ret, $token_array);
-        if ($thead !== false)   $ret = array_merge($ret, $thead);
-        if ($tfoot !== false)   $ret = array_merge($ret, $tfoot);
-        foreach ($content as $token_array) $ret = array_merge($ret, $token_array);
-        if (!empty($collection) && $is_collecting == false){
-            // grab the trailing space
-            $ret = array_merge($ret, $collection);
-        }
-
-        array_pop($tokens_of_children); // remove phantom token
-
-        return ($ret === $tokens_of_children) ? true : $ret;
-
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Config.php b/library/HTMLPurifier/Config.php
deleted file mode 100644
index 2a334b0d83..0000000000
--- a/library/HTMLPurifier/Config.php
+++ /dev/null
@@ -1,580 +0,0 @@
-<?php
-
-/**
- * Configuration object that triggers customizable behavior.
- *
- * @warning This class is strongly defined: that means that the class
- *          will fail if an undefined directive is retrieved or set.
- *
- * @note Many classes that could (although many times don't) use the
- *       configuration object make it a mandatory parameter.  This is
- *       because a configuration object should always be forwarded,
- *       otherwise, you run the risk of missing a parameter and then
- *       being stumped when a configuration directive doesn't work.
- *
- * @todo Reconsider some of the public member variables
- */
-class HTMLPurifier_Config
-{
-
-    /**
-     * HTML Purifier's version
-     */
-    public $version = '4.1.1';
-
-    /**
-     * Bool indicator whether or not to automatically finalize
-     * the object if a read operation is done
-     */
-    public $autoFinalize = true;
-
-    // protected member variables
-
-    /**
-     * Namespace indexed array of serials for specific namespaces (see
-     * getSerial() for more info).
-     */
-    protected $serials = array();
-
-    /**
-     * Serial for entire configuration object
-     */
-    protected $serial;
-
-    /**
-     * Parser for variables
-     */
-    protected $parser;
-
-    /**
-     * Reference HTMLPurifier_ConfigSchema for value checking
-     * @note This is public for introspective purposes. Please don't
-     *       abuse!
-     */
-    public $def;
-
-    /**
-     * Indexed array of definitions
-     */
-    protected $definitions;
-
-    /**
-     * Bool indicator whether or not config is finalized
-     */
-    protected $finalized = false;
-
-    /**
-     * Property list containing configuration directives.
-     */
-    protected $plist;
-
-    /**
-     * Whether or not a set is taking place due to an
-     * alias lookup.
-     */
-    private $aliasMode;
-
-    /**
-     * Set to false if you do not want line and file numbers in errors
-     * (useful when unit testing)
-     */
-    public $chatty = true;
-
-    /**
-     * Current lock; only gets to this namespace are allowed.
-     */
-    private $lock;
-
-    /**
-     * @param $definition HTMLPurifier_ConfigSchema that defines what directives
-     *                    are allowed.
-     */
-    public function __construct($definition, $parent = null) {
-        $parent = $parent ? $parent : $definition->defaultPlist;
-        $this->plist = new HTMLPurifier_PropertyList($parent);
-        $this->def = $definition; // keep a copy around for checking
-        $this->parser = new HTMLPurifier_VarParser_Flexible();
-    }
-
-    /**
-     * Convenience constructor that creates a config object based on a mixed var
-     * @param mixed $config Variable that defines the state of the config
-     *                      object. Can be: a HTMLPurifier_Config() object,
-     *                      an array of directives based on loadArray(),
-     *                      or a string filename of an ini file.
-     * @param HTMLPurifier_ConfigSchema Schema object
-     * @return Configured HTMLPurifier_Config object
-     */
-    public static function create($config, $schema = null) {
-        if ($config instanceof HTMLPurifier_Config) {
-            // pass-through
-            return $config;
-        }
-        if (!$schema) {
-            $ret = HTMLPurifier_Config::createDefault();
-        } else {
-            $ret = new HTMLPurifier_Config($schema);
-        }
-        if (is_string($config)) $ret->loadIni($config);
-        elseif (is_array($config)) $ret->loadArray($config);
-        return $ret;
-    }
-
-    /**
-     * Creates a new config object that inherits from a previous one.
-     * @param HTMLPurifier_Config $config Configuration object to inherit
-     *        from.
-     * @return HTMLPurifier_Config object with $config as its parent.
-     */
-    public static function inherit(HTMLPurifier_Config $config) {
-        return new HTMLPurifier_Config($config->def, $config->plist);
-    }
-
-    /**
-     * Convenience constructor that creates a default configuration object.
-     * @return Default HTMLPurifier_Config object.
-     */
-    public static function createDefault() {
-        $definition = HTMLPurifier_ConfigSchema::instance();
-        $config = new HTMLPurifier_Config($definition);
-        return $config;
-    }
-
-    /**
-     * Retreives a value from the configuration.
-     * @param $key String key
-     */
-    public function get($key, $a = null) {
-        if ($a !== null) {
-            $this->triggerError("Using deprecated API: use \$config->get('$key.$a') instead", E_USER_WARNING);
-            $key = "$key.$a";
-        }
-        if (!$this->finalized) $this->autoFinalize();
-        if (!isset($this->def->info[$key])) {
-            // can't add % due to SimpleTest bug
-            $this->triggerError('Cannot retrieve value of undefined directive ' . htmlspecialchars($key),
-                E_USER_WARNING);
-            return;
-        }
-        if (isset($this->def->info[$key]->isAlias)) {
-            $d = $this->def->info[$key];
-            $this->triggerError('Cannot get value from aliased directive, use real name ' . $d->key,
-                E_USER_ERROR);
-            return;
-        }
-        if ($this->lock) {
-            list($ns) = explode('.', $key);
-            if ($ns !== $this->lock) {
-                $this->triggerError('Cannot get value of namespace ' . $ns . ' when lock for ' . $this->lock . ' is active, this probably indicates a Definition setup method is accessing directives that are not within its namespace', E_USER_ERROR);
-                return;
-            }
-        }
-        return $this->plist->get($key);
-    }
-
-    /**
-     * Retreives an array of directives to values from a given namespace
-     * @param $namespace String namespace
-     */
-    public function getBatch($namespace) {
-        if (!$this->finalized) $this->autoFinalize();
-        $full = $this->getAll();
-        if (!isset($full[$namespace])) {
-            $this->triggerError('Cannot retrieve undefined namespace ' . htmlspecialchars($namespace),
-                E_USER_WARNING);
-            return;
-        }
-        return $full[$namespace];
-    }
-
-    /**
-     * Returns a md5 signature of a segment of the configuration object
-     * that uniquely identifies that particular configuration
-     * @note Revision is handled specially and is removed from the batch
-     *       before processing!
-     * @param $namespace Namespace to get serial for
-     */
-    public function getBatchSerial($namespace) {
-        if (empty($this->serials[$namespace])) {
-            $batch = $this->getBatch($namespace);
-            unset($batch['DefinitionRev']);
-            $this->serials[$namespace] = md5(serialize($batch));
-        }
-        return $this->serials[$namespace];
-    }
-
-    /**
-     * Returns a md5 signature for the entire configuration object
-     * that uniquely identifies that particular configuration
-     */
-    public function getSerial() {
-        if (empty($this->serial)) {
-            $this->serial = md5(serialize($this->getAll()));
-        }
-        return $this->serial;
-    }
-
-    /**
-     * Retrieves all directives, organized by namespace
-     * @warning This is a pretty inefficient function, avoid if you can
-     */
-    public function getAll() {
-        if (!$this->finalized) $this->autoFinalize();
-        $ret = array();
-        foreach ($this->plist->squash() as $name => $value) {
-            list($ns, $key) = explode('.', $name, 2);
-            $ret[$ns][$key] = $value;
-        }
-        return $ret;
-    }
-
-    /**
-     * Sets a value to configuration.
-     * @param $key String key
-     * @param $value Mixed value
-     */
-    public function set($key, $value, $a = null) {
-        if (strpos($key, '.') === false) {
-            $namespace = $key;
-            $directive = $value;
-            $value = $a;
-            $key = "$key.$directive";
-            $this->triggerError("Using deprecated API: use \$config->set('$key', ...) instead", E_USER_NOTICE);
-        } else {
-            list($namespace) = explode('.', $key);
-        }
-        if ($this->isFinalized('Cannot set directive after finalization')) return;
-        if (!isset($this->def->info[$key])) {
-            $this->triggerError('Cannot set undefined directive ' . htmlspecialchars($key) . ' to value',
-                E_USER_WARNING);
-            return;
-        }
-        $def = $this->def->info[$key];
-
-        if (isset($def->isAlias)) {
-            if ($this->aliasMode) {
-                $this->triggerError('Double-aliases not allowed, please fix '.
-                    'ConfigSchema bug with' . $key, E_USER_ERROR);
-                return;
-            }
-            $this->aliasMode = true;
-            $this->set($def->key, $value);
-            $this->aliasMode = false;
-            $this->triggerError("$key is an alias, preferred directive name is {$def->key}", E_USER_NOTICE);
-            return;
-        }
-
-        // Raw type might be negative when using the fully optimized form
-        // of stdclass, which indicates allow_null == true
-        $rtype = is_int($def) ? $def : $def->type;
-        if ($rtype < 0) {
-            $type = -$rtype;
-            $allow_null = true;
-        } else {
-            $type = $rtype;
-            $allow_null = isset($def->allow_null);
-        }
-
-        try {
-            $value = $this->parser->parse($value, $type, $allow_null);
-        } catch (HTMLPurifier_VarParserException $e) {
-            $this->triggerError('Value for ' . $key . ' is of invalid type, should be ' . HTMLPurifier_VarParser::getTypeName($type), E_USER_WARNING);
-            return;
-        }
-        if (is_string($value) && is_object($def)) {
-            // resolve value alias if defined
-            if (isset($def->aliases[$value])) {
-                $value = $def->aliases[$value];
-            }
-            // check to see if the value is allowed
-            if (isset($def->allowed) && !isset($def->allowed[$value])) {
-                $this->triggerError('Value not supported, valid values are: ' .
-                    $this->_listify($def->allowed), E_USER_WARNING);
-                return;
-            }
-        }
-        $this->plist->set($key, $value);
-
-        // reset definitions if the directives they depend on changed
-        // this is a very costly process, so it's discouraged
-        // with finalization
-        if ($namespace == 'HTML' || $namespace == 'CSS' || $namespace == 'URI') {
-            $this->definitions[$namespace] = null;
-        }
-
-        $this->serials[$namespace] = false;
-    }
-
-    /**
-     * Convenience function for error reporting
-     */
-    private function _listify($lookup) {
-        $list = array();
-        foreach ($lookup as $name => $b) $list[] = $name;
-        return implode(', ', $list);
-    }
-
-    /**
-     * Retrieves object reference to the HTML definition.
-     * @param $raw Return a copy that has not been setup yet. Must be
-     *             called before it's been setup, otherwise won't work.
-     */
-    public function getHTMLDefinition($raw = false) {
-        return $this->getDefinition('HTML', $raw);
-    }
-
-    /**
-     * Retrieves object reference to the CSS definition
-     * @param $raw Return a copy that has not been setup yet. Must be
-     *             called before it's been setup, otherwise won't work.
-     */
-    public function getCSSDefinition($raw = false) {
-        return $this->getDefinition('CSS', $raw);
-    }
-
-    /**
-     * Retrieves a definition
-     * @param $type Type of definition: HTML, CSS, etc
-     * @param $raw  Whether or not definition should be returned raw
-     */
-    public function getDefinition($type, $raw = false) {
-        if (!$this->finalized) $this->autoFinalize();
-        // temporarily suspend locks, so we can handle recursive definition calls
-        $lock = $this->lock;
-        $this->lock = null;
-        $factory = HTMLPurifier_DefinitionCacheFactory::instance();
-        $cache = $factory->create($type, $this);
-        $this->lock = $lock;
-        if (!$raw) {
-            // see if we can quickly supply a definition
-            if (!empty($this->definitions[$type])) {
-                if (!$this->definitions[$type]->setup) {
-                    $this->definitions[$type]->setup($this);
-                    $cache->set($this->definitions[$type], $this);
-                }
-                return $this->definitions[$type];
-            }
-            // memory check missed, try cache
-            $this->definitions[$type] = $cache->get($this);
-            if ($this->definitions[$type]) {
-                // definition in cache, return it
-                return $this->definitions[$type];
-            }
-        } elseif (
-            !empty($this->definitions[$type]) &&
-            !$this->definitions[$type]->setup
-        ) {
-            // raw requested, raw in memory, quick return
-            return $this->definitions[$type];
-        }
-        // quick checks failed, let's create the object
-        if ($type == 'HTML') {
-            $this->definitions[$type] = new HTMLPurifier_HTMLDefinition();
-        } elseif ($type == 'CSS') {
-            $this->definitions[$type] = new HTMLPurifier_CSSDefinition();
-        } elseif ($type == 'URI') {
-            $this->definitions[$type] = new HTMLPurifier_URIDefinition();
-        } else {
-            throw new HTMLPurifier_Exception("Definition of $type type not supported");
-        }
-        // quick abort if raw
-        if ($raw) {
-            if (is_null($this->get($type . '.DefinitionID'))) {
-                // fatally error out if definition ID not set
-                throw new HTMLPurifier_Exception("Cannot retrieve raw version without specifying %$type.DefinitionID");
-            }
-            return $this->definitions[$type];
-        }
-        // set it up
-        $this->lock = $type;
-        $this->definitions[$type]->setup($this);
-        $this->lock = null;
-        // save in cache
-        $cache->set($this->definitions[$type], $this);
-        return $this->definitions[$type];
-    }
-
-    /**
-     * Loads configuration values from an array with the following structure:
-     * Namespace.Directive => Value
-     * @param $config_array Configuration associative array
-     */
-    public function loadArray($config_array) {
-        if ($this->isFinalized('Cannot load directives after finalization')) return;
-        foreach ($config_array as $key => $value) {
-            $key = str_replace('_', '.', $key);
-            if (strpos($key, '.') !== false) {
-                $this->set($key, $value);
-            } else {
-                $namespace = $key;
-                $namespace_values = $value;
-                foreach ($namespace_values as $directive => $value) {
-                    $this->set($namespace .'.'. $directive, $value);
-                }
-            }
-        }
-    }
-
-    /**
-     * Returns a list of array(namespace, directive) for all directives
-     * that are allowed in a web-form context as per an allowed
-     * namespaces/directives list.
-     * @param $allowed List of allowed namespaces/directives
-     */
-    public static function getAllowedDirectivesForForm($allowed, $schema = null) {
-        if (!$schema) {
-            $schema = HTMLPurifier_ConfigSchema::instance();
-        }
-        if ($allowed !== true) {
-             if (is_string($allowed)) $allowed = array($allowed);
-             $allowed_ns = array();
-             $allowed_directives = array();
-             $blacklisted_directives = array();
-             foreach ($allowed as $ns_or_directive) {
-                 if (strpos($ns_or_directive, '.') !== false) {
-                     // directive
-                     if ($ns_or_directive[0] == '-') {
-                         $blacklisted_directives[substr($ns_or_directive, 1)] = true;
-                     } else {
-                         $allowed_directives[$ns_or_directive] = true;
-                     }
-                 } else {
-                     // namespace
-                     $allowed_ns[$ns_or_directive] = true;
-                 }
-             }
-        }
-        $ret = array();
-        foreach ($schema->info as $key => $def) {
-            list($ns, $directive) = explode('.', $key, 2);
-            if ($allowed !== true) {
-                if (isset($blacklisted_directives["$ns.$directive"])) continue;
-                if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) continue;
-            }
-            if (isset($def->isAlias)) continue;
-            if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') continue;
-            $ret[] = array($ns, $directive);
-        }
-        return $ret;
-    }
-
-    /**
-     * Loads configuration values from $_GET/$_POST that were posted
-     * via ConfigForm
-     * @param $array $_GET or $_POST array to import
-     * @param $index Index/name that the config variables are in
-     * @param $allowed List of allowed namespaces/directives
-     * @param $mq_fix Boolean whether or not to enable magic quotes fix
-     * @param $schema Instance of HTMLPurifier_ConfigSchema to use, if not global copy
-     */
-    public static function loadArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null) {
-        $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $schema);
-        $config = HTMLPurifier_Config::create($ret, $schema);
-        return $config;
-    }
-
-    /**
-     * Merges in configuration values from $_GET/$_POST to object. NOT STATIC.
-     * @note Same parameters as loadArrayFromForm
-     */
-    public function mergeArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true) {
-         $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $this->def);
-         $this->loadArray($ret);
-    }
-
-    /**
-     * Prepares an array from a form into something usable for the more
-     * strict parts of HTMLPurifier_Config
-     */
-    public static function prepareArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null) {
-        if ($index !== false) $array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array();
-        $mq = $mq_fix && function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc();
-
-        $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $schema);
-        $ret = array();
-        foreach ($allowed as $key) {
-            list($ns, $directive) = $key;
-            $skey = "$ns.$directive";
-            if (!empty($array["Null_$skey"])) {
-                $ret[$ns][$directive] = null;
-                continue;
-            }
-            if (!isset($array[$skey])) continue;
-            $value = $mq ? stripslashes($array[$skey]) : $array[$skey];
-            $ret[$ns][$directive] = $value;
-        }
-        return $ret;
-    }
-
-    /**
-     * Loads configuration values from an ini file
-     * @param $filename Name of ini file
-     */
-    public function loadIni($filename) {
-        if ($this->isFinalized('Cannot load directives after finalization')) return;
-        $array = parse_ini_file($filename, true);
-        $this->loadArray($array);
-    }
-
-    /**
-     * Checks whether or not the configuration object is finalized.
-     * @param $error String error message, or false for no error
-     */
-    public function isFinalized($error = false) {
-        if ($this->finalized && $error) {
-            $this->triggerError($error, E_USER_ERROR);
-        }
-        return $this->finalized;
-    }
-
-    /**
-     * Finalizes configuration only if auto finalize is on and not
-     * already finalized
-     */
-    public function autoFinalize() {
-        if ($this->autoFinalize) {
-            $this->finalize();
-        } else {
-            $this->plist->squash(true);
-        }
-    }
-
-    /**
-     * Finalizes a configuration object, prohibiting further change
-     */
-    public function finalize() {
-        $this->finalized = true;
-        unset($this->parser);
-    }
-
-    /**
-     * Produces a nicely formatted error message by supplying the
-     * stack frame information from two levels up and OUTSIDE of
-     * HTMLPurifier_Config.
-     */
-    protected function triggerError($msg, $no) {
-        // determine previous stack frame
-        $backtrace = debug_backtrace();
-        if ($this->chatty && isset($backtrace[1])) {
-            $frame = $backtrace[1];
-            $extra = " on line {$frame['line']} in file {$frame['file']}";
-        } else {
-            $extra = '';
-        }
-        trigger_error($msg . $extra, $no);
-    }
-
-    /**
-     * Returns a serialized form of the configuration object that can
-     * be reconstituted.
-     */
-    public function serialize() {
-        $this->getDefinition('HTML');
-        $this->getDefinition('CSS');
-        $this->getDefinition('URI');
-        return serialize($this);
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php b/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php
deleted file mode 100644
index b95aea18cc..0000000000
--- a/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-
-/**
- * Fluent interface for validating the contents of member variables.
- * This should be immutable. See HTMLPurifier_ConfigSchema_Validator for
- * use-cases. We name this an 'atom' because it's ONLY for validations that
- * are independent and usually scalar.
- */
-class HTMLPurifier_ConfigSchema_ValidatorAtom
-{
-
-    protected $context, $obj, $member, $contents;
-
-    public function __construct($context, $obj, $member) {
-        $this->context     = $context;
-        $this->obj         = $obj;
-        $this->member      = $member;
-        $this->contents    =& $obj->$member;
-    }
-
-    public function assertIsString() {
-        if (!is_string($this->contents)) $this->error('must be a string');
-        return $this;
-    }
-
-    public function assertIsBool() {
-        if (!is_bool($this->contents)) $this->error('must be a boolean');
-        return $this;
-    }
-
-    public function assertIsArray() {
-        if (!is_array($this->contents)) $this->error('must be an array');
-        return $this;
-    }
-
-    public function assertNotNull() {
-        if ($this->contents === null) $this->error('must not be null');
-        return $this;
-    }
-
-    public function assertAlnum() {
-        $this->assertIsString();
-        if (!ctype_alnum($this->contents)) $this->error('must be alphanumeric');
-        return $this;
-    }
-
-    public function assertNotEmpty() {
-        if (empty($this->contents)) $this->error('must not be empty');
-        return $this;
-    }
-
-    public function assertIsLookup() {
-        $this->assertIsArray();
-        foreach ($this->contents as $v) {
-            if ($v !== true) $this->error('must be a lookup array');
-        }
-        return $this;
-    }
-
-    protected function error($msg) {
-        throw new HTMLPurifier_ConfigSchema_Exception(ucfirst($this->member) . ' in ' . $this->context . ' ' . $msg);
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema.ser b/library/HTMLPurifier/ConfigSchema/schema.ser
deleted file mode 100644
index 22b8d54a59f17f73071055bc601d5a5f3a3f6b31..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 13244
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
Q8uHP_ug&>z-|yf52WIevWdHyG

diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt b/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt
deleted file mode 100644
index 888d558196..0000000000
--- a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-HTML.AllowedElements
-TYPE: lookup/null
-VERSION: 1.3.0
-DEFAULT: NULL
---DESCRIPTION--
-<p>
-    If HTML Purifier's tag set is unsatisfactory for your needs, you
-    can overload it with your own list of tags to allow.  Note that this
-    method is subtractive: it does its job by taking away from HTML Purifier
-    usual feature set, so you cannot add a tag that HTML Purifier never
-    supported in the first place (like embed, form or head).  If you
-    change this, you probably also want to change %HTML.AllowedAttributes.
-</p>
-<p>
-    <strong>Warning:</strong> If another directive conflicts with the
-    elements here, <em>that</em> directive will win and override.
-</p>
---# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Context.php b/library/HTMLPurifier/Context.php
deleted file mode 100644
index 9ddf0c5476..0000000000
--- a/library/HTMLPurifier/Context.php
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-
-/**
- * Registry object that contains information about the current context.
- * @warning Is a bit buggy when variables are set to null: it thinks
- *          they don't exist! So use false instead, please.
- * @note Since the variables Context deals with may not be objects,
- *       references are very important here! Do not remove!
- */
-class HTMLPurifier_Context
-{
-
-    /**
-     * Private array that stores the references.
-     */
-    private $_storage = array();
-
-    /**
-     * Registers a variable into the context.
-     * @param $name String name
-     * @param $ref Reference to variable to be registered
-     */
-    public function register($name, &$ref) {
-        if (isset($this->_storage[$name])) {
-            trigger_error("Name $name produces collision, cannot re-register",
-                          E_USER_ERROR);
-            return;
-        }
-        $this->_storage[$name] =& $ref;
-    }
-
-    /**
-     * Retrieves a variable reference from the context.
-     * @param $name String name
-     * @param $ignore_error Boolean whether or not to ignore error
-     */
-    public function &get($name, $ignore_error = false) {
-        if (!isset($this->_storage[$name])) {
-            if (!$ignore_error) {
-                trigger_error("Attempted to retrieve non-existent variable $name",
-                              E_USER_ERROR);
-            }
-            $var = null; // so we can return by reference
-            return $var;
-        }
-        return $this->_storage[$name];
-    }
-
-    /**
-     * Destorys a variable in the context.
-     * @param $name String name
-     */
-    public function destroy($name) {
-        if (!isset($this->_storage[$name])) {
-            trigger_error("Attempted to destroy non-existent variable $name",
-                          E_USER_ERROR);
-            return;
-        }
-        unset($this->_storage[$name]);
-    }
-
-    /**
-     * Checks whether or not the variable exists.
-     * @param $name String name
-     */
-    public function exists($name) {
-        return isset($this->_storage[$name]);
-    }
-
-    /**
-     * Loads a series of variables from an associative array
-     * @param $context_array Assoc array of variables to load
-     */
-    public function loadArray($context_array) {
-        foreach ($context_array as $key => $discard) {
-            $this->register($key, $context_array[$key]);
-        }
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Definition.php b/library/HTMLPurifier/Definition.php
deleted file mode 100644
index a7408c9749..0000000000
--- a/library/HTMLPurifier/Definition.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-/**
- * Super-class for definition datatype objects, implements serialization
- * functions for the class.
- */
-abstract class HTMLPurifier_Definition
-{
-
-    /**
-     * Has setup() been called yet?
-     */
-    public $setup = false;
-
-    /**
-     * What type of definition is it?
-     */
-    public $type;
-
-    /**
-     * Sets up the definition object into the final form, something
-     * not done by the constructor
-     * @param $config HTMLPurifier_Config instance
-     */
-    abstract protected function doSetup($config);
-
-    /**
-     * Setup function that aborts if already setup
-     * @param $config HTMLPurifier_Config instance
-     */
-    public function setup($config) {
-        if ($this->setup) return;
-        $this->setup = true;
-        $this->doSetup($config);
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/DefinitionCache/Decorator.php b/library/HTMLPurifier/DefinitionCache/Decorator.php
deleted file mode 100644
index b0fb6d0cd6..0000000000
--- a/library/HTMLPurifier/DefinitionCache/Decorator.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-
-class HTMLPurifier_DefinitionCache_Decorator extends HTMLPurifier_DefinitionCache
-{
-
-    /**
-     * Cache object we are decorating
-     */
-    public $cache;
-
-    public function __construct() {}
-
-    /**
-     * Lazy decorator function
-     * @param $cache Reference to cache object to decorate
-     */
-    public function decorate(&$cache) {
-        $decorator = $this->copy();
-        // reference is necessary for mocks in PHP 4
-        $decorator->cache =& $cache;
-        $decorator->type  = $cache->type;
-        return $decorator;
-    }
-
-    /**
-     * Cross-compatible clone substitute
-     */
-    public function copy() {
-        return new HTMLPurifier_DefinitionCache_Decorator();
-    }
-
-    public function add($def, $config) {
-        return $this->cache->add($def, $config);
-    }
-
-    public function set($def, $config) {
-        return $this->cache->set($def, $config);
-    }
-
-    public function replace($def, $config) {
-        return $this->cache->replace($def, $config);
-    }
-
-    public function get($config) {
-        return $this->cache->get($config);
-    }
-
-    public function remove($config) {
-        return $this->cache->remove($config);
-    }
-
-    public function flush($config) {
-        return $this->cache->flush($config);
-    }
-
-    public function cleanup($config) {
-        return $this->cache->cleanup($config);
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php b/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php
deleted file mode 100644
index d4cc35c4bc..0000000000
--- a/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-/**
- * Definition cache decorator class that cleans up the cache
- * whenever there is a cache miss.
- */
-class HTMLPurifier_DefinitionCache_Decorator_Cleanup extends
-      HTMLPurifier_DefinitionCache_Decorator
-{
-
-    public $name = 'Cleanup';
-
-    public function copy() {
-        return new HTMLPurifier_DefinitionCache_Decorator_Cleanup();
-    }
-
-    public function add($def, $config) {
-        $status = parent::add($def, $config);
-        if (!$status) parent::cleanup($config);
-        return $status;
-    }
-
-    public function set($def, $config) {
-        $status = parent::set($def, $config);
-        if (!$status) parent::cleanup($config);
-        return $status;
-    }
-
-    public function replace($def, $config) {
-        $status = parent::replace($def, $config);
-        if (!$status) parent::cleanup($config);
-        return $status;
-    }
-
-    public function get($config) {
-        $ret = parent::get($config);
-        if (!$ret) parent::cleanup($config);
-        return $ret;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php b/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php
deleted file mode 100644
index 18f16d32b6..0000000000
--- a/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-
-/**
- * Definition cache decorator class that saves all cache retrievals
- * to PHP's memory; good for unit tests or circumstances where
- * there are lots of configuration objects floating around.
- */
-class HTMLPurifier_DefinitionCache_Decorator_Memory extends
-      HTMLPurifier_DefinitionCache_Decorator
-{
-
-    protected $definitions;
-    public $name = 'Memory';
-
-    public function copy() {
-        return new HTMLPurifier_DefinitionCache_Decorator_Memory();
-    }
-
-    public function add($def, $config) {
-        $status = parent::add($def, $config);
-        if ($status) $this->definitions[$this->generateKey($config)] = $def;
-        return $status;
-    }
-
-    public function set($def, $config) {
-        $status = parent::set($def, $config);
-        if ($status) $this->definitions[$this->generateKey($config)] = $def;
-        return $status;
-    }
-
-    public function replace($def, $config) {
-        $status = parent::replace($def, $config);
-        if ($status) $this->definitions[$this->generateKey($config)] = $def;
-        return $status;
-    }
-
-    public function get($config) {
-        $key = $this->generateKey($config);
-        if (isset($this->definitions[$key])) return $this->definitions[$key];
-        $this->definitions[$key] = parent::get($config);
-        return $this->definitions[$key];
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in b/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in
deleted file mode 100644
index 21a8fcfda2..0000000000
--- a/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-require_once 'HTMLPurifier/DefinitionCache/Decorator.php';
-
-/**
- * Definition cache decorator template.
- */
-class HTMLPurifier_DefinitionCache_Decorator_Template extends
-      HTMLPurifier_DefinitionCache_Decorator
-{
-
-    var $name = 'Template'; // replace this
-
-    function copy() {
-        // replace class name with yours
-        return new HTMLPurifier_DefinitionCache_Decorator_Template();
-    }
-
-    // remove methods you don't need
-
-    function add($def, $config) {
-        return parent::add($def, $config);
-    }
-
-    function set($def, $config) {
-        return parent::set($def, $config);
-    }
-
-    function replace($def, $config) {
-        return parent::replace($def, $config);
-    }
-
-    function get($config) {
-        return parent::get($config);
-    }
-
-    function flush() {
-        return parent::flush();
-    }
-
-    function cleanup($config) {
-        return parent::cleanup($config);
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/DefinitionCache/Null.php b/library/HTMLPurifier/DefinitionCache/Null.php
deleted file mode 100644
index 41d97e734f..0000000000
--- a/library/HTMLPurifier/DefinitionCache/Null.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-/**
- * Null cache object to use when no caching is on.
- */
-class HTMLPurifier_DefinitionCache_Null extends HTMLPurifier_DefinitionCache
-{
-
-    public function add($def, $config) {
-        return false;
-    }
-
-    public function set($def, $config) {
-        return false;
-    }
-
-    public function replace($def, $config) {
-        return false;
-    }
-
-    public function remove($config) {
-        return false;
-    }
-
-    public function get($config) {
-        return false;
-    }
-
-    public function flush($config) {
-        return false;
-    }
-
-    public function cleanup($config) {
-        return false;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/DefinitionCache/Serializer.php b/library/HTMLPurifier/DefinitionCache/Serializer.php
deleted file mode 100644
index 7a6aa93f02..0000000000
--- a/library/HTMLPurifier/DefinitionCache/Serializer.php
+++ /dev/null
@@ -1,172 +0,0 @@
-<?php
-
-class HTMLPurifier_DefinitionCache_Serializer extends
-      HTMLPurifier_DefinitionCache
-{
-
-    public function add($def, $config) {
-        if (!$this->checkDefType($def)) return;
-        $file = $this->generateFilePath($config);
-        if (file_exists($file)) return false;
-        if (!$this->_prepareDir($config)) return false;
-        return $this->_write($file, serialize($def));
-    }
-
-    public function set($def, $config) {
-        if (!$this->checkDefType($def)) return;
-        $file = $this->generateFilePath($config);
-        if (!$this->_prepareDir($config)) return false;
-        return $this->_write($file, serialize($def));
-    }
-
-    public function replace($def, $config) {
-        if (!$this->checkDefType($def)) return;
-        $file = $this->generateFilePath($config);
-        if (!file_exists($file)) return false;
-        if (!$this->_prepareDir($config)) return false;
-        return $this->_write($file, serialize($def));
-    }
-
-    public function get($config) {
-        $file = $this->generateFilePath($config);
-        if (!file_exists($file)) return false;
-        return unserialize(file_get_contents($file));
-    }
-
-    public function remove($config) {
-        $file = $this->generateFilePath($config);
-        if (!file_exists($file)) return false;
-        return unlink($file);
-    }
-
-    public function flush($config) {
-        if (!$this->_prepareDir($config)) return false;
-        $dir = $this->generateDirectoryPath($config);
-        $dh  = opendir($dir);
-        while (false !== ($filename = readdir($dh))) {
-            if (empty($filename)) continue;
-            if ($filename[0] === '.') continue;
-            unlink($dir . '/' . $filename);
-        }
-    }
-
-    public function cleanup($config) {
-        if (!$this->_prepareDir($config)) return false;
-        $dir = $this->generateDirectoryPath($config);
-        $dh  = opendir($dir);
-        while (false !== ($filename = readdir($dh))) {
-            if (empty($filename)) continue;
-            if ($filename[0] === '.') continue;
-            $key = substr($filename, 0, strlen($filename) - 4);
-            if ($this->isOld($key, $config)) unlink($dir . '/' . $filename);
-        }
-    }
-
-    /**
-     * Generates the file path to the serial file corresponding to
-     * the configuration and definition name
-     * @todo Make protected
-     */
-    public function generateFilePath($config) {
-        $key = $this->generateKey($config);
-        return $this->generateDirectoryPath($config) . '/' . $key . '.ser';
-    }
-
-    /**
-     * Generates the path to the directory contain this cache's serial files
-     * @note No trailing slash
-     * @todo Make protected
-     */
-    public function generateDirectoryPath($config) {
-        $base = $this->generateBaseDirectoryPath($config);
-        return $base . '/' . $this->type;
-    }
-
-    /**
-     * Generates path to base directory that contains all definition type
-     * serials
-     * @todo Make protected
-     */
-    public function generateBaseDirectoryPath($config) {
-        $base = $config->get('Cache.SerializerPath');
-        $base = is_null($base) ? HTMLPURIFIER_PREFIX . '/HTMLPurifier/DefinitionCache/Serializer' : $base;
-        return $base;
-    }
-
-    /**
-     * Convenience wrapper function for file_put_contents
-     * @param $file File name to write to
-     * @param $data Data to write into file
-     * @return Number of bytes written if success, or false if failure.
-     */
-    private function _write($file, $data) {
-        return file_put_contents($file, $data);
-    }
-
-    /**
-     * Prepares the directory that this type stores the serials in
-     * @return True if successful
-     */
-    private function _prepareDir($config) {
-        $directory = $this->generateDirectoryPath($config);
-        if (!is_dir($directory)) {
-            $base = $this->generateBaseDirectoryPath($config);
-            if (!is_dir($base)) {
-                trigger_error('Base directory '.$base.' does not exist,
-                    please create or change using %Cache.SerializerPath',
-                    E_USER_WARNING);
-                return false;
-            } elseif (!$this->_testPermissions($base)) {
-                return false;
-            }
-            $old = umask(0022); // disable group and world writes
-            mkdir($directory);
-            umask($old);
-        } elseif (!$this->_testPermissions($directory)) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Tests permissions on a directory and throws out friendly
-     * error messages and attempts to chmod it itself if possible
-     */
-    private function _testPermissions($dir) {
-        // early abort, if it is writable, everything is hunky-dory
-        if (is_writable($dir)) return true;
-        if (!is_dir($dir)) {
-            // generally, you'll want to handle this beforehand
-            // so a more specific error message can be given
-            trigger_error('Directory '.$dir.' does not exist',
-                E_USER_WARNING);
-            return false;
-        }
-        if (function_exists('posix_getuid')) {
-            // POSIX system, we can give more specific advice
-            if (fileowner($dir) === posix_getuid()) {
-                // we can chmod it ourselves
-                chmod($dir, 0755);
-                return true;
-            } elseif (filegroup($dir) === posix_getgid()) {
-                $chmod = '775';
-            } else {
-                // PHP's probably running as nobody, so we'll
-                // need to give global permissions
-                $chmod = '777';
-            }
-            trigger_error('Directory '.$dir.' not writable, '.
-                'please chmod to ' . $chmod,
-                E_USER_WARNING);
-        } else {
-            // generic error message
-            trigger_error('Directory '.$dir.' not writable, '.
-                'please alter file permissions',
-                E_USER_WARNING);
-        }
-        return false;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/EntityLookup/entities.ser b/library/HTMLPurifier/EntityLookup/entities.ser
deleted file mode 100644
index f2b8b8f2db..0000000000
--- a/library/HTMLPurifier/EntityLookup/entities.ser
+++ /dev/null
@@ -1 +0,0 @@
-a:246:{s:4:"nbsp";s:2:" ";s:5:"iexcl";s:2:"¡";s:4:"cent";s:2:"¢";s:5:"pound";s:2:"£";s:6:"curren";s:2:"¤";s:3:"yen";s:2:"¥";s:6:"brvbar";s:2:"¦";s:4:"sect";s:2:"§";s:3:"uml";s:2:"¨";s:4:"copy";s:2:"©";s:4:"ordf";s:2:"ª";s:5:"laquo";s:2:"«";s:3:"not";s:2:"¬";s:3:"shy";s:2:"­";s:3:"reg";s:2:"®";s:4:"macr";s:2:"¯";s:3:"deg";s:2:"°";s:6:"plusmn";s:2:"±";s:5:"acute";s:2:"´";s:5:"micro";s:2:"µ";s:4:"para";s:2:"¶";s:6:"middot";s:2:"·";s:5:"cedil";s:2:"¸";s:4:"ordm";s:2:"º";s:5:"raquo";s:2:"»";s:6:"iquest";s:2:"¿";s:6:"Agrave";s:2:"À";s:6:"Aacute";s:2:"Á";s:5:"Acirc";s:2:"Â";s:6:"Atilde";s:2:"Ã";s:4:"Auml";s:2:"Ä";s:5:"Aring";s:2:"Å";s:5:"AElig";s:2:"Æ";s:6:"Ccedil";s:2:"Ç";s:6:"Egrave";s:2:"È";s:6:"Eacute";s:2:"É";s:5:"Ecirc";s:2:"Ê";s:4:"Euml";s:2:"Ë";s:6:"Igrave";s:2:"Ì";s:6:"Iacute";s:2:"Í";s:5:"Icirc";s:2:"Î";s:4:"Iuml";s:2:"Ï";s:3:"ETH";s:2:"Ð";s:6:"Ntilde";s:2:"Ñ";s:6:"Ograve";s:2:"Ò";s:6:"Oacute";s:2:"Ó";s:5:"Ocirc";s:2:"Ô";s:6:"Otilde";s:2:"Õ";s:4:"Ouml";s:2:"Ö";s:5:"times";s:2:"×";s:6:"Oslash";s:2:"Ø";s:6:"Ugrave";s:2:"Ù";s:6:"Uacute";s:2:"Ú";s:5:"Ucirc";s:2:"Û";s:4:"Uuml";s:2:"Ü";s:6:"Yacute";s:2:"Ý";s:5:"THORN";s:2:"Þ";s:5:"szlig";s:2:"ß";s:6:"agrave";s:2:"à";s:6:"aacute";s:2:"á";s:5:"acirc";s:2:"â";s:6:"atilde";s:2:"ã";s:4:"auml";s:2:"ä";s:5:"aring";s:2:"å";s:5:"aelig";s:2:"æ";s:6:"ccedil";s:2:"ç";s:6:"egrave";s:2:"è";s:6:"eacute";s:2:"é";s:5:"ecirc";s:2:"ê";s:4:"euml";s:2:"ë";s:6:"igrave";s:2:"ì";s:6:"iacute";s:2:"í";s:5:"icirc";s:2:"î";s:4:"iuml";s:2:"ï";s:3:"eth";s:2:"ð";s:6:"ntilde";s:2:"ñ";s:6:"ograve";s:2:"ò";s:6:"oacute";s:2:"ó";s:5:"ocirc";s:2:"ô";s:6:"otilde";s:2:"õ";s:4:"ouml";s:2:"ö";s:6:"divide";s:2:"÷";s:6:"oslash";s:2:"ø";s:6:"ugrave";s:2:"ù";s:6:"uacute";s:2:"ú";s:5:"ucirc";s:2:"û";s:4:"uuml";s:2:"ü";s:6:"yacute";s:2:"ý";s:5:"thorn";s:2:"þ";s:4:"yuml";s:2:"ÿ";s:4:"quot";s:1:""";s:3:"amp";s:1:"&";s:2:"lt";s:1:"<";s:2:"gt";s:1:">";s:4:"apos";s:1:"'";s:5:"OElig";s:2:"Œ";s:5:"oelig";s:2:"œ";s:6:"Scaron";s:2:"Š";s:6:"scaron";s:2:"š";s:4:"Yuml";s:2:"Ÿ";s:4:"circ";s:2:"ˆ";s:5:"tilde";s:2:"˜";s:4:"ensp";s:3:" ";s:4:"emsp";s:3:" ";s:6:"thinsp";s:3:" ";s:4:"zwnj";s:3:"‌";s:3:"zwj";s:3:"‍";s:3:"lrm";s:3:"‎";s:3:"rlm";s:3:"‏";s:5:"ndash";s:3:"–";s:5:"mdash";s:3:"—";s:5:"lsquo";s:3:"‘";s:5:"rsquo";s:3:"’";s:5:"sbquo";s:3:"‚";s:5:"ldquo";s:3:"“";s:5:"rdquo";s:3:"”";s:5:"bdquo";s:3:"„";s:6:"dagger";s:3:"†";s:6:"Dagger";s:3:"‡";s:6:"permil";s:3:"‰";s:6:"lsaquo";s:3:"‹";s:6:"rsaquo";s:3:"›";s:4:"euro";s:3:"€";s:4:"fnof";s:2:"ƒ";s:5:"Alpha";s:2:"Α";s:4:"Beta";s:2:"Β";s:5:"Gamma";s:2:"Γ";s:5:"Delta";s:2:"Δ";s:7:"Epsilon";s:2:"Ε";s:4:"Zeta";s:2:"Ζ";s:3:"Eta";s:2:"Η";s:5:"Theta";s:2:"Θ";s:4:"Iota";s:2:"Ι";s:5:"Kappa";s:2:"Κ";s:6:"Lambda";s:2:"Λ";s:2:"Mu";s:2:"Μ";s:2:"Nu";s:2:"Ν";s:2:"Xi";s:2:"Ξ";s:7:"Omicron";s:2:"Ο";s:2:"Pi";s:2:"Π";s:3:"Rho";s:2:"Ρ";s:5:"Sigma";s:2:"Σ";s:3:"Tau";s:2:"Τ";s:7:"Upsilon";s:2:"Υ";s:3:"Phi";s:2:"Φ";s:3:"Chi";s:2:"Χ";s:3:"Psi";s:2:"Ψ";s:5:"Omega";s:2:"Ω";s:5:"alpha";s:2:"α";s:4:"beta";s:2:"β";s:5:"gamma";s:2:"γ";s:5:"delta";s:2:"δ";s:7:"epsilon";s:2:"ε";s:4:"zeta";s:2:"ζ";s:3:"eta";s:2:"η";s:5:"theta";s:2:"θ";s:4:"iota";s:2:"ι";s:5:"kappa";s:2:"κ";s:6:"lambda";s:2:"λ";s:2:"mu";s:2:"μ";s:2:"nu";s:2:"ν";s:2:"xi";s:2:"ξ";s:7:"omicron";s:2:"ο";s:2:"pi";s:2:"π";s:3:"rho";s:2:"ρ";s:6:"sigmaf";s:2:"ς";s:5:"sigma";s:2:"σ";s:3:"tau";s:2:"τ";s:7:"upsilon";s:2:"υ";s:3:"phi";s:2:"φ";s:3:"chi";s:2:"χ";s:3:"psi";s:2:"ψ";s:5:"omega";s:2:"ω";s:8:"thetasym";s:2:"ϑ";s:5:"upsih";s:2:"ϒ";s:3:"piv";s:2:"ϖ";s:4:"bull";s:3:"•";s:6:"hellip";s:3:"…";s:5:"prime";s:3:"′";s:5:"Prime";s:3:"″";s:5:"oline";s:3:"‾";s:5:"frasl";s:3:"⁄";s:6:"weierp";s:3:"℘";s:5:"image";s:3:"ℑ";s:4:"real";s:3:"ℜ";s:5:"trade";s:3:"™";s:7:"alefsym";s:3:"ℵ";s:4:"larr";s:3:"←";s:4:"uarr";s:3:"↑";s:4:"rarr";s:3:"→";s:4:"darr";s:3:"↓";s:4:"harr";s:3:"↔";s:5:"crarr";s:3:"↵";s:4:"lArr";s:3:"⇐";s:4:"uArr";s:3:"⇑";s:4:"rArr";s:3:"⇒";s:4:"dArr";s:3:"⇓";s:4:"hArr";s:3:"⇔";s:6:"forall";s:3:"∀";s:4:"part";s:3:"∂";s:5:"exist";s:3:"∃";s:5:"empty";s:3:"∅";s:5:"nabla";s:3:"∇";s:4:"isin";s:3:"∈";s:5:"notin";s:3:"∉";s:2:"ni";s:3:"∋";s:4:"prod";s:3:"∏";s:3:"sum";s:3:"∑";s:5:"minus";s:3:"−";s:6:"lowast";s:3:"∗";s:5:"radic";s:3:"√";s:4:"prop";s:3:"∝";s:5:"infin";s:3:"∞";s:3:"ang";s:3:"∠";s:3:"and";s:3:"∧";s:2:"or";s:3:"∨";s:3:"cap";s:3:"∩";s:3:"cup";s:3:"∪";s:3:"int";s:3:"∫";s:3:"sim";s:3:"∼";s:4:"cong";s:3:"≅";s:5:"asymp";s:3:"≈";s:2:"ne";s:3:"≠";s:5:"equiv";s:3:"≡";s:2:"le";s:3:"≤";s:2:"ge";s:3:"≥";s:3:"sub";s:3:"⊂";s:3:"sup";s:3:"⊃";s:4:"nsub";s:3:"⊄";s:4:"sube";s:3:"⊆";s:4:"supe";s:3:"⊇";s:5:"oplus";s:3:"⊕";s:6:"otimes";s:3:"⊗";s:4:"perp";s:3:"⊥";s:4:"sdot";s:3:"⋅";s:5:"lceil";s:3:"⌈";s:5:"rceil";s:3:"⌉";s:6:"lfloor";s:3:"⌊";s:6:"rfloor";s:3:"⌋";s:4:"lang";s:3:"〈";s:4:"rang";s:3:"〉";s:3:"loz";s:3:"◊";s:6:"spades";s:3:"♠";s:5:"clubs";s:3:"♣";s:6:"hearts";s:3:"♥";s:5:"diams";s:3:"♦";}
\ No newline at end of file
diff --git a/library/HTMLPurifier/Filter/ExtractStyleBlocks.php b/library/HTMLPurifier/Filter/ExtractStyleBlocks.php
deleted file mode 100644
index bbf78a6630..0000000000
--- a/library/HTMLPurifier/Filter/ExtractStyleBlocks.php
+++ /dev/null
@@ -1,135 +0,0 @@
-<?php
-
-/**
- * This filter extracts <style> blocks from input HTML, cleans them up
- * using CSSTidy, and then places them in $purifier->context->get('StyleBlocks')
- * so they can be used elsewhere in the document.
- *
- * @note
- *      See tests/HTMLPurifier/Filter/ExtractStyleBlocksTest.php for
- *      sample usage.
- *
- * @note
- *      This filter can also be used on stylesheets not included in the
- *      document--something purists would probably prefer. Just directly
- *      call HTMLPurifier_Filter_ExtractStyleBlocks->cleanCSS()
- */
-class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
-{
-
-    public $name = 'ExtractStyleBlocks';
-    private $_styleMatches = array();
-    private $_tidy;
-
-    public function __construct() {
-        $this->_tidy = new csstidy();
-    }
-
-    /**
-     * Save the contents of CSS blocks to style matches
-     * @param $matches preg_replace style $matches array
-     */
-    protected function styleCallback($matches) {
-        $this->_styleMatches[] = $matches[1];
-    }
-
-    /**
-     * Removes inline <style> tags from HTML, saves them for later use
-     * @todo Extend to indicate non-text/css style blocks
-     */
-    public function preFilter($html, $config, $context) {
-        $tidy = $config->get('Filter.ExtractStyleBlocks.TidyImpl');
-        if ($tidy !== null) $this->_tidy = $tidy;
-        $html = preg_replace_callback('#<style(?:\s.*)?>(.+)</style>#isU', array($this, 'styleCallback'), $html);
-        $style_blocks = $this->_styleMatches;
-        $this->_styleMatches = array(); // reset
-        $context->register('StyleBlocks', $style_blocks); // $context must not be reused
-        if ($this->_tidy) {
-            foreach ($style_blocks as &$style) {
-                $style = $this->cleanCSS($style, $config, $context);
-            }
-        }
-        return $html;
-    }
-
-    /**
-     * Takes CSS (the stuff found in <style>) and cleans it.
-     * @warning Requires CSSTidy <http://csstidy.sourceforge.net/>
-     * @param $css     CSS styling to clean
-     * @param $config  Instance of HTMLPurifier_Config
-     * @param $context Instance of HTMLPurifier_Context
-     * @return Cleaned CSS
-     */
-    public function cleanCSS($css, $config, $context) {
-        // prepare scope
-        $scope = $config->get('Filter.ExtractStyleBlocks.Scope');
-        if ($scope !== null) {
-            $scopes = array_map('trim', explode(',', $scope));
-        } else {
-            $scopes = array();
-        }
-        // remove comments from CSS
-        $css = trim($css);
-        if (strncmp('<!--', $css, 4) === 0) {
-            $css = substr($css, 4);
-        }
-        if (strlen($css) > 3 && substr($css, -3) == '-->') {
-            $css = substr($css, 0, -3);
-        }
-        $css = trim($css);
-        $this->_tidy->parse($css);
-        $css_definition = $config->getDefinition('CSS');
-        foreach ($this->_tidy->css as $k => $decls) {
-            // $decls are all CSS declarations inside an @ selector
-            $new_decls = array();
-            foreach ($decls as $selector => $style) {
-                $selector = trim($selector);
-                if ($selector === '') continue; // should not happen
-                if ($selector[0] === '+') {
-                    if ($selector !== '' && $selector[0] === '+') continue;
-                }
-                if (!empty($scopes)) {
-                    $new_selector = array(); // because multiple ones are possible
-                    $selectors = array_map('trim', explode(',', $selector));
-                    foreach ($scopes as $s1) {
-                        foreach ($selectors as $s2) {
-                            $new_selector[] = "$s1 $s2";
-                        }
-                    }
-                    $selector = implode(', ', $new_selector); // now it's a string
-                }
-                foreach ($style as $name => $value) {
-                    if (!isset($css_definition->info[$name])) {
-                        unset($style[$name]);
-                        continue;
-                    }
-                    $def = $css_definition->info[$name];
-                    $ret = $def->validate($value, $config, $context);
-                    if ($ret === false) unset($style[$name]);
-                    else $style[$name] = $ret;
-                }
-                $new_decls[$selector] = $style;
-            }
-            $this->_tidy->css[$k] = $new_decls;
-        }
-        // remove stuff that shouldn't be used, could be reenabled
-        // after security risks are analyzed
-        $this->_tidy->import = array();
-        $this->_tidy->charset = null;
-        $this->_tidy->namespace = null;
-        $css = $this->_tidy->print->plain();
-        // we are going to escape any special characters <>& to ensure
-        // that no funny business occurs (i.e. </style> in a font-family prop).
-        if ($config->get('Filter.ExtractStyleBlocks.Escaping')) {
-            $css = str_replace(
-                array('<',    '>',    '&'),
-                array('\3C ', '\3E ', '\26 '),
-                $css
-            );
-        }
-        return $css;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Filter/YouTube.php b/library/HTMLPurifier/Filter/YouTube.php
deleted file mode 100644
index 23df221eaa..0000000000
--- a/library/HTMLPurifier/Filter/YouTube.php
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-
-class HTMLPurifier_Filter_YouTube extends HTMLPurifier_Filter
-{
-
-    public $name = 'YouTube';
-
-    public function preFilter($html, $config, $context) {
-        $pre_regex = '#<object[^>]+>.+?'.
-            'http://www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?</object>#s';
-        $pre_replace = '<span class="youtube-embed">\1</span>';
-        return preg_replace($pre_regex, $pre_replace, $html);
-    }
-
-    public function postFilter($html, $config, $context) {
-        $post_regex = '#<span class="youtube-embed">((?:v|cp)/[A-Za-z0-9\-_=]+)</span>#';
-        return preg_replace_callback($post_regex, array($this, 'postFilterCallback'), $html);
-    }
-
-    protected function armorUrl($url) {
-        return str_replace('--', '-&#45;', $url);
-    }
-
-    protected function postFilterCallback($matches) {
-        $url = $this->armorUrl($matches[1]);
-        return '<object width="425" height="350" type="application/x-shockwave-flash" '.
-            'data="http://www.youtube.com/'.$url.'">'.
-            '<param name="movie" value="http://www.youtube.com/'.$url.'"></param>'.
-            '<!--[if IE]>'.
-            '<embed src="http://www.youtube.com/'.$url.'"'.
-            'type="application/x-shockwave-flash"'.
-            'wmode="transparent" width="425" height="350" />'.
-            '<![endif]-->'.
-            '</object>';
-
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Forms.php b/library/HTMLPurifier/HTMLModule/Forms.php
deleted file mode 100644
index 44c22f6f8b..0000000000
--- a/library/HTMLPurifier/HTMLModule/Forms.php
+++ /dev/null
@@ -1,118 +0,0 @@
-<?php
-
-/**
- * XHTML 1.1 Forms module, defines all form-related elements found in HTML 4.
- */
-class HTMLPurifier_HTMLModule_Forms extends HTMLPurifier_HTMLModule
-{
-    public $name = 'Forms';
-    public $safe = false;
-
-    public $content_sets = array(
-        'Block' => 'Form',
-        'Inline' => 'Formctrl',
-    );
-
-    public function setup($config) {
-        $form = $this->addElement('form', 'Form',
-          'Required: Heading | List | Block | fieldset', 'Common', array(
-            'accept' => 'ContentTypes',
-            'accept-charset' => 'Charsets',
-            'action*' => 'URI',
-            'method' => 'Enum#get,post',
-            // really ContentType, but these two are the only ones used today
-            'enctype' => 'Enum#application/x-www-form-urlencoded,multipart/form-data',
-        ));
-        $form->excludes = array('form' => true);
-
-        $input = $this->addElement('input', 'Formctrl', 'Empty', 'Common', array(
-            'accept' => 'ContentTypes',
-            'accesskey' => 'Character',
-            'alt' => 'Text',
-            'checked' => 'Bool#checked',
-            'disabled' => 'Bool#disabled',
-            'maxlength' => 'Number',
-            'name' => 'CDATA',
-            'readonly' => 'Bool#readonly',
-            'size' => 'Number',
-            'src' => 'URI#embeds',
-            'tabindex' => 'Number',
-            'type' => 'Enum#text,password,checkbox,button,radio,submit,reset,file,hidden,image',
-            'value' => 'CDATA',
-        ));
-        $input->attr_transform_post[] = new HTMLPurifier_AttrTransform_Input();
-
-        $this->addElement('select', 'Formctrl', 'Required: optgroup | option', 'Common', array(
-            'disabled' => 'Bool#disabled',
-            'multiple' => 'Bool#multiple',
-            'name' => 'CDATA',
-            'size' => 'Number',
-            'tabindex' => 'Number',
-        ));
-
-        $this->addElement('option', false, 'Optional: #PCDATA', 'Common', array(
-            'disabled' => 'Bool#disabled',
-            'label' => 'Text',
-            'selected' => 'Bool#selected',
-            'value' => 'CDATA',
-        ));
-        // It's illegal for there to be more than one selected, but not
-        // be multiple. Also, no selected means undefined behavior. This might
-        // be difficult to implement; perhaps an injector, or a context variable.
-
-        $textarea = $this->addElement('textarea', 'Formctrl', 'Optional: #PCDATA', 'Common', array(
-            'accesskey' => 'Character',
-            'cols*' => 'Number',
-            'disabled' => 'Bool#disabled',
-            'name' => 'CDATA',
-            'readonly' => 'Bool#readonly',
-            'rows*' => 'Number',
-            'tabindex' => 'Number',
-        ));
-        $textarea->attr_transform_pre[] = new HTMLPurifier_AttrTransform_Textarea();
-
-        $button = $this->addElement('button', 'Formctrl', 'Optional: #PCDATA | Heading | List | Block | Inline', 'Common', array(
-            'accesskey' => 'Character',
-            'disabled' => 'Bool#disabled',
-            'name' => 'CDATA',
-            'tabindex' => 'Number',
-            'type' => 'Enum#button,submit,reset',
-            'value' => 'CDATA',
-        ));
-
-        // For exclusions, ideally we'd specify content sets, not literal elements
-        $button->excludes = $this->makeLookup(
-            'form', 'fieldset', // Form
-            'input', 'select', 'textarea', 'label', 'button', // Formctrl
-            'a' // as per HTML 4.01 spec, this is omitted by modularization
-        );
-
-        // Extra exclusion: img usemap="" is not permitted within this element.
-        // We'll omit this for now, since we don't have any good way of
-        // indicating it yet.
-
-        // This is HIGHLY user-unfriendly; we need a custom child-def for this
-        $this->addElement('fieldset', 'Form', 'Custom: (#WS?,legend,(Flow|#PCDATA)*)', 'Common');
-
-        $label = $this->addElement('label', 'Formctrl', 'Optional: #PCDATA | Inline', 'Common', array(
-            'accesskey' => 'Character',
-            // 'for' => 'IDREF', // IDREF not implemented, cannot allow
-        ));
-        $label->excludes = array('label' => true);
-
-        $this->addElement('legend', false, 'Optional: #PCDATA | Inline', 'Common', array(
-            'accesskey' => 'Character',
-        ));
-
-        $this->addElement('optgroup', false, 'Required: option', 'Common', array(
-            'disabled' => 'Bool#disabled',
-            'label*' => 'Text',
-        ));
-
-        // Don't forget an injector for <isindex>. This one's a little complex
-        // because it maps to multiple elements.
-
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Tidy/Strict.php b/library/HTMLPurifier/HTMLModule/Tidy/Strict.php
deleted file mode 100644
index c73dc3c4d1..0000000000
--- a/library/HTMLPurifier/HTMLModule/Tidy/Strict.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-class HTMLPurifier_HTMLModule_Tidy_Strict extends HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4
-{
-    public $name = 'Tidy_Strict';
-    public $defaultLevel = 'light';
-
-    public function makeFixes() {
-        $r = parent::makeFixes();
-        $r['blockquote#content_model_type'] = 'strictblockquote';
-        return $r;
-    }
-
-    public $defines_child_def = true;
-    public function getChildDef($def) {
-        if ($def->content_model_type != 'strictblockquote') return parent::getChildDef($def);
-        return new HTMLPurifier_ChildDef_StrictBlockquote($def->content_model);
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Injector/RemoveEmpty.php b/library/HTMLPurifier/Injector/RemoveEmpty.php
deleted file mode 100644
index 638bfca03b..0000000000
--- a/library/HTMLPurifier/Injector/RemoveEmpty.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector
-{
-
-    private $context, $config, $attrValidator, $removeNbsp, $removeNbspExceptions;
-
-    public function prepare($config, $context) {
-        parent::prepare($config, $context);
-        $this->config = $config;
-        $this->context = $context;
-        $this->removeNbsp = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp');
-        $this->removeNbspExceptions = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions');
-        $this->attrValidator = new HTMLPurifier_AttrValidator();
-    }
-
-    public function handleElement(&$token) {
-        if (!$token instanceof HTMLPurifier_Token_Start) return;
-        $next = false;
-        for ($i = $this->inputIndex + 1, $c = count($this->inputTokens); $i < $c; $i++) {
-            $next = $this->inputTokens[$i];
-            if ($next instanceof HTMLPurifier_Token_Text) {
-                if ($next->is_whitespace) continue;
-                if ($this->removeNbsp && !isset($this->removeNbspExceptions[$token->name])) {
-                    $plain = str_replace("\xC2\xA0", "", $next->data);
-                    $isWsOrNbsp = $plain === '' || ctype_space($plain);
-                    if ($isWsOrNbsp) continue;
-                }
-            }
-            break;
-        }
-        if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) {
-            if ($token->name == 'colgroup') return;
-            $this->attrValidator->validateToken($token, $this->config, $this->context);
-            $token->armor['ValidateAttributes'] = true;
-            if (isset($token->attr['id']) || isset($token->attr['name'])) return;
-            $token = $i - $this->inputIndex + 1;
-            for ($b = $this->inputIndex - 1; $b > 0; $b--) {
-                $prev = $this->inputTokens[$b];
-                if ($prev instanceof HTMLPurifier_Token_Text && $prev->is_whitespace) continue;
-                break;
-            }
-            // This is safe because we removed the token that triggered this.
-            $this->rewind($b - 1);
-            return;
-        }
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Language/messages/en.php b/library/HTMLPurifier/Language/messages/en.php
deleted file mode 100644
index 8d7b5736bb..0000000000
--- a/library/HTMLPurifier/Language/messages/en.php
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-
-$fallback = false;
-
-$messages = array(
-
-'HTMLPurifier' => 'HTML Purifier',
-
-// for unit testing purposes
-'LanguageFactoryTest: Pizza' => 'Pizza',
-'LanguageTest: List' => '$1',
-'LanguageTest: Hash' => '$1.Keys; $1.Values',
-
-'Item separator' => ', ',
-'Item separator last' => ' and ', // non-Harvard style
-
-'ErrorCollector: No errors' => 'No errors detected. However, because error reporting is still incomplete, there may have been errors that the error collector was not notified of; please inspect the output HTML carefully.',
-'ErrorCollector: At line'   => ' at line $line',
-'ErrorCollector: Incidental errors'  => 'Incidental errors',
-
-'Lexer: Unclosed comment'      => 'Unclosed comment',
-'Lexer: Unescaped lt'          => 'Unescaped less-than sign (<) should be &lt;',
-'Lexer: Missing gt'            => 'Missing greater-than sign (>), previous less-than sign (<) should be escaped',
-'Lexer: Missing attribute key' => 'Attribute declaration has no key',
-'Lexer: Missing end quote'     => 'Attribute declaration has no end quote',
-'Lexer: Extracted body'        => 'Removed document metadata tags',
-
-'Strategy_RemoveForeignElements: Tag transform'              => '<$1> element transformed into $CurrentToken.Serialized',
-'Strategy_RemoveForeignElements: Missing required attribute' => '$CurrentToken.Compact element missing required attribute $1',
-'Strategy_RemoveForeignElements: Foreign element to text'    => 'Unrecognized $CurrentToken.Serialized tag converted to text',
-'Strategy_RemoveForeignElements: Foreign element removed'    => 'Unrecognized $CurrentToken.Serialized tag removed',
-'Strategy_RemoveForeignElements: Comment removed'            => 'Comment containing "$CurrentToken.Data" removed',
-'Strategy_RemoveForeignElements: Foreign meta element removed' => 'Unrecognized $CurrentToken.Serialized meta tag and all descendants removed',
-'Strategy_RemoveForeignElements: Token removed to end'       => 'Tags and text starting from $1 element where removed to end',
-'Strategy_RemoveForeignElements: Trailing hyphen in comment removed' => 'Trailing hyphen(s) in comment removed',
-'Strategy_RemoveForeignElements: Hyphens in comment collapsed' => 'Double hyphens in comments are not allowed, and were collapsed into single hyphens',
-
-'Strategy_MakeWellFormed: Unnecessary end tag removed' => 'Unnecessary $CurrentToken.Serialized tag removed',
-'Strategy_MakeWellFormed: Unnecessary end tag to text' => 'Unnecessary $CurrentToken.Serialized tag converted to text',
-'Strategy_MakeWellFormed: Tag auto closed'             => '$1.Compact started on line $1.Line auto-closed by $CurrentToken.Compact',
-'Strategy_MakeWellFormed: Tag carryover'               => '$1.Compact started on line $1.Line auto-continued into $CurrentToken.Compact',
-'Strategy_MakeWellFormed: Stray end tag removed'       => 'Stray $CurrentToken.Serialized tag removed',
-'Strategy_MakeWellFormed: Stray end tag to text'       => 'Stray $CurrentToken.Serialized tag converted to text',
-'Strategy_MakeWellFormed: Tag closed by element end'   => '$1.Compact tag started on line $1.Line closed by end of $CurrentToken.Serialized',
-'Strategy_MakeWellFormed: Tag closed by document end'  => '$1.Compact tag started on line $1.Line closed by end of document',
-
-'Strategy_FixNesting: Node removed'          => '$CurrentToken.Compact node removed',
-'Strategy_FixNesting: Node excluded'         => '$CurrentToken.Compact node removed due to descendant exclusion by ancestor element',
-'Strategy_FixNesting: Node reorganized'      => 'Contents of $CurrentToken.Compact node reorganized to enforce its content model',
-'Strategy_FixNesting: Node contents removed' => 'Contents of $CurrentToken.Compact node removed',
-
-'AttrValidator: Attributes transformed' => 'Attributes on $CurrentToken.Compact transformed from $1.Keys to $2.Keys',
-'AttrValidator: Attribute removed' => '$CurrentAttr.Name attribute on $CurrentToken.Compact removed',
-
-);
-
-$errorNames = array(
-    E_ERROR   => 'Error',
-    E_WARNING => 'Warning',
-    E_NOTICE  => 'Notice'
-);
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Lexer/PEARSax3.php b/library/HTMLPurifier/Lexer/PEARSax3.php
deleted file mode 100644
index 1d358c7b6b..0000000000
--- a/library/HTMLPurifier/Lexer/PEARSax3.php
+++ /dev/null
@@ -1,139 +0,0 @@
-<?php
-
-/**
- * Proof-of-concept lexer that uses the PEAR package XML_HTMLSax3 to parse HTML.
- *
- * PEAR, not suprisingly, also has a SAX parser for HTML.  I don't know
- * very much about implementation, but it's fairly well written.  However, that
- * abstraction comes at a price: performance. You need to have it installed,
- * and if the API changes, it might break our adapter. Not sure whether or not
- * it's UTF-8 aware, but it has some entity parsing trouble (in all areas,
- * text and attributes).
- *
- * Quite personally, I don't recommend using the PEAR class, and the defaults
- * don't use it. The unit tests do perform the tests on the SAX parser too, but
- * whatever it does for poorly formed HTML is up to it.
- *
- * @todo Generalize so that XML_HTMLSax is also supported.
- *
- * @warning Entity-resolution inside attributes is broken.
- */
-
-class HTMLPurifier_Lexer_PEARSax3 extends HTMLPurifier_Lexer
-{
-
-    /**
-     * Internal accumulator array for SAX parsers.
-     */
-    protected $tokens = array();
-    protected $last_token_was_empty;
-
-    private $parent_handler;
-    private $stack = array();
-
-    public function tokenizeHTML($string, $config, $context) {
-
-        $this->tokens = array();
-        $this->last_token_was_empty = false;
-
-        $string = $this->normalize($string, $config, $context);
-
-        $this->parent_handler = set_error_handler(array($this, 'muteStrictErrorHandler'));
-
-        $parser = new XML_HTMLSax3();
-        $parser->set_object($this);
-        $parser->set_element_handler('openHandler','closeHandler');
-        $parser->set_data_handler('dataHandler');
-        $parser->set_escape_handler('escapeHandler');
-
-        // doesn't seem to work correctly for attributes
-        $parser->set_option('XML_OPTION_ENTITIES_PARSED', 1);
-
-        $parser->parse($string);
-
-        restore_error_handler();
-
-        return $this->tokens;
-
-    }
-
-    /**
-     * Open tag event handler, interface is defined by PEAR package.
-     */
-    public function openHandler(&$parser, $name, $attrs, $closed) {
-        // entities are not resolved in attrs
-        foreach ($attrs as $key => $attr) {
-            $attrs[$key] = $this->parseData($attr);
-        }
-        if ($closed) {
-            $this->tokens[] = new HTMLPurifier_Token_Empty($name, $attrs);
-            $this->last_token_was_empty = true;
-        } else {
-            $this->tokens[] = new HTMLPurifier_Token_Start($name, $attrs);
-        }
-        $this->stack[] = $name;
-        return true;
-    }
-
-    /**
-     * Close tag event handler, interface is defined by PEAR package.
-     */
-    public function closeHandler(&$parser, $name) {
-        // HTMLSax3 seems to always send empty tags an extra close tag
-        // check and ignore if you see it:
-        // [TESTME] to make sure it doesn't overreach
-        if ($this->last_token_was_empty) {
-            $this->last_token_was_empty = false;
-            return true;
-        }
-        $this->tokens[] = new HTMLPurifier_Token_End($name);
-        if (!empty($this->stack)) array_pop($this->stack);
-        return true;
-    }
-
-    /**
-     * Data event handler, interface is defined by PEAR package.
-     */
-    public function dataHandler(&$parser, $data) {
-        $this->last_token_was_empty = false;
-        $this->tokens[] = new HTMLPurifier_Token_Text($data);
-        return true;
-    }
-
-    /**
-     * Escaped text handler, interface is defined by PEAR package.
-     */
-    public function escapeHandler(&$parser, $data) {
-        if (strpos($data, '--') === 0) {
-            // remove trailing and leading double-dashes
-            $data = substr($data, 2);
-            if (strlen($data) >= 2 && substr($data, -2) == "--") {
-                $data = substr($data, 0, -2);
-            }
-            if (isset($this->stack[sizeof($this->stack) - 1]) &&
-                $this->stack[sizeof($this->stack) - 1] == "style") {
-                $this->tokens[] = new HTMLPurifier_Token_Text($data);
-            } else {
-                $this->tokens[] = new HTMLPurifier_Token_Comment($data);
-            }
-            $this->last_token_was_empty = false;
-        }
-        // CDATA is handled elsewhere, but if it was handled here:
-        //if (strpos($data, '[CDATA[') === 0) {
-        //    $this->tokens[] = new HTMLPurifier_Token_Text(
-        //        substr($data, 7, strlen($data) - 9) );
-        //}
-        return true;
-    }
-
-    /**
-     * An error handler that mutes strict errors
-     */
-    public function muteStrictErrorHandler($errno, $errstr, $errfile=null, $errline=null, $errcontext=null) {
-        if ($errno == E_STRICT) return;
-        return call_user_func($this->parent_handler, $errno, $errstr, $errfile, $errline, $errcontext);
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Lexer/PH5P.php b/library/HTMLPurifier/Lexer/PH5P.php
deleted file mode 100644
index fa1bf973e0..0000000000
--- a/library/HTMLPurifier/Lexer/PH5P.php
+++ /dev/null
@@ -1,3906 +0,0 @@
-<?php
-
-/**
- * Experimental HTML5-based parser using Jeroen van der Meer's PH5P library.
- * Occupies space in the HTML5 pseudo-namespace, which may cause conflicts.
- * 
- * @note
- *    Recent changes to PHP's DOM extension have resulted in some fatal
- *    error conditions with the original version of PH5P. Pending changes,
- *    this lexer will punt to DirectLex if DOM throughs an exception.
- */
-
-class HTMLPurifier_Lexer_PH5P extends HTMLPurifier_Lexer_DOMLex {
-    
-    public function tokenizeHTML($html, $config, $context) {
-        $new_html = $this->normalize($html, $config, $context);
-        $new_html = $this->wrapHTML($new_html, $config, $context);
-        try {
-            $parser = new HTML5($new_html);
-            $doc = $parser->save();
-        } catch (DOMException $e) {
-            // Uh oh, it failed. Punt to DirectLex.
-            $lexer = new HTMLPurifier_Lexer_DirectLex();
-            $context->register('PH5PError', $e); // save the error, so we can detect it
-            return $lexer->tokenizeHTML($html, $config, $context); // use original HTML
-        }
-        $tokens = array();
-        $this->tokenizeDOM(
-            $doc->getElementsByTagName('html')->item(0)-> // <html>
-                  getElementsByTagName('body')->item(0)-> //   <body>
-                  getElementsByTagName('div')->item(0)    //     <div>
-            , $tokens);
-        return $tokens;
-    }
-    
-}
-
-/*
-
-Copyright 2007 Jeroen van der Meer <http://jero.net/> 
-
-Permission is hereby granted, free of charge, to any person obtaining a 
-copy of this software and associated documentation files (the 
-"Software"), to deal in the Software without restriction, including 
-without limitation the rights to use, copy, modify, merge, publish, 
-distribute, sublicense, and/or sell copies of the Software, and to 
-permit persons to whom the Software is furnished to do so, subject to 
-the following conditions: 
-
-The above copyright notice and this permission notice shall be included 
-in all copies or substantial portions of the Software. 
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
-
-*/
-
-class HTML5 {
-    private $data;
-    private $char;
-    private $EOF;
-    private $state;
-    private $tree;
-    private $token;
-    private $content_model;
-    private $escape = false;
-    private $entities = array('AElig;','AElig','AMP;','AMP','Aacute;','Aacute',
-    'Acirc;','Acirc','Agrave;','Agrave','Alpha;','Aring;','Aring','Atilde;',
-    'Atilde','Auml;','Auml','Beta;','COPY;','COPY','Ccedil;','Ccedil','Chi;',
-    'Dagger;','Delta;','ETH;','ETH','Eacute;','Eacute','Ecirc;','Ecirc','Egrave;',
-    'Egrave','Epsilon;','Eta;','Euml;','Euml','GT;','GT','Gamma;','Iacute;',
-    'Iacute','Icirc;','Icirc','Igrave;','Igrave','Iota;','Iuml;','Iuml','Kappa;',
-    'LT;','LT','Lambda;','Mu;','Ntilde;','Ntilde','Nu;','OElig;','Oacute;',
-    'Oacute','Ocirc;','Ocirc','Ograve;','Ograve','Omega;','Omicron;','Oslash;',
-    'Oslash','Otilde;','Otilde','Ouml;','Ouml','Phi;','Pi;','Prime;','Psi;',
-    'QUOT;','QUOT','REG;','REG','Rho;','Scaron;','Sigma;','THORN;','THORN',
-    'TRADE;','Tau;','Theta;','Uacute;','Uacute','Ucirc;','Ucirc','Ugrave;',
-    'Ugrave','Upsilon;','Uuml;','Uuml','Xi;','Yacute;','Yacute','Yuml;','Zeta;',
-    'aacute;','aacute','acirc;','acirc','acute;','acute','aelig;','aelig',
-    'agrave;','agrave','alefsym;','alpha;','amp;','amp','and;','ang;','apos;',
-    'aring;','aring','asymp;','atilde;','atilde','auml;','auml','bdquo;','beta;',
-    'brvbar;','brvbar','bull;','cap;','ccedil;','ccedil','cedil;','cedil',
-    'cent;','cent','chi;','circ;','clubs;','cong;','copy;','copy','crarr;',
-    'cup;','curren;','curren','dArr;','dagger;','darr;','deg;','deg','delta;',
-    'diams;','divide;','divide','eacute;','eacute','ecirc;','ecirc','egrave;',
-    'egrave','empty;','emsp;','ensp;','epsilon;','equiv;','eta;','eth;','eth',
-    'euml;','euml','euro;','exist;','fnof;','forall;','frac12;','frac12',
-    'frac14;','frac14','frac34;','frac34','frasl;','gamma;','ge;','gt;','gt',
-    'hArr;','harr;','hearts;','hellip;','iacute;','iacute','icirc;','icirc',
-    'iexcl;','iexcl','igrave;','igrave','image;','infin;','int;','iota;',
-    'iquest;','iquest','isin;','iuml;','iuml','kappa;','lArr;','lambda;','lang;',
-    'laquo;','laquo','larr;','lceil;','ldquo;','le;','lfloor;','lowast;','loz;',
-    'lrm;','lsaquo;','lsquo;','lt;','lt','macr;','macr','mdash;','micro;','micro',
-    'middot;','middot','minus;','mu;','nabla;','nbsp;','nbsp','ndash;','ne;',
-    'ni;','not;','not','notin;','nsub;','ntilde;','ntilde','nu;','oacute;',
-    'oacute','ocirc;','ocirc','oelig;','ograve;','ograve','oline;','omega;',
-    'omicron;','oplus;','or;','ordf;','ordf','ordm;','ordm','oslash;','oslash',
-    'otilde;','otilde','otimes;','ouml;','ouml','para;','para','part;','permil;',
-    'perp;','phi;','pi;','piv;','plusmn;','plusmn','pound;','pound','prime;',
-    'prod;','prop;','psi;','quot;','quot','rArr;','radic;','rang;','raquo;',
-    'raquo','rarr;','rceil;','rdquo;','real;','reg;','reg','rfloor;','rho;',
-    'rlm;','rsaquo;','rsquo;','sbquo;','scaron;','sdot;','sect;','sect','shy;',
-    'shy','sigma;','sigmaf;','sim;','spades;','sub;','sube;','sum;','sup1;',
-    'sup1','sup2;','sup2','sup3;','sup3','sup;','supe;','szlig;','szlig','tau;',
-    'there4;','theta;','thetasym;','thinsp;','thorn;','thorn','tilde;','times;',
-    'times','trade;','uArr;','uacute;','uacute','uarr;','ucirc;','ucirc',
-    'ugrave;','ugrave','uml;','uml','upsih;','upsilon;','uuml;','uuml','weierp;',
-    'xi;','yacute;','yacute','yen;','yen','yuml;','yuml','zeta;','zwj;','zwnj;');
-
-    const PCDATA    = 0;
-    const RCDATA    = 1;
-    const CDATA     = 2;
-    const PLAINTEXT = 3;
-
-    const DOCTYPE  = 0;
-    const STARTTAG = 1;
-    const ENDTAG   = 2;
-    const COMMENT  = 3;
-    const CHARACTR = 4;
-    const EOF      = 5;
-
-    public function __construct($data) {
-        $data = str_replace("\r\n", "\n", $data);
-        $data = str_replace("\r", null, $data);
-
-        $this->data = $data;
-        $this->char = -1;
-        $this->EOF  = strlen($data);
-        $this->tree = new HTML5TreeConstructer;
-        $this->content_model = self::PCDATA;
-
-        $this->state = 'data';
-
-        while($this->state !== null) {
-            $this->{$this->state.'State'}();
-        }
-    }
-
-    public function save() {
-        return $this->tree->save();
-    }
-
-    private function char() {
-        return ($this->char < $this->EOF)
-            ? $this->data[$this->char]
-            : false;
-    }
-
-    private function character($s, $l = 0) {
-        if($s + $l < $this->EOF) {
-            if($l === 0) {
-                return $this->data[$s];
-            } else {
-                return substr($this->data, $s, $l);
-            }
-        }
-    }
-
-    private function characters($char_class, $start) {
-        return preg_replace('#^(['.$char_class.']+).*#s', '\\1', substr($this->data, $start));
-    }
-
-    private function dataState() {
-        // Consume the next input character
-        $this->char++;
-        $char = $this->char();
-
-        if($char === '&' && ($this->content_model === self::PCDATA || $this->content_model === self::RCDATA)) {
-            /* U+0026 AMPERSAND (&)
-            When the content model flag is set to one of the PCDATA or RCDATA
-            states: switch to the entity data state. Otherwise: treat it as per
-            the "anything else"    entry below. */
-            $this->state = 'entityData';
-
-        } elseif($char === '-') {
-            /* If the content model flag is set to either the RCDATA state or
-            the CDATA state, and the escape flag is false, and there are at
-            least three characters before this one in the input stream, and the
-            last four characters in the input stream, including this one, are
-            U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+002D HYPHEN-MINUS,
-            and U+002D HYPHEN-MINUS ("<!--"), then set the escape flag to true. */
-            if(($this->content_model === self::RCDATA || $this->content_model ===
-            self::CDATA) && $this->escape === false &&
-            $this->char >= 3 && $this->character($this->char - 4, 4) === '<!--') {
-                $this->escape = true;
-            }
-
-            /* In any case, emit the input character as a character token. Stay
-            in the data state. */
-            $this->emitToken(array(
-                'type' => self::CHARACTR,
-                'data' => $char
-            ));
-
-        /* U+003C LESS-THAN SIGN (<) */
-        } elseif($char === '<' && ($this->content_model === self::PCDATA ||
-        (($this->content_model === self::RCDATA ||
-        $this->content_model === self::CDATA) && $this->escape === false))) {
-            /* When the content model flag is set to the PCDATA state: switch
-            to the tag open state.
-
-            When the content model flag is set to either the RCDATA state or
-            the CDATA state and the escape flag is false: switch to the tag
-            open state.
-
-            Otherwise: treat it as per the "anything else" entry below. */
-            $this->state = 'tagOpen';
-
-        /* U+003E GREATER-THAN SIGN (>) */
-        } elseif($char === '>') {
-            /* If the content model flag is set to either the RCDATA state or
-            the CDATA state, and the escape flag is true, and the last three
-            characters in the input stream including this one are U+002D
-            HYPHEN-MINUS, U+002D HYPHEN-MINUS, U+003E GREATER-THAN SIGN ("-->"),
-            set the escape flag to false. */
-            if(($this->content_model === self::RCDATA ||
-            $this->content_model === self::CDATA) && $this->escape === true &&
-            $this->character($this->char, 3) === '-->') {
-                $this->escape = false;
-            }
-
-            /* In any case, emit the input character as a character token.
-            Stay in the data state. */
-            $this->emitToken(array(
-                'type' => self::CHARACTR,
-                'data' => $char
-            ));
-
-        } elseif($this->char === $this->EOF) {
-            /* EOF
-            Emit an end-of-file token. */
-            $this->EOF();
-
-        } elseif($this->content_model === self::PLAINTEXT) {
-            /* When the content model flag is set to the PLAINTEXT state
-            THIS DIFFERS GREATLY FROM THE SPEC: Get the remaining characters of
-            the text and emit it as a character token. */
-            $this->emitToken(array(
-                'type' => self::CHARACTR,
-                'data' => substr($this->data, $this->char)
-            ));
-
-            $this->EOF();
-
-        } else {
-            /* Anything else
-            THIS DIFFERS GREATLY FROM THE SPEC: Get as many character that
-            otherwise would also be treated as a character token and emit it
-            as a single character token. Stay in the data state. */
-            $len  = strcspn($this->data, '<&', $this->char);
-            $char = substr($this->data, $this->char, $len);
-            $this->char += $len - 1;
-
-            $this->emitToken(array(
-                'type' => self::CHARACTR,
-                'data' => $char
-            ));
-
-            $this->state = 'data';
-        }
-    }
-
-    private function entityDataState() {
-        // Attempt to consume an entity.
-        $entity = $this->entity();
-
-        // If nothing is returned, emit a U+0026 AMPERSAND character token.
-        // Otherwise, emit the character token that was returned.
-        $char = (!$entity) ? '&' : $entity;
-        $this->emitToken(array(
-            'type' => self::CHARACTR,
-            'data' => $char
-        ));
-
-        // Finally, switch to the data state.
-        $this->state = 'data';
-    }
-
-    private function tagOpenState() {
-        switch($this->content_model) {
-            case self::RCDATA:
-            case self::CDATA:
-                /* If the next input character is a U+002F SOLIDUS (/) character,
-                consume it and switch to the close tag open state. If the next
-                input character is not a U+002F SOLIDUS (/) character, emit a
-                U+003C LESS-THAN SIGN character token and switch to the data
-                state to process the next input character. */
-                if($this->character($this->char + 1) === '/') {
-                    $this->char++;
-                    $this->state = 'closeTagOpen';
-
-                } else {
-                    $this->emitToken(array(
-                        'type' => self::CHARACTR,
-                        'data' => '<'
-                    ));
-
-                    $this->state = 'data';
-                }
-            break;
-
-            case self::PCDATA:
-                // If the content model flag is set to the PCDATA state
-                // Consume the next input character:
-                $this->char++;
-                $char = $this->char();
-
-                if($char === '!') {
-                    /* U+0021 EXCLAMATION MARK (!)
-                    Switch to the markup declaration open state. */
-                    $this->state = 'markupDeclarationOpen';
-
-                } elseif($char === '/') {
-                    /* U+002F SOLIDUS (/)
-                    Switch to the close tag open state. */
-                    $this->state = 'closeTagOpen';
-
-                } elseif(preg_match('/^[A-Za-z]$/', $char)) {
-                    /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z
-                    Create a new start tag token, set its tag name to the lowercase
-                    version of the input character (add 0x0020 to the character's code
-                    point), then switch to the tag name state. (Don't emit the token
-                    yet; further details will be filled in before it is emitted.) */
-                    $this->token = array(
-                        'name'  => strtolower($char),
-                        'type'  => self::STARTTAG,
-                        'attr'  => array()
-                    );
-
-                    $this->state = 'tagName';
-
-                } elseif($char === '>') {
-                    /* U+003E GREATER-THAN SIGN (>)
-                    Parse error. Emit a U+003C LESS-THAN SIGN character token and a
-                    U+003E GREATER-THAN SIGN character token. Switch to the data state. */
-                    $this->emitToken(array(
-                        'type' => self::CHARACTR,
-                        'data' => '<>'
-                    ));
-
-                    $this->state = 'data';
-
-                } elseif($char === '?') {
-                    /* U+003F QUESTION MARK (?)
-                    Parse error. Switch to the bogus comment state. */
-                    $this->state = 'bogusComment';
-
-                } else {
-                    /* Anything else
-                    Parse error. Emit a U+003C LESS-THAN SIGN character token and
-                    reconsume the current input character in the data state. */
-                    $this->emitToken(array(
-                        'type' => self::CHARACTR,
-                        'data' => '<'
-                    ));
-
-                    $this->char--;
-                    $this->state = 'data';
-                }
-            break;
-        }
-    }
-
-    private function closeTagOpenState() {
-        $next_node = strtolower($this->characters('A-Za-z', $this->char + 1));
-        $the_same = count($this->tree->stack) > 0 && $next_node === end($this->tree->stack)->nodeName;
-
-        if(($this->content_model === self::RCDATA || $this->content_model === self::CDATA) &&
-        (!$the_same || ($the_same && (!preg_match('/[\t\n\x0b\x0c >\/]/',
-        $this->character($this->char + 1 + strlen($next_node))) || $this->EOF === $this->char)))) {
-            /* If the content model flag is set to the RCDATA or CDATA states then
-            examine the next few characters. If they do not match the tag name of
-            the last start tag token emitted (case insensitively), or if they do but
-            they are not immediately followed by one of the following characters:
-                * U+0009 CHARACTER TABULATION
-                * U+000A LINE FEED (LF)
-                * U+000B LINE TABULATION
-                * U+000C FORM FEED (FF)
-                * U+0020 SPACE
-                * U+003E GREATER-THAN SIGN (>)
-                * U+002F SOLIDUS (/)
-                * EOF
-            ...then there is a parse error. Emit a U+003C LESS-THAN SIGN character
-            token, a U+002F SOLIDUS character token, and switch to the data state
-            to process the next input character. */
-            $this->emitToken(array(
-                'type' => self::CHARACTR,
-                'data' => '</'
-            ));
-
-            $this->state = 'data';
-
-        } else {
-            /* Otherwise, if the content model flag is set to the PCDATA state,
-            or if the next few characters do match that tag name, consume the
-            next input character: */
-            $this->char++;
-            $char = $this->char();
-
-            if(preg_match('/^[A-Za-z]$/', $char)) {
-                /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z
-                Create a new end tag token, set its tag name to the lowercase version
-                of the input character (add 0x0020 to the character's code point), then
-                switch to the tag name state. (Don't emit the token yet; further details
-                will be filled in before it is emitted.) */
-                $this->token = array(
-                    'name'  => strtolower($char),
-                    'type'  => self::ENDTAG
-                );
-
-                $this->state = 'tagName';
-
-            } elseif($char === '>') {
-                /* U+003E GREATER-THAN SIGN (>)
-                Parse error. Switch to the data state. */
-                $this->state = 'data';
-
-            } elseif($this->char === $this->EOF) {
-                /* EOF
-                Parse error. Emit a U+003C LESS-THAN SIGN character token and a U+002F
-                SOLIDUS character token. Reconsume the EOF character in the data state. */
-                $this->emitToken(array(
-                    'type' => self::CHARACTR,
-                    'data' => '</'
-                ));
-
-                $this->char--;
-                $this->state = 'data';
-
-            } else {
-                /* Parse error. Switch to the bogus comment state. */
-                $this->state = 'bogusComment';
-            }
-        }
-    }
-
-    private function tagNameState() {
-        // Consume the next input character:
-        $this->char++;
-        $char = $this->character($this->char);
-
-        if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
-            /* U+0009 CHARACTER TABULATION
-            U+000A LINE FEED (LF)
-            U+000B LINE TABULATION
-            U+000C FORM FEED (FF)
-            U+0020 SPACE
-            Switch to the before attribute name state. */
-            $this->state = 'beforeAttributeName';
-
-        } elseif($char === '>') {
-            /* U+003E GREATER-THAN SIGN (>)
-            Emit the current tag token. Switch to the data state. */
-            $this->emitToken($this->token);
-            $this->state = 'data';
-
-        } elseif($this->char === $this->EOF) {
-            /* EOF
-            Parse error. Emit the current tag token. Reconsume the EOF
-            character in the data state. */
-            $this->emitToken($this->token);
-
-            $this->char--;
-            $this->state = 'data';
-
-        } elseif($char === '/') {
-            /* U+002F SOLIDUS (/)
-            Parse error unless this is a permitted slash. Switch to the before
-            attribute name state. */
-            $this->state = 'beforeAttributeName';
-
-        } else {
-            /* Anything else
-            Append the current input character to the current tag token's tag name.
-            Stay in the tag name state. */
-            $this->token['name'] .= strtolower($char);
-            $this->state = 'tagName';
-        }
-    }
-
-    private function beforeAttributeNameState() {
-        // Consume the next input character:
-        $this->char++;
-        $char = $this->character($this->char);
-
-        if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
-            /* U+0009 CHARACTER TABULATION
-            U+000A LINE FEED (LF)
-            U+000B LINE TABULATION
-            U+000C FORM FEED (FF)
-            U+0020 SPACE
-            Stay in the before attribute name state. */
-            $this->state = 'beforeAttributeName';
-
-        } elseif($char === '>') {
-            /* U+003E GREATER-THAN SIGN (>)
-            Emit the current tag token. Switch to the data state. */
-            $this->emitToken($this->token);
-            $this->state = 'data';
-
-        } elseif($char === '/') {
-            /* U+002F SOLIDUS (/)
-            Parse error unless this is a permitted slash. Stay in the before
-            attribute name state. */
-            $this->state = 'beforeAttributeName';
-
-        } elseif($this->char === $this->EOF) {
-            /* EOF
-            Parse error. Emit the current tag token. Reconsume the EOF
-            character in the data state. */
-            $this->emitToken($this->token);
-
-            $this->char--;
-            $this->state = 'data';
-
-        } else {
-            /* Anything else
-            Start a new attribute in the current tag token. Set that attribute's
-            name to the current input character, and its value to the empty string.
-            Switch to the attribute name state. */
-            $this->token['attr'][] = array(
-                'name'  => strtolower($char),
-                'value' => null
-            );
-
-            $this->state = 'attributeName';
-        }
-    }
-
-    private function attributeNameState() {
-        // Consume the next input character:
-        $this->char++;
-        $char = $this->character($this->char);
-
-        if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
-            /* U+0009 CHARACTER TABULATION
-            U+000A LINE FEED (LF)
-            U+000B LINE TABULATION
-            U+000C FORM FEED (FF)
-            U+0020 SPACE
-            Stay in the before attribute name state. */
-            $this->state = 'afterAttributeName';
-
-        } elseif($char === '=') {
-            /* U+003D EQUALS SIGN (=)
-            Switch to the before attribute value state. */
-            $this->state = 'beforeAttributeValue';
-
-        } elseif($char === '>') {
-            /* U+003E GREATER-THAN SIGN (>)
-            Emit the current tag token. Switch to the data state. */
-            $this->emitToken($this->token);
-            $this->state = 'data';
-
-        } elseif($char === '/' && $this->character($this->char + 1) !== '>') {
-            /* U+002F SOLIDUS (/)
-            Parse error unless this is a permitted slash. Switch to the before
-            attribute name state. */
-            $this->state = 'beforeAttributeName';
-
-        } elseif($this->char === $this->EOF) {
-            /* EOF
-            Parse error. Emit the current tag token. Reconsume the EOF
-            character in the data state. */
-            $this->emitToken($this->token);
-
-            $this->char--;
-            $this->state = 'data';
-
-        } else {
-            /* Anything else
-            Append the current input character to the current attribute's name.
-            Stay in the attribute name state. */
-            $last = count($this->token['attr']) - 1;
-            $this->token['attr'][$last]['name'] .= strtolower($char);
-
-            $this->state = 'attributeName';
-        }
-    }
-
-    private function afterAttributeNameState() {
-        // Consume the next input character:
-        $this->char++;
-        $char = $this->character($this->char);
-
-        if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
-            /* U+0009 CHARACTER TABULATION
-            U+000A LINE FEED (LF)
-            U+000B LINE TABULATION
-            U+000C FORM FEED (FF)
-            U+0020 SPACE
-            Stay in the after attribute name state. */
-            $this->state = 'afterAttributeName';
-
-        } elseif($char === '=') {
-            /* U+003D EQUALS SIGN (=)
-            Switch to the before attribute value state. */
-            $this->state = 'beforeAttributeValue';
-
-        } elseif($char === '>') {
-            /* U+003E GREATER-THAN SIGN (>)
-            Emit the current tag token. Switch to the data state. */
-            $this->emitToken($this->token);
-            $this->state = 'data';
-
-        } elseif($char === '/' && $this->character($this->char + 1) !== '>') {
-            /* U+002F SOLIDUS (/)
-            Parse error unless this is a permitted slash. Switch to the
-            before attribute name state. */
-            $this->state = 'beforeAttributeName';
-
-        } elseif($this->char === $this->EOF) {
-            /* EOF
-            Parse error. Emit the current tag token. Reconsume the EOF
-            character in the data state. */
-            $this->emitToken($this->token);
-
-            $this->char--;
-            $this->state = 'data';
-
-        } else {
-            /* Anything else
-            Start a new attribute in the current tag token. Set that attribute's
-            name to the current input character, and its value to the empty string.
-            Switch to the attribute name state. */
-            $this->token['attr'][] = array(
-                'name'  => strtolower($char),
-                'value' => null
-            );
-
-            $this->state = 'attributeName';
-        }
-    }
-
-    private function beforeAttributeValueState() {
-        // Consume the next input character:
-        $this->char++;
-        $char = $this->character($this->char);
-
-        if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
-            /* U+0009 CHARACTER TABULATION
-            U+000A LINE FEED (LF)
-            U+000B LINE TABULATION
-            U+000C FORM FEED (FF)
-            U+0020 SPACE
-            Stay in the before attribute value state. */
-            $this->state = 'beforeAttributeValue';
-
-        } elseif($char === '"') {
-            /* U+0022 QUOTATION MARK (")
-            Switch to the attribute value (double-quoted) state. */
-            $this->state = 'attributeValueDoubleQuoted';
-
-        } elseif($char === '&') {
-            /* U+0026 AMPERSAND (&)
-            Switch to the attribute value (unquoted) state and reconsume
-            this input character. */
-            $this->char--;
-            $this->state = 'attributeValueUnquoted';
-
-        } elseif($char === '\'') {
-            /* U+0027 APOSTROPHE (')
-            Switch to the attribute value (single-quoted) state. */
-            $this->state = 'attributeValueSingleQuoted';
-
-        } elseif($char === '>') {
-            /* U+003E GREATER-THAN SIGN (>)
-            Emit the current tag token. Switch to the data state. */
-            $this->emitToken($this->token);
-            $this->state = 'data';
-
-        } else {
-            /* Anything else
-            Append the current input character to the current attribute's value.
-            Switch to the attribute value (unquoted) state. */
-            $last = count($this->token['attr']) - 1;
-            $this->token['attr'][$last]['value'] .= $char;
-
-            $this->state = 'attributeValueUnquoted';
-        }
-    }
-
-    private function attributeValueDoubleQuotedState() {
-        // Consume the next input character:
-        $this->char++;
-        $char = $this->character($this->char);
-
-        if($char === '"') {
-            /* U+0022 QUOTATION MARK (")
-            Switch to the before attribute name state. */
-            $this->state = 'beforeAttributeName';
-
-        } elseif($char === '&') {
-            /* U+0026 AMPERSAND (&)
-            Switch to the entity in attribute value state. */
-            $this->entityInAttributeValueState('double');
-
-        } elseif($this->char === $this->EOF) {
-            /* EOF
-            Parse error. Emit the current tag token. Reconsume the character
-            in the data state. */
-            $this->emitToken($this->token);
-
-            $this->char--;
-            $this->state = 'data';
-
-        } else {
-            /* Anything else
-            Append the current input character to the current attribute's value.
-            Stay in the attribute value (double-quoted) state. */
-            $last = count($this->token['attr']) - 1;
-            $this->token['attr'][$last]['value'] .= $char;
-
-            $this->state = 'attributeValueDoubleQuoted';
-        }
-    }
-
-    private function attributeValueSingleQuotedState() {
-        // Consume the next input character:
-        $this->char++;
-        $char = $this->character($this->char);
-
-        if($char === '\'') {
-            /* U+0022 QUOTATION MARK (')
-            Switch to the before attribute name state. */
-            $this->state = 'beforeAttributeName';
-
-        } elseif($char === '&') {
-            /* U+0026 AMPERSAND (&)
-            Switch to the entity in attribute value state. */
-            $this->entityInAttributeValueState('single');
-
-        } elseif($this->char === $this->EOF) {
-            /* EOF
-            Parse error. Emit the current tag token. Reconsume the character
-            in the data state. */
-            $this->emitToken($this->token);
-
-            $this->char--;
-            $this->state = 'data';
-
-        } else {
-            /* Anything else
-            Append the current input character to the current attribute's value.
-            Stay in the attribute value (single-quoted) state. */
-            $last = count($this->token['attr']) - 1;
-            $this->token['attr'][$last]['value'] .= $char;
-
-            $this->state = 'attributeValueSingleQuoted';
-        }
-    }
-
-    private function attributeValueUnquotedState() {
-        // Consume the next input character:
-        $this->char++;
-        $char = $this->character($this->char);
-
-        if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
-            /* U+0009 CHARACTER TABULATION
-            U+000A LINE FEED (LF)
-            U+000B LINE TABULATION
-            U+000C FORM FEED (FF)
-            U+0020 SPACE
-            Switch to the before attribute name state. */
-            $this->state = 'beforeAttributeName';
-
-        } elseif($char === '&') {
-            /* U+0026 AMPERSAND (&)
-            Switch to the entity in attribute value state. */
-            $this->entityInAttributeValueState();
-
-        } elseif($char === '>') {
-            /* U+003E GREATER-THAN SIGN (>)
-            Emit the current tag token. Switch to the data state. */
-            $this->emitToken($this->token);
-            $this->state = 'data';
-
-        } else {
-            /* Anything else
-            Append the current input character to the current attribute's value.
-            Stay in the attribute value (unquoted) state. */
-            $last = count($this->token['attr']) - 1;
-            $this->token['attr'][$last]['value'] .= $char;
-
-            $this->state = 'attributeValueUnquoted';
-        }
-    }
-
-    private function entityInAttributeValueState() {
-        // Attempt to consume an entity.
-        $entity = $this->entity();
-
-        // If nothing is returned, append a U+0026 AMPERSAND character to the
-        // current attribute's value. Otherwise, emit the character token that
-        // was returned.
-        $char = (!$entity)
-            ? '&'
-            : $entity;
-
-        $last = count($this->token['attr']) - 1;
-        $this->token['attr'][$last]['value'] .= $char;
-    }
-
-    private function bogusCommentState() {
-        /* Consume every character up to the first U+003E GREATER-THAN SIGN
-        character (>) or the end of the file (EOF), whichever comes first. Emit
-        a comment token whose data is the concatenation of all the characters
-        starting from and including the character that caused the state machine
-        to switch into the bogus comment state, up to and including the last
-        consumed character before the U+003E character, if any, or up to the
-        end of the file otherwise. (If the comment was started by the end of
-        the file (EOF), the token is empty.) */
-        $data = $this->characters('^>', $this->char);
-        $this->emitToken(array(
-            'data' => $data,
-            'type' => self::COMMENT
-        ));
-
-        $this->char += strlen($data);
-
-        /* Switch to the data state. */
-        $this->state = 'data';
-
-        /* If the end of the file was reached, reconsume the EOF character. */
-        if($this->char === $this->EOF) {
-            $this->char = $this->EOF - 1;
-        }
-    }
-
-    private function markupDeclarationOpenState() {
-        /* If the next two characters are both U+002D HYPHEN-MINUS (-)
-        characters, consume those two characters, create a comment token whose
-        data is the empty string, and switch to the comment state. */
-        if($this->character($this->char + 1, 2) === '--') {
-            $this->char += 2;
-            $this->state = 'comment';
-            $this->token = array(
-                'data' => null,
-                'type' => self::COMMENT
-            );
-
-        /* Otherwise if the next seven chacacters are a case-insensitive match
-        for the word "DOCTYPE", then consume those characters and switch to the
-        DOCTYPE state. */
-        } elseif(strtolower($this->character($this->char + 1, 7)) === 'doctype') {
-            $this->char += 7;
-            $this->state = 'doctype';
-
-        /* Otherwise, is is a parse error. Switch to the bogus comment state.
-        The next character that is consumed, if any, is the first character
-        that will be in the comment. */
-        } else {
-            $this->char++;
-            $this->state = 'bogusComment';
-        }
-    }
-
-    private function commentState() {
-        /* Consume the next input character: */
-        $this->char++;
-        $char = $this->char();
-
-        /* U+002D HYPHEN-MINUS (-) */
-        if($char === '-') {
-            /* Switch to the comment dash state  */
-            $this->state = 'commentDash';
-
-        /* EOF */
-        } elseif($this->char === $this->EOF) {
-            /* Parse error. Emit the comment token. Reconsume the EOF character
-            in the data state. */
-            $this->emitToken($this->token);
-            $this->char--;
-            $this->state = 'data';
-
-        /* Anything else */
-        } else {
-            /* Append the input character to the comment token's data. Stay in
-            the comment state. */
-            $this->token['data'] .= $char;
-        }
-    }
-
-    private function commentDashState() {
-        /* Consume the next input character: */
-        $this->char++;
-        $char = $this->char();
-
-        /* U+002D HYPHEN-MINUS (-) */
-        if($char === '-') {
-            /* Switch to the comment end state  */
-            $this->state = 'commentEnd';
-
-        /* EOF */
-        } elseif($this->char === $this->EOF) {
-            /* Parse error. Emit the comment token. Reconsume the EOF character
-            in the data state. */
-            $this->emitToken($this->token);
-            $this->char--;
-            $this->state = 'data';
-
-        /* Anything else */
-        } else {
-            /* Append a U+002D HYPHEN-MINUS (-) character and the input
-            character to the comment token's data. Switch to the comment state. */
-            $this->token['data'] .= '-'.$char;
-            $this->state = 'comment';
-        }
-    }
-
-    private function commentEndState() {
-        /* Consume the next input character: */
-        $this->char++;
-        $char = $this->char();
-
-        if($char === '>') {
-            $this->emitToken($this->token);
-            $this->state = 'data';
-
-        } elseif($char === '-') {
-            $this->token['data'] .= '-';
-
-        } elseif($this->char === $this->EOF) {
-            $this->emitToken($this->token);
-            $this->char--;
-            $this->state = 'data';
-
-        } else {
-            $this->token['data'] .= '--'.$char;
-            $this->state = 'comment';
-        }
-    }
-
-    private function doctypeState() {
-        /* Consume the next input character: */
-        $this->char++;
-        $char = $this->char();
-
-        if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
-            $this->state = 'beforeDoctypeName';
-
-        } else {
-            $this->char--;
-            $this->state = 'beforeDoctypeName';
-        }
-    }
-
-    private function beforeDoctypeNameState() {
-        /* Consume the next input character: */
-        $this->char++;
-        $char = $this->char();
-
-        if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
-            // Stay in the before DOCTYPE name state.
-
-        } elseif(preg_match('/^[a-z]$/', $char)) {
-            $this->token = array(
-                'name' => strtoupper($char),
-                'type' => self::DOCTYPE,
-                'error' => true
-            );
-
-            $this->state = 'doctypeName';
-
-        } elseif($char === '>') {
-            $this->emitToken(array(
-                'name' => null,
-                'type' => self::DOCTYPE,
-                'error' => true
-            ));
-
-            $this->state = 'data';
-
-        } elseif($this->char === $this->EOF) {
-            $this->emitToken(array(
-                'name' => null,
-                'type' => self::DOCTYPE,
-                'error' => true
-            ));
-
-            $this->char--;
-            $this->state = 'data';
-
-        } else {
-            $this->token = array(
-                'name' => $char,
-                'type' => self::DOCTYPE,
-                'error' => true
-            );
-
-            $this->state = 'doctypeName';
-        }
-    }
-
-    private function doctypeNameState() {
-        /* Consume the next input character: */
-        $this->char++;
-        $char = $this->char();
-
-        if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
-            $this->state = 'AfterDoctypeName';
-
-        } elseif($char === '>') {
-            $this->emitToken($this->token);
-            $this->state = 'data';
-
-        } elseif(preg_match('/^[a-z]$/', $char)) {
-            $this->token['name'] .= strtoupper($char);
-
-        } elseif($this->char === $this->EOF) {
-            $this->emitToken($this->token);
-            $this->char--;
-            $this->state = 'data';
-
-        } else {
-            $this->token['name'] .= $char;
-        }
-
-        $this->token['error'] = ($this->token['name'] === 'HTML')
-            ? false
-            : true;
-    }
-
-    private function afterDoctypeNameState() {
-        /* Consume the next input character: */
-        $this->char++;
-        $char = $this->char();
-
-        if(preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
-            // Stay in the DOCTYPE name state.
-
-        } elseif($char === '>') {
-            $this->emitToken($this->token);
-            $this->state = 'data';
-
-        } elseif($this->char === $this->EOF) {
-            $this->emitToken($this->token);
-            $this->char--;
-            $this->state = 'data';
-
-        } else {
-            $this->token['error'] = true;
-            $this->state = 'bogusDoctype';
-        }
-    }
-
-    private function bogusDoctypeState() {
-        /* Consume the next input character: */
-        $this->char++;
-        $char = $this->char();
-
-        if($char === '>') {
-            $this->emitToken($this->token);
-            $this->state = 'data';
-
-        } elseif($this->char === $this->EOF) {
-            $this->emitToken($this->token);
-            $this->char--;
-            $this->state = 'data';
-
-        } else {
-            // Stay in the bogus DOCTYPE state.
-        }
-    }
-
-    private function entity() {
-        $start = $this->char;
-
-        // This section defines how to consume an entity. This definition is
-        // used when parsing entities in text and in attributes.
-
-        // The behaviour depends on the identity of the next character (the
-        // one immediately after the U+0026 AMPERSAND character): 
-
-        switch($this->character($this->char + 1)) {
-            // U+0023 NUMBER SIGN (#)
-            case '#':
-
-                // The behaviour further depends on the character after the
-                // U+0023 NUMBER SIGN:
-                switch($this->character($this->char + 1)) {
-                    // U+0078 LATIN SMALL LETTER X
-                    // U+0058 LATIN CAPITAL LETTER X
-                    case 'x':
-                    case 'X':
-                        // Follow the steps below, but using the range of
-                        // characters U+0030 DIGIT ZERO through to U+0039 DIGIT
-                        // NINE, U+0061 LATIN SMALL LETTER A through to U+0066
-                        // LATIN SMALL LETTER F, and U+0041 LATIN CAPITAL LETTER
-                        // A, through to U+0046 LATIN CAPITAL LETTER F (in other
-                        // words, 0-9, A-F, a-f).
-                        $char = 1;
-                        $char_class = '0-9A-Fa-f';
-                    break;
-
-                    // Anything else
-                    default:
-                        // Follow the steps below, but using the range of
-                        // characters U+0030 DIGIT ZERO through to U+0039 DIGIT
-                        // NINE (i.e. just 0-9).
-                        $char = 0;
-                        $char_class = '0-9';
-                    break;
-                }
-
-                // Consume as many characters as match the range of characters
-                // given above.
-                $this->char++;
-                $e_name = $this->characters($char_class, $this->char + $char + 1);
-                $entity = $this->character($start, $this->char);
-                $cond = strlen($e_name) > 0;
-
-                // The rest of the parsing happens bellow.
-            break;
-
-            // Anything else
-            default:
-                // Consume the maximum number of characters possible, with the
-                // consumed characters case-sensitively matching one of the
-                // identifiers in the first column of the entities table.
-                $e_name = $this->characters('0-9A-Za-z;', $this->char + 1);
-                $len = strlen($e_name);
-
-                for($c = 1; $c <= $len; $c++) {
-                    $id = substr($e_name, 0, $c);
-                    $this->char++;
-
-                    if(in_array($id, $this->entities)) {
-                        if ($e_name[$c-1] !== ';') {
-                            if ($c < $len && $e_name[$c] == ';') {
-                                $this->char++; // consume extra semicolon
-                            }
-                        }
-                        $entity = $id;
-                        break;
-                    }
-                }
-
-                $cond = isset($entity);
-                // The rest of the parsing happens bellow.
-            break;
-        }
-
-        if(!$cond) {
-            // If no match can be made, then this is a parse error. No
-            // characters are consumed, and nothing is returned.
-            $this->char = $start;
-            return false;
-        }
-
-        // Return a character token for the character corresponding to the
-        // entity name (as given by the second column of the entities table).
-        return html_entity_decode('&'.$entity.';', ENT_QUOTES, 'UTF-8');
-    }
-
-    private function emitToken($token) {
-        $emit = $this->tree->emitToken($token);
-
-        if(is_int($emit)) {
-            $this->content_model = $emit;
-
-        } elseif($token['type'] === self::ENDTAG) {
-            $this->content_model = self::PCDATA;
-        }
-    }
-
-    private function EOF() {
-        $this->state = null;
-        $this->tree->emitToken(array(
-            'type' => self::EOF
-        ));
-    }
-}
-
-class HTML5TreeConstructer {
-    public $stack = array();
-
-    private $phase;
-    private $mode;
-    private $dom;
-    private $foster_parent = null;
-    private $a_formatting  = array();
-
-    private $head_pointer = null;
-    private $form_pointer = null;
-
-    private $scoping = array('button','caption','html','marquee','object','table','td','th');
-    private $formatting = array('a','b','big','em','font','i','nobr','s','small','strike','strong','tt','u');
-    private $special = array('address','area','base','basefont','bgsound',
-    'blockquote','body','br','center','col','colgroup','dd','dir','div','dl',
-    'dt','embed','fieldset','form','frame','frameset','h1','h2','h3','h4','h5',
-    'h6','head','hr','iframe','image','img','input','isindex','li','link',
-    'listing','menu','meta','noembed','noframes','noscript','ol','optgroup',
-    'option','p','param','plaintext','pre','script','select','spacer','style',
-    'tbody','textarea','tfoot','thead','title','tr','ul','wbr');
-
-    // The different phases.
-    const INIT_PHASE = 0;
-    const ROOT_PHASE = 1;
-    const MAIN_PHASE = 2;
-    const END_PHASE  = 3;
-
-    // The different insertion modes for the main phase.
-    const BEFOR_HEAD = 0;
-    const IN_HEAD    = 1;
-    const AFTER_HEAD = 2;
-    const IN_BODY    = 3;
-    const IN_TABLE   = 4;
-    const IN_CAPTION = 5;
-    const IN_CGROUP  = 6;
-    const IN_TBODY   = 7;
-    const IN_ROW     = 8;
-    const IN_CELL    = 9;
-    const IN_SELECT  = 10;
-    const AFTER_BODY = 11;
-    const IN_FRAME   = 12;
-    const AFTR_FRAME = 13;
-
-    // The different types of elements.
-    const SPECIAL    = 0;
-    const SCOPING    = 1;
-    const FORMATTING = 2;
-    const PHRASING   = 3;
-
-    const MARKER     = 0;
-
-    public function __construct() {
-        $this->phase = self::INIT_PHASE;
-        $this->mode = self::BEFOR_HEAD;
-        $this->dom = new DOMDocument;
-
-        $this->dom->encoding = 'UTF-8';
-        $this->dom->preserveWhiteSpace = true;
-        $this->dom->substituteEntities = true;
-        $this->dom->strictErrorChecking = false;
-    }
-
-    // Process tag tokens
-    public function emitToken($token) {
-        switch($this->phase) {
-            case self::INIT_PHASE: return $this->initPhase($token); break;
-            case self::ROOT_PHASE: return $this->rootElementPhase($token); break;
-            case self::MAIN_PHASE: return $this->mainPhase($token); break;
-            case self::END_PHASE : return $this->trailingEndPhase($token); break;
-        }
-    }
-
-    private function initPhase($token) {
-        /* Initially, the tree construction stage must handle each token
-        emitted from the tokenisation stage as follows: */
-
-        /* A DOCTYPE token that is marked as being in error
-        A comment token
-        A start tag token
-        An end tag token
-        A character token that is not one of one of U+0009 CHARACTER TABULATION,
-            U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-            or U+0020 SPACE
-        An end-of-file token */
-        if((isset($token['error']) && $token['error']) ||
-        $token['type'] === HTML5::COMMENT ||
-        $token['type'] === HTML5::STARTTAG ||
-        $token['type'] === HTML5::ENDTAG ||
-        $token['type'] === HTML5::EOF ||
-        ($token['type'] === HTML5::CHARACTR && isset($token['data']) &&
-        !preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data']))) {
-            /* This specification does not define how to handle this case. In
-            particular, user agents may ignore the entirety of this specification
-            altogether for such documents, and instead invoke special parse modes
-            with a greater emphasis on backwards compatibility. */
-
-            $this->phase = self::ROOT_PHASE;
-            return $this->rootElementPhase($token);
-
-        /* A DOCTYPE token marked as being correct */
-        } elseif(isset($token['error']) && !$token['error']) {
-            /* Append a DocumentType node to the Document  node, with the name
-            attribute set to the name given in the DOCTYPE token (which will be
-            "HTML"), and the other attributes specific to DocumentType objects
-            set to null, empty lists, or the empty string as appropriate. */
-            $doctype = new DOMDocumentType(null, null, 'HTML');
-
-            /* Then, switch to the root element phase of the tree construction
-            stage. */
-            $this->phase = self::ROOT_PHASE;
-
-        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        or U+0020 SPACE */
-        } elseif(isset($token['data']) && preg_match('/^[\t\n\x0b\x0c ]+$/',
-        $token['data'])) {
-            /* Append that character  to the Document node. */
-            $text = $this->dom->createTextNode($token['data']);
-            $this->dom->appendChild($text);
-        }
-    }
-
-    private function rootElementPhase($token) {
-        /* After the initial phase, as each token is emitted from the tokenisation
-        stage, it must be processed as described in this section. */
-
-        /* A DOCTYPE token */
-        if($token['type'] === HTML5::DOCTYPE) {
-            // Parse error. Ignore the token.
-
-        /* A comment token */
-        } elseif($token['type'] === HTML5::COMMENT) {
-            /* Append a Comment node to the Document object with the data
-            attribute set to the data given in the comment token. */
-            $comment = $this->dom->createComment($token['data']);
-            $this->dom->appendChild($comment);
-
-        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        or U+0020 SPACE */
-        } elseif($token['type'] === HTML5::CHARACTR &&
-        preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) {
-            /* Append that character  to the Document node. */
-            $text = $this->dom->createTextNode($token['data']);
-            $this->dom->appendChild($text);
-
-        /* A character token that is not one of U+0009 CHARACTER TABULATION,
-            U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED
-            (FF), or U+0020 SPACE
-        A start tag token
-        An end tag token
-        An end-of-file token */
-        } elseif(($token['type'] === HTML5::CHARACTR &&
-        !preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) ||
-        $token['type'] === HTML5::STARTTAG ||
-        $token['type'] === HTML5::ENDTAG ||
-        $token['type'] === HTML5::EOF) {
-            /* Create an HTMLElement node with the tag name html, in the HTML
-            namespace. Append it to the Document object. Switch to the main
-            phase and reprocess the current token. */
-            $html = $this->dom->createElement('html');
-            $this->dom->appendChild($html);
-            $this->stack[] = $html;
-
-            $this->phase = self::MAIN_PHASE;
-            return $this->mainPhase($token);
-        }
-    }
-
-    private function mainPhase($token) {
-        /* Tokens in the main phase must be handled as follows: */
-
-        /* A DOCTYPE token */
-        if($token['type'] === HTML5::DOCTYPE) {
-            // Parse error. Ignore the token.
-
-        /* A start tag token with the tag name "html" */
-        } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'html') {
-            /* If this start tag token was not the first start tag token, then
-            it is a parse error. */
-
-            /* For each attribute on the token, check to see if the attribute
-            is already present on the top element of the stack of open elements.
-            If it is not, add the attribute and its corresponding value to that
-            element. */
-            foreach($token['attr'] as $attr) {
-                if(!$this->stack[0]->hasAttribute($attr['name'])) {
-                    $this->stack[0]->setAttribute($attr['name'], $attr['value']);
-                }
-            }
-
-        /* An end-of-file token */
-        } elseif($token['type'] === HTML5::EOF) {
-            /* Generate implied end tags. */
-            $this->generateImpliedEndTags();
-
-        /* Anything else. */
-        } else {
-            /* Depends on the insertion mode: */
-            switch($this->mode) {
-                case self::BEFOR_HEAD: return $this->beforeHead($token); break;
-                case self::IN_HEAD:    return $this->inHead($token); break;
-                case self::AFTER_HEAD: return $this->afterHead($token); break;
-                case self::IN_BODY:    return $this->inBody($token); break;
-                case self::IN_TABLE:   return $this->inTable($token); break;
-                case self::IN_CAPTION: return $this->inCaption($token); break;
-                case self::IN_CGROUP:  return $this->inColumnGroup($token); break;
-                case self::IN_TBODY:   return $this->inTableBody($token); break;
-                case self::IN_ROW:     return $this->inRow($token); break;
-                case self::IN_CELL:    return $this->inCell($token); break;
-                case self::IN_SELECT:  return $this->inSelect($token); break;
-                case self::AFTER_BODY: return $this->afterBody($token); break;
-                case self::IN_FRAME:   return $this->inFrameset($token); break;
-                case self::AFTR_FRAME: return $this->afterFrameset($token); break;
-                case self::END_PHASE:  return $this->trailingEndPhase($token); break;
-            }
-        }
-    }
-
-    private function beforeHead($token) {
-        /* Handle the token as follows: */
-
-        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        or U+0020 SPACE */
-        if($token['type'] === HTML5::CHARACTR &&
-        preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) {
-            /* Append the character to the current node. */
-            $this->insertText($token['data']);
-
-        /* A comment token */
-        } elseif($token['type'] === HTML5::COMMENT) {
-            /* Append a Comment node to the current node with the data attribute
-            set to the data given in the comment token. */
-            $this->insertComment($token['data']);
-
-        /* A start tag token with the tag name "head" */
-        } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'head') {
-            /* Create an element for the token, append the new element to the
-            current node and push it onto the stack of open elements. */
-            $element = $this->insertElement($token);
-
-            /* Set the head element pointer to this new element node. */
-            $this->head_pointer = $element;
-
-            /* Change the insertion mode to "in head". */
-            $this->mode = self::IN_HEAD;
-
-        /* A start tag token whose tag name is one of: "base", "link", "meta",
-        "script", "style", "title". Or an end tag with the tag name "html".
-        Or a character token that is not one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        or U+0020 SPACE. Or any other start tag token */
-        } elseif($token['type'] === HTML5::STARTTAG ||
-        ($token['type'] === HTML5::ENDTAG && $token['name'] === 'html') ||
-        ($token['type'] === HTML5::CHARACTR && !preg_match('/^[\t\n\x0b\x0c ]$/',
-        $token['data']))) {
-            /* Act as if a start tag token with the tag name "head" and no
-            attributes had been seen, then reprocess the current token. */
-            $this->beforeHead(array(
-                'name' => 'head',
-                'type' => HTML5::STARTTAG,
-                'attr' => array()
-            ));
-
-            return $this->inHead($token);
-
-        /* Any other end tag */
-        } elseif($token['type'] === HTML5::ENDTAG) {
-            /* Parse error. Ignore the token. */
-        }
-    }
-
-    private function inHead($token) {
-        /* Handle the token as follows: */
-
-        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        or U+0020 SPACE.
-
-        THIS DIFFERS FROM THE SPEC: If the current node is either a title, style
-        or script element, append the character to the current node regardless
-        of its content. */
-        if(($token['type'] === HTML5::CHARACTR &&
-        preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) || (
-        $token['type'] === HTML5::CHARACTR && in_array(end($this->stack)->nodeName,
-        array('title', 'style', 'script')))) {
-            /* Append the character to the current node. */
-            $this->insertText($token['data']);
-
-        /* A comment token */
-        } elseif($token['type'] === HTML5::COMMENT) {
-            /* Append a Comment node to the current node with the data attribute
-            set to the data given in the comment token. */
-            $this->insertComment($token['data']);
-
-        } elseif($token['type'] === HTML5::ENDTAG &&
-        in_array($token['name'], array('title', 'style', 'script'))) {
-            array_pop($this->stack);
-            return HTML5::PCDATA;
-
-        /* A start tag with the tag name "title" */
-        } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'title') {
-            /* Create an element for the token and append the new element to the
-            node pointed to by the head element pointer, or, if that is null
-            (innerHTML case), to the current node. */
-            if($this->head_pointer !== null) {
-                $element = $this->insertElement($token, false);
-                $this->head_pointer->appendChild($element);
-
-            } else {
-                $element = $this->insertElement($token);
-            }
-
-            /* Switch the tokeniser's content model flag  to the RCDATA state. */
-            return HTML5::RCDATA;
-
-        /* A start tag with the tag name "style" */
-        } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'style') {
-            /* Create an element for the token and append the new element to the
-            node pointed to by the head element pointer, or, if that is null
-            (innerHTML case), to the current node. */
-            if($this->head_pointer !== null) {
-                $element = $this->insertElement($token, false);
-                $this->head_pointer->appendChild($element);
-
-            } else {
-                $this->insertElement($token);
-            }
-
-            /* Switch the tokeniser's content model flag  to the CDATA state. */
-            return HTML5::CDATA;
-
-        /* A start tag with the tag name "script" */
-        } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'script') {
-            /* Create an element for the token. */
-            $element = $this->insertElement($token, false);
-            $this->head_pointer->appendChild($element);
-
-            /* Switch the tokeniser's content model flag  to the CDATA state. */
-            return HTML5::CDATA;
-
-        /* A start tag with the tag name "base", "link", or "meta" */
-        } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'],
-        array('base', 'link', 'meta'))) {
-            /* Create an element for the token and append the new element to the
-            node pointed to by the head element pointer, or, if that is null
-            (innerHTML case), to the current node. */
-            if($this->head_pointer !== null) {
-                $element = $this->insertElement($token, false);
-                $this->head_pointer->appendChild($element);
-                array_pop($this->stack);
-
-            } else {
-                $this->insertElement($token);
-            }
-
-        /* An end tag with the tag name "head" */
-        } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'head') {
-            /* If the current node is a head element, pop the current node off
-            the stack of open elements. */
-            if($this->head_pointer->isSameNode(end($this->stack))) {
-                array_pop($this->stack);
-
-            /* Otherwise, this is a parse error. */
-            } else {
-                // k
-            }
-
-            /* Change the insertion mode to "after head". */
-            $this->mode = self::AFTER_HEAD;
-
-        /* A start tag with the tag name "head" or an end tag except "html". */
-        } elseif(($token['type'] === HTML5::STARTTAG && $token['name'] === 'head') ||
-        ($token['type'] === HTML5::ENDTAG && $token['name'] !== 'html')) {
-            // Parse error. Ignore the token.
-
-        /* Anything else */
-        } else {
-            /* If the current node is a head element, act as if an end tag
-            token with the tag name "head" had been seen. */
-            if($this->head_pointer->isSameNode(end($this->stack))) {
-                $this->inHead(array(
-                    'name' => 'head',
-                    'type' => HTML5::ENDTAG
-                ));
-
-            /* Otherwise, change the insertion mode to "after head". */
-            } else {
-                $this->mode = self::AFTER_HEAD;
-            }
-
-            /* Then, reprocess the current token. */
-            return $this->afterHead($token);
-        }
-    }
-
-    private function afterHead($token) {
-        /* Handle the token as follows: */
-
-        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        or U+0020 SPACE */
-        if($token['type'] === HTML5::CHARACTR &&
-        preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) {
-            /* Append the character to the current node. */
-            $this->insertText($token['data']);
-
-        /* A comment token */
-        } elseif($token['type'] === HTML5::COMMENT) {
-            /* Append a Comment node to the current node with the data attribute
-            set to the data given in the comment token. */
-            $this->insertComment($token['data']);
-
-        /* A start tag token with the tag name "body" */
-        } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'body') {
-            /* Insert a body element for the token. */
-            $this->insertElement($token);
-
-            /* Change the insertion mode to "in body". */
-            $this->mode = self::IN_BODY;
-
-        /* A start tag token with the tag name "frameset" */
-        } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'frameset') {
-            /* Insert a frameset element for the token. */
-            $this->insertElement($token);
-
-            /* Change the insertion mode to "in frameset". */
-            $this->mode = self::IN_FRAME;
-
-        /* A start tag token whose tag name is one of: "base", "link", "meta",
-        "script", "style", "title" */
-        } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'],
-        array('base', 'link', 'meta', 'script', 'style', 'title'))) {
-            /* Parse error. Switch the insertion mode back to "in head" and
-            reprocess the token. */
-            $this->mode = self::IN_HEAD;
-            return $this->inHead($token);
-
-        /* Anything else */
-        } else {
-            /* Act as if a start tag token with the tag name "body" and no
-            attributes had been seen, and then reprocess the current token. */
-            $this->afterHead(array(
-                'name' => 'body',
-                'type' => HTML5::STARTTAG,
-                'attr' => array()
-            ));
-
-            return $this->inBody($token);
-        }
-    }
-
-    private function inBody($token) {
-        /* Handle the token as follows: */
-
-        switch($token['type']) {
-            /* A character token */
-            case HTML5::CHARACTR:
-                /* Reconstruct the active formatting elements, if any. */
-                $this->reconstructActiveFormattingElements();
-
-                /* Append the token's character to the current node. */
-                $this->insertText($token['data']);
-            break;
-
-            /* A comment token */
-            case HTML5::COMMENT:
-                /* Append a Comment node to the current node with the data
-                attribute set to the data given in the comment token. */
-                $this->insertComment($token['data']);
-            break;
-
-            case HTML5::STARTTAG:
-            switch($token['name']) {
-                /* A start tag token whose tag name is one of: "script",
-                "style" */
-                case 'script': case 'style':
-                    /* Process the token as if the insertion mode had been "in
-                    head". */
-                    return $this->inHead($token);
-                break;
-
-                /* A start tag token whose tag name is one of: "base", "link",
-                "meta", "title" */
-                case 'base': case 'link': case 'meta': case 'title':
-                    /* Parse error. Process the token as if the insertion mode
-                    had    been "in head". */
-                    return $this->inHead($token);
-                break;
-
-                /* A start tag token with the tag name "body" */
-                case 'body':
-                    /* Parse error. If the second element on the stack of open
-                    elements is not a body element, or, if the stack of open
-                    elements has only one node on it, then ignore the token.
-                    (innerHTML case) */
-                    if(count($this->stack) === 1 || $this->stack[1]->nodeName !== 'body') {
-                        // Ignore
-
-                    /* Otherwise, for each attribute on the token, check to see
-                    if the attribute is already present on the body element (the
-                    second element)    on the stack of open elements. If it is not,
-                    add the attribute and its corresponding value to that
-                    element. */
-                    } else {
-                        foreach($token['attr'] as $attr) {
-                            if(!$this->stack[1]->hasAttribute($attr['name'])) {
-                                $this->stack[1]->setAttribute($attr['name'], $attr['value']);
-                            }
-                        }
-                    }
-                break;
-
-                /* A start tag whose tag name is one of: "address",
-                "blockquote", "center", "dir", "div", "dl", "fieldset",
-                "listing", "menu", "ol", "p", "ul" */
-                case 'address': case 'blockquote': case 'center': case 'dir':
-                case 'div': case 'dl': case 'fieldset': case 'listing':
-                case 'menu': case 'ol': case 'p': case 'ul':
-                    /* If the stack of open elements has a p element in scope,
-                    then act as if an end tag with the tag name p had been
-                    seen. */
-                    if($this->elementInScope('p')) {
-                        $this->emitToken(array(
-                            'name' => 'p',
-                            'type' => HTML5::ENDTAG
-                        ));
-                    }
-
-                    /* Insert an HTML element for the token. */
-                    $this->insertElement($token);
-                break;
-
-                /* A start tag whose tag name is "form" */
-                case 'form':
-                    /* If the form element pointer is not null, ignore the
-                    token with a parse error. */
-                    if($this->form_pointer !== null) {
-                        // Ignore.
-
-                    /* Otherwise: */
-                    } else {
-                        /* If the stack of open elements has a p element in
-                        scope, then act as if an end tag with the tag name p
-                        had been seen. */
-                        if($this->elementInScope('p')) {
-                            $this->emitToken(array(
-                                'name' => 'p',
-                                'type' => HTML5::ENDTAG
-                            ));
-                        }
-
-                        /* Insert an HTML element for the token, and set the
-                        form element pointer to point to the element created. */
-                        $element = $this->insertElement($token);
-                        $this->form_pointer = $element;
-                    }
-                break;
-
-                /* A start tag whose tag name is "li", "dd" or "dt" */
-                case 'li': case 'dd': case 'dt':
-                    /* If the stack of open elements has a p  element in scope,
-                    then act as if an end tag with the tag name p had been
-                    seen. */
-                    if($this->elementInScope('p')) {
-                        $this->emitToken(array(
-                            'name' => 'p',
-                            'type' => HTML5::ENDTAG
-                        ));
-                    }
-
-                    $stack_length = count($this->stack) - 1;
-
-                    for($n = $stack_length; 0 <= $n; $n--) {
-                        /* 1. Initialise node to be the current node (the
-                        bottommost node of the stack). */
-                        $stop = false;
-                        $node = $this->stack[$n];
-                        $cat  = $this->getElementCategory($node->tagName);
-
-                        /* 2. If node is an li, dd or dt element, then pop all
-                        the    nodes from the current node up to node, including
-                        node, then stop this algorithm. */
-                        if($token['name'] === $node->tagName ||    ($token['name'] !== 'li'
-                        && ($node->tagName === 'dd' || $node->tagName === 'dt'))) {
-                            for($x = $stack_length; $x >= $n ; $x--) {
-                                array_pop($this->stack);
-                            }
-
-                            break;
-                        }
-
-                        /* 3. If node is not in the formatting category, and is
-                        not    in the phrasing category, and is not an address or
-                        div element, then stop this algorithm. */
-                        if($cat !== self::FORMATTING && $cat !== self::PHRASING &&
-                        $node->tagName !== 'address' && $node->tagName !== 'div') {
-                            break;
-                        }
-                    }
-
-                    /* Finally, insert an HTML element with the same tag
-                    name as the    token's. */
-                    $this->insertElement($token);
-                break;
-
-                /* A start tag token whose tag name is "plaintext" */
-                case 'plaintext':
-                    /* If the stack of open elements has a p  element in scope,
-                    then act as if an end tag with the tag name p had been
-                    seen. */
-                    if($this->elementInScope('p')) {
-                        $this->emitToken(array(
-                            'name' => 'p',
-                            'type' => HTML5::ENDTAG
-                        ));
-                    }
-
-                    /* Insert an HTML element for the token. */
-                    $this->insertElement($token);
-
-                    return HTML5::PLAINTEXT;
-                break;
-
-                /* A start tag whose tag name is one of: "h1", "h2", "h3", "h4",
-                "h5", "h6" */
-                case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6':
-                    /* If the stack of open elements has a p  element in scope,
-                    then act as if an end tag with the tag name p had been seen. */
-                    if($this->elementInScope('p')) {
-                        $this->emitToken(array(
-                            'name' => 'p',
-                            'type' => HTML5::ENDTAG
-                        ));
-                    }
-
-                    /* If the stack of open elements has in scope an element whose
-                    tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then
-                    this is a parse error; pop elements from the stack until an
-                    element with one of those tag names has been popped from the
-                    stack. */
-                    while($this->elementInScope(array('h1', 'h2', 'h3', 'h4', 'h5', 'h6'))) {
-                        array_pop($this->stack);
-                    }
-
-                    /* Insert an HTML element for the token. */
-                    $this->insertElement($token);
-                break;
-
-                /* A start tag whose tag name is "a" */
-                case 'a':
-                    /* If the list of active formatting elements contains
-                    an element whose tag name is "a" between the end of the
-                    list and the last marker on the list (or the start of
-                    the list if there is no marker on the list), then this
-                    is a parse error; act as if an end tag with the tag name
-                    "a" had been seen, then remove that element from the list
-                    of active formatting elements and the stack of open
-                    elements if the end tag didn't already remove it (it
-                    might not have if the element is not in table scope). */
-                    $leng = count($this->a_formatting);
-
-                    for($n = $leng - 1; $n >= 0; $n--) {
-                        if($this->a_formatting[$n] === self::MARKER) {
-                            break;
-
-                        } elseif($this->a_formatting[$n]->nodeName === 'a') {
-                            $this->emitToken(array(
-                                'name' => 'a',
-                                'type' => HTML5::ENDTAG
-                            ));
-                            break;
-                        }
-                    }
-
-                    /* Reconstruct the active formatting elements, if any. */
-                    $this->reconstructActiveFormattingElements();
-
-                    /* Insert an HTML element for the token. */
-                    $el = $this->insertElement($token);
-
-                    /* Add that element to the list of active formatting
-                    elements. */
-                    $this->a_formatting[] = $el;
-                break;
-
-                /* A start tag whose tag name is one of: "b", "big", "em", "font",
-                "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */
-                case 'b': case 'big': case 'em': case 'font': case 'i':
-                case 'nobr': case 's': case 'small': case 'strike':
-                case 'strong': case 'tt': case 'u':
-                    /* Reconstruct the active formatting elements, if any. */
-                    $this->reconstructActiveFormattingElements();
-
-                    /* Insert an HTML element for the token. */
-                    $el = $this->insertElement($token);
-
-                    /* Add that element to the list of active formatting
-                    elements. */
-                    $this->a_formatting[] = $el;
-                break;
-
-                /* A start tag token whose tag name is "button" */
-                case 'button':
-                    /* If the stack of open elements has a button element in scope,
-                    then this is a parse error; act as if an end tag with the tag
-                    name "button" had been seen, then reprocess the token. (We don't
-                    do that. Unnecessary.) */
-                    if($this->elementInScope('button')) {
-                        $this->inBody(array(
-                            'name' => 'button',
-                            'type' => HTML5::ENDTAG
-                        ));
-                    }
-
-                    /* Reconstruct the active formatting elements, if any. */
-                    $this->reconstructActiveFormattingElements();
-
-                    /* Insert an HTML element for the token. */
-                    $this->insertElement($token);
-
-                    /* Insert a marker at the end of the list of active
-                    formatting elements. */
-                    $this->a_formatting[] = self::MARKER;
-                break;
-
-                /* A start tag token whose tag name is one of: "marquee", "object" */
-                case 'marquee': case 'object':
-                    /* Reconstruct the active formatting elements, if any. */
-                    $this->reconstructActiveFormattingElements();
-
-                    /* Insert an HTML element for the token. */
-                    $this->insertElement($token);
-
-                    /* Insert a marker at the end of the list of active
-                    formatting elements. */
-                    $this->a_formatting[] = self::MARKER;
-                break;
-
-                /* A start tag token whose tag name is "xmp" */
-                case 'xmp':
-                    /* Reconstruct the active formatting elements, if any. */
-                    $this->reconstructActiveFormattingElements();
-
-                    /* Insert an HTML element for the token. */
-                    $this->insertElement($token);
-
-                    /* Switch the content model flag to the CDATA state. */
-                    return HTML5::CDATA;
-                break;
-
-                /* A start tag whose tag name is "table" */
-                case 'table':
-                    /* If the stack of open elements has a p element in scope,
-                    then act as if an end tag with the tag name p had been seen. */
-                    if($this->elementInScope('p')) {
-                        $this->emitToken(array(
-                            'name' => 'p',
-                            'type' => HTML5::ENDTAG
-                        ));
-                    }
-
-                    /* Insert an HTML element for the token. */
-                    $this->insertElement($token);
-
-                    /* Change the insertion mode to "in table". */
-                    $this->mode = self::IN_TABLE;
-                break;
-
-                /* A start tag whose tag name is one of: "area", "basefont",
-                "bgsound", "br", "embed", "img", "param", "spacer", "wbr" */
-                case 'area': case 'basefont': case 'bgsound': case 'br':
-                case 'embed': case 'img': case 'param': case 'spacer':
-                case 'wbr':
-                    /* Reconstruct the active formatting elements, if any. */
-                    $this->reconstructActiveFormattingElements();
-
-                    /* Insert an HTML element for the token. */
-                    $this->insertElement($token);
-
-                    /* Immediately pop the current node off the stack of open elements. */
-                    array_pop($this->stack);
-                break;
-
-                /* A start tag whose tag name is "hr" */
-                case 'hr':
-                    /* If the stack of open elements has a p element in scope,
-                    then act as if an end tag with the tag name p had been seen. */
-                    if($this->elementInScope('p')) {
-                        $this->emitToken(array(
-                            'name' => 'p',
-                            'type' => HTML5::ENDTAG
-                        ));
-                    }
-
-                    /* Insert an HTML element for the token. */
-                    $this->insertElement($token);
-
-                    /* Immediately pop the current node off the stack of open elements. */
-                    array_pop($this->stack);
-                break;
-
-                /* A start tag whose tag name is "image" */
-                case 'image':
-                    /* Parse error. Change the token's tag name to "img" and
-                    reprocess it. (Don't ask.) */
-                    $token['name'] = 'img';
-                    return $this->inBody($token);
-                break;
-
-                /* A start tag whose tag name is "input" */
-                case 'input':
-                    /* Reconstruct the active formatting elements, if any. */
-                    $this->reconstructActiveFormattingElements();
-
-                    /* Insert an input element for the token. */
-                    $element = $this->insertElement($token, false);
-
-                    /* If the form element pointer is not null, then associate the
-                    input element with the form element pointed to by the form
-                    element pointer. */
-                    $this->form_pointer !== null
-                        ? $this->form_pointer->appendChild($element)
-                        : end($this->stack)->appendChild($element);
-
-                    /* Pop that input element off the stack of open elements. */
-                    array_pop($this->stack);
-                break;
-
-                /* A start tag whose tag name is "isindex" */
-                case 'isindex':
-                    /* Parse error. */
-                    // w/e
-
-                    /* If the form element pointer is not null,
-                    then ignore the token. */
-                    if($this->form_pointer === null) {
-                        /* Act as if a start tag token with the tag name "form" had
-                        been seen. */
-                        $this->inBody(array(
-                            'name' => 'body',
-                            'type' => HTML5::STARTTAG,
-                            'attr' => array()
-                        ));
-
-                        /* Act as if a start tag token with the tag name "hr" had
-                        been seen. */
-                        $this->inBody(array(
-                            'name' => 'hr',
-                            'type' => HTML5::STARTTAG,
-                            'attr' => array()
-                        ));
-
-                        /* Act as if a start tag token with the tag name "p" had
-                        been seen. */
-                        $this->inBody(array(
-                            'name' => 'p',
-                            'type' => HTML5::STARTTAG,
-                            'attr' => array()
-                        ));
-
-                        /* Act as if a start tag token with the tag name "label"
-                        had been seen. */
-                        $this->inBody(array(
-                            'name' => 'label',
-                            'type' => HTML5::STARTTAG,
-                            'attr' => array()
-                        ));
-
-                        /* Act as if a stream of character tokens had been seen. */
-                        $this->insertText('This is a searchable index. '.
-                        'Insert your search keywords here: ');
-
-                        /* Act as if a start tag token with the tag name "input"
-                        had been seen, with all the attributes from the "isindex"
-                        token, except with the "name" attribute set to the value
-                        "isindex" (ignoring any explicit "name" attribute). */
-                        $attr = $token['attr'];
-                        $attr[] = array('name' => 'name', 'value' => 'isindex');
-
-                        $this->inBody(array(
-                            'name' => 'input',
-                            'type' => HTML5::STARTTAG,
-                            'attr' => $attr
-                        ));
-
-                        /* Act as if a stream of character tokens had been seen
-                        (see below for what they should say). */
-                        $this->insertText('This is a searchable index. '.
-                        'Insert your search keywords here: ');
-
-                        /* Act as if an end tag token with the tag name "label"
-                        had been seen. */
-                        $this->inBody(array(
-                            'name' => 'label',
-                            'type' => HTML5::ENDTAG
-                        ));
-
-                        /* Act as if an end tag token with the tag name "p" had
-                        been seen. */
-                        $this->inBody(array(
-                            'name' => 'p',
-                            'type' => HTML5::ENDTAG
-                        ));
-
-                        /* Act as if a start tag token with the tag name "hr" had
-                        been seen. */
-                        $this->inBody(array(
-                            'name' => 'hr',
-                            'type' => HTML5::ENDTAG
-                        ));
-
-                        /* Act as if an end tag token with the tag name "form" had
-                        been seen. */
-                        $this->inBody(array(
-                            'name' => 'form',
-                            'type' => HTML5::ENDTAG
-                        ));
-                    }
-                break;
-
-                /* A start tag whose tag name is "textarea" */
-                case 'textarea':
-                    $this->insertElement($token);
-
-                    /* Switch the tokeniser's content model flag to the
-                    RCDATA state. */
-                    return HTML5::RCDATA;
-                break;
-
-                /* A start tag whose tag name is one of: "iframe", "noembed",
-                "noframes" */
-                case 'iframe': case 'noembed': case 'noframes':
-                    $this->insertElement($token);
-
-                    /* Switch the tokeniser's content model flag to the CDATA state. */
-                    return HTML5::CDATA;
-                break;
-
-                /* A start tag whose tag name is "select" */
-                case 'select':
-                    /* Reconstruct the active formatting elements, if any. */
-                    $this->reconstructActiveFormattingElements();
-
-                    /* Insert an HTML element for the token. */
-                    $this->insertElement($token);
-
-                    /* Change the insertion mode to "in select". */
-                    $this->mode = self::IN_SELECT;
-                break;
-
-                /* A start or end tag whose tag name is one of: "caption", "col",
-                "colgroup", "frame", "frameset", "head", "option", "optgroup",
-                "tbody", "td", "tfoot", "th", "thead", "tr". */
-                case 'caption': case 'col': case 'colgroup': case 'frame':
-                case 'frameset': case 'head': case 'option': case 'optgroup':
-                case 'tbody': case 'td': case 'tfoot': case 'th': case 'thead':
-                case 'tr':
-                    // Parse error. Ignore the token.
-                break;
-
-                /* A start or end tag whose tag name is one of: "event-source",
-                "section", "nav", "article", "aside", "header", "footer",
-                "datagrid", "command" */
-                case 'event-source': case 'section': case 'nav': case 'article':
-                case 'aside': case 'header': case 'footer': case 'datagrid':
-                case 'command':
-                    // Work in progress!
-                break;
-
-                /* A start tag token not covered by the previous entries */
-                default:
-                    /* Reconstruct the active formatting elements, if any. */
-                    $this->reconstructActiveFormattingElements();
-
-                    $this->insertElement($token, true, true);
-                break;
-            }
-            break;
-
-            case HTML5::ENDTAG:
-            switch($token['name']) {
-                /* An end tag with the tag name "body" */
-                case 'body':
-                    /* If the second element in the stack of open elements is
-                    not a body element, this is a parse error. Ignore the token.
-                    (innerHTML case) */
-                    if(count($this->stack) < 2 || $this->stack[1]->nodeName !== 'body') {
-                        // Ignore.
-
-                    /* If the current node is not the body element, then this
-                    is a parse error. */
-                    } elseif(end($this->stack)->nodeName !== 'body') {
-                        // Parse error.
-                    }
-
-                    /* Change the insertion mode to "after body". */
-                    $this->mode = self::AFTER_BODY;
-                break;
-
-                /* An end tag with the tag name "html" */
-                case 'html':
-                    /* Act as if an end tag with tag name "body" had been seen,
-                    then, if that token wasn't ignored, reprocess the current
-                    token. */
-                    $this->inBody(array(
-                        'name' => 'body',
-                        'type' => HTML5::ENDTAG
-                    ));
-
-                    return $this->afterBody($token);
-                break;
-
-                /* An end tag whose tag name is one of: "address", "blockquote",
-                "center", "dir", "div", "dl", "fieldset", "listing", "menu",
-                "ol", "pre", "ul" */
-                case 'address': case 'blockquote': case 'center': case 'dir':
-                case 'div': case 'dl': case 'fieldset': case 'listing':
-                case 'menu': case 'ol': case 'pre': case 'ul':
-                    /* If the stack of open elements has an element in scope
-                    with the same tag name as that of the token, then generate
-                    implied end tags. */
-                    if($this->elementInScope($token['name'])) {
-                        $this->generateImpliedEndTags();
-
-                        /* Now, if the current node is not an element with
-                        the same tag name as that of the token, then this
-                        is a parse error. */
-                        // w/e
-
-                        /* If the stack of open elements has an element in
-                        scope with the same tag name as that of the token,
-                        then pop elements from this stack until an element
-                        with that tag name has been popped from the stack. */
-                        for($n = count($this->stack) - 1; $n >= 0; $n--) {
-                            if($this->stack[$n]->nodeName === $token['name']) {
-                                $n = -1;
-                            }
-
-                            array_pop($this->stack);
-                        }
-                    }
-                break;
-
-                /* An end tag whose tag name is "form" */
-                case 'form':
-                    /* If the stack of open elements has an element in scope
-                    with the same tag name as that of the token, then generate
-                    implied    end tags. */
-                    if($this->elementInScope($token['name'])) {
-                        $this->generateImpliedEndTags();
-
-                    } 
-
-                    if(end($this->stack)->nodeName !== $token['name']) {
-                        /* Now, if the current node is not an element with the
-                        same tag name as that of the token, then this is a parse
-                        error. */
-                        // w/e
-
-                    } else {
-                        /* Otherwise, if the current node is an element with
-                        the same tag name as that of the token pop that element
-                        from the stack. */
-                        array_pop($this->stack);
-                    }
-
-                    /* In any case, set the form element pointer to null. */
-                    $this->form_pointer = null;
-                break;
-
-                /* An end tag whose tag name is "p" */
-                case 'p':
-                    /* If the stack of open elements has a p element in scope,
-                    then generate implied end tags, except for p elements. */
-                    if($this->elementInScope('p')) {
-                        $this->generateImpliedEndTags(array('p'));
-
-                        /* If the current node is not a p element, then this is
-                        a parse error. */
-                        // k
-
-                        /* If the stack of open elements has a p element in
-                        scope, then pop elements from this stack until the stack
-                        no longer has a p element in scope. */
-                        for($n = count($this->stack) - 1; $n >= 0; $n--) {
-                            if($this->elementInScope('p')) {
-                                array_pop($this->stack);
-
-                            } else {
-                                break;
-                            }
-                        }
-                    }
-                break;
-
-                /* An end tag whose tag name is "dd", "dt", or "li" */
-                case 'dd': case 'dt': case 'li':
-                    /* If the stack of open elements has an element in scope
-                    whose tag name matches the tag name of the token, then
-                    generate implied end tags, except for elements with the
-                    same tag name as the token. */
-                    if($this->elementInScope($token['name'])) {
-                        $this->generateImpliedEndTags(array($token['name']));
-
-                        /* If the current node is not an element with the same
-                        tag name as the token, then this is a parse error. */
-                        // w/e
-
-                        /* If the stack of open elements has an element in scope
-                        whose tag name matches the tag name of the token, then
-                        pop elements from this stack until an element with that
-                        tag name has been popped from the stack. */
-                        for($n = count($this->stack) - 1; $n >= 0; $n--) {
-                            if($this->stack[$n]->nodeName === $token['name']) {
-                                $n = -1;
-                            }
-
-                            array_pop($this->stack);
-                        }
-                    }
-                break;
-
-                /* An end tag whose tag name is one of: "h1", "h2", "h3", "h4",
-                "h5", "h6" */
-                case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6':
-                    $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6');
-
-                    /* If the stack of open elements has in scope an element whose
-                    tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then
-                    generate implied end tags. */
-                    if($this->elementInScope($elements)) {
-                        $this->generateImpliedEndTags();
-
-                        /* Now, if the current node is not an element with the same
-                        tag name as that of the token, then this is a parse error. */
-                        // w/e
-
-                        /* If the stack of open elements has in scope an element
-                        whose tag name is one of "h1", "h2", "h3", "h4", "h5", or
-                        "h6", then pop elements from the stack until an element
-                        with one of those tag names has been popped from the stack. */
-                        while($this->elementInScope($elements)) {
-                            array_pop($this->stack);
-                        }
-                    }
-                break;
-
-                /* An end tag whose tag name is one of: "a", "b", "big", "em",
-                "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */
-                case 'a': case 'b': case 'big': case 'em': case 'font':
-                case 'i': case 'nobr': case 's': case 'small': case 'strike':
-                case 'strong': case 'tt': case 'u':
-                    /* 1. Let the formatting element be the last element in
-                    the list of active formatting elements that:
-                        * is between the end of the list and the last scope
-                        marker in the list, if any, or the start of the list
-                        otherwise, and
-                        * has the same tag name as the token.
-                    */
-                    while(true) {
-                        for($a = count($this->a_formatting) - 1; $a >= 0; $a--) {
-                            if($this->a_formatting[$a] === self::MARKER) {
-                                break;
-
-                            } elseif($this->a_formatting[$a]->tagName === $token['name']) {
-                                $formatting_element = $this->a_formatting[$a];
-                                $in_stack = in_array($formatting_element, $this->stack, true);
-                                $fe_af_pos = $a;
-                                break;
-                            }
-                        }
-
-                        /* If there is no such node, or, if that node is
-                        also in the stack of open elements but the element
-                        is not in scope, then this is a parse error. Abort
-                        these steps. The token is ignored. */
-                        if(!isset($formatting_element) || ($in_stack &&
-                        !$this->elementInScope($token['name']))) {
-                            break;
-
-                        /* Otherwise, if there is such a node, but that node
-                        is not in the stack of open elements, then this is a
-                        parse error; remove the element from the list, and
-                        abort these steps. */
-                        } elseif(isset($formatting_element) && !$in_stack) {
-                            unset($this->a_formatting[$fe_af_pos]);
-                            $this->a_formatting = array_merge($this->a_formatting);
-                            break;
-                        }
-
-                        /* 2. Let the furthest block be the topmost node in the
-                        stack of open elements that is lower in the stack
-                        than the formatting element, and is not an element in
-                        the phrasing or formatting categories. There might
-                        not be one. */
-                        $fe_s_pos = array_search($formatting_element, $this->stack, true);
-                        $length = count($this->stack);
-
-                        for($s = $fe_s_pos + 1; $s < $length; $s++) {
-                            $category = $this->getElementCategory($this->stack[$s]->nodeName);
-
-                            if($category !== self::PHRASING && $category !== self::FORMATTING) {
-                                $furthest_block = $this->stack[$s];
-                            }
-                        }
-
-                        /* 3. If there is no furthest block, then the UA must
-                        skip the subsequent steps and instead just pop all
-                        the nodes from the bottom of the stack of open
-                        elements, from the current node up to the formatting
-                        element, and remove the formatting element from the
-                        list of active formatting elements. */
-                        if(!isset($furthest_block)) {
-                            for($n = $length - 1; $n >= $fe_s_pos; $n--) {
-                                array_pop($this->stack);
-                            }
-
-                            unset($this->a_formatting[$fe_af_pos]);
-                            $this->a_formatting = array_merge($this->a_formatting);
-                            break;
-                        }
-
-                        /* 4. Let the common ancestor be the element
-                        immediately above the formatting element in the stack
-                        of open elements. */
-                        $common_ancestor = $this->stack[$fe_s_pos - 1];
-
-                        /* 5. If the furthest block has a parent node, then
-                        remove the furthest block from its parent node. */
-                        if($furthest_block->parentNode !== null) {
-                            $furthest_block->parentNode->removeChild($furthest_block);
-                        }
-
-                        /* 6. Let a bookmark note the position of the
-                        formatting element in the list of active formatting
-                        elements relative to the elements on either side
-                        of it in the list. */
-                        $bookmark = $fe_af_pos;
-
-                        /* 7. Let node and last node  be the furthest block.
-                        Follow these steps: */
-                        $node = $furthest_block;
-                        $last_node = $furthest_block;
-
-                        while(true) {
-                            for($n = array_search($node, $this->stack, true) - 1; $n >= 0; $n--) {
-                                /* 7.1 Let node be the element immediately
-                                prior to node in the stack of open elements. */
-                                $node = $this->stack[$n];
-
-                                /* 7.2 If node is not in the list of active
-                                formatting elements, then remove node from
-                                the stack of open elements and then go back
-                                to step 1. */
-                                if(!in_array($node, $this->a_formatting, true)) {
-                                    unset($this->stack[$n]);
-                                    $this->stack = array_merge($this->stack);
-
-                                } else {
-                                    break;
-                                }
-                            }
-
-                            /* 7.3 Otherwise, if node is the formatting
-                            element, then go to the next step in the overall
-                            algorithm. */
-                            if($node === $formatting_element) {
-                                break;
-
-                            /* 7.4 Otherwise, if last node is the furthest
-                            block, then move the aforementioned bookmark to
-                            be immediately after the node in the list of
-                            active formatting elements. */
-                            } elseif($last_node === $furthest_block) {
-                                $bookmark = array_search($node, $this->a_formatting, true) + 1;
-                            }
-
-                            /* 7.5 If node has any children, perform a
-                            shallow clone of node, replace the entry for
-                            node in the list of active formatting elements
-                            with an entry for the clone, replace the entry
-                            for node in the stack of open elements with an
-                            entry for the clone, and let node be the clone. */
-                            if($node->hasChildNodes()) {
-                                $clone = $node->cloneNode();
-                                $s_pos = array_search($node, $this->stack, true);
-                                $a_pos = array_search($node, $this->a_formatting, true);
-
-                                $this->stack[$s_pos] = $clone;
-                                $this->a_formatting[$a_pos] = $clone;
-                                $node = $clone;
-                            }
-
-                            /* 7.6 Insert last node into node, first removing
-                            it from its previous parent node if any. */
-                            if($last_node->parentNode !== null) {
-                                $last_node->parentNode->removeChild($last_node);
-                            }
-
-                            $node->appendChild($last_node);
-
-                            /* 7.7 Let last node be node. */
-                            $last_node = $node;
-                        }
-
-                        /* 8. Insert whatever last node ended up being in
-                        the previous step into the common ancestor node,
-                        first removing it from its previous parent node if
-                        any. */
-                        if($last_node->parentNode !== null) {
-                            $last_node->parentNode->removeChild($last_node);
-                        }
-
-                        $common_ancestor->appendChild($last_node);
-
-                        /* 9. Perform a shallow clone of the formatting
-                        element. */
-                        $clone = $formatting_element->cloneNode();
-
-                        /* 10. Take all of the child nodes of the furthest
-                        block and append them to the clone created in the
-                        last step. */
-                        while($furthest_block->hasChildNodes()) {
-                            $child = $furthest_block->firstChild;
-                            $furthest_block->removeChild($child);
-                            $clone->appendChild($child);
-                        }
-
-                        /* 11. Append that clone to the furthest block. */
-                        $furthest_block->appendChild($clone);
-
-                        /* 12. Remove the formatting element from the list
-                        of active formatting elements, and insert the clone
-                        into the list of active formatting elements at the
-                        position of the aforementioned bookmark. */
-                        $fe_af_pos = array_search($formatting_element, $this->a_formatting, true);
-                        unset($this->a_formatting[$fe_af_pos]);
-                        $this->a_formatting = array_merge($this->a_formatting);
-
-                        $af_part1 = array_slice($this->a_formatting, 0, $bookmark - 1);
-                        $af_part2 = array_slice($this->a_formatting, $bookmark, count($this->a_formatting));
-                        $this->a_formatting = array_merge($af_part1, array($clone), $af_part2);
-
-                        /* 13. Remove the formatting element from the stack
-                        of open elements, and insert the clone into the stack
-                        of open elements immediately after (i.e. in a more
-                        deeply nested position than) the position of the
-                        furthest block in that stack. */
-                        $fe_s_pos = array_search($formatting_element, $this->stack, true);
-                        $fb_s_pos = array_search($furthest_block, $this->stack, true);
-                        unset($this->stack[$fe_s_pos]);
-
-                        $s_part1 = array_slice($this->stack, 0, $fb_s_pos);
-                        $s_part2 = array_slice($this->stack, $fb_s_pos + 1, count($this->stack));
-                        $this->stack = array_merge($s_part1, array($clone), $s_part2);
-
-                        /* 14. Jump back to step 1 in this series of steps. */
-                        unset($formatting_element, $fe_af_pos, $fe_s_pos, $furthest_block);
-                    }
-                break;
-
-                /* An end tag token whose tag name is one of: "button",
-                "marquee", "object" */
-                case 'button': case 'marquee': case 'object':
-                    /* If the stack of open elements has an element in scope whose
-                    tag name matches the tag name of the token, then generate implied
-                    tags. */
-                    if($this->elementInScope($token['name'])) {
-                        $this->generateImpliedEndTags();
-
-                        /* Now, if the current node is not an element with the same
-                        tag name as the token, then this is a parse error. */
-                        // k
-
-                        /* Now, if the stack of open elements has an element in scope
-                        whose tag name matches the tag name of the token, then pop
-                        elements from the stack until that element has been popped from
-                        the stack, and clear the list of active formatting elements up
-                        to the last marker. */
-                        for($n = count($this->stack) - 1; $n >= 0; $n--) {
-                            if($this->stack[$n]->nodeName === $token['name']) {
-                                $n = -1;
-                            }
-
-                            array_pop($this->stack);
-                        }
-
-                        $marker = end(array_keys($this->a_formatting, self::MARKER, true));
-
-                        for($n = count($this->a_formatting) - 1; $n > $marker; $n--) {
-                            array_pop($this->a_formatting);
-                        }
-                    }
-                break;
-
-                /* Or an end tag whose tag name is one of: "area", "basefont",
-                "bgsound", "br", "embed", "hr", "iframe", "image", "img",
-                "input", "isindex", "noembed", "noframes", "param", "select",
-                "spacer", "table", "textarea", "wbr" */
-                case 'area': case 'basefont': case 'bgsound': case 'br':
-                case 'embed': case 'hr': case 'iframe': case 'image':
-                case 'img': case 'input': case 'isindex': case 'noembed':
-                case 'noframes': case 'param': case 'select': case 'spacer':
-                case 'table': case 'textarea': case 'wbr':
-                    // Parse error. Ignore the token.
-                break;
-
-                /* An end tag token not covered by the previous entries */
-                default:
-                    for($n = count($this->stack) - 1; $n >= 0; $n--) {
-                        /* Initialise node to be the current node (the bottommost
-                        node of the stack). */
-                        $node = end($this->stack);
-
-                        /* If node has the same tag name as the end tag token,
-                        then: */
-                        if($token['name'] === $node->nodeName) {
-                            /* Generate implied end tags. */
-                            $this->generateImpliedEndTags();
-
-                            /* If the tag name of the end tag token does not
-                            match the tag name of the current node, this is a
-                            parse error. */
-                            // k
-
-                            /* Pop all the nodes from the current node up to
-                            node, including node, then stop this algorithm. */
-                            for($x = count($this->stack) - $n; $x >= $n; $x--) {
-                                array_pop($this->stack);
-                            }
-                                    
-                        } else {
-                            $category = $this->getElementCategory($node);
-
-                            if($category !== self::SPECIAL && $category !== self::SCOPING) {
-                                /* Otherwise, if node is in neither the formatting
-                                category nor the phrasing category, then this is a
-                                parse error. Stop this algorithm. The end tag token
-                                is ignored. */
-                                return false;
-                            }
-                        }
-                    }
-                break;
-            }
-            break;
-        }
-    }
-
-    private function inTable($token) {
-        $clear = array('html', 'table');
-
-        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        or U+0020 SPACE */
-        if($token['type'] === HTML5::CHARACTR &&
-        preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) {
-            /* Append the character to the current node. */
-            $text = $this->dom->createTextNode($token['data']);
-            end($this->stack)->appendChild($text);
-
-        /* A comment token */
-        } elseif($token['type'] === HTML5::COMMENT) {
-            /* Append a Comment node to the current node with the data
-            attribute set to the data given in the comment token. */
-            $comment = $this->dom->createComment($token['data']);
-            end($this->stack)->appendChild($comment);
-
-        /* A start tag whose tag name is "caption" */
-        } elseif($token['type'] === HTML5::STARTTAG &&
-        $token['name'] === 'caption') {
-            /* Clear the stack back to a table context. */
-            $this->clearStackToTableContext($clear);
-
-            /* Insert a marker at the end of the list of active
-            formatting elements. */
-            $this->a_formatting[] = self::MARKER;
-
-            /* Insert an HTML element for the token, then switch the
-            insertion mode to "in caption". */
-            $this->insertElement($token);
-            $this->mode = self::IN_CAPTION;
-
-        /* A start tag whose tag name is "colgroup" */
-        } elseif($token['type'] === HTML5::STARTTAG &&
-        $token['name'] === 'colgroup') {
-            /* Clear the stack back to a table context. */
-            $this->clearStackToTableContext($clear);
-
-            /* Insert an HTML element for the token, then switch the
-            insertion mode to "in column group". */
-            $this->insertElement($token);
-            $this->mode = self::IN_CGROUP;
-
-        /* A start tag whose tag name is "col" */
-        } elseif($token['type'] === HTML5::STARTTAG &&
-        $token['name'] === 'col') {
-            $this->inTable(array(
-                'name' => 'colgroup',
-                'type' => HTML5::STARTTAG,
-                'attr' => array()
-            ));
-
-            $this->inColumnGroup($token);
-
-        /* A start tag whose tag name is one of: "tbody", "tfoot", "thead" */
-        } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'],
-        array('tbody', 'tfoot', 'thead'))) {
-            /* Clear the stack back to a table context. */
-            $this->clearStackToTableContext($clear);
-
-            /* Insert an HTML element for the token, then switch the insertion
-            mode to "in table body". */
-            $this->insertElement($token);
-            $this->mode = self::IN_TBODY;
-
-        /* A start tag whose tag name is one of: "td", "th", "tr" */
-        } elseif($token['type'] === HTML5::STARTTAG &&
-        in_array($token['name'], array('td', 'th', 'tr'))) {
-            /* Act as if a start tag token with the tag name "tbody" had been
-            seen, then reprocess the current token. */
-            $this->inTable(array(
-                'name' => 'tbody',
-                'type' => HTML5::STARTTAG,
-                'attr' => array()
-            ));
-
-            return $this->inTableBody($token);
-
-        /* A start tag whose tag name is "table" */
-        } elseif($token['type'] === HTML5::STARTTAG &&
-        $token['name'] === 'table') {
-            /* Parse error. Act as if an end tag token with the tag name "table"
-            had been seen, then, if that token wasn't ignored, reprocess the
-            current token. */
-            $this->inTable(array(
-                'name' => 'table',
-                'type' => HTML5::ENDTAG
-            ));
-
-            return $this->mainPhase($token);
-
-        /* An end tag whose tag name is "table" */
-        } elseif($token['type'] === HTML5::ENDTAG &&
-        $token['name'] === 'table') {
-            /* If the stack of open elements does not have an element in table
-            scope with the same tag name as the token, this is a parse error.
-            Ignore the token. (innerHTML case) */
-            if(!$this->elementInScope($token['name'], true)) {
-                return false;
-
-            /* Otherwise: */
-            } else {
-                /* Generate implied end tags. */
-                $this->generateImpliedEndTags();
-
-                /* Now, if the current node is not a table element, then this
-                is a parse error. */
-                // w/e
-
-                /* Pop elements from this stack until a table element has been
-                popped from the stack. */
-                while(true) {
-                    $current = end($this->stack)->nodeName;
-                    array_pop($this->stack);
-
-                    if($current === 'table') {
-                        break;
-                    }
-                }
-
-                /* Reset the insertion mode appropriately. */
-                $this->resetInsertionMode();
-            }
-
-        /* An end tag whose tag name is one of: "body", "caption", "col",
-        "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr" */
-        } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'],
-        array('body', 'caption', 'col', 'colgroup', 'html', 'tbody', 'td',
-        'tfoot', 'th', 'thead', 'tr'))) {
-            // Parse error. Ignore the token.
-
-        /* Anything else */
-        } else {
-            /* Parse error. Process the token as if the insertion mode was "in
-            body", with the following exception: */
-
-            /* If the current node is a table, tbody, tfoot, thead, or tr
-            element, then, whenever a node would be inserted into the current
-            node, it must instead be inserted into the foster parent element. */
-            if(in_array(end($this->stack)->nodeName,
-            array('table', 'tbody', 'tfoot', 'thead', 'tr'))) {
-                /* The foster parent element is the parent element of the last
-                table element in the stack of open elements, if there is a
-                table element and it has such a parent element. If there is no
-                table element in the stack of open elements (innerHTML case),
-                then the foster parent element is the first element in the
-                stack of open elements (the html  element). Otherwise, if there
-                is a table element in the stack of open elements, but the last
-                table element in the stack of open elements has no parent, or
-                its parent node is not an element, then the foster parent
-                element is the element before the last table element in the
-                stack of open elements. */
-                for($n = count($this->stack) - 1; $n >= 0; $n--) {
-                    if($this->stack[$n]->nodeName === 'table') {
-                        $table = $this->stack[$n];
-                        break;
-                    }
-                }
-
-                if(isset($table) && $table->parentNode !== null) {
-                    $this->foster_parent = $table->parentNode;
-
-                } elseif(!isset($table)) {
-                    $this->foster_parent = $this->stack[0];
-
-                } elseif(isset($table) && ($table->parentNode === null ||
-                $table->parentNode->nodeType !== XML_ELEMENT_NODE)) {
-                    $this->foster_parent = $this->stack[$n - 1];
-                }
-            }
-
-            $this->inBody($token);
-        }
-    }
-
-    private function inCaption($token) {
-        /* An end tag whose tag name is "caption" */
-        if($token['type'] === HTML5::ENDTAG && $token['name'] === 'caption') {
-            /* If the stack of open elements does not have an element in table
-            scope with the same tag name as the token, this is a parse error.
-            Ignore the token. (innerHTML case) */
-            if(!$this->elementInScope($token['name'], true)) {
-                // Ignore
-
-            /* Otherwise: */
-            } else {
-                /* Generate implied end tags. */
-                $this->generateImpliedEndTags();
-
-                /* Now, if the current node is not a caption element, then this
-                is a parse error. */
-                // w/e
-
-                /* Pop elements from this stack until a caption element has
-                been popped from the stack. */
-                while(true) {
-                    $node = end($this->stack)->nodeName;
-                    array_pop($this->stack);
-
-                    if($node === 'caption') {
-                        break;
-                    }
-                }
-
-                /* Clear the list of active formatting elements up to the last
-                marker. */
-                $this->clearTheActiveFormattingElementsUpToTheLastMarker();
-
-                /* Switch the insertion mode to "in table". */
-                $this->mode = self::IN_TABLE;
-            }
-
-        /* A start tag whose tag name is one of: "caption", "col", "colgroup",
-        "tbody", "td", "tfoot", "th", "thead", "tr", or an end tag whose tag
-        name is "table" */
-        } elseif(($token['type'] === HTML5::STARTTAG && in_array($token['name'],
-        array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th',
-        'thead', 'tr'))) || ($token['type'] === HTML5::ENDTAG &&
-        $token['name'] === 'table')) {
-            /* Parse error. Act as if an end tag with the tag name "caption"
-            had been seen, then, if that token wasn't ignored, reprocess the
-            current token. */
-            $this->inCaption(array(
-                'name' => 'caption',
-                'type' => HTML5::ENDTAG
-            ));
-
-            return $this->inTable($token);
-
-        /* An end tag whose tag name is one of: "body", "col", "colgroup",
-        "html", "tbody", "td", "tfoot", "th", "thead", "tr" */
-        } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'],
-        array('body', 'col', 'colgroup', 'html', 'tbody', 'tfoot', 'th',
-        'thead', 'tr'))) {
-            // Parse error. Ignore the token.
-
-        /* Anything else */
-        } else {
-            /* Process the token as if the insertion mode was "in body". */
-            $this->inBody($token);
-        }
-    }
-
-    private function inColumnGroup($token) {
-        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        or U+0020 SPACE */
-        if($token['type'] === HTML5::CHARACTR &&
-        preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) {
-            /* Append the character to the current node. */
-            $text = $this->dom->createTextNode($token['data']);
-            end($this->stack)->appendChild($text);
-
-        /* A comment token */
-        } elseif($token['type'] === HTML5::COMMENT) {
-            /* Append a Comment node to the current node with the data
-            attribute set to the data given in the comment token. */
-            $comment = $this->dom->createComment($token['data']);
-            end($this->stack)->appendChild($comment);
-
-        /* A start tag whose tag name is "col" */
-        } elseif($token['type'] === HTML5::STARTTAG && $token['name'] === 'col') {
-            /* Insert a col element for the token. Immediately pop the current
-            node off the stack of open elements. */
-            $this->insertElement($token);
-            array_pop($this->stack);
-
-        /* An end tag whose tag name is "colgroup" */
-        } elseif($token['type'] === HTML5::ENDTAG &&
-        $token['name'] === 'colgroup') {
-            /* If the current node is the root html element, then this is a
-            parse error, ignore the token. (innerHTML case) */
-            if(end($this->stack)->nodeName === 'html') {
-                // Ignore
-
-            /* Otherwise, pop the current node (which will be a colgroup
-            element) from the stack of open elements. Switch the insertion
-            mode to "in table". */
-            } else {
-                array_pop($this->stack);
-                $this->mode = self::IN_TABLE;
-            }
-
-        /* An end tag whose tag name is "col" */
-        } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'col') {
-            /* Parse error. Ignore the token. */
-
-        /* Anything else */
-        } else {
-            /* Act as if an end tag with the tag name "colgroup" had been seen,
-            and then, if that token wasn't ignored, reprocess the current token. */
-            $this->inColumnGroup(array(
-                'name' => 'colgroup',
-                'type' => HTML5::ENDTAG
-            ));
-
-            return $this->inTable($token);
-        }
-    }
-
-    private function inTableBody($token) {
-        $clear = array('tbody', 'tfoot', 'thead', 'html');
-
-        /* A start tag whose tag name is "tr" */
-        if($token['type'] === HTML5::STARTTAG && $token['name'] === 'tr') {
-            /* Clear the stack back to a table body context. */
-            $this->clearStackToTableContext($clear);
-
-            /* Insert a tr element for the token, then switch the insertion
-            mode to "in row". */
-            $this->insertElement($token);
-            $this->mode = self::IN_ROW;
-
-        /* A start tag whose tag name is one of: "th", "td" */
-        } elseif($token['type'] === HTML5::STARTTAG &&
-        ($token['name'] === 'th' ||    $token['name'] === 'td')) {
-            /* Parse error. Act as if a start tag with the tag name "tr" had
-            been seen, then reprocess the current token. */
-            $this->inTableBody(array(
-                'name' => 'tr',
-                'type' => HTML5::STARTTAG,
-                'attr' => array()
-            ));
-
-            return $this->inRow($token);
-
-        /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */
-        } elseif($token['type'] === HTML5::ENDTAG &&
-        in_array($token['name'], array('tbody', 'tfoot', 'thead'))) {
-            /* If the stack of open elements does not have an element in table
-            scope with the same tag name as the token, this is a parse error.
-            Ignore the token. */
-            if(!$this->elementInScope($token['name'], true)) {
-                // Ignore
-
-            /* Otherwise: */
-            } else {
-                /* Clear the stack back to a table body context. */
-                $this->clearStackToTableContext($clear);
-
-                /* Pop the current node from the stack of open elements. Switch
-                the insertion mode to "in table". */
-                array_pop($this->stack);
-                $this->mode = self::IN_TABLE;
-            }
-
-        /* A start tag whose tag name is one of: "caption", "col", "colgroup",
-        "tbody", "tfoot", "thead", or an end tag whose tag name is "table" */
-        } elseif(($token['type'] === HTML5::STARTTAG && in_array($token['name'],
-        array('caption', 'col', 'colgroup', 'tbody', 'tfoor', 'thead'))) ||
-        ($token['type'] === HTML5::STARTTAG && $token['name'] === 'table')) {
-            /* If the stack of open elements does not have a tbody, thead, or
-            tfoot element in table scope, this is a parse error. Ignore the
-            token. (innerHTML case) */
-            if(!$this->elementInScope(array('tbody', 'thead', 'tfoot'), true)) {
-                // Ignore.
-
-            /* Otherwise: */
-            } else {
-                /* Clear the stack back to a table body context. */
-                $this->clearStackToTableContext($clear);
-
-                /* Act as if an end tag with the same tag name as the current
-                node ("tbody", "tfoot", or "thead") had been seen, then
-                reprocess the current token. */
-                $this->inTableBody(array(
-                    'name' => end($this->stack)->nodeName,
-                    'type' => HTML5::ENDTAG
-                ));
-
-                return $this->mainPhase($token);
-            }
-
-        /* An end tag whose tag name is one of: "body", "caption", "col",
-        "colgroup", "html", "td", "th", "tr" */
-        } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'],
-        array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr'))) {
-            /* Parse error. Ignore the token. */
-
-        /* Anything else */
-        } else {
-            /* Process the token as if the insertion mode was "in table". */
-            $this->inTable($token);
-        }
-    }
-
-    private function inRow($token) {
-        $clear = array('tr', 'html');
-
-        /* A start tag whose tag name is one of: "th", "td" */
-        if($token['type'] === HTML5::STARTTAG &&
-        ($token['name'] === 'th' || $token['name'] === 'td')) {
-            /* Clear the stack back to a table row context. */
-            $this->clearStackToTableContext($clear);
-
-            /* Insert an HTML element for the token, then switch the insertion
-            mode to "in cell". */
-            $this->insertElement($token);
-            $this->mode = self::IN_CELL;
-
-            /* Insert a marker at the end of the list of active formatting
-            elements. */
-            $this->a_formatting[] = self::MARKER;
-
-        /* An end tag whose tag name is "tr" */
-        } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'tr') {
-            /* If the stack of open elements does not have an element in table
-            scope with the same tag name as the token, this is a parse error.
-            Ignore the token. (innerHTML case) */
-            if(!$this->elementInScope($token['name'], true)) {
-                // Ignore.
-
-            /* Otherwise: */
-            } else {
-                /* Clear the stack back to a table row context. */
-                $this->clearStackToTableContext($clear);
-
-                /* Pop the current node (which will be a tr element) from the
-                stack of open elements. Switch the insertion mode to "in table
-                body". */
-                array_pop($this->stack);
-                $this->mode = self::IN_TBODY;
-            }
-
-        /* A start tag whose tag name is one of: "caption", "col", "colgroup",
-        "tbody", "tfoot", "thead", "tr" or an end tag whose tag name is "table" */
-        } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'],
-        array('caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead', 'tr'))) {
-            /* Act as if an end tag with the tag name "tr" had been seen, then,
-            if that token wasn't ignored, reprocess the current token. */
-            $this->inRow(array(
-                'name' => 'tr',
-                'type' => HTML5::ENDTAG
-            ));
-
-            return $this->inCell($token);
-
-        /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */
-        } elseif($token['type'] === HTML5::ENDTAG &&
-        in_array($token['name'], array('tbody', 'tfoot', 'thead'))) {
-            /* If the stack of open elements does not have an element in table
-            scope with the same tag name as the token, this is a parse error.
-            Ignore the token. */
-            if(!$this->elementInScope($token['name'], true)) {
-                // Ignore.
-
-            /* Otherwise: */
-            } else {
-                /* Otherwise, act as if an end tag with the tag name "tr" had
-                been seen, then reprocess the current token. */
-                $this->inRow(array(
-                    'name' => 'tr',
-                    'type' => HTML5::ENDTAG
-                ));
-
-                return $this->inCell($token);
-            }
-
-        /* An end tag whose tag name is one of: "body", "caption", "col",
-        "colgroup", "html", "td", "th" */
-        } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'],
-        array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr'))) {
-            /* Parse error. Ignore the token. */
-
-        /* Anything else */
-        } else {
-            /* Process the token as if the insertion mode was "in table". */
-            $this->inTable($token);
-        }
-    }
-
-    private function inCell($token) {
-        /* An end tag whose tag name is one of: "td", "th" */
-        if($token['type'] === HTML5::ENDTAG &&
-        ($token['name'] === 'td' || $token['name'] === 'th')) {
-            /* If the stack of open elements does not have an element in table
-            scope with the same tag name as that of the token, then this is a
-            parse error and the token must be ignored. */
-            if(!$this->elementInScope($token['name'], true)) {
-                // Ignore.
-
-            /* Otherwise: */
-            } else {
-                /* Generate implied end tags, except for elements with the same
-                tag name as the token. */
-                $this->generateImpliedEndTags(array($token['name']));
-
-                /* Now, if the current node is not an element with the same tag
-                name as the token, then this is a parse error. */
-                // k
-
-                /* Pop elements from this stack until an element with the same
-                tag name as the token has been popped from the stack. */
-                while(true) {
-                    $node = end($this->stack)->nodeName;
-                    array_pop($this->stack);
-
-                    if($node === $token['name']) {
-                        break;
-                    }
-                }
-
-                /* Clear the list of active formatting elements up to the last
-                marker. */
-                $this->clearTheActiveFormattingElementsUpToTheLastMarker();
-
-                /* Switch the insertion mode to "in row". (The current node
-                will be a tr element at this point.) */
-                $this->mode = self::IN_ROW;
-            }
-
-        /* A start tag whose tag name is one of: "caption", "col", "colgroup",
-        "tbody", "td", "tfoot", "th", "thead", "tr" */
-        } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'],
-        array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th',
-        'thead', 'tr'))) {
-            /* If the stack of open elements does not have a td or th element
-            in table scope, then this is a parse error; ignore the token.
-            (innerHTML case) */
-            if(!$this->elementInScope(array('td', 'th'), true)) {
-                // Ignore.
-
-            /* Otherwise, close the cell (see below) and reprocess the current
-            token. */
-            } else {
-                $this->closeCell();
-                return $this->inRow($token);
-            }
-
-        /* A start tag whose tag name is one of: "caption", "col", "colgroup",
-        "tbody", "td", "tfoot", "th", "thead", "tr" */
-        } elseif($token['type'] === HTML5::STARTTAG && in_array($token['name'],
-        array('caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th',
-        'thead', 'tr'))) {
-            /* If the stack of open elements does not have a td or th element
-            in table scope, then this is a parse error; ignore the token.
-            (innerHTML case) */
-            if(!$this->elementInScope(array('td', 'th'), true)) {
-                // Ignore.
-
-            /* Otherwise, close the cell (see below) and reprocess the current
-            token. */
-            } else {
-                $this->closeCell();
-                return $this->inRow($token);
-            }
-
-        /* An end tag whose tag name is one of: "body", "caption", "col",
-        "colgroup", "html" */
-        } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'],
-        array('body', 'caption', 'col', 'colgroup', 'html'))) {
-            /* Parse error. Ignore the token. */
-
-        /* An end tag whose tag name is one of: "table", "tbody", "tfoot",
-        "thead", "tr" */
-        } elseif($token['type'] === HTML5::ENDTAG && in_array($token['name'],
-        array('table', 'tbody', 'tfoot', 'thead', 'tr'))) {
-            /* If the stack of open elements does not have an element in table
-            scope with the same tag name as that of the token (which can only
-            happen for "tbody", "tfoot" and "thead", or, in the innerHTML case),
-            then this is a parse error and the token must be ignored. */
-            if(!$this->elementInScope($token['name'], true)) {
-                // Ignore.
-
-            /* Otherwise, close the cell (see below) and reprocess the current
-            token. */
-            } else {
-                $this->closeCell();
-                return $this->inRow($token);
-            }
-
-        /* Anything else */
-        } else {
-            /* Process the token as if the insertion mode was "in body". */
-            $this->inBody($token);
-        }
-    }
-
-    private function inSelect($token) {
-        /* Handle the token as follows: */
-
-        /* A character token */
-        if($token['type'] === HTML5::CHARACTR) {
-            /* Append the token's character to the current node. */
-            $this->insertText($token['data']);
-
-        /* A comment token */
-        } elseif($token['type'] === HTML5::COMMENT) {
-            /* Append a Comment node to the current node with the data
-            attribute set to the data given in the comment token. */
-            $this->insertComment($token['data']);
-
-        /* A start tag token whose tag name is "option" */
-        } elseif($token['type'] === HTML5::STARTTAG &&
-        $token['name'] === 'option') {
-            /* If the current node is an option element, act as if an end tag
-            with the tag name "option" had been seen. */
-            if(end($this->stack)->nodeName === 'option') {
-                $this->inSelect(array(
-                    'name' => 'option',
-                    'type' => HTML5::ENDTAG
-                ));
-            }
-
-            /* Insert an HTML element for the token. */
-            $this->insertElement($token);
-
-        /* A start tag token whose tag name is "optgroup" */
-        } elseif($token['type'] === HTML5::STARTTAG &&
-        $token['name'] === 'optgroup') {
-            /* If the current node is an option element, act as if an end tag
-            with the tag name "option" had been seen. */
-            if(end($this->stack)->nodeName === 'option') {
-                $this->inSelect(array(
-                    'name' => 'option',
-                    'type' => HTML5::ENDTAG
-                ));
-            }
-
-            /* If the current node is an optgroup element, act as if an end tag
-            with the tag name "optgroup" had been seen. */
-            if(end($this->stack)->nodeName === 'optgroup') {
-                $this->inSelect(array(
-                    'name' => 'optgroup',
-                    'type' => HTML5::ENDTAG
-                ));
-            }
-
-            /* Insert an HTML element for the token. */
-            $this->insertElement($token);
-
-        /* An end tag token whose tag name is "optgroup" */
-        } elseif($token['type'] === HTML5::ENDTAG &&
-        $token['name'] === 'optgroup') {
-            /* First, if the current node is an option element, and the node
-            immediately before it in the stack of open elements is an optgroup
-            element, then act as if an end tag with the tag name "option" had
-            been seen. */
-            $elements_in_stack = count($this->stack);
-
-            if($this->stack[$elements_in_stack - 1]->nodeName === 'option' &&
-            $this->stack[$elements_in_stack - 2]->nodeName === 'optgroup') {
-                $this->inSelect(array(
-                    'name' => 'option',
-                    'type' => HTML5::ENDTAG
-                ));
-            }
-
-            /* If the current node is an optgroup element, then pop that node
-            from the stack of open elements. Otherwise, this is a parse error,
-            ignore the token. */
-            if($this->stack[$elements_in_stack - 1] === 'optgroup') {
-                array_pop($this->stack);
-            }
-
-        /* An end tag token whose tag name is "option" */
-        } elseif($token['type'] === HTML5::ENDTAG &&
-        $token['name'] === 'option') {
-            /* If the current node is an option element, then pop that node
-            from the stack of open elements. Otherwise, this is a parse error,
-            ignore the token. */
-            if(end($this->stack)->nodeName === 'option') {
-                array_pop($this->stack);
-            }
-
-        /* An end tag whose tag name is "select" */
-        } elseif($token['type'] === HTML5::ENDTAG &&
-        $token['name'] === 'select') {
-            /* If the stack of open elements does not have an element in table
-            scope with the same tag name as the token, this is a parse error.
-            Ignore the token. (innerHTML case) */
-            if(!$this->elementInScope($token['name'], true)) {
-                // w/e
-
-            /* Otherwise: */
-            } else {
-                /* Pop elements from the stack of open elements until a select
-                element has been popped from the stack. */
-                while(true) {
-                    $current = end($this->stack)->nodeName;
-                    array_pop($this->stack);
-
-                    if($current === 'select') {
-                        break;
-                    }
-                }
-
-                /* Reset the insertion mode appropriately. */
-                $this->resetInsertionMode();
-            }
-
-        /* A start tag whose tag name is "select" */
-        } elseif($token['name'] === 'select' &&
-        $token['type'] === HTML5::STARTTAG) {
-            /* Parse error. Act as if the token had been an end tag with the
-            tag name "select" instead. */
-            $this->inSelect(array(
-                'name' => 'select',
-                'type' => HTML5::ENDTAG
-            ));
-
-        /* An end tag whose tag name is one of: "caption", "table", "tbody",
-        "tfoot", "thead", "tr", "td", "th" */
-        } elseif(in_array($token['name'], array('caption', 'table', 'tbody',
-        'tfoot', 'thead', 'tr', 'td', 'th')) && $token['type'] === HTML5::ENDTAG) {
-            /* Parse error. */
-            // w/e
-
-            /* If the stack of open elements has an element in table scope with
-            the same tag name as that of the token, then act as if an end tag
-            with the tag name "select" had been seen, and reprocess the token.
-            Otherwise, ignore the token. */
-            if($this->elementInScope($token['name'], true)) {
-                $this->inSelect(array(
-                    'name' => 'select',
-                    'type' => HTML5::ENDTAG
-                ));
-
-                $this->mainPhase($token);
-            }
-
-        /* Anything else */
-        } else {
-            /* Parse error. Ignore the token. */
-        }
-    }
-
-    private function afterBody($token) {
-        /* Handle the token as follows: */
-
-        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        or U+0020 SPACE */
-        if($token['type'] === HTML5::CHARACTR &&
-        preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) {
-            /* Process the token as it would be processed if the insertion mode
-            was "in body". */
-            $this->inBody($token);
-
-        /* A comment token */
-        } elseif($token['type'] === HTML5::COMMENT) {
-            /* Append a Comment node to the first element in the stack of open
-            elements (the html element), with the data attribute set to the
-            data given in the comment token. */
-            $comment = $this->dom->createComment($token['data']);
-            $this->stack[0]->appendChild($comment);
-
-        /* An end tag with the tag name "html" */
-        } elseif($token['type'] === HTML5::ENDTAG && $token['name'] === 'html') {
-            /* If the parser was originally created in order to handle the
-            setting of an element's innerHTML attribute, this is a parse error;
-            ignore the token. (The element will be an html element in this
-            case.) (innerHTML case) */
-
-            /* Otherwise, switch to the trailing end phase. */
-            $this->phase = self::END_PHASE;
-
-        /* Anything else */
-        } else {
-            /* Parse error. Set the insertion mode to "in body" and reprocess
-            the token. */
-            $this->mode = self::IN_BODY;
-            return $this->inBody($token);
-        }
-    }
-
-    private function inFrameset($token) {
-        /* Handle the token as follows: */
-
-        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */
-        if($token['type'] === HTML5::CHARACTR &&
-        preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) {
-            /* Append the character to the current node. */
-            $this->insertText($token['data']);
-
-        /* A comment token */
-        } elseif($token['type'] === HTML5::COMMENT) {
-            /* Append a Comment node to the current node with the data
-            attribute set to the data given in the comment token. */
-            $this->insertComment($token['data']);
-
-        /* A start tag with the tag name "frameset" */
-        } elseif($token['name'] === 'frameset' &&
-        $token['type'] === HTML5::STARTTAG) {
-            $this->insertElement($token);
-
-        /* An end tag with the tag name "frameset" */
-        } elseif($token['name'] === 'frameset' &&
-        $token['type'] === HTML5::ENDTAG) {
-            /* If the current node is the root html element, then this is a
-            parse error; ignore the token. (innerHTML case) */
-            if(end($this->stack)->nodeName === 'html') {
-                // Ignore
-
-            } else {
-                /* Otherwise, pop the current node from the stack of open
-                elements. */
-                array_pop($this->stack);
-
-                /* If the parser was not originally created in order to handle
-                the setting of an element's innerHTML attribute (innerHTML case),
-                and the current node is no longer a frameset element, then change
-                the insertion mode to "after frameset". */
-                $this->mode = self::AFTR_FRAME;
-            }
-
-        /* A start tag with the tag name "frame" */
-        } elseif($token['name'] === 'frame' &&
-        $token['type'] === HTML5::STARTTAG) {
-            /* Insert an HTML element for the token. */
-            $this->insertElement($token);
-
-            /* Immediately pop the current node off the stack of open elements. */
-            array_pop($this->stack);
-
-        /* A start tag with the tag name "noframes" */
-        } elseif($token['name'] === 'noframes' &&
-        $token['type'] === HTML5::STARTTAG) {
-            /* Process the token as if the insertion mode had been "in body". */
-            $this->inBody($token);
-
-        /* Anything else */
-        } else {
-            /* Parse error. Ignore the token. */
-        }
-    }
-
-    private function afterFrameset($token) {
-        /* Handle the token as follows: */
-
-        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */
-        if($token['type'] === HTML5::CHARACTR &&
-        preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) {
-            /* Append the character to the current node. */
-            $this->insertText($token['data']);
-
-        /* A comment token */
-        } elseif($token['type'] === HTML5::COMMENT) {
-            /* Append a Comment node to the current node with the data
-            attribute set to the data given in the comment token. */
-            $this->insertComment($token['data']);
-
-        /* An end tag with the tag name "html" */
-        } elseif($token['name'] === 'html' &&
-        $token['type'] === HTML5::ENDTAG) {
-            /* Switch to the trailing end phase. */
-            $this->phase = self::END_PHASE;
-
-        /* A start tag with the tag name "noframes" */
-        } elseif($token['name'] === 'noframes' &&
-        $token['type'] === HTML5::STARTTAG) {
-            /* Process the token as if the insertion mode had been "in body". */
-            $this->inBody($token);
-
-        /* Anything else */
-        } else {
-            /* Parse error. Ignore the token. */
-        }
-    }
-
-    private function trailingEndPhase($token) {
-        /* After the main phase, as each token is emitted from the tokenisation
-        stage, it must be processed as described in this section. */
-
-        /* A DOCTYPE token */
-        if($token['type'] === HTML5::DOCTYPE) {
-            // Parse error. Ignore the token.
-
-        /* A comment token */
-        } elseif($token['type'] === HTML5::COMMENT) {
-            /* Append a Comment node to the Document object with the data
-            attribute set to the data given in the comment token. */
-            $comment = $this->dom->createComment($token['data']);
-            $this->dom->appendChild($comment);
-
-        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        or U+0020 SPACE */
-        } elseif($token['type'] === HTML5::CHARACTR &&
-        preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) {
-            /* Process the token as it would be processed in the main phase. */
-            $this->mainPhase($token);
-
-        /* A character token that is not one of U+0009 CHARACTER TABULATION,
-        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
-        or U+0020 SPACE. Or a start tag token. Or an end tag token. */
-        } elseif(($token['type'] === HTML5::CHARACTR &&
-        preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) ||
-        $token['type'] === HTML5::STARTTAG || $token['type'] === HTML5::ENDTAG) {
-            /* Parse error. Switch back to the main phase and reprocess the
-            token. */
-            $this->phase = self::MAIN_PHASE;
-            return $this->mainPhase($token);
-
-        /* An end-of-file token */
-        } elseif($token['type'] === HTML5::EOF) {
-            /* OMG DONE!! */
-        }
-    }
-
-    private function insertElement($token, $append = true, $check = false) {
-        // Proprietary workaround for libxml2's limitations with tag names
-        if ($check) {
-            // Slightly modified HTML5 tag-name modification,
-            // removing anything that's not an ASCII letter, digit, or hyphen
-            $token['name'] = preg_replace('/[^a-z0-9-]/i', '', $token['name']);
-            // Remove leading hyphens and numbers
-            $token['name'] = ltrim($token['name'], '-0..9');
-            // In theory, this should ever be needed, but just in case
-            if ($token['name'] === '') $token['name'] = 'span'; // arbitrary generic choice
-        }
-        
-        $el = $this->dom->createElement($token['name']);
-
-        foreach($token['attr'] as $attr) {
-            if(!$el->hasAttribute($attr['name'])) {
-                $el->setAttribute($attr['name'], $attr['value']);
-            }
-        }
-
-        $this->appendToRealParent($el);
-        $this->stack[] = $el;
-
-        return $el;
-    }
-
-    private function insertText($data) {
-        $text = $this->dom->createTextNode($data);
-        $this->appendToRealParent($text);
-    }
-
-    private function insertComment($data) {
-        $comment = $this->dom->createComment($data);
-        $this->appendToRealParent($comment);
-    }
-
-    private function appendToRealParent($node) {
-        if($this->foster_parent === null) {
-            end($this->stack)->appendChild($node);
-
-        } elseif($this->foster_parent !== null) {
-            /* If the foster parent element is the parent element of the
-            last table element in the stack of open elements, then the new
-            node must be inserted immediately before the last table element
-            in the stack of open elements in the foster parent element;
-            otherwise, the new node must be appended to the foster parent
-            element. */
-            for($n = count($this->stack) - 1; $n >= 0; $n--) {
-                if($this->stack[$n]->nodeName === 'table' &&
-                $this->stack[$n]->parentNode !== null) {
-                    $table = $this->stack[$n];
-                    break;
-                }
-            }
-
-            if(isset($table) && $this->foster_parent->isSameNode($table->parentNode))
-                $this->foster_parent->insertBefore($node, $table);
-            else
-                $this->foster_parent->appendChild($node);
-
-            $this->foster_parent = null;
-        }
-    }
-
-    private function elementInScope($el, $table = false) {
-        if(is_array($el)) {
-            foreach($el as $element) {
-                if($this->elementInScope($element, $table)) {
-                    return true;
-                }
-            }
-
-            return false;
-        }
-
-        $leng = count($this->stack);
-
-        for($n = 0; $n < $leng; $n++) {
-            /* 1. Initialise node to be the current node (the bottommost node of
-            the stack). */
-            $node = $this->stack[$leng - 1 - $n];
-
-            if($node->tagName === $el) {
-                /* 2. If node is the target node, terminate in a match state. */
-                return true;
-
-            } elseif($node->tagName === 'table') {
-                /* 3. Otherwise, if node is a table element, terminate in a failure
-                state. */
-                return false;
-
-            } elseif($table === true && in_array($node->tagName, array('caption', 'td',
-            'th', 'button', 'marquee', 'object'))) {
-                /* 4. Otherwise, if the algorithm is the "has an element in scope"
-                variant (rather than the "has an element in table scope" variant),
-                and node is one of the following, terminate in a failure state. */
-                return false;
-
-            } elseif($node === $node->ownerDocument->documentElement) {
-                /* 5. Otherwise, if node is an html element (root element), terminate
-                in a failure state. (This can only happen if the node is the topmost
-                node of the    stack of open elements, and prevents the next step from
-                being invoked if there are no more elements in the stack.) */
-                return false;
-            }
-
-            /* Otherwise, set node to the previous entry in the stack of open
-            elements and return to step 2. (This will never fail, since the loop
-            will always terminate in the previous step if the top of the stack
-            is reached.) */
-        }
-    }
-
-    private function reconstructActiveFormattingElements() {
-        /* 1. If there are no entries in the list of active formatting elements,
-        then there is nothing to reconstruct; stop this algorithm. */
-        $formatting_elements = count($this->a_formatting);
-
-        if($formatting_elements === 0) {
-            return false;
-        }
-
-        /* 3. Let entry be the last (most recently added) element in the list
-        of active formatting elements. */
-        $entry = end($this->a_formatting);
-
-        /* 2. If the last (most recently added) entry in the list of active
-        formatting elements is a marker, or if it is an element that is in the
-        stack of open elements, then there is nothing to reconstruct; stop this
-        algorithm. */
-        if($entry === self::MARKER || in_array($entry, $this->stack, true)) {
-            return false;
-        }
-
-        for($a = $formatting_elements - 1; $a >= 0; true) {
-            /* 4. If there are no entries before entry in the list of active
-            formatting elements, then jump to step 8. */
-            if($a === 0) {
-                $step_seven = false;
-                break;
-            }
-
-            /* 5. Let entry be the entry one earlier than entry in the list of
-            active formatting elements. */
-            $a--;
-            $entry = $this->a_formatting[$a];
-
-            /* 6. If entry is neither a marker nor an element that is also in
-            thetack of open elements, go to step 4. */
-            if($entry === self::MARKER || in_array($entry, $this->stack, true)) {
-                break;
-            }
-        }
-
-        while(true) {
-            /* 7. Let entry be the element one later than entry in the list of
-            active formatting elements. */
-            if(isset($step_seven) && $step_seven === true) {
-                $a++;
-                $entry = $this->a_formatting[$a];
-            }
-
-            /* 8. Perform a shallow clone of the element entry to obtain clone. */
-            $clone = $entry->cloneNode();
-
-            /* 9. Append clone to the current node and push it onto the stack
-            of open elements  so that it is the new current node. */
-            end($this->stack)->appendChild($clone);
-            $this->stack[] = $clone;
-
-            /* 10. Replace the entry for entry in the list with an entry for
-            clone. */
-            $this->a_formatting[$a] = $clone;
-
-            /* 11. If the entry for clone in the list of active formatting
-            elements is not the last entry in the list, return to step 7. */
-            if(end($this->a_formatting) !== $clone) {
-                $step_seven = true;
-            } else {
-                break;
-            }
-        }
-    }
-
-    private function clearTheActiveFormattingElementsUpToTheLastMarker() {
-        /* When the steps below require the UA to clear the list of active
-        formatting elements up to the last marker, the UA must perform the
-        following steps: */
-
-        while(true) {
-            /* 1. Let entry be the last (most recently added) entry in the list
-            of active formatting elements. */
-            $entry = end($this->a_formatting);
-
-            /* 2. Remove entry from the list of active formatting elements. */
-            array_pop($this->a_formatting);
-
-            /* 3. If entry was a marker, then stop the algorithm at this point.
-            The list has been cleared up to the last marker. */
-            if($entry === self::MARKER) {
-                break;
-            }
-        }
-    }
-
-    private function generateImpliedEndTags($exclude = array()) {
-        /* When the steps below require the UA to generate implied end tags,
-        then, if the current node is a dd element, a dt element, an li element,
-        a p element, a td element, a th  element, or a tr element, the UA must
-        act as if an end tag with the respective tag name had been seen and
-        then generate implied end tags again. */
-        $node = end($this->stack);
-        $elements = array_diff(array('dd', 'dt', 'li', 'p', 'td', 'th', 'tr'), $exclude);
-
-        while(in_array(end($this->stack)->nodeName, $elements)) {
-            array_pop($this->stack);
-        }
-    }
-
-    private function getElementCategory($node) {
-        $name = $node->tagName;
-        if(in_array($name, $this->special))
-            return self::SPECIAL;
-
-        elseif(in_array($name, $this->scoping))
-            return self::SCOPING;
-
-        elseif(in_array($name, $this->formatting))
-            return self::FORMATTING;
-
-        else
-            return self::PHRASING;
-    }
-
-    private function clearStackToTableContext($elements) {
-        /* When the steps above require the UA to clear the stack back to a
-        table context, it means that the UA must, while the current node is not
-        a table element or an html element, pop elements from the stack of open
-        elements. If this causes any elements to be popped from the stack, then
-        this is a parse error. */
-        while(true) {
-            $node = end($this->stack)->nodeName;
-
-            if(in_array($node, $elements)) {
-                break;
-            } else {
-                array_pop($this->stack);
-            }
-        }
-    }
-
-    private function resetInsertionMode() {
-        /* 1. Let last be false. */
-        $last = false;
-        $leng = count($this->stack);
-
-        for($n = $leng - 1; $n >= 0; $n--) {
-            /* 2. Let node be the last node in the stack of open elements. */
-            $node = $this->stack[$n];
-
-            /* 3. If node is the first node in the stack of open elements, then
-            set last to true. If the element whose innerHTML  attribute is being
-            set is neither a td  element nor a th element, then set node to the
-            element whose innerHTML  attribute is being set. (innerHTML  case) */
-            if($this->stack[0]->isSameNode($node)) {
-                $last = true;
-            }
-
-            /* 4. If node is a select element, then switch the insertion mode to
-            "in select" and abort these steps. (innerHTML case) */
-            if($node->nodeName === 'select') {
-                $this->mode = self::IN_SELECT;
-                break;
-
-            /* 5. If node is a td or th element, then switch the insertion mode
-            to "in cell" and abort these steps. */
-            } elseif($node->nodeName === 'td' || $node->nodeName === 'th') {
-                $this->mode = self::IN_CELL;
-                break;
-
-            /* 6. If node is a tr element, then switch the insertion mode to
-            "in    row" and abort these steps. */
-            } elseif($node->nodeName === 'tr') {
-                $this->mode = self::IN_ROW;
-                break;
-
-            /* 7. If node is a tbody, thead, or tfoot element, then switch the
-            insertion mode to "in table body" and abort these steps. */
-            } elseif(in_array($node->nodeName, array('tbody', 'thead', 'tfoot'))) {
-                $this->mode = self::IN_TBODY;
-                break;
-
-            /* 8. If node is a caption element, then switch the insertion mode
-            to "in caption" and abort these steps. */
-            } elseif($node->nodeName === 'caption') {
-                $this->mode = self::IN_CAPTION;
-                break;
-
-            /* 9. If node is a colgroup element, then switch the insertion mode
-            to "in column group" and abort these steps. (innerHTML case) */
-            } elseif($node->nodeName === 'colgroup') {
-                $this->mode = self::IN_CGROUP;
-                break;
-
-            /* 10. If node is a table element, then switch the insertion mode
-            to "in table" and abort these steps. */
-            } elseif($node->nodeName === 'table') {
-                $this->mode = self::IN_TABLE;
-                break;
-
-            /* 11. If node is a head element, then switch the insertion mode
-            to "in body" ("in body"! not "in head"!) and abort these steps.
-            (innerHTML case) */
-            } elseif($node->nodeName === 'head') {
-                $this->mode = self::IN_BODY;
-                break;
-
-            /* 12. If node is a body element, then switch the insertion mode to
-            "in body" and abort these steps. */
-            } elseif($node->nodeName === 'body') {
-                $this->mode = self::IN_BODY;
-                break;
-
-            /* 13. If node is a frameset element, then switch the insertion
-            mode to "in frameset" and abort these steps. (innerHTML case) */
-            } elseif($node->nodeName === 'frameset') {
-                $this->mode = self::IN_FRAME;
-                break;
-
-            /* 14. If node is an html element, then: if the head element
-            pointer is null, switch the insertion mode to "before head",
-            otherwise, switch the insertion mode to "after head". In either
-            case, abort these steps. (innerHTML case) */
-            } elseif($node->nodeName === 'html') {
-                $this->mode = ($this->head_pointer === null)
-                    ? self::BEFOR_HEAD
-                    : self::AFTER_HEAD;
-
-                break;
-
-            /* 15. If last is true, then set the insertion mode to "in body"
-            and    abort these steps. (innerHTML case) */
-            } elseif($last) {
-                $this->mode = self::IN_BODY;
-                break;
-            }
-        }
-    }
-
-    private function closeCell() {
-        /* If the stack of open elements has a td or th element in table scope,
-        then act as if an end tag token with that tag name had been seen. */
-        foreach(array('td', 'th') as $cell) {
-            if($this->elementInScope($cell, true)) {
-                $this->inCell(array(
-                    'name' => $cell,
-                    'type' => HTML5::ENDTAG
-                ));
-
-                break;
-            }
-        }
-    }
-
-    public function save() {
-        return $this->dom;
-    }
-}
-?>
diff --git a/library/HTMLPurifier/Strategy/FixNesting.php b/library/HTMLPurifier/Strategy/FixNesting.php
deleted file mode 100644
index f81802391b..0000000000
--- a/library/HTMLPurifier/Strategy/FixNesting.php
+++ /dev/null
@@ -1,328 +0,0 @@
-<?php
-
-/**
- * Takes a well formed list of tokens and fixes their nesting.
- *
- * HTML elements dictate which elements are allowed to be their children,
- * for example, you can't have a p tag in a span tag.  Other elements have
- * much more rigorous definitions: tables, for instance, require a specific
- * order for their elements.  There are also constraints not expressible by
- * document type definitions, such as the chameleon nature of ins/del
- * tags and global child exclusions.
- *
- * The first major objective of this strategy is to iterate through all the
- * nodes (not tokens) of the list of tokens and determine whether or not
- * their children conform to the element's definition.  If they do not, the
- * child definition may optionally supply an amended list of elements that
- * is valid or require that the entire node be deleted (and the previous
- * node rescanned).
- *
- * The second objective is to ensure that explicitly excluded elements of
- * an element do not appear in its children.  Code that accomplishes this
- * task is pervasive through the strategy, though the two are distinct tasks
- * and could, theoretically, be seperated (although it's not recommended).
- *
- * @note Whether or not unrecognized children are silently dropped or
- *       translated into text depends on the child definitions.
- *
- * @todo Enable nodes to be bubbled out of the structure.
- */
-
-class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
-{
-
-    public function execute($tokens, $config, $context) {
-        //####################################################################//
-        // Pre-processing
-
-        // get a copy of the HTML definition
-        $definition = $config->getHTMLDefinition();
-
-        // insert implicit "parent" node, will be removed at end.
-        // DEFINITION CALL
-        $parent_name = $definition->info_parent;
-        array_unshift($tokens, new HTMLPurifier_Token_Start($parent_name));
-        $tokens[] = new HTMLPurifier_Token_End($parent_name);
-
-        // setup the context variable 'IsInline', for chameleon processing
-        // is 'false' when we are not inline, 'true' when it must always
-        // be inline, and an integer when it is inline for a certain
-        // branch of the document tree
-        $is_inline = $definition->info_parent_def->descendants_are_inline;
-        $context->register('IsInline', $is_inline);
-
-        // setup error collector
-        $e =& $context->get('ErrorCollector', true);
-
-        //####################################################################//
-        // Loop initialization
-
-        // stack that contains the indexes of all parents,
-        // $stack[count($stack)-1] being the current parent
-        $stack = array();
-
-        // stack that contains all elements that are excluded
-        // it is organized by parent elements, similar to $stack,
-        // but it is only populated when an element with exclusions is
-        // processed, i.e. there won't be empty exclusions.
-        $exclude_stack = array();
-
-        // variable that contains the start token while we are processing
-        // nodes. This enables error reporting to do its job
-        $start_token = false;
-        $context->register('CurrentToken', $start_token);
-
-        //####################################################################//
-        // Loop
-
-        // iterate through all start nodes. Determining the start node
-        // is complicated so it has been omitted from the loop construct
-        for ($i = 0, $size = count($tokens) ; $i < $size; ) {
-
-            //################################################################//
-            // Gather information on children
-
-            // child token accumulator
-            $child_tokens = array();
-
-            // scroll to the end of this node, report number, and collect
-            // all children
-            for ($j = $i, $depth = 0; ; $j++) {
-                if ($tokens[$j] instanceof HTMLPurifier_Token_Start) {
-                    $depth++;
-                    // skip token assignment on first iteration, this is the
-                    // token we currently are on
-                    if ($depth == 1) continue;
-                } elseif ($tokens[$j] instanceof HTMLPurifier_Token_End) {
-                    $depth--;
-                    // skip token assignment on last iteration, this is the
-                    // end token of the token we're currently on
-                    if ($depth == 0) break;
-                }
-                $child_tokens[] = $tokens[$j];
-            }
-
-            // $i is index of start token
-            // $j is index of end token
-
-            $start_token = $tokens[$i]; // to make token available via CurrentToken
-
-            //################################################################//
-            // Gather information on parent
-
-            // calculate parent information
-            if ($count = count($stack)) {
-                $parent_index = $stack[$count-1];
-                $parent_name  = $tokens[$parent_index]->name;
-                if ($parent_index == 0) {
-                    $parent_def   = $definition->info_parent_def;
-                } else {
-                    $parent_def   = $definition->info[$parent_name];
-                }
-            } else {
-                // processing as if the parent were the "root" node
-                // unknown info, it won't be used anyway, in the future,
-                // we may want to enforce one element only (this is
-                // necessary for HTML Purifier to clean entire documents
-                $parent_index = $parent_name = $parent_def = null;
-            }
-
-            // calculate context
-            if ($is_inline === false) {
-                // check if conditions make it inline
-                if (!empty($parent_def) && $parent_def->descendants_are_inline) {
-                    $is_inline = $count - 1;
-                }
-            } else {
-                // check if we're out of inline
-                if ($count === $is_inline) {
-                    $is_inline = false;
-                }
-            }
-
-            //################################################################//
-            // Determine whether element is explicitly excluded SGML-style
-
-            // determine whether or not element is excluded by checking all
-            // parent exclusions. The array should not be very large, two
-            // elements at most.
-            $excluded = false;
-            if (!empty($exclude_stack)) {
-                foreach ($exclude_stack as $lookup) {
-                    if (isset($lookup[$tokens[$i]->name])) {
-                        $excluded = true;
-                        // no need to continue processing
-                        break;
-                    }
-                }
-            }
-
-            //################################################################//
-            // Perform child validation
-
-            if ($excluded) {
-                // there is an exclusion, remove the entire node
-                $result = false;
-                $excludes = array(); // not used, but good to initialize anyway
-            } else {
-                // DEFINITION CALL
-                if ($i === 0) {
-                    // special processing for the first node
-                    $def = $definition->info_parent_def;
-                } else {
-                    $def = $definition->info[$tokens[$i]->name];
-
-                }
-
-                if (!empty($def->child)) {
-                    // have DTD child def validate children
-                    $result = $def->child->validateChildren(
-                        $child_tokens, $config, $context);
-                } else {
-                    // weird, no child definition, get rid of everything
-                    $result = false;
-                }
-
-                // determine whether or not this element has any exclusions
-                $excludes = $def->excludes;
-            }
-
-            // $result is now a bool or array
-
-            //################################################################//
-            // Process result by interpreting $result
-
-            if ($result === true || $child_tokens === $result) {
-                // leave the node as is
-
-                // register start token as a parental node start
-                $stack[] = $i;
-
-                // register exclusions if there are any
-                if (!empty($excludes)) $exclude_stack[] = $excludes;
-
-                // move cursor to next possible start node
-                $i++;
-
-            } elseif($result === false) {
-                // remove entire node
-
-                if ($e) {
-                    if ($excluded) {
-                        $e->send(E_ERROR, 'Strategy_FixNesting: Node excluded');
-                    } else {
-                        $e->send(E_ERROR, 'Strategy_FixNesting: Node removed');
-                    }
-                }
-
-                // calculate length of inner tokens and current tokens
-                $length = $j - $i + 1;
-
-                // perform removal
-                array_splice($tokens, $i, $length);
-
-                // update size
-                $size -= $length;
-
-                // there is no start token to register,
-                // current node is now the next possible start node
-                // unless it turns out that we need to do a double-check
-
-                // this is a rought heuristic that covers 100% of HTML's
-                // cases and 99% of all other cases. A child definition
-                // that would be tricked by this would be something like:
-                // ( | a b c) where it's all or nothing. Fortunately,
-                // our current implementation claims that that case would
-                // not allow empty, even if it did
-                if (!$parent_def->child->allow_empty) {
-                    // we need to do a double-check
-                    $i = $parent_index;
-                    array_pop($stack);
-                }
-
-                // PROJECTED OPTIMIZATION: Process all children elements before
-                // reprocessing parent node.
-
-            } else {
-                // replace node with $result
-
-                // calculate length of inner tokens
-                $length = $j - $i - 1;
-
-                if ($e) {
-                    if (empty($result) && $length) {
-                        $e->send(E_ERROR, 'Strategy_FixNesting: Node contents removed');
-                    } else {
-                        $e->send(E_WARNING, 'Strategy_FixNesting: Node reorganized');
-                    }
-                }
-
-                // perform replacement
-                array_splice($tokens, $i + 1, $length, $result);
-
-                // update size
-                $size -= $length;
-                $size += count($result);
-
-                // register start token as a parental node start
-                $stack[] = $i;
-
-                // register exclusions if there are any
-                if (!empty($excludes)) $exclude_stack[] = $excludes;
-
-                // move cursor to next possible start node
-                $i++;
-
-            }
-
-            //################################################################//
-            // Scroll to next start node
-
-            // We assume, at this point, that $i is the index of the token
-            // that is the first possible new start point for a node.
-
-            // Test if the token indeed is a start tag, if not, move forward
-            // and test again.
-            $size = count($tokens);
-            while ($i < $size and !$tokens[$i] instanceof HTMLPurifier_Token_Start) {
-                if ($tokens[$i] instanceof HTMLPurifier_Token_End) {
-                    // pop a token index off the stack if we ended a node
-                    array_pop($stack);
-                    // pop an exclusion lookup off exclusion stack if
-                    // we ended node and that node had exclusions
-                    if ($i == 0 || $i == $size - 1) {
-                        // use specialized var if it's the super-parent
-                        $s_excludes = $definition->info_parent_def->excludes;
-                    } else {
-                        $s_excludes = $definition->info[$tokens[$i]->name]->excludes;
-                    }
-                    if ($s_excludes) {
-                        array_pop($exclude_stack);
-                    }
-                }
-                $i++;
-            }
-
-        }
-
-        //####################################################################//
-        // Post-processing
-
-        // remove implicit parent tokens at the beginning and end
-        array_shift($tokens);
-        array_pop($tokens);
-
-        // remove context variables
-        $context->destroy('IsInline');
-        $context->destroy('CurrentToken');
-
-        //####################################################################//
-        // Return
-
-        return $tokens;
-
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Token.php b/library/HTMLPurifier/Token.php
deleted file mode 100644
index 7900e6cb10..0000000000
--- a/library/HTMLPurifier/Token.php
+++ /dev/null
@@ -1,57 +0,0 @@
-<?php
-
-/**
- * Abstract base token class that all others inherit from.
- */
-class HTMLPurifier_Token {
-    public $line; /**< Line number node was on in source document. Null if unknown. */
-    public $col;  /**< Column of line node was on in source document. Null if unknown. */
-
-    /**
-     * Lookup array of processing that this token is exempt from.
-     * Currently, valid values are "ValidateAttributes" and
-     * "MakeWellFormed_TagClosedError"
-     */
-    public $armor = array();
-
-    /**
-     * Used during MakeWellFormed.
-     */
-    public $skip;
-    public $rewind;
-    public $carryover;
-
-    public function __get($n) {
-      if ($n === 'type') {
-        trigger_error('Deprecated type property called; use instanceof', E_USER_NOTICE);
-        switch (get_class($this)) {
-          case 'HTMLPurifier_Token_Start':      return 'start';
-          case 'HTMLPurifier_Token_Empty':      return 'empty';
-          case 'HTMLPurifier_Token_End':        return 'end';
-          case 'HTMLPurifier_Token_Text':       return 'text';
-          case 'HTMLPurifier_Token_Comment':    return 'comment';
-          default: return null;
-        }
-      }
-    }
-
-    /**
-     * Sets the position of the token in the source document.
-     */
-    public function position($l = null, $c = null) {
-        $this->line = $l;
-        $this->col  = $c;
-    }
-
-    /**
-     * Convenience function for DirectLex settings line/col position.
-     */
-    public function rawPosition($l, $c) {
-        if ($c === -1) $l++;
-        $this->line = $l;
-        $this->col  = $c;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Token/Comment.php b/library/HTMLPurifier/Token/Comment.php
deleted file mode 100644
index dc6bdcabb8..0000000000
--- a/library/HTMLPurifier/Token/Comment.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-/**
- * Concrete comment token class. Generally will be ignored.
- */
-class HTMLPurifier_Token_Comment extends HTMLPurifier_Token
-{
-    public $data; /**< Character data within comment. */
-    public $is_whitespace = true;
-    /**
-     * Transparent constructor.
-     *
-     * @param $data String comment data.
-     */
-    public function __construct($data, $line = null, $col = null) {
-        $this->data = $data;
-        $this->line = $line;
-        $this->col  = $col;
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/TokenFactory.php b/library/HTMLPurifier/TokenFactory.php
deleted file mode 100644
index 7cf48fb41c..0000000000
--- a/library/HTMLPurifier/TokenFactory.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-
-/**
- * Factory for token generation.
- *
- * @note Doing some benchmarking indicates that the new operator is much
- *       slower than the clone operator (even discounting the cost of the
- *       constructor).  This class is for that optimization.
- *       Other then that, there's not much point as we don't
- *       maintain parallel HTMLPurifier_Token hierarchies (the main reason why
- *       you'd want to use an abstract factory).
- * @todo Port DirectLex to use this
- */
-class HTMLPurifier_TokenFactory
-{
-
-    /**
-     * Prototypes that will be cloned.
-     * @private
-     */
-    // p stands for prototype
-    private $p_start, $p_end, $p_empty, $p_text, $p_comment;
-
-    /**
-     * Generates blank prototypes for cloning.
-     */
-    public function __construct() {
-        $this->p_start  = new HTMLPurifier_Token_Start('', array());
-        $this->p_end    = new HTMLPurifier_Token_End('');
-        $this->p_empty  = new HTMLPurifier_Token_Empty('', array());
-        $this->p_text   = new HTMLPurifier_Token_Text('');
-        $this->p_comment= new HTMLPurifier_Token_Comment('');
-    }
-
-    /**
-     * Creates a HTMLPurifier_Token_Start.
-     * @param $name Tag name
-     * @param $attr Associative array of attributes
-     * @return Generated HTMLPurifier_Token_Start
-     */
-    public function createStart($name, $attr = array()) {
-        $p = clone $this->p_start;
-        $p->__construct($name, $attr);
-        return $p;
-    }
-
-    /**
-     * Creates a HTMLPurifier_Token_End.
-     * @param $name Tag name
-     * @return Generated HTMLPurifier_Token_End
-     */
-    public function createEnd($name) {
-        $p = clone $this->p_end;
-        $p->__construct($name);
-        return $p;
-    }
-
-    /**
-     * Creates a HTMLPurifier_Token_Empty.
-     * @param $name Tag name
-     * @param $attr Associative array of attributes
-     * @return Generated HTMLPurifier_Token_Empty
-     */
-    public function createEmpty($name, $attr = array()) {
-        $p = clone $this->p_empty;
-        $p->__construct($name, $attr);
-        return $p;
-    }
-
-    /**
-     * Creates a HTMLPurifier_Token_Text.
-     * @param $data Data of text token
-     * @return Generated HTMLPurifier_Token_Text
-     */
-    public function createText($data) {
-        $p = clone $this->p_text;
-        $p->__construct($data);
-        return $p;
-    }
-
-    /**
-     * Creates a HTMLPurifier_Token_Comment.
-     * @param $data Data of comment token
-     * @return Generated HTMLPurifier_Token_Comment
-     */
-    public function createComment($data) {
-        $p = clone $this->p_comment;
-        $p->__construct($data);
-        return $p;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URI.php b/library/HTMLPurifier/URI.php
deleted file mode 100644
index 8b50d0d18d..0000000000
--- a/library/HTMLPurifier/URI.php
+++ /dev/null
@@ -1,173 +0,0 @@
-<?php
-
-/**
- * HTML Purifier's internal representation of a URI.
- * @note
- *      Internal data-structures are completely escaped. If the data needs
- *      to be used in a non-URI context (which is very unlikely), be sure
- *      to decode it first. The URI may not necessarily be well-formed until
- *      validate() is called.
- */
-class HTMLPurifier_URI
-{
-
-    public $scheme, $userinfo, $host, $port, $path, $query, $fragment;
-
-    /**
-     * @note Automatically normalizes scheme and port
-     */
-    public function __construct($scheme, $userinfo, $host, $port, $path, $query, $fragment) {
-        $this->scheme = is_null($scheme) || ctype_lower($scheme) ? $scheme : strtolower($scheme);
-        $this->userinfo = $userinfo;
-        $this->host = $host;
-        $this->port = is_null($port) ? $port : (int) $port;
-        $this->path = $path;
-        $this->query = $query;
-        $this->fragment = $fragment;
-    }
-
-    /**
-     * Retrieves a scheme object corresponding to the URI's scheme/default
-     * @param $config Instance of HTMLPurifier_Config
-     * @param $context Instance of HTMLPurifier_Context
-     * @return Scheme object appropriate for validating this URI
-     */
-    public function getSchemeObj($config, $context) {
-        $registry = HTMLPurifier_URISchemeRegistry::instance();
-        if ($this->scheme !== null) {
-            $scheme_obj = $registry->getScheme($this->scheme, $config, $context);
-            if (!$scheme_obj) return false; // invalid scheme, clean it out
-        } else {
-            // no scheme: retrieve the default one
-            $def = $config->getDefinition('URI');
-            $scheme_obj = $registry->getScheme($def->defaultScheme, $config, $context);
-            if (!$scheme_obj) {
-                // something funky happened to the default scheme object
-                trigger_error(
-                    'Default scheme object "' . $def->defaultScheme . '" was not readable',
-                    E_USER_WARNING
-                );
-                return false;
-            }
-        }
-        return $scheme_obj;
-    }
-
-    /**
-     * Generic validation method applicable for all schemes. May modify
-     * this URI in order to get it into a compliant form.
-     * @param $config Instance of HTMLPurifier_Config
-     * @param $context Instance of HTMLPurifier_Context
-     * @return True if validation/filtering succeeds, false if failure
-     */
-    public function validate($config, $context) {
-
-        // ABNF definitions from RFC 3986
-        $chars_sub_delims = '!$&\'()*+,;=';
-        $chars_gen_delims = ':/?#[]@';
-        $chars_pchar = $chars_sub_delims . ':@';
-
-        // validate scheme (MUST BE FIRST!)
-        if (!is_null($this->scheme) && is_null($this->host)) {
-            $def = $config->getDefinition('URI');
-            if ($def->defaultScheme === $this->scheme) {
-                $this->scheme = null;
-            }
-        }
-
-        // validate host
-        if (!is_null($this->host)) {
-            $host_def = new HTMLPurifier_AttrDef_URI_Host();
-            $this->host = $host_def->validate($this->host, $config, $context);
-            if ($this->host === false) $this->host = null;
-        }
-
-        // validate username
-        if (!is_null($this->userinfo)) {
-            $encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . ':');
-            $this->userinfo = $encoder->encode($this->userinfo);
-        }
-
-        // validate port
-        if (!is_null($this->port)) {
-            if ($this->port < 1 || $this->port > 65535) $this->port = null;
-        }
-
-        // validate path
-        $path_parts = array();
-        $segments_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/');
-        if (!is_null($this->host)) {
-            // path-abempty (hier and relative)
-            $this->path = $segments_encoder->encode($this->path);
-        } elseif ($this->path !== '' && $this->path[0] === '/') {
-            // path-absolute (hier and relative)
-            if (strlen($this->path) >= 2 && $this->path[1] === '/') {
-                // This shouldn't ever happen!
-                $this->path = '';
-            } else {
-                $this->path = $segments_encoder->encode($this->path);
-            }
-        } elseif (!is_null($this->scheme) && $this->path !== '') {
-            // path-rootless (hier)
-            // Short circuit evaluation means we don't need to check nz
-            $this->path = $segments_encoder->encode($this->path);
-        } elseif (is_null($this->scheme) && $this->path !== '') {
-            // path-noscheme (relative)
-            // (once again, not checking nz)
-            $segment_nc_encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . '@');
-            $c = strpos($this->path, '/');
-            if ($c !== false) {
-                $this->path =
-                    $segment_nc_encoder->encode(substr($this->path, 0, $c)) .
-                    $segments_encoder->encode(substr($this->path, $c));
-            } else {
-                $this->path = $segment_nc_encoder->encode($this->path);
-            }
-        } else {
-            // path-empty (hier and relative)
-            $this->path = ''; // just to be safe
-        }
-
-        // qf = query and fragment
-        $qf_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/?');
-
-        if (!is_null($this->query)) {
-            $this->query = $qf_encoder->encode($this->query);
-        }
-
-        if (!is_null($this->fragment)) {
-            $this->fragment = $qf_encoder->encode($this->fragment);
-        }
-
-        return true;
-
-    }
-
-    /**
-     * Convert URI back to string
-     * @return String URI appropriate for output
-     */
-    public function toString() {
-        // reconstruct authority
-        $authority = null;
-        if (!is_null($this->host)) {
-            $authority = '';
-            if(!is_null($this->userinfo)) $authority .= $this->userinfo . '@';
-            $authority .= $this->host;
-            if(!is_null($this->port))     $authority .= ':' . $this->port;
-        }
-
-        // reconstruct the result
-        $result = '';
-        if (!is_null($this->scheme))    $result .= $this->scheme . ':';
-        if (!is_null($authority))       $result .=  '//' . $authority;
-        $result .= $this->path;
-        if (!is_null($this->query))     $result .= '?' . $this->query;
-        if (!is_null($this->fragment))  $result .= '#' . $this->fragment;
-
-        return $result;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIFilter.php b/library/HTMLPurifier/URIFilter.php
deleted file mode 100644
index c116f93dff..0000000000
--- a/library/HTMLPurifier/URIFilter.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-/**
- * Chainable filters for custom URI processing.
- *
- * These filters can perform custom actions on a URI filter object,
- * including transformation or blacklisting.
- *
- * @warning This filter is called before scheme object validation occurs.
- *          Make sure, if you require a specific scheme object, you
- *          you check that it exists. This allows filters to convert
- *          proprietary URI schemes into regular ones.
- */
-abstract class HTMLPurifier_URIFilter
-{
-
-    /**
-     * Unique identifier of filter
-     */
-    public $name;
-
-    /**
-     * True if this filter should be run after scheme validation.
-     */
-    public $post = false;
-
-    /**
-     * Performs initialization for the filter
-     */
-    public function prepare($config) {return true;}
-
-    /**
-     * Filter a URI object
-     * @param $uri Reference to URI object variable
-     * @param $config Instance of HTMLPurifier_Config
-     * @param $context Instance of HTMLPurifier_Context
-     * @return bool Whether or not to continue processing: false indicates
-     *         URL is no good, true indicates continue processing. Note that
-     *         all changes are committed directly on the URI object
-     */
-    abstract public function filter(&$uri, $config, $context);
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIFilter/DisableExternal.php b/library/HTMLPurifier/URIFilter/DisableExternal.php
deleted file mode 100644
index d8a39a5011..0000000000
--- a/library/HTMLPurifier/URIFilter/DisableExternal.php
+++ /dev/null
@@ -1,23 +0,0 @@
-<?php
-
-class HTMLPurifier_URIFilter_DisableExternal extends HTMLPurifier_URIFilter
-{
-    public $name = 'DisableExternal';
-    protected $ourHostParts = false;
-    public function prepare($config) {
-        $our_host = $config->getDefinition('URI')->host;
-        if ($our_host !== null) $this->ourHostParts = array_reverse(explode('.', $our_host));
-    }
-    public function filter(&$uri, $config, $context) {
-        if (is_null($uri->host)) return true;
-        if ($this->ourHostParts === false) return false;
-        $host_parts = array_reverse(explode('.', $uri->host));
-        foreach ($this->ourHostParts as $i => $x) {
-            if (!isset($host_parts[$i])) return false;
-            if ($host_parts[$i] != $this->ourHostParts[$i]) return false;
-        }
-        return true;
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIFilter/DisableExternalResources.php b/library/HTMLPurifier/URIFilter/DisableExternalResources.php
deleted file mode 100644
index 881abc43cf..0000000000
--- a/library/HTMLPurifier/URIFilter/DisableExternalResources.php
+++ /dev/null
@@ -1,12 +0,0 @@
-<?php
-
-class HTMLPurifier_URIFilter_DisableExternalResources extends HTMLPurifier_URIFilter_DisableExternal
-{
-    public $name = 'DisableExternalResources';
-    public function filter(&$uri, $config, $context) {
-        if (!$context->get('EmbeddedURI', true)) return true;
-        return parent::filter($uri, $config, $context);
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIFilter/HostBlacklist.php b/library/HTMLPurifier/URIFilter/HostBlacklist.php
deleted file mode 100644
index 045aa0992c..0000000000
--- a/library/HTMLPurifier/URIFilter/HostBlacklist.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-class HTMLPurifier_URIFilter_HostBlacklist extends HTMLPurifier_URIFilter
-{
-    public $name = 'HostBlacklist';
-    protected $blacklist = array();
-    public function prepare($config) {
-        $this->blacklist = $config->get('URI.HostBlacklist');
-        return true;
-    }
-    public function filter(&$uri, $config, $context) {
-        foreach($this->blacklist as $blacklisted_host_fragment) {
-            if (strpos($uri->host, $blacklisted_host_fragment) !== false) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIFilter/Munge.php b/library/HTMLPurifier/URIFilter/Munge.php
deleted file mode 100644
index efa10a6458..0000000000
--- a/library/HTMLPurifier/URIFilter/Munge.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-class HTMLPurifier_URIFilter_Munge extends HTMLPurifier_URIFilter
-{
-    public $name = 'Munge';
-    public $post = true;
-    private $target, $parser, $doEmbed, $secretKey;
-
-    protected $replace = array();
-
-    public function prepare($config) {
-        $this->target    = $config->get('URI.' . $this->name);
-        $this->parser    = new HTMLPurifier_URIParser();
-        $this->doEmbed   = $config->get('URI.MungeResources');
-        $this->secretKey = $config->get('URI.MungeSecretKey');
-        return true;
-    }
-    public function filter(&$uri, $config, $context) {
-        if ($context->get('EmbeddedURI', true) && !$this->doEmbed) return true;
-
-        $scheme_obj = $uri->getSchemeObj($config, $context);
-        if (!$scheme_obj) return true; // ignore unknown schemes, maybe another postfilter did it
-        if (is_null($uri->host) || empty($scheme_obj->browsable)) {
-            return true;
-        }
-        // don't redirect if target host is our host
-        if ($uri->host === $config->getDefinition('URI')->host) {
-            return true;
-        }
-
-        $this->makeReplace($uri, $config, $context);
-        $this->replace = array_map('rawurlencode', $this->replace);
-
-        $new_uri = strtr($this->target, $this->replace);
-        $new_uri = $this->parser->parse($new_uri);
-        // don't redirect if the target host is the same as the
-        // starting host
-        if ($uri->host === $new_uri->host) return true;
-        $uri = $new_uri; // overwrite
-        return true;
-    }
-
-    protected function makeReplace($uri, $config, $context) {
-        $string = $uri->toString();
-        // always available
-        $this->replace['%s'] = $string;
-        $this->replace['%r'] = $context->get('EmbeddedURI', true);
-        $token = $context->get('CurrentToken', true);
-        $this->replace['%n'] = $token ? $token->name : null;
-        $this->replace['%m'] = $context->get('CurrentAttr', true);
-        $this->replace['%p'] = $context->get('CurrentCSSProperty', true);
-        // not always available
-        if ($this->secretKey) $this->replace['%t'] = sha1($this->secretKey . ':' . $string);
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIScheme.php b/library/HTMLPurifier/URIScheme.php
deleted file mode 100644
index 039710fd15..0000000000
--- a/library/HTMLPurifier/URIScheme.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-
-/**
- * Validator for the components of a URI for a specific scheme
- */
-class HTMLPurifier_URIScheme
-{
-
-    /**
-     * Scheme's default port (integer)
-     */
-    public $default_port = null;
-
-    /**
-     * Whether or not URIs of this schem are locatable by a browser
-     * http and ftp are accessible, while mailto and news are not.
-     */
-    public $browsable = false;
-
-    /**
-     * Whether or not the URI always uses <hier_part>, resolves edge cases
-     * with making relative URIs absolute
-     */
-    public $hierarchical = false;
-
-    /**
-     * Validates the components of a URI
-     * @note This implementation should be called by children if they define
-     *       a default port, as it does port processing.
-     * @param $uri Instance of HTMLPurifier_URI
-     * @param $config HTMLPurifier_Config object
-     * @param $context HTMLPurifier_Context object
-     * @return Bool success or failure
-     */
-    public function validate(&$uri, $config, $context) {
-        if ($this->default_port == $uri->port) $uri->port = null;
-        return true;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIScheme/news.php b/library/HTMLPurifier/URIScheme/news.php
deleted file mode 100644
index f5f54f4f56..0000000000
--- a/library/HTMLPurifier/URIScheme/news.php
+++ /dev/null
@@ -1,22 +0,0 @@
-<?php
-
-/**
- * Validates news (Usenet) as defined by generic RFC 1738
- */
-class HTMLPurifier_URIScheme_news extends HTMLPurifier_URIScheme {
-
-    public $browsable = false;
-
-    public function validate(&$uri, $config, $context) {
-        parent::validate($uri, $config, $context);
-        $uri->userinfo = null;
-        $uri->host     = null;
-        $uri->port     = null;
-        $uri->query    = null;
-        // typecode check needed on path
-        return true;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIScheme/nntp.php b/library/HTMLPurifier/URIScheme/nntp.php
deleted file mode 100644
index 5bf93ea784..0000000000
--- a/library/HTMLPurifier/URIScheme/nntp.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php
-
-/**
- * Validates nntp (Network News Transfer Protocol) as defined by generic RFC 1738
- */
-class HTMLPurifier_URIScheme_nntp extends HTMLPurifier_URIScheme {
-
-    public $default_port = 119;
-    public $browsable = false;
-
-    public function validate(&$uri, $config, $context) {
-        parent::validate($uri, $config, $context);
-        $uri->userinfo = null;
-        $uri->query    = null;
-        return true;
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/VarParser.php b/library/HTMLPurifier/VarParser.php
deleted file mode 100644
index 68e72ae869..0000000000
--- a/library/HTMLPurifier/VarParser.php
+++ /dev/null
@@ -1,154 +0,0 @@
-<?php
-
-/**
- * Parses string representations into their corresponding native PHP
- * variable type. The base implementation does a simple type-check.
- */
-class HTMLPurifier_VarParser
-{
-
-    const STRING    = 1;
-    const ISTRING   = 2;
-    const TEXT      = 3;
-    const ITEXT     = 4;
-    const INT       = 5;
-    const FLOAT     = 6;
-    const BOOL      = 7;
-    const LOOKUP    = 8;
-    const ALIST     = 9;
-    const HASH      = 10;
-    const MIXED     = 11;
-
-    /**
-     * Lookup table of allowed types. Mainly for backwards compatibility, but
-     * also convenient for transforming string type names to the integer constants.
-     */
-    static public $types = array(
-        'string'    => self::STRING,
-        'istring'   => self::ISTRING,
-        'text'      => self::TEXT,
-        'itext'     => self::ITEXT,
-        'int'       => self::INT,
-        'float'     => self::FLOAT,
-        'bool'      => self::BOOL,
-        'lookup'    => self::LOOKUP,
-        'list'      => self::ALIST,
-        'hash'      => self::HASH,
-        'mixed'     => self::MIXED
-    );
-
-    /**
-     * Lookup table of types that are string, and can have aliases or
-     * allowed value lists.
-     */
-    static public $stringTypes = array(
-        self::STRING    => true,
-        self::ISTRING   => true,
-        self::TEXT      => true,
-        self::ITEXT     => true,
-    );
-
-    /**
-     * Validate a variable according to type. Throws
-     * HTMLPurifier_VarParserException if invalid.
-     * It may return NULL as a valid type if $allow_null is true.
-     *
-     * @param $var Variable to validate
-     * @param $type Type of variable, see HTMLPurifier_VarParser->types
-     * @param $allow_null Whether or not to permit null as a value
-     * @return Validated and type-coerced variable
-     */
-    final public function parse($var, $type, $allow_null = false) {
-        if (is_string($type)) {
-            if (!isset(HTMLPurifier_VarParser::$types[$type])) {
-                throw new HTMLPurifier_VarParserException("Invalid type '$type'");
-            } else {
-                $type = HTMLPurifier_VarParser::$types[$type];
-            }
-        }
-        $var = $this->parseImplementation($var, $type, $allow_null);
-        if ($allow_null && $var === null) return null;
-        // These are basic checks, to make sure nothing horribly wrong
-        // happened in our implementations.
-        switch ($type) {
-            case (self::STRING):
-            case (self::ISTRING):
-            case (self::TEXT):
-            case (self::ITEXT):
-                if (!is_string($var)) break;
-                if ($type == self::ISTRING || $type == self::ITEXT) $var = strtolower($var);
-                return $var;
-            case (self::INT):
-                if (!is_int($var)) break;
-                return $var;
-            case (self::FLOAT):
-                if (!is_float($var)) break;
-                return $var;
-            case (self::BOOL):
-                if (!is_bool($var)) break;
-                return $var;
-            case (self::LOOKUP):
-            case (self::ALIST):
-            case (self::HASH):
-                if (!is_array($var)) break;
-                if ($type === self::LOOKUP) {
-                    foreach ($var as $k) if ($k !== true) $this->error('Lookup table contains value other than true');
-                } elseif ($type === self::ALIST) {
-                    $keys = array_keys($var);
-                    if (array_keys($keys) !== $keys) $this->error('Indices for list are not uniform');
-                }
-                return $var;
-            case (self::MIXED):
-                return $var;
-            default:
-                $this->errorInconsistent(get_class($this), $type);
-        }
-        $this->errorGeneric($var, $type);
-    }
-
-    /**
-     * Actually implements the parsing. Base implementation is to not
-     * do anything to $var. Subclasses should overload this!
-     */
-    protected function parseImplementation($var, $type, $allow_null) {
-        return $var;
-    }
-
-    /**
-     * Throws an exception.
-     */
-    protected function error($msg) {
-        throw new HTMLPurifier_VarParserException($msg);
-    }
-
-    /**
-     * Throws an inconsistency exception.
-     * @note This should not ever be called. It would be called if we
-     *       extend the allowed values of HTMLPurifier_VarParser without
-     *       updating subclasses.
-     */
-    protected function errorInconsistent($class, $type) {
-        throw new HTMLPurifier_Exception("Inconsistency in $class: ".HTMLPurifier_VarParser::getTypeName($type)." not implemented");
-    }
-
-    /**
-     * Generic error for if a type didn't work.
-     */
-    protected function errorGeneric($var, $type) {
-        $vtype = gettype($var);
-        $this->error("Expected type ".HTMLPurifier_VarParser::getTypeName($type).", got $vtype");
-    }
-
-    static public function getTypeName($type) {
-        static $lookup;
-        if (!$lookup) {
-            // Lazy load the alternative lookup table
-            $lookup = array_flip(HTMLPurifier_VarParser::$types);
-        }
-        if (!isset($lookup[$type])) return 'unknown';
-        return $lookup[$type];
-    }
-
-}
-
-// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/CREDITS b/library/ezyang/htmlpurifier/CREDITS
new file mode 100644
index 0000000000..7921b45af7
--- /dev/null
+++ b/library/ezyang/htmlpurifier/CREDITS
@@ -0,0 +1,9 @@
+
+CREDITS
+
+Almost everything written by Edward Z. Yang (Ambush Commander).  Lots of thanks
+to the DevNetwork Community for their help (see docs/ref-devnetwork.html for
+more details), Feyd especially (namely IPv6 and optimization).  Thanks to RSnake
+for letting me package his fantastic XSS cheatsheet for a smoketest.
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/INSTALL b/library/ezyang/htmlpurifier/INSTALL
new file mode 100644
index 0000000000..677c04aa04
--- /dev/null
+++ b/library/ezyang/htmlpurifier/INSTALL
@@ -0,0 +1,374 @@
+
+Install
+    How to install HTML Purifier
+
+HTML Purifier is designed to run out of the box, so actually using the
+library is extremely easy.  (Although... if you were looking for a
+step-by-step installation GUI, you've downloaded the wrong software!)
+
+While the impatient can get going immediately with some of the sample
+code at the bottom of this library, it's well worth reading this entire
+document--most of the other documentation assumes that you are familiar
+with these contents.
+
+
+---------------------------------------------------------------------------
+1.  Compatibility
+
+HTML Purifier is PHP 5 only, and is actively tested from PHP 5.0.5 and
+up. It has no core dependencies with other libraries. PHP
+4 support was deprecated on December 31, 2007 with HTML Purifier 3.0.0.
+HTML Purifier is not compatible with zend.ze1_compatibility_mode.
+
+These optional extensions can enhance the capabilities of HTML Purifier:
+
+    * iconv  : Converts text to and from non-UTF-8 encodings
+    * bcmath : Used for unit conversion and imagecrash protection
+    * tidy   : Used for pretty-printing HTML
+
+These optional libraries can enhance the capabilities of HTML Purifier:
+
+    * CSSTidy : Clean CSS stylesheets using %Core.ExtractStyleBlocks
+    * Net_IDNA2 (PEAR) : IRI support using %Core.EnableIDNA
+
+---------------------------------------------------------------------------
+2.  Reconnaissance
+
+A big plus of HTML Purifier is its inerrant support of standards, so
+your web-pages should be standards-compliant.  (They should also use
+semantic markup, but that's another issue altogether, one HTML Purifier
+cannot fix without reading your mind.)
+
+HTML Purifier can process these doctypes:
+
+* XHTML 1.0 Transitional (default)
+* XHTML 1.0 Strict
+* HTML 4.01 Transitional
+* HTML 4.01 Strict
+* XHTML 1.1
+
+...and these character encodings:
+
+* UTF-8 (default)
+* Any encoding iconv supports (with crippled internationalization support)
+
+These defaults reflect what my choices would be if I were authoring an
+HTML document, however, what you choose depends on the nature of your
+codebase.  If you don't know what doctype you are using, you can determine
+the doctype from this identifier at the top of your source code:
+
+    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+...and the character encoding from this code:
+
+    <meta http-equiv="Content-type" content="text/html;charset=ENCODING">
+
+If the character encoding declaration is missing, STOP NOW, and
+read 'docs/enduser-utf8.html' (web accessible at
+http://htmlpurifier.org/docs/enduser-utf8.html).  In fact, even if it is
+present, read this document anyway, as many websites specify their
+document's character encoding incorrectly.
+
+
+---------------------------------------------------------------------------
+3.  Including the library
+
+The procedure is quite simple:
+
+    require_once '/path/to/library/HTMLPurifier.auto.php';
+
+This will setup an autoloader, so the library's files are only included
+when you use them.
+
+Only the contents in the library/ folder are necessary, so you can remove
+everything else when using HTML Purifier in a production environment.
+
+If you installed HTML Purifier via PEAR, all you need to do is:
+
+    require_once 'HTMLPurifier.auto.php';
+
+Please note that the usual PEAR practice of including just the classes you
+want will not work with HTML Purifier's autoloading scheme.
+
+Advanced users, read on; other users can skip to section 4.
+
+Autoload compatibility
+----------------------
+
+    HTML Purifier attempts to be as smart as possible when registering an
+    autoloader, but there are some cases where you will need to change
+    your own code to accomodate HTML Purifier. These are those cases:
+
+    PHP VERSION IS LESS THAN 5.1.2, AND YOU'VE DEFINED __autoload
+        Because spl_autoload_register() doesn't exist in early versions
+        of PHP 5, HTML Purifier has no way of adding itself to the autoload
+        stack. Modify your __autoload function to test
+        HTMLPurifier_Bootstrap::autoload($class)
+
+        For example, suppose your autoload function looks like this:
+
+            function __autoload($class) {
+                require str_replace('_', '/', $class) . '.php';
+                return true;
+            }
+
+        A modified version with HTML Purifier would look like this:
+
+            function __autoload($class) {
+                if (HTMLPurifier_Bootstrap::autoload($class)) return true;
+                require str_replace('_', '/', $class) . '.php';
+                return true;
+            }
+
+        Note that there *is* some custom behavior in our autoloader; the
+        original autoloader in our example would work for 99% of the time,
+        but would fail when including language files.
+
+    AN __autoload FUNCTION IS DECLARED AFTER OUR AUTOLOADER IS REGISTERED
+        spl_autoload_register() has the curious behavior of disabling
+        the existing __autoload() handler. Users need to explicitly
+        spl_autoload_register('__autoload'). Because we use SPL when it
+        is available, __autoload() will ALWAYS be disabled. If __autoload()
+        is declared before HTML Purifier is loaded, this is not a problem:
+        HTML Purifier will register the function for you. But if it is
+        declared afterwards, it will mysteriously not work. This
+        snippet of code (after your autoloader is defined) will fix it:
+
+            spl_autoload_register('__autoload')
+
+    Users should also be on guard if they use a version of PHP previous
+    to 5.1.2 without an autoloader--HTML Purifier will define __autoload()
+    for you, which can collide with an autoloader that was added by *you*
+    later.
+
+
+For better performance
+----------------------
+
+    Opcode caches, which greatly speed up PHP initialization for scripts
+    with large amounts of code (HTML Purifier included), don't like
+    autoloaders. We offer an include file that includes all of HTML Purifier's
+    files in one go in an opcode cache friendly manner:
+
+        // If /path/to/library isn't already in your include path, uncomment
+        // the below line:
+        // require '/path/to/library/HTMLPurifier.path.php';
+
+        require 'HTMLPurifier.includes.php';
+
+    Optional components still need to be included--you'll know if you try to
+    use a feature and you get a class doesn't exists error! The autoloader
+    can be used in conjunction with this approach to catch classes that are
+    missing. Simply add this afterwards:
+
+        require 'HTMLPurifier.autoload.php';
+
+Standalone version
+------------------
+
+    HTML Purifier has a standalone distribution; you can also generate
+    a standalone file from the full version by running the script
+    maintenance/generate-standalone.php . The standalone version has the
+    benefit of having most of its code in one file, so parsing is much
+    faster and the library is easier to manage.
+
+    If HTMLPurifier.standalone.php exists in the library directory, you
+    can use it like this:
+
+        require '/path/to/HTMLPurifier.standalone.php';
+
+    This is equivalent to including HTMLPurifier.includes.php, except that
+    the contents of standalone/ will be added to your path. To override this
+    behavior, specify a new HTMLPURIFIER_PREFIX where standalone files can
+    be found (usually, this will be one directory up, the "true" library
+    directory in full distributions). Don't forget to set your path too!
+
+    The autoloader can be added to the end to ensure the classes are
+    loaded when necessary; otherwise you can manually include them.
+    To use the autoloader, use this:
+
+        require 'HTMLPurifier.autoload.php';
+
+For advanced users
+------------------
+
+    HTMLPurifier.auto.php performs a number of operations that can be done
+    individually. These are:
+
+        HTMLPurifier.path.php
+            Puts /path/to/library in the include path. For high performance,
+            this should be done in php.ini.
+
+        HTMLPurifier.autoload.php
+            Registers our autoload handler HTMLPurifier_Bootstrap::autoload($class).
+
+    You can do these operations by yourself--in fact, you must modify your own
+    autoload handler if you are using a version of PHP earlier than PHP 5.1.2
+    (See "Autoload compatibility" above).
+
+
+---------------------------------------------------------------------------
+4. Configuration
+
+HTML Purifier is designed to run out-of-the-box, but occasionally HTML
+Purifier needs to be told what to do.  If you answer no to any of these
+questions, read on; otherwise, you can skip to the next section (or, if you're
+into configuring things just for the heck of it, skip to 4.3).
+
+* Am I using UTF-8?
+* Am I using XHTML 1.0 Transitional?
+
+If you answered no to any of these questions, instantiate a configuration
+object and read on:
+
+    $config = HTMLPurifier_Config::createDefault();
+
+
+4.1. Setting a different character encoding
+
+You really shouldn't use any other encoding except UTF-8, especially if you
+plan to support multilingual websites (read section three for more details).
+However, switching to UTF-8 is not always immediately feasible, so we can
+adapt.
+
+HTML Purifier uses iconv to support other character encodings, as such,
+any encoding that iconv supports <http://www.gnu.org/software/libiconv/>
+HTML Purifier supports with this code:
+
+    $config->set('Core.Encoding', /* put your encoding here */);
+
+An example usage for Latin-1 websites (the most common encoding for English
+websites):
+
+    $config->set('Core.Encoding', 'ISO-8859-1');
+
+Note that HTML Purifier's support for non-Unicode encodings is crippled by the
+fact that any character not supported by that encoding will be silently
+dropped, EVEN if it is ampersand escaped.  If you want to work around
+this, you are welcome to read docs/enduser-utf8.html for a fix,
+but please be cognizant of the issues the "solution" creates (for this
+reason, I do not include the solution in this document).
+
+
+4.2. Setting a different doctype
+
+For those of you using HTML 4.01 Transitional, you can disable
+XHTML output like this:
+
+    $config->set('HTML.Doctype', 'HTML 4.01 Transitional');
+
+Other supported doctypes include:
+
+    * HTML 4.01 Strict
+    * HTML 4.01 Transitional
+    * XHTML 1.0 Strict
+    * XHTML 1.0 Transitional
+    * XHTML 1.1
+
+
+4.3. Other settings
+
+There are more configuration directives which can be read about
+here: <http://htmlpurifier.org/live/configdoc/plain.html>  They're a bit boring,
+but they can help out for those of you who like to exert maximum control over
+your code.  Some of the more interesting ones are configurable at the
+demo <http://htmlpurifier.org/demo.php> and are well worth looking into
+for your own system.
+
+For example, you can fine tune allowed elements and attributes, convert
+relative URLs to absolute ones, and even autoparagraph input text! These
+are, respectively, %HTML.Allowed, %URI.MakeAbsolute and %URI.Base, and
+%AutoFormat.AutoParagraph. The %Namespace.Directive naming convention
+translates to:
+
+    $config->set('Namespace.Directive', $value);
+
+E.g.
+
+    $config->set('HTML.Allowed', 'p,b,a[href],i');
+    $config->set('URI.Base', 'http://www.example.com');
+    $config->set('URI.MakeAbsolute', true);
+    $config->set('AutoFormat.AutoParagraph', true);
+
+
+---------------------------------------------------------------------------
+5. Caching
+
+HTML Purifier generates some cache files (generally one or two) to speed up
+its execution. For maximum performance, make sure that
+library/HTMLPurifier/DefinitionCache/Serializer is writeable by the webserver.
+
+If you are in the library/ folder of HTML Purifier, you can set the
+appropriate permissions using:
+
+    chmod -R 0755 HTMLPurifier/DefinitionCache/Serializer
+
+If the above command doesn't work, you may need to assign write permissions
+to all. This may be necessary if your webserver runs as nobody, but is
+not recommended since it means any other user can write files in the
+directory. Use:
+
+    chmod -R 0777 HTMLPurifier/DefinitionCache/Serializer
+
+You can also chmod files via your FTP client; this option
+is usually accessible by right clicking the corresponding directory and
+then selecting "chmod" or "file permissions".
+
+Starting with 2.0.1, HTML Purifier will generate friendly error messages
+that will tell you exactly what you have to chmod the directory to, if in doubt,
+follow its advice.
+
+If you are unable or unwilling to give write permissions to the cache
+directory, you can either disable the cache (and suffer a performance
+hit):
+
+    $config->set('Core.DefinitionCache', null);
+
+Or move the cache directory somewhere else (no trailing slash):
+
+    $config->set('Cache.SerializerPath', '/home/user/absolute/path');
+
+
+---------------------------------------------------------------------------
+6.   Using the code
+
+The interface is mind-numbingly simple:
+
+    $purifier = new HTMLPurifier($config);
+    $clean_html = $purifier->purify( $dirty_html );
+
+That's it!  For more examples, check out docs/examples/ (they aren't very
+different though).  Also, docs/enduser-slow.html gives advice on what to
+do if HTML Purifier is slowing down your application.
+
+
+---------------------------------------------------------------------------
+7.   Quick install
+
+First, make sure library/HTMLPurifier/DefinitionCache/Serializer is
+writable by the webserver (see Section 5: Caching above for details).
+If your website is in UTF-8 and XHTML Transitional, use this code:
+
+<?php
+    require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
+
+    $config = HTMLPurifier_Config::createDefault();
+    $purifier = new HTMLPurifier($config);
+    $clean_html = $purifier->purify($dirty_html);
+?>
+
+If your website is in a different encoding or doctype, use this code:
+
+<?php
+    require_once '/path/to/htmlpurifier/library/HTMLPurifier.auto.php';
+
+    $config = HTMLPurifier_Config::createDefault();
+    $config->set('Core.Encoding', 'ISO-8859-1'); // replace with your encoding
+    $config->set('HTML.Doctype', 'HTML 4.01 Transitional'); // replace with your doctype
+    $purifier = new HTMLPurifier($config);
+
+    $clean_html = $purifier->purify($dirty_html);
+?>
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/INSTALL.fr.utf8 b/library/ezyang/htmlpurifier/INSTALL.fr.utf8
new file mode 100644
index 0000000000..06e628cc96
--- /dev/null
+++ b/library/ezyang/htmlpurifier/INSTALL.fr.utf8
@@ -0,0 +1,60 @@
+
+Installation
+    Comment installer HTML Purifier
+
+Attention : Ce document est encodé en UTF-8, si les lettres avec des accents
+ne s'affichent pas, prenez un meilleur éditeur de texte.
+
+L'installation de HTML Purifier est très simple, parce qu'il n'a pas besoin
+de configuration. Pour les utilisateurs impatients, le code se trouve dans le
+pied de page, mais je recommande de lire le document.
+
+1.  Compatibilité
+
+HTML Purifier fonctionne avec PHP 5. PHP 5.0.5 est la dernière version testée.
+Il ne dépend pas d'autres librairies.
+
+Les extensions optionnelles sont iconv (généralement déjà installée) et tidy
+(répendue aussi). Si vous utilisez UTF-8 et que vous ne voulez pas l'indentation,
+vous pouvez utiliser HTML Purifier sans ces extensions.
+
+
+2.  Inclure la librairie
+
+Quand vous devez l'utilisez, incluez le :
+
+    require_once('/path/to/library/HTMLPurifier.auto.php');
+
+Ne pas l'inclure si ce n'est pas nécessaire, car HTML Purifier est lourd.
+
+HTML Purifier utilise "autoload". Si vous avez défini la fonction __autoload,
+vous devez ajouter cette fonction :
+
+    spl_autoload_register('__autoload')
+
+Plus d'informations dans le document "INSTALL".
+
+3.  Installation rapide
+
+Si votre site Web est en UTF-8 et XHTML Transitional, utilisez :
+
+<?php
+    require_once('/path/to/htmlpurifier/library/HTMLPurifier.auto.php');
+    $purificateur = new HTMLPurifier();
+    $html_propre = $purificateur->purify($html_a_purifier);
+?>
+
+Sinon, utilisez :
+
+<?php
+    require_once('/path/to/html/purifier/library/HTMLPurifier.auto.load');
+    $config = $HTMLPurifier_Config::createDefault();
+    $config->set('Core', 'Encoding', 'ISO-8859-1'); //Remplacez par votre
+    encodage
+    $config->set('Core', 'XHTML', true); //Remplacer par false si HTML 4.01
+    $purificateur = new HTMLPurifier($config);
+    $html_propre = $purificateur->purify($html_a_purifier);
+?>
+
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/LICENSE b/library/ezyang/htmlpurifier/LICENSE
new file mode 100644
index 0000000000..8c88a20d45
--- /dev/null
+++ b/library/ezyang/htmlpurifier/LICENSE
@@ -0,0 +1,504 @@
+		  GNU LESSER GENERAL PUBLIC LICENSE
+		       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+		  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+			    NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/NEWS b/library/ezyang/htmlpurifier/NEWS
new file mode 100644
index 0000000000..a9124af1a1
--- /dev/null
+++ b/library/ezyang/htmlpurifier/NEWS
@@ -0,0 +1,1094 @@
+NEWS ( CHANGELOG and HISTORY )                                     HTMLPurifier
+|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+= KEY ====================
+    # Breaks back-compat
+    ! Feature
+    - Bugfix
+      + Sub-comment
+    . Internal change
+==========================
+
+4.7.0, released 2015-08-04
+# opacity is now considered a "tricky" CSS property rather than a
+  proprietary one.
+! %AutoFormat.RemoveEmpty.Predicate for specifying exactly when
+  an element should be considered "empty" (maybe preserve if it
+  has attributes), and modify iframe support so that the iframe
+  is removed if it is missing a src attribute.  Thanks meeva for
+  reporting.
+- Don't truncate upon encountering </div> when using DOMLex.  Thanks
+  Myrto Christina for finally convincing me to fix this.
+- Update YouTube filter for new code.
+- Fix parsing of rgb() values with spaces in them for 'border'
+  attribute.
+- Don't remove foo="" attributes if foo is a boolean attribute.  Thanks
+  valME for reporting.
+
+4.6.0, released 2013-11-30
+# Secure URI munge hashing algorithm has changed to hash_hmac("sha256", $url, $secret).
+  Please update any verification scripts you may have.
+# URI parsing algorithm was made more strict, so only prefixes which
+  looks like schemes will actually be schemes.  Thanks
+  Michael Gusev <mgusev@sugarcrm.com> for fixing.
+# %Core.EscapeInvalidChildren is no longer supported, and no longer does
+  anything.
+! New directive %Core.AllowHostnameUnderscore which allows underscores
+  in hostnames.
+- Eliminate quadratic behavior in DOMLex by using a proper queue.
+  Thanks Ole Laursen for noticing this.
+- Rewritten MakeWellFormed/FixNesting implementation eliminates quadratic
+  behavior in the rest of the purificaiton pipeline.  Thanks Chedburn
+  Networks for sponsoring this work.
+- Made Linkify URL parser a bit less permissive, so that non-breaking
+  spaces and commas are not included as part of URL.  Thanks nAS for fixing.
+- Fix some bad interactions with %HTML.Allowed and injectors.  Thanks
+  David Hirtz for reporting.
+- Fix infinite loop in DirectLex. Thanks Ashar Javed (@soaj1664ashar)
+  for reporting.
+
+4.5.0, released 2013-02-17
+# Fix bug where stacked attribute transforms clobber each other;
+  this also means it's no longer possible to override attribute
+  transforms in later modules.  No internal code was using this
+  but this may break some clients.
+# We now use SHA-1 to identify cached definitions, instead of MD5.
+! Support display:inline-block
+! Support for more white-space CSS values.
+! Permit underscores in font families
+! Support for page-break-* CSS3 properties when proprietary properties
+  are enabled.
+! New directive %Core.DisableExcludes; can be set to 'true' to turn off
+  SGML excludes checking.  If HTML Purifier is removing too much text
+  and you don't care about full standards compliance, try setting this to
+  'true'.
+- Use prepend for SPL autoloading on PHP 5.3 and later.
+- Fix bug with nofollow transform when pre-existing rel exists.
+- Fix bug where background:url() always gets lower-cased
+  (but not background-image:url())
+- Fix bug with non lower-case color names in HTML
+- Fix bug where data URI validation doesn't remove temporary files.
+  Thanks Javier Marín Ros <javiermarinros@gmail.com> for reporting.
+- Don't remove certain empty tags on RemoveEmpty.
+
+4.4.0, released 2012-01-18
+# Removed PEARSax3 handler.
+# URI.Munge now munges URIs inside the same host that go from https
+  to http.  Reported by Neike Taika-Tessaro.
+# Core.EscapeNonASCIICharacters now always transforms entities to
+  entities, even if target encoding is UTF-8.
+# Tighten up selector validation in ExtractStyleBlocks.
+  Non-syntactically valid selectors are now rejected, along with
+  some of the more obscure ones such as attribute selectors, the
+  :lang pseudoselector, and anything not in CSS2.1.  Furthermore,
+  ID and class selectors now work properly with the relevant
+  configuration attributes.  Also, mute errors when parsing CSS
+  with CSS Tidy.  Reported by Mario Heiderich and Norman Hippert.
+! Added support for 'scope' attribute on tables.
+! Added %HTML.TargetBlank, which adds target="blank" to all outgoing links.
+! Properly handle sub-lists directly nested inside of lists in
+  a standards compliant way, by moving them into the preceding <li>
+! Added %HTML.AllowedComments and %HTML.AllowedCommentsRegexp for
+  limited allowed comments in untrusted situations.
+! Implement iframes, and allow them to be used in untrusted mode with
+  %HTML.SafeIframe and %URI.SafeIframeRegexp.  Thanks Bradley M. Froehle
+  <brad.froehle@gmail.com> for submitting an initial version of the patch.
+! The Forms module now works properly for transitional doctypes.
+! Added support for internationalized domain names. You need the PEAR
+  Net_IDNA2 module to be in your path; if it is installed, ensure the
+  class can be loaded and then set %Core.EnableIDNA to true.
+- Color keywords are now case insensitive.  Thanks Yzmir Ramirez
+  <yramirez-htmlpurifier@adicio.com> for reporting.
+- Explicitly initialize anonModule variable to null.
+- Do not duplicate nofollow if already present.  Thanks 178
+  for reporting.
+- Do not add nofollow if hostname matches our current host.  Thanks 178
+  for reporting, and Neike Taika-Tessaro for helping diagnose.
+- Do not unset parser variable; this fixes intermittent serialization
+  problems.  Thanks Neike Taika-Tessaro for reporting, bill
+  <10010tiger@gmail.com> for diagnosing.
+- Fix iconv truncation bug, where non-UTF-8 target encodings see
+  output truncated after around 8000 characters.  Thanks Jörg Ludwig
+  <joerg.ludwig@iserv.eu> for reporting.
+- Fix broken table content model for XHTML1.1 (and also earlier
+  versions, although the W3C validator doesn't catch those violations).
+  Thanks GlitchMr <glitch.mr@gmail.com> for reporting.
+
+4.3.0, released 2011-03-27
+# Fixed broken caching of customized raw definitions, but requires an
+  API change.  The old API still works but will emit a warning,
+  see http://htmlpurifier.org/docs/enduser-customize.html#optimized
+  for how to upgrade your code.
+# Protect against Internet Explorer innerHTML behavior by specially
+  treating attributes with backticks but no angled brackets, quotes or
+  spaces.  This constitutes a slight semantic change, which can be
+  reverted using %Output.FixInnerHTML.  Reported by Neike Taika-Tessaro
+  and Mario Heiderich.
+# Protect against cssText/innerHTML by restricting allowed characters
+  used in fonts further than mandated by the specification and encoding
+  some extra special characters in URLs.  Reported by Neike
+  Taika-Tessaro and Mario Heiderich.
+! Added %HTML.Nofollow to add rel="nofollow" to external links.
+! More types of SPL autoloaders allowed on later versions of PHP.
+! Implementations for position, top, left, right, bottom, z-index
+  when %CSS.Trusted is on.
+! Add %Cache.SerializerPermissions option for custom serializer
+  directory/file permissions
+! Fix longstanding bug in Flash support for non-IE browsers, and
+  allow more wmode attributes.
+! Add %CSS.AllowedFonts to restrict permissible font names.
+- Switch to an iterative traversal of the DOM, which prevents us
+  from running out of stack space for deeply nested documents.
+  Thanks Maxim Krizhanovsky for contributing a patch.
+- Make removal of conditional IE comments ungreedy; thanks Bernd
+  for reporting.
+- Escape CDATA before removing Internet Explorer comments.
+- Fix removal of id attributes under certain conditions by ensuring
+  armor attributes are preserved when recreating tags.
+- Check if schema.ser was corrupted.
+- Check if zend.ze1_compatibility_mode is on, and error out if it is.
+  This safety check is only done for HTMLPurifier.auto.php; if you
+  are using standalone or the specialized includes files, you're
+  expected to know what you're doing.
+- Stop repeatedly writing the cache file after I'm done customizing a
+  raw definition.  Reported by ajh.
+- Switch to using require_once in the Bootstrap to work around bad
+  interaction with Zend Debugger and APC.  Reported by Antonio Parraga.
+- Fix URI handling when hostname is missing but scheme is present.
+  Reported by Neike Taika-Tessaro.
+- Fix missing numeric entities on DirectLex; thanks Neike Taika-Tessaro
+  for reporting.
+- Fix harmless notice from indexing into empty string.  Thanks Matthijs
+  Kooijman <matthijs@stdin.nl> for reporting.
+- Don't autoclose no parent elements are able to support the element
+  that triggered the autoclose.  In particular fixes strange behavior
+  of stray <li> tags.  Thanks pkuliga@gmail.com for reporting and
+  Neike Taika-Tessaro <pinkgothic@gmail.com> for debugging assistance.
+
+4.2.0, released 2010-09-15
+! Added %Core.RemoveProcessingInstructions, which lets you remove
+  <? ... ?> statements.
+! Added %URI.DisableResources functionality; the directive originally
+  did nothing.  Thanks David Rothstein for reporting.
+! Add documentation about configuration directive types.
+! Add %CSS.ForbiddenProperties configuration directive.
+! Add %HTML.FlashAllowFullScreen to permit embedded Flash objects
+  to utilize full-screen mode.
+! Add optional support for the <code>file</code> URI scheme, enable
+  by explicitly setting %URI.AllowedSchemes.
+! Add %Core.NormalizeNewlines options to allow turning off newline
+  normalization.
+- Fix improper handling of Internet Explorer conditional comments
+  by parser.  Thanks zmonteca for reporting.
+- Fix missing attributes bug when running on Mac Snow Leopard and APC.
+  Thanks sidepodcast for the fix.
+- Warn if an element is allowed, but an attribute it requires is
+  not allowed.
+
+4.1.1, released 2010-05-31
+- Fix undefined index warnings in maintenance scripts.
+- Fix bug in DirectLex for parsing elements with a single attribute
+  with entities.
+- Rewrite CSS output logic for font-family and url().  Thanks Mario
+  Heiderich <mario.heiderich@googlemail.com> for reporting and Takeshi
+  Terada <t-terada@violet.plala.or.jp> for suggesting the fix.
+- Emit an error for CollectErrors if a body is extracted
+- Fix bug where in background-position for center keyword handling.
+- Fix infinite loop when a wrapper element is inserted in a context
+  where it's not allowed.  Thanks Lars <lars@renoz.dk> for reporting.
+- Remove +x bit and shebang from index.php; only supported mode is to
+  explicitly call it with php.
+- Make test script less chatty when log_errors is on.
+
+4.1.0, released 2010-04-26
+! Support proprietary height attribute on table element
+! Support YouTube slideshows that contain /cp/ in their URL.
+! Support for data: URI scheme; not enabled by default, add it using
+  %URI.AllowedSchemes
+! Support flashvars when using %HTML.SafeObject and %HTML.SafeEmbed.
+! Support for Internet Explorer compatibility with %HTML.SafeObject
+  using %Output.FlashCompat.
+! Handle <ol><ol> properly, by inserting the necessary <li> tag.
+- Always quote the insides of url(...) in CSS.
+
+4.0.0, released 2009-07-07
+# APIs for ConfigSchema subsystem have substantially changed. See
+  docs/dev-config-bcbreaks.txt for details; in essence, anything that
+  had both namespace and directive now have a single unified key.
+# Some configuration directives were renamed, specifically:
+    %AutoFormatParam.PurifierLinkifyDocURL -> %AutoFormat.PurifierLinkify.DocURL
+    %FilterParam.ExtractStyleBlocksEscaping -> %Filter.ExtractStyleBlocks.Escaping
+    %FilterParam.ExtractStyleBlocksScope -> %Filter.ExtractStyleBlocks.Scope
+    %FilterParam.ExtractStyleBlocksTidyImpl -> %Filter.ExtractStyleBlocks.TidyImpl
+  As usual, the old directive names will still work, but will throw E_NOTICE
+  errors.
+# The allowed values for class have been relaxed to allow all of CDATA for
+  doctypes that are not XHTML 1.1 or XHTML 2.0.  For old behavior, set
+  %Attr.ClassUseCDATA to false.
+# Instead of appending the content model to an old content model, a blank
+  element will replace the old content model.  You can use #SUPER to get
+  the old content model.
+! More robust support for name="" and id=""
+! HTMLPurifier_Config::inherit($config) allows you to inherit one
+  configuration, and have changes to that configuration be propagated
+  to all of its children.
+! Implement %HTML.Attr.Name.UseCDATA, which relaxes validation rules on
+  the name attribute when set. Use with care. Thanks Ian Cook for
+  sponsoring.
+! Implement %AutoFormat.RemoveEmpty.RemoveNbsp, which removes empty
+  tags that contain non-breaking spaces as well other whitespace. You
+  can also modify which tags should have &nbsp; maintained with
+  %AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.
+! Implement %Attr.AllowedClasses, which allows administrators to restrict
+  classes users can use to a specified finite set of classes, and
+  %Attr.ForbiddenClasses, which is the logical inverse.
+! You can now maintain your own configuration schema directories by
+  creating a config-schema.php file or passing an extra argument. Check
+  docs/dev-config-schema.html for more details.
+! Added HTMLPurifier_Config->serialize() method, which lets you save away
+  your configuration in a compact serial file, which you can unserialize
+  and use directly without having to go through the overhead of setup.
+- Fix bug where URIDefinition would not get cleared if it's directives got
+  changed.
+- Fix fatal error in HTMLPurifier_Encoder on certain platforms (probably NetBSD 5.0)
+- Fix bug in Linkify autoformatter involving <a><span>http://foo</span></a>
+- Make %URI.Munge not apply to links that have the same host as your host.
+- Prevent stray </body> tag from truncating output, if a second </body>
+  is present.
+. Created script maintenance/rename-config.php for renaming a configuration
+  directive while maintaining its alias.  This script does not change source code.
+. Implement namespace locking for definition construction, to prevent
+  bugs where a directive is used for definition construction but is not
+  used to construct the cache hash.
+
+3.3.0, released 2009-02-16
+! Implement CSS property 'overflow' when %CSS.AllowTricky is true.
+! Implement generic property list classess
+- Fix bug with testEncodingSupportsASCII() algorithm when iconv() implementation
+  does not do the "right thing" with characters not supported in the output
+  set.
+- Spellcheck UTF-8: The Secret To Character Encoding
+- Fix improper removal of the contents of elements with only whitespace. Thanks
+  Eric Wald for reporting.
+- Fix broken test suite in versions of PHP without spl_autoload_register()
+- Fix degenerate case with YouTube filter involving double hyphens.
+  Thanks Pierre Attar for reporting.
+- Fix YouTube rendering problem on certain versions of Firefox.
+- Fix CSSDefinition Printer problems with decorators
+- Add text parameter to unit tests, forces text output
+. Add verbose mode to command line test runner, use (--verbose)
+. Turn on unit tests for UnitConverter
+. Fix missing version number in configuration %Attr.DefaultImageAlt (added 3.2.0)
+. Fix newline errors that caused spurious failures when CRLF HTML Purifier was
+  tested on Linux.
+. Removed trailing whitespace from all text files, see
+  remote-trailing-whitespace.php maintenance script.
+. Convert configuration to use property list backend.
+
+3.2.0, released 2008-10-31
+# Using %Core.CollectErrors forces line number/column tracking on, whereas
+  previously you could theoretically turn it off.
+# HTMLPurifier_Injector->notifyEnd() is formally deprecated. Please
+  use handleEnd() instead.
+! %Output.AttrSort for when you need your attributes in alphabetical order to
+  deal with a bug in FCKEditor. Requested by frank farmer.
+! Enable HTML comments when %HTML.Trusted is on. Requested by Waldo Jaquith.
+! Proper support for name attribute. It is now allowed and equivalent to the id
+  attribute in a and img tags, and is only converted to id when %HTML.TidyLevel
+  is heavy (for all doctypes).
+! %AutoFormat.RemoveEmpty to remove some empty tags from documents. Please don't
+  use on hand-written HTML.
+! Add error-cases for unsupported elements in MakeWellFormed. This enables
+  the strategy to be used, standalone, on untrusted input.
+! %Core.AggressivelyFixLt is on by default. This causes more sensible
+  processing of left angled brackets in smileys and other whatnot.
+! Test scripts now have a 'type' parameter, which lets you say 'htmlpurifier',
+  'phpt', 'vtest', etc. in order to only execute those tests. This supercedes
+  the --only-phpt parameter, although for backwards-compatibility the flag
+  will still work.
+! AutoParagraph auto-formatter will now preserve double-newlines upon output.
+  Users who are not performing inbound filtering, this may seem a little
+  useless, but as a bonus, the test suite and handling of edge cases is also
+  improved.
+! Experimental implementation of forms for %HTML.Trusted
+! Track column numbers when maintain line numbers is on
+! Proprietary 'background' attribute on table-related elements converted into
+  corresponding CSS.  Thanks Fusemail for sponsoring this feature!
+! Add forward(), forwardUntilEndToken(), backward() and current() to Injector
+  supertype.
+! HTMLPurifier_Injector->handleEnd() permits modification to end tokens. The
+  time of operation varies slightly from notifyEnd() as *all* end tokens are
+  processed by the injector before they are subject to the well-formedness rules.
+! %Attr.DefaultImageAlt allows overriding default behavior of setting alt to
+  basename of image when not present.
+! %AutoFormat.DisplayLinkURI neuters <a> tags into plain text URLs.
+- Fix two bugs in %URI.MakeAbsolute; one involving empty paths in base URLs,
+  the other involving an undefined $is_folder error.
+- Throw error when %Core.Encoding is set to a spurious value. Previously,
+  this errored silently and returned false.
+- Redirected stderr to stdout for flush error output.
+- %URI.DisableExternal will now use the host in %URI.Base if %URI.Host is not
+  available.
+- Do not re-munge URL if the output URL has the same host as the input URL.
+  Requested by Chris.
+- Fix error in documentation regarding %Filter.ExtractStyleBlocks
+- Prevent <![CDATA[<body></body>]]> from triggering %Core.ConvertDocumentToFragment
+- Fix bug with inline elements in blockquotes conflicting with strict doctype
+- Detect if HTML support is disabled for DOM by checking for loadHTML() method.
+- Fix bug where dots and double-dots in absolute URLs without hostname were
+  not collapsed by URIFilter_MakeAbsolute.
+- Fix bug with anonymous modules operating on SafeEmbed or SafeObject elements
+  by reordering their addition.
+- Will now throw exception on many error conditions during lexer creation; also
+  throw an exception when MaintainLineNumbers is true, but a non-tracksLineNumbers
+  is being used.
+- Detect if domxml extension is loaded, and use DirectLEx accordingly.
+- Improve handling of big numbers with floating point arithmetic in UnitConverter.
+  Reported by David Morton.
+. Strategy_MakeWellFormed now operates in-place, saving memory and allowing
+  for more interesting filter-backtracking
+. New HTMLPurifier_Injector->rewind() functionality, allows injectors to rewind
+  index to reprocess tokens.
+. StringHashParser now allows for multiline sections with "empty" content;
+  previously the section would remain undefined.
+. Added --quick option to multitest.php, which tests only the most recent
+  release for each series.
+. Added --distro option to multitest.php, which accepts either 'normal' or
+  'standalone'. This supercedes --exclude-normal and --exclude-standalone
+
+3.1.1, released 2008-06-19
+# %URI.Munge now, by default, does not munge resources (for example, <img src="">)
+  In order to enable this again, please set %URI.MungeResources to true.
+! More robust imagecrash protection with height/width CSS with %CSS.MaxImgLength,
+  and height/width HTML with %HTML.MaxImgLength.
+! %URI.MungeSecretKey for secure URI munging. Thanks Chris
+  for sponsoring this feature. Check out the corresponding documentation
+  for details. (Att Nightly testers: The API for this feature changed before
+  the general release. Namely, rename your directives %URI.SecureMungeSecretKey =>
+  %URI.MungeSecretKey and and %URI.SecureMunge => %URI.Munge)
+! Implemented post URI filtering. Set member variable $post to true to set
+  a URIFilter as such.
+! Allow modules to define injectors via $info_injector. Injectors are
+  automatically disabled if injector's needed elements are not found.
+! Support for "safe" objects added, use %HTML.SafeObject and %HTML.SafeEmbed.
+  Thanks Chris for sponsoring. If you've been using ad hoc code from the
+  forums, PLEASE use this instead.
+! Added substitutions for %e, %n, %a and %p in %URI.Munge (in order,
+  embedded, tag name, attribute name, CSS property name). See %URI.Munge
+  for more details. Requested by Jochem Blok.
+- Disable percent height/width attributes for img.
+- AttrValidator operations are now atomic; updates to attributes are not
+  manifest in token until end of operations. This prevents naughty internal
+  code from directly modifying CurrentToken when they're not supposed to.
+  This semantics change was requested by frank farmer.
+- Percent encoding checks enabled for URI query and fragment
+- Fix stray backslashes in font-family; CSS Unicode character escapes are
+  now properly resolved (although *only* in font-family). Thanks Takeshi Terada
+  for reporting.
+- Improve parseCDATA algorithm to take into account newline normalization
+- Account for browser confusion between Yen character and backslash in
+  Shift_JIS encoding. This fix generalizes to any other encoding which is not
+  a strict superset of printable ASCII. Thanks Takeshi Terada for reporting.
+- Fix missing configuration parameter in Generator calls. Thanks vs for the
+  partial patch.
+- Improved adherence to Unicode by checking for non-character codepoints.
+  Thanks Geoffrey Sneddon for reporting. This may result in degraded
+  performance for extremely large inputs.
+- Allow CSS property-value pair ''text-decoration: none''. Thanks Jochem Blok
+  for reporting.
+. Added HTMLPurifier_UnitConverter and HTMLPurifier_Length for convenient
+  handling of CSS-style lengths. HTMLPurifier_AttrDef_CSS_Length now uses
+  this class.
+. API of HTMLPurifier_AttrDef_CSS_Length changed from __construct($disable_negative)
+  to __construct($min, $max). __construct(true) is equivalent to
+  __construct('0').
+. Added HTMLPurifier_AttrDef_Switch class
+. Rename HTMLPurifier_HTMLModule_Tidy->construct() to setup() and bubble method
+  up inheritance hierarchy to HTMLPurifier_HTMLModule. All HTMLModules
+  get this called with the configuration object.  All modules now
+  use this rather than __construct(), although legacy code using constructors
+  will still work--the new format, however, lets modules access the
+  configuration object for HTML namespace dependant tweaks.
+. AttrDef_HTML_Pixels now takes a single construction parameter, pixels.
+. ConfigSchema data-structure heavily optimized; on average it uses a third
+  the memory it did previously. The interface has changed accordingly,
+  consult changes to HTMLPurifier_Config for details.
+. Variable parsing types now are magic integers instead of strings
+. Added benchmark for ConfigSchema
+. HTMLPurifier_Generator requires $config and $context parameters. If you
+  don't know what they should be, use HTMLPurifier_Config::createDefault()
+  and new HTMLPurifier_Context().
+. Printers now properly distinguish between output configuration, and
+  target configuration. This is not applicable to scripts using
+  the Printers for HTML Purifier related tasks.
+. HTML/CSS Printers must be primed with prepareGenerator($gen_config), otherwise
+  fatal errors will ensue.
+. URIFilter->prepare can return false in order to abort loading of the filter
+. Factory for AttrDef_URI implemented, URI#embedded to indicate URI that embeds
+  an external resource.
+. %URI.Munge functionality factored out into a post-filter class.
+. Added CurrentCSSProperty context variable during CSS validation
+
+3.1.0, released 2008-05-18
+# Unnecessary references to objects (vestiges of PHP4) removed from method
+  signatures.  The following methods do not need references when assigning from
+  them and will result in E_STRICT errors if you try:
+    + HTMLPurifier_Config->get*Definition() [* = HTML, CSS]
+    + HTMLPurifier_ConfigSchema::instance()
+    + HTMLPurifier_DefinitionCacheFactory::instance()
+    + HTMLPurifier_DefinitionCacheFactory->create()
+    + HTMLPurifier_DoctypeRegistry->register()
+    + HTMLPurifier_DoctypeRegistry->get()
+    + HTMLPurifier_HTMLModule->addElement()
+    + HTMLPurifier_HTMLModule->addBlankElement()
+    + HTMLPurifier_LanguageFactory::instance()
+# Printer_ConfigForm's get*() functions were static-ified
+# %HTML.ForbiddenAttributes requires attribute declarations to be in the
+  form of tag@attr, NOT tag.attr (which will throw an error and won't do
+  anything). This is for forwards compatibility with XML; you'd do best
+  to migrate an %HTML.AllowedAttributes directives to this syntax too.
+! Allow index to be false for config from form creation
+! Added HTMLPurifier::VERSION constant
+! Commas, not dashes, used for serializer IDs. This change is forwards-compatible
+  and allows for version numbers like "3.1.0-dev".
+! %HTML.Allowed deals gracefully with whitespace anywhere, anytime!
+! HTML Purifier's URI handling is a lot more robust, with much stricter
+  validation checks and better percent encoding handling. Thanks Gareth Heyes
+  for indicating security vulnerabilities from lax percent encoding.
+! Bootstrap autoloader deals more robustly with classes that don't exist,
+  preventing class_exists($class, true) from barfing.
+- InterchangeBuilder now alphabetizes its lists
+- Validation error in configdoc output fixed
+- Iconv and other encoding errors muted even with custom error handlers that
+  do not honor error_reporting
+- Add protection against imagecrash attack with CSS height/width
+- HTMLPurifier::instance() created for consistency, is equivalent to getInstance()
+- Fixed and revamped broken ConfigForm smoketest
+- Bug with bool/null fields in Printer_ConfigForm fixed
+- Bug with global forbidden attributes fixed
+- Improved error messages for allowed and forbidden HTML elements and attributes
+- Missing (or null) in configdoc documentation restored
+- If DOM throws and exception during parsing with PH5P (occurs in newer versions
+  of DOM), HTML Purifier punts to DirectLex
+- Fatal error with unserialization of ScriptRequired
+- Created directories are now chmod'ed properly
+- Fixed bug with fallback languages in LanguageFactory
+- Standalone testing setup properly with autoload
+. Out-of-date documentation revised
+. UTF-8 encoding check optimization as suggested by Diego
+. HTMLPurifier_Error removed in favor of exceptions
+. More copy() function removed; should use clone instead
+. More extensive unit tests for HTMLDefinition
+. assertPurification moved to central harness
+. HTMLPurifier_Generator accepts $config and $context parameters during
+  instantiation, not runtime
+. Double-quotes outside of attribute values are now unescaped
+
+3.1.0rc1, released 2008-04-22
+# Autoload support added. Internal require_once's removed in favor of an
+  explicit require list or autoloading. To use HTML Purifier,
+  you must now either use HTMLPurifier.auto.php
+  or HTMLPurifier.includes.php; setting the include path and including
+  HTMLPurifier.php is insufficient--in such cases include HTMLPurifier.autoload.php
+  as well to register our autoload handler (or modify your autoload function
+  to check HTMLPurifier_Bootstrap::getPath($class)). You can also use
+  HTMLPurifier.safe-includes.php for a less performance friendly but more
+  user-friendly library load.
+# HTMLPurifier_ConfigSchema static functions are officially deprecated. Schema
+  information is stored in the ConfigSchema directory, and the
+  maintenance/generate-schema-cache.php generates the schema.ser file, which
+  is now instantiated. Support for userland schema changes coming soon!
+# HTMLPurifier_Config will now throw E_USER_NOTICE when you use a directive
+  alias; to get rid of these errors just modify your configuration to use
+  the new directive name.
+# HTMLPurifier->addFilter is deprecated; built-in filters can now be
+  enabled using %Filter.$filter_name or by setting your own filters using
+  %Filter.Custom
+# Directive-level safety properties superceded in favor of module-level
+  safety. Internal method HTMLModule->addElement() has changed, although
+  the externally visible HTMLDefinition->addElement has *not* changed.
+! Extra utility classes for testing and non-library operations can
+  be found in extras/. Specifically, these are FSTools and ConfigDoc.
+  You may find a use for these in your own project, but right now they
+  are highly experimental and volatile.
+! Integration with PHPT allows for automated smoketests
+! Limited support for proprietary HTML elements, namely <marquee>, sponsored
+  by Chris. You can enable them with %HTML.Proprietary if your client
+  demands them.
+! Support for !important CSS cascade modifier. By default, this will be stripped
+  from CSS, but you can enable it using %CSS.AllowImportant
+! Support for display and visibility CSS properties added, set %CSS.AllowTricky
+  to true to use them.
+! HTML Purifier now has its own Exception hierarchy under HTMLPurifier_Exception.
+  Developer error (not enduser error) can cause these to be triggered.
+! Experimental kses() wrapper introduced with HTMLPurifier.kses.php
+! Finally %CSS.AllowedProperties for tweaking allowed CSS properties without
+  mucking around with HTMLPurifier_CSSDefinition
+! ConfigDoc output has been enhanced with version and deprecation info.
+! %HTML.ForbiddenAttributes and %HTML.ForbiddenElements implemented.
+- Autoclose now operates iteratively, i.e. <span><span><div> now has
+  both span tags closed.
+- Various HTMLPurifier_Config convenience functions now accept another parameter
+  $schema which defines what HTMLPurifier_ConfigSchema to use besides the
+  global default.
+- Fix bug with trusted script handling in libxml versions later than 2.6.28.
+- Fix bug in ExtractStyleBlocks with comments in style tags
+- Fix bug in comment parsing for DirectLex
+- Flush output now displayed when in command line mode for unit tester
+- Fix bug with rgb(0, 1, 2) color syntax with spaces inside shorthand syntax
+- HTMLPurifier_HTMLDefinition->addAttribute can now be called multiple times
+  on the same element without emitting errors.
+- Fixed fatal error in PH5P lexer with invalid tag names
+. Plugins now get their own changelogs according to project conventions.
+. Convert tokens to use instanceof, reducing memory footprint and
+  improving comparison speed.
+. Dry runs now supported in SimpleTest; testing facilities improved
+. Bootstrap class added for handling autoloading functionality
+. Implemented recursive glob at FSTools->globr
+. ConfigSchema now has instance methods for all corresponding define*
+  static methods.
+. A couple of new historical maintenance scripts were added.
+. HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php split into two files
+. tests/index.php can now be run from any directory.
+. HTMLPurifier_Token subclasses split into seperate files
+. HTMLPURIFIER_PREFIX now is defined in Bootstrap.php, NOT HTMLPurifier.php
+. HTMLPURIFIER_PREFIX can now be defined outside of HTML Purifier
+. New --php=php flag added, allows PHP executable to be specified (command
+  line only!)
+. htmlpurifier_add_test() preferred method to translate test files in to
+  classes, because it handles PHPT files too.
+. Debugger class is deprecated and will be removed soon.
+. Command line argument parsing for testing scripts revamped, now --opt value
+  format is supported.
+. Smoketests now cleanup after magic quotes
+. Generator now can output comments (however, comments are still stripped
+  from HTML Purifier output)
+. HTMLPurifier_ConfigSchema->validate() deprecated in favor of
+  HTMLPurifier_VarParser->parse()
+. Integers auto-cast into float type by VarParser.
+. HTMLPURIFIER_STRICT removed; no validation is performed on runtime, only
+  during cache generation
+. Reordered script calls in maintenance/flush.php
+. Command line scripts now honor exit codes
+. When --flush fails in unit testers, abort tests and print message
+. Improved documentation in docs/dev-flush.html about the maintenance scripts
+. copy() methods removed in favor of clone keyword
+
+3.0.0, released 2008-01-06
+# HTML Purifier is PHP 5 only! The 2.1.x branch will be maintained
+  until PHP 4 is completely deprecated, but no new features will be added
+  to it.
+  + Visibility declarations added
+  + Constructor methods renamed to __construct()
+  + PHP4 reference cruft removed (in progress)
+! CSS properties are now case-insensitive
+! DefinitionCacheFactory now can register new implementations
+! New HTMLPurifier_Filter_ExtractStyleBlocks for extracting <style> from
+  documents and cleaning their contents up. Requires the CSSTidy library
+  <http://csstidy.sourceforge.net/>. You can access the blocks with the
+  'StyleBlocks' Context variable ($purifier->context->get('StyleBlocks')).
+  The output CSS can also be "scoped" for a specific element, use:
+  %Filter.ExtractStyleBlocksScope
+! Experimental support for some proprietary CSS attributes allowed:
+  opacity (and all of the browser-specific equivalents) and scrollbar colors.
+  Enable by setting %CSS.Proprietary to true.
+- Colors missing # but in hex form will be corrected
+- CSS Number algorithm improved
+- Unit testing and multi-testing now on steroids: command lines,
+  XML output, and other goodies now added.
+. Unit tests for Injector improved
+. New classes:
+  + HTMLPurifier_AttrDef_CSS_AlphaValue
+  + HTMLPurifier_AttrDef_CSS_Filter
+. Multitest now has a file docblock
+
+2.1.3, released 2007-11-05
+! tests/multitest.php allows you to test multiple versions by running
+  tests/index.php through multiple interpreters using `phpv` shell
+  script (you must provide this script!)
+- Fixed poor include ordering for Email URI AttrDefs, causes fatal errors
+  on some systems.
+- Injector algorithm further refined: off-by-one error regarding skip
+  counts for dormant injectors fixed
+- Corrective blockquote definition now enabled for HTML 4.01 Strict
+- Fatal error when <img> tag (or any other element with required attributes)
+  has 'id' attribute fixed, thanks NykO18 for reporting
+- Fix warning emitted when a non-supported URI scheme is passed to the
+  MakeAbsolute URIFilter, thanks NykO18 (again)
+- Further refine AutoParagraph injector. Behavior inside of elements
+  allowing paragraph tags clarified: only inline content delimeted by
+  double newlines (not block elements) are paragraphed.
+- Buggy treatment of end tags of elements that have required attributes
+  fixed (does not manifest on default tag-set)
+- Spurious internal content reorganization error suppressed
+- HTMLDefinition->addElement now returns a reference to the created
+  element object, as implied by the documentation
+- Phorum mod's HTML Purifier help message expanded (unreleased elsewhere)
+- Fix a theoretical class of infinite loops from DirectLex reported
+  by Nate Abele
+- Work around unnecessary DOMElement type-cast in PH5P that caused errors
+  in PHP 5.1
+- Work around PHP 4 SimpleTest lack-of-error complaining for one-time-only
+  HTMLDefinition errors, this may indicate problems with error-collecting
+  facilities in PHP 5
+- Make ErrorCollectorEMock work in both PHP 4 and PHP 5
+- Make PH5P work with PHP 5.0 by removing unnecessary array parameter typedef
+. %Core.AcceptFullDocuments renamed to %Core.ConvertDocumentToFragment
+  to better communicate its purpose
+. Error unit tests can now specify the expectation of no errors. Future
+  iterations of the harness will be extremely strict about what errors
+  are allowed
+. Extend Injector hooks to allow for more powerful injector routines
+. HTMLDefinition->addBlankElement created, as according to the HTMLModule
+  method
+. Doxygen configuration file updated, with minor improvements
+. Test runner now checks for similarly named files in conf/ directory too.
+. Minor cosmetic change to flush-definition-cache.php: trailing newline is
+  outputted
+. Maintenance script for generating PH5P patch added, original PH5P source
+  file also added under version control
+. Full unit test runner script title made more descriptive with PHP version
+. Updated INSTALL file to state that 4.3.7 is the earliest version we
+  are actively testing
+
+2.1.2, released 2007-09-03
+! Implemented Object module for trusted users
+! Implemented experimental HTML5 parsing mode using PH5P. To use, add
+  this to your code:
+        require_once 'HTMLPurifier/Lexer/PH5P.php';
+        $config->set('Core', 'LexerImpl', 'PH5P');
+  Note that this Lexer introduces some classes not in the HTMLPurifier
+  namespace.  Also, this is PHP5 only.
+! CSS property border-spacing implemented
+- Fix non-visible parsing error in DirectLex with empty tags that have
+  slashes inside attribute values.
+- Fix typo in CSS definition: border-collapse:seperate; was incorrectly
+  accepted as valid CSS. Usually non-visible, because this styling is the
+  default for tables in most browsers. Thanks Brett Zamir for pointing
+  this out.
+- Fix validation errors in configuration form
+- Hammer out a bunch of edge-case bugs in the standalone distribution
+- Inclusion reflection removed from URISchemeRegistry; you must manually
+  include any new schema files you wish to use
+- Numerous typo fixes in documentation thanks to Brett Zamir
+. Unit test refactoring for one logical test per test function
+. Config and context parameters in ComplexHarness deprecated: instead, edit
+  the $config and $context member variables
+. HTML wrapper in DOMLex now takes DTD identifiers into account; doesn't
+  really make a difference, but is good for completeness sake
+. merge-library.php script refactored for greater code reusability and
+  PHP4 compatibility
+
+2.1.1, released 2007-08-04
+- Fix show-stopper bug in %URI.MakeAbsolute functionality
+- Fix PHP4 syntax error in standalone version
+. Add prefix directory to include path for standalone, this prevents
+  other installations from clobbering the standalone's URI schemes
+. Single test methods can be invoked by prefixing with __only
+
+2.1.0, released 2007-08-02
+# flush-htmldefinition-cache.php superseded in favor of a generic
+  flush-definition-cache.php script, you can clear a specific cache
+  by passing its name as a parameter to the script
+! Phorum mod implemented for HTML Purifier
+! With %Core.AggressivelyFixLt, <3 and similar emoticons no longer
+  trigger HTML removal in PHP5 (DOMLex). This directive is not necessary
+  for PHP4 (DirectLex).
+! Standalone file now available, which greatly reduces the amount of
+  includes (although there are still a few files that reside in the
+  standalone folder)
+! Relative URIs can now be transformed into their absolute equivalents
+  using %URI.Base and %URI.MakeAbsolute
+! Ruby implemented for XHTML 1.1
+! You can now define custom URI filtering behavior, see enduser-uri-filter.html
+  for more details
+! UTF-8 font names now supported in CSS
+- AutoFormatters emit friendly error messages if tags or attributes they
+  need are not allowed
+- ConfigForm's compactification of directive names is now configurable
+- AutoParagraph autoformatter algorithm refined after field-testing
+- XHTML 1.1 now applies XHTML 1.0 Strict cleanup routines, namely
+  blockquote wrapping
+- Contents of <style> tags removed by default when tags are removed
+. HTMLPurifier_Config->getSerial() implemented, this is extremely useful
+  for output cache invalidation
+. ConfigForm printer now can retrieve CSS and JS files as strings, in
+  case HTML Purifier's directory is not publically accessible
+. Introduce new text/itext configuration directive values: these represent
+  longer strings that would be more appropriately edited with a textarea
+. Allow newlines to act as separators for lists, hashes, lookups and
+  %HTML.Allowed
+. ConfigForm generates textareas instead of text inputs for lists, hashes,
+  lookups, text and itext fields
+. Hidden element content removal genericized: %Core.HiddenElements can
+  be used to customize this behavior, by default <script> and <style> are
+  hidden
+. Added HTMLPURIFIER_PREFIX constant, should be used instead of dirname(__FILE__)
+. Custom ChildDef added to default include list
+. URIScheme reflection improved: will not attempt to include file if class
+  already exists. May clobber autoload, so I need to keep an eye on it
+. ConfigSchema heavily optimized, will only collect information and validate
+  definitions when HTMLPURIFIER_SCHEMA_STRICT is true.
+. AttrDef_URI unit tests and implementation refactored
+. benchmarks/ directory now protected from public view with .htaccess file;
+  run the tests via command line
+. URI scheme is munged off if there is no authority and the scheme is the
+  default one
+. All unit tests inherit from HTMLPurifier_Harness, not UnitTestCase
+. Interface for URIScheme changed
+. Generic URI object to hold components of URI added, most systems involved
+  in URI validation have been migrated to use it
+. Custom filtering for URIs factored out to URIDefinition interface for
+  maximum extensibility
+
+2.0.1, released 2007-06-27
+! Tag auto-closing now based on a ChildDef heuristic rather than a
+  manually set auto_close array; some behavior may change
+! Experimental AutoFormat functionality added: auto-paragraph and
+  linkify your HTML input by setting %AutoFormat.AutoParagraph and
+  %AutoFormat.Linkify to true
+! Newlines normalized internally, and then converted back to the
+  value of PHP_EOL. If this is not desired, set your newline format
+  using %Output.Newline.
+! Beta error collection, messages are implemented for the most generic
+  cases involving Lexing or Strategies
+- Clean up special case code for <script> tags
+- Reorder includes for DefinitionCache decorators, fixes a possible
+  missing class error
+- Fixed bug where manually modified definitions were not saved via cache
+  (mostly harmless, except for the fact that it would be a little slower)
+- Configuration objects with different serials do not clobber each
+  others when revision numbers are unequal
+- Improve Serializer DefinitionCache directory permissions checks
+- DefinitionCache no longer throws errors when it encounters old
+  serial files that do not conform to the current style
+- Stray xmlns attributes removed from configuration documentation
+- configForm.php smoketest no longer has XSS vulnerability due to
+  unescaped print_r output
+- Printer adheres to configuration's directives on output format
+- Fix improperly named form field in ConfigForm printer
+. Rewire some test-cases to swallow errors rather than expect them
+. HTMLDefinition printer updated with some of the new attributes
+. DefinitionCache keys reordered to reflect precedence: version number,
+  hash, then revision number
+. %Core.DefinitionCache renamed to %Cache.DefinitionImpl
+. Interlinking in configuration documentation added using
+  Injector_PurifierLinkify
+. Directives now keep track of aliases to themselves
+. Error collector now requires a severity to be passed, use PHP's internal
+  error constants for this
+. HTMLPurifier_Config::getAllowedDirectivesForForm implemented, allows
+  much easier selective embedding of configuration values
+. Doctype objects now accept public and system DTD identifiers
+. %HTML.Doctype is now constrained by specific values, to specify a custom
+  doctype use new %HTML.CustomDoctype
+. ConfigForm truncates long directives to keep the form small, and does
+  not re-output namespaces
+
+2.0.0, released 2007-06-20
+# Completely refactored HTMLModuleManager, decentralizing safety
+  information
+# Transform modules changed to Tidy modules, which offer more flexibility
+  and better modularization
+# Configuration object now finalizes itself when a read operation is
+  performed on it, ensuring that its internal state stays consistent.
+  To revert this behavior, you can set the $autoFinalize member variable
+  off, but it's not recommended.
+# New compact syntax for AttrDef objects that can be used to instantiate
+  new objects via make()
+# Definitions (esp. HTMLDefinition) are now cached for a significant
+  performance boost. You can disable caching by setting %Core.DefinitionCache
+  to null. You CANNOT edit raw definitions without setting the corresponding
+  DefinitionID directive (%HTML.DefinitionID for HTMLDefinition).
+# Contents between <script> tags are now completely removed if <script>
+  is not allowed
+# Prototype-declarations for Lexer removed in favor of configuration
+  determination of Lexer implementations.
+! HTML Purifier now works in PHP 4.3.2.
+! Configuration form-editing API makes tweaking HTMLPurifier_Config a
+  breeze!
+! Configuration directives that accept hashes now allow new string
+  format: key1:value1,key2:value2
+! ConfigDoc now factored into OOP design
+! All deprecated elements now natively supported
+! Implement TinyMCE styled whitelist specification format in
+  %HTML.Allowed
+! Config object gives more friendly error messages when things go wrong
+! Advanced API implemented: easy functions for creating elements (addElement)
+  and attributes (addAttribute) on HTMLDefinition
+! Add native support for required attributes
+- Deprecated and removed EnableRedundantUTF8Cleaning. It didn't even work!
+- DOMLex will not emit errors when a custom error handler that does not
+  honor error_reporting is used
+- StrictBlockquote child definition refrains from wrapping whitespace
+  in tags now.
+- Bug resulting from tag transforms to non-allowed elements fixed
+- ChildDef_Custom's regex generation has been improved, removing several
+  false positives
+. Unit test for ElementDef created, ElementDef behavior modified to
+  be more flexible
+. Added convenience functions for HTMLModule constructors
+. AttrTypes now has accessor functions that should be used instead
+  of directly manipulating info
+. TagTransform_Center deprecated in favor of generic TagTransform_Simple
+. Add extra protection in AttrDef_URI against phantom Schemes
+. Doctype object added to HTMLDefinition which describes certain aspects
+  of the operational document type
+. Lexer is now pre-emptively included, with a conditional include for the
+  PHP5 only version.
+. HTMLDefinition and CSSDefinition have a common parent class: Definition.
+. DirectLex can now track line-numbers
+. Preliminary error collector is in place, although no code actually reports
+  errors yet
+. Factor out most of ValidateAttributes to new AttrValidator class
+
+1.6.1, released 2007-05-05
+! Support for more deprecated attributes via transformations:
+  + hspace and vspace in img
+  + size and noshade in hr
+  + nowrap in td
+  + clear in br
+  + align in caption, table, img and hr
+  + type in ul, ol and li
+! DirectLex now preserves text in which a < bracket is followed by
+  a non-alphanumeric character. This means that certain emoticons
+  are now preserved.
+! %Core.RemoveInvalidImg is now operational, when set to false invalid
+  images will hang around with an empty src
+! target attribute in a tag supported, use %Attr.AllowedFrameTargets
+  to enable
+! CSS property white-space now allows nowrap (supported in all modern
+  browsers) but not others (which have spotty browser implementations)
+! XHTML 1.1 mode now sort-of works without any fatal errors, and
+  lang is now moved over to xml:lang.
+! Attribute transformation smoketest available at smoketests/attrTransform.php
+! Transformation of font's size attribute now handles super-large numbers
+- Possibly fatal bug with __autoload() fixed in module manager
+- Invert HTMLModuleManager->addModule() processing order to check
+  prefixes first and then the literal module
+- Empty strings get converted to empty arrays instead of arrays with
+  an empty string in them.
+- Merging in attribute lists now works.
+. Demo script removed: it has been added to the website's repository
+. Basic.php script modified to work out of the box
+. Refactor AttrTransform classes to reduce duplication
+. AttrTransform_TextAlign axed in favor of a more general
+  AttrTransform_EnumToCSS, refer to HTMLModule/TransformToStrict.php to
+  see how the new equivalent is implemented
+. Unit tests now use exclusively assertIdentical
+
+1.6.0, released 2007-04-01
+! Support for most common deprecated attributes via transformations:
+  + bgcolor in td, th, tr and table
+  + border in img
+  + name in a and img
+  + width in td, th and hr
+  + height in td, th
+! Support for CSS attribute 'height' added
+! Support for rel and rev attributes in a tags added, use %Attr.AllowedRel
+  and %Attr.AllowedRev to activate
+- You can define ID blacklists using regular expressions via
+  %Attr.IDBlacklistRegexp
+- Error messages are emitted when you attempt to "allow" elements or
+  attributes that HTML Purifier does not support
+- Fix segfault in unit test. The problem is not very reproduceable and
+  I don't know what causes it, but a six line patch fixed it.
+
+1.5.0, released 2007-03-23
+! Added a rudimentary I18N and L10N system modeled off MediaWiki. It
+  doesn't actually do anything yet, but keep your eyes peeled.
+! docs/enduser-utf8.html explains how to use UTF-8 and HTML Purifier
+! Newly structured HTMLDefinition modeled off of XHTML 1.1 modules.
+  I am loathe to release beta quality APIs, but this is exactly that;
+  don't use the internal interfaces if you're not willing to do migration
+  later on.
+- Allow 'x' subtag in language codes
+- Fixed buggy chameleon-support for ins and del
+. Added support for IDREF attributes (i.e. for)
+. Renamed HTMLPurifier_AttrDef_Class to HTMLPurifier_AttrDef_Nmtokens
+. Removed context variable ParentType, replaced with IsInline, which
+  is false when you're not inline and an integer of the parent that
+  caused you to become inline when you are (so possibly zero)
+. Removed ElementDef->type in favor of ElementDef->descendants_are_inline
+  and HTMLDefinition->content_sets
+. StrictBlockquote now reports what elements its supposed to allow,
+  rather than what it does allow
+. Removed HTMLDefinition->info_flow_elements in favor of
+  HTMLDefinition->content_sets['Flow']
+. Removed redundant "exclusionary" definitions from DTD roster
+. StrictBlockquote now requires a construction parameter as if it
+  were an Required ChildDef, this is the "real" set of allowed elements
+. AttrDef partitioned into HTML, CSS and URI segments
+. Modify Youtube filter regexp to be multiline
+. Require both PHP5 and DOM extension in order to use DOMLex, fixes
+  some edge cases where a DOMDocument class exists in a PHP4 environment
+  due to DOM XML extension.
+
+1.4.1, released 2007-01-21
+! docs/enduser-youtube.html updated according to new functionality
+- YouTube IDs can have underscores and dashes
+
+1.4.0, released 2007-01-21
+! Implemented list-style-image, URIs now allowed in list-style
+! Implemented background-image, background-repeat, background-attachment
+  and background-position CSS properties. Shorthand property background
+  supports all of these properties.
+! Configuration documentation looks nicer
+! Added %Core.EscapeNonASCIICharacters to workaround loss of Unicode
+  characters while %Core.Encoding is set to a non-UTF-8 encoding.
+! Support for configuration directive aliases added
+! Config object can now be instantiated from ini files
+! YouTube preservation code added to the core, with two lines of code
+  you can add it as a filter to your code. See smoketests/preserveYouTube.php
+  for sample code.
+! Moved SLOW to docs/enduser-slow.html and added code examples
+- Replaced version check with functionality check for DOM (thanks Stephen
+  Khoo)
+. Added smoketest 'all.php', which loads all other smoketests via frames
+. Implemented AttrDef_CSSURI for url(http://google.com) style declarations
+. Added convenient single test selector form on test runner
+
+1.3.2, released 2006-12-25
+! HTMLPurifier object now accepts configuration arrays, no need to manually
+  instantiate a configuration object
+! Context object now accessible to outside
+! Added enduser-youtube.html, explains how to embed YouTube videos. See
+  also corresponding smoketest preserveYouTube.php.
+! Added purifyArray(), which takes a list of HTML and purifies it all
+! Added static member variable $version to HTML Purifier with PHP-compatible
+  version number string.
+- Fixed fatal error thrown by upper-cased language attributes
+- printDefinition.php: added labels, added better clarification
+. HTMLPurifier_Config::create() added, takes mixed variable and converts into
+  a HTMLPurifier_Config object.
+
+1.3.1, released 2006-12-06
+! Added HTMLPurifier.func.php stub for a convenient function to call the library
+- Fixed bug in RemoveInvalidImg code that caused all images to be dropped
+  (thanks to .mario for reporting this)
+. Standardized all attribute handling variables to attr, made it plural
+
+1.3.0, released 2006-11-26
+# Invalid images are now removed, rather than replaced with a dud
+  <img src="" alt="Invalid image" />. Previous behavior can be restored
+  with new directive %Core.RemoveInvalidImg set to false.
+! (X)HTML Strict now supported
+  + Transparently handles inline elements in block context (blockquote)
+! Added GET method to demo for easier validation, added 50kb max input size
+! New directive %HTML.BlockWrapper, for block-ifying inline elements
+! New directive %HTML.Parent, allows you to only allow inline content
+! New directives %HTML.AllowedElements and %HTML.AllowedAttributes to let
+  users narrow the set of allowed tags
+! <li value="4"> and <ul start="2"> now allowed in loose mode
+! New directives %URI.DisableExternalResources and %URI.DisableResources
+! New directive %Attr.DisableURI, which eliminates all hyperlinking
+! New directive %URI.Munge, munges URI so you can use some sort of redirector
+  service to avoid PageRank leaks or warn users that they are exiting your site.
+! Added spiffy new smoketest printDefinition.php, which lets you twiddle with
+  the configuration settings and see how the internal rules are affected.
+! New directive %URI.HostBlacklist for blocking links to bad hosts.
+  xssAttacks.php smoketest updated accordingly.
+- Added missing type to ChildDef_Chameleon
+- Remove Tidy option from demo if there is not Tidy available
+. ChildDef_Required guards against empty tags
+. Lookup table HTMLDefinition->info_flow_elements added
+. Added peace-of-mind variable initialization to Strategy_FixNesting
+. Added HTMLPurifier->info_parent_def, parent child processing made special
+. Added internal documents briefly summarizing future progression of HTML
+. HTMLPurifier_Config->getBatch($namespace) added
+. More lenient casting to bool from string in HTMLPurifier_ConfigSchema
+. Refactored ChildDef classes into their own files
+
+1.2.0, released 2006-11-19
+# ID attributes now disabled by default. New directives:
+  + %HTML.EnableAttrID - restores old behavior by allowing IDs
+  + %Attr.IDPrefix - %Attr.IDBlacklist alternative that munges all user IDs
+    so that they don't collide with your IDs
+  + %Attr.IDPrefixLocal - Same as above, but for when there are multiple
+    instances of user content on the page
+  + Profuse documentation on how to use these available in docs/enduser-id.txt
+! Added MODx plugin <http://modxcms.com/forums/index.php/topic,6604.0.html>
+! Added percent encoding normalization
+! XSS attacks smoketest given facelift
+! Configuration documentation now has table of contents
+! Added %URI.DisableExternal, which prevents links to external websites.  You
+  can also use %URI.Host to permit absolute linking to subdomains
+! Non-accessible resources (ex. mailto) blocked from embedded URIs (img src)
+- Type variable in HTMLDefinition was not being set properly, fixed
+- Documentation updated
+  + TODO added request Phalanger
+  + TODO added request Native compression
+  + TODO added request Remove redundant tags
+  + TODO added possible plaintext formatter for HTML Purifier documentation
+  + Updated ConfigDoc TODO
+  + Improved inline comments in AttrDef/Class.php, AttrDef/CSS.php
+    and AttrDef/Host.php
+  + Revamped documentation into HTML, along with misc updates
+- HTMLPurifier_Context doesn't throw a variable reference error if you attempt
+  to retrieve a non-existent variable
+. Switched to purify()-wide Context object registry
+. Refactored unit tests to minimize duplication
+. XSS attack sheet updated
+. configdoc.xml now has xml:space attached to default value nodes
+. Allow configuration directives to permit null values
+. Cleaned up test-cases to remove unnecessary swallowErrors()
+
+1.1.2, released 2006-09-30
+! Add HTMLPurifier.auto.php stub file that configures include_path
+- Documentation updated
+  + INSTALL document rewritten
+  + TODO added semi-lossy conversion
+  + API Doxygen docs' file exclusions updated
+  + Added notes on HTML versus XML attribute whitespace handling
+  + Noted that HTMLPurifier_ChildDef_Custom isn't being used
+  + Noted that config object's definitions are cached versions
+- Fixed lack of attribute parsing in HTMLPurifier_Lexer_PEARSax3
+- ftp:// URIs now have their typecodes checked
+- Hooked up HTMLPurifier_ChildDef_Custom's unit tests (they weren't being run)
+. Line endings standardized throughout project (svn:eol-style standardized)
+. Refactored parseData() to general Lexer class
+. Tester named "HTML Purifier" not "HTMLPurifier"
+
+1.1.1, released 2006-09-24
+! Configuration option to optionally Tidy up output for indentation to make up
+  for dropped whitespace by DOMLex (pretty-printing for the entire application
+  should be done by a page-wide Tidy)
+- Various documentation updates
+- Fixed parse error in configuration documentation script
+- Fixed fatal error in benchmark scripts, slightly augmented
+- As far as possible, whitespace is preserved in-between table children
+- Sample test-settings.php file included
+
+1.1.0, released 2006-09-16
+! Directive documentation generation using XSLT
+! XHTML can now be turned off, output becomes <br>
+- Made URI validator more forgiving: will ignore leading and trailing
+  quotes, apostrophes and less than or greater than signs.
+- Enforce alphanumeric namespace and directive names for configuration.
+- Table child definition made more flexible, will fix up poorly ordered elements
+. Renamed ConfigDef to ConfigSchema
+
+1.0.1, released 2006-09-04
+- Fixed slight bug in DOMLex attribute parsing
+- Fixed rejection of case-insensitive configuration values when there is a
+  set of allowed values.  This manifested in %Core.Encoding.
+- Fixed rejection of inline style declarations that had lots of extra
+  space in them.  This manifested in TinyMCE.
+
+1.0.0, released 2006-09-01
+! Shorthand CSS properties implemented: font, border, background, list-style
+! Basic color keywords translated into hexadecimal values
+! Table CSS properties implemented
+! Support for charsets other than UTF-8 (defined by iconv)
+! Malformed UTF-8 and non-SGML character detection and cleaning implemented
+- Fixed broken numeric entity conversion
+- API documentation completed
+. (HTML|CSS)Definition de-singleton-ized
+
+1.0.0beta, released 2006-08-16
+! First public release, most functionality implemented. Notable omissions are:
+  + Shorthand CSS properties
+  + Table CSS properties
+  + Deprecated attribute transformations
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/README b/library/ezyang/htmlpurifier/README
new file mode 100644
index 0000000000..53f26f1c28
--- /dev/null
+++ b/library/ezyang/htmlpurifier/README
@@ -0,0 +1,24 @@
+
+README
+    All about HTML Purifier
+
+HTML Purifier is an HTML filtering solution that uses a unique combination
+of robust whitelists and agressive parsing to ensure that not only are
+XSS attacks thwarted, but the resulting HTML is standards compliant.
+
+HTML Purifier is oriented towards richly formatted documents from
+untrusted sources that require CSS and a full tag-set.  This library can
+be configured to accept a more restrictive set of tags, but it won't be
+as efficient as more bare-bones parsers. It will, however, do the job
+right, which may be more important.
+
+Places to go:
+
+* See INSTALL for a quick installation guide
+* See docs/ for developer-oriented documentation, code examples and
+  an in-depth installation guide.
+* See WYSIWYG for information on editors like TinyMCE and FCKeditor
+
+HTML Purifier can be found on the web at: http://htmlpurifier.org/
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/TODO b/library/ezyang/htmlpurifier/TODO
new file mode 100644
index 0000000000..a92abf2802
--- /dev/null
+++ b/library/ezyang/htmlpurifier/TODO
@@ -0,0 +1,150 @@
+
+TODO List
+
+= KEY ====================
+    # Flagship
+    - Regular
+    ? Maybe I'll Do It
+==========================
+
+If no interest is expressed for a feature that may require a considerable
+amount of effort to implement, it may get endlessly delayed. Do not be
+afraid to cast your vote for the next feature to be implemented!
+
+Things to do as soon as possible:
+
+ - http://htmlpurifier.org/phorum/read.php?3,5560,6307#msg-6307
+ - Think about allowing explicit order of operations hooks for transforms
+ - Fix "<.<" bug (trailing < is removed if not EOD)
+ - Build in better internal state dumps and debugging tools for remote
+   debugging
+ - Allowed/Allowed* have strange interactions when both set
+ ? Transform lone embeds into object tags
+ - Deprecated config options that emit warnings when you set them (with'
+   a way of muting the warning if you really want to)
+ - Make HTML.Trusted work with Output.FlashCompat
+ - HTML.Trusted and HTML.SafeObject have funny interaction; general
+   problem is what to do when a module "supersedes" another
+   (see also tables and basic tables.)  This is a little dicier
+   because HTML.SafeObject has some extra functionality that
+   trusted might find useful.  See http://htmlpurifier.org/phorum/read.php?3,5762,6100
+
+FUTURE VERSIONS
+---------------
+
+4.8 release [OMG CONFIG PONIES]
+ ! Fix Printer. It's from the old days when we didn't have decent XML classes
+ ! Factor demo.php into a set of Printer classes, and then create a stub
+   file for users here (inside the actual HTML Purifier library)
+ - Fix error handling with form construction
+ - Do encoding validation in Printers, or at least, where user data comes in
+ - Config: Add examples to everything (make built-in which also automatically
+   gives output)
+ - Add "register" field to config schemas to eliminate dependence on
+   naming conventions (try to remember why we ultimately decided on tihs)
+
+5.0 release [HTML 5]
+ # Swap out code to use html5lib tokenizer and tree-builder
+ ! Allow turning off of FixNesting and required attribute insertion
+
+5.1 release [It's All About Trust] (floating)
+ # Implement untrusted, dangerous elements/attributes
+ # Implement IDREF support (harder than it seems, since you cannot have
+   IDREFs to non-existent IDs)
+     - Implement <area> (client and server side image maps are blocking
+       on IDREF support)
+ # Frameset XHTML 1.0 and HTML 4.01 doctypes
+ - Figure out how to simultaneously set %CSS.Trusted and %HTML.Trusted (?)
+
+5.2 release [Error'ed]
+ # Error logging for filtering/cleanup procedures
+ # Additional support for poorly written HTML
+    - Microsoft Word HTML cleaning (i.e. MsoNormal, but research essential!)
+    - Friendly strict handling of <address> (block -> <br>)
+ - XSS-attempt detection--certain errors are flagged XSS-like
+ - Append something to duplicate IDs so they're still usable (impl. note: the
+   dupe detector would also need to detect the suffix as well)
+
+6.0 release [Beyond HTML]
+ # Legit token based CSS parsing (will require revamping almost every
+   AttrDef class). Probably will use CSSTidy
+ # More control over allowed CSS properties using a modularization
+ # IRI support (this includes IDN)
+ - Standardize token armor for all areas of processing
+
+7.0 release [To XML and Beyond]
+ - Extended HTML capabilities based on namespacing and tag transforms (COMPLEX)
+    - Hooks for adding custom processors to custom namespaced tags and
+      attributes, offer default implementation
+    - Lots of documentation and samples
+
+Ongoing
+ - More refactoring to take advantage of PHP5's facilities
+ - Refactor unit tests into lots of test methods
+ - Plugins for major CMSes (COMPLEX)
+    - phpBB
+    - Also, a FAQ for extension writers with HTML Purifier
+
+AutoFormat
+ - Smileys
+ - Syntax highlighting (with GeSHi) with <pre> and possibly <?php
+ - Look at http://drupal.org/project/Modules/category/63 for ideas
+
+Neat feature related
+ ! Support exporting configuration, so users can easily tweak settings
+   in the demo, and then copy-paste into their own setup
+ - Advanced URI filtering schemes (see docs/proposal-new-directives.txt)
+ - Allow scoped="scoped" attribute in <style> tags; may be troublesome
+   because regular CSS has no way of uniquely identifying nodes, so we'd
+   have to generate IDs
+ - Explain how to use HTML Purifier in non-PHP languages / create
+   a simple command line stub (or complicated?)
+ - Fixes for Firefox's inability to handle COL alignment props (Bug 915)
+ - Automatically add non-breaking spaces to empty table cells when
+   empty-cells:show is applied to have compatibility with Internet Explorer
+ - Table of Contents generation (XHTML Compiler might be reusable). May also
+   be out-of-band information.
+ - Full set of color keywords. Also, a way to add onto them without
+   finalizing the configuration object.
+ - Write a var_export and memcached DefinitionCache - Denis
+ - Built-in support for target="_blank" on all external links
+ - Convert RTL/LTR override characters to <bdo> tags, or vice versa on demand.
+   Also, enable disabling of directionality
+ ? Externalize inline CSS to promote clean HTML, proposed by Sander Tekelenburg
+ ? Remove redundant tags, ex. <u><u>Underlined</u></u>. Implementation notes:
+    1. Analyzing which tags to remove duplicants
+    2. Ensure attributes are merged into the parent tag
+    3. Extend the tag exclusion system to specify whether or not the
+    contents should be dropped or not (currently, there's code that could do
+    something like this if it didn't drop the inner text too.)
+ ? Make AutoParagraph also support paragraph-izing double <br> tags, and not
+   just double newlines.  This is kind of tough to do in the current framework,
+   though, and might be reasonably approximated by search replacing double <br>s
+   with newlines before running it through HTML Purifier.
+
+Maintenance related (slightly boring)
+ # CHMOD install script for PEAR installs
+ ! Factor out command line parser into its own class, and unit test it
+ - Reduce size of internal data-structures (esp. HTMLDefinition)
+ - Allow merging configurations.  Thus,
+        a -> b -> default
+        c -> d -> default
+   becomes
+        a -> b -> c -> d -> default
+   Maybe allow more fine-grained tuning of this behavior. Alternatively,
+   encourage people to use short plist depths before building them up.
+ - Time PHPT tests
+
+ChildDef related (very boring)
+ - Abstract ChildDef_BlockQuote to work with all elements that only
+   allow blocks in them, required or optional
+ - Implement lenient <ruby> child validation
+
+Wontfix
+ - Non-lossy smart alternate character encoding transformations (unless
+   patch provided)
+ - Pretty-printing HTML: users can use Tidy on the output on entire page
+ - Native content compression, whitespace stripping: use gzip if this is
+   really important
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/VERSION b/library/ezyang/htmlpurifier/VERSION
new file mode 100644
index 0000000000..1163055e28
--- /dev/null
+++ b/library/ezyang/htmlpurifier/VERSION
@@ -0,0 +1 @@
+4.7.0
\ No newline at end of file
diff --git a/library/ezyang/htmlpurifier/WHATSNEW b/library/ezyang/htmlpurifier/WHATSNEW
new file mode 100644
index 0000000000..4e5eb2b691
--- /dev/null
+++ b/library/ezyang/htmlpurifier/WHATSNEW
@@ -0,0 +1,4 @@
+HTML Purifier 4.7.0 is a bugfix release, collecting two years
+worth of accumulated bug fixes.  Highlighted bugfixes are updated
+YouTube filter code, corrected rgb() CSS parsing, and one new
+configuration option, %AutoFormat.RemoveEmpty.Predicate.
diff --git a/library/ezyang/htmlpurifier/WYSIWYG b/library/ezyang/htmlpurifier/WYSIWYG
new file mode 100644
index 0000000000..c518aacdd9
--- /dev/null
+++ b/library/ezyang/htmlpurifier/WYSIWYG
@@ -0,0 +1,20 @@
+
+WYSIWYG - What You See Is What You Get
+    HTML Purifier: A Pretty Good Fit for TinyMCE and FCKeditor
+
+Javascript-based WYSIWYG editors, simply stated, are quite amazing.  But I've
+always been wary about using them due to security issues: they handle the
+client-side magic, but once you've been served a piping hot load of unfiltered
+HTML, what should be done then?  In some situations, you can serve it uncleaned,
+since you only offer these facilities to trusted(?) authors.
+
+Unfortunantely, for blog comments and anonymous input, BBCode, Textile and
+other markup languages still reign supreme.  Put simply: filtering HTML is
+hard work, and these WYSIWYG authors don't offer anything to alleviate that
+trouble.  Therein lies the solution:
+
+HTML Purifier is perfect for filtering pure-HTML input from WYSIWYG editors.
+
+Enough said.
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/composer.json b/library/ezyang/htmlpurifier/composer.json
new file mode 100644
index 0000000000..2f59d0fede
--- /dev/null
+++ b/library/ezyang/htmlpurifier/composer.json
@@ -0,0 +1,22 @@
+{
+    "name": "ezyang/htmlpurifier",
+    "description": "Standards compliant HTML filter written in PHP",
+    "type": "library",
+    "keywords": ["html"],
+    "homepage": "http://htmlpurifier.org/",
+    "license": "LGPL",
+    "authors": [
+        {
+            "name": "Edward Z. Yang",
+            "email": "admin@htmlpurifier.org",
+            "homepage": "http://ezyang.com"
+        }
+    ],
+    "require": {
+        "php": ">=5.2"
+    },
+    "autoload": {
+        "psr-0": { "HTMLPurifier": "library/" },
+        "files": ["library/HTMLPurifier.composer.php"]
+    }
+}
diff --git a/library/ezyang/htmlpurifier/extras/ConfigDoc/HTMLXSLTProcessor.php b/library/ezyang/htmlpurifier/extras/ConfigDoc/HTMLXSLTProcessor.php
new file mode 100644
index 0000000000..1cfec5d762
--- /dev/null
+++ b/library/ezyang/htmlpurifier/extras/ConfigDoc/HTMLXSLTProcessor.php
@@ -0,0 +1,91 @@
+<?php
+
+/**
+ * Decorator/extender XSLT processor specifically for HTML documents.
+ */
+class ConfigDoc_HTMLXSLTProcessor
+{
+
+    /**
+     * Instance of XSLTProcessor
+     */
+    protected $xsltProcessor;
+
+    public function __construct($proc = false)
+    {
+        if ($proc === false) $proc = new XSLTProcessor();
+        $this->xsltProcessor = $proc;
+    }
+
+    /**
+     * @note Allows a string $xsl filename to be passed
+     */
+    public function importStylesheet($xsl)
+    {
+        if (is_string($xsl)) {
+            $xsl_file = $xsl;
+            $xsl = new DOMDocument();
+            $xsl->load($xsl_file);
+        }
+        return $this->xsltProcessor->importStylesheet($xsl);
+    }
+
+    /**
+     * Transforms an XML file into compatible XHTML based on the stylesheet
+     * @param $xml XML DOM tree, or string filename
+     * @return string HTML output
+     * @todo Rename to transformToXHTML, as transformToHTML is misleading
+     */
+    public function transformToHTML($xml)
+    {
+        if (is_string($xml)) {
+            $dom = new DOMDocument();
+            $dom->load($xml);
+        } else {
+            $dom = $xml;
+        }
+        $out = $this->xsltProcessor->transformToXML($dom);
+
+        // fudges for HTML backwards compatibility
+        // assumes that document is XHTML
+        $out = str_replace('/>', ' />', $out); // <br /> not <br/>
+        $out = str_replace(' xmlns=""', '', $out); // rm unnecessary xmlns
+
+        if (class_exists('Tidy')) {
+            // cleanup output
+            $config = array(
+                'indent'        => true,
+                'output-xhtml'  => true,
+                'wrap'          => 80
+            );
+            $tidy = new Tidy;
+            $tidy->parseString($out, $config, 'utf8');
+            $tidy->cleanRepair();
+            $out = (string) $tidy;
+        }
+
+        return $out;
+    }
+
+    /**
+     * Bulk sets parameters for the XSL stylesheet
+     * @param array $options Associative array of options to set
+     */
+    public function setParameters($options)
+    {
+        foreach ($options as $name => $value) {
+            $this->xsltProcessor->setParameter('', $name, $value);
+        }
+    }
+
+    /**
+     * Forward any other calls to the XSLT processor
+     */
+    public function __call($name, $arguments)
+    {
+        call_user_func_array(array($this->xsltProcessor, $name), $arguments);
+    }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/extras/FSTools.php b/library/ezyang/htmlpurifier/extras/FSTools.php
new file mode 100644
index 0000000000..ce00763166
--- /dev/null
+++ b/library/ezyang/htmlpurifier/extras/FSTools.php
@@ -0,0 +1,164 @@
+<?php
+
+/**
+ * Filesystem tools not provided by default; can recursively create, copy
+ * and delete folders. Some template methods are provided for extensibility.
+ *
+ * @note This class must be instantiated to be used, although it does
+ *       not maintain state.
+ */
+class FSTools
+{
+
+    private static $singleton;
+
+    /**
+     * Returns a global instance of FSTools
+     */
+    public static function singleton()
+    {
+        if (empty(FSTools::$singleton)) FSTools::$singleton = new FSTools();
+        return FSTools::$singleton;
+    }
+
+    /**
+     * Sets our global singleton to something else; useful for overloading
+     * functions.
+     */
+    public static function setSingleton($singleton)
+    {
+        FSTools::$singleton = $singleton;
+    }
+
+    /**
+     * Recursively creates a directory
+     * @param string $folder Name of folder to create
+     * @note Adapted from the PHP manual comment 76612
+     */
+    public function mkdirr($folder)
+    {
+        $folders = preg_split("#[\\\\/]#", $folder);
+        $base = '';
+        for($i = 0, $c = count($folders); $i < $c; $i++) {
+            if(empty($folders[$i])) {
+                if (!$i) {
+                    // special case for root level
+                    $base .= DIRECTORY_SEPARATOR;
+                }
+                continue;
+            }
+            $base .= $folders[$i];
+            if(!is_dir($base)){
+                $this->mkdir($base);
+            }
+            $base .= DIRECTORY_SEPARATOR;
+        }
+    }
+
+    /**
+     * Copy a file, or recursively copy a folder and its contents; modified
+     * so that copied files, if PHP, have includes removed
+     * @note Adapted from http://aidanlister.com/repos/v/function.copyr.php
+     */
+    public function copyr($source, $dest)
+    {
+        // Simple copy for a file
+        if (is_file($source)) {
+            return $this->copy($source, $dest);
+        }
+        // Make destination directory
+        if (!is_dir($dest)) {
+            $this->mkdir($dest);
+        }
+        // Loop through the folder
+        $dir = $this->dir($source);
+        while ( false !== ($entry = $dir->read()) ) {
+            // Skip pointers
+            if ($entry == '.' || $entry == '..') {
+                continue;
+            }
+            if (!$this->copyable($entry)) {
+                continue;
+            }
+            // Deep copy directories
+            if ($dest !== "$source/$entry") {
+                $this->copyr("$source/$entry", "$dest/$entry");
+            }
+        }
+        // Clean up
+        $dir->close();
+        return true;
+    }
+
+    /**
+     * Overloadable function that tests a filename for copyability. By
+     * default, everything should be copied; you can restrict things to
+     * ignore hidden files, unreadable files, etc. This function
+     * applies to copyr().
+     */
+    public function copyable($file)
+    {
+        return true;
+    }
+
+    /**
+     * Delete a file, or a folder and its contents
+     * @note Adapted from http://aidanlister.com/repos/v/function.rmdirr.php
+     */
+    public function rmdirr($dirname)
+    {
+        // Sanity check
+        if (!$this->file_exists($dirname)) {
+            return false;
+        }
+
+        // Simple delete for a file
+        if ($this->is_file($dirname) || $this->is_link($dirname)) {
+            return $this->unlink($dirname);
+        }
+
+        // Loop through the folder
+        $dir = $this->dir($dirname);
+        while (false !== $entry = $dir->read()) {
+            // Skip pointers
+            if ($entry == '.' || $entry == '..') {
+                continue;
+            }
+            // Recurse
+            $this->rmdirr($dirname . DIRECTORY_SEPARATOR . $entry);
+        }
+
+        // Clean up
+        $dir->close();
+        return $this->rmdir($dirname);
+    }
+
+    /**
+     * Recursively globs a directory.
+     */
+    public function globr($dir, $pattern, $flags = NULL)
+    {
+        $files = $this->glob("$dir/$pattern", $flags);
+        if ($files === false) $files = array();
+        $sub_dirs = $this->glob("$dir/*", GLOB_ONLYDIR);
+        if ($sub_dirs === false) $sub_dirs = array();
+        foreach ($sub_dirs as $sub_dir) {
+            $sub_files = $this->globr($sub_dir, $pattern, $flags);
+            $files = array_merge($files, $sub_files);
+        }
+        return $files;
+    }
+
+    /**
+     * Allows for PHP functions to be called and be stubbed.
+     * @warning This function will not work for functions that need
+     *      to pass references; manually define a stub function for those.
+     */
+    public function __call($name, $args)
+    {
+        return call_user_func_array($name, $args);
+    }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/extras/FSTools/File.php b/library/ezyang/htmlpurifier/extras/FSTools/File.php
new file mode 100644
index 0000000000..6453a7a450
--- /dev/null
+++ b/library/ezyang/htmlpurifier/extras/FSTools/File.php
@@ -0,0 +1,141 @@
+<?php
+
+/**
+ * Represents a file in the filesystem
+ *
+ * @warning Be sure to distinguish between get() and write() versus
+ *      read() and put(), the former operates on the entire file, while
+ *      the latter operates on a handle.
+ */
+class FSTools_File
+{
+
+    /** Filename of file this object represents */
+    protected $name;
+
+    /** Handle for the file */
+    protected $handle = false;
+
+    /** Instance of FSTools for interfacing with filesystem */
+    protected $fs;
+
+    /**
+     * Filename of file you wish to instantiate.
+     * @note This file need not exist
+     */
+    public function __construct($name, $fs = false)
+    {
+        $this->name = $name;
+        $this->fs = $fs ? $fs : FSTools::singleton();
+    }
+
+    /** Returns the filename of the file. */
+    public function getName() {return $this->name;}
+
+    /** Returns directory of the file without trailing slash */
+    public function getDirectory() {return $this->fs->dirname($this->name);}
+
+    /**
+     * Retrieves the contents of a file
+     * @todo Throw an exception if file doesn't exist
+     */
+    public function get()
+    {
+        return $this->fs->file_get_contents($this->name);
+    }
+
+    /** Writes contents to a file, creates new file if necessary */
+    public function write($contents)
+    {
+        return $this->fs->file_put_contents($this->name, $contents);
+    }
+
+    /** Deletes the file */
+    public function delete()
+    {
+        return $this->fs->unlink($this->name);
+    }
+
+    /** Returns true if file exists and is a file. */
+    public function exists()
+    {
+        return $this->fs->is_file($this->name);
+    }
+
+    /** Returns last file modification time */
+    public function getMTime()
+    {
+        return $this->fs->filemtime($this->name);
+    }
+
+    /**
+     * Chmod a file
+     * @note We ignore errors because of some weird owner trickery due
+     *       to SVN duality
+     */
+    public function chmod($octal_code)
+    {
+        return @$this->fs->chmod($this->name, $octal_code);
+    }
+
+    /** Opens file's handle */
+    public function open($mode)
+    {
+        if ($this->handle) $this->close();
+        $this->handle = $this->fs->fopen($this->name, $mode);
+        return true;
+    }
+
+    /** Closes file's handle */
+    public function close()
+    {
+        if (!$this->handle) return false;
+        $status = $this->fs->fclose($this->handle);
+        $this->handle = false;
+        return $status;
+    }
+
+    /** Retrieves a line from an open file, with optional max length $length */
+    public function getLine($length = null)
+    {
+        if (!$this->handle) $this->open('r');
+        if ($length === null) return $this->fs->fgets($this->handle);
+        else return $this->fs->fgets($this->handle, $length);
+    }
+
+    /** Retrieves a character from an open file */
+    public function getChar()
+    {
+        if (!$this->handle) $this->open('r');
+        return $this->fs->fgetc($this->handle);
+    }
+
+    /** Retrieves an $length bytes of data from an open data */
+    public function read($length)
+    {
+        if (!$this->handle) $this->open('r');
+        return $this->fs->fread($this->handle, $length);
+    }
+
+    /** Writes to an open file */
+    public function put($string)
+    {
+        if (!$this->handle) $this->open('a');
+        return $this->fs->fwrite($this->handle, $string);
+    }
+
+    /** Returns TRUE if the end of the file has been reached */
+    public function eof()
+    {
+        if (!$this->handle) return true;
+        return $this->fs->feof($this->handle);
+    }
+
+    public function __destruct()
+    {
+        if ($this->handle) $this->close();
+    }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.auto.php b/library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.auto.php
new file mode 100644
index 0000000000..4016d8afd1
--- /dev/null
+++ b/library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.auto.php
@@ -0,0 +1,11 @@
+<?php
+
+/**
+ * This is a stub include that automatically configures the include path.
+ */
+
+set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path() );
+require_once 'HTMLPurifierExtras.php';
+require_once 'HTMLPurifierExtras.autoload.php';
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.autoload.php b/library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.autoload.php
new file mode 100644
index 0000000000..de4a8aaafe
--- /dev/null
+++ b/library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.autoload.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Convenience file that registers autoload handler for HTML Purifier.
+ *
+ * @warning
+ *      This autoloader does not contain the compatibility code seen in
+ *      HTMLPurifier_Bootstrap; the user is expected to make any necessary
+ *      changes to use this library.
+ */
+
+if (function_exists('spl_autoload_register')) {
+    spl_autoload_register(array('HTMLPurifierExtras', 'autoload'));
+    if (function_exists('__autoload')) {
+        // Be polite and ensure that userland autoload gets retained
+        spl_autoload_register('__autoload');
+    }
+} elseif (!function_exists('__autoload')) {
+    function __autoload($class)
+    {
+        return HTMLPurifierExtras::autoload($class);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.php b/library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.php
new file mode 100644
index 0000000000..35c2ca7e72
--- /dev/null
+++ b/library/ezyang/htmlpurifier/extras/HTMLPurifierExtras.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * Meta-class for HTML Purifier's extra class hierarchies, similar to
+ * HTMLPurifier_Bootstrap.
+ */
+class HTMLPurifierExtras
+{
+
+    public static function autoload($class)
+    {
+        $path = HTMLPurifierExtras::getPath($class);
+        if (!$path) return false;
+        require $path;
+        return true;
+    }
+
+    public static function getPath($class)
+    {
+        if (
+            strncmp('FSTools', $class, 7) !== 0 &&
+            strncmp('ConfigDoc', $class, 9) !== 0
+        ) return false;
+        // Custom implementations can go here
+        // Standard implementation:
+        return str_replace('_', '/', $class) . '.php';
+    }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/extras/README b/library/ezyang/htmlpurifier/extras/README
new file mode 100644
index 0000000000..4bfece79ea
--- /dev/null
+++ b/library/ezyang/htmlpurifier/extras/README
@@ -0,0 +1,32 @@
+
+HTML Purifier Extras
+    The Method Behind The Madness!
+
+The extras/ folder in HTML Purifier contains--you guessed it--extra things
+for HTML Purifier.  Specifically, these are two extra libraries called
+FSTools and ConfigSchema.  They're extra for a reason: you don't need them
+if you're using HTML Purifier for normal usage: filtering HTML.  However,
+if you're a developer, and would like to test HTML Purifier, or need to
+use one of HTML Purifier's maintenance scripts, chances are they'll need
+these libraries. Who knows: maybe you'll find them useful too!
+
+Here are the libraries:
+
+
+FSTools
+-------
+
+Short for File System Tools, this is a poor-man's object-oriented wrapper for
+the filesystem. It currently consists of two classes:
+
+- FSTools: This is a singleton that contains a manner of useful functions
+  such as recursive glob, directory removal, etc, as well as the ability
+  to call arbitrary native PHP functions through it like $FS->fopen(...).
+  This makes it a lot simpler to mock these filesystem calls for unit testing.
+
+- FSTools_File: This object represents a single file, and has almost any
+  method imaginable one would need.
+
+Check the files themselves for more information.
+
+    vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier.auto.php b/library/ezyang/htmlpurifier/library/HTMLPurifier.auto.php
similarity index 100%
rename from library/HTMLPurifier.auto.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier.auto.php
diff --git a/library/HTMLPurifier.autoload.php b/library/ezyang/htmlpurifier/library/HTMLPurifier.autoload.php
similarity index 70%
rename from library/HTMLPurifier.autoload.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier.autoload.php
index 8d40176406..c3ea67e814 100644
--- a/library/HTMLPurifier.autoload.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier.autoload.php
@@ -3,6 +3,7 @@
 /**
  * @file
  * Convenience file that registers autoload handler for HTML Purifier.
+ * It also does some sanity checks.
  */
 
 if (function_exists('spl_autoload_register') && function_exists('spl_autoload_unregister')) {
@@ -13,9 +14,14 @@ if (function_exists('spl_autoload_register') && function_exists('spl_autoload_un
         spl_autoload_register('__autoload');
     }
 } elseif (!function_exists('__autoload')) {
-    function __autoload($class) {
+    function __autoload($class)
+    {
         return HTMLPurifier_Bootstrap::autoload($class);
     }
 }
 
+if (ini_get('zend.ze1_compatibility_mode')) {
+    trigger_error("HTML Purifier is not compatible with zend.ze1_compatibility_mode; please turn it off", E_USER_ERROR);
+}
+
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier.composer.php b/library/ezyang/htmlpurifier/library/HTMLPurifier.composer.php
new file mode 100644
index 0000000000..52acc56b0d
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier.composer.php
@@ -0,0 +1,4 @@
+<?php
+if (!defined('HTMLPURIFIER_PREFIX')) {
+    define('HTMLPURIFIER_PREFIX', dirname(__FILE__));
+}
diff --git a/library/HTMLPurifier.func.php b/library/ezyang/htmlpurifier/library/HTMLPurifier.func.php
similarity index 67%
rename from library/HTMLPurifier.func.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier.func.php
index 56a55b2fed..64b140bec2 100644
--- a/library/HTMLPurifier.func.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier.func.php
@@ -8,11 +8,13 @@
 
 /**
  * Purify HTML.
- * @param $html String HTML to purify
- * @param $config Configuration to use, can be any value accepted by
+ * @param string $html String HTML to purify
+ * @param mixed $config Configuration to use, can be any value accepted by
  *        HTMLPurifier_Config::create()
+ * @return string
  */
-function HTMLPurifier($html, $config = null) {
+function HTMLPurifier($html, $config = null)
+{
     static $purifier = false;
     if (!$purifier) {
         $purifier = new HTMLPurifier();
diff --git a/library/HTMLPurifier.includes.php b/library/ezyang/htmlpurifier/library/HTMLPurifier.includes.php
similarity index 91%
rename from library/HTMLPurifier.includes.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier.includes.php
index 2ed0f0c17f..fdb58c2d37 100644
--- a/library/HTMLPurifier.includes.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier.includes.php
@@ -7,7 +7,7 @@
  * primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
  * FILE, changes will be overwritten the next time the script is run.
  *
- * @version 4.1.1
+ * @version 4.7.0
  *
  * @warning
  *      You must *not* include any other HTML Purifier files before this file,
@@ -19,6 +19,7 @@
  */
 
 require 'HTMLPurifier.php';
+require 'HTMLPurifier/Arborize.php';
 require 'HTMLPurifier/AttrCollections.php';
 require 'HTMLPurifier/AttrDef.php';
 require 'HTMLPurifier/AttrTransform.php';
@@ -54,9 +55,11 @@ require 'HTMLPurifier/Language.php';
 require 'HTMLPurifier/LanguageFactory.php';
 require 'HTMLPurifier/Length.php';
 require 'HTMLPurifier/Lexer.php';
+require 'HTMLPurifier/Node.php';
 require 'HTMLPurifier/PercentEncoder.php';
 require 'HTMLPurifier/PropertyList.php';
 require 'HTMLPurifier/PropertyListIterator.php';
+require 'HTMLPurifier/Queue.php';
 require 'HTMLPurifier/Strategy.php';
 require 'HTMLPurifier/StringHash.php';
 require 'HTMLPurifier/StringHashParser.php';
@@ -72,7 +75,9 @@ require 'HTMLPurifier/URISchemeRegistry.php';
 require 'HTMLPurifier/UnitConverter.php';
 require 'HTMLPurifier/VarParser.php';
 require 'HTMLPurifier/VarParserException.php';
+require 'HTMLPurifier/Zipper.php';
 require 'HTMLPurifier/AttrDef/CSS.php';
+require 'HTMLPurifier/AttrDef/Clone.php';
 require 'HTMLPurifier/AttrDef/Enum.php';
 require 'HTMLPurifier/AttrDef/Integer.php';
 require 'HTMLPurifier/AttrDef/Lang.php';
@@ -90,6 +95,7 @@ require 'HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
 require 'HTMLPurifier/AttrDef/CSS/Filter.php';
 require 'HTMLPurifier/AttrDef/CSS/Font.php';
 require 'HTMLPurifier/AttrDef/CSS/FontFamily.php';
+require 'HTMLPurifier/AttrDef/CSS/Ident.php';
 require 'HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
 require 'HTMLPurifier/AttrDef/CSS/Length.php';
 require 'HTMLPurifier/AttrDef/CSS/ListStyle.php';
@@ -125,14 +131,17 @@ require 'HTMLPurifier/AttrTransform/Lang.php';
 require 'HTMLPurifier/AttrTransform/Length.php';
 require 'HTMLPurifier/AttrTransform/Name.php';
 require 'HTMLPurifier/AttrTransform/NameSync.php';
+require 'HTMLPurifier/AttrTransform/Nofollow.php';
 require 'HTMLPurifier/AttrTransform/SafeEmbed.php';
 require 'HTMLPurifier/AttrTransform/SafeObject.php';
 require 'HTMLPurifier/AttrTransform/SafeParam.php';
 require 'HTMLPurifier/AttrTransform/ScriptRequired.php';
+require 'HTMLPurifier/AttrTransform/TargetBlank.php';
 require 'HTMLPurifier/AttrTransform/Textarea.php';
 require 'HTMLPurifier/ChildDef/Chameleon.php';
 require 'HTMLPurifier/ChildDef/Custom.php';
 require 'HTMLPurifier/ChildDef/Empty.php';
+require 'HTMLPurifier/ChildDef/List.php';
 require 'HTMLPurifier/ChildDef/Required.php';
 require 'HTMLPurifier/ChildDef/Optional.php';
 require 'HTMLPurifier/ChildDef/StrictBlockquote.php';
@@ -147,10 +156,12 @@ require 'HTMLPurifier/HTMLModule/CommonAttributes.php';
 require 'HTMLPurifier/HTMLModule/Edit.php';
 require 'HTMLPurifier/HTMLModule/Forms.php';
 require 'HTMLPurifier/HTMLModule/Hypertext.php';
+require 'HTMLPurifier/HTMLModule/Iframe.php';
 require 'HTMLPurifier/HTMLModule/Image.php';
 require 'HTMLPurifier/HTMLModule/Legacy.php';
 require 'HTMLPurifier/HTMLModule/List.php';
 require 'HTMLPurifier/HTMLModule/Name.php';
+require 'HTMLPurifier/HTMLModule/Nofollow.php';
 require 'HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
 require 'HTMLPurifier/HTMLModule/Object.php';
 require 'HTMLPurifier/HTMLModule/Presentation.php';
@@ -158,10 +169,12 @@ require 'HTMLPurifier/HTMLModule/Proprietary.php';
 require 'HTMLPurifier/HTMLModule/Ruby.php';
 require 'HTMLPurifier/HTMLModule/SafeEmbed.php';
 require 'HTMLPurifier/HTMLModule/SafeObject.php';
+require 'HTMLPurifier/HTMLModule/SafeScripting.php';
 require 'HTMLPurifier/HTMLModule/Scripting.php';
 require 'HTMLPurifier/HTMLModule/StyleAttribute.php';
 require 'HTMLPurifier/HTMLModule/Tables.php';
 require 'HTMLPurifier/HTMLModule/Target.php';
+require 'HTMLPurifier/HTMLModule/TargetBlank.php';
 require 'HTMLPurifier/HTMLModule/Text.php';
 require 'HTMLPurifier/HTMLModule/Tidy.php';
 require 'HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
@@ -180,6 +193,9 @@ require 'HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
 require 'HTMLPurifier/Injector/SafeObject.php';
 require 'HTMLPurifier/Lexer/DOMLex.php';
 require 'HTMLPurifier/Lexer/DirectLex.php';
+require 'HTMLPurifier/Node/Comment.php';
+require 'HTMLPurifier/Node/Element.php';
+require 'HTMLPurifier/Node/Text.php';
 require 'HTMLPurifier/Strategy/Composite.php';
 require 'HTMLPurifier/Strategy/Core.php';
 require 'HTMLPurifier/Strategy/FixNesting.php';
@@ -196,10 +212,13 @@ require 'HTMLPurifier/Token/Start.php';
 require 'HTMLPurifier/Token/Text.php';
 require 'HTMLPurifier/URIFilter/DisableExternal.php';
 require 'HTMLPurifier/URIFilter/DisableExternalResources.php';
+require 'HTMLPurifier/URIFilter/DisableResources.php';
 require 'HTMLPurifier/URIFilter/HostBlacklist.php';
 require 'HTMLPurifier/URIFilter/MakeAbsolute.php';
 require 'HTMLPurifier/URIFilter/Munge.php';
+require 'HTMLPurifier/URIFilter/SafeIframe.php';
 require 'HTMLPurifier/URIScheme/data.php';
+require 'HTMLPurifier/URIScheme/file.php';
 require 'HTMLPurifier/URIScheme/ftp.php';
 require 'HTMLPurifier/URIScheme/http.php';
 require 'HTMLPurifier/URIScheme/https.php';
diff --git a/library/HTMLPurifier.kses.php b/library/ezyang/htmlpurifier/library/HTMLPurifier.kses.php
similarity index 96%
rename from library/HTMLPurifier.kses.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier.kses.php
index 3143feb17f..752290077f 100644
--- a/library/HTMLPurifier.kses.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier.kses.php
@@ -7,7 +7,8 @@
 
 require_once dirname(__FILE__) . '/HTMLPurifier.auto.php';
 
-function kses($string, $allowed_html, $allowed_protocols = null) {
+function kses($string, $allowed_html, $allowed_protocols = null)
+{
     $config = HTMLPurifier_Config::createDefault();
     $allowed_elements = array();
     $allowed_attributes = array();
@@ -19,7 +20,6 @@ function kses($string, $allowed_html, $allowed_protocols = null) {
     }
     $config->set('HTML.AllowedElements', $allowed_elements);
     $config->set('HTML.AllowedAttributes', $allowed_attributes);
-    $allowed_schemes = array();
     if ($allowed_protocols !== null) {
         $config->set('URI.AllowedSchemes', $allowed_protocols);
     }
diff --git a/library/HTMLPurifier.path.php b/library/ezyang/htmlpurifier/library/HTMLPurifier.path.php
similarity index 100%
rename from library/HTMLPurifier.path.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier.path.php
diff --git a/library/HTMLPurifier.php b/library/ezyang/htmlpurifier/library/HTMLPurifier.php
similarity index 66%
rename from library/HTMLPurifier.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier.php
index ba2c7b3067..c6041bc113 100644
--- a/library/HTMLPurifier.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier.php
@@ -19,7 +19,7 @@
  */
 
 /*
-    HTML Purifier 4.1.1 - Standards Compliant HTML Filtering
+    HTML Purifier 4.7.0 - Standards Compliant HTML Filtering
     Copyright (C) 2006-2008 Edward Z. Yang
 
     This library is free software; you can redistribute it and/or
@@ -54,66 +54,97 @@
 class HTMLPurifier
 {
 
-    /** Version of HTML Purifier */
-    public $version = '4.1.1';
-
-    /** Constant with version of HTML Purifier */
-    const VERSION = '4.1.1';
-
-    /** Global configuration object */
-    public $config;
-
-    /** Array of extra HTMLPurifier_Filter objects to run on HTML, for backwards compatibility */
-    private $filters = array();
-
-    /** Single instance of HTML Purifier */
-    private static $instance;
-
-    protected $strategy, $generator;
+    /**
+     * Version of HTML Purifier.
+     * @type string
+     */
+    public $version = '4.7.0';
 
     /**
-     * Resultant HTMLPurifier_Context of last run purification. Is an array
-     * of contexts if the last called method was purifyArray().
+     * Constant with version of HTML Purifier.
+     */
+    const VERSION = '4.7.0';
+
+    /**
+     * Global configuration object.
+     * @type HTMLPurifier_Config
+     */
+    public $config;
+
+    /**
+     * Array of extra filter objects to run on HTML,
+     * for backwards compatibility.
+     * @type HTMLPurifier_Filter[]
+     */
+    private $filters = array();
+
+    /**
+     * Single instance of HTML Purifier.
+     * @type HTMLPurifier
+     */
+    private static $instance;
+
+    /**
+     * @type HTMLPurifier_Strategy_Core
+     */
+    protected $strategy;
+
+    /**
+     * @type HTMLPurifier_Generator
+     */
+    protected $generator;
+
+    /**
+     * Resultant context of last run purification.
+     * Is an array of contexts if the last called method was purifyArray().
+     * @type HTMLPurifier_Context
      */
     public $context;
 
     /**
      * Initializes the purifier.
-     * @param $config Optional HTMLPurifier_Config object for all instances of
-     *                the purifier, if omitted, a default configuration is
-     *                supplied (which can be overridden on a per-use basis).
+     *
+     * @param HTMLPurifier_Config $config Optional HTMLPurifier_Config object
+     *                for all instances of the purifier, if omitted, a default
+     *                configuration is supplied (which can be overridden on a
+     *                per-use basis).
      *                The parameter can also be any type that
      *                HTMLPurifier_Config::create() supports.
      */
-    public function __construct($config = null) {
-
+    public function __construct($config = null)
+    {
         $this->config = HTMLPurifier_Config::create($config);
-
-        $this->strategy     = new HTMLPurifier_Strategy_Core();
-
+        $this->strategy = new HTMLPurifier_Strategy_Core();
     }
 
     /**
      * Adds a filter to process the output. First come first serve
-     * @param $filter HTMLPurifier_Filter object
+     *
+     * @param HTMLPurifier_Filter $filter HTMLPurifier_Filter object
      */
-    public function addFilter($filter) {
-        trigger_error('HTMLPurifier->addFilter() is deprecated, use configuration directives in the Filter namespace or Filter.Custom', E_USER_WARNING);
+    public function addFilter($filter)
+    {
+        trigger_error(
+            'HTMLPurifier->addFilter() is deprecated, use configuration directives' .
+            ' in the Filter namespace or Filter.Custom',
+            E_USER_WARNING
+        );
         $this->filters[] = $filter;
     }
 
     /**
      * Filters an HTML snippet/document to be XSS-free and standards-compliant.
      *
-     * @param $html String of HTML to purify
-     * @param $config HTMLPurifier_Config object for this operation, if omitted,
-     *                defaults to the config object specified during this
+     * @param string $html String of HTML to purify
+     * @param HTMLPurifier_Config $config Config object for this operation,
+     *                if omitted, defaults to the config object specified during this
      *                object's construction. The parameter can also be any type
      *                that HTMLPurifier_Config::create() supports.
-     * @return Purified HTML
+     *
+     * @return string Purified HTML
      */
-    public function purify($html, $config = null) {
-
+    public function purify($html, $config = null)
+    {
         // :TODO: make the config merge in, instead of replace
         $config = $config ? HTMLPurifier_Config::create($config) : $this->config;
 
@@ -151,8 +182,12 @@ class HTMLPurifier
         unset($filter_flags['Custom']);
         $filters = array();
         foreach ($filter_flags as $filter => $flag) {
-            if (!$flag) continue;
-            if (strpos($filter, '.') !== false) continue;
+            if (!$flag) {
+                continue;
+            }
+            if (strpos($filter, '.') !== false) {
+                continue;
+            }
             $class = "HTMLPurifier_Filter_$filter";
             $filters[] = new $class;
         }
@@ -175,9 +210,12 @@ class HTMLPurifier
                     // list of un-purified tokens
                     $lexer->tokenizeHTML(
                         // un-purified HTML
-                        $html, $config, $context
+                        $html,
+                        $config,
+                        $context
                     ),
-                    $config, $context
+                    $config,
+                    $context
                 )
             );
 
@@ -192,11 +230,15 @@ class HTMLPurifier
 
     /**
      * Filters an array of HTML snippets
-     * @param $config Optional HTMLPurifier_Config object for this operation.
+     *
+     * @param string[] $array_of_html Array of html snippets
+     * @param HTMLPurifier_Config $config Optional config object for this operation.
      *                See HTMLPurifier::purify() for more details.
-     * @return Array of purified HTML
+     *
+     * @return string[] Array of purified HTML
      */
-    public function purifyArray($array_of_html, $config = null) {
+    public function purifyArray($array_of_html, $config = null)
+    {
         $context_array = array();
         foreach ($array_of_html as $key => $html) {
             $array_of_html[$key] = $this->purify($html, $config);
@@ -208,11 +250,16 @@ class HTMLPurifier
 
     /**
      * Singleton for enforcing just one HTML Purifier in your system
-     * @param $prototype Optional prototype HTMLPurifier instance to
-     *                   overload singleton with, or HTMLPurifier_Config
-     *                   instance to configure the generated version with.
+     *
+     * @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype
+     *                   HTMLPurifier instance to overload singleton with,
+     *                   or HTMLPurifier_Config instance to configure the
+     *                   generated version with.
+     *
+     * @return HTMLPurifier
      */
-    public static function instance($prototype = null) {
+    public static function instance($prototype = null)
+    {
         if (!self::$instance || $prototype) {
             if ($prototype instanceof HTMLPurifier) {
                 self::$instance = $prototype;
@@ -226,12 +273,20 @@ class HTMLPurifier
     }
 
     /**
+     * Singleton for enforcing just one HTML Purifier in your system
+     *
+     * @param HTMLPurifier|HTMLPurifier_Config $prototype Optional prototype
+     *                   HTMLPurifier instance to overload singleton with,
+     *                   or HTMLPurifier_Config instance to configure the
+     *                   generated version with.
+     *
+     * @return HTMLPurifier
      * @note Backwards compatibility, see instance()
      */
-    public static function getInstance($prototype = null) {
+    public static function getInstance($prototype = null)
+    {
         return HTMLPurifier::instance($prototype);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier.safe-includes.php b/library/ezyang/htmlpurifier/library/HTMLPurifier.safe-includes.php
similarity index 91%
rename from library/HTMLPurifier.safe-includes.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier.safe-includes.php
index 6402de0458..9dea6d1ed5 100644
--- a/library/HTMLPurifier.safe-includes.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier.safe-includes.php
@@ -13,6 +13,7 @@
 $__dir = dirname(__FILE__);
 
 require_once $__dir . '/HTMLPurifier.php';
+require_once $__dir . '/HTMLPurifier/Arborize.php';
 require_once $__dir . '/HTMLPurifier/AttrCollections.php';
 require_once $__dir . '/HTMLPurifier/AttrDef.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform.php';
@@ -48,9 +49,11 @@ require_once $__dir . '/HTMLPurifier/Language.php';
 require_once $__dir . '/HTMLPurifier/LanguageFactory.php';
 require_once $__dir . '/HTMLPurifier/Length.php';
 require_once $__dir . '/HTMLPurifier/Lexer.php';
+require_once $__dir . '/HTMLPurifier/Node.php';
 require_once $__dir . '/HTMLPurifier/PercentEncoder.php';
 require_once $__dir . '/HTMLPurifier/PropertyList.php';
 require_once $__dir . '/HTMLPurifier/PropertyListIterator.php';
+require_once $__dir . '/HTMLPurifier/Queue.php';
 require_once $__dir . '/HTMLPurifier/Strategy.php';
 require_once $__dir . '/HTMLPurifier/StringHash.php';
 require_once $__dir . '/HTMLPurifier/StringHashParser.php';
@@ -66,7 +69,9 @@ require_once $__dir . '/HTMLPurifier/URISchemeRegistry.php';
 require_once $__dir . '/HTMLPurifier/UnitConverter.php';
 require_once $__dir . '/HTMLPurifier/VarParser.php';
 require_once $__dir . '/HTMLPurifier/VarParserException.php';
+require_once $__dir . '/HTMLPurifier/Zipper.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/CSS.php';
+require_once $__dir . '/HTMLPurifier/AttrDef/Clone.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/Enum.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/Integer.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/Lang.php';
@@ -84,6 +89,7 @@ require_once $__dir . '/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Filter.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Font.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/CSS/FontFamily.php';
+require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Ident.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/CSS/Length.php';
 require_once $__dir . '/HTMLPurifier/AttrDef/CSS/ListStyle.php';
@@ -119,14 +125,17 @@ require_once $__dir . '/HTMLPurifier/AttrTransform/Lang.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/Length.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/Name.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/NameSync.php';
+require_once $__dir . '/HTMLPurifier/AttrTransform/Nofollow.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/SafeEmbed.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/SafeObject.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/SafeParam.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/ScriptRequired.php';
+require_once $__dir . '/HTMLPurifier/AttrTransform/TargetBlank.php';
 require_once $__dir . '/HTMLPurifier/AttrTransform/Textarea.php';
 require_once $__dir . '/HTMLPurifier/ChildDef/Chameleon.php';
 require_once $__dir . '/HTMLPurifier/ChildDef/Custom.php';
 require_once $__dir . '/HTMLPurifier/ChildDef/Empty.php';
+require_once $__dir . '/HTMLPurifier/ChildDef/List.php';
 require_once $__dir . '/HTMLPurifier/ChildDef/Required.php';
 require_once $__dir . '/HTMLPurifier/ChildDef/Optional.php';
 require_once $__dir . '/HTMLPurifier/ChildDef/StrictBlockquote.php';
@@ -141,10 +150,12 @@ require_once $__dir . '/HTMLPurifier/HTMLModule/CommonAttributes.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Edit.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Forms.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Hypertext.php';
+require_once $__dir . '/HTMLPurifier/HTMLModule/Iframe.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Image.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Legacy.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/List.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Name.php';
+require_once $__dir . '/HTMLPurifier/HTMLModule/Nofollow.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Object.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Presentation.php';
@@ -152,10 +163,12 @@ require_once $__dir . '/HTMLPurifier/HTMLModule/Proprietary.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Ruby.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/SafeEmbed.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/SafeObject.php';
+require_once $__dir . '/HTMLPurifier/HTMLModule/SafeScripting.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Scripting.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/StyleAttribute.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Tables.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Target.php';
+require_once $__dir . '/HTMLPurifier/HTMLModule/TargetBlank.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Text.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/Tidy.php';
 require_once $__dir . '/HTMLPurifier/HTMLModule/XMLCommonAttributes.php';
@@ -174,6 +187,9 @@ require_once $__dir . '/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php';
 require_once $__dir . '/HTMLPurifier/Injector/SafeObject.php';
 require_once $__dir . '/HTMLPurifier/Lexer/DOMLex.php';
 require_once $__dir . '/HTMLPurifier/Lexer/DirectLex.php';
+require_once $__dir . '/HTMLPurifier/Node/Comment.php';
+require_once $__dir . '/HTMLPurifier/Node/Element.php';
+require_once $__dir . '/HTMLPurifier/Node/Text.php';
 require_once $__dir . '/HTMLPurifier/Strategy/Composite.php';
 require_once $__dir . '/HTMLPurifier/Strategy/Core.php';
 require_once $__dir . '/HTMLPurifier/Strategy/FixNesting.php';
@@ -190,10 +206,13 @@ require_once $__dir . '/HTMLPurifier/Token/Start.php';
 require_once $__dir . '/HTMLPurifier/Token/Text.php';
 require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternal.php';
 require_once $__dir . '/HTMLPurifier/URIFilter/DisableExternalResources.php';
+require_once $__dir . '/HTMLPurifier/URIFilter/DisableResources.php';
 require_once $__dir . '/HTMLPurifier/URIFilter/HostBlacklist.php';
 require_once $__dir . '/HTMLPurifier/URIFilter/MakeAbsolute.php';
 require_once $__dir . '/HTMLPurifier/URIFilter/Munge.php';
+require_once $__dir . '/HTMLPurifier/URIFilter/SafeIframe.php';
 require_once $__dir . '/HTMLPurifier/URIScheme/data.php';
+require_once $__dir . '/HTMLPurifier/URIScheme/file.php';
 require_once $__dir . '/HTMLPurifier/URIScheme/ftp.php';
 require_once $__dir . '/HTMLPurifier/URIScheme/http.php';
 require_once $__dir . '/HTMLPurifier/URIScheme/https.php';
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Arborize.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Arborize.php
new file mode 100644
index 0000000000..9e6617be5d
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Arborize.php
@@ -0,0 +1,71 @@
+<?php
+
+/**
+ * Converts a stream of HTMLPurifier_Token into an HTMLPurifier_Node,
+ * and back again.
+ *
+ * @note This transformation is not an equivalence.  We mutate the input
+ * token stream to make it so; see all [MUT] markers in code.
+ */
+class HTMLPurifier_Arborize
+{
+    public static function arborize($tokens, $config, $context) {
+        $definition = $config->getHTMLDefinition();
+        $parent = new HTMLPurifier_Token_Start($definition->info_parent);
+        $stack = array($parent->toNode());
+        foreach ($tokens as $token) {
+            $token->skip = null; // [MUT]
+            $token->carryover = null; // [MUT]
+            if ($token instanceof HTMLPurifier_Token_End) {
+                $token->start = null; // [MUT]
+                $r = array_pop($stack);
+                assert($r->name === $token->name);
+                assert(empty($token->attr));
+                $r->endCol = $token->col;
+                $r->endLine = $token->line;
+                $r->endArmor = $token->armor;
+                continue;
+            }
+            $node = $token->toNode();
+            $stack[count($stack)-1]->children[] = $node;
+            if ($token instanceof HTMLPurifier_Token_Start) {
+                $stack[] = $node;
+            }
+        }
+        assert(count($stack) == 1);
+        return $stack[0];
+    }
+
+    public static function flatten($node, $config, $context) {
+        $level = 0;
+        $nodes = array($level => new HTMLPurifier_Queue(array($node)));
+        $closingTokens = array();
+        $tokens = array();
+        do {
+            while (!$nodes[$level]->isEmpty()) {
+                $node = $nodes[$level]->shift(); // FIFO
+                list($start, $end) = $node->toTokenPair();
+                if ($level > 0) {
+                    $tokens[] = $start;
+                }
+                if ($end !== NULL) {
+                    $closingTokens[$level][] = $end;
+                }
+                if ($node instanceof HTMLPurifier_Node_Element) {
+                    $level++;
+                    $nodes[$level] = new HTMLPurifier_Queue();
+                    foreach ($node->children as $childNode) {
+                        $nodes[$level]->push($childNode);
+                    }
+                }
+            }
+            $level--;
+            if ($level && isset($closingTokens[$level])) {
+                while ($token = array_pop($closingTokens[$level])) {
+                    $tokens[] = $token;
+                }
+            }
+        } while ($level > 0);
+        return $tokens;
+    }
+}
diff --git a/library/HTMLPurifier/AttrCollections.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrCollections.php
similarity index 74%
rename from library/HTMLPurifier/AttrCollections.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrCollections.php
index 555b86d042..4f6c2e39a2 100644
--- a/library/HTMLPurifier/AttrCollections.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrCollections.php
@@ -8,7 +8,8 @@ class HTMLPurifier_AttrCollections
 {
 
     /**
-     * Associative array of attribute collections, indexed by name
+     * Associative array of attribute collections, indexed by name.
+     * @type array
      */
     public $info = array();
 
@@ -16,10 +17,11 @@ class HTMLPurifier_AttrCollections
      * Performs all expansions on internal data for use by other inclusions
      * It also collects all attribute collection extensions from
      * modules
-     * @param $attr_types HTMLPurifier_AttrTypes instance
-     * @param $modules Hash array of HTMLPurifier_HTMLModule members
+     * @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
+     * @param HTMLPurifier_HTMLModule[] $modules Hash array of HTMLPurifier_HTMLModule members
      */
-    public function __construct($attr_types, $modules) {
+    public function __construct($attr_types, $modules)
+    {
         // load extensions from the modules
         foreach ($modules as $module) {
             foreach ($module->attr_collections as $coll_i => $coll) {
@@ -30,7 +32,9 @@ class HTMLPurifier_AttrCollections
                     if ($attr_i === 0 && isset($this->info[$coll_i][$attr_i])) {
                         // merge in includes
                         $this->info[$coll_i][$attr_i] = array_merge(
-                            $this->info[$coll_i][$attr_i], $attr);
+                            $this->info[$coll_i][$attr_i],
+                            $attr
+                        );
                         continue;
                     }
                     $this->info[$coll_i][$attr_i] = $attr;
@@ -49,20 +53,29 @@ class HTMLPurifier_AttrCollections
     /**
      * Takes a reference to an attribute associative array and performs
      * all inclusions specified by the zero index.
-     * @param &$attr Reference to attribute array
+     * @param array &$attr Reference to attribute array
      */
-    public function performInclusions(&$attr) {
-        if (!isset($attr[0])) return;
+    public function performInclusions(&$attr)
+    {
+        if (!isset($attr[0])) {
+            return;
+        }
         $merge = $attr[0];
         $seen  = array(); // recursion guard
         // loop through all the inclusions
         for ($i = 0; isset($merge[$i]); $i++) {
-            if (isset($seen[$merge[$i]])) continue;
+            if (isset($seen[$merge[$i]])) {
+                continue;
+            }
             $seen[$merge[$i]] = true;
             // foreach attribute of the inclusion, copy it over
-            if (!isset($this->info[$merge[$i]])) continue;
+            if (!isset($this->info[$merge[$i]])) {
+                continue;
+            }
             foreach ($this->info[$merge[$i]] as $key => $value) {
-                if (isset($attr[$key])) continue; // also catches more inclusions
+                if (isset($attr[$key])) {
+                    continue;
+                } // also catches more inclusions
                 $attr[$key] = $value;
             }
             if (isset($this->info[$merge[$i]][0])) {
@@ -76,20 +89,24 @@ class HTMLPurifier_AttrCollections
     /**
      * Expands all string identifiers in an attribute array by replacing
      * them with the appropriate values inside HTMLPurifier_AttrTypes
-     * @param &$attr Reference to attribute array
-     * @param $attr_types HTMLPurifier_AttrTypes instance
+     * @param array &$attr Reference to attribute array
+     * @param HTMLPurifier_AttrTypes $attr_types HTMLPurifier_AttrTypes instance
      */
-    public function expandIdentifiers(&$attr, $attr_types) {
-
+    public function expandIdentifiers(&$attr, $attr_types)
+    {
         // because foreach will process new elements we add, make sure we
         // skip duplicates
         $processed = array();
 
         foreach ($attr as $def_i => $def) {
             // skip inclusions
-            if ($def_i === 0) continue;
+            if ($def_i === 0) {
+                continue;
+            }
 
-            if (isset($processed[$def_i])) continue;
+            if (isset($processed[$def_i])) {
+                continue;
+            }
 
             // determine whether or not attribute is required
             if ($required = (strpos($def_i, '*') !== false)) {
@@ -120,9 +137,7 @@ class HTMLPurifier_AttrCollections
                 unset($attr[$def_i]);
             }
         }
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef.php
similarity index 74%
rename from library/HTMLPurifier/AttrDef.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef.php
index b2e4f36c5d..5ac06522b9 100644
--- a/library/HTMLPurifier/AttrDef.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef.php
@@ -14,23 +14,25 @@ abstract class HTMLPurifier_AttrDef
 {
 
     /**
-     * Tells us whether or not an HTML attribute is minimized. Has no
-     * meaning in other contexts.
+     * Tells us whether or not an HTML attribute is minimized.
+     * Has no meaning in other contexts.
+     * @type bool
      */
     public $minimized = false;
 
     /**
-     * Tells us whether or not an HTML attribute is required. Has no
-     * meaning in other contexts
+     * Tells us whether or not an HTML attribute is required.
+     * Has no meaning in other contexts
+     * @type bool
      */
     public $required = false;
 
     /**
      * Validates and cleans passed string according to a definition.
      *
-     * @param $string String to be validated and cleaned.
-     * @param $config Mandatory HTMLPurifier_Config object.
-     * @param $context Mandatory HTMLPurifier_AttrContext object.
+     * @param string $string String to be validated and cleaned.
+     * @param HTMLPurifier_Config $config Mandatory HTMLPurifier_Config object.
+     * @param HTMLPurifier_Context $context Mandatory HTMLPurifier_Context object.
      */
     abstract public function validate($string, $config, $context);
 
@@ -55,7 +57,8 @@ abstract class HTMLPurifier_AttrDef
      *          parsing XML, thus, this behavior may still be correct. We
      *          assume that newlines have been normalized.
      */
-    public function parseCDATA($string) {
+    public function parseCDATA($string)
+    {
         $string = trim($string);
         $string = str_replace(array("\n", "\t", "\r"), ' ', $string);
         return $string;
@@ -63,10 +66,11 @@ abstract class HTMLPurifier_AttrDef
 
     /**
      * Factory method for creating this class from a string.
-     * @param $string String construction info
-     * @return Created AttrDef object corresponding to $string
+     * @param string $string String construction info
+     * @return HTMLPurifier_AttrDef Created AttrDef object corresponding to $string
      */
-    public function make($string) {
+    public function make($string)
+    {
         // default implementation, return a flyweight of this object.
         // If $string has an effect on the returned object (i.e. you
         // need to overload this method), it is best
@@ -77,16 +81,20 @@ abstract class HTMLPurifier_AttrDef
     /**
      * Removes spaces from rgb(0, 0, 0) so that shorthand CSS properties work
      * properly. THIS IS A HACK!
+     * @param string $string a CSS colour definition
+     * @return string
      */
-    protected function mungeRgb($string) {
+    protected function mungeRgb($string)
+    {
         return preg_replace('/rgb\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\)/', 'rgb(\1,\2,\3)', $string);
     }
 
     /**
-     * Parses a possibly escaped CSS string and returns the "pure" 
+     * Parses a possibly escaped CSS string and returns the "pure"
      * version of it.
      */
-    protected function expandCSSEscape($string) {
+    protected function expandCSSEscape($string)
+    {
         // flexibly parse it
         $ret = '';
         for ($i = 0, $c = strlen($string); $i < $c; $i++) {
@@ -99,25 +107,32 @@ abstract class HTMLPurifier_AttrDef
                 if (ctype_xdigit($string[$i])) {
                     $code = $string[$i];
                     for ($a = 1, $i++; $i < $c && $a < 6; $i++, $a++) {
-                        if (!ctype_xdigit($string[$i])) break;
+                        if (!ctype_xdigit($string[$i])) {
+                            break;
+                        }
                         $code .= $string[$i];
                     }
                     // We have to be extremely careful when adding
                     // new characters, to make sure we're not breaking
                     // the encoding.
                     $char = HTMLPurifier_Encoder::unichr(hexdec($code));
-                    if (HTMLPurifier_Encoder::cleanUTF8($char) === '') continue;
+                    if (HTMLPurifier_Encoder::cleanUTF8($char) === '') {
+                        continue;
+                    }
                     $ret .= $char;
-                    if ($i < $c && trim($string[$i]) !== '') $i--;
+                    if ($i < $c && trim($string[$i]) !== '') {
+                        $i--;
+                    }
+                    continue;
+                }
+                if ($string[$i] === "\n") {
                     continue;
                 }
-                if ($string[$i] === "\n") continue;
             }
             $ret .= $string[$i];
         }
         return $ret;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php
similarity index 77%
rename from library/HTMLPurifier/AttrDef/CSS.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php
index 953e706755..02c1641fb2 100644
--- a/library/HTMLPurifier/AttrDef/CSS.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS.php
@@ -14,8 +14,14 @@
 class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
 {
 
-    public function validate($css, $config, $context) {
-
+    /**
+     * @param string $css
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($css, $config, $context)
+    {
         $css = $this->parseCDATA($css);
 
         $definition = $config->getCSSDefinition();
@@ -36,34 +42,47 @@ class HTMLPurifier_AttrDef_CSS extends HTMLPurifier_AttrDef
         $context->register('CurrentCSSProperty', $property);
 
         foreach ($declarations as $declaration) {
-            if (!$declaration) continue;
-            if (!strpos($declaration, ':')) continue;
+            if (!$declaration) {
+                continue;
+            }
+            if (!strpos($declaration, ':')) {
+                continue;
+            }
             list($property, $value) = explode(':', $declaration, 2);
             $property = trim($property);
-            $value    = trim($value);
+            $value = trim($value);
             $ok = false;
             do {
                 if (isset($definition->info[$property])) {
                     $ok = true;
                     break;
                 }
-                if (ctype_lower($property)) break;
+                if (ctype_lower($property)) {
+                    break;
+                }
                 $property = strtolower($property);
                 if (isset($definition->info[$property])) {
                     $ok = true;
                     break;
                 }
-            } while(0);
-            if (!$ok) continue;
+            } while (0);
+            if (!$ok) {
+                continue;
+            }
             // inefficient call, since the validator will do this again
             if (strtolower(trim($value)) !== 'inherit') {
                 // inherit works for everything (but only on the base property)
                 $result = $definition->info[$property]->validate(
-                    $value, $config, $context );
+                    $value,
+                    $config,
+                    $context
+                );
             } else {
                 $result = 'inherit';
             }
-            if ($result === false) continue;
+            if ($result === false) {
+                continue;
+            }
             $propvalues[$property] = $result;
         }
 
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
new file mode 100644
index 0000000000..af2b83dff8
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/AlphaValue.php
@@ -0,0 +1,34 @@
+<?php
+
+class HTMLPurifier_AttrDef_CSS_AlphaValue extends HTMLPurifier_AttrDef_CSS_Number
+{
+
+    public function __construct()
+    {
+        parent::__construct(false); // opacity is non-negative, but we will clamp it
+    }
+
+    /**
+     * @param string $number
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
+     */
+    public function validate($number, $config, $context)
+    {
+        $result = parent::validate($number, $config, $context);
+        if ($result === false) {
+            return $result;
+        }
+        $float = (float)$result;
+        if ($float < 0.0) {
+            $result = '0';
+        }
+        if ($float > 1.0) {
+            $result = '1';
+        }
+        return $result;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Background.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php
similarity index 63%
rename from library/HTMLPurifier/AttrDef/CSS/Background.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php
index 3a3d20cd6a..7f1ea3b0f1 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Background.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Background.php
@@ -9,11 +9,16 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
 
     /**
      * Local copy of component validators.
+     * @type HTMLPurifier_AttrDef[]
      * @note See HTMLPurifier_AttrDef_Font::$info for a similar impl.
      */
     protected $info;
 
-    public function __construct($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function __construct($config)
+    {
         $def = $config->getCSSDefinition();
         $this->info['background-color'] = $def->info['background-color'];
         $this->info['background-image'] = $def->info['background-image'];
@@ -22,40 +27,55 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
         $this->info['background-position'] = $def->info['background-position'];
     }
 
-    public function validate($string, $config, $context) {
-
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         // regular pre-processing
         $string = $this->parseCDATA($string);
-        if ($string === '') return false;
+        if ($string === '') {
+            return false;
+        }
 
         // munge rgb() decl if necessary
         $string = $this->mungeRgb($string);
 
         // assumes URI doesn't have spaces in it
-        $bits = explode(' ', strtolower($string)); // bits to process
+        $bits = explode(' ', $string); // bits to process
 
         $caught = array();
-        $caught['color']    = false;
-        $caught['image']    = false;
-        $caught['repeat']   = false;
+        $caught['color'] = false;
+        $caught['image'] = false;
+        $caught['repeat'] = false;
         $caught['attachment'] = false;
         $caught['position'] = false;
 
         $i = 0; // number of catches
-        $none = false;
 
         foreach ($bits as $bit) {
-            if ($bit === '') continue;
+            if ($bit === '') {
+                continue;
+            }
             foreach ($caught as $key => $status) {
                 if ($key != 'position') {
-                    if ($status !== false) continue;
+                    if ($status !== false) {
+                        continue;
+                    }
                     $r = $this->info['background-' . $key]->validate($bit, $config, $context);
                 } else {
                     $r = $bit;
                 }
-                if ($r === false) continue;
+                if ($r === false) {
+                    continue;
+                }
                 if ($key == 'position') {
-                    if ($caught[$key] === false) $caught[$key] = '';
+                    if ($caught[$key] === false) {
+                        $caught[$key] = '';
+                    }
                     $caught[$key] .= $r . ' ';
                 } else {
                     $caught[$key] = $r;
@@ -65,7 +85,9 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
             }
         }
 
-        if (!$i) return false;
+        if (!$i) {
+            return false;
+        }
         if ($caught['position'] !== false) {
             $caught['position'] = $this->info['background-position']->
                 validate($caught['position'], $config, $context);
@@ -73,15 +95,17 @@ class HTMLPurifier_AttrDef_CSS_Background extends HTMLPurifier_AttrDef
 
         $ret = array();
         foreach ($caught as $value) {
-            if ($value === false) continue;
+            if ($value === false) {
+                continue;
+            }
             $ret[] = $value;
         }
 
-        if (empty($ret)) return false;
+        if (empty($ret)) {
+            return false;
+        }
         return implode(' ', $ret);
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
similarity index 73%
rename from library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
index fae82eaec8..4580ef5a91 100644
--- a/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/BackgroundPosition.php
@@ -44,15 +44,30 @@
 class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
 {
 
+    /**
+     * @type HTMLPurifier_AttrDef_CSS_Length
+     */
     protected $length;
+
+    /**
+     * @type HTMLPurifier_AttrDef_CSS_Percentage
+     */
     protected $percentage;
 
-    public function __construct() {
-        $this->length     = new HTMLPurifier_AttrDef_CSS_Length();
+    public function __construct()
+    {
+        $this->length = new HTMLPurifier_AttrDef_CSS_Length();
         $this->percentage = new HTMLPurifier_AttrDef_CSS_Percentage();
     }
 
-    public function validate($string, $config, $context) {
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         $string = $this->parseCDATA($string);
         $bits = explode(' ', $string);
 
@@ -74,7 +89,9 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
         );
 
         foreach ($bits as $bit) {
-            if ($bit === '') continue;
+            if ($bit === '') {
+                continue;
+            }
 
             // test for keyword
             $lbit = ctype_lower($bit) ? $bit : strtolower($bit);
@@ -104,30 +121,37 @@ class HTMLPurifier_AttrDef_CSS_BackgroundPosition extends HTMLPurifier_AttrDef
                 $measures[] = $r;
                 $i++;
             }
-
         }
 
-        if (!$i) return false; // no valid values were caught
+        if (!$i) {
+            return false;
+        } // no valid values were caught
 
         $ret = array();
 
         // first keyword
-        if     ($keywords['h'])     $ret[] = $keywords['h'];
-        elseif ($keywords['ch']) {
+        if ($keywords['h']) {
+            $ret[] = $keywords['h'];
+        } elseif ($keywords['ch']) {
             $ret[] = $keywords['ch'];
             $keywords['cv'] = false; // prevent re-use: center = center center
+        } elseif (count($measures)) {
+            $ret[] = array_shift($measures);
         }
-        elseif (count($measures))   $ret[] = array_shift($measures);
 
-        if     ($keywords['v'])     $ret[] = $keywords['v'];
-        elseif ($keywords['cv'])    $ret[] = $keywords['cv'];
-        elseif (count($measures))   $ret[] = array_shift($measures);
+        if ($keywords['v']) {
+            $ret[] = $keywords['v'];
+        } elseif ($keywords['cv']) {
+            $ret[] = $keywords['cv'];
+        } elseif (count($measures)) {
+            $ret[] = array_shift($measures);
+        }
 
-        if (empty($ret)) return false;
+        if (empty($ret)) {
+            return false;
+        }
         return implode(' ', $ret);
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Border.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php
similarity index 71%
rename from library/HTMLPurifier/AttrDef/CSS/Border.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php
index 42a1d1b4ae..16243ba1ed 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Border.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Border.php
@@ -8,17 +8,29 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
 
     /**
      * Local copy of properties this property is shorthand for.
+     * @type HTMLPurifier_AttrDef[]
      */
     protected $info = array();
 
-    public function __construct($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function __construct($config)
+    {
         $def = $config->getCSSDefinition();
         $this->info['border-width'] = $def->info['border-width'];
         $this->info['border-style'] = $def->info['border-style'];
         $this->info['border-top-color'] = $def->info['border-top-color'];
     }
 
-    public function validate($string, $config, $context) {
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         $string = $this->parseCDATA($string);
         $string = $this->mungeRgb($string);
         $bits = explode(' ', $string);
@@ -26,7 +38,9 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
         $ret = ''; // return value
         foreach ($bits as $bit) {
             foreach ($this->info as $propname => $validator) {
-                if (isset($done[$propname])) continue;
+                if (isset($done[$propname])) {
+                    continue;
+                }
                 $r = $validator->validate($bit, $config, $context);
                 if ($r !== false) {
                     $ret .= $r . ' ';
@@ -37,7 +51,6 @@ class HTMLPurifier_AttrDef_CSS_Border extends HTMLPurifier_AttrDef
         }
         return rtrim($ret);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Color.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php
similarity index 54%
rename from library/HTMLPurifier/AttrDef/CSS/Color.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php
index 07f95a6719..16d2a6b98c 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Color.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Color.php
@@ -6,29 +6,47 @@
 class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
 {
 
-    public function validate($color, $config, $context) {
-
+    /**
+     * @param string $color
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($color, $config, $context)
+    {
         static $colors = null;
-        if ($colors === null) $colors = $config->get('Core.ColorKeywords');
+        if ($colors === null) {
+            $colors = $config->get('Core.ColorKeywords');
+        }
 
         $color = trim($color);
-        if ($color === '') return false;
+        if ($color === '') {
+            return false;
+        }
 
         $lower = strtolower($color);
-        if (isset($colors[$lower])) return $colors[$lower];
+        if (isset($colors[$lower])) {
+            return $colors[$lower];
+        }
 
         if (strpos($color, 'rgb(') !== false) {
             // rgb literal handling
             $length = strlen($color);
-            if (strpos($color, ')') !== $length - 1) return false;
+            if (strpos($color, ')') !== $length - 1) {
+                return false;
+            }
             $triad = substr($color, 4, $length - 4 - 1);
             $parts = explode(',', $triad);
-            if (count($parts) !== 3) return false;
+            if (count($parts) !== 3) {
+                return false;
+            }
             $type = false; // to ensure that they're all the same type
             $new_parts = array();
             foreach ($parts as $part) {
                 $part = trim($part);
-                if ($part === '') return false;
+                if ($part === '') {
+                    return false;
+                }
                 $length = strlen($part);
                 if ($part[$length - 1] === '%') {
                     // handle percents
@@ -37,9 +55,13 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
                     } elseif ($type !== 'percentage') {
                         return false;
                     }
-                    $num = (float) substr($part, 0, $length - 1);
-                    if ($num < 0) $num = 0;
-                    if ($num > 100) $num = 100;
+                    $num = (float)substr($part, 0, $length - 1);
+                    if ($num < 0) {
+                        $num = 0;
+                    }
+                    if ($num > 100) {
+                        $num = 100;
+                    }
                     $new_parts[] = "$num%";
                 } else {
                     // handle integers
@@ -48,10 +70,14 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
                     } elseif ($type !== 'integer') {
                         return false;
                     }
-                    $num = (int) $part;
-                    if ($num < 0) $num = 0;
-                    if ($num > 255) $num = 255;
-                    $new_parts[] = (string) $num;
+                    $num = (int)$part;
+                    if ($num < 0) {
+                        $num = 0;
+                    }
+                    if ($num > 255) {
+                        $num = 255;
+                    }
+                    $new_parts[] = (string)$num;
                 }
             }
             $new_triad = implode(',', $new_parts);
@@ -65,14 +91,15 @@ class HTMLPurifier_AttrDef_CSS_Color extends HTMLPurifier_AttrDef
                 $color = '#' . $color;
             }
             $length = strlen($hex);
-            if ($length !== 3 && $length !== 6) return false;
-            if (!ctype_xdigit($hex)) return false;
+            if ($length !== 3 && $length !== 6) {
+                return false;
+            }
+            if (!ctype_xdigit($hex)) {
+                return false;
+            }
         }
-
         return $color;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Composite.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php
similarity index 61%
rename from library/HTMLPurifier/AttrDef/CSS/Composite.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php
index de1289cba8..9c1750554f 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Composite.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Composite.php
@@ -13,26 +13,36 @@ class HTMLPurifier_AttrDef_CSS_Composite extends HTMLPurifier_AttrDef
 {
 
     /**
-     * List of HTMLPurifier_AttrDef objects that may process strings
+     * List of objects that may process strings.
+     * @type HTMLPurifier_AttrDef[]
      * @todo Make protected
      */
     public $defs;
 
     /**
-     * @param $defs List of HTMLPurifier_AttrDef objects
+     * @param HTMLPurifier_AttrDef[] $defs List of HTMLPurifier_AttrDef objects
      */
-    public function __construct($defs) {
+    public function __construct($defs)
+    {
         $this->defs = $defs;
     }
 
-    public function validate($string, $config, $context) {
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         foreach ($this->defs as $i => $def) {
             $result = $this->defs[$i]->validate($string, $config, $context);
-            if ($result !== false) return $result;
+            if ($result !== false) {
+                return $result;
+            }
         }
         return false;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
new file mode 100644
index 0000000000..9d77cc9aaf
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/DenyElementDecorator.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * Decorator which enables CSS properties to be disabled for specific elements.
+ */
+class HTMLPurifier_AttrDef_CSS_DenyElementDecorator extends HTMLPurifier_AttrDef
+{
+    /**
+     * @type HTMLPurifier_AttrDef
+     */
+    public $def;
+    /**
+     * @type string
+     */
+    public $element;
+
+    /**
+     * @param HTMLPurifier_AttrDef $def Definition to wrap
+     * @param string $element Element to deny
+     */
+    public function __construct($def, $element)
+    {
+        $this->def = $def;
+        $this->element = $element;
+    }
+
+    /**
+     * Checks if CurrentToken is set and equal to $this->element
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        $token = $context->get('CurrentToken', true);
+        if ($token && $token->name == $this->element) {
+            return false;
+        }
+        return $this->def->validate($string, $config, $context);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Filter.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php
similarity index 62%
rename from library/HTMLPurifier/AttrDef/CSS/Filter.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php
index 147894b861..bde4c3301f 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Filter.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Filter.php
@@ -7,23 +7,37 @@
  */
 class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
 {
-
+    /**
+     * @type HTMLPurifier_AttrDef_Integer
+     */
     protected $intValidator;
 
-    public function __construct() {
+    public function __construct()
+    {
         $this->intValidator = new HTMLPurifier_AttrDef_Integer();
     }
 
-    public function validate($value, $config, $context) {
+    /**
+     * @param string $value
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($value, $config, $context)
+    {
         $value = $this->parseCDATA($value);
-        if ($value === 'none') return $value;
+        if ($value === 'none') {
+            return $value;
+        }
         // if we looped this we could support multiple filters
         $function_length = strcspn($value, '(');
         $function = trim(substr($value, 0, $function_length));
         if ($function !== 'alpha' &&
             $function !== 'Alpha' &&
             $function !== 'progid:DXImageTransform.Microsoft.Alpha'
-            ) return false;
+        ) {
+            return false;
+        }
         $cursor = $function_length + 1;
         $parameters_length = strcspn($value, ')', $cursor);
         $parameters = substr($value, $cursor, $parameters_length);
@@ -32,15 +46,25 @@ class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
         $lookup = array();
         foreach ($params as $param) {
             list($key, $value) = explode('=', $param);
-            $key   = trim($key);
+            $key = trim($key);
             $value = trim($value);
-            if (isset($lookup[$key])) continue;
-            if ($key !== 'opacity') continue;
+            if (isset($lookup[$key])) {
+                continue;
+            }
+            if ($key !== 'opacity') {
+                continue;
+            }
             $value = $this->intValidator->validate($value, $config, $context);
-            if ($value === false) continue;
-            $int = (int) $value;
-            if ($int > 100) $value = '100';
-            if ($int < 0) $value = '0';
+            if ($value === false) {
+                continue;
+            }
+            $int = (int)$value;
+            if ($int > 100) {
+                $value = '100';
+            }
+            if ($int < 0) {
+                $value = '0';
+            }
             $ret_params[] = "$key=$value";
             $lookup[$key] = true;
         }
@@ -48,7 +72,6 @@ class HTMLPurifier_AttrDef_CSS_Filter extends HTMLPurifier_AttrDef
         $ret_function = "$function($ret_parameters)";
         return $ret_function;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Font.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php
similarity index 67%
rename from library/HTMLPurifier/AttrDef/CSS/Font.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php
index 699ee0b701..579b97ef1c 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Font.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Font.php
@@ -7,8 +7,8 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
 {
 
     /**
-     * Local copy of component validators.
-     *
+     * Local copy of validators
+     * @type HTMLPurifier_AttrDef[]
      * @note If we moved specific CSS property definitions to their own
      *       classes instead of having them be assembled at run time by
      *       CSSDefinition, this wouldn't be necessary.  We'd instantiate
@@ -16,18 +16,28 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
      */
     protected $info = array();
 
-    public function __construct($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function __construct($config)
+    {
         $def = $config->getCSSDefinition();
-        $this->info['font-style']   = $def->info['font-style'];
+        $this->info['font-style'] = $def->info['font-style'];
         $this->info['font-variant'] = $def->info['font-variant'];
-        $this->info['font-weight']  = $def->info['font-weight'];
-        $this->info['font-size']    = $def->info['font-size'];
-        $this->info['line-height']  = $def->info['line-height'];
-        $this->info['font-family']  = $def->info['font-family'];
+        $this->info['font-weight'] = $def->info['font-weight'];
+        $this->info['font-size'] = $def->info['font-size'];
+        $this->info['line-height'] = $def->info['line-height'];
+        $this->info['font-family'] = $def->info['font-family'];
     }
 
-    public function validate($string, $config, $context) {
-
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         static $system_fonts = array(
             'caption' => true,
             'icon' => true,
@@ -39,7 +49,9 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
 
         // regular pre-processing
         $string = $this->parseCDATA($string);
-        if ($string === '') return false;
+        if ($string === '') {
+            return false;
+        }
 
         // check if it's one of the keywords
         $lowercase_string = strtolower($string);
@@ -54,15 +66,20 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
         $final = ''; // output
 
         for ($i = 0, $size = count($bits); $i < $size; $i++) {
-            if ($bits[$i] === '') continue;
+            if ($bits[$i] === '') {
+                continue;
+            }
             switch ($stage) {
-
-                // attempting to catch font-style, font-variant or font-weight
-                case 0:
+                case 0: // attempting to catch font-style, font-variant or font-weight
                     foreach ($stage_1 as $validator_name) {
-                        if (isset($caught[$validator_name])) continue;
+                        if (isset($caught[$validator_name])) {
+                            continue;
+                        }
                         $r = $this->info[$validator_name]->validate(
-                                                $bits[$i], $config, $context);
+                            $bits[$i],
+                            $config,
+                            $context
+                        );
                         if ($r !== false) {
                             $final .= $r . ' ';
                             $caught[$validator_name] = true;
@@ -70,15 +87,17 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
                         }
                     }
                     // all three caught, continue on
-                    if (count($caught) >= 3) $stage = 1;
-                    if ($r !== false) break;
-
-                // attempting to catch font-size and perhaps line-height
-                case 1:
+                    if (count($caught) >= 3) {
+                        $stage = 1;
+                    }
+                    if ($r !== false) {
+                        break;
+                    }
+                case 1: // attempting to catch font-size and perhaps line-height
                     $found_slash = false;
                     if (strpos($bits[$i], '/') !== false) {
                         list($font_size, $line_height) =
-                                                    explode('/', $bits[$i]);
+                            explode('/', $bits[$i]);
                         if ($line_height === '') {
                             // ooh, there's a space after the slash!
                             $line_height = false;
@@ -89,14 +108,19 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
                         $line_height = false;
                     }
                     $r = $this->info['font-size']->validate(
-                                              $font_size, $config, $context);
+                        $font_size,
+                        $config,
+                        $context
+                    );
                     if ($r !== false) {
                         $final .= $r;
                         // attempt to catch line-height
                         if ($line_height === false) {
                             // we need to scroll forward
                             for ($j = $i + 1; $j < $size; $j++) {
-                                if ($bits[$j] === '') continue;
+                                if ($bits[$j] === '') {
+                                    continue;
+                                }
                                 if ($bits[$j] === '/') {
                                     if ($found_slash) {
                                         return false;
@@ -116,7 +140,10 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
                         if ($found_slash) {
                             $i = $j;
                             $r = $this->info['line-height']->validate(
-                                              $line_height, $config, $context);
+                                $line_height,
+                                $config,
+                                $context
+                            );
                             if ($r !== false) {
                                 $final .= '/' . $r;
                             }
@@ -126,13 +153,14 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
                         break;
                     }
                     return false;
-
-                // attempting to catch font-family
-                case 2:
+                case 2: // attempting to catch font-family
                     $font_family =
                         implode(' ', array_slice($bits, $i, $size - $i));
                     $r = $this->info['font-family']->validate(
-                                              $font_family, $config, $context);
+                        $font_family,
+                        $config,
+                        $context
+                    );
                     if ($r !== false) {
                         $final .= $r . ' ';
                         // processing completed successfully
@@ -143,7 +171,6 @@ class HTMLPurifier_AttrDef_CSS_Font extends HTMLPurifier_AttrDef
         }
         return false;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
new file mode 100644
index 0000000000..74e24c8816
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/FontFamily.php
@@ -0,0 +1,219 @@
+<?php
+
+/**
+ * Validates a font family list according to CSS spec
+ */
+class HTMLPurifier_AttrDef_CSS_FontFamily extends HTMLPurifier_AttrDef
+{
+
+    protected $mask = null;
+
+    public function __construct()
+    {
+        $this->mask = '_- ';
+        for ($c = 'a'; $c <= 'z'; $c++) {
+            $this->mask .= $c;
+        }
+        for ($c = 'A'; $c <= 'Z'; $c++) {
+            $this->mask .= $c;
+        }
+        for ($c = '0'; $c <= '9'; $c++) {
+            $this->mask .= $c;
+        } // cast-y, but should be fine
+        // special bytes used by UTF-8
+        for ($i = 0x80; $i <= 0xFF; $i++) {
+            // We don't bother excluding invalid bytes in this range,
+            // because the our restriction of well-formed UTF-8 will
+            // prevent these from ever occurring.
+            $this->mask .= chr($i);
+        }
+
+        /*
+            PHP's internal strcspn implementation is
+            O(length of string * length of mask), making it inefficient
+            for large masks.  However, it's still faster than
+            preg_match 8)
+          for (p = s1;;) {
+            spanp = s2;
+            do {
+              if (*spanp == c || p == s1_end) {
+                return p - s1;
+              }
+            } while (spanp++ < (s2_end - 1));
+            c = *++p;
+          }
+         */
+        // possible optimization: invert the mask.
+    }
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        static $generic_names = array(
+            'serif' => true,
+            'sans-serif' => true,
+            'monospace' => true,
+            'fantasy' => true,
+            'cursive' => true
+        );
+        $allowed_fonts = $config->get('CSS.AllowedFonts');
+
+        // assume that no font names contain commas in them
+        $fonts = explode(',', $string);
+        $final = '';
+        foreach ($fonts as $font) {
+            $font = trim($font);
+            if ($font === '') {
+                continue;
+            }
+            // match a generic name
+            if (isset($generic_names[$font])) {
+                if ($allowed_fonts === null || isset($allowed_fonts[$font])) {
+                    $final .= $font . ', ';
+                }
+                continue;
+            }
+            // match a quoted name
+            if ($font[0] === '"' || $font[0] === "'") {
+                $length = strlen($font);
+                if ($length <= 2) {
+                    continue;
+                }
+                $quote = $font[0];
+                if ($font[$length - 1] !== $quote) {
+                    continue;
+                }
+                $font = substr($font, 1, $length - 2);
+            }
+
+            $font = $this->expandCSSEscape($font);
+
+            // $font is a pure representation of the font name
+
+            if ($allowed_fonts !== null && !isset($allowed_fonts[$font])) {
+                continue;
+            }
+
+            if (ctype_alnum($font) && $font !== '') {
+                // very simple font, allow it in unharmed
+                $final .= $font . ', ';
+                continue;
+            }
+
+            // bugger out on whitespace.  form feed (0C) really
+            // shouldn't show up regardless
+            $font = str_replace(array("\n", "\t", "\r", "\x0C"), ' ', $font);
+
+            // Here, there are various classes of characters which need
+            // to be treated differently:
+            //  - Alphanumeric characters are essentially safe.  We
+            //    handled these above.
+            //  - Spaces require quoting, though most parsers will do
+            //    the right thing if there aren't any characters that
+            //    can be misinterpreted
+            //  - Dashes rarely occur, but they fairly unproblematic
+            //    for parsing/rendering purposes.
+            //  The above characters cover the majority of Western font
+            //  names.
+            //  - Arbitrary Unicode characters not in ASCII.  Because
+            //    most parsers give little thought to Unicode, treatment
+            //    of these codepoints is basically uniform, even for
+            //    punctuation-like codepoints.  These characters can
+            //    show up in non-Western pages and are supported by most
+            //    major browsers, for example: "MS 明朝" is a
+            //    legitimate font-name
+            //    <http://ja.wikipedia.org/wiki/MS_明朝>.  See
+            //    the CSS3 spec for more examples:
+            //    <http://www.w3.org/TR/2011/WD-css3-fonts-20110324/localizedfamilynames.png>
+            //    You can see live samples of these on the Internet:
+            //    <http://www.google.co.jp/search?q=font-family+MS+明朝|ゴシック>
+            //    However, most of these fonts have ASCII equivalents:
+            //    for example, 'MS Mincho', and it's considered
+            //    professional to use ASCII font names instead of
+            //    Unicode font names.  Thanks Takeshi Terada for
+            //    providing this information.
+            //  The following characters, to my knowledge, have not been
+            //  used to name font names.
+            //  - Single quote.  While theoretically you might find a
+            //    font name that has a single quote in its name (serving
+            //    as an apostrophe, e.g. Dave's Scribble), I haven't
+            //    been able to find any actual examples of this.
+            //    Internet Explorer's cssText translation (which I
+            //    believe is invoked by innerHTML) normalizes any
+            //    quoting to single quotes, and fails to escape single
+            //    quotes.  (Note that this is not IE's behavior for all
+            //    CSS properties, just some sort of special casing for
+            //    font-family).  So a single quote *cannot* be used
+            //    safely in the font-family context if there will be an
+            //    innerHTML/cssText translation.  Note that Firefox 3.x
+            //    does this too.
+            //  - Double quote.  In IE, these get normalized to
+            //    single-quotes, no matter what the encoding.  (Fun
+            //    fact, in IE8, the 'content' CSS property gained
+            //    support, where they special cased to preserve encoded
+            //    double quotes, but still translate unadorned double
+            //    quotes into single quotes.)  So, because their
+            //    fixpoint behavior is identical to single quotes, they
+            //    cannot be allowed either.  Firefox 3.x displays
+            //    single-quote style behavior.
+            //  - Backslashes are reduced by one (so \\ -> \) every
+            //    iteration, so they cannot be used safely.  This shows
+            //    up in IE7, IE8 and FF3
+            //  - Semicolons, commas and backticks are handled properly.
+            //  - The rest of the ASCII punctuation is handled properly.
+            // We haven't checked what browsers do to unadorned
+            // versions, but this is not important as long as the
+            // browser doesn't /remove/ surrounding quotes (as IE does
+            // for HTML).
+            //
+            // With these results in hand, we conclude that there are
+            // various levels of safety:
+            //  - Paranoid: alphanumeric, spaces and dashes(?)
+            //  - International: Paranoid + non-ASCII Unicode
+            //  - Edgy: Everything except quotes, backslashes
+            //  - NoJS: Standards compliance, e.g. sod IE. Note that
+            //    with some judicious character escaping (since certain
+            //    types of escaping doesn't work) this is theoretically
+            //    OK as long as innerHTML/cssText is not called.
+            // We believe that international is a reasonable default
+            // (that we will implement now), and once we do more
+            // extensive research, we may feel comfortable with dropping
+            // it down to edgy.
+
+            // Edgy: alphanumeric, spaces, dashes, underscores and Unicode.  Use of
+            // str(c)spn assumes that the string was already well formed
+            // Unicode (which of course it is).
+            if (strspn($font, $this->mask) !== strlen($font)) {
+                continue;
+            }
+
+            // Historical:
+            // In the absence of innerHTML/cssText, these ugly
+            // transforms don't pose a security risk (as \\ and \"
+            // might--these escapes are not supported by most browsers).
+            // We could try to be clever and use single-quote wrapping
+            // when there is a double quote present, but I have choosen
+            // not to implement that.  (NOTE: you can reduce the amount
+            // of escapes by one depending on what quoting style you use)
+            // $font = str_replace('\\', '\\5C ', $font);
+            // $font = str_replace('"',  '\\22 ', $font);
+            // $font = str_replace("'",  '\\27 ', $font);
+
+            // font possibly with spaces, requires quoting
+            $final .= "'$font', ";
+        }
+        $final = rtrim($final, ', ');
+        if ($final === '') {
+            return false;
+        }
+        return $final;
+    }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php
new file mode 100644
index 0000000000..973002c17f
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ident.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Validates based on {ident} CSS grammar production
+ */
+class HTMLPurifier_AttrDef_CSS_Ident extends HTMLPurifier_AttrDef
+{
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        $string = trim($string);
+
+        // early abort: '' and '0' (strings that convert to false) are invalid
+        if (!$string) {
+            return false;
+        }
+
+        $pattern = '/^(-?[A-Za-z_][A-Za-z_\-0-9]*)$/';
+        if (!preg_match($pattern, $string)) {
+            return false;
+        }
+        return $string;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
similarity index 62%
rename from library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
index 4e6b35e5a0..ffc989fe80 100644
--- a/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ImportantDecorator.php
@@ -5,20 +5,34 @@
  */
 class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
 {
-    public $def, $allow;
+    /**
+     * @type HTMLPurifier_AttrDef
+     */
+    public $def;
+    /**
+     * @type bool
+     */
+    public $allow;
 
     /**
-     * @param $def Definition to wrap
-     * @param $allow Whether or not to allow !important
+     * @param HTMLPurifier_AttrDef $def Definition to wrap
+     * @param bool $allow Whether or not to allow !important
      */
-    public function __construct($def, $allow = false) {
+    public function __construct($def, $allow = false)
+    {
         $this->def = $def;
         $this->allow = $allow;
     }
+
     /**
      * Intercepts and removes !important if necessary
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
      */
-    public function validate($string, $config, $context) {
+    public function validate($string, $config, $context)
+    {
         // test for ! and important tokens
         $string = trim($string);
         $is_important = false;
@@ -32,7 +46,9 @@ class HTMLPurifier_AttrDef_CSS_ImportantDecorator extends HTMLPurifier_AttrDef
             }
         }
         $string = $this->def->validate($string, $config, $context);
-        if ($this->allow && $is_important) $string .= ' !important';
+        if ($this->allow && $is_important) {
+            $string .= ' !important';
+        }
         return $string;
     }
 }
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php
new file mode 100644
index 0000000000..f12453a04a
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Length.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * Represents a Length as defined by CSS.
+ */
+class HTMLPurifier_AttrDef_CSS_Length extends HTMLPurifier_AttrDef
+{
+
+    /**
+     * @type HTMLPurifier_Length|string
+     */
+    protected $min;
+
+    /**
+     * @type HTMLPurifier_Length|string
+     */
+    protected $max;
+
+    /**
+     * @param HTMLPurifier_Length|string $min Minimum length, or null for no bound. String is also acceptable.
+     * @param HTMLPurifier_Length|string $max Maximum length, or null for no bound. String is also acceptable.
+     */
+    public function __construct($min = null, $max = null)
+    {
+        $this->min = $min !== null ? HTMLPurifier_Length::make($min) : null;
+        $this->max = $max !== null ? HTMLPurifier_Length::make($max) : null;
+    }
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        $string = $this->parseCDATA($string);
+
+        // Optimizations
+        if ($string === '') {
+            return false;
+        }
+        if ($string === '0') {
+            return '0';
+        }
+        if (strlen($string) === 1) {
+            return false;
+        }
+
+        $length = HTMLPurifier_Length::make($string);
+        if (!$length->isValid()) {
+            return false;
+        }
+
+        if ($this->min) {
+            $c = $length->compareTo($this->min);
+            if ($c === false) {
+                return false;
+            }
+            if ($c < 0) {
+                return false;
+            }
+        }
+        if ($this->max) {
+            $c = $length->compareTo($this->max);
+            if ($c === false) {
+                return false;
+            }
+            if ($c > 0) {
+                return false;
+            }
+        }
+        return $length->toString();
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
new file mode 100644
index 0000000000..e74d42654e
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/ListStyle.php
@@ -0,0 +1,112 @@
+<?php
+
+/**
+ * Validates shorthand CSS property list-style.
+ * @warning Does not support url tokens that have internal spaces.
+ */
+class HTMLPurifier_AttrDef_CSS_ListStyle extends HTMLPurifier_AttrDef
+{
+
+    /**
+     * Local copy of validators.
+     * @type HTMLPurifier_AttrDef[]
+     * @note See HTMLPurifier_AttrDef_CSS_Font::$info for a similar impl.
+     */
+    protected $info;
+
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function __construct($config)
+    {
+        $def = $config->getCSSDefinition();
+        $this->info['list-style-type'] = $def->info['list-style-type'];
+        $this->info['list-style-position'] = $def->info['list-style-position'];
+        $this->info['list-style-image'] = $def->info['list-style-image'];
+    }
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        // regular pre-processing
+        $string = $this->parseCDATA($string);
+        if ($string === '') {
+            return false;
+        }
+
+        // assumes URI doesn't have spaces in it
+        $bits = explode(' ', strtolower($string)); // bits to process
+
+        $caught = array();
+        $caught['type'] = false;
+        $caught['position'] = false;
+        $caught['image'] = false;
+
+        $i = 0; // number of catches
+        $none = false;
+
+        foreach ($bits as $bit) {
+            if ($i >= 3) {
+                return;
+            } // optimization bit
+            if ($bit === '') {
+                continue;
+            }
+            foreach ($caught as $key => $status) {
+                if ($status !== false) {
+                    continue;
+                }
+                $r = $this->info['list-style-' . $key]->validate($bit, $config, $context);
+                if ($r === false) {
+                    continue;
+                }
+                if ($r === 'none') {
+                    if ($none) {
+                        continue;
+                    } else {
+                        $none = true;
+                    }
+                    if ($key == 'image') {
+                        continue;
+                    }
+                }
+                $caught[$key] = $r;
+                $i++;
+                break;
+            }
+        }
+
+        if (!$i) {
+            return false;
+        }
+
+        $ret = array();
+
+        // construct type
+        if ($caught['type']) {
+            $ret[] = $caught['type'];
+        }
+
+        // construct image
+        if ($caught['image']) {
+            $ret[] = $caught['image'];
+        }
+
+        // construct position
+        if ($caught['position']) {
+            $ret[] = $caught['position'];
+        }
+
+        if (empty($ret)) {
+            return false;
+        }
+        return implode(' ', $ret);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Multiple.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php
similarity index 65%
rename from library/HTMLPurifier/AttrDef/CSS/Multiple.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php
index 4d62a40d7f..e707f871ca 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Multiple.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php
@@ -13,9 +13,9 @@
  */
 class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
 {
-
     /**
      * Instance of component definition to defer validation to.
+     * @type HTMLPurifier_AttrDef
      * @todo Make protected
      */
     public $single;
@@ -27,32 +27,45 @@ class HTMLPurifier_AttrDef_CSS_Multiple extends HTMLPurifier_AttrDef
     public $max;
 
     /**
-     * @param $single HTMLPurifier_AttrDef to multiply
-     * @param $max Max number of values allowed (usually four)
+     * @param HTMLPurifier_AttrDef $single HTMLPurifier_AttrDef to multiply
+     * @param int $max Max number of values allowed (usually four)
      */
-    public function __construct($single, $max = 4) {
+    public function __construct($single, $max = 4)
+    {
         $this->single = $single;
         $this->max = $max;
     }
 
-    public function validate($string, $config, $context) {
-        $string = $this->parseCDATA($string);
-        if ($string === '') return false;
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        $string = $this->mungeRgb($this->parseCDATA($string));
+        if ($string === '') {
+            return false;
+        }
         $parts = explode(' ', $string); // parseCDATA replaced \r, \t and \n
         $length = count($parts);
         $final = '';
         for ($i = 0, $num = 0; $i < $length && $num < $this->max; $i++) {
-            if (ctype_space($parts[$i])) continue;
+            if (ctype_space($parts[$i])) {
+                continue;
+            }
             $result = $this->single->validate($parts[$i], $config, $context);
             if ($result !== false) {
                 $final .= $result . ' ';
                 $num++;
             }
         }
-        if ($final === '') return false;
+        if ($final === '') {
+            return false;
+        }
         return rtrim($final);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/Number.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php
similarity index 55%
rename from library/HTMLPurifier/AttrDef/CSS/Number.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php
index 3f99e12ec2..8edc159e72 100644
--- a/library/HTMLPurifier/AttrDef/CSS/Number.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php
@@ -7,32 +7,44 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
 {
 
     /**
-     * Bool indicating whether or not only positive values allowed.
+     * Indicates whether or not only positive values are allowed.
+     * @type bool
      */
     protected $non_negative = false;
 
     /**
-     * @param $non_negative Bool indicating whether negatives are forbidden
+     * @param bool $non_negative indicates whether negatives are forbidden
      */
-    public function __construct($non_negative = false) {
+    public function __construct($non_negative = false)
+    {
         $this->non_negative = $non_negative;
     }
 
     /**
+     * @param string $number
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string|bool
      * @warning Some contexts do not pass $config, $context. These
      *          variables should not be used without checking HTMLPurifier_Length
      */
-    public function validate($number, $config, $context) {
-
+    public function validate($number, $config, $context)
+    {
         $number = $this->parseCDATA($number);
 
-        if ($number === '') return false;
-        if ($number === '0') return '0';
+        if ($number === '') {
+            return false;
+        }
+        if ($number === '0') {
+            return '0';
+        }
 
         $sign = '';
         switch ($number[0]) {
             case '-':
-                if ($this->non_negative) return false;
+                if ($this->non_negative) {
+                    return false;
+                }
                 $sign = '-';
             case '+':
                 $number = substr($number, 1);
@@ -44,14 +56,20 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
         }
 
         // Period is the only non-numeric character allowed
-        if (strpos($number, '.') === false) return false;
+        if (strpos($number, '.') === false) {
+            return false;
+        }
 
         list($left, $right) = explode('.', $number, 2);
 
-        if ($left === '' && $right === '') return false;
-        if ($left !== '' && !ctype_digit($left)) return false;
+        if ($left === '' && $right === '') {
+            return false;
+        }
+        if ($left !== '' && !ctype_digit($left)) {
+            return false;
+        }
 
-        $left  = ltrim($left,  '0');
+        $left = ltrim($left, '0');
         $right = rtrim($right, '0');
 
         if ($right === '') {
@@ -59,11 +77,8 @@ class HTMLPurifier_AttrDef_CSS_Number extends HTMLPurifier_AttrDef
         } elseif (!ctype_digit($right)) {
             return false;
         }
-
         return $sign . $left . '.' . $right;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php
new file mode 100644
index 0000000000..f0f25c50a8
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * Validates a Percentage as defined by the CSS spec.
+ */
+class HTMLPurifier_AttrDef_CSS_Percentage extends HTMLPurifier_AttrDef
+{
+
+    /**
+     * Instance to defer number validation to.
+     * @type HTMLPurifier_AttrDef_CSS_Number
+     */
+    protected $number_def;
+
+    /**
+     * @param bool $non_negative Whether to forbid negative values
+     */
+    public function __construct($non_negative = false)
+    {
+        $this->number_def = new HTMLPurifier_AttrDef_CSS_Number($non_negative);
+    }
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        $string = $this->parseCDATA($string);
+
+        if ($string === '') {
+            return false;
+        }
+        $length = strlen($string);
+        if ($length === 1) {
+            return false;
+        }
+        if ($string[$length - 1] !== '%') {
+            return false;
+        }
+
+        $number = substr($string, 0, $length - 1);
+        $number = $this->number_def->validate($number, $config, $context);
+
+        if ($number === false) {
+            return false;
+        }
+        return "$number%";
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
similarity index 69%
rename from library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
index 772c922d80..5fd4b7f7b4 100644
--- a/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php
@@ -8,8 +8,14 @@
 class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
 {
 
-    public function validate($string, $config, $context) {
-
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         static $allowed_values = array(
             'line-through' => true,
             'overline' => true,
@@ -18,7 +24,9 @@ class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
 
         $string = strtolower($this->parseCDATA($string));
 
-        if ($string === 'none') return $string;
+        if ($string === 'none') {
+            return $string;
+        }
 
         $parts = explode(' ', $string);
         $final = '';
@@ -28,11 +36,11 @@ class HTMLPurifier_AttrDef_CSS_TextDecoration extends HTMLPurifier_AttrDef
             }
         }
         $final = rtrim($final);
-        if ($final === '') return false;
+        if ($final === '') {
+            return false;
+        }
         return $final;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/CSS/URI.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php
similarity index 58%
rename from library/HTMLPurifier/AttrDef/CSS/URI.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php
index 1df17dc25b..f9434230e2 100644
--- a/library/HTMLPurifier/AttrDef/CSS/URI.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php
@@ -12,25 +12,39 @@
 class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
 {
 
-    public function __construct() {
+    public function __construct()
+    {
         parent::__construct(true); // always embedded
     }
 
-    public function validate($uri_string, $config, $context) {
+    /**
+     * @param string $uri_string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($uri_string, $config, $context)
+    {
         // parse the URI out of the string and then pass it onto
         // the parent object
 
         $uri_string = $this->parseCDATA($uri_string);
-        if (strpos($uri_string, 'url(') !== 0) return false;
+        if (strpos($uri_string, 'url(') !== 0) {
+            return false;
+        }
         $uri_string = substr($uri_string, 4);
         $new_length = strlen($uri_string) - 1;
-        if ($uri_string[$new_length] != ')') return false;
+        if ($uri_string[$new_length] != ')') {
+            return false;
+        }
         $uri = trim(substr($uri_string, 0, $new_length));
 
         if (!empty($uri) && ($uri[0] == "'" || $uri[0] == '"')) {
             $quote = $uri[0];
             $new_length = strlen($uri) - 1;
-            if ($uri[$new_length] !== $quote) return false;
+            if ($uri[$new_length] !== $quote) {
+                return false;
+            }
             $uri = substr($uri, 1, $new_length - 1);
         }
 
@@ -38,15 +52,23 @@ class HTMLPurifier_AttrDef_CSS_URI extends HTMLPurifier_AttrDef_URI
 
         $result = parent::validate($uri, $config, $context);
 
-        if ($result === false) return false;
+        if ($result === false) {
+            return false;
+        }
 
         // extra sanity check; should have been done by URI
         $result = str_replace(array('"', "\\", "\n", "\x0c", "\r"), "", $result);
 
+        // suspicious characters are ()'; we're going to percent encode
+        // them for safety.
+        $result = str_replace(array('(', ')', "'"), array('%28', '%29', '%27'), $result);
+
+        // there's an extra bug where ampersands lose their escaping on
+        // an innerHTML cycle, so a very unlucky query parameter could
+        // then change the meaning of the URL.  Unfortunately, there's
+        // not much we can do about that...
         return "url(\"$result\")";
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php
new file mode 100644
index 0000000000..6698a00c01
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * Dummy AttrDef that mimics another AttrDef, BUT it generates clones
+ * with make.
+ */
+class HTMLPurifier_AttrDef_Clone extends HTMLPurifier_AttrDef
+{
+    /**
+     * What we're cloning.
+     * @type HTMLPurifier_AttrDef
+     */
+    protected $clone;
+
+    /**
+     * @param HTMLPurifier_AttrDef $clone
+     */
+    public function __construct($clone)
+    {
+        $this->clone = $clone;
+    }
+
+    /**
+     * @param string $v
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($v, $config, $context)
+    {
+        return $this->clone->validate($v, $config, $context);
+    }
+
+    /**
+     * @param string $string
+     * @return HTMLPurifier_AttrDef
+     */
+    public function make($string)
+    {
+        return clone $this->clone;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/Enum.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php
similarity index 70%
rename from library/HTMLPurifier/AttrDef/Enum.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php
index 5d603ebcc6..8abda7f6e2 100644
--- a/library/HTMLPurifier/AttrDef/Enum.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Enum.php
@@ -12,9 +12,10 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
 
     /**
      * Lookup table of valid values.
+     * @type array
      * @todo Make protected
      */
-    public $valid_values   = array();
+    public $valid_values = array();
 
     /**
      * Bool indicating whether or not enumeration is case sensitive.
@@ -23,17 +24,23 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
     protected $case_sensitive = false; // values according to W3C spec
 
     /**
-     * @param $valid_values List of valid values
-     * @param $case_sensitive Bool indicating whether or not case sensitive
+     * @param array $valid_values List of valid values
+     * @param bool $case_sensitive Whether or not case sensitive
      */
-    public function __construct(
-        $valid_values = array(), $case_sensitive = false
-    ) {
+    public function __construct($valid_values = array(), $case_sensitive = false)
+    {
         $this->valid_values = array_flip($valid_values);
         $this->case_sensitive = $case_sensitive;
     }
 
-    public function validate($string, $config, $context) {
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         $string = trim($string);
         if (!$this->case_sensitive) {
             // we may want to do full case-insensitive libraries
@@ -45,11 +52,13 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
     }
 
     /**
-     * @param $string In form of comma-delimited list of case-insensitive
+     * @param string $string In form of comma-delimited list of case-insensitive
      *      valid values. Example: "foo,bar,baz". Prepend "s:" to make
      *      case sensitive
+     * @return HTMLPurifier_AttrDef_Enum
      */
-    public function make($string) {
+    public function make($string)
+    {
         if (strlen($string) > 2 && $string[0] == 's' && $string[1] == ':') {
             $string = substr($string, 2);
             $sensitive = true;
@@ -59,7 +68,6 @@ class HTMLPurifier_AttrDef_Enum extends HTMLPurifier_AttrDef
         $values = explode(',', $string);
         return new HTMLPurifier_AttrDef_Enum($values, $sensitive);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php
new file mode 100644
index 0000000000..dea15d2cd2
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Bool.php
@@ -0,0 +1,48 @@
+<?php
+
+/**
+ * Validates a boolean attribute
+ */
+class HTMLPurifier_AttrDef_HTML_Bool extends HTMLPurifier_AttrDef
+{
+
+    /**
+     * @type bool
+     */
+    protected $name;
+
+    /**
+     * @type bool
+     */
+    public $minimized = true;
+
+    /**
+     * @param bool $name
+     */
+    public function __construct($name = false)
+    {
+        $this->name = $name;
+    }
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        return $this->name;
+    }
+
+    /**
+     * @param string $string Name of attribute
+     * @return HTMLPurifier_AttrDef_HTML_Bool
+     */
+    public function make($string)
+    {
+        return new HTMLPurifier_AttrDef_HTML_Bool($string);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/HTML/Class.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php
similarity index 66%
rename from library/HTMLPurifier/AttrDef/HTML/Class.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php
index 370068d975..d5013488fc 100644
--- a/library/HTMLPurifier/AttrDef/HTML/Class.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Class.php
@@ -5,7 +5,14 @@
  */
 class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
 {
-    protected function split($string, $config, $context) {
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    protected function split($string, $config, $context)
+    {
         // really, this twiddle should be lazy loaded
         $name = $config->getDefinition('HTML')->doctype->name;
         if ($name == "XHTML 1.1" || $name == "XHTML 2.0") {
@@ -14,13 +21,20 @@ class HTMLPurifier_AttrDef_HTML_Class extends HTMLPurifier_AttrDef_HTML_Nmtokens
             return preg_split('/\s+/', $string);
         }
     }
-    protected function filter($tokens, $config, $context) {
+
+    /**
+     * @param array $tokens
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    protected function filter($tokens, $config, $context)
+    {
         $allowed = $config->get('Attr.AllowedClasses');
         $forbidden = $config->get('Attr.ForbiddenClasses');
         $ret = array();
         foreach ($tokens as $token) {
-            if (
-                ($allowed === null || isset($allowed[$token])) &&
+            if (($allowed === null || isset($allowed[$token])) &&
                 !isset($forbidden[$token]) &&
                 // We need this O(n) check because of PHP's array
                 // implementation that casts -0 to 0.
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php
new file mode 100644
index 0000000000..946ebb7820
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Color.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * Validates a color according to the HTML spec.
+ */
+class HTMLPurifier_AttrDef_HTML_Color extends HTMLPurifier_AttrDef
+{
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        static $colors = null;
+        if ($colors === null) {
+            $colors = $config->get('Core.ColorKeywords');
+        }
+
+        $string = trim($string);
+
+        if (empty($string)) {
+            return false;
+        }
+        $lower = strtolower($string);
+        if (isset($colors[$lower])) {
+            return $colors[$lower];
+        }
+        if ($string[0] === '#') {
+            $hex = substr($string, 1);
+        } else {
+            $hex = $string;
+        }
+
+        $length = strlen($hex);
+        if ($length !== 3 && $length !== 6) {
+            return false;
+        }
+        if (!ctype_xdigit($hex)) {
+            return false;
+        }
+        if ($length === 3) {
+            $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2];
+        }
+        return "#$hex";
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
new file mode 100644
index 0000000000..d79ba12b3f
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/FrameTarget.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * Special-case enum attribute definition that lazy loads allowed frame targets
+ */
+class HTMLPurifier_AttrDef_HTML_FrameTarget extends HTMLPurifier_AttrDef_Enum
+{
+
+    /**
+     * @type array
+     */
+    public $valid_values = false; // uninitialized value
+
+    /**
+     * @type bool
+     */
+    protected $case_sensitive = false;
+
+    public function __construct()
+    {
+    }
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        if ($this->valid_values === false) {
+            $this->valid_values = $config->get('Attr.AllowedFrameTargets');
+        }
+        return parent::validate($string, $config, $context);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php
new file mode 100644
index 0000000000..3d86efb44c
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/ID.php
@@ -0,0 +1,105 @@
+<?php
+
+/**
+ * Validates the HTML attribute ID.
+ * @warning Even though this is the id processor, it
+ *          will ignore the directive Attr:IDBlacklist, since it will only
+ *          go according to the ID accumulator. Since the accumulator is
+ *          automatically generated, it will have already absorbed the
+ *          blacklist. If you're hacking around, make sure you use load()!
+ */
+
+class HTMLPurifier_AttrDef_HTML_ID extends HTMLPurifier_AttrDef
+{
+
+    // selector is NOT a valid thing to use for IDREFs, because IDREFs
+    // *must* target IDs that exist, whereas selector #ids do not.
+
+    /**
+     * Determines whether or not we're validating an ID in a CSS
+     * selector context.
+     * @type bool
+     */
+    protected $selector;
+
+    /**
+     * @param bool $selector
+     */
+    public function __construct($selector = false)
+    {
+        $this->selector = $selector;
+    }
+
+    /**
+     * @param string $id
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($id, $config, $context)
+    {
+        if (!$this->selector && !$config->get('Attr.EnableID')) {
+            return false;
+        }
+
+        $id = trim($id); // trim it first
+
+        if ($id === '') {
+            return false;
+        }
+
+        $prefix = $config->get('Attr.IDPrefix');
+        if ($prefix !== '') {
+            $prefix .= $config->get('Attr.IDPrefixLocal');
+            // prevent re-appending the prefix
+            if (strpos($id, $prefix) !== 0) {
+                $id = $prefix . $id;
+            }
+        } elseif ($config->get('Attr.IDPrefixLocal') !== '') {
+            trigger_error(
+                '%Attr.IDPrefixLocal cannot be used unless ' .
+                '%Attr.IDPrefix is set',
+                E_USER_WARNING
+            );
+        }
+
+        if (!$this->selector) {
+            $id_accumulator =& $context->get('IDAccumulator');
+            if (isset($id_accumulator->ids[$id])) {
+                return false;
+            }
+        }
+
+        // we purposely avoid using regex, hopefully this is faster
+
+        if (ctype_alpha($id)) {
+            $result = true;
+        } else {
+            if (!ctype_alpha(@$id[0])) {
+                return false;
+            }
+            // primitive style of regexps, I suppose
+            $trim = trim(
+                $id,
+                'A..Za..z0..9:-._'
+            );
+            $result = ($trim === '');
+        }
+
+        $regexp = $config->get('Attr.IDBlacklistRegexp');
+        if ($regexp && preg_match($regexp, $id)) {
+            return false;
+        }
+
+        if (!$this->selector && $result) {
+            $id_accumulator->add($id);
+        }
+
+        // if no change was made to the ID, return the result
+        // else, return the new id if stripping whitespace made it
+        //     valid, or return false.
+        return $result ? $id : false;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php
new file mode 100644
index 0000000000..1c4006fbbd
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Length.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * Validates the HTML type length (not to be confused with CSS's length).
+ *
+ * This accepts integer pixels or percentages as lengths for certain
+ * HTML attributes.
+ */
+
+class HTMLPurifier_AttrDef_HTML_Length extends HTMLPurifier_AttrDef_HTML_Pixels
+{
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        $string = trim($string);
+        if ($string === '') {
+            return false;
+        }
+
+        $parent_result = parent::validate($string, $config, $context);
+        if ($parent_result !== false) {
+            return $parent_result;
+        }
+
+        $length = strlen($string);
+        $last_char = $string[$length - 1];
+
+        if ($last_char !== '%') {
+            return false;
+        }
+
+        $points = substr($string, 0, $length - 1);
+
+        if (!is_numeric($points)) {
+            return false;
+        }
+
+        $points = (int)$points;
+
+        if ($points < 0) {
+            return '0%';
+        }
+        if ($points > 100) {
+            return '100%';
+        }
+        return ((string)$points) . '%';
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php
similarity index 56%
rename from library/HTMLPurifier/AttrDef/HTML/LinkTypes.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php
index 76d25ed088..63fa04c15c 100644
--- a/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/LinkTypes.php
@@ -9,26 +9,44 @@
 class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
 {
 
-    /** Name config attribute to pull. */
+    /**
+     * Name config attribute to pull.
+     * @type string
+     */
     protected $name;
 
-    public function __construct($name) {
+    /**
+     * @param string $name
+     */
+    public function __construct($name)
+    {
         $configLookup = array(
             'rel' => 'AllowedRel',
             'rev' => 'AllowedRev'
         );
         if (!isset($configLookup[$name])) {
-            trigger_error('Unrecognized attribute name for link '.
-                'relationship.', E_USER_ERROR);
+            trigger_error(
+                'Unrecognized attribute name for link ' .
+                'relationship.',
+                E_USER_ERROR
+            );
             return;
         }
         $this->name = $configLookup[$name];
     }
 
-    public function validate($string, $config, $context) {
-
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         $allowed = $config->get('Attr.' . $this->name);
-        if (empty($allowed)) return false;
+        if (empty($allowed)) {
+            return false;
+        }
 
         $string = $this->parseCDATA($string);
         $parts = explode(' ', $string);
@@ -37,17 +55,18 @@ class HTMLPurifier_AttrDef_HTML_LinkTypes extends HTMLPurifier_AttrDef
         $ret_lookup = array();
         foreach ($parts as $part) {
             $part = strtolower(trim($part));
-            if (!isset($allowed[$part])) continue;
+            if (!isset($allowed[$part])) {
+                continue;
+            }
             $ret_lookup[$part] = true;
         }
 
-        if (empty($ret_lookup)) return false;
+        if (empty($ret_lookup)) {
+            return false;
+        }
         $string = implode(' ', array_keys($ret_lookup));
-
         return $string;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php
new file mode 100644
index 0000000000..bbb20f2f80
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/MultiLength.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * Validates a MultiLength as defined by the HTML spec.
+ *
+ * A multilength is either a integer (pixel count), a percentage, or
+ * a relative number.
+ */
+class HTMLPurifier_AttrDef_HTML_MultiLength extends HTMLPurifier_AttrDef_HTML_Length
+{
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        $string = trim($string);
+        if ($string === '') {
+            return false;
+        }
+
+        $parent_result = parent::validate($string, $config, $context);
+        if ($parent_result !== false) {
+            return $parent_result;
+        }
+
+        $length = strlen($string);
+        $last_char = $string[$length - 1];
+
+        if ($last_char !== '*') {
+            return false;
+        }
+
+        $int = substr($string, 0, $length - 1);
+
+        if ($int == '') {
+            return '*';
+        }
+        if (!is_numeric($int)) {
+            return false;
+        }
+
+        $int = (int)$int;
+        if ($int < 0) {
+            return false;
+        }
+        if ($int == 0) {
+            return '0';
+        }
+        if ($int == 1) {
+            return '*';
+        }
+        return ((string)$int) . '*';
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php
similarity index 55%
rename from library/HTMLPurifier/AttrDef/HTML/Nmtokens.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php
index aa34120bd2..f79683b4fc 100644
--- a/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Nmtokens.php
@@ -6,24 +6,38 @@
 class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
 {
 
-    public function validate($string, $config, $context) {
-
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         $string = trim($string);
 
         // early abort: '' and '0' (strings that convert to false) are invalid
-        if (!$string) return false;
+        if (!$string) {
+            return false;
+        }
 
         $tokens = $this->split($string, $config, $context);
         $tokens = $this->filter($tokens, $config, $context);
-        if (empty($tokens)) return false;
+        if (empty($tokens)) {
+            return false;
+        }
         return implode(' ', $tokens);
-
     }
 
     /**
      * Splits a space separated list of tokens into its constituent parts.
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
      */
-    protected function split($string, $config, $context) {
+    protected function split($string, $config, $context)
+    {
         // OPTIMIZABLE!
         // do the preg_match, capture all subpatterns for reformulation
 
@@ -31,9 +45,9 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
         // escaping because I don't know how to do that with regexps
         // and plus it would complicate optimization efforts (you never
         // see that anyway).
-        $pattern = '/(?:(?<=\s)|\A)'. // look behind for space or string start
-                   '((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)'.
-                   '(?:(?=\s)|\z)/'; // look ahead for space or string end
+        $pattern = '/(?:(?<=\s)|\A)' . // look behind for space or string start
+            '((?:--|-?[A-Za-z_])[A-Za-z_\-0-9]*)' .
+            '(?:(?=\s)|\z)/'; // look ahead for space or string end
         preg_match_all($pattern, $string, $matches);
         return $matches[1];
     }
@@ -42,11 +56,15 @@ class HTMLPurifier_AttrDef_HTML_Nmtokens extends HTMLPurifier_AttrDef
      * Template method for removing certain tokens based on arbitrary criteria.
      * @note If we wanted to be really functional, we'd do an array_filter
      *       with a callback. But... we're not.
+     * @param array $tokens
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
      */
-    protected function filter($tokens, $config, $context) {
+    protected function filter($tokens, $config, $context)
+    {
         return $tokens;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php
new file mode 100644
index 0000000000..a1d019e095
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/HTML/Pixels.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * Validates an integer representation of pixels according to the HTML spec.
+ */
+class HTMLPurifier_AttrDef_HTML_Pixels extends HTMLPurifier_AttrDef
+{
+
+    /**
+     * @type int
+     */
+    protected $max;
+
+    /**
+     * @param int $max
+     */
+    public function __construct($max = null)
+    {
+        $this->max = $max;
+    }
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        $string = trim($string);
+        if ($string === '0') {
+            return $string;
+        }
+        if ($string === '') {
+            return false;
+        }
+        $length = strlen($string);
+        if (substr($string, $length - 2) == 'px') {
+            $string = substr($string, 0, $length - 2);
+        }
+        if (!is_numeric($string)) {
+            return false;
+        }
+        $int = (int)$string;
+
+        if ($int < 0) {
+            return '0';
+        }
+
+        // upper-bound value, extremely high values can
+        // crash operating systems, see <http://ha.ckers.org/imagecrash.html>
+        // WARNING, above link WILL crash you if you're using Windows
+
+        if ($this->max !== null && $int > $this->max) {
+            return (string)$this->max;
+        }
+        return (string)$int;
+    }
+
+    /**
+     * @param string $string
+     * @return HTMLPurifier_AttrDef
+     */
+    public function make($string)
+    {
+        if ($string === '') {
+            $max = null;
+        } else {
+            $max = (int)$string;
+        }
+        $class = get_class($this);
+        return new $class($max);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/Integer.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php
similarity index 55%
rename from library/HTMLPurifier/AttrDef/Integer.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php
index d59738d2a2..400e707d2f 100644
--- a/library/HTMLPurifier/AttrDef/Integer.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Integer.php
@@ -11,17 +11,20 @@ class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef
 {
 
     /**
-     * Bool indicating whether or not negative values are allowed
+     * Whether or not negative values are allowed.
+     * @type bool
      */
     protected $negative = true;
 
     /**
-     * Bool indicating whether or not zero is allowed
+     * Whether or not zero is allowed.
+     * @type bool
      */
     protected $zero = true;
 
     /**
-     * Bool indicating whether or not positive values are allowed
+     * Whether or not positive values are allowed.
+     * @type bool
      */
     protected $positive = true;
 
@@ -30,44 +33,59 @@ class HTMLPurifier_AttrDef_Integer extends HTMLPurifier_AttrDef
      * @param $zero Bool indicating whether or not zero is allowed
      * @param $positive Bool indicating whether or not positive values are allowed
      */
-    public function __construct(
-        $negative = true, $zero = true, $positive = true
-    ) {
+    public function __construct($negative = true, $zero = true, $positive = true)
+    {
         $this->negative = $negative;
-        $this->zero     = $zero;
+        $this->zero = $zero;
         $this->positive = $positive;
     }
 
-    public function validate($integer, $config, $context) {
-
+    /**
+     * @param string $integer
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($integer, $config, $context)
+    {
         $integer = $this->parseCDATA($integer);
-        if ($integer === '') return false;
+        if ($integer === '') {
+            return false;
+        }
 
         // we could possibly simply typecast it to integer, but there are
         // certain fringe cases that must not return an integer.
 
         // clip leading sign
-        if ( $this->negative && $integer[0] === '-' ) {
+        if ($this->negative && $integer[0] === '-') {
             $digits = substr($integer, 1);
-            if ($digits === '0') $integer = '0'; // rm minus sign for zero
-        } elseif( $this->positive && $integer[0] === '+' ) {
+            if ($digits === '0') {
+                $integer = '0';
+            } // rm minus sign for zero
+        } elseif ($this->positive && $integer[0] === '+') {
             $digits = $integer = substr($integer, 1); // rm unnecessary plus
         } else {
             $digits = $integer;
         }
 
         // test if it's numeric
-        if (!ctype_digit($digits)) return false;
+        if (!ctype_digit($digits)) {
+            return false;
+        }
 
         // perform scope tests
-        if (!$this->zero     && $integer == 0) return false;
-        if (!$this->positive && $integer > 0) return false;
-        if (!$this->negative && $integer < 0) return false;
+        if (!$this->zero && $integer == 0) {
+            return false;
+        }
+        if (!$this->positive && $integer > 0) {
+            return false;
+        }
+        if (!$this->negative && $integer < 0) {
+            return false;
+        }
 
         return $integer;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/Lang.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php
similarity index 67%
rename from library/HTMLPurifier/AttrDef/Lang.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php
index 10e6da56db..2a55cea642 100644
--- a/library/HTMLPurifier/AttrDef/Lang.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Lang.php
@@ -7,15 +7,25 @@
 class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
 {
 
-    public function validate($string, $config, $context) {
-
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         $string = trim($string);
-        if (!$string) return false;
+        if (!$string) {
+            return false;
+        }
 
         $subtags = explode('-', $string);
         $num_subtags = count($subtags);
 
-        if ($num_subtags == 0) return false; // sanity check
+        if ($num_subtags == 0) { // sanity check
+            return false;
+        }
 
         // process primary subtag : $subtags[0]
         $length = strlen($subtags[0]);
@@ -23,15 +33,15 @@ class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
             case 0:
                 return false;
             case 1:
-                if (! ($subtags[0] == 'x' || $subtags[0] == 'i') ) {
+                if (!($subtags[0] == 'x' || $subtags[0] == 'i')) {
                     return false;
                 }
                 break;
             case 2:
             case 3:
-                if (! ctype_alpha($subtags[0]) ) {
+                if (!ctype_alpha($subtags[0])) {
                     return false;
-                } elseif (! ctype_lower($subtags[0]) ) {
+                } elseif (!ctype_lower($subtags[0])) {
                     $subtags[0] = strtolower($subtags[0]);
                 }
                 break;
@@ -40,17 +50,23 @@ class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
         }
 
         $new_string = $subtags[0];
-        if ($num_subtags == 1) return $new_string;
+        if ($num_subtags == 1) {
+            return $new_string;
+        }
 
         // process second subtag : $subtags[1]
         $length = strlen($subtags[1]);
         if ($length == 0 || ($length == 1 && $subtags[1] != 'x') || $length > 8 || !ctype_alnum($subtags[1])) {
             return $new_string;
         }
-        if (!ctype_lower($subtags[1])) $subtags[1] = strtolower($subtags[1]);
+        if (!ctype_lower($subtags[1])) {
+            $subtags[1] = strtolower($subtags[1]);
+        }
 
         $new_string .= '-' . $subtags[1];
-        if ($num_subtags == 2) return $new_string;
+        if ($num_subtags == 2) {
+            return $new_string;
+        }
 
         // process all other subtags, index 2 and up
         for ($i = 2; $i < $num_subtags; $i++) {
@@ -63,11 +79,8 @@ class HTMLPurifier_AttrDef_Lang extends HTMLPurifier_AttrDef
             }
             $new_string .= '-' . $subtags[$i];
         }
-
         return $new_string;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/Switch.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php
similarity index 62%
rename from library/HTMLPurifier/AttrDef/Switch.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php
index c9e3ed193e..c7eb3199a4 100644
--- a/library/HTMLPurifier/AttrDef/Switch.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Switch.php
@@ -6,21 +6,41 @@
 class HTMLPurifier_AttrDef_Switch
 {
 
+    /**
+     * @type string
+     */
     protected $tag;
-    protected $withTag, $withoutTag;
+
+    /**
+     * @type HTMLPurifier_AttrDef
+     */
+    protected $withTag;
+
+    /**
+     * @type HTMLPurifier_AttrDef
+     */
+    protected $withoutTag;
 
     /**
      * @param string $tag Tag name to switch upon
      * @param HTMLPurifier_AttrDef $with_tag Call if token matches tag
      * @param HTMLPurifier_AttrDef $without_tag Call if token doesn't match, or there is no token
      */
-    public function __construct($tag, $with_tag, $without_tag) {
+    public function __construct($tag, $with_tag, $without_tag)
+    {
         $this->tag = $tag;
         $this->withTag = $with_tag;
         $this->withoutTag = $without_tag;
     }
 
-    public function validate($string, $config, $context) {
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         $token = $context->get('CurrentToken', true);
         if (!$token || $token->name !== $this->tag) {
             return $this->withoutTag->validate($string, $config, $context);
@@ -28,7 +48,6 @@ class HTMLPurifier_AttrDef_Switch
             return $this->withTag->validate($string, $config, $context);
         }
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php
new file mode 100644
index 0000000000..4553a4ea9b
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Text.php
@@ -0,0 +1,21 @@
+<?php
+
+/**
+ * Validates arbitrary text according to the HTML spec.
+ */
+class HTMLPurifier_AttrDef_Text extends HTMLPurifier_AttrDef
+{
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        return $this->parseCDATA($string);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/URI.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php
similarity index 53%
rename from library/HTMLPurifier/AttrDef/URI.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php
index 01a6d83e95..c1cd89772c 100644
--- a/library/HTMLPurifier/AttrDef/URI.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI.php
@@ -7,31 +7,54 @@
 class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
 {
 
+    /**
+     * @type HTMLPurifier_URIParser
+     */
     protected $parser;
+
+    /**
+     * @type bool
+     */
     protected $embedsResource;
 
     /**
-     * @param $embeds_resource_resource Does the URI here result in an extra HTTP request?
+     * @param bool $embeds_resource Does the URI here result in an extra HTTP request?
      */
-    public function __construct($embeds_resource = false) {
+    public function __construct($embeds_resource = false)
+    {
         $this->parser = new HTMLPurifier_URIParser();
-        $this->embedsResource = (bool) $embeds_resource;
+        $this->embedsResource = (bool)$embeds_resource;
     }
 
-    public function make($string) {
-        $embeds = (bool) $string;
+    /**
+     * @param string $string
+     * @return HTMLPurifier_AttrDef_URI
+     */
+    public function make($string)
+    {
+        $embeds = ($string === 'embedded');
         return new HTMLPurifier_AttrDef_URI($embeds);
     }
 
-    public function validate($uri, $config, $context) {
-
-        if ($config->get('URI.Disable')) return false;
+    /**
+     * @param string $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($uri, $config, $context)
+    {
+        if ($config->get('URI.Disable')) {
+            return false;
+        }
 
         $uri = $this->parseCDATA($uri);
 
         // parse the URI
         $uri = $this->parser->parse($uri);
-        if ($uri === false) return false;
+        if ($uri === false) {
+            return false;
+        }
 
         // add embedded flag to context for validators
         $context->register('EmbeddedURI', $this->embedsResource);
@@ -41,23 +64,35 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
 
             // generic validation
             $result = $uri->validate($config, $context);
-            if (!$result) break;
+            if (!$result) {
+                break;
+            }
 
             // chained filtering
             $uri_def = $config->getDefinition('URI');
             $result = $uri_def->filter($uri, $config, $context);
-            if (!$result) break;
+            if (!$result) {
+                break;
+            }
 
             // scheme-specific validation
             $scheme_obj = $uri->getSchemeObj($config, $context);
-            if (!$scheme_obj) break;
-            if ($this->embedsResource && !$scheme_obj->browsable) break;
+            if (!$scheme_obj) {
+                break;
+            }
+            if ($this->embedsResource && !$scheme_obj->browsable) {
+                break;
+            }
             $result = $scheme_obj->validate($uri, $config, $context);
-            if (!$result) break;
+            if (!$result) {
+                break;
+            }
 
             // Post chained filtering
             $result = $uri_def->postFilter($uri, $config, $context);
-            if (!$result) break;
+            if (!$result) {
+                break;
+            }
 
             // survived gauntlet
             $ok = true;
@@ -65,13 +100,12 @@ class HTMLPurifier_AttrDef_URI extends HTMLPurifier_AttrDef
         } while (false);
 
         $context->destroy('EmbeddedURI');
-        if (!$ok) return false;
-
+        if (!$ok) {
+            return false;
+        }
         // back to string
         return $uri->toString();
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/URI/Email.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php
similarity index 73%
rename from library/HTMLPurifier/AttrDef/URI/Email.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php
index bfee9d166c..daf32b7643 100644
--- a/library/HTMLPurifier/AttrDef/URI/Email.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email.php
@@ -5,8 +5,11 @@ abstract class HTMLPurifier_AttrDef_URI_Email extends HTMLPurifier_AttrDef
 
     /**
      * Unpacks a mailbox into its display-name and address
+     * @param string $string
+     * @return mixed
      */
-    function unpack($string) {
+    public function unpack($string)
+    {
         // needs to be implemented
     }
 
diff --git a/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
similarity index 65%
rename from library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
index 94c715ab43..52c0d59683 100644
--- a/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Email/SimpleCheck.php
@@ -7,15 +7,23 @@
 class HTMLPurifier_AttrDef_URI_Email_SimpleCheck extends HTMLPurifier_AttrDef_URI_Email
 {
 
-    public function validate($string, $config, $context) {
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
         // no support for named mailboxes i.e. "Bob <bob@example.com>"
         // that needs more percent encoding to be done
-        if ($string == '') return false;
+        if ($string == '') {
+            return false;
+        }
         $string = trim($string);
         $result = preg_match('/^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i', $string);
         return $result ? $string : false;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php
new file mode 100644
index 0000000000..e7df800b1e
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/Host.php
@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * Validates a host according to the IPv4, IPv6 and DNS (future) specifications.
+ */
+class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
+{
+
+    /**
+     * IPv4 sub-validator.
+     * @type HTMLPurifier_AttrDef_URI_IPv4
+     */
+    protected $ipv4;
+
+    /**
+     * IPv6 sub-validator.
+     * @type HTMLPurifier_AttrDef_URI_IPv6
+     */
+    protected $ipv6;
+
+    public function __construct()
+    {
+        $this->ipv4 = new HTMLPurifier_AttrDef_URI_IPv4();
+        $this->ipv6 = new HTMLPurifier_AttrDef_URI_IPv6();
+    }
+
+    /**
+     * @param string $string
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($string, $config, $context)
+    {
+        $length = strlen($string);
+        // empty hostname is OK; it's usually semantically equivalent:
+        // the default host as defined by a URI scheme is used:
+        //
+        //      If the URI scheme defines a default for host, then that
+        //      default applies when the host subcomponent is undefined
+        //      or when the registered name is empty (zero length).
+        if ($string === '') {
+            return '';
+        }
+        if ($length > 1 && $string[0] === '[' && $string[$length - 1] === ']') {
+            //IPv6
+            $ip = substr($string, 1, $length - 2);
+            $valid = $this->ipv6->validate($ip, $config, $context);
+            if ($valid === false) {
+                return false;
+            }
+            return '[' . $valid . ']';
+        }
+
+        // need to do checks on unusual encodings too
+        $ipv4 = $this->ipv4->validate($string, $config, $context);
+        if ($ipv4 !== false) {
+            return $ipv4;
+        }
+
+        // A regular domain name.
+
+        // This doesn't match I18N domain names, but we don't have proper IRI support,
+        // so force users to insert Punycode.
+
+        // There is not a good sense in which underscores should be
+        // allowed, since it's technically not! (And if you go as
+        // far to allow everything as specified by the DNS spec...
+        // well, that's literally everything, modulo some space limits
+        // for the components and the overall name (which, by the way,
+        // we are NOT checking!).  So we (arbitrarily) decide this:
+        // let's allow underscores wherever we would have allowed
+        // hyphens, if they are enabled.  This is a pretty good match
+        // for browser behavior, for example, a large number of browsers
+        // cannot handle foo_.example.com, but foo_bar.example.com is
+        // fairly well supported.
+        $underscore = $config->get('Core.AllowHostnameUnderscore') ? '_' : '';
+
+        // The productions describing this are:
+        $a   = '[a-z]';     // alpha
+        $an  = '[a-z0-9]';  // alphanum
+        $and = "[a-z0-9-$underscore]"; // alphanum | "-"
+        // domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
+        $domainlabel = "$an($and*$an)?";
+        // toplabel    = alpha | alpha *( alphanum | "-" ) alphanum
+        $toplabel = "$a($and*$an)?";
+        // hostname    = *( domainlabel "." ) toplabel [ "." ]
+        if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
+            return $string;
+        }
+
+        // If we have Net_IDNA2 support, we can support IRIs by
+        // punycoding them. (This is the most portable thing to do,
+        // since otherwise we have to assume browsers support
+
+        if ($config->get('Core.EnableIDNA')) {
+            $idna = new Net_IDNA2(array('encoding' => 'utf8', 'overlong' => false, 'strict' => true));
+            // we need to encode each period separately
+            $parts = explode('.', $string);
+            try {
+                $new_parts = array();
+                foreach ($parts as $part) {
+                    $encodable = false;
+                    for ($i = 0, $c = strlen($part); $i < $c; $i++) {
+                        if (ord($part[$i]) > 0x7a) {
+                            $encodable = true;
+                            break;
+                        }
+                    }
+                    if (!$encodable) {
+                        $new_parts[] = $part;
+                    } else {
+                        $new_parts[] = $idna->encode($part);
+                    }
+                }
+                $string = implode('.', $new_parts);
+                if (preg_match("/^($domainlabel\.)*$toplabel\.?$/i", $string)) {
+                    return $string;
+                }
+            } catch (Exception $e) {
+                // XXX error reporting
+            }
+        }
+        return false;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrDef/URI/IPv4.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php
similarity index 51%
rename from library/HTMLPurifier/AttrDef/URI/IPv4.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php
index ec4cf591b8..30ac16c9e7 100644
--- a/library/HTMLPurifier/AttrDef/URI/IPv4.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv4.php
@@ -8,32 +8,38 @@ class HTMLPurifier_AttrDef_URI_IPv4 extends HTMLPurifier_AttrDef
 {
 
     /**
-     * IPv4 regex, protected so that IPv6 can reuse it
+     * IPv4 regex, protected so that IPv6 can reuse it.
+     * @type string
      */
     protected $ip4;
 
-    public function validate($aIP, $config, $context) {
-
-        if (!$this->ip4) $this->_loadRegex();
-
-        if (preg_match('#^' . $this->ip4 . '$#s', $aIP))
-        {
-                return $aIP;
+    /**
+     * @param string $aIP
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($aIP, $config, $context)
+    {
+        if (!$this->ip4) {
+            $this->_loadRegex();
         }
 
+        if (preg_match('#^' . $this->ip4 . '$#s', $aIP)) {
+            return $aIP;
+        }
         return false;
-
     }
 
     /**
      * Lazy load function to prevent regex from being stuffed in
      * cache.
      */
-    protected function _loadRegex() {
+    protected function _loadRegex()
+    {
         $oct = '(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])'; // 0-255
         $this->ip4 = "(?:{$oct}\\.{$oct}\\.{$oct}\\.{$oct})";
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php
new file mode 100644
index 0000000000..f243793eeb
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/URI/IPv6.php
@@ -0,0 +1,89 @@
+<?php
+
+/**
+ * Validates an IPv6 address.
+ * @author Feyd @ forums.devnetwork.net (public domain)
+ * @note This function requires brackets to have been removed from address
+ *       in URI.
+ */
+class HTMLPurifier_AttrDef_URI_IPv6 extends HTMLPurifier_AttrDef_URI_IPv4
+{
+
+    /**
+     * @param string $aIP
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string
+     */
+    public function validate($aIP, $config, $context)
+    {
+        if (!$this->ip4) {
+            $this->_loadRegex();
+        }
+
+        $original = $aIP;
+
+        $hex = '[0-9a-fA-F]';
+        $blk = '(?:' . $hex . '{1,4})';
+        $pre = '(?:/(?:12[0-8]|1[0-1][0-9]|[1-9][0-9]|[0-9]))'; // /0 - /128
+
+        //      prefix check
+        if (strpos($aIP, '/') !== false) {
+            if (preg_match('#' . $pre . '$#s', $aIP, $find)) {
+                $aIP = substr($aIP, 0, 0 - strlen($find[0]));
+                unset($find);
+            } else {
+                return false;
+            }
+        }
+
+        //      IPv4-compatiblity check
+        if (preg_match('#(?<=:' . ')' . $this->ip4 . '$#s', $aIP, $find)) {
+            $aIP = substr($aIP, 0, 0 - strlen($find[0]));
+            $ip = explode('.', $find[0]);
+            $ip = array_map('dechex', $ip);
+            $aIP .= $ip[0] . $ip[1] . ':' . $ip[2] . $ip[3];
+            unset($find, $ip);
+        }
+
+        //      compression check
+        $aIP = explode('::', $aIP);
+        $c = count($aIP);
+        if ($c > 2) {
+            return false;
+        } elseif ($c == 2) {
+            list($first, $second) = $aIP;
+            $first = explode(':', $first);
+            $second = explode(':', $second);
+
+            if (count($first) + count($second) > 8) {
+                return false;
+            }
+
+            while (count($first) < 8) {
+                array_push($first, '0');
+            }
+
+            array_splice($first, 8 - count($second), 8, $second);
+            $aIP = $first;
+            unset($first, $second);
+        } else {
+            $aIP = explode(':', $aIP[0]);
+        }
+        $c = count($aIP);
+
+        if ($c != 8) {
+            return false;
+        }
+
+        //      All the pieces should be 16-bit hex strings. Are they?
+        foreach ($aIP as $piece) {
+            if (!preg_match('#^[0-9a-fA-F]{4}$#s', sprintf('%04s', $piece))) {
+                return false;
+            }
+        }
+        return $original;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform.php
similarity index 63%
rename from library/HTMLPurifier/AttrTransform.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform.php
index e61d3e01b6..b428331f15 100644
--- a/library/HTMLPurifier/AttrTransform.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform.php
@@ -20,37 +20,41 @@ abstract class HTMLPurifier_AttrTransform
     /**
      * Abstract: makes changes to the attributes dependent on multiple values.
      *
-     * @param $attr Assoc array of attributes, usually from
+     * @param array $attr Assoc array of attributes, usually from
      *              HTMLPurifier_Token_Tag::$attr
-     * @param $config Mandatory HTMLPurifier_Config object.
-     * @param $context Mandatory HTMLPurifier_Context object
-     * @returns Processed attribute array.
+     * @param HTMLPurifier_Config $config Mandatory HTMLPurifier_Config object.
+     * @param HTMLPurifier_Context $context Mandatory HTMLPurifier_Context object
+     * @return array Processed attribute array.
      */
     abstract public function transform($attr, $config, $context);
 
     /**
      * Prepends CSS properties to the style attribute, creating the
      * attribute if it doesn't exist.
-     * @param $attr Attribute array to process (passed by reference)
-     * @param $css CSS to prepend
+     * @param array &$attr Attribute array to process (passed by reference)
+     * @param string $css CSS to prepend
      */
-    public function prependCSS(&$attr, $css) {
+    public function prependCSS(&$attr, $css)
+    {
         $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
         $attr['style'] = $css . $attr['style'];
     }
 
     /**
      * Retrieves and removes an attribute
-     * @param $attr Attribute array to process (passed by reference)
-     * @param $key Key of attribute to confiscate
+     * @param array &$attr Attribute array to process (passed by reference)
+     * @param mixed $key Key of attribute to confiscate
+     * @return mixed
      */
-    public function confiscateAttr(&$attr, $key) {
-        if (!isset($attr[$key])) return null;
+    public function confiscateAttr(&$attr, $key)
+    {
+        if (!isset($attr[$key])) {
+            return null;
+        }
         $value = $attr[$key];
         unset($attr[$key]);
         return $value;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/Background.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php
similarity index 55%
rename from library/HTMLPurifier/AttrTransform/Background.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php
index 0e1ff24a3e..2f72869a5e 100644
--- a/library/HTMLPurifier/AttrTransform/Background.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Background.php
@@ -3,21 +3,26 @@
 /**
  * Pre-transform that changes proprietary background attribute to CSS.
  */
-class HTMLPurifier_AttrTransform_Background extends HTMLPurifier_AttrTransform {
-
-    public function transform($attr, $config, $context) {
-
-        if (!isset($attr['background'])) return $attr;
+class HTMLPurifier_AttrTransform_Background extends HTMLPurifier_AttrTransform
+{
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr['background'])) {
+            return $attr;
+        }
 
         $background = $this->confiscateAttr($attr, 'background');
         // some validation should happen here
 
         $this->prependCSS($attr, "background-image:url($background);");
-
         return $attr;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/BdoDir.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php
similarity index 55%
rename from library/HTMLPurifier/AttrTransform/BdoDir.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php
index 4d1a05665e..d66c04a5b8 100644
--- a/library/HTMLPurifier/AttrTransform/BdoDir.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BdoDir.php
@@ -8,12 +8,20 @@
 class HTMLPurifier_AttrTransform_BdoDir extends HTMLPurifier_AttrTransform
 {
 
-    public function transform($attr, $config, $context) {
-        if (isset($attr['dir'])) return $attr;
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (isset($attr['dir'])) {
+            return $attr;
+        }
         $attr['dir'] = $config->get('Attr.DefaultTextDir');
         return $attr;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/BgColor.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BgColor.php
similarity index 55%
rename from library/HTMLPurifier/AttrTransform/BgColor.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BgColor.php
index ad3916bb96..0f51fd2cec 100644
--- a/library/HTMLPurifier/AttrTransform/BgColor.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BgColor.php
@@ -3,21 +3,26 @@
 /**
  * Pre-transform that changes deprecated bgcolor attribute to CSS.
  */
-class HTMLPurifier_AttrTransform_BgColor extends HTMLPurifier_AttrTransform {
-
-    public function transform($attr, $config, $context) {
-
-        if (!isset($attr['bgcolor'])) return $attr;
+class HTMLPurifier_AttrTransform_BgColor extends HTMLPurifier_AttrTransform
+{
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr['bgcolor'])) {
+            return $attr;
+        }
 
         $bgcolor = $this->confiscateAttr($attr, 'bgcolor');
         // some validation should happen here
 
         $this->prependCSS($attr, "background-color:$bgcolor;");
-
         return $attr;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php
new file mode 100644
index 0000000000..f25cd01955
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/BoolToCSS.php
@@ -0,0 +1,47 @@
+<?php
+
+/**
+ * Pre-transform that changes converts a boolean attribute to fixed CSS
+ */
+class HTMLPurifier_AttrTransform_BoolToCSS extends HTMLPurifier_AttrTransform
+{
+    /**
+     * Name of boolean attribute that is trigger.
+     * @type string
+     */
+    protected $attr;
+
+    /**
+     * CSS declarations to add to style, needs trailing semicolon.
+     * @type string
+     */
+    protected $css;
+
+    /**
+     * @param string $attr attribute name to convert from
+     * @param string $css CSS declarations to add to style (needs semicolon)
+     */
+    public function __construct($attr, $css)
+    {
+        $this->attr = $attr;
+        $this->css = $css;
+    }
+
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr[$this->attr])) {
+            return $attr;
+        }
+        unset($attr[$this->attr]);
+        $this->prependCSS($attr, $this->css);
+        return $attr;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/Border.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Border.php
similarity index 55%
rename from library/HTMLPurifier/AttrTransform/Border.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Border.php
index 476b0b079b..057dc017fa 100644
--- a/library/HTMLPurifier/AttrTransform/Border.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Border.php
@@ -3,16 +3,24 @@
 /**
  * Pre-transform that changes deprecated border attribute to CSS.
  */
-class HTMLPurifier_AttrTransform_Border extends HTMLPurifier_AttrTransform {
-
-    public function transform($attr, $config, $context) {
-        if (!isset($attr['border'])) return $attr;
+class HTMLPurifier_AttrTransform_Border extends HTMLPurifier_AttrTransform
+{
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr['border'])) {
+            return $attr;
+        }
         $border_width = $this->confiscateAttr($attr, 'border');
         // some validation should happen here
         $this->prependCSS($attr, "border:{$border_width}px solid;");
         return $attr;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php
new file mode 100644
index 0000000000..7ccd0e3fb7
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/EnumToCSS.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * Generic pre-transform that converts an attribute with a fixed number of
+ * values (enumerated) to CSS.
+ */
+class HTMLPurifier_AttrTransform_EnumToCSS extends HTMLPurifier_AttrTransform
+{
+    /**
+     * Name of attribute to transform from.
+     * @type string
+     */
+    protected $attr;
+
+    /**
+     * Lookup array of attribute values to CSS.
+     * @type array
+     */
+    protected $enumToCSS = array();
+
+    /**
+     * Case sensitivity of the matching.
+     * @type bool
+     * @warning Currently can only be guaranteed to work with ASCII
+     *          values.
+     */
+    protected $caseSensitive = false;
+
+    /**
+     * @param string $attr Attribute name to transform from
+     * @param array $enum_to_css Lookup array of attribute values to CSS
+     * @param bool $case_sensitive Case sensitivity indicator, default false
+     */
+    public function __construct($attr, $enum_to_css, $case_sensitive = false)
+    {
+        $this->attr = $attr;
+        $this->enumToCSS = $enum_to_css;
+        $this->caseSensitive = (bool)$case_sensitive;
+    }
+
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr[$this->attr])) {
+            return $attr;
+        }
+
+        $value = trim($attr[$this->attr]);
+        unset($attr[$this->attr]);
+
+        if (!$this->caseSensitive) {
+            $value = strtolower($value);
+        }
+
+        if (!isset($this->enumToCSS[$value])) {
+            return $attr;
+        }
+        $this->prependCSS($attr, $this->enumToCSS[$value]);
+        return $attr;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/ImgRequired.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php
similarity index 77%
rename from library/HTMLPurifier/AttrTransform/ImgRequired.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php
index 7f0e4b7a59..7df6cb3e1b 100644
--- a/library/HTMLPurifier/AttrTransform/ImgRequired.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgRequired.php
@@ -11,11 +11,19 @@
 class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform
 {
 
-    public function transform($attr, $config, $context) {
-
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
         $src = true;
         if (!isset($attr['src'])) {
-            if ($config->get('Core.RemoveInvalidImg')) return $attr;
+            if ($config->get('Core.RemoveInvalidImg')) {
+                return $attr;
+            }
             $attr['src'] = $config->get('Attr.DefaultInvalidImage');
             $src = false;
         }
@@ -25,7 +33,7 @@ class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform
                 $alt = $config->get('Attr.DefaultImageAlt');
                 if ($alt === null) {
                     // truncate if the alt is too long
-                    $attr['alt'] = substr(basename($attr['src']),0,40);
+                    $attr['alt'] = substr(basename($attr['src']), 0, 40);
                 } else {
                     $attr['alt'] = $alt;
                 }
@@ -33,11 +41,8 @@ class HTMLPurifier_AttrTransform_ImgRequired extends HTMLPurifier_AttrTransform
                 $attr['alt'] = $config->get('Attr.DefaultInvalidImageAlt');
             }
         }
-
         return $attr;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/ImgSpace.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgSpace.php
similarity index 60%
rename from library/HTMLPurifier/AttrTransform/ImgSpace.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgSpace.php
index fd84c10c36..350b3358fc 100644
--- a/library/HTMLPurifier/AttrTransform/ImgSpace.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ImgSpace.php
@@ -3,42 +3,59 @@
 /**
  * Pre-transform that changes deprecated hspace and vspace attributes to CSS
  */
-class HTMLPurifier_AttrTransform_ImgSpace extends HTMLPurifier_AttrTransform {
-
+class HTMLPurifier_AttrTransform_ImgSpace extends HTMLPurifier_AttrTransform
+{
+    /**
+     * @type string
+     */
     protected $attr;
+
+    /**
+     * @type array
+     */
     protected $css = array(
         'hspace' => array('left', 'right'),
         'vspace' => array('top', 'bottom')
     );
 
-    public function __construct($attr) {
+    /**
+     * @param string $attr
+     */
+    public function __construct($attr)
+    {
         $this->attr = $attr;
         if (!isset($this->css[$attr])) {
             trigger_error(htmlspecialchars($attr) . ' is not valid space attribute');
         }
     }
 
-    public function transform($attr, $config, $context) {
-
-        if (!isset($attr[$this->attr])) return $attr;
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr[$this->attr])) {
+            return $attr;
+        }
 
         $width = $this->confiscateAttr($attr, $this->attr);
         // some validation could happen here
 
-        if (!isset($this->css[$this->attr])) return $attr;
+        if (!isset($this->css[$this->attr])) {
+            return $attr;
+        }
 
         $style = '';
         foreach ($this->css[$this->attr] as $suffix) {
             $property = "margin-$suffix";
             $style .= "$property:{$width}px;";
         }
-
         $this->prependCSS($attr, $style);
-
         return $attr;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/Input.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Input.php
similarity index 61%
rename from library/HTMLPurifier/AttrTransform/Input.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Input.php
index 16829552d1..3ab47ed8c9 100644
--- a/library/HTMLPurifier/AttrTransform/Input.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Input.php
@@ -4,17 +4,31 @@
  * Performs miscellaneous cross attribute validation and filtering for
  * input elements. This is meant to be a post-transform.
  */
-class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform {
-
+class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform
+{
+    /**
+     * @type HTMLPurifier_AttrDef_HTML_Pixels
+     */
     protected $pixels;
 
-    public function __construct() {
+    public function __construct()
+    {
         $this->pixels = new HTMLPurifier_AttrDef_HTML_Pixels();
     }
 
-    public function transform($attr, $config, $context) {
-        if (!isset($attr['type'])) $t = 'text';
-        else $t = strtolower($attr['type']);
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr['type'])) {
+            $t = 'text';
+        } else {
+            $t = strtolower($attr['type']);
+        }
         if (isset($attr['checked']) && $t !== 'radio' && $t !== 'checkbox') {
             unset($attr['checked']);
         }
@@ -23,8 +37,11 @@ class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform {
         }
         if (isset($attr['size']) && $t !== 'text' && $t !== 'password') {
             $result = $this->pixels->validate($attr['size'], $config, $context);
-            if ($result === false) unset($attr['size']);
-            else $attr['size'] = $result;
+            if ($result === false) {
+                unset($attr['size']);
+            } else {
+                $attr['size'] = $result;
+            }
         }
         if (isset($attr['src']) && $t !== 'image') {
             unset($attr['src']);
@@ -34,7 +51,6 @@ class HTMLPurifier_AttrTransform_Input extends HTMLPurifier_AttrTransform {
         }
         return $attr;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/Lang.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Lang.php
similarity index 68%
rename from library/HTMLPurifier/AttrTransform/Lang.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Lang.php
index 5869e7f820..5b0aff0e40 100644
--- a/library/HTMLPurifier/AttrTransform/Lang.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Lang.php
@@ -8,9 +8,15 @@
 class HTMLPurifier_AttrTransform_Lang extends HTMLPurifier_AttrTransform
 {
 
-    public function transform($attr, $config, $context) {
-
-        $lang     = isset($attr['lang']) ? $attr['lang'] : false;
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        $lang = isset($attr['lang']) ? $attr['lang'] : false;
         $xml_lang = isset($attr['xml:lang']) ? $attr['xml:lang'] : false;
 
         if ($lang !== false && $xml_lang === false) {
@@ -18,11 +24,8 @@ class HTMLPurifier_AttrTransform_Lang extends HTMLPurifier_AttrTransform
         } elseif ($xml_lang !== false) {
             $attr['lang'] = $xml_lang;
         }
-
         return $attr;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Length.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Length.php
new file mode 100644
index 0000000000..853f33549b
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Length.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * Class for handling width/height length attribute transformations to CSS
+ */
+class HTMLPurifier_AttrTransform_Length extends HTMLPurifier_AttrTransform
+{
+
+    /**
+     * @type string
+     */
+    protected $name;
+
+    /**
+     * @type string
+     */
+    protected $cssName;
+
+    public function __construct($name, $css_name = null)
+    {
+        $this->name = $name;
+        $this->cssName = $css_name ? $css_name : $name;
+    }
+
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr[$this->name])) {
+            return $attr;
+        }
+        $length = $this->confiscateAttr($attr, $this->name);
+        if (ctype_digit($length)) {
+            $length .= 'px';
+        }
+        $this->prependCSS($attr, $this->cssName . ":$length;");
+        return $attr;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php
new file mode 100644
index 0000000000..63cce6837a
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Name.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * Pre-transform that changes deprecated name attribute to ID if necessary
+ */
+class HTMLPurifier_AttrTransform_Name extends HTMLPurifier_AttrTransform
+{
+
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        // Abort early if we're using relaxed definition of name
+        if ($config->get('HTML.Attr.Name.UseCDATA')) {
+            return $attr;
+        }
+        if (!isset($attr['name'])) {
+            return $attr;
+        }
+        $id = $this->confiscateAttr($attr, 'name');
+        if (isset($attr['id'])) {
+            return $attr;
+        }
+        $attr['id'] = $id;
+        return $attr;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php
new file mode 100644
index 0000000000..36079b786f
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/NameSync.php
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * Post-transform that performs validation to the name attribute; if
+ * it is present with an equivalent id attribute, it is passed through;
+ * otherwise validation is performed.
+ */
+class HTMLPurifier_AttrTransform_NameSync extends HTMLPurifier_AttrTransform
+{
+
+    public function __construct()
+    {
+        $this->idDef = new HTMLPurifier_AttrDef_HTML_ID();
+    }
+
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr['name'])) {
+            return $attr;
+        }
+        $name = $attr['name'];
+        if (isset($attr['id']) && $attr['id'] === $name) {
+            return $attr;
+        }
+        $result = $this->idDef->validate($name, $config, $context);
+        if ($result === false) {
+            unset($attr['name']);
+        } else {
+            $attr['name'] = $result;
+        }
+        return $attr;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php
new file mode 100644
index 0000000000..1057ebee1b
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Nofollow.php
@@ -0,0 +1,52 @@
+<?php
+
+// must be called POST validation
+
+/**
+ * Adds rel="nofollow" to all outbound links.  This transform is
+ * only attached if Attr.Nofollow is TRUE.
+ */
+class HTMLPurifier_AttrTransform_Nofollow extends HTMLPurifier_AttrTransform
+{
+    /**
+     * @type HTMLPurifier_URIParser
+     */
+    private $parser;
+
+    public function __construct()
+    {
+        $this->parser = new HTMLPurifier_URIParser();
+    }
+
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr['href'])) {
+            return $attr;
+        }
+
+        // XXX Kind of inefficient
+        $url = $this->parser->parse($attr['href']);
+        $scheme = $url->getSchemeObj($config, $context);
+
+        if ($scheme->browsable && !$url->isLocal($config, $context)) {
+            if (isset($attr['rel'])) {
+                $rels = explode(' ', $attr['rel']);
+                if (!in_array('nofollow', $rels)) {
+                    $rels[] = 'nofollow';
+                }
+                $attr['rel'] = implode(' ', $rels);
+            } else {
+                $attr['rel'] = 'nofollow';
+            }
+        }
+        return $attr;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/SafeEmbed.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeEmbed.php
similarity index 56%
rename from library/HTMLPurifier/AttrTransform/SafeEmbed.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeEmbed.php
index 4da449981f..231c81a3f0 100644
--- a/library/HTMLPurifier/AttrTransform/SafeEmbed.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeEmbed.php
@@ -2,9 +2,19 @@
 
 class HTMLPurifier_AttrTransform_SafeEmbed extends HTMLPurifier_AttrTransform
 {
+    /**
+     * @type string
+     */
     public $name = "SafeEmbed";
 
-    public function transform($attr, $config, $context) {
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
         $attr['allowscriptaccess'] = 'never';
         $attr['allownetworking'] = 'internal';
         $attr['type'] = 'application/x-shockwave-flash';
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php
new file mode 100644
index 0000000000..d1f3a4d2ed
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeObject.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * Writes default type for all objects. Currently only supports flash.
+ */
+class HTMLPurifier_AttrTransform_SafeObject extends HTMLPurifier_AttrTransform
+{
+    /**
+     * @type string
+     */
+    public $name = "SafeObject";
+
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr['type'])) {
+            $attr['type'] = 'application/x-shockwave-flash';
+        }
+        return $attr;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTransform/SafeParam.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeParam.php
similarity index 67%
rename from library/HTMLPurifier/AttrTransform/SafeParam.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeParam.php
index 3f992ec31b..1143b4b493 100644
--- a/library/HTMLPurifier/AttrTransform/SafeParam.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/SafeParam.php
@@ -14,14 +14,30 @@
  */
 class HTMLPurifier_AttrTransform_SafeParam extends HTMLPurifier_AttrTransform
 {
+    /**
+     * @type string
+     */
     public $name = "SafeParam";
+
+    /**
+     * @type HTMLPurifier_AttrDef_URI
+     */
     private $uri;
 
-    public function __construct() {
+    public function __construct()
+    {
         $this->uri = new HTMLPurifier_AttrDef_URI(true); // embedded
+        $this->wmode = new HTMLPurifier_AttrDef_Enum(array('window', 'opaque', 'transparent'));
     }
 
-    public function transform($attr, $config, $context) {
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
         // If we add support for other objects, we'll need to alter the
         // transforms.
         switch ($attr['name']) {
@@ -33,8 +49,15 @@ class HTMLPurifier_AttrTransform_SafeParam extends HTMLPurifier_AttrTransform
             case 'allowNetworking':
                 $attr['value'] = 'internal';
                 break;
+            case 'allowFullScreen':
+                if ($config->get('HTML.FlashAllowFullScreen')) {
+                    $attr['value'] = ($attr['value'] == 'true') ? 'true' : 'false';
+                } else {
+                    $attr['value'] = 'false';
+                }
+                break;
             case 'wmode':
-                $attr['value'] = 'window';
+                $attr['value'] = $this->wmode->validate($attr['value'], $config, $context);
                 break;
             case 'movie':
             case 'src':
diff --git a/library/HTMLPurifier/AttrTransform/ScriptRequired.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php
similarity index 59%
rename from library/HTMLPurifier/AttrTransform/ScriptRequired.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php
index 4499050a22..b7057bbf8e 100644
--- a/library/HTMLPurifier/AttrTransform/ScriptRequired.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/ScriptRequired.php
@@ -5,7 +5,14 @@
  */
 class HTMLPurifier_AttrTransform_ScriptRequired extends HTMLPurifier_AttrTransform
 {
-    public function transform($attr, $config, $context) {
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
         if (!isset($attr['type'])) {
             $attr['type'] = 'text/javascript';
         }
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php
new file mode 100644
index 0000000000..dd63ea89cb
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/TargetBlank.php
@@ -0,0 +1,45 @@
+<?php
+
+// must be called POST validation
+
+/**
+ * Adds target="blank" to all outbound links.  This transform is
+ * only attached if Attr.TargetBlank is TRUE.  This works regardless
+ * of whether or not Attr.AllowedFrameTargets
+ */
+class HTMLPurifier_AttrTransform_TargetBlank extends HTMLPurifier_AttrTransform
+{
+    /**
+     * @type HTMLPurifier_URIParser
+     */
+    private $parser;
+
+    public function __construct()
+    {
+        $this->parser = new HTMLPurifier_URIParser();
+    }
+
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        if (!isset($attr['href'])) {
+            return $attr;
+        }
+
+        // XXX Kind of inefficient
+        $url = $this->parser->parse($attr['href']);
+        $scheme = $url->getSchemeObj($config, $context);
+
+        if ($scheme->browsable && !$url->isBenign($config, $context)) {
+            $attr['target'] = '_blank';
+        }
+        return $attr;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Textarea.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Textarea.php
new file mode 100644
index 0000000000..6a9f33a0c8
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTransform/Textarea.php
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * Sets height/width defaults for <textarea>
+ */
+class HTMLPurifier_AttrTransform_Textarea extends HTMLPurifier_AttrTransform
+{
+    /**
+     * @param array $attr
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function transform($attr, $config, $context)
+    {
+        // Calculated from Firefox
+        if (!isset($attr['cols'])) {
+            $attr['cols'] = '22';
+        }
+        if (!isset($attr['rows'])) {
+            $attr['rows'] = '3';
+        }
+        return $attr;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/AttrTypes.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTypes.php
similarity index 64%
rename from library/HTMLPurifier/AttrTypes.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTypes.php
index fc2ea4e588..3b70520b6a 100644
--- a/library/HTMLPurifier/AttrTypes.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrTypes.php
@@ -6,7 +6,8 @@
 class HTMLPurifier_AttrTypes
 {
     /**
-     * Lookup array of attribute string identifiers to concrete implementations
+     * Lookup array of attribute string identifiers to concrete implementations.
+     * @type HTMLPurifier_AttrDef[]
      */
     protected $info = array();
 
@@ -14,7 +15,15 @@ class HTMLPurifier_AttrTypes
      * Constructs the info array, supplying default implementations for attribute
      * types.
      */
-    public function __construct() {
+    public function __construct()
+    {
+        // XXX This is kind of poor, since we don't actually /clone/
+        // instances; instead, we use the supplied make() attribute. So,
+        // the underlying class must know how to deal with arguments.
+        // With the old implementation of Enum, that ignored its
+        // arguments when handling a make dispatch, the IAlign
+        // definition wouldn't work.
+
         // pseudo-types, must be instantiated via shorthand
         $this->info['Enum']    = new HTMLPurifier_AttrDef_Enum();
         $this->info['Bool']    = new HTMLPurifier_AttrDef_HTML_Bool();
@@ -29,6 +38,9 @@ class HTMLPurifier_AttrTypes
         $this->info['URI']      = new HTMLPurifier_AttrDef_URI();
         $this->info['LanguageCode'] = new HTMLPurifier_AttrDef_Lang();
         $this->info['Color']    = new HTMLPurifier_AttrDef_HTML_Color();
+        $this->info['IAlign']   = self::makeEnum('top,middle,bottom,left,right');
+        $this->info['LAlign']   = self::makeEnum('top,bottom,left,right');
+        $this->info['FrameTarget'] = new HTMLPurifier_AttrDef_HTML_FrameTarget();
 
         // unimplemented aliases
         $this->info['ContentType'] = new HTMLPurifier_AttrDef_Text();
@@ -44,32 +56,39 @@ class HTMLPurifier_AttrTypes
         $this->info['Number']   = new HTMLPurifier_AttrDef_Integer(false, false, true);
     }
 
+    private static function makeEnum($in)
+    {
+        return new HTMLPurifier_AttrDef_Clone(new HTMLPurifier_AttrDef_Enum(explode(',', $in)));
+    }
+
     /**
      * Retrieves a type
-     * @param $type String type name
-     * @return Object AttrDef for type
+     * @param string $type String type name
+     * @return HTMLPurifier_AttrDef Object AttrDef for type
      */
-    public function get($type) {
-
+    public function get($type)
+    {
         // determine if there is any extra info tacked on
-        if (strpos($type, '#') !== false) list($type, $string) = explode('#', $type, 2);
-        else $string = '';
+        if (strpos($type, '#') !== false) {
+            list($type, $string) = explode('#', $type, 2);
+        } else {
+            $string = '';
+        }
 
         if (!isset($this->info[$type])) {
             trigger_error('Cannot retrieve undefined attribute type ' . $type, E_USER_ERROR);
             return;
         }
-
         return $this->info[$type]->make($string);
-
     }
 
     /**
      * Sets a new implementation for a type
-     * @param $type String type name
-     * @param $impl Object AttrDef for type
+     * @param string $type String type name
+     * @param HTMLPurifier_AttrDef $impl Object AttrDef for type
      */
-    public function set($type, $impl) {
+    public function set($type, $impl)
+    {
         $this->info[$type] = $impl;
     }
 }
diff --git a/library/HTMLPurifier/AttrValidator.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrValidator.php
similarity index 74%
rename from library/HTMLPurifier/AttrValidator.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/AttrValidator.php
index 829a0f8f22..f97dc93edd 100644
--- a/library/HTMLPurifier/AttrValidator.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/AttrValidator.php
@@ -9,17 +9,14 @@ class HTMLPurifier_AttrValidator
 {
 
     /**
-     * Validates the attributes of a token, returning a modified token
+     * Validates the attributes of a token, mutating it as necessary.
      * that has valid tokens
-     * @param $token Reference to token to validate. We require a reference
-     *     because the operation this class performs on the token are
-     *     not atomic, so the context CurrentToken to be updated
-     *     throughout
-     * @param $config Instance of HTMLPurifier_Config
-     * @param $context Instance of HTMLPurifier_Context
+     * @param HTMLPurifier_Token $token Token to validate.
+     * @param HTMLPurifier_Config $config Instance of HTMLPurifier_Config
+     * @param HTMLPurifier_Context $context Instance of HTMLPurifier_Context
      */
-    public function validateToken(&$token, &$config, $context) {
-
+    public function validateToken($token, $config, $context)
+    {
         $definition = $config->getHTMLDefinition();
         $e =& $context->get('ErrorCollector', true);
 
@@ -32,12 +29,15 @@ class HTMLPurifier_AttrValidator
 
         // initialize CurrentToken if necessary
         $current_token =& $context->get('CurrentToken', true);
-        if (!$current_token) $context->register('CurrentToken', $token);
+        if (!$current_token) {
+            $context->register('CurrentToken', $token);
+        }
 
-        if (
-            !$token instanceof HTMLPurifier_Token_Start &&
+        if (!$token instanceof HTMLPurifier_Token_Start &&
             !$token instanceof HTMLPurifier_Token_Empty
-        ) return $token;
+        ) {
+            return;
+        }
 
         // create alias to global definition array, see also $defs
         // DEFINITION CALL
@@ -51,7 +51,9 @@ class HTMLPurifier_AttrValidator
         foreach ($definition->info_attr_transform_pre as $transform) {
             $attr = $transform->transform($o = $attr, $config, $context);
             if ($e) {
-                if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
+                if ($attr != $o) {
+                    $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
+                }
             }
         }
 
@@ -60,7 +62,9 @@ class HTMLPurifier_AttrValidator
         foreach ($definition->info[$token->name]->attr_transform_pre as $transform) {
             $attr = $transform->transform($o = $attr, $config, $context);
             if ($e) {
-                if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
+                if ($attr != $o) {
+                    $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
+                }
             }
         }
 
@@ -77,7 +81,7 @@ class HTMLPurifier_AttrValidator
         foreach ($attr as $attr_key => $value) {
 
             // call the definition
-            if ( isset($defs[$attr_key]) ) {
+            if (isset($defs[$attr_key])) {
                 // there is a local definition defined
                 if ($defs[$attr_key] === false) {
                     // We've explicitly been told not to allow this element.
@@ -89,15 +93,19 @@ class HTMLPurifier_AttrValidator
                 } else {
                     // validate according to the element's definition
                     $result = $defs[$attr_key]->validate(
-                                    $value, $config, $context
-                               );
+                        $value,
+                        $config,
+                        $context
+                    );
                 }
-            } elseif ( isset($d_defs[$attr_key]) ) {
+            } elseif (isset($d_defs[$attr_key])) {
                 // there is a global definition defined, validate according
                 // to the global definition
                 $result = $d_defs[$attr_key]->validate(
-                                $value, $config, $context
-                           );
+                    $value,
+                    $config,
+                    $context
+                );
             } else {
                 // system never heard of the attribute? DELETE!
                 $result = false;
@@ -107,7 +115,9 @@ class HTMLPurifier_AttrValidator
             if ($result === false || $result === null) {
                 // this is a generic error message that should replaced
                 // with more specific ones when possible
-                if ($e) $e->send(E_ERROR, 'AttrValidator: Attribute removed');
+                if ($e) {
+                    $e->send(E_ERROR, 'AttrValidator: Attribute removed');
+                }
 
                 // remove the attribute
                 unset($attr[$attr_key]);
@@ -137,7 +147,9 @@ class HTMLPurifier_AttrValidator
         foreach ($definition->info_attr_transform_post as $transform) {
             $attr = $transform->transform($o = $attr, $config, $context);
             if ($e) {
-                if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
+                if ($attr != $o) {
+                    $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
+                }
             }
         }
 
@@ -145,14 +157,18 @@ class HTMLPurifier_AttrValidator
         foreach ($definition->info[$token->name]->attr_transform_post as $transform) {
             $attr = $transform->transform($o = $attr, $config, $context);
             if ($e) {
-                if ($attr != $o) $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
+                if ($attr != $o) {
+                    $e->send(E_NOTICE, 'AttrValidator: Attributes transformed', $o, $attr);
+                }
             }
         }
 
         $token->attr = $attr;
 
         // destroy CurrentToken if we made it ourselves
-        if (!$current_token) $context->destroy('CurrentToken');
+        if (!$current_token) {
+            $context->destroy('CurrentToken');
+        }
 
     }
 
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php
new file mode 100644
index 0000000000..707122bb29
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Bootstrap.php
@@ -0,0 +1,124 @@
+<?php
+
+// constants are slow, so we use as few as possible
+if (!defined('HTMLPURIFIER_PREFIX')) {
+    define('HTMLPURIFIER_PREFIX', realpath(dirname(__FILE__) . '/..'));
+}
+
+// accomodations for versions earlier than 5.0.2
+// borrowed from PHP_Compat, LGPL licensed, by Aidan Lister <aidan@php.net>
+if (!defined('PHP_EOL')) {
+    switch (strtoupper(substr(PHP_OS, 0, 3))) {
+        case 'WIN':
+            define('PHP_EOL', "\r\n");
+            break;
+        case 'DAR':
+            define('PHP_EOL', "\r");
+            break;
+        default:
+            define('PHP_EOL', "\n");
+    }
+}
+
+/**
+ * Bootstrap class that contains meta-functionality for HTML Purifier such as
+ * the autoload function.
+ *
+ * @note
+ *      This class may be used without any other files from HTML Purifier.
+ */
+class HTMLPurifier_Bootstrap
+{
+
+    /**
+     * Autoload function for HTML Purifier
+     * @param string $class Class to load
+     * @return bool
+     */
+    public static function autoload($class)
+    {
+        $file = HTMLPurifier_Bootstrap::getPath($class);
+        if (!$file) {
+            return false;
+        }
+        // Technically speaking, it should be ok and more efficient to
+        // just do 'require', but Antonio Parraga reports that with
+        // Zend extensions such as Zend debugger and APC, this invariant
+        // may be broken.  Since we have efficient alternatives, pay
+        // the cost here and avoid the bug.
+        require_once HTMLPURIFIER_PREFIX . '/' . $file;
+        return true;
+    }
+
+    /**
+     * Returns the path for a specific class.
+     * @param string $class Class path to get
+     * @return string
+     */
+    public static function getPath($class)
+    {
+        if (strncmp('HTMLPurifier', $class, 12) !== 0) {
+            return false;
+        }
+        // Custom implementations
+        if (strncmp('HTMLPurifier_Language_', $class, 22) === 0) {
+            $code = str_replace('_', '-', substr($class, 22));
+            $file = 'HTMLPurifier/Language/classes/' . $code . '.php';
+        } else {
+            $file = str_replace('_', '/', $class) . '.php';
+        }
+        if (!file_exists(HTMLPURIFIER_PREFIX . '/' . $file)) {
+            return false;
+        }
+        return $file;
+    }
+
+    /**
+     * "Pre-registers" our autoloader on the SPL stack.
+     */
+    public static function registerAutoload()
+    {
+        $autoload = array('HTMLPurifier_Bootstrap', 'autoload');
+        if (($funcs = spl_autoload_functions()) === false) {
+            spl_autoload_register($autoload);
+        } elseif (function_exists('spl_autoload_unregister')) {
+            if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
+                // prepend flag exists, no need for shenanigans
+                spl_autoload_register($autoload, true, true);
+            } else {
+                $buggy  = version_compare(PHP_VERSION, '5.2.11', '<');
+                $compat = version_compare(PHP_VERSION, '5.1.2', '<=') &&
+                          version_compare(PHP_VERSION, '5.1.0', '>=');
+                foreach ($funcs as $func) {
+                    if ($buggy && is_array($func)) {
+                        // :TRICKY: There are some compatibility issues and some
+                        // places where we need to error out
+                        $reflector = new ReflectionMethod($func[0], $func[1]);
+                        if (!$reflector->isStatic()) {
+                            throw new Exception(
+                                'HTML Purifier autoloader registrar is not compatible
+                                with non-static object methods due to PHP Bug #44144;
+                                Please do not use HTMLPurifier.autoload.php (or any
+                                file that includes this file); instead, place the code:
+                                spl_autoload_register(array(\'HTMLPurifier_Bootstrap\', \'autoload\'))
+                                after your own autoloaders.'
+                            );
+                        }
+                        // Suprisingly, spl_autoload_register supports the
+                        // Class::staticMethod callback format, although call_user_func doesn't
+                        if ($compat) {
+                            $func = implode('::', $func);
+                        }
+                    }
+                    spl_autoload_unregister($func);
+                }
+                spl_autoload_register($autoload);
+                foreach ($funcs as $func) {
+                    spl_autoload_register($func);
+                }
+            }
+        }
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php
new file mode 100644
index 0000000000..07cc941758
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/CSSDefinition.php
@@ -0,0 +1,474 @@
+<?php
+
+/**
+ * Defines allowed CSS attributes and what their values are.
+ * @see HTMLPurifier_HTMLDefinition
+ */
+class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
+{
+
+    public $type = 'CSS';
+
+    /**
+     * Assoc array of attribute name to definition object.
+     * @type HTMLPurifier_AttrDef[]
+     */
+    public $info = array();
+
+    /**
+     * Constructs the info array.  The meat of this class.
+     * @param HTMLPurifier_Config $config
+     */
+    protected function doSetup($config)
+    {
+        $this->info['text-align'] = new HTMLPurifier_AttrDef_Enum(
+            array('left', 'right', 'center', 'justify'),
+            false
+        );
+
+        $border_style =
+            $this->info['border-bottom-style'] =
+            $this->info['border-right-style'] =
+            $this->info['border-left-style'] =
+            $this->info['border-top-style'] = new HTMLPurifier_AttrDef_Enum(
+                array(
+                    'none',
+                    'hidden',
+                    'dotted',
+                    'dashed',
+                    'solid',
+                    'double',
+                    'groove',
+                    'ridge',
+                    'inset',
+                    'outset'
+                ),
+                false
+            );
+
+        $this->info['border-style'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_style);
+
+        $this->info['clear'] = new HTMLPurifier_AttrDef_Enum(
+            array('none', 'left', 'right', 'both'),
+            false
+        );
+        $this->info['float'] = new HTMLPurifier_AttrDef_Enum(
+            array('none', 'left', 'right'),
+            false
+        );
+        $this->info['font-style'] = new HTMLPurifier_AttrDef_Enum(
+            array('normal', 'italic', 'oblique'),
+            false
+        );
+        $this->info['font-variant'] = new HTMLPurifier_AttrDef_Enum(
+            array('normal', 'small-caps'),
+            false
+        );
+
+        $uri_or_none = new HTMLPurifier_AttrDef_CSS_Composite(
+            array(
+                new HTMLPurifier_AttrDef_Enum(array('none')),
+                new HTMLPurifier_AttrDef_CSS_URI()
+            )
+        );
+
+        $this->info['list-style-position'] = new HTMLPurifier_AttrDef_Enum(
+            array('inside', 'outside'),
+            false
+        );
+        $this->info['list-style-type'] = new HTMLPurifier_AttrDef_Enum(
+            array(
+                'disc',
+                'circle',
+                'square',
+                'decimal',
+                'lower-roman',
+                'upper-roman',
+                'lower-alpha',
+                'upper-alpha',
+                'none'
+            ),
+            false
+        );
+        $this->info['list-style-image'] = $uri_or_none;
+
+        $this->info['list-style'] = new HTMLPurifier_AttrDef_CSS_ListStyle($config);
+
+        $this->info['text-transform'] = new HTMLPurifier_AttrDef_Enum(
+            array('capitalize', 'uppercase', 'lowercase', 'none'),
+            false
+        );
+        $this->info['color'] = new HTMLPurifier_AttrDef_CSS_Color();
+
+        $this->info['background-image'] = $uri_or_none;
+        $this->info['background-repeat'] = new HTMLPurifier_AttrDef_Enum(
+            array('repeat', 'repeat-x', 'repeat-y', 'no-repeat')
+        );
+        $this->info['background-attachment'] = new HTMLPurifier_AttrDef_Enum(
+            array('scroll', 'fixed')
+        );
+        $this->info['background-position'] = new HTMLPurifier_AttrDef_CSS_BackgroundPosition();
+
+        $border_color =
+            $this->info['border-top-color'] =
+            $this->info['border-bottom-color'] =
+            $this->info['border-left-color'] =
+            $this->info['border-right-color'] =
+            $this->info['background-color'] = new HTMLPurifier_AttrDef_CSS_Composite(
+                array(
+                    new HTMLPurifier_AttrDef_Enum(array('transparent')),
+                    new HTMLPurifier_AttrDef_CSS_Color()
+                )
+            );
+
+        $this->info['background'] = new HTMLPurifier_AttrDef_CSS_Background($config);
+
+        $this->info['border-color'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_color);
+
+        $border_width =
+            $this->info['border-top-width'] =
+            $this->info['border-bottom-width'] =
+            $this->info['border-left-width'] =
+            $this->info['border-right-width'] = new HTMLPurifier_AttrDef_CSS_Composite(
+                array(
+                    new HTMLPurifier_AttrDef_Enum(array('thin', 'medium', 'thick')),
+                    new HTMLPurifier_AttrDef_CSS_Length('0') //disallow negative
+                )
+            );
+
+        $this->info['border-width'] = new HTMLPurifier_AttrDef_CSS_Multiple($border_width);
+
+        $this->info['letter-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(
+            array(
+                new HTMLPurifier_AttrDef_Enum(array('normal')),
+                new HTMLPurifier_AttrDef_CSS_Length()
+            )
+        );
+
+        $this->info['word-spacing'] = new HTMLPurifier_AttrDef_CSS_Composite(
+            array(
+                new HTMLPurifier_AttrDef_Enum(array('normal')),
+                new HTMLPurifier_AttrDef_CSS_Length()
+            )
+        );
+
+        $this->info['font-size'] = new HTMLPurifier_AttrDef_CSS_Composite(
+            array(
+                new HTMLPurifier_AttrDef_Enum(
+                    array(
+                        'xx-small',
+                        'x-small',
+                        'small',
+                        'medium',
+                        'large',
+                        'x-large',
+                        'xx-large',
+                        'larger',
+                        'smaller'
+                    )
+                ),
+                new HTMLPurifier_AttrDef_CSS_Percentage(),
+                new HTMLPurifier_AttrDef_CSS_Length()
+            )
+        );
+
+        $this->info['line-height'] = new HTMLPurifier_AttrDef_CSS_Composite(
+            array(
+                new HTMLPurifier_AttrDef_Enum(array('normal')),
+                new HTMLPurifier_AttrDef_CSS_Number(true), // no negatives
+                new HTMLPurifier_AttrDef_CSS_Length('0'),
+                new HTMLPurifier_AttrDef_CSS_Percentage(true)
+            )
+        );
+
+        $margin =
+            $this->info['margin-top'] =
+            $this->info['margin-bottom'] =
+            $this->info['margin-left'] =
+            $this->info['margin-right'] = new HTMLPurifier_AttrDef_CSS_Composite(
+                array(
+                    new HTMLPurifier_AttrDef_CSS_Length(),
+                    new HTMLPurifier_AttrDef_CSS_Percentage(),
+                    new HTMLPurifier_AttrDef_Enum(array('auto'))
+                )
+            );
+
+        $this->info['margin'] = new HTMLPurifier_AttrDef_CSS_Multiple($margin);
+
+        // non-negative
+        $padding =
+            $this->info['padding-top'] =
+            $this->info['padding-bottom'] =
+            $this->info['padding-left'] =
+            $this->info['padding-right'] = new HTMLPurifier_AttrDef_CSS_Composite(
+                array(
+                    new HTMLPurifier_AttrDef_CSS_Length('0'),
+                    new HTMLPurifier_AttrDef_CSS_Percentage(true)
+                )
+            );
+
+        $this->info['padding'] = new HTMLPurifier_AttrDef_CSS_Multiple($padding);
+
+        $this->info['text-indent'] = new HTMLPurifier_AttrDef_CSS_Composite(
+            array(
+                new HTMLPurifier_AttrDef_CSS_Length(),
+                new HTMLPurifier_AttrDef_CSS_Percentage()
+            )
+        );
+
+        $trusted_wh = new HTMLPurifier_AttrDef_CSS_Composite(
+            array(
+                new HTMLPurifier_AttrDef_CSS_Length('0'),
+                new HTMLPurifier_AttrDef_CSS_Percentage(true),
+                new HTMLPurifier_AttrDef_Enum(array('auto'))
+            )
+        );
+        $max = $config->get('CSS.MaxImgLength');
+
+        $this->info['width'] =
+        $this->info['height'] =
+            $max === null ?
+                $trusted_wh :
+                new HTMLPurifier_AttrDef_Switch(
+                    'img',
+                    // For img tags:
+                    new HTMLPurifier_AttrDef_CSS_Composite(
+                        array(
+                            new HTMLPurifier_AttrDef_CSS_Length('0', $max),
+                            new HTMLPurifier_AttrDef_Enum(array('auto'))
+                        )
+                    ),
+                    // For everyone else:
+                    $trusted_wh
+                );
+
+        $this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration();
+
+        $this->info['font-family'] = new HTMLPurifier_AttrDef_CSS_FontFamily();
+
+        // this could use specialized code
+        $this->info['font-weight'] = new HTMLPurifier_AttrDef_Enum(
+            array(
+                'normal',
+                'bold',
+                'bolder',
+                'lighter',
+                '100',
+                '200',
+                '300',
+                '400',
+                '500',
+                '600',
+                '700',
+                '800',
+                '900'
+            ),
+            false
+        );
+
+        // MUST be called after other font properties, as it references
+        // a CSSDefinition object
+        $this->info['font'] = new HTMLPurifier_AttrDef_CSS_Font($config);
+
+        // same here
+        $this->info['border'] =
+        $this->info['border-bottom'] =
+        $this->info['border-top'] =
+        $this->info['border-left'] =
+        $this->info['border-right'] = new HTMLPurifier_AttrDef_CSS_Border($config);
+
+        $this->info['border-collapse'] = new HTMLPurifier_AttrDef_Enum(
+            array('collapse', 'separate')
+        );
+
+        $this->info['caption-side'] = new HTMLPurifier_AttrDef_Enum(
+            array('top', 'bottom')
+        );
+
+        $this->info['table-layout'] = new HTMLPurifier_AttrDef_Enum(
+            array('auto', 'fixed')
+        );
+
+        $this->info['vertical-align'] = new HTMLPurifier_AttrDef_CSS_Composite(
+            array(
+                new HTMLPurifier_AttrDef_Enum(
+                    array(
+                        'baseline',
+                        'sub',
+                        'super',
+                        'top',
+                        'text-top',
+                        'middle',
+                        'bottom',
+                        'text-bottom'
+                    )
+                ),
+                new HTMLPurifier_AttrDef_CSS_Length(),
+                new HTMLPurifier_AttrDef_CSS_Percentage()
+            )
+        );
+
+        $this->info['border-spacing'] = new HTMLPurifier_AttrDef_CSS_Multiple(new HTMLPurifier_AttrDef_CSS_Length(), 2);
+
+        // These CSS properties don't work on many browsers, but we live
+        // in THE FUTURE!
+        $this->info['white-space'] = new HTMLPurifier_AttrDef_Enum(
+            array('nowrap', 'normal', 'pre', 'pre-wrap', 'pre-line')
+        );
+
+        if ($config->get('CSS.Proprietary')) {
+            $this->doSetupProprietary($config);
+        }
+
+        if ($config->get('CSS.AllowTricky')) {
+            $this->doSetupTricky($config);
+        }
+
+        if ($config->get('CSS.Trusted')) {
+            $this->doSetupTrusted($config);
+        }
+
+        $allow_important = $config->get('CSS.AllowImportant');
+        // wrap all attr-defs with decorator that handles !important
+        foreach ($this->info as $k => $v) {
+            $this->info[$k] = new HTMLPurifier_AttrDef_CSS_ImportantDecorator($v, $allow_important);
+        }
+
+        $this->setupConfigStuff($config);
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    protected function doSetupProprietary($config)
+    {
+        // Internet Explorer only scrollbar colors
+        $this->info['scrollbar-arrow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
+        $this->info['scrollbar-base-color'] = new HTMLPurifier_AttrDef_CSS_Color();
+        $this->info['scrollbar-darkshadow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
+        $this->info['scrollbar-face-color'] = new HTMLPurifier_AttrDef_CSS_Color();
+        $this->info['scrollbar-highlight-color'] = new HTMLPurifier_AttrDef_CSS_Color();
+        $this->info['scrollbar-shadow-color'] = new HTMLPurifier_AttrDef_CSS_Color();
+
+        // vendor specific prefixes of opacity
+        $this->info['-moz-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
+        $this->info['-khtml-opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
+
+        // only opacity, for now
+        $this->info['filter'] = new HTMLPurifier_AttrDef_CSS_Filter();
+
+        // more CSS3
+        $this->info['page-break-after'] =
+        $this->info['page-break-before'] = new HTMLPurifier_AttrDef_Enum(
+            array(
+                'auto',
+                'always',
+                'avoid',
+                'left',
+                'right'
+            )
+        );
+        $this->info['page-break-inside'] = new HTMLPurifier_AttrDef_Enum(array('auto', 'avoid'));
+
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    protected function doSetupTricky($config)
+    {
+        $this->info['display'] = new HTMLPurifier_AttrDef_Enum(
+            array(
+                'inline',
+                'block',
+                'list-item',
+                'run-in',
+                'compact',
+                'marker',
+                'table',
+                'inline-block',
+                'inline-table',
+                'table-row-group',
+                'table-header-group',
+                'table-footer-group',
+                'table-row',
+                'table-column-group',
+                'table-column',
+                'table-cell',
+                'table-caption',
+                'none'
+            )
+        );
+        $this->info['visibility'] = new HTMLPurifier_AttrDef_Enum(
+            array('visible', 'hidden', 'collapse')
+        );
+        $this->info['overflow'] = new HTMLPurifier_AttrDef_Enum(array('visible', 'hidden', 'auto', 'scroll'));
+        $this->info['opacity'] = new HTMLPurifier_AttrDef_CSS_AlphaValue();
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    protected function doSetupTrusted($config)
+    {
+        $this->info['position'] = new HTMLPurifier_AttrDef_Enum(
+            array('static', 'relative', 'absolute', 'fixed')
+        );
+        $this->info['top'] =
+        $this->info['left'] =
+        $this->info['right'] =
+        $this->info['bottom'] = new HTMLPurifier_AttrDef_CSS_Composite(
+            array(
+                new HTMLPurifier_AttrDef_CSS_Length(),
+                new HTMLPurifier_AttrDef_CSS_Percentage(),
+                new HTMLPurifier_AttrDef_Enum(array('auto')),
+            )
+        );
+        $this->info['z-index'] = new HTMLPurifier_AttrDef_CSS_Composite(
+            array(
+                new HTMLPurifier_AttrDef_Integer(),
+                new HTMLPurifier_AttrDef_Enum(array('auto')),
+            )
+        );
+    }
+
+    /**
+     * Performs extra config-based processing. Based off of
+     * HTMLPurifier_HTMLDefinition.
+     * @param HTMLPurifier_Config $config
+     * @todo Refactor duplicate elements into common class (probably using
+     *       composition, not inheritance).
+     */
+    protected function setupConfigStuff($config)
+    {
+        // setup allowed elements
+        $support = "(for information on implementing this, see the " .
+            "support forums) ";
+        $allowed_properties = $config->get('CSS.AllowedProperties');
+        if ($allowed_properties !== null) {
+            foreach ($this->info as $name => $d) {
+                if (!isset($allowed_properties[$name])) {
+                    unset($this->info[$name]);
+                }
+                unset($allowed_properties[$name]);
+            }
+            // emit errors
+            foreach ($allowed_properties as $name => $d) {
+                // :TODO: Is this htmlspecialchars() call really necessary?
+                $name = htmlspecialchars($name);
+                trigger_error("Style attribute '$name' is not supported $support", E_USER_WARNING);
+            }
+        }
+
+        $forbidden_properties = $config->get('CSS.ForbiddenProperties');
+        if ($forbidden_properties !== null) {
+            foreach ($this->info as $name => $d) {
+                if (isset($forbidden_properties[$name])) {
+                    unset($this->info[$name]);
+                }
+            }
+        }
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ChildDef.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef.php
similarity index 52%
rename from library/HTMLPurifier/ChildDef.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef.php
index c5d5216dab..8eb17b82e1 100644
--- a/library/HTMLPurifier/ChildDef.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef.php
@@ -1,48 +1,52 @@
 <?php
 
 /**
- * Defines allowed child nodes and validates tokens against it.
+ * Defines allowed child nodes and validates nodes against it.
  */
 abstract class HTMLPurifier_ChildDef
 {
     /**
      * Type of child definition, usually right-most part of class name lowercase.
      * Used occasionally in terms of context.
+     * @type string
      */
     public $type;
 
     /**
-     * Bool that indicates whether or not an empty array of children is okay
+     * Indicates whether or not an empty array of children is okay.
      *
      * This is necessary for redundant checking when changes affecting
      * a child node may cause a parent node to now be disallowed.
+     * @type bool
      */
     public $allow_empty;
 
     /**
-     * Lookup array of all elements that this definition could possibly allow
+     * Lookup array of all elements that this definition could possibly allow.
+     * @type array
      */
     public $elements = array();
 
     /**
      * Get lookup of tag names that should not close this element automatically.
      * All other elements will do so.
+     * @param HTMLPurifier_Config $config HTMLPurifier_Config object
+     * @return array
      */
-    public function getAllowedElements($config) {
+    public function getAllowedElements($config)
+    {
         return $this->elements;
     }
 
     /**
      * Validates nodes according to definition and returns modification.
      *
-     * @param $tokens_of_children Array of HTMLPurifier_Token
-     * @param $config HTMLPurifier_Config object
-     * @param $context HTMLPurifier_Context object
-     * @return bool true to leave nodes as is
-     * @return bool false to remove parent node
-     * @return array of replacement child tokens
+     * @param HTMLPurifier_Node[] $children Array of HTMLPurifier_Node
+     * @param HTMLPurifier_Config $config HTMLPurifier_Config object
+     * @param HTMLPurifier_Context $context HTMLPurifier_Context object
+     * @return bool|array true to leave nodes as is, false to remove parent node, array of replacement children
      */
-    abstract public function validateChildren($tokens_of_children, $config, $context);
+    abstract public function validateChildren($children, $config, $context);
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ChildDef/Chameleon.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Chameleon.php
similarity index 57%
rename from library/HTMLPurifier/ChildDef/Chameleon.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Chameleon.php
index 15c364ee33..7439be26b6 100644
--- a/library/HTMLPurifier/ChildDef/Chameleon.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Chameleon.php
@@ -14,33 +14,52 @@ class HTMLPurifier_ChildDef_Chameleon extends HTMLPurifier_ChildDef
 
     /**
      * Instance of the definition object to use when inline. Usually stricter.
+     * @type HTMLPurifier_ChildDef_Optional
      */
     public $inline;
 
     /**
      * Instance of the definition object to use when block.
+     * @type HTMLPurifier_ChildDef_Optional
      */
     public $block;
 
+    /**
+     * @type string
+     */
     public $type = 'chameleon';
 
     /**
-     * @param $inline List of elements to allow when inline.
-     * @param $block List of elements to allow when block.
+     * @param array $inline List of elements to allow when inline.
+     * @param array $block List of elements to allow when block.
      */
-    public function __construct($inline, $block) {
+    public function __construct($inline, $block)
+    {
         $this->inline = new HTMLPurifier_ChildDef_Optional($inline);
-        $this->block  = new HTMLPurifier_ChildDef_Optional($block);
+        $this->block = new HTMLPurifier_ChildDef_Optional($block);
         $this->elements = $this->block->elements;
     }
 
-    public function validateChildren($tokens_of_children, $config, $context) {
+    /**
+     * @param HTMLPurifier_Node[] $children
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function validateChildren($children, $config, $context)
+    {
         if ($context->get('IsInline') === false) {
             return $this->block->validateChildren(
-                $tokens_of_children, $config, $context);
+                $children,
+                $config,
+                $context
+            );
         } else {
             return $this->inline->validateChildren(
-                $tokens_of_children, $config, $context);
+                $children,
+                $config,
+                $context
+            );
         }
     }
 }
diff --git a/library/HTMLPurifier/ChildDef/Custom.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Custom.php
similarity index 71%
rename from library/HTMLPurifier/ChildDef/Custom.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Custom.php
index b68047b4b5..128132e96d 100644
--- a/library/HTMLPurifier/ChildDef/Custom.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Custom.php
@@ -8,28 +8,42 @@
  */
 class HTMLPurifier_ChildDef_Custom extends HTMLPurifier_ChildDef
 {
-    public $type = 'custom';
-    public $allow_empty = false;
     /**
-     * Allowed child pattern as defined by the DTD
+     * @type string
+     */
+    public $type = 'custom';
+
+    /**
+     * @type bool
+     */
+    public $allow_empty = false;
+
+    /**
+     * Allowed child pattern as defined by the DTD.
+     * @type string
      */
     public $dtd_regex;
+
     /**
-     * PCRE regex derived from $dtd_regex
-     * @private
+     * PCRE regex derived from $dtd_regex.
+     * @type string
      */
     private $_pcre_regex;
+
     /**
      * @param $dtd_regex Allowed child pattern from the DTD
      */
-    public function __construct($dtd_regex) {
+    public function __construct($dtd_regex)
+    {
         $this->dtd_regex = $dtd_regex;
         $this->_compileRegex();
     }
+
     /**
      * Compiles the PCRE regex from a DTD regex ($dtd_regex to $_pcre_regex)
      */
-    protected function _compileRegex() {
+    protected function _compileRegex()
+    {
         $raw = str_replace(' ', '', $this->dtd_regex);
         if ($raw{0} != '(') {
             $raw = "($raw)";
@@ -57,33 +71,31 @@ class HTMLPurifier_ChildDef_Custom extends HTMLPurifier_ChildDef
 
         $this->_pcre_regex = $reg;
     }
-    public function validateChildren($tokens_of_children, $config, $context) {
+
+    /**
+     * @param HTMLPurifier_Node[] $children
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function validateChildren($children, $config, $context)
+    {
         $list_of_children = '';
         $nesting = 0; // depth into the nest
-        foreach ($tokens_of_children as $token) {
-            if (!empty($token->is_whitespace)) continue;
-
-            $is_child = ($nesting == 0); // direct
-
-            if ($token instanceof HTMLPurifier_Token_Start) {
-                $nesting++;
-            } elseif ($token instanceof HTMLPurifier_Token_End) {
-                $nesting--;
-            }
-
-            if ($is_child) {
-                $list_of_children .= $token->name . ',';
+        foreach ($children as $node) {
+            if (!empty($node->is_whitespace)) {
+                continue;
             }
+            $list_of_children .= $node->name . ',';
         }
         // add leading comma to deal with stray comma declarations
         $list_of_children = ',' . rtrim($list_of_children, ',');
         $okay =
             preg_match(
-                '/^,?'.$this->_pcre_regex.'$/',
+                '/^,?' . $this->_pcre_regex . '$/',
                 $list_of_children
             );
-
-        return (bool) $okay;
+        return (bool)$okay;
     }
 }
 
diff --git a/library/HTMLPurifier/ChildDef/Empty.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Empty.php
similarity index 58%
rename from library/HTMLPurifier/ChildDef/Empty.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Empty.php
index 13171f6651..a8a6cbdd2c 100644
--- a/library/HTMLPurifier/ChildDef/Empty.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Empty.php
@@ -9,10 +9,28 @@
  */
 class HTMLPurifier_ChildDef_Empty extends HTMLPurifier_ChildDef
 {
+    /**
+     * @type bool
+     */
     public $allow_empty = true;
+
+    /**
+     * @type string
+     */
     public $type = 'empty';
-    public function __construct() {}
-    public function validateChildren($tokens_of_children, $config, $context) {
+
+    public function __construct()
+    {
+    }
+
+    /**
+     * @param HTMLPurifier_Node[] $children
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function validateChildren($children, $config, $context)
+    {
         return array();
     }
 }
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/List.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/List.php
new file mode 100644
index 0000000000..891b9f6f5b
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/List.php
@@ -0,0 +1,86 @@
+<?php
+
+/**
+ * Definition for list containers ul and ol.
+ *
+ * What does this do?  The big thing is to handle ol/ul at the top
+ * level of list nodes, which should be handled specially by /folding/
+ * them into the previous list node.  We generally shouldn't ever
+ * see other disallowed elements, because the autoclose behavior
+ * in MakeWellFormed handles it.
+ */
+class HTMLPurifier_ChildDef_List extends HTMLPurifier_ChildDef
+{
+    /**
+     * @type string
+     */
+    public $type = 'list';
+    /**
+     * @type array
+     */
+    // lying a little bit, so that we can handle ul and ol ourselves
+    // XXX: This whole business with 'wrap' is all a bit unsatisfactory
+    public $elements = array('li' => true, 'ul' => true, 'ol' => true);
+
+    /**
+     * @param array $children
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function validateChildren($children, $config, $context)
+    {
+        // Flag for subclasses
+        $this->whitespace = false;
+
+        // if there are no tokens, delete parent node
+        if (empty($children)) {
+            return false;
+        }
+
+        // the new set of children
+        $result = array();
+
+        // a little sanity check to make sure it's not ALL whitespace
+        $all_whitespace = true;
+
+        $current_li = false;
+
+        foreach ($children as $node) {
+            if (!empty($node->is_whitespace)) {
+                $result[] = $node;
+                continue;
+            }
+            $all_whitespace = false; // phew, we're not talking about whitespace
+
+            if ($node->name === 'li') {
+                // good
+                $current_li = $node;
+                $result[] = $node;
+            } else {
+                // we want to tuck this into the previous li
+                // Invariant: we expect the node to be ol/ul
+                // ToDo: Make this more robust in the case of not ol/ul
+                // by distinguishing between existing li and li created
+                // to handle non-list elements; non-list elements should
+                // not be appended to an existing li; only li created
+                // for non-list. This distinction is not currently made.
+                if ($current_li === false) {
+                    $current_li = new HTMLPurifier_Node_Element('li');
+                    $result[] = $current_li;
+                }
+                $current_li->children[] = $node;
+                $current_li->empty = false; // XXX fascinating! Check for this error elsewhere ToDo
+            }
+        }
+        if (empty($result)) {
+            return false;
+        }
+        if ($all_whitespace) {
+            return false;
+        }
+        return $result;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php
new file mode 100644
index 0000000000..b9468063b1
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Optional.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * Definition that allows a set of elements, and allows no children.
+ * @note This is a hack to reuse code from HTMLPurifier_ChildDef_Required,
+ *       really, one shouldn't inherit from the other.  Only altered behavior
+ *       is to overload a returned false with an array.  Thus, it will never
+ *       return false.
+ */
+class HTMLPurifier_ChildDef_Optional extends HTMLPurifier_ChildDef_Required
+{
+    /**
+     * @type bool
+     */
+    public $allow_empty = true;
+
+    /**
+     * @type string
+     */
+    public $type = 'optional';
+
+    /**
+     * @param array $children
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function validateChildren($children, $config, $context)
+    {
+        $result = parent::validateChildren($children, $config, $context);
+        // we assume that $children is not modified
+        if ($result === false) {
+            if (empty($children)) {
+                return true;
+            } elseif ($this->whitespace) {
+                return $children;
+            } else {
+                return array();
+            }
+        }
+        return $result;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php
new file mode 100644
index 0000000000..0d1c8f5f39
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Required.php
@@ -0,0 +1,118 @@
+<?php
+
+/**
+ * Definition that allows a set of elements, but disallows empty children.
+ */
+class HTMLPurifier_ChildDef_Required extends HTMLPurifier_ChildDef
+{
+    /**
+     * Lookup table of allowed elements.
+     * @type array
+     */
+    public $elements = array();
+
+    /**
+     * Whether or not the last passed node was all whitespace.
+     * @type bool
+     */
+    protected $whitespace = false;
+
+    /**
+     * @param array|string $elements List of allowed element names (lowercase).
+     */
+    public function __construct($elements)
+    {
+        if (is_string($elements)) {
+            $elements = str_replace(' ', '', $elements);
+            $elements = explode('|', $elements);
+        }
+        $keys = array_keys($elements);
+        if ($keys == array_keys($keys)) {
+            $elements = array_flip($elements);
+            foreach ($elements as $i => $x) {
+                $elements[$i] = true;
+                if (empty($i)) {
+                    unset($elements[$i]);
+                } // remove blank
+            }
+        }
+        $this->elements = $elements;
+    }
+
+    /**
+     * @type bool
+     */
+    public $allow_empty = false;
+
+    /**
+     * @type string
+     */
+    public $type = 'required';
+
+    /**
+     * @param array $children
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function validateChildren($children, $config, $context)
+    {
+        // Flag for subclasses
+        $this->whitespace = false;
+
+        // if there are no tokens, delete parent node
+        if (empty($children)) {
+            return false;
+        }
+
+        // the new set of children
+        $result = array();
+
+        // whether or not parsed character data is allowed
+        // this controls whether or not we silently drop a tag
+        // or generate escaped HTML from it
+        $pcdata_allowed = isset($this->elements['#PCDATA']);
+
+        // a little sanity check to make sure it's not ALL whitespace
+        $all_whitespace = true;
+
+        $stack = array_reverse($children);
+        while (!empty($stack)) {
+            $node = array_pop($stack);
+            if (!empty($node->is_whitespace)) {
+                $result[] = $node;
+                continue;
+            }
+            $all_whitespace = false; // phew, we're not talking about whitespace
+
+            if (!isset($this->elements[$node->name])) {
+                // special case text
+                // XXX One of these ought to be redundant or something
+                if ($pcdata_allowed && $node instanceof HTMLPurifier_Node_Text) {
+                    $result[] = $node;
+                    continue;
+                }
+                // spill the child contents in
+                // ToDo: Make configurable
+                if ($node instanceof HTMLPurifier_Node_Element) {
+                    for ($i = count($node->children) - 1; $i >= 0; $i--) {
+                        $stack[] = $node->children[$i];
+                    }
+                    continue;
+                }
+                continue;
+            }
+            $result[] = $node;
+        }
+        if (empty($result)) {
+            return false;
+        }
+        if ($all_whitespace) {
+            $this->whitespace = true;
+            return false;
+        }
+        return $result;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php
new file mode 100644
index 0000000000..3270a46e1b
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/StrictBlockquote.php
@@ -0,0 +1,110 @@
+<?php
+
+/**
+ * Takes the contents of blockquote when in strict and reformats for validation.
+ */
+class HTMLPurifier_ChildDef_StrictBlockquote extends HTMLPurifier_ChildDef_Required
+{
+    /**
+     * @type array
+     */
+    protected $real_elements;
+
+    /**
+     * @type array
+     */
+    protected $fake_elements;
+
+    /**
+     * @type bool
+     */
+    public $allow_empty = true;
+
+    /**
+     * @type string
+     */
+    public $type = 'strictblockquote';
+
+    /**
+     * @type bool
+     */
+    protected $init = false;
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return array
+     * @note We don't want MakeWellFormed to auto-close inline elements since
+     *       they might be allowed.
+     */
+    public function getAllowedElements($config)
+    {
+        $this->init($config);
+        return $this->fake_elements;
+    }
+
+    /**
+     * @param array $children
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function validateChildren($children, $config, $context)
+    {
+        $this->init($config);
+
+        // trick the parent class into thinking it allows more
+        $this->elements = $this->fake_elements;
+        $result = parent::validateChildren($children, $config, $context);
+        $this->elements = $this->real_elements;
+
+        if ($result === false) {
+            return array();
+        }
+        if ($result === true) {
+            $result = $children;
+        }
+
+        $def = $config->getHTMLDefinition();
+        $block_wrap_name = $def->info_block_wrapper;
+        $block_wrap = false;
+        $ret = array();
+
+        foreach ($result as $node) {
+            if ($block_wrap === false) {
+                if (($node instanceof HTMLPurifier_Node_Text && !$node->is_whitespace) ||
+                    ($node instanceof HTMLPurifier_Node_Element && !isset($this->elements[$node->name]))) {
+                        $block_wrap = new HTMLPurifier_Node_Element($def->info_block_wrapper);
+                        $ret[] = $block_wrap;
+                }
+            } else {
+                if ($node instanceof HTMLPurifier_Node_Element && isset($this->elements[$node->name])) {
+                    $block_wrap = false;
+
+                }
+            }
+            if ($block_wrap) {
+                $block_wrap->children[] = $node;
+            } else {
+                $ret[] = $node;
+            }
+        }
+        return $ret;
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    private function init($config)
+    {
+        if (!$this->init) {
+            $def = $config->getHTMLDefinition();
+            // allow all inline elements
+            $this->real_elements = $this->elements;
+            $this->fake_elements = $def->info_content_sets['Flow'];
+            $this->fake_elements['#PCDATA'] = true;
+            $this->init = true;
+        }
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php
new file mode 100644
index 0000000000..3e4a0f2182
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ChildDef/Table.php
@@ -0,0 +1,224 @@
+<?php
+
+/**
+ * Definition for tables.  The general idea is to extract out all of the
+ * essential bits, and then reconstruct it later.
+ *
+ * This is a bit confusing, because the DTDs and the W3C
+ * validators seem to disagree on the appropriate definition. The
+ * DTD claims:
+ *
+ *      (CAPTION?, (COL*|COLGROUP*), THEAD?, TFOOT?, TBODY+)
+ *
+ * But actually, the HTML4 spec then has this to say:
+ *
+ *      The TBODY start tag is always required except when the table
+ *      contains only one table body and no table head or foot sections.
+ *      The TBODY end tag may always be safely omitted.
+ *
+ * So the DTD is kind of wrong.  The validator is, unfortunately, kind
+ * of on crack.
+ *
+ * The definition changed again in XHTML1.1; and in my opinion, this
+ * formulation makes the most sense.
+ *
+ *      caption?, ( col* | colgroup* ), (( thead?, tfoot?, tbody+ ) | ( tr+ ))
+ *
+ * Essentially, we have two modes: thead/tfoot/tbody mode, and tr mode.
+ * If we encounter a thead, tfoot or tbody, we are placed in the former
+ * mode, and we *must* wrap any stray tr segments with a tbody. But if
+ * we don't run into any of them, just have tr tags is OK.
+ */
+class HTMLPurifier_ChildDef_Table extends HTMLPurifier_ChildDef
+{
+    /**
+     * @type bool
+     */
+    public $allow_empty = false;
+
+    /**
+     * @type string
+     */
+    public $type = 'table';
+
+    /**
+     * @type array
+     */
+    public $elements = array(
+        'tr' => true,
+        'tbody' => true,
+        'thead' => true,
+        'tfoot' => true,
+        'caption' => true,
+        'colgroup' => true,
+        'col' => true
+    );
+
+    public function __construct()
+    {
+    }
+
+    /**
+     * @param array $children
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array
+     */
+    public function validateChildren($children, $config, $context)
+    {
+        if (empty($children)) {
+            return false;
+        }
+
+        // only one of these elements is allowed in a table
+        $caption = false;
+        $thead = false;
+        $tfoot = false;
+
+        // whitespace
+        $initial_ws = array();
+        $after_caption_ws = array();
+        $after_thead_ws = array();
+        $after_tfoot_ws = array();
+
+        // as many of these as you want
+        $cols = array();
+        $content = array();
+
+        $tbody_mode = false; // if true, then we need to wrap any stray
+                             // <tr>s with a <tbody>.
+
+        $ws_accum =& $initial_ws;
+
+        foreach ($children as $node) {
+            if ($node instanceof HTMLPurifier_Node_Comment) {
+                $ws_accum[] = $node;
+                continue;
+            }
+            switch ($node->name) {
+            case 'tbody':
+                $tbody_mode = true;
+                // fall through
+            case 'tr':
+                $content[] = $node;
+                $ws_accum =& $content;
+                break;
+            case 'caption':
+                // there can only be one caption!
+                if ($caption !== false)  break;
+                $caption = $node;
+                $ws_accum =& $after_caption_ws;
+                break;
+            case 'thead':
+                $tbody_mode = true;
+                // XXX This breaks rendering properties with
+                // Firefox, which never floats a <thead> to
+                // the top. Ever. (Our scheme will float the
+                // first <thead> to the top.)  So maybe
+                // <thead>s that are not first should be
+                // turned into <tbody>? Very tricky, indeed.
+                if ($thead === false) {
+                    $thead = $node;
+                    $ws_accum =& $after_thead_ws;
+                } else {
+                    // Oops, there's a second one! What
+                    // should we do?  Current behavior is to
+                    // transmutate the first and last entries into
+                    // tbody tags, and then put into content.
+                    // Maybe a better idea is to *attach
+                    // it* to the existing thead or tfoot?
+                    // We don't do this, because Firefox
+                    // doesn't float an extra tfoot to the
+                    // bottom like it does for the first one.
+                    $node->name = 'tbody';
+                    $content[] = $node;
+                    $ws_accum =& $content;
+                }
+                break;
+            case 'tfoot':
+                // see above for some aveats
+                $tbody_mode = true;
+                if ($tfoot === false) {
+                    $tfoot = $node;
+                    $ws_accum =& $after_tfoot_ws;
+                } else {
+                    $node->name = 'tbody';
+                    $content[] = $node;
+                    $ws_accum =& $content;
+                }
+                break;
+            case 'colgroup':
+            case 'col':
+                $cols[] = $node;
+                $ws_accum =& $cols;
+                break;
+            case '#PCDATA':
+                // How is whitespace handled? We treat is as sticky to
+                // the *end* of the previous element. So all of the
+                // nonsense we have worked on is to keep things
+                // together.
+                if (!empty($node->is_whitespace)) {
+                    $ws_accum[] = $node;
+                }
+                break;
+            }
+        }
+
+        if (empty($content)) {
+            return false;
+        }
+
+        $ret = $initial_ws;
+        if ($caption !== false) {
+            $ret[] = $caption;
+            $ret = array_merge($ret, $after_caption_ws);
+        }
+        if ($cols !== false) {
+            $ret = array_merge($ret, $cols);
+        }
+        if ($thead !== false) {
+            $ret[] = $thead;
+            $ret = array_merge($ret, $after_thead_ws);
+        }
+        if ($tfoot !== false) {
+            $ret[] = $tfoot;
+            $ret = array_merge($ret, $after_tfoot_ws);
+        }
+
+        if ($tbody_mode) {
+            // we have to shuffle tr into tbody
+            $current_tr_tbody = null;
+
+            foreach($content as $node) {
+                switch ($node->name) {
+                case 'tbody':
+                    $current_tr_tbody = null;
+                    $ret[] = $node;
+                    break;
+                case 'tr':
+                    if ($current_tr_tbody === null) {
+                        $current_tr_tbody = new HTMLPurifier_Node_Element('tbody');
+                        $ret[] = $current_tr_tbody;
+                    }
+                    $current_tr_tbody->children[] = $node;
+                    break;
+                case '#PCDATA':
+                    assert($node->is_whitespace);
+                    if ($current_tr_tbody === null) {
+                        $ret[] = $node;
+                    } else {
+                        $current_tr_tbody->children[] = $node;
+                    }
+                    break;
+                }
+            }
+        } else {
+            $ret = array_merge($ret, $content);
+        }
+
+        return $ret;
+
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Config.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Config.php
new file mode 100644
index 0000000000..2b2db0c264
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Config.php
@@ -0,0 +1,920 @@
+<?php
+
+/**
+ * Configuration object that triggers customizable behavior.
+ *
+ * @warning This class is strongly defined: that means that the class
+ *          will fail if an undefined directive is retrieved or set.
+ *
+ * @note Many classes that could (although many times don't) use the
+ *       configuration object make it a mandatory parameter.  This is
+ *       because a configuration object should always be forwarded,
+ *       otherwise, you run the risk of missing a parameter and then
+ *       being stumped when a configuration directive doesn't work.
+ *
+ * @todo Reconsider some of the public member variables
+ */
+class HTMLPurifier_Config
+{
+
+    /**
+     * HTML Purifier's version
+     * @type string
+     */
+    public $version = '4.7.0';
+
+    /**
+     * Whether or not to automatically finalize
+     * the object if a read operation is done.
+     * @type bool
+     */
+    public $autoFinalize = true;
+
+    // protected member variables
+
+    /**
+     * Namespace indexed array of serials for specific namespaces.
+     * @see getSerial() for more info.
+     * @type string[]
+     */
+    protected $serials = array();
+
+    /**
+     * Serial for entire configuration object.
+     * @type string
+     */
+    protected $serial;
+
+    /**
+     * Parser for variables.
+     * @type HTMLPurifier_VarParser_Flexible
+     */
+    protected $parser = null;
+
+    /**
+     * Reference HTMLPurifier_ConfigSchema for value checking.
+     * @type HTMLPurifier_ConfigSchema
+     * @note This is public for introspective purposes. Please don't
+     *       abuse!
+     */
+    public $def;
+
+    /**
+     * Indexed array of definitions.
+     * @type HTMLPurifier_Definition[]
+     */
+    protected $definitions;
+
+    /**
+     * Whether or not config is finalized.
+     * @type bool
+     */
+    protected $finalized = false;
+
+    /**
+     * Property list containing configuration directives.
+     * @type array
+     */
+    protected $plist;
+
+    /**
+     * Whether or not a set is taking place due to an alias lookup.
+     * @type bool
+     */
+    private $aliasMode;
+
+    /**
+     * Set to false if you do not want line and file numbers in errors.
+     * (useful when unit testing).  This will also compress some errors
+     * and exceptions.
+     * @type bool
+     */
+    public $chatty = true;
+
+    /**
+     * Current lock; only gets to this namespace are allowed.
+     * @type string
+     */
+    private $lock;
+
+    /**
+     * Constructor
+     * @param HTMLPurifier_ConfigSchema $definition ConfigSchema that defines
+     * what directives are allowed.
+     * @param HTMLPurifier_PropertyList $parent
+     */
+    public function __construct($definition, $parent = null)
+    {
+        $parent = $parent ? $parent : $definition->defaultPlist;
+        $this->plist = new HTMLPurifier_PropertyList($parent);
+        $this->def = $definition; // keep a copy around for checking
+        $this->parser = new HTMLPurifier_VarParser_Flexible();
+    }
+
+    /**
+     * Convenience constructor that creates a config object based on a mixed var
+     * @param mixed $config Variable that defines the state of the config
+     *                      object. Can be: a HTMLPurifier_Config() object,
+     *                      an array of directives based on loadArray(),
+     *                      or a string filename of an ini file.
+     * @param HTMLPurifier_ConfigSchema $schema Schema object
+     * @return HTMLPurifier_Config Configured object
+     */
+    public static function create($config, $schema = null)
+    {
+        if ($config instanceof HTMLPurifier_Config) {
+            // pass-through
+            return $config;
+        }
+        if (!$schema) {
+            $ret = HTMLPurifier_Config::createDefault();
+        } else {
+            $ret = new HTMLPurifier_Config($schema);
+        }
+        if (is_string($config)) {
+            $ret->loadIni($config);
+        } elseif (is_array($config)) $ret->loadArray($config);
+        return $ret;
+    }
+
+    /**
+     * Creates a new config object that inherits from a previous one.
+     * @param HTMLPurifier_Config $config Configuration object to inherit from.
+     * @return HTMLPurifier_Config object with $config as its parent.
+     */
+    public static function inherit(HTMLPurifier_Config $config)
+    {
+        return new HTMLPurifier_Config($config->def, $config->plist);
+    }
+
+    /**
+     * Convenience constructor that creates a default configuration object.
+     * @return HTMLPurifier_Config default object.
+     */
+    public static function createDefault()
+    {
+        $definition = HTMLPurifier_ConfigSchema::instance();
+        $config = new HTMLPurifier_Config($definition);
+        return $config;
+    }
+
+    /**
+     * Retrieves a value from the configuration.
+     *
+     * @param string $key String key
+     * @param mixed $a
+     *
+     * @return mixed
+     */
+    public function get($key, $a = null)
+    {
+        if ($a !== null) {
+            $this->triggerError(
+                "Using deprecated API: use \$config->get('$key.$a') instead",
+                E_USER_WARNING
+            );
+            $key = "$key.$a";
+        }
+        if (!$this->finalized) {
+            $this->autoFinalize();
+        }
+        if (!isset($this->def->info[$key])) {
+            // can't add % due to SimpleTest bug
+            $this->triggerError(
+                'Cannot retrieve value of undefined directive ' . htmlspecialchars($key),
+                E_USER_WARNING
+            );
+            return;
+        }
+        if (isset($this->def->info[$key]->isAlias)) {
+            $d = $this->def->info[$key];
+            $this->triggerError(
+                'Cannot get value from aliased directive, use real name ' . $d->key,
+                E_USER_ERROR
+            );
+            return;
+        }
+        if ($this->lock) {
+            list($ns) = explode('.', $key);
+            if ($ns !== $this->lock) {
+                $this->triggerError(
+                    'Cannot get value of namespace ' . $ns . ' when lock for ' .
+                    $this->lock .
+                    ' is active, this probably indicates a Definition setup method ' .
+                    'is accessing directives that are not within its namespace',
+                    E_USER_ERROR
+                );
+                return;
+            }
+        }
+        return $this->plist->get($key);
+    }
+
+    /**
+     * Retrieves an array of directives to values from a given namespace
+     *
+     * @param string $namespace String namespace
+     *
+     * @return array
+     */
+    public function getBatch($namespace)
+    {
+        if (!$this->finalized) {
+            $this->autoFinalize();
+        }
+        $full = $this->getAll();
+        if (!isset($full[$namespace])) {
+            $this->triggerError(
+                'Cannot retrieve undefined namespace ' .
+                htmlspecialchars($namespace),
+                E_USER_WARNING
+            );
+            return;
+        }
+        return $full[$namespace];
+    }
+
+    /**
+     * Returns a SHA-1 signature of a segment of the configuration object
+     * that uniquely identifies that particular configuration
+     *
+     * @param string $namespace Namespace to get serial for
+     *
+     * @return string
+     * @note Revision is handled specially and is removed from the batch
+     *       before processing!
+     */
+    public function getBatchSerial($namespace)
+    {
+        if (empty($this->serials[$namespace])) {
+            $batch = $this->getBatch($namespace);
+            unset($batch['DefinitionRev']);
+            $this->serials[$namespace] = sha1(serialize($batch));
+        }
+        return $this->serials[$namespace];
+    }
+
+    /**
+     * Returns a SHA-1 signature for the entire configuration object
+     * that uniquely identifies that particular configuration
+     *
+     * @return string
+     */
+    public function getSerial()
+    {
+        if (empty($this->serial)) {
+            $this->serial = sha1(serialize($this->getAll()));
+        }
+        return $this->serial;
+    }
+
+    /**
+     * Retrieves all directives, organized by namespace
+     *
+     * @warning This is a pretty inefficient function, avoid if you can
+     */
+    public function getAll()
+    {
+        if (!$this->finalized) {
+            $this->autoFinalize();
+        }
+        $ret = array();
+        foreach ($this->plist->squash() as $name => $value) {
+            list($ns, $key) = explode('.', $name, 2);
+            $ret[$ns][$key] = $value;
+        }
+        return $ret;
+    }
+
+    /**
+     * Sets a value to configuration.
+     *
+     * @param string $key key
+     * @param mixed $value value
+     * @param mixed $a
+     */
+    public function set($key, $value, $a = null)
+    {
+        if (strpos($key, '.') === false) {
+            $namespace = $key;
+            $directive = $value;
+            $value = $a;
+            $key = "$key.$directive";
+            $this->triggerError("Using deprecated API: use \$config->set('$key', ...) instead", E_USER_NOTICE);
+        } else {
+            list($namespace) = explode('.', $key);
+        }
+        if ($this->isFinalized('Cannot set directive after finalization')) {
+            return;
+        }
+        if (!isset($this->def->info[$key])) {
+            $this->triggerError(
+                'Cannot set undefined directive ' . htmlspecialchars($key) . ' to value',
+                E_USER_WARNING
+            );
+            return;
+        }
+        $def = $this->def->info[$key];
+
+        if (isset($def->isAlias)) {
+            if ($this->aliasMode) {
+                $this->triggerError(
+                    'Double-aliases not allowed, please fix '.
+                    'ConfigSchema bug with' . $key,
+                    E_USER_ERROR
+                );
+                return;
+            }
+            $this->aliasMode = true;
+            $this->set($def->key, $value);
+            $this->aliasMode = false;
+            $this->triggerError("$key is an alias, preferred directive name is {$def->key}", E_USER_NOTICE);
+            return;
+        }
+
+        // Raw type might be negative when using the fully optimized form
+        // of stdclass, which indicates allow_null == true
+        $rtype = is_int($def) ? $def : $def->type;
+        if ($rtype < 0) {
+            $type = -$rtype;
+            $allow_null = true;
+        } else {
+            $type = $rtype;
+            $allow_null = isset($def->allow_null);
+        }
+
+        try {
+            $value = $this->parser->parse($value, $type, $allow_null);
+        } catch (HTMLPurifier_VarParserException $e) {
+            $this->triggerError(
+                'Value for ' . $key . ' is of invalid type, should be ' .
+                HTMLPurifier_VarParser::getTypeName($type),
+                E_USER_WARNING
+            );
+            return;
+        }
+        if (is_string($value) && is_object($def)) {
+            // resolve value alias if defined
+            if (isset($def->aliases[$value])) {
+                $value = $def->aliases[$value];
+            }
+            // check to see if the value is allowed
+            if (isset($def->allowed) && !isset($def->allowed[$value])) {
+                $this->triggerError(
+                    'Value not supported, valid values are: ' .
+                    $this->_listify($def->allowed),
+                    E_USER_WARNING
+                );
+                return;
+            }
+        }
+        $this->plist->set($key, $value);
+
+        // reset definitions if the directives they depend on changed
+        // this is a very costly process, so it's discouraged
+        // with finalization
+        if ($namespace == 'HTML' || $namespace == 'CSS' || $namespace == 'URI') {
+            $this->definitions[$namespace] = null;
+        }
+
+        $this->serials[$namespace] = false;
+    }
+
+    /**
+     * Convenience function for error reporting
+     *
+     * @param array $lookup
+     *
+     * @return string
+     */
+    private function _listify($lookup)
+    {
+        $list = array();
+        foreach ($lookup as $name => $b) {
+            $list[] = $name;
+        }
+        return implode(', ', $list);
+    }
+
+    /**
+     * Retrieves object reference to the HTML definition.
+     *
+     * @param bool $raw Return a copy that has not been setup yet. Must be
+     *             called before it's been setup, otherwise won't work.
+     * @param bool $optimized If true, this method may return null, to
+     *             indicate that a cached version of the modified
+     *             definition object is available and no further edits
+     *             are necessary.  Consider using
+     *             maybeGetRawHTMLDefinition, which is more explicitly
+     *             named, instead.
+     *
+     * @return HTMLPurifier_HTMLDefinition
+     */
+    public function getHTMLDefinition($raw = false, $optimized = false)
+    {
+        return $this->getDefinition('HTML', $raw, $optimized);
+    }
+
+    /**
+     * Retrieves object reference to the CSS definition
+     *
+     * @param bool $raw Return a copy that has not been setup yet. Must be
+     *             called before it's been setup, otherwise won't work.
+     * @param bool $optimized If true, this method may return null, to
+     *             indicate that a cached version of the modified
+     *             definition object is available and no further edits
+     *             are necessary.  Consider using
+     *             maybeGetRawCSSDefinition, which is more explicitly
+     *             named, instead.
+     *
+     * @return HTMLPurifier_CSSDefinition
+     */
+    public function getCSSDefinition($raw = false, $optimized = false)
+    {
+        return $this->getDefinition('CSS', $raw, $optimized);
+    }
+
+    /**
+     * Retrieves object reference to the URI definition
+     *
+     * @param bool $raw Return a copy that has not been setup yet. Must be
+     *             called before it's been setup, otherwise won't work.
+     * @param bool $optimized If true, this method may return null, to
+     *             indicate that a cached version of the modified
+     *             definition object is available and no further edits
+     *             are necessary.  Consider using
+     *             maybeGetRawURIDefinition, which is more explicitly
+     *             named, instead.
+     *
+     * @return HTMLPurifier_URIDefinition
+     */
+    public function getURIDefinition($raw = false, $optimized = false)
+    {
+        return $this->getDefinition('URI', $raw, $optimized);
+    }
+
+    /**
+     * Retrieves a definition
+     *
+     * @param string $type Type of definition: HTML, CSS, etc
+     * @param bool $raw Whether or not definition should be returned raw
+     * @param bool $optimized Only has an effect when $raw is true.  Whether
+     *        or not to return null if the result is already present in
+     *        the cache.  This is off by default for backwards
+     *        compatibility reasons, but you need to do things this
+     *        way in order to ensure that caching is done properly.
+     *        Check out enduser-customize.html for more details.
+     *        We probably won't ever change this default, as much as the
+     *        maybe semantics is the "right thing to do."
+     *
+     * @throws HTMLPurifier_Exception
+     * @return HTMLPurifier_Definition
+     */
+    public function getDefinition($type, $raw = false, $optimized = false)
+    {
+        if ($optimized && !$raw) {
+            throw new HTMLPurifier_Exception("Cannot set optimized = true when raw = false");
+        }
+        if (!$this->finalized) {
+            $this->autoFinalize();
+        }
+        // temporarily suspend locks, so we can handle recursive definition calls
+        $lock = $this->lock;
+        $this->lock = null;
+        $factory = HTMLPurifier_DefinitionCacheFactory::instance();
+        $cache = $factory->create($type, $this);
+        $this->lock = $lock;
+        if (!$raw) {
+            // full definition
+            // ---------------
+            // check if definition is in memory
+            if (!empty($this->definitions[$type])) {
+                $def = $this->definitions[$type];
+                // check if the definition is setup
+                if ($def->setup) {
+                    return $def;
+                } else {
+                    $def->setup($this);
+                    if ($def->optimized) {
+                        $cache->add($def, $this);
+                    }
+                    return $def;
+                }
+            }
+            // check if definition is in cache
+            $def = $cache->get($this);
+            if ($def) {
+                // definition in cache, save to memory and return it
+                $this->definitions[$type] = $def;
+                return $def;
+            }
+            // initialize it
+            $def = $this->initDefinition($type);
+            // set it up
+            $this->lock = $type;
+            $def->setup($this);
+            $this->lock = null;
+            // save in cache
+            $cache->add($def, $this);
+            // return it
+            return $def;
+        } else {
+            // raw definition
+            // --------------
+            // check preconditions
+            $def = null;
+            if ($optimized) {
+                if (is_null($this->get($type . '.DefinitionID'))) {
+                    // fatally error out if definition ID not set
+                    throw new HTMLPurifier_Exception(
+                        "Cannot retrieve raw version without specifying %$type.DefinitionID"
+                    );
+                }
+            }
+            if (!empty($this->definitions[$type])) {
+                $def = $this->definitions[$type];
+                if ($def->setup && !$optimized) {
+                    $extra = $this->chatty ?
+                        " (try moving this code block earlier in your initialization)" :
+                        "";
+                    throw new HTMLPurifier_Exception(
+                        "Cannot retrieve raw definition after it has already been setup" .
+                        $extra
+                    );
+                }
+                if ($def->optimized === null) {
+                    $extra = $this->chatty ? " (try flushing your cache)" : "";
+                    throw new HTMLPurifier_Exception(
+                        "Optimization status of definition is unknown" . $extra
+                    );
+                }
+                if ($def->optimized !== $optimized) {
+                    $msg = $optimized ? "optimized" : "unoptimized";
+                    $extra = $this->chatty ?
+                        " (this backtrace is for the first inconsistent call, which was for a $msg raw definition)"
+                        : "";
+                    throw new HTMLPurifier_Exception(
+                        "Inconsistent use of optimized and unoptimized raw definition retrievals" . $extra
+                    );
+                }
+            }
+            // check if definition was in memory
+            if ($def) {
+                if ($def->setup) {
+                    // invariant: $optimized === true (checked above)
+                    return null;
+                } else {
+                    return $def;
+                }
+            }
+            // if optimized, check if definition was in cache
+            // (because we do the memory check first, this formulation
+            // is prone to cache slamming, but I think
+            // guaranteeing that either /all/ of the raw
+            // setup code or /none/ of it is run is more important.)
+            if ($optimized) {
+                // This code path only gets run once; once we put
+                // something in $definitions (which is guaranteed by the
+                // trailing code), we always short-circuit above.
+                $def = $cache->get($this);
+                if ($def) {
+                    // save the full definition for later, but don't
+                    // return it yet
+                    $this->definitions[$type] = $def;
+                    return null;
+                }
+            }
+            // check invariants for creation
+            if (!$optimized) {
+                if (!is_null($this->get($type . '.DefinitionID'))) {
+                    if ($this->chatty) {
+                        $this->triggerError(
+                            'Due to a documentation error in previous version of HTML Purifier, your ' .
+                            'definitions are not being cached.  If this is OK, you can remove the ' .
+                            '%$type.DefinitionRev and %$type.DefinitionID declaration.  Otherwise, ' .
+                            'modify your code to use maybeGetRawDefinition, and test if the returned ' .
+                            'value is null before making any edits (if it is null, that means that a ' .
+                            'cached version is available, and no raw operations are necessary).  See ' .
+                            '<a href="http://htmlpurifier.org/docs/enduser-customize.html#optimized">' .
+                            'Customize</a> for more details',
+                            E_USER_WARNING
+                        );
+                    } else {
+                        $this->triggerError(
+                            "Useless DefinitionID declaration",
+                            E_USER_WARNING
+                        );
+                    }
+                }
+            }
+            // initialize it
+            $def = $this->initDefinition($type);
+            $def->optimized = $optimized;
+            return $def;
+        }
+        throw new HTMLPurifier_Exception("The impossible happened!");
+    }
+
+    /**
+     * Initialise definition
+     *
+     * @param string $type What type of definition to create
+     *
+     * @return HTMLPurifier_CSSDefinition|HTMLPurifier_HTMLDefinition|HTMLPurifier_URIDefinition
+     * @throws HTMLPurifier_Exception
+     */
+    private function initDefinition($type)
+    {
+        // quick checks failed, let's create the object
+        if ($type == 'HTML') {
+            $def = new HTMLPurifier_HTMLDefinition();
+        } elseif ($type == 'CSS') {
+            $def = new HTMLPurifier_CSSDefinition();
+        } elseif ($type == 'URI') {
+            $def = new HTMLPurifier_URIDefinition();
+        } else {
+            throw new HTMLPurifier_Exception(
+                "Definition of $type type not supported"
+            );
+        }
+        $this->definitions[$type] = $def;
+        return $def;
+    }
+
+    public function maybeGetRawDefinition($name)
+    {
+        return $this->getDefinition($name, true, true);
+    }
+
+    /**
+     * @return HTMLPurifier_HTMLDefinition
+     */
+    public function maybeGetRawHTMLDefinition()
+    {
+        return $this->getDefinition('HTML', true, true);
+    }
+    
+    /**
+     * @return HTMLPurifier_CSSDefinition
+     */
+    public function maybeGetRawCSSDefinition()
+    {
+        return $this->getDefinition('CSS', true, true);
+    }
+    
+    /**
+     * @return HTMLPurifier_URIDefinition
+     */
+    public function maybeGetRawURIDefinition()
+    {
+        return $this->getDefinition('URI', true, true);
+    }
+
+    /**
+     * Loads configuration values from an array with the following structure:
+     * Namespace.Directive => Value
+     *
+     * @param array $config_array Configuration associative array
+     */
+    public function loadArray($config_array)
+    {
+        if ($this->isFinalized('Cannot load directives after finalization')) {
+            return;
+        }
+        foreach ($config_array as $key => $value) {
+            $key = str_replace('_', '.', $key);
+            if (strpos($key, '.') !== false) {
+                $this->set($key, $value);
+            } else {
+                $namespace = $key;
+                $namespace_values = $value;
+                foreach ($namespace_values as $directive => $value2) {
+                    $this->set($namespace .'.'. $directive, $value2);
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns a list of array(namespace, directive) for all directives
+     * that are allowed in a web-form context as per an allowed
+     * namespaces/directives list.
+     *
+     * @param array $allowed List of allowed namespaces/directives
+     * @param HTMLPurifier_ConfigSchema $schema Schema to use, if not global copy
+     *
+     * @return array
+     */
+    public static function getAllowedDirectivesForForm($allowed, $schema = null)
+    {
+        if (!$schema) {
+            $schema = HTMLPurifier_ConfigSchema::instance();
+        }
+        if ($allowed !== true) {
+            if (is_string($allowed)) {
+                $allowed = array($allowed);
+            }
+            $allowed_ns = array();
+            $allowed_directives = array();
+            $blacklisted_directives = array();
+            foreach ($allowed as $ns_or_directive) {
+                if (strpos($ns_or_directive, '.') !== false) {
+                    // directive
+                    if ($ns_or_directive[0] == '-') {
+                        $blacklisted_directives[substr($ns_or_directive, 1)] = true;
+                    } else {
+                        $allowed_directives[$ns_or_directive] = true;
+                    }
+                } else {
+                    // namespace
+                    $allowed_ns[$ns_or_directive] = true;
+                }
+            }
+        }
+        $ret = array();
+        foreach ($schema->info as $key => $def) {
+            list($ns, $directive) = explode('.', $key, 2);
+            if ($allowed !== true) {
+                if (isset($blacklisted_directives["$ns.$directive"])) {
+                    continue;
+                }
+                if (!isset($allowed_directives["$ns.$directive"]) && !isset($allowed_ns[$ns])) {
+                    continue;
+                }
+            }
+            if (isset($def->isAlias)) {
+                continue;
+            }
+            if ($directive == 'DefinitionID' || $directive == 'DefinitionRev') {
+                continue;
+            }
+            $ret[] = array($ns, $directive);
+        }
+        return $ret;
+    }
+
+    /**
+     * Loads configuration values from $_GET/$_POST that were posted
+     * via ConfigForm
+     *
+     * @param array $array $_GET or $_POST array to import
+     * @param string|bool $index Index/name that the config variables are in
+     * @param array|bool $allowed List of allowed namespaces/directives
+     * @param bool $mq_fix Boolean whether or not to enable magic quotes fix
+     * @param HTMLPurifier_ConfigSchema $schema Schema to use, if not global copy
+     *
+     * @return mixed
+     */
+    public static function loadArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null)
+    {
+        $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $schema);
+        $config = HTMLPurifier_Config::create($ret, $schema);
+        return $config;
+    }
+
+    /**
+     * Merges in configuration values from $_GET/$_POST to object. NOT STATIC.
+     *
+     * @param array $array $_GET or $_POST array to import
+     * @param string|bool $index Index/name that the config variables are in
+     * @param array|bool $allowed List of allowed namespaces/directives
+     * @param bool $mq_fix Boolean whether or not to enable magic quotes fix
+     */
+    public function mergeArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true)
+    {
+         $ret = HTMLPurifier_Config::prepareArrayFromForm($array, $index, $allowed, $mq_fix, $this->def);
+         $this->loadArray($ret);
+    }
+
+    /**
+     * Prepares an array from a form into something usable for the more
+     * strict parts of HTMLPurifier_Config
+     *
+     * @param array $array $_GET or $_POST array to import
+     * @param string|bool $index Index/name that the config variables are in
+     * @param array|bool $allowed List of allowed namespaces/directives
+     * @param bool $mq_fix Boolean whether or not to enable magic quotes fix
+     * @param HTMLPurifier_ConfigSchema $schema Schema to use, if not global copy
+     *
+     * @return array
+     */
+    public static function prepareArrayFromForm($array, $index = false, $allowed = true, $mq_fix = true, $schema = null)
+    {
+        if ($index !== false) {
+            $array = (isset($array[$index]) && is_array($array[$index])) ? $array[$index] : array();
+        }
+        $mq = $mq_fix && function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc();
+
+        $allowed = HTMLPurifier_Config::getAllowedDirectivesForForm($allowed, $schema);
+        $ret = array();
+        foreach ($allowed as $key) {
+            list($ns, $directive) = $key;
+            $skey = "$ns.$directive";
+            if (!empty($array["Null_$skey"])) {
+                $ret[$ns][$directive] = null;
+                continue;
+            }
+            if (!isset($array[$skey])) {
+                continue;
+            }
+            $value = $mq ? stripslashes($array[$skey]) : $array[$skey];
+            $ret[$ns][$directive] = $value;
+        }
+        return $ret;
+    }
+
+    /**
+     * Loads configuration values from an ini file
+     *
+     * @param string $filename Name of ini file
+     */
+    public function loadIni($filename)
+    {
+        if ($this->isFinalized('Cannot load directives after finalization')) {
+            return;
+        }
+        $array = parse_ini_file($filename, true);
+        $this->loadArray($array);
+    }
+
+    /**
+     * Checks whether or not the configuration object is finalized.
+     *
+     * @param string|bool $error String error message, or false for no error
+     *
+     * @return bool
+     */
+    public function isFinalized($error = false)
+    {
+        if ($this->finalized && $error) {
+            $this->triggerError($error, E_USER_ERROR);
+        }
+        return $this->finalized;
+    }
+
+    /**
+     * Finalizes configuration only if auto finalize is on and not
+     * already finalized
+     */
+    public function autoFinalize()
+    {
+        if ($this->autoFinalize) {
+            $this->finalize();
+        } else {
+            $this->plist->squash(true);
+        }
+    }
+
+    /**
+     * Finalizes a configuration object, prohibiting further change
+     */
+    public function finalize()
+    {
+        $this->finalized = true;
+        $this->parser = null;
+    }
+
+    /**
+     * Produces a nicely formatted error message by supplying the
+     * stack frame information OUTSIDE of HTMLPurifier_Config.
+     *
+     * @param string $msg An error message
+     * @param int $no An error number
+     */
+    protected function triggerError($msg, $no)
+    {
+        // determine previous stack frame
+        $extra = '';
+        if ($this->chatty) {
+            $trace = debug_backtrace();
+            // zip(tail(trace), trace) -- but PHP is not Haskell har har
+            for ($i = 0, $c = count($trace); $i < $c - 1; $i++) {
+                // XXX this is not correct on some versions of HTML Purifier
+                if ($trace[$i + 1]['class'] === 'HTMLPurifier_Config') {
+                    continue;
+                }
+                $frame = $trace[$i];
+                $extra = " invoked on line {$frame['line']} in file {$frame['file']}";
+                break;
+            }
+        }
+        trigger_error($msg . $extra, $no);
+    }
+
+    /**
+     * Returns a serialized form of the configuration object that can
+     * be reconstituted.
+     *
+     * @return string
+     */
+    public function serialize()
+    {
+        $this->getDefinition('HTML');
+        $this->getDefinition('CSS');
+        $this->getDefinition('URI');
+        return serialize($this);
+    }
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema.php
similarity index 69%
rename from library/HTMLPurifier/ConfigSchema.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema.php
index 67be5c71fd..bfbb0f92f5 100644
--- a/library/HTMLPurifier/ConfigSchema.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema.php
@@ -3,21 +3,24 @@
 /**
  * Configuration definition, defines directives and their defaults.
  */
-class HTMLPurifier_ConfigSchema {
-
+class HTMLPurifier_ConfigSchema
+{
     /**
      * Defaults of the directives and namespaces.
+     * @type array
      * @note This shares the exact same structure as HTMLPurifier_Config::$conf
      */
     public $defaults = array();
 
     /**
      * The default property list. Do not edit this property list.
+     * @type array
      */
     public $defaultPlist;
 
     /**
-     * Definition of the directives. The structure of this is:
+     * Definition of the directives.
+     * The structure of this is:
      *
      *  array(
      *      'Namespace' => array(
@@ -44,29 +47,43 @@ class HTMLPurifier_ConfigSchema {
      * This class is friendly with HTMLPurifier_Config. If you need introspection
      * about the schema, you're better of using the ConfigSchema_Interchange,
      * which uses more memory but has much richer information.
+     * @type array
      */
     public $info = array();
 
     /**
      * Application-wide singleton
+     * @type HTMLPurifier_ConfigSchema
      */
-    static protected $singleton;
+    protected static $singleton;
 
-    public function __construct() {
+    public function __construct()
+    {
         $this->defaultPlist = new HTMLPurifier_PropertyList();
     }
 
     /**
      * Unserializes the default ConfigSchema.
+     * @return HTMLPurifier_ConfigSchema
      */
-    public static function makeFromSerial() {
-        return unserialize(file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema.ser'));
+    public static function makeFromSerial()
+    {
+        $contents = file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema.ser');
+        $r = unserialize($contents);
+        if (!$r) {
+            $hash = sha1($contents);
+            trigger_error("Unserialization of configuration schema failed, sha1 of file was $hash", E_USER_ERROR);
+        }
+        return $r;
     }
 
     /**
      * Retrieves an instance of the application-wide configuration definition.
+     * @param HTMLPurifier_ConfigSchema $prototype
+     * @return HTMLPurifier_ConfigSchema
      */
-    public static function instance($prototype = null) {
+    public static function instance($prototype = null)
+    {
         if ($prototype !== null) {
             HTMLPurifier_ConfigSchema::$singleton = $prototype;
         } elseif (HTMLPurifier_ConfigSchema::$singleton === null || $prototype === true) {
@@ -80,17 +97,19 @@ class HTMLPurifier_ConfigSchema {
      * @warning Will fail of directive's namespace is defined.
      * @warning This method's signature is slightly different from the legacy
      *          define() static method! Beware!
-     * @param $namespace Namespace the directive is in
-     * @param $name Key of directive
-     * @param $default Default value of directive
-     * @param $type Allowed type of the directive. See
+     * @param string $key Name of directive
+     * @param mixed $default Default value of directive
+     * @param string $type Allowed type of the directive. See
      *      HTMLPurifier_DirectiveDef::$type for allowed values
-     * @param $allow_null Whether or not to allow null values
+     * @param bool $allow_null Whether or not to allow null values
      */
-    public function add($key, $default, $type, $allow_null) {
+    public function add($key, $default, $type, $allow_null)
+    {
         $obj = new stdclass();
         $obj->type = is_int($type) ? $type : HTMLPurifier_VarParser::$types[$type];
-        if ($allow_null) $obj->allow_null = true;
+        if ($allow_null) {
+            $obj->allow_null = true;
+        }
         $this->info[$key] = $obj;
         $this->defaults[$key] = $default;
         $this->defaultPlist->set($key, $default);
@@ -101,11 +120,11 @@ class HTMLPurifier_ConfigSchema {
      *
      * Directive value aliases are convenient for developers because it lets
      * them set a directive to several values and get the same result.
-     * @param $namespace Directive's namespace
-     * @param $name Name of Directive
-     * @param $aliases Hash of aliased values to the real alias
+     * @param string $key Name of Directive
+     * @param array $aliases Hash of aliased values to the real alias
      */
-    public function addValueAliases($key, $aliases) {
+    public function addValueAliases($key, $aliases)
+    {
         if (!isset($this->info[$key]->aliases)) {
             $this->info[$key]->aliases = array();
         }
@@ -118,22 +137,21 @@ class HTMLPurifier_ConfigSchema {
      * Defines a set of allowed values for a directive.
      * @warning This is slightly different from the corresponding static
      *          method definition.
-     * @param $namespace Namespace of directive
-     * @param $name Name of directive
-     * @param $allowed Lookup array of allowed values
+     * @param string $key Name of directive
+     * @param array $allowed Lookup array of allowed values
      */
-    public function addAllowedValues($key, $allowed) {
+    public function addAllowedValues($key, $allowed)
+    {
         $this->info[$key]->allowed = $allowed;
     }
 
     /**
      * Defines a directive alias for backwards compatibility
-     * @param $namespace
-     * @param $name Directive that will be aliased
-     * @param $new_namespace
-     * @param $new_name Directive that the alias will be to
+     * @param string $key Directive that will be aliased
+     * @param string $new_key Directive that the alias will be to
      */
-    public function addAlias($key, $new_key) {
+    public function addAlias($key, $new_key)
+    {
         $obj = new stdclass;
         $obj->key = $new_key;
         $obj->isAlias = true;
@@ -143,7 +161,8 @@ class HTMLPurifier_ConfigSchema {
     /**
      * Replaces any stdclass that only has the type property with type integer.
      */
-    public function postProcess() {
+    public function postProcess()
+    {
         foreach ($this->info as $key => $v) {
             if (count((array) $v) == 1) {
                 $this->info[$key] = $v->type;
@@ -152,7 +171,6 @@ class HTMLPurifier_ConfigSchema {
             }
         }
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php
similarity index 86%
rename from library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php
index c05668a706..d5906cd46d 100644
--- a/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/ConfigSchema.php
@@ -7,7 +7,12 @@
 class HTMLPurifier_ConfigSchema_Builder_ConfigSchema
 {
 
-    public function build($interchange) {
+    /**
+     * @param HTMLPurifier_ConfigSchema_Interchange $interchange
+     * @return HTMLPurifier_ConfigSchema
+     */
+    public function build($interchange)
+    {
         $schema = new HTMLPurifier_ConfigSchema();
         foreach ($interchange->directives as $d) {
             $schema->add(
@@ -38,7 +43,6 @@ class HTMLPurifier_ConfigSchema_Builder_ConfigSchema
         $schema->postProcess();
         return $schema;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/Builder/Xml.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/Xml.php
similarity index 52%
rename from library/HTMLPurifier/ConfigSchema/Builder/Xml.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/Xml.php
index 244561a372..5fa56f7ddb 100644
--- a/library/HTMLPurifier/ConfigSchema/Builder/Xml.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Builder/Xml.php
@@ -7,10 +7,21 @@
 class HTMLPurifier_ConfigSchema_Builder_Xml extends XMLWriter
 {
 
+    /**
+     * @type HTMLPurifier_ConfigSchema_Interchange
+     */
     protected $interchange;
+
+    /**
+     * @type string
+     */
     private $namespace;
 
-    protected function writeHTMLDiv($html) {
+    /**
+     * @param string $html
+     */
+    protected function writeHTMLDiv($html)
+    {
         $this->startElement('div');
 
         $purifier = HTMLPurifier::getInstance();
@@ -21,12 +32,23 @@ class HTMLPurifier_ConfigSchema_Builder_Xml extends XMLWriter
         $this->endElement(); // div
     }
 
-    protected function export($var) {
-        if ($var === array()) return 'array()';
+    /**
+     * @param mixed $var
+     * @return string
+     */
+    protected function export($var)
+    {
+        if ($var === array()) {
+            return 'array()';
+        }
         return var_export($var, true);
     }
 
-    public function build($interchange) {
+    /**
+     * @param HTMLPurifier_ConfigSchema_Interchange $interchange
+     */
+    public function build($interchange)
+    {
         // global access, only use as last resort
         $this->interchange = $interchange;
 
@@ -39,19 +61,26 @@ class HTMLPurifier_ConfigSchema_Builder_Xml extends XMLWriter
             $this->buildDirective($directive);
         }
 
-        if ($this->namespace) $this->endElement(); // namespace
+        if ($this->namespace) {
+            $this->endElement();
+        } // namespace
 
         $this->endElement(); // configdoc
         $this->flush();
     }
 
-    public function buildDirective($directive) {
-
+    /**
+     * @param HTMLPurifier_ConfigSchema_Interchange_Directive $directive
+     */
+    public function buildDirective($directive)
+    {
         // Kludge, although I suppose having a notion of a "root namespace"
         // certainly makes things look nicer when documentation is built.
         // Depends on things being sorted.
         if (!$this->namespace || $this->namespace !== $directive->id->getRootNamespace()) {
-            if ($this->namespace) $this->endElement(); // namespace
+            if ($this->namespace) {
+                $this->endElement();
+            } // namespace
             $this->namespace = $directive->id->getRootNamespace();
             $this->startElement('namespace');
             $this->writeAttribute('id', $this->namespace);
@@ -64,43 +93,52 @@ class HTMLPurifier_ConfigSchema_Builder_Xml extends XMLWriter
         $this->writeElement('name', $directive->id->getDirective());
 
         $this->startElement('aliases');
-            foreach ($directive->aliases as $alias) $this->writeElement('alias', $alias->toString());
+        foreach ($directive->aliases as $alias) {
+            $this->writeElement('alias', $alias->toString());
+        }
         $this->endElement(); // aliases
 
         $this->startElement('constraints');
-            if ($directive->version) $this->writeElement('version', $directive->version);
-            $this->startElement('type');
-                if ($directive->typeAllowsNull) $this->writeAttribute('allow-null', 'yes');
-                $this->text($directive->type);
-            $this->endElement(); // type
-            if ($directive->allowed) {
-                $this->startElement('allowed');
-                    foreach ($directive->allowed as $value => $x) $this->writeElement('value', $value);
-                $this->endElement(); // allowed
+        if ($directive->version) {
+            $this->writeElement('version', $directive->version);
+        }
+        $this->startElement('type');
+        if ($directive->typeAllowsNull) {
+            $this->writeAttribute('allow-null', 'yes');
+        }
+        $this->text($directive->type);
+        $this->endElement(); // type
+        if ($directive->allowed) {
+            $this->startElement('allowed');
+            foreach ($directive->allowed as $value => $x) {
+                $this->writeElement('value', $value);
             }
-            $this->writeElement('default', $this->export($directive->default));
-            $this->writeAttribute('xml:space', 'preserve');
-            if ($directive->external) {
-                $this->startElement('external');
-                    foreach ($directive->external as $project) $this->writeElement('project', $project);
-                $this->endElement();
+            $this->endElement(); // allowed
+        }
+        $this->writeElement('default', $this->export($directive->default));
+        $this->writeAttribute('xml:space', 'preserve');
+        if ($directive->external) {
+            $this->startElement('external');
+            foreach ($directive->external as $project) {
+                $this->writeElement('project', $project);
             }
+            $this->endElement();
+        }
         $this->endElement(); // constraints
 
         if ($directive->deprecatedVersion) {
             $this->startElement('deprecated');
-                $this->writeElement('version', $directive->deprecatedVersion);
-                $this->writeElement('use', $directive->deprecatedUse->toString());
+            $this->writeElement('version', $directive->deprecatedVersion);
+            $this->writeElement('use', $directive->deprecatedUse->toString());
             $this->endElement(); // deprecated
         }
 
         $this->startElement('description');
-            $this->writeHTMLDiv($directive->description);
+        $this->writeHTMLDiv($directive->description);
         $this->endElement(); // description
 
         $this->endElement(); // directive
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/Exception.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Exception.php
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/Exception.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Exception.php
diff --git a/library/HTMLPurifier/ConfigSchema/Interchange.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange.php
similarity index 76%
rename from library/HTMLPurifier/ConfigSchema/Interchange.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange.php
index 91a5aa7303..0e08ae8fe7 100644
--- a/library/HTMLPurifier/ConfigSchema/Interchange.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange.php
@@ -10,18 +10,23 @@ class HTMLPurifier_ConfigSchema_Interchange
 
     /**
      * Name of the application this schema is describing.
+     * @type string
      */
     public $name;
 
     /**
      * Array of Directive ID => array(directive info)
+     * @type HTMLPurifier_ConfigSchema_Interchange_Directive[]
      */
     public $directives = array();
 
     /**
      * Adds a directive array to $directives
+     * @param HTMLPurifier_ConfigSchema_Interchange_Directive $directive
+     * @throws HTMLPurifier_ConfigSchema_Exception
      */
-    public function addDirective($directive) {
+    public function addDirective($directive)
+    {
         if (isset($this->directives[$i = $directive->id->toString()])) {
             throw new HTMLPurifier_ConfigSchema_Exception("Cannot redefine directive '$i'");
         }
@@ -32,11 +37,11 @@ class HTMLPurifier_ConfigSchema_Interchange
      * Convenience function to perform standard validation. Throws exception
      * on failed validation.
      */
-    public function validate() {
+    public function validate()
+    {
         $validator = new HTMLPurifier_ConfigSchema_Validator();
         return $validator->validate($this);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php
similarity index 65%
rename from library/HTMLPurifier/ConfigSchema/Interchange/Directive.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php
index ac8be0d970..127a39a673 100644
--- a/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Directive.php
@@ -7,71 +7,83 @@ class HTMLPurifier_ConfigSchema_Interchange_Directive
 {
 
     /**
-     * ID of directive, instance of HTMLPurifier_ConfigSchema_Interchange_Id.
+     * ID of directive.
+     * @type HTMLPurifier_ConfigSchema_Interchange_Id
      */
     public $id;
 
     /**
-     * String type, e.g. 'integer' or 'istring'.
+     * Type, e.g. 'integer' or 'istring'.
+     * @type string
      */
     public $type;
 
     /**
      * Default value, e.g. 3 or 'DefaultVal'.
+     * @type mixed
      */
     public $default;
 
     /**
      * HTML description.
+     * @type string
      */
     public $description;
 
     /**
-     * Boolean whether or not null is allowed as a value.
+     * Whether or not null is allowed as a value.
+     * @type bool
      */
     public $typeAllowsNull = false;
 
     /**
-     * Lookup table of allowed scalar values, e.g. array('allowed' => true).
+     * Lookup table of allowed scalar values.
+     * e.g. array('allowed' => true).
      * Null if all values are allowed.
+     * @type array
      */
     public $allowed;
 
     /**
-     * List of aliases for the directive,
+     * List of aliases for the directive.
      * e.g. array(new HTMLPurifier_ConfigSchema_Interchange_Id('Ns', 'Dir'))).
+     * @type HTMLPurifier_ConfigSchema_Interchange_Id[]
      */
     public $aliases = array();
 
     /**
      * Hash of value aliases, e.g. array('alt' => 'real'). Null if value
      * aliasing is disabled (necessary for non-scalar types).
+     * @type array
      */
     public $valueAliases;
 
     /**
      * Version of HTML Purifier the directive was introduced, e.g. '1.3.1'.
      * Null if the directive has always existed.
+     * @type string
      */
     public $version;
 
     /**
-     * ID of directive that supercedes this old directive, is an instance
-     * of HTMLPurifier_ConfigSchema_Interchange_Id. Null if not deprecated.
+     * ID of directive that supercedes this old directive.
+     * Null if not deprecated.
+     * @type HTMLPurifier_ConfigSchema_Interchange_Id
      */
     public $deprecatedUse;
 
     /**
      * Version of HTML Purifier this directive was deprecated. Null if not
      * deprecated.
+     * @type string
      */
     public $deprecatedVersion;
 
     /**
      * List of external projects this directive depends on, e.g. array('CSSTidy').
+     * @type array
      */
     public $external = array();
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/Interchange/Id.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Id.php
similarity index 54%
rename from library/HTMLPurifier/ConfigSchema/Interchange/Id.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Id.php
index b9b3c6f5cf..126f09d957 100644
--- a/library/HTMLPurifier/ConfigSchema/Interchange/Id.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Interchange/Id.php
@@ -6,32 +6,53 @@
 class HTMLPurifier_ConfigSchema_Interchange_Id
 {
 
+    /**
+     * @type string
+     */
     public $key;
 
-    public function __construct($key) {
+    /**
+     * @param string $key
+     */
+    public function __construct($key)
+    {
         $this->key = $key;
     }
 
     /**
+     * @return string
      * @warning This is NOT magic, to ensure that people don't abuse SPL and
      *          cause problems for PHP 5.0 support.
      */
-    public function toString() {
+    public function toString()
+    {
         return $this->key;
     }
 
-    public function getRootNamespace() {
+    /**
+     * @return string
+     */
+    public function getRootNamespace()
+    {
         return substr($this->key, 0, strpos($this->key, "."));
     }
 
-    public function getDirective() {
+    /**
+     * @return string
+     */
+    public function getDirective()
+    {
         return substr($this->key, strpos($this->key, ".") + 1);
     }
 
-    public static function make($id) {
+    /**
+     * @param string $id
+     * @return HTMLPurifier_ConfigSchema_Interchange_Id
+     */
+    public static function make($id)
+    {
         return new HTMLPurifier_ConfigSchema_Interchange_Id($id);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php
similarity index 67%
rename from library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php
index 785b72ce8e..655e6dd1b9 100644
--- a/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/InterchangeBuilder.php
@@ -5,21 +5,39 @@ class HTMLPurifier_ConfigSchema_InterchangeBuilder
 
     /**
      * Used for processing DEFAULT, nothing else.
+     * @type HTMLPurifier_VarParser
      */
     protected $varParser;
 
-    public function __construct($varParser = null) {
+    /**
+     * @param HTMLPurifier_VarParser $varParser
+     */
+    public function __construct($varParser = null)
+    {
         $this->varParser = $varParser ? $varParser : new HTMLPurifier_VarParser_Native();
     }
 
-    public static function buildFromDirectory($dir = null) {
-        $builder     = new HTMLPurifier_ConfigSchema_InterchangeBuilder();
+    /**
+     * @param string $dir
+     * @return HTMLPurifier_ConfigSchema_Interchange
+     */
+    public static function buildFromDirectory($dir = null)
+    {
+        $builder = new HTMLPurifier_ConfigSchema_InterchangeBuilder();
         $interchange = new HTMLPurifier_ConfigSchema_Interchange();
         return $builder->buildDir($interchange, $dir);
     }
 
-    public function buildDir($interchange, $dir = null) {
-        if (!$dir) $dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema';
+    /**
+     * @param HTMLPurifier_ConfigSchema_Interchange $interchange
+     * @param string $dir
+     * @return HTMLPurifier_ConfigSchema_Interchange
+     */
+    public function buildDir($interchange, $dir = null)
+    {
+        if (!$dir) {
+            $dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier/ConfigSchema/schema';
+        }
         if (file_exists($dir . '/info.ini')) {
             $info = parse_ini_file($dir . '/info.ini');
             $interchange->name = $info['name'];
@@ -39,24 +57,30 @@ class HTMLPurifier_ConfigSchema_InterchangeBuilder
         foreach ($files as $file) {
             $this->buildFile($interchange, $dir . '/' . $file);
         }
-
         return $interchange;
     }
 
-    public function buildFile($interchange, $file) {
+    /**
+     * @param HTMLPurifier_ConfigSchema_Interchange $interchange
+     * @param string $file
+     */
+    public function buildFile($interchange, $file)
+    {
         $parser = new HTMLPurifier_StringHashParser();
         $this->build(
             $interchange,
-            new HTMLPurifier_StringHash( $parser->parseFile($file) )
+            new HTMLPurifier_StringHash($parser->parseFile($file))
         );
     }
 
     /**
      * Builds an interchange object based on a hash.
-     * @param $interchange HTMLPurifier_ConfigSchema_Interchange object to build
-     * @param $hash HTMLPurifier_ConfigSchema_StringHash source data
+     * @param HTMLPurifier_ConfigSchema_Interchange $interchange HTMLPurifier_ConfigSchema_Interchange object to build
+     * @param HTMLPurifier_StringHash $hash source data
+     * @throws HTMLPurifier_ConfigSchema_Exception
      */
-    public function build($interchange, $hash) {
+    public function build($interchange, $hash)
+    {
         if (!$hash instanceof HTMLPurifier_StringHash) {
             $hash = new HTMLPurifier_StringHash($hash);
         }
@@ -75,7 +99,13 @@ class HTMLPurifier_ConfigSchema_InterchangeBuilder
         $this->_findUnused($hash);
     }
 
-    public function buildDirective($interchange, $hash) {
+    /**
+     * @param HTMLPurifier_ConfigSchema_Interchange $interchange
+     * @param HTMLPurifier_StringHash $hash
+     * @throws HTMLPurifier_ConfigSchema_Exception
+     */
+    public function buildDirective($interchange, $hash)
+    {
         $directive = new HTMLPurifier_ConfigSchema_Interchange_Directive();
 
         // These are required elements:
@@ -84,7 +114,9 @@ class HTMLPurifier_ConfigSchema_InterchangeBuilder
 
         if (isset($hash['TYPE'])) {
             $type = explode('/', $hash->offsetGet('TYPE'));
-            if (isset($type[1])) $directive->typeAllowsNull = true;
+            if (isset($type[1])) {
+                $directive->typeAllowsNull = true;
+            }
             $directive->type = $type[0];
         } else {
             throw new HTMLPurifier_ConfigSchema_Exception("TYPE in directive hash '$id' not defined");
@@ -92,7 +124,11 @@ class HTMLPurifier_ConfigSchema_InterchangeBuilder
 
         if (isset($hash['DEFAULT'])) {
             try {
-                $directive->default = $this->varParser->parse($hash->offsetGet('DEFAULT'), $directive->type, $directive->typeAllowsNull);
+                $directive->default = $this->varParser->parse(
+                    $hash->offsetGet('DEFAULT'),
+                    $directive->type,
+                    $directive->typeAllowsNull
+                );
             } catch (HTMLPurifier_VarParserException $e) {
                 throw new HTMLPurifier_ConfigSchema_Exception($e->getMessage() . " in DEFAULT in directive hash '$id'");
             }
@@ -139,34 +175,45 @@ class HTMLPurifier_ConfigSchema_InterchangeBuilder
 
     /**
      * Evaluates an array PHP code string without array() wrapper
+     * @param string $contents
      */
-    protected function evalArray($contents) {
-        return eval('return array('. $contents .');');
+    protected function evalArray($contents)
+    {
+        return eval('return array(' . $contents . ');');
     }
 
     /**
      * Converts an array list into a lookup array.
+     * @param array $array
+     * @return array
      */
-    protected function lookup($array) {
+    protected function lookup($array)
+    {
         $ret = array();
-        foreach ($array as $val) $ret[$val] = true;
+        foreach ($array as $val) {
+            $ret[$val] = true;
+        }
         return $ret;
     }
 
     /**
      * Convenience function that creates an HTMLPurifier_ConfigSchema_Interchange_Id
      * object based on a string Id.
+     * @param string $id
+     * @return HTMLPurifier_ConfigSchema_Interchange_Id
      */
-    protected function id($id) {
+    protected function id($id)
+    {
         return HTMLPurifier_ConfigSchema_Interchange_Id::make($id);
     }
 
     /**
      * Triggers errors for any unused keys passed in the hash; such keys
      * may indicate typos, missing values, etc.
-     * @param $hash Instance of ConfigSchema_StringHash to check.
+     * @param HTMLPurifier_StringHash $hash Hash to check.
      */
-    protected function _findUnused($hash) {
+    protected function _findUnused($hash)
+    {
         $accessed = $hash->getAccessed();
         foreach ($hash as $k => $v) {
             if (!isset($accessed[$k])) {
@@ -174,7 +221,6 @@ class HTMLPurifier_ConfigSchema_InterchangeBuilder
             }
         }
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/Validator.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Validator.php
similarity index 73%
rename from library/HTMLPurifier/ConfigSchema/Validator.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Validator.php
index f374f6a022..fb31277889 100644
--- a/library/HTMLPurifier/ConfigSchema/Validator.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/Validator.php
@@ -12,36 +12,48 @@ class HTMLPurifier_ConfigSchema_Validator
 {
 
     /**
-     * Easy to access global objects.
+     * @type HTMLPurifier_ConfigSchema_Interchange
      */
-    protected $interchange, $aliases;
+    protected $interchange;
+
+    /**
+     * @type array
+     */
+    protected $aliases;
 
     /**
      * Context-stack to provide easy to read error messages.
+     * @type array
      */
     protected $context = array();
 
     /**
-     * HTMLPurifier_VarParser to test default's type.
+     * to test default's type.
+     * @type HTMLPurifier_VarParser
      */
     protected $parser;
 
-    public function __construct() {
+    public function __construct()
+    {
         $this->parser = new HTMLPurifier_VarParser();
     }
 
     /**
-     * Validates a fully-formed interchange object. Throws an
-     * HTMLPurifier_ConfigSchema_Exception if there's a problem.
+     * Validates a fully-formed interchange object.
+     * @param HTMLPurifier_ConfigSchema_Interchange $interchange
+     * @return bool
      */
-    public function validate($interchange) {
+    public function validate($interchange)
+    {
         $this->interchange = $interchange;
         $this->aliases = array();
         // PHP is a bit lax with integer <=> string conversions in
         // arrays, so we don't use the identical !== comparison
         foreach ($interchange->directives as $i => $directive) {
             $id = $directive->id->toString();
-            if ($i != $id) $this->error(false, "Integrity violation: key '$i' does not match internal id '$id'");
+            if ($i != $id) {
+                $this->error(false, "Integrity violation: key '$i' does not match internal id '$id'");
+            }
             $this->validateDirective($directive);
         }
         return true;
@@ -49,8 +61,10 @@ class HTMLPurifier_ConfigSchema_Validator
 
     /**
      * Validates a HTMLPurifier_ConfigSchema_Interchange_Id object.
+     * @param HTMLPurifier_ConfigSchema_Interchange_Id $id
      */
-    public function validateId($id) {
+    public function validateId($id)
+    {
         $id_string = $id->toString();
         $this->context[] = "id '$id_string'";
         if (!$id instanceof HTMLPurifier_ConfigSchema_Interchange_Id) {
@@ -67,8 +81,10 @@ class HTMLPurifier_ConfigSchema_Validator
 
     /**
      * Validates a HTMLPurifier_ConfigSchema_Interchange_Directive object.
+     * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
      */
-    public function validateDirective($d) {
+    public function validateDirective($d)
+    {
         $id = $d->id->toString();
         $this->context[] = "directive '$id'";
         $this->validateId($d->id);
@@ -108,9 +124,13 @@ class HTMLPurifier_ConfigSchema_Validator
     /**
      * Extra validation if $allowed member variable of
      * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
+     * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
      */
-    public function validateDirectiveAllowed($d) {
-        if (is_null($d->allowed)) return;
+    public function validateDirectiveAllowed($d)
+    {
+        if (is_null($d->allowed)) {
+            return;
+        }
         $this->with($d, 'allowed')
             ->assertNotEmpty()
             ->assertIsLookup(); // handled by InterchangeBuilder
@@ -119,7 +139,9 @@ class HTMLPurifier_ConfigSchema_Validator
         }
         $this->context[] = 'allowed';
         foreach ($d->allowed as $val => $x) {
-            if (!is_string($val)) $this->error("value $val", 'must be a string');
+            if (!is_string($val)) {
+                $this->error("value $val", 'must be a string');
+            }
         }
         array_pop($this->context);
     }
@@ -127,15 +149,23 @@ class HTMLPurifier_ConfigSchema_Validator
     /**
      * Extra validation if $valueAliases member variable of
      * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
+     * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
      */
-    public function validateDirectiveValueAliases($d) {
-        if (is_null($d->valueAliases)) return;
+    public function validateDirectiveValueAliases($d)
+    {
+        if (is_null($d->valueAliases)) {
+            return;
+        }
         $this->with($d, 'valueAliases')
             ->assertIsArray(); // handled by InterchangeBuilder
         $this->context[] = 'valueAliases';
         foreach ($d->valueAliases as $alias => $real) {
-            if (!is_string($alias)) $this->error("alias $alias", 'must be a string');
-            if (!is_string($real))  $this->error("alias target $real from alias '$alias'",  'must be a string');
+            if (!is_string($alias)) {
+                $this->error("alias $alias", 'must be a string');
+            }
+            if (!is_string($real)) {
+                $this->error("alias target $real from alias '$alias'", 'must be a string');
+            }
             if ($alias === $real) {
                 $this->error("alias '$alias'", "must not be an alias to itself");
             }
@@ -155,8 +185,10 @@ class HTMLPurifier_ConfigSchema_Validator
     /**
      * Extra validation if $aliases member variable of
      * HTMLPurifier_ConfigSchema_Interchange_Directive is defined.
+     * @param HTMLPurifier_ConfigSchema_Interchange_Directive $d
      */
-    public function validateDirectiveAliases($d) {
+    public function validateDirectiveAliases($d)
+    {
         $this->with($d, 'aliases')
             ->assertIsArray(); // handled by InterchangeBuilder
         $this->context[] = 'aliases';
@@ -180,27 +212,37 @@ class HTMLPurifier_ConfigSchema_Validator
     /**
      * Convenience function for generating HTMLPurifier_ConfigSchema_ValidatorAtom
      * for validating simple member variables of objects.
+     * @param $obj
+     * @param $member
+     * @return HTMLPurifier_ConfigSchema_ValidatorAtom
      */
-    protected function with($obj, $member) {
+    protected function with($obj, $member)
+    {
         return new HTMLPurifier_ConfigSchema_ValidatorAtom($this->getFormattedContext(), $obj, $member);
     }
 
     /**
      * Emits an error, providing helpful context.
+     * @throws HTMLPurifier_ConfigSchema_Exception
      */
-    protected function error($target, $msg) {
-        if ($target !== false) $prefix = ucfirst($target) . ' in ' .  $this->getFormattedContext();
-        else $prefix = ucfirst($this->getFormattedContext());
+    protected function error($target, $msg)
+    {
+        if ($target !== false) {
+            $prefix = ucfirst($target) . ' in ' . $this->getFormattedContext();
+        } else {
+            $prefix = ucfirst($this->getFormattedContext());
+        }
         throw new HTMLPurifier_ConfigSchema_Exception(trim($prefix . ' ' . $msg));
     }
 
     /**
      * Returns a formatted context string.
+     * @return string
      */
-    protected function getFormattedContext() {
+    protected function getFormattedContext()
+    {
         return implode(' in ', array_reverse($this->context));
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php
new file mode 100644
index 0000000000..c9aa3644af
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/ValidatorAtom.php
@@ -0,0 +1,130 @@
+<?php
+
+/**
+ * Fluent interface for validating the contents of member variables.
+ * This should be immutable. See HTMLPurifier_ConfigSchema_Validator for
+ * use-cases. We name this an 'atom' because it's ONLY for validations that
+ * are independent and usually scalar.
+ */
+class HTMLPurifier_ConfigSchema_ValidatorAtom
+{
+    /**
+     * @type string
+     */
+    protected $context;
+
+    /**
+     * @type object
+     */
+    protected $obj;
+
+    /**
+     * @type string
+     */
+    protected $member;
+
+    /**
+     * @type mixed
+     */
+    protected $contents;
+
+    public function __construct($context, $obj, $member)
+    {
+        $this->context = $context;
+        $this->obj = $obj;
+        $this->member = $member;
+        $this->contents =& $obj->$member;
+    }
+
+    /**
+     * @return HTMLPurifier_ConfigSchema_ValidatorAtom
+     */
+    public function assertIsString()
+    {
+        if (!is_string($this->contents)) {
+            $this->error('must be a string');
+        }
+        return $this;
+    }
+
+    /**
+     * @return HTMLPurifier_ConfigSchema_ValidatorAtom
+     */
+    public function assertIsBool()
+    {
+        if (!is_bool($this->contents)) {
+            $this->error('must be a boolean');
+        }
+        return $this;
+    }
+
+    /**
+     * @return HTMLPurifier_ConfigSchema_ValidatorAtom
+     */
+    public function assertIsArray()
+    {
+        if (!is_array($this->contents)) {
+            $this->error('must be an array');
+        }
+        return $this;
+    }
+
+    /**
+     * @return HTMLPurifier_ConfigSchema_ValidatorAtom
+     */
+    public function assertNotNull()
+    {
+        if ($this->contents === null) {
+            $this->error('must not be null');
+        }
+        return $this;
+    }
+
+    /**
+     * @return HTMLPurifier_ConfigSchema_ValidatorAtom
+     */
+    public function assertAlnum()
+    {
+        $this->assertIsString();
+        if (!ctype_alnum($this->contents)) {
+            $this->error('must be alphanumeric');
+        }
+        return $this;
+    }
+
+    /**
+     * @return HTMLPurifier_ConfigSchema_ValidatorAtom
+     */
+    public function assertNotEmpty()
+    {
+        if (empty($this->contents)) {
+            $this->error('must not be empty');
+        }
+        return $this;
+    }
+
+    /**
+     * @return HTMLPurifier_ConfigSchema_ValidatorAtom
+     */
+    public function assertIsLookup()
+    {
+        $this->assertIsArray();
+        foreach ($this->contents as $v) {
+            if ($v !== true) {
+                $this->error('must be a lookup array');
+            }
+        }
+        return $this;
+    }
+
+    /**
+     * @param string $msg
+     * @throws HTMLPurifier_ConfigSchema_Exception
+     */
+    protected function error($msg)
+    {
+        throw new HTMLPurifier_ConfigSchema_Exception(ucfirst($this->member) . ' in ' . $this->context . ' ' . $msg);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema.ser
new file mode 100644
index 0000000000000000000000000000000000000000..1e6ccd22755dfa27722e17f457a00ea42bdc1d6f
GIT binary patch
literal 15305
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

literal 0
HcmV?d00001

diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedClasses.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedFrameTargets.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRel.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.AllowedRev.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ClassUseCDATA.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultImageAlt.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImage.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultInvalidImageAlt.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.DefaultTextDir.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.EnableID.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.ForbiddenClasses.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklist.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDBlacklistRegexp.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefix.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Attr.IDPrefixLocal.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.AutoParagraph.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Custom.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.DisplayLinkURI.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.Linkify.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.DocURL.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.PurifierLinkify.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.Predicate.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.Predicate.txt
new file mode 100644
index 0000000000..6367fe23c9
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.Predicate.txt
@@ -0,0 +1,14 @@
+AutoFormat.RemoveEmpty.Predicate
+TYPE: hash
+VERSION: 4.7.0
+DEFAULT: array('colgroup' => array(), 'th' => array(), 'td' => array(), 'iframe' => array('src'))
+--DESCRIPTION--
+<p>
+  Given that an element has no contents, it will be removed by default, unless
+  this predicate dictates otherwise.  The predicate can either be an associative
+  map from tag name to list of attributes that must be present for the element
+  to be considered preserved: thus, the default always preserves <code>colgroup</code>,
+  <code>th</code> and <code>td</code>, and also <code>iframe</code> if it
+  has a <code>src</code>.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.RemoveNbsp.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveEmpty.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/AutoFormat.RemoveSpansWithoutAttributes.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowImportant.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowTricky.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt
new file mode 100644
index 0000000000..3fd4654065
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedFonts.txt
@@ -0,0 +1,12 @@
+CSS.AllowedFonts
+TYPE: lookup/null
+VERSION: 4.3.0
+DEFAULT: NULL
+--DESCRIPTION--
+<p>
+    Allows you to manually specify a set of allowed fonts.  If
+    <code>NULL</code>, all fonts are allowed.  This directive
+    affects generic names (serif, sans-serif, monospace, cursive,
+    fantasy) as well as specific font families.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.AllowedProperties.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.DefinitionRev.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt
new file mode 100644
index 0000000000..f1f5c5f12b
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.ForbiddenProperties.txt
@@ -0,0 +1,13 @@
+CSS.ForbiddenProperties
+TYPE: lookup
+VERSION: 4.2.0
+DEFAULT: array()
+--DESCRIPTION--
+<p>
+    This is the logical inverse of %CSS.AllowedProperties, and it will
+    override that directive or any other directive.  If possible,
+    %CSS.AllowedProperties is recommended over this directive,
+    because it can sometimes be difficult to tell whether or not you've
+    forbidden all of the CSS properties you truly would like to disallow.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.MaxImgLength.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Proprietary.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt
new file mode 100644
index 0000000000..e733a61e8a
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/CSS.Trusted.txt
@@ -0,0 +1,9 @@
+CSS.Trusted
+TYPE: bool
+VERSION: 4.2.1
+DEFAULT: false
+--DESCRIPTION--
+Indicates whether or not the user's CSS input is trusted or not. If the
+input is trusted, a more expansive set of allowed properties.  See
+also %HTML.Trusted.
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.DefinitionImpl.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPath.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt
new file mode 100644
index 0000000000..b2b83d9ab6
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Cache.SerializerPermissions.txt
@@ -0,0 +1,11 @@
+Cache.SerializerPermissions
+TYPE: int
+VERSION: 4.3.0
+DEFAULT: 0755
+--DESCRIPTION--
+
+<p>
+    Directory permissions of the files and directories created inside
+    the DefinitionCache/Serializer or other custom serializer path.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AggressivelyFixLt.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt
new file mode 100644
index 0000000000..2c910cc7de
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.AllowHostnameUnderscore.txt
@@ -0,0 +1,16 @@
+Core.AllowHostnameUnderscore
+TYPE: bool
+VERSION: 4.6.0
+DEFAULT: false
+--DESCRIPTION--
+<p>
+    By RFC 1123, underscores are not permitted in host names.
+    (This is in contrast to the specification for DNS, RFC
+    2181, which allows underscores.)
+    However, most browsers do the right thing when faced with
+    an underscore in the host name, and so some poorly written
+    websites are written with the expectation this should work.
+    Setting this parameter to true relaxes our allowed character
+    check so that underscores are permitted.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.CollectErrors.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt
similarity index 84%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt
index 08b381d34c..c572c14ec1 100644
--- a/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ColorKeywords.txt
@@ -24,5 +24,6 @@ array (
 --DESCRIPTION--
 
 Lookup array of color names to six digit hexadecimal number corresponding
-to color, with preceding hash mark. Used when parsing colors.
+to color, with preceding hash mark. Used when parsing colors.  The lookup
+is done in a case-insensitive manner.
 --# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.ConvertDocumentToFragment.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DirectLexLineNumberSyncInterval.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt
new file mode 100644
index 0000000000..1cd4c2c964
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.DisableExcludes.txt
@@ -0,0 +1,14 @@
+Core.DisableExcludes
+TYPE: bool
+DEFAULT: false
+VERSION: 4.5.0
+--DESCRIPTION--
+<p>
+  This directive disables SGML-style exclusions, e.g. the exclusion of
+  <code>&lt;object&gt;</code> in any descendant of a
+  <code>&lt;pre&gt;</code> tag.  Disabling excludes will allow some
+  invalid documents to pass through HTML Purifier, but HTML Purifier
+  will also be less likely to accidentally remove large documents during
+  processing.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt
new file mode 100644
index 0000000000..ce243c35dc
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EnableIDNA.txt
@@ -0,0 +1,9 @@
+Core.EnableIDNA
+TYPE: bool
+DEFAULT: false
+VERSION: 4.4.0
+--DESCRIPTION--
+Allows international domain names in URLs.  This configuration option
+requires the PEAR Net_IDNA2 module to be installed.  It operates by
+punycoding any internationalized host names for maximum portability.
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Encoding.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt
similarity index 62%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt
index 4d5b5055cd..a3881be75c 100644
--- a/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidChildren.txt
@@ -2,9 +2,11 @@ Core.EscapeInvalidChildren
 TYPE: bool
 DEFAULT: false
 --DESCRIPTION--
-When true, a child is found that is not allowed in the context of the
+<p><strong>Warning:</strong> this configuration option is no longer does anything as of 4.6.0.</p>
+
+<p>When true, a child is found that is not allowed in the context of the
 parent element will be transformed into text as if it were ASCII. When
 false, that element and all internal tags will be dropped, though text will
 be preserved.  There is no option for dropping the element but preserving
-child nodes.
+child nodes.</p>
 --# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeInvalidTags.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.EscapeNonASCIICharacters.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.HiddenElements.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.Language.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.LexerImpl.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.MaintainLineNumbers.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt
new file mode 100644
index 0000000000..d77f5360d7
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.NormalizeNewlines.txt
@@ -0,0 +1,11 @@
+Core.NormalizeNewlines
+TYPE: bool
+VERSION: 4.2.0
+DEFAULT: true
+--DESCRIPTION--
+<p>
+    Whether or not to normalize newlines to the operating
+    system default.  When <code>false</code>, HTML Purifier
+    will attempt to preserve mixed newline files.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveInvalidImg.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt
new file mode 100644
index 0000000000..3397d9f71f
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveProcessingInstructions.txt
@@ -0,0 +1,11 @@
+Core.RemoveProcessingInstructions
+TYPE: bool
+VERSION: 4.2.0
+DEFAULT: false
+--DESCRIPTION--
+Instead of escaping processing instructions in the form <code>&lt;? ...
+?&gt;</code>, remove it out-right.  This may be useful if the HTML
+you are validating contains XML processing instruction gunk, however,
+it can also be user-unfriendly for people attempting to post PHP
+snippets.
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Core.RemoveScriptContents.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.Custom.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Escaping.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.Scope.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.TidyImpl.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.ExtractStyleBlocks.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt
similarity index 65%
rename from library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt
index 7fa6536b2c..321eaa2d80 100644
--- a/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Filter.YouTube.txt
@@ -3,6 +3,11 @@ TYPE: bool
 VERSION: 3.1.0
 DEFAULT: false
 --DESCRIPTION--
+<p>
+  <strong>Warning:</strong> Deprecated in favor of %HTML.SafeObject and
+  %Output.FlashCompat (turn both on to allow YouTube videos and other
+  Flash content).
+</p>
 <p>
   This directive enables YouTube video embedding in HTML Purifier. Check
   <a href="http://htmlpurifier.org/docs/enduser-youtube.html">this document
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt
similarity index 54%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt
index 3e231d2d16..0b2c106da5 100644
--- a/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Allowed.txt
@@ -5,11 +5,14 @@ DEFAULT: NULL
 --DESCRIPTION--
 
 <p>
-    This is a convenience directive that rolls the functionality of
-    %HTML.AllowedElements and %HTML.AllowedAttributes into one directive.
+    This is a preferred convenience directive that combines
+    %HTML.AllowedElements and %HTML.AllowedAttributes.
     Specify elements and attributes that are allowed using:
-    <code>element1[attr1|attr2],element2...</code>. You can also use
-    newlines instead of commas to separate elements.
+    <code>element1[attr1|attr2],element2...</code>.  For example,
+    if you would like to only allow paragraphs and links, specify
+    <code>a[href],p</code>.  You can specify attributes that apply
+    to all elements using an asterisk, e.g. <code>*[lang]</code>.
+    You can also use newlines instead of commas to separate elements.
 </p>
 <p>
     <strong>Warning</strong>:
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedAttributes.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt
new file mode 100644
index 0000000000..140e21423e
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedComments.txt
@@ -0,0 +1,10 @@
+HTML.AllowedComments
+TYPE: lookup
+VERSION: 4.4.0
+DEFAULT: array()
+--DESCRIPTION--
+A whitelist which indicates what explicit comment bodies should be
+allowed, modulo leading and trailing whitespace.  See also %HTML.AllowedCommentsRegexp
+(these directives are union'ed together, so a comment is considered
+valid if any directive deems it valid.)
+--# vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt
new file mode 100644
index 0000000000..f22e977d43
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedCommentsRegexp.txt
@@ -0,0 +1,15 @@
+HTML.AllowedCommentsRegexp
+TYPE: string/null
+VERSION: 4.4.0
+DEFAULT: NULL
+--DESCRIPTION--
+A regexp, which if it matches the body of a comment, indicates that
+it should be allowed. Trailing and leading spaces are removed prior
+to running this regular expression.
+<strong>Warning:</strong> Make sure you specify
+correct anchor metacharacters <code>^regex$</code>, otherwise you may accept
+comments that you did not mean to! In particular, the regex <code>/foo|bar/</code>
+is probably not sufficiently strict, since it also allows <code>foobar</code>.
+See also %HTML.AllowedComments (these directives are union'ed together,
+so a comment is considered valid if any directive deems it valid.)
+--# vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt
new file mode 100644
index 0000000000..1d3fa7907d
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedElements.txt
@@ -0,0 +1,23 @@
+HTML.AllowedElements
+TYPE: lookup/null
+VERSION: 1.3.0
+DEFAULT: NULL
+--DESCRIPTION--
+<p>
+    If HTML Purifier's tag set is unsatisfactory for your needs, you can
+    overload it with your own list of tags to allow.  If you change
+    this, you probably also want to change %HTML.AllowedAttributes; see
+    also %HTML.Allowed which lets you set allowed elements and
+    attributes at the same time.
+</p>
+<p>
+    If you attempt to allow an element that HTML Purifier does not know
+    about, HTML Purifier will raise an error.  You will need to manually
+    tell HTML Purifier about this element by using the
+    <a href="http://htmlpurifier.org/docs/enduser-customize.html">advanced customization features.</a>
+</p>
+<p>
+    <strong>Warning:</strong> If another directive conflicts with the
+    elements here, <em>that</em> directive will win and override.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.AllowedModules.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Attr.Name.UseCDATA.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.BlockWrapper.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CoreModules.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt
similarity index 72%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt
index a64e3d7c36..6ed70b599f 100644
--- a/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.CustomDoctype.txt
@@ -4,6 +4,6 @@ VERSION: 2.0.1
 DEFAULT: NULL
 --DESCRIPTION--
 
-A custom doctype for power-users who defined there own document
+A custom doctype for power-users who defined their own document
 type. This directive only applies when %HTML.Doctype is blank.
 --# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionID.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.DefinitionRev.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Doctype.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt
new file mode 100644
index 0000000000..7878dc0bf6
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.FlashAllowFullScreen.txt
@@ -0,0 +1,11 @@
+HTML.FlashAllowFullScreen
+TYPE: bool
+VERSION: 4.2.0
+DEFAULT: false
+--DESCRIPTION--
+<p>
+    Whether or not to permit embedded Flash content from
+    %HTML.SafeObject to expand to the full screen.  Corresponds to
+    the <code>allowFullScreen</code> parameter.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenAttributes.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.ForbiddenElements.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.MaxImgLength.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt
new file mode 100644
index 0000000000..700b30924a
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Nofollow.txt
@@ -0,0 +1,7 @@
+HTML.Nofollow
+TYPE: bool
+VERSION: 4.3.0
+DEFAULT: FALSE
+--DESCRIPTION--
+If enabled, nofollow rel attributes are added to all outgoing links.
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Parent.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Proprietary.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeEmbed.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt
new file mode 100644
index 0000000000..5eb6ec2b5a
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeIframe.txt
@@ -0,0 +1,13 @@
+HTML.SafeIframe
+TYPE: bool
+VERSION: 4.4.0
+DEFAULT: false
+--DESCRIPTION--
+<p>
+    Whether or not to permit iframe tags in untrusted documents.  This
+    directive must be accompanied by a whitelist of permitted iframes,
+    such as %URI.SafeIframeRegexp, otherwise it will fatally error.
+    This directive has no effect on strict doctypes, as iframes are not
+    valid.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeObject.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt
new file mode 100644
index 0000000000..5ebc7a19d5
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.SafeScripting.txt
@@ -0,0 +1,10 @@
+HTML.SafeScripting
+TYPE: lookup
+VERSION: 4.5.0
+DEFAULT: array()
+--DESCRIPTION--
+<p>
+    Whether or not to permit script tags to external scripts in documents.
+    Inline scripting is not allowed, and the script must match an explicit whitelist.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Strict.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt
new file mode 100644
index 0000000000..587a16778b
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TargetBlank.txt
@@ -0,0 +1,8 @@
+HTML.TargetBlank
+TYPE: bool
+VERSION: 4.4.0
+DEFAULT: FALSE
+--DESCRIPTION--
+If enabled, <code>target=blank</code> attributes are added to all outgoing links.
+(This includes links from an HTTPS version of a page to an HTTP version.)
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyAdd.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyLevel.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.TidyRemove.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt
similarity index 91%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt
index 89133b1a38..1db9237e9e 100644
--- a/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.Trusted.txt
@@ -5,4 +5,5 @@ DEFAULT: false
 --DESCRIPTION--
 Indicates whether or not the user input is trusted or not. If the input is
 trusted, a more expansive set of allowed tags and attributes will be used.
+See also %CSS.Trusted.
 --# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/HTML.XHTML.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.CommentScriptContents.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt
new file mode 100644
index 0000000000..d6f0d9f295
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.FixInnerHTML.txt
@@ -0,0 +1,15 @@
+Output.FixInnerHTML
+TYPE: bool
+VERSION: 4.3.0
+DEFAULT: true
+--DESCRIPTION--
+<p>
+  If true, HTML Purifier will protect against Internet Explorer's
+  mishandling of the <code>innerHTML</code> attribute by appending
+  a space to any attribute that does not contain angled brackets, spaces
+  or quotes, but contains a backtick.  This slightly changes the
+  semantics of any given attribute, so if this is unacceptable and
+  you do not use <code>innerHTML</code> on any of your pages, you can
+  turn this directive off.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Output.FlashCompat.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.FlashCompat.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Output.FlashCompat.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.FlashCompat.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.Newline.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.SortAttr.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Output.TidyFormat.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/Test.ForceNoIconv.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt
similarity index 74%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt
index ae3a913f24..666635a5ff 100644
--- a/library/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.AllowedSchemes.txt
@@ -12,6 +12,6 @@ array (
 --DESCRIPTION--
 Whitelist that defines the schemes that a URI is allowed to have.  This
 prevents XSS attacks from using pseudo-schemes like javascript or mocha.
-There is also support for the <code>data</code> URI scheme, but it is not
-enabled by default.
+There is also support for the <code>data</code> and <code>file</code>
+URI schemes, but they are not enabled by default.
 --# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.Base.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Base.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.Base.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Base.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefaultScheme.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionID.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DefinitionRev.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Disable.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternal.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableExternalResources.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt
similarity index 64%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt
index 51e6ea91f7..f891de4996 100644
--- a/library/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.DisableResources.txt
@@ -1,12 +1,15 @@
 URI.DisableResources
 TYPE: bool
-VERSION: 1.3.0
+VERSION: 4.2.0
 DEFAULT: false
 --DESCRIPTION--
-
 <p>
     Disables embedding resources, essentially meaning no pictures. You can
     still link to them though. See %URI.DisableExternalResources for why
     this might be a good idea.
 </p>
+<p>
+    <em>Note:</em> While this directive has been available since 1.3.0,
+    it didn't actually start doing anything until 4.2.0.
+</p>
 --# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.Host.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Host.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.Host.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Host.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.HostBlacklist.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MakeAbsolute.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.Munge.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MungeResources.txt
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt
similarity index 93%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt
index 0d00f62ea8..1e17c1d461 100644
--- a/library/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.MungeSecretKey.txt
@@ -11,7 +11,7 @@ DEFAULT: NULL
     to check if a URI has passed through HTML Purifier with this line:
 </p>
 
-<pre>$checksum === sha1($secret_key . ':' . $url)</pre>
+<pre>$checksum === hash_hmac("sha256", $url, $secret_key)</pre>
 
 <p>
     If the output is TRUE, the redirector script should accept the URI.
diff --git a/library/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.OverrideAllowedSchemes.txt
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.SafeIframeRegexp.txt b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.SafeIframeRegexp.txt
new file mode 100644
index 0000000000..79084832be
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/URI.SafeIframeRegexp.txt
@@ -0,0 +1,22 @@
+URI.SafeIframeRegexp
+TYPE: string/null
+VERSION: 4.4.0
+DEFAULT: NULL
+--DESCRIPTION--
+<p>
+    A PCRE regular expression that will be matched against an iframe URI.  This is
+    a relatively inflexible scheme, but works well enough for the most common
+    use-case of iframes: embedded video.  This directive only has an effect if
+    %HTML.SafeIframe is enabled.  Here are some example values:
+</p>
+<ul>
+    <li><code>%^http://www.youtube.com/embed/%</code> - Allow YouTube videos</li>
+    <li><code>%^http://player.vimeo.com/video/%</code> - Allow Vimeo videos</li>
+    <li><code>%^http://(www.youtube.com/embed/|player.vimeo.com/video/)%</code> - Allow both</li>
+</ul>
+<p>
+    Note that this directive does not give you enough granularity to, say, disable
+    all <code>autoplay</code> videos.  Pipe up on the HTML Purifier forums if this
+    is a capability you want.
+</p>
+--# vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ConfigSchema/schema/info.ini b/library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/info.ini
similarity index 100%
rename from library/HTMLPurifier/ConfigSchema/schema/info.ini
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ConfigSchema/schema/info.ini
diff --git a/library/HTMLPurifier/ContentSets.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ContentSets.php
similarity index 76%
rename from library/HTMLPurifier/ContentSets.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ContentSets.php
index 3b6e96f5f5..543e3f8f11 100644
--- a/library/HTMLPurifier/ContentSets.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ContentSets.php
@@ -7,35 +7,42 @@ class HTMLPurifier_ContentSets
 {
 
     /**
-     * List of content set strings (pipe seperators) indexed by name.
+     * List of content set strings (pipe separators) indexed by name.
+     * @type array
      */
     public $info = array();
 
     /**
      * List of content set lookups (element => true) indexed by name.
+     * @type array
      * @note This is in HTMLPurifier_HTMLDefinition->info_content_sets
      */
     public $lookup = array();
 
     /**
-     * Synchronized list of defined content sets (keys of info)
+     * Synchronized list of defined content sets (keys of info).
+     * @type array
      */
     protected $keys = array();
     /**
-     * Synchronized list of defined content values (values of info)
+     * Synchronized list of defined content values (values of info).
+     * @type array
      */
     protected $values = array();
 
     /**
      * Merges in module's content sets, expands identifiers in the content
      * sets and populates the keys, values and lookup member variables.
-     * @param $modules List of HTMLPurifier_HTMLModule
+     * @param HTMLPurifier_HTMLModule[] $modules List of HTMLPurifier_HTMLModule
      */
-    public function __construct($modules) {
-        if (!is_array($modules)) $modules = array($modules);
+    public function __construct($modules)
+    {
+        if (!is_array($modules)) {
+            $modules = array($modules);
+        }
         // populate content_sets based on module hints
         // sorry, no way of overloading
-        foreach ($modules as $module_i => $module) {
+        foreach ($modules as $module) {
             foreach ($module->content_sets as $key => $value) {
                 $temp = $this->convertToLookup($value);
                 if (isset($this->lookup[$key])) {
@@ -70,11 +77,14 @@ class HTMLPurifier_ContentSets
 
     /**
      * Accepts a definition; generates and assigns a ChildDef for it
-     * @param $def HTMLPurifier_ElementDef reference
-     * @param $module Module that defined the ElementDef
+     * @param HTMLPurifier_ElementDef $def HTMLPurifier_ElementDef reference
+     * @param HTMLPurifier_HTMLModule $module Module that defined the ElementDef
      */
-    public function generateChildDef(&$def, $module) {
-        if (!empty($def->child)) return; // already done!
+    public function generateChildDef(&$def, $module)
+    {
+        if (!empty($def->child)) { // already done!
+            return;
+        }
         $content_model = $def->content_model;
         if (is_string($content_model)) {
             // Assume that $this->keys is alphanumeric
@@ -89,7 +99,8 @@ class HTMLPurifier_ContentSets
         $def->child = $this->getChildDef($def, $module);
     }
 
-    public function generateChildDefCallback($matches) {
+    public function generateChildDefCallback($matches)
+    {
         return $this->info[$matches[0]];
     }
 
@@ -98,10 +109,12 @@ class HTMLPurifier_ContentSets
      * member variables in HTMLPurifier_ElementDef
      * @note This will also defer to modules for custom HTMLPurifier_ChildDef
      *       subclasses that need content set expansion
-     * @param $def HTMLPurifier_ElementDef to have ChildDef extracted
+     * @param HTMLPurifier_ElementDef $def HTMLPurifier_ElementDef to have ChildDef extracted
+     * @param HTMLPurifier_HTMLModule $module Module that defined the ElementDef
      * @return HTMLPurifier_ChildDef corresponding to ElementDef
      */
-    public function getChildDef($def, $module) {
+    public function getChildDef($def, $module)
+    {
         $value = $def->content_model;
         if (is_object($value)) {
             trigger_error(
@@ -126,7 +139,9 @@ class HTMLPurifier_ContentSets
         if ($module->defines_child_def) { // save a func call
             $return = $module->getChildDef($def);
         }
-        if ($return !== false) return $return;
+        if ($return !== false) {
+            return $return;
+        }
         // error-out
         trigger_error(
             'Could not determine which ChildDef class to instantiate',
@@ -138,18 +153,18 @@ class HTMLPurifier_ContentSets
     /**
      * Converts a string list of elements separated by pipes into
      * a lookup array.
-     * @param $string List of elements
-     * @return Lookup array of elements
+     * @param string $string List of elements
+     * @return array Lookup array of elements
      */
-    protected function convertToLookup($string) {
+    protected function convertToLookup($string)
+    {
         $array = explode('|', str_replace(' ', '', $string));
         $ret = array();
-        foreach ($array as $i => $k) {
+        foreach ($array as $k) {
             $ret[$k] = true;
         }
         return $ret;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Context.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Context.php
new file mode 100644
index 0000000000..00e509c85c
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Context.php
@@ -0,0 +1,95 @@
+<?php
+
+/**
+ * Registry object that contains information about the current context.
+ * @warning Is a bit buggy when variables are set to null: it thinks
+ *          they don't exist! So use false instead, please.
+ * @note Since the variables Context deals with may not be objects,
+ *       references are very important here! Do not remove!
+ */
+class HTMLPurifier_Context
+{
+
+    /**
+     * Private array that stores the references.
+     * @type array
+     */
+    private $_storage = array();
+
+    /**
+     * Registers a variable into the context.
+     * @param string $name String name
+     * @param mixed $ref Reference to variable to be registered
+     */
+    public function register($name, &$ref)
+    {
+        if (array_key_exists($name, $this->_storage)) {
+            trigger_error(
+                "Name $name produces collision, cannot re-register",
+                E_USER_ERROR
+            );
+            return;
+        }
+        $this->_storage[$name] =& $ref;
+    }
+
+    /**
+     * Retrieves a variable reference from the context.
+     * @param string $name String name
+     * @param bool $ignore_error Boolean whether or not to ignore error
+     * @return mixed
+     */
+    public function &get($name, $ignore_error = false)
+    {
+        if (!array_key_exists($name, $this->_storage)) {
+            if (!$ignore_error) {
+                trigger_error(
+                    "Attempted to retrieve non-existent variable $name",
+                    E_USER_ERROR
+                );
+            }
+            $var = null; // so we can return by reference
+            return $var;
+        }
+        return $this->_storage[$name];
+    }
+
+    /**
+     * Destroys a variable in the context.
+     * @param string $name String name
+     */
+    public function destroy($name)
+    {
+        if (!array_key_exists($name, $this->_storage)) {
+            trigger_error(
+                "Attempted to destroy non-existent variable $name",
+                E_USER_ERROR
+            );
+            return;
+        }
+        unset($this->_storage[$name]);
+    }
+
+    /**
+     * Checks whether or not the variable exists.
+     * @param string $name String name
+     * @return bool
+     */
+    public function exists($name)
+    {
+        return array_key_exists($name, $this->_storage);
+    }
+
+    /**
+     * Loads a series of variables from an associative array
+     * @param array $context_array Assoc array of variables to load
+     */
+    public function loadArray($context_array)
+    {
+        foreach ($context_array as $key => $discard) {
+            $this->register($key, $context_array[$key]);
+        }
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Definition.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Definition.php
new file mode 100644
index 0000000000..bc6d433647
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Definition.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * Super-class for definition datatype objects, implements serialization
+ * functions for the class.
+ */
+abstract class HTMLPurifier_Definition
+{
+
+    /**
+     * Has setup() been called yet?
+     * @type bool
+     */
+    public $setup = false;
+
+    /**
+     * If true, write out the final definition object to the cache after
+     * setup.  This will be true only if all invocations to get a raw
+     * definition object are also optimized.  This does not cause file
+     * system thrashing because on subsequent calls the cached object
+     * is used and any writes to the raw definition object are short
+     * circuited.  See enduser-customize.html for the high-level
+     * picture.
+     * @type bool
+     */
+    public $optimized = null;
+
+    /**
+     * What type of definition is it?
+     * @type string
+     */
+    public $type;
+
+    /**
+     * Sets up the definition object into the final form, something
+     * not done by the constructor
+     * @param HTMLPurifier_Config $config
+     */
+    abstract protected function doSetup($config);
+
+    /**
+     * Setup function that aborts if already setup
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        if ($this->setup) {
+            return;
+        }
+        $this->setup = true;
+        $this->doSetup($config);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/DefinitionCache.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache.php
similarity index 66%
rename from library/HTMLPurifier/DefinitionCache.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache.php
index c6e1e388c6..67bb5b1e69 100644
--- a/library/HTMLPurifier/DefinitionCache.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache.php
@@ -10,22 +10,27 @@
  */
 abstract class HTMLPurifier_DefinitionCache
 {
-
+    /**
+     * @type string
+     */
     public $type;
 
     /**
-     * @param $name Type of definition objects this instance of the
+     * @param string $type Type of definition objects this instance of the
      *      cache will handle.
      */
-    public function __construct($type) {
+    public function __construct($type)
+    {
         $this->type = $type;
     }
 
     /**
      * Generates a unique identifier for a particular configuration
-     * @param Instance of HTMLPurifier_Config
+     * @param HTMLPurifier_Config $config Instance of HTMLPurifier_Config
+     * @return string
      */
-    public function generateKey($config) {
+    public function generateKey($config)
+    {
         return $config->version . ',' . // possibly replace with function calls
                $config->getBatchSerial($this->type) . ',' .
                $config->get($this->type . '.DefinitionRev');
@@ -34,30 +39,37 @@ abstract class HTMLPurifier_DefinitionCache
     /**
      * Tests whether or not a key is old with respect to the configuration's
      * version and revision number.
-     * @param $key Key to test
-     * @param $config Instance of HTMLPurifier_Config to test against
+     * @param string $key Key to test
+     * @param HTMLPurifier_Config $config Instance of HTMLPurifier_Config to test against
+     * @return bool
      */
-    public function isOld($key, $config) {
-        if (substr_count($key, ',') < 2) return true;
+    public function isOld($key, $config)
+    {
+        if (substr_count($key, ',') < 2) {
+            return true;
+        }
         list($version, $hash, $revision) = explode(',', $key, 3);
         $compare = version_compare($version, $config->version);
         // version mismatch, is always old
-        if ($compare != 0) return true;
+        if ($compare != 0) {
+            return true;
+        }
         // versions match, ids match, check revision number
-        if (
-            $hash == $config->getBatchSerial($this->type) &&
-            $revision < $config->get($this->type . '.DefinitionRev')
-        ) return true;
+        if ($hash == $config->getBatchSerial($this->type) &&
+            $revision < $config->get($this->type . '.DefinitionRev')) {
+            return true;
+        }
         return false;
     }
 
     /**
      * Checks if a definition's type jives with the cache's type
      * @note Throws an error on failure
-     * @param $def Definition object to check
-     * @return Boolean true if good, false if not
+     * @param HTMLPurifier_Definition $def Definition object to check
+     * @return bool true if good, false if not
      */
-    public function checkDefType($def) {
+    public function checkDefType($def)
+    {
         if ($def->type !== $this->type) {
             trigger_error("Cannot use definition of type {$def->type} in cache for {$this->type}");
             return false;
@@ -67,31 +79,40 @@ abstract class HTMLPurifier_DefinitionCache
 
     /**
      * Adds a definition object to the cache
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
      */
     abstract public function add($def, $config);
 
     /**
      * Unconditionally saves a definition object to the cache
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
      */
     abstract public function set($def, $config);
 
     /**
      * Replace an object in the cache
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
      */
     abstract public function replace($def, $config);
 
     /**
      * Retrieves a definition object from the cache
+     * @param HTMLPurifier_Config $config
      */
     abstract public function get($config);
 
     /**
      * Removes a definition object to the cache
+     * @param HTMLPurifier_Config $config
      */
     abstract public function remove($config);
 
     /**
      * Clears all objects from cache
+     * @param HTMLPurifier_Config $config
      */
     abstract public function flush($config);
 
@@ -100,9 +121,9 @@ abstract class HTMLPurifier_DefinitionCache
      * @note Be carefuly implementing this method as flush. Flush must
      *       not interfere with other Definition types, and cleanup()
      *       should not be repeatedly called by userland code.
+     * @param HTMLPurifier_Config $config
      */
     abstract public function cleanup($config);
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator.php
new file mode 100644
index 0000000000..b57a51b6cb
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator.php
@@ -0,0 +1,112 @@
+<?php
+
+class HTMLPurifier_DefinitionCache_Decorator extends HTMLPurifier_DefinitionCache
+{
+
+    /**
+     * Cache object we are decorating
+     * @type HTMLPurifier_DefinitionCache
+     */
+    public $cache;
+
+    /**
+     * The name of the decorator
+     * @var string
+     */
+    public $name;
+
+    public function __construct()
+    {
+    }
+
+    /**
+     * Lazy decorator function
+     * @param HTMLPurifier_DefinitionCache $cache Reference to cache object to decorate
+     * @return HTMLPurifier_DefinitionCache_Decorator
+     */
+    public function decorate(&$cache)
+    {
+        $decorator = $this->copy();
+        // reference is necessary for mocks in PHP 4
+        $decorator->cache =& $cache;
+        $decorator->type = $cache->type;
+        return $decorator;
+    }
+
+    /**
+     * Cross-compatible clone substitute
+     * @return HTMLPurifier_DefinitionCache_Decorator
+     */
+    public function copy()
+    {
+        return new HTMLPurifier_DefinitionCache_Decorator();
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function add($def, $config)
+    {
+        return $this->cache->add($def, $config);
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function set($def, $config)
+    {
+        return $this->cache->set($def, $config);
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function replace($def, $config)
+    {
+        return $this->cache->replace($def, $config);
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function get($config)
+    {
+        return $this->cache->get($config);
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function remove($config)
+    {
+        return $this->cache->remove($config);
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function flush($config)
+    {
+        return $this->cache->flush($config);
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function cleanup($config)
+    {
+        return $this->cache->cleanup($config);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php
new file mode 100644
index 0000000000..4991777ce1
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Cleanup.php
@@ -0,0 +1,78 @@
+<?php
+
+/**
+ * Definition cache decorator class that cleans up the cache
+ * whenever there is a cache miss.
+ */
+class HTMLPurifier_DefinitionCache_Decorator_Cleanup extends HTMLPurifier_DefinitionCache_Decorator
+{
+    /**
+     * @type string
+     */
+    public $name = 'Cleanup';
+
+    /**
+     * @return HTMLPurifier_DefinitionCache_Decorator_Cleanup
+     */
+    public function copy()
+    {
+        return new HTMLPurifier_DefinitionCache_Decorator_Cleanup();
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function add($def, $config)
+    {
+        $status = parent::add($def, $config);
+        if (!$status) {
+            parent::cleanup($config);
+        }
+        return $status;
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function set($def, $config)
+    {
+        $status = parent::set($def, $config);
+        if (!$status) {
+            parent::cleanup($config);
+        }
+        return $status;
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function replace($def, $config)
+    {
+        $status = parent::replace($def, $config);
+        if (!$status) {
+            parent::cleanup($config);
+        }
+        return $status;
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function get($config)
+    {
+        $ret = parent::get($config);
+        if (!$ret) {
+            parent::cleanup($config);
+        }
+        return $ret;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php
new file mode 100644
index 0000000000..d529dce48d
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Memory.php
@@ -0,0 +1,85 @@
+<?php
+
+/**
+ * Definition cache decorator class that saves all cache retrievals
+ * to PHP's memory; good for unit tests or circumstances where
+ * there are lots of configuration objects floating around.
+ */
+class HTMLPurifier_DefinitionCache_Decorator_Memory extends HTMLPurifier_DefinitionCache_Decorator
+{
+    /**
+     * @type array
+     */
+    protected $definitions;
+
+    /**
+     * @type string
+     */
+    public $name = 'Memory';
+
+    /**
+     * @return HTMLPurifier_DefinitionCache_Decorator_Memory
+     */
+    public function copy()
+    {
+        return new HTMLPurifier_DefinitionCache_Decorator_Memory();
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function add($def, $config)
+    {
+        $status = parent::add($def, $config);
+        if ($status) {
+            $this->definitions[$this->generateKey($config)] = $def;
+        }
+        return $status;
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function set($def, $config)
+    {
+        $status = parent::set($def, $config);
+        if ($status) {
+            $this->definitions[$this->generateKey($config)] = $def;
+        }
+        return $status;
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function replace($def, $config)
+    {
+        $status = parent::replace($def, $config);
+        if ($status) {
+            $this->definitions[$this->generateKey($config)] = $def;
+        }
+        return $status;
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function get($config)
+    {
+        $key = $this->generateKey($config);
+        if (isset($this->definitions[$key])) {
+            return $this->definitions[$key];
+        }
+        $this->definitions[$key] = parent::get($config);
+        return $this->definitions[$key];
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in
new file mode 100644
index 0000000000..b1fec8d367
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Decorator/Template.php.in
@@ -0,0 +1,82 @@
+<?php
+
+require_once 'HTMLPurifier/DefinitionCache/Decorator.php';
+
+/**
+ * Definition cache decorator template.
+ */
+class HTMLPurifier_DefinitionCache_Decorator_Template extends HTMLPurifier_DefinitionCache_Decorator
+{
+
+    /**
+     * @type string
+     */
+    public $name = 'Template'; // replace this
+
+    public function copy()
+    {
+        // replace class name with yours
+        return new HTMLPurifier_DefinitionCache_Decorator_Template();
+    }
+
+    // remove methods you don't need
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function add($def, $config)
+    {
+        return parent::add($def, $config);
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function set($def, $config)
+    {
+        return parent::set($def, $config);
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function replace($def, $config)
+    {
+        return parent::replace($def, $config);
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function get($config)
+    {
+        return parent::get($config);
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function flush($config)
+    {
+        return parent::flush($config);
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return mixed
+     */
+    public function cleanup($config)
+    {
+        return parent::cleanup($config);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Null.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Null.php
new file mode 100644
index 0000000000..d9a75ce227
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Null.php
@@ -0,0 +1,76 @@
+<?php
+
+/**
+ * Null cache object to use when no caching is on.
+ */
+class HTMLPurifier_DefinitionCache_Null extends HTMLPurifier_DefinitionCache
+{
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function add($def, $config)
+    {
+        return false;
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function set($def, $config)
+    {
+        return false;
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function replace($def, $config)
+    {
+        return false;
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function remove($config)
+    {
+        return false;
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function get($config)
+    {
+        return false;
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function flush($config)
+    {
+        return false;
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function cleanup($config)
+    {
+        return false;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php
new file mode 100644
index 0000000000..ce268d91b4
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer.php
@@ -0,0 +1,291 @@
+<?php
+
+class HTMLPurifier_DefinitionCache_Serializer extends HTMLPurifier_DefinitionCache
+{
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return int|bool
+     */
+    public function add($def, $config)
+    {
+        if (!$this->checkDefType($def)) {
+            return;
+        }
+        $file = $this->generateFilePath($config);
+        if (file_exists($file)) {
+            return false;
+        }
+        if (!$this->_prepareDir($config)) {
+            return false;
+        }
+        return $this->_write($file, serialize($def), $config);
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return int|bool
+     */
+    public function set($def, $config)
+    {
+        if (!$this->checkDefType($def)) {
+            return;
+        }
+        $file = $this->generateFilePath($config);
+        if (!$this->_prepareDir($config)) {
+            return false;
+        }
+        return $this->_write($file, serialize($def), $config);
+    }
+
+    /**
+     * @param HTMLPurifier_Definition $def
+     * @param HTMLPurifier_Config $config
+     * @return int|bool
+     */
+    public function replace($def, $config)
+    {
+        if (!$this->checkDefType($def)) {
+            return;
+        }
+        $file = $this->generateFilePath($config);
+        if (!file_exists($file)) {
+            return false;
+        }
+        if (!$this->_prepareDir($config)) {
+            return false;
+        }
+        return $this->_write($file, serialize($def), $config);
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool|HTMLPurifier_Config
+     */
+    public function get($config)
+    {
+        $file = $this->generateFilePath($config);
+        if (!file_exists($file)) {
+            return false;
+        }
+        return unserialize(file_get_contents($file));
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function remove($config)
+    {
+        $file = $this->generateFilePath($config);
+        if (!file_exists($file)) {
+            return false;
+        }
+        return unlink($file);
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function flush($config)
+    {
+        if (!$this->_prepareDir($config)) {
+            return false;
+        }
+        $dir = $this->generateDirectoryPath($config);
+        $dh = opendir($dir);
+        while (false !== ($filename = readdir($dh))) {
+            if (empty($filename)) {
+                continue;
+            }
+            if ($filename[0] === '.') {
+                continue;
+            }
+            unlink($dir . '/' . $filename);
+        }
+    }
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function cleanup($config)
+    {
+        if (!$this->_prepareDir($config)) {
+            return false;
+        }
+        $dir = $this->generateDirectoryPath($config);
+        $dh = opendir($dir);
+        while (false !== ($filename = readdir($dh))) {
+            if (empty($filename)) {
+                continue;
+            }
+            if ($filename[0] === '.') {
+                continue;
+            }
+            $key = substr($filename, 0, strlen($filename) - 4);
+            if ($this->isOld($key, $config)) {
+                unlink($dir . '/' . $filename);
+            }
+        }
+    }
+
+    /**
+     * Generates the file path to the serial file corresponding to
+     * the configuration and definition name
+     * @param HTMLPurifier_Config $config
+     * @return string
+     * @todo Make protected
+     */
+    public function generateFilePath($config)
+    {
+        $key = $this->generateKey($config);
+        return $this->generateDirectoryPath($config) . '/' . $key . '.ser';
+    }
+
+    /**
+     * Generates the path to the directory contain this cache's serial files
+     * @param HTMLPurifier_Config $config
+     * @return string
+     * @note No trailing slash
+     * @todo Make protected
+     */
+    public function generateDirectoryPath($config)
+    {
+        $base = $this->generateBaseDirectoryPath($config);
+        return $base . '/' . $this->type;
+    }
+
+    /**
+     * Generates path to base directory that contains all definition type
+     * serials
+     * @param HTMLPurifier_Config $config
+     * @return mixed|string
+     * @todo Make protected
+     */
+    public function generateBaseDirectoryPath($config)
+    {
+        $base = $config->get('Cache.SerializerPath');
+        $base = is_null($base) ? HTMLPURIFIER_PREFIX . '/HTMLPurifier/DefinitionCache/Serializer' : $base;
+        return $base;
+    }
+
+    /**
+     * Convenience wrapper function for file_put_contents
+     * @param string $file File name to write to
+     * @param string $data Data to write into file
+     * @param HTMLPurifier_Config $config
+     * @return int|bool Number of bytes written if success, or false if failure.
+     */
+    private function _write($file, $data, $config)
+    {
+        $result = file_put_contents($file, $data);
+        if ($result !== false) {
+            // set permissions of the new file (no execute)
+            $chmod = $config->get('Cache.SerializerPermissions');
+            if (!$chmod) {
+                $chmod = 0644; // invalid config or simpletest
+            }
+            $chmod = $chmod & 0666;
+            chmod($file, $chmod);
+        }
+        return $result;
+    }
+
+    /**
+     * Prepares the directory that this type stores the serials in
+     * @param HTMLPurifier_Config $config
+     * @return bool True if successful
+     */
+    private function _prepareDir($config)
+    {
+        $directory = $this->generateDirectoryPath($config);
+        $chmod = $config->get('Cache.SerializerPermissions');
+        if (!$chmod) {
+            $chmod = 0755; // invalid config or simpletest
+        }
+        if (!is_dir($directory)) {
+            $base = $this->generateBaseDirectoryPath($config);
+            if (!is_dir($base)) {
+                trigger_error(
+                    'Base directory ' . $base . ' does not exist,
+                    please create or change using %Cache.SerializerPath',
+                    E_USER_WARNING
+                );
+                return false;
+            } elseif (!$this->_testPermissions($base, $chmod)) {
+                return false;
+            }
+            mkdir($directory, $chmod);
+            if (!$this->_testPermissions($directory, $chmod)) {
+                trigger_error(
+                    'Base directory ' . $base . ' does not exist,
+                    please create or change using %Cache.SerializerPath',
+                    E_USER_WARNING
+                );
+                return false;
+            }
+        } elseif (!$this->_testPermissions($directory, $chmod)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Tests permissions on a directory and throws out friendly
+     * error messages and attempts to chmod it itself if possible
+     * @param string $dir Directory path
+     * @param int $chmod Permissions
+     * @return bool True if directory is writable
+     */
+    private function _testPermissions($dir, $chmod)
+    {
+        // early abort, if it is writable, everything is hunky-dory
+        if (is_writable($dir)) {
+            return true;
+        }
+        if (!is_dir($dir)) {
+            // generally, you'll want to handle this beforehand
+            // so a more specific error message can be given
+            trigger_error(
+                'Directory ' . $dir . ' does not exist',
+                E_USER_WARNING
+            );
+            return false;
+        }
+        if (function_exists('posix_getuid')) {
+            // POSIX system, we can give more specific advice
+            if (fileowner($dir) === posix_getuid()) {
+                // we can chmod it ourselves
+                $chmod = $chmod | 0700;
+                if (chmod($dir, $chmod)) {
+                    return true;
+                }
+            } elseif (filegroup($dir) === posix_getgid()) {
+                $chmod = $chmod | 0070;
+            } else {
+                // PHP's probably running as nobody, so we'll
+                // need to give global permissions
+                $chmod = $chmod | 0777;
+            }
+            trigger_error(
+                'Directory ' . $dir . ' not writable, ' .
+                'please chmod to ' . decoct($chmod),
+                E_USER_WARNING
+            );
+        } else {
+            // generic error message
+            trigger_error(
+                'Directory ' . $dir . ' not writable, ' .
+                'please alter file permissions',
+                E_USER_WARNING
+            );
+        }
+        return false;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/DefinitionCache/Serializer/README b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/README
similarity index 100%
rename from library/HTMLPurifier/DefinitionCache/Serializer/README
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCache/Serializer/README
diff --git a/library/HTMLPurifier/DefinitionCacheFactory.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php
similarity index 67%
rename from library/HTMLPurifier/DefinitionCacheFactory.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php
index a6ead62818..fd1cc9be46 100644
--- a/library/HTMLPurifier/DefinitionCacheFactory.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/DefinitionCacheFactory.php
@@ -5,22 +5,36 @@
  */
 class HTMLPurifier_DefinitionCacheFactory
 {
-
+    /**
+     * @type array
+     */
     protected $caches = array('Serializer' => array());
+
+    /**
+     * @type array
+     */
     protected $implementations = array();
+
+    /**
+     * @type HTMLPurifier_DefinitionCache_Decorator[]
+     */
     protected $decorators = array();
 
     /**
      * Initialize default decorators
      */
-    public function setup() {
+    public function setup()
+    {
         $this->addDecorator('Cleanup');
     }
 
     /**
      * Retrieves an instance of global definition cache factory.
+     * @param HTMLPurifier_DefinitionCacheFactory $prototype
+     * @return HTMLPurifier_DefinitionCacheFactory
      */
-    public static function instance($prototype = null) {
+    public static function instance($prototype = null)
+    {
         static $instance;
         if ($prototype !== null) {
             $instance = $prototype;
@@ -33,19 +47,22 @@ class HTMLPurifier_DefinitionCacheFactory
 
     /**
      * Registers a new definition cache object
-     * @param $short Short name of cache object, for reference
-     * @param $long Full class name of cache object, for construction
+     * @param string $short Short name of cache object, for reference
+     * @param string $long Full class name of cache object, for construction
      */
-    public function register($short, $long) {
+    public function register($short, $long)
+    {
         $this->implementations[$short] = $long;
     }
 
     /**
      * Factory method that creates a cache object based on configuration
-     * @param $name Name of definitions handled by cache
-     * @param $config Instance of HTMLPurifier_Config
+     * @param string $type Name of definitions handled by cache
+     * @param HTMLPurifier_Config $config Config instance
+     * @return mixed
      */
-    public function create($type, $config) {
+    public function create($type, $config)
+    {
         $method = $config->get('Cache.DefinitionImpl');
         if ($method === null) {
             return new HTMLPurifier_DefinitionCache_Null($type);
@@ -53,10 +70,8 @@ class HTMLPurifier_DefinitionCacheFactory
         if (!empty($this->caches[$method][$type])) {
             return $this->caches[$method][$type];
         }
-        if (
-          isset($this->implementations[$method]) &&
-          class_exists($class = $this->implementations[$method], false)
-        ) {
+        if (isset($this->implementations[$method]) &&
+            class_exists($class = $this->implementations[$method], false)) {
             $cache = new $class($type);
         } else {
             if ($method != 'Serializer') {
@@ -76,16 +91,16 @@ class HTMLPurifier_DefinitionCacheFactory
 
     /**
      * Registers a decorator to add to all new cache objects
-     * @param
+     * @param HTMLPurifier_DefinitionCache_Decorator|string $decorator An instance or the name of a decorator
      */
-    public function addDecorator($decorator) {
+    public function addDecorator($decorator)
+    {
         if (is_string($decorator)) {
             $class = "HTMLPurifier_DefinitionCache_Decorator_$decorator";
             $decorator = new $class;
         }
         $this->decorators[$decorator->name] = $decorator;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Doctype.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Doctype.php
similarity index 77%
rename from library/HTMLPurifier/Doctype.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Doctype.php
index 1e3c574c06..4acd06e5bd 100644
--- a/library/HTMLPurifier/Doctype.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Doctype.php
@@ -10,42 +10,55 @@ class HTMLPurifier_Doctype
 {
     /**
      * Full name of doctype
+     * @type string
      */
     public $name;
 
     /**
      * List of standard modules (string identifiers or literal objects)
      * that this doctype uses
+     * @type array
      */
     public $modules = array();
 
     /**
      * List of modules to use for tidying up code
+     * @type array
      */
     public $tidyModules = array();
 
     /**
      * Is the language derived from XML (i.e. XHTML)?
+     * @type bool
      */
     public $xml = true;
 
     /**
      * List of aliases for this doctype
+     * @type array
      */
     public $aliases = array();
 
     /**
      * Public DTD identifier
+     * @type string
      */
     public $dtdPublic;
 
     /**
      * System DTD identifier
+     * @type string
      */
     public $dtdSystem;
 
-    public function __construct($name = null, $xml = true, $modules = array(),
-        $tidyModules = array(), $aliases = array(), $dtd_public = null, $dtd_system = null
+    public function __construct(
+        $name = null,
+        $xml = true,
+        $modules = array(),
+        $tidyModules = array(),
+        $aliases = array(),
+        $dtd_public = null,
+        $dtd_system = null
     ) {
         $this->name         = $name;
         $this->xml          = $xml;
diff --git a/library/HTMLPurifier/DoctypeRegistry.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/DoctypeRegistry.php
similarity index 51%
rename from library/HTMLPurifier/DoctypeRegistry.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/DoctypeRegistry.php
index 86049e9391..acc1d64a62 100644
--- a/library/HTMLPurifier/DoctypeRegistry.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/DoctypeRegistry.php
@@ -4,12 +4,14 @@ class HTMLPurifier_DoctypeRegistry
 {
 
     /**
-     * Hash of doctype names to doctype objects
+     * Hash of doctype names to doctype objects.
+     * @type array
      */
     protected $doctypes;
 
     /**
-     * Lookup table of aliases to real doctype names
+     * Lookup table of aliases to real doctype names.
+     * @type array
      */
     protected $aliases;
 
@@ -17,32 +19,57 @@ class HTMLPurifier_DoctypeRegistry
      * Registers a doctype to the registry
      * @note Accepts a fully-formed doctype object, or the
      *       parameters for constructing a doctype object
-     * @param $doctype Name of doctype or literal doctype object
-     * @param $modules Modules doctype will load
-     * @param $modules_for_modes Modules doctype will load for certain modes
-     * @param $aliases Alias names for doctype
-     * @return Editable registered doctype
+     * @param string $doctype Name of doctype or literal doctype object
+     * @param bool $xml
+     * @param array $modules Modules doctype will load
+     * @param array $tidy_modules Modules doctype will load for certain modes
+     * @param array $aliases Alias names for doctype
+     * @param string $dtd_public
+     * @param string $dtd_system
+     * @return HTMLPurifier_Doctype Editable registered doctype
      */
-    public function register($doctype, $xml = true, $modules = array(),
-        $tidy_modules = array(), $aliases = array(), $dtd_public = null, $dtd_system = null
+    public function register(
+        $doctype,
+        $xml = true,
+        $modules = array(),
+        $tidy_modules = array(),
+        $aliases = array(),
+        $dtd_public = null,
+        $dtd_system = null
     ) {
-        if (!is_array($modules)) $modules = array($modules);
-        if (!is_array($tidy_modules)) $tidy_modules = array($tidy_modules);
-        if (!is_array($aliases)) $aliases = array($aliases);
+        if (!is_array($modules)) {
+            $modules = array($modules);
+        }
+        if (!is_array($tidy_modules)) {
+            $tidy_modules = array($tidy_modules);
+        }
+        if (!is_array($aliases)) {
+            $aliases = array($aliases);
+        }
         if (!is_object($doctype)) {
             $doctype = new HTMLPurifier_Doctype(
-                $doctype, $xml, $modules, $tidy_modules, $aliases, $dtd_public, $dtd_system
+                $doctype,
+                $xml,
+                $modules,
+                $tidy_modules,
+                $aliases,
+                $dtd_public,
+                $dtd_system
             );
         }
         $this->doctypes[$doctype->name] = $doctype;
         $name = $doctype->name;
         // hookup aliases
         foreach ($doctype->aliases as $alias) {
-            if (isset($this->doctypes[$alias])) continue;
+            if (isset($this->doctypes[$alias])) {
+                continue;
+            }
             $this->aliases[$alias] = $name;
         }
         // remove old aliases
-        if (isset($this->aliases[$name])) unset($this->aliases[$name]);
+        if (isset($this->aliases[$name])) {
+            unset($this->aliases[$name]);
+        }
         return $doctype;
     }
 
@@ -50,11 +77,14 @@ class HTMLPurifier_DoctypeRegistry
      * Retrieves reference to a doctype of a certain name
      * @note This function resolves aliases
      * @note When possible, use the more fully-featured make()
-     * @param $doctype Name of doctype
-     * @return Editable doctype object
+     * @param string $doctype Name of doctype
+     * @return HTMLPurifier_Doctype Editable doctype object
      */
-    public function get($doctype) {
-        if (isset($this->aliases[$doctype])) $doctype = $this->aliases[$doctype];
+    public function get($doctype)
+    {
+        if (isset($this->aliases[$doctype])) {
+            $doctype = $this->aliases[$doctype];
+        }
         if (!isset($this->doctypes[$doctype])) {
             trigger_error('Doctype ' . htmlspecialchars($doctype) . ' does not exist', E_USER_ERROR);
             $anon = new HTMLPurifier_Doctype($doctype);
@@ -70,20 +100,30 @@ class HTMLPurifier_DoctypeRegistry
      *       can hold on to (this is necessary in order to tell
      *       Generator whether or not the current document is XML
      *       based or not).
+     * @param HTMLPurifier_Config $config
+     * @return HTMLPurifier_Doctype
      */
-    public function make($config) {
+    public function make($config)
+    {
         return clone $this->get($this->getDoctypeFromConfig($config));
     }
 
     /**
      * Retrieves the doctype from the configuration object
+     * @param HTMLPurifier_Config $config
+     * @return string
      */
-    public function getDoctypeFromConfig($config) {
+    public function getDoctypeFromConfig($config)
+    {
         // recommended test
         $doctype = $config->get('HTML.Doctype');
-        if (!empty($doctype)) return $doctype;
+        if (!empty($doctype)) {
+            return $doctype;
+        }
         $doctype = $config->get('HTML.CustomDoctype');
-        if (!empty($doctype)) return $doctype;
+        if (!empty($doctype)) {
+            return $doctype;
+        }
         // backwards-compatibility
         if ($config->get('HTML.XHTML')) {
             $doctype = 'XHTML 1.0';
@@ -97,7 +137,6 @@ class HTMLPurifier_DoctypeRegistry
         }
         return $doctype;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ElementDef.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ElementDef.php
similarity index 69%
rename from library/HTMLPurifier/ElementDef.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ElementDef.php
index 5498d95670..d5311cedcf 100644
--- a/library/HTMLPurifier/ElementDef.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ElementDef.php
@@ -10,15 +10,16 @@
  */
 class HTMLPurifier_ElementDef
 {
-
     /**
      * Does the definition work by itself, or is it created solely
      * for the purpose of merging into another definition?
+     * @type bool
      */
     public $standalone = true;
 
     /**
-     * Associative array of attribute name to HTMLPurifier_AttrDef
+     * Associative array of attribute name to HTMLPurifier_AttrDef.
+     * @type array
      * @note Before being processed by HTMLPurifier_AttrCollections
      *       when modules are finalized during
      *       HTMLPurifier_HTMLDefinition->setup(), this array may also
@@ -30,27 +31,43 @@ class HTMLPurifier_ElementDef
      */
     public $attr = array();
 
+    // XXX: Design note: currently, it's not possible to override
+    // previously defined AttrTransforms without messing around with
+    // the final generated config. This is by design; a previous version
+    // used an associated list of attr_transform, but it was extremely
+    // easy to accidentally override other attribute transforms by
+    // forgetting to specify an index (and just using 0.)  While we
+    // could check this by checking the index number and complaining,
+    // there is a second problem which is that it is not at all easy to
+    // tell when something is getting overridden. Combine this with a
+    // codebase where this isn't really being used, and it's perfect for
+    // nuking.
+
     /**
-     * Indexed list of tag's HTMLPurifier_AttrTransform to be done before validation
+     * List of tags HTMLPurifier_AttrTransform to be done before validation.
+     * @type array
      */
     public $attr_transform_pre = array();
 
     /**
-     * Indexed list of tag's HTMLPurifier_AttrTransform to be done after validation
+     * List of tags HTMLPurifier_AttrTransform to be done after validation.
+     * @type array
      */
     public $attr_transform_post = array();
 
     /**
      * HTMLPurifier_ChildDef of this tag.
+     * @type HTMLPurifier_ChildDef
      */
     public $child;
 
     /**
-     * Abstract string representation of internal ChildDef rules. See
-     * HTMLPurifier_ContentSets for how this is parsed and then transformed
+     * Abstract string representation of internal ChildDef rules.
+     * @see HTMLPurifier_ContentSets for how this is parsed and then transformed
      * into an HTMLPurifier_ChildDef.
      * @warning This is a temporary variable that is not available after
      *      being processed by HTMLDefinition
+     * @type string
      */
     public $content_model;
 
@@ -60,27 +77,29 @@ class HTMLPurifier_ElementDef
      * @warning This must be lowercase
      * @warning This is a temporary variable that is not available after
      *      being processed by HTMLDefinition
+     * @type string
      */
     public $content_model_type;
 
-
-
     /**
      * Does the element have a content model (#PCDATA | Inline)*? This
      * is important for chameleon ins and del processing in
      * HTMLPurifier_ChildDef_Chameleon. Dynamically set: modules don't
      * have to worry about this one.
+     * @type bool
      */
     public $descendants_are_inline = false;
 
     /**
-     * List of the names of required attributes this element has. Dynamically
-     * populated by HTMLPurifier_HTMLDefinition::getElement
+     * List of the names of required attributes this element has.
+     * Dynamically populated by HTMLPurifier_HTMLDefinition::getElement()
+     * @type array
      */
     public $required_attr = array();
 
     /**
      * Lookup table of tags excluded from all descendants of this tag.
+     * @type array
      * @note SGML permits exclusions for all descendants, but this is
      *       not possible with DTDs or XML Schemas. W3C has elected to
      *       use complicated compositions of content_models to simulate
@@ -94,6 +113,7 @@ class HTMLPurifier_ElementDef
 
     /**
      * This tag is explicitly auto-closed by the following tags.
+     * @type array
      */
     public $autoclose = array();
 
@@ -101,19 +121,22 @@ class HTMLPurifier_ElementDef
      * If a foreign element is found in this element, test if it is
      * allowed by this sub-element; if it is, instead of closing the
      * current element, place it inside this element.
+     * @type string
      */
     public $wrap;
 
     /**
      * Whether or not this is a formatting element affected by the
      * "Active Formatting Elements" algorithm.
+     * @type bool
      */
     public $formatting;
 
     /**
      * Low-level factory constructor for creating new standalone element defs
      */
-    public static function create($content_model, $content_model_type, $attr) {
+    public static function create($content_model, $content_model_type, $attr)
+    {
         $def = new HTMLPurifier_ElementDef();
         $def->content_model = $content_model;
         $def->content_model_type = $content_model_type;
@@ -125,11 +148,12 @@ class HTMLPurifier_ElementDef
      * Merges the values of another element definition into this one.
      * Values from the new element def take precedence if a value is
      * not mergeable.
+     * @param HTMLPurifier_ElementDef $def
      */
-    public function mergeIn($def) {
-
+    public function mergeIn($def)
+    {
         // later keys takes precedence
-        foreach($def->attr as $k => $v) {
+        foreach ($def->attr as $k => $v) {
             if ($k === 0) {
                 // merge in the includes
                 // sorry, no way to override an include
@@ -139,28 +163,35 @@ class HTMLPurifier_ElementDef
                 continue;
             }
             if ($v === false) {
-                if (isset($this->attr[$k])) unset($this->attr[$k]);
+                if (isset($this->attr[$k])) {
+                    unset($this->attr[$k]);
+                }
                 continue;
             }
             $this->attr[$k] = $v;
         }
-        $this->_mergeAssocArray($this->attr_transform_pre, $def->attr_transform_pre);
-        $this->_mergeAssocArray($this->attr_transform_post, $def->attr_transform_post);
         $this->_mergeAssocArray($this->excludes, $def->excludes);
+        $this->attr_transform_pre = array_merge($this->attr_transform_pre, $def->attr_transform_pre);
+        $this->attr_transform_post = array_merge($this->attr_transform_post, $def->attr_transform_post);
 
-        if(!empty($def->content_model)) {
+        if (!empty($def->content_model)) {
             $this->content_model =
                 str_replace("#SUPER", $this->content_model, $def->content_model);
             $this->child = false;
         }
-        if(!empty($def->content_model_type)) {
+        if (!empty($def->content_model_type)) {
             $this->content_model_type = $def->content_model_type;
             $this->child = false;
         }
-        if(!is_null($def->child)) $this->child = $def->child;
-        if(!is_null($def->formatting)) $this->formatting = $def->formatting;
-        if($def->descendants_are_inline) $this->descendants_are_inline = $def->descendants_are_inline;
-
+        if (!is_null($def->child)) {
+            $this->child = $def->child;
+        }
+        if (!is_null($def->formatting)) {
+            $this->formatting = $def->formatting;
+        }
+        if ($def->descendants_are_inline) {
+            $this->descendants_are_inline = $def->descendants_are_inline;
+        }
     }
 
     /**
@@ -168,16 +199,18 @@ class HTMLPurifier_ElementDef
      * @param $a1 Array by reference that is merged into
      * @param $a2 Array that merges into $a1
      */
-    private function _mergeAssocArray(&$a1, $a2) {
+    private function _mergeAssocArray(&$a1, $a2)
+    {
         foreach ($a2 as $k => $v) {
             if ($v === false) {
-                if (isset($a1[$k])) unset($a1[$k]);
+                if (isset($a1[$k])) {
+                    unset($a1[$k]);
+                }
                 continue;
             }
             $a1[$k] = $v;
         }
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Encoder.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Encoder.php
similarity index 63%
rename from library/HTMLPurifier/Encoder.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Encoder.php
index 2b3140caaf..fef9b58906 100644
--- a/library/HTMLPurifier/Encoder.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Encoder.php
@@ -10,14 +10,90 @@ class HTMLPurifier_Encoder
     /**
      * Constructor throws fatal error if you attempt to instantiate class
      */
-    private function __construct() {
+    private function __construct()
+    {
         trigger_error('Cannot instantiate encoder, call methods statically', E_USER_ERROR);
     }
 
     /**
      * Error-handler that mutes errors, alternative to shut-up operator.
      */
-    public static function muteErrorHandler() {}
+    public static function muteErrorHandler()
+    {
+    }
+
+    /**
+     * iconv wrapper which mutes errors, but doesn't work around bugs.
+     * @param string $in Input encoding
+     * @param string $out Output encoding
+     * @param string $text The text to convert
+     * @return string
+     */
+    public static function unsafeIconv($in, $out, $text)
+    {
+        set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
+        $r = iconv($in, $out, $text);
+        restore_error_handler();
+        return $r;
+    }
+
+    /**
+     * iconv wrapper which mutes errors and works around bugs.
+     * @param string $in Input encoding
+     * @param string $out Output encoding
+     * @param string $text The text to convert
+     * @param int $max_chunk_size
+     * @return string
+     */
+    public static function iconv($in, $out, $text, $max_chunk_size = 8000)
+    {
+        $code = self::testIconvTruncateBug();
+        if ($code == self::ICONV_OK) {
+            return self::unsafeIconv($in, $out, $text);
+        } elseif ($code == self::ICONV_TRUNCATES) {
+            // we can only work around this if the input character set
+            // is utf-8
+            if ($in == 'utf-8') {
+                if ($max_chunk_size < 4) {
+                    trigger_error('max_chunk_size is too small', E_USER_WARNING);
+                    return false;
+                }
+                // split into 8000 byte chunks, but be careful to handle
+                // multibyte boundaries properly
+                if (($c = strlen($text)) <= $max_chunk_size) {
+                    return self::unsafeIconv($in, $out, $text);
+                }
+                $r = '';
+                $i = 0;
+                while (true) {
+                    if ($i + $max_chunk_size >= $c) {
+                        $r .= self::unsafeIconv($in, $out, substr($text, $i));
+                        break;
+                    }
+                    // wibble the boundary
+                    if (0x80 != (0xC0 & ord($text[$i + $max_chunk_size]))) {
+                        $chunk_size = $max_chunk_size;
+                    } elseif (0x80 != (0xC0 & ord($text[$i + $max_chunk_size - 1]))) {
+                        $chunk_size = $max_chunk_size - 1;
+                    } elseif (0x80 != (0xC0 & ord($text[$i + $max_chunk_size - 2]))) {
+                        $chunk_size = $max_chunk_size - 2;
+                    } elseif (0x80 != (0xC0 & ord($text[$i + $max_chunk_size - 3]))) {
+                        $chunk_size = $max_chunk_size - 3;
+                    } else {
+                        return false; // rather confusing UTF-8...
+                    }
+                    $chunk = substr($text, $i, $chunk_size); // substr doesn't mind overlong lengths
+                    $r .= self::unsafeIconv($in, $out, $chunk);
+                    $i += $chunk_size;
+                }
+                return $r;
+            } else {
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
 
     /**
      * Cleans a UTF-8 string for well-formedness and SGML validity
@@ -25,6 +101,10 @@ class HTMLPurifier_Encoder
      * It will parse according to UTF-8 and return a valid UTF8 string, with
      * non-SGML codepoints excluded.
      *
+     * @param string $str The string to clean
+     * @param bool $force_php
+     * @return string
+     *
      * @note Just for reference, the non-SGML code points are 0 to 31 and
      *       127 to 159, inclusive.  However, we allow code points 9, 10
      *       and 13, which are the tab, line feed and carriage return
@@ -44,14 +124,17 @@ class HTMLPurifier_Encoder
      *       would need that, and I'm probably not going to implement them.
      *       Once again, PHP 6 should solve all our problems.
      */
-    public static function cleanUTF8($str, $force_php = false) {
-
+    public static function cleanUTF8($str, $force_php = false)
+    {
         // UTF-8 validity is checked since PHP 4.3.5
         // This is an optimization: if the string is already valid UTF-8, no
         // need to do PHP stuff. 99% of the time, this will be the case.
         // The regexp matches the XML char production, as well as well as excluding
         // non-SGML codepoints U+007F to U+009F
-        if (preg_match('/^[\x{9}\x{A}\x{D}\x{20}-\x{7E}\x{A0}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]*$/Du', $str)) {
+        if (preg_match(
+            '/^[\x{9}\x{A}\x{D}\x{20}-\x{7E}\x{A0}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]*$/Du',
+            $str
+        )) {
             return $str;
         }
 
@@ -70,7 +153,7 @@ class HTMLPurifier_Encoder
         $char = '';
 
         $len = strlen($str);
-        for($i = 0; $i < $len; $i++) {
+        for ($i = 0; $i < $len; $i++) {
             $in = ord($str{$i});
             $char .= $str[$i]; // append byte to char
             if (0 == $mState) {
@@ -223,8 +306,9 @@ class HTMLPurifier_Encoder
     // | 00000000 | 00010000 | 11111111 | 11111111 | Defined upper limit of legal scalar codes
     // +----------+----------+----------+----------+
 
-    public static function unichr($code) {
-        if($code > 1114111 or $code < 0 or
+    public static function unichr($code)
+    {
+        if ($code > 1114111 or $code < 0 or
           ($code >= 55296 and $code <= 57343) ) {
             // bits are set outside the "valid" range as defined
             // by UNICODE 4.1.0
@@ -242,7 +326,7 @@ class HTMLPurifier_Encoder
                 $y = (($code & 2047) >> 6) | 192;
             } else {
                 $y = (($code & 4032) >> 6) | 128;
-                if($code < 65536) {
+                if ($code < 65536) {
                     $z = (($code >> 12) & 15) | 224;
                 } else {
                     $z = (($code >> 12) & 63) | 128;
@@ -252,84 +336,129 @@ class HTMLPurifier_Encoder
         }
         // set up the actual character
         $ret = '';
-        if($w) $ret .= chr($w);
-        if($z) $ret .= chr($z);
-        if($y) $ret .= chr($y);
+        if ($w) {
+            $ret .= chr($w);
+        }
+        if ($z) {
+            $ret .= chr($z);
+        }
+        if ($y) {
+            $ret .= chr($y);
+        }
         $ret .= chr($x);
 
         return $ret;
     }
 
     /**
-     * Converts a string to UTF-8 based on configuration.
+     * @return bool
      */
-    public static function convertToUTF8($str, $config, $context) {
-        $encoding = $config->get('Core.Encoding');
-        if ($encoding === 'utf-8') return $str;
+    public static function iconvAvailable()
+    {
         static $iconv = null;
-        if ($iconv === null) $iconv = function_exists('iconv');
-        set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
+        if ($iconv === null) {
+            $iconv = function_exists('iconv') && self::testIconvTruncateBug() != self::ICONV_UNUSABLE;
+        }
+        return $iconv;
+    }
+
+    /**
+     * Convert a string to UTF-8 based on configuration.
+     * @param string $str The string to convert
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
+     */
+    public static function convertToUTF8($str, $config, $context)
+    {
+        $encoding = $config->get('Core.Encoding');
+        if ($encoding === 'utf-8') {
+            return $str;
+        }
+        static $iconv = null;
+        if ($iconv === null) {
+            $iconv = self::iconvAvailable();
+        }
         if ($iconv && !$config->get('Test.ForceNoIconv')) {
-            $str = iconv($encoding, 'utf-8//IGNORE', $str);
+            // unaffected by bugs, since UTF-8 support all characters
+            $str = self::unsafeIconv($encoding, 'utf-8//IGNORE', $str);
             if ($str === false) {
                 // $encoding is not a valid encoding
-                restore_error_handler();
                 trigger_error('Invalid encoding ' . $encoding, E_USER_ERROR);
                 return '';
             }
             // If the string is bjorked by Shift_JIS or a similar encoding
             // that doesn't support all of ASCII, convert the naughty
             // characters to their true byte-wise ASCII/UTF-8 equivalents.
-            $str = strtr($str, HTMLPurifier_Encoder::testEncodingSupportsASCII($encoding));
-            restore_error_handler();
+            $str = strtr($str, self::testEncodingSupportsASCII($encoding));
             return $str;
         } elseif ($encoding === 'iso-8859-1') {
             $str = utf8_encode($str);
-            restore_error_handler();
             return $str;
         }
-        trigger_error('Encoding not supported, please install iconv', E_USER_ERROR);
+        $bug = HTMLPurifier_Encoder::testIconvTruncateBug();
+        if ($bug == self::ICONV_OK) {
+            trigger_error('Encoding not supported, please install iconv', E_USER_ERROR);
+        } else {
+            trigger_error(
+                'You have a buggy version of iconv, see https://bugs.php.net/bug.php?id=48147 ' .
+                'and http://sourceware.org/bugzilla/show_bug.cgi?id=13541',
+                E_USER_ERROR
+            );
+        }
     }
 
     /**
      * Converts a string from UTF-8 based on configuration.
+     * @param string $str The string to convert
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
      * @note Currently, this is a lossy conversion, with unexpressable
      *       characters being omitted.
      */
-    public static function convertFromUTF8($str, $config, $context) {
+    public static function convertFromUTF8($str, $config, $context)
+    {
         $encoding = $config->get('Core.Encoding');
-        if ($encoding === 'utf-8') return $str;
-        static $iconv = null;
-        if ($iconv === null) $iconv = function_exists('iconv');
         if ($escape = $config->get('Core.EscapeNonASCIICharacters')) {
-            $str = HTMLPurifier_Encoder::convertToASCIIDumbLossless($str);
+            $str = self::convertToASCIIDumbLossless($str);
+        }
+        if ($encoding === 'utf-8') {
+            return $str;
+        }
+        static $iconv = null;
+        if ($iconv === null) {
+            $iconv = self::iconvAvailable();
         }
-        set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
         if ($iconv && !$config->get('Test.ForceNoIconv')) {
             // Undo our previous fix in convertToUTF8, otherwise iconv will barf
-            $ascii_fix = HTMLPurifier_Encoder::testEncodingSupportsASCII($encoding);
+            $ascii_fix = self::testEncodingSupportsASCII($encoding);
             if (!$escape && !empty($ascii_fix)) {
                 $clear_fix = array();
-                foreach ($ascii_fix as $utf8 => $native) $clear_fix[$utf8] = '';
+                foreach ($ascii_fix as $utf8 => $native) {
+                    $clear_fix[$utf8] = '';
+                }
                 $str = strtr($str, $clear_fix);
             }
             $str = strtr($str, array_flip($ascii_fix));
             // Normal stuff
-            $str = iconv('utf-8', $encoding . '//IGNORE', $str);
-            restore_error_handler();
+            $str = self::iconv('utf-8', $encoding . '//IGNORE', $str);
             return $str;
         } elseif ($encoding === 'iso-8859-1') {
             $str = utf8_decode($str);
-            restore_error_handler();
             return $str;
         }
         trigger_error('Encoding not supported', E_USER_ERROR);
+        // You might be tempted to assume that the ASCII representation
+        // might be OK, however, this is *not* universally true over all
+        // encodings.  So we take the conservative route here, rather
+        // than forcibly turn on %Core.EscapeNonASCIICharacters
     }
 
     /**
      * Lossless (character-wise) conversion of HTML to ASCII
-     * @param $str UTF-8 string to be converted to ASCII
-     * @returns ASCII encoded string with non-ASCII character entity-ized
+     * @param string $str UTF-8 string to be converted to ASCII
+     * @return string ASCII encoded string with non-ASCII character entity-ized
      * @warning Adapted from MediaWiki, claiming fair use: this is a common
      *       algorithm. If you disagree with this license fudgery,
      *       implement it yourself.
@@ -342,27 +471,28 @@ class HTMLPurifier_Encoder
      * @note Sort of with cleanUTF8() but it assumes that $str is
      *       well-formed UTF-8
      */
-    public static function convertToASCIIDumbLossless($str) {
+    public static function convertToASCIIDumbLossless($str)
+    {
         $bytesleft = 0;
         $result = '';
         $working = 0;
         $len = strlen($str);
-        for( $i = 0; $i < $len; $i++ ) {
-            $bytevalue = ord( $str[$i] );
-            if( $bytevalue <= 0x7F ) { //0xxx xxxx
-                $result .= chr( $bytevalue );
+        for ($i = 0; $i < $len; $i++) {
+            $bytevalue = ord($str[$i]);
+            if ($bytevalue <= 0x7F) { //0xxx xxxx
+                $result .= chr($bytevalue);
                 $bytesleft = 0;
-            } elseif( $bytevalue <= 0xBF ) { //10xx xxxx
+            } elseif ($bytevalue <= 0xBF) { //10xx xxxx
                 $working = $working << 6;
                 $working += ($bytevalue & 0x3F);
                 $bytesleft--;
-                if( $bytesleft <= 0 ) {
+                if ($bytesleft <= 0) {
                     $result .= "&#" . $working . ";";
                 }
-            } elseif( $bytevalue <= 0xDF ) { //110x xxxx
+            } elseif ($bytevalue <= 0xDF) { //110x xxxx
                 $working = $bytevalue & 0x1F;
                 $bytesleft = 1;
-            } elseif( $bytevalue <= 0xEF ) { //1110 xxxx
+            } elseif ($bytevalue <= 0xEF) { //1110 xxxx
                 $working = $bytevalue & 0x0F;
                 $bytesleft = 2;
             } else { //1111 0xxx
@@ -373,6 +503,54 @@ class HTMLPurifier_Encoder
         return $result;
     }
 
+    /** No bugs detected in iconv. */
+    const ICONV_OK = 0;
+
+    /** Iconv truncates output if converting from UTF-8 to another
+     *  character set with //IGNORE, and a non-encodable character is found */
+    const ICONV_TRUNCATES = 1;
+
+    /** Iconv does not support //IGNORE, making it unusable for
+     *  transcoding purposes */
+    const ICONV_UNUSABLE = 2;
+
+    /**
+     * glibc iconv has a known bug where it doesn't handle the magic
+     * //IGNORE stanza correctly.  In particular, rather than ignore
+     * characters, it will return an EILSEQ after consuming some number
+     * of characters, and expect you to restart iconv as if it were
+     * an E2BIG.  Old versions of PHP did not respect the errno, and
+     * returned the fragment, so as a result you would see iconv
+     * mysteriously truncating output. We can work around this by
+     * manually chopping our input into segments of about 8000
+     * characters, as long as PHP ignores the error code.  If PHP starts
+     * paying attention to the error code, iconv becomes unusable.
+     *
+     * @return int Error code indicating severity of bug.
+     */
+    public static function testIconvTruncateBug()
+    {
+        static $code = null;
+        if ($code === null) {
+            // better not use iconv, otherwise infinite loop!
+            $r = self::unsafeIconv('utf-8', 'ascii//IGNORE', "\xCE\xB1" . str_repeat('a', 9000));
+            if ($r === false) {
+                $code = self::ICONV_UNUSABLE;
+            } elseif (($c = strlen($r)) < 9000) {
+                $code = self::ICONV_TRUNCATES;
+            } elseif ($c > 9000) {
+                trigger_error(
+                    'Your copy of iconv is extremely buggy. Please notify HTML Purifier maintainers: ' .
+                    'include your iconv version as per phpversion()',
+                    E_USER_ERROR
+                );
+            } else {
+                $code = self::ICONV_OK;
+            }
+        }
+        return $code;
+    }
+
     /**
      * This expensive function tests whether or not a given character
      * encoding supports ASCII. 7/8-bit encodings like Shift_JIS will
@@ -384,10 +562,18 @@ class HTMLPurifier_Encoder
      * @return Array of UTF-8 characters to their corresponding ASCII,
      *      which can be used to "undo" any overzealous iconv action.
      */
-    public static function testEncodingSupportsASCII($encoding, $bypass = false) {
+    public static function testEncodingSupportsASCII($encoding, $bypass = false)
+    {
+        // All calls to iconv here are unsafe, proof by case analysis:
+        // If ICONV_OK, no difference.
+        // If ICONV_TRUNCATE, all calls involve one character inputs,
+        // so bug is not triggered.
+        // If ICONV_UNUSABLE, this call is irrelevant
         static $encodings = array();
         if (!$bypass) {
-            if (isset($encodings[$encoding])) return $encodings[$encoding];
+            if (isset($encodings[$encoding])) {
+                return $encodings[$encoding];
+            }
             $lenc = strtolower($encoding);
             switch ($lenc) {
                 case 'shift_jis':
@@ -395,32 +581,31 @@ class HTMLPurifier_Encoder
                 case 'johab':
                     return array("\xE2\x82\xA9" => '\\');
             }
-            if (strpos($lenc, 'iso-8859-') === 0) return array();
+            if (strpos($lenc, 'iso-8859-') === 0) {
+                return array();
+            }
         }
         $ret = array();
-        set_error_handler(array('HTMLPurifier_Encoder', 'muteErrorHandler'));
-        if (iconv('UTF-8', $encoding, 'a') === false) return false;
+        if (self::unsafeIconv('UTF-8', $encoding, 'a') === false) {
+            return false;
+        }
         for ($i = 0x20; $i <= 0x7E; $i++) { // all printable ASCII chars
             $c = chr($i); // UTF-8 char
-            $r = iconv('UTF-8', "$encoding//IGNORE", $c); // initial conversion
-            if (
-                $r === '' ||
+            $r = self::unsafeIconv('UTF-8', "$encoding//IGNORE", $c); // initial conversion
+            if ($r === '' ||
                 // This line is needed for iconv implementations that do not
                 // omit characters that do not exist in the target character set
-                ($r === $c && iconv($encoding, 'UTF-8//IGNORE', $r) !== $c)
+                ($r === $c && self::unsafeIconv($encoding, 'UTF-8//IGNORE', $r) !== $c)
             ) {
                 // Reverse engineer: what's the UTF-8 equiv of this byte
                 // sequence? This assumes that there's no variable width
                 // encoding that doesn't support ASCII.
-                $ret[iconv($encoding, 'UTF-8//IGNORE', $c)] = $c;
+                $ret[self::unsafeIconv($encoding, 'UTF-8//IGNORE', $c)] = $c;
             }
         }
-        restore_error_handler();
         $encodings[$encoding] = $ret;
         return $ret;
     }
-
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/EntityLookup.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup.php
similarity index 75%
rename from library/HTMLPurifier/EntityLookup.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup.php
index b4dfce94c3..f12ff13a35 100644
--- a/library/HTMLPurifier/EntityLookup.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup.php
@@ -3,20 +3,23 @@
 /**
  * Object that provides entity lookup table from entity name to character
  */
-class HTMLPurifier_EntityLookup {
-
+class HTMLPurifier_EntityLookup
+{
     /**
      * Assoc array of entity name to character represented.
+     * @type array
      */
     public $table;
 
     /**
      * Sets up the entity lookup table from the serialized file contents.
+     * @param bool $file
      * @note The serialized contents are versioned, but were generated
      *       using the maintenance script generate_entity_file.php
      * @warning This is not in constructor to help enforce the Singleton
      */
-    public function setup($file = false) {
+    public function setup($file = false)
+    {
         if (!$file) {
             $file = HTMLPURIFIER_PREFIX . '/HTMLPurifier/EntityLookup/entities.ser';
         }
@@ -25,9 +28,11 @@ class HTMLPurifier_EntityLookup {
 
     /**
      * Retrieves sole instance of the object.
-     * @param Optional prototype of custom lookup table to overload with.
+     * @param bool|HTMLPurifier_EntityLookup $prototype Optional prototype of custom lookup table to overload with.
+     * @return HTMLPurifier_EntityLookup
      */
-    public static function instance($prototype = false) {
+    public static function instance($prototype = false)
+    {
         // no references, since PHP doesn't copy unless modified
         static $instance = null;
         if ($prototype) {
@@ -38,7 +43,6 @@ class HTMLPurifier_EntityLookup {
         }
         return $instance;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup/entities.ser b/library/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup/entities.ser
new file mode 100644
index 0000000000..e8b08128be
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/EntityLookup/entities.ser
@@ -0,0 +1 @@
+a:253:{s:4:"fnof";s:2:"ƒ";s:5:"Alpha";s:2:"Α";s:4:"Beta";s:2:"Β";s:5:"Gamma";s:2:"Γ";s:5:"Delta";s:2:"Δ";s:7:"Epsilon";s:2:"Ε";s:4:"Zeta";s:2:"Ζ";s:3:"Eta";s:2:"Η";s:5:"Theta";s:2:"Θ";s:4:"Iota";s:2:"Ι";s:5:"Kappa";s:2:"Κ";s:6:"Lambda";s:2:"Λ";s:2:"Mu";s:2:"Μ";s:2:"Nu";s:2:"Ν";s:2:"Xi";s:2:"Ξ";s:7:"Omicron";s:2:"Ο";s:2:"Pi";s:2:"Π";s:3:"Rho";s:2:"Ρ";s:5:"Sigma";s:2:"Σ";s:3:"Tau";s:2:"Τ";s:7:"Upsilon";s:2:"Υ";s:3:"Phi";s:2:"Φ";s:3:"Chi";s:2:"Χ";s:3:"Psi";s:2:"Ψ";s:5:"Omega";s:2:"Ω";s:5:"alpha";s:2:"α";s:4:"beta";s:2:"β";s:5:"gamma";s:2:"γ";s:5:"delta";s:2:"δ";s:7:"epsilon";s:2:"ε";s:4:"zeta";s:2:"ζ";s:3:"eta";s:2:"η";s:5:"theta";s:2:"θ";s:4:"iota";s:2:"ι";s:5:"kappa";s:2:"κ";s:6:"lambda";s:2:"λ";s:2:"mu";s:2:"μ";s:2:"nu";s:2:"ν";s:2:"xi";s:2:"ξ";s:7:"omicron";s:2:"ο";s:2:"pi";s:2:"π";s:3:"rho";s:2:"ρ";s:6:"sigmaf";s:2:"ς";s:5:"sigma";s:2:"σ";s:3:"tau";s:2:"τ";s:7:"upsilon";s:2:"υ";s:3:"phi";s:2:"φ";s:3:"chi";s:2:"χ";s:3:"psi";s:2:"ψ";s:5:"omega";s:2:"ω";s:8:"thetasym";s:2:"ϑ";s:5:"upsih";s:2:"ϒ";s:3:"piv";s:2:"ϖ";s:4:"bull";s:3:"•";s:6:"hellip";s:3:"…";s:5:"prime";s:3:"′";s:5:"Prime";s:3:"″";s:5:"oline";s:3:"‾";s:5:"frasl";s:3:"⁄";s:6:"weierp";s:3:"℘";s:5:"image";s:3:"ℑ";s:4:"real";s:3:"ℜ";s:5:"trade";s:3:"™";s:7:"alefsym";s:3:"ℵ";s:4:"larr";s:3:"←";s:4:"uarr";s:3:"↑";s:4:"rarr";s:3:"→";s:4:"darr";s:3:"↓";s:4:"harr";s:3:"↔";s:5:"crarr";s:3:"↵";s:4:"lArr";s:3:"⇐";s:4:"uArr";s:3:"⇑";s:4:"rArr";s:3:"⇒";s:4:"dArr";s:3:"⇓";s:4:"hArr";s:3:"⇔";s:6:"forall";s:3:"∀";s:4:"part";s:3:"∂";s:5:"exist";s:3:"∃";s:5:"empty";s:3:"∅";s:5:"nabla";s:3:"∇";s:4:"isin";s:3:"∈";s:5:"notin";s:3:"∉";s:2:"ni";s:3:"∋";s:4:"prod";s:3:"∏";s:3:"sum";s:3:"∑";s:5:"minus";s:3:"−";s:6:"lowast";s:3:"∗";s:5:"radic";s:3:"√";s:4:"prop";s:3:"∝";s:5:"infin";s:3:"∞";s:3:"ang";s:3:"∠";s:3:"and";s:3:"∧";s:2:"or";s:3:"∨";s:3:"cap";s:3:"∩";s:3:"cup";s:3:"∪";s:3:"int";s:3:"∫";s:6:"there4";s:3:"∴";s:3:"sim";s:3:"∼";s:4:"cong";s:3:"≅";s:5:"asymp";s:3:"≈";s:2:"ne";s:3:"≠";s:5:"equiv";s:3:"≡";s:2:"le";s:3:"≤";s:2:"ge";s:3:"≥";s:3:"sub";s:3:"⊂";s:3:"sup";s:3:"⊃";s:4:"nsub";s:3:"⊄";s:4:"sube";s:3:"⊆";s:4:"supe";s:3:"⊇";s:5:"oplus";s:3:"⊕";s:6:"otimes";s:3:"⊗";s:4:"perp";s:3:"⊥";s:4:"sdot";s:3:"⋅";s:5:"lceil";s:3:"⌈";s:5:"rceil";s:3:"⌉";s:6:"lfloor";s:3:"⌊";s:6:"rfloor";s:3:"⌋";s:4:"lang";s:3:"〈";s:4:"rang";s:3:"〉";s:3:"loz";s:3:"◊";s:6:"spades";s:3:"♠";s:5:"clubs";s:3:"♣";s:6:"hearts";s:3:"♥";s:5:"diams";s:3:"♦";s:4:"quot";s:1:""";s:3:"amp";s:1:"&";s:2:"lt";s:1:"<";s:2:"gt";s:1:">";s:4:"apos";s:1:"'";s:5:"OElig";s:2:"Œ";s:5:"oelig";s:2:"œ";s:6:"Scaron";s:2:"Š";s:6:"scaron";s:2:"š";s:4:"Yuml";s:2:"Ÿ";s:4:"circ";s:2:"ˆ";s:5:"tilde";s:2:"˜";s:4:"ensp";s:3:" ";s:4:"emsp";s:3:" ";s:6:"thinsp";s:3:" ";s:4:"zwnj";s:3:"‌";s:3:"zwj";s:3:"‍";s:3:"lrm";s:3:"‎";s:3:"rlm";s:3:"‏";s:5:"ndash";s:3:"–";s:5:"mdash";s:3:"—";s:5:"lsquo";s:3:"‘";s:5:"rsquo";s:3:"’";s:5:"sbquo";s:3:"‚";s:5:"ldquo";s:3:"“";s:5:"rdquo";s:3:"”";s:5:"bdquo";s:3:"„";s:6:"dagger";s:3:"†";s:6:"Dagger";s:3:"‡";s:6:"permil";s:3:"‰";s:6:"lsaquo";s:3:"‹";s:6:"rsaquo";s:3:"›";s:4:"euro";s:3:"€";s:4:"nbsp";s:2:" ";s:5:"iexcl";s:2:"¡";s:4:"cent";s:2:"¢";s:5:"pound";s:2:"£";s:6:"curren";s:2:"¤";s:3:"yen";s:2:"¥";s:6:"brvbar";s:2:"¦";s:4:"sect";s:2:"§";s:3:"uml";s:2:"¨";s:4:"copy";s:2:"©";s:4:"ordf";s:2:"ª";s:5:"laquo";s:2:"«";s:3:"not";s:2:"¬";s:3:"shy";s:2:"­";s:3:"reg";s:2:"®";s:4:"macr";s:2:"¯";s:3:"deg";s:2:"°";s:6:"plusmn";s:2:"±";s:4:"sup2";s:2:"²";s:4:"sup3";s:2:"³";s:5:"acute";s:2:"´";s:5:"micro";s:2:"µ";s:4:"para";s:2:"¶";s:6:"middot";s:2:"·";s:5:"cedil";s:2:"¸";s:4:"sup1";s:2:"¹";s:4:"ordm";s:2:"º";s:5:"raquo";s:2:"»";s:6:"frac14";s:2:"¼";s:6:"frac12";s:2:"½";s:6:"frac34";s:2:"¾";s:6:"iquest";s:2:"¿";s:6:"Agrave";s:2:"À";s:6:"Aacute";s:2:"Á";s:5:"Acirc";s:2:"Â";s:6:"Atilde";s:2:"Ã";s:4:"Auml";s:2:"Ä";s:5:"Aring";s:2:"Å";s:5:"AElig";s:2:"Æ";s:6:"Ccedil";s:2:"Ç";s:6:"Egrave";s:2:"È";s:6:"Eacute";s:2:"É";s:5:"Ecirc";s:2:"Ê";s:4:"Euml";s:2:"Ë";s:6:"Igrave";s:2:"Ì";s:6:"Iacute";s:2:"Í";s:5:"Icirc";s:2:"Î";s:4:"Iuml";s:2:"Ï";s:3:"ETH";s:2:"Ð";s:6:"Ntilde";s:2:"Ñ";s:6:"Ograve";s:2:"Ò";s:6:"Oacute";s:2:"Ó";s:5:"Ocirc";s:2:"Ô";s:6:"Otilde";s:2:"Õ";s:4:"Ouml";s:2:"Ö";s:5:"times";s:2:"×";s:6:"Oslash";s:2:"Ø";s:6:"Ugrave";s:2:"Ù";s:6:"Uacute";s:2:"Ú";s:5:"Ucirc";s:2:"Û";s:4:"Uuml";s:2:"Ü";s:6:"Yacute";s:2:"Ý";s:5:"THORN";s:2:"Þ";s:5:"szlig";s:2:"ß";s:6:"agrave";s:2:"à";s:6:"aacute";s:2:"á";s:5:"acirc";s:2:"â";s:6:"atilde";s:2:"ã";s:4:"auml";s:2:"ä";s:5:"aring";s:2:"å";s:5:"aelig";s:2:"æ";s:6:"ccedil";s:2:"ç";s:6:"egrave";s:2:"è";s:6:"eacute";s:2:"é";s:5:"ecirc";s:2:"ê";s:4:"euml";s:2:"ë";s:6:"igrave";s:2:"ì";s:6:"iacute";s:2:"í";s:5:"icirc";s:2:"î";s:4:"iuml";s:2:"ï";s:3:"eth";s:2:"ð";s:6:"ntilde";s:2:"ñ";s:6:"ograve";s:2:"ò";s:6:"oacute";s:2:"ó";s:5:"ocirc";s:2:"ô";s:6:"otilde";s:2:"õ";s:4:"ouml";s:2:"ö";s:6:"divide";s:2:"÷";s:6:"oslash";s:2:"ø";s:6:"ugrave";s:2:"ù";s:6:"uacute";s:2:"ú";s:5:"ucirc";s:2:"û";s:4:"uuml";s:2:"ü";s:6:"yacute";s:2:"ý";s:5:"thorn";s:2:"þ";s:4:"yuml";s:2:"ÿ";}
\ No newline at end of file
diff --git a/library/HTMLPurifier/EntityParser.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php
similarity index 75%
rename from library/HTMLPurifier/EntityParser.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php
index 8c384472dc..61529dcd9d 100644
--- a/library/HTMLPurifier/EntityParser.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/EntityParser.php
@@ -12,19 +12,21 @@ class HTMLPurifier_EntityParser
 
     /**
      * Reference to entity lookup table.
+     * @type HTMLPurifier_EntityLookup
      */
     protected $_entity_lookup;
 
     /**
      * Callback regex string for parsing entities.
+     * @type string
      */
     protected $_substituteEntitiesRegex =
-'/&(?:[#]x([a-fA-F0-9]+)|[#]0*(\d+)|([A-Za-z_:][A-Za-z0-9.\-_:]*));?/';
-//     1. hex             2. dec      3. string (XML style)
-
+        '/&(?:[#]x([a-fA-F0-9]+)|[#]0*(\d+)|([A-Za-z_:][A-Za-z0-9.\-_:]*));?/';
+        //     1. hex             2. dec      3. string (XML style)
 
     /**
      * Decimal to parsed string conversion table for special entities.
+     * @type array
      */
     protected $_special_dec2str =
             array(
@@ -37,6 +39,7 @@ class HTMLPurifier_EntityParser
 
     /**
      * Stripped entity names to decimal conversion table for special entities.
+     * @type array
      */
     protected $_special_ent2dec =
             array(
@@ -51,41 +54,45 @@ class HTMLPurifier_EntityParser
      * running this whenever you have parsed character is t3h 5uck, we run
      * it before everything else.
      *
-     * @param $string String to have non-special entities parsed.
-     * @returns Parsed string.
+     * @param string $string String to have non-special entities parsed.
+     * @return string Parsed string.
      */
-    public function substituteNonSpecialEntities($string) {
+    public function substituteNonSpecialEntities($string)
+    {
         // it will try to detect missing semicolons, but don't rely on it
         return preg_replace_callback(
             $this->_substituteEntitiesRegex,
             array($this, 'nonSpecialEntityCallback'),
             $string
-            );
+        );
     }
 
     /**
      * Callback function for substituteNonSpecialEntities() that does the work.
      *
-     * @param $matches  PCRE matches array, with 0 the entire match, and
+     * @param array $matches  PCRE matches array, with 0 the entire match, and
      *                  either index 1, 2 or 3 set with a hex value, dec value,
      *                  or string (respectively).
-     * @returns Replacement string.
+     * @return string Replacement string.
      */
 
-    protected function nonSpecialEntityCallback($matches) {
+    protected function nonSpecialEntityCallback($matches)
+    {
         // replaces all but big five
         $entity = $matches[0];
         $is_num = (@$matches[0][1] === '#');
         if ($is_num) {
             $is_hex = (@$entity[2] === 'x');
             $code = $is_hex ? hexdec($matches[1]) : (int) $matches[2];
-
             // abort for special characters
-            if (isset($this->_special_dec2str[$code]))  return $entity;
-
+            if (isset($this->_special_dec2str[$code])) {
+                return $entity;
+            }
             return HTMLPurifier_Encoder::unichr($code);
         } else {
-            if (isset($this->_special_ent2dec[$matches[3]])) return $entity;
+            if (isset($this->_special_ent2dec[$matches[3]])) {
+                return $entity;
+            }
             if (!$this->_entity_lookup) {
                 $this->_entity_lookup = HTMLPurifier_EntityLookup::instance();
             }
@@ -103,14 +110,16 @@ class HTMLPurifier_EntityParser
      * @notice We try to avoid calling this function because otherwise, it
      * would have to be called a lot (for every parsed section).
      *
-     * @param $string String to have non-special entities parsed.
-     * @returns Parsed string.
+     * @param string $string String to have non-special entities parsed.
+     * @return string Parsed string.
      */
-    public function substituteSpecialEntities($string) {
+    public function substituteSpecialEntities($string)
+    {
         return preg_replace_callback(
             $this->_substituteEntitiesRegex,
             array($this, 'specialEntityCallback'),
-            $string);
+            $string
+        );
     }
 
     /**
@@ -118,12 +127,13 @@ class HTMLPurifier_EntityParser
      *
      * This callback has same syntax as nonSpecialEntityCallback().
      *
-     * @param $matches  PCRE-style matches array, with 0 the entire match, and
+     * @param array $matches  PCRE-style matches array, with 0 the entire match, and
      *                  either index 1, 2 or 3 set with a hex value, dec value,
      *                  or string (respectively).
-     * @returns Replacement string.
+     * @return string Replacement string.
      */
-    protected function specialEntityCallback($matches) {
+    protected function specialEntityCallback($matches)
+    {
         $entity = $matches[0];
         $is_num = (@$matches[0][1] === '#');
         if ($is_num) {
@@ -138,7 +148,6 @@ class HTMLPurifier_EntityParser
                 $entity;
         }
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ErrorCollector.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ErrorCollector.php
similarity index 82%
rename from library/HTMLPurifier/ErrorCollector.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ErrorCollector.php
index 6713eaf773..d47e3f2e24 100644
--- a/library/HTMLPurifier/ErrorCollector.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ErrorCollector.php
@@ -16,16 +16,46 @@ class HTMLPurifier_ErrorCollector
     const MESSAGE  = 2;
     const CHILDREN = 3;
 
+    /**
+     * @type array
+     */
     protected $errors;
+
+    /**
+     * @type array
+     */
     protected $_current;
+
+    /**
+     * @type array
+     */
     protected $_stacks = array(array());
+
+    /**
+     * @type HTMLPurifier_Language
+     */
     protected $locale;
+
+    /**
+     * @type HTMLPurifier_Generator
+     */
     protected $generator;
+
+    /**
+     * @type HTMLPurifier_Context
+     */
     protected $context;
 
+    /**
+     * @type array
+     */
     protected $lines = array();
 
-    public function __construct($context) {
+    /**
+     * @param HTMLPurifier_Context $context
+     */
+    public function __construct($context)
+    {
         $this->locale    =& $context->get('Locale');
         $this->context   = $context;
         $this->_current  =& $this->_stacks[0];
@@ -34,13 +64,11 @@ class HTMLPurifier_ErrorCollector
 
     /**
      * Sends an error message to the collector for later use
-     * @param $severity int Error severity, PHP error style (don't use E_USER_)
-     * @param $msg string Error message text
-     * @param $subst1 string First substitution for $msg
-     * @param $subst2 string ...
+     * @param int $severity Error severity, PHP error style (don't use E_USER_)
+     * @param string $msg Error message text
      */
-    public function send($severity, $msg) {
-
+    public function send($severity, $msg)
+    {
         $args = array();
         if (func_num_args() > 2) {
             $args = func_get_args();
@@ -50,7 +78,7 @@ class HTMLPurifier_ErrorCollector
 
         $token = $this->context->get('CurrentToken', true);
         $line  = $token ? $token->line : $this->context->get('CurrentLine', true);
-        $col   = $token ? $token->col  : $this->context->get('CurrentCol',  true);
+        $col   = $token ? $token->col  : $this->context->get('CurrentCol', true);
         $attr  = $this->context->get('CurrentAttr', true);
 
         // perform special substitutions, also add custom parameters
@@ -60,7 +88,9 @@ class HTMLPurifier_ErrorCollector
         }
         if (!is_null($attr)) {
             $subst['$CurrentAttr.Name'] = $attr;
-            if (isset($token->attr[$attr])) $subst['$CurrentAttr.Value'] = $token->attr[$attr];
+            if (isset($token->attr[$attr])) {
+                $subst['$CurrentAttr.Value'] = $token->attr[$attr];
+            }
         }
 
         if (empty($args)) {
@@ -69,7 +99,9 @@ class HTMLPurifier_ErrorCollector
             $msg = $this->locale->formatMessage($msg, $args);
         }
 
-        if (!empty($subst)) $msg = strtr($msg, $subst);
+        if (!empty($subst)) {
+            $msg = strtr($msg, $subst);
+        }
 
         // (numerically indexed)
         $error = array(
@@ -80,16 +112,15 @@ class HTMLPurifier_ErrorCollector
         );
         $this->_current[] = $error;
 
-
         // NEW CODE BELOW ...
-
-        $struct = null;
         // Top-level errors are either:
         //  TOKEN type, if $value is set appropriately, or
         //  "syntax" type, if $value is null
         $new_struct = new HTMLPurifier_ErrorStruct();
         $new_struct->type = HTMLPurifier_ErrorStruct::TOKEN;
-        if ($token) $new_struct->value = clone $token;
+        if ($token) {
+            $new_struct->value = clone $token;
+        }
         if (is_int($line) && is_int($col)) {
             if (isset($this->lines[$line][$col])) {
                 $struct = $this->lines[$line][$col];
@@ -128,30 +159,34 @@ class HTMLPurifier_ErrorCollector
 
     /**
      * Retrieves raw error data for custom formatter to use
-     * @param List of arrays in format of array(line of error,
-     *        error severity, error message,
-     *        recursive sub-errors array)
      */
-    public function getRaw() {
+    public function getRaw()
+    {
         return $this->errors;
     }
 
     /**
      * Default HTML formatting implementation for error messages
-     * @param $config Configuration array, vital for HTML output nature
-     * @param $errors Errors array to display; used for recursion.
+     * @param HTMLPurifier_Config $config Configuration, vital for HTML output nature
+     * @param array $errors Errors array to display; used for recursion.
+     * @return string
      */
-    public function getHTMLFormatted($config, $errors = null) {
+    public function getHTMLFormatted($config, $errors = null)
+    {
         $ret = array();
 
         $this->generator = new HTMLPurifier_Generator($config, $this->context);
-        if ($errors === null) $errors = $this->errors;
+        if ($errors === null) {
+            $errors = $this->errors;
+        }
 
         // 'At line' message needs to be removed
 
         // generation code for new structure goes here. It needs to be recursive.
         foreach ($this->lines as $line => $col_array) {
-            if ($line == -1) continue;
+            if ($line == -1) {
+                continue;
+            }
             foreach ($col_array as $col => $struct) {
                 $this->_renderStruct($ret, $struct, $line, $col);
             }
@@ -168,7 +203,8 @@ class HTMLPurifier_ErrorCollector
 
     }
 
-    private function _renderStruct(&$ret, $struct, $line = null, $col = null) {
+    private function _renderStruct(&$ret, $struct, $line = null, $col = null)
+    {
         $stack = array($struct);
         $context_stack = array(array());
         while ($current = array_pop($stack)) {
@@ -194,7 +230,7 @@ class HTMLPurifier_ErrorCollector
                 //$string .= '</pre>';
                 $ret[] = $string;
             }
-            foreach ($current->children as $type => $array) {
+            foreach ($current->children as $array) {
                 $context[] = $current;
                 $stack = array_merge($stack, array_reverse($array, true));
                 for ($i = count($array); $i > 0; $i--) {
@@ -203,7 +239,6 @@ class HTMLPurifier_ErrorCollector
             }
         }
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/ErrorStruct.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/ErrorStruct.php
similarity index 81%
rename from library/HTMLPurifier/ErrorStruct.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/ErrorStruct.php
index 9bc8996ec1..cf869d3212 100644
--- a/library/HTMLPurifier/ErrorStruct.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/ErrorStruct.php
@@ -19,6 +19,7 @@ class HTMLPurifier_ErrorStruct
 
     /**
      * Type of this struct.
+     * @type string
      */
     public $type;
 
@@ -28,11 +29,13 @@ class HTMLPurifier_ErrorStruct
      *  - TOKEN: Instance of HTMLPurifier_Token
      *  - ATTR: array('attr-name', 'value')
      *  - CSSPROP: array('prop-name', 'value')
+     * @type mixed
      */
     public $value;
 
     /**
      * Errors registered for this structure.
+     * @type array
      */
     public $errors = array();
 
@@ -40,10 +43,17 @@ class HTMLPurifier_ErrorStruct
      * Child ErrorStructs that are from this structure. For example, a TOKEN
      * ErrorStruct would contain ATTR ErrorStructs. This is a multi-dimensional
      * array in structure: [TYPE]['identifier']
+     * @type array
      */
     public $children = array();
 
-    public function getChild($type, $id) {
+    /**
+     * @param string $type
+     * @param string $id
+     * @return mixed
+     */
+    public function getChild($type, $id)
+    {
         if (!isset($this->children[$type][$id])) {
             $this->children[$type][$id] = new HTMLPurifier_ErrorStruct();
             $this->children[$type][$id]->type = $type;
@@ -51,10 +61,14 @@ class HTMLPurifier_ErrorStruct
         return $this->children[$type][$id];
     }
 
-    public function addError($severity, $message) {
+    /**
+     * @param int $severity
+     * @param string $message
+     */
+    public function addError($severity, $message)
+    {
         $this->errors[] = array($severity, $message);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Exception.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Exception.php
similarity index 100%
rename from library/HTMLPurifier/Exception.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Exception.php
diff --git a/library/HTMLPurifier/Filter.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Filter.php
similarity index 71%
rename from library/HTMLPurifier/Filter.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Filter.php
index 9a0e7b09f3..c1f41ee162 100644
--- a/library/HTMLPurifier/Filter.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Filter.php
@@ -23,24 +23,34 @@ class HTMLPurifier_Filter
 {
 
     /**
-     * Name of the filter for identification purposes
+     * Name of the filter for identification purposes.
+     * @type string
      */
     public $name;
 
     /**
      * Pre-processor function, handles HTML before HTML Purifier
+     * @param string $html
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
      */
-    public function preFilter($html, $config, $context) {
+    public function preFilter($html, $config, $context)
+    {
         return $html;
     }
 
     /**
      * Post-processor function, handles HTML after HTML Purifier
+     * @param string $html
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
      */
-    public function postFilter($html, $config, $context) {
+    public function postFilter($html, $config, $context)
+    {
         return $html;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php
new file mode 100644
index 0000000000..08e62c16bf
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Filter/ExtractStyleBlocks.php
@@ -0,0 +1,338 @@
+<?php
+
+// why is this a top level function? Because PHP 5.2.0 doesn't seem to
+// understand how to interpret this filter if it's a static method.
+// It's all really silly, but if we go this route it might be reasonable
+// to coalesce all of these methods into one.
+function htmlpurifier_filter_extractstyleblocks_muteerrorhandler()
+{
+}
+
+/**
+ * This filter extracts <style> blocks from input HTML, cleans them up
+ * using CSSTidy, and then places them in $purifier->context->get('StyleBlocks')
+ * so they can be used elsewhere in the document.
+ *
+ * @note
+ *      See tests/HTMLPurifier/Filter/ExtractStyleBlocksTest.php for
+ *      sample usage.
+ *
+ * @note
+ *      This filter can also be used on stylesheets not included in the
+ *      document--something purists would probably prefer. Just directly
+ *      call HTMLPurifier_Filter_ExtractStyleBlocks->cleanCSS()
+ */
+class HTMLPurifier_Filter_ExtractStyleBlocks extends HTMLPurifier_Filter
+{
+    /**
+     * @type string
+     */
+    public $name = 'ExtractStyleBlocks';
+
+    /**
+     * @type array
+     */
+    private $_styleMatches = array();
+
+    /**
+     * @type csstidy
+     */
+    private $_tidy;
+
+    /**
+     * @type HTMLPurifier_AttrDef_HTML_ID
+     */
+    private $_id_attrdef;
+
+    /**
+     * @type HTMLPurifier_AttrDef_CSS_Ident
+     */
+    private $_class_attrdef;
+
+    /**
+     * @type HTMLPurifier_AttrDef_Enum
+     */
+    private $_enum_attrdef;
+
+    public function __construct()
+    {
+        $this->_tidy = new csstidy();
+        $this->_tidy->set_cfg('lowercase_s', false);
+        $this->_id_attrdef = new HTMLPurifier_AttrDef_HTML_ID(true);
+        $this->_class_attrdef = new HTMLPurifier_AttrDef_CSS_Ident();
+        $this->_enum_attrdef = new HTMLPurifier_AttrDef_Enum(
+            array(
+                'first-child',
+                'link',
+                'visited',
+                'active',
+                'hover',
+                'focus'
+            )
+        );
+    }
+
+    /**
+     * Save the contents of CSS blocks to style matches
+     * @param array $matches preg_replace style $matches array
+     */
+    protected function styleCallback($matches)
+    {
+        $this->_styleMatches[] = $matches[1];
+    }
+
+    /**
+     * Removes inline <style> tags from HTML, saves them for later use
+     * @param string $html
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
+     * @todo Extend to indicate non-text/css style blocks
+     */
+    public function preFilter($html, $config, $context)
+    {
+        $tidy = $config->get('Filter.ExtractStyleBlocks.TidyImpl');
+        if ($tidy !== null) {
+            $this->_tidy = $tidy;
+        }
+        $html = preg_replace_callback('#<style(?:\s.*)?>(.+)</style>#isU', array($this, 'styleCallback'), $html);
+        $style_blocks = $this->_styleMatches;
+        $this->_styleMatches = array(); // reset
+        $context->register('StyleBlocks', $style_blocks); // $context must not be reused
+        if ($this->_tidy) {
+            foreach ($style_blocks as &$style) {
+                $style = $this->cleanCSS($style, $config, $context);
+            }
+        }
+        return $html;
+    }
+
+    /**
+     * Takes CSS (the stuff found in <style>) and cleans it.
+     * @warning Requires CSSTidy <http://csstidy.sourceforge.net/>
+     * @param string $css CSS styling to clean
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @throws HTMLPurifier_Exception
+     * @return string Cleaned CSS
+     */
+    public function cleanCSS($css, $config, $context)
+    {
+        // prepare scope
+        $scope = $config->get('Filter.ExtractStyleBlocks.Scope');
+        if ($scope !== null) {
+            $scopes = array_map('trim', explode(',', $scope));
+        } else {
+            $scopes = array();
+        }
+        // remove comments from CSS
+        $css = trim($css);
+        if (strncmp('<!--', $css, 4) === 0) {
+            $css = substr($css, 4);
+        }
+        if (strlen($css) > 3 && substr($css, -3) == '-->') {
+            $css = substr($css, 0, -3);
+        }
+        $css = trim($css);
+        set_error_handler('htmlpurifier_filter_extractstyleblocks_muteerrorhandler');
+        $this->_tidy->parse($css);
+        restore_error_handler();
+        $css_definition = $config->getDefinition('CSS');
+        $html_definition = $config->getDefinition('HTML');
+        $new_css = array();
+        foreach ($this->_tidy->css as $k => $decls) {
+            // $decls are all CSS declarations inside an @ selector
+            $new_decls = array();
+            foreach ($decls as $selector => $style) {
+                $selector = trim($selector);
+                if ($selector === '') {
+                    continue;
+                } // should not happen
+                // Parse the selector
+                // Here is the relevant part of the CSS grammar:
+                //
+                // ruleset
+                //   : selector [ ',' S* selector ]* '{' ...
+                // selector
+                //   : simple_selector [ combinator selector | S+ [ combinator? selector ]? ]?
+                // combinator
+                //   : '+' S*
+                //   : '>' S*
+                // simple_selector
+                //   : element_name [ HASH | class | attrib | pseudo ]*
+                //   | [ HASH | class | attrib | pseudo ]+
+                // element_name
+                //   : IDENT | '*'
+                //   ;
+                // class
+                //   : '.' IDENT
+                //   ;
+                // attrib
+                //   : '[' S* IDENT S* [ [ '=' | INCLUDES | DASHMATCH ] S*
+                //     [ IDENT | STRING ] S* ]? ']'
+                //   ;
+                // pseudo
+                //   : ':' [ IDENT | FUNCTION S* [IDENT S*]? ')' ]
+                //   ;
+                //
+                // For reference, here are the relevant tokens:
+                //
+                // HASH         #{name}
+                // IDENT        {ident}
+                // INCLUDES     ==
+                // DASHMATCH    |=
+                // STRING       {string}
+                // FUNCTION     {ident}\(
+                //
+                // And the lexical scanner tokens
+                //
+                // name         {nmchar}+
+                // nmchar       [_a-z0-9-]|{nonascii}|{escape}
+                // nonascii     [\240-\377]
+                // escape       {unicode}|\\[^\r\n\f0-9a-f]
+                // unicode      \\{h}}{1,6}(\r\n|[ \t\r\n\f])?
+                // ident        -?{nmstart}{nmchar*}
+                // nmstart      [_a-z]|{nonascii}|{escape}
+                // string       {string1}|{string2}
+                // string1      \"([^\n\r\f\\"]|\\{nl}|{escape})*\"
+                // string2      \'([^\n\r\f\\"]|\\{nl}|{escape})*\'
+                //
+                // We'll implement a subset (in order to reduce attack
+                // surface); in particular:
+                //
+                //      - No Unicode support
+                //      - No escapes support
+                //      - No string support (by proxy no attrib support)
+                //      - element_name is matched against allowed
+                //        elements (some people might find this
+                //        annoying...)
+                //      - Pseudo-elements one of :first-child, :link,
+                //        :visited, :active, :hover, :focus
+
+                // handle ruleset
+                $selectors = array_map('trim', explode(',', $selector));
+                $new_selectors = array();
+                foreach ($selectors as $sel) {
+                    // split on +, > and spaces
+                    $basic_selectors = preg_split('/\s*([+> ])\s*/', $sel, -1, PREG_SPLIT_DELIM_CAPTURE);
+                    // even indices are chunks, odd indices are
+                    // delimiters
+                    $nsel = null;
+                    $delim = null; // guaranteed to be non-null after
+                    // two loop iterations
+                    for ($i = 0, $c = count($basic_selectors); $i < $c; $i++) {
+                        $x = $basic_selectors[$i];
+                        if ($i % 2) {
+                            // delimiter
+                            if ($x === ' ') {
+                                $delim = ' ';
+                            } else {
+                                $delim = ' ' . $x . ' ';
+                            }
+                        } else {
+                            // simple selector
+                            $components = preg_split('/([#.:])/', $x, -1, PREG_SPLIT_DELIM_CAPTURE);
+                            $sdelim = null;
+                            $nx = null;
+                            for ($j = 0, $cc = count($components); $j < $cc; $j++) {
+                                $y = $components[$j];
+                                if ($j === 0) {
+                                    if ($y === '*' || isset($html_definition->info[$y = strtolower($y)])) {
+                                        $nx = $y;
+                                    } else {
+                                        // $nx stays null; this matters
+                                        // if we don't manage to find
+                                        // any valid selector content,
+                                        // in which case we ignore the
+                                        // outer $delim
+                                    }
+                                } elseif ($j % 2) {
+                                    // set delimiter
+                                    $sdelim = $y;
+                                } else {
+                                    $attrdef = null;
+                                    if ($sdelim === '#') {
+                                        $attrdef = $this->_id_attrdef;
+                                    } elseif ($sdelim === '.') {
+                                        $attrdef = $this->_class_attrdef;
+                                    } elseif ($sdelim === ':') {
+                                        $attrdef = $this->_enum_attrdef;
+                                    } else {
+                                        throw new HTMLPurifier_Exception('broken invariant sdelim and preg_split');
+                                    }
+                                    $r = $attrdef->validate($y, $config, $context);
+                                    if ($r !== false) {
+                                        if ($r !== true) {
+                                            $y = $r;
+                                        }
+                                        if ($nx === null) {
+                                            $nx = '';
+                                        }
+                                        $nx .= $sdelim . $y;
+                                    }
+                                }
+                            }
+                            if ($nx !== null) {
+                                if ($nsel === null) {
+                                    $nsel = $nx;
+                                } else {
+                                    $nsel .= $delim . $nx;
+                                }
+                            } else {
+                                // delimiters to the left of invalid
+                                // basic selector ignored
+                            }
+                        }
+                    }
+                    if ($nsel !== null) {
+                        if (!empty($scopes)) {
+                            foreach ($scopes as $s) {
+                                $new_selectors[] = "$s $nsel";
+                            }
+                        } else {
+                            $new_selectors[] = $nsel;
+                        }
+                    }
+                }
+                if (empty($new_selectors)) {
+                    continue;
+                }
+                $selector = implode(', ', $new_selectors);
+                foreach ($style as $name => $value) {
+                    if (!isset($css_definition->info[$name])) {
+                        unset($style[$name]);
+                        continue;
+                    }
+                    $def = $css_definition->info[$name];
+                    $ret = $def->validate($value, $config, $context);
+                    if ($ret === false) {
+                        unset($style[$name]);
+                    } else {
+                        $style[$name] = $ret;
+                    }
+                }
+                $new_decls[$selector] = $style;
+            }
+            $new_css[$k] = $new_decls;
+        }
+        // remove stuff that shouldn't be used, could be reenabled
+        // after security risks are analyzed
+        $this->_tidy->css = $new_css;
+        $this->_tidy->import = array();
+        $this->_tidy->charset = null;
+        $this->_tidy->namespace = null;
+        $css = $this->_tidy->print->plain();
+        // we are going to escape any special characters <>& to ensure
+        // that no funny business occurs (i.e. </style> in a font-family prop).
+        if ($config->get('Filter.ExtractStyleBlocks.Escaping')) {
+            $css = str_replace(
+                array('<', '>', '&'),
+                array('\3C ', '\3E ', '\26 '),
+                $css
+            );
+        }
+        return $css;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php
new file mode 100644
index 0000000000..276d8362fa
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Filter/YouTube.php
@@ -0,0 +1,65 @@
+<?php
+
+class HTMLPurifier_Filter_YouTube extends HTMLPurifier_Filter
+{
+
+    /**
+     * @type string
+     */
+    public $name = 'YouTube';
+
+    /**
+     * @param string $html
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
+     */
+    public function preFilter($html, $config, $context)
+    {
+        $pre_regex = '#<object[^>]+>.+?' .
+            '(?:http:)?//www.youtube.com/((?:v|cp)/[A-Za-z0-9\-_=]+).+?</object>#s';
+        $pre_replace = '<span class="youtube-embed">\1</span>';
+        return preg_replace($pre_regex, $pre_replace, $html);
+    }
+
+    /**
+     * @param string $html
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
+     */
+    public function postFilter($html, $config, $context)
+    {
+        $post_regex = '#<span class="youtube-embed">((?:v|cp)/[A-Za-z0-9\-_=]+)</span>#';
+        return preg_replace_callback($post_regex, array($this, 'postFilterCallback'), $html);
+    }
+
+    /**
+     * @param $url
+     * @return string
+     */
+    protected function armorUrl($url)
+    {
+        return str_replace('--', '-&#45;', $url);
+    }
+
+    /**
+     * @param array $matches
+     * @return string
+     */
+    protected function postFilterCallback($matches)
+    {
+        $url = $this->armorUrl($matches[1]);
+        return '<object width="425" height="350" type="application/x-shockwave-flash" ' .
+        'data="//www.youtube.com/' . $url . '">' .
+        '<param name="movie" value="//www.youtube.com/' . $url . '"></param>' .
+        '<!--[if IE]>' .
+        '<embed src="//www.youtube.com/' . $url . '"' .
+        'type="application/x-shockwave-flash"' .
+        'wmode="transparent" width="425" height="350" />' .
+        '<![endif]-->' .
+        '</object>';
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Generator.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Generator.php
similarity index 56%
rename from library/HTMLPurifier/Generator.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Generator.php
index 4a62417271..6fb5687146 100644
--- a/library/HTMLPurifier/Generator.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Generator.php
@@ -11,49 +11,64 @@ class HTMLPurifier_Generator
 {
 
     /**
-     * Whether or not generator should produce XML output
+     * Whether or not generator should produce XML output.
+     * @type bool
      */
     private $_xhtml = true;
 
     /**
-     * :HACK: Whether or not generator should comment the insides of <script> tags
+     * :HACK: Whether or not generator should comment the insides of <script> tags.
+     * @type bool
      */
     private $_scriptFix = false;
 
     /**
      * Cache of HTMLDefinition during HTML output to determine whether or
      * not attributes should be minimized.
+     * @type HTMLPurifier_HTMLDefinition
      */
     private $_def;
 
     /**
-     * Cache of %Output.SortAttr
+     * Cache of %Output.SortAttr.
+     * @type bool
      */
     private $_sortAttr;
 
     /**
-     * Cache of %Output.FlashCompat
+     * Cache of %Output.FlashCompat.
+     * @type bool
      */
     private $_flashCompat;
 
+    /**
+     * Cache of %Output.FixInnerHTML.
+     * @type bool
+     */
+    private $_innerHTMLFix;
+
     /**
      * Stack for keeping track of object information when outputting IE
      * compatibility code.
+     * @type array
      */
     private $_flashStack = array();
 
     /**
      * Configuration for the generator
+     * @type HTMLPurifier_Config
      */
     protected $config;
 
     /**
-     * @param $config Instance of HTMLPurifier_Config
-     * @param $context Instance of HTMLPurifier_Context
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
      */
-    public function __construct($config, $context) {
+    public function __construct($config, $context)
+    {
         $this->config = $config;
         $this->_scriptFix = $config->get('Output.CommentScriptContents');
+        $this->_innerHTMLFix = $config->get('Output.FixInnerHTML');
         $this->_sortAttr = $config->get('Output.SortAttr');
         $this->_flashCompat = $config->get('Output.FlashCompat');
         $this->_def = $config->getHTMLDefinition();
@@ -62,12 +77,14 @@ class HTMLPurifier_Generator
 
     /**
      * Generates HTML from an array of tokens.
-     * @param $tokens Array of HTMLPurifier_Token
-     * @param $config HTMLPurifier_Config object
-     * @return Generated HTML
+     * @param HTMLPurifier_Token[] $tokens Array of HTMLPurifier_Token
+     * @return string Generated HTML
      */
-    public function generateFromTokens($tokens) {
-        if (!$tokens) return '';
+    public function generateFromTokens($tokens)
+    {
+        if (!$tokens) {
+            return '';
+        }
 
         // Basic algorithm
         $html = '';
@@ -86,30 +103,41 @@ class HTMLPurifier_Generator
         // Tidy cleanup
         if (extension_loaded('tidy') && $this->config->get('Output.TidyFormat')) {
             $tidy = new Tidy;
-            $tidy->parseString($html, array(
-               'indent'=> true,
-               'output-xhtml' => $this->_xhtml,
-               'show-body-only' => true,
-               'indent-spaces' => 2,
-               'wrap' => 68,
-            ), 'utf8');
+            $tidy->parseString(
+                $html,
+                array(
+                   'indent'=> true,
+                   'output-xhtml' => $this->_xhtml,
+                   'show-body-only' => true,
+                   'indent-spaces' => 2,
+                   'wrap' => 68,
+                ),
+                'utf8'
+            );
             $tidy->cleanRepair();
             $html = (string) $tidy; // explicit cast necessary
         }
 
         // Normalize newlines to system defined value
-        $nl = $this->config->get('Output.Newline');
-        if ($nl === null) $nl = PHP_EOL;
-        if ($nl !== "\n") $html = str_replace("\n", $nl, $html);
+        if ($this->config->get('Core.NormalizeNewlines')) {
+            $nl = $this->config->get('Output.Newline');
+            if ($nl === null) {
+                $nl = PHP_EOL;
+            }
+            if ($nl !== "\n") {
+                $html = str_replace("\n", $nl, $html);
+            }
+        }
         return $html;
     }
 
     /**
      * Generates HTML from a single token.
-     * @param $token HTMLPurifier_Token object.
-     * @return Generated HTML
+     * @param HTMLPurifier_Token $token HTMLPurifier_Token object.
+     * @return string Generated HTML
      */
-    public function generateFromToken($token) {
+    public function generateFromToken($token)
+    {
         if (!$token instanceof HTMLPurifier_Token) {
             trigger_error('Cannot generate HTML from non-HTMLPurifier_Token object', E_USER_WARNING);
             return '';
@@ -130,19 +158,7 @@ class HTMLPurifier_Generator
             $_extra = '';
             if ($this->_flashCompat) {
                 if ($token->name == "object" && !empty($this->_flashStack)) {
-                    $flash = array_pop($this->_flashStack);
-                    $compat_token = new HTMLPurifier_Token_Empty("embed");
-                    foreach ($flash->attr as $name => $val) {
-                        if ($name == "classid") continue;
-                        if ($name == "type") continue;
-                        if ($name == "data") $name = "src";
-                        $compat_token->attr[$name] = $val;
-                    }
-                    foreach ($flash->param as $name => $val) {
-                        if ($name == "movie") $name = "src";
-                        $compat_token->attr[$name] = $val;
-                    }
-                    $_extra = "<!--[if IE]>".$this->generateFromToken($compat_token)."<![endif]-->";
+                    // doesn't do anything for now
                 }
             }
             return $_extra . '</' . $token->name . '>';
@@ -169,11 +185,16 @@ class HTMLPurifier_Generator
 
     /**
      * Special case processor for the contents of script tags
+     * @param HTMLPurifier_Token $token HTMLPurifier_Token object.
+     * @return string
      * @warning This runs into problems if there's already a literal
      *          --> somewhere inside the script contents.
      */
-    public function generateScriptFromToken($token) {
-        if (!$token instanceof HTMLPurifier_Token_Text) return $this->generateFromToken($token);
+    public function generateScriptFromToken($token)
+    {
+        if (!$token instanceof HTMLPurifier_Token_Text) {
+            return $this->generateFromToken($token);
+        }
         // Thanks <http://lachy.id.au/log/2005/05/script-comments>
         $data = preg_replace('#//\s*$#', '', $token->data);
         return '<!--//--><![CDATA[//><!--' . "\n" . trim($data) . "\n" . '//--><!]]>';
@@ -182,24 +203,60 @@ class HTMLPurifier_Generator
     /**
      * Generates attribute declarations from attribute array.
      * @note This does not include the leading or trailing space.
-     * @param $assoc_array_of_attributes Attribute array
-     * @param $element Name of element attributes are for, used to check
+     * @param array $assoc_array_of_attributes Attribute array
+     * @param string $element Name of element attributes are for, used to check
      *        attribute minimization.
-     * @return Generate HTML fragment for insertion.
+     * @return string Generated HTML fragment for insertion.
      */
-    public function generateAttributes($assoc_array_of_attributes, $element = false) {
+    public function generateAttributes($assoc_array_of_attributes, $element = '')
+    {
         $html = '';
-        if ($this->_sortAttr) ksort($assoc_array_of_attributes);
+        if ($this->_sortAttr) {
+            ksort($assoc_array_of_attributes);
+        }
         foreach ($assoc_array_of_attributes as $key => $value) {
             if (!$this->_xhtml) {
                 // Remove namespaced attributes
-                if (strpos($key, ':') !== false) continue;
+                if (strpos($key, ':') !== false) {
+                    continue;
+                }
                 // Check if we should minimize the attribute: val="val" -> val
                 if ($element && !empty($this->_def->info[$element]->attr[$key]->minimized)) {
                     $html .= $key . ' ';
                     continue;
                 }
             }
+            // Workaround for Internet Explorer innerHTML bug.
+            // Essentially, Internet Explorer, when calculating
+            // innerHTML, omits quotes if there are no instances of
+            // angled brackets, quotes or spaces.  However, when parsing
+            // HTML (for example, when you assign to innerHTML), it
+            // treats backticks as quotes.  Thus,
+            //      <img alt="``" />
+            // becomes
+            //      <img alt=`` />
+            // becomes
+            //      <img alt='' />
+            // Fortunately, all we need to do is trigger an appropriate
+            // quoting style, which we do by adding an extra space.
+            // This also is consistent with the W3C spec, which states
+            // that user agents may ignore leading or trailing
+            // whitespace (in fact, most don't, at least for attributes
+            // like alt, but an extra space at the end is barely
+            // noticeable).  Still, we have a configuration knob for
+            // this, since this transformation is not necesary if you
+            // don't process user input with innerHTML or you don't plan
+            // on supporting Internet Explorer.
+            if ($this->_innerHTMLFix) {
+                if (strpos($value, '`') !== false) {
+                    // check if correct quoting style would not already be
+                    // triggered
+                    if (strcspn($value, '"\' <>') === strlen($value)) {
+                        // protect!
+                        $value .= ' ';
+                    }
+                }
+            }
             $html .= $key.'="'.$this->escape($value).'" ';
         }
         return rtrim($html);
@@ -210,15 +267,20 @@ class HTMLPurifier_Generator
      * @todo This really ought to be protected, but until we have a facility
      *       for properly generating HTML here w/o using tokens, it stays
      *       public.
-     * @param $string String data to escape for HTML.
-     * @param $quote Quoting style, like htmlspecialchars. ENT_NOQUOTES is
+     * @param string $string String data to escape for HTML.
+     * @param int $quote Quoting style, like htmlspecialchars. ENT_NOQUOTES is
      *               permissible for non-attribute output.
-     * @return String escaped data.
+     * @return string escaped data.
      */
-    public function escape($string, $quote = ENT_COMPAT) {
+    public function escape($string, $quote = null)
+    {
+        // Workaround for APC bug on Mac Leopard reported by sidepodcast
+        // http://htmlpurifier.org/phorum/read.php?3,4823,4846
+        if ($quote === null) {
+            $quote = ENT_COMPAT;
+        }
         return htmlspecialchars($string, $quote, 'UTF-8');
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLDefinition.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLDefinition.php
similarity index 70%
rename from library/HTMLPurifier/HTMLDefinition.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLDefinition.php
index c99ac11eb2..9b7b334dd9 100644
--- a/library/HTMLPurifier/HTMLDefinition.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLDefinition.php
@@ -29,60 +29,71 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
     // FULLY-PUBLIC VARIABLES ---------------------------------------------
 
     /**
-     * Associative array of element names to HTMLPurifier_ElementDef
+     * Associative array of element names to HTMLPurifier_ElementDef.
+     * @type HTMLPurifier_ElementDef[]
      */
     public $info = array();
 
     /**
      * Associative array of global attribute name to attribute definition.
+     * @type array
      */
     public $info_global_attr = array();
 
     /**
      * String name of parent element HTML will be going into.
+     * @type string
      */
     public $info_parent = 'div';
 
     /**
      * Definition for parent element, allows parent element to be a
      * tag that's not allowed inside the HTML fragment.
+     * @type HTMLPurifier_ElementDef
      */
     public $info_parent_def;
 
     /**
-     * String name of element used to wrap inline elements in block context
+     * String name of element used to wrap inline elements in block context.
+     * @type string
      * @note This is rarely used except for BLOCKQUOTEs in strict mode
      */
     public $info_block_wrapper = 'p';
 
     /**
-     * Associative array of deprecated tag name to HTMLPurifier_TagTransform
+     * Associative array of deprecated tag name to HTMLPurifier_TagTransform.
+     * @type array
      */
     public $info_tag_transform = array();
 
     /**
      * Indexed list of HTMLPurifier_AttrTransform to be performed before validation.
+     * @type HTMLPurifier_AttrTransform[]
      */
     public $info_attr_transform_pre = array();
 
     /**
      * Indexed list of HTMLPurifier_AttrTransform to be performed after validation.
+     * @type HTMLPurifier_AttrTransform[]
      */
     public $info_attr_transform_post = array();
 
     /**
      * Nested lookup array of content set name (Block, Inline) to
      * element name to whether or not it belongs in that content set.
+     * @type array
      */
     public $info_content_sets = array();
 
     /**
      * Indexed list of HTMLPurifier_Injector to be used.
+     * @type HTMLPurifier_Injector[]
      */
     public $info_injector = array();
 
     /**
      * Doctype object
+     * @type HTMLPurifier_Doctype
      */
     public $doctype;
 
@@ -94,12 +105,13 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
      * Adds a custom attribute to a pre-existing element
      * @note This is strictly convenience, and does not have a corresponding
      *       method in HTMLPurifier_HTMLModule
-     * @param $element_name String element name to add attribute to
-     * @param $attr_name String name of attribute
-     * @param $def Attribute definition, can be string or object, see
+     * @param string $element_name Element name to add attribute to
+     * @param string $attr_name Name of attribute
+     * @param mixed $def Attribute definition, can be string or object, see
      *             HTMLPurifier_AttrTypes for details
      */
-    public function addAttribute($element_name, $attr_name, $def) {
+    public function addAttribute($element_name, $attr_name, $def)
+    {
         $module = $this->getAnonymousModule();
         if (!isset($module->info[$element_name])) {
             $element = $module->addBlankElement($element_name);
@@ -111,10 +123,11 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
 
     /**
      * Adds a custom element to your HTML definition
-     * @note See HTMLPurifier_HTMLModule::addElement for detailed
+     * @see HTMLPurifier_HTMLModule::addElement() for detailed
      *       parameter and return value descriptions.
      */
-    public function addElement($element_name, $type, $contents, $attr_collections, $attributes = array()) {
+    public function addElement($element_name, $type, $contents, $attr_collections, $attributes = array())
+    {
         $module = $this->getAnonymousModule();
         // assume that if the user is calling this, the element
         // is safe. This may not be a good idea
@@ -125,10 +138,13 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
     /**
      * Adds a blank element to your HTML definition, for overriding
      * existing behavior
-     * @note See HTMLPurifier_HTMLModule::addBlankElement for detailed
+     * @param string $element_name
+     * @return HTMLPurifier_ElementDef
+     * @see HTMLPurifier_HTMLModule::addBlankElement() for detailed
      *       parameter and return value descriptions.
      */
-    public function addBlankElement($element_name) {
+    public function addBlankElement($element_name)
+    {
         $module  = $this->getAnonymousModule();
         $element = $module->addBlankElement($element_name);
         return $element;
@@ -138,8 +154,10 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
      * Retrieves a reference to the anonymous module, so you can
      * bust out advanced features without having to make your own
      * module.
+     * @return HTMLPurifier_HTMLModule
      */
-    public function getAnonymousModule() {
+    public function getAnonymousModule()
+    {
         if (!$this->_anonModule) {
             $this->_anonModule = new HTMLPurifier_HTMLModule();
             $this->_anonModule->name = 'Anonymous';
@@ -147,22 +165,33 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
         return $this->_anonModule;
     }
 
-    private $_anonModule;
-
+    private $_anonModule = null;
 
     // PUBLIC BUT INTERNAL VARIABLES --------------------------------------
 
+    /**
+     * @type string
+     */
     public $type = 'HTML';
-    public $manager; /**< Instance of HTMLPurifier_HTMLModuleManager */
+
+    /**
+     * @type HTMLPurifier_HTMLModuleManager
+     */
+    public $manager;
 
     /**
      * Performs low-cost, preliminary initialization.
      */
-    public function __construct() {
+    public function __construct()
+    {
         $this->manager = new HTMLPurifier_HTMLModuleManager();
     }
 
-    protected function doSetup($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    protected function doSetup($config)
+    {
         $this->processModules($config);
         $this->setupConfigStuff($config);
         unset($this->manager);
@@ -176,9 +205,10 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
 
     /**
      * Extract out the information from the manager
+     * @param HTMLPurifier_Config $config
      */
-    protected function processModules($config) {
-
+    protected function processModules($config)
+    {
         if ($this->_anonModule) {
             // for user specific changes
             // this is late-loaded so we don't have to deal with PHP4
@@ -191,40 +221,53 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
         $this->doctype = $this->manager->doctype;
 
         foreach ($this->manager->modules as $module) {
-            foreach($module->info_tag_transform as $k => $v) {
-                if ($v === false) unset($this->info_tag_transform[$k]);
-                else $this->info_tag_transform[$k] = $v;
+            foreach ($module->info_tag_transform as $k => $v) {
+                if ($v === false) {
+                    unset($this->info_tag_transform[$k]);
+                } else {
+                    $this->info_tag_transform[$k] = $v;
+                }
             }
-            foreach($module->info_attr_transform_pre as $k => $v) {
-                if ($v === false) unset($this->info_attr_transform_pre[$k]);
-                else $this->info_attr_transform_pre[$k] = $v;
+            foreach ($module->info_attr_transform_pre as $k => $v) {
+                if ($v === false) {
+                    unset($this->info_attr_transform_pre[$k]);
+                } else {
+                    $this->info_attr_transform_pre[$k] = $v;
+                }
             }
-            foreach($module->info_attr_transform_post as $k => $v) {
-                if ($v === false) unset($this->info_attr_transform_post[$k]);
-                else $this->info_attr_transform_post[$k] = $v;
+            foreach ($module->info_attr_transform_post as $k => $v) {
+                if ($v === false) {
+                    unset($this->info_attr_transform_post[$k]);
+                } else {
+                    $this->info_attr_transform_post[$k] = $v;
+                }
             }
             foreach ($module->info_injector as $k => $v) {
-                if ($v === false) unset($this->info_injector[$k]);
-                else $this->info_injector[$k] = $v;
+                if ($v === false) {
+                    unset($this->info_injector[$k]);
+                } else {
+                    $this->info_injector[$k] = $v;
+                }
             }
         }
-
         $this->info = $this->manager->getElements();
         $this->info_content_sets = $this->manager->contentSets->lookup;
-
     }
 
     /**
      * Sets up stuff based on config. We need a better way of doing this.
+     * @param HTMLPurifier_Config $config
      */
-    protected function setupConfigStuff($config) {
-
+    protected function setupConfigStuff($config)
+    {
         $block_wrapper = $config->get('HTML.BlockWrapper');
         if (isset($this->info_content_sets['Block'][$block_wrapper])) {
             $this->info_block_wrapper = $block_wrapper;
         } else {
-            trigger_error('Cannot use non-block element as block wrapper',
-                E_USER_ERROR);
+            trigger_error(
+                'Cannot use non-block element as block wrapper',
+                E_USER_ERROR
+            );
         }
 
         $parent = $config->get('HTML.Parent');
@@ -233,14 +276,15 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
             $this->info_parent = $parent;
             $this->info_parent_def = $def;
         } else {
-            trigger_error('Cannot use unrecognized element as parent',
-                E_USER_ERROR);
+            trigger_error(
+                'Cannot use unrecognized element as parent',
+                E_USER_ERROR
+            );
             $this->info_parent_def = $this->manager->getElement($this->info_parent, true);
         }
 
         // support template text
-        $support = "(for information on implementing this, see the ".
-                   "support forums) ";
+        $support = "(for information on implementing this, see the support forums) ";
 
         // setup allowed elements -----------------------------------------
 
@@ -256,7 +300,9 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
 
         if (is_array($allowed_elements)) {
             foreach ($this->info as $name => $d) {
-                if(!isset($allowed_elements[$name])) unset($this->info[$name]);
+                if (!isset($allowed_elements[$name])) {
+                    unset($this->info[$name]);
+                }
                 unset($allowed_elements[$name]);
             }
             // emit errors
@@ -270,7 +316,6 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
 
         $allowed_attributes_mutable = $allowed_attributes; // by copy!
         if (is_array($allowed_attributes)) {
-
             // This actually doesn't do anything, since we went away from
             // global attributes. It's possible that userland code uses
             // it, but HTMLModuleManager doesn't!
@@ -285,7 +330,9 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
                         unset($allowed_attributes_mutable[$key]);
                     }
                 }
-                if ($delete) unset($this->info_global_attr[$attr]);
+                if ($delete) {
+                    unset($this->info_global_attr[$attr]);
+                }
             }
 
             foreach ($this->info as $tag => $info) {
@@ -300,7 +347,16 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
                             unset($allowed_attributes_mutable[$key]);
                         }
                     }
-                    if ($delete) unset($this->info[$tag]->attr[$attr]);
+                    if ($delete) {
+                        if ($this->info[$tag]->attr[$attr]->required) {
+                            trigger_error(
+                                "Required attribute '$attr' in element '$tag' " .
+                                "was not allowed, which means '$tag' will not be allowed either",
+                                E_USER_WARNING
+                            );
+                        }
+                        unset($this->info[$tag]->attr[$attr]);
+                    }
                 }
             }
             // emit errors
@@ -313,23 +369,29 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
                             $element = htmlspecialchars($bits[0]);
                             $attribute = htmlspecialchars($bits[1]);
                             if (!isset($this->info[$element])) {
-                                trigger_error("Cannot allow attribute '$attribute' if element '$element' is not allowed/supported $support");
+                                trigger_error(
+                                    "Cannot allow attribute '$attribute' if element " .
+                                    "'$element' is not allowed/supported $support"
+                                );
                             } else {
-                                trigger_error("Attribute '$attribute' in element '$element' not supported $support",
-                                    E_USER_WARNING);
+                                trigger_error(
+                                    "Attribute '$attribute' in element '$element' not supported $support",
+                                    E_USER_WARNING
+                                );
                             }
                             break;
                         }
                         // otherwise fall through
                     case 1:
                         $attribute = htmlspecialchars($bits[0]);
-                        trigger_error("Global attribute '$attribute' is not ".
+                        trigger_error(
+                            "Global attribute '$attribute' is not ".
                             "supported in any elements $support",
-                            E_USER_WARNING);
+                            E_USER_WARNING
+                        );
                         break;
                 }
             }
-
         }
 
         // setup forbidden elements ---------------------------------------
@@ -343,25 +405,34 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
                 continue;
             }
             foreach ($info->attr as $attr => $x) {
-                if (
-                    isset($forbidden_attributes["$tag@$attr"]) ||
+                if (isset($forbidden_attributes["$tag@$attr"]) ||
                     isset($forbidden_attributes["*@$attr"]) ||
                     isset($forbidden_attributes[$attr])
                 ) {
                     unset($this->info[$tag]->attr[$attr]);
                     continue;
-                } // this segment might get removed eventually
-                elseif (isset($forbidden_attributes["$tag.$attr"])) {
+                } elseif (isset($forbidden_attributes["$tag.$attr"])) { // this segment might get removed eventually
                     // $tag.$attr are not user supplied, so no worries!
-                    trigger_error("Error with $tag.$attr: tag.attr syntax not supported for HTML.ForbiddenAttributes; use tag@attr instead", E_USER_WARNING);
+                    trigger_error(
+                        "Error with $tag.$attr: tag.attr syntax not supported for " .
+                        "HTML.ForbiddenAttributes; use tag@attr instead",
+                        E_USER_WARNING
+                    );
                 }
             }
         }
         foreach ($forbidden_attributes as $key => $v) {
-            if (strlen($key) < 2) continue;
-            if ($key[0] != '*') continue;
+            if (strlen($key) < 2) {
+                continue;
+            }
+            if ($key[0] != '*') {
+                continue;
+            }
             if ($key[1] == '.') {
-                trigger_error("Error with $key: *.attr syntax not supported for HTML.ForbiddenAttributes; use attr instead", E_USER_WARNING);
+                trigger_error(
+                    "Error with $key: *.attr syntax not supported for HTML.ForbiddenAttributes; use attr instead",
+                    E_USER_WARNING
+                );
             }
         }
 
@@ -380,12 +451,12 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
      * separate lists for processing. Format is element[attr1|attr2],element2...
      * @warning Although it's largely drawn from TinyMCE's implementation,
      *      it is different, and you'll probably have to modify your lists
-     * @param $list String list to parse
-     * @param array($allowed_elements, $allowed_attributes)
+     * @param array $list String list to parse
+     * @return array
      * @todo Give this its own class, probably static interface
      */
-    public function parseTinyMCEAllowedList($list) {
-
+    public function parseTinyMCEAllowedList($list)
+    {
         $list = str_replace(array(' ', "\t"), '', $list);
 
         $elements = array();
@@ -393,7 +464,9 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
 
         $chunks = preg_split('/(,|[\n\r]+)/', $list);
         foreach ($chunks as $chunk) {
-            if (empty($chunk)) continue;
+            if (empty($chunk)) {
+                continue;
+            }
             // remove TinyMCE element control characters
             if (!strpos($chunk, '[')) {
                 $element = $chunk;
@@ -401,20 +474,20 @@ class HTMLPurifier_HTMLDefinition extends HTMLPurifier_Definition
             } else {
                 list($element, $attr) = explode('[', $chunk);
             }
-            if ($element !== '*') $elements[$element] = true;
-            if (!$attr) continue;
+            if ($element !== '*') {
+                $elements[$element] = true;
+            }
+            if (!$attr) {
+                continue;
+            }
             $attr = substr($attr, 0, strlen($attr) - 1); // remove trailing ]
             $attr = explode('|', $attr);
             foreach ($attr as $key) {
                 $attributes["$element.$key"] = true;
             }
         }
-
         return array($elements, $attributes);
-
     }
-
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule.php
similarity index 71%
rename from library/HTMLPurifier/HTMLModule.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule.php
index 072cf68084..bb3a9230b1 100644
--- a/library/HTMLPurifier/HTMLModule.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule.php
@@ -21,13 +21,15 @@ class HTMLPurifier_HTMLModule
     // -- Overloadable ----------------------------------------------------
 
     /**
-     * Short unique string identifier of the module
+     * Short unique string identifier of the module.
+     * @type string
      */
     public $name;
 
     /**
-     * Informally, a list of elements this module changes. Not used in
-     * any significant way.
+     * Informally, a list of elements this module changes.
+     * Not used in any significant way.
+     * @type array
      */
     public $elements = array();
 
@@ -35,6 +37,7 @@ class HTMLPurifier_HTMLModule
      * Associative array of element names to element definitions.
      * Some definitions may be incomplete, to be merged in later
      * with the full definition.
+     * @type array
      */
     public $info = array();
 
@@ -43,6 +46,7 @@ class HTMLPurifier_HTMLModule
      * This is commonly used to, say, add an A element to the Inline
      * content set. This corresponds to an internal variable $content_sets
      * and NOT info_content_sets member variable of HTMLDefinition.
+     * @type array
      */
     public $content_sets = array();
 
@@ -53,21 +57,25 @@ class HTMLPurifier_HTMLModule
      * the style attribute to the Core. Corresponds to HTMLDefinition's
      * attr_collections->info, since the object's data is only info,
      * with extra behavior associated with it.
+     * @type array
      */
     public $attr_collections = array();
 
     /**
-     * Associative array of deprecated tag name to HTMLPurifier_TagTransform
+     * Associative array of deprecated tag name to HTMLPurifier_TagTransform.
+     * @type array
      */
     public $info_tag_transform = array();
 
     /**
      * List of HTMLPurifier_AttrTransform to be performed before validation.
+     * @type array
      */
     public $info_attr_transform_pre = array();
 
     /**
      * List of HTMLPurifier_AttrTransform to be performed after validation.
+     * @type array
      */
     public $info_attr_transform_post = array();
 
@@ -76,6 +84,7 @@ class HTMLPurifier_HTMLModule
      * An injector will only be invoked if all of it's pre-requisites are met;
      * if an injector fails setup, there will be no error; it will simply be
      * silently disabled.
+     * @type array
      */
     public $info_injector = array();
 
@@ -84,6 +93,7 @@ class HTMLPurifier_HTMLModule
      * For optimization reasons: may save a call to a function. Be sure
      * to set it if you do implement getChildDef(), otherwise it will have
      * no effect!
+     * @type bool
      */
     public $defines_child_def = false;
 
@@ -94,6 +104,7 @@ class HTMLPurifier_HTMLModule
      * which is based off of safe HTML, to explicitly say, "This is safe," even
      * though there are modules which are "unsafe")
      *
+     * @type bool
      * @note Previously, safety could be applied at an element level granularity.
      *       We've removed this ability, so in order to add "unsafe" elements
      *       or attributes, a dedicated module with this property set to false
@@ -106,51 +117,62 @@ class HTMLPurifier_HTMLModule
      * content_model and content_model_type member variables of
      * the HTMLPurifier_ElementDef class. There is a similar function
      * in HTMLPurifier_HTMLDefinition.
-     * @param $def HTMLPurifier_ElementDef instance
+     * @param HTMLPurifier_ElementDef $def
      * @return HTMLPurifier_ChildDef subclass
      */
-    public function getChildDef($def) {return false;}
+    public function getChildDef($def)
+    {
+        return false;
+    }
 
     // -- Convenience -----------------------------------------------------
 
     /**
      * Convenience function that sets up a new element
-     * @param $element Name of element to add
-     * @param $type What content set should element be registered to?
+     * @param string $element Name of element to add
+     * @param string|bool $type What content set should element be registered to?
      *              Set as false to skip this step.
-     * @param $contents Allowed children in form of:
+     * @param string $contents Allowed children in form of:
      *              "$content_model_type: $content_model"
-     * @param $attr_includes What attribute collections to register to
+     * @param array $attr_includes What attribute collections to register to
      *              element?
-     * @param $attr What unique attributes does the element define?
-     * @note See ElementDef for in-depth descriptions of these parameters.
-     * @return Created element definition object, so you
+     * @param array $attr What unique attributes does the element define?
+     * @see HTMLPurifier_ElementDef:: for in-depth descriptions of these parameters.
+     * @return HTMLPurifier_ElementDef Created element definition object, so you
      *         can set advanced parameters
      */
-    public function addElement($element, $type, $contents, $attr_includes = array(), $attr = array()) {
+    public function addElement($element, $type, $contents, $attr_includes = array(), $attr = array())
+    {
         $this->elements[] = $element;
         // parse content_model
         list($content_model_type, $content_model) = $this->parseContents($contents);
         // merge in attribute inclusions
         $this->mergeInAttrIncludes($attr, $attr_includes);
         // add element to content sets
-        if ($type) $this->addElementToContentSet($element, $type);
+        if ($type) {
+            $this->addElementToContentSet($element, $type);
+        }
         // create element
         $this->info[$element] = HTMLPurifier_ElementDef::create(
-            $content_model, $content_model_type, $attr
+            $content_model,
+            $content_model_type,
+            $attr
         );
         // literal object $contents means direct child manipulation
-        if (!is_string($contents)) $this->info[$element]->child = $contents;
+        if (!is_string($contents)) {
+            $this->info[$element]->child = $contents;
+        }
         return $this->info[$element];
     }
 
     /**
      * Convenience function that creates a totally blank, non-standalone
      * element.
-     * @param $element Name of element to create
-     * @return Created element
+     * @param string $element Name of element to create
+     * @return HTMLPurifier_ElementDef Created element
      */
-    public function addBlankElement($element) {
+    public function addBlankElement($element)
+    {
         if (!isset($this->info[$element])) {
             $this->elements[] = $element;
             $this->info[$element] = new HTMLPurifier_ElementDef();
@@ -163,27 +185,35 @@ class HTMLPurifier_HTMLModule
 
     /**
      * Convenience function that registers an element to a content set
-     * @param Element to register
-     * @param Name content set (warning: case sensitive, usually upper-case
+     * @param string $element Element to register
+     * @param string $type Name content set (warning: case sensitive, usually upper-case
      *        first letter)
      */
-    public function addElementToContentSet($element, $type) {
-        if (!isset($this->content_sets[$type])) $this->content_sets[$type] = '';
-        else $this->content_sets[$type] .= ' | ';
+    public function addElementToContentSet($element, $type)
+    {
+        if (!isset($this->content_sets[$type])) {
+            $this->content_sets[$type] = '';
+        } else {
+            $this->content_sets[$type] .= ' | ';
+        }
         $this->content_sets[$type] .= $element;
     }
 
     /**
      * Convenience function that transforms single-string contents
      * into separate content model and content model type
-     * @param $contents Allowed children in form of:
+     * @param string $contents Allowed children in form of:
      *                  "$content_model_type: $content_model"
+     * @return array
      * @note If contents is an object, an array of two nulls will be
      *       returned, and the callee needs to take the original $contents
      *       and use it directly.
      */
-    public function parseContents($contents) {
-        if (!is_string($contents)) return array(null, null); // defer
+    public function parseContents($contents)
+    {
+        if (!is_string($contents)) {
+            return array(null, null);
+        } // defer
         switch ($contents) {
             // check for shorthand content model forms
             case 'Empty':
@@ -202,13 +232,17 @@ class HTMLPurifier_HTMLModule
     /**
      * Convenience function that merges a list of attribute includes into
      * an attribute array.
-     * @param $attr Reference to attr array to modify
-     * @param $attr_includes Array of includes / string include to merge in
+     * @param array $attr Reference to attr array to modify
+     * @param array $attr_includes Array of includes / string include to merge in
      */
-    public function mergeInAttrIncludes(&$attr, $attr_includes) {
+    public function mergeInAttrIncludes(&$attr, $attr_includes)
+    {
         if (!is_array($attr_includes)) {
-            if (empty($attr_includes)) $attr_includes = array();
-            else $attr_includes = array($attr_includes);
+            if (empty($attr_includes)) {
+                $attr_includes = array();
+            } else {
+                $attr_includes = array($attr_includes);
+            }
         }
         $attr[0] = $attr_includes;
     }
@@ -216,16 +250,21 @@ class HTMLPurifier_HTMLModule
     /**
      * Convenience function that generates a lookup table with boolean
      * true as value.
-     * @param $list List of values to turn into a lookup
+     * @param string $list List of values to turn into a lookup
      * @note You can also pass an arbitrary number of arguments in
      *       place of the regular argument
-     * @return Lookup array equivalent of list
+     * @return array array equivalent of list
      */
-    public function makeLookup($list) {
-        if (is_string($list)) $list = func_get_args();
+    public function makeLookup($list)
+    {
+        if (is_string($list)) {
+            $list = func_get_args();
+        }
         $ret = array();
         foreach ($list as $value) {
-            if (is_null($value)) continue;
+            if (is_null($value)) {
+                continue;
+            }
             $ret[$value] = true;
         }
         return $ret;
@@ -235,10 +274,11 @@ class HTMLPurifier_HTMLModule
      * Lazy load construction of the module after determining whether
      * or not it's needed, and also when a finalized configuration object
      * is available.
-     * @param $config Instance of HTMLPurifier_Config
+     * @param HTMLPurifier_Config $config
      */
-    public function setup($config) {}
-
+    public function setup($config)
+    {
+    }
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Bdo.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Bdo.php
similarity index 66%
rename from library/HTMLPurifier/HTMLModule/Bdo.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Bdo.php
index 3d66f1b4e1..1e67c790d0 100644
--- a/library/HTMLPurifier/HTMLModule/Bdo.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Bdo.php
@@ -7,25 +7,38 @@
 class HTMLPurifier_HTMLModule_Bdo extends HTMLPurifier_HTMLModule
 {
 
+    /**
+     * @type string
+     */
     public $name = 'Bdo';
+
+    /**
+     * @type array
+     */
     public $attr_collections = array(
         'I18N' => array('dir' => false)
     );
 
-    public function setup($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         $bdo = $this->addElement(
-            'bdo', 'Inline', 'Inline', array('Core', 'Lang'),
+            'bdo',
+            'Inline',
+            'Inline',
+            array('Core', 'Lang'),
             array(
                 'dir' => 'Enum#ltr,rtl', // required
                 // The Abstract Module specification has the attribute
                 // inclusions wrong for bdo: bdo allows Lang
             )
         );
-        $bdo->attr_transform_post['required-dir'] = new HTMLPurifier_AttrTransform_BdoDir();
+        $bdo->attr_transform_post[] = new HTMLPurifier_AttrTransform_BdoDir();
 
         $this->attr_collections['I18N']['dir'] = 'Enum#ltr,rtl';
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/CommonAttributes.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/CommonAttributes.php
similarity index 89%
rename from library/HTMLPurifier/HTMLModule/CommonAttributes.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/CommonAttributes.php
index 7c15da84fc..a96ab1bef1 100644
--- a/library/HTMLPurifier/HTMLModule/CommonAttributes.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/CommonAttributes.php
@@ -2,8 +2,14 @@
 
 class HTMLPurifier_HTMLModule_CommonAttributes extends HTMLPurifier_HTMLModule
 {
+    /**
+     * @type string
+     */
     public $name = 'CommonAttributes';
 
+    /**
+     * @type array
+     */
     public $attr_collections = array(
         'Core' => array(
             0 => array('Style'),
@@ -20,7 +26,6 @@ class HTMLPurifier_HTMLModule_CommonAttributes extends HTMLPurifier_HTMLModule
             0 => array('Core', 'I18N')
         )
     );
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Edit.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php
similarity index 71%
rename from library/HTMLPurifier/HTMLModule/Edit.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php
index ff93690555..a9042a3577 100644
--- a/library/HTMLPurifier/HTMLModule/Edit.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Edit.php
@@ -7,9 +7,16 @@
 class HTMLPurifier_HTMLModule_Edit extends HTMLPurifier_HTMLModule
 {
 
+    /**
+     * @type string
+     */
     public $name = 'Edit';
 
-    public function setup($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         $contents = 'Chameleon: #PCDATA | Inline ! #PCDATA | Flow';
         $attr = array(
             'cite' => 'URI',
@@ -26,13 +33,23 @@ class HTMLPurifier_HTMLModule_Edit extends HTMLPurifier_HTMLModule
     // Inline context ! Block context (exclamation mark is
     // separator, see getChildDef for parsing)
 
+    /**
+     * @type bool
+     */
     public $defines_child_def = true;
-    public function getChildDef($def) {
-        if ($def->content_model_type != 'chameleon') return false;
+
+    /**
+     * @param HTMLPurifier_ElementDef $def
+     * @return HTMLPurifier_ChildDef_Chameleon
+     */
+    public function getChildDef($def)
+    {
+        if ($def->content_model_type != 'chameleon') {
+            return false;
+        }
         $value = explode('!', $def->content_model);
         return new HTMLPurifier_ChildDef_Chameleon($value[0], $value[1]);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php
new file mode 100644
index 0000000000..6f7ddbc05b
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Forms.php
@@ -0,0 +1,190 @@
+<?php
+
+/**
+ * XHTML 1.1 Forms module, defines all form-related elements found in HTML 4.
+ */
+class HTMLPurifier_HTMLModule_Forms extends HTMLPurifier_HTMLModule
+{
+    /**
+     * @type string
+     */
+    public $name = 'Forms';
+
+    /**
+     * @type bool
+     */
+    public $safe = false;
+
+    /**
+     * @type array
+     */
+    public $content_sets = array(
+        'Block' => 'Form',
+        'Inline' => 'Formctrl',
+    );
+
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        $form = $this->addElement(
+            'form',
+            'Form',
+            'Required: Heading | List | Block | fieldset',
+            'Common',
+            array(
+                'accept' => 'ContentTypes',
+                'accept-charset' => 'Charsets',
+                'action*' => 'URI',
+                'method' => 'Enum#get,post',
+                // really ContentType, but these two are the only ones used today
+                'enctype' => 'Enum#application/x-www-form-urlencoded,multipart/form-data',
+            )
+        );
+        $form->excludes = array('form' => true);
+
+        $input = $this->addElement(
+            'input',
+            'Formctrl',
+            'Empty',
+            'Common',
+            array(
+                'accept' => 'ContentTypes',
+                'accesskey' => 'Character',
+                'alt' => 'Text',
+                'checked' => 'Bool#checked',
+                'disabled' => 'Bool#disabled',
+                'maxlength' => 'Number',
+                'name' => 'CDATA',
+                'readonly' => 'Bool#readonly',
+                'size' => 'Number',
+                'src' => 'URI#embedded',
+                'tabindex' => 'Number',
+                'type' => 'Enum#text,password,checkbox,button,radio,submit,reset,file,hidden,image',
+                'value' => 'CDATA',
+            )
+        );
+        $input->attr_transform_post[] = new HTMLPurifier_AttrTransform_Input();
+
+        $this->addElement(
+            'select',
+            'Formctrl',
+            'Required: optgroup | option',
+            'Common',
+            array(
+                'disabled' => 'Bool#disabled',
+                'multiple' => 'Bool#multiple',
+                'name' => 'CDATA',
+                'size' => 'Number',
+                'tabindex' => 'Number',
+            )
+        );
+
+        $this->addElement(
+            'option',
+            false,
+            'Optional: #PCDATA',
+            'Common',
+            array(
+                'disabled' => 'Bool#disabled',
+                'label' => 'Text',
+                'selected' => 'Bool#selected',
+                'value' => 'CDATA',
+            )
+        );
+        // It's illegal for there to be more than one selected, but not
+        // be multiple. Also, no selected means undefined behavior. This might
+        // be difficult to implement; perhaps an injector, or a context variable.
+
+        $textarea = $this->addElement(
+            'textarea',
+            'Formctrl',
+            'Optional: #PCDATA',
+            'Common',
+            array(
+                'accesskey' => 'Character',
+                'cols*' => 'Number',
+                'disabled' => 'Bool#disabled',
+                'name' => 'CDATA',
+                'readonly' => 'Bool#readonly',
+                'rows*' => 'Number',
+                'tabindex' => 'Number',
+            )
+        );
+        $textarea->attr_transform_pre[] = new HTMLPurifier_AttrTransform_Textarea();
+
+        $button = $this->addElement(
+            'button',
+            'Formctrl',
+            'Optional: #PCDATA | Heading | List | Block | Inline',
+            'Common',
+            array(
+                'accesskey' => 'Character',
+                'disabled' => 'Bool#disabled',
+                'name' => 'CDATA',
+                'tabindex' => 'Number',
+                'type' => 'Enum#button,submit,reset',
+                'value' => 'CDATA',
+            )
+        );
+
+        // For exclusions, ideally we'd specify content sets, not literal elements
+        $button->excludes = $this->makeLookup(
+            'form',
+            'fieldset', // Form
+            'input',
+            'select',
+            'textarea',
+            'label',
+            'button', // Formctrl
+            'a', // as per HTML 4.01 spec, this is omitted by modularization
+            'isindex',
+            'iframe' // legacy items
+        );
+
+        // Extra exclusion: img usemap="" is not permitted within this element.
+        // We'll omit this for now, since we don't have any good way of
+        // indicating it yet.
+
+        // This is HIGHLY user-unfriendly; we need a custom child-def for this
+        $this->addElement('fieldset', 'Form', 'Custom: (#WS?,legend,(Flow|#PCDATA)*)', 'Common');
+
+        $label = $this->addElement(
+            'label',
+            'Formctrl',
+            'Optional: #PCDATA | Inline',
+            'Common',
+            array(
+                'accesskey' => 'Character',
+                // 'for' => 'IDREF', // IDREF not implemented, cannot allow
+            )
+        );
+        $label->excludes = array('label' => true);
+
+        $this->addElement(
+            'legend',
+            false,
+            'Optional: #PCDATA | Inline',
+            'Common',
+            array(
+                'accesskey' => 'Character',
+            )
+        );
+
+        $this->addElement(
+            'optgroup',
+            false,
+            'Required: option',
+            'Common',
+            array(
+                'disabled' => 'Bool#disabled',
+                'label*' => 'Text',
+            )
+        );
+        // Don't forget an injector for <isindex>. This one's a little complex
+        // because it maps to multiple elements.
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Hypertext.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Hypertext.php
similarity index 78%
rename from library/HTMLPurifier/HTMLModule/Hypertext.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Hypertext.php
index d7e9bdd27e..72d7a31e68 100644
--- a/library/HTMLPurifier/HTMLModule/Hypertext.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Hypertext.php
@@ -6,11 +6,21 @@
 class HTMLPurifier_HTMLModule_Hypertext extends HTMLPurifier_HTMLModule
 {
 
+    /**
+     * @type string
+     */
     public $name = 'Hypertext';
 
-    public function setup($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         $a = $this->addElement(
-            'a', 'Inline', 'Inline', 'Common',
+            'a',
+            'Inline',
+            'Inline',
+            'Common',
             array(
                 // 'accesskey' => 'Character',
                 // 'charset' => 'Charset',
@@ -25,7 +35,6 @@ class HTMLPurifier_HTMLModule_Hypertext extends HTMLPurifier_HTMLModule
         $a->formatting = true;
         $a->excludes = array('a' => true);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php
new file mode 100644
index 0000000000..f7e7c91c02
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Iframe.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * XHTML 1.1 Iframe Module provides inline frames.
+ *
+ * @note This module is not considered safe unless an Iframe
+ * whitelisting mechanism is specified.  Currently, the only
+ * such mechanism is %URL.SafeIframeRegexp
+ */
+class HTMLPurifier_HTMLModule_Iframe extends HTMLPurifier_HTMLModule
+{
+
+    /**
+     * @type string
+     */
+    public $name = 'Iframe';
+
+    /**
+     * @type bool
+     */
+    public $safe = false;
+
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        if ($config->get('HTML.SafeIframe')) {
+            $this->safe = true;
+        }
+        $this->addElement(
+            'iframe',
+            'Inline',
+            'Flow',
+            'Common',
+            array(
+                'src' => 'URI#embedded',
+                'width' => 'Length',
+                'height' => 'Length',
+                'name' => 'ID',
+                'scrolling' => 'Enum#yes,no,auto',
+                'frameborder' => 'Enum#0,1',
+                'longdesc' => 'URI',
+                'marginheight' => 'Pixels',
+                'marginwidth' => 'Pixels',
+            )
+        );
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Image.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Image.php
similarity index 80%
rename from library/HTMLPurifier/HTMLModule/Image.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Image.php
index 948d435bcd..0f5fdb3baf 100644
--- a/library/HTMLPurifier/HTMLModule/Image.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Image.php
@@ -8,18 +8,28 @@
 class HTMLPurifier_HTMLModule_Image extends HTMLPurifier_HTMLModule
 {
 
+    /**
+     * @type string
+     */
     public $name = 'Image';
 
-    public function setup($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         $max = $config->get('HTML.MaxImgLength');
         $img = $this->addElement(
-            'img', 'Inline', 'Empty', 'Common',
+            'img',
+            'Inline',
+            'Empty',
+            'Common',
             array(
                 'alt*' => 'Text',
                 // According to the spec, it's Length, but percents can
                 // be abused, so we allow only Pixels.
                 'height' => 'Pixels#' . $max,
-                'width'  => 'Pixels#' . $max,
+                'width' => 'Pixels#' . $max,
                 'longdesc' => 'URI',
                 'src*' => new HTMLPurifier_AttrDef_URI(true), // embedded
             )
@@ -34,7 +44,6 @@ class HTMLPurifier_HTMLModule_Image extends HTMLPurifier_HTMLModule
         $img->attr_transform_post[] =
             new HTMLPurifier_AttrTransform_ImgRequired();
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Legacy.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Legacy.php
similarity index 67%
rename from library/HTMLPurifier/HTMLModule/Legacy.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Legacy.php
index df33927ba6..86b5299579 100644
--- a/library/HTMLPurifier/HTMLModule/Legacy.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Legacy.php
@@ -18,29 +18,58 @@
 
 class HTMLPurifier_HTMLModule_Legacy extends HTMLPurifier_HTMLModule
 {
-
+    /**
+     * @type string
+     */
     public $name = 'Legacy';
 
-    public function setup($config) {
-
-        $this->addElement('basefont', 'Inline', 'Empty', false, array(
-            'color' => 'Color',
-            'face' => 'Text', // extremely broad, we should
-            'size' => 'Text', // tighten it
-            'id' => 'ID'
-        ));
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        $this->addElement(
+            'basefont',
+            'Inline',
+            'Empty',
+            null,
+            array(
+                'color' => 'Color',
+                'face' => 'Text', // extremely broad, we should
+                'size' => 'Text', // tighten it
+                'id' => 'ID'
+            )
+        );
         $this->addElement('center', 'Block', 'Flow', 'Common');
-        $this->addElement('dir', 'Block', 'Required: li', 'Common', array(
-            'compact' => 'Bool#compact'
-        ));
-        $this->addElement('font', 'Inline', 'Inline', array('Core', 'I18N'), array(
-            'color' => 'Color',
-            'face' => 'Text', // extremely broad, we should
-            'size' => 'Text', // tighten it
-        ));
-        $this->addElement('menu', 'Block', 'Required: li', 'Common', array(
-            'compact' => 'Bool#compact'
-        ));
+        $this->addElement(
+            'dir',
+            'Block',
+            'Required: li',
+            'Common',
+            array(
+                'compact' => 'Bool#compact'
+            )
+        );
+        $this->addElement(
+            'font',
+            'Inline',
+            'Inline',
+            array('Core', 'I18N'),
+            array(
+                'color' => 'Color',
+                'face' => 'Text', // extremely broad, we should
+                'size' => 'Text', // tighten it
+            )
+        );
+        $this->addElement(
+            'menu',
+            'Block',
+            'Required: li',
+            'Common',
+            array(
+                'compact' => 'Bool#compact'
+            )
+        );
 
         $s = $this->addElement('s', 'Inline', 'Inline', 'Common');
         $s->formatting = true;
@@ -89,7 +118,7 @@ class HTMLPurifier_HTMLModule_Legacy extends HTMLPurifier_HTMLModule
         $hr->attr['width'] = 'Length';
 
         $img = $this->addBlankElement('img');
-        $img->attr['align'] = 'Enum#top,middle,bottom,left,right';
+        $img->attr['align'] = 'IAlign';
         $img->attr['border'] = 'Pixels';
         $img->attr['hspace'] = 'Pixels';
         $img->attr['vspace'] = 'Pixels';
@@ -98,7 +127,7 @@ class HTMLPurifier_HTMLModule_Legacy extends HTMLPurifier_HTMLModule
 
         $li = $this->addBlankElement('li');
         $li->attr['value'] = new HTMLPurifier_AttrDef_Integer();
-        $li->attr['type']  = 'Enum#s:1,i,I,a,A,disc,square,circle';
+        $li->attr['type'] = 'Enum#s:1,i,I,a,A,disc,square,circle';
 
         $ol = $this->addBlankElement('ol');
         $ol->attr['compact'] = 'Bool#compact';
@@ -136,8 +165,22 @@ class HTMLPurifier_HTMLModule_Legacy extends HTMLPurifier_HTMLModule
         $ul->attr['compact'] = 'Bool#compact';
         $ul->attr['type'] = 'Enum#square,disc,circle';
 
-    }
+        // "safe" modifications to "unsafe" elements
+        // WARNING: If you want to add support for an unsafe, legacy
+        // attribute, make a new TrustedLegacy module with the trusted
+        // bit set appropriately
 
+        $form = $this->addBlankElement('form');
+        $form->content_model = 'Flow | #PCDATA';
+        $form->content_model_type = 'optional';
+        $form->attr['target'] = 'FrameTarget';
+
+        $input = $this->addBlankElement('input');
+        $input->attr['align'] = 'IAlign';
+
+        $legend = $this->addBlankElement('legend');
+        $legend->attr['align'] = 'LAlign';
+    }
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/List.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/List.php
similarity index 57%
rename from library/HTMLPurifier/HTMLModule/List.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/List.php
index 74d4522f4e..7a20ff701c 100644
--- a/library/HTMLPurifier/HTMLModule/List.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/List.php
@@ -5,7 +5,9 @@
  */
 class HTMLPurifier_HTMLModule_List extends HTMLPurifier_HTMLModule
 {
-
+    /**
+     * @type string
+     */
     public $name = 'List';
 
     // According to the abstract schema, the List content set is a fully formed
@@ -17,13 +19,26 @@ class HTMLPurifier_HTMLModule_List extends HTMLPurifier_HTMLModule
     // we don't have support for such nested expressions without using
     // the incredibly inefficient and draconic Custom ChildDef.
 
+    /**
+     * @type array
+     */
     public $content_sets = array('Flow' => 'List');
 
-    public function setup($config) {
-        $ol = $this->addElement('ol', 'List', 'Required: li', 'Common');
-        $ol->wrap = "li";
-        $ul = $this->addElement('ul', 'List', 'Required: li', 'Common');
-        $ul->wrap = "li";
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        $ol = $this->addElement('ol', 'List', new HTMLPurifier_ChildDef_List(), 'Common');
+        $ul = $this->addElement('ul', 'List', new HTMLPurifier_ChildDef_List(), 'Common');
+        // XXX The wrap attribute is handled by MakeWellFormed.  This is all
+        // quite unsatisfactory, because we generated this
+        // *specifically* for lists, and now a big chunk of the handling
+        // is done properly by the List ChildDef.  So actually, we just
+        // want enough information to make autoclosing work properly,
+        // and then hand off the tricky stuff to the ChildDef.
+        $ol->wrap = 'li';
+        $ul->wrap = 'li';
         $this->addElement('dl', 'List', 'Required: dt | dd', 'Common');
 
         $this->addElement('li', false, 'Flow', 'Common');
@@ -31,7 +46,6 @@ class HTMLPurifier_HTMLModule_List extends HTMLPurifier_HTMLModule
         $this->addElement('dd', false, 'Flow', 'Common');
         $this->addElement('dt', false, 'Inline', 'Common');
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Name.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Name.php
similarity index 65%
rename from library/HTMLPurifier/HTMLModule/Name.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Name.php
index 05694b4504..60c0545154 100644
--- a/library/HTMLPurifier/HTMLModule/Name.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Name.php
@@ -2,20 +2,25 @@
 
 class HTMLPurifier_HTMLModule_Name extends HTMLPurifier_HTMLModule
 {
-
+    /**
+     * @type string
+     */
     public $name = 'Name';
 
-    public function setup($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         $elements = array('a', 'applet', 'form', 'frame', 'iframe', 'img', 'map');
         foreach ($elements as $name) {
             $element = $this->addBlankElement($name);
             $element->attr['name'] = 'CDATA';
             if (!$config->get('HTML.Attr.Name.UseCDATA')) {
-                $element->attr_transform_post['NameSync'] = new HTMLPurifier_AttrTransform_NameSync();
+                $element->attr_transform_post[] = new HTMLPurifier_AttrTransform_NameSync();
             }
         }
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Nofollow.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Nofollow.php
new file mode 100644
index 0000000000..dc9410a895
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Nofollow.php
@@ -0,0 +1,25 @@
+<?php
+
+/**
+ * Module adds the nofollow attribute transformation to a tags.  It
+ * is enabled by HTML.Nofollow
+ */
+class HTMLPurifier_HTMLModule_Nofollow extends HTMLPurifier_HTMLModule
+{
+
+    /**
+     * @type string
+     */
+    public $name = 'Nofollow';
+
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        $a = $this->addBlankElement('a');
+        $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_Nofollow();
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php
similarity index 79%
rename from library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php
index 5f1b14abb8..da722253ac 100644
--- a/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/NonXMLCommonAttributes.php
@@ -2,8 +2,14 @@
 
 class HTMLPurifier_HTMLModule_NonXMLCommonAttributes extends HTMLPurifier_HTMLModule
 {
+    /**
+     * @type string
+     */
     public $name = 'NonXMLCommonAttributes';
 
+    /**
+     * @type array
+     */
     public $attr_collections = array(
         'Lang' => array(
             'lang' => 'LanguageCode',
diff --git a/library/HTMLPurifier/HTMLModule/Object.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Object.php
similarity index 71%
rename from library/HTMLPurifier/HTMLModule/Object.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Object.php
index 193c1011f8..2f9efc5c88 100644
--- a/library/HTMLPurifier/HTMLModule/Object.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Object.php
@@ -7,13 +7,26 @@
  */
 class HTMLPurifier_HTMLModule_Object extends HTMLPurifier_HTMLModule
 {
-
+    /**
+     * @type string
+     */
     public $name = 'Object';
+
+    /**
+     * @type bool
+     */
     public $safe = false;
 
-    public function setup($config) {
-
-        $this->addElement('object', 'Inline', 'Optional: #PCDATA | Flow | param', 'Common',
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        $this->addElement(
+            'object',
+            'Inline',
+            'Optional: #PCDATA | Flow | param',
+            'Common',
             array(
                 'archive' => 'URI',
                 'classid' => 'URI',
@@ -30,18 +43,20 @@ class HTMLPurifier_HTMLModule_Object extends HTMLPurifier_HTMLModule
             )
         );
 
-        $this->addElement('param', false, 'Empty', false,
+        $this->addElement(
+            'param',
+            false,
+            'Empty',
+            null,
             array(
                 'id' => 'ID',
                 'name*' => 'Text',
                 'type' => 'Text',
                 'value' => 'Text',
                 'valuetype' => 'Enum#data,ref,object'
-           )
+            )
         );
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Presentation.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Presentation.php
similarity index 52%
rename from library/HTMLPurifier/HTMLModule/Presentation.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Presentation.php
index 8ff0b5ed78..6458ce9d88 100644
--- a/library/HTMLPurifier/HTMLModule/Presentation.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Presentation.php
@@ -13,24 +13,30 @@
 class HTMLPurifier_HTMLModule_Presentation extends HTMLPurifier_HTMLModule
 {
 
+    /**
+     * @type string
+     */
     public $name = 'Presentation';
 
-    public function setup($config) {
-        $this->addElement('hr',     'Block',  'Empty',  'Common');
-        $this->addElement('sub',    'Inline', 'Inline', 'Common');
-        $this->addElement('sup',    'Inline', 'Inline', 'Common');
-        $b = $this->addElement('b',      'Inline', 'Inline', 'Common');
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        $this->addElement('hr', 'Block', 'Empty', 'Common');
+        $this->addElement('sub', 'Inline', 'Inline', 'Common');
+        $this->addElement('sup', 'Inline', 'Inline', 'Common');
+        $b = $this->addElement('b', 'Inline', 'Inline', 'Common');
         $b->formatting = true;
-        $big = $this->addElement('big',    'Inline', 'Inline', 'Common');
+        $big = $this->addElement('big', 'Inline', 'Inline', 'Common');
         $big->formatting = true;
-        $i = $this->addElement('i',      'Inline', 'Inline', 'Common');
+        $i = $this->addElement('i', 'Inline', 'Inline', 'Common');
         $i->formatting = true;
-        $small = $this->addElement('small',  'Inline', 'Inline', 'Common');
+        $small = $this->addElement('small', 'Inline', 'Inline', 'Common');
         $small->formatting = true;
-        $tt = $this->addElement('tt',     'Inline', 'Inline', 'Common');
+        $tt = $this->addElement('tt', 'Inline', 'Inline', 'Common');
         $tt->formatting = true;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Proprietary.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Proprietary.php
similarity index 74%
rename from library/HTMLPurifier/HTMLModule/Proprietary.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Proprietary.php
index dd36a3de0e..5ee3c8e67f 100644
--- a/library/HTMLPurifier/HTMLModule/Proprietary.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Proprietary.php
@@ -6,12 +6,21 @@
  */
 class HTMLPurifier_HTMLModule_Proprietary extends HTMLPurifier_HTMLModule
 {
-
+    /**
+     * @type string
+     */
     public $name = 'Proprietary';
 
-    public function setup($config) {
-
-        $this->addElement('marquee', 'Inline', 'Flow', 'Common',
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        $this->addElement(
+            'marquee',
+            'Inline',
+            'Flow',
+            'Common',
             array(
                 'direction' => 'Enum#left,right,up,down',
                 'behavior' => 'Enum#alternate',
@@ -25,9 +34,7 @@ class HTMLPurifier_HTMLModule_Proprietary extends HTMLPurifier_HTMLModule
                 'vspace' => 'Pixels',
             )
         );
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Ruby.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php
similarity index 77%
rename from library/HTMLPurifier/HTMLModule/Ruby.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php
index b26a0a30a0..a0d48924da 100644
--- a/library/HTMLPurifier/HTMLModule/Ruby.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Ruby.php
@@ -7,12 +7,22 @@
 class HTMLPurifier_HTMLModule_Ruby extends HTMLPurifier_HTMLModule
 {
 
+    /**
+     * @type string
+     */
     public $name = 'Ruby';
 
-    public function setup($config) {
-        $this->addElement('ruby', 'Inline',
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        $this->addElement(
+            'ruby',
+            'Inline',
             'Custom: ((rb, (rt | (rp, rt, rp))) | (rbc, rtc, rtc?))',
-            'Common');
+            'Common'
+        );
         $this->addElement('rbc', false, 'Required: rb', 'Common');
         $this->addElement('rtc', false, 'Required: rt', 'Common');
         $rb = $this->addElement('rb', false, 'Inline', 'Common');
@@ -21,7 +31,6 @@ class HTMLPurifier_HTMLModule_Ruby extends HTMLPurifier_HTMLModule
         $rt->excludes = array('ruby' => true);
         $this->addElement('rp', false, 'Optional: #PCDATA', 'Common');
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/SafeEmbed.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeEmbed.php
similarity index 74%
rename from library/HTMLPurifier/HTMLModule/SafeEmbed.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeEmbed.php
index ea256716bb..04e6689ea6 100644
--- a/library/HTMLPurifier/HTMLModule/SafeEmbed.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeEmbed.php
@@ -5,14 +5,22 @@
  */
 class HTMLPurifier_HTMLModule_SafeEmbed extends HTMLPurifier_HTMLModule
 {
-
+    /**
+     * @type string
+     */
     public $name = 'SafeEmbed';
 
-    public function setup($config) {
-
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         $max = $config->get('HTML.MaxImgLength');
         $embed = $this->addElement(
-            'embed', 'Inline', 'Empty', 'Common',
+            'embed',
+            'Inline',
+            'Empty',
+            'Common',
             array(
                 'src*' => 'URI#embedded',
                 'type' => 'Enum#application/x-shockwave-flash',
@@ -21,14 +29,12 @@ class HTMLPurifier_HTMLModule_SafeEmbed extends HTMLPurifier_HTMLModule
                 'allowscriptaccess' => 'Enum#never',
                 'allownetworking' => 'Enum#internal',
                 'flashvars' => 'Text',
-                'wmode' => 'Enum#window',
+                'wmode' => 'Enum#window,transparent,opaque',
                 'name' => 'ID',
             )
         );
         $embed->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeEmbed();
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/SafeObject.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeObject.php
similarity index 67%
rename from library/HTMLPurifier/HTMLModule/SafeObject.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeObject.php
index 64ab8c0703..1297f80a39 100644
--- a/library/HTMLPurifier/HTMLModule/SafeObject.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeObject.php
@@ -8,11 +8,16 @@
  */
 class HTMLPurifier_HTMLModule_SafeObject extends HTMLPurifier_HTMLModule
 {
-
+    /**
+     * @type string
+     */
     public $name = 'SafeObject';
 
-    public function setup($config) {
-
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         // These definitions are not intrinsically safe: the attribute transforms
         // are a vital part of ensuring safety.
 
@@ -25,18 +30,24 @@ class HTMLPurifier_HTMLModule_SafeObject extends HTMLPurifier_HTMLModule
             array(
                 // While technically not required by the spec, we're forcing
                 // it to this value.
-                'type'   => 'Enum#application/x-shockwave-flash',
-                'width'  => 'Pixels#' . $max,
+                'type' => 'Enum#application/x-shockwave-flash',
+                'width' => 'Pixels#' . $max,
                 'height' => 'Pixels#' . $max,
-                'data'   => 'URI#embedded',
-                'classid' => 'Enum#clsid:d27cdb6e-ae6d-11cf-96b8-444553540000',
-                'codebase' => new HTMLPurifier_AttrDef_Enum(array(
-                    'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0')),
+                'data' => 'URI#embedded',
+                'codebase' => new HTMLPurifier_AttrDef_Enum(
+                    array(
+                        'http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0'
+                    )
+                ),
             )
         );
         $object->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeObject();
 
-        $param = $this->addElement('param', false, 'Empty', false,
+        $param = $this->addElement(
+            'param',
+            false,
+            'Empty',
+            false,
             array(
                 'id' => 'ID',
                 'name*' => 'Text',
@@ -45,9 +56,7 @@ class HTMLPurifier_HTMLModule_SafeObject extends HTMLPurifier_HTMLModule
         );
         $param->attr_transform_post[] = new HTMLPurifier_AttrTransform_SafeParam();
         $this->info_injector[] = 'SafeObject';
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeScripting.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeScripting.php
new file mode 100644
index 0000000000..0330cd97f8
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/SafeScripting.php
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * A "safe" script module. No inline JS is allowed, and pointed to JS
+ * files must match whitelist.
+ */
+class HTMLPurifier_HTMLModule_SafeScripting extends HTMLPurifier_HTMLModule
+{
+    /**
+     * @type string
+     */
+    public $name = 'SafeScripting';
+
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        // These definitions are not intrinsically safe: the attribute transforms
+        // are a vital part of ensuring safety.
+
+        $allowed = $config->get('HTML.SafeScripting');
+        $script = $this->addElement(
+            'script',
+            'Inline',
+            'Empty',
+            null,
+            array(
+                // While technically not required by the spec, we're forcing
+                // it to this value.
+                'type' => 'Enum#text/javascript',
+                'src*' => new HTMLPurifier_AttrDef_Enum(array_keys($allowed))
+            )
+        );
+        $script->attr_transform_pre[] =
+        $script->attr_transform_post[] = new HTMLPurifier_AttrTransform_ScriptRequired();
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Scripting.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Scripting.php
similarity index 76%
rename from library/HTMLPurifier/HTMLModule/Scripting.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Scripting.php
index cecdea6c30..8b28a7b7ea 100644
--- a/library/HTMLPurifier/HTMLModule/Scripting.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Scripting.php
@@ -15,12 +15,31 @@ INSIDE HTML PURIFIER DOCUMENTS. USE ONLY WITH TRUSTED USER INPUT!!!
  */
 class HTMLPurifier_HTMLModule_Scripting extends HTMLPurifier_HTMLModule
 {
+    /**
+     * @type string
+     */
     public $name = 'Scripting';
+
+    /**
+     * @type array
+     */
     public $elements = array('script', 'noscript');
+
+    /**
+     * @type array
+     */
     public $content_sets = array('Block' => 'script | noscript', 'Inline' => 'script | noscript');
+
+    /**
+     * @type bool
+     */
     public $safe = false;
 
-    public function setup($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         // TODO: create custom child-definition for noscript that
         // auto-wraps stray #PCDATA in a similar manner to
         // blockquote's custom definition (we would use it but
@@ -33,20 +52,20 @@ class HTMLPurifier_HTMLModule_Scripting extends HTMLPurifier_HTMLModule
         // In theory, this could be safe, but I don't see any reason to
         // allow it.
         $this->info['noscript'] = new HTMLPurifier_ElementDef();
-        $this->info['noscript']->attr = array( 0 => array('Common') );
+        $this->info['noscript']->attr = array(0 => array('Common'));
         $this->info['noscript']->content_model = 'Heading | List | Block';
         $this->info['noscript']->content_model_type = 'required';
 
         $this->info['script'] = new HTMLPurifier_ElementDef();
         $this->info['script']->attr = array(
             'defer' => new HTMLPurifier_AttrDef_Enum(array('defer')),
-            'src'   => new HTMLPurifier_AttrDef_URI(true),
-            'type'  => new HTMLPurifier_AttrDef_Enum(array('text/javascript'))
+            'src' => new HTMLPurifier_AttrDef_URI(true),
+            'type' => new HTMLPurifier_AttrDef_Enum(array('text/javascript'))
         );
         $this->info['script']->content_model = '#PCDATA';
         $this->info['script']->content_model_type = 'optional';
-        $this->info['script']->attr_transform_pre['type'] =
-        $this->info['script']->attr_transform_post['type'] =
+        $this->info['script']->attr_transform_pre[] =
+        $this->info['script']->attr_transform_post[] =
             new HTMLPurifier_AttrTransform_ScriptRequired();
     }
 }
diff --git a/library/HTMLPurifier/HTMLModule/StyleAttribute.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/StyleAttribute.php
similarity index 78%
rename from library/HTMLPurifier/HTMLModule/StyleAttribute.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/StyleAttribute.php
index eb78464cc0..497b832ae2 100644
--- a/library/HTMLPurifier/HTMLModule/StyleAttribute.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/StyleAttribute.php
@@ -6,8 +6,14 @@
  */
 class HTMLPurifier_HTMLModule_StyleAttribute extends HTMLPurifier_HTMLModule
 {
-
+    /**
+     * @type string
+     */
     public $name = 'StyleAttribute';
+
+    /**
+     * @type array
+     */
     public $attr_collections = array(
         // The inclusion routine differs from the Abstract Modules but
         // is in line with the DTD and XML Schemas.
@@ -15,10 +21,13 @@ class HTMLPurifier_HTMLModule_StyleAttribute extends HTMLPurifier_HTMLModule
         'Core' => array(0 => array('Style'))
     );
 
-    public function setup($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         $this->attr_collections['Style']['style'] = new HTMLPurifier_AttrDef_CSS();
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Tables.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tables.php
similarity index 75%
rename from library/HTMLPurifier/HTMLModule/Tables.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tables.php
index f314ced3f8..8a0b3b4616 100644
--- a/library/HTMLPurifier/HTMLModule/Tables.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tables.php
@@ -5,15 +5,23 @@
  */
 class HTMLPurifier_HTMLModule_Tables extends HTMLPurifier_HTMLModule
 {
-
+    /**
+     * @type string
+     */
     public $name = 'Tables';
 
-    public function setup($config) {
-
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         $this->addElement('caption', false, 'Inline', 'Common');
 
-        $this->addElement('table', 'Block',
-            new HTMLPurifier_ChildDef_Table(),  'Common',
+        $this->addElement(
+            'table',
+            'Block',
+            new HTMLPurifier_ChildDef_Table(),
+            'Common',
             array(
                 'border' => 'Pixels',
                 'cellpadding' => 'Length',
@@ -34,9 +42,12 @@ class HTMLPurifier_HTMLModule_Tables extends HTMLPurifier_HTMLModule
 
         $cell_t = array_merge(
             array(
-                'abbr'    => 'Text',
+                'abbr' => 'Text',
                 'colspan' => 'Number',
                 'rowspan' => 'Number',
+                // Apparently, as of HTML5 this attribute only applies
+                // to 'th' elements.
+                'scope' => 'Enum#row,col,rowgroup,colgroup',
             ),
             $cell_align
         );
@@ -47,20 +58,18 @@ class HTMLPurifier_HTMLModule_Tables extends HTMLPurifier_HTMLModule
 
         $cell_col = array_merge(
             array(
-                'span'  => 'Number',
+                'span' => 'Number',
                 'width' => 'MultiLength',
             ),
             $cell_align
         );
-        $this->addElement('col',      false, 'Empty',         'Common', $cell_col);
+        $this->addElement('col', false, 'Empty', 'Common', $cell_col);
         $this->addElement('colgroup', false, 'Optional: col', 'Common', $cell_col);
 
         $this->addElement('tbody', false, 'Required: tr', 'Common', $cell_align);
         $this->addElement('thead', false, 'Required: tr', 'Common', $cell_align);
         $this->addElement('tfoot', false, 'Required: tr', 'Common', $cell_align);
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Target.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Target.php
similarity index 77%
rename from library/HTMLPurifier/HTMLModule/Target.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Target.php
index 2b844ecc45..b188ac9369 100644
--- a/library/HTMLPurifier/HTMLModule/Target.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Target.php
@@ -5,10 +5,16 @@
  */
 class HTMLPurifier_HTMLModule_Target extends HTMLPurifier_HTMLModule
 {
-
+    /**
+     * @type string
+     */
     public $name = 'Target';
 
-    public function setup($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         $elements = array('a');
         foreach ($elements as $name) {
             $e = $this->addBlankElement($name);
@@ -17,7 +23,6 @@ class HTMLPurifier_HTMLModule_Target extends HTMLPurifier_HTMLModule
             );
         }
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetBlank.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetBlank.php
new file mode 100644
index 0000000000..58ccc68941
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/TargetBlank.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * Module adds the target=blank attribute transformation to a tags.  It
+ * is enabled by HTML.TargetBlank
+ */
+class HTMLPurifier_HTMLModule_TargetBlank extends HTMLPurifier_HTMLModule
+{
+    /**
+     * @type string
+     */
+    public $name = 'TargetBlank';
+
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
+        $a = $this->addBlankElement('a');
+        $a->attr_transform_post[] = new HTMLPurifier_AttrTransform_TargetBlank();
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Text.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Text.php
similarity index 58%
rename from library/HTMLPurifier/HTMLModule/Text.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Text.php
index ae77c71886..7a65e0048f 100644
--- a/library/HTMLPurifier/HTMLModule/Text.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Text.php
@@ -14,43 +14,59 @@
  */
 class HTMLPurifier_HTMLModule_Text extends HTMLPurifier_HTMLModule
 {
-
+    /**
+     * @type string
+     */
     public $name = 'Text';
+
+    /**
+     * @type array
+     */
     public $content_sets = array(
         'Flow' => 'Heading | Block | Inline'
     );
 
-    public function setup($config) {
-
+    /**
+     * @param HTMLPurifier_Config $config
+     */
+    public function setup($config)
+    {
         // Inline Phrasal -------------------------------------------------
-        $this->addElement('abbr',    'Inline', 'Inline', 'Common');
+        $this->addElement('abbr', 'Inline', 'Inline', 'Common');
         $this->addElement('acronym', 'Inline', 'Inline', 'Common');
-        $this->addElement('cite',    'Inline', 'Inline', 'Common');
-        $this->addElement('dfn',     'Inline', 'Inline', 'Common');
-        $this->addElement('kbd',     'Inline', 'Inline', 'Common');
-        $this->addElement('q',       'Inline', 'Inline', 'Common', array('cite' => 'URI'));
-        $this->addElement('samp',    'Inline', 'Inline', 'Common');
-        $this->addElement('var',     'Inline', 'Inline', 'Common');
+        $this->addElement('cite', 'Inline', 'Inline', 'Common');
+        $this->addElement('dfn', 'Inline', 'Inline', 'Common');
+        $this->addElement('kbd', 'Inline', 'Inline', 'Common');
+        $this->addElement('q', 'Inline', 'Inline', 'Common', array('cite' => 'URI'));
+        $this->addElement('samp', 'Inline', 'Inline', 'Common');
+        $this->addElement('var', 'Inline', 'Inline', 'Common');
 
-        $em = $this->addElement('em',      'Inline', 'Inline', 'Common');
+        $em = $this->addElement('em', 'Inline', 'Inline', 'Common');
         $em->formatting = true;
 
-        $strong = $this->addElement('strong',  'Inline', 'Inline', 'Common');
+        $strong = $this->addElement('strong', 'Inline', 'Inline', 'Common');
         $strong->formatting = true;
 
-        $code = $this->addElement('code',    'Inline', 'Inline', 'Common');
+        $code = $this->addElement('code', 'Inline', 'Inline', 'Common');
         $code->formatting = true;
 
         // Inline Structural ----------------------------------------------
         $this->addElement('span', 'Inline', 'Inline', 'Common');
-        $this->addElement('br',   'Inline', 'Empty',  'Core');
+        $this->addElement('br', 'Inline', 'Empty', 'Core');
 
         // Block Phrasal --------------------------------------------------
-        $this->addElement('address',     'Block', 'Inline', 'Common');
-        $this->addElement('blockquote',  'Block', 'Optional: Heading | Block | List', 'Common', array('cite' => 'URI') );
+        $this->addElement('address', 'Block', 'Inline', 'Common');
+        $this->addElement('blockquote', 'Block', 'Optional: Heading | Block | List', 'Common', array('cite' => 'URI'));
         $pre = $this->addElement('pre', 'Block', 'Inline', 'Common');
         $pre->excludes = $this->makeLookup(
-            'img', 'big', 'small', 'object', 'applet', 'font', 'basefont' );
+            'img',
+            'big',
+            'small',
+            'object',
+            'applet',
+            'font',
+            'basefont'
+        );
         $this->addElement('h1', 'Heading', 'Inline', 'Common');
         $this->addElement('h2', 'Heading', 'Inline', 'Common');
         $this->addElement('h3', 'Heading', 'Inline', 'Common');
@@ -60,12 +76,12 @@ class HTMLPurifier_HTMLModule_Text extends HTMLPurifier_HTMLModule
 
         // Block Structural -----------------------------------------------
         $p = $this->addElement('p', 'Block', 'Inline', 'Common');
-        $p->autoclose = array_flip(array("address", "blockquote", "center", "dir", "div", "dl", "fieldset", "ol", "p", "ul"));
+        $p->autoclose = array_flip(
+            array("address", "blockquote", "center", "dir", "div", "dl", "fieldset", "ol", "p", "ul")
+        );
 
         $this->addElement('div', 'Block', 'Flow', 'Common');
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Tidy.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php
similarity index 78%
rename from library/HTMLPurifier/HTMLModule/Tidy.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php
index 21783f18eb..08aa232470 100644
--- a/library/HTMLPurifier/HTMLModule/Tidy.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy.php
@@ -7,36 +7,41 @@
  */
 class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule
 {
-
     /**
-     * List of supported levels. Index zero is a special case "no fixes"
-     * level.
+     * List of supported levels.
+     * Index zero is a special case "no fixes" level.
+     * @type array
      */
     public $levels = array(0 => 'none', 'light', 'medium', 'heavy');
 
     /**
-     * Default level to place all fixes in. Disabled by default
+     * Default level to place all fixes in.
+     * Disabled by default.
+     * @type string
      */
     public $defaultLevel = null;
 
     /**
-     * Lists of fixes used by getFixesForLevel(). Format is:
+     * Lists of fixes used by getFixesForLevel().
+     * Format is:
      *      HTMLModule_Tidy->fixesForLevel[$level] = array('fix-1', 'fix-2');
+     * @type array
      */
     public $fixesForLevel = array(
-        'light'  => array(),
+        'light' => array(),
         'medium' => array(),
-        'heavy'  => array()
+        'heavy' => array()
     );
 
     /**
      * Lazy load constructs the module by determining the necessary
      * fixes to create and then delegating to the populate() function.
+     * @param HTMLPurifier_Config $config
      * @todo Wildcard matching and error reporting when an added or
      *       subtracted fix has no effect.
      */
-    public function setup($config) {
-
+    public function setup($config)
+    {
         // create fixes, initialize fixesForLevel
         $fixes = $this->makeFixes();
         $this->makeFixesForLevel($fixes);
@@ -46,38 +51,38 @@ class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule
         $fixes_lookup = $this->getFixesForLevel($level);
 
         // get custom fix declarations: these need namespace processing
-        $add_fixes    = $config->get('HTML.TidyAdd');
+        $add_fixes = $config->get('HTML.TidyAdd');
         $remove_fixes = $config->get('HTML.TidyRemove');
 
         foreach ($fixes as $name => $fix) {
             // needs to be refactored a little to implement globbing
-            if (
-                isset($remove_fixes[$name]) ||
-                (!isset($add_fixes[$name]) && !isset($fixes_lookup[$name]))
-            ) {
+            if (isset($remove_fixes[$name]) ||
+                (!isset($add_fixes[$name]) && !isset($fixes_lookup[$name]))) {
                 unset($fixes[$name]);
             }
         }
 
         // populate this module with necessary fixes
         $this->populate($fixes);
-
     }
 
     /**
      * Retrieves all fixes per a level, returning fixes for that specific
      * level as well as all levels below it.
-     * @param $level String level identifier, see $levels for valid values
-     * @return Lookup up table of fixes
+     * @param string $level level identifier, see $levels for valid values
+     * @return array Lookup up table of fixes
      */
-    public function getFixesForLevel($level) {
+    public function getFixesForLevel($level)
+    {
         if ($level == $this->levels[0]) {
             return array();
         }
         $activated_levels = array();
         for ($i = 1, $c = count($this->levels); $i < $c; $i++) {
             $activated_levels[] = $this->levels[$i];
-            if ($this->levels[$i] == $level) break;
+            if ($this->levels[$i] == $level) {
+                break;
+            }
         }
         if ($i == $c) {
             trigger_error(
@@ -99,9 +104,13 @@ class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule
      * Dynamically populates the $fixesForLevel member variable using
      * the fixes array. It may be custom overloaded, used in conjunction
      * with $defaultLevel, or not used at all.
+     * @param array $fixes
      */
-    public function makeFixesForLevel($fixes) {
-        if (!isset($this->defaultLevel)) return;
+    public function makeFixesForLevel($fixes)
+    {
+        if (!isset($this->defaultLevel)) {
+            return;
+        }
         if (!isset($this->fixesForLevel[$this->defaultLevel])) {
             trigger_error(
                 'Default level ' . $this->defaultLevel . ' does not exist',
@@ -115,9 +124,10 @@ class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule
     /**
      * Populates the module with transforms and other special-case code
      * based on a list of fixes passed to it
-     * @param $lookup Lookup table of fixes to activate
+     * @param array $fixes Lookup table of fixes to activate
      */
-    public function populate($fixes) {
+    public function populate($fixes)
+    {
         foreach ($fixes as $name => $fix) {
             // determine what the fix is for
             list($type, $params) = $this->getFixType($name);
@@ -169,20 +179,31 @@ class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule
      * @note $fix_parameters is type dependant, see populate() for usage
      *       of these parameters
      */
-    public function getFixType($name) {
+    public function getFixType($name)
+    {
         // parse it
         $property = $attr = null;
-        if (strpos($name, '#') !== false) list($name, $property) = explode('#', $name);
-        if (strpos($name, '@') !== false) list($name, $attr)     = explode('@', $name);
+        if (strpos($name, '#') !== false) {
+            list($name, $property) = explode('#', $name);
+        }
+        if (strpos($name, '@') !== false) {
+            list($name, $attr) = explode('@', $name);
+        }
 
         // figure out the parameters
         $params = array();
-        if ($name !== '')    $params['element'] = $name;
-        if (!is_null($attr)) $params['attr'] = $attr;
+        if ($name !== '') {
+            $params['element'] = $name;
+        }
+        if (!is_null($attr)) {
+            $params['attr'] = $attr;
+        }
 
         // special case: attribute transform
         if (!is_null($attr)) {
-            if (is_null($property)) $property = 'pre';
+            if (is_null($property)) {
+                $property = 'pre';
+            }
             $type = 'attr_transform_' . $property;
             return array($type, $params);
         }
@@ -199,9 +220,11 @@ class HTMLPurifier_HTMLModule_Tidy extends HTMLPurifier_HTMLModule
     /**
      * Defines all fixes the module will perform in a compact
      * associative array of fix name to fix implementation.
+     * @return array
      */
-    public function makeFixes() {}
-
+    public function makeFixes()
+    {
+    }
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Tidy/Name.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php
similarity index 80%
rename from library/HTMLPurifier/HTMLModule/Tidy/Name.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php
index 61ff85ce2f..a995161b28 100644
--- a/library/HTMLPurifier/HTMLModule/Tidy/Name.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Name.php
@@ -5,18 +5,27 @@
  */
 class HTMLPurifier_HTMLModule_Tidy_Name extends HTMLPurifier_HTMLModule_Tidy
 {
+    /**
+     * @type string
+     */
     public $name = 'Tidy_Name';
+
+    /**
+     * @type string
+     */
     public $defaultLevel = 'heavy';
-    public function makeFixes() {
 
+    /**
+     * @return array
+     */
+    public function makeFixes()
+    {
         $r = array();
-
         // @name for img, a -----------------------------------------------
         // Technically, it's allowed even on strict, so we allow authors to use
         // it. However, it's deprecated in future versions of XHTML.
         $r['img@name'] =
         $r['a@name'] = new HTMLPurifier_AttrTransform_Name();
-
         return $r;
     }
 }
diff --git a/library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php
similarity index 85%
rename from library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php
index 14c15c4a06..3326438216 100644
--- a/library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Proprietary.php
@@ -3,10 +3,21 @@
 class HTMLPurifier_HTMLModule_Tidy_Proprietary extends HTMLPurifier_HTMLModule_Tidy
 {
 
+    /**
+     * @type string
+     */
     public $name = 'Tidy_Proprietary';
+
+    /**
+     * @type string
+     */
     public $defaultLevel = 'light';
 
-    public function makeFixes() {
+    /**
+     * @return array
+     */
+    public function makeFixes()
+    {
         $r = array();
         $r['table@background'] = new HTMLPurifier_AttrTransform_Background();
         $r['td@background']    = new HTMLPurifier_AttrTransform_Background();
@@ -18,7 +29,6 @@ class HTMLPurifier_HTMLModule_Tidy_Proprietary extends HTMLPurifier_HTMLModule_T
         $r['table@height']     = new HTMLPurifier_AttrTransform_Length('height');
         return $r;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Strict.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Strict.php
new file mode 100644
index 0000000000..803c44fabd
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Strict.php
@@ -0,0 +1,43 @@
+<?php
+
+class HTMLPurifier_HTMLModule_Tidy_Strict extends HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4
+{
+    /**
+     * @type string
+     */
+    public $name = 'Tidy_Strict';
+
+    /**
+     * @type string
+     */
+    public $defaultLevel = 'light';
+
+    /**
+     * @return array
+     */
+    public function makeFixes()
+    {
+        $r = parent::makeFixes();
+        $r['blockquote#content_model_type'] = 'strictblockquote';
+        return $r;
+    }
+
+    /**
+     * @type bool
+     */
+    public $defines_child_def = true;
+
+    /**
+     * @param HTMLPurifier_ElementDef $def
+     * @return HTMLPurifier_ChildDef_StrictBlockquote
+     */
+    public function getChildDef($def)
+    {
+        if ($def->content_model_type != 'strictblockquote') {
+            return parent::getChildDef($def);
+        }
+        return new HTMLPurifier_ChildDef_StrictBlockquote($def->content_model);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php
similarity index 74%
rename from library/HTMLPurifier/HTMLModule/Tidy/Transitional.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php
index 9960b1dd10..c095ad9745 100644
--- a/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/Transitional.php
@@ -2,7 +2,14 @@
 
 class HTMLPurifier_HTMLModule_Tidy_Transitional extends HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4
 {
+    /**
+     * @type string
+     */
     public $name = 'Tidy_Transitional';
+
+    /**
+     * @type string
+     */
     public $defaultLevel = 'heavy';
 }
 
diff --git a/library/HTMLPurifier/HTMLModule/Tidy/XHTML.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTML.php
similarity index 66%
rename from library/HTMLPurifier/HTMLModule/Tidy/XHTML.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTML.php
index db5a378e53..3ecddc434b 100644
--- a/library/HTMLPurifier/HTMLModule/Tidy/XHTML.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTML.php
@@ -2,16 +2,25 @@
 
 class HTMLPurifier_HTMLModule_Tidy_XHTML extends HTMLPurifier_HTMLModule_Tidy
 {
-
+    /**
+     * @type string
+     */
     public $name = 'Tidy_XHTML';
+
+    /**
+     * @type string
+     */
     public $defaultLevel = 'medium';
 
-    public function makeFixes() {
+    /**
+     * @return array
+     */
+    public function makeFixes()
+    {
         $r = array();
         $r['@lang'] = new HTMLPurifier_AttrTransform_Lang();
         return $r;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php
similarity index 50%
rename from library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php
index 02e9438139..c4f16a4dc9 100644
--- a/library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/Tidy/XHTMLAndHTML4.php
@@ -3,69 +3,86 @@
 class HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4 extends HTMLPurifier_HTMLModule_Tidy
 {
 
-    public function makeFixes() {
-
+    /**
+     * @return array
+     */
+    public function makeFixes()
+    {
         $r = array();
 
         // == deprecated tag transforms ===================================
 
-        $r['font']   = new HTMLPurifier_TagTransform_Font();
-        $r['menu']   = new HTMLPurifier_TagTransform_Simple('ul');
-        $r['dir']    = new HTMLPurifier_TagTransform_Simple('ul');
-        $r['center'] = new HTMLPurifier_TagTransform_Simple('div',  'text-align:center;');
-        $r['u']      = new HTMLPurifier_TagTransform_Simple('span', 'text-decoration:underline;');
-        $r['s']      = new HTMLPurifier_TagTransform_Simple('span', 'text-decoration:line-through;');
+        $r['font'] = new HTMLPurifier_TagTransform_Font();
+        $r['menu'] = new HTMLPurifier_TagTransform_Simple('ul');
+        $r['dir'] = new HTMLPurifier_TagTransform_Simple('ul');
+        $r['center'] = new HTMLPurifier_TagTransform_Simple('div', 'text-align:center;');
+        $r['u'] = new HTMLPurifier_TagTransform_Simple('span', 'text-decoration:underline;');
+        $r['s'] = new HTMLPurifier_TagTransform_Simple('span', 'text-decoration:line-through;');
         $r['strike'] = new HTMLPurifier_TagTransform_Simple('span', 'text-decoration:line-through;');
 
         // == deprecated attribute transforms =============================
 
         $r['caption@align'] =
-            new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
-                // we're following IE's behavior, not Firefox's, due
-                // to the fact that no one supports caption-side:right,
-                // W3C included (with CSS 2.1). This is a slightly
-                // unreasonable attribute!
-                'left'   => 'text-align:left;',
-                'right'  => 'text-align:right;',
-                'top'    => 'caption-side:top;',
-                'bottom' => 'caption-side:bottom;' // not supported by IE
-            ));
+            new HTMLPurifier_AttrTransform_EnumToCSS(
+                'align',
+                array(
+                    // we're following IE's behavior, not Firefox's, due
+                    // to the fact that no one supports caption-side:right,
+                    // W3C included (with CSS 2.1). This is a slightly
+                    // unreasonable attribute!
+                    'left' => 'text-align:left;',
+                    'right' => 'text-align:right;',
+                    'top' => 'caption-side:top;',
+                    'bottom' => 'caption-side:bottom;' // not supported by IE
+                )
+            );
 
         // @align for img -------------------------------------------------
         $r['img@align'] =
-            new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
-                'left'   => 'float:left;',
-                'right'  => 'float:right;',
-                'top'    => 'vertical-align:top;',
-                'middle' => 'vertical-align:middle;',
-                'bottom' => 'vertical-align:baseline;',
-            ));
+            new HTMLPurifier_AttrTransform_EnumToCSS(
+                'align',
+                array(
+                    'left' => 'float:left;',
+                    'right' => 'float:right;',
+                    'top' => 'vertical-align:top;',
+                    'middle' => 'vertical-align:middle;',
+                    'bottom' => 'vertical-align:baseline;',
+                )
+            );
 
         // @align for table -----------------------------------------------
         $r['table@align'] =
-            new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
-                'left'   => 'float:left;',
-                'center' => 'margin-left:auto;margin-right:auto;',
-                'right'  => 'float:right;'
-            ));
+            new HTMLPurifier_AttrTransform_EnumToCSS(
+                'align',
+                array(
+                    'left' => 'float:left;',
+                    'center' => 'margin-left:auto;margin-right:auto;',
+                    'right' => 'float:right;'
+                )
+            );
 
         // @align for hr -----------------------------------------------
         $r['hr@align'] =
-            new HTMLPurifier_AttrTransform_EnumToCSS('align', array(
-                // we use both text-align and margin because these work
-                // for different browsers (IE and Firefox, respectively)
-                // and the melange makes for a pretty cross-compatible
-                // solution
-                'left'   => 'margin-left:0;margin-right:auto;text-align:left;',
-                'center' => 'margin-left:auto;margin-right:auto;text-align:center;',
-                'right'  => 'margin-left:auto;margin-right:0;text-align:right;'
-            ));
+            new HTMLPurifier_AttrTransform_EnumToCSS(
+                'align',
+                array(
+                    // we use both text-align and margin because these work
+                    // for different browsers (IE and Firefox, respectively)
+                    // and the melange makes for a pretty cross-compatible
+                    // solution
+                    'left' => 'margin-left:0;margin-right:auto;text-align:left;',
+                    'center' => 'margin-left:auto;margin-right:auto;text-align:center;',
+                    'right' => 'margin-left:auto;margin-right:0;text-align:right;'
+                )
+            );
 
         // @align for h1, h2, h3, h4, h5, h6, p, div ----------------------
         // {{{
-            $align_lookup = array();
-            $align_values = array('left', 'right', 'center', 'justify');
-            foreach ($align_values as $v) $align_lookup[$v] = "text-align:$v;";
+        $align_lookup = array();
+        $align_values = array('left', 'right', 'center', 'justify');
+        foreach ($align_values as $v) {
+            $align_lookup[$v] = "text-align:$v;";
+        }
         // }}}
         $r['h1@align'] =
         $r['h2@align'] =
@@ -73,7 +90,7 @@ class HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4 extends HTMLPurifier_HTMLModule
         $r['h4@align'] =
         $r['h5@align'] =
         $r['h6@align'] =
-        $r['p@align']  =
+        $r['p@align'] =
         $r['div@align'] =
             new HTMLPurifier_AttrTransform_EnumToCSS('align', $align_lookup);
 
@@ -88,12 +105,15 @@ class HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4 extends HTMLPurifier_HTMLModule
 
         // @clear for br --------------------------------------------------
         $r['br@clear'] =
-            new HTMLPurifier_AttrTransform_EnumToCSS('clear', array(
-                'left'  => 'clear:left;',
-                'right' => 'clear:right;',
-                'all'   => 'clear:both;',
-                'none'  => 'clear:none;',
-            ));
+            new HTMLPurifier_AttrTransform_EnumToCSS(
+                'clear',
+                array(
+                    'left' => 'clear:left;',
+                    'right' => 'clear:right;',
+                    'all' => 'clear:both;',
+                    'none' => 'clear:none;',
+                )
+            );
 
         // @height for td, th ---------------------------------------------
         $r['td@height'] =
@@ -125,19 +145,19 @@ class HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4 extends HTMLPurifier_HTMLModule
 
         // @type for li, ol, ul -------------------------------------------
         // {{{
-            $ul_types = array(
-                'disc'   => 'list-style-type:disc;',
-                'square' => 'list-style-type:square;',
-                'circle' => 'list-style-type:circle;'
-            );
-            $ol_types = array(
-                '1'   => 'list-style-type:decimal;',
-                'i'   => 'list-style-type:lower-roman;',
-                'I'   => 'list-style-type:upper-roman;',
-                'a'   => 'list-style-type:lower-alpha;',
-                'A'   => 'list-style-type:upper-alpha;'
-            );
-            $li_types = $ul_types + $ol_types;
+        $ul_types = array(
+            'disc' => 'list-style-type:disc;',
+            'square' => 'list-style-type:square;',
+            'circle' => 'list-style-type:circle;'
+        );
+        $ol_types = array(
+            '1' => 'list-style-type:decimal;',
+            'i' => 'list-style-type:lower-roman;',
+            'I' => 'list-style-type:upper-roman;',
+            'a' => 'list-style-type:lower-alpha;',
+            'A' => 'list-style-type:upper-alpha;'
+        );
+        $li_types = $ul_types + $ol_types;
         // }}}
 
         $r['ul@type'] = new HTMLPurifier_AttrTransform_EnumToCSS('type', $ul_types);
@@ -153,9 +173,7 @@ class HTMLPurifier_HTMLModule_Tidy_XHTMLAndHTML4 extends HTMLPurifier_HTMLModule
         $r['hr@width'] = new HTMLPurifier_AttrTransform_Length('width');
 
         return $r;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php
similarity index 79%
rename from library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php
index 9c0e031984..01dbe9deb6 100644
--- a/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModule/XMLCommonAttributes.php
@@ -2,8 +2,14 @@
 
 class HTMLPurifier_HTMLModule_XMLCommonAttributes extends HTMLPurifier_HTMLModule
 {
+    /**
+     * @type string
+     */
     public $name = 'XMLCommonAttributes';
 
+    /**
+     * @type array
+     */
     public $attr_collections = array(
         'Lang' => array(
             'xml:lang' => 'LanguageCode',
diff --git a/library/HTMLPurifier/HTMLModuleManager.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModuleManager.php
similarity index 75%
rename from library/HTMLPurifier/HTMLModuleManager.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModuleManager.php
index f5c4a1d2cb..f3a17cb03b 100644
--- a/library/HTMLPurifier/HTMLModuleManager.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/HTMLModuleManager.php
@@ -4,57 +4,75 @@ class HTMLPurifier_HTMLModuleManager
 {
 
     /**
-     * Instance of HTMLPurifier_DoctypeRegistry
+     * @type HTMLPurifier_DoctypeRegistry
      */
     public $doctypes;
 
     /**
-     * Instance of current doctype
+     * Instance of current doctype.
+     * @type string
      */
     public $doctype;
 
     /**
-     * Instance of HTMLPurifier_AttrTypes
+     * @type HTMLPurifier_AttrTypes
      */
     public $attrTypes;
 
     /**
      * Active instances of modules for the specified doctype are
      * indexed, by name, in this array.
+     * @type HTMLPurifier_HTMLModule[]
      */
     public $modules = array();
 
     /**
-     * Array of recognized HTMLPurifier_Module instances, indexed by
-     * module's class name. This array is usually lazy loaded, but a
+     * Array of recognized HTMLPurifier_HTMLModule instances,
+     * indexed by module's class name. This array is usually lazy loaded, but a
      * user can overload a module by pre-emptively registering it.
+     * @type HTMLPurifier_HTMLModule[]
      */
     public $registeredModules = array();
 
     /**
-     * List of extra modules that were added by the user using addModule().
-     * These get unconditionally merged into the current doctype, whatever
+     * List of extra modules that were added by the user
+     * using addModule(). These get unconditionally merged into the current doctype, whatever
      * it may be.
+     * @type HTMLPurifier_HTMLModule[]
      */
     public $userModules = array();
 
     /**
      * Associative array of element name to list of modules that have
      * definitions for the element; this array is dynamically filled.
+     * @type array
      */
     public $elementLookup = array();
 
-    /** List of prefixes we should use for registering small names */
+    /**
+     * List of prefixes we should use for registering small names.
+     * @type array
+     */
     public $prefixes = array('HTMLPurifier_HTMLModule_');
 
-    public $contentSets;     /**< Instance of HTMLPurifier_ContentSets */
-    public $attrCollections; /**< Instance of HTMLPurifier_AttrCollections */
+    /**
+     * @type HTMLPurifier_ContentSets
+     */
+    public $contentSets;
 
-    /** If set to true, unsafe elements and attributes will be allowed */
+    /**
+     * @type HTMLPurifier_AttrCollections
+     */
+    public $attrCollections;
+
+    /**
+     * If set to true, unsafe elements and attributes will be allowed.
+     * @type bool
+     */
     public $trusted = false;
 
-    public function __construct() {
-
+    public function __construct()
+    {
         // editable internal objects
         $this->attrTypes = new HTMLPurifier_AttrTypes();
         $this->doctypes  = new HTMLPurifier_DoctypeRegistry();
@@ -65,17 +83,18 @@ class HTMLPurifier_HTMLModuleManager
             'Presentation', 'Edit', 'Bdo', 'Tables', 'Image',
             'StyleAttribute',
             // Unsafe:
-            'Scripting', 'Object',  'Forms',
+            'Scripting', 'Object', 'Forms',
             // Sorta legacy, but present in strict:
             'Name',
         );
-        $transitional = array('Legacy', 'Target');
+        $transitional = array('Legacy', 'Target', 'Iframe');
         $xml = array('XMLCommonAttributes');
         $non_xml = array('NonXMLCommonAttributes');
 
         // setup basic doctypes
         $this->doctypes->register(
-            'HTML 4.01 Transitional', false,
+            'HTML 4.01 Transitional',
+            false,
             array_merge($common, $transitional, $non_xml),
             array('Tidy_Transitional', 'Tidy_Proprietary'),
             array(),
@@ -84,7 +103,8 @@ class HTMLPurifier_HTMLModuleManager
         );
 
         $this->doctypes->register(
-            'HTML 4.01 Strict', false,
+            'HTML 4.01 Strict',
+            false,
             array_merge($common, $non_xml),
             array('Tidy_Strict', 'Tidy_Proprietary', 'Tidy_Name'),
             array(),
@@ -93,7 +113,8 @@ class HTMLPurifier_HTMLModuleManager
         );
 
         $this->doctypes->register(
-            'XHTML 1.0 Transitional', true,
+            'XHTML 1.0 Transitional',
+            true,
             array_merge($common, $transitional, $xml, $non_xml),
             array('Tidy_Transitional', 'Tidy_XHTML', 'Tidy_Proprietary', 'Tidy_Name'),
             array(),
@@ -102,7 +123,8 @@ class HTMLPurifier_HTMLModuleManager
         );
 
         $this->doctypes->register(
-            'XHTML 1.0 Strict', true,
+            'XHTML 1.0 Strict',
+            true,
             array_merge($common, $xml, $non_xml),
             array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_Strict', 'Tidy_Proprietary', 'Tidy_Name'),
             array(),
@@ -111,8 +133,11 @@ class HTMLPurifier_HTMLModuleManager
         );
 
         $this->doctypes->register(
-            'XHTML 1.1', true,
-            array_merge($common, $xml, array('Ruby')),
+            'XHTML 1.1',
+            true,
+            // Iframe is a real XHTML 1.1 module, despite being
+            // "transitional"!
+            array_merge($common, $xml, array('Ruby', 'Iframe')),
             array('Tidy_Strict', 'Tidy_XHTML', 'Tidy_Proprietary', 'Tidy_Strict', 'Tidy_Name'), // Tidy_XHTML1_1
             array(),
             '-//W3C//DTD XHTML 1.1//EN',
@@ -142,7 +167,8 @@ class HTMLPurifier_HTMLModuleManager
      *       your module manually. All modules must have been included
      *       externally: registerModule will not perform inclusions for you!
      */
-    public function registerModule($module, $overload = false) {
+    public function registerModule($module, $overload = false)
+    {
         if (is_string($module)) {
             // attempt to load the module
             $original_module = $module;
@@ -157,8 +183,10 @@ class HTMLPurifier_HTMLModuleManager
             if (!$ok) {
                 $module = $original_module;
                 if (!class_exists($module)) {
-                    trigger_error($original_module . ' module does not exist',
-                        E_USER_ERROR);
+                    trigger_error(
+                        $original_module . ' module does not exist',
+                        E_USER_ERROR
+                    );
                     return;
                 }
             }
@@ -178,9 +206,12 @@ class HTMLPurifier_HTMLModuleManager
      * Adds a module to the current doctype by first registering it,
      * and then tacking it on to the active doctype
      */
-    public function addModule($module) {
+    public function addModule($module)
+    {
         $this->registerModule($module);
-        if (is_object($module)) $module = $module->name;
+        if (is_object($module)) {
+            $module = $module->name;
+        }
         $this->userModules[] = $module;
     }
 
@@ -188,17 +219,18 @@ class HTMLPurifier_HTMLModuleManager
      * Adds a class prefix that registerModule() will use to resolve a
      * string name to a concrete class
      */
-    public function addPrefix($prefix) {
+    public function addPrefix($prefix)
+    {
         $this->prefixes[] = $prefix;
     }
 
     /**
      * Performs processing on modules, after being called you may
      * use getElement() and getElements()
-     * @param $config Instance of HTMLPurifier_Config
+     * @param HTMLPurifier_Config $config
      */
-    public function setup($config) {
-
+    public function setup($config)
+    {
         $this->trusted = $config->get('HTML.Trusted');
 
         // generate
@@ -211,24 +243,34 @@ class HTMLPurifier_HTMLModuleManager
 
         if (is_array($lookup)) {
             foreach ($modules as $k => $m) {
-                if (isset($special_cases[$m])) continue;
-                if (!isset($lookup[$m])) unset($modules[$k]);
+                if (isset($special_cases[$m])) {
+                    continue;
+                }
+                if (!isset($lookup[$m])) {
+                    unset($modules[$k]);
+                }
             }
         }
 
-        // add proprietary module (this gets special treatment because
-        // it is completely removed from doctypes, etc.)
+        // custom modules
         if ($config->get('HTML.Proprietary')) {
             $modules[] = 'Proprietary';
         }
-
-        // add SafeObject/Safeembed modules
         if ($config->get('HTML.SafeObject')) {
             $modules[] = 'SafeObject';
         }
         if ($config->get('HTML.SafeEmbed')) {
             $modules[] = 'SafeEmbed';
         }
+        if ($config->get('HTML.SafeScripting') !== array()) {
+            $modules[] = 'SafeScripting';
+        }
+        if ($config->get('HTML.Nofollow')) {
+            $modules[] = 'Nofollow';
+        }
+        if ($config->get('HTML.TargetBlank')) {
+            $modules[] = 'TargetBlank';
+        }
 
         // merge in custom modules
         $modules = array_merge($modules, $this->userModules);
@@ -246,7 +288,7 @@ class HTMLPurifier_HTMLModuleManager
         // prepare any injectors
         foreach ($this->modules as $module) {
             $n = array();
-            foreach ($module->info_injector as $i => $injector) {
+            foreach ($module->info_injector as $injector) {
                 if (!is_object($injector)) {
                     $class = "HTMLPurifier_Injector_$injector";
                     $injector = new $class;
@@ -285,7 +327,8 @@ class HTMLPurifier_HTMLModuleManager
      * Takes a module and adds it to the active module collection,
      * registering it if necessary.
      */
-    public function processModule($module) {
+    public function processModule($module)
+    {
         if (!isset($this->registeredModules[$module]) || is_object($module)) {
             $this->registerModule($module);
         }
@@ -296,13 +339,17 @@ class HTMLPurifier_HTMLModuleManager
      * Retrieves merged element definitions.
      * @return Array of HTMLPurifier_ElementDef
      */
-    public function getElements() {
-
+    public function getElements()
+    {
         $elements = array();
         foreach ($this->modules as $module) {
-            if (!$this->trusted && !$module->safe) continue;
+            if (!$this->trusted && !$module->safe) {
+                continue;
+            }
             foreach ($module->info as $name => $v) {
-                if (isset($elements[$name])) continue;
+                if (isset($elements[$name])) {
+                    continue;
+                }
                 $elements[$name] = $this->getElement($name);
             }
         }
@@ -310,7 +357,9 @@ class HTMLPurifier_HTMLModuleManager
         // remove dud elements, this happens when an element that
         // appeared to be safe actually wasn't
         foreach ($elements as $n => $v) {
-            if ($v === false) unset($elements[$n]);
+            if ($v === false) {
+                unset($elements[$n]);
+            }
         }
 
         return $elements;
@@ -319,28 +368,29 @@ class HTMLPurifier_HTMLModuleManager
 
     /**
      * Retrieves a single merged element definition
-     * @param $name Name of element
-     * @param $trusted Boolean trusted overriding parameter: set to true
+     * @param string $name Name of element
+     * @param bool $trusted Boolean trusted overriding parameter: set to true
      *                 if you want the full version of an element
-     * @return Merged HTMLPurifier_ElementDef
+     * @return HTMLPurifier_ElementDef Merged HTMLPurifier_ElementDef
      * @note You may notice that modules are getting iterated over twice (once
      *       in getElements() and once here). This
      *       is because
      */
-    public function getElement($name, $trusted = null) {
-
+    public function getElement($name, $trusted = null)
+    {
         if (!isset($this->elementLookup[$name])) {
             return false;
         }
 
         // setup global state variables
         $def = false;
-        if ($trusted === null) $trusted = $this->trusted;
+        if ($trusted === null) {
+            $trusted = $this->trusted;
+        }
 
         // iterate through each module that has registered itself to this
         // element
-        foreach($this->elementLookup[$name] as $module_name) {
-
+        foreach ($this->elementLookup[$name] as $module_name) {
             $module = $this->modules[$module_name];
 
             // refuse to create/merge from a module that is deemed unsafe--
@@ -364,6 +414,13 @@ class HTMLPurifier_HTMLModuleManager
                 // :TODO:
                 // non-standalone definitions that don't have a standalone
                 // to merge into could be deferred to the end
+                // HOWEVER, it is perfectly valid for a non-standalone
+                // definition to lack a standalone definition, even
+                // after all processing: this allows us to safely
+                // specify extra attributes for elements that may not be
+                // enabled all in one place.  In particular, this might
+                // be the case for trusted elements.  WARNING: care must
+                // be taken that the /extra/ definitions are all safe.
                 continue;
             }
 
@@ -385,7 +442,9 @@ class HTMLPurifier_HTMLModuleManager
 
         // This can occur if there is a blank definition, but no base to
         // mix it in with
-        if (!$def) return false;
+        if (!$def) {
+            return false;
+        }
 
         // add information on required attributes
         foreach ($def->attr as $attr_name => $attr_def) {
@@ -393,11 +452,8 @@ class HTMLPurifier_HTMLModuleManager
                 $def->required_attr[] = $attr_name;
             }
         }
-
         return $def;
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/IDAccumulator.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/IDAccumulator.php
similarity index 66%
rename from library/HTMLPurifier/IDAccumulator.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/IDAccumulator.php
index 73215295a5..65c902c076 100644
--- a/library/HTMLPurifier/IDAccumulator.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/IDAccumulator.php
@@ -17,11 +17,12 @@ class HTMLPurifier_IDAccumulator
 
     /**
      * Builds an IDAccumulator, also initializing the default blacklist
-     * @param $config Instance of HTMLPurifier_Config
-     * @param $context Instance of HTMLPurifier_Context
-     * @return Fully initialized HTMLPurifier_IDAccumulator
+     * @param HTMLPurifier_Config $config Instance of HTMLPurifier_Config
+     * @param HTMLPurifier_Context $context Instance of HTMLPurifier_Context
+     * @return HTMLPurifier_IDAccumulator Fully initialized HTMLPurifier_IDAccumulator
      */
-    public static function build($config, $context) {
+    public static function build($config, $context)
+    {
         $id_accumulator = new HTMLPurifier_IDAccumulator();
         $id_accumulator->load($config->get('Attr.IDBlacklist'));
         return $id_accumulator;
@@ -29,11 +30,14 @@ class HTMLPurifier_IDAccumulator
 
     /**
      * Add an ID to the lookup table.
-     * @param $id ID to be added.
-     * @return Bool status, true if success, false if there's a dupe
+     * @param string $id ID to be added.
+     * @return bool status, true if success, false if there's a dupe
      */
-    public function add($id) {
-        if (isset($this->ids[$id])) return false;
+    public function add($id)
+    {
+        if (isset($this->ids[$id])) {
+            return false;
+        }
         return $this->ids[$id] = true;
     }
 
@@ -42,12 +46,12 @@ class HTMLPurifier_IDAccumulator
      * @param $array_of_ids Array of IDs to load
      * @note This function doesn't care about duplicates
      */
-    public function load($array_of_ids) {
+    public function load($array_of_ids)
+    {
         foreach ($array_of_ids as $id) {
             $this->ids[$id] = true;
         }
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Injector.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector.php
similarity index 55%
rename from library/HTMLPurifier/Injector.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Injector.php
index 5922f81305..5060eef9e2 100644
--- a/library/HTMLPurifier/Injector.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector.php
@@ -17,64 +17,71 @@ abstract class HTMLPurifier_Injector
 {
 
     /**
-     * Advisory name of injector, this is for friendly error messages
+     * Advisory name of injector, this is for friendly error messages.
+     * @type string
      */
     public $name;
 
     /**
-     * Instance of HTMLPurifier_HTMLDefinition
+     * @type HTMLPurifier_HTMLDefinition
      */
     protected $htmlDefinition;
 
     /**
      * Reference to CurrentNesting variable in Context. This is an array
      * list of tokens that we are currently "inside"
+     * @type array
      */
     protected $currentNesting;
 
     /**
-     * Reference to InputTokens variable in Context. This is an array
-     * list of the input tokens that are being processed.
+     * Reference to current token.
+     * @type HTMLPurifier_Token
      */
-    protected $inputTokens;
+    protected $currentToken;
 
     /**
-     * Reference to InputIndex variable in Context. This is an integer
-     * array index for $this->inputTokens that indicates what token
-     * is currently being processed.
+     * Reference to InputZipper variable in Context.
+     * @type HTMLPurifier_Zipper
      */
-    protected $inputIndex;
+    protected $inputZipper;
 
     /**
      * Array of elements and attributes this injector creates and therefore
      * need to be allowed by the definition. Takes form of
      * array('element' => array('attr', 'attr2'), 'element2')
+     * @type array
      */
     public $needed = array();
 
     /**
-     * Index of inputTokens to rewind to.
+     * Number of elements to rewind backwards (relative).
+     * @type bool|int
      */
-    protected $rewind = false;
+    protected $rewindOffset = false;
 
     /**
      * Rewind to a spot to re-perform processing. This is useful if you
      * deleted a node, and now need to see if this change affected any
      * earlier nodes. Rewinding does not affect other injectors, and can
      * result in infinite loops if not used carefully.
+     * @param bool|int $offset
      * @warning HTML Purifier will prevent you from fast-forwarding with this
      *          function.
      */
-    public function rewind($index) {
-        $this->rewind = $index;
+    public function rewindOffset($offset)
+    {
+        $this->rewindOffset = $offset;
     }
 
     /**
-     * Retrieves rewind, and then unsets it.
+     * Retrieves rewind offset, and then unsets it.
+     * @return bool|int
      */
-    public function getRewind() {
-        $r = $this->rewind;
-        $this->rewind = false;
+    public function getRewindOffset()
+    {
+        $r = $this->rewindOffset;
+        $this->rewindOffset = false;
         return $r;
     }
 
@@ -83,20 +90,23 @@ abstract class HTMLPurifier_Injector
      * this allows references to important variables to be made within
      * the injector. This function also checks if the HTML environment
      * will work with the Injector (see checkNeeded()).
-     * @param $config Instance of HTMLPurifier_Config
-     * @param $context Instance of HTMLPurifier_Context
-     * @return Boolean false if success, string of missing needed element/attribute if failure
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool|string Boolean false if success, string of missing needed element/attribute if failure
      */
-    public function prepare($config, $context) {
+    public function prepare($config, $context)
+    {
         $this->htmlDefinition = $config->getHTMLDefinition();
         // Even though this might fail, some unit tests ignore this and
         // still test checkNeeded, so be careful. Maybe get rid of that
         // dependency.
         $result = $this->checkNeeded($config);
-        if ($result !== false) return $result;
+        if ($result !== false) {
+            return $result;
+        }
         $this->currentNesting =& $context->get('CurrentNesting');
-        $this->inputTokens    =& $context->get('InputTokens');
-        $this->inputIndex     =& $context->get('InputIndex');
+        $this->currentToken   =& $context->get('CurrentToken');
+        $this->inputZipper    =& $context->get('InputZipper');
         return false;
     }
 
@@ -104,18 +114,26 @@ abstract class HTMLPurifier_Injector
      * This function checks if the HTML environment
      * will work with the Injector: if p tags are not allowed, the
      * Auto-Paragraphing injector should not be enabled.
-     * @param $config Instance of HTMLPurifier_Config
-     * @param $context Instance of HTMLPurifier_Context
-     * @return Boolean false if success, string of missing needed element/attribute if failure
+     * @param HTMLPurifier_Config $config
+     * @return bool|string Boolean false if success, string of missing needed element/attribute if failure
      */
-    public function checkNeeded($config) {
+    public function checkNeeded($config)
+    {
         $def = $config->getHTMLDefinition();
         foreach ($this->needed as $element => $attributes) {
-            if (is_int($element)) $element = $attributes;
-            if (!isset($def->info[$element])) return $element;
-            if (!is_array($attributes)) continue;
+            if (is_int($element)) {
+                $element = $attributes;
+            }
+            if (!isset($def->info[$element])) {
+                return $element;
+            }
+            if (!is_array($attributes)) {
+                continue;
+            }
             foreach ($attributes as $name) {
-                if (!isset($def->info[$element]->attr[$name])) return "$element.$name";
+                if (!isset($def->info[$element]->attr[$name])) {
+                    return "$element.$name";
+                }
             }
         }
         return false;
@@ -123,10 +141,11 @@ abstract class HTMLPurifier_Injector
 
     /**
      * Tests if the context node allows a certain element
-     * @param $name Name of element to test for
-     * @return True if element is allowed, false if it is not
+     * @param string $name Name of element to test for
+     * @return bool True if element is allowed, false if it is not
      */
-    public function allowsElement($name) {
+    public function allowsElement($name)
+    {
         if (!empty($this->currentNesting)) {
             $parent_token = array_pop($this->currentNesting);
             $this->currentNesting[] = $parent_token;
@@ -141,7 +160,9 @@ abstract class HTMLPurifier_Injector
         for ($i = count($this->currentNesting) - 2; $i >= 0; $i--) {
             $node = $this->currentNesting[$i];
             $def  = $this->htmlDefinition->info[$node->name];
-            if (isset($def->excludes[$name])) return false;
+            if (isset($def->excludes[$name])) {
+                return false;
+            }
         }
         return true;
     }
@@ -151,14 +172,22 @@ abstract class HTMLPurifier_Injector
      * you reach the end of the input tokens.
      * @warning Please prevent previous references from interfering with this
      *          functions by setting $i = null beforehand!
-     * @param &$i Current integer index variable for inputTokens
-     * @param &$current Current token variable. Do NOT use $token, as that variable is also a reference
+     * @param int $i Current integer index variable for inputTokens
+     * @param HTMLPurifier_Token $current Current token variable.
+     *          Do NOT use $token, as that variable is also a reference
+     * @return bool
      */
-    protected function forward(&$i, &$current) {
-        if ($i === null) $i = $this->inputIndex + 1;
-        else $i++;
-        if (!isset($this->inputTokens[$i])) return false;
-        $current = $this->inputTokens[$i];
+    protected function forward(&$i, &$current)
+    {
+        if ($i === null) {
+            $i = count($this->inputZipper->back) - 1;
+        } else {
+            $i--;
+        }
+        if ($i < 0) {
+            return false;
+        }
+        $current = $this->inputZipper->back[$i];
         return true;
     }
 
@@ -166,14 +195,27 @@ abstract class HTMLPurifier_Injector
      * Similar to _forward, but accepts a third parameter $nesting (which
      * should be initialized at 0) and stops when we hit the end tag
      * for the node $this->inputIndex starts in.
+     * @param int $i Current integer index variable for inputTokens
+     * @param HTMLPurifier_Token $current Current token variable.
+     *          Do NOT use $token, as that variable is also a reference
+     * @param int $nesting
+     * @return bool
      */
-    protected function forwardUntilEndToken(&$i, &$current, &$nesting) {
+    protected function forwardUntilEndToken(&$i, &$current, &$nesting)
+    {
         $result = $this->forward($i, $current);
-        if (!$result) return false;
-        if ($nesting === null) $nesting = 0;
-        if     ($current instanceof HTMLPurifier_Token_Start) $nesting++;
-        elseif ($current instanceof HTMLPurifier_Token_End) {
-            if ($nesting <= 0) return false;
+        if (!$result) {
+            return false;
+        }
+        if ($nesting === null) {
+            $nesting = 0;
+        }
+        if ($current instanceof HTMLPurifier_Token_Start) {
+            $nesting++;
+        } elseif ($current instanceof HTMLPurifier_Token_End) {
+            if ($nesting <= 0) {
+                return false;
+            }
             $nesting--;
         }
         return true;
@@ -184,56 +226,56 @@ abstract class HTMLPurifier_Injector
      * you reach the beginning of input tokens.
      * @warning Please prevent previous references from interfering with this
      *          functions by setting $i = null beforehand!
-     * @param &$i Current integer index variable for inputTokens
-     * @param &$current Current token variable. Do NOT use $token, as that variable is also a reference
+     * @param int $i Current integer index variable for inputTokens
+     * @param HTMLPurifier_Token $current Current token variable.
+     *          Do NOT use $token, as that variable is also a reference
+     * @return bool
      */
-    protected function backward(&$i, &$current) {
-        if ($i === null) $i = $this->inputIndex - 1;
-        else $i--;
-        if ($i < 0) return false;
-        $current = $this->inputTokens[$i];
+    protected function backward(&$i, &$current)
+    {
+        if ($i === null) {
+            $i = count($this->inputZipper->front) - 1;
+        } else {
+            $i--;
+        }
+        if ($i < 0) {
+            return false;
+        }
+        $current = $this->inputZipper->front[$i];
         return true;
     }
 
-    /**
-     * Initializes the iterator at the current position. Use in a do {} while;
-     * loop to force the _forward and _backward functions to start at the
-     * current location.
-     * @warning Please prevent previous references from interfering with this
-     *          functions by setting $i = null beforehand!
-     * @param &$i Current integer index variable for inputTokens
-     * @param &$current Current token variable. Do NOT use $token, as that variable is also a reference
-     */
-    protected function current(&$i, &$current) {
-        if ($i === null) $i = $this->inputIndex;
-        $current = $this->inputTokens[$i];
-    }
-
     /**
      * Handler that is called when a text token is processed
      */
-    public function handleText(&$token) {}
+    public function handleText(&$token)
+    {
+    }
 
     /**
      * Handler that is called when a start or empty token is processed
      */
-    public function handleElement(&$token) {}
+    public function handleElement(&$token)
+    {
+    }
 
     /**
      * Handler that is called when an end token is processed
      */
-    public function handleEnd(&$token) {
+    public function handleEnd(&$token)
+    {
         $this->notifyEnd($token);
     }
 
     /**
      * Notifier that is called when an end token is processed
+     * @param HTMLPurifier_Token $token Current token variable.
      * @note This differs from handlers in that the token is read-only
      * @deprecated
      */
-    public function notifyEnd($token) {}
-
-
+    public function notifyEnd($token)
+    {
+    }
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Injector/AutoParagraph.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/AutoParagraph.php
similarity index 88%
rename from library/HTMLPurifier/Injector/AutoParagraph.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/AutoParagraph.php
index afa7608924..4afdd128d5 100644
--- a/library/HTMLPurifier/Injector/AutoParagraph.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/AutoParagraph.php
@@ -8,17 +8,31 @@
  */
 class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
 {
-
+    /**
+     * @type string
+     */
     public $name = 'AutoParagraph';
+
+    /**
+     * @type array
+     */
     public $needed = array('p');
 
-    private function _pStart() {
+    /**
+     * @return HTMLPurifier_Token_Start
+     */
+    private function _pStart()
+    {
         $par = new HTMLPurifier_Token_Start('p');
         $par->armor['MakeWellFormed_TagClosedError'] = true;
         return $par;
     }
 
-    public function handleText(&$token) {
+    /**
+     * @param HTMLPurifier_Token_Text $token
+     */
+    public function handleText(&$token)
+    {
         $text = $token->data;
         // Does the current parent allow <p> tags?
         if ($this->allowsElement('p')) {
@@ -72,11 +86,9 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
                     //                   ----
                 }
             }
-        // Is the current parent a <p> tag?
-        } elseif (
-            !empty($this->currentNesting) &&
-            $this->currentNesting[count($this->currentNesting)-1]->name == 'p'
-        ) {
+            // Is the current parent a <p> tag?
+        } elseif (!empty($this->currentNesting) &&
+            $this->currentNesting[count($this->currentNesting) - 1]->name == 'p') {
             // State 3.1: ...<p>PAR1
             //                  ----
 
@@ -84,7 +96,7 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
             //                  ------------
             $token = array();
             $this->_splitText($text, $token);
-        // Abort!
+            // Abort!
         } else {
             // State 4.1: ...<b>PAR1
             //                  ----
@@ -94,7 +106,11 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
         }
     }
 
-    public function handleElement(&$token) {
+    /**
+     * @param HTMLPurifier_Token $token
+     */
+    public function handleElement(&$token)
+    {
         // We don't have to check if we're already in a <p> tag for block
         // tokens, because the tag would have been autoclosed by MakeWellFormed.
         if ($this->allowsElement('p')) {
@@ -102,7 +118,6 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
                 if ($this->_isInline($token)) {
                     // State 1: <div>...<b>
                     //                  ---
-
                     // Check if this token is adjacent to the parent token
                     // (seek backwards until token isn't whitespace)
                     $i = null;
@@ -110,31 +125,24 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
 
                     if (!$prev instanceof HTMLPurifier_Token_Start) {
                         // Token wasn't adjacent
-
-                        if (
-                            $prev instanceof HTMLPurifier_Token_Text &&
+                        if ($prev instanceof HTMLPurifier_Token_Text &&
                             substr($prev->data, -2) === "\n\n"
                         ) {
                             // State 1.1.4: <div><p>PAR1</p>\n\n<b>
                             //                                  ---
-
                             // Quite frankly, this should be handled by splitText
                             $token = array($this->_pStart(), $token);
                         } else {
                             // State 1.1.1: <div><p>PAR1</p><b>
                             //                              ---
-
                             // State 1.1.2: <div><br /><b>
                             //                         ---
-
                             // State 1.1.3: <div>PAR<b>
                             //                      ---
                         }
-
                     } else {
                         // State 1.2.1: <div><b>
                         //                   ---
-
                         // Lookahead to see if <p> is needed.
                         if ($this->_pLookAhead()) {
                             // State 1.3.1: <div><b>PAR1\n\nPAR2
@@ -166,24 +174,20 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
 
                 $i = null;
                 if ($this->backward($i, $prev)) {
-                    if (
-                        !$prev instanceof HTMLPurifier_Token_Text
-                    ) {
+                    if (!$prev instanceof HTMLPurifier_Token_Text) {
                         // State 3.1.1: ...</p>{p}<b>
                         //                        ---
-
                         // State 3.2.1: ...</p><div>
                         //                     -----
-
-                        if (!is_array($token)) $token = array($token);
+                        if (!is_array($token)) {
+                            $token = array($token);
+                        }
                         array_unshift($token, new HTMLPurifier_Token_Text("\n\n"));
                     } else {
                         // State 3.1.2: ...</p>\n\n{p}<b>
                         //                            ---
-
                         // State 3.2.2: ...</p>\n\n<div>
                         //                         -----
-
                         // Note: PAR<ELEM> cannot occur because PAR would have been
                         // wrapped in <p> tags.
                     }
@@ -192,7 +196,6 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
         } else {
             // State 2.2: <ul><li>
             //                ----
-
             // State 2.4: <p><b>
             //               ---
         }
@@ -201,18 +204,17 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
     /**
      * Splits up a text in paragraph tokens and appends them
      * to the result stream that will replace the original
-     * @param $data String text data that will be processed
+     * @param string $data String text data that will be processed
      *    into paragraphs
-     * @param $result Reference to array of tokens that the
+     * @param HTMLPurifier_Token[] $result Reference to array of tokens that the
      *    tags will be appended onto
-     * @param $config Instance of HTMLPurifier_Config
-     * @param $context Instance of HTMLPurifier_Context
      */
-    private function _splitText($data, &$result) {
+    private function _splitText($data, &$result)
+    {
         $raw_paragraphs = explode("\n\n", $data);
-        $paragraphs  = array(); // without empty paragraphs
+        $paragraphs = array(); // without empty paragraphs
         $needs_start = false;
-        $needs_end   = false;
+        $needs_end = false;
 
         $c = count($raw_paragraphs);
         if ($c == 1) {
@@ -285,26 +287,33 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
             array_pop($result); // removes \n\n
             array_pop($result); // removes </p>
         }
-
     }
 
     /**
      * Returns true if passed token is inline (and, ergo, allowed in
      * paragraph tags)
+     * @param HTMLPurifier_Token $token
+     * @return bool
      */
-    private function _isInline($token) {
+    private function _isInline($token)
+    {
         return isset($this->htmlDefinition->info['p']->child->elements[$token->name]);
     }
 
     /**
      * Looks ahead in the token list and determines whether or not we need
      * to insert a <p> tag.
+     * @return bool
      */
-    private function _pLookAhead() {
-        $this->current($i, $current);
-        if ($current instanceof HTMLPurifier_Token_Start) $nesting = 1;
-        else $nesting = 0;
+    private function _pLookAhead()
+    {
+        if ($this->currentToken instanceof HTMLPurifier_Token_Start) {
+            $nesting = 1;
+        } else {
+            $nesting = 0;
+        }
         $ok = false;
+        $i = null;
         while ($this->forwardUntilEndToken($i, $current, $nesting)) {
             $result = $this->_checkNeedsP($current);
             if ($result !== null) {
@@ -318,9 +327,12 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
     /**
      * Determines if a particular token requires an earlier inline token
      * to get a paragraph. This should be used with _forwardUntilEndToken
+     * @param HTMLPurifier_Token $current
+     * @return bool
      */
-    private function _checkNeedsP($current) {
-        if ($current instanceof HTMLPurifier_Token_Start){
+    private function _checkNeedsP($current)
+    {
+        if ($current instanceof HTMLPurifier_Token_Start) {
             if (!$this->_isInline($current)) {
                 // <div>PAR1<div>
                 //      ----
@@ -339,7 +351,6 @@ class HTMLPurifier_Injector_AutoParagraph extends HTMLPurifier_Injector
         }
         return null;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Injector/DisplayLinkURI.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/DisplayLinkURI.php
similarity index 64%
rename from library/HTMLPurifier/Injector/DisplayLinkURI.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/DisplayLinkURI.php
index 9dce9bd085..c19b1bc271 100644
--- a/library/HTMLPurifier/Injector/DisplayLinkURI.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/DisplayLinkURI.php
@@ -5,15 +5,29 @@
  */
 class HTMLPurifier_Injector_DisplayLinkURI extends HTMLPurifier_Injector
 {
-
+    /**
+     * @type string
+     */
     public $name = 'DisplayLinkURI';
+
+    /**
+     * @type array
+     */
     public $needed = array('a');
 
-    public function handleElement(&$token) {
+    /**
+     * @param $token
+     */
+    public function handleElement(&$token)
+    {
     }
 
-    public function handleEnd(&$token) {
-        if (isset($token->start->attr['href'])){
+    /**
+     * @param HTMLPurifier_Token $token
+     */
+    public function handleEnd(&$token)
+    {
+        if (isset($token->start->attr['href'])) {
             $url = $token->start->attr['href'];
             unset($token->start->attr['href']);
             $token = array($token, new HTMLPurifier_Token_Text(" ($url)"));
diff --git a/library/HTMLPurifier/Injector/Linkify.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/Linkify.php
similarity index 72%
rename from library/HTMLPurifier/Injector/Linkify.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/Linkify.php
index 296dac2829..069708c250 100644
--- a/library/HTMLPurifier/Injector/Linkify.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/Linkify.php
@@ -5,12 +5,24 @@
  */
 class HTMLPurifier_Injector_Linkify extends HTMLPurifier_Injector
 {
-
+    /**
+     * @type string
+     */
     public $name = 'Linkify';
+
+    /**
+     * @type array
+     */
     public $needed = array('a' => array('href'));
 
-    public function handleText(&$token) {
-        if (!$this->allowsElement('a')) return;
+    /**
+     * @param HTMLPurifier_Token $token
+     */
+    public function handleText(&$token)
+    {
+        if (!$this->allowsElement('a')) {
+            return;
+        }
 
         if (strpos($token->data, '://') === false) {
             // our really quick heuristic failed, abort
@@ -21,7 +33,8 @@ class HTMLPurifier_Injector_Linkify extends HTMLPurifier_Injector
 
         // there is/are URL(s). Let's split the string:
         // Note: this regex is extremely permissive
-        $bits = preg_split('#((?:https?|ftp)://[^\s\'"<>()]+)#S', $token->data, -1, PREG_SPLIT_DELIM_CAPTURE);
+        $bits = preg_split('#((?:https?|ftp)://[^\s\'",<>()]+)#Su', $token->data, -1, PREG_SPLIT_DELIM_CAPTURE);
+
 
         $token = array();
 
@@ -30,7 +43,9 @@ class HTMLPurifier_Injector_Linkify extends HTMLPurifier_Injector
         // $l = is link
         for ($i = 0, $c = count($bits), $l = false; $i < $c; $i++, $l = !$l) {
             if (!$l) {
-                if ($bits[$i] === '') continue;
+                if ($bits[$i] === '') {
+                    continue;
+                }
                 $token[] = new HTMLPurifier_Token_Text($bits[$i]);
             } else {
                 $token[] = new HTMLPurifier_Token_Start('a', array('href' => $bits[$i]));
@@ -38,9 +53,7 @@ class HTMLPurifier_Injector_Linkify extends HTMLPurifier_Injector
                 $token[] = new HTMLPurifier_Token_End('a');
             }
         }
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Injector/PurifierLinkify.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/PurifierLinkify.php
similarity index 58%
rename from library/HTMLPurifier/Injector/PurifierLinkify.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/PurifierLinkify.php
index ad2455a91c..cb9046f334 100644
--- a/library/HTMLPurifier/Injector/PurifierLinkify.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/PurifierLinkify.php
@@ -6,19 +6,43 @@
  */
 class HTMLPurifier_Injector_PurifierLinkify extends HTMLPurifier_Injector
 {
-
+    /**
+     * @type string
+     */
     public $name = 'PurifierLinkify';
+
+    /**
+     * @type string
+     */
     public $docURL;
+
+    /**
+     * @type array
+     */
     public $needed = array('a' => array('href'));
 
-    public function prepare($config, $context) {
+    /**
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
+     */
+    public function prepare($config, $context)
+    {
         $this->docURL = $config->get('AutoFormat.PurifierLinkify.DocURL');
         return parent::prepare($config, $context);
     }
 
-    public function handleText(&$token) {
-        if (!$this->allowsElement('a')) return;
-        if (strpos($token->data, '%') === false) return;
+    /**
+     * @param HTMLPurifier_Token $token
+     */
+    public function handleText(&$token)
+    {
+        if (!$this->allowsElement('a')) {
+            return;
+        }
+        if (strpos($token->data, '%') === false) {
+            return;
+        }
 
         $bits = preg_split('#%([a-z0-9]+\.[a-z0-9]+)#Si', $token->data, -1, PREG_SPLIT_DELIM_CAPTURE);
         $token = array();
@@ -28,18 +52,20 @@ class HTMLPurifier_Injector_PurifierLinkify extends HTMLPurifier_Injector
         // $l = is link
         for ($i = 0, $c = count($bits), $l = false; $i < $c; $i++, $l = !$l) {
             if (!$l) {
-                if ($bits[$i] === '') continue;
+                if ($bits[$i] === '') {
+                    continue;
+                }
                 $token[] = new HTMLPurifier_Token_Text($bits[$i]);
             } else {
-                $token[] = new HTMLPurifier_Token_Start('a',
-                    array('href' => str_replace('%s', $bits[$i], $this->docURL)));
+                $token[] = new HTMLPurifier_Token_Start(
+                    'a',
+                    array('href' => str_replace('%s', $bits[$i], $this->docURL))
+                );
                 $token[] = new HTMLPurifier_Token_Text('%' . $bits[$i]);
                 $token[] = new HTMLPurifier_Token_End('a');
             }
         }
-
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php
new file mode 100644
index 0000000000..01353ff1d5
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveEmpty.php
@@ -0,0 +1,106 @@
+<?php
+
+class HTMLPurifier_Injector_RemoveEmpty extends HTMLPurifier_Injector
+{
+    /**
+     * @type HTMLPurifier_Context
+     */
+    private $context;
+
+    /**
+     * @type HTMLPurifier_Config
+     */
+    private $config;
+
+    /**
+     * @type HTMLPurifier_AttrValidator
+     */
+    private $attrValidator;
+
+    /**
+     * @type bool
+     */
+    private $removeNbsp;
+
+    /**
+     * @type bool
+     */
+    private $removeNbspExceptions;
+
+    /**
+     * Cached contents of %AutoFormat.RemoveEmpty.Predicate
+     * @type array
+     */
+    private $exclude;
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return void
+     */
+    public function prepare($config, $context)
+    {
+        parent::prepare($config, $context);
+        $this->config = $config;
+        $this->context = $context;
+        $this->removeNbsp = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp');
+        $this->removeNbspExceptions = $config->get('AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions');
+        $this->exclude = $config->get('AutoFormat.RemoveEmpty.Predicate');
+        $this->attrValidator = new HTMLPurifier_AttrValidator();
+    }
+
+    /**
+     * @param HTMLPurifier_Token $token
+     */
+    public function handleElement(&$token)
+    {
+        if (!$token instanceof HTMLPurifier_Token_Start) {
+            return;
+        }
+        $next = false;
+        $deleted = 1; // the current tag
+        for ($i = count($this->inputZipper->back) - 1; $i >= 0; $i--, $deleted++) {
+            $next = $this->inputZipper->back[$i];
+            if ($next instanceof HTMLPurifier_Token_Text) {
+                if ($next->is_whitespace) {
+                    continue;
+                }
+                if ($this->removeNbsp && !isset($this->removeNbspExceptions[$token->name])) {
+                    $plain = str_replace("\xC2\xA0", "", $next->data);
+                    $isWsOrNbsp = $plain === '' || ctype_space($plain);
+                    if ($isWsOrNbsp) {
+                        continue;
+                    }
+                }
+            }
+            break;
+        }
+        if (!$next || ($next instanceof HTMLPurifier_Token_End && $next->name == $token->name)) {
+            $this->attrValidator->validateToken($token, $this->config, $this->context);
+            $token->armor['ValidateAttributes'] = true;
+            if (isset($this->exclude[$token->name])) {
+                $r = true;
+                foreach ($this->exclude[$token->name] as $elem) {
+                    if (!isset($token->attr[$elem])) $r = false;
+                }
+                if ($r) return;
+            }
+            if (isset($token->attr['id']) || isset($token->attr['name'])) {
+                return;
+            }
+            $token = $deleted + 1;
+            for ($b = 0, $c = count($this->inputZipper->front); $b < $c; $b++) {
+                $prev = $this->inputZipper->front[$b];
+                if ($prev instanceof HTMLPurifier_Token_Text && $prev->is_whitespace) {
+                    continue;
+                }
+                break;
+            }
+            // This is safe because we removed the token that triggered this.
+            $this->rewindOffset($b+$deleted);
+            return;
+        }
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php
similarity index 74%
rename from library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php
index b21313470e..9ee7aa84d7 100644
--- a/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/RemoveSpansWithoutAttributes.php
@@ -5,25 +5,45 @@
  */
 class HTMLPurifier_Injector_RemoveSpansWithoutAttributes extends HTMLPurifier_Injector
 {
+    /**
+     * @type string
+     */
     public $name = 'RemoveSpansWithoutAttributes';
+
+    /**
+     * @type array
+     */
     public $needed = array('span');
 
+    /**
+     * @type HTMLPurifier_AttrValidator
+     */
     private $attrValidator;
 
     /**
-     * Used by AttrValidator
+     * Used by AttrValidator.
+     * @type HTMLPurifier_Config
      */
     private $config;
+
+    /**
+     * @type HTMLPurifier_Context
+     */
     private $context;
 
-    public function prepare($config, $context) {
+    public function prepare($config, $context)
+    {
         $this->attrValidator = new HTMLPurifier_AttrValidator();
         $this->config = $config;
         $this->context = $context;
         return parent::prepare($config, $context);
     }
 
-    public function handleElement(&$token) {
+    /**
+     * @param HTMLPurifier_Token $token
+     */
+    public function handleElement(&$token)
+    {
         if ($token->name !== 'span' || !$token instanceof HTMLPurifier_Token_Start) {
             return;
         }
@@ -39,8 +59,8 @@ class HTMLPurifier_Injector_RemoveSpansWithoutAttributes extends HTMLPurifier_In
         }
 
         $nesting = 0;
-        $spanContentTokens = array();
-        while ($this->forwardUntilEndToken($i, $current, $nesting)) {}
+        while ($this->forwardUntilEndToken($i, $current, $nesting)) {
+        }
 
         if ($current instanceof HTMLPurifier_Token_End && $current->name === 'span') {
             // Mark closing span tag for deletion
@@ -50,7 +70,11 @@ class HTMLPurifier_Injector_RemoveSpansWithoutAttributes extends HTMLPurifier_In
         }
     }
 
-    public function handleEnd(&$token) {
+    /**
+     * @param HTMLPurifier_Token $token
+     */
+    public function handleEnd(&$token)
+    {
         if ($token->markForDeletion) {
             $token = false;
         }
diff --git a/library/HTMLPurifier/Injector/SafeObject.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/SafeObject.php
similarity index 78%
rename from library/HTMLPurifier/Injector/SafeObject.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/SafeObject.php
index 9e178ce01a..3d17e07af2 100644
--- a/library/HTMLPurifier/Injector/SafeObject.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Injector/SafeObject.php
@@ -6,29 +6,61 @@
  */
 class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector
 {
+    /**
+     * @type string
+     */
     public $name = 'SafeObject';
+
+    /**
+     * @type array
+     */
     public $needed = array('object', 'param');
 
+    /**
+     * @type array
+     */
     protected $objectStack = array();
-    protected $paramStack  = array();
 
-    // Keep this synchronized with AttrTransform/SafeParam.php
+    /**
+     * @type array
+     */
+    protected $paramStack = array();
+
+    /**
+     * Keep this synchronized with AttrTransform/SafeParam.php.
+     * @type array
+     */
     protected $addParam = array(
         'allowScriptAccess' => 'never',
         'allowNetworking' => 'internal',
     );
+
+    /**
+     * @type array
+     */
     protected $allowedParam = array(
         'wmode' => true,
         'movie' => true,
         'flashvars' => true,
         'src' => true,
+        'allowFullScreen' => true, // if omitted, assume to be 'false'
     );
 
-    public function prepare($config, $context) {
+    /**
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return void
+     */
+    public function prepare($config, $context)
+    {
         parent::prepare($config, $context);
     }
 
-    public function handleElement(&$token) {
+    /**
+     * @param HTMLPurifier_Token $token
+     */
+    public function handleElement(&$token)
+    {
         if ($token->name == 'object') {
             $this->objectStack[] = $token;
             $this->paramStack[] = array();
@@ -50,16 +82,15 @@ class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector
                 // attribute, which we need if a type is specified. This is
                 // *very* Flash specific.
                 if (!isset($this->objectStack[$i]->attr['data']) &&
-                    ($token->attr['name'] == 'movie' || $token->attr['name'] == 'src')) {
+                    ($token->attr['name'] == 'movie' || $token->attr['name'] == 'src')
+                ) {
                     $this->objectStack[$i]->attr['data'] = $token->attr['value'];
                 }
                 // Check if the parameter is the correct value but has not
                 // already been added
-                if (
-                    !isset($this->paramStack[$i][$n]) &&
+                if (!isset($this->paramStack[$i][$n]) &&
                     isset($this->addParam[$n]) &&
-                    $token->attr['name'] === $this->addParam[$n]
-                ) {
+                    $token->attr['name'] === $this->addParam[$n]) {
                     // keep token, and add to param stack
                     $this->paramStack[$i][$n] = true;
                 } elseif (isset($this->allowedParam[$n])) {
@@ -75,7 +106,8 @@ class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector
         }
     }
 
-    public function handleEnd(&$token) {
+    public function handleEnd(&$token)
+    {
         // This is the WRONG way of handling the object and param stacks;
         // we should be inserting them directly on the relevant object tokens
         // so that the global stack handling handles it.
@@ -84,7 +116,6 @@ class HTMLPurifier_Injector_SafeObject extends HTMLPurifier_Injector
             array_pop($this->paramStack);
         }
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Language.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Language.php
similarity index 67%
rename from library/HTMLPurifier/Language.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Language.php
index 3e2be03b58..65277dd43c 100644
--- a/library/HTMLPurifier/Language.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Language.php
@@ -8,22 +8,26 @@ class HTMLPurifier_Language
 {
 
     /**
-     * ISO 639 language code of language. Prefers shortest possible version
+     * ISO 639 language code of language. Prefers shortest possible version.
+     * @type string
      */
     public $code = 'en';
 
     /**
-     * Fallback language code
+     * Fallback language code.
+     * @type bool|string
      */
     public $fallback = false;
 
     /**
-     * Array of localizable messages
+     * Array of localizable messages.
+     * @type array
      */
     public $messages = array();
 
     /**
-     * Array of localizable error codes
+     * Array of localizable error codes.
+     * @type array
      */
     public $errorNames = array();
 
@@ -31,21 +35,33 @@ class HTMLPurifier_Language
      * True if no message file was found for this language, so English
      * is being used instead. Check this if you'd like to notify the
      * user that they've used a non-supported language.
+     * @type bool
      */
     public $error = false;
 
     /**
      * Has the language object been loaded yet?
+     * @type bool
      * @todo Make it private, fix usage in HTMLPurifier_LanguageTest
      */
     public $_loaded = false;
 
     /**
-     * Instances of HTMLPurifier_Config and HTMLPurifier_Context
+     * @type HTMLPurifier_Config
      */
-    protected $config, $context;
+    protected $config;
 
-    public function __construct($config, $context) {
+    /**
+     * @type HTMLPurifier_Context
+     */
+    protected $context;
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     */
+    public function __construct($config, $context)
+    {
         $this->config  = $config;
         $this->context = $context;
     }
@@ -54,8 +70,11 @@ class HTMLPurifier_Language
      * Loads language object with necessary info from factory cache
      * @note This is a lazy loader
      */
-    public function load() {
-        if ($this->_loaded) return;
+    public function load()
+    {
+        if ($this->_loaded) {
+            return;
+        }
         $factory = HTMLPurifier_LanguageFactory::instance();
         $factory->loadLanguage($this->code);
         foreach ($factory->keys as $key) {
@@ -66,31 +85,43 @@ class HTMLPurifier_Language
 
     /**
      * Retrieves a localised message.
-     * @param $key string identifier of message
+     * @param string $key string identifier of message
      * @return string localised message
      */
-    public function getMessage($key) {
-        if (!$this->_loaded) $this->load();
-        if (!isset($this->messages[$key])) return "[$key]";
+    public function getMessage($key)
+    {
+        if (!$this->_loaded) {
+            $this->load();
+        }
+        if (!isset($this->messages[$key])) {
+            return "[$key]";
+        }
         return $this->messages[$key];
     }
 
     /**
      * Retrieves a localised error name.
-     * @param $int integer error number, corresponding to PHP's error
-     *             reporting
+     * @param int $int error number, corresponding to PHP's error reporting
      * @return string localised message
      */
-    public function getErrorName($int) {
-        if (!$this->_loaded) $this->load();
-        if (!isset($this->errorNames[$int])) return "[Error: $int]";
+    public function getErrorName($int)
+    {
+        if (!$this->_loaded) {
+            $this->load();
+        }
+        if (!isset($this->errorNames[$int])) {
+            return "[Error: $int]";
+        }
         return $this->errorNames[$int];
     }
 
     /**
      * Converts an array list into a string readable representation
+     * @param array $array
+     * @return string
      */
-    public function listify($array) {
+    public function listify($array)
+    {
         $sep      = $this->getMessage('Item separator');
         $sep_last = $this->getMessage('Item separator last');
         $ret = '';
@@ -108,15 +139,20 @@ class HTMLPurifier_Language
 
     /**
      * Formats a localised message with passed parameters
-     * @param $key string identifier of message
-     * @param $args Parameters to substitute in
+     * @param string $key string identifier of message
+     * @param array $args Parameters to substitute in
      * @return string localised message
      * @todo Implement conditionals? Right now, some messages make
      *     reference to line numbers, but those aren't always available
      */
-    public function formatMessage($key, $args = array()) {
-        if (!$this->_loaded) $this->load();
-        if (!isset($this->messages[$key])) return "[$key]";
+    public function formatMessage($key, $args = array())
+    {
+        if (!$this->_loaded) {
+            $this->load();
+        }
+        if (!isset($this->messages[$key])) {
+            return "[$key]";
+        }
         $raw = $this->messages[$key];
         $subst = array();
         $generator = false;
@@ -124,9 +160,15 @@ class HTMLPurifier_Language
             if (is_object($value)) {
                 if ($value instanceof HTMLPurifier_Token) {
                     // factor this out some time
-                    if (!$generator) $generator = $this->context->get('Generator');
-                    if (isset($value->name)) $subst['$'.$i.'.Name'] = $value->name;
-                    if (isset($value->data)) $subst['$'.$i.'.Data'] = $value->data;
+                    if (!$generator) {
+                        $generator = $this->context->get('Generator');
+                    }
+                    if (isset($value->name)) {
+                        $subst['$'.$i.'.Name'] = $value->name;
+                    }
+                    if (isset($value->data)) {
+                        $subst['$'.$i.'.Data'] = $value->data;
+                    }
                     $subst['$'.$i.'.Compact'] =
                     $subst['$'.$i.'.Serialized'] = $generator->generateFromToken($value);
                     // a more complex algorithm for compact representation
@@ -157,7 +199,6 @@ class HTMLPurifier_Language
         }
         return strtr($raw, $subst);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Language/classes/en-x-test.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Language/classes/en-x-test.php
similarity index 97%
rename from library/HTMLPurifier/Language/classes/en-x-test.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Language/classes/en-x-test.php
index d52fcb7ac1..8828f5cded 100644
--- a/library/HTMLPurifier/Language/classes/en-x-test.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Language/classes/en-x-test.php
@@ -4,9 +4,6 @@
 
 class HTMLPurifier_Language_en_x_test extends HTMLPurifier_Language
 {
-
-
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Language/messages/en-x-test.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en-x-test.php
similarity index 100%
rename from library/HTMLPurifier/Language/messages/en-x-test.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en-x-test.php
diff --git a/library/HTMLPurifier/Language/messages/en-x-testmini.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en-x-testmini.php
similarity index 100%
rename from library/HTMLPurifier/Language/messages/en-x-testmini.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en-x-testmini.php
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en.php
new file mode 100644
index 0000000000..c7f197e1e1
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Language/messages/en.php
@@ -0,0 +1,55 @@
+<?php
+
+$fallback = false;
+
+$messages = array(
+
+    'HTMLPurifier' => 'HTML Purifier',
+// for unit testing purposes
+    'LanguageFactoryTest: Pizza' => 'Pizza',
+    'LanguageTest: List' => '$1',
+    'LanguageTest: Hash' => '$1.Keys; $1.Values',
+    'Item separator' => ', ',
+    'Item separator last' => ' and ', // non-Harvard style
+
+    'ErrorCollector: No errors' => 'No errors detected. However, because error reporting is still incomplete, there may have been errors that the error collector was not notified of; please inspect the output HTML carefully.',
+    'ErrorCollector: At line' => ' at line $line',
+    'ErrorCollector: Incidental errors' => 'Incidental errors',
+    'Lexer: Unclosed comment' => 'Unclosed comment',
+    'Lexer: Unescaped lt' => 'Unescaped less-than sign (<) should be &lt;',
+    'Lexer: Missing gt' => 'Missing greater-than sign (>), previous less-than sign (<) should be escaped',
+    'Lexer: Missing attribute key' => 'Attribute declaration has no key',
+    'Lexer: Missing end quote' => 'Attribute declaration has no end quote',
+    'Lexer: Extracted body' => 'Removed document metadata tags',
+    'Strategy_RemoveForeignElements: Tag transform' => '<$1> element transformed into $CurrentToken.Serialized',
+    'Strategy_RemoveForeignElements: Missing required attribute' => '$CurrentToken.Compact element missing required attribute $1',
+    'Strategy_RemoveForeignElements: Foreign element to text' => 'Unrecognized $CurrentToken.Serialized tag converted to text',
+    'Strategy_RemoveForeignElements: Foreign element removed' => 'Unrecognized $CurrentToken.Serialized tag removed',
+    'Strategy_RemoveForeignElements: Comment removed' => 'Comment containing "$CurrentToken.Data" removed',
+    'Strategy_RemoveForeignElements: Foreign meta element removed' => 'Unrecognized $CurrentToken.Serialized meta tag and all descendants removed',
+    'Strategy_RemoveForeignElements: Token removed to end' => 'Tags and text starting from $1 element where removed to end',
+    'Strategy_RemoveForeignElements: Trailing hyphen in comment removed' => 'Trailing hyphen(s) in comment removed',
+    'Strategy_RemoveForeignElements: Hyphens in comment collapsed' => 'Double hyphens in comments are not allowed, and were collapsed into single hyphens',
+    'Strategy_MakeWellFormed: Unnecessary end tag removed' => 'Unnecessary $CurrentToken.Serialized tag removed',
+    'Strategy_MakeWellFormed: Unnecessary end tag to text' => 'Unnecessary $CurrentToken.Serialized tag converted to text',
+    'Strategy_MakeWellFormed: Tag auto closed' => '$1.Compact started on line $1.Line auto-closed by $CurrentToken.Compact',
+    'Strategy_MakeWellFormed: Tag carryover' => '$1.Compact started on line $1.Line auto-continued into $CurrentToken.Compact',
+    'Strategy_MakeWellFormed: Stray end tag removed' => 'Stray $CurrentToken.Serialized tag removed',
+    'Strategy_MakeWellFormed: Stray end tag to text' => 'Stray $CurrentToken.Serialized tag converted to text',
+    'Strategy_MakeWellFormed: Tag closed by element end' => '$1.Compact tag started on line $1.Line closed by end of $CurrentToken.Serialized',
+    'Strategy_MakeWellFormed: Tag closed by document end' => '$1.Compact tag started on line $1.Line closed by end of document',
+    'Strategy_FixNesting: Node removed' => '$CurrentToken.Compact node removed',
+    'Strategy_FixNesting: Node excluded' => '$CurrentToken.Compact node removed due to descendant exclusion by ancestor element',
+    'Strategy_FixNesting: Node reorganized' => 'Contents of $CurrentToken.Compact node reorganized to enforce its content model',
+    'Strategy_FixNesting: Node contents removed' => 'Contents of $CurrentToken.Compact node removed',
+    'AttrValidator: Attributes transformed' => 'Attributes on $CurrentToken.Compact transformed from $1.Keys to $2.Keys',
+    'AttrValidator: Attribute removed' => '$CurrentAttr.Name attribute on $CurrentToken.Compact removed',
+);
+
+$errorNames = array(
+    E_ERROR => 'Error',
+    E_WARNING => 'Warning',
+    E_NOTICE => 'Notice'
+);
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/LanguageFactory.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/LanguageFactory.php
similarity index 75%
rename from library/HTMLPurifier/LanguageFactory.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/LanguageFactory.php
index 134ef8c745..4e35272d87 100644
--- a/library/HTMLPurifier/LanguageFactory.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/LanguageFactory.php
@@ -11,50 +11,53 @@ class HTMLPurifier_LanguageFactory
 {
 
     /**
-     * Cache of language code information used to load HTMLPurifier_Language objects
+     * Cache of language code information used to load HTMLPurifier_Language objects.
      * Structure is: $factory->cache[$language_code][$key] = $value
-     * @value array map
+     * @type array
      */
     public $cache;
 
     /**
      * Valid keys in the HTMLPurifier_Language object. Designates which
      * variables to slurp out of a message file.
-     * @value array list
+     * @type array
      */
     public $keys = array('fallback', 'messages', 'errorNames');
 
     /**
-     * Instance of HTMLPurifier_AttrDef_Lang to validate language codes
-     * @value object HTMLPurifier_AttrDef_Lang
+     * Instance to validate language codes.
+     * @type HTMLPurifier_AttrDef_Lang
+     *
      */
     protected $validator;
 
     /**
      * Cached copy of dirname(__FILE__), directory of current file without
-     * trailing slash
-     * @value string filename
+     * trailing slash.
+     * @type string
      */
     protected $dir;
 
     /**
-     * Keys whose contents are a hash map and can be merged
-     * @value array lookup
+     * Keys whose contents are a hash map and can be merged.
+     * @type array
      */
     protected $mergeable_keys_map = array('messages' => true, 'errorNames' => true);
 
     /**
-     * Keys whose contents are a list and can be merged
+     * Keys whose contents are a list and can be merged.
      * @value array lookup
      */
     protected $mergeable_keys_list = array();
 
     /**
      * Retrieve sole instance of the factory.
-     * @param $prototype Optional prototype to overload sole instance with,
+     * @param HTMLPurifier_LanguageFactory $prototype Optional prototype to overload sole instance with,
      *                   or bool true to reset to default factory.
+     * @return HTMLPurifier_LanguageFactory
      */
-    public static function instance($prototype = null) {
+    public static function instance($prototype = null)
+    {
         static $instance = null;
         if ($prototype !== null) {
             $instance = $prototype;
@@ -69,28 +72,34 @@ class HTMLPurifier_LanguageFactory
      * Sets up the singleton, much like a constructor
      * @note Prevents people from getting this outside of the singleton
      */
-    public function setup() {
+    public function setup()
+    {
         $this->validator = new HTMLPurifier_AttrDef_Lang();
         $this->dir = HTMLPURIFIER_PREFIX . '/HTMLPurifier';
     }
 
     /**
      * Creates a language object, handles class fallbacks
-     * @param $config Instance of HTMLPurifier_Config
-     * @param $context Instance of HTMLPurifier_Context
-     * @param $code Code to override configuration with. Private parameter.
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @param bool|string $code Code to override configuration with. Private parameter.
+     * @return HTMLPurifier_Language
      */
-    public function create($config, $context, $code = false) {
-
+    public function create($config, $context, $code = false)
+    {
         // validate language code
         if ($code === false) {
             $code = $this->validator->validate(
-              $config->get('Core.Language'), $config, $context
+                $config->get('Core.Language'),
+                $config,
+                $context
             );
         } else {
             $code = $this->validator->validate($code, $config, $context);
         }
-        if ($code === false) $code = 'en'; // malformed code becomes English
+        if ($code === false) {
+            $code = 'en'; // malformed code becomes English
+        }
 
         $pcode = str_replace('-', '_', $code); // make valid PHP classname
         static $depth = 0; // recursion protection
@@ -114,32 +123,34 @@ class HTMLPurifier_LanguageFactory
                 $depth--;
             }
         }
-
         $lang->code = $code;
-
         return $lang;
-
     }
 
     /**
      * Returns the fallback language for language
      * @note Loads the original language into cache
-     * @param $code string language code
+     * @param string $code language code
+     * @return string|bool
      */
-    public function getFallbackFor($code) {
+    public function getFallbackFor($code)
+    {
         $this->loadLanguage($code);
         return $this->cache[$code]['fallback'];
     }
 
     /**
      * Loads language into the cache, handles message file and fallbacks
-     * @param $code string language code
+     * @param string $code language code
      */
-    public function loadLanguage($code) {
+    public function loadLanguage($code)
+    {
         static $languages_seen = array(); // recursion guard
 
         // abort if we've already loaded it
-        if (isset($this->cache[$code])) return;
+        if (isset($this->cache[$code])) {
+            return;
+        }
 
         // generate filename
         $filename = $this->dir . '/Language/messages/' . $code . '.php';
@@ -162,8 +173,11 @@ class HTMLPurifier_LanguageFactory
 
             // infinite recursion guard
             if (isset($languages_seen[$code])) {
-                trigger_error('Circular fallback reference in language ' .
-                    $code, E_USER_ERROR);
+                trigger_error(
+                    'Circular fallback reference in language ' .
+                    $code,
+                    E_USER_ERROR
+                );
                 $fallback = 'en';
             }
             $language_seen[$code] = true;
@@ -173,26 +187,23 @@ class HTMLPurifier_LanguageFactory
             $fallback_cache = $this->cache[$fallback];
 
             // merge fallback with current language
-            foreach ( $this->keys as $key ) {
+            foreach ($this->keys as $key) {
                 if (isset($cache[$key]) && isset($fallback_cache[$key])) {
                     if (isset($this->mergeable_keys_map[$key])) {
                         $cache[$key] = $cache[$key] + $fallback_cache[$key];
                     } elseif (isset($this->mergeable_keys_list[$key])) {
-                        $cache[$key] = array_merge( $fallback_cache[$key], $cache[$key] );
+                        $cache[$key] = array_merge($fallback_cache[$key], $cache[$key]);
                     }
                 } else {
                     $cache[$key] = $fallback_cache[$key];
                 }
             }
-
         }
 
         // save to cache for later retrieval
         $this->cache[$code] = $cache;
-
         return;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Length.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Length.php
similarity index 56%
rename from library/HTMLPurifier/Length.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Length.php
index 8d2a46b7da..bbfbe6624d 100644
--- a/library/HTMLPurifier/Length.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Length.php
@@ -9,21 +9,25 @@ class HTMLPurifier_Length
 
     /**
      * String numeric magnitude.
+     * @type string
      */
     protected $n;
 
     /**
      * String unit. False is permitted if $n = 0.
+     * @type string|bool
      */
     protected $unit;
 
     /**
      * Whether or not this length is valid. Null if not calculated yet.
+     * @type bool
      */
     protected $isValid;
 
     /**
-     * Lookup array of units recognized by CSS 2.1
+     * Array Lookup array of units recognized by CSS 2.1
+     * @type array
      */
     protected static $allowedUnits = array(
         'em' => true, 'ex' => true, 'px' => true, 'in' => true,
@@ -31,85 +35,126 @@ class HTMLPurifier_Length
     );
 
     /**
-     * @param number $n Magnitude
-     * @param string $u Unit
+     * @param string $n Magnitude
+     * @param bool|string $u Unit
      */
-    public function __construct($n = '0', $u = false) {
+    public function __construct($n = '0', $u = false)
+    {
         $this->n = (string) $n;
         $this->unit = $u !== false ? (string) $u : false;
     }
 
     /**
      * @param string $s Unit string, like '2em' or '3.4in'
+     * @return HTMLPurifier_Length
      * @warning Does not perform validation.
      */
-    static public function make($s) {
-        if ($s instanceof HTMLPurifier_Length) return $s;
+    public static function make($s)
+    {
+        if ($s instanceof HTMLPurifier_Length) {
+            return $s;
+        }
         $n_length = strspn($s, '1234567890.+-');
         $n = substr($s, 0, $n_length);
         $unit = substr($s, $n_length);
-        if ($unit === '') $unit = false;
+        if ($unit === '') {
+            $unit = false;
+        }
         return new HTMLPurifier_Length($n, $unit);
     }
 
     /**
      * Validates the number and unit.
+     * @return bool
      */
-    protected function validate() {
+    protected function validate()
+    {
         // Special case:
-        if ($this->n === '+0' || $this->n === '-0') $this->n = '0';
-        if ($this->n === '0' && $this->unit === false) return true;
-        if (!ctype_lower($this->unit)) $this->unit = strtolower($this->unit);
-        if (!isset(HTMLPurifier_Length::$allowedUnits[$this->unit])) return false;
+        if ($this->n === '+0' || $this->n === '-0') {
+            $this->n = '0';
+        }
+        if ($this->n === '0' && $this->unit === false) {
+            return true;
+        }
+        if (!ctype_lower($this->unit)) {
+            $this->unit = strtolower($this->unit);
+        }
+        if (!isset(HTMLPurifier_Length::$allowedUnits[$this->unit])) {
+            return false;
+        }
         // Hack:
         $def = new HTMLPurifier_AttrDef_CSS_Number();
         $result = $def->validate($this->n, false, false);
-        if ($result === false) return false;
+        if ($result === false) {
+            return false;
+        }
         $this->n = $result;
         return true;
     }
 
     /**
      * Returns string representation of number.
+     * @return string
      */
-    public function toString() {
-        if (!$this->isValid()) return false;
+    public function toString()
+    {
+        if (!$this->isValid()) {
+            return false;
+        }
         return $this->n . $this->unit;
     }
 
     /**
      * Retrieves string numeric magnitude.
+     * @return string
      */
-    public function getN() {return $this->n;}
+    public function getN()
+    {
+        return $this->n;
+    }
 
     /**
      * Retrieves string unit.
+     * @return string
      */
-    public function getUnit() {return $this->unit;}
+    public function getUnit()
+    {
+        return $this->unit;
+    }
 
     /**
      * Returns true if this length unit is valid.
+     * @return bool
      */
-    public function isValid() {
-        if ($this->isValid === null) $this->isValid = $this->validate();
+    public function isValid()
+    {
+        if ($this->isValid === null) {
+            $this->isValid = $this->validate();
+        }
         return $this->isValid;
     }
 
     /**
      * Compares two lengths, and returns 1 if greater, -1 if less and 0 if equal.
+     * @param HTMLPurifier_Length $l
+     * @return int
      * @warning If both values are too large or small, this calculation will
      *          not work properly
      */
-    public function compareTo($l) {
-        if ($l === false) return false;
+    public function compareTo($l)
+    {
+        if ($l === false) {
+            return false;
+        }
         if ($l->unit !== $this->unit) {
             $converter = new HTMLPurifier_UnitConverter();
             $l = $converter->convert($l, $this->unit);
-            if ($l === false) return false;
+            if ($l === false) {
+                return false;
+            }
         }
         return $this->n - $l->n;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Lexer.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php
similarity index 63%
rename from library/HTMLPurifier/Lexer.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php
index b05e115468..43732621dc 100644
--- a/library/HTMLPurifier/Lexer.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer.php
@@ -62,16 +62,20 @@ class HTMLPurifier_Lexer
      *       To specify your own prototype, set %Core.LexerImpl to it.
      *       This change in behavior de-singletonizes the lexer object.
      *
-     * @param $config Instance of HTMLPurifier_Config
-     * @return Concrete lexer.
+     * @param HTMLPurifier_Config $config
+     * @return HTMLPurifier_Lexer
+     * @throws HTMLPurifier_Exception
      */
-    public static function create($config) {
-
+    public static function create($config)
+    {
         if (!($config instanceof HTMLPurifier_Config)) {
             $lexer = $config;
-            trigger_error("Passing a prototype to
-              HTMLPurifier_Lexer::create() is deprecated, please instead
-              use %Core.LexerImpl", E_USER_WARNING);
+            trigger_error(
+                "Passing a prototype to
+                HTMLPurifier_Lexer::create() is deprecated, please instead
+                use %Core.LexerImpl",
+                E_USER_WARNING
+            );
         } else {
             $lexer = $config->get('Core.LexerImpl');
         }
@@ -84,30 +88,28 @@ class HTMLPurifier_Lexer
         if (is_object($lexer)) {
             $inst = $lexer;
         } else {
+            if (is_null($lexer)) {
+                do {
+                    // auto-detection algorithm
+                    if ($needs_tracking) {
+                        $lexer = 'DirectLex';
+                        break;
+                    }
 
-            if (is_null($lexer)) { do {
-                // auto-detection algorithm
-
-                if ($needs_tracking) {
-                    $lexer = 'DirectLex';
-                    break;
-                }
-
-                if (
-                    class_exists('DOMDocument') &&
-                    method_exists('DOMDocument', 'loadHTML') &&
-                    !extension_loaded('domxml')
-                ) {
-                    // check for DOM support, because while it's part of the
-                    // core, it can be disabled compile time. Also, the PECL
-                    // domxml extension overrides the default DOM, and is evil
-                    // and nasty and we shan't bother to support it
-                    $lexer = 'DOMLex';
-                } else {
-                    $lexer = 'DirectLex';
-                }
-
-            } while(0); } // do..while so we can break
+                    if (class_exists('DOMDocument') &&
+                        method_exists('DOMDocument', 'loadHTML') &&
+                        !extension_loaded('domxml')
+                    ) {
+                        // check for DOM support, because while it's part of the
+                        // core, it can be disabled compile time. Also, the PECL
+                        // domxml extension overrides the default DOM, and is evil
+                        // and nasty and we shan't bother to support it
+                        $lexer = 'DOMLex';
+                    } else {
+                        $lexer = 'DirectLex';
+                    }
+                } while (0);
+            } // do..while so we can break
 
             // instantiate recognized string names
             switch ($lexer) {
@@ -121,16 +123,24 @@ class HTMLPurifier_Lexer
                     $inst = new HTMLPurifier_Lexer_PH5P();
                     break;
                 default:
-                    throw new HTMLPurifier_Exception("Cannot instantiate unrecognized Lexer type " . htmlspecialchars($lexer));
+                    throw new HTMLPurifier_Exception(
+                        "Cannot instantiate unrecognized Lexer type " .
+                        htmlspecialchars($lexer)
+                    );
             }
         }
 
-        if (!$inst) throw new HTMLPurifier_Exception('No lexer was instantiated');
+        if (!$inst) {
+            throw new HTMLPurifier_Exception('No lexer was instantiated');
+        }
 
         // once PHP DOM implements native line numbers, or we
         // hack out something using XSLT, remove this stipulation
         if ($needs_tracking && !$inst->tracksLineNumbers) {
-            throw new HTMLPurifier_Exception('Cannot use lexer that does not support line numbers with Core.MaintainLineNumbers or Core.CollectErrors (use DirectLex instead)');
+            throw new HTMLPurifier_Exception(
+                'Cannot use lexer that does not support line numbers with ' .
+                'Core.MaintainLineNumbers or Core.CollectErrors (use DirectLex instead)'
+            );
         }
 
         return $inst;
@@ -139,23 +149,25 @@ class HTMLPurifier_Lexer
 
     // -- CONVENIENCE MEMBERS ---------------------------------------------
 
-    public function __construct() {
+    public function __construct()
+    {
         $this->_entity_parser = new HTMLPurifier_EntityParser();
     }
 
     /**
      * Most common entity to raw value conversion table for special entities.
+     * @type array
      */
     protected $_special_entity2str =
-            array(
-                    '&quot;' => '"',
-                    '&amp;'  => '&',
-                    '&lt;'   => '<',
-                    '&gt;'   => '>',
-                    '&#39;'  => "'",
-                    '&#039;' => "'",
-                    '&#x27;' => "'"
-            );
+        array(
+            '&quot;' => '"',
+            '&amp;' => '&',
+            '&lt;' => '<',
+            '&gt;' => '>',
+            '&#39;' => "'",
+            '&#039;' => "'",
+            '&#x27;' => "'"
+        );
 
     /**
      * Parses special entities into the proper characters.
@@ -168,27 +180,33 @@ class HTMLPurifier_Lexer
      * completely parsed, but that's only because all other entities should
      * have been handled previously in substituteNonSpecialEntities()
      *
-     * @param $string String character data to be parsed.
-     * @returns Parsed character data.
+     * @param string $string String character data to be parsed.
+     * @return string Parsed character data.
      */
-    public function parseData($string) {
-
+    public function parseData($string)
+    {
         // following functions require at least one character
-        if ($string === '') return '';
+        if ($string === '') {
+            return '';
+        }
 
         // subtracts amps that cannot possibly be escaped
         $num_amp = substr_count($string, '&') - substr_count($string, '& ') -
-            ($string[strlen($string)-1] === '&' ? 1 : 0);
+            ($string[strlen($string) - 1] === '&' ? 1 : 0);
 
-        if (!$num_amp) return $string; // abort if no entities
+        if (!$num_amp) {
+            return $string;
+        } // abort if no entities
         $num_esc_amp = substr_count($string, '&amp;');
         $string = strtr($string, $this->_special_entity2str);
 
         // code duplication for sake of optimization, see above
         $num_amp_2 = substr_count($string, '&') - substr_count($string, '& ') -
-            ($string[strlen($string)-1] === '&' ? 1 : 0);
+            ($string[strlen($string) - 1] === '&' ? 1 : 0);
 
-        if ($num_amp_2 <= $num_esc_amp) return $string;
+        if ($num_amp_2 <= $num_esc_amp) {
+            return $string;
+        }
 
         // hmm... now we have some uncommon entities. Use the callback.
         $string = $this->_entity_parser->substituteSpecialEntities($string);
@@ -197,21 +215,23 @@ class HTMLPurifier_Lexer
 
     /**
      * Lexes an HTML string into tokens.
-     *
      * @param $string String HTML.
-     * @return HTMLPurifier_Token array representation of HTML.
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return HTMLPurifier_Token[] array representation of HTML.
      */
-    public function tokenizeHTML($string, $config, $context) {
+    public function tokenizeHTML($string, $config, $context)
+    {
         trigger_error('Call to abstract class', E_USER_ERROR);
     }
 
     /**
      * Translates CDATA sections into regular sections (through escaping).
-     *
-     * @param $string HTML string to process.
-     * @returns HTML with CDATA sections escaped.
+     * @param string $string HTML string to process.
+     * @return string HTML with CDATA sections escaped.
      */
-    protected static function escapeCDATA($string) {
+    protected static function escapeCDATA($string)
+    {
         return preg_replace_callback(
             '/<!\[CDATA\[(.+?)\]\]>/s',
             array('HTMLPurifier_Lexer', 'CDATACallback'),
@@ -221,8 +241,11 @@ class HTMLPurifier_Lexer
 
     /**
      * Special CDATA case that is especially convoluted for <script>
+     * @param string $string HTML string to process.
+     * @return string HTML with CDATA sections escaped.
      */
-    protected static function escapeCommentedCDATA($string) {
+    protected static function escapeCommentedCDATA($string)
+    {
         return preg_replace_callback(
             '#<!--//--><!\[CDATA\[//><!--(.+?)//--><!\]\]>#s',
             array('HTMLPurifier_Lexer', 'CDATACallback'),
@@ -230,16 +253,31 @@ class HTMLPurifier_Lexer
         );
     }
 
+    /**
+     * Special Internet Explorer conditional comments should be removed.
+     * @param string $string HTML string to process.
+     * @return string HTML with conditional comments removed.
+     */
+    protected static function removeIEConditional($string)
+    {
+        return preg_replace(
+            '#<!--\[if [^>]+\]>.*?<!\[endif\]-->#si', // probably should generalize for all strings
+            '',
+            $string
+        );
+    }
+
     /**
      * Callback function for escapeCDATA() that does the work.
      *
      * @warning Though this is public in order to let the callback happen,
      *          calling it directly is not recommended.
-     * @params $matches PCRE matches array, with index 0 the entire match
+     * @param array $matches PCRE matches array, with index 0 the entire match
      *                  and 1 the inside of the CDATA section.
-     * @returns Escaped internals of the CDATA section.
+     * @return string Escaped internals of the CDATA section.
      */
-    protected static function CDATACallback($matches) {
+    protected static function CDATACallback($matches)
+    {
         // not exactly sure why the character set is needed, but whatever
         return htmlspecialchars($matches[1], ENT_COMPAT, 'UTF-8');
     }
@@ -247,13 +285,19 @@ class HTMLPurifier_Lexer
     /**
      * Takes a piece of HTML and normalizes it by converting entities, fixing
      * encoding, extracting bits, and other good stuff.
+     * @param string $html HTML.
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
      * @todo Consider making protected
      */
-    public function normalize($html, $config, $context) {
-
+    public function normalize($html, $config, $context)
+    {
         // normalize newlines to \n
-        $html = str_replace("\r\n", "\n", $html);
-        $html = str_replace("\r", "\n", $html);
+        if ($config->get('Core.NormalizeNewlines')) {
+            $html = str_replace("\r\n", "\n", $html);
+            $html = str_replace("\r", "\n", $html);
+        }
 
         if ($config->get('HTML.Trusted')) {
             // escape convoluted CDATA
@@ -263,6 +307,8 @@ class HTMLPurifier_Lexer
         // escape CDATA
         $html = $this->escapeCDATA($html);
 
+        $html = $this->removeIEConditional($html);
+
         // extract body from document if applicable
         if ($config->get('Core.ConvertDocumentToFragment')) {
             $e = false;
@@ -284,6 +330,11 @@ class HTMLPurifier_Lexer
         // represent non-SGML characters (horror, horror!)
         $html = HTMLPurifier_Encoder::cleanUTF8($html);
 
+        // if processing instructions are to removed, remove them now
+        if ($config->get('Core.RemoveProcessingInstructions')) {
+            $html = preg_replace('#<\?.+?\?>#s', '', $html);
+        }
+
         return $html;
     }
 
@@ -291,7 +342,8 @@ class HTMLPurifier_Lexer
      * Takes a string of HTML (fragment or document) and returns the content
      * @todo Consider making protected
      */
-    public function extractBody($html) {
+    public function extractBody($html)
+    {
         $matches = array();
         $result = preg_match('!<body[^>]*>(.*)</body>!is', $html, $matches);
         if ($result) {
@@ -300,7 +352,6 @@ class HTMLPurifier_Lexer
             return $html;
         }
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Lexer/DOMLex.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php
similarity index 58%
rename from library/HTMLPurifier/Lexer/DOMLex.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php
index 20dc2ed48c..b818192909 100644
--- a/library/HTMLPurifier/Lexer/DOMLex.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DOMLex.php
@@ -27,16 +27,26 @@
 class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer
 {
 
+    /**
+     * @type HTMLPurifier_TokenFactory
+     */
     private $factory;
 
-    public function __construct() {
+    public function __construct()
+    {
         // setup the factory
         parent::__construct();
         $this->factory = new HTMLPurifier_TokenFactory();
     }
 
-    public function tokenizeHTML($html, $config, $context) {
-
+    /**
+     * @param string $html
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return HTMLPurifier_Token[]
+     */
+    public function tokenizeHTML($html, $config, $context)
+    {
         $html = $this->normalize($html, $config, $context);
 
         // attempt to armor stray angled brackets that cannot possibly
@@ -65,30 +75,66 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer
         $tokens = array();
         $this->tokenizeDOM(
             $doc->getElementsByTagName('html')->item(0)-> // <html>
-                  getElementsByTagName('body')->item(0)-> //   <body>
-                  getElementsByTagName('div')->item(0)    //     <div>
-            , $tokens);
+            getElementsByTagName('body')->item(0), //   <body>
+            $tokens
+        );
         return $tokens;
     }
 
     /**
-     * Recursive function that tokenizes a node, putting it into an accumulator.
-     *
-     * @param $node     DOMNode to be tokenized.
-     * @param $tokens   Array-list of already tokenized tokens.
-     * @param $collect  Says whether or start and close are collected, set to
-     *                  false at first recursion because it's the implicit DIV
-     *                  tag you're dealing with.
-     * @returns Tokens of node appended to previously passed tokens.
+     * Iterative function that tokenizes a node, putting it into an accumulator.
+     * To iterate is human, to recurse divine - L. Peter Deutsch
+     * @param DOMNode $node DOMNode to be tokenized.
+     * @param HTMLPurifier_Token[] $tokens   Array-list of already tokenized tokens.
+     * @return HTMLPurifier_Token of node appended to previously passed tokens.
      */
-    protected function tokenizeDOM($node, &$tokens, $collect = false) {
+    protected function tokenizeDOM($node, &$tokens)
+    {
+        $level = 0;
+        $nodes = array($level => new HTMLPurifier_Queue(array($node)));
+        $closingNodes = array();
+        do {
+            while (!$nodes[$level]->isEmpty()) {
+                $node = $nodes[$level]->shift(); // FIFO
+                $collect = $level > 0 ? true : false;
+                $needEndingTag = $this->createStartNode($node, $tokens, $collect);
+                if ($needEndingTag) {
+                    $closingNodes[$level][] = $node;
+                }
+                if ($node->childNodes && $node->childNodes->length) {
+                    $level++;
+                    $nodes[$level] = new HTMLPurifier_Queue();
+                    foreach ($node->childNodes as $childNode) {
+                        $nodes[$level]->push($childNode);
+                    }
+                }
+            }
+            $level--;
+            if ($level && isset($closingNodes[$level])) {
+                while ($node = array_pop($closingNodes[$level])) {
+                    $this->createEndNode($node, $tokens);
+                }
+            }
+        } while ($level > 0);
+    }
 
+    /**
+     * @param DOMNode $node DOMNode to be tokenized.
+     * @param HTMLPurifier_Token[] $tokens   Array-list of already tokenized tokens.
+     * @param bool $collect  Says whether or start and close are collected, set to
+     *                    false at first recursion because it's the implicit DIV
+     *                    tag you're dealing with.
+     * @return bool if the token needs an endtoken
+     * @todo data and tagName properties don't seem to exist in DOMNode?
+     */
+    protected function createStartNode($node, &$tokens, $collect)
+    {
         // intercept non element nodes. WE MUST catch all of them,
         // but we're not getting the character reference nodes because
         // those should have been preprocessed
         if ($node->nodeType === XML_TEXT_NODE) {
             $tokens[] = $this->factory->createText($node->data);
-            return;
+            return false;
         } elseif ($node->nodeType === XML_CDATA_SECTION_NODE) {
             // undo libxml's special treatment of <script> and <style> tags
             $last = end($tokens);
@@ -106,59 +152,61 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer
                 }
             }
             $tokens[] = $this->factory->createText($this->parseData($data));
-            return;
+            return false;
         } elseif ($node->nodeType === XML_COMMENT_NODE) {
             // this is code is only invoked for comments in script/style in versions
             // of libxml pre-2.6.28 (regular comments, of course, are still
             // handled regularly)
             $tokens[] = $this->factory->createComment($node->data);
-            return;
-        } elseif (
+            return false;
+        } elseif ($node->nodeType !== XML_ELEMENT_NODE) {
             // not-well tested: there may be other nodes we have to grab
-            $node->nodeType !== XML_ELEMENT_NODE
-        ) {
-            return;
+            return false;
         }
 
-        $attr = $node->hasAttributes() ?
-            $this->transformAttrToAssoc($node->attributes) :
-            array();
+        $attr = $node->hasAttributes() ? $this->transformAttrToAssoc($node->attributes) : array();
 
         // We still have to make sure that the element actually IS empty
         if (!$node->childNodes->length) {
             if ($collect) {
                 $tokens[] = $this->factory->createEmpty($node->tagName, $attr);
             }
+            return false;
         } else {
-            if ($collect) { // don't wrap on first iteration
+            if ($collect) {
                 $tokens[] = $this->factory->createStart(
                     $tag_name = $node->tagName, // somehow, it get's dropped
                     $attr
                 );
             }
-            foreach ($node->childNodes as $node) {
-                // remember, it's an accumulator. Otherwise, we'd have
-                // to use array_merge
-                $this->tokenizeDOM($node, $tokens, true);
-            }
-            if ($collect) {
-                $tokens[] = $this->factory->createEnd($tag_name);
-            }
+            return true;
         }
-
     }
 
+    /**
+     * @param DOMNode $node
+     * @param HTMLPurifier_Token[] $tokens
+     */
+    protected function createEndNode($node, &$tokens)
+    {
+        $tokens[] = $this->factory->createEnd($node->tagName);
+    }
+
+
     /**
      * Converts a DOMNamedNodeMap of DOMAttr objects into an assoc array.
      *
-     * @param $attribute_list DOMNamedNodeMap of DOMAttr objects.
-     * @returns Associative array of attributes.
+     * @param DOMNamedNodeMap $node_map DOMNamedNodeMap of DOMAttr objects.
+     * @return array Associative array of attributes.
      */
-    protected function transformAttrToAssoc($node_map) {
+    protected function transformAttrToAssoc($node_map)
+    {
         // NamedNodeMap is documented very well, so we're using undocumented
         // features, namely, the fact that it implements Iterator and
         // has a ->length attribute
-        if ($node_map->length === 0) return array();
+        if ($node_map->length === 0) {
+            return array();
+        }
         $array = array();
         foreach ($node_map as $attr) {
             $array[$attr->name] = $attr->value;
@@ -168,46 +216,64 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer
 
     /**
      * An error handler that mutes all errors
+     * @param int $errno
+     * @param string $errstr
      */
-    public function muteErrorHandler($errno, $errstr) {}
+    public function muteErrorHandler($errno, $errstr)
+    {
+    }
 
     /**
      * Callback function for undoing escaping of stray angled brackets
      * in comments
+     * @param array $matches
+     * @return string
      */
-    public function callbackUndoCommentSubst($matches) {
-        return '<!--' . strtr($matches[1], array('&amp;'=>'&','&lt;'=>'<')) . $matches[2];
+    public function callbackUndoCommentSubst($matches)
+    {
+        return '<!--' . strtr($matches[1], array('&amp;' => '&', '&lt;' => '<')) . $matches[2];
     }
 
     /**
      * Callback function that entity-izes ampersands in comments so that
      * callbackUndoCommentSubst doesn't clobber them
+     * @param array $matches
+     * @return string
      */
-    public function callbackArmorCommentEntities($matches) {
+    public function callbackArmorCommentEntities($matches)
+    {
         return '<!--' . str_replace('&', '&amp;', $matches[1]) . $matches[2];
     }
 
     /**
      * Wraps an HTML fragment in the necessary HTML
+     * @param string $html
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
      */
-    protected function wrapHTML($html, $config, $context) {
+    protected function wrapHTML($html, $config, $context)
+    {
         $def = $config->getDefinition('HTML');
         $ret = '';
 
         if (!empty($def->doctype->dtdPublic) || !empty($def->doctype->dtdSystem)) {
             $ret .= '<!DOCTYPE html ';
-            if (!empty($def->doctype->dtdPublic)) $ret .= 'PUBLIC "' . $def->doctype->dtdPublic . '" ';
-            if (!empty($def->doctype->dtdSystem)) $ret .= '"' . $def->doctype->dtdSystem . '" ';
+            if (!empty($def->doctype->dtdPublic)) {
+                $ret .= 'PUBLIC "' . $def->doctype->dtdPublic . '" ';
+            }
+            if (!empty($def->doctype->dtdSystem)) {
+                $ret .= '"' . $def->doctype->dtdSystem . '" ';
+            }
             $ret .= '>';
         }
 
         $ret .= '<html><head>';
         $ret .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
         // No protection if $html contains a stray </div>!
-        $ret .= '</head><body><div>'.$html.'</div></body></html>';
+        $ret .= '</head><body>' . $html . '</body></html>';
         return $ret;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Lexer/DirectLex.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DirectLex.php
similarity index 76%
rename from library/HTMLPurifier/Lexer/DirectLex.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DirectLex.php
index 456e6e1908..746b6e315f 100644
--- a/library/HTMLPurifier/Lexer/DirectLex.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/DirectLex.php
@@ -12,30 +12,44 @@
  */
 class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
 {
-
+    /**
+     * @type bool
+     */
     public $tracksLineNumbers = true;
 
     /**
      * Whitespace characters for str(c)spn.
+     * @type string
      */
     protected $_whitespace = "\x20\x09\x0D\x0A";
 
     /**
      * Callback function for script CDATA fudge
-     * @param $matches, in form of array(opening tag, contents, closing tag)
+     * @param array $matches, in form of array(opening tag, contents, closing tag)
+     * @return string
      */
-    protected function scriptCallback($matches) {
+    protected function scriptCallback($matches)
+    {
         return $matches[1] . htmlspecialchars($matches[2], ENT_COMPAT, 'UTF-8') . $matches[3];
     }
 
-    public function tokenizeHTML($html, $config, $context) {
-
+    /**
+     * @param String $html
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array|HTMLPurifier_Token[]
+     */
+    public function tokenizeHTML($html, $config, $context)
+    {
         // special normalization for script tags without any armor
         // our "armor" heurstic is a < sign any number of whitespaces after
         // the first script tag
         if ($config->get('HTML.Trusted')) {
-            $html = preg_replace_callback('#(<script[^>]*>)(\s*[^<].+?)(</script>)#si',
-                array($this, 'scriptCallback'), $html);
+            $html = preg_replace_callback(
+                '#(<script[^>]*>)(\s*[^<].+?)(</script>)#si',
+                array($this, 'scriptCallback'),
+                $html
+            );
         }
 
         $html = $this->normalize($html, $config, $context);
@@ -55,15 +69,15 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
 
         if ($maintain_line_numbers) {
             $current_line = 1;
-            $current_col  = 0;
+            $current_col = 0;
             $length = strlen($html);
         } else {
             $current_line = false;
-            $current_col  = false;
+            $current_col = false;
             $length = false;
         }
         $context->register('CurrentLine', $current_line);
-        $context->register('CurrentCol',  $current_col);
+        $context->register('CurrentCol', $current_col);
         $nl = "\n";
         // how often to manually recalculate. This will ALWAYS be right,
         // but it's pretty wasteful. Set to 0 to turn off
@@ -77,16 +91,14 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
         // for testing synchronization
         $loops = 0;
 
-        while(++$loops) {
-
+        while (++$loops) {
             // $cursor is either at the start of a token, or inside of
             // a tag (i.e. there was a < immediately before it), as indicated
             // by $inside_tag
 
             if ($maintain_line_numbers) {
-
                 // $rcursor, however, is always at the start of a token.
-                $rcursor = $cursor - (int) $inside_tag;
+                $rcursor = $cursor - (int)$inside_tag;
 
                 // Column number is cheap, so we calculate it every round.
                 // We're interested at the *end* of the newline string, so
@@ -96,14 +108,11 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
                 $current_col = $rcursor - (is_bool($nl_pos) ? 0 : $nl_pos + 1);
 
                 // recalculate lines
-                if (
-                    $synchronize_interval &&  // synchronization is on
-                    $cursor > 0 &&            // cursor is further than zero
-                    $loops % $synchronize_interval === 0 // time to synchronize!
-                ) {
+                if ($synchronize_interval && // synchronization is on
+                    $cursor > 0 && // cursor is further than zero
+                    $loops % $synchronize_interval === 0) { // time to synchronize!
                     $current_line = 1 + $this->substrCount($html, $nl, 0, $cursor);
                 }
-
             }
 
             $position_next_lt = strpos($html, '<', $cursor);
@@ -119,35 +128,42 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
             if (!$inside_tag && $position_next_lt !== false) {
                 // We are not inside tag and there still is another tag to parse
                 $token = new
-                    HTMLPurifier_Token_Text(
-                        $this->parseData(
-                            substr(
-                                $html, $cursor, $position_next_lt - $cursor
-                            )
+                HTMLPurifier_Token_Text(
+                    $this->parseData(
+                        substr(
+                            $html,
+                            $cursor,
+                            $position_next_lt - $cursor
                         )
-                    );
+                    )
+                );
                 if ($maintain_line_numbers) {
                     $token->rawPosition($current_line, $current_col);
                     $current_line += $this->substrCount($html, $nl, $cursor, $position_next_lt - $cursor);
                 }
                 $array[] = $token;
-                $cursor  = $position_next_lt + 1;
+                $cursor = $position_next_lt + 1;
                 $inside_tag = true;
                 continue;
             } elseif (!$inside_tag) {
                 // We are not inside tag but there are no more tags
                 // If we're already at the end, break
-                if ($cursor === strlen($html)) break;
+                if ($cursor === strlen($html)) {
+                    break;
+                }
                 // Create Text of rest of string
                 $token = new
-                    HTMLPurifier_Token_Text(
-                        $this->parseData(
-                            substr(
-                                $html, $cursor
-                            )
+                HTMLPurifier_Token_Text(
+                    $this->parseData(
+                        substr(
+                            $html,
+                            $cursor
                         )
-                    );
-                if ($maintain_line_numbers) $token->rawPosition($current_line, $current_col);
+                    )
+                );
+                if ($maintain_line_numbers) {
+                    $token->rawPosition($current_line, $current_col);
+                }
                 $array[] = $token;
                 break;
             } elseif ($inside_tag && $position_next_gt !== false) {
@@ -171,16 +187,16 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
                 }
 
                 // Check if it's a comment
-                if (
-                    substr($segment, 0, 3) === '!--'
-                ) {
+                if (substr($segment, 0, 3) === '!--') {
                     // re-determine segment length, looking for -->
                     $position_comment_end = strpos($html, '-->', $cursor);
                     if ($position_comment_end === false) {
                         // uh oh, we have a comment that extends to
                         // infinity. Can't be helped: set comment
                         // end position to end of string
-                        if ($e) $e->send(E_WARNING, 'Lexer: Unclosed comment');
+                        if ($e) {
+                            $e->send(E_WARNING, 'Lexer: Unclosed comment');
+                        }
                         $position_comment_end = strlen($html);
                         $end = true;
                     } else {
@@ -189,11 +205,13 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
                     $strlen_segment = $position_comment_end - $cursor;
                     $segment = substr($html, $cursor, $strlen_segment);
                     $token = new
-                        HTMLPurifier_Token_Comment(
-                            substr(
-                                $segment, 3, $strlen_segment - 3
-                            )
-                        );
+                    HTMLPurifier_Token_Comment(
+                        substr(
+                            $segment,
+                            3,
+                            $strlen_segment - 3
+                        )
+                    );
                     if ($maintain_line_numbers) {
                         $token->rawPosition($current_line, $current_col);
                         $current_line += $this->substrCount($html, $nl, $cursor, $strlen_segment);
@@ -205,7 +223,7 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
                 }
 
                 // Check if it's an end tag
-                $is_end_tag = (strpos($segment,'/') === 0);
+                $is_end_tag = (strpos($segment, '/') === 0);
                 if ($is_end_tag) {
                     $type = substr($segment, 1);
                     $token = new HTMLPurifier_Token_End($type);
@@ -224,7 +242,9 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
                 // text and go our merry way
                 if (!ctype_alpha($segment[0])) {
                     // XML:  $segment[0] !== '_' && $segment[0] !== ':'
-                    if ($e) $e->send(E_NOTICE, 'Lexer: Unescaped lt');
+                    if ($e) {
+                        $e->send(E_NOTICE, 'Lexer: Unescaped lt');
+                    }
                     $token = new HTMLPurifier_Token_Text('<');
                     if ($maintain_line_numbers) {
                         $token->rawPosition($current_line, $current_col);
@@ -239,7 +259,7 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
                 // trailing slash. Remember, we could have a tag like <br>, so
                 // any later token processing scripts must convert improperly
                 // classified EmptyTags from StartTags.
-                $is_self_closing = (strrpos($segment,'/') === $strlen_segment-1);
+                $is_self_closing = (strrpos($segment, '/') === $strlen_segment - 1);
                 if ($is_self_closing) {
                     $strlen_segment--;
                     $segment = substr($segment, 0, $strlen_segment);
@@ -269,14 +289,16 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
                 $attribute_string =
                     trim(
                         substr(
-                            $segment, $position_first_space
+                            $segment,
+                            $position_first_space
                         )
                     );
                 if ($attribute_string) {
                     $attr = $this->parseAttributeString(
-                                    $attribute_string
-                                  , $config, $context
-                              );
+                        $attribute_string,
+                        $config,
+                        $context
+                    );
                 } else {
                     $attr = array();
                 }
@@ -296,15 +318,19 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
                 continue;
             } else {
                 // inside tag, but there's no ending > sign
-                if ($e) $e->send(E_WARNING, 'Lexer: Missing gt');
+                if ($e) {
+                    $e->send(E_WARNING, 'Lexer: Missing gt');
+                }
                 $token = new
-                    HTMLPurifier_Token_Text(
-                        '<' .
-                        $this->parseData(
-                            substr($html, $cursor)
-                        )
-                    );
-                if ($maintain_line_numbers) $token->rawPosition($current_line, $current_col);
+                HTMLPurifier_Token_Text(
+                    '<' .
+                    $this->parseData(
+                        substr($html, $cursor)
+                    )
+                );
+                if ($maintain_line_numbers) {
+                    $token->rawPosition($current_line, $current_col);
+                }
                 // no cursor scroll? Hmm...
                 $array[] = $token;
                 break;
@@ -319,8 +345,14 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
 
     /**
      * PHP 5.0.x compatible substr_count that implements offset and length
+     * @param string $haystack
+     * @param string $needle
+     * @param int $offset
+     * @param int $length
+     * @return int
      */
-    protected function substrCount($haystack, $needle, $offset, $length) {
+    protected function substrCount($haystack, $needle, $offset, $length)
+    {
         static $oldVersion;
         if ($oldVersion === null) {
             $oldVersion = version_compare(PHP_VERSION, '5.1', '<');
@@ -336,13 +368,18 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
     /**
      * Takes the inside of an HTML tag and makes an assoc array of attributes.
      *
-     * @param $string Inside of tag excluding name.
-     * @returns Assoc array of attributes.
+     * @param string $string Inside of tag excluding name.
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array Assoc array of attributes.
      */
-    public function parseAttributeString($string, $config, $context) {
-        $string = (string) $string; // quick typecast
+    public function parseAttributeString($string, $config, $context)
+    {
+        $string = (string)$string; // quick typecast
 
-        if ($string == '') return array(); // no attributes
+        if ($string == '') {
+            return array();
+        } // no attributes
 
         $e = false;
         if ($config->get('Core.CollectErrors')) {
@@ -361,46 +398,55 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
             list($key, $quoted_value) = explode('=', $string);
             $quoted_value = trim($quoted_value);
             if (!$key) {
-                if ($e) $e->send(E_ERROR, 'Lexer: Missing attribute key');
+                if ($e) {
+                    $e->send(E_ERROR, 'Lexer: Missing attribute key');
+                }
                 return array();
             }
-            if (!$quoted_value) return array($key => '');
+            if (!$quoted_value) {
+                return array($key => '');
+            }
             $first_char = @$quoted_value[0];
-            $last_char  = @$quoted_value[strlen($quoted_value)-1];
+            $last_char = @$quoted_value[strlen($quoted_value) - 1];
 
             $same_quote = ($first_char == $last_char);
             $open_quote = ($first_char == '"' || $first_char == "'");
 
-            if ( $same_quote && $open_quote) {
+            if ($same_quote && $open_quote) {
                 // well behaved
                 $value = substr($quoted_value, 1, strlen($quoted_value) - 2);
             } else {
                 // not well behaved
                 if ($open_quote) {
-                    if ($e) $e->send(E_ERROR, 'Lexer: Missing end quote');
+                    if ($e) {
+                        $e->send(E_ERROR, 'Lexer: Missing end quote');
+                    }
                     $value = substr($quoted_value, 1);
                 } else {
                     $value = $quoted_value;
                 }
             }
-            if ($value === false) $value = '';
+            if ($value === false) {
+                $value = '';
+            }
             return array($key => $this->parseData($value));
         }
 
         // setup loop environment
-        $array  = array(); // return assoc array of attributes
+        $array = array(); // return assoc array of attributes
         $cursor = 0; // current position in string (moves forward)
-        $size   = strlen($string); // size of the string (stays the same)
+        $size = strlen($string); // size of the string (stays the same)
 
         // if we have unquoted attributes, the parser expects a terminating
         // space, so let's guarantee that there's always a terminating space.
         $string .= ' ';
 
-        while(true) {
-
-            if ($cursor >= $size) {
-                break;
+        $old_cursor = -1;
+        while ($cursor < $size) {
+            if ($old_cursor >= $cursor) {
+                throw new Exception("Infinite loop detected");
             }
+            $old_cursor = $cursor;
 
             $cursor += ($value = strspn($string, $this->_whitespace, $cursor));
             // grab the key
@@ -415,8 +461,10 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
             $key = substr($string, $key_begin, $key_end - $key_begin);
 
             if (!$key) {
-                if ($e) $e->send(E_ERROR, 'Lexer: Missing attribute key');
-                $cursor += strcspn($string, $this->_whitespace, $cursor + 1); // prevent infinite loop
+                if ($e) {
+                    $e->send(E_ERROR, 'Lexer: Missing attribute key');
+                }
+                $cursor += 1 + strcspn($string, $this->_whitespace, $cursor + 1); // prevent infinite loop
                 continue; // empty key
             }
 
@@ -467,24 +515,25 @@ class HTMLPurifier_Lexer_DirectLex extends HTMLPurifier_Lexer
                 }
 
                 $value = substr($string, $value_begin, $value_end - $value_begin);
-                if ($value === false) $value = '';
+                if ($value === false) {
+                    $value = '';
+                }
                 $array[$key] = $this->parseData($value);
                 $cursor++;
-
             } else {
                 // boolattr
                 if ($key !== '') {
                     $array[$key] = $key;
                 } else {
                     // purely theoretical
-                    if ($e) $e->send(E_ERROR, 'Lexer: Missing attribute key');
+                    if ($e) {
+                        $e->send(E_ERROR, 'Lexer: Missing attribute key');
+                    }
                 }
-
             }
         }
         return $array;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/PH5P.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/PH5P.php
new file mode 100644
index 0000000000..ff4fa218fb
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Lexer/PH5P.php
@@ -0,0 +1,4787 @@
+<?php
+
+/**
+ * Experimental HTML5-based parser using Jeroen van der Meer's PH5P library.
+ * Occupies space in the HTML5 pseudo-namespace, which may cause conflicts.
+ *
+ * @note
+ *    Recent changes to PHP's DOM extension have resulted in some fatal
+ *    error conditions with the original version of PH5P. Pending changes,
+ *    this lexer will punt to DirectLex if DOM throws an exception.
+ */
+
+class HTMLPurifier_Lexer_PH5P extends HTMLPurifier_Lexer_DOMLex
+{
+    /**
+     * @param string $html
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return HTMLPurifier_Token[]
+     */
+    public function tokenizeHTML($html, $config, $context)
+    {
+        $new_html = $this->normalize($html, $config, $context);
+        $new_html = $this->wrapHTML($new_html, $config, $context);
+        try {
+            $parser = new HTML5($new_html);
+            $doc = $parser->save();
+        } catch (DOMException $e) {
+            // Uh oh, it failed. Punt to DirectLex.
+            $lexer = new HTMLPurifier_Lexer_DirectLex();
+            $context->register('PH5PError', $e); // save the error, so we can detect it
+            return $lexer->tokenizeHTML($html, $config, $context); // use original HTML
+        }
+        $tokens = array();
+        $this->tokenizeDOM(
+            $doc->getElementsByTagName('html')->item(0)-> // <html>
+                getElementsByTagName('body')->item(0) //   <body>
+            ,
+            $tokens
+        );
+        return $tokens;
+    }
+}
+
+/*
+
+Copyright 2007 Jeroen van der Meer <http://jero.net/>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+class HTML5
+{
+    private $data;
+    private $char;
+    private $EOF;
+    private $state;
+    private $tree;
+    private $token;
+    private $content_model;
+    private $escape = false;
+    private $entities = array(
+        'AElig;',
+        'AElig',
+        'AMP;',
+        'AMP',
+        'Aacute;',
+        'Aacute',
+        'Acirc;',
+        'Acirc',
+        'Agrave;',
+        'Agrave',
+        'Alpha;',
+        'Aring;',
+        'Aring',
+        'Atilde;',
+        'Atilde',
+        'Auml;',
+        'Auml',
+        'Beta;',
+        'COPY;',
+        'COPY',
+        'Ccedil;',
+        'Ccedil',
+        'Chi;',
+        'Dagger;',
+        'Delta;',
+        'ETH;',
+        'ETH',
+        'Eacute;',
+        'Eacute',
+        'Ecirc;',
+        'Ecirc',
+        'Egrave;',
+        'Egrave',
+        'Epsilon;',
+        'Eta;',
+        'Euml;',
+        'Euml',
+        'GT;',
+        'GT',
+        'Gamma;',
+        'Iacute;',
+        'Iacute',
+        'Icirc;',
+        'Icirc',
+        'Igrave;',
+        'Igrave',
+        'Iota;',
+        'Iuml;',
+        'Iuml',
+        'Kappa;',
+        'LT;',
+        'LT',
+        'Lambda;',
+        'Mu;',
+        'Ntilde;',
+        'Ntilde',
+        'Nu;',
+        'OElig;',
+        'Oacute;',
+        'Oacute',
+        'Ocirc;',
+        'Ocirc',
+        'Ograve;',
+        'Ograve',
+        'Omega;',
+        'Omicron;',
+        'Oslash;',
+        'Oslash',
+        'Otilde;',
+        'Otilde',
+        'Ouml;',
+        'Ouml',
+        'Phi;',
+        'Pi;',
+        'Prime;',
+        'Psi;',
+        'QUOT;',
+        'QUOT',
+        'REG;',
+        'REG',
+        'Rho;',
+        'Scaron;',
+        'Sigma;',
+        'THORN;',
+        'THORN',
+        'TRADE;',
+        'Tau;',
+        'Theta;',
+        'Uacute;',
+        'Uacute',
+        'Ucirc;',
+        'Ucirc',
+        'Ugrave;',
+        'Ugrave',
+        'Upsilon;',
+        'Uuml;',
+        'Uuml',
+        'Xi;',
+        'Yacute;',
+        'Yacute',
+        'Yuml;',
+        'Zeta;',
+        'aacute;',
+        'aacute',
+        'acirc;',
+        'acirc',
+        'acute;',
+        'acute',
+        'aelig;',
+        'aelig',
+        'agrave;',
+        'agrave',
+        'alefsym;',
+        'alpha;',
+        'amp;',
+        'amp',
+        'and;',
+        'ang;',
+        'apos;',
+        'aring;',
+        'aring',
+        'asymp;',
+        'atilde;',
+        'atilde',
+        'auml;',
+        'auml',
+        'bdquo;',
+        'beta;',
+        'brvbar;',
+        'brvbar',
+        'bull;',
+        'cap;',
+        'ccedil;',
+        'ccedil',
+        'cedil;',
+        'cedil',
+        'cent;',
+        'cent',
+        'chi;',
+        'circ;',
+        'clubs;',
+        'cong;',
+        'copy;',
+        'copy',
+        'crarr;',
+        'cup;',
+        'curren;',
+        'curren',
+        'dArr;',
+        'dagger;',
+        'darr;',
+        'deg;',
+        'deg',
+        'delta;',
+        'diams;',
+        'divide;',
+        'divide',
+        'eacute;',
+        'eacute',
+        'ecirc;',
+        'ecirc',
+        'egrave;',
+        'egrave',
+        'empty;',
+        'emsp;',
+        'ensp;',
+        'epsilon;',
+        'equiv;',
+        'eta;',
+        'eth;',
+        'eth',
+        'euml;',
+        'euml',
+        'euro;',
+        'exist;',
+        'fnof;',
+        'forall;',
+        'frac12;',
+        'frac12',
+        'frac14;',
+        'frac14',
+        'frac34;',
+        'frac34',
+        'frasl;',
+        'gamma;',
+        'ge;',
+        'gt;',
+        'gt',
+        'hArr;',
+        'harr;',
+        'hearts;',
+        'hellip;',
+        'iacute;',
+        'iacute',
+        'icirc;',
+        'icirc',
+        'iexcl;',
+        'iexcl',
+        'igrave;',
+        'igrave',
+        'image;',
+        'infin;',
+        'int;',
+        'iota;',
+        'iquest;',
+        'iquest',
+        'isin;',
+        'iuml;',
+        'iuml',
+        'kappa;',
+        'lArr;',
+        'lambda;',
+        'lang;',
+        'laquo;',
+        'laquo',
+        'larr;',
+        'lceil;',
+        'ldquo;',
+        'le;',
+        'lfloor;',
+        'lowast;',
+        'loz;',
+        'lrm;',
+        'lsaquo;',
+        'lsquo;',
+        'lt;',
+        'lt',
+        'macr;',
+        'macr',
+        'mdash;',
+        'micro;',
+        'micro',
+        'middot;',
+        'middot',
+        'minus;',
+        'mu;',
+        'nabla;',
+        'nbsp;',
+        'nbsp',
+        'ndash;',
+        'ne;',
+        'ni;',
+        'not;',
+        'not',
+        'notin;',
+        'nsub;',
+        'ntilde;',
+        'ntilde',
+        'nu;',
+        'oacute;',
+        'oacute',
+        'ocirc;',
+        'ocirc',
+        'oelig;',
+        'ograve;',
+        'ograve',
+        'oline;',
+        'omega;',
+        'omicron;',
+        'oplus;',
+        'or;',
+        'ordf;',
+        'ordf',
+        'ordm;',
+        'ordm',
+        'oslash;',
+        'oslash',
+        'otilde;',
+        'otilde',
+        'otimes;',
+        'ouml;',
+        'ouml',
+        'para;',
+        'para',
+        'part;',
+        'permil;',
+        'perp;',
+        'phi;',
+        'pi;',
+        'piv;',
+        'plusmn;',
+        'plusmn',
+        'pound;',
+        'pound',
+        'prime;',
+        'prod;',
+        'prop;',
+        'psi;',
+        'quot;',
+        'quot',
+        'rArr;',
+        'radic;',
+        'rang;',
+        'raquo;',
+        'raquo',
+        'rarr;',
+        'rceil;',
+        'rdquo;',
+        'real;',
+        'reg;',
+        'reg',
+        'rfloor;',
+        'rho;',
+        'rlm;',
+        'rsaquo;',
+        'rsquo;',
+        'sbquo;',
+        'scaron;',
+        'sdot;',
+        'sect;',
+        'sect',
+        'shy;',
+        'shy',
+        'sigma;',
+        'sigmaf;',
+        'sim;',
+        'spades;',
+        'sub;',
+        'sube;',
+        'sum;',
+        'sup1;',
+        'sup1',
+        'sup2;',
+        'sup2',
+        'sup3;',
+        'sup3',
+        'sup;',
+        'supe;',
+        'szlig;',
+        'szlig',
+        'tau;',
+        'there4;',
+        'theta;',
+        'thetasym;',
+        'thinsp;',
+        'thorn;',
+        'thorn',
+        'tilde;',
+        'times;',
+        'times',
+        'trade;',
+        'uArr;',
+        'uacute;',
+        'uacute',
+        'uarr;',
+        'ucirc;',
+        'ucirc',
+        'ugrave;',
+        'ugrave',
+        'uml;',
+        'uml',
+        'upsih;',
+        'upsilon;',
+        'uuml;',
+        'uuml',
+        'weierp;',
+        'xi;',
+        'yacute;',
+        'yacute',
+        'yen;',
+        'yen',
+        'yuml;',
+        'yuml',
+        'zeta;',
+        'zwj;',
+        'zwnj;'
+    );
+
+    const PCDATA = 0;
+    const RCDATA = 1;
+    const CDATA = 2;
+    const PLAINTEXT = 3;
+
+    const DOCTYPE = 0;
+    const STARTTAG = 1;
+    const ENDTAG = 2;
+    const COMMENT = 3;
+    const CHARACTR = 4;
+    const EOF = 5;
+
+    public function __construct($data)
+    {
+        $this->data = $data;
+        $this->char = -1;
+        $this->EOF = strlen($data);
+        $this->tree = new HTML5TreeConstructer;
+        $this->content_model = self::PCDATA;
+
+        $this->state = 'data';
+
+        while ($this->state !== null) {
+            $this->{$this->state . 'State'}();
+        }
+    }
+
+    public function save()
+    {
+        return $this->tree->save();
+    }
+
+    private function char()
+    {
+        return ($this->char < $this->EOF)
+            ? $this->data[$this->char]
+            : false;
+    }
+
+    private function character($s, $l = 0)
+    {
+        if ($s + $l < $this->EOF) {
+            if ($l === 0) {
+                return $this->data[$s];
+            } else {
+                return substr($this->data, $s, $l);
+            }
+        }
+    }
+
+    private function characters($char_class, $start)
+    {
+        return preg_replace('#^([' . $char_class . ']+).*#s', '\\1', substr($this->data, $start));
+    }
+
+    private function dataState()
+    {
+        // Consume the next input character
+        $this->char++;
+        $char = $this->char();
+
+        if ($char === '&' && ($this->content_model === self::PCDATA || $this->content_model === self::RCDATA)) {
+            /* U+0026 AMPERSAND (&)
+            When the content model flag is set to one of the PCDATA or RCDATA
+            states: switch to the entity data state. Otherwise: treat it as per
+            the "anything else"    entry below. */
+            $this->state = 'entityData';
+
+        } elseif ($char === '-') {
+            /* If the content model flag is set to either the RCDATA state or
+            the CDATA state, and the escape flag is false, and there are at
+            least three characters before this one in the input stream, and the
+            last four characters in the input stream, including this one, are
+            U+003C LESS-THAN SIGN, U+0021 EXCLAMATION MARK, U+002D HYPHEN-MINUS,
+            and U+002D HYPHEN-MINUS ("<!--"), then set the escape flag to true. */
+            if (($this->content_model === self::RCDATA || $this->content_model ===
+                    self::CDATA) && $this->escape === false &&
+                $this->char >= 3 && $this->character($this->char - 4, 4) === '<!--'
+            ) {
+                $this->escape = true;
+            }
+
+            /* In any case, emit the input character as a character token. Stay
+            in the data state. */
+            $this->emitToken(
+                array(
+                    'type' => self::CHARACTR,
+                    'data' => $char
+                )
+            );
+
+            /* U+003C LESS-THAN SIGN (<) */
+        } elseif ($char === '<' && ($this->content_model === self::PCDATA ||
+                (($this->content_model === self::RCDATA ||
+                        $this->content_model === self::CDATA) && $this->escape === false))
+        ) {
+            /* When the content model flag is set to the PCDATA state: switch
+            to the tag open state.
+
+            When the content model flag is set to either the RCDATA state or
+            the CDATA state and the escape flag is false: switch to the tag
+            open state.
+
+            Otherwise: treat it as per the "anything else" entry below. */
+            $this->state = 'tagOpen';
+
+            /* U+003E GREATER-THAN SIGN (>) */
+        } elseif ($char === '>') {
+            /* If the content model flag is set to either the RCDATA state or
+            the CDATA state, and the escape flag is true, and the last three
+            characters in the input stream including this one are U+002D
+            HYPHEN-MINUS, U+002D HYPHEN-MINUS, U+003E GREATER-THAN SIGN ("-->"),
+            set the escape flag to false. */
+            if (($this->content_model === self::RCDATA ||
+                    $this->content_model === self::CDATA) && $this->escape === true &&
+                $this->character($this->char, 3) === '-->'
+            ) {
+                $this->escape = false;
+            }
+
+            /* In any case, emit the input character as a character token.
+            Stay in the data state. */
+            $this->emitToken(
+                array(
+                    'type' => self::CHARACTR,
+                    'data' => $char
+                )
+            );
+
+        } elseif ($this->char === $this->EOF) {
+            /* EOF
+            Emit an end-of-file token. */
+            $this->EOF();
+
+        } elseif ($this->content_model === self::PLAINTEXT) {
+            /* When the content model flag is set to the PLAINTEXT state
+            THIS DIFFERS GREATLY FROM THE SPEC: Get the remaining characters of
+            the text and emit it as a character token. */
+            $this->emitToken(
+                array(
+                    'type' => self::CHARACTR,
+                    'data' => substr($this->data, $this->char)
+                )
+            );
+
+            $this->EOF();
+
+        } else {
+            /* Anything else
+            THIS DIFFERS GREATLY FROM THE SPEC: Get as many character that
+            otherwise would also be treated as a character token and emit it
+            as a single character token. Stay in the data state. */
+            $len = strcspn($this->data, '<&', $this->char);
+            $char = substr($this->data, $this->char, $len);
+            $this->char += $len - 1;
+
+            $this->emitToken(
+                array(
+                    'type' => self::CHARACTR,
+                    'data' => $char
+                )
+            );
+
+            $this->state = 'data';
+        }
+    }
+
+    private function entityDataState()
+    {
+        // Attempt to consume an entity.
+        $entity = $this->entity();
+
+        // If nothing is returned, emit a U+0026 AMPERSAND character token.
+        // Otherwise, emit the character token that was returned.
+        $char = (!$entity) ? '&' : $entity;
+        $this->emitToken(
+            array(
+                'type' => self::CHARACTR,
+                'data' => $char
+            )
+        );
+
+        // Finally, switch to the data state.
+        $this->state = 'data';
+    }
+
+    private function tagOpenState()
+    {
+        switch ($this->content_model) {
+            case self::RCDATA:
+            case self::CDATA:
+                /* If the next input character is a U+002F SOLIDUS (/) character,
+                consume it and switch to the close tag open state. If the next
+                input character is not a U+002F SOLIDUS (/) character, emit a
+                U+003C LESS-THAN SIGN character token and switch to the data
+                state to process the next input character. */
+                if ($this->character($this->char + 1) === '/') {
+                    $this->char++;
+                    $this->state = 'closeTagOpen';
+
+                } else {
+                    $this->emitToken(
+                        array(
+                            'type' => self::CHARACTR,
+                            'data' => '<'
+                        )
+                    );
+
+                    $this->state = 'data';
+                }
+                break;
+
+            case self::PCDATA:
+                // If the content model flag is set to the PCDATA state
+                // Consume the next input character:
+                $this->char++;
+                $char = $this->char();
+
+                if ($char === '!') {
+                    /* U+0021 EXCLAMATION MARK (!)
+                    Switch to the markup declaration open state. */
+                    $this->state = 'markupDeclarationOpen';
+
+                } elseif ($char === '/') {
+                    /* U+002F SOLIDUS (/)
+                    Switch to the close tag open state. */
+                    $this->state = 'closeTagOpen';
+
+                } elseif (preg_match('/^[A-Za-z]$/', $char)) {
+                    /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z
+                    Create a new start tag token, set its tag name to the lowercase
+                    version of the input character (add 0x0020 to the character's code
+                    point), then switch to the tag name state. (Don't emit the token
+                    yet; further details will be filled in before it is emitted.) */
+                    $this->token = array(
+                        'name' => strtolower($char),
+                        'type' => self::STARTTAG,
+                        'attr' => array()
+                    );
+
+                    $this->state = 'tagName';
+
+                } elseif ($char === '>') {
+                    /* U+003E GREATER-THAN SIGN (>)
+                    Parse error. Emit a U+003C LESS-THAN SIGN character token and a
+                    U+003E GREATER-THAN SIGN character token. Switch to the data state. */
+                    $this->emitToken(
+                        array(
+                            'type' => self::CHARACTR,
+                            'data' => '<>'
+                        )
+                    );
+
+                    $this->state = 'data';
+
+                } elseif ($char === '?') {
+                    /* U+003F QUESTION MARK (?)
+                    Parse error. Switch to the bogus comment state. */
+                    $this->state = 'bogusComment';
+
+                } else {
+                    /* Anything else
+                    Parse error. Emit a U+003C LESS-THAN SIGN character token and
+                    reconsume the current input character in the data state. */
+                    $this->emitToken(
+                        array(
+                            'type' => self::CHARACTR,
+                            'data' => '<'
+                        )
+                    );
+
+                    $this->char--;
+                    $this->state = 'data';
+                }
+                break;
+        }
+    }
+
+    private function closeTagOpenState()
+    {
+        $next_node = strtolower($this->characters('A-Za-z', $this->char + 1));
+        $the_same = count($this->tree->stack) > 0 && $next_node === end($this->tree->stack)->nodeName;
+
+        if (($this->content_model === self::RCDATA || $this->content_model === self::CDATA) &&
+            (!$the_same || ($the_same && (!preg_match(
+                            '/[\t\n\x0b\x0c >\/]/',
+                            $this->character($this->char + 1 + strlen($next_node))
+                        ) || $this->EOF === $this->char)))
+        ) {
+            /* If the content model flag is set to the RCDATA or CDATA states then
+            examine the next few characters. If they do not match the tag name of
+            the last start tag token emitted (case insensitively), or if they do but
+            they are not immediately followed by one of the following characters:
+                * U+0009 CHARACTER TABULATION
+                * U+000A LINE FEED (LF)
+                * U+000B LINE TABULATION
+                * U+000C FORM FEED (FF)
+                * U+0020 SPACE
+                * U+003E GREATER-THAN SIGN (>)
+                * U+002F SOLIDUS (/)
+                * EOF
+            ...then there is a parse error. Emit a U+003C LESS-THAN SIGN character
+            token, a U+002F SOLIDUS character token, and switch to the data state
+            to process the next input character. */
+            $this->emitToken(
+                array(
+                    'type' => self::CHARACTR,
+                    'data' => '</'
+                )
+            );
+
+            $this->state = 'data';
+
+        } else {
+            /* Otherwise, if the content model flag is set to the PCDATA state,
+            or if the next few characters do match that tag name, consume the
+            next input character: */
+            $this->char++;
+            $char = $this->char();
+
+            if (preg_match('/^[A-Za-z]$/', $char)) {
+                /* U+0041 LATIN LETTER A through to U+005A LATIN LETTER Z
+                Create a new end tag token, set its tag name to the lowercase version
+                of the input character (add 0x0020 to the character's code point), then
+                switch to the tag name state. (Don't emit the token yet; further details
+                will be filled in before it is emitted.) */
+                $this->token = array(
+                    'name' => strtolower($char),
+                    'type' => self::ENDTAG
+                );
+
+                $this->state = 'tagName';
+
+            } elseif ($char === '>') {
+                /* U+003E GREATER-THAN SIGN (>)
+                Parse error. Switch to the data state. */
+                $this->state = 'data';
+
+            } elseif ($this->char === $this->EOF) {
+                /* EOF
+                Parse error. Emit a U+003C LESS-THAN SIGN character token and a U+002F
+                SOLIDUS character token. Reconsume the EOF character in the data state. */
+                $this->emitToken(
+                    array(
+                        'type' => self::CHARACTR,
+                        'data' => '</'
+                    )
+                );
+
+                $this->char--;
+                $this->state = 'data';
+
+            } else {
+                /* Parse error. Switch to the bogus comment state. */
+                $this->state = 'bogusComment';
+            }
+        }
+    }
+
+    private function tagNameState()
+    {
+        // Consume the next input character:
+        $this->char++;
+        $char = $this->character($this->char);
+
+        if (preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
+            /* U+0009 CHARACTER TABULATION
+            U+000A LINE FEED (LF)
+            U+000B LINE TABULATION
+            U+000C FORM FEED (FF)
+            U+0020 SPACE
+            Switch to the before attribute name state. */
+            $this->state = 'beforeAttributeName';
+
+        } elseif ($char === '>') {
+            /* U+003E GREATER-THAN SIGN (>)
+            Emit the current tag token. Switch to the data state. */
+            $this->emitToken($this->token);
+            $this->state = 'data';
+
+        } elseif ($this->char === $this->EOF) {
+            /* EOF
+            Parse error. Emit the current tag token. Reconsume the EOF
+            character in the data state. */
+            $this->emitToken($this->token);
+
+            $this->char--;
+            $this->state = 'data';
+
+        } elseif ($char === '/') {
+            /* U+002F SOLIDUS (/)
+            Parse error unless this is a permitted slash. Switch to the before
+            attribute name state. */
+            $this->state = 'beforeAttributeName';
+
+        } else {
+            /* Anything else
+            Append the current input character to the current tag token's tag name.
+            Stay in the tag name state. */
+            $this->token['name'] .= strtolower($char);
+            $this->state = 'tagName';
+        }
+    }
+
+    private function beforeAttributeNameState()
+    {
+        // Consume the next input character:
+        $this->char++;
+        $char = $this->character($this->char);
+
+        if (preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
+            /* U+0009 CHARACTER TABULATION
+            U+000A LINE FEED (LF)
+            U+000B LINE TABULATION
+            U+000C FORM FEED (FF)
+            U+0020 SPACE
+            Stay in the before attribute name state. */
+            $this->state = 'beforeAttributeName';
+
+        } elseif ($char === '>') {
+            /* U+003E GREATER-THAN SIGN (>)
+            Emit the current tag token. Switch to the data state. */
+            $this->emitToken($this->token);
+            $this->state = 'data';
+
+        } elseif ($char === '/') {
+            /* U+002F SOLIDUS (/)
+            Parse error unless this is a permitted slash. Stay in the before
+            attribute name state. */
+            $this->state = 'beforeAttributeName';
+
+        } elseif ($this->char === $this->EOF) {
+            /* EOF
+            Parse error. Emit the current tag token. Reconsume the EOF
+            character in the data state. */
+            $this->emitToken($this->token);
+
+            $this->char--;
+            $this->state = 'data';
+
+        } else {
+            /* Anything else
+            Start a new attribute in the current tag token. Set that attribute's
+            name to the current input character, and its value to the empty string.
+            Switch to the attribute name state. */
+            $this->token['attr'][] = array(
+                'name' => strtolower($char),
+                'value' => null
+            );
+
+            $this->state = 'attributeName';
+        }
+    }
+
+    private function attributeNameState()
+    {
+        // Consume the next input character:
+        $this->char++;
+        $char = $this->character($this->char);
+
+        if (preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
+            /* U+0009 CHARACTER TABULATION
+            U+000A LINE FEED (LF)
+            U+000B LINE TABULATION
+            U+000C FORM FEED (FF)
+            U+0020 SPACE
+            Stay in the before attribute name state. */
+            $this->state = 'afterAttributeName';
+
+        } elseif ($char === '=') {
+            /* U+003D EQUALS SIGN (=)
+            Switch to the before attribute value state. */
+            $this->state = 'beforeAttributeValue';
+
+        } elseif ($char === '>') {
+            /* U+003E GREATER-THAN SIGN (>)
+            Emit the current tag token. Switch to the data state. */
+            $this->emitToken($this->token);
+            $this->state = 'data';
+
+        } elseif ($char === '/' && $this->character($this->char + 1) !== '>') {
+            /* U+002F SOLIDUS (/)
+            Parse error unless this is a permitted slash. Switch to the before
+            attribute name state. */
+            $this->state = 'beforeAttributeName';
+
+        } elseif ($this->char === $this->EOF) {
+            /* EOF
+            Parse error. Emit the current tag token. Reconsume the EOF
+            character in the data state. */
+            $this->emitToken($this->token);
+
+            $this->char--;
+            $this->state = 'data';
+
+        } else {
+            /* Anything else
+            Append the current input character to the current attribute's name.
+            Stay in the attribute name state. */
+            $last = count($this->token['attr']) - 1;
+            $this->token['attr'][$last]['name'] .= strtolower($char);
+
+            $this->state = 'attributeName';
+        }
+    }
+
+    private function afterAttributeNameState()
+    {
+        // Consume the next input character:
+        $this->char++;
+        $char = $this->character($this->char);
+
+        if (preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
+            /* U+0009 CHARACTER TABULATION
+            U+000A LINE FEED (LF)
+            U+000B LINE TABULATION
+            U+000C FORM FEED (FF)
+            U+0020 SPACE
+            Stay in the after attribute name state. */
+            $this->state = 'afterAttributeName';
+
+        } elseif ($char === '=') {
+            /* U+003D EQUALS SIGN (=)
+            Switch to the before attribute value state. */
+            $this->state = 'beforeAttributeValue';
+
+        } elseif ($char === '>') {
+            /* U+003E GREATER-THAN SIGN (>)
+            Emit the current tag token. Switch to the data state. */
+            $this->emitToken($this->token);
+            $this->state = 'data';
+
+        } elseif ($char === '/' && $this->character($this->char + 1) !== '>') {
+            /* U+002F SOLIDUS (/)
+            Parse error unless this is a permitted slash. Switch to the
+            before attribute name state. */
+            $this->state = 'beforeAttributeName';
+
+        } elseif ($this->char === $this->EOF) {
+            /* EOF
+            Parse error. Emit the current tag token. Reconsume the EOF
+            character in the data state. */
+            $this->emitToken($this->token);
+
+            $this->char--;
+            $this->state = 'data';
+
+        } else {
+            /* Anything else
+            Start a new attribute in the current tag token. Set that attribute's
+            name to the current input character, and its value to the empty string.
+            Switch to the attribute name state. */
+            $this->token['attr'][] = array(
+                'name' => strtolower($char),
+                'value' => null
+            );
+
+            $this->state = 'attributeName';
+        }
+    }
+
+    private function beforeAttributeValueState()
+    {
+        // Consume the next input character:
+        $this->char++;
+        $char = $this->character($this->char);
+
+        if (preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
+            /* U+0009 CHARACTER TABULATION
+            U+000A LINE FEED (LF)
+            U+000B LINE TABULATION
+            U+000C FORM FEED (FF)
+            U+0020 SPACE
+            Stay in the before attribute value state. */
+            $this->state = 'beforeAttributeValue';
+
+        } elseif ($char === '"') {
+            /* U+0022 QUOTATION MARK (")
+            Switch to the attribute value (double-quoted) state. */
+            $this->state = 'attributeValueDoubleQuoted';
+
+        } elseif ($char === '&') {
+            /* U+0026 AMPERSAND (&)
+            Switch to the attribute value (unquoted) state and reconsume
+            this input character. */
+            $this->char--;
+            $this->state = 'attributeValueUnquoted';
+
+        } elseif ($char === '\'') {
+            /* U+0027 APOSTROPHE (')
+            Switch to the attribute value (single-quoted) state. */
+            $this->state = 'attributeValueSingleQuoted';
+
+        } elseif ($char === '>') {
+            /* U+003E GREATER-THAN SIGN (>)
+            Emit the current tag token. Switch to the data state. */
+            $this->emitToken($this->token);
+            $this->state = 'data';
+
+        } else {
+            /* Anything else
+            Append the current input character to the current attribute's value.
+            Switch to the attribute value (unquoted) state. */
+            $last = count($this->token['attr']) - 1;
+            $this->token['attr'][$last]['value'] .= $char;
+
+            $this->state = 'attributeValueUnquoted';
+        }
+    }
+
+    private function attributeValueDoubleQuotedState()
+    {
+        // Consume the next input character:
+        $this->char++;
+        $char = $this->character($this->char);
+
+        if ($char === '"') {
+            /* U+0022 QUOTATION MARK (")
+            Switch to the before attribute name state. */
+            $this->state = 'beforeAttributeName';
+
+        } elseif ($char === '&') {
+            /* U+0026 AMPERSAND (&)
+            Switch to the entity in attribute value state. */
+            $this->entityInAttributeValueState('double');
+
+        } elseif ($this->char === $this->EOF) {
+            /* EOF
+            Parse error. Emit the current tag token. Reconsume the character
+            in the data state. */
+            $this->emitToken($this->token);
+
+            $this->char--;
+            $this->state = 'data';
+
+        } else {
+            /* Anything else
+            Append the current input character to the current attribute's value.
+            Stay in the attribute value (double-quoted) state. */
+            $last = count($this->token['attr']) - 1;
+            $this->token['attr'][$last]['value'] .= $char;
+
+            $this->state = 'attributeValueDoubleQuoted';
+        }
+    }
+
+    private function attributeValueSingleQuotedState()
+    {
+        // Consume the next input character:
+        $this->char++;
+        $char = $this->character($this->char);
+
+        if ($char === '\'') {
+            /* U+0022 QUOTATION MARK (')
+            Switch to the before attribute name state. */
+            $this->state = 'beforeAttributeName';
+
+        } elseif ($char === '&') {
+            /* U+0026 AMPERSAND (&)
+            Switch to the entity in attribute value state. */
+            $this->entityInAttributeValueState('single');
+
+        } elseif ($this->char === $this->EOF) {
+            /* EOF
+            Parse error. Emit the current tag token. Reconsume the character
+            in the data state. */
+            $this->emitToken($this->token);
+
+            $this->char--;
+            $this->state = 'data';
+
+        } else {
+            /* Anything else
+            Append the current input character to the current attribute's value.
+            Stay in the attribute value (single-quoted) state. */
+            $last = count($this->token['attr']) - 1;
+            $this->token['attr'][$last]['value'] .= $char;
+
+            $this->state = 'attributeValueSingleQuoted';
+        }
+    }
+
+    private function attributeValueUnquotedState()
+    {
+        // Consume the next input character:
+        $this->char++;
+        $char = $this->character($this->char);
+
+        if (preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
+            /* U+0009 CHARACTER TABULATION
+            U+000A LINE FEED (LF)
+            U+000B LINE TABULATION
+            U+000C FORM FEED (FF)
+            U+0020 SPACE
+            Switch to the before attribute name state. */
+            $this->state = 'beforeAttributeName';
+
+        } elseif ($char === '&') {
+            /* U+0026 AMPERSAND (&)
+            Switch to the entity in attribute value state. */
+            $this->entityInAttributeValueState();
+
+        } elseif ($char === '>') {
+            /* U+003E GREATER-THAN SIGN (>)
+            Emit the current tag token. Switch to the data state. */
+            $this->emitToken($this->token);
+            $this->state = 'data';
+
+        } else {
+            /* Anything else
+            Append the current input character to the current attribute's value.
+            Stay in the attribute value (unquoted) state. */
+            $last = count($this->token['attr']) - 1;
+            $this->token['attr'][$last]['value'] .= $char;
+
+            $this->state = 'attributeValueUnquoted';
+        }
+    }
+
+    private function entityInAttributeValueState()
+    {
+        // Attempt to consume an entity.
+        $entity = $this->entity();
+
+        // If nothing is returned, append a U+0026 AMPERSAND character to the
+        // current attribute's value. Otherwise, emit the character token that
+        // was returned.
+        $char = (!$entity)
+            ? '&'
+            : $entity;
+
+        $last = count($this->token['attr']) - 1;
+        $this->token['attr'][$last]['value'] .= $char;
+    }
+
+    private function bogusCommentState()
+    {
+        /* Consume every character up to the first U+003E GREATER-THAN SIGN
+        character (>) or the end of the file (EOF), whichever comes first. Emit
+        a comment token whose data is the concatenation of all the characters
+        starting from and including the character that caused the state machine
+        to switch into the bogus comment state, up to and including the last
+        consumed character before the U+003E character, if any, or up to the
+        end of the file otherwise. (If the comment was started by the end of
+        the file (EOF), the token is empty.) */
+        $data = $this->characters('^>', $this->char);
+        $this->emitToken(
+            array(
+                'data' => $data,
+                'type' => self::COMMENT
+            )
+        );
+
+        $this->char += strlen($data);
+
+        /* Switch to the data state. */
+        $this->state = 'data';
+
+        /* If the end of the file was reached, reconsume the EOF character. */
+        if ($this->char === $this->EOF) {
+            $this->char = $this->EOF - 1;
+        }
+    }
+
+    private function markupDeclarationOpenState()
+    {
+        /* If the next two characters are both U+002D HYPHEN-MINUS (-)
+        characters, consume those two characters, create a comment token whose
+        data is the empty string, and switch to the comment state. */
+        if ($this->character($this->char + 1, 2) === '--') {
+            $this->char += 2;
+            $this->state = 'comment';
+            $this->token = array(
+                'data' => null,
+                'type' => self::COMMENT
+            );
+
+            /* Otherwise if the next seven chacacters are a case-insensitive match
+            for the word "DOCTYPE", then consume those characters and switch to the
+            DOCTYPE state. */
+        } elseif (strtolower($this->character($this->char + 1, 7)) === 'doctype') {
+            $this->char += 7;
+            $this->state = 'doctype';
+
+            /* Otherwise, is is a parse error. Switch to the bogus comment state.
+            The next character that is consumed, if any, is the first character
+            that will be in the comment. */
+        } else {
+            $this->char++;
+            $this->state = 'bogusComment';
+        }
+    }
+
+    private function commentState()
+    {
+        /* Consume the next input character: */
+        $this->char++;
+        $char = $this->char();
+
+        /* U+002D HYPHEN-MINUS (-) */
+        if ($char === '-') {
+            /* Switch to the comment dash state  */
+            $this->state = 'commentDash';
+
+            /* EOF */
+        } elseif ($this->char === $this->EOF) {
+            /* Parse error. Emit the comment token. Reconsume the EOF character
+            in the data state. */
+            $this->emitToken($this->token);
+            $this->char--;
+            $this->state = 'data';
+
+            /* Anything else */
+        } else {
+            /* Append the input character to the comment token's data. Stay in
+            the comment state. */
+            $this->token['data'] .= $char;
+        }
+    }
+
+    private function commentDashState()
+    {
+        /* Consume the next input character: */
+        $this->char++;
+        $char = $this->char();
+
+        /* U+002D HYPHEN-MINUS (-) */
+        if ($char === '-') {
+            /* Switch to the comment end state  */
+            $this->state = 'commentEnd';
+
+            /* EOF */
+        } elseif ($this->char === $this->EOF) {
+            /* Parse error. Emit the comment token. Reconsume the EOF character
+            in the data state. */
+            $this->emitToken($this->token);
+            $this->char--;
+            $this->state = 'data';
+
+            /* Anything else */
+        } else {
+            /* Append a U+002D HYPHEN-MINUS (-) character and the input
+            character to the comment token's data. Switch to the comment state. */
+            $this->token['data'] .= '-' . $char;
+            $this->state = 'comment';
+        }
+    }
+
+    private function commentEndState()
+    {
+        /* Consume the next input character: */
+        $this->char++;
+        $char = $this->char();
+
+        if ($char === '>') {
+            $this->emitToken($this->token);
+            $this->state = 'data';
+
+        } elseif ($char === '-') {
+            $this->token['data'] .= '-';
+
+        } elseif ($this->char === $this->EOF) {
+            $this->emitToken($this->token);
+            $this->char--;
+            $this->state = 'data';
+
+        } else {
+            $this->token['data'] .= '--' . $char;
+            $this->state = 'comment';
+        }
+    }
+
+    private function doctypeState()
+    {
+        /* Consume the next input character: */
+        $this->char++;
+        $char = $this->char();
+
+        if (preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
+            $this->state = 'beforeDoctypeName';
+
+        } else {
+            $this->char--;
+            $this->state = 'beforeDoctypeName';
+        }
+    }
+
+    private function beforeDoctypeNameState()
+    {
+        /* Consume the next input character: */
+        $this->char++;
+        $char = $this->char();
+
+        if (preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
+            // Stay in the before DOCTYPE name state.
+
+        } elseif (preg_match('/^[a-z]$/', $char)) {
+            $this->token = array(
+                'name' => strtoupper($char),
+                'type' => self::DOCTYPE,
+                'error' => true
+            );
+
+            $this->state = 'doctypeName';
+
+        } elseif ($char === '>') {
+            $this->emitToken(
+                array(
+                    'name' => null,
+                    'type' => self::DOCTYPE,
+                    'error' => true
+                )
+            );
+
+            $this->state = 'data';
+
+        } elseif ($this->char === $this->EOF) {
+            $this->emitToken(
+                array(
+                    'name' => null,
+                    'type' => self::DOCTYPE,
+                    'error' => true
+                )
+            );
+
+            $this->char--;
+            $this->state = 'data';
+
+        } else {
+            $this->token = array(
+                'name' => $char,
+                'type' => self::DOCTYPE,
+                'error' => true
+            );
+
+            $this->state = 'doctypeName';
+        }
+    }
+
+    private function doctypeNameState()
+    {
+        /* Consume the next input character: */
+        $this->char++;
+        $char = $this->char();
+
+        if (preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
+            $this->state = 'AfterDoctypeName';
+
+        } elseif ($char === '>') {
+            $this->emitToken($this->token);
+            $this->state = 'data';
+
+        } elseif (preg_match('/^[a-z]$/', $char)) {
+            $this->token['name'] .= strtoupper($char);
+
+        } elseif ($this->char === $this->EOF) {
+            $this->emitToken($this->token);
+            $this->char--;
+            $this->state = 'data';
+
+        } else {
+            $this->token['name'] .= $char;
+        }
+
+        $this->token['error'] = ($this->token['name'] === 'HTML')
+            ? false
+            : true;
+    }
+
+    private function afterDoctypeNameState()
+    {
+        /* Consume the next input character: */
+        $this->char++;
+        $char = $this->char();
+
+        if (preg_match('/^[\t\n\x0b\x0c ]$/', $char)) {
+            // Stay in the DOCTYPE name state.
+
+        } elseif ($char === '>') {
+            $this->emitToken($this->token);
+            $this->state = 'data';
+
+        } elseif ($this->char === $this->EOF) {
+            $this->emitToken($this->token);
+            $this->char--;
+            $this->state = 'data';
+
+        } else {
+            $this->token['error'] = true;
+            $this->state = 'bogusDoctype';
+        }
+    }
+
+    private function bogusDoctypeState()
+    {
+        /* Consume the next input character: */
+        $this->char++;
+        $char = $this->char();
+
+        if ($char === '>') {
+            $this->emitToken($this->token);
+            $this->state = 'data';
+
+        } elseif ($this->char === $this->EOF) {
+            $this->emitToken($this->token);
+            $this->char--;
+            $this->state = 'data';
+
+        } else {
+            // Stay in the bogus DOCTYPE state.
+        }
+    }
+
+    private function entity()
+    {
+        $start = $this->char;
+
+        // This section defines how to consume an entity. This definition is
+        // used when parsing entities in text and in attributes.
+
+        // The behaviour depends on the identity of the next character (the
+        // one immediately after the U+0026 AMPERSAND character):
+
+        switch ($this->character($this->char + 1)) {
+            // U+0023 NUMBER SIGN (#)
+            case '#':
+
+                // The behaviour further depends on the character after the
+                // U+0023 NUMBER SIGN:
+                switch ($this->character($this->char + 1)) {
+                    // U+0078 LATIN SMALL LETTER X
+                    // U+0058 LATIN CAPITAL LETTER X
+                    case 'x':
+                    case 'X':
+                        // Follow the steps below, but using the range of
+                        // characters U+0030 DIGIT ZERO through to U+0039 DIGIT
+                        // NINE, U+0061 LATIN SMALL LETTER A through to U+0066
+                        // LATIN SMALL LETTER F, and U+0041 LATIN CAPITAL LETTER
+                        // A, through to U+0046 LATIN CAPITAL LETTER F (in other
+                        // words, 0-9, A-F, a-f).
+                        $char = 1;
+                        $char_class = '0-9A-Fa-f';
+                        break;
+
+                    // Anything else
+                    default:
+                        // Follow the steps below, but using the range of
+                        // characters U+0030 DIGIT ZERO through to U+0039 DIGIT
+                        // NINE (i.e. just 0-9).
+                        $char = 0;
+                        $char_class = '0-9';
+                        break;
+                }
+
+                // Consume as many characters as match the range of characters
+                // given above.
+                $this->char++;
+                $e_name = $this->characters($char_class, $this->char + $char + 1);
+                $entity = $this->character($start, $this->char);
+                $cond = strlen($e_name) > 0;
+
+                // The rest of the parsing happens bellow.
+                break;
+
+            // Anything else
+            default:
+                // Consume the maximum number of characters possible, with the
+                // consumed characters case-sensitively matching one of the
+                // identifiers in the first column of the entities table.
+                $e_name = $this->characters('0-9A-Za-z;', $this->char + 1);
+                $len = strlen($e_name);
+
+                for ($c = 1; $c <= $len; $c++) {
+                    $id = substr($e_name, 0, $c);
+                    $this->char++;
+
+                    if (in_array($id, $this->entities)) {
+                        if ($e_name[$c - 1] !== ';') {
+                            if ($c < $len && $e_name[$c] == ';') {
+                                $this->char++; // consume extra semicolon
+                            }
+                        }
+                        $entity = $id;
+                        break;
+                    }
+                }
+
+                $cond = isset($entity);
+                // The rest of the parsing happens bellow.
+                break;
+        }
+
+        if (!$cond) {
+            // If no match can be made, then this is a parse error. No
+            // characters are consumed, and nothing is returned.
+            $this->char = $start;
+            return false;
+        }
+
+        // Return a character token for the character corresponding to the
+        // entity name (as given by the second column of the entities table).
+        return html_entity_decode('&' . $entity . ';', ENT_QUOTES, 'UTF-8');
+    }
+
+    private function emitToken($token)
+    {
+        $emit = $this->tree->emitToken($token);
+
+        if (is_int($emit)) {
+            $this->content_model = $emit;
+
+        } elseif ($token['type'] === self::ENDTAG) {
+            $this->content_model = self::PCDATA;
+        }
+    }
+
+    private function EOF()
+    {
+        $this->state = null;
+        $this->tree->emitToken(
+            array(
+                'type' => self::EOF
+            )
+        );
+    }
+}
+
+class HTML5TreeConstructer
+{
+    public $stack = array();
+
+    private $phase;
+    private $mode;
+    private $dom;
+    private $foster_parent = null;
+    private $a_formatting = array();
+
+    private $head_pointer = null;
+    private $form_pointer = null;
+
+    private $scoping = array('button', 'caption', 'html', 'marquee', 'object', 'table', 'td', 'th');
+    private $formatting = array(
+        'a',
+        'b',
+        'big',
+        'em',
+        'font',
+        'i',
+        'nobr',
+        's',
+        'small',
+        'strike',
+        'strong',
+        'tt',
+        'u'
+    );
+    private $special = array(
+        'address',
+        'area',
+        'base',
+        'basefont',
+        'bgsound',
+        'blockquote',
+        'body',
+        'br',
+        'center',
+        'col',
+        'colgroup',
+        'dd',
+        'dir',
+        'div',
+        'dl',
+        'dt',
+        'embed',
+        'fieldset',
+        'form',
+        'frame',
+        'frameset',
+        'h1',
+        'h2',
+        'h3',
+        'h4',
+        'h5',
+        'h6',
+        'head',
+        'hr',
+        'iframe',
+        'image',
+        'img',
+        'input',
+        'isindex',
+        'li',
+        'link',
+        'listing',
+        'menu',
+        'meta',
+        'noembed',
+        'noframes',
+        'noscript',
+        'ol',
+        'optgroup',
+        'option',
+        'p',
+        'param',
+        'plaintext',
+        'pre',
+        'script',
+        'select',
+        'spacer',
+        'style',
+        'tbody',
+        'textarea',
+        'tfoot',
+        'thead',
+        'title',
+        'tr',
+        'ul',
+        'wbr'
+    );
+
+    // The different phases.
+    const INIT_PHASE = 0;
+    const ROOT_PHASE = 1;
+    const MAIN_PHASE = 2;
+    const END_PHASE = 3;
+
+    // The different insertion modes for the main phase.
+    const BEFOR_HEAD = 0;
+    const IN_HEAD = 1;
+    const AFTER_HEAD = 2;
+    const IN_BODY = 3;
+    const IN_TABLE = 4;
+    const IN_CAPTION = 5;
+    const IN_CGROUP = 6;
+    const IN_TBODY = 7;
+    const IN_ROW = 8;
+    const IN_CELL = 9;
+    const IN_SELECT = 10;
+    const AFTER_BODY = 11;
+    const IN_FRAME = 12;
+    const AFTR_FRAME = 13;
+
+    // The different types of elements.
+    const SPECIAL = 0;
+    const SCOPING = 1;
+    const FORMATTING = 2;
+    const PHRASING = 3;
+
+    const MARKER = 0;
+
+    public function __construct()
+    {
+        $this->phase = self::INIT_PHASE;
+        $this->mode = self::BEFOR_HEAD;
+        $this->dom = new DOMDocument;
+
+        $this->dom->encoding = 'UTF-8';
+        $this->dom->preserveWhiteSpace = true;
+        $this->dom->substituteEntities = true;
+        $this->dom->strictErrorChecking = false;
+    }
+
+    // Process tag tokens
+    public function emitToken($token)
+    {
+        switch ($this->phase) {
+            case self::INIT_PHASE:
+                return $this->initPhase($token);
+                break;
+            case self::ROOT_PHASE:
+                return $this->rootElementPhase($token);
+                break;
+            case self::MAIN_PHASE:
+                return $this->mainPhase($token);
+                break;
+            case self::END_PHASE :
+                return $this->trailingEndPhase($token);
+                break;
+        }
+    }
+
+    private function initPhase($token)
+    {
+        /* Initially, the tree construction stage must handle each token
+        emitted from the tokenisation stage as follows: */
+
+        /* A DOCTYPE token that is marked as being in error
+        A comment token
+        A start tag token
+        An end tag token
+        A character token that is not one of one of U+0009 CHARACTER TABULATION,
+            U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+            or U+0020 SPACE
+        An end-of-file token */
+        if ((isset($token['error']) && $token['error']) ||
+            $token['type'] === HTML5::COMMENT ||
+            $token['type'] === HTML5::STARTTAG ||
+            $token['type'] === HTML5::ENDTAG ||
+            $token['type'] === HTML5::EOF ||
+            ($token['type'] === HTML5::CHARACTR && isset($token['data']) &&
+                !preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data']))
+        ) {
+            /* This specification does not define how to handle this case. In
+            particular, user agents may ignore the entirety of this specification
+            altogether for such documents, and instead invoke special parse modes
+            with a greater emphasis on backwards compatibility. */
+
+            $this->phase = self::ROOT_PHASE;
+            return $this->rootElementPhase($token);
+
+            /* A DOCTYPE token marked as being correct */
+        } elseif (isset($token['error']) && !$token['error']) {
+            /* Append a DocumentType node to the Document  node, with the name
+            attribute set to the name given in the DOCTYPE token (which will be
+            "HTML"), and the other attributes specific to DocumentType objects
+            set to null, empty lists, or the empty string as appropriate. */
+            $doctype = new DOMDocumentType(null, null, 'HTML');
+
+            /* Then, switch to the root element phase of the tree construction
+            stage. */
+            $this->phase = self::ROOT_PHASE;
+
+            /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+            U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+            or U+0020 SPACE */
+        } elseif (isset($token['data']) && preg_match(
+                '/^[\t\n\x0b\x0c ]+$/',
+                $token['data']
+            )
+        ) {
+            /* Append that character  to the Document node. */
+            $text = $this->dom->createTextNode($token['data']);
+            $this->dom->appendChild($text);
+        }
+    }
+
+    private function rootElementPhase($token)
+    {
+        /* After the initial phase, as each token is emitted from the tokenisation
+        stage, it must be processed as described in this section. */
+
+        /* A DOCTYPE token */
+        if ($token['type'] === HTML5::DOCTYPE) {
+            // Parse error. Ignore the token.
+
+            /* A comment token */
+        } elseif ($token['type'] === HTML5::COMMENT) {
+            /* Append a Comment node to the Document object with the data
+            attribute set to the data given in the comment token. */
+            $comment = $this->dom->createComment($token['data']);
+            $this->dom->appendChild($comment);
+
+            /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+            U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+            or U+0020 SPACE */
+        } elseif ($token['type'] === HTML5::CHARACTR &&
+            preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
+        ) {
+            /* Append that character  to the Document node. */
+            $text = $this->dom->createTextNode($token['data']);
+            $this->dom->appendChild($text);
+
+            /* A character token that is not one of U+0009 CHARACTER TABULATION,
+                U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED
+                (FF), or U+0020 SPACE
+            A start tag token
+            An end tag token
+            An end-of-file token */
+        } elseif (($token['type'] === HTML5::CHARACTR &&
+                !preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) ||
+            $token['type'] === HTML5::STARTTAG ||
+            $token['type'] === HTML5::ENDTAG ||
+            $token['type'] === HTML5::EOF
+        ) {
+            /* Create an HTMLElement node with the tag name html, in the HTML
+            namespace. Append it to the Document object. Switch to the main
+            phase and reprocess the current token. */
+            $html = $this->dom->createElement('html');
+            $this->dom->appendChild($html);
+            $this->stack[] = $html;
+
+            $this->phase = self::MAIN_PHASE;
+            return $this->mainPhase($token);
+        }
+    }
+
+    private function mainPhase($token)
+    {
+        /* Tokens in the main phase must be handled as follows: */
+
+        /* A DOCTYPE token */
+        if ($token['type'] === HTML5::DOCTYPE) {
+            // Parse error. Ignore the token.
+
+            /* A start tag token with the tag name "html" */
+        } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'html') {
+            /* If this start tag token was not the first start tag token, then
+            it is a parse error. */
+
+            /* For each attribute on the token, check to see if the attribute
+            is already present on the top element of the stack of open elements.
+            If it is not, add the attribute and its corresponding value to that
+            element. */
+            foreach ($token['attr'] as $attr) {
+                if (!$this->stack[0]->hasAttribute($attr['name'])) {
+                    $this->stack[0]->setAttribute($attr['name'], $attr['value']);
+                }
+            }
+
+            /* An end-of-file token */
+        } elseif ($token['type'] === HTML5::EOF) {
+            /* Generate implied end tags. */
+            $this->generateImpliedEndTags();
+
+            /* Anything else. */
+        } else {
+            /* Depends on the insertion mode: */
+            switch ($this->mode) {
+                case self::BEFOR_HEAD:
+                    return $this->beforeHead($token);
+                    break;
+                case self::IN_HEAD:
+                    return $this->inHead($token);
+                    break;
+                case self::AFTER_HEAD:
+                    return $this->afterHead($token);
+                    break;
+                case self::IN_BODY:
+                    return $this->inBody($token);
+                    break;
+                case self::IN_TABLE:
+                    return $this->inTable($token);
+                    break;
+                case self::IN_CAPTION:
+                    return $this->inCaption($token);
+                    break;
+                case self::IN_CGROUP:
+                    return $this->inColumnGroup($token);
+                    break;
+                case self::IN_TBODY:
+                    return $this->inTableBody($token);
+                    break;
+                case self::IN_ROW:
+                    return $this->inRow($token);
+                    break;
+                case self::IN_CELL:
+                    return $this->inCell($token);
+                    break;
+                case self::IN_SELECT:
+                    return $this->inSelect($token);
+                    break;
+                case self::AFTER_BODY:
+                    return $this->afterBody($token);
+                    break;
+                case self::IN_FRAME:
+                    return $this->inFrameset($token);
+                    break;
+                case self::AFTR_FRAME:
+                    return $this->afterFrameset($token);
+                    break;
+                case self::END_PHASE:
+                    return $this->trailingEndPhase($token);
+                    break;
+            }
+        }
+    }
+
+    private function beforeHead($token)
+    {
+        /* Handle the token as follows: */
+
+        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+        or U+0020 SPACE */
+        if ($token['type'] === HTML5::CHARACTR &&
+            preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
+        ) {
+            /* Append the character to the current node. */
+            $this->insertText($token['data']);
+
+            /* A comment token */
+        } elseif ($token['type'] === HTML5::COMMENT) {
+            /* Append a Comment node to the current node with the data attribute
+            set to the data given in the comment token. */
+            $this->insertComment($token['data']);
+
+            /* A start tag token with the tag name "head" */
+        } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'head') {
+            /* Create an element for the token, append the new element to the
+            current node and push it onto the stack of open elements. */
+            $element = $this->insertElement($token);
+
+            /* Set the head element pointer to this new element node. */
+            $this->head_pointer = $element;
+
+            /* Change the insertion mode to "in head". */
+            $this->mode = self::IN_HEAD;
+
+            /* A start tag token whose tag name is one of: "base", "link", "meta",
+            "script", "style", "title". Or an end tag with the tag name "html".
+            Or a character token that is not one of U+0009 CHARACTER TABULATION,
+            U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+            or U+0020 SPACE. Or any other start tag token */
+        } elseif ($token['type'] === HTML5::STARTTAG ||
+            ($token['type'] === HTML5::ENDTAG && $token['name'] === 'html') ||
+            ($token['type'] === HTML5::CHARACTR && !preg_match(
+                    '/^[\t\n\x0b\x0c ]$/',
+                    $token['data']
+                ))
+        ) {
+            /* Act as if a start tag token with the tag name "head" and no
+            attributes had been seen, then reprocess the current token. */
+            $this->beforeHead(
+                array(
+                    'name' => 'head',
+                    'type' => HTML5::STARTTAG,
+                    'attr' => array()
+                )
+            );
+
+            return $this->inHead($token);
+
+            /* Any other end tag */
+        } elseif ($token['type'] === HTML5::ENDTAG) {
+            /* Parse error. Ignore the token. */
+        }
+    }
+
+    private function inHead($token)
+    {
+        /* Handle the token as follows: */
+
+        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+        or U+0020 SPACE.
+
+        THIS DIFFERS FROM THE SPEC: If the current node is either a title, style
+        or script element, append the character to the current node regardless
+        of its content. */
+        if (($token['type'] === HTML5::CHARACTR &&
+                preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) || (
+                $token['type'] === HTML5::CHARACTR && in_array(
+                    end($this->stack)->nodeName,
+                    array('title', 'style', 'script')
+                ))
+        ) {
+            /* Append the character to the current node. */
+            $this->insertText($token['data']);
+
+            /* A comment token */
+        } elseif ($token['type'] === HTML5::COMMENT) {
+            /* Append a Comment node to the current node with the data attribute
+            set to the data given in the comment token. */
+            $this->insertComment($token['data']);
+
+        } elseif ($token['type'] === HTML5::ENDTAG &&
+            in_array($token['name'], array('title', 'style', 'script'))
+        ) {
+            array_pop($this->stack);
+            return HTML5::PCDATA;
+
+            /* A start tag with the tag name "title" */
+        } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'title') {
+            /* Create an element for the token and append the new element to the
+            node pointed to by the head element pointer, or, if that is null
+            (innerHTML case), to the current node. */
+            if ($this->head_pointer !== null) {
+                $element = $this->insertElement($token, false);
+                $this->head_pointer->appendChild($element);
+
+            } else {
+                $element = $this->insertElement($token);
+            }
+
+            /* Switch the tokeniser's content model flag  to the RCDATA state. */
+            return HTML5::RCDATA;
+
+            /* A start tag with the tag name "style" */
+        } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'style') {
+            /* Create an element for the token and append the new element to the
+            node pointed to by the head element pointer, or, if that is null
+            (innerHTML case), to the current node. */
+            if ($this->head_pointer !== null) {
+                $element = $this->insertElement($token, false);
+                $this->head_pointer->appendChild($element);
+
+            } else {
+                $this->insertElement($token);
+            }
+
+            /* Switch the tokeniser's content model flag  to the CDATA state. */
+            return HTML5::CDATA;
+
+            /* A start tag with the tag name "script" */
+        } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'script') {
+            /* Create an element for the token. */
+            $element = $this->insertElement($token, false);
+            $this->head_pointer->appendChild($element);
+
+            /* Switch the tokeniser's content model flag  to the CDATA state. */
+            return HTML5::CDATA;
+
+            /* A start tag with the tag name "base", "link", or "meta" */
+        } elseif ($token['type'] === HTML5::STARTTAG && in_array(
+                $token['name'],
+                array('base', 'link', 'meta')
+            )
+        ) {
+            /* Create an element for the token and append the new element to the
+            node pointed to by the head element pointer, or, if that is null
+            (innerHTML case), to the current node. */
+            if ($this->head_pointer !== null) {
+                $element = $this->insertElement($token, false);
+                $this->head_pointer->appendChild($element);
+                array_pop($this->stack);
+
+            } else {
+                $this->insertElement($token);
+            }
+
+            /* An end tag with the tag name "head" */
+        } elseif ($token['type'] === HTML5::ENDTAG && $token['name'] === 'head') {
+            /* If the current node is a head element, pop the current node off
+            the stack of open elements. */
+            if ($this->head_pointer->isSameNode(end($this->stack))) {
+                array_pop($this->stack);
+
+                /* Otherwise, this is a parse error. */
+            } else {
+                // k
+            }
+
+            /* Change the insertion mode to "after head". */
+            $this->mode = self::AFTER_HEAD;
+
+            /* A start tag with the tag name "head" or an end tag except "html". */
+        } elseif (($token['type'] === HTML5::STARTTAG && $token['name'] === 'head') ||
+            ($token['type'] === HTML5::ENDTAG && $token['name'] !== 'html')
+        ) {
+            // Parse error. Ignore the token.
+
+            /* Anything else */
+        } else {
+            /* If the current node is a head element, act as if an end tag
+            token with the tag name "head" had been seen. */
+            if ($this->head_pointer->isSameNode(end($this->stack))) {
+                $this->inHead(
+                    array(
+                        'name' => 'head',
+                        'type' => HTML5::ENDTAG
+                    )
+                );
+
+                /* Otherwise, change the insertion mode to "after head". */
+            } else {
+                $this->mode = self::AFTER_HEAD;
+            }
+
+            /* Then, reprocess the current token. */
+            return $this->afterHead($token);
+        }
+    }
+
+    private function afterHead($token)
+    {
+        /* Handle the token as follows: */
+
+        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+        or U+0020 SPACE */
+        if ($token['type'] === HTML5::CHARACTR &&
+            preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
+        ) {
+            /* Append the character to the current node. */
+            $this->insertText($token['data']);
+
+            /* A comment token */
+        } elseif ($token['type'] === HTML5::COMMENT) {
+            /* Append a Comment node to the current node with the data attribute
+            set to the data given in the comment token. */
+            $this->insertComment($token['data']);
+
+            /* A start tag token with the tag name "body" */
+        } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'body') {
+            /* Insert a body element for the token. */
+            $this->insertElement($token);
+
+            /* Change the insertion mode to "in body". */
+            $this->mode = self::IN_BODY;
+
+            /* A start tag token with the tag name "frameset" */
+        } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'frameset') {
+            /* Insert a frameset element for the token. */
+            $this->insertElement($token);
+
+            /* Change the insertion mode to "in frameset". */
+            $this->mode = self::IN_FRAME;
+
+            /* A start tag token whose tag name is one of: "base", "link", "meta",
+            "script", "style", "title" */
+        } elseif ($token['type'] === HTML5::STARTTAG && in_array(
+                $token['name'],
+                array('base', 'link', 'meta', 'script', 'style', 'title')
+            )
+        ) {
+            /* Parse error. Switch the insertion mode back to "in head" and
+            reprocess the token. */
+            $this->mode = self::IN_HEAD;
+            return $this->inHead($token);
+
+            /* Anything else */
+        } else {
+            /* Act as if a start tag token with the tag name "body" and no
+            attributes had been seen, and then reprocess the current token. */
+            $this->afterHead(
+                array(
+                    'name' => 'body',
+                    'type' => HTML5::STARTTAG,
+                    'attr' => array()
+                )
+            );
+
+            return $this->inBody($token);
+        }
+    }
+
+    private function inBody($token)
+    {
+        /* Handle the token as follows: */
+
+        switch ($token['type']) {
+            /* A character token */
+            case HTML5::CHARACTR:
+                /* Reconstruct the active formatting elements, if any. */
+                $this->reconstructActiveFormattingElements();
+
+                /* Append the token's character to the current node. */
+                $this->insertText($token['data']);
+                break;
+
+            /* A comment token */
+            case HTML5::COMMENT:
+                /* Append a Comment node to the current node with the data
+                attribute set to the data given in the comment token. */
+                $this->insertComment($token['data']);
+                break;
+
+            case HTML5::STARTTAG:
+                switch ($token['name']) {
+                    /* A start tag token whose tag name is one of: "script",
+                    "style" */
+                    case 'script':
+                    case 'style':
+                        /* Process the token as if the insertion mode had been "in
+                        head". */
+                        return $this->inHead($token);
+                        break;
+
+                    /* A start tag token whose tag name is one of: "base", "link",
+                    "meta", "title" */
+                    case 'base':
+                    case 'link':
+                    case 'meta':
+                    case 'title':
+                        /* Parse error. Process the token as if the insertion mode
+                        had    been "in head". */
+                        return $this->inHead($token);
+                        break;
+
+                    /* A start tag token with the tag name "body" */
+                    case 'body':
+                        /* Parse error. If the second element on the stack of open
+                        elements is not a body element, or, if the stack of open
+                        elements has only one node on it, then ignore the token.
+                        (innerHTML case) */
+                        if (count($this->stack) === 1 || $this->stack[1]->nodeName !== 'body') {
+                            // Ignore
+
+                            /* Otherwise, for each attribute on the token, check to see
+                            if the attribute is already present on the body element (the
+                            second element)    on the stack of open elements. If it is not,
+                            add the attribute and its corresponding value to that
+                            element. */
+                        } else {
+                            foreach ($token['attr'] as $attr) {
+                                if (!$this->stack[1]->hasAttribute($attr['name'])) {
+                                    $this->stack[1]->setAttribute($attr['name'], $attr['value']);
+                                }
+                            }
+                        }
+                        break;
+
+                    /* A start tag whose tag name is one of: "address",
+                    "blockquote", "center", "dir", "div", "dl", "fieldset",
+                    "listing", "menu", "ol", "p", "ul" */
+                    case 'address':
+                    case 'blockquote':
+                    case 'center':
+                    case 'dir':
+                    case 'div':
+                    case 'dl':
+                    case 'fieldset':
+                    case 'listing':
+                    case 'menu':
+                    case 'ol':
+                    case 'p':
+                    case 'ul':
+                        /* If the stack of open elements has a p element in scope,
+                        then act as if an end tag with the tag name p had been
+                        seen. */
+                        if ($this->elementInScope('p')) {
+                            $this->emitToken(
+                                array(
+                                    'name' => 'p',
+                                    'type' => HTML5::ENDTAG
+                                )
+                            );
+                        }
+
+                        /* Insert an HTML element for the token. */
+                        $this->insertElement($token);
+                        break;
+
+                    /* A start tag whose tag name is "form" */
+                    case 'form':
+                        /* If the form element pointer is not null, ignore the
+                        token with a parse error. */
+                        if ($this->form_pointer !== null) {
+                            // Ignore.
+
+                            /* Otherwise: */
+                        } else {
+                            /* If the stack of open elements has a p element in
+                            scope, then act as if an end tag with the tag name p
+                            had been seen. */
+                            if ($this->elementInScope('p')) {
+                                $this->emitToken(
+                                    array(
+                                        'name' => 'p',
+                                        'type' => HTML5::ENDTAG
+                                    )
+                                );
+                            }
+
+                            /* Insert an HTML element for the token, and set the
+                            form element pointer to point to the element created. */
+                            $element = $this->insertElement($token);
+                            $this->form_pointer = $element;
+                        }
+                        break;
+
+                    /* A start tag whose tag name is "li", "dd" or "dt" */
+                    case 'li':
+                    case 'dd':
+                    case 'dt':
+                        /* If the stack of open elements has a p  element in scope,
+                        then act as if an end tag with the tag name p had been
+                        seen. */
+                        if ($this->elementInScope('p')) {
+                            $this->emitToken(
+                                array(
+                                    'name' => 'p',
+                                    'type' => HTML5::ENDTAG
+                                )
+                            );
+                        }
+
+                        $stack_length = count($this->stack) - 1;
+
+                        for ($n = $stack_length; 0 <= $n; $n--) {
+                            /* 1. Initialise node to be the current node (the
+                            bottommost node of the stack). */
+                            $stop = false;
+                            $node = $this->stack[$n];
+                            $cat = $this->getElementCategory($node->tagName);
+
+                            /* 2. If node is an li, dd or dt element, then pop all
+                            the    nodes from the current node up to node, including
+                            node, then stop this algorithm. */
+                            if ($token['name'] === $node->tagName || ($token['name'] !== 'li'
+                                    && ($node->tagName === 'dd' || $node->tagName === 'dt'))
+                            ) {
+                                for ($x = $stack_length; $x >= $n; $x--) {
+                                    array_pop($this->stack);
+                                }
+
+                                break;
+                            }
+
+                            /* 3. If node is not in the formatting category, and is
+                            not    in the phrasing category, and is not an address or
+                            div element, then stop this algorithm. */
+                            if ($cat !== self::FORMATTING && $cat !== self::PHRASING &&
+                                $node->tagName !== 'address' && $node->tagName !== 'div'
+                            ) {
+                                break;
+                            }
+                        }
+
+                        /* Finally, insert an HTML element with the same tag
+                        name as the    token's. */
+                        $this->insertElement($token);
+                        break;
+
+                    /* A start tag token whose tag name is "plaintext" */
+                    case 'plaintext':
+                        /* If the stack of open elements has a p  element in scope,
+                        then act as if an end tag with the tag name p had been
+                        seen. */
+                        if ($this->elementInScope('p')) {
+                            $this->emitToken(
+                                array(
+                                    'name' => 'p',
+                                    'type' => HTML5::ENDTAG
+                                )
+                            );
+                        }
+
+                        /* Insert an HTML element for the token. */
+                        $this->insertElement($token);
+
+                        return HTML5::PLAINTEXT;
+                        break;
+
+                    /* A start tag whose tag name is one of: "h1", "h2", "h3", "h4",
+                    "h5", "h6" */
+                    case 'h1':
+                    case 'h2':
+                    case 'h3':
+                    case 'h4':
+                    case 'h5':
+                    case 'h6':
+                        /* If the stack of open elements has a p  element in scope,
+                        then act as if an end tag with the tag name p had been seen. */
+                        if ($this->elementInScope('p')) {
+                            $this->emitToken(
+                                array(
+                                    'name' => 'p',
+                                    'type' => HTML5::ENDTAG
+                                )
+                            );
+                        }
+
+                        /* If the stack of open elements has in scope an element whose
+                        tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then
+                        this is a parse error; pop elements from the stack until an
+                        element with one of those tag names has been popped from the
+                        stack. */
+                        while ($this->elementInScope(array('h1', 'h2', 'h3', 'h4', 'h5', 'h6'))) {
+                            array_pop($this->stack);
+                        }
+
+                        /* Insert an HTML element for the token. */
+                        $this->insertElement($token);
+                        break;
+
+                    /* A start tag whose tag name is "a" */
+                    case 'a':
+                        /* If the list of active formatting elements contains
+                        an element whose tag name is "a" between the end of the
+                        list and the last marker on the list (or the start of
+                        the list if there is no marker on the list), then this
+                        is a parse error; act as if an end tag with the tag name
+                        "a" had been seen, then remove that element from the list
+                        of active formatting elements and the stack of open
+                        elements if the end tag didn't already remove it (it
+                        might not have if the element is not in table scope). */
+                        $leng = count($this->a_formatting);
+
+                        for ($n = $leng - 1; $n >= 0; $n--) {
+                            if ($this->a_formatting[$n] === self::MARKER) {
+                                break;
+
+                            } elseif ($this->a_formatting[$n]->nodeName === 'a') {
+                                $this->emitToken(
+                                    array(
+                                        'name' => 'a',
+                                        'type' => HTML5::ENDTAG
+                                    )
+                                );
+                                break;
+                            }
+                        }
+
+                        /* Reconstruct the active formatting elements, if any. */
+                        $this->reconstructActiveFormattingElements();
+
+                        /* Insert an HTML element for the token. */
+                        $el = $this->insertElement($token);
+
+                        /* Add that element to the list of active formatting
+                        elements. */
+                        $this->a_formatting[] = $el;
+                        break;
+
+                    /* A start tag whose tag name is one of: "b", "big", "em", "font",
+                    "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */
+                    case 'b':
+                    case 'big':
+                    case 'em':
+                    case 'font':
+                    case 'i':
+                    case 'nobr':
+                    case 's':
+                    case 'small':
+                    case 'strike':
+                    case 'strong':
+                    case 'tt':
+                    case 'u':
+                        /* Reconstruct the active formatting elements, if any. */
+                        $this->reconstructActiveFormattingElements();
+
+                        /* Insert an HTML element for the token. */
+                        $el = $this->insertElement($token);
+
+                        /* Add that element to the list of active formatting
+                        elements. */
+                        $this->a_formatting[] = $el;
+                        break;
+
+                    /* A start tag token whose tag name is "button" */
+                    case 'button':
+                        /* If the stack of open elements has a button element in scope,
+                        then this is a parse error; act as if an end tag with the tag
+                        name "button" had been seen, then reprocess the token. (We don't
+                        do that. Unnecessary.) */
+                        if ($this->elementInScope('button')) {
+                            $this->inBody(
+                                array(
+                                    'name' => 'button',
+                                    'type' => HTML5::ENDTAG
+                                )
+                            );
+                        }
+
+                        /* Reconstruct the active formatting elements, if any. */
+                        $this->reconstructActiveFormattingElements();
+
+                        /* Insert an HTML element for the token. */
+                        $this->insertElement($token);
+
+                        /* Insert a marker at the end of the list of active
+                        formatting elements. */
+                        $this->a_formatting[] = self::MARKER;
+                        break;
+
+                    /* A start tag token whose tag name is one of: "marquee", "object" */
+                    case 'marquee':
+                    case 'object':
+                        /* Reconstruct the active formatting elements, if any. */
+                        $this->reconstructActiveFormattingElements();
+
+                        /* Insert an HTML element for the token. */
+                        $this->insertElement($token);
+
+                        /* Insert a marker at the end of the list of active
+                        formatting elements. */
+                        $this->a_formatting[] = self::MARKER;
+                        break;
+
+                    /* A start tag token whose tag name is "xmp" */
+                    case 'xmp':
+                        /* Reconstruct the active formatting elements, if any. */
+                        $this->reconstructActiveFormattingElements();
+
+                        /* Insert an HTML element for the token. */
+                        $this->insertElement($token);
+
+                        /* Switch the content model flag to the CDATA state. */
+                        return HTML5::CDATA;
+                        break;
+
+                    /* A start tag whose tag name is "table" */
+                    case 'table':
+                        /* If the stack of open elements has a p element in scope,
+                        then act as if an end tag with the tag name p had been seen. */
+                        if ($this->elementInScope('p')) {
+                            $this->emitToken(
+                                array(
+                                    'name' => 'p',
+                                    'type' => HTML5::ENDTAG
+                                )
+                            );
+                        }
+
+                        /* Insert an HTML element for the token. */
+                        $this->insertElement($token);
+
+                        /* Change the insertion mode to "in table". */
+                        $this->mode = self::IN_TABLE;
+                        break;
+
+                    /* A start tag whose tag name is one of: "area", "basefont",
+                    "bgsound", "br", "embed", "img", "param", "spacer", "wbr" */
+                    case 'area':
+                    case 'basefont':
+                    case 'bgsound':
+                    case 'br':
+                    case 'embed':
+                    case 'img':
+                    case 'param':
+                    case 'spacer':
+                    case 'wbr':
+                        /* Reconstruct the active formatting elements, if any. */
+                        $this->reconstructActiveFormattingElements();
+
+                        /* Insert an HTML element for the token. */
+                        $this->insertElement($token);
+
+                        /* Immediately pop the current node off the stack of open elements. */
+                        array_pop($this->stack);
+                        break;
+
+                    /* A start tag whose tag name is "hr" */
+                    case 'hr':
+                        /* If the stack of open elements has a p element in scope,
+                        then act as if an end tag with the tag name p had been seen. */
+                        if ($this->elementInScope('p')) {
+                            $this->emitToken(
+                                array(
+                                    'name' => 'p',
+                                    'type' => HTML5::ENDTAG
+                                )
+                            );
+                        }
+
+                        /* Insert an HTML element for the token. */
+                        $this->insertElement($token);
+
+                        /* Immediately pop the current node off the stack of open elements. */
+                        array_pop($this->stack);
+                        break;
+
+                    /* A start tag whose tag name is "image" */
+                    case 'image':
+                        /* Parse error. Change the token's tag name to "img" and
+                        reprocess it. (Don't ask.) */
+                        $token['name'] = 'img';
+                        return $this->inBody($token);
+                        break;
+
+                    /* A start tag whose tag name is "input" */
+                    case 'input':
+                        /* Reconstruct the active formatting elements, if any. */
+                        $this->reconstructActiveFormattingElements();
+
+                        /* Insert an input element for the token. */
+                        $element = $this->insertElement($token, false);
+
+                        /* If the form element pointer is not null, then associate the
+                        input element with the form element pointed to by the form
+                        element pointer. */
+                        $this->form_pointer !== null
+                            ? $this->form_pointer->appendChild($element)
+                            : end($this->stack)->appendChild($element);
+
+                        /* Pop that input element off the stack of open elements. */
+                        array_pop($this->stack);
+                        break;
+
+                    /* A start tag whose tag name is "isindex" */
+                    case 'isindex':
+                        /* Parse error. */
+                        // w/e
+
+                        /* If the form element pointer is not null,
+                        then ignore the token. */
+                        if ($this->form_pointer === null) {
+                            /* Act as if a start tag token with the tag name "form" had
+                            been seen. */
+                            $this->inBody(
+                                array(
+                                    'name' => 'body',
+                                    'type' => HTML5::STARTTAG,
+                                    'attr' => array()
+                                )
+                            );
+
+                            /* Act as if a start tag token with the tag name "hr" had
+                            been seen. */
+                            $this->inBody(
+                                array(
+                                    'name' => 'hr',
+                                    'type' => HTML5::STARTTAG,
+                                    'attr' => array()
+                                )
+                            );
+
+                            /* Act as if a start tag token with the tag name "p" had
+                            been seen. */
+                            $this->inBody(
+                                array(
+                                    'name' => 'p',
+                                    'type' => HTML5::STARTTAG,
+                                    'attr' => array()
+                                )
+                            );
+
+                            /* Act as if a start tag token with the tag name "label"
+                            had been seen. */
+                            $this->inBody(
+                                array(
+                                    'name' => 'label',
+                                    'type' => HTML5::STARTTAG,
+                                    'attr' => array()
+                                )
+                            );
+
+                            /* Act as if a stream of character tokens had been seen. */
+                            $this->insertText(
+                                'This is a searchable index. ' .
+                                'Insert your search keywords here: '
+                            );
+
+                            /* Act as if a start tag token with the tag name "input"
+                            had been seen, with all the attributes from the "isindex"
+                            token, except with the "name" attribute set to the value
+                            "isindex" (ignoring any explicit "name" attribute). */
+                            $attr = $token['attr'];
+                            $attr[] = array('name' => 'name', 'value' => 'isindex');
+
+                            $this->inBody(
+                                array(
+                                    'name' => 'input',
+                                    'type' => HTML5::STARTTAG,
+                                    'attr' => $attr
+                                )
+                            );
+
+                            /* Act as if a stream of character tokens had been seen
+                            (see below for what they should say). */
+                            $this->insertText(
+                                'This is a searchable index. ' .
+                                'Insert your search keywords here: '
+                            );
+
+                            /* Act as if an end tag token with the tag name "label"
+                            had been seen. */
+                            $this->inBody(
+                                array(
+                                    'name' => 'label',
+                                    'type' => HTML5::ENDTAG
+                                )
+                            );
+
+                            /* Act as if an end tag token with the tag name "p" had
+                            been seen. */
+                            $this->inBody(
+                                array(
+                                    'name' => 'p',
+                                    'type' => HTML5::ENDTAG
+                                )
+                            );
+
+                            /* Act as if a start tag token with the tag name "hr" had
+                            been seen. */
+                            $this->inBody(
+                                array(
+                                    'name' => 'hr',
+                                    'type' => HTML5::ENDTAG
+                                )
+                            );
+
+                            /* Act as if an end tag token with the tag name "form" had
+                            been seen. */
+                            $this->inBody(
+                                array(
+                                    'name' => 'form',
+                                    'type' => HTML5::ENDTAG
+                                )
+                            );
+                        }
+                        break;
+
+                    /* A start tag whose tag name is "textarea" */
+                    case 'textarea':
+                        $this->insertElement($token);
+
+                        /* Switch the tokeniser's content model flag to the
+                        RCDATA state. */
+                        return HTML5::RCDATA;
+                        break;
+
+                    /* A start tag whose tag name is one of: "iframe", "noembed",
+                    "noframes" */
+                    case 'iframe':
+                    case 'noembed':
+                    case 'noframes':
+                        $this->insertElement($token);
+
+                        /* Switch the tokeniser's content model flag to the CDATA state. */
+                        return HTML5::CDATA;
+                        break;
+
+                    /* A start tag whose tag name is "select" */
+                    case 'select':
+                        /* Reconstruct the active formatting elements, if any. */
+                        $this->reconstructActiveFormattingElements();
+
+                        /* Insert an HTML element for the token. */
+                        $this->insertElement($token);
+
+                        /* Change the insertion mode to "in select". */
+                        $this->mode = self::IN_SELECT;
+                        break;
+
+                    /* A start or end tag whose tag name is one of: "caption", "col",
+                    "colgroup", "frame", "frameset", "head", "option", "optgroup",
+                    "tbody", "td", "tfoot", "th", "thead", "tr". */
+                    case 'caption':
+                    case 'col':
+                    case 'colgroup':
+                    case 'frame':
+                    case 'frameset':
+                    case 'head':
+                    case 'option':
+                    case 'optgroup':
+                    case 'tbody':
+                    case 'td':
+                    case 'tfoot':
+                    case 'th':
+                    case 'thead':
+                    case 'tr':
+                        // Parse error. Ignore the token.
+                        break;
+
+                    /* A start or end tag whose tag name is one of: "event-source",
+                    "section", "nav", "article", "aside", "header", "footer",
+                    "datagrid", "command" */
+                    case 'event-source':
+                    case 'section':
+                    case 'nav':
+                    case 'article':
+                    case 'aside':
+                    case 'header':
+                    case 'footer':
+                    case 'datagrid':
+                    case 'command':
+                        // Work in progress!
+                        break;
+
+                    /* A start tag token not covered by the previous entries */
+                    default:
+                        /* Reconstruct the active formatting elements, if any. */
+                        $this->reconstructActiveFormattingElements();
+
+                        $this->insertElement($token, true, true);
+                        break;
+                }
+                break;
+
+            case HTML5::ENDTAG:
+                switch ($token['name']) {
+                    /* An end tag with the tag name "body" */
+                    case 'body':
+                        /* If the second element in the stack of open elements is
+                        not a body element, this is a parse error. Ignore the token.
+                        (innerHTML case) */
+                        if (count($this->stack) < 2 || $this->stack[1]->nodeName !== 'body') {
+                            // Ignore.
+
+                            /* If the current node is not the body element, then this
+                            is a parse error. */
+                        } elseif (end($this->stack)->nodeName !== 'body') {
+                            // Parse error.
+                        }
+
+                        /* Change the insertion mode to "after body". */
+                        $this->mode = self::AFTER_BODY;
+                        break;
+
+                    /* An end tag with the tag name "html" */
+                    case 'html':
+                        /* Act as if an end tag with tag name "body" had been seen,
+                        then, if that token wasn't ignored, reprocess the current
+                        token. */
+                        $this->inBody(
+                            array(
+                                'name' => 'body',
+                                'type' => HTML5::ENDTAG
+                            )
+                        );
+
+                        return $this->afterBody($token);
+                        break;
+
+                    /* An end tag whose tag name is one of: "address", "blockquote",
+                    "center", "dir", "div", "dl", "fieldset", "listing", "menu",
+                    "ol", "pre", "ul" */
+                    case 'address':
+                    case 'blockquote':
+                    case 'center':
+                    case 'dir':
+                    case 'div':
+                    case 'dl':
+                    case 'fieldset':
+                    case 'listing':
+                    case 'menu':
+                    case 'ol':
+                    case 'pre':
+                    case 'ul':
+                        /* If the stack of open elements has an element in scope
+                        with the same tag name as that of the token, then generate
+                        implied end tags. */
+                        if ($this->elementInScope($token['name'])) {
+                            $this->generateImpliedEndTags();
+
+                            /* Now, if the current node is not an element with
+                            the same tag name as that of the token, then this
+                            is a parse error. */
+                            // w/e
+
+                            /* If the stack of open elements has an element in
+                            scope with the same tag name as that of the token,
+                            then pop elements from this stack until an element
+                            with that tag name has been popped from the stack. */
+                            for ($n = count($this->stack) - 1; $n >= 0; $n--) {
+                                if ($this->stack[$n]->nodeName === $token['name']) {
+                                    $n = -1;
+                                }
+
+                                array_pop($this->stack);
+                            }
+                        }
+                        break;
+
+                    /* An end tag whose tag name is "form" */
+                    case 'form':
+                        /* If the stack of open elements has an element in scope
+                        with the same tag name as that of the token, then generate
+                        implied    end tags. */
+                        if ($this->elementInScope($token['name'])) {
+                            $this->generateImpliedEndTags();
+
+                        }
+
+                        if (end($this->stack)->nodeName !== $token['name']) {
+                            /* Now, if the current node is not an element with the
+                            same tag name as that of the token, then this is a parse
+                            error. */
+                            // w/e
+
+                        } else {
+                            /* Otherwise, if the current node is an element with
+                            the same tag name as that of the token pop that element
+                            from the stack. */
+                            array_pop($this->stack);
+                        }
+
+                        /* In any case, set the form element pointer to null. */
+                        $this->form_pointer = null;
+                        break;
+
+                    /* An end tag whose tag name is "p" */
+                    case 'p':
+                        /* If the stack of open elements has a p element in scope,
+                        then generate implied end tags, except for p elements. */
+                        if ($this->elementInScope('p')) {
+                            $this->generateImpliedEndTags(array('p'));
+
+                            /* If the current node is not a p element, then this is
+                            a parse error. */
+                            // k
+
+                            /* If the stack of open elements has a p element in
+                            scope, then pop elements from this stack until the stack
+                            no longer has a p element in scope. */
+                            for ($n = count($this->stack) - 1; $n >= 0; $n--) {
+                                if ($this->elementInScope('p')) {
+                                    array_pop($this->stack);
+
+                                } else {
+                                    break;
+                                }
+                            }
+                        }
+                        break;
+
+                    /* An end tag whose tag name is "dd", "dt", or "li" */
+                    case 'dd':
+                    case 'dt':
+                    case 'li':
+                        /* If the stack of open elements has an element in scope
+                        whose tag name matches the tag name of the token, then
+                        generate implied end tags, except for elements with the
+                        same tag name as the token. */
+                        if ($this->elementInScope($token['name'])) {
+                            $this->generateImpliedEndTags(array($token['name']));
+
+                            /* If the current node is not an element with the same
+                            tag name as the token, then this is a parse error. */
+                            // w/e
+
+                            /* If the stack of open elements has an element in scope
+                            whose tag name matches the tag name of the token, then
+                            pop elements from this stack until an element with that
+                            tag name has been popped from the stack. */
+                            for ($n = count($this->stack) - 1; $n >= 0; $n--) {
+                                if ($this->stack[$n]->nodeName === $token['name']) {
+                                    $n = -1;
+                                }
+
+                                array_pop($this->stack);
+                            }
+                        }
+                        break;
+
+                    /* An end tag whose tag name is one of: "h1", "h2", "h3", "h4",
+                    "h5", "h6" */
+                    case 'h1':
+                    case 'h2':
+                    case 'h3':
+                    case 'h4':
+                    case 'h5':
+                    case 'h6':
+                        $elements = array('h1', 'h2', 'h3', 'h4', 'h5', 'h6');
+
+                        /* If the stack of open elements has in scope an element whose
+                        tag name is one of "h1", "h2", "h3", "h4", "h5", or "h6", then
+                        generate implied end tags. */
+                        if ($this->elementInScope($elements)) {
+                            $this->generateImpliedEndTags();
+
+                            /* Now, if the current node is not an element with the same
+                            tag name as that of the token, then this is a parse error. */
+                            // w/e
+
+                            /* If the stack of open elements has in scope an element
+                            whose tag name is one of "h1", "h2", "h3", "h4", "h5", or
+                            "h6", then pop elements from the stack until an element
+                            with one of those tag names has been popped from the stack. */
+                            while ($this->elementInScope($elements)) {
+                                array_pop($this->stack);
+                            }
+                        }
+                        break;
+
+                    /* An end tag whose tag name is one of: "a", "b", "big", "em",
+                    "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u" */
+                    case 'a':
+                    case 'b':
+                    case 'big':
+                    case 'em':
+                    case 'font':
+                    case 'i':
+                    case 'nobr':
+                    case 's':
+                    case 'small':
+                    case 'strike':
+                    case 'strong':
+                    case 'tt':
+                    case 'u':
+                        /* 1. Let the formatting element be the last element in
+                        the list of active formatting elements that:
+                            * is between the end of the list and the last scope
+                            marker in the list, if any, or the start of the list
+                            otherwise, and
+                            * has the same tag name as the token.
+                        */
+                        while (true) {
+                            for ($a = count($this->a_formatting) - 1; $a >= 0; $a--) {
+                                if ($this->a_formatting[$a] === self::MARKER) {
+                                    break;
+
+                                } elseif ($this->a_formatting[$a]->tagName === $token['name']) {
+                                    $formatting_element = $this->a_formatting[$a];
+                                    $in_stack = in_array($formatting_element, $this->stack, true);
+                                    $fe_af_pos = $a;
+                                    break;
+                                }
+                            }
+
+                            /* If there is no such node, or, if that node is
+                            also in the stack of open elements but the element
+                            is not in scope, then this is a parse error. Abort
+                            these steps. The token is ignored. */
+                            if (!isset($formatting_element) || ($in_stack &&
+                                    !$this->elementInScope($token['name']))
+                            ) {
+                                break;
+
+                                /* Otherwise, if there is such a node, but that node
+                                is not in the stack of open elements, then this is a
+                                parse error; remove the element from the list, and
+                                abort these steps. */
+                            } elseif (isset($formatting_element) && !$in_stack) {
+                                unset($this->a_formatting[$fe_af_pos]);
+                                $this->a_formatting = array_merge($this->a_formatting);
+                                break;
+                            }
+
+                            /* 2. Let the furthest block be the topmost node in the
+                            stack of open elements that is lower in the stack
+                            than the formatting element, and is not an element in
+                            the phrasing or formatting categories. There might
+                            not be one. */
+                            $fe_s_pos = array_search($formatting_element, $this->stack, true);
+                            $length = count($this->stack);
+
+                            for ($s = $fe_s_pos + 1; $s < $length; $s++) {
+                                $category = $this->getElementCategory($this->stack[$s]->nodeName);
+
+                                if ($category !== self::PHRASING && $category !== self::FORMATTING) {
+                                    $furthest_block = $this->stack[$s];
+                                }
+                            }
+
+                            /* 3. If there is no furthest block, then the UA must
+                            skip the subsequent steps and instead just pop all
+                            the nodes from the bottom of the stack of open
+                            elements, from the current node up to the formatting
+                            element, and remove the formatting element from the
+                            list of active formatting elements. */
+                            if (!isset($furthest_block)) {
+                                for ($n = $length - 1; $n >= $fe_s_pos; $n--) {
+                                    array_pop($this->stack);
+                                }
+
+                                unset($this->a_formatting[$fe_af_pos]);
+                                $this->a_formatting = array_merge($this->a_formatting);
+                                break;
+                            }
+
+                            /* 4. Let the common ancestor be the element
+                            immediately above the formatting element in the stack
+                            of open elements. */
+                            $common_ancestor = $this->stack[$fe_s_pos - 1];
+
+                            /* 5. If the furthest block has a parent node, then
+                            remove the furthest block from its parent node. */
+                            if ($furthest_block->parentNode !== null) {
+                                $furthest_block->parentNode->removeChild($furthest_block);
+                            }
+
+                            /* 6. Let a bookmark note the position of the
+                            formatting element in the list of active formatting
+                            elements relative to the elements on either side
+                            of it in the list. */
+                            $bookmark = $fe_af_pos;
+
+                            /* 7. Let node and last node  be the furthest block.
+                            Follow these steps: */
+                            $node = $furthest_block;
+                            $last_node = $furthest_block;
+
+                            while (true) {
+                                for ($n = array_search($node, $this->stack, true) - 1; $n >= 0; $n--) {
+                                    /* 7.1 Let node be the element immediately
+                                    prior to node in the stack of open elements. */
+                                    $node = $this->stack[$n];
+
+                                    /* 7.2 If node is not in the list of active
+                                    formatting elements, then remove node from
+                                    the stack of open elements and then go back
+                                    to step 1. */
+                                    if (!in_array($node, $this->a_formatting, true)) {
+                                        unset($this->stack[$n]);
+                                        $this->stack = array_merge($this->stack);
+
+                                    } else {
+                                        break;
+                                    }
+                                }
+
+                                /* 7.3 Otherwise, if node is the formatting
+                                element, then go to the next step in the overall
+                                algorithm. */
+                                if ($node === $formatting_element) {
+                                    break;
+
+                                    /* 7.4 Otherwise, if last node is the furthest
+                                    block, then move the aforementioned bookmark to
+                                    be immediately after the node in the list of
+                                    active formatting elements. */
+                                } elseif ($last_node === $furthest_block) {
+                                    $bookmark = array_search($node, $this->a_formatting, true) + 1;
+                                }
+
+                                /* 7.5 If node has any children, perform a
+                                shallow clone of node, replace the entry for
+                                node in the list of active formatting elements
+                                with an entry for the clone, replace the entry
+                                for node in the stack of open elements with an
+                                entry for the clone, and let node be the clone. */
+                                if ($node->hasChildNodes()) {
+                                    $clone = $node->cloneNode();
+                                    $s_pos = array_search($node, $this->stack, true);
+                                    $a_pos = array_search($node, $this->a_formatting, true);
+
+                                    $this->stack[$s_pos] = $clone;
+                                    $this->a_formatting[$a_pos] = $clone;
+                                    $node = $clone;
+                                }
+
+                                /* 7.6 Insert last node into node, first removing
+                                it from its previous parent node if any. */
+                                if ($last_node->parentNode !== null) {
+                                    $last_node->parentNode->removeChild($last_node);
+                                }
+
+                                $node->appendChild($last_node);
+
+                                /* 7.7 Let last node be node. */
+                                $last_node = $node;
+                            }
+
+                            /* 8. Insert whatever last node ended up being in
+                            the previous step into the common ancestor node,
+                            first removing it from its previous parent node if
+                            any. */
+                            if ($last_node->parentNode !== null) {
+                                $last_node->parentNode->removeChild($last_node);
+                            }
+
+                            $common_ancestor->appendChild($last_node);
+
+                            /* 9. Perform a shallow clone of the formatting
+                            element. */
+                            $clone = $formatting_element->cloneNode();
+
+                            /* 10. Take all of the child nodes of the furthest
+                            block and append them to the clone created in the
+                            last step. */
+                            while ($furthest_block->hasChildNodes()) {
+                                $child = $furthest_block->firstChild;
+                                $furthest_block->removeChild($child);
+                                $clone->appendChild($child);
+                            }
+
+                            /* 11. Append that clone to the furthest block. */
+                            $furthest_block->appendChild($clone);
+
+                            /* 12. Remove the formatting element from the list
+                            of active formatting elements, and insert the clone
+                            into the list of active formatting elements at the
+                            position of the aforementioned bookmark. */
+                            $fe_af_pos = array_search($formatting_element, $this->a_formatting, true);
+                            unset($this->a_formatting[$fe_af_pos]);
+                            $this->a_formatting = array_merge($this->a_formatting);
+
+                            $af_part1 = array_slice($this->a_formatting, 0, $bookmark - 1);
+                            $af_part2 = array_slice($this->a_formatting, $bookmark, count($this->a_formatting));
+                            $this->a_formatting = array_merge($af_part1, array($clone), $af_part2);
+
+                            /* 13. Remove the formatting element from the stack
+                            of open elements, and insert the clone into the stack
+                            of open elements immediately after (i.e. in a more
+                            deeply nested position than) the position of the
+                            furthest block in that stack. */
+                            $fe_s_pos = array_search($formatting_element, $this->stack, true);
+                            $fb_s_pos = array_search($furthest_block, $this->stack, true);
+                            unset($this->stack[$fe_s_pos]);
+
+                            $s_part1 = array_slice($this->stack, 0, $fb_s_pos);
+                            $s_part2 = array_slice($this->stack, $fb_s_pos + 1, count($this->stack));
+                            $this->stack = array_merge($s_part1, array($clone), $s_part2);
+
+                            /* 14. Jump back to step 1 in this series of steps. */
+                            unset($formatting_element, $fe_af_pos, $fe_s_pos, $furthest_block);
+                        }
+                        break;
+
+                    /* An end tag token whose tag name is one of: "button",
+                    "marquee", "object" */
+                    case 'button':
+                    case 'marquee':
+                    case 'object':
+                        /* If the stack of open elements has an element in scope whose
+                        tag name matches the tag name of the token, then generate implied
+                        tags. */
+                        if ($this->elementInScope($token['name'])) {
+                            $this->generateImpliedEndTags();
+
+                            /* Now, if the current node is not an element with the same
+                            tag name as the token, then this is a parse error. */
+                            // k
+
+                            /* Now, if the stack of open elements has an element in scope
+                            whose tag name matches the tag name of the token, then pop
+                            elements from the stack until that element has been popped from
+                            the stack, and clear the list of active formatting elements up
+                            to the last marker. */
+                            for ($n = count($this->stack) - 1; $n >= 0; $n--) {
+                                if ($this->stack[$n]->nodeName === $token['name']) {
+                                    $n = -1;
+                                }
+
+                                array_pop($this->stack);
+                            }
+
+                            $marker = end(array_keys($this->a_formatting, self::MARKER, true));
+
+                            for ($n = count($this->a_formatting) - 1; $n > $marker; $n--) {
+                                array_pop($this->a_formatting);
+                            }
+                        }
+                        break;
+
+                    /* Or an end tag whose tag name is one of: "area", "basefont",
+                    "bgsound", "br", "embed", "hr", "iframe", "image", "img",
+                    "input", "isindex", "noembed", "noframes", "param", "select",
+                    "spacer", "table", "textarea", "wbr" */
+                    case 'area':
+                    case 'basefont':
+                    case 'bgsound':
+                    case 'br':
+                    case 'embed':
+                    case 'hr':
+                    case 'iframe':
+                    case 'image':
+                    case 'img':
+                    case 'input':
+                    case 'isindex':
+                    case 'noembed':
+                    case 'noframes':
+                    case 'param':
+                    case 'select':
+                    case 'spacer':
+                    case 'table':
+                    case 'textarea':
+                    case 'wbr':
+                        // Parse error. Ignore the token.
+                        break;
+
+                    /* An end tag token not covered by the previous entries */
+                    default:
+                        for ($n = count($this->stack) - 1; $n >= 0; $n--) {
+                            /* Initialise node to be the current node (the bottommost
+                            node of the stack). */
+                            $node = end($this->stack);
+
+                            /* If node has the same tag name as the end tag token,
+                            then: */
+                            if ($token['name'] === $node->nodeName) {
+                                /* Generate implied end tags. */
+                                $this->generateImpliedEndTags();
+
+                                /* If the tag name of the end tag token does not
+                                match the tag name of the current node, this is a
+                                parse error. */
+                                // k
+
+                                /* Pop all the nodes from the current node up to
+                                node, including node, then stop this algorithm. */
+                                for ($x = count($this->stack) - $n; $x >= $n; $x--) {
+                                    array_pop($this->stack);
+                                }
+
+                            } else {
+                                $category = $this->getElementCategory($node);
+
+                                if ($category !== self::SPECIAL && $category !== self::SCOPING) {
+                                    /* Otherwise, if node is in neither the formatting
+                                    category nor the phrasing category, then this is a
+                                    parse error. Stop this algorithm. The end tag token
+                                    is ignored. */
+                                    return false;
+                                }
+                            }
+                        }
+                        break;
+                }
+                break;
+        }
+    }
+
+    private function inTable($token)
+    {
+        $clear = array('html', 'table');
+
+        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+        or U+0020 SPACE */
+        if ($token['type'] === HTML5::CHARACTR &&
+            preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
+        ) {
+            /* Append the character to the current node. */
+            $text = $this->dom->createTextNode($token['data']);
+            end($this->stack)->appendChild($text);
+
+            /* A comment token */
+        } elseif ($token['type'] === HTML5::COMMENT) {
+            /* Append a Comment node to the current node with the data
+            attribute set to the data given in the comment token. */
+            $comment = $this->dom->createComment($token['data']);
+            end($this->stack)->appendChild($comment);
+
+            /* A start tag whose tag name is "caption" */
+        } elseif ($token['type'] === HTML5::STARTTAG &&
+            $token['name'] === 'caption'
+        ) {
+            /* Clear the stack back to a table context. */
+            $this->clearStackToTableContext($clear);
+
+            /* Insert a marker at the end of the list of active
+            formatting elements. */
+            $this->a_formatting[] = self::MARKER;
+
+            /* Insert an HTML element for the token, then switch the
+            insertion mode to "in caption". */
+            $this->insertElement($token);
+            $this->mode = self::IN_CAPTION;
+
+            /* A start tag whose tag name is "colgroup" */
+        } elseif ($token['type'] === HTML5::STARTTAG &&
+            $token['name'] === 'colgroup'
+        ) {
+            /* Clear the stack back to a table context. */
+            $this->clearStackToTableContext($clear);
+
+            /* Insert an HTML element for the token, then switch the
+            insertion mode to "in column group". */
+            $this->insertElement($token);
+            $this->mode = self::IN_CGROUP;
+
+            /* A start tag whose tag name is "col" */
+        } elseif ($token['type'] === HTML5::STARTTAG &&
+            $token['name'] === 'col'
+        ) {
+            $this->inTable(
+                array(
+                    'name' => 'colgroup',
+                    'type' => HTML5::STARTTAG,
+                    'attr' => array()
+                )
+            );
+
+            $this->inColumnGroup($token);
+
+            /* A start tag whose tag name is one of: "tbody", "tfoot", "thead" */
+        } elseif ($token['type'] === HTML5::STARTTAG && in_array(
+                $token['name'],
+                array('tbody', 'tfoot', 'thead')
+            )
+        ) {
+            /* Clear the stack back to a table context. */
+            $this->clearStackToTableContext($clear);
+
+            /* Insert an HTML element for the token, then switch the insertion
+            mode to "in table body". */
+            $this->insertElement($token);
+            $this->mode = self::IN_TBODY;
+
+            /* A start tag whose tag name is one of: "td", "th", "tr" */
+        } elseif ($token['type'] === HTML5::STARTTAG &&
+            in_array($token['name'], array('td', 'th', 'tr'))
+        ) {
+            /* Act as if a start tag token with the tag name "tbody" had been
+            seen, then reprocess the current token. */
+            $this->inTable(
+                array(
+                    'name' => 'tbody',
+                    'type' => HTML5::STARTTAG,
+                    'attr' => array()
+                )
+            );
+
+            return $this->inTableBody($token);
+
+            /* A start tag whose tag name is "table" */
+        } elseif ($token['type'] === HTML5::STARTTAG &&
+            $token['name'] === 'table'
+        ) {
+            /* Parse error. Act as if an end tag token with the tag name "table"
+            had been seen, then, if that token wasn't ignored, reprocess the
+            current token. */
+            $this->inTable(
+                array(
+                    'name' => 'table',
+                    'type' => HTML5::ENDTAG
+                )
+            );
+
+            return $this->mainPhase($token);
+
+            /* An end tag whose tag name is "table" */
+        } elseif ($token['type'] === HTML5::ENDTAG &&
+            $token['name'] === 'table'
+        ) {
+            /* If the stack of open elements does not have an element in table
+            scope with the same tag name as the token, this is a parse error.
+            Ignore the token. (innerHTML case) */
+            if (!$this->elementInScope($token['name'], true)) {
+                return false;
+
+                /* Otherwise: */
+            } else {
+                /* Generate implied end tags. */
+                $this->generateImpliedEndTags();
+
+                /* Now, if the current node is not a table element, then this
+                is a parse error. */
+                // w/e
+
+                /* Pop elements from this stack until a table element has been
+                popped from the stack. */
+                while (true) {
+                    $current = end($this->stack)->nodeName;
+                    array_pop($this->stack);
+
+                    if ($current === 'table') {
+                        break;
+                    }
+                }
+
+                /* Reset the insertion mode appropriately. */
+                $this->resetInsertionMode();
+            }
+
+            /* An end tag whose tag name is one of: "body", "caption", "col",
+            "colgroup", "html", "tbody", "td", "tfoot", "th", "thead", "tr" */
+        } elseif ($token['type'] === HTML5::ENDTAG && in_array(
+                $token['name'],
+                array(
+                    'body',
+                    'caption',
+                    'col',
+                    'colgroup',
+                    'html',
+                    'tbody',
+                    'td',
+                    'tfoot',
+                    'th',
+                    'thead',
+                    'tr'
+                )
+            )
+        ) {
+            // Parse error. Ignore the token.
+
+            /* Anything else */
+        } else {
+            /* Parse error. Process the token as if the insertion mode was "in
+            body", with the following exception: */
+
+            /* If the current node is a table, tbody, tfoot, thead, or tr
+            element, then, whenever a node would be inserted into the current
+            node, it must instead be inserted into the foster parent element. */
+            if (in_array(
+                end($this->stack)->nodeName,
+                array('table', 'tbody', 'tfoot', 'thead', 'tr')
+            )
+            ) {
+                /* The foster parent element is the parent element of the last
+                table element in the stack of open elements, if there is a
+                table element and it has such a parent element. If there is no
+                table element in the stack of open elements (innerHTML case),
+                then the foster parent element is the first element in the
+                stack of open elements (the html  element). Otherwise, if there
+                is a table element in the stack of open elements, but the last
+                table element in the stack of open elements has no parent, or
+                its parent node is not an element, then the foster parent
+                element is the element before the last table element in the
+                stack of open elements. */
+                for ($n = count($this->stack) - 1; $n >= 0; $n--) {
+                    if ($this->stack[$n]->nodeName === 'table') {
+                        $table = $this->stack[$n];
+                        break;
+                    }
+                }
+
+                if (isset($table) && $table->parentNode !== null) {
+                    $this->foster_parent = $table->parentNode;
+
+                } elseif (!isset($table)) {
+                    $this->foster_parent = $this->stack[0];
+
+                } elseif (isset($table) && ($table->parentNode === null ||
+                        $table->parentNode->nodeType !== XML_ELEMENT_NODE)
+                ) {
+                    $this->foster_parent = $this->stack[$n - 1];
+                }
+            }
+
+            $this->inBody($token);
+        }
+    }
+
+    private function inCaption($token)
+    {
+        /* An end tag whose tag name is "caption" */
+        if ($token['type'] === HTML5::ENDTAG && $token['name'] === 'caption') {
+            /* If the stack of open elements does not have an element in table
+            scope with the same tag name as the token, this is a parse error.
+            Ignore the token. (innerHTML case) */
+            if (!$this->elementInScope($token['name'], true)) {
+                // Ignore
+
+                /* Otherwise: */
+            } else {
+                /* Generate implied end tags. */
+                $this->generateImpliedEndTags();
+
+                /* Now, if the current node is not a caption element, then this
+                is a parse error. */
+                // w/e
+
+                /* Pop elements from this stack until a caption element has
+                been popped from the stack. */
+                while (true) {
+                    $node = end($this->stack)->nodeName;
+                    array_pop($this->stack);
+
+                    if ($node === 'caption') {
+                        break;
+                    }
+                }
+
+                /* Clear the list of active formatting elements up to the last
+                marker. */
+                $this->clearTheActiveFormattingElementsUpToTheLastMarker();
+
+                /* Switch the insertion mode to "in table". */
+                $this->mode = self::IN_TABLE;
+            }
+
+            /* A start tag whose tag name is one of: "caption", "col", "colgroup",
+            "tbody", "td", "tfoot", "th", "thead", "tr", or an end tag whose tag
+            name is "table" */
+        } elseif (($token['type'] === HTML5::STARTTAG && in_array(
+                    $token['name'],
+                    array(
+                        'caption',
+                        'col',
+                        'colgroup',
+                        'tbody',
+                        'td',
+                        'tfoot',
+                        'th',
+                        'thead',
+                        'tr'
+                    )
+                )) || ($token['type'] === HTML5::ENDTAG &&
+                $token['name'] === 'table')
+        ) {
+            /* Parse error. Act as if an end tag with the tag name "caption"
+            had been seen, then, if that token wasn't ignored, reprocess the
+            current token. */
+            $this->inCaption(
+                array(
+                    'name' => 'caption',
+                    'type' => HTML5::ENDTAG
+                )
+            );
+
+            return $this->inTable($token);
+
+            /* An end tag whose tag name is one of: "body", "col", "colgroup",
+            "html", "tbody", "td", "tfoot", "th", "thead", "tr" */
+        } elseif ($token['type'] === HTML5::ENDTAG && in_array(
+                $token['name'],
+                array(
+                    'body',
+                    'col',
+                    'colgroup',
+                    'html',
+                    'tbody',
+                    'tfoot',
+                    'th',
+                    'thead',
+                    'tr'
+                )
+            )
+        ) {
+            // Parse error. Ignore the token.
+
+            /* Anything else */
+        } else {
+            /* Process the token as if the insertion mode was "in body". */
+            $this->inBody($token);
+        }
+    }
+
+    private function inColumnGroup($token)
+    {
+        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+        or U+0020 SPACE */
+        if ($token['type'] === HTML5::CHARACTR &&
+            preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
+        ) {
+            /* Append the character to the current node. */
+            $text = $this->dom->createTextNode($token['data']);
+            end($this->stack)->appendChild($text);
+
+            /* A comment token */
+        } elseif ($token['type'] === HTML5::COMMENT) {
+            /* Append a Comment node to the current node with the data
+            attribute set to the data given in the comment token. */
+            $comment = $this->dom->createComment($token['data']);
+            end($this->stack)->appendChild($comment);
+
+            /* A start tag whose tag name is "col" */
+        } elseif ($token['type'] === HTML5::STARTTAG && $token['name'] === 'col') {
+            /* Insert a col element for the token. Immediately pop the current
+            node off the stack of open elements. */
+            $this->insertElement($token);
+            array_pop($this->stack);
+
+            /* An end tag whose tag name is "colgroup" */
+        } elseif ($token['type'] === HTML5::ENDTAG &&
+            $token['name'] === 'colgroup'
+        ) {
+            /* If the current node is the root html element, then this is a
+            parse error, ignore the token. (innerHTML case) */
+            if (end($this->stack)->nodeName === 'html') {
+                // Ignore
+
+                /* Otherwise, pop the current node (which will be a colgroup
+                element) from the stack of open elements. Switch the insertion
+                mode to "in table". */
+            } else {
+                array_pop($this->stack);
+                $this->mode = self::IN_TABLE;
+            }
+
+            /* An end tag whose tag name is "col" */
+        } elseif ($token['type'] === HTML5::ENDTAG && $token['name'] === 'col') {
+            /* Parse error. Ignore the token. */
+
+            /* Anything else */
+        } else {
+            /* Act as if an end tag with the tag name "colgroup" had been seen,
+            and then, if that token wasn't ignored, reprocess the current token. */
+            $this->inColumnGroup(
+                array(
+                    'name' => 'colgroup',
+                    'type' => HTML5::ENDTAG
+                )
+            );
+
+            return $this->inTable($token);
+        }
+    }
+
+    private function inTableBody($token)
+    {
+        $clear = array('tbody', 'tfoot', 'thead', 'html');
+
+        /* A start tag whose tag name is "tr" */
+        if ($token['type'] === HTML5::STARTTAG && $token['name'] === 'tr') {
+            /* Clear the stack back to a table body context. */
+            $this->clearStackToTableContext($clear);
+
+            /* Insert a tr element for the token, then switch the insertion
+            mode to "in row". */
+            $this->insertElement($token);
+            $this->mode = self::IN_ROW;
+
+            /* A start tag whose tag name is one of: "th", "td" */
+        } elseif ($token['type'] === HTML5::STARTTAG &&
+            ($token['name'] === 'th' || $token['name'] === 'td')
+        ) {
+            /* Parse error. Act as if a start tag with the tag name "tr" had
+            been seen, then reprocess the current token. */
+            $this->inTableBody(
+                array(
+                    'name' => 'tr',
+                    'type' => HTML5::STARTTAG,
+                    'attr' => array()
+                )
+            );
+
+            return $this->inRow($token);
+
+            /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */
+        } elseif ($token['type'] === HTML5::ENDTAG &&
+            in_array($token['name'], array('tbody', 'tfoot', 'thead'))
+        ) {
+            /* If the stack of open elements does not have an element in table
+            scope with the same tag name as the token, this is a parse error.
+            Ignore the token. */
+            if (!$this->elementInScope($token['name'], true)) {
+                // Ignore
+
+                /* Otherwise: */
+            } else {
+                /* Clear the stack back to a table body context. */
+                $this->clearStackToTableContext($clear);
+
+                /* Pop the current node from the stack of open elements. Switch
+                the insertion mode to "in table". */
+                array_pop($this->stack);
+                $this->mode = self::IN_TABLE;
+            }
+
+            /* A start tag whose tag name is one of: "caption", "col", "colgroup",
+            "tbody", "tfoot", "thead", or an end tag whose tag name is "table" */
+        } elseif (($token['type'] === HTML5::STARTTAG && in_array(
+                    $token['name'],
+                    array('caption', 'col', 'colgroup', 'tbody', 'tfoor', 'thead')
+                )) ||
+            ($token['type'] === HTML5::STARTTAG && $token['name'] === 'table')
+        ) {
+            /* If the stack of open elements does not have a tbody, thead, or
+            tfoot element in table scope, this is a parse error. Ignore the
+            token. (innerHTML case) */
+            if (!$this->elementInScope(array('tbody', 'thead', 'tfoot'), true)) {
+                // Ignore.
+
+                /* Otherwise: */
+            } else {
+                /* Clear the stack back to a table body context. */
+                $this->clearStackToTableContext($clear);
+
+                /* Act as if an end tag with the same tag name as the current
+                node ("tbody", "tfoot", or "thead") had been seen, then
+                reprocess the current token. */
+                $this->inTableBody(
+                    array(
+                        'name' => end($this->stack)->nodeName,
+                        'type' => HTML5::ENDTAG
+                    )
+                );
+
+                return $this->mainPhase($token);
+            }
+
+            /* An end tag whose tag name is one of: "body", "caption", "col",
+            "colgroup", "html", "td", "th", "tr" */
+        } elseif ($token['type'] === HTML5::ENDTAG && in_array(
+                $token['name'],
+                array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr')
+            )
+        ) {
+            /* Parse error. Ignore the token. */
+
+            /* Anything else */
+        } else {
+            /* Process the token as if the insertion mode was "in table". */
+            $this->inTable($token);
+        }
+    }
+
+    private function inRow($token)
+    {
+        $clear = array('tr', 'html');
+
+        /* A start tag whose tag name is one of: "th", "td" */
+        if ($token['type'] === HTML5::STARTTAG &&
+            ($token['name'] === 'th' || $token['name'] === 'td')
+        ) {
+            /* Clear the stack back to a table row context. */
+            $this->clearStackToTableContext($clear);
+
+            /* Insert an HTML element for the token, then switch the insertion
+            mode to "in cell". */
+            $this->insertElement($token);
+            $this->mode = self::IN_CELL;
+
+            /* Insert a marker at the end of the list of active formatting
+            elements. */
+            $this->a_formatting[] = self::MARKER;
+
+            /* An end tag whose tag name is "tr" */
+        } elseif ($token['type'] === HTML5::ENDTAG && $token['name'] === 'tr') {
+            /* If the stack of open elements does not have an element in table
+            scope with the same tag name as the token, this is a parse error.
+            Ignore the token. (innerHTML case) */
+            if (!$this->elementInScope($token['name'], true)) {
+                // Ignore.
+
+                /* Otherwise: */
+            } else {
+                /* Clear the stack back to a table row context. */
+                $this->clearStackToTableContext($clear);
+
+                /* Pop the current node (which will be a tr element) from the
+                stack of open elements. Switch the insertion mode to "in table
+                body". */
+                array_pop($this->stack);
+                $this->mode = self::IN_TBODY;
+            }
+
+            /* A start tag whose tag name is one of: "caption", "col", "colgroup",
+            "tbody", "tfoot", "thead", "tr" or an end tag whose tag name is "table" */
+        } elseif ($token['type'] === HTML5::STARTTAG && in_array(
+                $token['name'],
+                array('caption', 'col', 'colgroup', 'tbody', 'tfoot', 'thead', 'tr')
+            )
+        ) {
+            /* Act as if an end tag with the tag name "tr" had been seen, then,
+            if that token wasn't ignored, reprocess the current token. */
+            $this->inRow(
+                array(
+                    'name' => 'tr',
+                    'type' => HTML5::ENDTAG
+                )
+            );
+
+            return $this->inCell($token);
+
+            /* An end tag whose tag name is one of: "tbody", "tfoot", "thead" */
+        } elseif ($token['type'] === HTML5::ENDTAG &&
+            in_array($token['name'], array('tbody', 'tfoot', 'thead'))
+        ) {
+            /* If the stack of open elements does not have an element in table
+            scope with the same tag name as the token, this is a parse error.
+            Ignore the token. */
+            if (!$this->elementInScope($token['name'], true)) {
+                // Ignore.
+
+                /* Otherwise: */
+            } else {
+                /* Otherwise, act as if an end tag with the tag name "tr" had
+                been seen, then reprocess the current token. */
+                $this->inRow(
+                    array(
+                        'name' => 'tr',
+                        'type' => HTML5::ENDTAG
+                    )
+                );
+
+                return $this->inCell($token);
+            }
+
+            /* An end tag whose tag name is one of: "body", "caption", "col",
+            "colgroup", "html", "td", "th" */
+        } elseif ($token['type'] === HTML5::ENDTAG && in_array(
+                $token['name'],
+                array('body', 'caption', 'col', 'colgroup', 'html', 'td', 'th', 'tr')
+            )
+        ) {
+            /* Parse error. Ignore the token. */
+
+            /* Anything else */
+        } else {
+            /* Process the token as if the insertion mode was "in table". */
+            $this->inTable($token);
+        }
+    }
+
+    private function inCell($token)
+    {
+        /* An end tag whose tag name is one of: "td", "th" */
+        if ($token['type'] === HTML5::ENDTAG &&
+            ($token['name'] === 'td' || $token['name'] === 'th')
+        ) {
+            /* If the stack of open elements does not have an element in table
+            scope with the same tag name as that of the token, then this is a
+            parse error and the token must be ignored. */
+            if (!$this->elementInScope($token['name'], true)) {
+                // Ignore.
+
+                /* Otherwise: */
+            } else {
+                /* Generate implied end tags, except for elements with the same
+                tag name as the token. */
+                $this->generateImpliedEndTags(array($token['name']));
+
+                /* Now, if the current node is not an element with the same tag
+                name as the token, then this is a parse error. */
+                // k
+
+                /* Pop elements from this stack until an element with the same
+                tag name as the token has been popped from the stack. */
+                while (true) {
+                    $node = end($this->stack)->nodeName;
+                    array_pop($this->stack);
+
+                    if ($node === $token['name']) {
+                        break;
+                    }
+                }
+
+                /* Clear the list of active formatting elements up to the last
+                marker. */
+                $this->clearTheActiveFormattingElementsUpToTheLastMarker();
+
+                /* Switch the insertion mode to "in row". (The current node
+                will be a tr element at this point.) */
+                $this->mode = self::IN_ROW;
+            }
+
+            /* A start tag whose tag name is one of: "caption", "col", "colgroup",
+            "tbody", "td", "tfoot", "th", "thead", "tr" */
+        } elseif ($token['type'] === HTML5::STARTTAG && in_array(
+                $token['name'],
+                array(
+                    'caption',
+                    'col',
+                    'colgroup',
+                    'tbody',
+                    'td',
+                    'tfoot',
+                    'th',
+                    'thead',
+                    'tr'
+                )
+            )
+        ) {
+            /* If the stack of open elements does not have a td or th element
+            in table scope, then this is a parse error; ignore the token.
+            (innerHTML case) */
+            if (!$this->elementInScope(array('td', 'th'), true)) {
+                // Ignore.
+
+                /* Otherwise, close the cell (see below) and reprocess the current
+                token. */
+            } else {
+                $this->closeCell();
+                return $this->inRow($token);
+            }
+
+            /* A start tag whose tag name is one of: "caption", "col", "colgroup",
+            "tbody", "td", "tfoot", "th", "thead", "tr" */
+        } elseif ($token['type'] === HTML5::STARTTAG && in_array(
+                $token['name'],
+                array(
+                    'caption',
+                    'col',
+                    'colgroup',
+                    'tbody',
+                    'td',
+                    'tfoot',
+                    'th',
+                    'thead',
+                    'tr'
+                )
+            )
+        ) {
+            /* If the stack of open elements does not have a td or th element
+            in table scope, then this is a parse error; ignore the token.
+            (innerHTML case) */
+            if (!$this->elementInScope(array('td', 'th'), true)) {
+                // Ignore.
+
+                /* Otherwise, close the cell (see below) and reprocess the current
+                token. */
+            } else {
+                $this->closeCell();
+                return $this->inRow($token);
+            }
+
+            /* An end tag whose tag name is one of: "body", "caption", "col",
+            "colgroup", "html" */
+        } elseif ($token['type'] === HTML5::ENDTAG && in_array(
+                $token['name'],
+                array('body', 'caption', 'col', 'colgroup', 'html')
+            )
+        ) {
+            /* Parse error. Ignore the token. */
+
+            /* An end tag whose tag name is one of: "table", "tbody", "tfoot",
+            "thead", "tr" */
+        } elseif ($token['type'] === HTML5::ENDTAG && in_array(
+                $token['name'],
+                array('table', 'tbody', 'tfoot', 'thead', 'tr')
+            )
+        ) {
+            /* If the stack of open elements does not have an element in table
+            scope with the same tag name as that of the token (which can only
+            happen for "tbody", "tfoot" and "thead", or, in the innerHTML case),
+            then this is a parse error and the token must be ignored. */
+            if (!$this->elementInScope($token['name'], true)) {
+                // Ignore.
+
+                /* Otherwise, close the cell (see below) and reprocess the current
+                token. */
+            } else {
+                $this->closeCell();
+                return $this->inRow($token);
+            }
+
+            /* Anything else */
+        } else {
+            /* Process the token as if the insertion mode was "in body". */
+            $this->inBody($token);
+        }
+    }
+
+    private function inSelect($token)
+    {
+        /* Handle the token as follows: */
+
+        /* A character token */
+        if ($token['type'] === HTML5::CHARACTR) {
+            /* Append the token's character to the current node. */
+            $this->insertText($token['data']);
+
+            /* A comment token */
+        } elseif ($token['type'] === HTML5::COMMENT) {
+            /* Append a Comment node to the current node with the data
+            attribute set to the data given in the comment token. */
+            $this->insertComment($token['data']);
+
+            /* A start tag token whose tag name is "option" */
+        } elseif ($token['type'] === HTML5::STARTTAG &&
+            $token['name'] === 'option'
+        ) {
+            /* If the current node is an option element, act as if an end tag
+            with the tag name "option" had been seen. */
+            if (end($this->stack)->nodeName === 'option') {
+                $this->inSelect(
+                    array(
+                        'name' => 'option',
+                        'type' => HTML5::ENDTAG
+                    )
+                );
+            }
+
+            /* Insert an HTML element for the token. */
+            $this->insertElement($token);
+
+            /* A start tag token whose tag name is "optgroup" */
+        } elseif ($token['type'] === HTML5::STARTTAG &&
+            $token['name'] === 'optgroup'
+        ) {
+            /* If the current node is an option element, act as if an end tag
+            with the tag name "option" had been seen. */
+            if (end($this->stack)->nodeName === 'option') {
+                $this->inSelect(
+                    array(
+                        'name' => 'option',
+                        'type' => HTML5::ENDTAG
+                    )
+                );
+            }
+
+            /* If the current node is an optgroup element, act as if an end tag
+            with the tag name "optgroup" had been seen. */
+            if (end($this->stack)->nodeName === 'optgroup') {
+                $this->inSelect(
+                    array(
+                        'name' => 'optgroup',
+                        'type' => HTML5::ENDTAG
+                    )
+                );
+            }
+
+            /* Insert an HTML element for the token. */
+            $this->insertElement($token);
+
+            /* An end tag token whose tag name is "optgroup" */
+        } elseif ($token['type'] === HTML5::ENDTAG &&
+            $token['name'] === 'optgroup'
+        ) {
+            /* First, if the current node is an option element, and the node
+            immediately before it in the stack of open elements is an optgroup
+            element, then act as if an end tag with the tag name "option" had
+            been seen. */
+            $elements_in_stack = count($this->stack);
+
+            if ($this->stack[$elements_in_stack - 1]->nodeName === 'option' &&
+                $this->stack[$elements_in_stack - 2]->nodeName === 'optgroup'
+            ) {
+                $this->inSelect(
+                    array(
+                        'name' => 'option',
+                        'type' => HTML5::ENDTAG
+                    )
+                );
+            }
+
+            /* If the current node is an optgroup element, then pop that node
+            from the stack of open elements. Otherwise, this is a parse error,
+            ignore the token. */
+            if ($this->stack[$elements_in_stack - 1] === 'optgroup') {
+                array_pop($this->stack);
+            }
+
+            /* An end tag token whose tag name is "option" */
+        } elseif ($token['type'] === HTML5::ENDTAG &&
+            $token['name'] === 'option'
+        ) {
+            /* If the current node is an option element, then pop that node
+            from the stack of open elements. Otherwise, this is a parse error,
+            ignore the token. */
+            if (end($this->stack)->nodeName === 'option') {
+                array_pop($this->stack);
+            }
+
+            /* An end tag whose tag name is "select" */
+        } elseif ($token['type'] === HTML5::ENDTAG &&
+            $token['name'] === 'select'
+        ) {
+            /* If the stack of open elements does not have an element in table
+            scope with the same tag name as the token, this is a parse error.
+            Ignore the token. (innerHTML case) */
+            if (!$this->elementInScope($token['name'], true)) {
+                // w/e
+
+                /* Otherwise: */
+            } else {
+                /* Pop elements from the stack of open elements until a select
+                element has been popped from the stack. */
+                while (true) {
+                    $current = end($this->stack)->nodeName;
+                    array_pop($this->stack);
+
+                    if ($current === 'select') {
+                        break;
+                    }
+                }
+
+                /* Reset the insertion mode appropriately. */
+                $this->resetInsertionMode();
+            }
+
+            /* A start tag whose tag name is "select" */
+        } elseif ($token['name'] === 'select' &&
+            $token['type'] === HTML5::STARTTAG
+        ) {
+            /* Parse error. Act as if the token had been an end tag with the
+            tag name "select" instead. */
+            $this->inSelect(
+                array(
+                    'name' => 'select',
+                    'type' => HTML5::ENDTAG
+                )
+            );
+
+            /* An end tag whose tag name is one of: "caption", "table", "tbody",
+            "tfoot", "thead", "tr", "td", "th" */
+        } elseif (in_array(
+                $token['name'],
+                array(
+                    'caption',
+                    'table',
+                    'tbody',
+                    'tfoot',
+                    'thead',
+                    'tr',
+                    'td',
+                    'th'
+                )
+            ) && $token['type'] === HTML5::ENDTAG
+        ) {
+            /* Parse error. */
+            // w/e
+
+            /* If the stack of open elements has an element in table scope with
+            the same tag name as that of the token, then act as if an end tag
+            with the tag name "select" had been seen, and reprocess the token.
+            Otherwise, ignore the token. */
+            if ($this->elementInScope($token['name'], true)) {
+                $this->inSelect(
+                    array(
+                        'name' => 'select',
+                        'type' => HTML5::ENDTAG
+                    )
+                );
+
+                $this->mainPhase($token);
+            }
+
+            /* Anything else */
+        } else {
+            /* Parse error. Ignore the token. */
+        }
+    }
+
+    private function afterBody($token)
+    {
+        /* Handle the token as follows: */
+
+        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+        or U+0020 SPACE */
+        if ($token['type'] === HTML5::CHARACTR &&
+            preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
+        ) {
+            /* Process the token as it would be processed if the insertion mode
+            was "in body". */
+            $this->inBody($token);
+
+            /* A comment token */
+        } elseif ($token['type'] === HTML5::COMMENT) {
+            /* Append a Comment node to the first element in the stack of open
+            elements (the html element), with the data attribute set to the
+            data given in the comment token. */
+            $comment = $this->dom->createComment($token['data']);
+            $this->stack[0]->appendChild($comment);
+
+            /* An end tag with the tag name "html" */
+        } elseif ($token['type'] === HTML5::ENDTAG && $token['name'] === 'html') {
+            /* If the parser was originally created in order to handle the
+            setting of an element's innerHTML attribute, this is a parse error;
+            ignore the token. (The element will be an html element in this
+            case.) (innerHTML case) */
+
+            /* Otherwise, switch to the trailing end phase. */
+            $this->phase = self::END_PHASE;
+
+            /* Anything else */
+        } else {
+            /* Parse error. Set the insertion mode to "in body" and reprocess
+            the token. */
+            $this->mode = self::IN_BODY;
+            return $this->inBody($token);
+        }
+    }
+
+    private function inFrameset($token)
+    {
+        /* Handle the token as follows: */
+
+        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+        U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */
+        if ($token['type'] === HTML5::CHARACTR &&
+            preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
+        ) {
+            /* Append the character to the current node. */
+            $this->insertText($token['data']);
+
+            /* A comment token */
+        } elseif ($token['type'] === HTML5::COMMENT) {
+            /* Append a Comment node to the current node with the data
+            attribute set to the data given in the comment token. */
+            $this->insertComment($token['data']);
+
+            /* A start tag with the tag name "frameset" */
+        } elseif ($token['name'] === 'frameset' &&
+            $token['type'] === HTML5::STARTTAG
+        ) {
+            $this->insertElement($token);
+
+            /* An end tag with the tag name "frameset" */
+        } elseif ($token['name'] === 'frameset' &&
+            $token['type'] === HTML5::ENDTAG
+        ) {
+            /* If the current node is the root html element, then this is a
+            parse error; ignore the token. (innerHTML case) */
+            if (end($this->stack)->nodeName === 'html') {
+                // Ignore
+
+            } else {
+                /* Otherwise, pop the current node from the stack of open
+                elements. */
+                array_pop($this->stack);
+
+                /* If the parser was not originally created in order to handle
+                the setting of an element's innerHTML attribute (innerHTML case),
+                and the current node is no longer a frameset element, then change
+                the insertion mode to "after frameset". */
+                $this->mode = self::AFTR_FRAME;
+            }
+
+            /* A start tag with the tag name "frame" */
+        } elseif ($token['name'] === 'frame' &&
+            $token['type'] === HTML5::STARTTAG
+        ) {
+            /* Insert an HTML element for the token. */
+            $this->insertElement($token);
+
+            /* Immediately pop the current node off the stack of open elements. */
+            array_pop($this->stack);
+
+            /* A start tag with the tag name "noframes" */
+        } elseif ($token['name'] === 'noframes' &&
+            $token['type'] === HTML5::STARTTAG
+        ) {
+            /* Process the token as if the insertion mode had been "in body". */
+            $this->inBody($token);
+
+            /* Anything else */
+        } else {
+            /* Parse error. Ignore the token. */
+        }
+    }
+
+    private function afterFrameset($token)
+    {
+        /* Handle the token as follows: */
+
+        /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+        U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+        U+000D CARRIAGE RETURN (CR), or U+0020 SPACE */
+        if ($token['type'] === HTML5::CHARACTR &&
+            preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
+        ) {
+            /* Append the character to the current node. */
+            $this->insertText($token['data']);
+
+            /* A comment token */
+        } elseif ($token['type'] === HTML5::COMMENT) {
+            /* Append a Comment node to the current node with the data
+            attribute set to the data given in the comment token. */
+            $this->insertComment($token['data']);
+
+            /* An end tag with the tag name "html" */
+        } elseif ($token['name'] === 'html' &&
+            $token['type'] === HTML5::ENDTAG
+        ) {
+            /* Switch to the trailing end phase. */
+            $this->phase = self::END_PHASE;
+
+            /* A start tag with the tag name "noframes" */
+        } elseif ($token['name'] === 'noframes' &&
+            $token['type'] === HTML5::STARTTAG
+        ) {
+            /* Process the token as if the insertion mode had been "in body". */
+            $this->inBody($token);
+
+            /* Anything else */
+        } else {
+            /* Parse error. Ignore the token. */
+        }
+    }
+
+    private function trailingEndPhase($token)
+    {
+        /* After the main phase, as each token is emitted from the tokenisation
+        stage, it must be processed as described in this section. */
+
+        /* A DOCTYPE token */
+        if ($token['type'] === HTML5::DOCTYPE) {
+            // Parse error. Ignore the token.
+
+            /* A comment token */
+        } elseif ($token['type'] === HTML5::COMMENT) {
+            /* Append a Comment node to the Document object with the data
+            attribute set to the data given in the comment token. */
+            $comment = $this->dom->createComment($token['data']);
+            $this->dom->appendChild($comment);
+
+            /* A character token that is one of one of U+0009 CHARACTER TABULATION,
+            U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+            or U+0020 SPACE */
+        } elseif ($token['type'] === HTML5::CHARACTR &&
+            preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])
+        ) {
+            /* Process the token as it would be processed in the main phase. */
+            $this->mainPhase($token);
+
+            /* A character token that is not one of U+0009 CHARACTER TABULATION,
+            U+000A LINE FEED (LF), U+000B LINE TABULATION, U+000C FORM FEED (FF),
+            or U+0020 SPACE. Or a start tag token. Or an end tag token. */
+        } elseif (($token['type'] === HTML5::CHARACTR &&
+                preg_match('/^[\t\n\x0b\x0c ]+$/', $token['data'])) ||
+            $token['type'] === HTML5::STARTTAG || $token['type'] === HTML5::ENDTAG
+        ) {
+            /* Parse error. Switch back to the main phase and reprocess the
+            token. */
+            $this->phase = self::MAIN_PHASE;
+            return $this->mainPhase($token);
+
+            /* An end-of-file token */
+        } elseif ($token['type'] === HTML5::EOF) {
+            /* OMG DONE!! */
+        }
+    }
+
+    private function insertElement($token, $append = true, $check = false)
+    {
+        // Proprietary workaround for libxml2's limitations with tag names
+        if ($check) {
+            // Slightly modified HTML5 tag-name modification,
+            // removing anything that's not an ASCII letter, digit, or hyphen
+            $token['name'] = preg_replace('/[^a-z0-9-]/i', '', $token['name']);
+            // Remove leading hyphens and numbers
+            $token['name'] = ltrim($token['name'], '-0..9');
+            // In theory, this should ever be needed, but just in case
+            if ($token['name'] === '') {
+                $token['name'] = 'span';
+            } // arbitrary generic choice
+        }
+
+        $el = $this->dom->createElement($token['name']);
+
+        foreach ($token['attr'] as $attr) {
+            if (!$el->hasAttribute($attr['name'])) {
+                $el->setAttribute($attr['name'], $attr['value']);
+            }
+        }
+
+        $this->appendToRealParent($el);
+        $this->stack[] = $el;
+
+        return $el;
+    }
+
+    private function insertText($data)
+    {
+        $text = $this->dom->createTextNode($data);
+        $this->appendToRealParent($text);
+    }
+
+    private function insertComment($data)
+    {
+        $comment = $this->dom->createComment($data);
+        $this->appendToRealParent($comment);
+    }
+
+    private function appendToRealParent($node)
+    {
+        if ($this->foster_parent === null) {
+            end($this->stack)->appendChild($node);
+
+        } elseif ($this->foster_parent !== null) {
+            /* If the foster parent element is the parent element of the
+            last table element in the stack of open elements, then the new
+            node must be inserted immediately before the last table element
+            in the stack of open elements in the foster parent element;
+            otherwise, the new node must be appended to the foster parent
+            element. */
+            for ($n = count($this->stack) - 1; $n >= 0; $n--) {
+                if ($this->stack[$n]->nodeName === 'table' &&
+                    $this->stack[$n]->parentNode !== null
+                ) {
+                    $table = $this->stack[$n];
+                    break;
+                }
+            }
+
+            if (isset($table) && $this->foster_parent->isSameNode($table->parentNode)) {
+                $this->foster_parent->insertBefore($node, $table);
+            } else {
+                $this->foster_parent->appendChild($node);
+            }
+
+            $this->foster_parent = null;
+        }
+    }
+
+    private function elementInScope($el, $table = false)
+    {
+        if (is_array($el)) {
+            foreach ($el as $element) {
+                if ($this->elementInScope($element, $table)) {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        $leng = count($this->stack);
+
+        for ($n = 0; $n < $leng; $n++) {
+            /* 1. Initialise node to be the current node (the bottommost node of
+            the stack). */
+            $node = $this->stack[$leng - 1 - $n];
+
+            if ($node->tagName === $el) {
+                /* 2. If node is the target node, terminate in a match state. */
+                return true;
+
+            } elseif ($node->tagName === 'table') {
+                /* 3. Otherwise, if node is a table element, terminate in a failure
+                state. */
+                return false;
+
+            } elseif ($table === true && in_array(
+                    $node->tagName,
+                    array(
+                        'caption',
+                        'td',
+                        'th',
+                        'button',
+                        'marquee',
+                        'object'
+                    )
+                )
+            ) {
+                /* 4. Otherwise, if the algorithm is the "has an element in scope"
+                variant (rather than the "has an element in table scope" variant),
+                and node is one of the following, terminate in a failure state. */
+                return false;
+
+            } elseif ($node === $node->ownerDocument->documentElement) {
+                /* 5. Otherwise, if node is an html element (root element), terminate
+                in a failure state. (This can only happen if the node is the topmost
+                node of the    stack of open elements, and prevents the next step from
+                being invoked if there are no more elements in the stack.) */
+                return false;
+            }
+
+            /* Otherwise, set node to the previous entry in the stack of open
+            elements and return to step 2. (This will never fail, since the loop
+            will always terminate in the previous step if the top of the stack
+            is reached.) */
+        }
+    }
+
+    private function reconstructActiveFormattingElements()
+    {
+        /* 1. If there are no entries in the list of active formatting elements,
+        then there is nothing to reconstruct; stop this algorithm. */
+        $formatting_elements = count($this->a_formatting);
+
+        if ($formatting_elements === 0) {
+            return false;
+        }
+
+        /* 3. Let entry be the last (most recently added) element in the list
+        of active formatting elements. */
+        $entry = end($this->a_formatting);
+
+        /* 2. If the last (most recently added) entry in the list of active
+        formatting elements is a marker, or if it is an element that is in the
+        stack of open elements, then there is nothing to reconstruct; stop this
+        algorithm. */
+        if ($entry === self::MARKER || in_array($entry, $this->stack, true)) {
+            return false;
+        }
+
+        for ($a = $formatting_elements - 1; $a >= 0; true) {
+            /* 4. If there are no entries before entry in the list of active
+            formatting elements, then jump to step 8. */
+            if ($a === 0) {
+                $step_seven = false;
+                break;
+            }
+
+            /* 5. Let entry be the entry one earlier than entry in the list of
+            active formatting elements. */
+            $a--;
+            $entry = $this->a_formatting[$a];
+
+            /* 6. If entry is neither a marker nor an element that is also in
+            thetack of open elements, go to step 4. */
+            if ($entry === self::MARKER || in_array($entry, $this->stack, true)) {
+                break;
+            }
+        }
+
+        while (true) {
+            /* 7. Let entry be the element one later than entry in the list of
+            active formatting elements. */
+            if (isset($step_seven) && $step_seven === true) {
+                $a++;
+                $entry = $this->a_formatting[$a];
+            }
+
+            /* 8. Perform a shallow clone of the element entry to obtain clone. */
+            $clone = $entry->cloneNode();
+
+            /* 9. Append clone to the current node and push it onto the stack
+            of open elements  so that it is the new current node. */
+            end($this->stack)->appendChild($clone);
+            $this->stack[] = $clone;
+
+            /* 10. Replace the entry for entry in the list with an entry for
+            clone. */
+            $this->a_formatting[$a] = $clone;
+
+            /* 11. If the entry for clone in the list of active formatting
+            elements is not the last entry in the list, return to step 7. */
+            if (end($this->a_formatting) !== $clone) {
+                $step_seven = true;
+            } else {
+                break;
+            }
+        }
+    }
+
+    private function clearTheActiveFormattingElementsUpToTheLastMarker()
+    {
+        /* When the steps below require the UA to clear the list of active
+        formatting elements up to the last marker, the UA must perform the
+        following steps: */
+
+        while (true) {
+            /* 1. Let entry be the last (most recently added) entry in the list
+            of active formatting elements. */
+            $entry = end($this->a_formatting);
+
+            /* 2. Remove entry from the list of active formatting elements. */
+            array_pop($this->a_formatting);
+
+            /* 3. If entry was a marker, then stop the algorithm at this point.
+            The list has been cleared up to the last marker. */
+            if ($entry === self::MARKER) {
+                break;
+            }
+        }
+    }
+
+    private function generateImpliedEndTags($exclude = array())
+    {
+        /* When the steps below require the UA to generate implied end tags,
+        then, if the current node is a dd element, a dt element, an li element,
+        a p element, a td element, a th  element, or a tr element, the UA must
+        act as if an end tag with the respective tag name had been seen and
+        then generate implied end tags again. */
+        $node = end($this->stack);
+        $elements = array_diff(array('dd', 'dt', 'li', 'p', 'td', 'th', 'tr'), $exclude);
+
+        while (in_array(end($this->stack)->nodeName, $elements)) {
+            array_pop($this->stack);
+        }
+    }
+
+    private function getElementCategory($node)
+    {
+        $name = $node->tagName;
+        if (in_array($name, $this->special)) {
+            return self::SPECIAL;
+        } elseif (in_array($name, $this->scoping)) {
+            return self::SCOPING;
+        } elseif (in_array($name, $this->formatting)) {
+            return self::FORMATTING;
+        } else {
+            return self::PHRASING;
+        }
+    }
+
+    private function clearStackToTableContext($elements)
+    {
+        /* When the steps above require the UA to clear the stack back to a
+        table context, it means that the UA must, while the current node is not
+        a table element or an html element, pop elements from the stack of open
+        elements. If this causes any elements to be popped from the stack, then
+        this is a parse error. */
+        while (true) {
+            $node = end($this->stack)->nodeName;
+
+            if (in_array($node, $elements)) {
+                break;
+            } else {
+                array_pop($this->stack);
+            }
+        }
+    }
+
+    private function resetInsertionMode()
+    {
+        /* 1. Let last be false. */
+        $last = false;
+        $leng = count($this->stack);
+
+        for ($n = $leng - 1; $n >= 0; $n--) {
+            /* 2. Let node be the last node in the stack of open elements. */
+            $node = $this->stack[$n];
+
+            /* 3. If node is the first node in the stack of open elements, then
+            set last to true. If the element whose innerHTML  attribute is being
+            set is neither a td  element nor a th element, then set node to the
+            element whose innerHTML  attribute is being set. (innerHTML  case) */
+            if ($this->stack[0]->isSameNode($node)) {
+                $last = true;
+            }
+
+            /* 4. If node is a select element, then switch the insertion mode to
+            "in select" and abort these steps. (innerHTML case) */
+            if ($node->nodeName === 'select') {
+                $this->mode = self::IN_SELECT;
+                break;
+
+                /* 5. If node is a td or th element, then switch the insertion mode
+                to "in cell" and abort these steps. */
+            } elseif ($node->nodeName === 'td' || $node->nodeName === 'th') {
+                $this->mode = self::IN_CELL;
+                break;
+
+                /* 6. If node is a tr element, then switch the insertion mode to
+                "in    row" and abort these steps. */
+            } elseif ($node->nodeName === 'tr') {
+                $this->mode = self::IN_ROW;
+                break;
+
+                /* 7. If node is a tbody, thead, or tfoot element, then switch the
+                insertion mode to "in table body" and abort these steps. */
+            } elseif (in_array($node->nodeName, array('tbody', 'thead', 'tfoot'))) {
+                $this->mode = self::IN_TBODY;
+                break;
+
+                /* 8. If node is a caption element, then switch the insertion mode
+                to "in caption" and abort these steps. */
+            } elseif ($node->nodeName === 'caption') {
+                $this->mode = self::IN_CAPTION;
+                break;
+
+                /* 9. If node is a colgroup element, then switch the insertion mode
+                to "in column group" and abort these steps. (innerHTML case) */
+            } elseif ($node->nodeName === 'colgroup') {
+                $this->mode = self::IN_CGROUP;
+                break;
+
+                /* 10. If node is a table element, then switch the insertion mode
+                to "in table" and abort these steps. */
+            } elseif ($node->nodeName === 'table') {
+                $this->mode = self::IN_TABLE;
+                break;
+
+                /* 11. If node is a head element, then switch the insertion mode
+                to "in body" ("in body"! not "in head"!) and abort these steps.
+                (innerHTML case) */
+            } elseif ($node->nodeName === 'head') {
+                $this->mode = self::IN_BODY;
+                break;
+
+                /* 12. If node is a body element, then switch the insertion mode to
+                "in body" and abort these steps. */
+            } elseif ($node->nodeName === 'body') {
+                $this->mode = self::IN_BODY;
+                break;
+
+                /* 13. If node is a frameset element, then switch the insertion
+                mode to "in frameset" and abort these steps. (innerHTML case) */
+            } elseif ($node->nodeName === 'frameset') {
+                $this->mode = self::IN_FRAME;
+                break;
+
+                /* 14. If node is an html element, then: if the head element
+                pointer is null, switch the insertion mode to "before head",
+                otherwise, switch the insertion mode to "after head". In either
+                case, abort these steps. (innerHTML case) */
+            } elseif ($node->nodeName === 'html') {
+                $this->mode = ($this->head_pointer === null)
+                    ? self::BEFOR_HEAD
+                    : self::AFTER_HEAD;
+
+                break;
+
+                /* 15. If last is true, then set the insertion mode to "in body"
+                and    abort these steps. (innerHTML case) */
+            } elseif ($last) {
+                $this->mode = self::IN_BODY;
+                break;
+            }
+        }
+    }
+
+    private function closeCell()
+    {
+        /* If the stack of open elements has a td or th element in table scope,
+        then act as if an end tag token with that tag name had been seen. */
+        foreach (array('td', 'th') as $cell) {
+            if ($this->elementInScope($cell, true)) {
+                $this->inCell(
+                    array(
+                        'name' => $cell,
+                        'type' => HTML5::ENDTAG
+                    )
+                );
+
+                break;
+            }
+        }
+    }
+
+    public function save()
+    {
+        return $this->dom;
+    }
+}
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Node.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Node.php
new file mode 100644
index 0000000000..3995fec9fe
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Node.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * Abstract base node class that all others inherit from.
+ *
+ * Why do we not use the DOM extension?  (1) It is not always available,
+ * (2) it has funny constraints on the data it can represent,
+ * whereas we want a maximally flexible representation, and (3) its
+ * interface is a bit cumbersome.
+ */
+abstract class HTMLPurifier_Node
+{
+    /**
+     * Line number of the start token in the source document
+     * @type int
+     */
+    public $line;
+
+    /**
+     * Column number of the start token in the source document. Null if unknown.
+     * @type int
+     */
+    public $col;
+
+    /**
+     * Lookup array of processing that this token is exempt from.
+     * Currently, valid values are "ValidateAttributes".
+     * @type array
+     */
+    public $armor = array();
+
+    /**
+     * When true, this node should be ignored as non-existent.
+     *
+     * Who is responsible for ignoring dead nodes?  FixNesting is
+     * responsible for removing them before passing on to child
+     * validators.
+     */
+    public $dead = false;
+
+    /**
+     * Returns a pair of start and end tokens, where the end token
+     * is null if it is not necessary. Does not include children.
+     * @type array
+     */
+    abstract public function toTokenPair();
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Comment.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Comment.php
new file mode 100644
index 0000000000..38ba193942
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Comment.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * Concrete comment node class.
+ */
+class HTMLPurifier_Node_Comment extends HTMLPurifier_Node
+{
+    /**
+     * Character data within comment.
+     * @type string
+     */
+    public $data;
+
+    /**
+     * @type bool
+     */
+    public $is_whitespace = true;
+
+    /**
+     * Transparent constructor.
+     *
+     * @param string $data String comment data.
+     * @param int $line
+     * @param int $col
+     */
+    public function __construct($data, $line = null, $col = null)
+    {
+        $this->data = $data;
+        $this->line = $line;
+        $this->col = $col;
+    }
+
+    public function toTokenPair() {
+        return array(new HTMLPurifier_Token_Comment($this->data, $this->line, $this->col), null);
+    }
+}
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Element.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Element.php
new file mode 100644
index 0000000000..6cbf56dada
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Element.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * Concrete element node class.
+ */
+class HTMLPurifier_Node_Element extends HTMLPurifier_Node
+{
+    /**
+     * The lower-case name of the tag, like 'a', 'b' or 'blockquote'.
+     *
+     * @note Strictly speaking, XML tags are case sensitive, so we shouldn't
+     * be lower-casing them, but these tokens cater to HTML tags, which are
+     * insensitive.
+     * @type string
+     */
+    public $name;
+
+    /**
+     * Associative array of the node's attributes.
+     * @type array
+     */
+    public $attr = array();
+
+    /**
+     * List of child elements.
+     * @type array
+     */
+    public $children = array();
+
+    /**
+     * Does this use the <a></a> form or the </a> form, i.e.
+     * is it a pair of start/end tokens or an empty token.
+     * @bool
+     */
+    public $empty = false;
+
+    public $endCol = null, $endLine = null, $endArmor = array();
+
+    public function __construct($name, $attr = array(), $line = null, $col = null, $armor = array()) {
+        $this->name = $name;
+        $this->attr = $attr;
+        $this->line = $line;
+        $this->col = $col;
+        $this->armor = $armor;
+    }
+
+    public function toTokenPair() {
+        // XXX inefficiency here, normalization is not necessary
+        if ($this->empty) {
+            return array(new HTMLPurifier_Token_Empty($this->name, $this->attr, $this->line, $this->col, $this->armor), null);
+        } else {
+            $start = new HTMLPurifier_Token_Start($this->name, $this->attr, $this->line, $this->col, $this->armor);
+            $end = new HTMLPurifier_Token_End($this->name, array(), $this->endLine, $this->endCol, $this->endArmor);
+            //$end->start = $start;
+            return array($start, $end);
+        }
+    }
+}
+
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Text.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Text.php
new file mode 100644
index 0000000000..aec9166473
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Node/Text.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * Concrete text token class.
+ *
+ * Text tokens comprise of regular parsed character data (PCDATA) and raw
+ * character data (from the CDATA sections). Internally, their
+ * data is parsed with all entities expanded. Surprisingly, the text token
+ * does have a "tag name" called #PCDATA, which is how the DTD represents it
+ * in permissible child nodes.
+ */
+class HTMLPurifier_Node_Text extends HTMLPurifier_Node
+{
+
+    /**
+     * PCDATA tag name compatible with DTD, see
+     * HTMLPurifier_ChildDef_Custom for details.
+     * @type string
+     */
+    public $name = '#PCDATA';
+
+    /**
+     * @type string
+     */
+    public $data;
+    /**< Parsed character data of text. */
+
+    /**
+     * @type bool
+     */
+    public $is_whitespace;
+
+    /**< Bool indicating if node is whitespace. */
+
+    /**
+     * Constructor, accepts data and determines if it is whitespace.
+     * @param string $data String parsed character data.
+     * @param int $line
+     * @param int $col
+     */
+    public function __construct($data, $is_whitespace, $line = null, $col = null)
+    {
+        $this->data = $data;
+        $this->is_whitespace = $is_whitespace;
+        $this->line = $line;
+        $this->col = $col;
+    }
+
+    public function toTokenPair() {
+        return array(new HTMLPurifier_Token_Text($this->data, $this->line, $this->col), null);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/PercentEncoder.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/PercentEncoder.php
similarity index 78%
rename from library/HTMLPurifier/PercentEncoder.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/PercentEncoder.php
index a43c44f4c5..18c8bbb00a 100644
--- a/library/HTMLPurifier/PercentEncoder.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/PercentEncoder.php
@@ -13,17 +13,26 @@ class HTMLPurifier_PercentEncoder
 
     /**
      * Reserved characters to preserve when using encode().
+     * @type array
      */
     protected $preserve = array();
 
     /**
      * String of characters that should be preserved while using encode().
+     * @param bool $preserve
      */
-    public function __construct($preserve = false) {
+    public function __construct($preserve = false)
+    {
         // unreserved letters, ought to const-ify
-        for ($i = 48; $i <= 57;  $i++) $this->preserve[$i] = true; // digits
-        for ($i = 65; $i <= 90;  $i++) $this->preserve[$i] = true; // upper-case
-        for ($i = 97; $i <= 122; $i++) $this->preserve[$i] = true; // lower-case
+        for ($i = 48; $i <= 57; $i++) { // digits
+            $this->preserve[$i] = true;
+        }
+        for ($i = 65; $i <= 90; $i++) { // upper-case
+            $this->preserve[$i] = true;
+        }
+        for ($i = 97; $i <= 122; $i++) { // lower-case
+            $this->preserve[$i] = true;
+        }
         $this->preserve[45] = true; // Dash         -
         $this->preserve[46] = true; // Period       .
         $this->preserve[95] = true; // Underscore   _
@@ -44,13 +53,14 @@ class HTMLPurifier_PercentEncoder
      *      Assumes that the string has already been normalized, making any
      *      and all percent escape sequences valid. Percents will not be
      *      re-escaped, regardless of their status in $preserve
-     * @param $string String to be encoded
-     * @return Encoded string.
+     * @param string $string String to be encoded
+     * @return string Encoded string.
      */
-    public function encode($string) {
+    public function encode($string)
+    {
         $ret = '';
         for ($i = 0, $c = strlen($string); $i < $c; $i++) {
-            if ($string[$i] !== '%' && !isset($this->preserve[$int = ord($string[$i])]) ) {
+            if ($string[$i] !== '%' && !isset($this->preserve[$int = ord($string[$i])])) {
                 $ret .= '%' . sprintf('%02X', $int);
             } else {
                 $ret .= $string[$i];
@@ -64,10 +74,14 @@ class HTMLPurifier_PercentEncoder
      * @warning This function is affected by $preserve, even though the
      *          usual desired behavior is for this not to preserve those
      *          characters. Be careful when reusing instances of PercentEncoder!
-     * @param $string String to normalize
+     * @param string $string String to normalize
+     * @return string
      */
-    public function normalize($string) {
-        if ($string == '') return '';
+    public function normalize($string)
+    {
+        if ($string == '') {
+            return '';
+        }
         $parts = explode('%', $string);
         $ret = array_shift($parts);
         foreach ($parts as $part) {
@@ -92,7 +106,6 @@ class HTMLPurifier_PercentEncoder
         }
         return $ret;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Printer.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Printer.php
similarity index 54%
rename from library/HTMLPurifier/Printer.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Printer.php
index e7eb82e83e..549e4cea1e 100644
--- a/library/HTMLPurifier/Printer.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Printer.php
@@ -7,25 +7,30 @@ class HTMLPurifier_Printer
 {
 
     /**
-     * Instance of HTMLPurifier_Generator for HTML generation convenience funcs
+     * For HTML generation convenience funcs.
+     * @type HTMLPurifier_Generator
      */
     protected $generator;
 
     /**
-     * Instance of HTMLPurifier_Config, for easy access
+     * For easy access.
+     * @type HTMLPurifier_Config
      */
     protected $config;
 
     /**
      * Initialize $generator.
      */
-    public function __construct() {
+    public function __construct()
+    {
     }
 
     /**
      * Give generator necessary configuration if possible
+     * @param HTMLPurifier_Config $config
      */
-    public function prepareGenerator($config) {
+    public function prepareGenerator($config)
+    {
         $all = $config->getAll();
         $context = new HTMLPurifier_Context();
         $this->generator = new HTMLPurifier_Generator($config, $context);
@@ -39,45 +44,62 @@ class HTMLPurifier_Printer
 
     /**
      * Returns a start tag
-     * @param $tag Tag name
-     * @param $attr Attribute array
+     * @param string $tag Tag name
+     * @param array $attr Attribute array
+     * @return string
      */
-    protected function start($tag, $attr = array()) {
+    protected function start($tag, $attr = array())
+    {
         return $this->generator->generateFromToken(
-                    new HTMLPurifier_Token_Start($tag, $attr ? $attr : array())
-               );
+            new HTMLPurifier_Token_Start($tag, $attr ? $attr : array())
+        );
     }
 
     /**
-     * Returns an end teg
-     * @param $tag Tag name
+     * Returns an end tag
+     * @param string $tag Tag name
+     * @return string
      */
-    protected function end($tag) {
+    protected function end($tag)
+    {
         return $this->generator->generateFromToken(
-                    new HTMLPurifier_Token_End($tag)
-               );
+            new HTMLPurifier_Token_End($tag)
+        );
     }
 
     /**
      * Prints a complete element with content inside
-     * @param $tag Tag name
-     * @param $contents Element contents
-     * @param $attr Tag attributes
-     * @param $escape Bool whether or not to escape contents
+     * @param string $tag Tag name
+     * @param string $contents Element contents
+     * @param array $attr Tag attributes
+     * @param bool $escape whether or not to escape contents
+     * @return string
      */
-    protected function element($tag, $contents, $attr = array(), $escape = true) {
+    protected function element($tag, $contents, $attr = array(), $escape = true)
+    {
         return $this->start($tag, $attr) .
-               ($escape ? $this->escape($contents) : $contents) .
-               $this->end($tag);
+            ($escape ? $this->escape($contents) : $contents) .
+            $this->end($tag);
     }
 
-    protected function elementEmpty($tag, $attr = array()) {
+    /**
+     * @param string $tag
+     * @param array $attr
+     * @return string
+     */
+    protected function elementEmpty($tag, $attr = array())
+    {
         return $this->generator->generateFromToken(
             new HTMLPurifier_Token_Empty($tag, $attr)
         );
     }
 
-    protected function text($text) {
+    /**
+     * @param string $text
+     * @return string
+     */
+    protected function text($text)
+    {
         return $this->generator->generateFromToken(
             new HTMLPurifier_Token_Text($text)
         );
@@ -85,24 +107,29 @@ class HTMLPurifier_Printer
 
     /**
      * Prints a simple key/value row in a table.
-     * @param $name Key
-     * @param $value Value
+     * @param string $name Key
+     * @param mixed $value Value
+     * @return string
      */
-    protected function row($name, $value) {
-        if (is_bool($value)) $value = $value ? 'On' : 'Off';
+    protected function row($name, $value)
+    {
+        if (is_bool($value)) {
+            $value = $value ? 'On' : 'Off';
+        }
         return
             $this->start('tr') . "\n" .
-                $this->element('th', $name) . "\n" .
-                $this->element('td', $value) . "\n" .
-            $this->end('tr')
-        ;
+            $this->element('th', $name) . "\n" .
+            $this->element('td', $value) . "\n" .
+            $this->end('tr');
     }
 
     /**
      * Escapes a string for HTML output.
-     * @param $string String to escape
+     * @param string $string String to escape
+     * @return string
      */
-    protected function escape($string) {
+    protected function escape($string)
+    {
         $string = HTMLPurifier_Encoder::cleanUTF8($string);
         $string = htmlspecialchars($string, ENT_COMPAT, 'UTF-8');
         return $string;
@@ -110,32 +137,46 @@ class HTMLPurifier_Printer
 
     /**
      * Takes a list of strings and turns them into a single list
-     * @param $array List of strings
-     * @param $polite Bool whether or not to add an end before the last
+     * @param string[] $array List of strings
+     * @param bool $polite Bool whether or not to add an end before the last
+     * @return string
      */
-    protected function listify($array, $polite = false) {
-        if (empty($array)) return 'None';
+    protected function listify($array, $polite = false)
+    {
+        if (empty($array)) {
+            return 'None';
+        }
         $ret = '';
         $i = count($array);
         foreach ($array as $value) {
             $i--;
             $ret .= $value;
-            if ($i > 0 && !($polite && $i == 1)) $ret .= ', ';
-            if ($polite && $i == 1) $ret .= 'and ';
+            if ($i > 0 && !($polite && $i == 1)) {
+                $ret .= ', ';
+            }
+            if ($polite && $i == 1) {
+                $ret .= 'and ';
+            }
         }
         return $ret;
     }
 
     /**
      * Retrieves the class of an object without prefixes, as well as metadata
-     * @param $obj Object to determine class of
-     * @param $prefix Further prefix to remove
+     * @param object $obj Object to determine class of
+     * @param string $sec_prefix Further prefix to remove
+     * @return string
      */
-    protected function getClass($obj, $sec_prefix = '') {
+    protected function getClass($obj, $sec_prefix = '')
+    {
         static $five = null;
-        if ($five === null) $five = version_compare(PHP_VERSION, '5', '>=');
+        if ($five === null) {
+            $five = version_compare(PHP_VERSION, '5', '>=');
+        }
         $prefix = 'HTMLPurifier_' . $sec_prefix;
-        if (!$five) $prefix = strtolower($prefix);
+        if (!$five) {
+            $prefix = strtolower($prefix);
+        }
         $class = str_replace($prefix, '', get_class($obj));
         $lclass = strtolower($class);
         $class .= '(';
@@ -164,13 +205,14 @@ class HTMLPurifier_Printer
                 break;
             case 'css_importantdecorator':
                 $class .= $this->getClass($obj->def, $sec_prefix);
-                if ($obj->allow) $class .= ', !important';
+                if ($obj->allow) {
+                    $class .= ', !important';
+                }
                 break;
         }
         $class .= ')';
         return $class;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Printer/CSSDefinition.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/CSSDefinition.php
similarity index 85%
rename from library/HTMLPurifier/Printer/CSSDefinition.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/CSSDefinition.php
index 81f9865901..29505fe12d 100644
--- a/library/HTMLPurifier/Printer/CSSDefinition.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/CSSDefinition.php
@@ -2,10 +2,17 @@
 
 class HTMLPurifier_Printer_CSSDefinition extends HTMLPurifier_Printer
 {
-
+    /**
+     * @type HTMLPurifier_CSSDefinition
+     */
     protected $def;
 
-    public function render($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return string
+     */
+    public function render($config)
+    {
         $this->def = $config->getCSSDefinition();
         $ret = '';
 
@@ -32,7 +39,6 @@ class HTMLPurifier_Printer_CSSDefinition extends HTMLPurifier_Printer
 
         return $ret;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Printer/ConfigForm.css b/library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.css
similarity index 100%
rename from library/HTMLPurifier/Printer/ConfigForm.css
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.css
diff --git a/library/HTMLPurifier/Printer/ConfigForm.js b/library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.js
similarity index 100%
rename from library/HTMLPurifier/Printer/ConfigForm.js
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.js
diff --git a/library/HTMLPurifier/Printer/ConfigForm.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php
similarity index 60%
rename from library/HTMLPurifier/Printer/ConfigForm.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php
index 02aa656894..36100ce738 100644
--- a/library/HTMLPurifier/Printer/ConfigForm.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/ConfigForm.php
@@ -7,17 +7,20 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
 {
 
     /**
-     * Printers for specific fields
+     * Printers for specific fields.
+     * @type HTMLPurifier_Printer[]
      */
     protected $fields = array();
 
     /**
-     * Documentation URL, can have fragment tagged on end
+     * Documentation URL, can have fragment tagged on end.
+     * @type string
      */
     protected $docURL;
 
     /**
-     * Name of form element to stuff config in
+     * Name of form element to stuff config in.
+     * @type string
      */
     protected $name;
 
@@ -25,24 +28,27 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
      * Whether or not to compress directive names, clipping them off
      * after a certain amount of letters. False to disable or integer letters
      * before clipping.
+     * @type bool
      */
     protected $compress = false;
 
     /**
-     * @param $name Form element name for directives to be stuffed into
-     * @param $doc_url String documentation URL, will have fragment tagged on
-     * @param $compress Integer max length before compressing a directive name, set to false to turn off
+     * @param string $name Form element name for directives to be stuffed into
+     * @param string $doc_url String documentation URL, will have fragment tagged on
+     * @param bool $compress Integer max length before compressing a directive name, set to false to turn off
      */
     public function __construct(
-        $name, $doc_url = null, $compress = false
+        $name,
+        $doc_url = null,
+        $compress = false
     ) {
         parent::__construct();
         $this->docURL = $doc_url;
-        $this->name   = $name;
+        $this->name = $name;
         $this->compress = $compress;
         // initialize sub-printers
-        $this->fields[0]    = new HTMLPurifier_Printer_ConfigForm_default();
-        $this->fields[HTMLPurifier_VarParser::BOOL]       = new HTMLPurifier_Printer_ConfigForm_bool();
+        $this->fields[0] = new HTMLPurifier_Printer_ConfigForm_default();
+        $this->fields[HTMLPurifier_VarParser::BOOL] = new HTMLPurifier_Printer_ConfigForm_bool();
     }
 
     /**
@@ -50,32 +56,42 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
      * @param $cols Integer columns of textarea, null to use default
      * @param $rows Integer rows of textarea, null to use default
      */
-    public function setTextareaDimensions($cols = null, $rows = null) {
-        if ($cols) $this->fields['default']->cols = $cols;
-        if ($rows) $this->fields['default']->rows = $rows;
+    public function setTextareaDimensions($cols = null, $rows = null)
+    {
+        if ($cols) {
+            $this->fields['default']->cols = $cols;
+        }
+        if ($rows) {
+            $this->fields['default']->rows = $rows;
+        }
     }
 
     /**
      * Retrieves styling, in case it is not accessible by webserver
      */
-    public static function getCSS() {
+    public static function getCSS()
+    {
         return file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/Printer/ConfigForm.css');
     }
 
     /**
      * Retrieves JavaScript, in case it is not accessible by webserver
      */
-    public static function getJavaScript() {
+    public static function getJavaScript()
+    {
         return file_get_contents(HTMLPURIFIER_PREFIX . '/HTMLPurifier/Printer/ConfigForm.js');
     }
 
     /**
      * Returns HTML output for a configuration form
-     * @param $config Configuration object of current form state, or an array
+     * @param HTMLPurifier_Config|array $config Configuration object of current form state, or an array
      *        where [0] has an HTML namespace and [1] is being rendered.
-     * @param $allowed Optional namespace(s) and directives to restrict form to.
+     * @param array|bool $allowed Optional namespace(s) and directives to restrict form to.
+     * @param bool $render_controls
+     * @return string
      */
-    public function render($config, $allowed = true, $render_controls = true) {
+    public function render($config, $allowed = true, $render_controls = true)
+    {
         if (is_array($config) && isset($config[0])) {
             $gen_config = $config[0];
             $config = $config[1];
@@ -91,29 +107,29 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
         $all = array();
         foreach ($allowed as $key) {
             list($ns, $directive) = $key;
-            $all[$ns][$directive] = $config->get($ns .'.'. $directive);
+            $all[$ns][$directive] = $config->get($ns . '.' . $directive);
         }
 
         $ret = '';
         $ret .= $this->start('table', array('class' => 'hp-config'));
         $ret .= $this->start('thead');
         $ret .= $this->start('tr');
-            $ret .= $this->element('th', 'Directive', array('class' => 'hp-directive'));
-            $ret .= $this->element('th', 'Value', array('class' => 'hp-value'));
+        $ret .= $this->element('th', 'Directive', array('class' => 'hp-directive'));
+        $ret .= $this->element('th', 'Value', array('class' => 'hp-value'));
         $ret .= $this->end('tr');
         $ret .= $this->end('thead');
         foreach ($all as $ns => $directives) {
             $ret .= $this->renderNamespace($ns, $directives);
         }
         if ($render_controls) {
-             $ret .= $this->start('tbody');
-             $ret .= $this->start('tr');
-                 $ret .= $this->start('td', array('colspan' => 2, 'class' => 'controls'));
-                     $ret .= $this->elementEmpty('input', array('type' => 'submit', 'value' => 'Submit'));
-                     $ret .= '[<a href="?">Reset</a>]';
-                 $ret .= $this->end('td');
-             $ret .= $this->end('tr');
-             $ret .= $this->end('tbody');
+            $ret .= $this->start('tbody');
+            $ret .= $this->start('tr');
+            $ret .= $this->start('td', array('colspan' => 2, 'class' => 'controls'));
+            $ret .= $this->elementEmpty('input', array('type' => 'submit', 'value' => 'Submit'));
+            $ret .= '[<a href="?">Reset</a>]';
+            $ret .= $this->end('td');
+            $ret .= $this->end('tr');
+            $ret .= $this->end('tbody');
         }
         $ret .= $this->end('table');
         return $ret;
@@ -122,13 +138,15 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
     /**
      * Renders a single namespace
      * @param $ns String namespace name
-     * @param $directive Associative array of directives to values
+     * @param array $directives array of directives to values
+     * @return string
      */
-    protected function renderNamespace($ns, $directives) {
+    protected function renderNamespace($ns, $directives)
+    {
         $ret = '';
         $ret .= $this->start('tbody', array('class' => 'namespace'));
         $ret .= $this->start('tr');
-            $ret .= $this->element('th', $ns, array('colspan' => 2));
+        $ret .= $this->element('th', $ns, array('colspan' => 2));
         $ret .= $this->end('tr');
         $ret .= $this->end('tbody');
         $ret .= $this->start('tbody');
@@ -139,40 +157,44 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
                 $url = str_replace('%s', urlencode("$ns.$directive"), $this->docURL);
                 $ret .= $this->start('a', array('href' => $url));
             }
-                $attr = array('for' => "{$this->name}:$ns.$directive");
+            $attr = array('for' => "{$this->name}:$ns.$directive");
 
-                // crop directive name if it's too long
-                if (!$this->compress || (strlen($directive) < $this->compress)) {
-                    $directive_disp = $directive;
-                } else {
-                    $directive_disp = substr($directive, 0, $this->compress - 2) . '...';
-                    $attr['title'] = $directive;
-                }
+            // crop directive name if it's too long
+            if (!$this->compress || (strlen($directive) < $this->compress)) {
+                $directive_disp = $directive;
+            } else {
+                $directive_disp = substr($directive, 0, $this->compress - 2) . '...';
+                $attr['title'] = $directive;
+            }
 
-                $ret .= $this->element(
-                    'label',
-                    $directive_disp,
-                    // component printers must create an element with this id
-                    $attr
-                );
-            if ($this->docURL) $ret .= $this->end('a');
+            $ret .= $this->element(
+                'label',
+                $directive_disp,
+                // component printers must create an element with this id
+                $attr
+            );
+            if ($this->docURL) {
+                $ret .= $this->end('a');
+            }
             $ret .= $this->end('th');
 
             $ret .= $this->start('td');
-                $def = $this->config->def->info["$ns.$directive"];
-                if (is_int($def)) {
-                    $allow_null = $def < 0;
-                    $type = abs($def);
-                } else {
-                    $type = $def->type;
-                    $allow_null = isset($def->allow_null);
-                }
-                if (!isset($this->fields[$type])) $type = 0; // default
-                $type_obj = $this->fields[$type];
-                if ($allow_null) {
-                    $type_obj = new HTMLPurifier_Printer_ConfigForm_NullDecorator($type_obj);
-                }
-                $ret .= $type_obj->render($ns, $directive, $value, $this->name, array($this->genConfig, $this->config));
+            $def = $this->config->def->info["$ns.$directive"];
+            if (is_int($def)) {
+                $allow_null = $def < 0;
+                $type = abs($def);
+            } else {
+                $type = $def->type;
+                $allow_null = isset($def->allow_null);
+            }
+            if (!isset($this->fields[$type])) {
+                $type = 0;
+            } // default
+            $type_obj = $this->fields[$type];
+            if ($allow_null) {
+                $type_obj = new HTMLPurifier_Printer_ConfigForm_NullDecorator($type_obj);
+            }
+            $ret .= $type_obj->render($ns, $directive, $value, $this->name, array($this->genConfig, $this->config));
             $ret .= $this->end('td');
             $ret .= $this->end('tr');
         }
@@ -185,19 +207,33 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
 /**
  * Printer decorator for directives that accept null
  */
-class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer {
+class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer
+{
     /**
      * Printer being decorated
+     * @type HTMLPurifier_Printer
      */
     protected $obj;
+
     /**
-     * @param $obj Printer to decorate
+     * @param HTMLPurifier_Printer $obj Printer to decorate
      */
-    public function __construct($obj) {
+    public function __construct($obj)
+    {
         parent::__construct();
         $this->obj = $obj;
     }
-    public function render($ns, $directive, $value, $name, $config) {
+
+    /**
+     * @param string $ns
+     * @param string $directive
+     * @param string $value
+     * @param string $name
+     * @param HTMLPurifier_Config|array $config
+     * @return string
+     */
+    public function render($ns, $directive, $value, $name, $config)
+    {
         if (is_array($config) && isset($config[0])) {
             $gen_config = $config[0];
             $config = $config[1];
@@ -215,15 +251,19 @@ class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer
             'type' => 'checkbox',
             'value' => '1',
             'class' => 'null-toggle',
-            'name' => "$name"."[Null_$ns.$directive]",
+            'name' => "$name" . "[Null_$ns.$directive]",
             'id' => "$name:Null_$ns.$directive",
             'onclick' => "toggleWriteability('$name:$ns.$directive',checked)" // INLINE JAVASCRIPT!!!!
         );
         if ($this->obj instanceof HTMLPurifier_Printer_ConfigForm_bool) {
             // modify inline javascript slightly
-            $attr['onclick'] = "toggleWriteability('$name:Yes_$ns.$directive',checked);toggleWriteability('$name:No_$ns.$directive',checked)";
+            $attr['onclick'] =
+                "toggleWriteability('$name:Yes_$ns.$directive',checked);" .
+                "toggleWriteability('$name:No_$ns.$directive',checked)";
+        }
+        if ($value === null) {
+            $attr['checked'] = 'checked';
         }
-        if ($value === null) $attr['checked'] = 'checked';
         $ret .= $this->elementEmpty('input', $attr);
         $ret .= $this->text(' or ');
         $ret .= $this->elementEmpty('br');
@@ -235,10 +275,28 @@ class HTMLPurifier_Printer_ConfigForm_NullDecorator extends HTMLPurifier_Printer
 /**
  * Swiss-army knife configuration form field printer
  */
-class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
+class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer
+{
+    /**
+     * @type int
+     */
     public $cols = 18;
+
+    /**
+     * @type int
+     */
     public $rows = 5;
-    public function render($ns, $directive, $value, $name, $config) {
+
+    /**
+     * @param string $ns
+     * @param string $directive
+     * @param string $value
+     * @param string $name
+     * @param HTMLPurifier_Config|array $config
+     * @return string
+     */
+    public function render($ns, $directive, $value, $name, $config)
+    {
         if (is_array($config) && isset($config[0])) {
             $gen_config = $config[0];
             $config = $config[1];
@@ -262,6 +320,7 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
                     foreach ($array as $val => $b) {
                         $value[] = $val;
                     }
+                    //TODO does this need a break?
                 case HTMLPurifier_VarParser::ALIST:
                     $value = implode(PHP_EOL, $value);
                     break;
@@ -281,25 +340,27 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
             $value = serialize($value);
         }
         $attr = array(
-            'name' => "$name"."[$ns.$directive]",
+            'name' => "$name" . "[$ns.$directive]",
             'id' => "$name:$ns.$directive"
         );
-        if ($value === null) $attr['disabled'] = 'disabled';
+        if ($value === null) {
+            $attr['disabled'] = 'disabled';
+        }
         if (isset($def->allowed)) {
             $ret .= $this->start('select', $attr);
             foreach ($def->allowed as $val => $b) {
                 $attr = array();
-                if ($value == $val) $attr['selected'] = 'selected';
+                if ($value == $val) {
+                    $attr['selected'] = 'selected';
+                }
                 $ret .= $this->element('option', $val, $attr);
             }
             $ret .= $this->end('select');
-        } elseif (
-            $type === HTMLPurifier_VarParser::TEXT ||
-            $type === HTMLPurifier_VarParser::ITEXT ||
-            $type === HTMLPurifier_VarParser::ALIST ||
-            $type === HTMLPurifier_VarParser::HASH ||
-            $type === HTMLPurifier_VarParser::LOOKUP
-        ) {
+        } elseif ($type === HTMLPurifier_VarParser::TEXT ||
+                $type === HTMLPurifier_VarParser::ITEXT ||
+                $type === HTMLPurifier_VarParser::ALIST ||
+                $type === HTMLPurifier_VarParser::HASH ||
+                $type === HTMLPurifier_VarParser::LOOKUP) {
             $attr['cols'] = $this->cols;
             $attr['rows'] = $this->rows;
             $ret .= $this->start('textarea', $attr);
@@ -317,8 +378,18 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer {
 /**
  * Bool form field printer
  */
-class HTMLPurifier_Printer_ConfigForm_bool extends HTMLPurifier_Printer {
-    public function render($ns, $directive, $value, $name, $config) {
+class HTMLPurifier_Printer_ConfigForm_bool extends HTMLPurifier_Printer
+{
+    /**
+     * @param string $ns
+     * @param string $directive
+     * @param string $value
+     * @param string $name
+     * @param HTMLPurifier_Config|array $config
+     * @return string
+     */
+    public function render($ns, $directive, $value, $name, $config)
+    {
         if (is_array($config) && isset($config[0])) {
             $gen_config = $config[0];
             $config = $config[1];
@@ -336,12 +407,16 @@ class HTMLPurifier_Printer_ConfigForm_bool extends HTMLPurifier_Printer {
 
         $attr = array(
             'type' => 'radio',
-            'name' => "$name"."[$ns.$directive]",
+            'name' => "$name" . "[$ns.$directive]",
             'id' => "$name:Yes_$ns.$directive",
             'value' => '1'
         );
-        if ($value === true) $attr['checked'] = 'checked';
-        if ($value === null) $attr['disabled'] = 'disabled';
+        if ($value === true) {
+            $attr['checked'] = 'checked';
+        }
+        if ($value === null) {
+            $attr['disabled'] = 'disabled';
+        }
         $ret .= $this->elementEmpty('input', $attr);
 
         $ret .= $this->start('label', array('for' => "$name:No_$ns.$directive"));
@@ -351,12 +426,16 @@ class HTMLPurifier_Printer_ConfigForm_bool extends HTMLPurifier_Printer {
 
         $attr = array(
             'type' => 'radio',
-            'name' => "$name"."[$ns.$directive]",
+            'name' => "$name" . "[$ns.$directive]",
             'id' => "$name:No_$ns.$directive",
             'value' => '0'
         );
-        if ($value === false) $attr['checked'] = 'checked';
-        if ($value === null) $attr['disabled'] = 'disabled';
+        if ($value === false) {
+            $attr['checked'] = 'checked';
+        }
+        if ($value === null) {
+            $attr['disabled'] = 'disabled';
+        }
         $ret .= $this->elementEmpty('input', $attr);
 
         $ret .= $this->end('div');
diff --git a/library/HTMLPurifier/Printer/HTMLDefinition.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/HTMLDefinition.php
similarity index 53%
rename from library/HTMLPurifier/Printer/HTMLDefinition.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/HTMLDefinition.php
index 8a8f126b81..5f2f2f8a7c 100644
--- a/library/HTMLPurifier/Printer/HTMLDefinition.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Printer/HTMLDefinition.php
@@ -4,11 +4,16 @@ class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
 {
 
     /**
-     * Instance of HTMLPurifier_HTMLDefinition, for easy access
+     * @type HTMLPurifier_HTMLDefinition, for easy access
      */
     protected $def;
 
-    public function render($config) {
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return string
+     */
+    public function render($config)
+    {
         $ret = '';
         $this->config =& $config;
 
@@ -28,8 +33,10 @@ class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
 
     /**
      * Renders the Doctype table
+     * @return string
      */
-    protected function renderDoctype() {
+    protected function renderDoctype()
+    {
         $doctype = $this->def->doctype;
         $ret = '';
         $ret .= $this->start('table');
@@ -45,8 +52,10 @@ class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
 
     /**
      * Renders environment table, which is miscellaneous info
+     * @return string
      */
-    protected function renderEnvironment() {
+    protected function renderEnvironment()
+    {
         $def = $this->def;
 
         $ret = '';
@@ -59,28 +68,28 @@ class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
         $ret .= $this->row('Block wrap name', $def->info_block_wrapper);
 
         $ret .= $this->start('tr');
-            $ret .= $this->element('th', 'Global attributes');
-            $ret .= $this->element('td', $this->listifyAttr($def->info_global_attr),0,0);
+        $ret .= $this->element('th', 'Global attributes');
+        $ret .= $this->element('td', $this->listifyAttr($def->info_global_attr), null, 0);
         $ret .= $this->end('tr');
 
         $ret .= $this->start('tr');
-            $ret .= $this->element('th', 'Tag transforms');
-            $list = array();
-            foreach ($def->info_tag_transform as $old => $new) {
-                $new = $this->getClass($new, 'TagTransform_');
-                $list[] = "<$old> with $new";
-            }
-            $ret .= $this->element('td', $this->listify($list));
+        $ret .= $this->element('th', 'Tag transforms');
+        $list = array();
+        foreach ($def->info_tag_transform as $old => $new) {
+            $new = $this->getClass($new, 'TagTransform_');
+            $list[] = "<$old> with $new";
+        }
+        $ret .= $this->element('td', $this->listify($list));
         $ret .= $this->end('tr');
 
         $ret .= $this->start('tr');
-            $ret .= $this->element('th', 'Pre-AttrTransform');
-            $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_pre));
+        $ret .= $this->element('th', 'Pre-AttrTransform');
+        $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_pre));
         $ret .= $this->end('tr');
 
         $ret .= $this->start('tr');
-            $ret .= $this->element('th', 'Post-AttrTransform');
-            $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_post));
+        $ret .= $this->element('th', 'Post-AttrTransform');
+        $ret .= $this->element('td', $this->listifyObjectList($def->info_attr_transform_post));
         $ret .= $this->end('tr');
 
         $ret .= $this->end('table');
@@ -89,8 +98,10 @@ class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
 
     /**
      * Renders the Content Sets table
+     * @return string
      */
-    protected function renderContentSets() {
+    protected function renderContentSets()
+    {
         $ret = '';
         $ret .= $this->start('table');
         $ret .= $this->element('caption', 'Content Sets');
@@ -106,8 +117,10 @@ class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
 
     /**
      * Renders the Elements ($info) table
+     * @return string
      */
-    protected function renderInfo() {
+    protected function renderInfo()
+    {
         $ret = '';
         $ret .= $this->start('table');
         $ret .= $this->element('caption', 'Elements ($info)');
@@ -118,39 +131,39 @@ class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
         $ret .= $this->end('tr');
         foreach ($this->def->info as $name => $def) {
             $ret .= $this->start('tr');
-                $ret .= $this->element('th', "<$name>", array('class'=>'heavy', 'colspan' => 2));
+            $ret .= $this->element('th', "<$name>", array('class' => 'heavy', 'colspan' => 2));
             $ret .= $this->end('tr');
             $ret .= $this->start('tr');
-                $ret .= $this->element('th', 'Inline content');
-                $ret .= $this->element('td', $def->descendants_are_inline ? 'Yes' : 'No');
+            $ret .= $this->element('th', 'Inline content');
+            $ret .= $this->element('td', $def->descendants_are_inline ? 'Yes' : 'No');
             $ret .= $this->end('tr');
             if (!empty($def->excludes)) {
                 $ret .= $this->start('tr');
-                    $ret .= $this->element('th', 'Excludes');
-                    $ret .= $this->element('td', $this->listifyTagLookup($def->excludes));
+                $ret .= $this->element('th', 'Excludes');
+                $ret .= $this->element('td', $this->listifyTagLookup($def->excludes));
                 $ret .= $this->end('tr');
             }
             if (!empty($def->attr_transform_pre)) {
                 $ret .= $this->start('tr');
-                    $ret .= $this->element('th', 'Pre-AttrTransform');
-                    $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_pre));
+                $ret .= $this->element('th', 'Pre-AttrTransform');
+                $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_pre));
                 $ret .= $this->end('tr');
             }
             if (!empty($def->attr_transform_post)) {
                 $ret .= $this->start('tr');
-                    $ret .= $this->element('th', 'Post-AttrTransform');
-                    $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_post));
+                $ret .= $this->element('th', 'Post-AttrTransform');
+                $ret .= $this->element('td', $this->listifyObjectList($def->attr_transform_post));
                 $ret .= $this->end('tr');
             }
             if (!empty($def->auto_close)) {
                 $ret .= $this->start('tr');
-                    $ret .= $this->element('th', 'Auto closed by');
-                    $ret .= $this->element('td', $this->listifyTagLookup($def->auto_close));
+                $ret .= $this->element('th', 'Auto closed by');
+                $ret .= $this->element('td', $this->listifyTagLookup($def->auto_close));
                 $ret .= $this->end('tr');
             }
             $ret .= $this->start('tr');
-                $ret .= $this->element('th', 'Allowed attributes');
-                $ret .= $this->element('td',$this->listifyAttr($def->attr), array(), 0);
+            $ret .= $this->element('th', 'Allowed attributes');
+            $ret .= $this->element('td', $this->listifyAttr($def->attr), array(), 0);
             $ret .= $this->end('tr');
 
             if (!empty($def->required_attr)) {
@@ -165,64 +178,94 @@ class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
 
     /**
      * Renders a row describing the allowed children of an element
-     * @param $def HTMLPurifier_ChildDef of pertinent element
+     * @param HTMLPurifier_ChildDef $def HTMLPurifier_ChildDef of pertinent element
+     * @return string
      */
-    protected function renderChildren($def) {
+    protected function renderChildren($def)
+    {
         $context = new HTMLPurifier_Context();
         $ret = '';
         $ret .= $this->start('tr');
+        $elements = array();
+        $attr = array();
+        if (isset($def->elements)) {
+            if ($def->type == 'strictblockquote') {
+                $def->validateChildren(array(), $this->config, $context);
+            }
+            $elements = $def->elements;
+        }
+        if ($def->type == 'chameleon') {
+            $attr['rowspan'] = 2;
+        } elseif ($def->type == 'empty') {
             $elements = array();
-            $attr = array();
-            if (isset($def->elements)) {
-                if ($def->type == 'strictblockquote') {
-                    $def->validateChildren(array(), $this->config, $context);
-                }
-                $elements = $def->elements;
-            }
-            if ($def->type == 'chameleon') {
-                $attr['rowspan'] = 2;
-            } elseif ($def->type == 'empty') {
-                $elements = array();
-            } elseif ($def->type == 'table') {
-                $elements = array_flip(array('col', 'caption', 'colgroup', 'thead',
-                    'tfoot', 'tbody', 'tr'));
-            }
-            $ret .= $this->element('th', 'Allowed children', $attr);
+        } elseif ($def->type == 'table') {
+            $elements = array_flip(
+                array(
+                    'col',
+                    'caption',
+                    'colgroup',
+                    'thead',
+                    'tfoot',
+                    'tbody',
+                    'tr'
+                )
+            );
+        }
+        $ret .= $this->element('th', 'Allowed children', $attr);
 
-            if ($def->type == 'chameleon') {
+        if ($def->type == 'chameleon') {
 
-                $ret .= $this->element('td',
-                    '<em>Block</em>: ' .
-                    $this->escape($this->listifyTagLookup($def->block->elements)),0,0);
-                $ret .= $this->end('tr');
-                $ret .= $this->start('tr');
-                $ret .= $this->element('td',
-                    '<em>Inline</em>: ' .
-                    $this->escape($this->listifyTagLookup($def->inline->elements)),0,0);
+            $ret .= $this->element(
+                'td',
+                '<em>Block</em>: ' .
+                $this->escape($this->listifyTagLookup($def->block->elements)),
+                null,
+                0
+            );
+            $ret .= $this->end('tr');
+            $ret .= $this->start('tr');
+            $ret .= $this->element(
+                'td',
+                '<em>Inline</em>: ' .
+                $this->escape($this->listifyTagLookup($def->inline->elements)),
+                null,
+                0
+            );
 
-            } elseif ($def->type == 'custom') {
+        } elseif ($def->type == 'custom') {
 
-                $ret .= $this->element('td', '<em>'.ucfirst($def->type).'</em>: ' .
-                    $def->dtd_regex);
+            $ret .= $this->element(
+                'td',
+                '<em>' . ucfirst($def->type) . '</em>: ' .
+                $def->dtd_regex
+            );
 
-            } else {
-                $ret .= $this->element('td',
-                    '<em>'.ucfirst($def->type).'</em>: ' .
-                    $this->escape($this->listifyTagLookup($elements)),0,0);
-            }
+        } else {
+            $ret .= $this->element(
+                'td',
+                '<em>' . ucfirst($def->type) . '</em>: ' .
+                $this->escape($this->listifyTagLookup($elements)),
+                null,
+                0
+            );
+        }
         $ret .= $this->end('tr');
         return $ret;
     }
 
     /**
      * Listifies a tag lookup table.
-     * @param $array Tag lookup array in form of array('tagname' => true)
+     * @param array $array Tag lookup array in form of array('tagname' => true)
+     * @return string
      */
-    protected function listifyTagLookup($array) {
+    protected function listifyTagLookup($array)
+    {
         ksort($array);
         $list = array();
         foreach ($array as $name => $discard) {
-            if ($name !== '#PCDATA' && !isset($this->def->info[$name])) continue;
+            if ($name !== '#PCDATA' && !isset($this->def->info[$name])) {
+                continue;
+            }
             $list[] = $name;
         }
         return $this->listify($list);
@@ -230,13 +273,15 @@ class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
 
     /**
      * Listifies a list of objects by retrieving class names and internal state
-     * @param $array List of objects
+     * @param array $array List of objects
+     * @return string
      * @todo Also add information about internal state
      */
-    protected function listifyObjectList($array) {
+    protected function listifyObjectList($array)
+    {
         ksort($array);
         $list = array();
-        foreach ($array as $discard => $obj) {
+        foreach ($array as $obj) {
             $list[] = $this->getClass($obj, 'AttrTransform_');
         }
         return $this->listify($list);
@@ -244,13 +289,17 @@ class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
 
     /**
      * Listifies a hash of attributes to AttrDef classes
-     * @param $array Array hash in form of array('attrname' => HTMLPurifier_AttrDef)
+     * @param array $array Array hash in form of array('attrname' => HTMLPurifier_AttrDef)
+     * @return string
      */
-    protected function listifyAttr($array) {
+    protected function listifyAttr($array)
+    {
         ksort($array);
         $list = array();
         foreach ($array as $name => $obj) {
-            if ($obj === false) continue;
+            if ($obj === false) {
+                continue;
+            }
             $list[] = "$name&nbsp;=&nbsp;<i>" . $this->getClass($obj, 'AttrDef_') . '</i>';
         }
         return $this->listify($list);
@@ -258,15 +307,18 @@ class HTMLPurifier_Printer_HTMLDefinition extends HTMLPurifier_Printer
 
     /**
      * Creates a heavy header row
+     * @param string $text
+     * @param int $num
+     * @return string
      */
-    protected function heavyHeader($text, $num = 1) {
+    protected function heavyHeader($text, $num = 1)
+    {
         $ret = '';
         $ret .= $this->start('tr');
         $ret .= $this->element('th', $text, array('colspan' => $num, 'class' => 'heavy'));
         $ret .= $this->end('tr');
         return $ret;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/PropertyList.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/PropertyList.php
similarity index 50%
rename from library/HTMLPurifier/PropertyList.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/PropertyList.php
index 2b99fb7bc3..189348fd9e 100644
--- a/library/HTMLPurifier/PropertyList.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/PropertyList.php
@@ -6,61 +6,93 @@
 class HTMLPurifier_PropertyList
 {
     /**
-     * Internal data-structure for properties
+     * Internal data-structure for properties.
+     * @type array
      */
     protected $data = array();
 
     /**
-     * Parent plist
+     * Parent plist.
+     * @type HTMLPurifier_PropertyList
      */
     protected $parent;
 
+    /**
+     * Cache.
+     * @type array
+     */
     protected $cache;
 
-    public function __construct($parent = null) {
+    /**
+     * @param HTMLPurifier_PropertyList $parent Parent plist
+     */
+    public function __construct($parent = null)
+    {
         $this->parent = $parent;
     }
 
     /**
      * Recursively retrieves the value for a key
+     * @param string $name
+     * @throws HTMLPurifier_Exception
      */
-    public function get($name) {
-        if ($this->has($name)) return $this->data[$name];
+    public function get($name)
+    {
+        if ($this->has($name)) {
+            return $this->data[$name];
+        }
         // possible performance bottleneck, convert to iterative if necessary
-        if ($this->parent) return $this->parent->get($name);
+        if ($this->parent) {
+            return $this->parent->get($name);
+        }
         throw new HTMLPurifier_Exception("Key '$name' not found");
     }
 
     /**
      * Sets the value of a key, for this plist
+     * @param string $name
+     * @param mixed $value
      */
-    public function set($name, $value) {
+    public function set($name, $value)
+    {
         $this->data[$name] = $value;
     }
 
     /**
      * Returns true if a given key exists
+     * @param string $name
+     * @return bool
      */
-    public function has($name) {
+    public function has($name)
+    {
         return array_key_exists($name, $this->data);
     }
 
     /**
      * Resets a value to the value of it's parent, usually the default. If
      * no value is specified, the entire plist is reset.
+     * @param string $name
      */
-    public function reset($name = null) {
-        if ($name == null) $this->data = array();
-        else unset($this->data[$name]);
+    public function reset($name = null)
+    {
+        if ($name == null) {
+            $this->data = array();
+        } else {
+            unset($this->data[$name]);
+        }
     }
 
     /**
      * Squashes this property list and all of its property lists into a single
      * array, and returns the array. This value is cached by default.
-     * @param $force If true, ignores the cache and regenerates the array.
+     * @param bool $force If true, ignores the cache and regenerates the array.
+     * @return array
      */
-    public function squash($force = false) {
-        if ($this->cache !== null && !$force) return $this->cache;
+    public function squash($force = false)
+    {
+        if ($this->cache !== null && !$force) {
+            return $this->cache;
+        }
         if ($this->parent) {
             return $this->cache = array_merge($this->parent->squash($force), $this->data);
         } else {
@@ -70,15 +102,19 @@ class HTMLPurifier_PropertyList
 
     /**
      * Returns the parent plist.
+     * @return HTMLPurifier_PropertyList
      */
-    public function getParent() {
+    public function getParent()
+    {
         return $this->parent;
     }
 
     /**
      * Sets the parent plist.
+     * @param HTMLPurifier_PropertyList $plist Parent plist
      */
-    public function setParent($plist) {
+    public function setParent($plist)
+    {
         $this->parent = $plist;
     }
 }
diff --git a/library/HTMLPurifier/PropertyListIterator.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/PropertyListIterator.php
similarity index 60%
rename from library/HTMLPurifier/PropertyListIterator.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/PropertyListIterator.php
index 8f250443e4..15b330ea30 100644
--- a/library/HTMLPurifier/PropertyListIterator.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/PropertyListIterator.php
@@ -6,27 +6,37 @@
 class HTMLPurifier_PropertyListIterator extends FilterIterator
 {
 
+    /**
+     * @type int
+     */
     protected $l;
+    /**
+     * @type string
+     */
     protected $filter;
 
     /**
-     * @param $data Array of data to iterate over
-     * @param $filter Optional prefix to only allow values of
+     * @param Iterator $iterator Array of data to iterate over
+     * @param string $filter Optional prefix to only allow values of
      */
-    public function __construct(Iterator $iterator, $filter = null) {
+    public function __construct(Iterator $iterator, $filter = null)
+    {
         parent::__construct($iterator);
         $this->l = strlen($filter);
         $this->filter = $filter;
     }
 
-    public function accept() {
+    /**
+     * @return bool
+     */
+    public function accept()
+    {
         $key = $this->getInnerIterator()->key();
-        if( strncmp($key, $this->filter, $this->l) !== 0 ) {
+        if (strncmp($key, $this->filter, $this->l) !== 0) {
             return false;
         }
         return true;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Queue.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Queue.php
new file mode 100644
index 0000000000..f58db9042a
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Queue.php
@@ -0,0 +1,56 @@
+<?php
+
+/**
+ * A simple array-backed queue, based off of the classic Okasaki
+ * persistent amortized queue.  The basic idea is to maintain two
+ * stacks: an input stack and an output stack.  When the output
+ * stack runs out, reverse the input stack and use it as the output
+ * stack.
+ *
+ * We don't use the SPL implementation because it's only supported
+ * on PHP 5.3 and later.
+ *
+ * Exercise: Prove that push/pop on this queue take amortized O(1) time.
+ *
+ * Exercise: Extend this queue to be a deque, while preserving amortized
+ * O(1) time.  Some care must be taken on rebalancing to avoid quadratic
+ * behaviour caused by repeatedly shuffling data from the input stack
+ * to the output stack and back.
+ */
+class HTMLPurifier_Queue {
+    private $input;
+    private $output;
+
+    public function __construct($input = array()) {
+        $this->input = $input;
+        $this->output = array();
+    }
+
+    /**
+     * Shifts an element off the front of the queue.
+     */
+    public function shift() {
+        if (empty($this->output)) {
+            $this->output = array_reverse($this->input);
+            $this->input = array();
+        }
+        if (empty($this->output)) {
+            return NULL;
+        }
+        return array_pop($this->output);
+    }
+
+    /**
+     * Pushes an element onto the front of the queue.
+     */
+    public function push($x) {
+        array_push($this->input, $x);
+    }
+
+    /**
+     * Checks if it's empty.
+     */
+    public function isEmpty() {
+        return empty($this->input) && empty($this->output);
+    }
+}
diff --git a/library/HTMLPurifier/Strategy.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy.php
similarity index 66%
rename from library/HTMLPurifier/Strategy.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy.php
index 2462865210..e1ff3b72df 100644
--- a/library/HTMLPurifier/Strategy.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy.php
@@ -15,12 +15,12 @@ abstract class HTMLPurifier_Strategy
     /**
      * Executes the strategy on the tokens.
      *
-     * @param $tokens Array of HTMLPurifier_Token objects to be operated on.
-     * @param $config Configuration options
-     * @returns Processed array of token objects.
+     * @param HTMLPurifier_Token[] $tokens Array of HTMLPurifier_Token objects to be operated on.
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return HTMLPurifier_Token[] Processed array of token objects.
      */
     abstract public function execute($tokens, $config, $context);
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Strategy/Composite.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Composite.php
similarity index 61%
rename from library/HTMLPurifier/Strategy/Composite.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Composite.php
index 816490b799..d7d35ce7d1 100644
--- a/library/HTMLPurifier/Strategy/Composite.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Composite.php
@@ -8,18 +8,23 @@ abstract class HTMLPurifier_Strategy_Composite extends HTMLPurifier_Strategy
 
     /**
      * List of strategies to run tokens through.
+     * @type HTMLPurifier_Strategy[]
      */
     protected $strategies = array();
 
-    abstract public function __construct();
-
-    public function execute($tokens, $config, $context) {
+    /**
+     * @param HTMLPurifier_Token[] $tokens
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return HTMLPurifier_Token[]
+     */
+    public function execute($tokens, $config, $context)
+    {
         foreach ($this->strategies as $strategy) {
             $tokens = $strategy->execute($tokens, $config, $context);
         }
         return $tokens;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Strategy/Core.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Core.php
similarity index 92%
rename from library/HTMLPurifier/Strategy/Core.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Core.php
index d90e158606..4414c17d6e 100644
--- a/library/HTMLPurifier/Strategy/Core.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/Core.php
@@ -5,14 +5,13 @@
  */
 class HTMLPurifier_Strategy_Core extends HTMLPurifier_Strategy_Composite
 {
-
-    public function __construct() {
+    public function __construct()
+    {
         $this->strategies[] = new HTMLPurifier_Strategy_RemoveForeignElements();
         $this->strategies[] = new HTMLPurifier_Strategy_MakeWellFormed();
         $this->strategies[] = new HTMLPurifier_Strategy_FixNesting();
         $this->strategies[] = new HTMLPurifier_Strategy_ValidateAttributes();
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/FixNesting.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/FixNesting.php
new file mode 100644
index 0000000000..6fa673db9a
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/FixNesting.php
@@ -0,0 +1,181 @@
+<?php
+
+/**
+ * Takes a well formed list of tokens and fixes their nesting.
+ *
+ * HTML elements dictate which elements are allowed to be their children,
+ * for example, you can't have a p tag in a span tag.  Other elements have
+ * much more rigorous definitions: tables, for instance, require a specific
+ * order for their elements.  There are also constraints not expressible by
+ * document type definitions, such as the chameleon nature of ins/del
+ * tags and global child exclusions.
+ *
+ * The first major objective of this strategy is to iterate through all
+ * the nodes and determine whether or not their children conform to the
+ * element's definition.  If they do not, the child definition may
+ * optionally supply an amended list of elements that is valid or
+ * require that the entire node be deleted (and the previous node
+ * rescanned).
+ *
+ * The second objective is to ensure that explicitly excluded elements of
+ * an element do not appear in its children.  Code that accomplishes this
+ * task is pervasive through the strategy, though the two are distinct tasks
+ * and could, theoretically, be seperated (although it's not recommended).
+ *
+ * @note Whether or not unrecognized children are silently dropped or
+ *       translated into text depends on the child definitions.
+ *
+ * @todo Enable nodes to be bubbled out of the structure.  This is
+ *       easier with our new algorithm.
+ */
+
+class HTMLPurifier_Strategy_FixNesting extends HTMLPurifier_Strategy
+{
+
+    /**
+     * @param HTMLPurifier_Token[] $tokens
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array|HTMLPurifier_Token[]
+     */
+    public function execute($tokens, $config, $context)
+    {
+
+        //####################################################################//
+        // Pre-processing
+
+        // O(n) pass to convert to a tree, so that we can efficiently
+        // refer to substrings
+        $top_node = HTMLPurifier_Arborize::arborize($tokens, $config, $context);
+
+        // get a copy of the HTML definition
+        $definition = $config->getHTMLDefinition();
+
+        $excludes_enabled = !$config->get('Core.DisableExcludes');
+
+        // setup the context variable 'IsInline', for chameleon processing
+        // is 'false' when we are not inline, 'true' when it must always
+        // be inline, and an integer when it is inline for a certain
+        // branch of the document tree
+        $is_inline = $definition->info_parent_def->descendants_are_inline;
+        $context->register('IsInline', $is_inline);
+
+        // setup error collector
+        $e =& $context->get('ErrorCollector', true);
+
+        //####################################################################//
+        // Loop initialization
+
+        // stack that contains all elements that are excluded
+        // it is organized by parent elements, similar to $stack,
+        // but it is only populated when an element with exclusions is
+        // processed, i.e. there won't be empty exclusions.
+        $exclude_stack = array($definition->info_parent_def->excludes);
+
+        // variable that contains the start token while we are processing
+        // nodes. This enables error reporting to do its job
+        $node = $top_node;
+        // dummy token
+        list($token, $d) = $node->toTokenPair();
+        $context->register('CurrentNode', $node);
+        $context->register('CurrentToken', $token);
+
+        //####################################################################//
+        // Loop
+
+        // We need to implement a post-order traversal iteratively, to
+        // avoid running into stack space limits.  This is pretty tricky
+        // to reason about, so we just manually stack-ify the recursive
+        // variant:
+        //
+        //  function f($node) {
+        //      foreach ($node->children as $child) {
+        //          f($child);
+        //      }
+        //      validate($node);
+        //  }
+        //
+        // Thus, we will represent a stack frame as array($node,
+        // $is_inline, stack of children)
+        // e.g. array_reverse($node->children) - already processed
+        // children.
+
+        $parent_def = $definition->info_parent_def;
+        $stack = array(
+            array($top_node,
+                  $parent_def->descendants_are_inline,
+                  $parent_def->excludes, // exclusions
+                  0)
+            );
+
+        while (!empty($stack)) {
+            list($node, $is_inline, $excludes, $ix) = array_pop($stack);
+            // recursive call
+            $go = false;
+            $def = empty($stack) ? $definition->info_parent_def : $definition->info[$node->name];
+            while (isset($node->children[$ix])) {
+                $child = $node->children[$ix++];
+                if ($child instanceof HTMLPurifier_Node_Element) {
+                    $go = true;
+                    $stack[] = array($node, $is_inline, $excludes, $ix);
+                    $stack[] = array($child,
+                        // ToDo: I don't think it matters if it's def or
+                        // child_def, but double check this...
+                        $is_inline || $def->descendants_are_inline,
+                        empty($def->excludes) ? $excludes
+                                              : array_merge($excludes, $def->excludes),
+                        0);
+                    break;
+                }
+            };
+            if ($go) continue;
+            list($token, $d) = $node->toTokenPair();
+            // base case
+            if ($excludes_enabled && isset($excludes[$node->name])) {
+                $node->dead = true;
+                if ($e) $e->send(E_ERROR, 'Strategy_FixNesting: Node excluded');
+            } else {
+                // XXX I suppose it would be slightly more efficient to
+                // avoid the allocation here and have children
+                // strategies handle it
+                $children = array();
+                foreach ($node->children as $child) {
+                    if (!$child->dead) $children[] = $child;
+                }
+                $result = $def->child->validateChildren($children, $config, $context);
+                if ($result === true) {
+                    // nop
+                    $node->children = $children;
+                } elseif ($result === false) {
+                    $node->dead = true;
+                    if ($e) $e->send(E_ERROR, 'Strategy_FixNesting: Node removed');
+                } else {
+                    $node->children = $result;
+                    if ($e) {
+                        // XXX This will miss mutations of internal nodes. Perhaps defer to the child validators
+                        if (empty($result) && !empty($children)) {
+                            $e->send(E_ERROR, 'Strategy_FixNesting: Node contents removed');
+                        } else if ($result != $children) {
+                            $e->send(E_WARNING, 'Strategy_FixNesting: Node reorganized');
+                        }
+                    }
+                }
+            }
+        }
+
+        //####################################################################//
+        // Post-processing
+
+        // remove context variables
+        $context->destroy('IsInline');
+        $context->destroy('CurrentNode');
+        $context->destroy('CurrentToken');
+
+        //####################################################################//
+        // Return
+
+        return HTMLPurifier_Arborize::flatten($node, $config, $context);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Strategy/MakeWellFormed.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/MakeWellFormed.php
similarity index 52%
rename from library/HTMLPurifier/Strategy/MakeWellFormed.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/MakeWellFormed.php
index c736584007..e389e00116 100644
--- a/library/HTMLPurifier/Strategy/MakeWellFormed.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/MakeWellFormed.php
@@ -2,66 +2,97 @@
 
 /**
  * Takes tokens makes them well-formed (balance end tags, etc.)
+ *
+ * Specification of the armor attributes this strategy uses:
+ *
+ *      - MakeWellFormed_TagClosedError: This armor field is used to
+ *        suppress tag closed errors for certain tokens [TagClosedSuppress],
+ *        in particular, if a tag was generated automatically by HTML
+ *        Purifier, we may rely on our infrastructure to close it for us
+ *        and shouldn't report an error to the user [TagClosedAuto].
  */
 class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
 {
 
     /**
      * Array stream of tokens being processed.
+     * @type HTMLPurifier_Token[]
      */
     protected $tokens;
 
     /**
-     * Current index in $tokens.
+     * Current token.
+     * @type HTMLPurifier_Token
      */
-    protected $t;
+    protected $token;
+
+    /**
+     * Zipper managing the true state.
+     * @type HTMLPurifier_Zipper
+     */
+    protected $zipper;
 
     /**
      * Current nesting of elements.
+     * @type array
      */
     protected $stack;
 
     /**
      * Injectors active in this stream processing.
+     * @type HTMLPurifier_Injector[]
      */
     protected $injectors;
 
     /**
      * Current instance of HTMLPurifier_Config.
+     * @type HTMLPurifier_Config
      */
     protected $config;
 
     /**
      * Current instance of HTMLPurifier_Context.
+     * @type HTMLPurifier_Context
      */
     protected $context;
 
-    public function execute($tokens, $config, $context) {
-
+    /**
+     * @param HTMLPurifier_Token[] $tokens
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return HTMLPurifier_Token[]
+     * @throws HTMLPurifier_Exception
+     */
+    public function execute($tokens, $config, $context)
+    {
         $definition = $config->getHTMLDefinition();
 
         // local variables
         $generator = new HTMLPurifier_Generator($config, $context);
         $escape_invalid_tags = $config->get('Core.EscapeInvalidTags');
+        // used for autoclose early abortion
+        $global_parent_allowed_elements = $definition->info_parent_def->child->getAllowedElements($config);
         $e = $context->get('ErrorCollector', true);
-        $t = false; // token index
         $i = false; // injector index
-        $token      = false; // the current token
-        $reprocess  = false; // whether or not to reprocess the same token
+        list($zipper, $token) = HTMLPurifier_Zipper::fromArray($tokens);
+        if ($token === NULL) {
+            return array();
+        }
+        $reprocess = false; // whether or not to reprocess the same token
         $stack = array();
 
         // member variables
-        $this->stack   =& $stack;
-        $this->t       =& $t;
-        $this->tokens  =& $tokens;
-        $this->config  = $config;
+        $this->stack =& $stack;
+        $this->tokens =& $tokens;
+        $this->token =& $token;
+        $this->zipper =& $zipper;
+        $this->config = $config;
         $this->context = $context;
 
         // context variables
         $context->register('CurrentNesting', $stack);
-        $context->register('InputIndex',     $t);
-        $context->register('InputTokens',    $tokens);
-        $context->register('CurrentToken',   $token);
+        $context->register('InputZipper', $zipper);
+        $context->register('CurrentToken', $token);
 
         // -- begin INJECTOR --
 
@@ -73,9 +104,13 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
         unset($injectors['Custom']); // special case
         foreach ($injectors as $injector => $b) {
             // XXX: Fix with a legitimate lookup table of enabled filters
-            if (strpos($injector, '.') !== false) continue;
+            if (strpos($injector, '.') !== false) {
+                continue;
+            }
             $injector = "HTMLPurifier_Injector_$injector";
-            if (!$b) continue;
+            if (!$b) {
+                continue;
+            }
             $this->injectors[] = new $injector;
         }
         foreach ($def_injectors as $injector) {
@@ -83,7 +118,9 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
             $this->injectors[] = $injector;
         }
         foreach ($custom_injectors as $injector) {
-            if (!$injector) continue;
+            if (!$injector) {
+                continue;
+            }
             if (is_string($injector)) {
                 $injector = "HTMLPurifier_Injector_$injector";
                 $injector = new $injector;
@@ -95,14 +132,16 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
         // variables for performance reasons
         foreach ($this->injectors as $ix => $injector) {
             $error = $injector->prepare($config, $context);
-            if (!$error) continue;
+            if (!$error) {
+                continue;
+            }
             array_splice($this->injectors, $ix, 1); // rm the injector
             trigger_error("Cannot enable {$injector->name} injector because $error is not allowed", E_USER_WARNING);
         }
 
         // -- end INJECTOR --
 
-        // a note on punting:
+        // a note on reprocessing:
         //      In order to reduce code duplication, whenever some code needs
         //      to make HTML changes in order to make things "correct", the
         //      new HTML gets sent through the purifier, regardless of its
@@ -111,70 +150,75 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
         //      punt ($reprocess = true; continue;) and it does that for us.
 
         // isset is in loop because $tokens size changes during loop exec
-        for (
-            $t = 0;
-            $t == 0 || isset($tokens[$t - 1]);
-            // only increment if we don't need to reprocess
-            $reprocess ? $reprocess = false : $t++
-        ) {
+        for (;;
+             // only increment if we don't need to reprocess
+             $reprocess ? $reprocess = false : $token = $zipper->next($token)) {
 
             // check for a rewind
-            if (is_int($i) && $i >= 0) {
+            if (is_int($i)) {
                 // possibility: disable rewinding if the current token has a
                 // rewind set on it already. This would offer protection from
                 // infinite loop, but might hinder some advanced rewinding.
-                $rewind_to = $this->injectors[$i]->getRewind();
-                if (is_int($rewind_to) && $rewind_to < $t) {
-                    if ($rewind_to < 0) $rewind_to = 0;
-                    while ($t > $rewind_to) {
-                        $t--;
-                        $prev = $tokens[$t];
+                $rewind_offset = $this->injectors[$i]->getRewindOffset();
+                if (is_int($rewind_offset)) {
+                    for ($j = 0; $j < $rewind_offset; $j++) {
+                        if (empty($zipper->front)) break;
+                        $token = $zipper->prev($token);
                         // indicate that other injectors should not process this token,
                         // but we need to reprocess it
-                        unset($prev->skip[$i]);
-                        $prev->rewind = $i;
-                        if ($prev instanceof HTMLPurifier_Token_Start) array_pop($this->stack);
-                        elseif ($prev instanceof HTMLPurifier_Token_End) $this->stack[] = $prev->start;
+                        unset($token->skip[$i]);
+                        $token->rewind = $i;
+                        if ($token instanceof HTMLPurifier_Token_Start) {
+                            array_pop($this->stack);
+                        } elseif ($token instanceof HTMLPurifier_Token_End) {
+                            $this->stack[] = $token->start;
+                        }
                     }
                 }
                 $i = false;
             }
 
             // handle case of document end
-            if (!isset($tokens[$t])) {
+            if ($token === NULL) {
                 // kill processing if stack is empty
-                if (empty($this->stack)) break;
+                if (empty($this->stack)) {
+                    break;
+                }
 
                 // peek
                 $top_nesting = array_pop($this->stack);
                 $this->stack[] = $top_nesting;
 
-                // send error
+                // send error [TagClosedSuppress]
                 if ($e && !isset($top_nesting->armor['MakeWellFormed_TagClosedError'])) {
                     $e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag closed by document end', $top_nesting);
                 }
 
                 // append, don't splice, since this is the end
-                $tokens[] = new HTMLPurifier_Token_End($top_nesting->name);
+                $token = new HTMLPurifier_Token_End($top_nesting->name);
 
                 // punt!
                 $reprocess = true;
                 continue;
             }
 
-            $token = $tokens[$t];
-
-            //echo '<br>'; printTokens($tokens, $t); printTokens($this->stack);
+            //echo '<br>'; printZipper($zipper, $token);//printTokens($this->stack);
             //flush();
 
             // quick-check: if it's not a tag, no need to process
             if (empty($token->is_tag)) {
                 if ($token instanceof HTMLPurifier_Token_Text) {
                     foreach ($this->injectors as $i => $injector) {
-                        if (isset($token->skip[$i])) continue;
-                        if ($token->rewind !== null && $token->rewind !== $i) continue;
-                        $injector->handleText($token);
-                        $this->processToken($token, $i);
+                        if (isset($token->skip[$i])) {
+                            continue;
+                        }
+                        if ($token->rewind !== null && $token->rewind !== $i) {
+                            continue;
+                        }
+                        // XXX fuckup
+                        $r = $token;
+                        $injector->handleText($r);
+                        $token = $this->processToken($r, $i);
                         $reprocess = true;
                         break;
                     }
@@ -193,12 +237,22 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
             $ok = false;
             if ($type === 'empty' && $token instanceof HTMLPurifier_Token_Start) {
                 // claims to be a start tag but is empty
-                $token = new HTMLPurifier_Token_Empty($token->name, $token->attr);
+                $token = new HTMLPurifier_Token_Empty(
+                    $token->name,
+                    $token->attr,
+                    $token->line,
+                    $token->col,
+                    $token->armor
+                );
                 $ok = true;
             } elseif ($type && $type !== 'empty' && $token instanceof HTMLPurifier_Token_Empty) {
                 // claims to be empty but really is a start tag
-                $this->swap(new HTMLPurifier_Token_End($token->name));
-                $this->insertBefore(new HTMLPurifier_Token_Start($token->name, $token->attr));
+                // NB: this assignment is required
+                $old_token = $token;
+                $token = new HTMLPurifier_Token_End($token->name);
+                $token = $this->insertBefore(
+                    new HTMLPurifier_Token_Start($old_token->name, $old_token->attr, $old_token->line, $old_token->col, $old_token->armor)
+                );
                 // punt (since we had to modify the input stream in a non-trivial way)
                 $reprocess = true;
                 continue;
@@ -211,56 +265,97 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
                 // ...unless they also have to close their parent
                 if (!empty($this->stack)) {
 
+                    // Performance note: you might think that it's rather
+                    // inefficient, recalculating the autoclose information
+                    // for every tag that a token closes (since when we
+                    // do an autoclose, we push a new token into the
+                    // stream and then /process/ that, before
+                    // re-processing this token.)  But this is
+                    // necessary, because an injector can make an
+                    // arbitrary transformations to the autoclosing
+                    // tokens we introduce, so things may have changed
+                    // in the meantime.  Also, doing the inefficient thing is
+                    // "easy" to reason about (for certain perverse definitions
+                    // of "easy")
+
                     $parent = array_pop($this->stack);
                     $this->stack[] = $parent;
 
+                    $parent_def = null;
+                    $parent_elements = null;
+                    $autoclose = false;
                     if (isset($definition->info[$parent->name])) {
-                        $elements = $definition->info[$parent->name]->child->getAllowedElements($config);
-                        $autoclose = !isset($elements[$token->name]);
-                    } else {
-                        $autoclose = false;
+                        $parent_def = $definition->info[$parent->name];
+                        $parent_elements = $parent_def->child->getAllowedElements($config);
+                        $autoclose = !isset($parent_elements[$token->name]);
                     }
 
                     if ($autoclose && $definition->info[$token->name]->wrap) {
-                        // Check if an element can be wrapped by another 
-                        // element to make it valid in a context (for 
+                        // Check if an element can be wrapped by another
+                        // element to make it valid in a context (for
                         // example, <ul><ul> needs a <li> in between)
                         $wrapname = $definition->info[$token->name]->wrap;
                         $wrapdef = $definition->info[$wrapname];
                         $elements = $wrapdef->child->getAllowedElements($config);
-                        $parent_elements = $definition->info[$parent->name]->child->getAllowedElements($config);
                         if (isset($elements[$token->name]) && isset($parent_elements[$wrapname])) {
                             $newtoken = new HTMLPurifier_Token_Start($wrapname);
-                            $this->insertBefore($newtoken);
+                            $token = $this->insertBefore($newtoken);
                             $reprocess = true;
                             continue;
                         }
                     }
 
                     $carryover = false;
-                    if ($autoclose && $definition->info[$parent->name]->formatting) {
+                    if ($autoclose && $parent_def->formatting) {
                         $carryover = true;
                     }
 
                     if ($autoclose) {
-                        // errors need to be updated
-                        $new_token = new HTMLPurifier_Token_End($parent->name);
-                        $new_token->start = $parent;
-                        if ($carryover) {
-                            $element = clone $parent;
-                            $element->armor['MakeWellFormed_TagClosedError'] = true;
-                            $element->carryover = true;
-                            $this->processToken(array($new_token, $token, $element));
-                        } else {
-                            $this->insertBefore($new_token);
-                        }
-                        if ($e && !isset($parent->armor['MakeWellFormed_TagClosedError'])) {
-                            if (!$carryover) {
-                                $e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag auto closed', $parent);
-                            } else {
-                                $e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag carryover', $parent);
+                        // check if this autoclose is doomed to fail
+                        // (this rechecks $parent, which his harmless)
+                        $autoclose_ok = isset($global_parent_allowed_elements[$token->name]);
+                        if (!$autoclose_ok) {
+                            foreach ($this->stack as $ancestor) {
+                                $elements = $definition->info[$ancestor->name]->child->getAllowedElements($config);
+                                if (isset($elements[$token->name])) {
+                                    $autoclose_ok = true;
+                                    break;
+                                }
+                                if ($definition->info[$token->name]->wrap) {
+                                    $wrapname = $definition->info[$token->name]->wrap;
+                                    $wrapdef = $definition->info[$wrapname];
+                                    $wrap_elements = $wrapdef->child->getAllowedElements($config);
+                                    if (isset($wrap_elements[$token->name]) && isset($elements[$wrapname])) {
+                                        $autoclose_ok = true;
+                                        break;
+                                    }
+                                }
                             }
                         }
+                        if ($autoclose_ok) {
+                            // errors need to be updated
+                            $new_token = new HTMLPurifier_Token_End($parent->name);
+                            $new_token->start = $parent;
+                            // [TagClosedSuppress]
+                            if ($e && !isset($parent->armor['MakeWellFormed_TagClosedError'])) {
+                                if (!$carryover) {
+                                    $e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag auto closed', $parent);
+                                } else {
+                                    $e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag carryover', $parent);
+                                }
+                            }
+                            if ($carryover) {
+                                $element = clone $parent;
+                                // [TagClosedAuto]
+                                $element->armor['MakeWellFormed_TagClosedError'] = true;
+                                $element->carryover = true;
+                                $token = $this->processToken(array($new_token, $token, $element));
+                            } else {
+                                $token = $this->insertBefore($new_token);
+                            }
+                        } else {
+                            $token = $this->remove();
+                        }
                         $reprocess = true;
                         continue;
                     }
@@ -271,20 +366,26 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
 
             if ($ok) {
                 foreach ($this->injectors as $i => $injector) {
-                    if (isset($token->skip[$i])) continue;
-                    if ($token->rewind !== null && $token->rewind !== $i) continue;
-                    $injector->handleElement($token);
-                    $this->processToken($token, $i);
+                    if (isset($token->skip[$i])) {
+                        continue;
+                    }
+                    if ($token->rewind !== null && $token->rewind !== $i) {
+                        continue;
+                    }
+                    $r = $token;
+                    $injector->handleElement($r);
+                    $token = $this->processToken($r, $i);
                     $reprocess = true;
                     break;
                 }
                 if (!$reprocess) {
                     // ah, nothing interesting happened; do normal processing
-                    $this->swap($token);
                     if ($token instanceof HTMLPurifier_Token_Start) {
                         $this->stack[] = $token;
                     } elseif ($token instanceof HTMLPurifier_Token_End) {
-                        throw new HTMLPurifier_Exception('Improper handling of end tag in start code; possible error in MakeWellFormed');
+                        throw new HTMLPurifier_Exception(
+                            'Improper handling of end tag in start code; possible error in MakeWellFormed'
+                        );
                     }
                 }
                 continue;
@@ -298,13 +399,15 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
             // make sure that we have something open
             if (empty($this->stack)) {
                 if ($escape_invalid_tags) {
-                    if ($e) $e->send(E_WARNING, 'Strategy_MakeWellFormed: Unnecessary end tag to text');
-                    $this->swap(new HTMLPurifier_Token_Text(
-                        $generator->generateFromToken($token)
-                    ));
+                    if ($e) {
+                        $e->send(E_WARNING, 'Strategy_MakeWellFormed: Unnecessary end tag to text');
+                    }
+                    $token = new HTMLPurifier_Token_Text($generator->generateFromToken($token));
                 } else {
-                    $this->remove();
-                    if ($e) $e->send(E_WARNING, 'Strategy_MakeWellFormed: Unnecessary end tag removed');
+                    if ($e) {
+                        $e->send(E_WARNING, 'Strategy_MakeWellFormed: Unnecessary end tag removed');
+                    }
+                    $token = $this->remove();
                 }
                 $reprocess = true;
                 continue;
@@ -318,10 +421,15 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
             if ($current_parent->name == $token->name) {
                 $token->start = $current_parent;
                 foreach ($this->injectors as $i => $injector) {
-                    if (isset($token->skip[$i])) continue;
-                    if ($token->rewind !== null && $token->rewind !== $i) continue;
-                    $injector->handleEnd($token);
-                    $this->processToken($token, $i);
+                    if (isset($token->skip[$i])) {
+                        continue;
+                    }
+                    if ($token->rewind !== null && $token->rewind !== $i) {
+                        continue;
+                    }
+                    $r = $token;
+                    $injector->handleEnd($r);
+                    $token = $this->processToken($r, $i);
                     $this->stack[] = $current_parent;
                     $reprocess = true;
                     break;
@@ -349,13 +457,15 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
             // we didn't find the tag, so remove
             if ($skipped_tags === false) {
                 if ($escape_invalid_tags) {
-                    $this->swap(new HTMLPurifier_Token_Text(
-                        $generator->generateFromToken($token)
-                    ));
-                    if ($e) $e->send(E_WARNING, 'Strategy_MakeWellFormed: Stray end tag to text');
+                    if ($e) {
+                        $e->send(E_WARNING, 'Strategy_MakeWellFormed: Stray end tag to text');
+                    }
+                    $token = new HTMLPurifier_Token_Text($generator->generateFromToken($token));
                 } else {
-                    $this->remove();
-                    if ($e) $e->send(E_WARNING, 'Strategy_MakeWellFormed: Stray end tag removed');
+                    if ($e) {
+                        $e->send(E_WARNING, 'Strategy_MakeWellFormed: Stray end tag removed');
+                    }
+                    $token = $this->remove();
                 }
                 $reprocess = true;
                 continue;
@@ -366,7 +476,7 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
             if ($e) {
                 for ($j = $c - 1; $j > 0; $j--) {
                     // notice we exclude $j == 0, i.e. the current ending tag, from
-                    // the errors...
+                    // the errors... [TagClosedSuppress]
                     if (!isset($skipped_tags[$j]->armor['MakeWellFormed_TagClosedError'])) {
                         $e->send(E_NOTICE, 'Strategy_MakeWellFormed: Tag closed by element end', $skipped_tags[$j]);
                     }
@@ -381,24 +491,24 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
                 $new_token->start = $skipped_tags[$j];
                 array_unshift($replace, $new_token);
                 if (isset($definition->info[$new_token->name]) && $definition->info[$new_token->name]->formatting) {
+                    // [TagClosedAuto]
                     $element = clone $skipped_tags[$j];
                     $element->carryover = true;
                     $element->armor['MakeWellFormed_TagClosedError'] = true;
                     $replace[] = $element;
                 }
             }
-            $this->processToken($replace);
+            $token = $this->processToken($replace);
             $reprocess = true;
             continue;
         }
 
-        $context->destroy('CurrentNesting');
-        $context->destroy('InputTokens');
-        $context->destroy('InputIndex');
         $context->destroy('CurrentToken');
+        $context->destroy('CurrentNesting');
+        $context->destroy('InputZipper');
 
-        unset($this->injectors, $this->stack, $this->tokens, $this->t);
-        return $tokens;
+        unset($this->injectors, $this->stack, $this->tokens);
+        return $zipper->toArray($token);
     }
 
     /**
@@ -417,25 +527,38 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
      * If $token is an integer, that number of tokens (with the first token
      * being the current one) will be deleted.
      *
-     * @param $token Token substitution value
-     * @param $injector Injector that performed the substitution; default is if
+     * @param HTMLPurifier_Token|array|int|bool $token Token substitution value
+     * @param HTMLPurifier_Injector|int $injector Injector that performed the substitution; default is if
      *        this is not an injector related operation.
+     * @throws HTMLPurifier_Exception
      */
-    protected function processToken($token, $injector = -1) {
-
+    protected function processToken($token, $injector = -1)
+    {
         // normalize forms of token
-        if (is_object($token)) $token = array(1, $token);
-        if (is_int($token))    $token = array($token);
-        if ($token === false)  $token = array(1);
-        if (!is_array($token)) throw new HTMLPurifier_Exception('Invalid token type from injector');
-        if (!is_int($token[0])) array_unshift($token, 1);
-        if ($token[0] === 0) throw new HTMLPurifier_Exception('Deleting zero tokens is not valid');
+        if (is_object($token)) {
+            $token = array(1, $token);
+        }
+        if (is_int($token)) {
+            $token = array($token);
+        }
+        if ($token === false) {
+            $token = array(1);
+        }
+        if (!is_array($token)) {
+            throw new HTMLPurifier_Exception('Invalid token type from injector');
+        }
+        if (!is_int($token[0])) {
+            array_unshift($token, 1);
+        }
+        if ($token[0] === 0) {
+            throw new HTMLPurifier_Exception('Deleting zero tokens is not valid');
+        }
 
         // $token is now an array with the following form:
         // array(number nodes to delete, new node 1, new node 2, ...)
 
         $delete = array_shift($token);
-        $old = array_splice($this->tokens, $this->t, $delete, $token);
+        list($old, $r) = $this->zipper->splice($this->token, $delete, $token);
 
         if ($injector > -1) {
             // determine appropriate skips
@@ -446,30 +569,32 @@ class HTMLPurifier_Strategy_MakeWellFormed extends HTMLPurifier_Strategy
             }
         }
 
+        return $r;
+
     }
 
     /**
-     * Inserts a token before the current token. Cursor now points to this token
+     * Inserts a token before the current token. Cursor now points to
+     * this token.  You must reprocess after this.
+     * @param HTMLPurifier_Token $token
      */
-    private function insertBefore($token) {
-        array_splice($this->tokens, $this->t, 0, array($token));
+    private function insertBefore($token)
+    {
+        // NB not $this->zipper->insertBefore(), due to positioning
+        // differences
+        $splice = $this->zipper->splice($this->token, 0, array($token));
+
+        return $splice[1];
     }
 
     /**
      * Removes current token. Cursor now points to new token occupying previously
-     * occupied space.
+     * occupied space.  You must reprocess after this.
      */
-    private function remove() {
-        array_splice($this->tokens, $this->t, 1);
+    private function remove()
+    {
+        return $this->zipper->delete();
     }
-
-    /**
-     * Swap current token with new token. Cursor points to new token (no change).
-     */
-    private function swap($token) {
-        $this->tokens[$this->t] = $token;
-    }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Strategy/RemoveForeignElements.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/RemoveForeignElements.php
similarity index 64%
rename from library/HTMLPurifier/Strategy/RemoveForeignElements.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/RemoveForeignElements.php
index cf3a33e406..1a8149eccb 100644
--- a/library/HTMLPurifier/Strategy/RemoveForeignElements.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/RemoveForeignElements.php
@@ -11,19 +11,29 @@
 class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
 {
 
-    public function execute($tokens, $config, $context) {
+    /**
+     * @param HTMLPurifier_Token[] $tokens
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return array|HTMLPurifier_Token[]
+     */
+    public function execute($tokens, $config, $context)
+    {
         $definition = $config->getHTMLDefinition();
         $generator = new HTMLPurifier_Generator($config, $context);
         $result = array();
 
         $escape_invalid_tags = $config->get('Core.EscapeInvalidTags');
-        $remove_invalid_img  = $config->get('Core.RemoveInvalidImg');
+        $remove_invalid_img = $config->get('Core.RemoveInvalidImg');
 
         // currently only used to determine if comments should be kept
         $trusted = $config->get('HTML.Trusted');
+        $comment_lookup = $config->get('HTML.AllowedComments');
+        $comment_regexp = $config->get('HTML.AllowedCommentsRegexp');
+        $check_comments = $comment_lookup !== array() || $comment_regexp !== null;
 
         $remove_script_contents = $config->get('Core.RemoveScriptContents');
-        $hidden_elements     = $config->get('Core.HiddenElements');
+        $hidden_elements = $config->get('Core.HiddenElements');
 
         // remove script contents compatibility
         if ($remove_script_contents === true) {
@@ -48,34 +58,31 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
             $e =& $context->get('ErrorCollector');
         }
 
-        foreach($tokens as $token) {
+        foreach ($tokens as $token) {
             if ($remove_until) {
                 if (empty($token->is_tag) || $token->name !== $remove_until) {
                     continue;
                 }
             }
-            if (!empty( $token->is_tag )) {
+            if (!empty($token->is_tag)) {
                 // DEFINITION CALL
 
                 // before any processing, try to transform the element
-                if (
-                    isset($definition->info_tag_transform[$token->name])
-                ) {
+                if (isset($definition->info_tag_transform[$token->name])) {
                     $original_name = $token->name;
                     // there is a transformation for this tag
                     // DEFINITION CALL
                     $token = $definition->
-                                info_tag_transform[$token->name]->
-                                    transform($token, $config, $context);
-                    if ($e) $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Tag transform', $original_name);
+                        info_tag_transform[$token->name]->transform($token, $config, $context);
+                    if ($e) {
+                        $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Tag transform', $original_name);
+                    }
                 }
 
                 if (isset($definition->info[$token->name])) {
-
                     // mostly everything's good, but
                     // we need to make sure required attributes are in order
-                    if (
-                        ($token instanceof HTMLPurifier_Token_Start || $token instanceof HTMLPurifier_Token_Empty) &&
+                    if (($token instanceof HTMLPurifier_Token_Start || $token instanceof HTMLPurifier_Token_Empty) &&
                         $definition->info[$token->name]->required_attr &&
                         ($token->name != 'img' || $remove_invalid_img) // ensure config option still works
                     ) {
@@ -88,7 +95,13 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
                             }
                         }
                         if (!$ok) {
-                            if ($e) $e->send(E_ERROR, 'Strategy_RemoveForeignElements: Missing required attribute', $name);
+                            if ($e) {
+                                $e->send(
+                                    E_ERROR,
+                                    'Strategy_RemoveForeignElements: Missing required attribute',
+                                    $name
+                                );
+                            }
                             continue;
                         }
                         $token->armor['ValidateAttributes'] = true;
@@ -102,7 +115,9 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
 
                 } elseif ($escape_invalid_tags) {
                     // invalid tag, generate HTML representation and insert in
-                    if ($e) $e->send(E_WARNING, 'Strategy_RemoveForeignElements: Foreign element to text');
+                    if ($e) {
+                        $e->send(E_WARNING, 'Strategy_RemoveForeignElements: Foreign element to text');
+                    }
                     $token = new HTMLPurifier_Token_Text(
                         $generator->generateFromToken($token)
                     );
@@ -117,9 +132,13 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
                         } else {
                             $remove_until = false;
                         }
-                        if ($e) $e->send(E_ERROR, 'Strategy_RemoveForeignElements: Foreign meta element removed');
+                        if ($e) {
+                            $e->send(E_ERROR, 'Strategy_RemoveForeignElements: Foreign meta element removed');
+                        }
                     } else {
-                        if ($e) $e->send(E_ERROR, 'Strategy_RemoveForeignElements: Foreign element removed');
+                        if ($e) {
+                            $e->send(E_ERROR, 'Strategy_RemoveForeignElements: Foreign element removed');
+                        }
                     }
                     continue;
                 }
@@ -128,26 +147,46 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
                 if ($textify_comments !== false) {
                     $data = $token->data;
                     $token = new HTMLPurifier_Token_Text($data);
-                } elseif ($trusted) {
-                    // keep, but perform comment cleaning
+                } elseif ($trusted || $check_comments) {
+                    // always cleanup comments
+                    $trailing_hyphen = false;
                     if ($e) {
                         // perform check whether or not there's a trailing hyphen
                         if (substr($token->data, -1) == '-') {
-                            $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Trailing hyphen in comment removed');
+                            $trailing_hyphen = true;
                         }
                     }
                     $token->data = rtrim($token->data, '-');
                     $found_double_hyphen = false;
                     while (strpos($token->data, '--') !== false) {
-                        if ($e && !$found_double_hyphen) {
-                            $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Hyphens in comment collapsed');
-                        }
-                        $found_double_hyphen = true; // prevent double-erroring
+                        $found_double_hyphen = true;
                         $token->data = str_replace('--', '-', $token->data);
                     }
+                    if ($trusted || !empty($comment_lookup[trim($token->data)]) ||
+                        ($comment_regexp !== null && preg_match($comment_regexp, trim($token->data)))) {
+                        // OK good
+                        if ($e) {
+                            if ($trailing_hyphen) {
+                                $e->send(
+                                    E_NOTICE,
+                                    'Strategy_RemoveForeignElements: Trailing hyphen in comment removed'
+                                );
+                            }
+                            if ($found_double_hyphen) {
+                                $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Hyphens in comment collapsed');
+                            }
+                        }
+                    } else {
+                        if ($e) {
+                            $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Comment removed');
+                        }
+                        continue;
+                    }
                 } else {
                     // strip comments
-                    if ($e) $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Comment removed');
+                    if ($e) {
+                        $e->send(E_NOTICE, 'Strategy_RemoveForeignElements: Comment removed');
+                    }
                     continue;
                 }
             } elseif ($token instanceof HTMLPurifier_Token_Text) {
@@ -160,12 +199,9 @@ class HTMLPurifier_Strategy_RemoveForeignElements extends HTMLPurifier_Strategy
             // we removed tokens until the end, throw error
             $e->send(E_ERROR, 'Strategy_RemoveForeignElements: Token removed to end', $remove_until);
         }
-
         $context->destroy('CurrentToken');
-
         return $result;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Strategy/ValidateAttributes.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/ValidateAttributes.php
similarity index 65%
rename from library/HTMLPurifier/Strategy/ValidateAttributes.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/ValidateAttributes.php
index c3328a9d44..fbb3d27c81 100644
--- a/library/HTMLPurifier/Strategy/ValidateAttributes.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Strategy/ValidateAttributes.php
@@ -7,8 +7,14 @@
 class HTMLPurifier_Strategy_ValidateAttributes extends HTMLPurifier_Strategy
 {
 
-    public function execute($tokens, $config, $context) {
-
+    /**
+     * @param HTMLPurifier_Token[] $tokens
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return HTMLPurifier_Token[]
+     */
+    public function execute($tokens, $config, $context)
+    {
         // setup validator
         $validator = new HTMLPurifier_AttrValidator();
 
@@ -19,21 +25,21 @@ class HTMLPurifier_Strategy_ValidateAttributes extends HTMLPurifier_Strategy
 
             // only process tokens that have attributes,
             //   namely start and empty tags
-            if (!$token instanceof HTMLPurifier_Token_Start && !$token instanceof HTMLPurifier_Token_Empty) continue;
+            if (!$token instanceof HTMLPurifier_Token_Start && !$token instanceof HTMLPurifier_Token_Empty) {
+                continue;
+            }
 
             // skip tokens that are armored
-            if (!empty($token->armor['ValidateAttributes'])) continue;
+            if (!empty($token->armor['ValidateAttributes'])) {
+                continue;
+            }
 
             // note that we have no facilities here for removing tokens
             $validator->validateToken($token, $config, $context);
-
-            $tokens[$key] = $token; // for PHP 4
         }
         $context->destroy('CurrentToken');
-
         return $tokens;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/StringHash.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/StringHash.php
similarity index 75%
rename from library/HTMLPurifier/StringHash.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/StringHash.php
index 62085c5c2f..c07370197a 100644
--- a/library/HTMLPurifier/StringHash.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/StringHash.php
@@ -10,28 +10,36 @@
  */
 class HTMLPurifier_StringHash extends ArrayObject
 {
+    /**
+     * @type array
+     */
     protected $accessed = array();
 
     /**
      * Retrieves a value, and logs the access.
+     * @param mixed $index
+     * @return mixed
      */
-    public function offsetGet($index) {
+    public function offsetGet($index)
+    {
         $this->accessed[$index] = true;
         return parent::offsetGet($index);
     }
 
     /**
      * Returns a lookup array of all array indexes that have been accessed.
-     * @return Array in form array($index => true).
+     * @return array in form array($index => true).
      */
-    public function getAccessed() {
+    public function getAccessed()
+    {
         return $this->accessed;
     }
 
     /**
      * Resets the access array.
      */
-    public function resetAccessed() {
+    public function resetAccessed()
+    {
         $this->accessed = array();
     }
 }
diff --git a/library/HTMLPurifier/StringHashParser.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/StringHashParser.php
similarity index 73%
rename from library/HTMLPurifier/StringHashParser.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/StringHashParser.php
index f3e70c712f..7c73f80835 100644
--- a/library/HTMLPurifier/StringHashParser.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/StringHashParser.php
@@ -28,15 +28,25 @@
 class HTMLPurifier_StringHashParser
 {
 
+    /**
+     * @type string
+     */
     public $default = 'ID';
 
     /**
      * Parses a file that contains a single string-hash.
+     * @param string $file
+     * @return array
      */
-    public function parseFile($file) {
-        if (!file_exists($file)) return false;
+    public function parseFile($file)
+    {
+        if (!file_exists($file)) {
+            return false;
+        }
         $fh = fopen($file, 'r');
-        if (!$fh) return false;
+        if (!$fh) {
+            return false;
+        }
         $ret = $this->parseHandle($fh);
         fclose($fh);
         return $ret;
@@ -44,12 +54,19 @@ class HTMLPurifier_StringHashParser
 
     /**
      * Parses a file that contains multiple string-hashes delimited by '----'
+     * @param string $file
+     * @return array
      */
-    public function parseMultiFile($file) {
-        if (!file_exists($file)) return false;
+    public function parseMultiFile($file)
+    {
+        if (!file_exists($file)) {
+            return false;
+        }
         $ret = array();
         $fh = fopen($file, 'r');
-        if (!$fh) return false;
+        if (!$fh) {
+            return false;
+        }
         while (!feof($fh)) {
             $ret[] = $this->parseHandle($fh);
         }
@@ -62,26 +79,36 @@ class HTMLPurifier_StringHashParser
      * @note While it's possible to simulate in-memory parsing by using
      *       custom stream wrappers, if such a use-case arises we should
      *       factor out the file handle into its own class.
-     * @param $fh File handle with pointer at start of valid string-hash
+     * @param resource $fh File handle with pointer at start of valid string-hash
      *            block.
+     * @return array
      */
-    protected function parseHandle($fh) {
+    protected function parseHandle($fh)
+    {
         $state   = false;
         $single  = false;
         $ret     = array();
         do {
             $line = fgets($fh);
-            if ($line === false) break;
+            if ($line === false) {
+                break;
+            }
             $line = rtrim($line, "\n\r");
-            if (!$state && $line === '') continue;
-            if ($line === '----') break;
+            if (!$state && $line === '') {
+                continue;
+            }
+            if ($line === '----') {
+                break;
+            }
             if (strncmp('--#', $line, 3) === 0) {
                 // Comment
                 continue;
             } elseif (strncmp('--', $line, 2) === 0) {
                 // Multiline declaration
                 $state = trim($line, '- ');
-                if (!isset($ret[$state])) $ret[$state] = '';
+                if (!isset($ret[$state])) {
+                    $ret[$state] = '';
+                }
                 continue;
             } elseif (!$state) {
                 $single = true;
@@ -104,7 +131,6 @@ class HTMLPurifier_StringHashParser
         } while (!feof($fh));
         return $ret;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/TagTransform.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform.php
similarity index 62%
rename from library/HTMLPurifier/TagTransform.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform.php
index 210a447217..7b8d833433 100644
--- a/library/HTMLPurifier/TagTransform.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform.php
@@ -8,14 +8,15 @@ abstract class HTMLPurifier_TagTransform
 
     /**
      * Tag name to transform the tag to.
+     * @type string
      */
     public $transform_to;
 
     /**
      * Transforms the obsolete tag into the valid tag.
-     * @param $tag Tag to be transformed.
-     * @param $config Mandatory HTMLPurifier_Config object
-     * @param $context Mandatory HTMLPurifier_Context object
+     * @param HTMLPurifier_Token_Tag $tag Tag to be transformed.
+     * @param HTMLPurifier_Config $config Mandatory HTMLPurifier_Config object
+     * @param HTMLPurifier_Context $context Mandatory HTMLPurifier_Context object
      */
     abstract public function transform($tag, $config, $context);
 
@@ -23,14 +24,14 @@ abstract class HTMLPurifier_TagTransform
      * Prepends CSS properties to the style attribute, creating the
      * attribute if it doesn't exist.
      * @warning Copied over from AttrTransform, be sure to keep in sync
-     * @param $attr Attribute array to process (passed by reference)
-     * @param $css CSS to prepend
+     * @param array $attr Attribute array to process (passed by reference)
+     * @param string $css CSS to prepend
      */
-    protected function prependCSS(&$attr, $css) {
+    protected function prependCSS(&$attr, $css)
+    {
         $attr['style'] = isset($attr['style']) ? $attr['style'] : '';
         $attr['style'] = $css . $attr['style'];
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/TagTransform/Font.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Font.php
similarity index 71%
rename from library/HTMLPurifier/TagTransform/Font.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Font.php
index ed2463786d..7853d90bc6 100644
--- a/library/HTMLPurifier/TagTransform/Font.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Font.php
@@ -17,9 +17,14 @@
  */
 class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform
 {
-
+    /**
+     * @type string
+     */
     public $transform_to = 'span';
 
+    /**
+     * @type array
+     */
     protected $_size_lookup = array(
         '0' => 'xx-small',
         '1' => 'xx-small',
@@ -37,8 +42,14 @@ class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform
         '+4' => '300%'
     );
 
-    public function transform($tag, $config, $context) {
-
+    /**
+     * @param HTMLPurifier_Token_Tag $tag
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return HTMLPurifier_Token_End|string
+     */
+    public function transform($tag, $config, $context)
+    {
         if ($tag instanceof HTMLPurifier_Token_End) {
             $new_tag = clone $tag;
             $new_tag->name = $this->transform_to;
@@ -63,17 +74,25 @@ class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform
         // handle size transform
         if (isset($attr['size'])) {
             // normalize large numbers
-            if ($attr['size']{0} == '+' || $attr['size']{0} == '-') {
-                $size = (int) $attr['size'];
-                if ($size < -2) $attr['size'] = '-2';
-                if ($size > 4)  $attr['size'] = '+4';
-            } else {
-                $size = (int) $attr['size'];
-                if ($size > 7) $attr['size'] = '7';
+            if ($attr['size'] !== '') {
+                if ($attr['size']{0} == '+' || $attr['size']{0} == '-') {
+                    $size = (int)$attr['size'];
+                    if ($size < -2) {
+                        $attr['size'] = '-2';
+                    }
+                    if ($size > 4) {
+                        $attr['size'] = '+4';
+                    }
+                } else {
+                    $size = (int)$attr['size'];
+                    if ($size > 7) {
+                        $attr['size'] = '7';
+                    }
+                }
             }
             if (isset($this->_size_lookup[$attr['size']])) {
                 $prepend_style .= 'font-size:' .
-                  $this->_size_lookup[$attr['size']] . ';';
+                    $this->_size_lookup[$attr['size']] . ';';
             }
             unset($attr['size']);
         }
@@ -89,7 +108,6 @@ class HTMLPurifier_TagTransform_Font extends HTMLPurifier_TagTransform
         $new_tag->attr = $attr;
 
         return $new_tag;
-
     }
 }
 
diff --git a/library/HTMLPurifier/TagTransform/Simple.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Simple.php
similarity index 61%
rename from library/HTMLPurifier/TagTransform/Simple.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Simple.php
index 0e36130f25..71bf10b91f 100644
--- a/library/HTMLPurifier/TagTransform/Simple.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/TagTransform/Simple.php
@@ -7,19 +7,29 @@
  */
 class HTMLPurifier_TagTransform_Simple extends HTMLPurifier_TagTransform
 {
-
+    /**
+     * @type string
+     */
     protected $style;
 
     /**
-     * @param $transform_to Tag name to transform to.
-     * @param $style CSS style to add to the tag
+     * @param string $transform_to Tag name to transform to.
+     * @param string $style CSS style to add to the tag
      */
-    public function __construct($transform_to, $style = null) {
+    public function __construct($transform_to, $style = null)
+    {
         $this->transform_to = $transform_to;
         $this->style = $style;
     }
 
-    public function transform($tag, $config, $context) {
+    /**
+     * @param HTMLPurifier_Token_Tag $tag
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return string
+     */
+    public function transform($tag, $config, $context)
+    {
         $new_tag = clone $tag;
         $new_tag->name = $this->transform_to;
         if (!is_null($this->style) &&
@@ -29,7 +39,6 @@ class HTMLPurifier_TagTransform_Simple extends HTMLPurifier_TagTransform
         }
         return $new_tag;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Token.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token.php
new file mode 100644
index 0000000000..85b85e072d
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * Abstract base token class that all others inherit from.
+ */
+abstract class HTMLPurifier_Token
+{
+    /**
+     * Line number node was on in source document. Null if unknown.
+     * @type int
+     */
+    public $line;
+
+    /**
+     * Column of line node was on in source document. Null if unknown.
+     * @type int
+     */
+    public $col;
+
+    /**
+     * Lookup array of processing that this token is exempt from.
+     * Currently, valid values are "ValidateAttributes" and
+     * "MakeWellFormed_TagClosedError"
+     * @type array
+     */
+    public $armor = array();
+
+    /**
+     * Used during MakeWellFormed.
+     * @type
+     */
+    public $skip;
+
+    /**
+     * @type
+     */
+    public $rewind;
+
+    /**
+     * @type
+     */
+    public $carryover;
+
+    /**
+     * @param string $n
+     * @return null|string
+     */
+    public function __get($n)
+    {
+        if ($n === 'type') {
+            trigger_error('Deprecated type property called; use instanceof', E_USER_NOTICE);
+            switch (get_class($this)) {
+                case 'HTMLPurifier_Token_Start':
+                    return 'start';
+                case 'HTMLPurifier_Token_Empty':
+                    return 'empty';
+                case 'HTMLPurifier_Token_End':
+                    return 'end';
+                case 'HTMLPurifier_Token_Text':
+                    return 'text';
+                case 'HTMLPurifier_Token_Comment':
+                    return 'comment';
+                default:
+                    return null;
+            }
+        }
+    }
+
+    /**
+     * Sets the position of the token in the source document.
+     * @param int $l
+     * @param int $c
+     */
+    public function position($l = null, $c = null)
+    {
+        $this->line = $l;
+        $this->col = $c;
+    }
+
+    /**
+     * Convenience function for DirectLex settings line/col position.
+     * @param int $l
+     * @param int $c
+     */
+    public function rawPosition($l, $c)
+    {
+        if ($c === -1) {
+            $l++;
+        }
+        $this->line = $l;
+        $this->col = $c;
+    }
+
+    /**
+     * Converts a token into its corresponding node.
+     */
+    abstract public function toNode();
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Comment.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Comment.php
new file mode 100644
index 0000000000..23453c7052
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Comment.php
@@ -0,0 +1,38 @@
+<?php
+
+/**
+ * Concrete comment token class. Generally will be ignored.
+ */
+class HTMLPurifier_Token_Comment extends HTMLPurifier_Token
+{
+    /**
+     * Character data within comment.
+     * @type string
+     */
+    public $data;
+
+    /**
+     * @type bool
+     */
+    public $is_whitespace = true;
+
+    /**
+     * Transparent constructor.
+     *
+     * @param string $data String comment data.
+     * @param int $line
+     * @param int $col
+     */
+    public function __construct($data, $line = null, $col = null)
+    {
+        $this->data = $data;
+        $this->line = $line;
+        $this->col = $col;
+    }
+
+    public function toNode() {
+        return new HTMLPurifier_Node_Comment($this->data, $this->line, $this->col);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Token/Empty.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Empty.php
similarity index 54%
rename from library/HTMLPurifier/Token/Empty.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Empty.php
index 2a82b47ad1..78a95f5555 100644
--- a/library/HTMLPurifier/Token/Empty.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Empty.php
@@ -5,7 +5,11 @@
  */
 class HTMLPurifier_Token_Empty extends HTMLPurifier_Token_Tag
 {
-
+    public function toNode() {
+        $n = parent::toNode();
+        $n->empty = true;
+        return $n;
+    }
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Token/End.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/End.php
similarity index 58%
rename from library/HTMLPurifier/Token/End.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Token/End.php
index 353e79daf7..59b38fdc57 100644
--- a/library/HTMLPurifier/Token/End.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/End.php
@@ -10,10 +10,15 @@
 class HTMLPurifier_Token_End extends HTMLPurifier_Token_Tag
 {
     /**
-     * Token that started this node. Added by MakeWellFormed. Please
-     * do not edit this!
+     * Token that started this node.
+     * Added by MakeWellFormed. Please do not edit this!
+     * @type HTMLPurifier_Token
      */
     public $start;
+
+    public function toNode() {
+        throw new Exception("HTMLPurifier_Token_End->toNode not supported!");
+    }
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Token/Start.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Start.php
similarity index 99%
rename from library/HTMLPurifier/Token/Start.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Start.php
index e0e14fc624..019f317ada 100644
--- a/library/HTMLPurifier/Token/Start.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Start.php
@@ -5,7 +5,6 @@
  */
 class HTMLPurifier_Token_Start extends HTMLPurifier_Token_Tag
 {
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/Token/Tag.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Tag.php
similarity index 72%
rename from library/HTMLPurifier/Token/Tag.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Tag.php
index 798be028ee..d643fa64e2 100644
--- a/library/HTMLPurifier/Token/Tag.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Tag.php
@@ -3,13 +3,14 @@
 /**
  * Abstract class of a tag token (start, end or empty), and its behavior.
  */
-class HTMLPurifier_Token_Tag extends HTMLPurifier_Token
+abstract class HTMLPurifier_Token_Tag extends HTMLPurifier_Token
 {
     /**
      * Static bool marker that indicates the class is a tag.
      *
      * This allows us to check objects with <tt>!empty($obj->is_tag)</tt>
      * without having to use a function call <tt>is_a()</tt>.
+     * @type bool
      */
     public $is_tag = true;
 
@@ -19,21 +20,27 @@ class HTMLPurifier_Token_Tag extends HTMLPurifier_Token
      * @note Strictly speaking, XML tags are case sensitive, so we shouldn't
      * be lower-casing them, but these tokens cater to HTML tags, which are
      * insensitive.
+     * @type string
      */
     public $name;
 
     /**
      * Associative array of the tag's attributes.
+     * @type array
      */
     public $attr = array();
 
     /**
      * Non-overloaded constructor, which lower-cases passed tag name.
      *
-     * @param $name String name.
-     * @param $attr Associative array of attributes.
+     * @param string $name String name.
+     * @param array $attr Associative array of attributes.
+     * @param int $line
+     * @param int $col
+     * @param array $armor
      */
-    public function __construct($name, $attr = array(), $line = null, $col = null) {
+    public function __construct($name, $attr = array(), $line = null, $col = null, $armor = array())
+    {
         $this->name = ctype_lower($name) ? $name : strtolower($name);
         foreach ($attr as $key => $value) {
             // normalization only necessary when key is not lowercase
@@ -49,7 +56,12 @@ class HTMLPurifier_Token_Tag extends HTMLPurifier_Token
         }
         $this->attr = $attr;
         $this->line = $line;
-        $this->col  = $col;
+        $this->col = $col;
+        $this->armor = $armor;
+    }
+
+    public function toNode() {
+        return new HTMLPurifier_Node_Element($this->name, $this->attr, $this->line, $this->col, $this->armor);
     }
 }
 
diff --git a/library/HTMLPurifier/Token/Text.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Text.php
similarity index 54%
rename from library/HTMLPurifier/Token/Text.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Text.php
index 82efd823d6..f26a1c211b 100644
--- a/library/HTMLPurifier/Token/Text.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Token/Text.php
@@ -12,22 +12,42 @@
 class HTMLPurifier_Token_Text extends HTMLPurifier_Token
 {
 
-    public $name = '#PCDATA'; /**< PCDATA tag name compatible with DTD. */
-    public $data; /**< Parsed character data of text. */
-    public $is_whitespace; /**< Bool indicating if node is whitespace. */
+    /**
+     * @type string
+     */
+    public $name = '#PCDATA';
+    /**< PCDATA tag name compatible with DTD. */
+
+    /**
+     * @type string
+     */
+    public $data;
+    /**< Parsed character data of text. */
+
+    /**
+     * @type bool
+     */
+    public $is_whitespace;
+
+    /**< Bool indicating if node is whitespace. */
 
     /**
      * Constructor, accepts data and determines if it is whitespace.
-     *
-     * @param $data String parsed character data.
+     * @param string $data String parsed character data.
+     * @param int $line
+     * @param int $col
      */
-    public function __construct($data, $line = null, $col = null) {
+    public function __construct($data, $line = null, $col = null)
+    {
         $this->data = $data;
         $this->is_whitespace = ctype_space($data);
         $this->line = $line;
-        $this->col  = $col;
+        $this->col = $col;
     }
 
+    public function toNode() {
+        return new HTMLPurifier_Node_Text($this->data, $this->is_whitespace, $this->line, $this->col);
+    }
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/TokenFactory.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/TokenFactory.php
new file mode 100644
index 0000000000..dea2446b93
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/TokenFactory.php
@@ -0,0 +1,118 @@
+<?php
+
+/**
+ * Factory for token generation.
+ *
+ * @note Doing some benchmarking indicates that the new operator is much
+ *       slower than the clone operator (even discounting the cost of the
+ *       constructor).  This class is for that optimization.
+ *       Other then that, there's not much point as we don't
+ *       maintain parallel HTMLPurifier_Token hierarchies (the main reason why
+ *       you'd want to use an abstract factory).
+ * @todo Port DirectLex to use this
+ */
+class HTMLPurifier_TokenFactory
+{
+    // p stands for prototype
+
+    /**
+     * @type HTMLPurifier_Token_Start
+     */
+    private $p_start;
+
+    /**
+     * @type HTMLPurifier_Token_End
+     */
+    private $p_end;
+
+    /**
+     * @type HTMLPurifier_Token_Empty
+     */
+    private $p_empty;
+
+    /**
+     * @type HTMLPurifier_Token_Text
+     */
+    private $p_text;
+
+    /**
+     * @type HTMLPurifier_Token_Comment
+     */
+    private $p_comment;
+
+    /**
+     * Generates blank prototypes for cloning.
+     */
+    public function __construct()
+    {
+        $this->p_start = new HTMLPurifier_Token_Start('', array());
+        $this->p_end = new HTMLPurifier_Token_End('');
+        $this->p_empty = new HTMLPurifier_Token_Empty('', array());
+        $this->p_text = new HTMLPurifier_Token_Text('');
+        $this->p_comment = new HTMLPurifier_Token_Comment('');
+    }
+
+    /**
+     * Creates a HTMLPurifier_Token_Start.
+     * @param string $name Tag name
+     * @param array $attr Associative array of attributes
+     * @return HTMLPurifier_Token_Start Generated HTMLPurifier_Token_Start
+     */
+    public function createStart($name, $attr = array())
+    {
+        $p = clone $this->p_start;
+        $p->__construct($name, $attr);
+        return $p;
+    }
+
+    /**
+     * Creates a HTMLPurifier_Token_End.
+     * @param string $name Tag name
+     * @return HTMLPurifier_Token_End Generated HTMLPurifier_Token_End
+     */
+    public function createEnd($name)
+    {
+        $p = clone $this->p_end;
+        $p->__construct($name);
+        return $p;
+    }
+
+    /**
+     * Creates a HTMLPurifier_Token_Empty.
+     * @param string $name Tag name
+     * @param array $attr Associative array of attributes
+     * @return HTMLPurifier_Token_Empty Generated HTMLPurifier_Token_Empty
+     */
+    public function createEmpty($name, $attr = array())
+    {
+        $p = clone $this->p_empty;
+        $p->__construct($name, $attr);
+        return $p;
+    }
+
+    /**
+     * Creates a HTMLPurifier_Token_Text.
+     * @param string $data Data of text token
+     * @return HTMLPurifier_Token_Text Generated HTMLPurifier_Token_Text
+     */
+    public function createText($data)
+    {
+        $p = clone $this->p_text;
+        $p->__construct($data);
+        return $p;
+    }
+
+    /**
+     * Creates a HTMLPurifier_Token_Comment.
+     * @param string $data Data of comment token
+     * @return HTMLPurifier_Token_Comment Generated HTMLPurifier_Token_Comment
+     */
+    public function createComment($data)
+    {
+        $p = clone $this->p_comment;
+        $p->__construct($data);
+        return $p;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URI.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URI.php
new file mode 100644
index 0000000000..a5e7ae2984
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URI.php
@@ -0,0 +1,314 @@
+<?php
+
+/**
+ * HTML Purifier's internal representation of a URI.
+ * @note
+ *      Internal data-structures are completely escaped. If the data needs
+ *      to be used in a non-URI context (which is very unlikely), be sure
+ *      to decode it first. The URI may not necessarily be well-formed until
+ *      validate() is called.
+ */
+class HTMLPurifier_URI
+{
+    /**
+     * @type string
+     */
+    public $scheme;
+
+    /**
+     * @type string
+     */
+    public $userinfo;
+
+    /**
+     * @type string
+     */
+    public $host;
+
+    /**
+     * @type int
+     */
+    public $port;
+
+    /**
+     * @type string
+     */
+    public $path;
+
+    /**
+     * @type string
+     */
+    public $query;
+
+    /**
+     * @type string
+     */
+    public $fragment;
+
+    /**
+     * @param string $scheme
+     * @param string $userinfo
+     * @param string $host
+     * @param int $port
+     * @param string $path
+     * @param string $query
+     * @param string $fragment
+     * @note Automatically normalizes scheme and port
+     */
+    public function __construct($scheme, $userinfo, $host, $port, $path, $query, $fragment)
+    {
+        $this->scheme = is_null($scheme) || ctype_lower($scheme) ? $scheme : strtolower($scheme);
+        $this->userinfo = $userinfo;
+        $this->host = $host;
+        $this->port = is_null($port) ? $port : (int)$port;
+        $this->path = $path;
+        $this->query = $query;
+        $this->fragment = $fragment;
+    }
+
+    /**
+     * Retrieves a scheme object corresponding to the URI's scheme/default
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return HTMLPurifier_URIScheme Scheme object appropriate for validating this URI
+     */
+    public function getSchemeObj($config, $context)
+    {
+        $registry = HTMLPurifier_URISchemeRegistry::instance();
+        if ($this->scheme !== null) {
+            $scheme_obj = $registry->getScheme($this->scheme, $config, $context);
+            if (!$scheme_obj) {
+                return false;
+            } // invalid scheme, clean it out
+        } else {
+            // no scheme: retrieve the default one
+            $def = $config->getDefinition('URI');
+            $scheme_obj = $def->getDefaultScheme($config, $context);
+            if (!$scheme_obj) {
+                // something funky happened to the default scheme object
+                trigger_error(
+                    'Default scheme object "' . $def->defaultScheme . '" was not readable',
+                    E_USER_WARNING
+                );
+                return false;
+            }
+        }
+        return $scheme_obj;
+    }
+
+    /**
+     * Generic validation method applicable for all schemes. May modify
+     * this URI in order to get it into a compliant form.
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool True if validation/filtering succeeds, false if failure
+     */
+    public function validate($config, $context)
+    {
+        // ABNF definitions from RFC 3986
+        $chars_sub_delims = '!$&\'()*+,;=';
+        $chars_gen_delims = ':/?#[]@';
+        $chars_pchar = $chars_sub_delims . ':@';
+
+        // validate host
+        if (!is_null($this->host)) {
+            $host_def = new HTMLPurifier_AttrDef_URI_Host();
+            $this->host = $host_def->validate($this->host, $config, $context);
+            if ($this->host === false) {
+                $this->host = null;
+            }
+        }
+
+        // validate scheme
+        // NOTE: It's not appropriate to check whether or not this
+        // scheme is in our registry, since a URIFilter may convert a
+        // URI that we don't allow into one we do.  So instead, we just
+        // check if the scheme can be dropped because there is no host
+        // and it is our default scheme.
+        if (!is_null($this->scheme) && is_null($this->host) || $this->host === '') {
+            // support for relative paths is pretty abysmal when the
+            // scheme is present, so axe it when possible
+            $def = $config->getDefinition('URI');
+            if ($def->defaultScheme === $this->scheme) {
+                $this->scheme = null;
+            }
+        }
+
+        // validate username
+        if (!is_null($this->userinfo)) {
+            $encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . ':');
+            $this->userinfo = $encoder->encode($this->userinfo);
+        }
+
+        // validate port
+        if (!is_null($this->port)) {
+            if ($this->port < 1 || $this->port > 65535) {
+                $this->port = null;
+            }
+        }
+
+        // validate path
+        $segments_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/');
+        if (!is_null($this->host)) { // this catches $this->host === ''
+            // path-abempty (hier and relative)
+            // http://www.example.com/my/path
+            // //www.example.com/my/path (looks odd, but works, and
+            //                            recognized by most browsers)
+            // (this set is valid or invalid on a scheme by scheme
+            // basis, so we'll deal with it later)
+            // file:///my/path
+            // ///my/path
+            $this->path = $segments_encoder->encode($this->path);
+        } elseif ($this->path !== '') {
+            if ($this->path[0] === '/') {
+                // path-absolute (hier and relative)
+                // http:/my/path
+                // /my/path
+                if (strlen($this->path) >= 2 && $this->path[1] === '/') {
+                    // This could happen if both the host gets stripped
+                    // out
+                    // http://my/path
+                    // //my/path
+                    $this->path = '';
+                } else {
+                    $this->path = $segments_encoder->encode($this->path);
+                }
+            } elseif (!is_null($this->scheme)) {
+                // path-rootless (hier)
+                // http:my/path
+                // Short circuit evaluation means we don't need to check nz
+                $this->path = $segments_encoder->encode($this->path);
+            } else {
+                // path-noscheme (relative)
+                // my/path
+                // (once again, not checking nz)
+                $segment_nc_encoder = new HTMLPurifier_PercentEncoder($chars_sub_delims . '@');
+                $c = strpos($this->path, '/');
+                if ($c !== false) {
+                    $this->path =
+                        $segment_nc_encoder->encode(substr($this->path, 0, $c)) .
+                        $segments_encoder->encode(substr($this->path, $c));
+                } else {
+                    $this->path = $segment_nc_encoder->encode($this->path);
+                }
+            }
+        } else {
+            // path-empty (hier and relative)
+            $this->path = ''; // just to be safe
+        }
+
+        // qf = query and fragment
+        $qf_encoder = new HTMLPurifier_PercentEncoder($chars_pchar . '/?');
+
+        if (!is_null($this->query)) {
+            $this->query = $qf_encoder->encode($this->query);
+        }
+
+        if (!is_null($this->fragment)) {
+            $this->fragment = $qf_encoder->encode($this->fragment);
+        }
+        return true;
+    }
+
+    /**
+     * Convert URI back to string
+     * @return string URI appropriate for output
+     */
+    public function toString()
+    {
+        // reconstruct authority
+        $authority = null;
+        // there is a rendering difference between a null authority
+        // (http:foo-bar) and an empty string authority
+        // (http:///foo-bar).
+        if (!is_null($this->host)) {
+            $authority = '';
+            if (!is_null($this->userinfo)) {
+                $authority .= $this->userinfo . '@';
+            }
+            $authority .= $this->host;
+            if (!is_null($this->port)) {
+                $authority .= ':' . $this->port;
+            }
+        }
+
+        // Reconstruct the result
+        // One might wonder about parsing quirks from browsers after
+        // this reconstruction.  Unfortunately, parsing behavior depends
+        // on what *scheme* was employed (file:///foo is handled *very*
+        // differently than http:///foo), so unfortunately we have to
+        // defer to the schemes to do the right thing.
+        $result = '';
+        if (!is_null($this->scheme)) {
+            $result .= $this->scheme . ':';
+        }
+        if (!is_null($authority)) {
+            $result .= '//' . $authority;
+        }
+        $result .= $this->path;
+        if (!is_null($this->query)) {
+            $result .= '?' . $this->query;
+        }
+        if (!is_null($this->fragment)) {
+            $result .= '#' . $this->fragment;
+        }
+
+        return $result;
+    }
+
+    /**
+     * Returns true if this URL might be considered a 'local' URL given
+     * the current context.  This is true when the host is null, or
+     * when it matches the host supplied to the configuration.
+     *
+     * Note that this does not do any scheme checking, so it is mostly
+     * only appropriate for metadata that doesn't care about protocol
+     * security.  isBenign is probably what you actually want.
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function isLocal($config, $context)
+    {
+        if ($this->host === null) {
+            return true;
+        }
+        $uri_def = $config->getDefinition('URI');
+        if ($uri_def->host === $this->host) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if this URL should be considered a 'benign' URL,
+     * that is:
+     *
+     *      - It is a local URL (isLocal), and
+     *      - It has a equal or better level of security
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function isBenign($config, $context)
+    {
+        if (!$this->isLocal($config, $context)) {
+            return false;
+        }
+
+        $scheme_obj = $this->getSchemeObj($config, $context);
+        if (!$scheme_obj) {
+            return false;
+        } // conservative approach
+
+        $current_scheme_obj = $config->getDefinition('URI')->getDefaultScheme($config, $context);
+        if ($current_scheme_obj->secure) {
+            if (!$scheme_obj->secure) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIDefinition.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIDefinition.php
similarity index 70%
rename from library/HTMLPurifier/URIDefinition.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/URIDefinition.php
index ea2b8fe245..e0bd8bcca8 100644
--- a/library/HTMLPurifier/URIDefinition.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIDefinition.php
@@ -23,19 +23,24 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
      */
     public $defaultScheme;
 
-    public function __construct() {
+    public function __construct()
+    {
         $this->registerFilter(new HTMLPurifier_URIFilter_DisableExternal());
         $this->registerFilter(new HTMLPurifier_URIFilter_DisableExternalResources());
+        $this->registerFilter(new HTMLPurifier_URIFilter_DisableResources());
         $this->registerFilter(new HTMLPurifier_URIFilter_HostBlacklist());
+        $this->registerFilter(new HTMLPurifier_URIFilter_SafeIframe());
         $this->registerFilter(new HTMLPurifier_URIFilter_MakeAbsolute());
         $this->registerFilter(new HTMLPurifier_URIFilter_Munge());
     }
 
-    public function registerFilter($filter) {
+    public function registerFilter($filter)
+    {
         $this->registeredFilters[$filter->name] = $filter;
     }
 
-    public function addFilter($filter, $config) {
+    public function addFilter($filter, $config)
+    {
         $r = $filter->prepare($config);
         if ($r === false) return; // null is ok, for backwards compat
         if ($filter->post) {
@@ -45,22 +50,29 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
         }
     }
 
-    protected function doSetup($config) {
+    protected function doSetup($config)
+    {
         $this->setupMemberVariables($config);
         $this->setupFilters($config);
     }
 
-    protected function setupFilters($config) {
+    protected function setupFilters($config)
+    {
         foreach ($this->registeredFilters as $name => $filter) {
-            $conf = $config->get('URI.' . $name);
-            if ($conf !== false && $conf !== null) {
+            if ($filter->always_load) {
                 $this->addFilter($filter, $config);
+            } else {
+                $conf = $config->get('URI.' . $name);
+                if ($conf !== false && $conf !== null) {
+                    $this->addFilter($filter, $config);
+                }
             }
         }
         unset($this->registeredFilters);
     }
 
-    protected function setupMemberVariables($config) {
+    protected function setupMemberVariables($config)
+    {
         $this->host = $config->get('URI.Host');
         $base_uri = $config->get('URI.Base');
         if (!is_null($base_uri)) {
@@ -72,7 +84,13 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
         if (is_null($this->defaultScheme)) $this->defaultScheme = $config->get('URI.DefaultScheme');
     }
 
-    public function filter(&$uri, $config, $context) {
+    public function getDefaultScheme($config, $context)
+    {
+        return HTMLPurifier_URISchemeRegistry::instance()->getScheme($this->defaultScheme, $config, $context);
+    }
+
+    public function filter(&$uri, $config, $context)
+    {
         foreach ($this->filters as $name => $f) {
             $result = $f->filter($uri, $config, $context);
             if (!$result) return false;
@@ -80,7 +98,8 @@ class HTMLPurifier_URIDefinition extends HTMLPurifier_Definition
         return true;
     }
 
-    public function postFilter(&$uri, $config, $context) {
+    public function postFilter(&$uri, $config, $context)
+    {
         foreach ($this->postFilters as $name => $f) {
             $result = $f->filter($uri, $config, $context);
             if (!$result) return false;
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter.php
new file mode 100644
index 0000000000..09724e9f41
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * Chainable filters for custom URI processing.
+ *
+ * These filters can perform custom actions on a URI filter object,
+ * including transformation or blacklisting.  A filter named Foo
+ * must have a corresponding configuration directive %URI.Foo,
+ * unless always_load is specified to be true.
+ *
+ * The following contexts may be available while URIFilters are being
+ * processed:
+ *
+ *      - EmbeddedURI: true if URI is an embedded resource that will
+ *        be loaded automatically on page load
+ *      - CurrentToken: a reference to the token that is currently
+ *        being processed
+ *      - CurrentAttr: the name of the attribute that is currently being
+ *        processed
+ *      - CurrentCSSProperty: the name of the CSS property that is
+ *        currently being processed (if applicable)
+ *
+ * @warning This filter is called before scheme object validation occurs.
+ *          Make sure, if you require a specific scheme object, you
+ *          you check that it exists. This allows filters to convert
+ *          proprietary URI schemes into regular ones.
+ */
+abstract class HTMLPurifier_URIFilter
+{
+
+    /**
+     * Unique identifier of filter.
+     * @type string
+     */
+    public $name;
+
+    /**
+     * True if this filter should be run after scheme validation.
+     * @type bool
+     */
+    public $post = false;
+
+    /**
+     * True if this filter should always be loaded.
+     * This permits a filter to be named Foo without the corresponding
+     * %URI.Foo directive existing.
+     * @type bool
+     */
+    public $always_load = false;
+
+    /**
+     * Performs initialization for the filter.  If the filter returns
+     * false, this means that it shouldn't be considered active.
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function prepare($config)
+    {
+        return true;
+    }
+
+    /**
+     * Filter a URI object
+     * @param HTMLPurifier_URI $uri Reference to URI object variable
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool Whether or not to continue processing: false indicates
+     *         URL is no good, true indicates continue processing. Note that
+     *         all changes are committed directly on the URI object
+     */
+    abstract public function filter(&$uri, $config, $context);
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternal.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternal.php
new file mode 100644
index 0000000000..ced1b13763
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternal.php
@@ -0,0 +1,54 @@
+<?php
+
+class HTMLPurifier_URIFilter_DisableExternal extends HTMLPurifier_URIFilter
+{
+    /**
+     * @type string
+     */
+    public $name = 'DisableExternal';
+
+    /**
+     * @type array
+     */
+    protected $ourHostParts = false;
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return void
+     */
+    public function prepare($config)
+    {
+        $our_host = $config->getDefinition('URI')->host;
+        if ($our_host !== null) {
+            $this->ourHostParts = array_reverse(explode('.', $our_host));
+        }
+    }
+
+    /**
+     * @param HTMLPurifier_URI $uri Reference
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function filter(&$uri, $config, $context)
+    {
+        if (is_null($uri->host)) {
+            return true;
+        }
+        if ($this->ourHostParts === false) {
+            return false;
+        }
+        $host_parts = array_reverse(explode('.', $uri->host));
+        foreach ($this->ourHostParts as $i => $x) {
+            if (!isset($host_parts[$i])) {
+                return false;
+            }
+            if ($host_parts[$i] != $this->ourHostParts[$i]) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternalResources.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternalResources.php
new file mode 100644
index 0000000000..c6562169e0
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableExternalResources.php
@@ -0,0 +1,25 @@
+<?php
+
+class HTMLPurifier_URIFilter_DisableExternalResources extends HTMLPurifier_URIFilter_DisableExternal
+{
+    /**
+     * @type string
+     */
+    public $name = 'DisableExternalResources';
+
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function filter(&$uri, $config, $context)
+    {
+        if (!$context->get('EmbeddedURI', true)) {
+            return true;
+        }
+        return parent::filter($uri, $config, $context);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableResources.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableResources.php
new file mode 100644
index 0000000000..d5c412c444
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/DisableResources.php
@@ -0,0 +1,22 @@
+<?php
+
+class HTMLPurifier_URIFilter_DisableResources extends HTMLPurifier_URIFilter
+{
+    /**
+     * @type string
+     */
+    public $name = 'DisableResources';
+
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function filter(&$uri, $config, $context)
+    {
+        return !$context->get('EmbeddedURI', true);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/HostBlacklist.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/HostBlacklist.php
new file mode 100644
index 0000000000..a6645c17ee
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/HostBlacklist.php
@@ -0,0 +1,46 @@
+<?php
+
+// It's not clear to me whether or not Punycode means that hostnames
+// do not have canonical forms anymore. As far as I can tell, it's
+// not a problem (punycoding should be identity when no Unicode
+// points are involved), but I'm not 100% sure
+class HTMLPurifier_URIFilter_HostBlacklist extends HTMLPurifier_URIFilter
+{
+    /**
+     * @type string
+     */
+    public $name = 'HostBlacklist';
+
+    /**
+     * @type array
+     */
+    protected $blacklist = array();
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function prepare($config)
+    {
+        $this->blacklist = $config->get('URI.HostBlacklist');
+        return true;
+    }
+
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function filter(&$uri, $config, $context)
+    {
+        foreach ($this->blacklist as $blacklisted_host_fragment) {
+            if (strpos($uri->host, $blacklisted_host_fragment) !== false) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIFilter/MakeAbsolute.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/MakeAbsolute.php
similarity index 71%
rename from library/HTMLPurifier/URIFilter/MakeAbsolute.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/MakeAbsolute.php
index f46ab2630d..c507bbff8e 100644
--- a/library/HTMLPurifier/URIFilter/MakeAbsolute.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/MakeAbsolute.php
@@ -4,14 +4,35 @@
 
 class HTMLPurifier_URIFilter_MakeAbsolute extends HTMLPurifier_URIFilter
 {
+    /**
+     * @type string
+     */
     public $name = 'MakeAbsolute';
+
+    /**
+     * @type
+     */
     protected $base;
+
+    /**
+     * @type array
+     */
     protected $basePathStack = array();
-    public function prepare($config) {
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function prepare($config)
+    {
         $def = $config->getDefinition('URI');
         $this->base = $def->base;
         if (is_null($this->base)) {
-            trigger_error('URI.MakeAbsolute is being ignored due to lack of value for URI.Base configuration', E_USER_WARNING);
+            trigger_error(
+                'URI.MakeAbsolute is being ignored due to lack of ' .
+                'value for URI.Base configuration',
+                E_USER_WARNING
+            );
             return false;
         }
         $this->base->fragment = null; // fragment is invalid for base URI
@@ -21,19 +42,29 @@ class HTMLPurifier_URIFilter_MakeAbsolute extends HTMLPurifier_URIFilter
         $this->basePathStack = $stack;
         return true;
     }
-    public function filter(&$uri, $config, $context) {
-        if (is_null($this->base)) return true; // abort early
-        if (
-            $uri->path === '' && is_null($uri->scheme) &&
-            is_null($uri->host) && is_null($uri->query) && is_null($uri->fragment)
-        ) {
+
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function filter(&$uri, $config, $context)
+    {
+        if (is_null($this->base)) {
+            return true;
+        } // abort early
+        if ($uri->path === '' && is_null($uri->scheme) &&
+            is_null($uri->host) && is_null($uri->query) && is_null($uri->fragment)) {
             // reference to current document
             $uri = clone $this->base;
             return true;
         }
         if (!is_null($uri->scheme)) {
             // absolute URI already: don't change
-            if (!is_null($uri->host)) return true;
+            if (!is_null($uri->host)) {
+                return true;
+            }
             $scheme_obj = $uri->getSchemeObj($config, $context);
             if (!$scheme_obj) {
                 // scheme not recognized
@@ -66,22 +97,33 @@ class HTMLPurifier_URIFilter_MakeAbsolute extends HTMLPurifier_URIFilter
         }
         // re-combine
         $uri->scheme = $this->base->scheme;
-        if (is_null($uri->userinfo)) $uri->userinfo = $this->base->userinfo;
-        if (is_null($uri->host))     $uri->host     = $this->base->host;
-        if (is_null($uri->port))     $uri->port     = $this->base->port;
+        if (is_null($uri->userinfo)) {
+            $uri->userinfo = $this->base->userinfo;
+        }
+        if (is_null($uri->host)) {
+            $uri->host = $this->base->host;
+        }
+        if (is_null($uri->port)) {
+            $uri->port = $this->base->port;
+        }
         return true;
     }
 
     /**
      * Resolve dots and double-dots in a path stack
+     * @param array $stack
+     * @return array
      */
-    private function _collapseStack($stack) {
+    private function _collapseStack($stack)
+    {
         $result = array();
         $is_folder = false;
         for ($i = 0; isset($stack[$i]); $i++) {
             $is_folder = false;
             // absorb an internally duplicated slash
-            if ($stack[$i] == '' && $i && isset($stack[$i+1])) continue;
+            if ($stack[$i] == '' && $i && isset($stack[$i + 1])) {
+                continue;
+            }
             if ($stack[$i] == '..') {
                 if (!empty($result)) {
                     $segment = array_pop($result);
@@ -106,7 +148,9 @@ class HTMLPurifier_URIFilter_MakeAbsolute extends HTMLPurifier_URIFilter
             }
             $result[] = $stack[$i];
         }
-        if ($is_folder) $result[] = '';
+        if ($is_folder) {
+            $result[] = '';
+        }
         return $result;
     }
 }
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/Munge.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/Munge.php
new file mode 100644
index 0000000000..6e03315a17
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/Munge.php
@@ -0,0 +1,115 @@
+<?php
+
+class HTMLPurifier_URIFilter_Munge extends HTMLPurifier_URIFilter
+{
+    /**
+     * @type string
+     */
+    public $name = 'Munge';
+
+    /**
+     * @type bool
+     */
+    public $post = true;
+
+    /**
+     * @type string
+     */
+    private $target;
+
+    /**
+     * @type HTMLPurifier_URIParser
+     */
+    private $parser;
+
+    /**
+     * @type bool
+     */
+    private $doEmbed;
+
+    /**
+     * @type string
+     */
+    private $secretKey;
+
+    /**
+     * @type array
+     */
+    protected $replace = array();
+
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function prepare($config)
+    {
+        $this->target = $config->get('URI.' . $this->name);
+        $this->parser = new HTMLPurifier_URIParser();
+        $this->doEmbed = $config->get('URI.MungeResources');
+        $this->secretKey = $config->get('URI.MungeSecretKey');
+        if ($this->secretKey && !function_exists('hash_hmac')) {
+            throw new Exception("Cannot use %URI.MungeSecretKey without hash_hmac support.");
+        }
+        return true;
+    }
+
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function filter(&$uri, $config, $context)
+    {
+        if ($context->get('EmbeddedURI', true) && !$this->doEmbed) {
+            return true;
+        }
+
+        $scheme_obj = $uri->getSchemeObj($config, $context);
+        if (!$scheme_obj) {
+            return true;
+        } // ignore unknown schemes, maybe another postfilter did it
+        if (!$scheme_obj->browsable) {
+            return true;
+        } // ignore non-browseable schemes, since we can't munge those in a reasonable way
+        if ($uri->isBenign($config, $context)) {
+            return true;
+        } // don't redirect if a benign URL
+
+        $this->makeReplace($uri, $config, $context);
+        $this->replace = array_map('rawurlencode', $this->replace);
+
+        $new_uri = strtr($this->target, $this->replace);
+        $new_uri = $this->parser->parse($new_uri);
+        // don't redirect if the target host is the same as the
+        // starting host
+        if ($uri->host === $new_uri->host) {
+            return true;
+        }
+        $uri = $new_uri; // overwrite
+        return true;
+    }
+
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     */
+    protected function makeReplace($uri, $config, $context)
+    {
+        $string = $uri->toString();
+        // always available
+        $this->replace['%s'] = $string;
+        $this->replace['%r'] = $context->get('EmbeddedURI', true);
+        $token = $context->get('CurrentToken', true);
+        $this->replace['%n'] = $token ? $token->name : null;
+        $this->replace['%m'] = $context->get('CurrentAttr', true);
+        $this->replace['%p'] = $context->get('CurrentCSSProperty', true);
+        // not always available
+        if ($this->secretKey) {
+            $this->replace['%t'] = hash_hmac("sha256", $string, $this->secretKey);
+        }
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/SafeIframe.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/SafeIframe.php
new file mode 100644
index 0000000000..f609c47a34
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIFilter/SafeIframe.php
@@ -0,0 +1,68 @@
+<?php
+
+/**
+ * Implements safety checks for safe iframes.
+ *
+ * @warning This filter is *critical* for ensuring that %HTML.SafeIframe
+ * works safely.
+ */
+class HTMLPurifier_URIFilter_SafeIframe extends HTMLPurifier_URIFilter
+{
+    /**
+     * @type string
+     */
+    public $name = 'SafeIframe';
+
+    /**
+     * @type bool
+     */
+    public $always_load = true;
+
+    /**
+     * @type string
+     */
+    protected $regexp = null;
+
+    // XXX: The not so good bit about how this is all set up now is we
+    // can't check HTML.SafeIframe in the 'prepare' step: we have to
+    // defer till the actual filtering.
+    /**
+     * @param HTMLPurifier_Config $config
+     * @return bool
+     */
+    public function prepare($config)
+    {
+        $this->regexp = $config->get('URI.SafeIframeRegexp');
+        return true;
+    }
+
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function filter(&$uri, $config, $context)
+    {
+        // check if filter not applicable
+        if (!$config->get('HTML.SafeIframe')) {
+            return true;
+        }
+        // check if the filter should actually trigger
+        if (!$context->get('EmbeddedURI', true)) {
+            return true;
+        }
+        $token = $context->get('CurrentToken', true);
+        if (!($token && $token->name == 'iframe')) {
+            return true;
+        }
+        // check if we actually have some whitelists enabled
+        if ($this->regexp === null) {
+            return false;
+        }
+        // actually check the whitelists
+        return preg_match($this->regexp, $uri->toString());
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIParser.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIParser.php
similarity index 94%
rename from library/HTMLPurifier/URIParser.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/URIParser.php
index 7179e4ab89..0e7381a07b 100644
--- a/library/HTMLPurifier/URIParser.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIParser.php
@@ -12,7 +12,8 @@ class HTMLPurifier_URIParser
      */
     protected $percentEncoder;
 
-    public function __construct() {
+    public function __construct()
+    {
         $this->percentEncoder = new HTMLPurifier_PercentEncoder();
     }
 
@@ -22,15 +23,15 @@ class HTMLPurifier_URIParser
      * @return HTMLPurifier_URI representation of URI. This representation has
      *         not been validated yet and may not conform to RFC.
      */
-    public function parse($uri) {
-
+    public function parse($uri)
+    {
         $uri = $this->percentEncoder->normalize($uri);
 
         // Regexp is as per Appendix B.
         // Note that ["<>] are an addition to the RFC's recommended
         // characters, because they represent external delimeters.
         $r_URI = '!'.
-            '(([^:/?#"<>]+):)?'. // 2. Scheme
+            '(([a-zA-Z0-9\.\+\-]+):)?'. // 2. Scheme
             '(//([^/?#"<>]*))?'. // 4. Authority
             '([^?#"<>]*)'.       // 5. Path
             '(\?([^#"<>]*))?'.   // 7. Query
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme.php
new file mode 100644
index 0000000000..fe9e82cf26
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme.php
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * Validator for the components of a URI for a specific scheme
+ */
+abstract class HTMLPurifier_URIScheme
+{
+
+    /**
+     * Scheme's default port (integer). If an explicit port number is
+     * specified that coincides with the default port, it will be
+     * elided.
+     * @type int
+     */
+    public $default_port = null;
+
+    /**
+     * Whether or not URIs of this scheme are locatable by a browser
+     * http and ftp are accessible, while mailto and news are not.
+     * @type bool
+     */
+    public $browsable = false;
+
+    /**
+     * Whether or not data transmitted over this scheme is encrypted.
+     * https is secure, http is not.
+     * @type bool
+     */
+    public $secure = false;
+
+    /**
+     * Whether or not the URI always uses <hier_part>, resolves edge cases
+     * with making relative URIs absolute
+     * @type bool
+     */
+    public $hierarchical = false;
+
+    /**
+     * Whether or not the URI may omit a hostname when the scheme is
+     * explicitly specified, ala file:///path/to/file. As of writing,
+     * 'file' is the only scheme that browsers support his properly.
+     * @type bool
+     */
+    public $may_omit_host = false;
+
+    /**
+     * Validates the components of a URI for a specific scheme.
+     * @param HTMLPurifier_URI $uri Reference to a HTMLPurifier_URI object
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool success or failure
+     */
+    abstract public function doValidate(&$uri, $config, $context);
+
+    /**
+     * Public interface for validating components of a URI.  Performs a
+     * bunch of default actions. Don't overload this method.
+     * @param HTMLPurifier_URI $uri Reference to a HTMLPurifier_URI object
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool success or failure
+     */
+    public function validate(&$uri, $config, $context)
+    {
+        if ($this->default_port == $uri->port) {
+            $uri->port = null;
+        }
+        // kludge: browsers do funny things when the scheme but not the
+        // authority is set
+        if (!$this->may_omit_host &&
+            // if the scheme is present, a missing host is always in error
+            (!is_null($uri->scheme) && ($uri->host === '' || is_null($uri->host))) ||
+            // if the scheme is not present, a *blank* host is in error,
+            // since this translates into '///path' which most browsers
+            // interpret as being 'http://path'.
+            (is_null($uri->scheme) && $uri->host === '')
+        ) {
+            do {
+                if (is_null($uri->scheme)) {
+                    if (substr($uri->path, 0, 2) != '//') {
+                        $uri->host = null;
+                        break;
+                    }
+                    // URI is '////path', so we cannot nullify the
+                    // host to preserve semantics.  Try expanding the
+                    // hostname instead (fall through)
+                }
+                // first see if we can manually insert a hostname
+                $host = $config->get('URI.Host');
+                if (!is_null($host)) {
+                    $uri->host = $host;
+                } else {
+                    // we can't do anything sensible, reject the URL.
+                    return false;
+                }
+            } while (false);
+        }
+        return $this->doValidate($uri, $config, $context);
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIScheme/data.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/data.php
similarity index 74%
rename from library/HTMLPurifier/URIScheme/data.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/data.php
index b7f1989cbf..6ebca49848 100644
--- a/library/HTMLPurifier/URIScheme/data.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/data.php
@@ -3,18 +3,38 @@
 /**
  * Implements data: URI for base64 encoded images supported by GD.
  */
-class HTMLPurifier_URIScheme_data extends HTMLPurifier_URIScheme {
-
+class HTMLPurifier_URIScheme_data extends HTMLPurifier_URIScheme
+{
+    /**
+     * @type bool
+     */
     public $browsable = true;
+
+    /**
+     * @type array
+     */
     public $allowed_types = array(
         // you better write validation code for other types if you
         // decide to allow them
         'image/jpeg' => true,
         'image/gif' => true,
         'image/png' => true,
-        );
+    );
+    // this is actually irrelevant since we only write out the path
+    // component
+    /**
+     * @type bool
+     */
+    public $may_omit_host = true;
 
-    public function validate(&$uri, $config, $context) {
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function doValidate(&$uri, $config, $context)
+    {
         $result = explode(',', $uri->path, 2);
         $is_base64 = false;
         $charset = null;
@@ -23,7 +43,7 @@ class HTMLPurifier_URIScheme_data extends HTMLPurifier_URIScheme {
             list($metadata, $data) = $result;
             // do some legwork on the metadata
             $metas = explode(';', $metadata);
-            while(!empty($metas)) {
+            while (!empty($metas)) {
                 $cur = array_shift($metas);
                 if ($cur == 'base64') {
                     $is_base64 = true;
@@ -32,10 +52,14 @@ class HTMLPurifier_URIScheme_data extends HTMLPurifier_URIScheme {
                 if (substr($cur, 0, 8) == 'charset=') {
                     // doesn't match if there are arbitrary spaces, but
                     // whatever dude
-                    if ($charset !== null) continue; // garbage
+                    if ($charset !== null) {
+                        continue;
+                    } // garbage
                     $charset = substr($cur, 8); // not used
                 } else {
-                    if ($content_type !== null) continue; // garbage
+                    if ($content_type !== null) {
+                        continue;
+                    } // garbage
                     $content_type = $cur;
                 }
             }
@@ -61,11 +85,15 @@ class HTMLPurifier_URIScheme_data extends HTMLPurifier_URIScheme {
         file_put_contents($file, $raw_data);
         if (function_exists('exif_imagetype')) {
             $image_code = exif_imagetype($file);
+            unlink($file);
         } elseif (function_exists('getimagesize')) {
             set_error_handler(array($this, 'muteErrorHandler'));
             $info = getimagesize($file);
             restore_error_handler();
-            if ($info == false) return false;
+            unlink($file);
+            if ($info == false) {
+                return false;
+            }
             $image_code = $info[2];
         } else {
             trigger_error("could not find exif_imagetype or getimagesize functions", E_USER_ERROR);
@@ -74,7 +102,9 @@ class HTMLPurifier_URIScheme_data extends HTMLPurifier_URIScheme {
         if ($real_content_type != $content_type) {
             // we're nice guys; if the content type is something else we
             // support, change it over
-            if (empty($this->allowed_types[$real_content_type])) return false;
+            if (empty($this->allowed_types[$real_content_type])) {
+                return false;
+            }
             $content_type = $real_content_type;
         }
         // ok, it's kosher, rewrite what we need
@@ -87,7 +117,11 @@ class HTMLPurifier_URIScheme_data extends HTMLPurifier_URIScheme {
         return true;
     }
 
-    public function muteErrorHandler($errno, $errstr) {}
-
+    /**
+     * @param int $errno
+     * @param string $errstr
+     */
+    public function muteErrorHandler($errno, $errstr)
+    {
+    }
 }
-
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/file.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/file.php
new file mode 100644
index 0000000000..215be4ba80
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/file.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * Validates file as defined by RFC 1630 and RFC 1738.
+ */
+class HTMLPurifier_URIScheme_file extends HTMLPurifier_URIScheme
+{
+    /**
+     * Generally file:// URLs are not accessible from most
+     * machines, so placing them as an img src is incorrect.
+     * @type bool
+     */
+    public $browsable = false;
+
+    /**
+     * Basically the *only* URI scheme for which this is true, since
+     * accessing files on the local machine is very common.  In fact,
+     * browsers on some operating systems don't understand the
+     * authority, though I hear it is used on Windows to refer to
+     * network shares.
+     * @type bool
+     */
+    public $may_omit_host = true;
+
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function doValidate(&$uri, $config, $context)
+    {
+        // Authentication method is not supported
+        $uri->userinfo = null;
+        // file:// makes no provisions for accessing the resource
+        $uri->port = null;
+        // While it seems to work on Firefox, the querystring has
+        // no possible effect and is thus stripped.
+        $uri->query = null;
+        return true;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIScheme/ftp.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/ftp.php
similarity index 74%
rename from library/HTMLPurifier/URIScheme/ftp.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/ftp.php
index 5849bf7ff0..1eb43ee5c4 100644
--- a/library/HTMLPurifier/URIScheme/ftp.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/ftp.php
@@ -3,15 +3,32 @@
 /**
  * Validates ftp (File Transfer Protocol) URIs as defined by generic RFC 1738.
  */
-class HTMLPurifier_URIScheme_ftp extends HTMLPurifier_URIScheme {
-
+class HTMLPurifier_URIScheme_ftp extends HTMLPurifier_URIScheme
+{
+    /**
+     * @type int
+     */
     public $default_port = 21;
+
+    /**
+     * @type bool
+     */
     public $browsable = true; // usually
+
+    /**
+     * @type bool
+     */
     public $hierarchical = true;
 
-    public function validate(&$uri, $config, $context) {
-        parent::validate($uri, $config, $context);
-        $uri->query    = null;
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function doValidate(&$uri, $config, $context)
+    {
+        $uri->query = null;
 
         // typecode check
         $semicolon_pos = strrpos($uri->path, ';'); // reverse
@@ -34,10 +51,8 @@ class HTMLPurifier_URIScheme_ftp extends HTMLPurifier_URIScheme {
             $uri->path = str_replace(';', '%3B', $uri->path);
             $uri->path .= $type_ret;
         }
-
         return true;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIScheme/http.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/http.php
similarity index 50%
rename from library/HTMLPurifier/URIScheme/http.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/http.php
index b097a31d6a..ce69ec438a 100644
--- a/library/HTMLPurifier/URIScheme/http.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/http.php
@@ -3,18 +3,34 @@
 /**
  * Validates http (HyperText Transfer Protocol) as defined by RFC 2616
  */
-class HTMLPurifier_URIScheme_http extends HTMLPurifier_URIScheme {
-
+class HTMLPurifier_URIScheme_http extends HTMLPurifier_URIScheme
+{
+    /**
+     * @type int
+     */
     public $default_port = 80;
+
+    /**
+     * @type bool
+     */
     public $browsable = true;
+
+    /**
+     * @type bool
+     */
     public $hierarchical = true;
 
-    public function validate(&$uri, $config, $context) {
-        parent::validate($uri, $config, $context);
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function doValidate(&$uri, $config, $context)
+    {
         $uri->userinfo = null;
         return true;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIScheme/https.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/https.php
similarity index 65%
rename from library/HTMLPurifier/URIScheme/https.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/https.php
index 29e380919f..0e96882db9 100644
--- a/library/HTMLPurifier/URIScheme/https.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/https.php
@@ -3,10 +3,16 @@
 /**
  * Validates https (Secure HTTP) according to http scheme.
  */
-class HTMLPurifier_URIScheme_https extends HTMLPurifier_URIScheme_http {
-
+class HTMLPurifier_URIScheme_https extends HTMLPurifier_URIScheme_http
+{
+    /**
+     * @type int
+     */
     public $default_port = 443;
-
+    /**
+     * @type bool
+     */
+    public $secure = true;
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URIScheme/mailto.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/mailto.php
similarity index 63%
rename from library/HTMLPurifier/URIScheme/mailto.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/mailto.php
index c1e2cd5aae..c3a6b602a7 100644
--- a/library/HTMLPurifier/URIScheme/mailto.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/mailto.php
@@ -9,19 +9,32 @@
  * @todo Filter allowed query parameters
  */
 
-class HTMLPurifier_URIScheme_mailto extends HTMLPurifier_URIScheme {
-
+class HTMLPurifier_URIScheme_mailto extends HTMLPurifier_URIScheme
+{
+    /**
+     * @type bool
+     */
     public $browsable = false;
 
-    public function validate(&$uri, $config, $context) {
-        parent::validate($uri, $config, $context);
+    /**
+     * @type bool
+     */
+    public $may_omit_host = true;
+
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function doValidate(&$uri, $config, $context)
+    {
         $uri->userinfo = null;
         $uri->host     = null;
         $uri->port     = null;
         // we need to validate path against RFC 2368's addr-spec
         return true;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/news.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/news.php
new file mode 100644
index 0000000000..7490927d63
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/news.php
@@ -0,0 +1,35 @@
+<?php
+
+/**
+ * Validates news (Usenet) as defined by generic RFC 1738
+ */
+class HTMLPurifier_URIScheme_news extends HTMLPurifier_URIScheme
+{
+    /**
+     * @type bool
+     */
+    public $browsable = false;
+
+    /**
+     * @type bool
+     */
+    public $may_omit_host = true;
+
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function doValidate(&$uri, $config, $context)
+    {
+        $uri->userinfo = null;
+        $uri->host = null;
+        $uri->port = null;
+        $uri->query = null;
+        // typecode check needed on path
+        return true;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/nntp.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/nntp.php
new file mode 100644
index 0000000000..f211d715e9
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URIScheme/nntp.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Validates nntp (Network News Transfer Protocol) as defined by generic RFC 1738
+ */
+class HTMLPurifier_URIScheme_nntp extends HTMLPurifier_URIScheme
+{
+    /**
+     * @type int
+     */
+    public $default_port = 119;
+
+    /**
+     * @type bool
+     */
+    public $browsable = false;
+
+    /**
+     * @param HTMLPurifier_URI $uri
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return bool
+     */
+    public function doValidate(&$uri, $config, $context)
+    {
+        $uri->userinfo = null;
+        $uri->query = null;
+        return true;
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/URISchemeRegistry.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/URISchemeRegistry.php
similarity index 58%
rename from library/HTMLPurifier/URISchemeRegistry.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/URISchemeRegistry.php
index 576bf7b6d1..4ac8a0b76e 100644
--- a/library/HTMLPurifier/URISchemeRegistry.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/URISchemeRegistry.php
@@ -8,12 +8,14 @@ class HTMLPurifier_URISchemeRegistry
 
     /**
      * Retrieve sole instance of the registry.
-     * @param $prototype Optional prototype to overload sole instance with,
+     * @param HTMLPurifier_URISchemeRegistry $prototype Optional prototype to overload sole instance with,
      *                   or bool true to reset to default registry.
+     * @return HTMLPurifier_URISchemeRegistry
      * @note Pass a registry object $prototype with a compatible interface and
      *       the function will copy it and return it all further times.
      */
-    public static function instance($prototype = null) {
+    public static function instance($prototype = null)
+    {
         static $instance = null;
         if ($prototype !== null) {
             $instance = $prototype;
@@ -25,17 +27,22 @@ class HTMLPurifier_URISchemeRegistry
 
     /**
      * Cache of retrieved schemes.
+     * @type HTMLPurifier_URIScheme[]
      */
     protected $schemes = array();
 
     /**
      * Retrieves a scheme validator object
-     * @param $scheme String scheme name like http or mailto
-     * @param $config HTMLPurifier_Config object
-     * @param $config HTMLPurifier_Context object
+     * @param string $scheme String scheme name like http or mailto
+     * @param HTMLPurifier_Config $config
+     * @param HTMLPurifier_Context $context
+     * @return HTMLPurifier_URIScheme
      */
-    public function getScheme($scheme, $config, $context) {
-        if (!$config) $config = HTMLPurifier_Config::createDefault();
+    public function getScheme($scheme, $config, $context)
+    {
+        if (!$config) {
+            $config = HTMLPurifier_Config::createDefault();
+        }
 
         // important, otherwise attacker could include arbitrary file
         $allowed_schemes = $config->get('URI.AllowedSchemes');
@@ -45,24 +52,30 @@ class HTMLPurifier_URISchemeRegistry
             return;
         }
 
-        if (isset($this->schemes[$scheme])) return $this->schemes[$scheme];
-        if (!isset($allowed_schemes[$scheme])) return;
+        if (isset($this->schemes[$scheme])) {
+            return $this->schemes[$scheme];
+        }
+        if (!isset($allowed_schemes[$scheme])) {
+            return;
+        }
 
         $class = 'HTMLPurifier_URIScheme_' . $scheme;
-        if (!class_exists($class)) return;
+        if (!class_exists($class)) {
+            return;
+        }
         $this->schemes[$scheme] = new $class();
         return $this->schemes[$scheme];
     }
 
     /**
      * Registers a custom scheme to the cache, bypassing reflection.
-     * @param $scheme Scheme name
-     * @param $scheme_obj HTMLPurifier_URIScheme object
+     * @param string $scheme Scheme name
+     * @param HTMLPurifier_URIScheme $scheme_obj
      */
-    public function register($scheme, $scheme_obj) {
+    public function register($scheme, $scheme_obj)
+    {
         $this->schemes[$scheme] = $scheme_obj;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/UnitConverter.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/UnitConverter.php
similarity index 75%
rename from library/HTMLPurifier/UnitConverter.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/UnitConverter.php
index 545d426220..166f3bf306 100644
--- a/library/HTMLPurifier/UnitConverter.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/UnitConverter.php
@@ -37,20 +37,24 @@ class HTMLPurifier_UnitConverter
 
     /**
      * Minimum bcmath precision for output.
+     * @type int
      */
     protected $outputPrecision;
 
     /**
      * Bcmath precision for internal calculations.
+     * @type int
      */
     protected $internalPrecision;
 
     /**
-     * Whether or not BCMath is available
+     * Whether or not BCMath is available.
+     * @type bool
      */
     private $bcmath;
 
-    public function __construct($output_precision = 4, $internal_precision = 10, $force_no_bcmath = false) {
+    public function __construct($output_precision = 4, $internal_precision = 10, $force_no_bcmath = false)
+    {
         $this->outputPrecision = $output_precision;
         $this->internalPrecision = $internal_precision;
         $this->bcmath = !$force_no_bcmath && function_exists('bcmul');
@@ -63,6 +67,7 @@ class HTMLPurifier_UnitConverter
      *      it before passing it here!
      * @param string $to_unit
      *      Unit to convert to.
+     * @return HTMLPurifier_Length|bool
      * @note
      *      About precision: This conversion function pays very special
      *      attention to the incoming precision of values and attempts
@@ -74,11 +79,13 @@ class HTMLPurifier_UnitConverter
      *            and this causes some decimals to be excluded, those
      *            decimals will be added on.
      */
-    public function convert($length, $to_unit) {
+    public function convert($length, $to_unit)
+    {
+        if (!$length->isValid()) {
+            return false;
+        }
 
-        if (!$length->isValid()) return false;
-
-        $n    = $length->getN();
+        $n = $length->getN();
         $unit = $length->getUnit();
 
         if ($n === '0' || $unit === false) {
@@ -87,21 +94,29 @@ class HTMLPurifier_UnitConverter
 
         $state = $dest_state = false;
         foreach (self::$units as $k => $x) {
-            if (isset($x[$unit])) $state = $k;
-            if (isset($x[$to_unit])) $dest_state = $k;
+            if (isset($x[$unit])) {
+                $state = $k;
+            }
+            if (isset($x[$to_unit])) {
+                $dest_state = $k;
+            }
+        }
+        if (!$state || !$dest_state) {
+            return false;
         }
-        if (!$state || !$dest_state) return false;
 
         // Some calculations about the initial precision of the number;
         // this will be useful when we need to do final rounding.
         $sigfigs = $this->getSigFigs($n);
-        if ($sigfigs < $this->outputPrecision) $sigfigs = $this->outputPrecision;
+        if ($sigfigs < $this->outputPrecision) {
+            $sigfigs = $this->outputPrecision;
+        }
 
         // BCMath's internal precision deals only with decimals. Use
         // our default if the initial number has no decimals, or increase
         // it by how ever many decimals, thus, the number of guard digits
         // will always be greater than or equal to internalPrecision.
-        $log = (int) floor(log(abs($n), 10));
+        $log = (int)floor(log(abs($n), 10));
         $cp = ($log < 0) ? $this->internalPrecision - $log : $this->internalPrecision; // internal precision
 
         for ($i = 0; $i < 2; $i++) {
@@ -152,14 +167,18 @@ class HTMLPurifier_UnitConverter
         }
 
         // Post-condition: $unit == $to_unit
-        if ($unit !== $to_unit) return false;
+        if ($unit !== $to_unit) {
+            return false;
+        }
 
         // Useful for debugging:
         //echo "<pre>n";
         //echo "$n\nsigfigs = $sigfigs\nnew_log = $new_log\nlog = $log\nrp = $rp\n</pre>\n";
 
         $n = $this->round($n, $sigfigs);
-        if (strpos($n, '.') !== false) $n = rtrim($n, '0');
+        if (strpos($n, '.') !== false) {
+            $n = rtrim($n, '0');
+        }
         $n = rtrim($n, '.');
 
         return new HTMLPurifier_Length($n, $unit);
@@ -170,53 +189,84 @@ class HTMLPurifier_UnitConverter
      * @param string $n Decimal number
      * @return int number of sigfigs
      */
-    public function getSigFigs($n) {
+    public function getSigFigs($n)
+    {
         $n = ltrim($n, '0+-');
         $dp = strpos($n, '.'); // decimal position
         if ($dp === false) {
             $sigfigs = strlen(rtrim($n, '0'));
         } else {
             $sigfigs = strlen(ltrim($n, '0.')); // eliminate extra decimal character
-            if ($dp !== 0) $sigfigs--;
+            if ($dp !== 0) {
+                $sigfigs--;
+            }
         }
         return $sigfigs;
     }
 
     /**
      * Adds two numbers, using arbitrary precision when available.
+     * @param string $s1
+     * @param string $s2
+     * @param int $scale
+     * @return string
      */
-    private function add($s1, $s2, $scale) {
-        if ($this->bcmath) return bcadd($s1, $s2, $scale);
-        else return $this->scale($s1 + $s2, $scale);
+    private function add($s1, $s2, $scale)
+    {
+        if ($this->bcmath) {
+            return bcadd($s1, $s2, $scale);
+        } else {
+            return $this->scale((float)$s1 + (float)$s2, $scale);
+        }
     }
 
     /**
      * Multiples two numbers, using arbitrary precision when available.
+     * @param string $s1
+     * @param string $s2
+     * @param int $scale
+     * @return string
      */
-    private function mul($s1, $s2, $scale) {
-        if ($this->bcmath) return bcmul($s1, $s2, $scale);
-        else return $this->scale($s1 * $s2, $scale);
+    private function mul($s1, $s2, $scale)
+    {
+        if ($this->bcmath) {
+            return bcmul($s1, $s2, $scale);
+        } else {
+            return $this->scale((float)$s1 * (float)$s2, $scale);
+        }
     }
 
     /**
      * Divides two numbers, using arbitrary precision when available.
+     * @param string $s1
+     * @param string $s2
+     * @param int $scale
+     * @return string
      */
-    private function div($s1, $s2, $scale) {
-        if ($this->bcmath) return bcdiv($s1, $s2, $scale);
-        else return $this->scale($s1 / $s2, $scale);
+    private function div($s1, $s2, $scale)
+    {
+        if ($this->bcmath) {
+            return bcdiv($s1, $s2, $scale);
+        } else {
+            return $this->scale((float)$s1 / (float)$s2, $scale);
+        }
     }
 
     /**
      * Rounds a number according to the number of sigfigs it should have,
      * using arbitrary precision when available.
+     * @param float $n
+     * @param int $sigfigs
+     * @return string
      */
-    private function round($n, $sigfigs) {
-        $new_log = (int) floor(log(abs($n), 10)); // Number of digits left of decimal - 1
+    private function round($n, $sigfigs)
+    {
+        $new_log = (int)floor(log(abs($n), 10)); // Number of digits left of decimal - 1
         $rp = $sigfigs - $new_log - 1; // Number of decimal places needed
         $neg = $n < 0 ? '-' : ''; // Negative sign
         if ($this->bcmath) {
             if ($rp >= 0) {
-                $n = bcadd($n, $neg . '0.' .  str_repeat('0', $rp) . '5', $rp + 1);
+                $n = bcadd($n, $neg . '0.' . str_repeat('0', $rp) . '5', $rp + 1);
                 $n = bcdiv($n, '1', $rp);
             } else {
                 // This algorithm partially depends on the standardized
@@ -232,23 +282,26 @@ class HTMLPurifier_UnitConverter
 
     /**
      * Scales a float to $scale digits right of decimal point, like BCMath.
+     * @param float $r
+     * @param int $scale
+     * @return string
      */
-    private function scale($r, $scale) {
+    private function scale($r, $scale)
+    {
         if ($scale < 0) {
             // The f sprintf type doesn't support negative numbers, so we
             // need to cludge things manually. First get the string.
-            $r = sprintf('%.0f', (float) $r);
+            $r = sprintf('%.0f', (float)$r);
             // Due to floating point precision loss, $r will more than likely
             // look something like 4652999999999.9234. We grab one more digit
             // than we need to precise from $r and then use that to round
             // appropriately.
-            $precise = (string) round(substr($r, 0, strlen($r) + $scale), -1);
+            $precise = (string)round(substr($r, 0, strlen($r) + $scale), -1);
             // Now we return it, truncating the zero that was rounded off.
             return substr($precise, 0, -1) . str_repeat('0', -$scale + 1);
         }
-        return sprintf('%.' . $scale . 'f', (float) $r);
+        return sprintf('%.' . $scale . 'f', (float)$r);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/VarParser.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/VarParser.php
new file mode 100644
index 0000000000..50cba6910d
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/VarParser.php
@@ -0,0 +1,198 @@
+<?php
+
+/**
+ * Parses string representations into their corresponding native PHP
+ * variable type. The base implementation does a simple type-check.
+ */
+class HTMLPurifier_VarParser
+{
+
+    const STRING = 1;
+    const ISTRING = 2;
+    const TEXT = 3;
+    const ITEXT = 4;
+    const INT = 5;
+    const FLOAT = 6;
+    const BOOL = 7;
+    const LOOKUP = 8;
+    const ALIST = 9;
+    const HASH = 10;
+    const MIXED = 11;
+
+    /**
+     * Lookup table of allowed types. Mainly for backwards compatibility, but
+     * also convenient for transforming string type names to the integer constants.
+     */
+    public static $types = array(
+        'string' => self::STRING,
+        'istring' => self::ISTRING,
+        'text' => self::TEXT,
+        'itext' => self::ITEXT,
+        'int' => self::INT,
+        'float' => self::FLOAT,
+        'bool' => self::BOOL,
+        'lookup' => self::LOOKUP,
+        'list' => self::ALIST,
+        'hash' => self::HASH,
+        'mixed' => self::MIXED
+    );
+
+    /**
+     * Lookup table of types that are string, and can have aliases or
+     * allowed value lists.
+     */
+    public static $stringTypes = array(
+        self::STRING => true,
+        self::ISTRING => true,
+        self::TEXT => true,
+        self::ITEXT => true,
+    );
+
+    /**
+     * Validate a variable according to type.
+     * It may return NULL as a valid type if $allow_null is true.
+     *
+     * @param mixed $var Variable to validate
+     * @param int $type Type of variable, see HTMLPurifier_VarParser->types
+     * @param bool $allow_null Whether or not to permit null as a value
+     * @return string Validated and type-coerced variable
+     * @throws HTMLPurifier_VarParserException
+     */
+    final public function parse($var, $type, $allow_null = false)
+    {
+        if (is_string($type)) {
+            if (!isset(HTMLPurifier_VarParser::$types[$type])) {
+                throw new HTMLPurifier_VarParserException("Invalid type '$type'");
+            } else {
+                $type = HTMLPurifier_VarParser::$types[$type];
+            }
+        }
+        $var = $this->parseImplementation($var, $type, $allow_null);
+        if ($allow_null && $var === null) {
+            return null;
+        }
+        // These are basic checks, to make sure nothing horribly wrong
+        // happened in our implementations.
+        switch ($type) {
+            case (self::STRING):
+            case (self::ISTRING):
+            case (self::TEXT):
+            case (self::ITEXT):
+                if (!is_string($var)) {
+                    break;
+                }
+                if ($type == self::ISTRING || $type == self::ITEXT) {
+                    $var = strtolower($var);
+                }
+                return $var;
+            case (self::INT):
+                if (!is_int($var)) {
+                    break;
+                }
+                return $var;
+            case (self::FLOAT):
+                if (!is_float($var)) {
+                    break;
+                }
+                return $var;
+            case (self::BOOL):
+                if (!is_bool($var)) {
+                    break;
+                }
+                return $var;
+            case (self::LOOKUP):
+            case (self::ALIST):
+            case (self::HASH):
+                if (!is_array($var)) {
+                    break;
+                }
+                if ($type === self::LOOKUP) {
+                    foreach ($var as $k) {
+                        if ($k !== true) {
+                            $this->error('Lookup table contains value other than true');
+                        }
+                    }
+                } elseif ($type === self::ALIST) {
+                    $keys = array_keys($var);
+                    if (array_keys($keys) !== $keys) {
+                        $this->error('Indices for list are not uniform');
+                    }
+                }
+                return $var;
+            case (self::MIXED):
+                return $var;
+            default:
+                $this->errorInconsistent(get_class($this), $type);
+        }
+        $this->errorGeneric($var, $type);
+    }
+
+    /**
+     * Actually implements the parsing. Base implementation does not
+     * do anything to $var. Subclasses should overload this!
+     * @param mixed $var
+     * @param int $type
+     * @param bool $allow_null
+     * @return string
+     */
+    protected function parseImplementation($var, $type, $allow_null)
+    {
+        return $var;
+    }
+
+    /**
+     * Throws an exception.
+     * @throws HTMLPurifier_VarParserException
+     */
+    protected function error($msg)
+    {
+        throw new HTMLPurifier_VarParserException($msg);
+    }
+
+    /**
+     * Throws an inconsistency exception.
+     * @note This should not ever be called. It would be called if we
+     *       extend the allowed values of HTMLPurifier_VarParser without
+     *       updating subclasses.
+     * @param string $class
+     * @param int $type
+     * @throws HTMLPurifier_Exception
+     */
+    protected function errorInconsistent($class, $type)
+    {
+        throw new HTMLPurifier_Exception(
+            "Inconsistency in $class: " . HTMLPurifier_VarParser::getTypeName($type) .
+            " not implemented"
+        );
+    }
+
+    /**
+     * Generic error for if a type didn't work.
+     * @param mixed $var
+     * @param int $type
+     */
+    protected function errorGeneric($var, $type)
+    {
+        $vtype = gettype($var);
+        $this->error("Expected type " . HTMLPurifier_VarParser::getTypeName($type) . ", got $vtype");
+    }
+
+    /**
+     * @param int $type
+     * @return string
+     */
+    public static function getTypeName($type)
+    {
+        static $lookup;
+        if (!$lookup) {
+            // Lazy load the alternative lookup table
+            $lookup = array_flip(HTMLPurifier_VarParser::$types);
+        }
+        if (!isset($lookup[$type])) {
+            return 'unknown';
+        }
+        return $lookup[$type];
+    }
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/VarParser/Flexible.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php
similarity index 56%
rename from library/HTMLPurifier/VarParser/Flexible.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php
index c954250e9f..b15016c5b2 100644
--- a/library/HTMLPurifier/VarParser/Flexible.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Flexible.php
@@ -7,28 +7,41 @@
  */
 class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
 {
-
-    protected function parseImplementation($var, $type, $allow_null) {
-        if ($allow_null && $var === null) return null;
+    /**
+     * @param mixed $var
+     * @param int $type
+     * @param bool $allow_null
+     * @return array|bool|float|int|mixed|null|string
+     * @throws HTMLPurifier_VarParserException
+     */
+    protected function parseImplementation($var, $type, $allow_null)
+    {
+        if ($allow_null && $var === null) {
+            return null;
+        }
         switch ($type) {
             // Note: if code "breaks" from the switch, it triggers a generic
             // exception to be thrown. Specific errors can be specifically
             // done here.
-            case self::MIXED :
-            case self::ISTRING :
-            case self::STRING :
-            case self::TEXT :
-            case self::ITEXT :
+            case self::MIXED:
+            case self::ISTRING:
+            case self::STRING:
+            case self::TEXT:
+            case self::ITEXT:
                 return $var;
-            case self::INT :
-                if (is_string($var) && ctype_digit($var)) $var = (int) $var;
+            case self::INT:
+                if (is_string($var) && ctype_digit($var)) {
+                    $var = (int)$var;
+                }
                 return $var;
-            case self::FLOAT :
-                if ((is_string($var) && is_numeric($var)) || is_int($var)) $var = (float) $var;
+            case self::FLOAT:
+                if ((is_string($var) && is_numeric($var)) || is_int($var)) {
+                    $var = (float)$var;
+                }
                 return $var;
-            case self::BOOL :
+            case self::BOOL:
                 if (is_int($var) && ($var === 0 || $var === 1)) {
-                    $var = (bool) $var;
+                    $var = (bool)$var;
                 } elseif (is_string($var)) {
                     if ($var == 'on' || $var == 'true' || $var == '1') {
                         $var = true;
@@ -39,48 +52,70 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
                     }
                 }
                 return $var;
-            case self::ALIST :
-            case self::HASH :
-            case self::LOOKUP :
+            case self::ALIST:
+            case self::HASH:
+            case self::LOOKUP:
                 if (is_string($var)) {
                     // special case: technically, this is an array with
                     // a single empty string item, but having an empty
                     // array is more intuitive
-                    if ($var == '') return array();
+                    if ($var == '') {
+                        return array();
+                    }
                     if (strpos($var, "\n") === false && strpos($var, "\r") === false) {
                         // simplistic string to array method that only works
                         // for simple lists of tag names or alphanumeric characters
-                        $var = explode(',',$var);
+                        $var = explode(',', $var);
                     } else {
                         $var = preg_split('/(,|[\n\r]+)/', $var);
                     }
                     // remove spaces
-                    foreach ($var as $i => $j) $var[$i] = trim($j);
+                    foreach ($var as $i => $j) {
+                        $var[$i] = trim($j);
+                    }
                     if ($type === self::HASH) {
                         // key:value,key2:value2
                         $nvar = array();
                         foreach ($var as $keypair) {
                             $c = explode(':', $keypair, 2);
-                            if (!isset($c[1])) continue;
-                            $nvar[$c[0]] = $c[1];
+                            if (!isset($c[1])) {
+                                continue;
+                            }
+                            $nvar[trim($c[0])] = trim($c[1]);
                         }
                         $var = $nvar;
                     }
                 }
-                if (!is_array($var)) break;
+                if (!is_array($var)) {
+                    break;
+                }
                 $keys = array_keys($var);
                 if ($keys === array_keys($keys)) {
-                    if ($type == self::ALIST) return $var;
-                    elseif ($type == self::LOOKUP) {
+                    if ($type == self::ALIST) {
+                        return $var;
+                    } elseif ($type == self::LOOKUP) {
                         $new = array();
                         foreach ($var as $key) {
                             $new[$key] = true;
                         }
                         return $new;
-                    } else break;
+                    } else {
+                        break;
+                    }
+                }
+                if ($type === self::ALIST) {
+                    trigger_error("Array list did not have consecutive integer indexes", E_USER_WARNING);
+                    return array_values($var);
                 }
                 if ($type === self::LOOKUP) {
                     foreach ($var as $key => $value) {
+                        if ($value !== true) {
+                            trigger_error(
+                                "Lookup array has non-true value at key '$key'; " .
+                                "maybe your input array was not indexed numerically",
+                                E_USER_WARNING
+                            );
+                        }
                         $var[$key] = true;
                     }
                 }
@@ -90,7 +125,6 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
         }
         $this->errorGeneric($var, $type);
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/VarParser/Native.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php
similarity index 67%
rename from library/HTMLPurifier/VarParser/Native.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php
index b02a6de54c..f11c318efb 100644
--- a/library/HTMLPurifier/VarParser/Native.php
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/VarParser/Native.php
@@ -8,11 +8,24 @@
 class HTMLPurifier_VarParser_Native extends HTMLPurifier_VarParser
 {
 
-    protected function parseImplementation($var, $type, $allow_null) {
+    /**
+     * @param mixed $var
+     * @param int $type
+     * @param bool $allow_null
+     * @return null|string
+     */
+    protected function parseImplementation($var, $type, $allow_null)
+    {
         return $this->evalExpression($var);
     }
 
-    protected function evalExpression($expr) {
+    /**
+     * @param string $expr
+     * @return mixed
+     * @throws HTMLPurifier_VarParserException
+     */
+    protected function evalExpression($expr)
+    {
         $var = null;
         $result = eval("\$var = $expr;");
         if ($result === false) {
@@ -20,7 +33,6 @@ class HTMLPurifier_VarParser_Native extends HTMLPurifier_VarParser
         }
         return $var;
     }
-
 }
 
 // vim: et sw=4 sts=4
diff --git a/library/HTMLPurifier/VarParserException.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/VarParserException.php
similarity index 100%
rename from library/HTMLPurifier/VarParserException.php
rename to library/ezyang/htmlpurifier/library/HTMLPurifier/VarParserException.php
diff --git a/library/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php b/library/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php
new file mode 100644
index 0000000000..6e21ea0703
--- /dev/null
+++ b/library/ezyang/htmlpurifier/library/HTMLPurifier/Zipper.php
@@ -0,0 +1,157 @@
+<?php
+
+/**
+ * A zipper is a purely-functional data structure which contains
+ * a focus that can be efficiently manipulated.  It is known as
+ * a "one-hole context".  This mutable variant implements a zipper
+ * for a list as a pair of two arrays, laid out as follows:
+ *
+ *      Base list: 1 2 3 4 [ ] 6 7 8 9
+ *      Front list: 1 2 3 4
+ *      Back list: 9 8 7 6
+ *
+ * User is expected to keep track of the "current element" and properly
+ * fill it back in as necessary.  (ToDo: Maybe it's more user friendly
+ * to implicitly track the current element?)
+ *
+ * Nota bene: the current class gets confused if you try to store NULLs
+ * in the list.
+ */
+
+class HTMLPurifier_Zipper
+{
+    public $front, $back;
+
+    public function __construct($front, $back) {
+        $this->front = $front;
+        $this->back = $back;
+    }
+
+    /**
+     * Creates a zipper from an array, with a hole in the
+     * 0-index position.
+     * @param Array to zipper-ify.
+     * @return Tuple of zipper and element of first position.
+     */
+    static public function fromArray($array) {
+        $z = new self(array(), array_reverse($array));
+        $t = $z->delete(); // delete the "dummy hole"
+        return array($z, $t);
+    }
+
+    /**
+     * Convert zipper back into a normal array, optionally filling in
+     * the hole with a value. (Usually you should supply a $t, unless you
+     * are at the end of the array.)
+     */
+    public function toArray($t = NULL) {
+        $a = $this->front;
+        if ($t !== NULL) $a[] = $t;
+        for ($i = count($this->back)-1; $i >= 0; $i--) {
+            $a[] = $this->back[$i];
+        }
+        return $a;
+    }
+
+    /**
+     * Move hole to the next element.
+     * @param $t Element to fill hole with
+     * @return Original contents of new hole.
+     */
+    public function next($t) {
+        if ($t !== NULL) array_push($this->front, $t);
+        return empty($this->back) ? NULL : array_pop($this->back);
+    }
+
+    /**
+     * Iterated hole advancement.
+     * @param $t Element to fill hole with
+     * @param $i How many forward to advance hole
+     * @return Original contents of new hole, i away
+     */
+    public function advance($t, $n) {
+        for ($i = 0; $i < $n; $i++) {
+            $t = $this->next($t);
+        }
+        return $t;
+    }
+
+    /**
+     * Move hole to the previous element
+     * @param $t Element to fill hole with
+     * @return Original contents of new hole.
+     */
+    public function prev($t) {
+        if ($t !== NULL) array_push($this->back, $t);
+        return empty($this->front) ? NULL : array_pop($this->front);
+    }
+
+    /**
+     * Delete contents of current hole, shifting hole to
+     * next element.
+     * @return Original contents of new hole.
+     */
+    public function delete() {
+        return empty($this->back) ? NULL : array_pop($this->back);
+    }
+
+    /**
+     * Returns true if we are at the end of the list.
+     * @return bool
+     */
+    public function done() {
+        return empty($this->back);
+    }
+
+    /**
+     * Insert element before hole.
+     * @param Element to insert
+     */
+    public function insertBefore($t) {
+        if ($t !== NULL) array_push($this->front, $t);
+    }
+
+    /**
+     * Insert element after hole.
+     * @param Element to insert
+     */
+    public function insertAfter($t) {
+        if ($t !== NULL) array_push($this->back, $t);
+    }
+
+    /**
+     * Splice in multiple elements at hole.  Functional specification
+     * in terms of array_splice:
+     *
+     *      $arr1 = $arr;
+     *      $old1 = array_splice($arr1, $i, $delete, $replacement);
+     *
+     *      list($z, $t) = HTMLPurifier_Zipper::fromArray($arr);
+     *      $t = $z->advance($t, $i);
+     *      list($old2, $t) = $z->splice($t, $delete, $replacement);
+     *      $arr2 = $z->toArray($t);
+     *
+     *      assert($old1 === $old2);
+     *      assert($arr1 === $arr2);
+     *
+     * NB: the absolute index location after this operation is
+     * *unchanged!*
+     *
+     * @param Current contents of hole.
+     */
+    public function splice($t, $delete, $replacement) {
+        // delete
+        $old = array();
+        $r = $t;
+        for ($i = $delete; $i > 0; $i--) {
+            $old[] = $r;
+            $r = $this->delete();
+        }
+        // insert
+        for ($i = count($replacement)-1; $i >= 0; $i--) {
+            $this->insertAfter($r);
+            $r = $replacement[$i];
+        }
+        return array($old, $r);
+    }
+}
diff --git a/library/ezyang/htmlpurifier/package.php b/library/ezyang/htmlpurifier/package.php
new file mode 100644
index 0000000000..bfef93622d
--- /dev/null
+++ b/library/ezyang/htmlpurifier/package.php
@@ -0,0 +1,61 @@
+<?php
+
+set_time_limit(0);
+
+require_once 'PEAR/PackageFileManager2.php';
+require_once 'PEAR/PackageFileManager/File.php';
+PEAR::setErrorHandling(PEAR_ERROR_PRINT);
+$pkg = new PEAR_PackageFileManager2;
+
+$pkg->setOptions(
+    array(
+        'baseinstalldir' => '/',
+        'packagefile' => 'package.xml',
+        'packagedirectory' => realpath(dirname(__FILE__) . '/library'),
+        'filelistgenerator' => 'file',
+        'include' => array('*'),
+        'dir_roles' => array('/' => 'php'), // hack to put *.ser files in the right place
+        'ignore' => array(
+            'HTMLPurifier.standalone.php',
+            'HTMLPurifier.path.php',
+            '*.tar.gz',
+            '*.tgz',
+            'standalone/'
+        ),
+    )
+);
+
+$pkg->setPackage('HTMLPurifier');
+$pkg->setLicense('LGPL', 'http://www.gnu.org/licenses/lgpl.html');
+$pkg->setSummary('Standards-compliant HTML filter');
+$pkg->setDescription(
+    'HTML Purifier is an HTML filter that will remove all malicious code
+    (better known as XSS) with a thoroughly audited, secure yet permissive
+    whitelist and will also make sure your documents are standards
+    compliant.'
+);
+
+$pkg->addMaintainer('lead', 'ezyang', 'Edward Z. Yang', 'admin@htmlpurifier.org', 'yes');
+
+$version = trim(file_get_contents('VERSION'));
+$api_version = substr($version, 0, strrpos($version, '.'));
+
+$pkg->setChannel('htmlpurifier.org');
+$pkg->setAPIVersion($api_version);
+$pkg->setAPIStability('stable');
+$pkg->setReleaseVersion($version);
+$pkg->setReleaseStability('stable');
+
+$pkg->addRelease();
+
+$pkg->setNotes(file_get_contents('WHATSNEW'));
+$pkg->setPackageType('php');
+
+$pkg->setPhpDep('5.0.0');
+$pkg->setPearinstallerDep('1.4.3');
+
+$pkg->generateContents();
+
+$pkg->writePackageFile();
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/phpdoc.ini b/library/ezyang/htmlpurifier/phpdoc.ini
new file mode 100644
index 0000000000..c4c3723538
--- /dev/null
+++ b/library/ezyang/htmlpurifier/phpdoc.ini
@@ -0,0 +1,102 @@
+;; phpDocumentor parse configuration file
+;;
+;; This file is designed to cut down on repetitive typing on the command-line or web interface
+;; You can copy this file to create a number of configuration files that can be used with the
+;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini.  The web
+;; interface will automatically generate a list of .ini files that can be used.
+;;
+;; default.ini is used to generate the online manual at http://www.phpdoc.org/docs
+;;
+;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini
+;;
+;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net>
+;;
+;; WARNING: do not change the name of any command-line parameters, phpDocumentor will ignore them
+
+[Parse Data]
+;; title of all the documentation
+;; legal values: any string
+title = HTML Purifier API Documentation
+
+;; parse files that start with a . like .bash_profile
+;; legal values: true, false
+hidden = false
+
+;; show elements marked @access private in documentation by setting this to on
+;; legal values: on, off
+parseprivate = off
+
+;; parse with javadoc-like description (first sentence is always the short description)
+;; legal values: on, off
+javadocdesc = on
+
+;; add any custom @tags separated by commas here
+;; legal values: any legal tagname separated by commas.
+;customtags = mytag1,mytag2
+
+;; This is only used by the XML:DocBook/peardoc2 converter
+defaultcategoryname = Documentation
+
+;; what is the main package?
+;; legal values: alphanumeric string plus - and _
+defaultpackagename = HTMLPurifier
+
+;; output any parsing information?  set to on for cron jobs
+;; legal values: on
+;quiet = on
+
+;; parse a PEAR-style repository.  Do not turn this on if your project does
+;; not have a parent directory named "pear"
+;; legal values: on/off
+;pear = on
+
+;; where should the documentation be written?
+;; legal values: a legal path
+target = docs/phpdoc
+
+;; Which files should be parsed out as special documentation files, such as README,
+;; INSTALL and CHANGELOG?  This overrides the default files found in
+;; phpDocumentor.ini (this file is not a user .ini file, but the global file)
+readmeinstallchangelog = README, INSTALL, NEWS, WYSIWYG, SLOW, LICENSE, CREDITS
+
+;; limit output to the specified packages, even if others are parsed
+;; legal values: package names separated by commas
+;packageoutput = package1,package2
+
+;; comma-separated list of files to parse
+;; legal values: paths separated by commas
+;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory
+
+;; comma-separated list of directories to parse
+;; legal values: directory paths separated by commas
+;directory = /path1,/path2,.,..,subdirectory
+;directory = /home/jeichorn/cvs/pear
+directory = .
+
+;; template base directory (the equivalent directory of <installdir>/phpDocumentor)
+;templatebase = /path/to/my/templates
+
+;; directory to find any example files in through @example and {@example} tags
+;examplesdir = /path/to/my/templates
+
+;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore
+;; legal values: any wildcard strings separated by commas
+;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/
+ignore = *tests*,*benchmarks*,*docs*,*test-settings.php,*configdoc*,*maintenance*,*smoketests*,*standalone*,*.svn*,*conf*
+
+sourcecode = on
+
+;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format
+;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib,
+;;               HTML:frames:earthli,
+;;               HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,
+;;               HTML:frames:DOM/phphtmllib,HTML:frames:DOM/earthli
+;;               HTML:Smarty:default,HTML:Smarty:PHP,HTML:Smarty:HandS
+;;               PDF:default:default,CHM:default:default,XML:DocBook/peardoc2:default
+output=HTML:frames:default
+
+;; turn this option on if you want highlighted source code for every file
+;; legal values: on/off
+sourcecode = on
+
+; vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/modx.txt b/library/ezyang/htmlpurifier/plugins/modx.txt
new file mode 100644
index 0000000000..0763821b50
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/modx.txt
@@ -0,0 +1,112 @@
+
+MODx Plugin
+
+MODx <http://www.modxcms.com/> is an open source PHP application framework.
+I first came across them in my referrer logs when tillda asked if anyone
+could implement an HTML Purifier plugin.  This forum thread
+<http://modxcms.com/forums/index.php/topic,6604.0.html> eventually resulted
+in the fruition of this plugin that davidm says, "is on top of my favorite
+list."  HTML Purifier goes great with WYSIWYG editors!
+
+
+
+1. Credits
+
+PaulGregory wrote the overall structure of the code.  I added the
+slashes hack.
+
+
+
+2. Install
+
+First, you need to place HTML Purifier library somewhere.  The code here
+assumes that you've placed in MODx's assets/plugins/htmlpurifier (no version
+number).
+
+Log into the manager, and navigate:
+
+Resources > Manage Resources > Plugins tab > New Plugin
+
+Type in a name (probably HTML Purifier), and copy paste this code into the
+textarea:
+
+--------------------------------------------------------------------------------
+$e = &$modx->Event;
+if ($e->name == 'OnBeforeDocFormSave') {
+    global $content;
+
+    include_once '../assets/plugins/htmlpurifier/library/HTMLPurifier.auto.php';
+    $purifier = new HTMLPurifier();
+
+    static $magic_quotes = null;
+    if ($magic_quotes === null) {
+        // this is an ugly hack because this hook hasn't
+        // had the backslashes removed yet when magic_quotes_gpc is on,
+        // but HTMLPurifier must not have the quotes slashed.
+        $magic_quotes = get_magic_quotes_gpc();
+    }
+
+    if ($magic_quotes) $content = stripslashes($content);
+    $content = $purifier->purify($content);
+    if ($magic_quotes) $content = addslashes($content);
+}
+--------------------------------------------------------------------------------
+
+Then navigate to the System Events tab and check "OnBeforeDocFormSave".
+Save the plugin.  HTML Purifier now is integrated!
+
+
+
+3. Making sure it works
+
+You can test HTML Purifier by deliberately putting in crappy HTML and seeing
+whether or not it gets fixed.  A better way is to put in something like this:
+
+<p lang="fr">Il est bon</p>
+
+...and seeing whether or not the content comes out as:
+
+<p lang="fr" xml:lang="fr">Il est bon</p>
+
+(lang to xml:lang synchronization is one of the many features HTML Purifier
+has).
+
+
+
+4. Caveat Emptor
+
+This code does not intercept save requests from the QuickEdit plugin, this may
+be added in a later version.  It also modifies things on save, so there's a
+slight chance that HTML Purifier may make a boo-boo and accidently mess things
+up (the original version is not saved).
+
+Finally, make sure that MODx is using UTF-8.  If you are using, say, a French
+localisation, you may be using Latin-1, if that's the case, configure
+HTML Purifier properly like this:
+
+$config = HTMLPurifier_Config::createDefault();
+$config->set('Core', 'Encoding', 'ISO-8859-1'); // or whatever encoding
+$purifier = new HTMLPurifier($config);
+
+
+
+5. Known Bugs
+
+'rn' characters sometimes mysteriously appear after purification. We are
+currently investigating this issue. See: <http://htmlpurifier.org/phorum/read.php?3,1866>
+
+
+
+6. See Also
+
+A modified version of Jot 1.1.3 is available, which integrates with HTML
+Purifier. You can check it out here: <http://modxcms.com/forums/index.php/topic,25621.msg161970.html>
+
+
+X. Changelog
+
+2008-06-16
+- Updated code to work with 3.1.0 and later
+- Add Known Bugs and See Also section
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/.gitignore b/library/ezyang/htmlpurifier/plugins/phorum/.gitignore
new file mode 100644
index 0000000000..8325e09020
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/.gitignore
@@ -0,0 +1,2 @@
+migrate.php
+htmlpurifier/*
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/Changelog b/library/ezyang/htmlpurifier/plugins/phorum/Changelog
new file mode 100644
index 0000000000..9f939e54ae
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/Changelog
@@ -0,0 +1,27 @@
+Changelog                                         HTMLPurifier : Phorum Mod
+|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
+
+= KEY ====================
+    # Breaks back-compat
+    ! Feature
+    - Bugfix
+      + Sub-comment
+    . Internal change
+==========================
+
+Version 4.0.0 for Phorum 5.2, released July 9, 2009
+# Works only with HTML Purifier 4.0.0
+! Better installation documentation
+- Fixed double encoded quotes
+- Fixed fatal error when migrate.php is blank
+
+Version 3.0.0 for Phorum 5.2, released January 12, 2008
+# WYSIWYG and suppress_message options are now configurable via web
+  interface.
+- Module now compatible with Phorum 5.2, primary bugs were in migration
+  code as well as signature and edit message handling. This module is NOT
+  compatible with Phorum 5.1.
+- Buggy WYSIWYG mode refined
+. AutoFormatParam added to list of default configuration namespaces
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/INSTALL b/library/ezyang/htmlpurifier/plugins/phorum/INSTALL
new file mode 100644
index 0000000000..23c76fc5c6
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/INSTALL
@@ -0,0 +1,84 @@
+
+Install
+    How to install the Phorum HTML Purifier plugin
+
+0. PREREQUISITES
+----------------
+This Phorum module only works on PHP5 and with HTML Purifier 4.0.0
+or later.
+
+1. UNZIP
+--------
+Unzip phorum-htmlpurifier-x.y.z, producing an htmlpurifier folder.
+You've already done this step if you're reading this!
+
+2. MOVE
+-------
+Move the htmlpurifier folder to the mods/ folder of your Phorum
+installation, so the directory structure looks like:
+
+phorum/
+    mods/
+        htmlpurifier/
+            INSTALL - this install file
+            info.txt, ... - the module files
+            htmlpurifier/
+
+3. INSTALL HTML PURIFIER
+------------------------
+Download and unzip HTML Purifier <htmlpurifier.org>. Place the contents of
+the library/ folder in the htmlpurifier/htmlpurifier folder. Your directory
+structure will look like:
+
+phorum/
+    mods/
+        htmlpurifier/
+            htmlpurifier/
+                HTMLPurifier.auto.php
+                ... - other files
+                HTMLPurifier/
+
+Advanced users:
+    If you have HTML Purifier installed elsewhere on your server,
+    all you need is an HTMLPurifier.auto.php file in the library folder which
+    includes the HTMLPurifier.auto.php file in your install.
+
+4. MIGRATE
+----------
+If you're setting up a new Phorum installation, all you need to do is create
+a blank migrate.php file in the htmlpurifier module folder (NOT the library
+folder.
+
+If you have an old Phorum installation and was using BBCode,
+copy migrate.bbcode.php to migrate.php. If you were using a different input
+format, follow the instructions in migrate.bbcode.php to create your own custom
+migrate.php file.
+
+Your directory structure should now look like this:
+
+phorum/
+    mods/
+        htmlpurifier/
+            migrate.php
+
+5. ENABLE
+---------
+Navigate to your Phorum admin panel at http://example.com/phorum/admin.php,
+click on Global Settings > Modules, scroll to "HTML Purifier Phorum Mod" and
+turn it On.
+
+6. MIGRATE SIGNATURES
+---------------------
+If you're setting up a new Phorum installation, skip this step.
+
+If you allowed your users to make signatures, navigate to the module settings
+page of HTML Purifier (Global Settings > Modules > HTML Purifier Phorum Mod >
+Configure), type in "yes" in the "Confirm" box, and press "Migrate."
+
+ONLY DO THIS ONCE! BE SURE TO BACK UP YOUR DATABASE!
+
+7. CONFIGURE
+------------
+Configure using Edit settings. See that page for more information.
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/README b/library/ezyang/htmlpurifier/plugins/phorum/README
new file mode 100644
index 0000000000..0524ed39db
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/README
@@ -0,0 +1,45 @@
+
+HTML Purifier Phorum Mod - Filter your HTML the Standards-Compliant Way!
+
+This Phorum mod enables HTML posting on Phorum.  Under normal circumstances,
+this would cause a huge security risk, but because we are running
+HTML through HTML Purifier, output is guaranteed to be XSS free and
+standards-compliant.
+
+This mod requires HTML input, and previous markup languages need to be
+converted accordingly.  Thus, it is vital that you create a 'migrate.php'
+file that works with your installation. If you're using the built-in
+BBCode formatting, simply move migrate.bbcode.php to that place; for
+other markup languages, consult said file for instructions on how
+to adapt it to your needs.
+
+    -- NOTE -------------------------------------------------
+    You can also run this module in parallel with another
+    formatting module; this module attempts to place itself
+    at the end of the filtering chain. However, if any
+    previous modules produce insecure HTML (for instance,
+    a JavaScript email obfuscator) they will get cleaned.
+
+This module will not work if 'migrate.php' is not created, and an improperly
+made migration file may *CORRUPT* Phorum, so please take your time to
+do this correctly. It should go without saying to *BACKUP YOUR DATABASE*
+before attempting anything here. If no migration is necessary, you can
+simply create a blank migrate.php file. HTML Purifier is smart and will
+not re-migrate already processed messages. However, the original code
+is irretrievably lost (we may change this in the future.)
+
+This module will not automatically migrate user signatures, because this
+process may take a long time. After installing the HTML Purifier module and
+then configuring 'migrate.php', navigate to Settings and click 'Migrate
+Signatures' to migrate all user signatures to HTML.
+
+All of HTML Purifier's usual functions are configurable via the mod settings
+page. If you require custom configuration, create config.php file in
+the mod directory that edits a $config variable. Be sure, also, to
+set $PHORUM['mod_htmlpurifier']['wysiwyg'] to TRUE if you are using a
+WYSIWYG editor (you can do this through a common hook or the web
+configuration form).
+
+Visit HTML Purifier at <http://htmlpurifier.org/>.
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/config.default.php b/library/ezyang/htmlpurifier/plugins/phorum/config.default.php
new file mode 100644
index 0000000000..e047c0b423
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/config.default.php
@@ -0,0 +1,57 @@
+<?php
+
+if(!defined("PHORUM")) exit;
+
+// default HTML Purifier configuration settings
+$config->set('HTML.Allowed',
+  // alphabetically sorted
+'a[href|title]
+abbr[title]
+acronym[title]
+b
+blockquote[cite]
+br
+caption
+cite
+code
+dd
+del
+dfn
+div
+dl
+dt
+em
+i
+img[src|alt|title|class]
+ins
+kbd
+li
+ol
+p
+pre
+s
+strike
+strong
+sub
+sup
+table
+tbody
+td
+tfoot
+th
+thead
+tr
+tt
+u
+ul
+var');
+$config->set('AutoFormat.AutoParagraph', true);
+$config->set('AutoFormat.Linkify', true);
+$config->set('HTML.Doctype', 'XHTML 1.0 Transitional');
+$config->set('Core.AggressivelyFixLt', true);
+$config->set('Core.Encoding', $GLOBALS['PHORUM']['DATA']['CHARSET']); // we'll change this eventually
+if (strtolower($GLOBALS['PHORUM']['DATA']['CHARSET']) !== 'utf-8') {
+  $config->set('Core.EscapeNonASCIICharacters', true);
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/htmlpurifier.php b/library/ezyang/htmlpurifier/plugins/phorum/htmlpurifier.php
new file mode 100644
index 0000000000..f66d8c36cd
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/htmlpurifier.php
@@ -0,0 +1,316 @@
+<?php
+
+/**
+ * HTML Purifier Phorum Mod. Filter your HTML the Standards-Compliant Way!
+ *
+ * This Phorum mod enables users to post raw HTML into Phorum.  But never
+ * fear: with the help of HTML Purifier, this HTML will be beat into
+ * de-XSSed and standards-compliant form, safe for general consumption.
+ * It is not recommended, but possible to run this mod in parallel
+ * with other formatters (in short, please DISABLE the BBcode mod).
+ *
+ * For help migrating from your previous markup language to pure HTML
+ * please check the migrate.bbcode.php file.
+ *
+ * If you'd like to use this with a WYSIWYG editor, make sure that
+ * editor sets $PHORUM['mod_htmlpurifier']['wysiwyg'] to true. Otherwise,
+ * administrators who need to edit other people's comments may be at
+ * risk for some nasty attacks.
+ *
+ * Tested with Phorum 5.2.11.
+ */
+
+// Note: Cache data is base64 encoded because Phorum insists on flinging
+// to the user and expecting it to come back unharmed, newlines and
+// all, which ain't happening. It's slower, it takes up more space, but
+// at least it won't get mutilated
+
+/**
+ * Purifies a data array
+ */
+function phorum_htmlpurifier_format($data)
+{
+    $PHORUM = $GLOBALS["PHORUM"];
+
+    $purifier =& HTMLPurifier::getInstance();
+    $cache_serial = $PHORUM['mod_htmlpurifier']['body_cache_serial'];
+
+    foreach($data as $message_id => $message){
+        if(isset($message['body'])) {
+
+            if ($message_id) {
+                // we're dealing with a real message, not a fake, so
+                // there a number of shortcuts that can be taken
+
+                if (isset($message['meta']['htmlpurifier_light'])) {
+                    // format hook was called outside of Phorum's normal
+                    // functions, do the abridged purification
+                    $data[$message_id]['body'] = $purifier->purify($message['body']);
+                    continue;
+                }
+
+                if (!empty($PHORUM['args']['purge'])) {
+                    // purge the cache, must be below the following if
+                    unset($message['meta']['body_cache']);
+                }
+
+                if (
+                    isset($message['meta']['body_cache']) &&
+                    isset($message['meta']['body_cache_serial']) &&
+                    $message['meta']['body_cache_serial'] == $cache_serial
+                ) {
+                    // cached version is present, bail out early
+                    $data[$message_id]['body'] = base64_decode($message['meta']['body_cache']);
+                    continue;
+                }
+            }
+
+            // migration might edit this array, that's why it's defined
+            // so early
+            $updated_message = array();
+
+            // create the $body variable
+            if (
+                $message_id && // message must be real to migrate
+                !isset($message['meta']['body_cache_serial'])
+            ) {
+                // perform migration
+                $fake_data = array();
+                list($signature, $edit_message) = phorum_htmlpurifier_remove_sig_and_editmessage($message);
+                $fake_data[$message_id] = $message;
+                $fake_data = phorum_htmlpurifier_migrate($fake_data);
+                $body = $fake_data[$message_id]['body'];
+                $body = str_replace("<phorum break>\n", "\n", $body);
+                $updated_message['body'] = $body; // save it in
+                $body .= $signature . $edit_message; // add it back in
+            } else {
+                // reverse Phorum's pre-processing
+                $body = $message['body'];
+                // order is important
+                $body = str_replace("<phorum break>\n", "\n", $body);
+                $body = str_replace(array('&lt;','&gt;','&amp;', '&quot;'), array('<','>','&','"'), $body);
+                if (!$message_id && defined('PHORUM_CONTROL_CENTER')) {
+                    // we're in control.php, so it was double-escaped
+                    $body = str_replace(array('&lt;','&gt;','&amp;', '&quot;'), array('<','>','&','"'), $body);
+                }
+            }
+
+            $body = $purifier->purify($body);
+
+            // dynamically update the cache (MUST BE DONE HERE!)
+            // this is inefficient because it's one db call per
+            // cache miss, but once the cache is in place things are
+            // a lot zippier.
+
+            if ($message_id) { // make sure it's not a fake id
+                $updated_message['meta'] = $message['meta'];
+                $updated_message['meta']['body_cache'] = base64_encode($body);
+                $updated_message['meta']['body_cache_serial'] = $cache_serial;
+                phorum_db_update_message($message_id, $updated_message);
+            }
+
+            // must not get overloaded until after we cache it, otherwise
+            // we'll inadvertently change the original text
+            $data[$message_id]['body'] = $body;
+
+        }
+    }
+
+    return $data;
+}
+
+// -----------------------------------------------------------------------
+// This is fragile code, copied from read.php:596 (Phorum 5.2.6). Please
+// keep this code in-sync with Phorum
+
+/**
+ * Generates a signature based on a message array
+ */
+function phorum_htmlpurifier_generate_sig($row)
+{
+    $phorum_sig = '';
+    if(isset($row["user"]["signature"])
+       && isset($row['meta']['show_signature']) && $row['meta']['show_signature']==1){
+           $phorum_sig=trim($row["user"]["signature"]);
+           if(!empty($phorum_sig)){
+               $phorum_sig="\n\n$phorum_sig";
+           }
+    }
+    return $phorum_sig;
+}
+
+/**
+ * Generates an edit message based on a message array
+ */
+function phorum_htmlpurifier_generate_editmessage($row)
+{
+    $PHORUM = $GLOBALS['PHORUM'];
+    $editmessage = '';
+    if(isset($row['meta']['edit_count']) && $row['meta']['edit_count'] > 0) {
+        $editmessage = str_replace ("%count%", $row['meta']['edit_count'], $PHORUM["DATA"]["LANG"]["EditedMessage"]);
+        $editmessage = str_replace ("%lastedit%", phorum_date($PHORUM["short_date_time"],$row['meta']['edit_date']),  $editmessage);
+        $editmessage = str_replace ("%lastuser%", $row['meta']['edit_username'],  $editmessage);
+        $editmessage = "\n\n\n\n$editmessage";
+    }
+    return $editmessage;
+}
+
+// End fragile code
+// -----------------------------------------------------------------------
+
+/**
+ * Removes the signature and edit message from a message
+ * @param $row Message passed by reference
+ */
+function phorum_htmlpurifier_remove_sig_and_editmessage(&$row)
+{
+    $signature = phorum_htmlpurifier_generate_sig($row);
+    $editmessage = phorum_htmlpurifier_generate_editmessage($row);
+    $replacements = array();
+    // we need to remove add <phorum break> as that is the form these
+    // extra bits are in.
+    if ($signature) $replacements[str_replace("\n", "<phorum break>\n", $signature)] = '';
+    if ($editmessage) $replacements[str_replace("\n", "<phorum break>\n", $editmessage)] = '';
+    $row['body'] = strtr($row['body'], $replacements);
+    return array($signature, $editmessage);
+}
+
+/**
+ * Indicate that data is fully HTML and not from migration, invalidate
+ * previous caches
+ * @note This function could generate the actual cache entries, but
+ *       since there's data missing that must be deferred to the first read
+ */
+function phorum_htmlpurifier_posting($message)
+{
+    $PHORUM = $GLOBALS["PHORUM"];
+    unset($message['meta']['body_cache']); // invalidate the cache
+    $message['meta']['body_cache_serial'] = $PHORUM['mod_htmlpurifier']['body_cache_serial'];
+    return $message;
+}
+
+/**
+ * Overload quoting mechanism to prevent default, mail-style quote from happening
+ */
+function phorum_htmlpurifier_quote($array)
+{
+    $PHORUM = $GLOBALS["PHORUM"];
+    $purifier =& HTMLPurifier::getInstance();
+    $text = $purifier->purify($array[1]);
+    $source = htmlspecialchars($array[0]);
+    return "<blockquote cite=\"$source\">\n$text\n</blockquote>";
+}
+
+/**
+ * Ensure that our format hook is processed last. Also, loads the library.
+ * @credits <http://secretsauce.phorum.org/snippets/make_bbcode_last_formatter.php.txt>
+ */
+function phorum_htmlpurifier_common()
+{
+    require_once(dirname(__FILE__).'/htmlpurifier/HTMLPurifier.auto.php');
+    require(dirname(__FILE__).'/init-config.php');
+
+    $config = phorum_htmlpurifier_get_config();
+    HTMLPurifier::getInstance($config);
+
+    // increment revision.txt if you want to invalidate the cache
+    $GLOBALS['PHORUM']['mod_htmlpurifier']['body_cache_serial'] = $config->getSerial();
+
+    // load migration
+    if (file_exists(dirname(__FILE__) . '/migrate.php')) {
+        include(dirname(__FILE__) . '/migrate.php');
+    } else {
+        echo '<strong>Error:</strong> No migration path specified for HTML Purifier, please check
+        <tt>modes/htmlpurifier/migrate.bbcode.php</tt> for instructions on
+        how to migrate from your previous markup language.';
+        exit;
+    }
+
+    if (!function_exists('phorum_htmlpurifier_migrate')) {
+        // Dummy function
+        function phorum_htmlpurifier_migrate($data) {return $data;}
+    }
+
+}
+
+/**
+ * Pre-emptively performs purification if it looks like a WYSIWYG editor
+ * is being used
+ */
+function phorum_htmlpurifier_before_editor($message)
+{
+    if (!empty($GLOBALS['PHORUM']['mod_htmlpurifier']['wysiwyg'])) {
+        if (!empty($message['body'])) {
+            $body = $message['body'];
+            // de-entity-ize contents
+            $body = str_replace(array('&lt;','&gt;','&amp;'), array('<','>','&'), $body);
+            $purifier =& HTMLPurifier::getInstance();
+            $body = $purifier->purify($body);
+            // re-entity-ize contents
+            $body = htmlspecialchars($body, ENT_QUOTES, $GLOBALS['PHORUM']['DATA']['CHARSET']);
+            $message['body'] = $body;
+        }
+    }
+    return $message;
+}
+
+function phorum_htmlpurifier_editor_after_subject()
+{
+    // don't show this message if it's a WYSIWYG editor, since it will
+    // then be handled automatically
+    if (!empty($GLOBALS['PHORUM']['mod_htmlpurifier']['wysiwyg'])) {
+        $i = $GLOBALS['PHORUM']['DATA']['MODE'];
+        if ($i == 'quote' || $i == 'edit' || $i == 'moderation') {
+          ?>
+          <div>
+            <p>
+              <strong>Notice:</strong> HTML has been scrubbed for your safety.
+              If you would like to see the original, turn off WYSIWYG mode
+              (consult your administrator for details.)
+            </p>
+          </div>
+          <?php
+        }
+        return;
+    }
+    if (!empty($GLOBALS['PHORUM']['mod_htmlpurifier']['suppress_message'])) return;
+    ?><div class="htmlpurifier-help">
+    <p>
+        <strong>HTML input</strong> is enabled. Make sure you escape all HTML and
+        angled brackets with <code>&amp;lt;</code> and <code>&amp;gt;</code>.
+    </p><?php
+            $purifier =& HTMLPurifier::getInstance();
+            $config = $purifier->config;
+            if ($config->get('AutoFormat.AutoParagraph')) {
+                ?><p>
+                    <strong>Auto-paragraphing</strong> is enabled. Double
+                    newlines will be converted to paragraphs; for single
+                    newlines, use the <code>pre</code> tag.
+                </p><?php
+            }
+            $html_definition = $config->getDefinition('HTML');
+            $allowed = array();
+            foreach ($html_definition->info as $name => $x) $allowed[] = "<code>$name</code>";
+            sort($allowed);
+            $allowed_text = implode(', ', $allowed);
+            ?><p><strong>Allowed tags:</strong> <?php
+            echo $allowed_text;
+            ?>.</p><?php
+        ?>
+    </p>
+    <p>
+        For inputting literal code such as HTML and PHP for display, use
+        CDATA tags to auto-escape your angled brackets, and <code>pre</code>
+        to preserve newlines:
+    </p>
+    <pre>&lt;pre&gt;&lt;![CDATA[
+<em>Place code here</em>
+]]&gt;&lt;/pre&gt;</pre>
+    <p>
+        Power users, you can hide this notice with:
+        <pre>.htmlpurifier-help {display:none;}</pre>
+    </p>
+    </div><?php
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/info.txt b/library/ezyang/htmlpurifier/plugins/phorum/info.txt
new file mode 100644
index 0000000000..7234654901
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/info.txt
@@ -0,0 +1,18 @@
+title:   HTML Purifier Phorum Mod
+desc:    This module enables standards-compliant HTML filtering on Phorum. Please check migrate.bbcode.php before enabling this mod.
+author:  Edward Z. Yang
+url:     http://htmlpurifier.org/
+version: 4.0.0
+
+hook:  format|phorum_htmlpurifier_format
+hook:  quote|phorum_htmlpurifier_quote
+hook:  posting_custom_action|phorum_htmlpurifier_posting
+hook:  common|phorum_htmlpurifier_common
+hook:  before_editor|phorum_htmlpurifier_before_editor
+hook:  tpl_editor_after_subject|phorum_htmlpurifier_editor_after_subject
+
+# This module is meant to be a drop-in for bbcode, so make it run last.
+priority: run module after *
+priority: run hook format after *
+
+    vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/init-config.php b/library/ezyang/htmlpurifier/plugins/phorum/init-config.php
new file mode 100644
index 0000000000..e19787b4bc
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/init-config.php
@@ -0,0 +1,30 @@
+<?php
+
+/**
+ * Initializes the appropriate configuration from either a PHP file
+ * or a module configuration value
+ * @return Instance of HTMLPurifier_Config
+ */
+function phorum_htmlpurifier_get_config($default = false)
+{
+    global $PHORUM;
+    $config_exists = phorum_htmlpurifier_config_file_exists();
+    if ($default || $config_exists || !isset($PHORUM['mod_htmlpurifier']['config'])) {
+        $config = HTMLPurifier_Config::createDefault();
+        include(dirname(__FILE__) . '/config.default.php');
+        if ($config_exists) {
+            include(dirname(__FILE__) . '/config.php');
+        }
+        unset($PHORUM['mod_htmlpurifier']['config']); // unnecessary
+    } else {
+        $config = HTMLPurifier_Config::create($PHORUM['mod_htmlpurifier']['config']);
+    }
+    return $config;
+}
+
+function phorum_htmlpurifier_config_file_exists()
+{
+    return file_exists(dirname(__FILE__) . '/config.php');
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/migrate.bbcode.php b/library/ezyang/htmlpurifier/plugins/phorum/migrate.bbcode.php
new file mode 100644
index 0000000000..0d09194556
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/migrate.bbcode.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * This file is responsible for migrating from a specific markup language
+ * like BBCode or Markdown to HTML. WARNING: THIS PROCESS IS NOT REVERSIBLE
+ *
+ * Copy this file to 'migrate.php' and it will automatically work for
+ * BBCode; you may need to tweak this a little to get it to work for other
+ * languages (usually, just replace the include name and the function name).
+ *
+ * If you do NOT want to have any migration performed (for instance, you
+ * are installing the module on a new forum with no posts), simply remove
+ * phorum_htmlpurifier_migrate() function. You still need migrate.php
+ * present, otherwise the module won't work. This ensures that the user
+ * explicitly says, "No, I do not need to migrate."
+ */
+
+if(!defined("PHORUM")) exit;
+
+require_once(dirname(__FILE__) . "/../bbcode/bbcode.php");
+
+/**
+ * 'format' hook style function that will be called to convert
+ * legacy markup into HTML.
+ */
+function phorum_htmlpurifier_migrate($data)
+{
+    return phorum_mod_bbcode_format($data); // bbcode's 'format' hook
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/settings.php b/library/ezyang/htmlpurifier/plugins/phorum/settings.php
new file mode 100644
index 0000000000..8158f02823
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/settings.php
@@ -0,0 +1,64 @@
+<?php
+
+// based off of BBCode's settings file
+
+/**
+ * HTML Purifier Phorum mod settings configuration. This provides
+ * a convenient web-interface for editing the most common HTML Purifier
+ * configuration directives. You can also specify custom configuration
+ * by creating a 'config.php' file.
+ */
+
+if(!defined("PHORUM_ADMIN")) exit;
+
+// error reporting is good!
+error_reporting(E_ALL ^ E_NOTICE);
+
+// load library and other paraphenalia
+require_once './include/admin/PhorumInputForm.php';
+require_once (dirname(__FILE__) . '/htmlpurifier/HTMLPurifier.auto.php');
+require_once (dirname(__FILE__) . '/init-config.php');
+require_once (dirname(__FILE__) . '/settings/migrate-sigs-form.php');
+require_once (dirname(__FILE__) . '/settings/migrate-sigs.php');
+require_once (dirname(__FILE__) . '/settings/form.php');
+require_once (dirname(__FILE__) . '/settings/save.php');
+
+// define friendly configuration directives. you can expand this array
+// to get more web-definable directives
+$PHORUM['mod_htmlpurifier']['directives'] = array(
+    'URI.Host', // auto-detectable
+    'URI.DisableExternal',
+    'URI.DisableExternalResources',
+    'URI.DisableResources',
+    'URI.Munge',
+    'URI.HostBlacklist',
+    'URI.Disable',
+    'HTML.TidyLevel',
+    'HTML.Doctype', // auto-detectable
+    'HTML.Allowed',
+    'AutoFormat',
+    '-AutoFormat.Custom',
+    'AutoFormatParam',
+    'Output.TidyFormat',
+);
+
+// lower this setting if you're getting time outs/out of memory
+$PHORUM['mod_htmlpurifier']['migrate-sigs-increment'] = 100;
+
+if (isset($_POST['reset'])) {
+    unset($PHORUM['mod_htmlpurifier']['config']);
+}
+
+if ($offset = phorum_htmlpurifier_migrate_sigs_check()) {
+    // migrate signatures
+    phorum_htmlpurifier_migrate_sigs($offset);
+} elseif(!empty($_POST)){
+    // save settings
+    phorum_htmlpurifier_save_settings();
+}
+
+phorum_htmlpurifier_show_migrate_sigs_form();
+echo '<br />';
+phorum_htmlpurifier_show_form();
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/settings/form.php b/library/ezyang/htmlpurifier/plugins/phorum/settings/form.php
new file mode 100644
index 0000000000..9b6ad5f39e
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/settings/form.php
@@ -0,0 +1,95 @@
+<?php
+
+function phorum_htmlpurifier_show_form()
+{
+    if (phorum_htmlpurifier_config_file_exists()) {
+        phorum_htmlpurifier_show_config_info();
+        return;
+    }
+
+    global $PHORUM;
+
+    $config = phorum_htmlpurifier_get_config();
+
+    $frm = new PhorumInputForm ("", "post", "Save");
+    $frm->hidden("module", "modsettings");
+    $frm->hidden("mod", "htmlpurifier"); // this is the directory name that the Settings file lives in
+
+    if (!empty($error)){
+        echo "$error<br />";
+    }
+
+    $frm->addbreak("Edit settings for the HTML Purifier module");
+
+    $frm->addMessage('<p>The box below sets <code>$PHORUM[\'mod_htmlpurifier\'][\'wysiwyg\']</code>.
+    When checked, contents sent for edit are now purified and the
+    informative message is disabled. If your WYSIWYG editor is disabled for
+    admin edits, you can safely keep this unchecked.</p>');
+    $frm->addRow('Use WYSIWYG?', $frm->checkbox('wysiwyg', '1', '', $PHORUM['mod_htmlpurifier']['wysiwyg']));
+
+    $frm->addMessage('<p>The box below sets <code>$PHORUM[\'mod_htmlpurifier\'][\'suppress_message\']</code>,
+    which removes the big how-to use
+    HTML Purifier message.</p>');
+    $frm->addRow('Suppress information?', $frm->checkbox('suppress_message', '1', '', $PHORUM['mod_htmlpurifier']['suppress_message']));
+
+    $frm->addMessage('<p>Click on directive links to read what each option does
+    (links do not open in new windows).</p>
+    <p>For more flexibility (for instance, you want to edit the full
+    range of configuration directives), you can create a <tt>config.php</tt>
+    file in your <tt>mods/htmlpurifier/</tt> directory. Doing so will,
+    however, make the web configuration interface unavailable.</p>');
+
+    require_once 'HTMLPurifier/Printer/ConfigForm.php';
+    $htmlpurifier_form = new HTMLPurifier_Printer_ConfigForm('config', 'http://htmlpurifier.org/live/configdoc/plain.html#%s');
+    $htmlpurifier_form->setTextareaDimensions(23, 7); // widen a little, since we have space
+
+    $frm->addMessage($htmlpurifier_form->render(
+        $config, $PHORUM['mod_htmlpurifier']['directives'], false));
+
+    $frm->addMessage("<strong>Warning: Changing HTML Purifier's configuration will invalidate
+      the cache. Expect to see a flurry of database activity after you change
+      any of these settings.</strong>");
+
+    $frm->addrow('Reset to defaults:', $frm->checkbox("reset", "1", "", false));
+
+    // hack to include extra styling
+    echo '<style type="text/css">' . $htmlpurifier_form->getCSS() . '
+    .hp-config {margin-left:auto;margin-right:auto;}
+    </style>';
+    $js = $htmlpurifier_form->getJavaScript();
+    echo '<script type="text/javascript">'."<!--\n$js\n//-->".'</script>';
+
+    $frm->show();
+}
+
+function phorum_htmlpurifier_show_config_info()
+{
+    global $PHORUM;
+
+    // update mod_htmlpurifier for housekeeping
+    phorum_htmlpurifier_commit_settings();
+
+    // politely tell user how to edit settings manually
+?>
+        <div class="input-form-td-break">How to edit settings for HTML Purifier module</div>
+        <p>
+          A <tt>config.php</tt> file exists in your <tt>mods/htmlpurifier/</tt>
+          directory. This file contains your custom configuration: in order to
+          change it, please navigate to that file and edit it accordingly.
+          You can also set <code>$GLOBALS['PHORUM']['mod_htmlpurifier']['wysiwyg']</code>
+          or <code>$GLOBALS['PHORUM']['mod_htmlpurifier']['suppress_message']</code>
+        </p>
+        <p>
+          To use the web interface, delete <tt>config.php</tt> (or rename it to
+          <tt>config.php.bak</tt>).
+        </p>
+        <p>
+          <strong>Warning: Changing HTML Purifier's configuration will invalidate
+          the cache. Expect to see a flurry of database activity after you change
+          any of these settings.</strong>
+        </p>
+<?php
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs-form.php b/library/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs-form.php
new file mode 100644
index 0000000000..abea3b51d7
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs-form.php
@@ -0,0 +1,22 @@
+<?php
+
+function phorum_htmlpurifier_show_migrate_sigs_form()
+{
+    $frm = new PhorumInputForm ('', "post", "Migrate");
+    $frm->hidden("module", "modsettings");
+    $frm->hidden("mod", "htmlpurifier");
+    $frm->hidden("migrate-sigs", "1");
+    $frm->addbreak("Migrate user signatures to HTML");
+    $frm->addMessage('This operation will migrate your users signatures
+        to HTML. <strong>This process is irreversible and must only be performed once.</strong>
+        Type in yes in the confirmation field to migrate.');
+    if (!file_exists(dirname(__FILE__) . '/../migrate.php')) {
+        $frm->addMessage('Migration file does not exist, cannot migrate signatures.
+            Please check <tt>migrate.bbcode.php</tt> on how to create an appropriate file.');
+    } else {
+        $frm->addrow('Confirm:', $frm->text_box("confirmation", ""));
+    }
+    $frm->show();
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs.php b/library/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs.php
new file mode 100644
index 0000000000..5ea9cd0b81
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/settings/migrate-sigs.php
@@ -0,0 +1,79 @@
+<?php
+
+function phorum_htmlpurifier_migrate_sigs_check()
+{
+    global $PHORUM;
+    $offset = 0;
+    if (!empty($_POST['migrate-sigs'])) {
+        if (!isset($_POST['confirmation']) || strtolower($_POST['confirmation']) !== 'yes') {
+            echo 'Invalid confirmation code.';
+            exit;
+        }
+        $PHORUM['mod_htmlpurifier']['migrate-sigs'] = true;
+        phorum_db_update_settings(array("mod_htmlpurifier"=>$PHORUM["mod_htmlpurifier"]));
+        $offset = 1;
+    } elseif (!empty($_GET['migrate-sigs']) && $PHORUM['mod_htmlpurifier']['migrate-sigs']) {
+        $offset = (int) $_GET['migrate-sigs'];
+    }
+    return $offset;
+}
+
+function phorum_htmlpurifier_migrate_sigs($offset)
+{
+    global $PHORUM;
+
+    if(!$offset) return; // bail out quick if $offset == 0
+
+    // theoretically, we could get rid of this multi-request
+    // doo-hickery if safe mode is off
+    @set_time_limit(0); // attempt to let this run
+    $increment = $PHORUM['mod_htmlpurifier']['migrate-sigs-increment'];
+
+    require_once(dirname(__FILE__) . '/../migrate.php');
+    // migrate signatures
+    // do this in batches so we don't run out of time/space
+    $end = $offset + $increment;
+    $user_ids = array();
+    for ($i = $offset; $i < $end; $i++) {
+        $user_ids[] = $i;
+    }
+    $userinfos = phorum_db_user_get_fields($user_ids, 'signature');
+    foreach ($userinfos as $i => $user) {
+        if (empty($user['signature'])) continue;
+        $sig = $user['signature'];
+        // perform standard Phorum processing on the sig
+        $sig = str_replace(array("&","<",">"), array("&amp;","&lt;","&gt;"), $sig);
+        $sig = preg_replace("/<((http|https|ftp):\/\/[a-z0-9;\/\?:@=\&\$\-_\.\+!*'\(\),~%]+?)>/i", "$1", $sig);
+        // prepare fake data to pass to migration function
+        $fake_data = array(array("author"=>"", "email"=>"", "subject"=>"", 'body' => $sig));
+        list($fake_message) = phorum_htmlpurifier_migrate($fake_data);
+        $user['signature'] = $fake_message['body'];
+        if (!phorum_api_user_save($user)) {
+            exit('Error while saving user data');
+        }
+    }
+    unset($userinfos); // free up memory
+
+    // query for highest ID in database
+    $type = $PHORUM['DBCONFIG']['type'];
+    $sql = "select MAX(user_id) from {$PHORUM['user_table']}";
+    $row = phorum_db_interact(DB_RETURN_ROW, $sql);
+    $top_id = (int) $row[0];
+
+    $offset += $increment;
+    if ($offset > $top_id) { // test for end condition
+        echo 'Migration finished';
+        $PHORUM['mod_htmlpurifier']['migrate-sigs'] = false;
+        phorum_htmlpurifier_commit_settings();
+        return true;
+    }
+    $host  = $_SERVER['HTTP_HOST'];
+    $uri   = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
+    $extra = 'admin.php?module=modsettings&mod=htmlpurifier&migrate-sigs=' . $offset;
+    // relies on output buffering to work
+    header("Location: http://$host$uri/$extra");
+    exit;
+
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/plugins/phorum/settings/save.php b/library/ezyang/htmlpurifier/plugins/phorum/settings/save.php
new file mode 100644
index 0000000000..2aefaf83a0
--- /dev/null
+++ b/library/ezyang/htmlpurifier/plugins/phorum/settings/save.php
@@ -0,0 +1,29 @@
+<?php
+
+function phorum_htmlpurifier_save_settings()
+{
+    global $PHORUM;
+    if (phorum_htmlpurifier_config_file_exists()) {
+        echo "Cannot update settings, <code>mods/htmlpurifier/config.php</code> already exists. To change
+        settings, edit that file. To use the web form, delete that file.<br />";
+    } else {
+        $config = phorum_htmlpurifier_get_config(true);
+        if (!isset($_POST['reset'])) $config->mergeArrayFromForm($_POST, 'config', $PHORUM['mod_htmlpurifier']['directives']);
+        $PHORUM['mod_htmlpurifier']['config'] = $config->getAll();
+    }
+    $PHORUM['mod_htmlpurifier']['wysiwyg'] = !empty($_POST['wysiwyg']);
+    $PHORUM['mod_htmlpurifier']['suppress_message'] = !empty($_POST['suppress_message']);
+    if(!phorum_htmlpurifier_commit_settings()){
+        $error="Database error while updating settings.";
+    } else {
+        echo "Settings Updated<br />";
+    }
+}
+
+function phorum_htmlpurifier_commit_settings()
+{
+    global $PHORUM;
+    return phorum_db_update_settings(array("mod_htmlpurifier"=>$PHORUM["mod_htmlpurifier"]));
+}
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/release1-update.php b/library/ezyang/htmlpurifier/release1-update.php
new file mode 100644
index 0000000000..834d385676
--- /dev/null
+++ b/library/ezyang/htmlpurifier/release1-update.php
@@ -0,0 +1,110 @@
+<?php
+
+// release script
+// PHP 5.0 only
+
+if (php_sapi_name() != 'cli') {
+    echo 'Release script cannot be called from web-browser.';
+    exit;
+}
+
+if (!isset($argv[1])) {
+    echo
+'php release.php [version]
+    HTML Purifier release script
+';
+    exit;
+}
+
+$version = trim($argv[1]);
+
+// Bump version numbers:
+
+// ...in VERSION
+file_put_contents('VERSION', $version);
+
+// ...in NEWS
+if ($is_dev = (strpos($version, 'dev') === false)) {
+  $date = date('Y-m-d');
+  $news_c = str_replace(
+      $l = "$version, unknown release date",
+      "$version, released $date",
+      file_get_contents('NEWS'),
+      $c
+  );
+  if (!$c) {
+      echo 'Could not update NEWS, missing ' . $l . PHP_EOL;
+      exit;
+  } elseif ($c > 1) {
+      echo 'More than one release declaration in NEWS replaced' . PHP_EOL;
+      exit;
+  }
+  file_put_contents('NEWS', $news_c);
+}
+
+// ...in Doxyfile
+$doxyfile_c = preg_replace(
+    '/(?<=PROJECT_NUMBER {9}= )[^\s]+/m', // brittle
+    $version,
+    file_get_contents('Doxyfile'),
+    1, $c
+);
+if (!$c) {
+    echo 'Could not update Doxyfile, missing PROJECT_NUMBER.' . PHP_EOL;
+    exit;
+}
+file_put_contents('Doxyfile', $doxyfile_c);
+
+// ...in HTMLPurifier.php
+$htmlpurifier_c = file_get_contents('library/HTMLPurifier.php');
+$htmlpurifier_c = preg_replace(
+    '/HTML Purifier .+? - /',
+    "HTML Purifier $version - ",
+    $htmlpurifier_c,
+    1, $c
+);
+if (!$c) {
+    echo 'Could not update HTMLPurifier.php, missing HTML Purifier [version] header.' . PHP_EOL;
+    exit;
+}
+$htmlpurifier_c = preg_replace(
+    '/public \$version = \'.+?\';/',
+    "public \$version = '$version';",
+    $htmlpurifier_c,
+    1, $c
+);
+if (!$c) {
+    echo 'Could not update HTMLPurifier.php, missing public $version.' . PHP_EOL;
+    exit;
+}
+$htmlpurifier_c = preg_replace(
+    '/const VERSION = \'.+?\';/',
+    "const VERSION = '$version';",
+    $htmlpurifier_c,
+    1, $c
+);
+if (!$c) {
+    echo 'Could not update HTMLPurifier.php, missing const $version.' . PHP_EOL;
+    exit;
+}
+file_put_contents('library/HTMLPurifier.php', $htmlpurifier_c);
+
+$config_c = file_get_contents('library/HTMLPurifier/Config.php');
+$config_c = preg_replace(
+    '/public \$version = \'.+?\';/',
+    "public \$version = '$version';",
+    $config_c,
+    1, $c
+);
+if (!$c) {
+    echo 'Could not update Config.php, missing public $version.' . PHP_EOL;
+    exit;
+}
+file_put_contents('library/HTMLPurifier/Config.php', $config_c);
+
+passthru('php maintenance/flush.php');
+
+if ($is_dev) echo "Review changes, write something in WHATSNEW and FOCUS, and then commit with log 'Release $version.'" . PHP_EOL;
+else echo "Numbers updated to dev, no other modifications necessary!";
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/release2-tag.php b/library/ezyang/htmlpurifier/release2-tag.php
new file mode 100644
index 0000000000..25e5300d81
--- /dev/null
+++ b/library/ezyang/htmlpurifier/release2-tag.php
@@ -0,0 +1,22 @@
+<?php
+
+// Tags releases
+
+if (php_sapi_name() != 'cli') {
+    echo 'Release script cannot be called from web-browser.';
+    exit;
+}
+
+require 'svn.php';
+
+$svn_info = my_svn_info('.');
+
+$version = trim(file_get_contents('VERSION'));
+
+$trunk_url  = $svn_info['Repository Root'] . '/htmlpurifier/trunk';
+$trunk_tag_url  = $svn_info['Repository Root'] . '/htmlpurifier/tags/' . $version;
+
+echo "Tagging trunk to tags/$version...";
+passthru("svn copy --message \"Tag $version release.\" $trunk_url $trunk_tag_url");
+
+// vim: et sw=4 sts=4
diff --git a/library/ezyang/htmlpurifier/test-settings.sample.php b/library/ezyang/htmlpurifier/test-settings.sample.php
new file mode 100644
index 0000000000..886b974867
--- /dev/null
+++ b/library/ezyang/htmlpurifier/test-settings.sample.php
@@ -0,0 +1,76 @@
+<?php
+
+// ATTENTION! DO NOT EDIT THIS FILE!
+// This file is necessary to run the unit tests and profiling scripts.
+// Please copy it to 'test-settings.php' and make the necessary edits.
+
+// Note: The only external library you *need* is SimpleTest; everything else
+//       is optional.
+
+// We've got a lot of tests, so we recommend turning the limit off.
+set_time_limit(0);
+
+// Turning off output buffering will prevent mysterious errors from core dumps.
+$data = @ob_get_clean();
+if ($data !== false && $data !== '') {
+    echo "Output buffer contains data [".urlencode($data)."]\n";
+    exit;
+}
+
+// -----------------------------------------------------------------------------
+// REQUIRED SETTINGS
+
+// Note on running SimpleTest:
+//      Because HTML Purifier is PHP5-only and E_STRICT compliant, SimpleTest
+//      1.0.1 will not work; you need to run SimpleTest off its trunk using:
+//
+//        $ svn co https://simpletest.svn.sourceforge.net/svnroot/simpletest/simpletest/trunk simpletest
+//
+//      If SimpleTest is borked with HTML Purifier, please contact me or
+//      the SimpleTest devs; I am a developer for SimpleTest so I should be
+//      able to quickly assess a fix. SimpleTest's problem is my problem!
+
+// Where is SimpleTest located? Remember to include a trailing slash!
+$simpletest_location = '/path/to/simpletest/';
+
+// -----------------------------------------------------------------------------
+// OPTIONAL SETTINGS
+
+// Note on running PHPT:
+//      Vanilla PHPT from https://github.com/tswicegood/PHPT_Core should
+//      work fine on Linux w/o multitest.
+//
+//      To do multitest or Windows testing, you'll need some more
+//      patches at https://github.com/ezyang/PHPT_Core
+//
+//      I haven't tested the Windows setup in a while so I don't know if
+//      it still works.
+
+// Should PHPT tests be enabled?
+$GLOBALS['HTMLPurifierTest']['PHPT'] = false;
+
+// If PHPT isn't in your Path via PEAR, set that here:
+// set_include_path('/path/to/phpt/Core/src' . PATH_SEPARATOR . get_include_path());
+
+// Where is CSSTidy located? (Include trailing slash. Leave false to disable.)
+$csstidy_location    = false;
+
+// For tests/multitest.php, which versions to test?
+$versions_to_test    = array();
+
+// Stable PHP binary to use when invoking maintenance scripts.
+$php = 'php';
+
+// For tests/multitest.php, what is the multi-version executable? It must
+// accept an extra parameter (version number) before all other arguments
+$phpv = false;
+
+// Should PEAR tests be run? If you've got a valid PEAR installation, set this
+// to true (or, if it's not in the include path, to its install directory).
+$GLOBALS['HTMLPurifierTest']['PEAR'] = false;
+
+// If PEAR is enabled, what PEAR tests should be run? (Note: you will
+// need to ensure these libraries are installed)
+$GLOBALS['HTMLPurifierTest']['Net_IDNA2'] = true;
+
+// vim: et sw=4 sts=4

From c6514d58dbece71f25a44985a41ec18cdd50422d Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Tue, 9 Feb 2016 11:07:37 +0100
Subject: [PATCH 075/273] add composer-derived autoloader

---
 boot.php                                   |   2 +
 include/autoloader.php                     |  63 ++++
 include/autoloader/ClassLoader.php         | 413 +++++++++++++++++++++
 include/autoloader/LICENSE.composer        |  19 +
 include/autoloader/autoload_classmap.php   |   9 +
 include/autoloader/autoload_files.php      |  10 +
 include/autoloader/autoload_namespaces.php |  10 +
 include/autoloader/autoload_psr4.php       |   9 +
 8 files changed, 535 insertions(+)
 create mode 100644 include/autoloader.php
 create mode 100644 include/autoloader/ClassLoader.php
 create mode 100644 include/autoloader/LICENSE.composer
 create mode 100644 include/autoloader/autoload_classmap.php
 create mode 100644 include/autoloader/autoload_files.php
 create mode 100644 include/autoloader/autoload_namespaces.php
 create mode 100644 include/autoloader/autoload_psr4.php

diff --git a/boot.php b/boot.php
index 4ef30eadac..dd70040c64 100644
--- a/boot.php
+++ b/boot.php
@@ -17,6 +17,8 @@
  * easily as email does today.
  */
 
+require_once('include/autoloader.php');
+ 
 require_once('include/config.php');
 require_once('include/network.php');
 require_once('include/plugin.php');
diff --git a/include/autoloader.php b/include/autoloader.php
new file mode 100644
index 0000000000..b3b83cbc7c
--- /dev/null
+++ b/include/autoloader.php
@@ -0,0 +1,63 @@
+<?php
+
+class FriendicaAutoloaderInit
+{
+    private static $loader;
+
+    public static function loadClassLoader($class)
+    {
+        if ('Composer\Autoload\ClassLoader' === $class) {
+            require __DIR__ . '/autoloader/ClassLoader.php';
+        }
+    }
+
+    public static function getLoader()
+    {
+        if (null !== self::$loader) {
+            return self::$loader;
+        }
+
+        spl_autoload_register(array('FriendicaAutoloaderInit', 'loadClassLoader'), true, true);
+        self::$loader = $loader = new \Composer\Autoload\ClassLoader();
+        spl_autoload_unregister(array('FriendicaAutoloaderInit', 'loadClassLoader'));
+
+        // library 
+        $map = require __DIR__ . '/autoloader/autoload_namespaces.php';
+        foreach ($map as $namespace => $path) {
+            $loader->set($namespace, $path);
+        }
+
+        $map = require __DIR__ . '/autoloader/autoload_psr4.php';
+        foreach ($map as $namespace => $path) {
+            $loader->setPsr4($namespace, $path);
+        }
+
+        $classMap = require __DIR__ . '/autoloader/autoload_classmap.php';
+        if ($classMap) {
+            $loader->addClassMap($classMap);
+        }
+        
+        $loader->register(true);
+        
+        $includeFiles = require __DIR__ . '/autoloader/autoload_files.php';
+        foreach ($includeFiles as $fileIdentifier => $file) {
+            friendicaRequire($fileIdentifier, $file);
+        }
+        
+
+        return $loader;
+    }
+}
+
+function friendicaRequire($fileIdentifier, $file)
+{
+    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
+        require $file;
+
+        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
+    }
+}
+
+
+
+return FriendicaAutoloaderInit::getLoader();
diff --git a/include/autoloader/ClassLoader.php b/include/autoloader/ClassLoader.php
new file mode 100644
index 0000000000..d916d802fe
--- /dev/null
+++ b/include/autoloader/ClassLoader.php
@@ -0,0 +1,413 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE.composer
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\Autoload;
+
+/**
+ * ClassLoader implements a PSR-0 class loader
+ *
+ * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
+ *
+ *     $loader = new \Composer\Autoload\ClassLoader();
+ *
+ *     // register classes with namespaces
+ *     $loader->add('Symfony\Component', __DIR__.'/component');
+ *     $loader->add('Symfony',           __DIR__.'/framework');
+ *
+ *     // activate the autoloader
+ *     $loader->register();
+ *
+ *     // to enable searching the include path (eg. for PEAR packages)
+ *     $loader->setUseIncludePath(true);
+ *
+ * In this example, if you try to use a class in the Symfony\Component
+ * namespace or one of its children (Symfony\Component\Console for instance),
+ * the autoloader will first look for the class under the component/
+ * directory, and it will then fallback to the framework/ directory if not
+ * found before giving up.
+ *
+ * This class is loosely based on the Symfony UniversalClassLoader.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ */
+class ClassLoader
+{
+    // PSR-4
+    private $prefixLengthsPsr4 = array();
+    private $prefixDirsPsr4 = array();
+    private $fallbackDirsPsr4 = array();
+
+    // PSR-0
+    private $prefixesPsr0 = array();
+    private $fallbackDirsPsr0 = array();
+
+    private $useIncludePath = false;
+    private $classMap = array();
+
+    private $classMapAuthoritative = false;
+
+    public function getPrefixes()
+    {
+        if (!empty($this->prefixesPsr0)) {
+            return call_user_func_array('array_merge', $this->prefixesPsr0);
+        }
+
+        return array();
+    }
+
+    public function getPrefixesPsr4()
+    {
+        return $this->prefixDirsPsr4;
+    }
+
+    public function getFallbackDirs()
+    {
+        return $this->fallbackDirsPsr0;
+    }
+
+    public function getFallbackDirsPsr4()
+    {
+        return $this->fallbackDirsPsr4;
+    }
+
+    public function getClassMap()
+    {
+        return $this->classMap;
+    }
+
+    /**
+     * @param array $classMap Class to filename map
+     */
+    public function addClassMap(array $classMap)
+    {
+        if ($this->classMap) {
+            $this->classMap = array_merge($this->classMap, $classMap);
+        } else {
+            $this->classMap = $classMap;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix, either
+     * appending or prepending to the ones previously set for this prefix.
+     *
+     * @param string       $prefix  The prefix
+     * @param array|string $paths   The PSR-0 root directories
+     * @param bool         $prepend Whether to prepend the directories
+     */
+    public function add($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            if ($prepend) {
+                $this->fallbackDirsPsr0 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr0
+                );
+            } else {
+                $this->fallbackDirsPsr0 = array_merge(
+                    $this->fallbackDirsPsr0,
+                    (array) $paths
+                );
+            }
+
+            return;
+        }
+
+        $first = $prefix[0];
+        if (!isset($this->prefixesPsr0[$first][$prefix])) {
+            $this->prefixesPsr0[$first][$prefix] = (array) $paths;
+
+            return;
+        }
+        if ($prepend) {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixesPsr0[$first][$prefix]
+            );
+        } else {
+            $this->prefixesPsr0[$first][$prefix] = array_merge(
+                $this->prefixesPsr0[$first][$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace, either
+     * appending or prepending to the ones previously set for this namespace.
+     *
+     * @param string       $prefix  The prefix/namespace, with trailing '\\'
+     * @param array|string $paths   The PSR-0 base directories
+     * @param bool         $prepend Whether to prepend the directories
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function addPsr4($prefix, $paths, $prepend = false)
+    {
+        if (!$prefix) {
+            // Register directories for the root namespace.
+            if ($prepend) {
+                $this->fallbackDirsPsr4 = array_merge(
+                    (array) $paths,
+                    $this->fallbackDirsPsr4
+                );
+            } else {
+                $this->fallbackDirsPsr4 = array_merge(
+                    $this->fallbackDirsPsr4,
+                    (array) $paths
+                );
+            }
+        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
+            // Register directories for a new namespace.
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        } elseif ($prepend) {
+            // Prepend directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                (array) $paths,
+                $this->prefixDirsPsr4[$prefix]
+            );
+        } else {
+            // Append directories for an already registered namespace.
+            $this->prefixDirsPsr4[$prefix] = array_merge(
+                $this->prefixDirsPsr4[$prefix],
+                (array) $paths
+            );
+        }
+    }
+
+    /**
+     * Registers a set of PSR-0 directories for a given prefix,
+     * replacing any others previously set for this prefix.
+     *
+     * @param string       $prefix The prefix
+     * @param array|string $paths  The PSR-0 base directories
+     */
+    public function set($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr0 = (array) $paths;
+        } else {
+            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Registers a set of PSR-4 directories for a given namespace,
+     * replacing any others previously set for this namespace.
+     *
+     * @param string       $prefix The prefix/namespace, with trailing '\\'
+     * @param array|string $paths  The PSR-4 base directories
+     *
+     * @throws \InvalidArgumentException
+     */
+    public function setPsr4($prefix, $paths)
+    {
+        if (!$prefix) {
+            $this->fallbackDirsPsr4 = (array) $paths;
+        } else {
+            $length = strlen($prefix);
+            if ('\\' !== $prefix[$length - 1]) {
+                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
+            }
+            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
+            $this->prefixDirsPsr4[$prefix] = (array) $paths;
+        }
+    }
+
+    /**
+     * Turns on searching the include path for class files.
+     *
+     * @param bool $useIncludePath
+     */
+    public function setUseIncludePath($useIncludePath)
+    {
+        $this->useIncludePath = $useIncludePath;
+    }
+
+    /**
+     * Can be used to check if the autoloader uses the include path to check
+     * for classes.
+     *
+     * @return bool
+     */
+    public function getUseIncludePath()
+    {
+        return $this->useIncludePath;
+    }
+
+    /**
+     * Turns off searching the prefix and fallback directories for classes
+     * that have not been registered with the class map.
+     *
+     * @param bool $classMapAuthoritative
+     */
+    public function setClassMapAuthoritative($classMapAuthoritative)
+    {
+        $this->classMapAuthoritative = $classMapAuthoritative;
+    }
+
+    /**
+     * Should class lookup fail if not found in the current class map?
+     *
+     * @return bool
+     */
+    public function isClassMapAuthoritative()
+    {
+        return $this->classMapAuthoritative;
+    }
+
+    /**
+     * Registers this instance as an autoloader.
+     *
+     * @param bool $prepend Whether to prepend the autoloader or not
+     */
+    public function register($prepend = false)
+    {
+        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
+    }
+
+    /**
+     * Unregisters this instance as an autoloader.
+     */
+    public function unregister()
+    {
+        spl_autoload_unregister(array($this, 'loadClass'));
+    }
+
+    /**
+     * Loads the given class or interface.
+     *
+     * @param  string    $class The name of the class
+     * @return bool|null True if loaded, null otherwise
+     */
+    public function loadClass($class)
+    {
+        if ($file = $this->findFile($class)) {
+            includeFile($file);
+
+            return true;
+        }
+    }
+
+    /**
+     * Finds the path to the file where the class is defined.
+     *
+     * @param string $class The name of the class
+     *
+     * @return string|false The path if found, false otherwise
+     */
+    public function findFile($class)
+    {
+        // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
+        if ('\\' == $class[0]) {
+            $class = substr($class, 1);
+        }
+
+        // class map lookup
+        if (isset($this->classMap[$class])) {
+            return $this->classMap[$class];
+        }
+        if ($this->classMapAuthoritative) {
+            return false;
+        }
+
+        $file = $this->findFileWithExtension($class, '.php');
+
+        // Search for Hack files if we are running on HHVM
+        if ($file === null && defined('HHVM_VERSION')) {
+            $file = $this->findFileWithExtension($class, '.hh');
+        }
+
+        if ($file === null) {
+            // Remember that this class does not exist.
+            return $this->classMap[$class] = false;
+        }
+
+        return $file;
+    }
+
+    private function findFileWithExtension($class, $ext)
+    {
+        // PSR-4 lookup
+        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
+
+        $first = $class[0];
+        if (isset($this->prefixLengthsPsr4[$first])) {
+            foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
+                        if (is_file($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-4 fallback dirs
+        foreach ($this->fallbackDirsPsr4 as $dir) {
+            if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 lookup
+        if (false !== $pos = strrpos($class, '\\')) {
+            // namespaced class name
+            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
+                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
+        } else {
+            // PEAR-like class name
+            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
+        }
+
+        if (isset($this->prefixesPsr0[$first])) {
+            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
+                if (0 === strpos($class, $prefix)) {
+                    foreach ($dirs as $dir) {
+                        if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                            return $file;
+                        }
+                    }
+                }
+            }
+        }
+
+        // PSR-0 fallback dirs
+        foreach ($this->fallbackDirsPsr0 as $dir) {
+            if (is_file($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
+                return $file;
+            }
+        }
+
+        // PSR-0 include paths.
+        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
+            return $file;
+        }
+    }
+}
+
+/**
+ * Scope isolated include.
+ *
+ * Prevents access to $this/self from included files.
+ */
+function includeFile($file)
+{
+    include $file;
+}
diff --git a/include/autoloader/LICENSE.composer b/include/autoloader/LICENSE.composer
new file mode 100644
index 0000000000..b365b1f5a7
--- /dev/null
+++ b/include/autoloader/LICENSE.composer
@@ -0,0 +1,19 @@
+Copyright (c) 2015 Nils Adermann, Jordi Boggiano
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the Software), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, andor sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/include/autoloader/autoload_classmap.php b/include/autoloader/autoload_classmap.php
new file mode 100644
index 0000000000..3efd09fc69
--- /dev/null
+++ b/include/autoloader/autoload_classmap.php
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_classmap.php @generated by Composer
+
+$vendorDir = dirname(dirname(dirname(__FILE__)))."/library";
+$baseDir = dirname($vendorDir);
+
+return array(
+);
diff --git a/include/autoloader/autoload_files.php b/include/autoloader/autoload_files.php
new file mode 100644
index 0000000000..859135cc48
--- /dev/null
+++ b/include/autoloader/autoload_files.php
@@ -0,0 +1,10 @@
+<?php
+
+// autoload_files.php @generated by Composer
+
+$vendorDir = dirname(dirname(dirname(__FILE__)))."/library";
+$baseDir = dirname($vendorDir);
+
+return array(
+    '2cffec82183ee1cea088009cef9a6fc3' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier.composer.php',
+);
diff --git a/include/autoloader/autoload_namespaces.php b/include/autoloader/autoload_namespaces.php
new file mode 100644
index 0000000000..315a349310
--- /dev/null
+++ b/include/autoloader/autoload_namespaces.php
@@ -0,0 +1,10 @@
+<?php
+
+// autoload_namespaces.php @generated by Composer
+
+$vendorDir = dirname(dirname(dirname(__FILE__)))."/library";
+$baseDir = dirname($vendorDir);
+
+return array(
+    'HTMLPurifier' => array($vendorDir . '/ezyang/htmlpurifier/library'),
+);
diff --git a/include/autoloader/autoload_psr4.php b/include/autoloader/autoload_psr4.php
new file mode 100644
index 0000000000..fe93afea21
--- /dev/null
+++ b/include/autoloader/autoload_psr4.php
@@ -0,0 +1,9 @@
+<?php
+
+// autoload_psr4.php @generated by Composer
+
+$vendorDir = dirname(dirname(dirname(__FILE__)))."/library";
+$baseDir = dirname($vendorDir);
+
+return array(
+);

From aec8a1883e1bf0bb1ea6c2b11a1ff64796425788 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Tue, 9 Feb 2016 11:08:26 +0100
Subject: [PATCH 076/273] let autoloader include files for HTMLPurifier

---
 include/api.php   | 5 -----
 include/dfrn.php  | 1 -
 include/event.php | 1 -
 3 files changed, 7 deletions(-)

diff --git a/include/api.php b/include/api.php
index 4d206da28e..bddd4cfc7d 100644
--- a/include/api.php
+++ b/include/api.php
@@ -781,8 +781,6 @@
 
 		if((strpos($txt,'<') !== false) || (strpos($txt,'>') !== false)) {
 
-			require_once('library/HTMLPurifier.auto.php');
-
 			$txt = html2bb_video($txt);
 			$config = HTMLPurifier_Config::createDefault();
 			$config->set('Cache.DefinitionImpl', null);
@@ -822,9 +820,6 @@
 		if(requestdata('htmlstatus')) {
 			$txt = requestdata('htmlstatus');
 			if((strpos($txt,'<') !== false) || (strpos($txt,'>') !== false)) {
-
-				require_once('library/HTMLPurifier.auto.php');
-
 				$txt = html2bb_video($txt);
 
 				$config = HTMLPurifier_Config::createDefault();
diff --git a/include/dfrn.php b/include/dfrn.php
index c4999a08e1..38c7b425fa 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -18,7 +18,6 @@ require_once("include/event.php");
 require_once("include/text.php");
 require_once("include/oembed.php");
 require_once("include/html2bbcode.php");
-require_once("library/HTMLPurifier.auto.php");
 
 /**
  * @brief This class contain functions to create and send DFRN XML files
diff --git a/include/event.php b/include/event.php
index 13c414c9e3..a9f054fc2e 100644
--- a/include/event.php
+++ b/include/event.php
@@ -76,7 +76,6 @@ function format_event_html($ev, $simple = false) {
 function parse_event($h) {
 
 	require_once('include/Scrape.php');
-	require_once('library/HTMLPurifier.auto.php');
 	require_once('include/html2bbcode');
 
 	$h = '<html><body>' . $h . '</body></html>';

From d2a9aa19721568bf28e844e1ca2f596d7dcca240 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Tue, 9 Feb 2016 11:10:00 +0100
Subject: [PATCH 077/273] add some doxygen comments

---
 include/autoloader.php | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/autoloader.php b/include/autoloader.php
index b3b83cbc7c..6caa082915 100644
--- a/include/autoloader.php
+++ b/include/autoloader.php
@@ -1,5 +1,11 @@
 <?php
+/**
+ * @file include/autoloader.php
+ */
 
+/**
+ * @brief composer-derived autoloader init
+ **/
 class FriendicaAutoloaderInit
 {
     private static $loader;

From 4d7a6aaed240aa04e969aa33e6fd6ed6b6cb6bc8 Mon Sep 17 00:00:00 2001
From: Andrej Stieben <e-mail@stieben.de>
Date: Tue, 9 Feb 2016 15:54:35 +0100
Subject: [PATCH 078/273] Moved div#pause from index.php to view/default.php

This closes #2320.
---
 index.php        | 9 ---------
 view/default.php | 5 +++--
 2 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/index.php b/index.php
index 2b1053cc1b..ca93eb61e7 100644
--- a/index.php
+++ b/index.php
@@ -416,15 +416,6 @@ if(x($_SESSION,'sysmsg_info')) {
 call_hooks('page_end', $a->page['content']);
 
 
-/**
- *
- * Add a place for the pause/resume Ajax indicator
- *
- */
-
-$a->page['content'] .=  '<div id="pause"></div>';
-
-
 /**
  *
  * Add the navigation (menu) template
diff --git a/view/default.php b/view/default.php
index 78ca97ac94..121d5212c6 100644
--- a/view/default.php
+++ b/view/default.php
@@ -8,11 +8,12 @@
 <body>
 	<?php if(x($page,'nav')) echo $page['nav']; ?>
 	<aside><?php if(x($page,'aside')) echo $page['aside']; ?></aside>
-	<section><?php if(x($page,'content')) echo $page['content']; ?>
+	<section>
+		<?php if(x($page,'content')) echo $page['content']; ?>
+		<div id="pause"></div> <!-- The pause/resume Ajax indicator -->
 		<div id="page-footer"></div>
 	</section>
 	<right_aside><?php if(x($page,'right_aside')) echo $page['right_aside']; ?></right_aside>
 	<footer><?php if(x($page,'footer')) echo $page['footer']; ?></footer>
 </body>
 </html>
-

From e104c5819123cc9e836e8c6bd5f253bc87da341d Mon Sep 17 00:00:00 2001
From: Andrej Stieben <e-mail@stieben.de>
Date: Tue, 9 Feb 2016 16:41:19 +0100
Subject: [PATCH 079/273] Added div#pause to themes' default.php

As requested by @tobiasd and @rabuzarus.
---
 view/theme/frost-mobile/default.php | 5 +++--
 view/theme/frost/default.php        | 5 +++--
 view/theme/smoothly/default.php     | 5 +++--
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/view/theme/frost-mobile/default.php b/view/theme/frost-mobile/default.php
index ad464760f7..3a424ad5f4 100644
--- a/view/theme/frost-mobile/default.php
+++ b/view/theme/frost-mobile/default.php
@@ -28,7 +28,9 @@
 <!--		<div class='main-content-container'>-->
 		<div class='section-wrapper'>
 		<?php if( ($a->module === 'settings' || $a->module === 'message' || $a->module === 'profile') && x($page,'aside')) echo $page['aside']; ?>
-		<section><?php if(x($page,'content')) echo $page['content']; ?>
+		<section>
+			<?php if(x($page,'content')) echo $page['content']; ?>
+			<div id="pause"></div> <!-- The pause/resume Ajax indicator -->
 			<div id="page-footer"></div>
 		</section>
 		</div>
@@ -41,4 +43,3 @@
 	<?php if(x($page,'end')) echo $page['end']; ?>
 </body>
 </html>
-
diff --git a/view/theme/frost/default.php b/view/theme/frost/default.php
index 95a9b1e8c7..c379955f79 100644
--- a/view/theme/frost/default.php
+++ b/view/theme/frost/default.php
@@ -28,7 +28,9 @@
 		<!--<div class='main-content-loading'><img src="/view/theme/frost/images/ajax-loader.gif" alt="Please wait..."></div>-->
 		<div class='main-content-container'>
 		<aside><?php if(x($page,'aside')) echo $page['aside']; ?></aside>
-		<section><?php if(x($page,'content')) echo $page['content']; ?>
+		<section>
+			<?php if(x($page,'content')) echo $page['content']; ?>
+			<div id="pause"></div> <!-- The pause/resume Ajax indicator -->
 			<div id="page-footer"></div>
 		</section>
 		<right_aside><?php if(x($page,'right_aside')) echo $page['right_aside']; ?></right_aside>
@@ -39,4 +41,3 @@
 	<?php if(x($page,'end')) echo $page['end']; ?>
 </body>
 </html>
-
diff --git a/view/theme/smoothly/default.php b/view/theme/smoothly/default.php
index 9ac49820aa..405e1cad34 100644
--- a/view/theme/smoothly/default.php
+++ b/view/theme/smoothly/default.php
@@ -19,7 +19,9 @@
 
 	<aside><?php if(x($page,'aside')) echo $page['aside']; ?></aside>
 
-	<section><?php if(x($page,'content')) echo $page['content']; ?>
+	<section>
+		<?php if(x($page,'content')) echo $page['content']; ?>
+		<div id="pause"></div> <!-- The pause/resume Ajax indicator -->
 		<div id="page-footer"></div>
 	</section>
 
@@ -41,4 +43,3 @@
 	<?php if (x($page, 'bottom')) echo $page['bottom']; ?>
 </body>
 </html>
-

From 211be5bfc521285f83c9b85211721d7815fa5689 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 9 Feb 2016 23:28:33 +0100
Subject: [PATCH 080/273] Poller: The maximum number of connections can now be
 configured

---
 include/dfrn.php   |  4 +++-
 include/poller.php | 11 ++++++++---
 2 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index c4999a08e1..6fa47af052 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -1252,8 +1252,10 @@ class dfrn {
 			 // Update check for this field has to be done differently
 			$datefields = array("name-date", "uri-date");
 			foreach ($datefields AS $field)
-				if (strtotime($contact[$field]) > strtotime($r[0][$field]))
+				if (strtotime($contact[$field]) > strtotime($r[0][$field])) {
+					logger("Difference for contact ".$contact["id"]." in field '".$field."'. Old value: '".$contact[$field]."', new value '".$r[0][$field]."'", LOGGER_DEBUG);
 					$update = true;
+				}
 
 			foreach ($fields AS $field => $data)
 				if ($contact[$field] != $r[0][$field]) {
diff --git a/include/poller.php b/include/poller.php
index 712f6d5788..03f0307712 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -130,9 +130,14 @@ function poller_max_connections_reached() {
 	if (!$r)
 		return false;
 
-	$max = intval($r[0]["Value"]);
-	if ($max == 0)
-		return false;
+	// Fetch the max value from the config. This is needed when the system cannot detect the correct value by itself.
+	$max = get_config("system", "max_connections");
+
+	if ($max == 0) {
+		$max = intval($r[0]["Value"]);
+		if ($max == 0)
+			return false;
+	}
 
 	$r = q("SHOW STATUS WHERE `variable_name` = 'Threads_connected'");
 	if (!$r)

From 902820b30d90c3b0930256388219a7e2d9b8cea6 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 10 Feb 2016 07:56:49 +0100
Subject: [PATCH 081/273] Added documentation

---
 doc/htconfig.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/doc/htconfig.md b/doc/htconfig.md
index 4764c287c8..f9c92bfa08 100644
--- a/doc/htconfig.md
+++ b/doc/htconfig.md
@@ -34,6 +34,7 @@ line to your .htconfig.php:
 * like_no_comment (Boolean) - Don't update the "commented" value of an item when it is liked.
 * local_block (Boolean) - Used in conjunction with "block_public".
 * local_search (Boolean) - Blocks the search for not logged in users to prevent crawlers from blocking your system.
+* max_connections - The poller process isn't started when 3/4 of the possible database connections are used. When the system can't detect the maximum numbers of connection then this value can be used.
 * max_contact_queue - Default value is 500.
 * max_batch_queue - Default value is 1000.
 * no_oembed (Boolean) - Don't use OEmbed to fetch more information about a link.

From 20d7d18379f3d0e8c9928995588ce716033bc07f Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 10 Feb 2016 23:39:18 +0100
Subject: [PATCH 082/273] Bugfix: The "keywords" field in the gcontact table
 wasn't set correctly

---
 include/socgraph.php | 21 +++++++++++----------
 mod/pubsub.php       |  4 ++--
 2 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/include/socgraph.php b/include/socgraph.php
index c545343393..3b8e9140f8 100644
--- a/include/socgraph.php
+++ b/include/socgraph.php
@@ -139,15 +139,16 @@ function poco_load($cid,$uid = 0,$zcid = 0,$url = null) {
 		poco_check($profile_url, $name, $network, $profile_photo, $about, $location, $gender, $keywords, $connect_url, $updated, $generation, $cid, $uid, $zcid);
 
 		// Update the Friendica contacts. Diaspora is doing it via a message. (See include/diaspora.php)
-		if (($location != "") OR ($about != "") OR ($keywords != "") OR ($gender != ""))
-			q("UPDATE `contact` SET `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s'
-				WHERE `nurl` = '%s' AND NOT `self` AND `network` = '%s'",
-				dbesc($location),
-				dbesc($about),
-				dbesc($keywords),
-				dbesc($gender),
-				dbesc(normalise_link($profile_url)),
-				dbesc(NETWORK_DFRN));
+		// Deactivated because we now update Friendica contacts in dfrn.php
+		//if (($location != "") OR ($about != "") OR ($keywords != "") OR ($gender != ""))
+		//	q("UPDATE `contact` SET `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s'
+		//		WHERE `nurl` = '%s' AND NOT `self` AND `network` = '%s'",
+		//		dbesc($location),
+		//		dbesc($about),
+		//		dbesc($keywords),
+		//		dbesc($gender),
+		//		dbesc(normalise_link($profile_url)),
+		//		dbesc(NETWORK_DFRN));
 	}
 	logger("poco_load: loaded $total entries",LOGGER_DEBUG);
 
@@ -1554,7 +1555,7 @@ function update_gcontact($contact) {
 
 	if ($update) {
 		q("UPDATE `gcontact` SET `photo` = '%s', `name` = '%s', `nick` = '%s', `addr` = '%s', `network` = '%s',
-					`birthday` = '%s', `gender` = '%s', `keywords` = %d, `hide` = %d, `nsfw` = %d,
+					`birthday` = '%s', `gender` = '%s', `keywords` = '%s', `hide` = %d, `nsfw` = %d,
 					`alias` = '%s', `notify` = '%s', `url` = '%s',
 					`location` = '%s', `about` = '%s', `generation` = %d, `updated` = '%s',
 					`server_url` = '%s', `connect` = '%s'
diff --git a/mod/pubsub.php b/mod/pubsub.php
index beb73b4e2c..6053ee2fbe 100644
--- a/mod/pubsub.php
+++ b/mod/pubsub.php
@@ -122,8 +122,8 @@ function pubsub_post(&$a) {
 
 	$importer = $r[0];
 
-	$r = q("SELECT * FROM `contact` WHERE `subhub` = 1 AND `id` = %d AND `uid` = %d
-		AND ( `rel` = %d OR `rel` = %d OR network = '%s' ) AND `blocked` = 0 AND `readonly` = 0 LIMIT 1",
+	$r = q("SELECT * FROM `contact` WHERE `subhub` AND `id` = %d AND `uid` = %d
+		AND (`rel` = %d OR `rel` = %d OR network = '%s') AND NOT `blocked` LIMIT 1",
 		intval($contact_id),
 		intval($importer['uid']),
 		intval(CONTACT_IS_SHARING),

From e20aad43477a4a4794b34e72b7a4106ac0dbd836 Mon Sep 17 00:00:00 2001
From: fabrixxm <fabrix.xm@gmail.com>
Date: Thu, 11 Feb 2016 09:05:00 +0100
Subject: [PATCH 083/273] fix missing html2plain() function declaration

---
 include/NotificationsManager.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/NotificationsManager.php b/include/NotificationsManager.php
index c99d00742c..5f8211eb87 100644
--- a/include/NotificationsManager.php
+++ b/include/NotificationsManager.php
@@ -2,6 +2,7 @@
 /**
  * @file include/NotificationsManager.php
  */
+require_once('include/html2plain.php');
 require_once("include/datetime.php");
 require_once("include/bbcode.php");
 

From 4af77b60cebc2e3bdf1a393fde0d2c2672acecec Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 11 Feb 2016 11:33:45 +0100
Subject: [PATCH 084/273] Poller: Use the processlist when the number of
 maximum database connections was provided manually

---
 include/poller.php | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/include/poller.php b/include/poller.php
index 03f0307712..9976e76db2 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -131,22 +131,29 @@ function poller_max_connections_reached() {
 		return false;
 
 	// Fetch the max value from the config. This is needed when the system cannot detect the correct value by itself.
+	// In that case we use the processlist to determine the current number of connections
 	$max = get_config("system", "max_connections");
 
 	if ($max == 0) {
 		$max = intval($r[0]["Value"]);
 		if ($max == 0)
 			return false;
+
+		$r = q("SHOW STATUS WHERE `variable_name` = 'Threads_connected'");
+		if (!$r)
+			return false;
+
+		$connected = intval($r[0]["Value"]);
+		if ($connected == 0)
+			return false;
+	} else {
+		$r = q("SHOW PROCESSLIST");
+		if (!$r)
+			return false;
+
+		$connected = count($r);
 	}
 
-	$r = q("SHOW STATUS WHERE `variable_name` = 'Threads_connected'");
-	if (!$r)
-		return false;
-
-	$connected = intval($r[0]["Value"]);
-	if ($connected == 0)
-		return false;
-
 	$level = $connected / $max;
 
 	logger("Connection usage: ".$connected."/".$max, LOGGER_DEBUG);

From 5027fbf733d362e3b2c5a4fdf63ebc746a065945 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 11 Feb 2016 21:39:34 +0100
Subject: [PATCH 085/273] Poller: Now the user limits can be detected
 automatically as well

---
 include/poller.php | 56 +++++++++++++++++++++++++++++++++-------------
 1 file changed, 41 insertions(+), 15 deletions(-)

diff --git a/include/poller.php b/include/poller.php
index 9976e76db2..d68e8081ca 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -68,6 +68,10 @@ function poller_run(&$argv, &$argc){
 
 	while ($r = q("SELECT * FROM `workerqueue` WHERE `executed` = '0000-00-00 00:00:00' ORDER BY `created` LIMIT 1")) {
 
+		// Constantly check the number of available database connections to let the frontend be accessible at any time
+		if (poller_max_connections_reached())
+			return;
+
 		// Count active workers and compare them with a maximum value that depends on the load
 		if (poller_too_much_workers(3))
 			return;
@@ -126,15 +130,43 @@ function poller_run(&$argv, &$argc){
  * @return bool Are more than 3/4 of the maximum connections used?
  */
 function poller_max_connections_reached() {
-	$r = q("SHOW VARIABLES WHERE `variable_name` = 'max_connections'");
-	if (!$r)
-		return false;
 
 	// Fetch the max value from the config. This is needed when the system cannot detect the correct value by itself.
-	// In that case we use the processlist to determine the current number of connections
 	$max = get_config("system", "max_connections");
 
 	if ($max == 0) {
+		// the maximum number of possible user connections can be a system variable
+		$r = q("SHOW VARIABLES WHERE `variable_name` = 'max_user_connections'");
+		if ($r)
+			$max = $r[0]["Value"];
+
+		// Or it can be granted. This overrides the system variable
+		$r = q("SHOW GRANTS");
+		if ($r)
+			foreach ($r AS $grants) {
+				$grant = array_pop($grants);
+				if (stristr($grant, "GRANT USAGE ON"))
+					if (preg_match("/WITH MAX_USER_CONNECTIONS (\d*)/", $grant, $match))
+						$max = $match[1];
+			}
+	}
+
+	// If $max is set we will use the processlist to determine the current number of connections
+	// The processlist only shows entries of the current user
+	if ($max != 0) {
+		$r = q("SHOW PROCESSLIST");
+		if (!$r)
+			return false;
+
+		$used = count($r);
+
+		logger("Connection usage (user values): ".$used."/".$max, LOGGER_DEBUG);
+	} else {
+		// Since there are no user specific limitations we will now check for the system values
+		$r = q("SHOW VARIABLES WHERE `variable_name` = 'max_connections'");
+		if (!$r)
+			return false;
+
 		$max = intval($r[0]["Value"]);
 		if ($max == 0)
 			return false;
@@ -143,25 +175,19 @@ function poller_max_connections_reached() {
 		if (!$r)
 			return false;
 
-		$connected = intval($r[0]["Value"]);
-		if ($connected == 0)
-			return false;
-	} else {
-		$r = q("SHOW PROCESSLIST");
-		if (!$r)
+		$used = intval($r[0]["Value"]);
+		if ($used == 0)
 			return false;
 
-		$connected = count($r);
+		logger("Connection usage (system values): ".$used."/".$max, LOGGER_DEBUG);
 	}
 
-	$level = $connected / $max;
-
-	logger("Connection usage: ".$connected."/".$max, LOGGER_DEBUG);
+	$level = $used / $max;
 
 	if ($level < (3/4))
 		return false;
 
-	logger("Maximum level (3/4) of connections reached: ".$connected."/".$max);
+	logger("Maximum level (3/4) of connections reached: ".$used."/".$max);
 	return true;
 
 }

From 4dad744c35565129ea9ba09922474c1dc6a32e04 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 11 Feb 2016 22:35:06 +0100
Subject: [PATCH 086/273] DFRN-Bugfix: Forums should work now

---
 include/dfrn.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index 6fa47af052..1cfa42a6b3 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -2053,10 +2053,10 @@ class dfrn {
 			if (($item["network"] != $author["network"]) AND ($author["network"] != ""))
 				$item["network"] = $author["network"];
 
-			if($importer["rel"] == CONTACT_IS_FOLLOWER) {
-				logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG);
-				return;
-			}
+			//if($importer["rel"] == CONTACT_IS_FOLLOWER) {
+			//	logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG);
+			//	return;
+			//}
 		}
 
 		if ($entrytype == DFRN_REPLY_RC) {

From b5c547174826b6145259381090843cc72a4c4790 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 12 Feb 2016 07:39:08 +0100
Subject: [PATCH 087/273] Added some documentation

---
 include/dfrn.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/dfrn.php b/include/dfrn.php
index 1cfa42a6b3..8938a9b6f7 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -2053,6 +2053,10 @@ class dfrn {
 			if (($item["network"] != $author["network"]) AND ($author["network"] != ""))
 				$item["network"] = $author["network"];
 
+			// This code was taken from the old DFRN code
+			// When activated, forums don't work.
+			// And: Why should we disallow commenting by followers?
+			// the behaviour is now similar to the Diaspora part.
 			//if($importer["rel"] == CONTACT_IS_FOLLOWER) {
 			//	logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG);
 			//	return;

From 45c4e3455e11b2b0ef20fbc53199721951247696 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Fri, 12 Feb 2016 09:25:33 +0100
Subject: [PATCH 088/273] docs: add brief autoloading help page, fix smarty3
 help page name

---
 doc/Home.md                                     |  2 ++
 doc/autoloader.md                               | 17 +++++++++++++++++
 ...narty3-templates.md => smarty3-templates.md} |  0
 3 files changed, 19 insertions(+)
 create mode 100644 doc/autoloader.md
 rename doc/{snarty3-templates.md => smarty3-templates.md} (100%)

diff --git a/doc/Home.md b/doc/Home.md
index 3b6442867c..1f9b0cfab7 100644
--- a/doc/Home.md
+++ b/doc/Home.md
@@ -47,8 +47,10 @@ Friendica Documentation and Resources
 * [Theme Development](help/themes)
 * [Smarty 3 Templates](help/smarty3-templates)
 * [Database schema documantation](help/database)
+* [Class Autoloading](help/autoloader)
 * [Code - Reference(Doxygen generated - sets cookies)](doc/html/)
 
+
 **External Resources**
 
 * [Main Website](http://friendica.com)
diff --git a/doc/autoloader.md b/doc/autoloader.md
new file mode 100644
index 0000000000..ea1a82b357
--- /dev/null
+++ b/doc/autoloader.md
@@ -0,0 +1,17 @@
+Autoloader
+==========
+
+* [Home](help)
+
+There is some initial support to class autoloading in Friendica core.
+
+The autoloader code is in `include/autoloader.php`.
+It's derived from composer autoloader code.
+
+Namespaces and Classes are mapped to folders and files in `library/`,
+and the map must be updated by hand, because we don't use composer yet.
+The mapping is defined by files in `include/autoloader/` folder.
+
+Currently, only HTMLPurifier library is loaded using autoloader.
+
+
diff --git a/doc/snarty3-templates.md b/doc/smarty3-templates.md
similarity index 100%
rename from doc/snarty3-templates.md
rename to doc/smarty3-templates.md

From 89d63b25238d2628cca3124ca92b1b8ea87a5667 Mon Sep 17 00:00:00 2001
From: Fabrixxm <fabrix.xm@gmail.com>
Date: Fri, 12 Feb 2016 09:26:42 +0100
Subject: [PATCH 089/273] docs: small fixes to help sidebar

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

diff --git a/mod/help.php b/mod/help.php
index 5465d3e900..7222569279 100644
--- a/mod/help.php
+++ b/mod/help.php
@@ -62,7 +62,7 @@ function help_content(&$a) {
 	if ($filename !== "Home") {
 		// create TOC but not for home
 		$lines = explode("\n", $html);
-		$toc="<style>aside ul {padding-left: 1em;}</style><h2>TOC</h2><ul id='toc'>";
+		$toc="<style>aside ul {padding-left: 1em;}aside h1{font-size:2em}</style><h2>TOC</h2><ul id='toc'>";
 		$lastlevel=1;
 		$idnum = array(0,0,0,0,0,0,0);
 		foreach($lines as &$line){
@@ -84,7 +84,7 @@ function help_content(&$a) {
 				}
 			}
 		}
-		for($k=1;$k<$lastlevel; $k++) $toc.="</ul>";
+		for($k=0;$k<$lastlevel; $k++) $toc.="</ul>";
 		$html = implode("\n",$lines);
 
 		$a->page['aside'] = $toc.$a->page['aside'];

From acb09d3a3d34ba180ef8804abf5e032b725f62e3 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 12 Feb 2016 11:04:25 +0100
Subject: [PATCH 090/273] Database connections: When we now check for user
 values we check the system values as well

---
 include/poller.php | 45 ++++++++++++++++++++++++++-------------------
 1 file changed, 26 insertions(+), 19 deletions(-)

diff --git a/include/poller.php b/include/poller.php
index d68e8081ca..90e94ede9e 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -161,35 +161,42 @@ function poller_max_connections_reached() {
 		$used = count($r);
 
 		logger("Connection usage (user values): ".$used."/".$max, LOGGER_DEBUG);
-	} else {
-		// Since there are no user specific limitations we will now check for the system values
-		$r = q("SHOW VARIABLES WHERE `variable_name` = 'max_connections'");
-		if (!$r)
-			return false;
 
-		$max = intval($r[0]["Value"]);
-		if ($max == 0)
-			return false;
+		$level = $used / $max;
 
-		$r = q("SHOW STATUS WHERE `variable_name` = 'Threads_connected'");
-		if (!$r)
-			return false;
-
-		$used = intval($r[0]["Value"]);
-		if ($used == 0)
-			return false;
-
-		logger("Connection usage (system values): ".$used."/".$max, LOGGER_DEBUG);
+		if ($level >= (3/4)) {
+			logger("Maximum level (3/4) of user connections reached: ".$used."/".$max);
+			return true;
+		}
 	}
 
+	// We will now check for the system values.
+	// This limit could be reached although the user limits are fine.
+	$r = q("SHOW VARIABLES WHERE `variable_name` = 'max_connections'");
+	if (!$r)
+		return false;
+
+	$max = intval($r[0]["Value"]);
+	if ($max == 0)
+		return false;
+
+	$r = q("SHOW STATUS WHERE `variable_name` = 'Threads_connected'");
+	if (!$r)
+		return false;
+
+	$used = intval($r[0]["Value"]);
+	if ($used == 0)
+		return false;
+
+	logger("Connection usage (system values): ".$used."/".$max, LOGGER_DEBUG);
+
 	$level = $used / $max;
 
 	if ($level < (3/4))
 		return false;
 
-	logger("Maximum level (3/4) of connections reached: ".$used."/".$max);
+	logger("Maximum level (3/4) of system connections reached: ".$used."/".$max);
 	return true;
-
 }
 
 /**

From a7498ef50dec2be410125da102285856d6219121 Mon Sep 17 00:00:00 2001
From: fabrixxm <fabrix.xm@gmail.com>
Date: Sat, 13 Feb 2016 10:57:37 +0100
Subject: [PATCH 091/273] doc: add quick intro to autoloading

---
 doc/autoloader.md | 192 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 192 insertions(+)

diff --git a/doc/autoloader.md b/doc/autoloader.md
index ea1a82b357..947eade23c 100644
--- a/doc/autoloader.md
+++ b/doc/autoloader.md
@@ -15,3 +15,195 @@ The mapping is defined by files in `include/autoloader/` folder.
 Currently, only HTMLPurifier library is loaded using autoloader.
 
 
+## A quick introdution to class autoloading
+
+The autoloader it's a way for php to automagically include the file that define a class when the class is first used, without the need to use "require_once" every time.
+
+Once is setup you don't have to use it in any way. You need a class? you use the class.
+
+At his basic is a function passed to the "spl_autoload_register()" function, which receive as argument the class name the script want and is it job to include the correct php file where that class is defined.
+The best source for documentation is [php site](http://php.net/manual/en/language.oop5.autoload.php).
+
+One example, based on fictional friendica code.
+
+Let's say you have a php file in "include/" that define a very useful class:
+
+```
+    file: include/ItemsManager.php
+    <?php
+    namespace \Friendica;
+    
+    class ItemsManager {
+       public function getAll() { ... }
+       public function getByID($id) { ... }
+    }
+```
+
+The class "ItemsManager" has been declared in "Friendica" namespace.
+Namespaces are useful to keep things separated and avoid names clash (could be that a library you want to use defines a class named "ItemsManager", but as long as is in another namespace, you don't have any problem)
+
+If we were using composer, we had configured it with path where to find the classes of "Friendica" namespace, and then the composer script will generate the autoloader machinery for us.
+As we don't use composer, we need check that the autoloader knows the Friendica namespace.
+So in "include/autoloader/autoload_psr4.php" there should be something like
+
+```
+    $vendorDir = dirname(dirname(dirname(__FILE__)))."/library";
+    $baseDir = dirname($vendorDir);
+    return array(
+       "Friendica" => array($baseDir."/include");
+    );
+```
+
+
+That tells the autoloader code to look for files that defines classes in "Friendica" namespace under "include/" folder. (And btw, that's why the file has the same name as the class it defines.)
+
+*note*: The structure of files in "include/autoloader/" has been copied from the code generated by composer, to ease the work of enable autoloader for external libraries under "library/"
+
+Let's say now that you need to load some items in a view, maybe in a fictional "mod/network.php".
+Somewere at the start of the scripts, the autoloader was initialized. In Friendica is done at the top of "boot.php", with "require_once('include/autoloader.php');".
+
+The code will be something like:
+
+```
+    file: mod/network.php
+    <?php
+    
+    function network_content(&$a) {
+       $itemsmanager = new \Friendica\ItemsManager();
+       $items = $itemsmanager->getAll();
+    
+       // pass $items to template
+       // return result
+    }
+```
+
+That's a quite simple example, but look: no "require()"!
+You need to use a class, you use the class and you don't need to do anything more.
+
+Going further: now we have a bunch of "*Manager" classes that cause some code duplication, let's define a BaseManager class, where to move all code in common between all managers:
+
+```
+    file: include/BaseManager.php
+    <?php
+    namespace \Friendica;
+    
+    class BaseManager {
+      public function thatFunctionEveryManagerUses() { ... }
+    }
+```
+
+and then let's change the ItemsManager class to use this code
+
+```
+    file: include/ItemsManager.php
+    <?php
+    namespace \Friendica;
+    
+    class ItemsManager extends BaseManager {
+       public function getAll() { ... }
+       public function getByID($id) { ... }
+    }
+```
+
+The autoloader don't mind what you need the class for. You need a class, you get the class.
+It works with the "BaseManager" example here, it works when we need to call static methods on a class:
+
+```
+    file: include/dfrn.php
+    <?php    
+    namespace \Friendica;
+    
+    class dfrn {
+      public static function  mail($item, $owner) { ... }
+    }
+```
+
+```
+    file: mod/mail.php
+    <?php
+    
+    mail_post($a){
+     ...
+     \Friendica\dfrn::mail($item, $owner);
+     ...
+    }
+```
+
+If your code is in same namespace as the class you need, you don't need to prepend it:
+
+```
+    file: include/delivery.php
+    <?php
+    
+    namespace \Friendica;
+    
+    // this is the same content of current include/delivery.php, 
+    // but has been declared to be in "Friendica" namespace
+    
+    [...]
+    switch($contact['network']) {
+    
+        case NETWORK_DFRN:
+            if ($mail) {
+                $item['body'] = ...
+                $atom = dfrn::mail($item, $owner);
+            } elseif ($fsuggest) {
+                $atom = dfrn::fsuggest($item, $owner);
+                q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item['id']));
+            } elseif ($relocate)
+                $atom = dfrn::relocate($owner, $uid);
+    [...]
+```
+
+This is real "include/delivery.php" unchanged, but as the code is declared to be in "Friendica" namespace, you don't need to write it when you need to use the "dfrn" class.
+But if you want to use classes from another library, you need to use the full namespace, e.g.
+
+```
+    <?php
+    namespace \Frienidca;
+    
+    class Diaspora {
+      public function md2bbcode() {
+        $html = \Michelf\MarkdownExtra::defaultTransform($text); 
+      }
+    }
+```
+
+if you use that class in many places of the code and you don't want to write the full path to the class everytime, you can use the "use" php keyword
+
+```
+    <?php
+    namespace \Frienidca;
+    
+    use \Michelf\MarkdownExtra;
+    
+    class Diaspora {
+      public function md2bbcode() {
+        $html = MarkdownExtra::defaultTransform($text); 
+      }
+    }
+```
+
+Note that namespaces are like paths in filesystem, separated by "\", with the first "\" being the global scope.
+You can go more deep if you want to, like:
+
+```
+    <?php
+    namespace \Friendica\Network;
+    
+    class DFRN {
+    }
+```
+
+or
+
+```
+    <?php
+    namespace \Friendica\DBA;
+    
+    class MySQL {
+    }
+```
+
+So you can think of namespaces as folders in a unix filesystem, with global scope as the root ("\").
+

From 2ca6cdf6b6e0fa4a04fb1d1fb6bf5d83f9ba74e8 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 13 Feb 2016 12:26:58 +0100
Subject: [PATCH 092/273] Improvements how gcontact entries are updated

---
 boot.php             |  26 +++--
 database.sql         |  18 +---
 include/Scrape.php   |  15 ++-
 include/dfrn.php     |  50 ++++++----
 include/items.php    |  13 +--
 include/socgraph.php | 219 ++++++++++++-------------------------------
 mod/noscrape.php     |   6 +-
 7 files changed, 133 insertions(+), 214 deletions(-)

diff --git a/boot.php b/boot.php
index 4ef30eadac..2b7d814123 100644
--- a/boot.php
+++ b/boot.php
@@ -1037,19 +1037,29 @@ class App {
 		$this->performance[$value] += (float)$duration;
 		$this->performance["marktime"] += (float)$duration;
 
-		// Trace the different functions with their timestamps
-		$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
+		$callstack = $this->callstack();
 
+		$this->callstack[$value][$callstack] += (float)$duration;
+
+	}
+
+	/**
+	 * @brief Returns a string with a callstack. Can be used for logging.
+	 *
+	 * @return string
+	 */
+	function callstack() {
+		$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 6);
+
+		// We remove the first two items from the list since they contain data that we don't need.
+		array_shift($trace);
 		array_shift($trace);
 
-		$function = array();
+		$callstack = array();
 		foreach ($trace AS $func)
-			$function[] = $func["function"];
-
-		$function = implode(", ", $function);
-
-		$this->callstack[$value][$function] += (float)$duration;
+			$callstack[] = $func["function"];
 
+		return implode(", ", $callstack);
 	}
 
 	function mark_timestamp($mark) {
diff --git a/database.sql b/database.sql
index 70b315ea24..25faf0f4c0 100644
--- a/database.sql
+++ b/database.sql
@@ -1,6 +1,6 @@
 -- ------------------------------------------
 -- Friendica 3.5-dev (Asparagus)
--- DB_UPDATE_VERSION 1193
+-- DB_UPDATE_VERSION 1194
 -- ------------------------------------------
 
 
@@ -119,6 +119,7 @@ CREATE TABLE IF NOT EXISTS `contact` (
 	`keywords` text NOT NULL,
 	`gender` varchar(32) NOT NULL DEFAULT '',
 	`attag` varchar(255) NOT NULL DEFAULT '',
+	`avatar` varchar(255) NOT NULL DEFAULT '',
 	`photo` text NOT NULL,
 	`thumb` text NOT NULL,
 	`micro` text NOT NULL,
@@ -411,21 +412,6 @@ CREATE TABLE IF NOT EXISTS `gserver` (
 	 INDEX `nurl` (`nurl`)
 ) DEFAULT CHARSET=utf8;
 
---
--- TABLE guid
---
-CREATE TABLE IF NOT EXISTS `guid` (
-	`id` int(10) unsigned NOT NULL auto_increment,
-	`guid` varchar(255) NOT NULL DEFAULT '',
-	`plink` varchar(255) NOT NULL DEFAULT '',
-	`uri` varchar(255) NOT NULL DEFAULT '',
-	`network` varchar(32) NOT NULL DEFAULT '',
-	 PRIMARY KEY(`id`),
-	 INDEX `guid` (`guid`),
-	 INDEX `plink` (`plink`),
-	 INDEX `uri` (`uri`)
-) DEFAULT CHARSET=utf8;
-
 --
 -- TABLE hook
 --
diff --git a/include/Scrape.php b/include/Scrape.php
index ca6489b16a..bc6aebbdcf 100644
--- a/include/Scrape.php
+++ b/include/Scrape.php
@@ -12,6 +12,18 @@ function scrape_dfrn($url, $dont_probe = false) {
 
 	logger('scrape_dfrn: url=' . $url);
 
+	// Try to fetch the data from noscrape. This is faster than parsing the HTML
+	$noscrape = str_replace("/hcard/", "/noscrape/", $url);
+	$noscrapejson = fetch_url($noscrape);
+	$noscrapedata = array();
+	if ($noscrapejson) {
+		$noscrapedata = json_decode($noscrapejson, true);
+
+		if (is_array($noscrapedata))
+			if ($noscrapedata["nick"] != "")
+				return($noscrapedata);
+	}
+
 	$s = fetch_url($url);
 
 	if(! $s)
@@ -91,8 +103,7 @@ function scrape_dfrn($url, $dont_probe = false) {
 			}
 		}
 	}
-
-	return $ret;
+	return array_merge($ret, $noscrapedata);
 }}
 
 
diff --git a/include/dfrn.php b/include/dfrn.php
index 8938a9b6f7..a37aaf29ce 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -1115,13 +1115,13 @@ class dfrn {
 	 *
 	 * @return Returns an array with relevant data of the author
 	 */
-	private function fetchauthor($xpath, $context, $importer, $element, $onlyfetch) {
+	private function fetchauthor($xpath, $context, $importer, $element, $onlyfetch, $xml = "") {
 
 		$author = array();
 		$author["name"] = $xpath->evaluate($element."/atom:name/text()", $context)->item(0)->nodeValue;
 		$author["link"] = $xpath->evaluate($element."/atom:uri/text()", $context)->item(0)->nodeValue;
 
-		$r = q("SELECT `id`, `uid`, `network`, `avatar-date`, `name-date`, `uri-date`, `addr`,
+		$r = q("SELECT `id`, `uid`, `url`, `network`, `avatar-date`, `name-date`, `uri-date`, `addr`,
 				`name`, `nick`, `about`, `location`, `keywords`, `bdyear`, `bd`
 				FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
 			intval($importer["uid"]), dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET));
@@ -1130,6 +1130,9 @@ class dfrn {
 			$author["contact-id"] = $r[0]["id"];
 			$author["network"] = $r[0]["network"];
 		} else {
+			if (!$onlyfetch)
+				logger("Contact ".$author["link"]." wasn't found for user ".$importer["uid"]." XML: ".$xml, LOGGER_DEBUG);
+
 			$author["contact-id"] = $importer["id"];
 			$author["network"] = $importer["network"];
 			$onlyfetch = true;
@@ -1159,38 +1162,41 @@ class dfrn {
 		}
 
 		if ($r AND !$onlyfetch) {
+			logger("Check if contact details for contact ".$r[0]["id"]." (".$r[0]["nick"].") have to be updated.", LOGGER_DEBUG);
+
+			$poco = array("url" => $contact["url"]);
 
 			// When was the last change to name or uri?
 			$name_element = $xpath->query($element."/atom:name", $context)->item(0);
 			foreach($name_element->attributes AS $attributes)
 				if ($attributes->name == "updated")
-					$contact["name-date"] = $attributes->textContent;
+					$poco["name-date"] = $attributes->textContent;
 
 			$link_element = $xpath->query($element."/atom:link", $context)->item(0);
 			foreach($link_element->attributes AS $attributes)
 				if ($attributes->name == "updated")
-					$contact["uri-date"] = $attributes->textContent;
+					$poco["uri-date"] = $attributes->textContent;
 
 			// Update contact data
 			$value = $xpath->evaluate($element."/dfrn:handle/text()", $context)->item(0)->nodeValue;
 			if ($value != "")
-				$contact["addr"] = $value;
+				$poco["addr"] = $value;
 
 			$value = $xpath->evaluate($element."/poco:displayName/text()", $context)->item(0)->nodeValue;
 			if ($value != "")
-				$contact["name"] = $value;
+				$poco["name"] = $value;
 
 			$value = $xpath->evaluate($element."/poco:preferredUsername/text()", $context)->item(0)->nodeValue;
 			if ($value != "")
-				$contact["nick"] = $value;
+				$poco["nick"] = $value;
 
 			$value = $xpath->evaluate($element."/poco:note/text()", $context)->item(0)->nodeValue;
 			if ($value != "")
-				$contact["about"] = $value;
+				$poco["about"] = $value;
 
 			$value = $xpath->evaluate($element."/poco:address/poco:formatted/text()", $context)->item(0)->nodeValue;
 			if ($value != "")
-				$contact["location"] = $value;
+				$poco["location"] = $value;
 
 			/// @todo Add support for the following fields that we don't support by now in the contact table:
 			/// - poco:utcOffset
@@ -1207,7 +1213,7 @@ class dfrn {
 				$tags[$tag->nodeValue] = $tag->nodeValue;
 
 			if (count($tags))
-				$contact["keywords"] = implode(", ", $tags);
+				$poco["keywords"] = implode(", ", $tags);
 
 			// "dfrn:birthday" contains the birthday converted to UTC
 			$old_bdyear = $contact["bdyear"];
@@ -1217,7 +1223,7 @@ class dfrn {
 			if (strtotime($birthday) > time()) {
 				$bd_timestamp = strtotime($birthday);
 
-				$contact["bdyear"] = date("Y", $bd_timestamp);
+				$poco["bdyear"] = date("Y", $bd_timestamp);
 			}
 
 			// "poco:birthday" is the birthday in the format "yyyy-mm-dd"
@@ -1232,9 +1238,11 @@ class dfrn {
 					$bdyear = $bdyear + 1;
 				}
 
-				$contact["bd"] = $value;
+				$poco["bd"] = $value;
 			}
 
+			$contact = array_merge($contact, $poco);
+
 			if ($old_bdyear != $contact["bdyear"])
 				self::birthday_event($contact, $birthday);
 
@@ -1245,6 +1253,7 @@ class dfrn {
 
 			unset($fields["id"]);
 			unset($fields["uid"]);
+			unset($fields["url"]);
 			unset($fields["avatar-date"]);
 			unset($fields["name-date"]);
 			unset($fields["uri-date"]);
@@ -1264,7 +1273,7 @@ class dfrn {
 				}
 
 			if ($update) {
-				logger("Update contact data for contact ".$contact["id"], LOGGER_DEBUG);
+				logger("Update contact data for contact ".$contact["id"]." (".$contact["nick"].")", LOGGER_DEBUG);
 
 				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s',
 					`addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s',
@@ -1283,9 +1292,10 @@ class dfrn {
 			// It is used in the socgraph.php to prevent that old contact data
 			// that was relayed over several servers can overwrite contact
 			// data that we received directly.
-			$contact["generation"] = 2;
-			$contact["photo"] = $author["avatar"];
-			update_gcontact($contact);
+
+			$poco["generation"] = 2;
+			$poco["photo"] = $author["avatar"];
+			update_gcontact($poco);
 		}
 
 		return($author);
@@ -2369,8 +2379,14 @@ class dfrn {
 		$header["contact-id"] = $importer["id"];
 
 		// Update the contact table if the data has changed
+
+		// The "atom:author" is only present in feeds
+		if ($xpath->query("/atom:feed/atom:author")->length > 0)
+			self::fetchauthor($xpath, $doc->firstChild, $importer, "atom:author", false, $xml);
+
 		// Only the "dfrn:owner" in the head section contains all data
-		self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", false);
+		if ($xpath->query("/atom:feed/dfrn:owner")->length > 0)
+			self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", false, $xml);
 
 		logger("Import DFRN message for user ".$importer["uid"]." from contact ".$importer["id"], LOGGER_DEBUG);
 
diff --git a/include/items.php b/include/items.php
index 1af6fe1b52..8d6b5b471c 100644
--- a/include/items.php
+++ b/include/items.php
@@ -500,14 +500,8 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
 	$arr['file']          = ((x($arr,'file'))          ? trim($arr['file'])                  : '');
 
 
-	if (($arr['author-link'] == "") AND ($arr['owner-link'] == "")) {
-		$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5);
-		foreach ($trace AS $func)
-		        $function[] = $func["function"];
-
-		$function = implode(", ", $function);
-		logger("Both author-link and owner-link are empty. Called by: ".$function, LOGGER_DEBUG);
-	}
+	if (($arr['author-link'] == "") AND ($arr['owner-link'] == ""))
+		logger("Both author-link and owner-link are empty. Called by: ".App::callstack(), LOGGER_DEBUG);
 
 	if ($arr['plink'] == "") {
 		$a = get_app();
@@ -888,9 +882,6 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
 			logger('item_store: new item not found in DB, id ' . $current_post);
 	}
 
-	// Add every contact of the post to the global contact table
-	poco_store($arr);
-
 	create_tags_from_item($current_post);
 	create_files_from_item($current_post);
 
diff --git a/include/socgraph.php b/include/socgraph.php
index 3b8e9140f8..8ad7a4cd31 100644
--- a/include/socgraph.php
+++ b/include/socgraph.php
@@ -10,6 +10,7 @@
 require_once('include/datetime.php');
 require_once("include/Scrape.php");
 require_once("include/html2bbcode.php");
+require_once("include/Contact.php");
 
 
 /*
@@ -428,7 +429,7 @@ function poco_last_updated($profile, $force = false) {
 	if (($gcontacts[0]["server_url"] != "") AND ($gcontacts[0]["nick"] != "")) {
 
 		//  Use noscrape if possible
-		$server = q("SELECT `noscrape` FROM `gserver` WHERE `nurl` = '%s' AND `noscrape` != ''", dbesc(normalise_link($gcontacts[0]["server_url"])));
+		$server = q("SELECT `noscrape`, `network` FROM `gserver` WHERE `nurl` = '%s' AND `noscrape` != ''", dbesc(normalise_link($gcontacts[0]["server_url"])));
 
 		if ($server) {
 			$noscraperet = z_fetch_url($server[0]["noscrape"]."/".$gcontacts[0]["nick"]);
@@ -437,67 +438,42 @@ function poco_last_updated($profile, $force = false) {
 
 				$noscrape = json_decode($noscraperet["body"], true);
 
-				if (($noscrape["fn"] != "") AND ($noscrape["fn"] != $gcontacts[0]["name"]))
-					q("UPDATE `gcontact` SET `name` = '%s' WHERE `nurl` = '%s'",
-						dbesc($noscrape["fn"]), dbesc(normalise_link($profile)));
+				$contact = array("url" => $profile,
+						"network" => $server[0]["network"],
+						"generation" => $gcontacts[0]["generation"]);
 
-				if (($noscrape["photo"] != "") AND ($noscrape["photo"] != $gcontacts[0]["photo"]))
-					q("UPDATE `gcontact` SET `photo` = '%s' WHERE `nurl` = '%s'",
-						dbesc($noscrape["photo"]), dbesc(normalise_link($profile)));
+				$contact["name"] = $noscrape["fn"];
+				$contact["community"] = $noscrape["comm"];
 
-				if (($noscrape["updated"] != "") AND ($noscrape["updated"] != $gcontacts[0]["updated"]))
-					q("UPDATE `gcontact` SET `updated` = '%s' WHERE `nurl` = '%s'",
-						dbesc($noscrape["updated"]), dbesc(normalise_link($profile)));
-
-				if (($noscrape["gender"] != "") AND ($noscrape["gender"] != $gcontacts[0]["gender"]))
-					q("UPDATE `gcontact` SET `gender` = '%s' WHERE `nurl` = '%s'",
-						dbesc($noscrape["gender"]), dbesc(normalise_link($profile)));
-
-				if (($noscrape["pdesc"] != "") AND ($noscrape["pdesc"] != $gcontacts[0]["about"]))
-					q("UPDATE `gcontact` SET `about` = '%s' WHERE `nurl` = '%s'",
-						dbesc($noscrape["pdesc"]), dbesc(normalise_link($profile)));
-
-				if (($noscrape["about"] != "") AND ($noscrape["about"] != $gcontacts[0]["about"]))
-					q("UPDATE `gcontact` SET `about` = '%s' WHERE `nurl` = '%s'",
-						dbesc($noscrape["about"]), dbesc(normalise_link($profile)));
-
-				if (isset($noscrape["comm"]) AND ($noscrape["comm"] != $gcontacts[0]["community"]))
-					q("UPDATE `gcontact` SET `community` = %d WHERE `nurl` = '%s'",
-						intval($noscrape["comm"]), dbesc(normalise_link($profile)));
-
-				if (isset($noscrape["tags"]))
+				if (isset($noscrape["tags"])) {
 					$keywords = implode(" ", $noscrape["tags"]);
-				else
-					$keywords = "";
-
-				if (($keywords != "") AND ($keywords != $gcontacts[0]["keywords"]))
-					q("UPDATE `gcontact` SET `keywords` = '%s' WHERE `nurl` = '%s'",
-						dbesc($keywords), dbesc(normalise_link($profile)));
-
-				$location = $noscrape["locality"];
-
-				if ($noscrape["region"] != "") {
-					if ($location != "")
-						$location .= ", ";
-
-					$location .= $noscrape["region"];
+					if ($keywords != "")
+						$contact["keywords"] = $keywords;
 				}
 
-				if ($noscrape["country-name"] != "") {
-					if ($location != "")
-						$location .= ", ";
+				$location = formatted_location($noscrape);
+				if ($location)
+					$contact["location"] = $location;
 
-					$location .= $noscrape["country-name"];
-				}
+				$contact["notify"] = $noscrape["dfrn-notify"];
 
-				if (($location != "") AND ($location != $gcontacts[0]["location"]))
-					q("UPDATE `gcontact` SET `location` = '%s' WHERE `nurl` = '%s'",
-						dbesc($location), dbesc(normalise_link($profile)));
+				// Remove all fields that are not present in the gcontact table
+				unset($noscrape["fn"]);
+				unset($noscrape["key"]);
+				unset($noscrape["homepage"]);
+				unset($noscrape["comm"]);
+				unset($noscrape["tags"]);
+				unset($noscrape["locality"]);
+				unset($noscrape["region"]);
+				unset($noscrape["country-name"]);
+				unset($noscrape["contacts"]);
+				unset($noscrape["dfrn-request"]);
+				unset($noscrape["dfrn-confirm"]);
+				unset($noscrape["dfrn-notify"]);
+				unset($noscrape["dfrn-poll"]);
 
-				// If we got data from noscrape then mark the contact as reachable
-				if (is_array($noscrape) AND count($noscrape))
-					q("UPDATE `gcontact` SET `last_contact` = '%s' WHERE `nurl` = '%s'",
-						dbesc(datetime_convert()), dbesc(normalise_link($profile)));
+				$contact = array_merge($contact, $noscrape);
+				update_gcontact($contact);
 
 				return $noscrape["updated"];
 			}
@@ -534,25 +510,22 @@ function poco_last_updated($profile, $force = false) {
 		return false;
 	}
 
-	if (($data["name"] != "") AND ($data["name"] != $gcontacts[0]["name"]))
-		q("UPDATE `gcontact` SET `name` = '%s' WHERE `nurl` = '%s'",
-			dbesc($data["name"]), dbesc(normalise_link($profile)));
+	$contact = array("generation" => $gcontacts[0]["generation"]);
 
-	if (($data["nick"] != "") AND ($data["nick"] != $gcontacts[0]["nick"]))
-		q("UPDATE `gcontact` SET `nick` = '%s' WHERE `nurl` = '%s'",
-			dbesc($data["nick"]), dbesc(normalise_link($profile)));
+	$contact = array_merge($contact, $data);
 
-	if (($data["addr"] != "") AND ($data["addr"] != $gcontacts[0]["connect"]))
-		q("UPDATE `gcontact` SET `connect` = '%s' WHERE `nurl` = '%s'",
-			dbesc($data["addr"]), dbesc(normalise_link($profile)));
+	$contact["server_url"] = $data["baseurl"];
 
-	if (($data["photo"] != "") AND ($data["photo"] != $gcontacts[0]["photo"]))
-		q("UPDATE `gcontact` SET `photo` = '%s' WHERE `nurl` = '%s'",
-			dbesc($data["photo"]), dbesc(normalise_link($profile)));
+	unset($contact["batch"]);
+	unset($contact["poll"]);
+	unset($contact["request"]);
+	unset($contact["confirm"]);
+	unset($contact["poco"]);
+	unset($contact["priority"]);
+	unset($contact["pubkey"]);
+	unset($contact["baseurl"]);
 
-	if (($data["baseurl"] != "") AND ($data["baseurl"] != $gcontacts[0]["server_url"]))
-		q("UPDATE `gcontact` SET `server_url` = '%s' WHERE `nurl` = '%s'",
-			dbesc($data["baseurl"]), dbesc(normalise_link($profile)));
+	update_gcontact($contact);
 
 	$feedret = z_fetch_url($data["poll"]);
 
@@ -921,88 +894,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
 	return !$failure;
 }
 
-function poco_contact_from_body($body, $created, $cid, $uid) {
-	preg_replace_callback("/\[share(.*?)\].*?\[\/share\]/ism",
-		function ($match) use ($created, $cid, $uid){
-			return(sub_poco_from_share($match, $created, $cid, $uid));
-		}, $body);
-}
-
-function sub_poco_from_share($share, $created, $cid, $uid) {
-	$profile = "";
-	preg_match("/profile='(.*?)'/ism", $share[1], $matches);
-	if ($matches[1] != "")
-		$profile = $matches[1];
-
-	preg_match('/profile="(.*?)"/ism', $share[1], $matches);
-	if ($matches[1] != "")
-		$profile = $matches[1];
-
-	if ($profile == "")
-		return;
-
-	logger("prepare poco_check for profile ".$profile, LOGGER_DEBUG);
-	poco_check($profile, "", "", "", "", "", "", "", "", $created, 3, $cid, $uid);
-}
-
-function poco_store($item) {
-
-	// Isn't it public?
-	if ($item['private'])
-		return;
-
-	// Or is it from a network where we don't store the global contacts?
-	if (!in_array($item["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, NETWORK_STATUSNET, "")))
-		return;
-
-	// Is it a global copy?
-	$store_gcontact = ($item["uid"] == 0);
-
-	// Is it a comment on a global copy?
-	if (!$store_gcontact AND ($item["uri"] != $item["parent-uri"])) {
-		$q = q("SELECT `id` FROM `item` WHERE `uri`='%s' AND `uid` = 0", $item["parent-uri"]);
-		$store_gcontact = count($q);
-	}
-
-	if (!$store_gcontact)
-		return;
-
-	// "3" means: We don't know this contact directly (Maybe a reshared item)
-	$generation = 3;
-	$network = "";
-	$profile_url = $item["author-link"];
-
-	// Is it a user from our server?
-	$q = q("SELECT `id` FROM `contact` WHERE `self` AND `nurl` = '%s' LIMIT 1",
-		dbesc(normalise_link($item["author-link"])));
-	if (count($q)) {
-		logger("Our user (generation 1): ".$item["author-link"], LOGGER_DEBUG);
-		$generation = 1;
-		$network = NETWORK_DFRN;
-	} else { // Is it a contact from a user on our server?
-		$q = q("SELECT `network`, `url` FROM `contact` WHERE `uid` != 0 AND `network` != ''
-			AND (`nurl` = '%s' OR `alias` IN ('%s', '%s')) AND `network` != '%s' LIMIT 1",
-			dbesc(normalise_link($item["author-link"])),
-			dbesc(normalise_link($item["author-link"])),
-			dbesc($item["author-link"]),
-			dbesc(NETWORK_STATUSNET));
-		if (count($q)) {
-			$generation = 2;
-			$network = $q[0]["network"];
-			$profile_url = $q[0]["url"];
-			logger("Known contact (generation 2): ".$profile_url, LOGGER_DEBUG);
-		}
-	}
-
-	if ($generation == 3)
-		logger("Unknown contact (generation 3): ".$item["author-link"], LOGGER_DEBUG);
-
-	poco_check($profile_url, $item["author-name"], $network, $item["author-avatar"], "", "", "", "", "", $item["received"], $generation, $item["contact-id"], $item["uid"]);
-
-	// Maybe its a body with a shared item? Then extract a global contact from it.
-	poco_contact_from_body($item["body"], $item["received"], $item["contact-id"], $item["uid"]);
-}
-
 function count_common_friends($uid,$cid) {
 
 	$r = q("SELECT count(*) as `total`
@@ -1533,7 +1424,7 @@ function update_gcontact($contact) {
 
 	// assign all unassigned fields from the database entry
 	foreach ($fields AS $field => $data)
-		if (!isset($contact[$field]))
+		if (!isset($contact[$field]) OR ($contact[$field] == ""))
 			$contact[$field] = $r[0][$field];
 
 	if ($contact["network"] == NETWORK_STATUSNET)
@@ -1546,14 +1437,22 @@ function update_gcontact($contact) {
 	$update = false;
 	unset($fields["generation"]);
 
-	foreach ($fields AS $field => $data)
-		if ($contact[$field] != $r[0][$field])
-			$update = true;
+	if ((($contact["generation"] > 0) AND ($contact["generation"] <= $r[0]["generation"])) OR ($r[0]["generation"] == 0)) {
+		foreach ($fields AS $field => $data)
+			if ($contact[$field] != $r[0][$field]) {
+				logger("Difference for contact ".$contact["url"]." in field '".$field."'. New value: '".$contact[$field]."', old value '".$r[0][$field]."'", LOGGER_DEBUG);
+				$update = true;
+			}
 
-	if ($contact["generation"] < $r[0]["generation"])
-		$update = true;
+		if ($contact["generation"] < $r[0]["generation"]) {
+			logger("Difference for contact ".$contact["url"]." in field 'generation'. new value: '".$contact["generation"]."', old value '".$r[0]["generation"]."'", LOGGER_DEBUG);
+			$update = true;
+		}
+	}
 
 	if ($update) {
+		logger("Update gcontact for ".$contact["url"]." Callstack: ".App::callstack(), LOGGER_DEBUG);
+
 		q("UPDATE `gcontact` SET `photo` = '%s', `name` = '%s', `nick` = '%s', `addr` = '%s', `network` = '%s',
 					`birthday` = '%s', `gender` = '%s', `keywords` = '%s', `hide` = %d, `nsfw` = %d,
 					`alias` = '%s', `notify` = '%s', `url` = '%s',
@@ -1581,8 +1480,10 @@ function update_gcontact($contact) {
 function update_gcontact_from_probe($url) {
 	$data = probe_url($url);
 
-	if ($data["network"] != NETWORK_PHANTOM)
-		update_gcontact($data);
+	if ($data["network"] == NETWORK_PHANTOM)
+		return;
+
+	update_gcontact($data);
 }
 
 /**
diff --git a/mod/noscrape.php b/mod/noscrape.php
index 51bd7234cf..1f7105b769 100644
--- a/mod/noscrape.php
+++ b/mod/noscrape.php
@@ -22,13 +22,17 @@ function noscrape_init(&$a) {
 	$keywords = str_replace(array('#',',',' ',',,'),array('',' ',',',','),$keywords);
 	$keywords = explode(',', $keywords);
 
+	$r = q("SELECT `photo` FROM `contact` WHERE `self` AND `uid` = %d",
+		intval($a->profile['uid']));
+
 	$json_info = array(
 		'fn' => $a->profile['name'],
 		'addr' => $a->profile['addr'],
+		'nick' => $a->user['nickname'],
 		'key' => $a->profile['pubkey'],
 		'homepage' => $a->get_baseurl()."/profile/{$which}",
 		'comm' => (x($a->profile,'page-flags')) && ($a->profile['page-flags'] == PAGE_COMMUNITY),
-		'photo' => $a->profile['photo'],
+		'photo' => $r[0]["photo"],
 		'tags' => $keywords
 	);
 

From 253ba45c1a9f080b5086decc9696c9cda89c7ca3 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 13 Feb 2016 13:30:53 +0100
Subject: [PATCH 093/273] Added a to-do

---
 include/dfrn.php | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/dfrn.php b/include/dfrn.php
index a37aaf29ce..1db2c6b33d 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -1965,6 +1965,8 @@ class dfrn {
 			$item['body'] = @html2bbcode($item['body']);
 		}
 
+		/// @todo We should check for a repeated post and if we know the repeated author.
+
 		// We don't need the content element since "dfrn:env" is always present
 		//$item["body"] = $xpath->query("atom:content/text()", $entry)->item(0)->nodeValue;
 

From a4da9fb55db84fe8a88129fe542422b70ae8e68e Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 13 Feb 2016 14:09:08 +0100
Subject: [PATCH 094/273] Update the gcontact entry when the contact entry is
 checked for updates

---
 include/follow.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/follow.php b/include/follow.php
index 22ff079b63..410e0e58aa 100644
--- a/include/follow.php
+++ b/include/follow.php
@@ -1,5 +1,6 @@
 <?php
 require_once("include/Scrape.php");
+require_once("include/socgraph.php");
 
 function update_contact($id) {
 	/*
@@ -43,6 +44,9 @@ function update_contact($id) {
 		intval($id)
 	);
 
+	// Update the corresponding gcontact entry
+	poco_last_updated($ret["url"]);
+
 	return true;
 }
 

From 307f90cdfe3df9165c8f3cd05e91c3bf18b772a3 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 13 Feb 2016 14:21:53 +0100
Subject: [PATCH 095/273] Vier: Pictures in the side bar shouldn't be larger
 than the side bar

---
 view/theme/vier/style.css | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css
index 2b78d25d7f..e35556f541 100644
--- a/view/theme/vier/style.css
+++ b/view/theme/vier/style.css
@@ -1141,6 +1141,10 @@ aside h4, right_aside h4 {
   font-size: 1.17em;
 }
 
+aside img {
+  max-width: 175px;
+}
+
 .nets-ul {
   margin-top: 0px;
 }

From bf7dedb03b96be90947d40829bdcac68869e250b Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 13 Feb 2016 18:15:24 +0100
Subject: [PATCH 096/273] Optimized query for unread group postings

---
 include/group.php | 23 +++++++++++------------
 mod/ping.php      | 18 ++++++++++--------
 2 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/include/group.php b/include/group.php
index a1375e00df..2b872f16a7 100644
--- a/include/group.php
+++ b/include/group.php
@@ -215,7 +215,7 @@ function mini_group_select($uid,$gid = 0) {
 
 /**
  * @brief Create group sidebar widget
- * 
+ *
  * @param string $every
  * @param string $each
  * @param string $editmode
@@ -234,7 +234,7 @@ function group_side($every="contacts",$each="group",$editmode = "standard", $gro
 		return '';
 
 	$groups = array();
-	
+
 	$groups[] = array(
 		'text' 	=> t('Everybody'),
 		'id' => 0,
@@ -255,7 +255,7 @@ function group_side($every="contacts",$each="group",$editmode = "standard", $gro
 	if(count($r)) {
 		foreach($r as $rr) {
 			$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
-			
+
 			if ($editmode == "full") {
 				$groupedit = array(
 					'href' => "group/".$rr['id'],
@@ -264,7 +264,7 @@ function group_side($every="contacts",$each="group",$editmode = "standard", $gro
 			} else {
 				$groupedit = null;
 			}
-			
+
 			$groups[] = array(
 				'id'		=> $rr['id'],
 				'cid'		=> $cid,
@@ -362,14 +362,13 @@ function groups_containing($uid,$c) {
  */
 function groups_count_unseen() {
 
-	$r = q("SELECT `group`.`id`, `group`.`name`, COUNT(`item`.`id`) AS `count` FROM `group`, `group_member`, `item`
-			WHERE `group`.`uid` = %d
-			AND `item`.`uid` = %d
-			AND `item`.`unseen` AND `item`.`visible`
-			AND NOT `item`.`deleted`
-			AND `item`.`contact-id` = `group_member`.`contact-id`
-			AND `group_member`.`gid` = `group`.`id`
-			GROUP BY `group`.`id` ",
+	$r = q("SELECT `group`.`id`, `group`.`name`,
+			(SELECT COUNT(*) FROM `item`
+				WHERE `uid` = %d AND `unseen` AND
+					`contact-id` IN (SELECT `contact-id` FROM `group_member`
+								WHERE `group_member`.`gid` = `group`.`id` AND `group_member`.`uid` = %d)) AS `count`
+			FROM `group` WHERE `group`.`uid` = %d;",
+		intval(local_user()),
 		intval(local_user()),
 		intval(local_user())
 	);
diff --git a/mod/ping.php b/mod/ping.php
index 50d179595e..2eb94576b3 100644
--- a/mod/ping.php
+++ b/mod/ping.php
@@ -219,19 +219,21 @@ function ping_init(&$a) {
 				<home>$home</home>\r\n";
 		if ($register!=0) echo "<register>$register</register>";
 
-		if ( count($groups_unseen) ) {
+		if (count($groups_unseen)) {
 			echo '<groups>';
-			foreach ($groups_unseen as $it) {
-				echo '<group id="' . $it['id'] . '">' . $it['count'] . "</group>";
-			}
+			foreach ($groups_unseen as $it)
+				if ($it['count'] > 0)
+					echo '<group id="'.$it['id'].'">'.$it['count']."</group>";
+
 			echo "</groups>";
 		}
 
-		if ( count($forums_unseen) ) {
+		if (count($forums_unseen)) {
 			echo '<forums>';
-			foreach ($forums_unseen as $it) {
-				echo '<forum id="' . $it['id'] . '">' . $it['count'] . "</forum>";
-			}
+			foreach ($forums_unseen as $it)
+				if ($it['count'] > 0)
+					echo '<forum id="'.$it['id'].'">'.$it['count']."</forum>";
+
 			echo "</forums>";
 		}
 

From f496af08bb71080d11f9d76377605bbd16cb9090 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 13 Feb 2016 21:35:05 +0100
Subject: [PATCH 097/273] OStatus: The gcontact table will now be updated from
 the conversation as well

---
 include/ostatus.php | 74 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/include/ostatus.php b/include/ostatus.php
index 00022f8c6c..983ed6e1b4 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -626,6 +626,77 @@ function check_conversations($mentions = false, $override = false) {
 	set_config('system','ostatus_last_poll', time());
 }
 
+/**
+ * @brief Updates the gcontact table with actor data from the conversation
+ *
+ * @param object $actor The actor object that contains the contact data
+ */
+function ostatus_conv_fetch_actor($actor) {
+
+	// We set the generation to "3" since the data here is not as reliable as the data we get on other occasions
+	$contact = array("network" => NETWORK_OSTATUS, "generation" => 3);
+
+	if (isset($actor->url))
+		$contact["url"] = $actor->url;
+
+	if (isset($actor->displayName))
+		$contact["name"] = $actor->displayName;
+
+	if (isset($actor->portablecontacts_net->displayName))
+		$contact["name"] = $actor->portablecontacts_net->displayName;
+
+	if (isset($actor->portablecontacts_net->preferredUsername))
+		$contact["nick"] = $actor->portablecontacts_net->preferredUsername;
+
+	if (isset($actor->id))
+		$contact["alias"] = $actor->id;
+
+	if (isset($actor->summary))
+		$contact["about"] = $actor->summary;
+
+	if (isset($actor->portablecontacts_net->note))
+		$contact["about"] = $actor->portablecontacts_net->note;
+
+	if (isset($actor->portablecontacts_net->addresses->formatted))
+		$contact["location"] = $actor->portablecontacts_net->addresses->formatted;
+
+
+	if (isset($actor->image->url))
+		$contact["photo"] = $actor->image->url;
+
+	if (isset($actor->image->width))
+		$avatarwidth = $actor->image->width;
+
+	if (is_array($actor->status_net->avatarLinks))
+		foreach ($actor->status_net->avatarLinks AS $avatar) {
+			if ($avatarsize < $avatar->width) {
+				$contact["photo"] = $avatar->url;
+				$avatarsize = $avatar->width;
+			}
+		}
+
+	$contact["server_url"] = $contact["url"];
+
+	$server_url = matching($contact["server_url"], $contact["alias"]);
+	if (strlen($server_url) > 8)
+		$contact["server_url"] = $server_url;
+
+	$server_url = matching($contact["server_url"], $contact["photo"]);
+	if (strlen($server_url) > 8)
+		$contact["server_url"] = $server_url;
+
+	if (($contact["server_url"] == $contact["url"]) OR ($contact["server_url"] == $contact["alias"]))
+		unset($contact["server_url"]);
+	else {
+		$hostname = str_replace("http://", "", normalise_link($contact["server_url"]));
+		if ($hostname AND $contact["nick"])
+			$contact["addr"] = $contact["nick"]."@".$hostname;
+	}
+
+	update_gcontact($contact);
+}
+
+
 function ostatus_completion($conversation_url, $uid, $item = array()) {
 
 	$a = get_app();
@@ -729,6 +800,9 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 
 	foreach ($items as $single_conv) {
 
+		// Update the gcontact table
+		ostatus_conv_fetch_actor($single_conv->actor);
+
 		// Test - remove before flight
 		//$tempfile = tempnam(get_temppath(), "conversation");
 		//file_put_contents($tempfile, json_encode($single_conv));

From 15296b8036a670fd32891d71927df81d9db6293a Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 13 Feb 2016 22:20:00 +0100
Subject: [PATCH 098/273] Avoid errors when noscrape data can't be fetched.

---
 include/Scrape.php | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/Scrape.php b/include/Scrape.php
index bc6aebbdcf..d54a838afd 100644
--- a/include/Scrape.php
+++ b/include/Scrape.php
@@ -19,9 +19,11 @@ function scrape_dfrn($url, $dont_probe = false) {
 	if ($noscrapejson) {
 		$noscrapedata = json_decode($noscrapejson, true);
 
-		if (is_array($noscrapedata))
+		if (is_array($noscrapedata)) {
 			if ($noscrapedata["nick"] != "")
 				return($noscrapedata);
+		} else
+			$noscrapedata = array();
 	}
 
 	$s = fetch_url($url);

From 5086b8b2a77c0d20898dd56e720a73f8228672fb Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 14 Feb 2016 00:14:03 +0100
Subject: [PATCH 099/273] DFRN Bugfix: The poco data wasn't sent

---
 include/dfrn.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index 17ef541cd3..f7a05bdb63 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -95,7 +95,7 @@ class dfrn {
 
 		$sql_extra = " AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = '' ";
 
-		$r = q("SELECT `contact`.*, `user`.`uid` AS `user_uid`, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`
+		$r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`
 			FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
 			WHERE `contact`.`self` = 1 AND `user`.`nickname` = '%s' LIMIT 1",
 			dbesc($owner_nick)
@@ -105,7 +105,7 @@ class dfrn {
 			killme();
 
 		$owner = $r[0];
-		$owner_id = $owner['user_uid'];
+		$owner_id = $owner['uid'];
 		$owner_nick = $owner['nickname'];
 
 		$sql_post_table = "";
@@ -483,7 +483,7 @@ class dfrn {
 					"media:width" => 175, "media:height" => 175, "href" => $owner['photo']);
 		xml_add_element($doc, $author, "link", "", $attributes);
 
-		$birthday = feed_birthday($owner['user_uid'], $owner['timezone']);
+		$birthday = feed_birthday($owner['uid'], $owner['timezone']);
 
 		if ($birthday)
 			xml_add_element($doc, $author, "dfrn:birthday", $birthday);
@@ -498,7 +498,7 @@ class dfrn {
 			FROM `profile`
 				INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
 				WHERE `profile`.`is-default` AND NOT `user`.`hidewall` AND `user`.`uid` = %d",
-			intval($owner['user_uid']));
+			intval($owner['uid']));
 		if ($r) {
 			$profile = $r[0];
 			xml_add_element($doc, $author, "poco:displayName", $profile["name"]);

From b9e179207678576e6ade8243a4868b523c19c919 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 14 Feb 2016 07:31:57 +0100
Subject: [PATCH 100/273] The shadow contact (contact with uid=0) will be
 updated now as well.

---
 include/socgraph.php | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/include/socgraph.php b/include/socgraph.php
index 8ad7a4cd31..ce5b08e641 100644
--- a/include/socgraph.php
+++ b/include/socgraph.php
@@ -11,7 +11,7 @@ require_once('include/datetime.php');
 require_once("include/Scrape.php");
 require_once("include/html2bbcode.php");
 require_once("include/Contact.php");
-
+require_once("include/Photo.php");
 
 /*
  * poco_load
@@ -1467,6 +1467,28 @@ function update_gcontact($contact) {
 			intval($contact["generation"]), dbesc($contact["updated"]),
 			dbesc($contact["server_url"]), dbesc($contact["connect"]),
 			dbesc(normalise_link($contact["url"])), intval($contact["generation"]));
+
+
+		// Now update the contact entry with the user id "0" as well.
+		// This is used for the shadow copies of public items.
+		$r = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0 ORDER BY `id` LIMIT 1",
+			dbesc(normalise_link($contact["url"])));
+
+		if ($r) {
+			logger("Update shadow contact ".$r[0]["id"], LOGGER_DEBUG);
+
+			update_contact_avatar($contact["photo"], 0, $r[0]["id"]);
+
+			q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s',
+						`network` = '%s', `bd` = '%s', `gender` = '%s',
+						`keywords` = '%s', `alias` = '%s', `url` = '%s',
+						`location` = '%s', `about` = '%s'
+					WHERE `id` = %d",
+				dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["addr"]),
+				dbesc($contact["network"]), dbesc($contact["birthday"]), dbesc($contact["gender"]),
+				dbesc($contact["keywords"]), dbesc($contact["alias"]), dbesc($contact["url"]),
+				dbesc($contact["location"]), dbesc($contact["about"]), intval($r[0]["id"]));
+		}
 	}
 
 	return $gcontact_id;

From 3f5f1351b98d2e495a12ba56652d0700b9239f80 Mon Sep 17 00:00:00 2001
From: fabrixxm <fabrix.xm@gmail.com>
Date: Sun, 14 Feb 2016 11:24:51 +0100
Subject: [PATCH 101/273] api: throw HTTPException instead of calling api_error
 directly

there was some places where api_error() was called instead of throwing
correct subclass of HTTPException. This was causing php errors.

Dogygen comment of api_error() is updated as well
---
 include/api.php | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/include/api.php b/include/api.php
index d54e540f79..55e39e3583 100644
--- a/include/api.php
+++ b/include/api.php
@@ -161,10 +161,7 @@
 		if (!isset($_SERVER['PHP_AUTH_USER'])) {
 			logger('API_login: ' . print_r($_SERVER,true), LOGGER_DEBUG);
 			header('WWW-Authenticate: Basic realm="Friendica"');
-			header('HTTP/1.0 401 Unauthorized');
-			die((api_error($a, 'json', "This api requires login")));
-
-			//die('This api requires login');
+			throw new UnauthorizedException("This API requires login");
 		}
 
 		$user = $_SERVER['PHP_AUTH_USER'];
@@ -216,8 +213,9 @@
 		if((! $record) || (! count($record))) {
 			logger('API_login failure: ' . print_r($_SERVER,true), LOGGER_DEBUG);
 			header('WWW-Authenticate: Basic realm="Friendica"');
-			header('HTTP/1.0 401 Unauthorized');
-			die('This api requires login');
+			#header('HTTP/1.0 401 Unauthorized');
+			#die('This api requires login');
+			throw new UnauthorizedException("This API requires login");
 		}
 
 		authenticate_success($record); $_SESSION["allow_api"] = true;
@@ -331,7 +329,8 @@
 	 *
 	 * @param Api $a
 	 * @param string $type Return type (xml, json, rss, as)
-	 * @param string $error Error message
+	 * @param HTTPException $error Error object
+	 * @return strin error message formatted as $type
 	 */
 	function api_error(&$a, $type, $e) {
 		$error = ($e->getMessage()!==""?$e->getMessage():$e->httpdesc);
@@ -903,7 +902,8 @@
 
 				if ($posts_day > $throttle_day) {
 					logger('Daily posting limit reached for user '.api_user(), LOGGER_DEBUG);
-					die(api_error($a, $type, sprintf(t("Daily posting limit of %d posts reached. The post was rejected."), $throttle_day)));
+					#die(api_error($a, $type, sprintf(t("Daily posting limit of %d posts reached. The post was rejected."), $throttle_day)));
+					throw new TooManyRequestsException(sprintf(t("Daily posting limit of %d posts reached. The post was rejected."), $throttle_day));
 				}
 			}
 
@@ -922,7 +922,9 @@
 
 				if ($posts_week > $throttle_week) {
 					logger('Weekly posting limit reached for user '.api_user(), LOGGER_DEBUG);
-					die(api_error($a, $type, sprintf(t("Weekly posting limit of %d posts reached. The post was rejected."), $throttle_week)));
+					#die(api_error($a, $type, sprintf(t("Weekly posting limit of %d posts reached. The post was rejected."), $throttle_week)));
+					throw new TooManyRequestsException(sprintf(t("Weekly posting limit of %d posts reached. The post was rejected."), $throttle_week));
+
 				}
 			}
 
@@ -941,7 +943,8 @@
 
 				if ($posts_month > $throttle_month) {
 					logger('Monthly posting limit reached for user '.api_user(), LOGGER_DEBUG);
-					die(api_error($a, $type, sprintf(t("Monthly posting limit of %d posts reached. The post was rejected."), $throttle_month)));
+					#die(api_error($a, $type, sprintf(t("Monthly posting limit of %d posts reached. The post was rejected."), $throttle_month)));
+					throw new TooManyRequestsException(sprintf(t("Monthly posting limit of %d posts reached. The post was rejected."), $throttle_month));
 				}
 			}
 
@@ -1809,7 +1812,7 @@
 		$action_argv_id=2;
 		if ($a->argv[1]=="1.1") $action_argv_id=3;
 
-		if ($a->argc<=$action_argv_id) die(api_error($a, $type, t("Invalid request.")));
+		if ($a->argc<=$action_argv_id) throw new BadRequestException("Invalid request.");
 		$action = str_replace(".".$type,"",$a->argv[$action_argv_id]);
 		if ($a->argc==$action_argv_id+2) {
 			$itemid = intval($a->argv[$action_argv_id+1]);

From 5d35974c19b50c98695c57cc1ad9195a36e7c396 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 14 Feb 2016 11:56:23 +0100
Subject: [PATCH 102/273] "addr" and "server_url" are now generated directly in
 "update_gcontact" if not given.

---
 include/Scrape.php   | 69 ++++++++++++++++++++++++++++++++++----------
 include/ostatus.php  | 20 -------------
 include/socgraph.php | 22 ++++++++++++++
 3 files changed, 75 insertions(+), 36 deletions(-)

diff --git a/include/Scrape.php b/include/Scrape.php
index d54a838afd..ef1db0312d 100644
--- a/include/Scrape.php
+++ b/include/Scrape.php
@@ -841,18 +841,18 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 		$vcard['fn'] = $url;
 
 	if (($notify != "") AND ($poll != "")) {
-		$baseurl = matching(normalise_link($notify), normalise_link($poll));
+		$baseurl = matching_url(normalise_link($notify), normalise_link($poll));
 
-		$baseurl2 = matching($baseurl, normalise_link($profile));
+		$baseurl2 = matching_url($baseurl, normalise_link($profile));
 		if ($baseurl2 != "")
 			$baseurl = $baseurl2;
 	}
 
 	if (($baseurl == "") AND ($notify != ""))
-		$baseurl = matching(normalise_link($profile), normalise_link($notify));
+		$baseurl = matching_url(normalise_link($profile), normalise_link($notify));
 
 	if (($baseurl == "") AND ($poll != ""))
-		$baseurl = matching(normalise_link($profile), normalise_link($poll));
+		$baseurl = matching_url(normalise_link($profile), normalise_link($poll));
 
 	$baseurl = rtrim($baseurl, "/");
 
@@ -907,19 +907,56 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 	return $result;
 }
 
-function matching($part1, $part2) {
-	$len = min(strlen($part1), strlen($part2));
+/**
+ * @brief Find the matching part between two url
+ *
+ * @param string $url1
+ * @param string $url2
+ * @return string The matching part
+ */
+function matching_url($url1, $url2) {
+
+	if (($url1 == "") OR ($url2 == ""))
+		return "";
+
+	$url1 = normalise_link($url1);
+	$url2 = normalise_link($url2);
+
+	$parts1 = parse_url($url1);
+	$parts2 = parse_url($url2);
+
+	if (!isset($parts1["host"]) OR !isset($parts2["host"]))
+		return "";
+
+	if ($parts1["scheme"] != $parts2["scheme"])
+		return "";
+
+	if ($parts1["host"] != $parts2["host"])
+		return "";
+
+	if ($parts1["port"] != $parts2["port"])
+		return "";
+
+	$match = $parts1["scheme"]."://".$parts1["host"];
+
+	if ($parts1["port"])
+		$match .= ":".$parts1["port"];
+
+	$pathparts1 = explode("/", $parts1["path"]);
+	$pathparts2 = explode("/", $parts2["path"]);
 
-	$match = "";
-	$matching = true;
 	$i = 0;
-	while (($i <= $len) AND $matching) {
-		if (substr($part1, $i, 1) == substr($part2, $i, 1))
-			$match .= substr($part1, $i, 1);
-		else
-			$matching = false;
+	$path = "";
+	do {
+		$path1 = $pathparts1[$i];
+		$path2 = $pathparts2[$i];
 
-		$i++;
-	}
-	return($match);
+		if ($path1 == $path2)
+			$path .= $path1."/";
+
+	} while (($path1 == $path2) AND ($i++ <= count($pathparts1)));
+
+	$match .= $path;
+
+	return normalise_link($match);
 }
diff --git a/include/ostatus.php b/include/ostatus.php
index 983ed6e1b4..5c5016d0fc 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -164,8 +164,6 @@ function ostatus_fetchauthor($xpath, $context, $importer, &$contact, $onlyfetch)
 			update_contact_avatar($author["author-avatar"], $importer["uid"], $contact["id"]);
 		}
 
-
-		/// @todo Add the "addr" field
 		$contact["generation"] = 2;
 		$contact["photo"] = $author["author-avatar"];
 		update_gcontact($contact);
@@ -675,24 +673,6 @@ function ostatus_conv_fetch_actor($actor) {
 			}
 		}
 
-	$contact["server_url"] = $contact["url"];
-
-	$server_url = matching($contact["server_url"], $contact["alias"]);
-	if (strlen($server_url) > 8)
-		$contact["server_url"] = $server_url;
-
-	$server_url = matching($contact["server_url"], $contact["photo"]);
-	if (strlen($server_url) > 8)
-		$contact["server_url"] = $server_url;
-
-	if (($contact["server_url"] == $contact["url"]) OR ($contact["server_url"] == $contact["alias"]))
-		unset($contact["server_url"]);
-	else {
-		$hostname = str_replace("http://", "", normalise_link($contact["server_url"]));
-		if ($hostname AND $contact["nick"])
-			$contact["addr"] = $contact["nick"]."@".$hostname;
-	}
-
 	update_gcontact($contact);
 }
 
diff --git a/include/socgraph.php b/include/socgraph.php
index ce5b08e641..e07e0d3533 100644
--- a/include/socgraph.php
+++ b/include/socgraph.php
@@ -1433,6 +1433,28 @@ function update_gcontact($contact) {
 	if (!isset($contact["updated"]))
 		$contact["updated"] = datetime_convert();
 
+	if ($contact["server_url"] == "") {
+		$server_url = $contact["url"];
+
+		$server_url = matching_url($server_url, $contact["alias"]);
+		if ($server_url != "")
+			$contact["server_url"] = $server_url;
+
+		$server_url = matching_url($server_url, $contact["photo"]);
+		if ($server_url != "")
+			$contact["server_url"] = $server_url;
+
+		$server_url = matching_url($server_url, $contact["notify"]);
+		if ($server_url != "")
+			$contact["server_url"] = $server_url;
+	} else
+		$contact["server_url"] = normalise_link($contact["server_url"]);
+
+	if (($contact["addr"] == "") AND ($contact["server_url"] != "") AND ($contact["nick"] != "")) {
+		$hostname = str_replace("http://", "", $contact["server_url"]);
+		$contact["addr"] = $contact["nick"]."@".$hostname;
+	}
+
 	// Check if any field changed
 	$update = false;
 	unset($fields["generation"]);

From 922186bdd1a09ddc45b346e46aef4762f9b64283 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 14 Feb 2016 12:39:57 +0100
Subject: [PATCH 103/273] Small bugfix for the keyword bug in the gcontact
 table

---
 include/socgraph.php | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/include/socgraph.php b/include/socgraph.php
index e07e0d3533..bd5b1817f0 100644
--- a/include/socgraph.php
+++ b/include/socgraph.php
@@ -1422,6 +1422,14 @@ function update_gcontact($contact) {
 	unset($fields["url"]);
 	unset($fields["updated"]);
 
+	// Bugfix: We had an error in the storing of keywords which lead to the "0"
+	// This value is still transmitted via poco.
+	if ($contact["keywords"] == "0")
+		unset($contact["keywords"]);
+
+	if ($r[0]["keywords"] == "0")
+		$r[0]["keywords"] = "";
+
 	// assign all unassigned fields from the database entry
 	foreach ($fields AS $field => $data)
 		if (!isset($contact[$field]) OR ($contact[$field] == ""))

From ec57b61f012562e3a2464869d62ade97fdc2e8d9 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 14 Feb 2016 15:02:59 +0100
Subject: [PATCH 104/273] The feed function has now a simulation mode

---
 include/feed.php | 89 ++++++++++++++++++++++++++++--------------------
 1 file changed, 52 insertions(+), 37 deletions(-)

diff --git a/include/feed.php b/include/feed.php
index eb91f7efd4..6d645ecffb 100644
--- a/include/feed.php
+++ b/include/feed.php
@@ -2,7 +2,7 @@
 require_once("include/html2bbcode.php");
 require_once("include/items.php");
 
-function feed_import($xml,$importer,&$contact, &$hub) {
+function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
 
 	$a = get_app();
 
@@ -25,7 +25,7 @@ function feed_import($xml,$importer,&$contact, &$hub) {
 
 	// Is it RDF?
 	if ($xpath->query('/rdf:RDF/rss:channel')->length > 0) {
-		//$author["author-link"] = $xpath->evaluate('/rdf:RDF/rss:channel/rss:link/text()')->item(0)->nodeValue;
+		$author["author-link"] = $xpath->evaluate('/rdf:RDF/rss:channel/rss:link/text()')->item(0)->nodeValue;
 		$author["author-name"] = $xpath->evaluate('/rdf:RDF/rss:channel/rss:title/text()')->item(0)->nodeValue;
 
 		if ($author["author-name"] == "")
@@ -36,19 +36,26 @@ function feed_import($xml,$importer,&$contact, &$hub) {
 
 	// Is it Atom?
 	if ($xpath->query('/atom:feed/atom:entry')->length > 0) {
-		//$self = $xpath->query("/atom:feed/atom:link[@rel='self']")->item(0)->attributes;
-		//if (is_object($self))
-		//	foreach($self AS $attributes)
-		//		if ($attributes->name == "href")
-		//			$author["author-link"] = $attributes->textContent;
+		$self = $xpath->query("atom:link[@rel='self']")->item(0)->attributes;
+		if (is_object($self))
+			foreach($self AS $attributes)
+				if ($attributes->name == "href")
+					$author["author-link"] = $attributes->textContent;
 
-		//if ($author["author-link"] == "") {
-		//	$alternate = $xpath->query("/atom:feed/atom:link[@rel='alternate']")->item(0)->attributes;
-		//	if (is_object($alternate))
-		//		foreach($alternate AS $attributes)
-		//			if ($attributes->name == "href")
-		//				$author["author-link"] = $attributes->textContent;
-		//}
+		if ($author["author-link"] == "") {
+			$alternate = $xpath->query("atom:link[@rel='alternate']")->item(0)->attributes;
+			if (is_object($alternate))
+				foreach($alternate AS $attributes)
+					if ($attributes->name == "href")
+						$author["author-link"] = $attributes->textContent;
+		}
+
+		if ($author["author-link"] == "")
+			$author["author-link"] = $xpath->evaluate('/atom:feed/atom:author/atom:uri/text()')->item(0)->nodeValue;
+		if ($author["author-link"] == "")
+			$author["author-link"] = $xpath->evaluate('/atom:feed/atom:id/text()')->item(0)->nodeValue;
+
+		$author["author-avatar"] = $xpath->evaluate('/atom:feed/atom:logo/text()')->item(0)->nodeValue;
 
 		$author["author-name"] = $xpath->evaluate('/atom:feed/atom:title/text()')->item(0)->nodeValue;
 
@@ -58,8 +65,6 @@ function feed_import($xml,$importer,&$contact, &$hub) {
 		if ($author["author-name"] == "")
 			$author["author-name"] = $xpath->evaluate('/atom:feed/atom:author/atom:name/text()')->item(0)->nodeValue;
 
-		//$author["author-avatar"] = $xpath->evaluate('/atom:feed/atom:logo/text()')->item(0)->nodeValue;
-
 		$author["edited"] = $author["created"] = $xpath->query('/atom:feed/atom:updated/text()')->item(0)->nodeValue;
 
 		$author["app"] = $xpath->evaluate('/atom:feed/atom:generator/text()')->item(0)->nodeValue;
@@ -69,9 +74,10 @@ function feed_import($xml,$importer,&$contact, &$hub) {
 
 	// Is it RSS?
 	if ($xpath->query('/rss/channel')->length > 0) {
-		//$author["author-link"] = $xpath->evaluate('/rss/channel/link/text()')->item(0)->nodeValue;
+		$author["author-link"] = $xpath->evaluate('/rss/channel/link/text()')->item(0)->nodeValue;
+
 		$author["author-name"] = $xpath->evaluate('/rss/channel/title/text()')->item(0)->nodeValue;
-		//$author["author-avatar"] = $xpath->evaluate('/rss/channel/image/url/text()')->item(0)->nodeValue;
+		$author["author-avatar"] = $xpath->evaluate('/rss/channel/image/url/text()')->item(0)->nodeValue;
 
 		if ($author["author-name"] == "")
 			$author["author-name"] = $xpath->evaluate('/rss/channel/copyright/text()')->item(0)->nodeValue;
@@ -86,18 +92,18 @@ function feed_import($xml,$importer,&$contact, &$hub) {
 		$entries = $xpath->query('/rss/channel/item');
 	}
 
-	//if ($author["author-link"] == "")
+	if (is_array($contact)) {
 		$author["author-link"] = $contact["url"];
 
-	if ($author["author-name"] == "")
-		$author["author-name"] = $contact["name"];
+		if ($author["author-name"] == "")
+			$author["author-name"] = $contact["name"];
 
-	//if ($author["author-avatar"] == "")
 		$author["author-avatar"] = $contact["thumb"];
 
-	$author["owner-link"] = $contact["url"];
-	$author["owner-name"] = $contact["name"];
-	$author["owner-avatar"] = $contact["thumb"];
+		$author["owner-link"] = $contact["url"];
+		$author["owner-name"] = $contact["name"];
+		$author["owner-avatar"] = $contact["thumb"];
+	}
 
 	$header = array();
 	$header["uid"] = $importer["uid"];
@@ -120,6 +126,8 @@ function feed_import($xml,$importer,&$contact, &$hub) {
 	if (!is_object($entries))
 		return;
 
+	$items = array();
+
 	$entrylist = array();
 
 	foreach ($entries AS $entry)
@@ -201,13 +209,13 @@ function feed_import($xml,$importer,&$contact, &$hub) {
 		if ($creator != "")
 			$item["author-name"] = $creator;
 
-		//$item["object"] = $xml;
-
-		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s', '%s')",
-			intval($importer["uid"]), dbesc($item["uri"]), dbesc(NETWORK_FEED), dbesc(NETWORK_DFRN));
-		if ($r) {
-			logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
-			continue;
+		if (!$simulate) {
+			$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s', '%s')",
+				intval($importer["uid"]), dbesc($item["uri"]), dbesc(NETWORK_FEED), dbesc(NETWORK_DFRN));
+			if ($r) {
+				logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
+				continue;
+			}
 		}
 
 		/// @TODO ?
@@ -272,14 +280,21 @@ function feed_import($xml,$importer,&$contact, &$hub) {
 			$item["body"] = html2bbcode($body);
 		}
 
-		logger("Stored feed: ".print_r($item, true), LOGGER_DEBUG);
+		if (!$simulate) {
+			logger("Stored feed: ".print_r($item, true), LOGGER_DEBUG);
 
-		$notify = item_is_remote_self($contact, $item);
-		$id = item_store($item, false, $notify);
+			$notify = item_is_remote_self($contact, $item);
+			$id = item_store($item, false, $notify);
 
-		//print_r($item);
+			logger("Feed for contact ".$contact["url"]." stored under id ".$id);
+		} else
+			$items[] = $item;
 
-		logger("Feed for contact ".$contact["url"]." stored under id ".$id);
+		if ($simulate)
+			break;
 	}
+
+	if ($simulate)
+		return array("header" => $author, "items" => $items);
 }
 ?>

From 21fc3c60d478db88b251599ee984e363e0c39bf8 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 14 Feb 2016 15:05:43 +0100
Subject: [PATCH 105/273] We now show the correct platform (redmatrix or
 hubzilla)

---
 include/contact_selectors.php | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/contact_selectors.php b/include/contact_selectors.php
index f104866232..a884a6b52b 100644
--- a/include/contact_selectors.php
+++ b/include/contact_selectors.php
@@ -99,8 +99,16 @@ function network_to_name($s, $profile = "") {
 
 	$networkname = str_replace($search,$replace,$s);
 
-	if (($s == NETWORK_DIASPORA) AND ($profile != "") AND diaspora_is_redmatrix($profile))
-		$networkname = t("Redmatrix");
+	if (($s == NETWORK_DIASPORA) AND ($profile != "") AND diaspora_is_redmatrix($profile)) {
+		$networkname = t("Hubzilla/Redmatrix");
+
+		$r = q("SELECT `gserver`.`platform` FROM `gcontact`
+				INNER JOIN `gserver` ON `gserver`.`nurl` = `gcontact`.`server_url`
+				WHERE `gcontact`.`nurl` = '%s' AND `platform` != ''",
+				dbesc(normalise_link($profile)));
+		if ($r)
+			$networkname = $r[0]["platform"];
+	}
 
 	return $networkname;
 }

From 7f1f549c6f435bfe29bf7d331748b2623f98e6ae Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 14 Feb 2016 15:08:49 +0100
Subject: [PATCH 106/273] Fallback when there is no nick name

---
 mod/item.php | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/mod/item.php b/mod/item.php
index 7e575a17e4..2ade524a05 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -160,6 +160,9 @@ function item_post(&$a) {
 				logger('no contact found: '.print_r($thrparent, true), LOGGER_DEBUG);
 			} else
 				logger('parent contact: '.print_r($parent_contact, true), LOGGER_DEBUG);
+
+			if ($parent_contact["nick"] == "")
+				$parent_contact["nick"] = $parent_contact["name"];
 		}
 	}
 

From b0548018d82cf6ecc717b3382ca5e699631458e9 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 14 Feb 2016 19:50:59 +0100
Subject: [PATCH 107/273] Simplepie is removed since we don't use it anymore

---
 boot.php                                      |     9 -
 include/Scrape.php                            |   127 +-
 include/feed.php                              |    28 +-
 library/simplepie/LICENSE.txt                 |    26 -
 library/simplepie/README.markdown             |    53 -
 .../COMPATIBILITY README.txt                  |     7 -
 .../sp_compatibility_test.php                 |   330 -
 library/simplepie/create.php                  |   178 -
 library/simplepie/db.sql                      |    38 -
 library/simplepie/demo/cli_test.php           |    23 -
 .../demo/for_the_demo/alternate_favicon.png   |   Bin 28621 -> 0 bytes
 .../for_the_demo/background_blockquote.png    |   Bin 27353 -> 0 bytes
 .../demo/for_the_demo/background_menuitem.gif |   Bin 533 -> 0 bytes
 .../for_the_demo/background_menuitem_off.gif  |   Bin 533 -> 0 bytes
 .../background_menuitem_shadow.gif            |   Bin 250 -> 0 bytes
 .../demo/for_the_demo/favicons/alternate.png  |   Bin 28621 -> 0 bytes
 .../demo/for_the_demo/favicons/blinklist.png  |   Bin 4377 -> 0 bytes
 .../demo/for_the_demo/favicons/blogmarks.png  |   Bin 3823 -> 0 bytes
 .../demo/for_the_demo/favicons/delicious.png  |   Bin 3739 -> 0 bytes
 .../demo/for_the_demo/favicons/digg.png       |   Bin 4004 -> 0 bytes
 .../demo/for_the_demo/favicons/magnolia.png   |   Bin 4574 -> 0 bytes
 .../demo/for_the_demo/favicons/myweb2.png     |   Bin 4010 -> 0 bytes
 .../demo/for_the_demo/favicons/newsvine.png   |   Bin 3804 -> 0 bytes
 .../demo/for_the_demo/favicons/reddit.png     |   Bin 4239 -> 0 bytes
 .../demo/for_the_demo/favicons/segnalo.png    |   Bin 4116 -> 0 bytes
 .../demo/for_the_demo/favicons/simpy.png      |   Bin 4256 -> 0 bytes
 .../demo/for_the_demo/favicons/spurl.png      |   Bin 3970 -> 0 bytes
 .../demo/for_the_demo/favicons/technorati.png |   Bin 4087 -> 0 bytes
 .../demo/for_the_demo/favicons/wists.png      |   Bin 3974 -> 0 bytes
 library/simplepie/demo/for_the_demo/feed.png  |   Bin 715 -> 0 bytes
 .../demo/for_the_demo/logo_simplepie_demo.png |   Bin 3047 -> 0 bytes
 .../demo/for_the_demo/lucida-grande-bold.swf  |   Bin 21159 -> 0 bytes
 .../demo/for_the_demo/mediaplayer.swf         |   Bin 32008 -> 0 bytes
 .../demo/for_the_demo/mediaplayer_readme.htm  |     5 -
 .../demo/for_the_demo/mini_podcast.png        |   Bin 1202 -> 0 bytes
 .../demo/for_the_demo/place_audio.png         |   Bin 851 -> 0 bytes
 .../demo/for_the_demo/place_video.png         |   Bin 36713 -> 0 bytes
 .../demo/for_the_demo/sIFR-print.css          |    35 -
 .../demo/for_the_demo/sIFR-screen.css         |    39 -
 .../demo/for_the_demo/sifr-config.js          |    40 -
 library/simplepie/demo/for_the_demo/sifr.js   |    19 -
 .../simplepie/demo/for_the_demo/simplepie.css |   397 -
 .../simplepie/demo/for_the_demo/sleight.js    |    31 -
 .../place_audio_fireworksfile.png             |   Bin 39177 -> 0 bytes
 .../place_video_fireworksfile.png             |   Bin 115826 -> 0 bytes
 .../source_files/sIFR-r245/SifrStyleSheet.as  |    71 -
 .../source_files/sIFR-r245/_README_.txt       |    12 -
 .../source_files/sIFR-r245/options.as         |    12 -
 .../source_files/sIFR-r245/sIFR.as            |   359 -
 .../source_files/sIFR-r245/sifr.fla           |   Bin 47104 -> 0 bytes
 .../demo/for_the_demo/top_gradient.gif        |   Bin 1378 -> 0 bytes
 .../simplepie/demo/for_the_demo/verdana.swf   |   Bin 28575 -> 0 bytes
 .../for_the_demo/yanone-kaffeesatz-bold.swf   |   Bin 76780 -> 0 bytes
 library/simplepie/demo/handler_image.php      |     6 -
 library/simplepie/demo/index.php              |   295 -
 library/simplepie/demo/minimalistic.php       |   137 -
 library/simplepie/demo/multifeeds.php         |   108 -
 library/simplepie/demo/test.php               |    62 -
 library/simplepie/idn/LICENCE                 |   502 -
 library/simplepie/idn/ReadMe.txt              |   123 -
 library/simplepie/idn/idna_convert.class.php  |   969 -
 library/simplepie/idn/npdata.ser              |     1 -
 library/simplepie/simplepie.inc               | 15150 ----------------
 util/README                                   |     2 +-
 64 files changed, 41 insertions(+), 19153 deletions(-)
 delete mode 100644 library/simplepie/LICENSE.txt
 delete mode 100644 library/simplepie/README.markdown
 delete mode 100644 library/simplepie/compatibility_test/COMPATIBILITY README.txt
 delete mode 100644 library/simplepie/compatibility_test/sp_compatibility_test.php
 delete mode 100644 library/simplepie/create.php
 delete mode 100644 library/simplepie/db.sql
 delete mode 100644 library/simplepie/demo/cli_test.php
 delete mode 100644 library/simplepie/demo/for_the_demo/alternate_favicon.png
 delete mode 100644 library/simplepie/demo/for_the_demo/background_blockquote.png
 delete mode 100644 library/simplepie/demo/for_the_demo/background_menuitem.gif
 delete mode 100644 library/simplepie/demo/for_the_demo/background_menuitem_off.gif
 delete mode 100644 library/simplepie/demo/for_the_demo/background_menuitem_shadow.gif
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/alternate.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/blinklist.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/blogmarks.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/delicious.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/digg.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/magnolia.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/myweb2.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/newsvine.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/reddit.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/segnalo.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/simpy.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/spurl.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/technorati.png
 delete mode 100644 library/simplepie/demo/for_the_demo/favicons/wists.png
 delete mode 100644 library/simplepie/demo/for_the_demo/feed.png
 delete mode 100644 library/simplepie/demo/for_the_demo/logo_simplepie_demo.png
 delete mode 100644 library/simplepie/demo/for_the_demo/lucida-grande-bold.swf
 delete mode 100644 library/simplepie/demo/for_the_demo/mediaplayer.swf
 delete mode 100644 library/simplepie/demo/for_the_demo/mediaplayer_readme.htm
 delete mode 100644 library/simplepie/demo/for_the_demo/mini_podcast.png
 delete mode 100644 library/simplepie/demo/for_the_demo/place_audio.png
 delete mode 100644 library/simplepie/demo/for_the_demo/place_video.png
 delete mode 100644 library/simplepie/demo/for_the_demo/sIFR-print.css
 delete mode 100644 library/simplepie/demo/for_the_demo/sIFR-screen.css
 delete mode 100644 library/simplepie/demo/for_the_demo/sifr-config.js
 delete mode 100644 library/simplepie/demo/for_the_demo/sifr.js
 delete mode 100644 library/simplepie/demo/for_the_demo/simplepie.css
 delete mode 100644 library/simplepie/demo/for_the_demo/sleight.js
 delete mode 100644 library/simplepie/demo/for_the_demo/source_files/place_audio_fireworksfile.png
 delete mode 100644 library/simplepie/demo/for_the_demo/source_files/place_video_fireworksfile.png
 delete mode 100644 library/simplepie/demo/for_the_demo/source_files/sIFR-r245/SifrStyleSheet.as
 delete mode 100644 library/simplepie/demo/for_the_demo/source_files/sIFR-r245/_README_.txt
 delete mode 100644 library/simplepie/demo/for_the_demo/source_files/sIFR-r245/options.as
 delete mode 100644 library/simplepie/demo/for_the_demo/source_files/sIFR-r245/sIFR.as
 delete mode 100644 library/simplepie/demo/for_the_demo/source_files/sIFR-r245/sifr.fla
 delete mode 100644 library/simplepie/demo/for_the_demo/top_gradient.gif
 delete mode 100644 library/simplepie/demo/for_the_demo/verdana.swf
 delete mode 100644 library/simplepie/demo/for_the_demo/yanone-kaffeesatz-bold.swf
 delete mode 100644 library/simplepie/demo/handler_image.php
 delete mode 100644 library/simplepie/demo/index.php
 delete mode 100644 library/simplepie/demo/minimalistic.php
 delete mode 100644 library/simplepie/demo/multifeeds.php
 delete mode 100644 library/simplepie/demo/test.php
 delete mode 100644 library/simplepie/idn/LICENCE
 delete mode 100644 library/simplepie/idn/ReadMe.txt
 delete mode 100644 library/simplepie/idn/idna_convert.class.php
 delete mode 100644 library/simplepie/idn/npdata.ser
 delete mode 100644 library/simplepie/simplepie.inc

diff --git a/boot.php b/boot.php
index 4ef30eadac..62b90aa2cd 100644
--- a/boot.php
+++ b/boot.php
@@ -588,15 +588,6 @@ class App {
 		if(x($_SERVER,'SERVER_NAME')) {
 			$this->hostname = $_SERVER['SERVER_NAME'];
 
-			// See bug 437 - this didn't work so disabling it
-			//if(stristr($this->hostname,'xn--')) {
-				// PHP or webserver may have converted idn to punycode, so
-				// convert punycode back to utf-8
-			//	require_once('library/simplepie/idn/idna_convert.class.php');
-			//	$x = new idna_convert();
-			//	$this->hostname = $x->decode($_SERVER['SERVER_NAME']);
-			//}
-
 			if(x($_SERVER,'SERVER_PORT') && $_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443)
 				$this->hostname .= ':' . $_SERVER['SERVER_PORT'];
 			/*
diff --git a/include/Scrape.php b/include/Scrape.php
index ca6489b16a..95a3c0221f 100644
--- a/include/Scrape.php
+++ b/include/Scrape.php
@@ -2,6 +2,7 @@
 
 require_once('library/HTML5/Parser.php');
 require_once('include/crypto.php');
+require_once('include/feed.php');
 
 if(! function_exists('scrape_dfrn')) {
 function scrape_dfrn($url, $dont_probe = false) {
@@ -366,8 +367,6 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 		$network = NETWORK_TWITTER;
 	}
 
-	// Twitter is deactivated since twitter closed its old API
-	//$twitter = ((strpos($url,'twitter.com') !== false) ? true : false);
 	$lastfm  = ((strpos($url,'last.fm/user') !== false) ? true : false);
 
 	$at_addr = ((strpos($url,'@') !== false) ? true : false);
@@ -604,21 +603,6 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 			$vcard['nick'] = $addr_parts[0];
 		}
 
-		/* if($twitter) {
-			logger('twitter: setup');
-			$tid = basename($url);
-			$tapi = 'https://api.twitter.com/1/statuses/user_timeline.rss';
-			if(intval($tid))
-				$poll = $tapi . '?user_id=' . $tid;
-			else
-				$poll = $tapi . '?screen_name=' . $tid;
-			$profile = 'http://twitter.com/#!/' . $tid;
-			//$vcard['photo'] = 'https://api.twitter.com/1/users/profile_image/' . $tid;
-			$vcard['photo'] = 'https://api.twitter.com/1/users/profile_image?screen_name=' . $tid . '&size=bigger';
-			$vcard['nick'] = $tid;
-			$vcard['fn'] = $tid;
-		} */
-
 		if($lastfm) {
 			$profile = $url;
 			$poll = str_replace(array('www.','last.fm/'),array('','ws.audioscrobbler.com/1.0/'),$url) . '/recenttracks.rss';
@@ -662,85 +646,34 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 
 			if(x($feedret,'photo') && (! x($vcard,'photo')))
 				$vcard['photo'] = $feedret['photo'];
-			require_once('library/simplepie/simplepie.inc');
-			$feed = new SimplePie();
+
 			$cookiejar = tempnam(get_temppath(), 'cookiejar-scrape-feed-');
 			$xml = fetch_url($poll, false, $redirects, 0, Null, $cookiejar);
 			unlink($cookiejar);
 
 			logger('probe_url: fetch feed: ' . $poll . ' returns: ' . $xml, LOGGER_DATA);
-			$a = get_app();
 
-			logger('probe_url: scrape_feed: headers: ' . $a->get_curl_headers(), LOGGER_DATA);
-
-			// Don't try and parse an empty string
-			$feed->set_raw_data(($xml) ? $xml : '<?xml version="1.0" encoding="utf-8" ?><xml></xml>');
-
-			$feed->init();
-			if($feed->error()) {
-				logger('probe_url: scrape_feed: Error parsing XML: ' . $feed->error());
+			if ($xml == "") {
+				logger("scrape_feed: XML is empty for feed ".$poll);
 				$network = NETWORK_PHANTOM;
-			}
+			} else {
+				$data = feed_import($xml,$dummy1,$dummy2, $dummy3, true);
 
-			if(! x($vcard,'photo'))
-				$vcard['photo'] = $feed->get_image_url();
-			$author = $feed->get_author();
+				if (!is_array($data)) {
+					logger("scrape_feed: This doesn't seem to be a feed: ".$poll);
+					$network = NETWORK_PHANTOM;
+				} else {
+					if (($vcard["photo"] == "") AND ($data["header"]["author-avatar"] != ""))
+						$vcard["photo"] = $data["header"]["author-avatar"];
 
-			if($author) {
-				$vcard['fn'] = unxmlify(trim($author->get_name()));
-				if(! $vcard['fn'])
-					$vcard['fn'] = trim(unxmlify($author->get_email()));
-				if(strpos($vcard['fn'],'@') !== false)
-					$vcard['fn'] = substr($vcard['fn'],0,strpos($vcard['fn'],'@'));
+					if (($vcard["fn"] == "") AND ($data["header"]["author-name"] != ""))
+						$vcard["fn"] = $data["header"]["author-name"];
 
-				$email = unxmlify($author->get_email());
-				if(! $profile && $author->get_link())
-					$profile = trim(unxmlify($author->get_link()));
-				if(! $vcard['photo']) {
-					$rawtags = $feed->get_feed_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author');
-					if($rawtags) {
-						$elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10];
-						if((x($elems,'link')) && ($elems['link'][0]['attribs']['']['rel'] === 'photo'))
-							$vcard['photo'] = $elems['link'][0]['attribs']['']['href'];
-					}
-				}
-				// Fetch fullname via poco:displayName
-				$pocotags = $feed->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author');
-				if ($pocotags) {
-					$elems = $pocotags[0]['child']['http://portablecontacts.net/spec/1.0'];
-					if (isset($elems["displayName"]))
-						$vcard['fn'] = $elems["displayName"][0]["data"];
-					if (isset($elems["preferredUsername"]))
-						$vcard['nick'] = $elems["preferredUsername"][0]["data"];
-				}
-			}
-			else {
-				$item = $feed->get_item(0);
-				if($item) {
-					$author = $item->get_author();
-					if($author) {
-						$vcard['fn'] = trim(unxmlify($author->get_name()));
-						if(! $vcard['fn'])
-							$vcard['fn'] = trim(unxmlify($author->get_email()));
-						if(strpos($vcard['fn'],'@') !== false)
-							$vcard['fn'] = substr($vcard['fn'],0,strpos($vcard['fn'],'@'));
-						$email = unxmlify($author->get_email());
-						if(! $profile && $author->get_link())
-							$profile = trim(unxmlify($author->get_link()));
-					}
-					if(! $vcard['photo']) {
-						$rawmedia = $item->get_item_tags('http://search.yahoo.com/mrss/','thumbnail');
-						if($rawmedia && $rawmedia[0]['attribs']['']['url'])
-							$vcard['photo'] = unxmlify($rawmedia[0]['attribs']['']['url']);
-					}
-					if(! $vcard['photo']) {
-						$rawtags = $item->get_item_tags( SIMPLEPIE_NAMESPACE_ATOM_10, 'author');
-						if($rawtags) {
-							$elems = $rawtags[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_10];
-							if((x($elems,'link')) && ($elems['link'][0]['attribs']['']['rel'] === 'photo'))
-								$vcard['photo'] = $elems['link'][0]['attribs']['']['href'];
-						}
-					}
+					if (($vcard["nick"] == "") AND ($data["header"]["author-nick"] != ""))
+						$vcard["nick"] = $data["header"]["author-nick"];
+
+					if(!$profile AND ($data["header"]["author-link"] != "") AND !in_array($network, array("", NETWORK_FEED)))
+						$profile = $data["header"]["author-link"];
 				}
 			}
 
@@ -783,27 +716,9 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 				}
 			}
 
-			if((! $vcard['photo']) && strlen($email))
-				$vcard['photo'] = avatar_img($email);
-			if($poll === $profile)
-				$lnk = $feed->get_permalink();
-			if(isset($lnk) && strlen($lnk))
-				$profile = $lnk;
-
-			if(! $network) {
+			if(! $network)
 				$network = NETWORK_FEED;
-				// If it is a feed, don't take the author name as feed name
-				unset($vcard['fn']);
-			}
-			if(! (x($vcard,'fn')))
-				$vcard['fn'] = notags($feed->get_title());
-			if(! (x($vcard,'fn')))
-				$vcard['fn'] = notags($feed->get_description());
 
-			if(strpos($vcard['fn'],'Twitter / ') !== false) {
-				$vcard['fn'] = substr($vcard['fn'],strpos($vcard['fn'],'/')+1);
-				$vcard['fn'] = trim($vcard['fn']);
-			}
 			if(! x($vcard,'nick')) {
 				$vcard['nick'] = strtolower(notags(unxmlify($vcard['fn'])));
 				if(strpos($vcard['nick'],' '))
@@ -816,7 +731,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 
 	if(! x($vcard,'photo')) {
 		$a = get_app();
-		$vcard['photo'] = $a->get_baseurl() . '/images/person-175.jpg' ;
+		$vcard['photo'] = App::get_baseurl() . '/images/person-175.jpg' ;
 	}
 
 	if(! $profile)
diff --git a/include/feed.php b/include/feed.php
index 6d645ecffb..184b784c72 100644
--- a/include/feed.php
+++ b/include/feed.php
@@ -14,12 +14,13 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
 	$doc = new DOMDocument();
 	@$doc->loadXML($xml);
 	$xpath = new DomXPath($doc);
-	$xpath->registerNamespace('atom', "http://www.w3.org/2005/Atom");
+	$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
 	$xpath->registerNamespace('dc', "http://purl.org/dc/elements/1.1/");
 	$xpath->registerNamespace('content', "http://purl.org/rss/1.0/modules/content/");
 	$xpath->registerNamespace('rdf', "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
 	$xpath->registerNamespace('rss', "http://purl.org/rss/1.0/");
 	$xpath->registerNamespace('media', "http://search.yahoo.com/mrss/");
+	$xpath->registerNamespace('poco', NAMESPACE_POCO);
 
 	$author = array();
 
@@ -36,22 +37,23 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
 
 	// Is it Atom?
 	if ($xpath->query('/atom:feed/atom:entry')->length > 0) {
-		$self = $xpath->query("atom:link[@rel='self']")->item(0)->attributes;
-		if (is_object($self))
-			foreach($self AS $attributes)
+		$alternate = $xpath->query("atom:link[@rel='alternate']")->item(0)->attributes;
+		if (is_object($alternate))
+			foreach($alternate AS $attributes)
 				if ($attributes->name == "href")
 					$author["author-link"] = $attributes->textContent;
 
+		if ($author["author-link"] == "")
+			$author["author-link"] = $xpath->evaluate('/atom:feed/atom:author/atom:uri/text()')->item(0)->nodeValue;
+
 		if ($author["author-link"] == "") {
-			$alternate = $xpath->query("atom:link[@rel='alternate']")->item(0)->attributes;
-			if (is_object($alternate))
-				foreach($alternate AS $attributes)
+			$self = $xpath->query("atom:link[@rel='self']")->item(0)->attributes;
+			if (is_object($self))
+				foreach($self AS $attributes)
 					if ($attributes->name == "href")
 						$author["author-link"] = $attributes->textContent;
 		}
 
-		if ($author["author-link"] == "")
-			$author["author-link"] = $xpath->evaluate('/atom:feed/atom:author/atom:uri/text()')->item(0)->nodeValue;
 		if ($author["author-link"] == "")
 			$author["author-link"] = $xpath->evaluate('/atom:feed/atom:id/text()')->item(0)->nodeValue;
 
@@ -65,6 +67,14 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
 		if ($author["author-name"] == "")
 			$author["author-name"] = $xpath->evaluate('/atom:feed/atom:author/atom:name/text()')->item(0)->nodeValue;
 
+		$value = $xpath->evaluate('atom:author/poco:displayName/text()')->item(0)->nodeValue;
+		if ($value != "")
+			$author["author-name"] = $value;
+
+		$value = $xpath->evaluate('atom:author/poco:preferredUsername/text()')->item(0)->nodeValue;
+		if ($value != "")
+			$author["author-nick"] = $value;
+
 		$author["edited"] = $author["created"] = $xpath->query('/atom:feed/atom:updated/text()')->item(0)->nodeValue;
 
 		$author["app"] = $xpath->evaluate('/atom:feed/atom:generator/text()')->item(0)->nodeValue;
diff --git a/library/simplepie/LICENSE.txt b/library/simplepie/LICENSE.txt
deleted file mode 100644
index a822a4bd98..0000000000
--- a/library/simplepie/LICENSE.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright (c) 2004-2007, Ryan Parman and Geoffrey Sneddon.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, are 
-permitted provided that the following conditions are met:
-
-	* Redistributions of source code must retain the above copyright notice, this list of 
-	  conditions and the following disclaimer.
-
-	* Redistributions in binary form must reproduce the above copyright notice, this list 
-	  of conditions and the following disclaimer in the documentation and/or other materials 
-	  provided with the distribution.
-
-	* Neither the name of the SimplePie Team nor the names of its contributors may be used 
-	  to endorse or promote products derived from this software without specific prior 
-	  written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS 
-OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
-AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS 
-AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
-OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
-POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/library/simplepie/README.markdown b/library/simplepie/README.markdown
deleted file mode 100644
index e5ca021ced..0000000000
--- a/library/simplepie/README.markdown
+++ /dev/null
@@ -1,53 +0,0 @@
-# SimplePie
-
-## Authors and contributors
-
-* [Ryan Parman](http://ryanparman.com)
-* [Geoffrey Sneddon](http://gsnedders.com)
-* [Ryan McCue](http://ryanmccue.info)
-* [Michael Shipley](http://michaelpshipley.com)
-* [Steve Minutillo](http://minutillo.com/steve/)
-
-
-## License
-
-[New BSD license](http://www.opensource.org/licenses/bsd-license.php)
-
-
-## Project status
-
-SimplePie is currently maintained by Ryan McCue.
-
-At the moment, there isn't a lot of active development happening. If the community decides that SimplePie is a valuable tool, then the community will come together to maintain it into the future.
-
-If you're interested in getting involved with SimplePie, please get in touch with Ryan McCue.
-
-
-## What comes in the package?
-
-1. `simplepie.inc` - The SimplePie library.  This is all that's required for your pages.
-2. `README.markdown` - This document.
-3. `LICENSE.txt` - A copy of the BSD license.
-4. `compatibility_test/` - The SimplePie compatibility test that checks your server for required settings.
-5. `demo/` - A basic feed reader demo that shows off some of SimplePie's more noticable features.
-6. `idn/` - A third-party library that SimplePie can optionally use to understand Internationalized Domain Names (IDNs).
-7. `test/` - SimplePie's unit test suite.
-
-
-## To start the demo
-
-1. Upload this package to your webserver.
-2. Make sure that the cache folder inside of the demo folder is server-writable.
-3. Navigate your browser to the demo folder.
-
-
-## Need support?
-
-For further setup and install documentation, function references, etc., visit:
-[http://simplepie.org/wiki/](http://simplepie.org/wiki/)
-
-For bug reports and feature requests, visit:
-[http://github.com/rmccue/simplepie/issues](http://github.com/rmccue/simplepie/issues)
-
-Support mailing list -- powered by users, for users.
-[http://tech.groups.yahoo.com/group/simplepie-support/](http://tech.groups.yahoo.com/group/simplepie-support/)
diff --git a/library/simplepie/compatibility_test/COMPATIBILITY README.txt b/library/simplepie/compatibility_test/COMPATIBILITY README.txt
deleted file mode 100644
index 5b24989927..0000000000
--- a/library/simplepie/compatibility_test/COMPATIBILITY README.txt	
+++ /dev/null
@@ -1,7 +0,0 @@
-SIMPLEPIE COMPATIBILITY TEST
-
-1) Upload sp_compatibility_test.php to the web-accessible root of your website.
-For example, if your website is www.example.com, upload it so that you can get 
-to it at www.example.com/sp_compatibility_test.php
-
-2) Open your web browser and go to the page you just uploaded.
\ No newline at end of file
diff --git a/library/simplepie/compatibility_test/sp_compatibility_test.php b/library/simplepie/compatibility_test/sp_compatibility_test.php
deleted file mode 100644
index a7a7f5fde2..0000000000
--- a/library/simplepie/compatibility_test/sp_compatibility_test.php
+++ /dev/null
@@ -1,330 +0,0 @@
-<?php
-if (isset($_GET['logopng']))
-{
-	$data='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';
-	header('Content-type: image/png');
-	echo base64_decode($data);
-	exit;
-}
-else if (isset($_GET['background']))
-{
-	$data='R0lGODlhMAEeAeYAAP///8ni6cTf5+72+PD3+c3k6+nz9ufy9ev099Pn7bnZ48bg6LfY4uHv8/r8/f3+/v7//7bX4cjh6fj7/Mvj6vz9/rva4+z19/X6+/f7/Pn8/fb6+7jZ4vv9/bra473b5Lzb5LXX4b7c5b/c5e31+NTo7tvs8dfq7/H3+bjY4tnq79Hm7c/l69nr8PL4+t7t8sDd5cLe5uPw9Nvr8Mri6fP4+tLn7er099Hm7O/2+dDm7OTw9OXx9Nbp7tbp7+Lv8+Du8szj6sXg57bY4d3s8djq7+jz9tzs8cPe58fh6M7k68Pf5+by9fz+/sDd5vT5+vT5+97t8bbY4trr8P7+/v7+/+Pw8+Xx9dXo7sHe5vH4+fP5+sHd5t/u8s/l7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAAwAR4BAAf/gCGCg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnp+goaKNEaWmp6ipqqusra6vsLGys7S1tre4ubq7vL2+v8DBwsPExbBDyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7KUuHi4+Tl5ufo6err7O3u7/Dx8vP09fb34wz6+/z9/v8AAwocSLCgwYMIEypcyLChw4cQI0qcSLGixYsYM2osmKKjx48gQ4ocSbKkyZMoU6pcybKly5cwY8qc+ZGDzZs4c+rcybOnz59AgwodSrSo0aNIkypdyrSp06dQo0qdSrWq1aAKsmrdyrWr169gw4odS7as2bNo06pdy7at27dw/+PKnUu3rt27ePOS9cC3r9+/gAMLHky4sOHDiBMrXsy4sePHkCNLnky5suXLmDNr3sz5sIXPoEOLHk26tOnTqFOrXs26tevXsGPLnk27tu3buHPr3s27t+/fqkEIH068uPHjyJMrX868ufPn0KNLn069uvXr2LNr3869u/fv4MOLb/6hvPnz6NOrX8++vfv38OPLn0+/vv37+PPr38+/v///AAYo4IAEFgifCAgmqOCCDDbo4IMQRijhhBRWaOGFGGao4YYcdujhhyCGKOKIJJZo4okoTjjCiiy26OKLMMYo44w01mjjjTjmqOOOPPbo449ABinkkEQWaeSRSCap5P+SNsLg5JNQRinllFRWaeWVWGap5ZZcdunll2CGKeaYZELpxJlopqnmmmy26eabcMYp55x01mnnnXjmqeeefPaZJheABirooIQWauihiCaq6KKMNuroo5BGKumklFZqqaBZZKrpppx26umnoIYq6qiklmrqqaimquqqrLbq6qubxiDrrLTWauutuOaq66689urrr8AGK+ywxBZr7LHI0orEssw26+yz0EYr7bTUVmvttdhmq+223Hbr7bfghtvsEuSWa+656Kar7rrstuvuu/DGK++89NZr77345quvuQL06++/AAcs8MAEF2zwwQgnrPDCDDfs8MMQRyzxxBRXbPH/xRhnrPHGHHeMsBAghyzyyCSXbPLJKKes8sost+zyyzDHLPPMNNdss8gL5Kzzzjz37PPPQAct9NBEF2300UgnrfTSTDft9NNQRy311FRXbfXVWGdNdBJcd+3112CHLfbYZJdt9tlop6322my37fbbcMctt9cS1G333XjnrffefPft99+ABy744IQXbvjhiCeu+OKMN+7445BHLvnklFcOeACYZ6755px37vnnoIcu+uikl2766ainrvrqrLfu+uuwxy777LTXbvvtuI9Ow+689+7778AHL/zwxBdv/PHIJ6/88sw37/zz0EffOwXUV2/99dhnr/323Hfv/ffghy/+//jkl2/++einr/767Lfv/vvwxy///PR/H8T9+Oev//789+///wAMoAAHSMACGvCACEygAhfIwAbmrwAQjKAEJ0jBClrwghjMoAY3yMEOevCDIAyhCEdIwhKa8IQoTKEKV8jCFrrwhTDcoBJmSMMa2vCGOMyhDnfIwx768IdADKIQh0jEIhrxiEhMYg1ZwMQmOvGJUIyiFKdIxSpa8YpYzKIWt8jFLnrxi2AMoxid6IUymvGMaEyjGtfIxja68Y1wjKMc50jHOtrxjnjMox73eEYd+PGPgAykIAdJyEIa8pCITKQiF8nIRjrykZCMpCQnSUlA4uCSmMykJjfJyU568v+ToAylKEdJylKa8pSoTKUqV8nKVmZyBbCMpSxnScta2vKWuMylLnfJy1768pfADKYwh0nMYhpTljZIpjKXycxmOvOZ0IymNKdJzWpa85rYzKY2t8nNbnrzm8tMgDjHSc5ymvOc6EynOtfJzna6853wjKc850nPetrznvjMpz73yc9++vOfAA2oQNtZgoIa9KAITahCF8rQhjr0oRCNqEQnStGKWvSiGM2oRjd6UCx49KMgDalIR0rSkpr0pChNqUpXytKWuvSlMI2pTGdKU5D24KY4zalOd8rTnvr0p0ANqlCHStSiGvWoSE2qUpfK1Kbm1AdQjapUp0rVqlr1qlj/zapWt8rVrnr1q2ANq1jHStaymlWqJ0irWtfK1ra69a1wjatc50rXutr1rnjNq173yte++vWvay2CYAdL2MIa9rCITaxiF8vYxjr2sZCNrGQnS9nKWvaymCWsCjbL2c569rOgDa1oR0va0pr2tKhNrWpXy9rWuva1sI1tZ1tA29ra9ra4za1ud8vb3vr2t8ANrnCHS9ziGve4yE2ucm07heY697nQja50p0vd6lr3utjNrna3y93ueve74A2veMf73BmY97zoTa9618ve9rr3vfCNr3znS9/62ve++M2vfvfLX/Sa4L8ADrCAB0zgAhv4wAhOsIIXzOAGO/jBEI6w/4QnTOEKB/gIGM6whjfM4Q57+MMgDrGIR0ziEpv4xChOsYpXzOIWu1jDRIixjGdM4xrb+MY4zrGOd8zjHvv4x0AOspCHTOQiG/nIM46CkpfM5CY7+clQjrKUp0zlKlv5yljOspa3zOUue/nLYGbyC8ZM5jKb+cxoTrOa18zmNrv5zXCOs5znTOc62/nOeM5zmbvA5z77+c+ADrSgB03oQhv60IhOtKIXzehGO/rRkI60pP0MhEpb+tKYzrSmN83pTnv606AOtahHTepSm/rUqE61qld96Qa4+tWwjrWsZ03rWtv61rjOta53zete+/rXwA62sIdN7GIb+9jITrayl//N7GY7O9c/iLa0p03talv72tjOtra3ze1ue/vb4A63uMdN7nKb+9zTtoK6183udrv73fCOt7znTe962/ve+M63vvfN7377+98AZ7cMBk7wghv84AhPuMIXzvCGO/zhEI+4xCdO8Ypb/OIYz3jBd8Dxjnv84yAPuchHTvKSm/zkKE+5ylfO8pa7/OUwj7nMPc6Dmtv85jjPuc53zvOe+/znQA+60IdO9KIb/ehIT7rSl37zKzj96VCPutSnTvWqW/3qWM+61rfO9a57/etgD7vYx052qDPh7GhPu9rXzva2u/3tcI+73OdO97rb/e54z7ve9873vqf9AIAPvOAHT/j/whv+8IhPvOIXz/jGO/7xkI+85CdP+cpb/vKYz7zmN8/5znv+86BfvBFGT/rSm/70qE+96lfP+ta7/vWwj73sZ0/72tv+9rjPfekNwPve+/73wA++8IdP/OIb//jIT77yl8/85jv/+dCPvvSnT/3qW//62M++9rfP/ePf4PvgD7/4x0/+8pv//OhPv/rXz/72u//98I+//OdP//qHHwH4z7/+98///vv//wAYgAI4gARYgAZ4gAiYgAq4gAzYgA74gBAYgRI4gRRYgRZ4gRg4gBewgRzYgR74gSAYgiI4giRYgiZ4giiYgiq4gizYgi74gjAYgzI4gzRYgzZ4gziY/4M6uIMmSAI++INAGIRCOIREWIRGeIRImIRKuIRM2IRO+IRQGIVSOIVUCIQDcIVYmIVauIVc2IVe+IVgGIZiOIZkWIZmeIZomIZquIZs2IZu+IZwGIdyOId0WId2eIdimAN6uId82Id++IeAGIiCOIiEWIiGeIiImIiKuIiM2IiO+IiQyIcEMImUWImWeImYmImauImc2Ime+ImgGIqiOIqkWIqmeIqomIqquIqs2Iqu+IqwGIuyOIueiAK2eIu4mIu6uIu82Iu++IvAGIzCOIzEWIzGeIzImIzKuIzMiIta8IzQGI3SOI3UWI3WeI3YmI3auI3c2I3e+I3gGI7iOP+O5FiO0egC6JiO6riO7NiO7viO8BiP8jiP9FiP9niP+JiP+riP/NiP/qiONRCQAjmQBFmQBnmQCJmQCrmQDNmQDvmQEBmREjmRFFmRFnmRA7kFGrmRHNmRHvmRIBmSIjmSJFmSJnmSKJmSKrmSLNmSLvmSMMmRTzCTNFmTNnmTOJmTOrmTPNmTPvmTQBmUQjmURFmURnmUSJmUNQkFTNmUTvmUUBmVUjmVVFmVVnmVWJmVWrmVXNmVXvmVYBmWYumUGFCWZnmWaJmWarmWbNmWbvmWcBmXcjmXdFmXdnmXeJmXermXfNmXfvmXgBmYgjmYhFmYcLkBiJmYirmYjNn/mI75mJAZmZI5mZRZmZZ5mZiZmZq5mZzZmZ75maAZmqI5mqRZmqZ5mqg5mRmwmqzZmq75mrAZm7I5m7RZm7Z5m7iZm7q5m7zZm775m8AZnMI5nMRZnMZ5nMiZnMq5nLY5Ac75nNAZndI5ndRZndZ5ndiZndq5ndzZnd75neAZnuI5nuRZnuZ5nuiZnuq5nuzZnu6ZnRoQn/I5n/RZn/Z5n/iZn/q5n/zZn/75nwAaoAI6oARaoAZ6oAiaoAq6oAzaoA76oBAaofzpABRaoRZ6oRiaoRq6oRzaoR76oSAaoiI6oiRaoiZ6oiiaoiq6oizaoi76ojAaozI6ozT6oR1w/6M4mqM6uqM82qM++qNAGqRCOqREWqRGeqRImqRKuqRM2qRO+qRQGqVSOqVUWqVWeqVCWgFauqVc2qVe+qVgGqZiOqZkWqZmeqZomqZquqZs2qZu+qZwGqdyOqd0Wqd2eqd4mqd6WqZN0Kd++qeAGqiCOqiEWqiGeqiImqiKuqiM2qiO+qiQGqmSOql/+gCWeqmYmqmauqmc2qme+qmgGqqiOqqkWqqmeqqomqqquqqs2qqu+qqwGquyOqu0Wqu2GqpUkKu6uqu82qu++qvAGqzCOqzEWqzGeqzImqzKuqzM2qzO+qy7WgXSOq3UWq3Weq3Ymq3auq3c2q3e+q3gGv+u4jqu5Fqu5nqu6EqtELCu7Nqu7vqu8Bqv8jqv9Fqv9nqv+Jqv+rqv/Nqv/vqvABuwAjuwBFuwBnuwCJuwCruw9goADvuwEBuxEjuxFFuxFnuxGJuxGruxHNuxHvuxIBuyIjuyJFuyJnuyKJuyKruyLNuyLvuyMBuzMjuzNFuzNnuzOJuzOruzPNuzPvuzQBu0Qju0RFu0Rnu0SJu0Sru0TNu0Tvu0UBu1Uju1VFu1Vnu1WJu1Wru1XNu1Xvu1YBu2Yju2ZFu2Znu2aJu2aru2bNu2bvu2cBu3cju3dFu3dnu3eJu3eru3fNu3fvu3gBu4gju4hFu4hnu4iJu4irv/uIzbuI77uJAbuZI7uZRbuZZ7uZibuZq7uZzbuZ77uaAbuqI7uqRbuqZ7uqibuqq7uqzbuq77urAbu7I7u7Rbu7Z7u7ibu7q7u7zbu777u8AbvMI7vMRbvMZ7vMibvMq7vMzbvM77vNAbvdI7vdRbvdZ7vdibvdq7vdzbvd77veAbvuI7vuRbvuZ7vuibvuq7vuzbvu77vvAbv/I7v/Rbv/Z7v/ibv/q7v/zbv/77vwAcwAI8wARcwAZ8wAicwAq8wAzcwA78wBAcwRI8wRRcwRZ8wRicwRq8wRzcwR78wSAcwiI8wiRcwiZ8wiicwiq8wizcwi78wjAcwzI8wzRcFcM2fMM4nMM6vMM83MM+/MNArLmBAAA7';
-	header('Content-type: image/gif');
-	echo base64_decode($data);
-	exit;
-}
-
-$php_ok = (function_exists('version_compare') && version_compare(phpversion(), '4.3.0', '>='));
-$pcre_ok = extension_loaded('pcre');
-$curl_ok = function_exists('curl_exec');
-$zlib_ok = extension_loaded('zlib');
-$mbstring_ok = extension_loaded('mbstring');
-$iconv_ok = extension_loaded('iconv');
-if (extension_loaded('xmlreader'))
-{
-	$xml_ok = true;
-}
-elseif (extension_loaded('xml'))
-{
-	$parser_check = xml_parser_create();
-	xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
-	xml_parser_free($parser_check);
-	$xml_ok = isset($values[0]['value']);
-}
-else
-{
-	$xml_ok = false;
-}
-
-header('Content-type: text/html; charset=UTF-8');
-
-?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
-
-<html lang="en">
-<head>
-<title>SimplePie: Server Compatibility Test 1.2</title>
-
-<style type="text/css">
-body {
-	font:14px/1.4em "Lucida Grande", Verdana, Arial, Helvetica, Clean, Sans, sans-serif;
-	letter-spacing:0px;
-	color:#333;
-	margin:0;
-	padding:0;
-	background:#fff url(<?php echo pathinfo(__FILE__, PATHINFO_BASENAME); ?>?background) repeat-x top left;
-}
-
-div#site {
-	width:550px;
-	margin:20px auto 0 auto;
-}
-
-a {
-	color:#000;
-	text-decoration:underline;
-	padding:0 1px;
-}
-
-a:hover {
-	color:#fff;
-	background-color:#333;
-	text-decoration:none;
-	padding:0 1px;
-}
-
-p {
-	margin:0;
-	padding:5px 0;
-}
-
-em {
-	font-style:normal;
-	background-color:#ffc;
-}
-
-ul, ol {
-	margin:10px 0 10px 20px;
-	padding:0 0 0 15px;
-}
-
-ul li, ol li {
-	margin:0 0 7px 0;
-	padding:0 0 0 3px;
-}
-
-h2 {
-	font-size:18px;
-	padding:0;
-	margin:30px 0 10px 0;
-}
-
-h3 {
-	font-size:16px;
-	padding:0;
-	margin:20px 0 5px 0;
-}
-
-h4 {
-	font-size:14px;
-	padding:0;
-	margin:15px 0 5px 0;
-}
-
-code {
-	font-size:1.1em;
-	background-color:#f3f3ff;
-	color:#000;
-}
-
-em strong {
-    text-transform: uppercase;
-}
-
-table#chart {
-	border-collapse:collapse;
-}
-
-table#chart th {
-	background-color:#eee;
-	padding:2px 3px;
-	border:1px solid #fff;
-}
-
-table#chart td {
-	text-align:center;
-	padding:2px 3px;
-	border:1px solid #eee;
-}
-
-table#chart tr.enabled td {
-	/* Leave this alone */
-}
-
-table#chart tr.disabled td, 
-table#chart tr.disabled td a {
-	color:#999;
-	font-style:italic;
-}
-
-table#chart tr.disabled td a {
-	text-decoration:underline;
-}
-
-div.chunk {
-	margin:20px 0 0 0;
-	padding:0 0 10px 0;
-	border-bottom:1px solid #ccc;
-}
-
-.footnote,
-.footnote a {
-	font:10px/12px verdana, sans-serif;
-	color:#aaa;
-}
-
-.footnote em {
-	background-color:transparent;
-	font-style:italic;
-}
-</style>
-
-<script type="text/javascript">
-// Sleight - Alpha transparency PNG's in Internet Explorer 5.5/6.0
-// (c) 2001, Aaron Boodman; http://www.youngpup.net
-
-if (navigator.platform == "Win32" && navigator.appName == "Microsoft Internet Explorer" && window.attachEvent) {
-	document.writeln('<style type="text/css">img, input.image { visibility:hidden; } </style>');
-	window.attachEvent("onload", fnLoadPngs);
-}
-
-function fnLoadPngs() {
-	var rslt = navigator.appVersion.match(/MSIE (\d+\.\d+)/, '');
-	var itsAllGood = (rslt != null && Number(rslt[1]) >= 5.5);
-
-	for (var i = document.images.length - 1, img = null; (img = document.images[i]); i--) {
-		if (itsAllGood && img.src.match(/\png$/i) != null) {
-			var src = img.src;
-			var div = document.createElement("DIV");
-			div.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizing='scale')";
-			div.style.width = img.width + "px";
-			div.style.height = img.height + "px";
-			img.replaceNode(div);
-		}
-		img.style.visibility = "visible";
-	}
-}
-</script>
-
-</head>
-
-<body>
-
-<div id="site">
-	<div id="content">
-
-		<div class="chunk">
-			<h2 style="text-align:center;"><img src="<?php echo pathinfo(__FILE__, PATHINFO_BASENAME); ?>?logopng" alt="SimplePie Compatibility Test" title="SimplePie Compatibility Test" /></h2>
-			<table cellpadding="0" cellspacing="0" border="0" width="100%" id="chart">
-				<thead>
-					<tr>
-						<th>Test</th>
-						<th>Should Be</th>
-						<th>What You Have</th>
-					</tr>
-				</thead>
-				<tbody>
-					<tr class="<?php echo ($php_ok) ? 'enabled' : 'disabled'; ?>">
-						<td>PHP&sup1;</td>
-						<td>4.3.0 or higher</td>
-						<td><?php echo phpversion(); ?></td>
-					</tr>
-					<tr class="<?php echo ($xml_ok) ? 'enabled, and sane' : 'disabled, or broken'; ?>">
-						<td><a href="http://php.net/xml">XML</a></td>
-						<td>Enabled</td>
-						<td><?php echo ($xml_ok) ? 'Enabled, and sane' : 'Disabled, or broken'; ?></td>
-					</tr>
-					<tr class="<?php echo ($pcre_ok) ? 'enabled' : 'disabled'; ?>">
-						<td><a href="http://php.net/pcre">PCRE</a>&sup2;</td>
-						<td>Enabled</td>
-						<td><?php echo ($pcre_ok) ? 'Enabled' : 'Disabled'; ?></td>
-					</tr>
-					<tr class="<?php echo ($curl_ok) ? 'enabled' : 'disabled'; ?>">
-						<td><a href="http://php.net/curl">cURL</a></td>
-						<td>Enabled</td>
-						<td><?php echo (extension_loaded('curl')) ? 'Enabled' : 'Disabled'; ?></td>
-					</tr>
-					<tr class="<?php echo ($zlib_ok) ? 'enabled' : 'disabled'; ?>">
-						<td><a href="http://php.net/zlib">Zlib</a></td>
-						<td>Enabled</td>
-						<td><?php echo ($zlib_ok) ? 'Enabled' : 'Disabled'; ?></td>
-					</tr>
-					<tr class="<?php echo ($mbstring_ok) ? 'enabled' : 'disabled'; ?>">
-						<td><a href="http://php.net/mbstring">mbstring</a></td>
-						<td>Enabled</td>
-						<td><?php echo ($mbstring_ok) ? 'Enabled' : 'Disabled'; ?></td>
-					</tr>
-					<tr class="<?php echo ($iconv_ok) ? 'enabled' : 'disabled'; ?>">
-						<td><a href="http://php.net/iconv">iconv</a></td>
-						<td>Enabled</td>
-						<td><?php echo ($iconv_ok) ? 'Enabled' : 'Disabled'; ?></td>
-					</tr>
-				</tbody>
-			</table>
-		</div>
-
-		<div class="chunk">
-			<h3>What does this mean?</h3>
-			<ol>
-				<?php if ($php_ok && $xml_ok && $pcre_ok && $mbstring_ok && $iconv_ok && $curl_ok && $zlib_ok): ?>
-				<li><em>You have everything you need to run SimplePie properly!  Congratulations!</em></li>
-				<?php else: ?>
-					<?php if ($php_ok): ?>
-						<li><strong>PHP:</strong> You are running a supported version of PHP.  <em>No problems here.</em></li>
-						<?php if ($xml_ok): ?>
-							<li><strong>XML:</strong> You have XMLReader support or a version of XML support that isn't broken installed.  <em>No problems here.</em></li>
-							<?php if ($pcre_ok): ?>
-								<li><strong>PCRE:</strong> You have PCRE support installed. <em>No problems here.</em></li>
-								<?php if ($curl_ok): ?>
-									<li><strong>cURL:</strong> You have <code>cURL</code> support installed.  <em>No problems here.</em></li>
-								<?php else: ?>
-									<li><strong>cURL:</strong> The <code>cURL</code> extension is not available.  SimplePie will use <code>fsockopen()</code> instead.</li>
-								<?php endif; ?>
-	
-								<?php if ($zlib_ok): ?>
-									<li><strong>Zlib:</strong> You have <code>Zlib</code> enabled.  This allows SimplePie to support GZIP-encoded feeds.  <em>No problems here.</em></li>
-								<?php else: ?>
-									<li><strong>Zlib:</strong> The <code>Zlib</code> extension is not available.  SimplePie will ignore any GZIP-encoding, and instead handle feeds as uncompressed text.</li>
-								<?php endif; ?>
-	
-								<?php if ($mbstring_ok && $iconv_ok): ?>
-									<li><strong>mbstring and iconv:</strong> You have both <code>mbstring</code> and <code>iconv</code> installed!  This will allow SimplePie to handle the greatest number of languages.  Check the <a href="http://simplepie.org/wiki/faq/supported_character_encodings">Supported Character Encodings</a> chart to see what's supported on your webhost.</li>
-								<?php elseif ($mbstring_ok): ?>
-									<li><strong>mbstring:</strong> <code>mbstring</code> is installed, but <code>iconv</code> is not.  Check the <a href="http://simplepie.org/wiki/faq/supported_character_encodings">Supported Character Encodings</a> chart to see what's supported on your webhost.</li>
-								<?php elseif ($iconv_ok): ?>
-									<li><strong>iconv:</strong> <code>iconv</code> is installed, but <code>mbstring</code> is not.  Check the <a href="http://simplepie.org/wiki/faq/supported_character_encodings">Supported Character Encodings</a> chart to see what's supported on your webhost.</li>
-								<?php else: ?>
-									<li><strong>mbstring and iconv:</strong> <em>You do not have either of the extensions installed.</em> This will significantly impair your ability to read non-English feeds, as well as even some English ones.  Check the <a href="http://simplepie.org/wiki/faq/supported_character_encodings">Supported Character Encodings</a> chart to see what's supported on your webhost.</li>
-								<?php endif; ?>
-							<?php else: ?>
-								<li><strong>PCRE:</strong> Your PHP installation doesn't support Perl-Compatible Regular Expressions.  <em>SimplePie is a no-go at the moment.</em></li>
-							<?php endif; ?>
-						<?php else: ?>
-							<li><strong>XML:</strong> Your PHP installation doesn't support XML parsing.  <em>SimplePie is a no-go at the moment.</em></li>
-						<?php endif; ?>
-					<?php else: ?>
-						<li><strong>PHP:</strong> You are running an unsupported version of PHP.  <em>SimplePie is a no-go at the moment.</em></li>
-					<?php endif; ?>
-				<?php endif; ?>
-			</ol>
-		</div>
-
-		<div class="chunk">
-			<?php if ($php_ok && $xml_ok && $pcre_ok && $mbstring_ok && $iconv_ok) { ?>
-				<h3>Bottom Line: Yes, you can!</h3>
-				<p><em>Your webhost has its act together!</em></p>
-				<p>You can download the latest version of SimplePie from <a href="http://simplepie.org/downloads/">SimplePie.org</a> and install it by <a href="http://simplepie.org/wiki/setup/start">following the instructions</a>.  You can find example uses with <a href="http://simplepie.org/ideas/">SimplePie Ideas</a>.</p>
-				<p>Take the time to read <a href="http://simplepie.org/wiki/setup/start">Requirements and Getting Started</a> to make sure you're prepared to use SimplePie. No seriously, read them.</p>
-				<p class="footnote"><em><strong>Note</strong></em>: Passing this test does not guarantee that SimplePie will run on your webhost &mdash; it only ensures that the basic requirements have been addressed.</p>
-			<?php } else if ($php_ok && $xml_ok && $pcre_ok) { ?>
-				<h3>Bottom Line: Yes, you can!</h3>
-				<p><em>For most feeds, it'll run with no problems.</em>  There are <a href="http://simplepie.org/wiki/faq/supported_character_encodings">certain languages</a> that you might have a hard time with though.</p>
-				<p>You can download the latest version of SimplePie from <a href="http://simplepie.org/downloads/">SimplePie.org</a> and install it by <a href="http://simplepie.org/wiki/setup/start">following the instructions</a>.  You can find example uses with <a href="http://simplepie.org/ideas/">SimplePie Ideas</a>.</p>
-				<p>Take the time to read <a href="http://simplepie.org/wiki/setup/start">Requirements and Getting Started</a> to make sure you're prepared to use SimplePie. No seriously, read them.</p>
-				<p class="footnote"><em><strong>Note</strong></em>: Passing this test does not guarantee that SimplePie will run on your webhost &mdash; it only ensures that the basic requirements have been addressed.</p>
-			<?php } else { ?>
-				<h3>Bottom Line: We're sorry…</h3>
-				<p><em>Your webhost does not support the minimum requirements for SimplePie.</em>  It may be a good idea to contact your webhost, and ask them to install a more recent version of PHP as well as the <code>xmlreader</code>, <code>xml</code>, <code>mbstring</code>, <code>iconv</code>, <code>curl</code>, and <code>zlib</code> extensions.</p>
-			<?php } ?>
-		</div>
-
-		<div class="chunk">
-			<p class="footnote">&sup1; &mdash; SimplePie 2 will not support PHP 4.x. The core PHP team has discontinued PHP 4.x patches and support. <a href="http://simplepie.org/blog/2007/07/13/simplepie-is-going-php5-only/">Read the announcement.</a></p>
-			<p class="footnote">&sup2; &mdash; Some recent versions of the PCRE (PERL-Compatible Regular Expression) engine compiled into PHP have been buggy, and are the source of PHP segmentation faults (e.g. crashes) which cause random things like blank, white screens. Check the <a href="http://simplepie.org/support/">Support Forums</a> for the latest information on patches and ongoing fixes.</p>
-		</div>
-
-	</div>
-
-</div>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/library/simplepie/create.php b/library/simplepie/create.php
deleted file mode 100644
index 908ed182bd..0000000000
--- a/library/simplepie/create.php
+++ /dev/null
@@ -1,178 +0,0 @@
-<?php
-
-require_once 'simplepie.inc';
-
-function normalize_character_set($charset)
-{
-	return strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset));
-}
-
-function build_character_set_list()
-{
-	$file = new SimplePie_File('http://www.iana.org/assignments/character-sets');
-	if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
-	{
-		return false;
-	}
-	else
-	{
-		$data = explode("\n", $file->body);
-		unset($file);
-		
-		foreach ($data as $line)
-		{
-			// New character set
-			if (substr($line, 0, 5) === 'Name:')
-			{
-				// If we already have one, push it on to the array
-				if (isset($aliases))
-				{
-					for ($i = 0, $count = count($aliases); $i < $count; $i++)
-					{
-						$aliases[$i] = normalize_character_set($aliases[$i]);
-					}
-					$charsets[$preferred] = array_unique($aliases);
-					natsort($charsets[$preferred]);
-				}
-				
-				$start = 5 + strspn($line, "\x09\x0A\x0B\xC\x0D\x20", 5);
-				$chars = strcspn($line, "\x09\x0A\x0B\xC\x0D\x20", $start);
-				$aliases = array(substr($line, $start, $chars));
-				$preferred = end($aliases);
-			}
-			// Another alias
-			elseif(substr($line, 0, 6) === 'Alias:')
-			{
-				$start = 7 + strspn($line, "\x09\x0A\x0B\xC\x0D\x20", 7);
-				$chars = strcspn($line, "\x09\x0A\x0B\xC\x0D\x20", $start);
-				$aliases[] = substr($line, $start, $chars);
-				
-				if (end($aliases) === 'None')
-				{
-					array_pop($aliases);
-				}
-				elseif (substr($line, 7 + $chars + 1, 21) === '(preferred MIME name)')
-				{
-					$preferred = end($aliases);
-				}
-			}
-		}
-		
-		// Compatibility replacements
-		$compat = array(
-			'EUC-KR' => 'windows-949',
-			'GB2312' => 'GBK',
-			'GB_2312-80' => 'GBK',
-			'ISO-8859-1' => 'windows-1252',
-			'ISO-8859-9' => 'windows-1254',
-			'ISO-8859-11' => 'windows-874',
-			'KS_C_5601-1987' => 'windows-949',
-			'TIS-620' => 'windows-874',
-			//'US-ASCII' => 'windows-1252',
-			'x-x-big5' => 'Big5',
-		);
-		
-		foreach ($compat as $real => $replace)
-		{
-			if (isset($charsets[$real]) && isset($charsets[$replace]))
-			{
-				$charsets[$replace] = array_merge($charsets[$replace], $charsets[$real]);
-				unset($charsets[$real]);
-			}
-			elseif (isset($charsets[$real]))
-			{
-				$charsets[$replace] = $charsets[$real];
-				$charsets[$replace][] = normalize_character_set($replace);
-				unset($charsets[$real]);
-			}
-			else
-			{
-				$charsets[$replace][] = normalize_character_set($real);
-			}
-			$charsets[$replace] = array_unique($charsets[$replace]);
-			natsort($charsets[$replace]);
-		}
-		
-		// Sort it
-		uksort($charsets, 'strnatcasecmp');
-		
-		// Check that nothing matches more than one
-		$all = call_user_func_array('array_merge', $charsets);
-		$all_count = array_count_values($all);
-		if (max($all_count) > 1)
-		{
-			echo "Duplicated charsets:\n";
-			foreach ($all_count as $charset => $count)
-			{
-				if ($count > 1)
-				{
-					echo "$charset\n";
-				}
-			}
-		}
-		
-		// And we're done!
-		return $charsets;
-	}
-}
-
-function charset($charset)
-{
-	$normalized_charset = normalize_character_set($charset);
-	if ($charsets = build_character_set_list())
-	{
-		foreach ($charsets as $preferred => $aliases)
-		{
-			if (in_array($normalized_charset, $aliases))
-			{
-				return $preferred;
-			}
-		}
-		return $charset;
-	}
-	else
-	{
-		return false;
-	}
-}
-
-function build_function()
-{
-	if ($charsets = build_character_set_list())
-	{
-		$return = <<<EOF
-function charset(\$charset)
-{
-	// Normalization from UTS #22
-	switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\\1', \$charset)))
-	{
-
-EOF;
-		foreach ($charsets as $preferred => $aliases)
-		{
-			foreach ($aliases as $alias)
-			{
-				$return .= "\t\tcase " . var_export($alias, true) . ":\n";
-			}
-			$return .= "\t\t\treturn " . var_export($preferred, true) . ";\n\n";
-		}
-		$return .= <<<EOF
-		default:
-			return \$charset;
-	}
-}
-EOF;
-		return $return;
-	}
-	else
-	{
-		return false;
-	}
-}
-
-if (php_sapi_name() === 'cli' && realpath($_SERVER['argv'][0]) === __FILE__)
-{
-	echo build_function();
-}
-
-?>
\ No newline at end of file
diff --git a/library/simplepie/db.sql b/library/simplepie/db.sql
deleted file mode 100644
index 13f504c214..0000000000
--- a/library/simplepie/db.sql
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SQLite */
-CREATE TABLE cache_data (
-	id TEXT NOT NULL,
-	items SMALLINT NOT NULL DEFAULT 0,
-	data BLOB NOT NULL,
-	mtime INTEGER UNSIGNED NOT NULL
-);
-CREATE UNIQUE INDEX id ON cache_data(id);
-
-CREATE TABLE items (
-	feed_id TEXT NOT NULL,
-	id TEXT NOT NULL,
-	data TEXT NOT NULL,
-	posted INTEGER UNSIGNED NOT NULL
-);
-CREATE INDEX feed_id ON items(feed_id);
-
-
-/* MySQL */
-CREATE TABLE `cache_data` (
-	`id` TEXT CHARACTER SET utf8 NOT NULL,
-	`items` SMALLINT NOT NULL DEFAULT 0,
-	`data` BLOB NOT NULL,
-	`mtime` INT UNSIGNED NOT NULL,
-	UNIQUE (
-		`id`(125)
-	)
-);
-
-CREATE TABLE `items` (
-	`feed_id` TEXT CHARACTER SET utf8 NOT NULL,
-	`id` TEXT CHARACTER SET utf8 NOT NULL,
-	`data` TEXT CHARACTER SET utf8 NOT NULL,
-	`posted` INT UNSIGNED NOT NULL,
-	INDEX `feed_id` (
-		`feed_id`(125)
-	)
-);
\ No newline at end of file
diff --git a/library/simplepie/demo/cli_test.php b/library/simplepie/demo/cli_test.php
deleted file mode 100644
index ec933c5ad7..0000000000
--- a/library/simplepie/demo/cli_test.php
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/php
-<?php
-include_once('../simplepie.inc');
-
-// Parse it
-$feed = new SimplePie();
-if (isset($argv[1]) && $argv[1] !== '')
-{
-	$feed->set_feed_url($argv[1]);
-	$feed->enable_cache(false);
-	$feed->init();
-}
-
-$items = $feed->get_items();
-
-foreach ($items as $item)
-{
-	echo $item->get_title() . "\n";
-}
-
-var_dump($feed->get_item_quantity());
-
-?>
\ No newline at end of file
diff --git a/library/simplepie/demo/for_the_demo/alternate_favicon.png b/library/simplepie/demo/for_the_demo/alternate_favicon.png
deleted file mode 100644
index 063fb280549db7a68a47cce157d680ed7af1a8a2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 28621
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

diff --git a/library/simplepie/demo/for_the_demo/background_blockquote.png b/library/simplepie/demo/for_the_demo/background_blockquote.png
deleted file mode 100644
index 8267e23a23575eb148f8b8e3305732e6f09870de..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 27353
zcmb@tcUV);vp5WjB7z_tq^XF2bdX*GA|TSFcTnkFdM6?RB2Ah|3nIPuUPA8>iu4kC
z=%Iv!kdVB5zW09beeV1F=Y8()-Dk5qXV31Onc1_mGnund?=)2&+<$bRfPmnE>YLX(
z1O$YL8~FacyEo-4$uh&6ipcYos@}bu6m-w}+s!q}r#Hr)1O%j1|NIE2Rzk2hjci^@
zMqavZwqCv;JZuOwK3I9Ux!71ce0Z$v;9=wI=HcY|Sfbv3%I~Ht-9KFwJ#0RBIk>q#
z)^l*NArKN05EK^>6isV?9CXuT_LGN!p<m|Fj1YOZAX)ea;;8VbG+mEZ<exq0#gwO_
z3i!nS=p5>8<Mn8Y$&j_C7q}MLtrw{}Z^w;4<C9knmy3UDDHKl0gArE#sJ}ywkDp(l
zNP6=c>8tRFO}=(Q6k>-+r@d`@2?PI$%ayJ~c#o$K0Ukh<{BuKFQX61yGZ&hs*yKG^
ziq9(k7iogTYhr{Kne-HDl`wd^oHJ??V_6WF)wu}A<8E-c;cq$aZ9cC;Vkig*8ej;S
zLF2ggr5iT>M{0OaP(l5m^i>K-?WX;Wi_<IRtJPuL4NUYu`u#61xbsAE2nblDU7YlE
zZ=_~!>bcaP*uT?TZ8OrirHA}rsaIcLuQk+_lB$wG!_k-AtN5<rke>b?m6(>bv`S;|
zNH-9A3?jTocK0#C>C>euss~YBWP+Byz?Er{&v6!YuC^-*fl|}hE<k*th^|wB)tn%<
z)?z8680TcrCUxj1qNaZx){`SXtp}{K3#@H9rZ}AD{@aMmA%$d20Km|Ll~I%6%b8Uc
zi}7SWo4lrB)BH;H<oFYZl1xnGfXch`hmLZuVhgah>UFmTBsQ1Xyfl^P_l|`w+MTrQ
z`t#Nsr6T>Z%X8VA=x9F8pPC|Bv#foK$K`(inaK?+r`M~C_a_cCzmj8^QeB}7J|HiW
zuq8gidCiug%b%1o*Q`d0wGL7q#M4H$`lSx|8J0jLCktxt(n$GCO9~b3b}O*l&!W9c
z7s79i(~XF!$vy0z<hjI=21!LuY4hjUwrP&mnSLxNzhA4uTpPT7>l0ehpTgU4_!%`*
z(g%^DPUV!3n=L}lf61Je@AmXhkmly5k+DX0Z3_B5A_LtGD_mc?7XOrz;I`Cum`&jL
z^EUBiWDtQIjG!S!>$h1pf$}@PcP+bV+JZS&uXG!0CcHd;bK9HHrGF`q9I4m*Qe}`N
zZ;vu9>$kO`nIdMMqFdP1bC>+BCHY(I^Ij<bG1u)&uLlGDq~!+R^LNrl>P>t292zyX
zTQz#@GpxJ_1_a)$1iZtz>-(5?QqXiNn?DfKqMl#Y0scJX7LT9s>F$2(6mM^;gs|&r
zpnVq*IpMF>LOJ*QjRsjCZ!$u9SblLzJK(uev0{VREyG{s8osog!Fv+22^+l&#S+R)
zumfI=8irSNii0gF?JV+pT;jtpfvHWWQ=`8h1&zs`M|N!q{@O~gwFqPS@<`*!C%n#s
zaif+lmvD*TTQHyc{@+3(M80E*APt*|BC<y*3c14edUs<Vh1q5(){=gACtPj61Foce
zMm}+y{GD8U#M9U{T@glkJ@CWd5ov@E$Bv#pjCEsV+#`FE^~75Et9rzbq31zdv-2?&
zkqXna67Pt5-ml6KU0jhSAEs+yYZ8(d-;4b)Nm4A1uXzr6njBsL$?y7`f$j|I?s5+6
z&eFZVWB$walGlju#WwLJRu!F`^?Tj6l(9L?TSGK@sXSl!S=7Uassc_(=0>yj1SYlI
zF4$y*7=Mg;gTmYZSxdyoj|^V!vUj!J_uHQ>Y=@Qc%HxTovo?%{KC4F)=EV}N+^+$?
z=ouUn*3*mbYf<{j&{f=@b&GrE{^z&*2KGfZ54;HK*@Y+K(;N##Q%mheviK{MAt7rF
z?YAsHaVQn?7yWwZZ9P^{?LfvBym|R9BtEgIoM;bl|1?0$lZF0eKgo1Ks961w+tY2k
z0rV}4^y9ab)c3&0bcWnXu(vF6X+mP2nDH~^h5N#V%QG}8HCkK1dOy)O@>3$7ewqR&
znG9N6M8aEQ<j?w^jSNt(*M`{>4aJ6YbP>P)*~ifpsqo<&e1O_kX^kVh`jec(z8M3Q
zBwoEr=$5)MF8`Jcf!W2-*ALI7Vx32ai3UA%@=_ALcFo$GVk6h9^F?+UBG6US&zp;d
z^ki0&G%c346y%Zw_(a5`wZ`nfzZ15~8u)Q>H(tkHCy|;@F*Qfu%6^8yMAUXThTybk
zkXoHFcy#SIK^&^bzE3;E^2Z|wL7EIQrTddlxk?(9Cat-IX_LCYIeqz-3kuEcn<jW@
zP)(zn#6Cn@*)LjYTM)`vF?#2Hz}cv7iw?Pi|Ga*Pz{kGkI$=u$uc4Z-t=He&{Bt%*
zhMIMPL5085g3zQ25TT-v1N$xhIx-<cPE|6?&xyxeD%k1Q&4amBN(8fIs-WZ;85$EE
zgpnF=SL2r$^?=J?u`7h(>u`Sw9H={+bT2>}O`@YEYI{7|`fSu(O5_PANZf6$jHVU)
z?#{x6#XaqoKT)+bhUryPBG0+c-xRzaY!{Y|u7S#|DhC$$wF+^6hFvo-hL{}(c#L~x
zw`2ytzBBrgNNt(%{5J8y>l&qUB`0bLZsR(s^<;BDm2pd=q$d(<ogav(sdRR~VrD#u
zg8h;WxFn1M!u;=@5w~v5zCnK?CA%V~R!jHd>pk%&Qj95eXAjdjkRi968AMXXc|A(J
ztrLS1p)#uIk)M$)s^A}e)i0B1D+0O`!l0MhwYb(K#!$r%t=RT>zY@VPvlgjv@}&9H
z{$a?y?i1YSz~ipRzwRv#sm7|)#CPvOAFYY^H?Pq@7k+Y;wy>A{ZEA}$f2c~_EJ8Nr
zZpzn}irU{_O1cyMq6zM#0SL5FDEd`$o%O~_rTTAVKfYk&RdpEOYEaY36ygmP+8F&F
z6usuixHdcbaqVuWg9U>s)#s~^1(&LF(>u`y=*vcnM4)Fgw;bUa^9PRb9*4M(2&ds)
z@z1(jB+->&CP7bVhA*dRqGyQ7-UW6RrvX)di)y_cikF<I99-p;X;)y930Kwb2)^IF
zXvyHcV`|s`QmO0xV{4+P$)@>Yd8T$fZA(Elnh8NCA3jlOJEnZ#J0uv3ckhTQT>ViH
zZy!+i`fHefA>~$F8J1v#onKK5p662Qz~mI&W%SJYLZUIi-Sr}q`SA`(zpJ!tVrdb-
z;*Y+vNroqxRneto3ddHR*AUL_ur;hZ5T(-B6V4L!OFkmUHjS*ugjunW;HzjcYl-kZ
z<Ex_4kSKZ5P3bM~iU_?&dcp_g?&o6^i@_W%cQ}{Qn1pj_f12oX8#snQ6@xN*9j*B_
z+rmL+Z`z)8QCS>@b;$|BZ&SbB2|iH-bWV`p%2nu0aDMxPV*0&Hbu_s}#O`2BI4BfJ
z8zn2kHu0FuhD5{Pt5-<W`d7<?W@)#xX1gTLhzwD&_@{*|TMH(hoUB_bUzfF|zMUJL
zLkV&f6LcB^Ol%CRN&RT(D3xpr?ihGH4oEEFWQCt?n)}FnO>Fbdl0J}{o*>ZCnYc|S
zK`Vls`)b$V8x^=~<`m!TCE|L-zGoo)WIQ<_wXRB*Z-mvdZ@c8psr7J3jqc}tcFBFG
z^g|*AEQGl?m8Pn-F8V4FWZv`lx!l`2MV_`MEkGclPI|4?!M6Y0*O<N`8u9T$8d45j
zZrdDxPT!5YP&f(4htX-cOno<3il+ka;<K^1*H^KAzb)TAMm5Qk<?DVNs{z@0T7$@n
zDdQzKA3bO=edN;qMAe+7>UZ%yO$wMq==WpYWwf2xN1ga=H-G~{TEj0Qv*Lld=fd#3
za@v|B!Mq?XX-mNo8P&r=st=_p8VQbQdcN+VTy36?DW=yu(V$kDdpp9!L(QX4cR`T~
z6Ou05Jn6J40`|)m7xqc-p7HI!DHIPq+g4?c%1O{e-;!hg+B|0cI&JQ=*4ible}<CQ
z7rvg)<yiDn!k(Rv0<4FU4|l}XgrV}pioR_DEb6@RYO-~c&b^-JpubLosnTD~nJO}G
z*$}o|KE9CQf%FX9FUA)0kX5->OB5TZo3cd~$7sE545H{f4|ZFSYHfpA)?mF9Ti}e;
zx|F>aPf0dkmfH{(W@V-bygE@O>H>3>HYgV7b~8*_)Zfw){3?+i?a7pH$r(Bn&8+#Y
z=9Q~?&B!<8vx(3(#fPtv{$BBl)(0vHpR(zsu&$M!A_vOZofmKD#5lGJ5>%3961#-j
z1=nt?!d})#jO2|F><Q~13Wx6>Q`)a6L~1gU8LbfVj8~nsP8u_}KEZVgjL&~H{XUyn
zFq_=Uk+niagIQ;hjl{V3(7%g8Tf<(Q$%T(hAj~_Sepf$u0S;TdTUok$3?^EOUn)CS
zyljIGq*i$?s2S*8!Bk4>et*AKTsQ*vOI;wZ?KxWSm7G|Lx3F|=VrmMKm)Z+Xqdk~D
zAreby%DFkk!-mF+whUgoYBeq2{TxG@+t)TEtq`E~ig9RMa?D**GD=GQk0!_DQ>tJF
zlcyDTejmg{Oj=lHJuZ?SE8^jlOi~>$duG^Amqt{<)$T*N#xef~n>o!4TmEh?T2AFa
znJ{j}6S;aU3N1T4r2&4zzTEbcbT?KvGvFu}p4!)axTg$KLS0%*Nra?(v}M-qtD9WB
zHL=N?;dtHugf&!eXFy9gE;Y#@Otn;7we(vZtEa=!DNG0dI3)TmXMA&zwOuB^Ol~G`
zhWgL3w?CDv{j*1El%k7M*QrYB<!F5<O|tyzGBeGdb2cXGQcAjnCrQ`QBClB7U&&Qc
za&Dccdk8a$q{Z^2rJOoe+JkqVt<U`D6KB7wI_apEj#{?@EDcDku#q3U7|Q>H<#^Tc
z=#_b&B4uiuJg+x2aEBRAqtyq0mCFF;?<|j>i-Pw0YI2nx9{C{V#o3W#F~Lk9D?7ki
zB!|L|S2BMJ=043jnamcf5Oh_4Yk8#2g7&Vs&#v#w3@~sAFA+ojma<r&G5vnkHcZN=
zu&$<X{Z%nmls$lHh}H#3uTU`rAF==4rA%BXzEdACT|D5V;bb9Q66NA#tZ~4oA$l73
zdNSC*5zHMv|DB8IF5Mu9r>LNf?{ry)sD>Z``^(RhP3tD7!^%dco)=LDN#xcWu`0(B
z+{0tb-37g;G0|4>NaVyKkBi<y;ZebaV?ykH$$CGWuVibn$aqfK;cbP6I;2h~xot<?
zOkYj+%z7Z*Po>!zp$WwmBtN~k*}dk%I>C2;^9uvdLB-iucl6Z)jXZ^<d;*F=Vda(@
zVOG(MqeIE;JEoF1m!A5iGp{9{mP9-_ut+bdCM_iD^}ZA+%wOJHg4R7H+vV=JHcI-l
zw1=7|f|tV@5@fEO@23|E*}nqTaCK_3nLXRr*T(`b8f+*ROZaQ{B!&x8U$5SCPyYKQ
zLzx=!bnJ@;3vi0p&pI|H;pfM$dXvOQJ9ILjwRjpL>sVzA!{9<UpswQymtGj)@+WB!
z3Le?l!Bu=2P$%5Aea<wS6%!R@FZ_^1B~3<Dgq`9+M^zy7<;=!y$!z;DT#83GRO`gG
z8ZebnVkJ6lR`&8|hY}!z+z}kUyj5QCMZq9O^7xIbbHWJu7jpkUFJz5EfjS(fGfF=b
zuqy{XuC{?IgDpE>-^=A?jY=fBcEOnfdK{|w#YotQ-IIBMm2S{csUunJ#g`aAt<&8c
z7wc2SUxrn%g95BTve%-(dKp}@Crt5sT`-MP;A??(Nj<5yF+7(@zGl6sQW%^5WQyfl
zEvd>0H7nD!<sYZcYN@|P2&>67@5^$92O;NHhAZju+Kex<CvTtf;3EI@j|VYGp3}<S
z_snmD!9pT^X{0gkTZiw@r|x7pguCp2=cro<vj{!h?IT1K@g~=GXM1SH@3|edv$v4p
zS|(H+eHj}BKk_x~nOmoJGCRPc4S#_L%6cqaHzvpv2nxXoFJG7Kly^(VWV+pBhkj|5
zEVN#<4y6GpkIVegNHfGj+|{{*$V?nw@gVCo)C*yVF4Gl59McJ^X{Wam^A%K%Pa444
z-`RYP;j^z)4k7EKu9A6NF@D??jr}Go^M`fZ|COQ-K4JEiS_UYDX`0KLkKLF5ed7RL
zp1_{Os6$b#(f&|1wn{Y>Pox@?3>4ylxxl+tK8_y?cirPlT%=uy*GTtGDPe?!MLt2N
z(HB4BX;{8*`rU^Qga&`^g@3}ECw70GQlmF}#Q7=KbHW_?@i)cqr0l^Bfi<J#1<iG=
z6_WWWcsTdo=J9KZRIU~xX$pIaxz_JlJU$kZ(x$Z1hKFX=p5#8O_ZQIV6_H|wLSB6n
zrM9~!eG{~bhGgcSb6j>a07n-8H1pWmCphs$R4}xBv}aVr|FX6Zk>g|KIgE!GWSYAp
zOC(JzC0aKQzt?(xLMo0gxD6s#J4IJRFZ7tr-4P{{i)9im8@u0gNv-9cGMoP=!rYI$
z-*b2($Qe!k3_-WXrOQ9Uq&vrF#&0MD`}lyIV8Zk0rFnnD>T~n=Fh`hq-#D!_>;ufr
z?FO9i4b3Ud^8FW`Uvt1&|A5dt5fwhG`eZlwS^ouP28&CyF8Uj~`}8gNOJGcwZ$O0k
z+U`HNCTUgZhk}BnrQt6kI!MXPkJ?Iac-xg!^j+iqi~lCmL$50w0RnrTx*V2W)YRX`
z&g!XOGAaUN^Q*iY=%S@|?}?m5R?kKwja48v0uGtA(cGUD5z8;LO6_8v4JF)t{JvZX
zbt`x=YVWP~3MrD-z4B~q&qTvW(HvAEdjH^&GW!*MnTu9agVJ>zL#*7|RfNC!36tfu
zoR#9lFNBfasB}nkLXkwAhRUBA{!IZPsu`lCil>uaA*-NsZb2`iBU3>HL4_d4Yp`ns
zoz>Vsg1niWVOrkQ95x7AkI~KpG5w3i*WT>VZ7fS=$7QLy5GR((S0zCl*xNBU>3u1*
zj{RKz;PNYQnhGv3k#YC5Rpnf6>u|}2lsAgbVBw2((BtW!!Y!y|?6Bm5cA5CLAy(CX
z?IYhKZjB##q~J+ktwC5u?{p~L2Uh~`!P_jPTXA;cYts9x4CAP|&s%@0Rp4vj_ho!d
z5h}i&GSj9_vv>SC5jMbXROtzB;yGTRZA$hLh8!1n5uoKxBzr~P&pP*qcv!+NVx9G`
zEr#<Wn#$x%u)tGcC1637bI0LxNM}=2)H};}VZ*h$prXp>gI4aZpI6wyVr`~^P90_P
zo9~h)9cY-{ZVXi$c=*9=+Rx|dpx_FI@m=e^T-~_(GYV~seDpBEir{CUavtC4oTx%&
z-7kv|*9-yLQPUIBV%%}8)NWCp$uqx=$)cL>#y;bN>cF!J(D6APoSVLeyRurP95psi
z%+XI;2I{`@$0$_L?S}PlV@Q==S*;PccP!qMrQg5R|HkUll0(BJlD}6afW8X)Mbf&{
zH8sDS(s=P}K>Ryfp`yFH##AJ`Oevq8+fEtI6U(-~>{z-<Qh>wZ@MP_h`o5($m>84W
zh4_@tBv0&6Nu`Iyp8FOSYq;<wpm*&ymJT!L5f_q}&NB4qx=kN9S!l`af><!5RAD;;
z$X(fS=K>3ffL1atnwb%w=XHF5TF<z6TQ+pLsr)ODToKA=QXiF7;s)P*05Tbd_&$w0
zmyT&nT7g=TJX$aeeA@T%G=;VQ$HU5;6-pmh>NxS2-P^rylLQTfkIl-SF}a!9_F8<s
z=CpZBIi3%O63e47JsAtem9fC5r=mPqw9rb;yf$`?^Qt#yLKw3QGM&}I1k>#9=>)DM
z`vAUNISor6zivM(-=yG+0gOu11M^~=zblk5<o#1@9rrzkq})D}z`t`gVQhI`&~xxU
z;)A5nkVK3sLYh8lixFs60B?@8$aGgI)j*~dZi@_mriYNZC`NlqiH}N=20XRoSWZUD
zX0nBvJYP5$g;fpYxjnZjG9NaRuA9r@-m20DX3dA(Gchg5N}*OTgy&cAjCc&86oB~O
zq96Y5K%V42LlHSE&9-aP_ZMf@mn>JSTezn|!*HhyXR5D<&A;0$wD2xvX+I}N*lT^i
zpD4d9v~zAB>)1h8qQm^{Y~Gofi|tg3mp=+80*WRFok7=6_xKT5;tG+JA73?vCx$$j
zKYG)@O){X&rEFH>kwqgPmMc?5tANRigV-v9MbbvWsnxe0?8|%)8vP_jGm3>zIorz(
zYrMy*FGRLBKZi=@i#BJi#c<ek&wP6BxGZ@{A1@a`0W5qY8sPJ=(qbZ}Kj-53;FIiy
z3d3Y&Z|@$UKK4y85A!y;>dC7ba7|I{p6`6W_2vrEvDWUsLQG(wS}j4>UG(=y?+w^3
z;ivk5B<pqUyn@LNx@ctMT7^NTlh`g9CuK^x@~s7S%LLw!wJ{V42P#Km&GGr%ucLrk
zE*TwQrRDO(zh4Pqq?r!9VV;w84;DxIoV5#aOnD?toSjcK<fG5u(D&11{j$ztHO_5)
zt}*xsy)U{x@T2(j%3b53T^y9~mAm;Rcl`x8$1C}K{%}irtNl)TRe78CiH0uQ&);`6
zaAZuv@_eJLyS;;#K}+8*2^e#gJ)0@rLse>}vvxi)1Xd`LPN}p9Jn*{<t8$`G!Ff82
zv?YQezGdbUptJb(+W6DlzWn1v-#$s!<Cj(<a!9jR9{q;UA~w2#7IHRTm0;-*gn|1H
zWsHLCuuDz5xJFHPz*F-3NR-QcJVM(|lS*q{4ls4jS!T<*oNx5=&Zc{@f8^$rl9i<_
zJ??dkI5?~^ITD;#h))&D9oo0-Z~EEU1hA_E4+r?D4x*T+-wN4!-NryUDjP*Axy#+C
zr<hZa`*B>5okUH>EpKzV^FAn@Yy!<8PRUaGNqnr(Lck%w<*z$_cf#0hU8>6%op+H`
zw=F8rC%bwuUW@--w|6!7DKd4vV`R5l*lcrB{rhRl$Yz<X^-Pwm$nP&@;+RqSpuAGM
zpL{h_5UOUYpI}v~__V!(DysDe-?Y^lRZn{M$e`@$5YLE_J7^iied)&Jt6v}YrTUCC
z5(8p)bjE)DRe8DO+MgGP5A-??*je%K$BXWF$JZ5{q{XMmGMzEXWtcr`I=2>xk>6;J
zdh#Kfofp95_HNwfmBIMav%A~&e<=N9h4FW{Kb(kT;y6s5Otpv-Ws%+|9+bvP*@0bY
z?12Vex*m=dV{x_p!E@GiO4^5aOnp~>KS+xzEHFqh*NpRJ5k^PN!U}?(+w}|<V5#Nu
zk0+#7&0bLKIF<4IRAqUlT_|Inb(V11s@yU4XV;!ZST)W^R>TZx8+|GAt!t^AoNMtK
zkpdoiit}1Mg9aL_)fr>?Nj2=Ncg^X3wewsZ<~0E;0y6F_(HganZ5-S<`ic`BV{*Be
z;9<{Z4?6Ny`5^UcD>{djz}*hH=lnQ>oEZ`Kv!h$I^oC~G3wL)Milc0Eg<pst8Snhq
z3JjKRORHaO-y1!@@pgR|8cD9tTd#lAvP}exEujN7B%Gkp%#s?+j5kphkzMck^l?PQ
zrZ1{R7wgK_<$EcXIsOtXy*r^AMp!ESzK@X(cT(mpLdstcNn&IBKp^01TY2?KQ}Ker
zPqGdw4;1{q{$v?-QYDf#(_Xzd>DY5p#^i<g_UpFs9(^J!PBxLHYRA8j?qE96cfnb#
zpJ;Q{7;if(`$xMj@HX$2?A0uk<8$DE#5Xy81<vayc=959oGW<XK2s#Pb*aFumF0!=
zuI(*5pQ<i7pOP!^1zs{MjXzlo6VUx#t^o>X{dk)30A@s<9C&!}uoW}rO4-{k_aQJw
zywMGHVg!-v`_uCsq)}tPq%!YZ>9YAg&T{Fp+-|xtY@O1_Ly+0xZe>u`kCJOu4j1hU
zNQ+mror)K}htQjtuUg{ZPzSamvMYZYA3vJGh)o}Nl%r+kd1+AeiqM800{`PzMDS=;
z+SN*O`Dk+cs&aS3FZZ3l7ukcjIB73YFzV4==u+^5bo@uQfdHxZ5+}v)Df&;0KUC5x
zr2HPv6^knId?Q~MXipb7uZ6i|0KbTHwY^?f@cUg;W@=*KG{GtIsKz~$%$+&RO2R?7
zMz7~3c6}&K9Mf0U6FGO1bC<KRl`E@bjOWVdT{S)P0%@FA82ifF8`9%H&|86WbwdwL
zeJHXuk5CG=>P4C|jc<KL445K-&c1DFcN87kLp4p@-q4%2x^)g>->Atb+LzWgm>d@@
zww3=xwG0(F?%3qGFm=h(ZohwcpN@uv=IS<+)S2b+6BDpw%eJqk>e9|hCbKSE!Yt)8
zx`w&hMJGwAiDxV{_7w%<0xtvX0TM)dZn=3XJtFUg_4}Myiyy6aC6wsq6qijDX<89`
zr+9zLb85S7J`ez$h{z$65(CW~khe1~XhSo)B*PRhUAsbONrH+t%Y7qSe=`Phn#)n)
zx1apNs`W?67eCE#%+zRn?3E_ZRV!kr-(U2|N>4OHo0|R%MVytfAZH>cAyXH~^-wkU
z?zWSGFsOVIU_TkkxD^t~-vIURy2pr*bR*uqBQ0?HiqnU*&*vkYN*o6`B|qp>OMbX|
z6MgNt3C-SwQOz}PoKwMvhhxwaYJ#ve%Hf`f@<&CKZK2g9h8pR=#&E5CkBMQzNoiSQ
zgD*sl{sz6yHd%WlyKmbPrEc}`c#kVt8F0U7oGCUg<G`L`YN`Qo>kB#At0_kHQje<B
z`nxKh65Xts?v~lHA*}@(Y~+S)?@P{8LClj3#|IT2(bSm5BF)q@Y_ClH9FCkJxw+KW
zVS1iyLdZ8H80{$M-ZyMt<_nb~CnxY;Y=_8F^35Myx={)yCwB@9ER7!@5gFYC@#}9m
z(YqSI2{Ho>TmBbu<^N;IO>j9YHepGEOj-BMBh@F|&tmg_&?GABym9@J;d_2e`ew+u
zl4Z$H1T?cBnRk!s55bQsv?oKvhyTicsvST)ZV5gR&xU7d<<yT0OkH0<pRD(|fh#S+
zxDwQ2huyWIWC>XhCbSK*fjs$%Yi@0bn{nd=R;U<02$T!K&d<)g#U10FfmevVIj9@7
z;~IOmJp#P?gQTyoJmY>LFuu(IOVGSFt5}3oFS?<Ve6ma(Oe|-rKS17&XW;~-&_Em(
zJtuadh39KdCi@{N{1E`t!wu4;&EcHs5l-VAfJW-YTiZ;?!!1kUv&+ieEr`(8D_}iY
zf@eJ~%6Mx)bWN^9DngE6*h*IDaA62vhSNg(!pV01w=96Ae2?cA8+flrjfS8B1iP3N
zkay37rv{pRE>Yk7K<<qt>Q|@#rE%hbPs@{~sEe3wOP5{;GQ5uW2F|mN&3w!#(}k_j
z(hkFIY`n@%apkgOKIhMyT2tn-_&6X!XlOtEKV|8s#4rF&QmL9N#Gktfz>UvVu2{|X
zom#{$D*V2V>>fE1Lw4-mWS#s(cC`LPoo8Vo^QZAa5&j^QcSkROdkPjGfjg%&!y#%v
zKza(|G@f7k?k)AuZ#nI;XF+~kJp+uJqi<`#-11_~;;#ogc$Wl@po{sbXN_zd+Dr1o
z&=4^;PXKpt)HrYRV<zX0Ls%w)bl%SBG5ev<9hf$(jv@(Z*T}L+hI$1`qdPl3Tu8GR
zhI%84HbX1$x4rG#*E(DPalwJ+F%$eDgTWI%mMHvN=>tEQ+o;`J<N?CiJaM)504U$E
zcbosPlsj$R%^j%t6AMlP1ViQI2QWt2o#W77XPkUkg01NxJXgD60sw-%%BZPsi$?S<
z(ZjA*_wFL1mPlIqS{QtA{mEd+!IoC$a2i4fmpO;-!TB7TssT(Dg7X1<*S^T3?fSni
zlQRj|!7?g?R@-V{Q@}#O-`Wbjw@>|c)B{!vSXuRPJ%VKa<abu4hZ$HIIk26XEb=p>
z6_~9d__S7|Bbv0G7TAOBv9q(A-p8)ZlI)TXe1$D{BKTfe9Gp8@+5tw-epf03GIMK7
zALCP2=6nQ$g688UnC5}91BGwE@A{9I>|maUjhg}k_H6SBr>YMIysno+=;s0x&R|!r
z7KOo~4RDj4ONti%*Pw&cbI4)ix#;e<Jv_{42$+vI^f^J~7izIEaUVU!R9gv-GmrQf
zuO-d*k&@wICTH-VkhNw@4gts=-f;x*liBByp=ST_s+&6k6GMB_0)7$nv+LuY7g)=^
zyN!|nJWJ`j(dA0fl~%JO)AmjOpw)$23_Y-m-dKsOzmS#7Y&(K240vR?T0L+J@GrRt
zlED}(*PKK;I$;rVb%~pox3Za*miy^11GXNO4qe`|49mg}&|hNBba9)cK{6HG_>V!M
z@qNQE@s7@aztpb$^(kHl5zHTeQ~>8*l!fAE3Y5~vsl05yoxNi1Mi@4jAIIGIIuRKW
zi#g&YriSKjr;{>kXS5Zt>v^N28c#;%wj1!N&DoU<|K>30eMZ;51(!&`=otjL>wQ1F
ztH61QN38V<>Qi@|A(Iv{_pqlj@<E4_xH(?HdD@D}^!>HgA`(5}8r(hyJ4^ps3MWla
z8HOIjRo_jY>kaVwLD^*C1Kkql1_GoFUHUyPM6<9gZd+DJw%Tl*>W!&<)$uDnLF*V5
z;D?F{Y<@mJ@B|ZX(;UE$E5^27XJM!5|MoqdteiZ`10o(YuLxmjX3w{}PF3vY@JE3>
zQ}MSO6M=KA&KO@A!fV-Jm6i6xMdkjY9~M{KY!_Lf4Tk}$ET6Viz$sYL%1yOHg0k7n
z@xZabg(0ZTAe<DFu95;w5E9-SSSqiCxK|dYIe5F+(x)cLf%(BRxRv0tim`*U%!&}u
zhr@r*SXH{IcO5u`=S2Kc*T=oA2Y$FSTaNS}4~N}nX$P!+NdU$NGc@FEXFf7Q!+ekW
z8WI+LMgh?6DroTu>h%deG#+iTlyt)9F7Oiotv!_m@5@k*jD|GCWJI!GLl<_+@e4bx
zat+f9%1-#0rKj$=%YZ6Ek8-f~t{aJDf3HUY@8!4S@<P`!V^eA7qe8bGDMD_bJVg`V
z`?*5CdGTm0SKv5PHMBBAcj~Bc<*HS_vb%m8dXcTR1(#&oJ;u)d1`jnQ0p%#9vR%7G
z_Gn@EElu&3FMtOwUR72uhdqjNTkd&yU0hwPdeY^?fqODF02q~w>!0|^O4ld&ZaG;L
zY(?g*O>6)tjout6MR;OSySU~5+O7iE{6=EZ%=&<<-&ZjEpIH204FJKp=r($GyeJ5|
zb{ViUFd3f~W(77csIAHIBe%HPcaA)3`<+5DF~CJVXN#`JONFpy7mQ3V<XR9q|8}70
zbA^dMlB}#PrUw}gKtdYLq-mA_J~-F7)T34;EK$s6)FU4{c?~|-|EL?{gD%A7S~R2d
z$+X0^xb}jidC<C$JrxA@We{NA_K2+xKY?m^0T}RzOGO!mK!hP~eVVwR3)#ar+CUd4
ziJuFxj{8sw`vp5Yo{d}{g1XSWi55d1x^x=hP4O#lapBiLLdHG$H>nnH`)5w#f4GFb
zTxif*K7!K*y<)|eTVp|Is7nFZ<pS|9T-QfY+|m$u&>y#Q3D^IxCI6o~@jo=9U>kq$
zJG#^m3L-Y#i`j7@c@?vbZ1C2y+VIKhL#T(E5&l=br!a7%nhTnL25X6XdvMrD*CLS|
z7sDyHk!U2p@w1J5T)PaTef{WT?%JX|A};I9*Ds3n@FR*l34CzeWI3!BloFrdGfw|_
zby)}&H>1%e_R#5`O|}i6@IVIqN)(+fnR?CwP_u|rYRL<Ul01V{Ys0H6j4S4pn<ai8
z04XUn0ox(cQnGJlQsGNbTn^u%7r|*uZ=%1Z!Yb3io?R<W5f?{dwvN%f-Y^<g+fVi6
z=G?PT!`qpKY`}zrGsKR9|JH&V*WujFtjn(ETCEt5o3GlKMp3nnks%RJ8;=9oKJ7Gb
zpoJxUKZ_+Z&j?KLGiL|z`5Z}Mc&-QVx#u++fvbk8tk?0Fx5mwtCaCh^{rW%eIT~Xg
z98KjpOU8${QNdD<Kn-ckGnEi_Er@;q&u*7K9w2>uO^x=9gDqR9hp_sbu4y)AM83{~
ziND}ChLtk$_()Cr+ejlWB}Re^LiX@0LE()xJUt1k;hH!}VD8#VXK+g3t9}r>*WJp!
zUvqxPKQ?E|J>!jrz)qDhx@BwzM;Taw8Ca|LTUob#GL>uaiA?lNt2!q>x8_{E>`aPc
z>$Q1}*s^1pZC2Wuo%*i>qJS)cN}l<4)4;eiC`*gS$%-OEqr!O3y&z<L*R+*6Fy249
zEw|!q%>NOI)t$ir1#saiq7{*_Dm{Jd3;$YL{dqt#wTwDo$TPqYoQ!!>k$HZ2ZV>sw
zPXtf!`^(kiH84jm0Rj2ke;crgq5p?9`oC!S4+EB&n=G8=8@2mm^4=(khr}DNnFlTQ
z_T}bU?NsF<5S&q^qoZA`!$Ycj6Jem#)UNk}3}ko1{#~sBuvZrc+b~ErFla*xRRY`a
z%r7IbxkPp0wfE59aUwx@-1YW!q1L}{3kRXkwxJOIj$jN@8eS!CLxjMnDF4OOfl@$P
z7vNiBleh|`<%RZ@Pf9`3+z}L=Wv+Ktwnb$AsNEueq{8l~El}>0Bdj#w;E-+G3F_Tk
z=N8DCPT_y21Xt;Aa}kHh1^{uWz+Jwn>&w$kRJ&h9OOXKSYpHhDJ(1Tq(DSozZO!yH
zr511K=PvyBe><=XXsNIu0<f`=68r%4ADcVm_`VdzQ^RKRj9nucB4V7)E{hVzw32Cq
zmhNQ?Kqt})qTn&6W}dQ2kFw4s>VlQz@>J*ti}&=7FMpFR)(o@E>9LjA@nxR|&*82{
zY0I!c1KU~r9x$sdbQHJmR-|j-d&nGM5Io7h5hgGpR}>N|W8mS_A}=@m1c0K|&$>qc
zfQ&#H@o*vfras)R%oY2^@m4-A<vN&UqqAXN7N>0b_=d%hh%$usV)U!?9L+TTlSY1?
zql9J)8=&=HSUXnTjmOlij}KYM;?xS?dSHz-1V+NguDF6%uH*N`j@?(TpLMX;0s<z)
ze(t@RE*^8BAA}<Z0B7phZN@S2iYJ>Qhgz1}!4uhp-WTwFH%2IPI&0dV>6I)fpTf&2
ze=r(zsnLl~=!ZYy3>LV3(I08uGT|YN9<m%zyo$ubYl^T^sl|xB7M6d%CQ=fp)D_^^
znOm1^(^nn|zVnyCeM_KjtL@%=BZ#$oXy8YE-2MV>_N@D_`0nEIiruCS7x<IX{)SS!
z7vm*oZ2D#ajaXB3or=QttSq%fA&-amDK@bFK;2+_28$zs>E{Eu@dk3`Q%UC$<J?!Q
zcVK=$!h<qz{&Ojt3hk$DwPSSvA~rM4`urW1Ev$C*ucpu3)~8>{Qs$C&)^?viIUmOL
z9_i7g)J_}c->wIE*q+(p@WZU>)EL9eRL|Mrb_3=GSM=YD7ug02Y{y1u_H7zj{HXHa
z@-?vJHl#EWn95_C^Qd%984=Rwf9Fl9nR;r-zX%@Jnu^Sgv8O<Yf>!Fmaf~3O9&sTO
zOuO&4_9)r6GDz2!z5=t{HJzOd<jJ1h<F0KSmu94|I~-Le+@`Cola}&(fH{~S8bEDu
z3w+bk9Vhj#IncjK`iFYq)p48K!`ucoBAmVz$*=@F6}z-JS@>IAg~flZ&HKF_-_V&~
zydOLL(&sHvqxM{4!NFMP6GT6|vKsGH@S^U*J{tK3k^%2*u$6&*XP>WJU8G?cMJlxC
zl0z>w%TBayeCF6l;?0SRD*GE-kd<~;Zz``wKrqH*hxRPg_rT*+#Hd1n2xt$X3OtvH
z7_hHB^F1539-Z=@^BoyPG==FitD?3HVeZLcClckyGjlN2Tsh(_p48k^`R&7Gice_>
zX6?T0_47d$E1XGc2{!A@tiNP*|0=Gnmr1{$y6g~|)ktJMI)xUvlsdxi4nst&VbVjT
zQg*K-2X(Sy2NCcf6~mB})Z;l{#!}(Z1L-r{02zgW_yp*8yTe1vJs`}P5`9%TLhnCu
z9S51hf%-OT&txmJYQO5I&0Mhfi^zf=GvQNA5n`4{nC3;ih`Ii?<;d|NoEcGqcUm>a
zSMC7K@pCo*fqT^v|2d9NE@C~~D`@YMC)Gg|SGw$q{|s6$9nZFFF&Q%slDQDl^zSPR
zQWD2GUHu0qs4Bok#VkHRz$s&SPHsyk9fFsQ9Zv|>%pTirWe6P)M}r6%v2xqq+lKz-
z)@8$G6_r!g0nGniJTG>a%>afHohrGBBXewQgpiF}#;q9E(HW^P*He(!w05OPs}4Jv
zXwp%nFi%a>=i`N$Ydq(HVLffNSUbqwbv`=~MC`Ha4SVX_Br~Pwgc#>fV?~(#_Q*@=
zaNTCoTEoC+<n#~Ye^G~6MY8Jwa!+|G4nY1$cwn10x|=ti*CNYZnMJ^;591@z!arMV
zN4-8L5_~k+v~f%89U6ETPZr|Jv1zYQysGk&ybyNDWr+#*bPX~L*0X!=XJK`KNa9sK
zx(;s`K+{(BOqMs1pOqr&c{ab3%5)9m*?EEmHuZfaUXAP6TSA86Ta!VpA|g*HTz-0(
ziR(+oxa>o@0{bSjK4qnK_}DCO-}0T<GsTo$`Bff}s}#ZON3XzfP;)%A8ek`V!3%SR
zPPN}&bn}&HF|VkdnoGe|LZBakDE#2@Cg5s7%V4if7TsjBV0k{?k7vQ;vV(nWuz>Yl
zpXPB*OT&JAR&5+@$pzSB)mZ)W!J?aV+(UF#_P9{3U5(@?1B(=u`VhG^Q_GwFO`2Mb
zx+oULY+8|j?}cr^PT1}uT)Qc;vBPwe72Yv7-$~+Q1Jp93ak7vgm`#o^y6q!Fcwq7|
zprx{AiP(%VZk^_l*5Rl8xXL>p={j7Wh0vV@mvxX2xa|g{h%lT^{(9h|wn@5My6L0e
zKaMlEXmzO5Y@t})ZZc$1K(?~iq5R?wl1uk)CG0pthrN0)4w*^aNn>lJh;zXZCE1Aw
z0UWd8P<J%9qSfh)F=4$@-;JZ?o>o^e?60G8&6mUDO~yr`W=4UrFMBsl$(g_W!eTzB
z25eDzSb6HcDC<Hc>mQ_ces<~8S89WeS~9!-<uUj@>m^}*_5hn~T*hgj;eONAiqI4W
zLzE>gyVAIQ=EuBvK>Z0L?ItgGm61I7Ywxa}+26Qp9#+Nbq`R^&;AumpLBGH%CvRD_
zniPk(ZyTDUf71HJ3Gvsa!RvohNLngoPgECgJZQf*xON}F5ncd?H@SVLxL`$_zlRfo
zA%|d7m2IL^G>dOhX7=$w%Pp2A#AYDhMwlC-oq1W8#d<Eqas&h)p9>qtT?%jiWs!E!
zd!Ft40y^${71@}UBz5=i-Il_E0lT^Kh9q5_R?a4|=jh?8WBkf~3!K9w)-=R&q|$nC
zwxTibw1y`ubM_R`JnCz{fEWMINxp3TeZXK2S$1MwI8u%A{?Wl>Q>boUN(CRE{Q@U+
zQ?Q7KRUJ#qs_5j@0x}8qd=4wC>1L&6P;?0YFO84g=;EJg9t$zS>b}WJLG#}o8*I`N
zg1obHW$FeV%RDc|g7-z#O8u!7i<=k(=+Q5K<}!N>a68D><6Z~^jmKI1Fdxxw)||)^
za*tDKz89PCE7#K;xSg_2Dx+L-aef{<-erKx_NWnVcU@R@cEiud&KC{@Rl78}Wi;I4
z+;IPRSbp?pI(p>TBkR2l@NnP8wi-_xzbkfMkhsV>ATirhVb!wc=4*?pV~Qz1@#@*b
z#@rXj`oXcs<vJA{=Zrk<O<=_e>M|^N$r47=xR@QHYId!SoC~RT0%Gs_7em-B8}W{A
z#38T!^|vWHD=bQ`K<`EIxu8!mEyUY&7^mjrNVj@`R37upNX7M#;sAMl^Re&35HYX<
zn>}(M2bfm#fow}DG~mvIm82R6$1O`;nRx;yao+eI*~7|n@cy#L@7fHM`&d%PXsx-N
z9Dc-lGMIs<{Sph=eiWqM7Jjj@b|Hwww+dl#|Cp%9;m+5M-)%lOA}Y{vc2eOLb1kP0
z-?KpP4d+n2A|qOxfYSB^Li5y)J7$uYccGVa$01{;Rk==D_<I;bw8No_6>UgA_vSs8
zUOpKRxo<%m|8=~G`)F_q#U=>I=~Lo;;`_{?I<d_4QPQN(`WaV^M@>sNzNtbq4lZ2W
z{!Lffuqk>N?-XMRQJaJ$pO;I#5+Gjb%CblADnVv`v!!xIOYZvufNIiHeo|+COeZaO
zWPTn7$v03eS=IJJ+AC-y3(*EwYyKPkw8X7eH%d%?>1UiStM8b^D`Mu9Gxv&~W4t*g
zmtHo0Pna0t9RF(CM$91C28n9^1}ZN-)4AqqoZssiSzjeFz(H+>ktTY~IR{@~u3*^U
zAAr_>%58*+R}-&!Tu+UWkR9OVtBcf@_*>a}?q4f(vA{X}?N%H)G<i=ZqX&KoEH`})
zk;MXS@o}a>5qK2E1<JE3;P@Skn^9$Vdv~F$BskDyE___1v^LFEyw4Fw{|RGw4j%Wl
z-S$Glo0P!55H!?upnXm{3>99DfA0+Vx7PgkCijm&ae`W>44hoRAQHMlsPSdU_S%6d
zr~~DDH+7`{S2=ID;vT4jnS0cs+Idhg{vMoQiUK1J8q)RgmK;+-9i0{*R)Vd%JJ^v6
zdvcAu5J$I@@-yGSi<yWk)`yX^Oe-~!>KG!lY^jUk?*7@Ju(xF%GPVpaF<<#}doSD3
z4FqUiWU6rju8zFEx`aZjbC5unwutL%U*f-Vh#vAo_KM%Z#Y-b}a~F+DQe}r)OF3H7
zGWasQXBO5!HRCwvZ*T_TVn&BkRB*^u%yIQhP`yTC1e{ZXQBjW`SCLcZ##3Z!2)g<*
zii~N$jL=WpDu%<g(=M((IFYFKV>1}AoD-Jlm8oak1o1_D9}VDteV#8{v}_nOJrv?D
zYnjtQ;9t_A(YkyJTUa0*8$kW6+!}~?!V!8E!awTD3h!Wo@~5gH{&kv*mcd$;$2N25
z<eh}}rFi7p^@*4ITBfd8w)=ZU{L!c*v+Z@A$WQi>z2&MKCtya16u)=$=BN^9j!I90
zMO|N*Jv}lU8C^BsJ}(=_VYQ??ggNCq4magPyi}ORu~IFi*b-Ra_KJ7tFm7L*&_yVk
z_U62nIrN=j7MlT#Nf@JB5w{&+4#^M5p7LbNx=t8cniHAmGxvefB^;M5ulV^+fe<TF
zi>Y#p{@-tAJ?E6-+cU>M2fpoeHy&*5f4jJ8u{YO*{|m47e+;>Cai<j?5D<{vsz!^C
z)xcg(NJ&s7T7NeWIVVW9Tmg{3Te&%=_<xZ)Yq`3qk4jC_p4=Q=^#5=2|A_rxApNhQ
zH{_>Bxf}>Sykq`9LQLNPVwYAj&Tkf~tuNDw$-I7SRF5b=t%vgDC+ocB{-?N}L!nT(
zg9E3x;n1)e)>L&2)t;rUe)fv1`1bj^C;sZ{$}?odyO33XmQTL}=<hE%e`BmwmLu>O
z3`XFscUb@+7w>?9tl`t-<m5sY2|Nj1aw~XZe7d~DXA&-H$J>q5y+<W#>#l0OH5sP>
zd4})ghK1gG=6yGGFu=pG3D=h1Y9~r;_$WxzHvx~#QFLziH_MH5JGB%;^SNqJ+L)3t
z>zS4F@Hww(LAG9|G1Hq?y^fp5kvC+Z@kd8TCvo3`{R&V6>g>S^8IRkhHZqYaSdanB
zh<ICSf(0sAF3DjE)KbF-W4_$QWjpNP52b@a>TfTr4vmhU59kfQLy27Lt+H1lphYZp
z_==OaY;3b=XY$9aHe1)6aM|y(mw@oGUv7IawCm@i>JP|+!wf`wkT^puEm|)98Zht!
zq5qR(M7k7C75}Fk8!vF`f~*H=0tI$ARpaUxP`2mVvtihPz`;|QY3tEFu|4ZFSG4qQ
z<>D|tzec;`_D>f~U?58L=-G8AhR9*Ez;A~JZzt3L?Cj~7MF)rMKDP2-GX>I3U4)H!
z!EFT4v&jdKQ>#7%GmUjPU7`M3)+7Dv0cDbZ(}$eL0%E7|!7l9Ja}_97&FM*52IAa_
zYeaHi1-mKK3Qk_#4fr|7Tdoa$e(XHvV6X%JeqFPSVYi%>Im<+Li!_geT%MsUB<&ug
z21-7!@~wT|wj?!@b`a$qe_=bDe$}EAj*^;fSLbmt96&JsFto^JE$j{8K&hs-ALk2a
z=N_jzyXE2_CQJ>sfDWgZNW-?}0lr=Kvh#8hfPuhas+9%4@d@h5!$3yw(fZ*!{ep$_
zM+=R3YK6?n>jb=tjhsp_4$y~Z1R`-id^R%M8RITR@Iyw_A&%`=nW=%dE(7!m5eki3
z7Lc>ys!2I&R4u?W%RhcNsG{Kn2vy<EepetPAT%o!BK&g_G#8PrBhbwtei=`|G~Myg
z(**@&^Yn;6`-MjXpPqAFU{>(8!r7%(I7l;#G$JI?oA2V3J2(vdZA7L)|5B*cj-g@e
zS_<}||I@}tSe<BK)};uFD?TL*=ydwTh0|piv@nRz70y2A9}F>_<qlSXj<<Y_pEOch
zR<DH3T`yp|(m!?o+)w%NH>^1iBMv*86lZ{-V9Nd%f{XIdXmuuPz&R+T8C9=l@6awU
z+kpW8=Yss#sx;S-ru_dsB}i|vMW)6%E=b2^-l$C7|5ifz;s2#c{x5(VB{aM45cZxX
zLYvr~lGyzrz5By|fa<nT(#C=(`0pgJP{j-_%z=jUxNhPz)&Ey!n{;P}b-=Y?H%EAV
zQQ#IWl$-gSC-Z=3dcgqXkl~sa^|#%dZlp%WVnC1#*b(UkudzxAuKnOsK8BI42hNCt
zak0mi4F`b+k_Xw_0a?MA{snN0#q{-vX9wI8KL_&<Sp>`-;)89L0*>e4OAXgoqbL~o
z8eDnBI)^Gn$ydzyVltIxvRUSw{)@CL)IUf1|G%Y6dBA;iS(DD<3tIw$7xe!v-oGa|
z2>$=rqJnvv4!LHLiEntRqI#buym>~)cvG_{7(Jt6jEaqkiHYS+18QS3k3pb4^k4kn
zZzi65a{7UDBvt(IR(`!5Sg;s~V6irVuYXSYePnLWtxx8Ccbo{I;UPWeA6eEy?>{7L
zxX&~Jde-H;lC)6$wd-^&$P;_2=thu|v7*2;<1W(B;jBeVv*wp2zs|KMc=DmSk_Uhy
zq58e7$D3yvd%IFRw8_&fYiSko%i@)@5I0tl@;qgVf`aF-(-POQvcKk2iHo1s?-WNZ
zCFusI<h1SzK6fsC*%Ytp!h<_LaQ)$Xyre=O@6lIv8Jo67D5G5x=1xK}NkhU@nOYP6
zCMlTgDyO2$CZ~}F=pNr(5fbvnl$$?S)G91WjCb~`sjsu^iwil3g~(g$_a(eY@{`%+
z^tFrt6NLbv4cpkH*(*f_O48`gxbum-f%Y*ivNw~Dd4^T^Qzs`yq_>*;`&%7#W0s9;
zi#wfcGXhO%7%}Wi7MT!&aMC(fadF*!rqF?P&6Sx~+H>o(N9PBHMakY8YpB5ZIE?5Z
z2mh-A&7tq43{FxEBu*Kcooz0mlJgW;*sT|Z-l6(^LBd553mnpuaLUk(QkEuj<@FD9
ziQEv<5*;OuH-=V%8g{q)<ytSf1-u;WlWc!o%#chr8AZqq4>K20jVO)uoo#Z{{`@OL
z!Mi7h^nBU3-U*x)%?Mcgcml}#^Oo&o4Qa+C!>Glq!J);@CB7xLCRIo$OOjQxe?1*d
zY^;!r>JEGJprQ2M5B1-kVj1JNHNuSc2hp#rjIy2&{Ce9??L}nM%0G;x!WKbDMEDsT
zZMc#lfWI<;EIy&VXP>gP2xSSbfqpcPsA5R*i`OJ<<}z=+x^o&0>@w2d2dVPPY&E3>
zuPL9CYde}xxN(@i`!IP;_)YAZ!HCKjJSMYFUjleoWb9^7@L3r|j};UXUk@#36ML(C
znyO-Y5`M?mhdUi24&Y_plJ||fAA8qTV{M>dh1zBG&ajgl;9_@3ebEt4QA;cPd4*z;
z!#B+2n?r!Ip5NWjhlsDwC_^iq-XSG2lp24yoL!PQDrlvh{++v8{agxSmJ7ipMr<#y
z%||4(+}(R6c~!qb5<xnfcS}OQyi|>uT(QTe&hg^`g*xf(HcYYY7W}h+<((W-7;CI_
zo(sJr={x?vcOIu+Zo*$Xoziyi`{Hu+@k-s@pG6SMMP11WDTxw(2l}1iZ-=qXo>cL<
zR8b(aueJBccmJPezWON+=l2^cTycjMhhhbayE_!W3hr9m-48A9R$N;gio3iy<luk;
zhr7EUeqTN_&mZypwAt)zW|G;RB$HP%k{{0|iXMQ0=2lIvfWJkh#X_y3Tzv{J(^<(0
z8>+x;<Hj0$cwtjXc&OO7(21on6#YC{9DimGi1PlBTP`;RYgxs^&nqI*G5G<brai7W
zn!=Z|ha^0@I@URS2&ot{f(cKAo%zZrLh}l=#7Tx6t?;+)!sHHbt1Lw^#VVffNKOAe
zNw7C<7UkvG4xQOWa>?ZDJG0zue(0e>YL5gLBrV-SoS*ry9mn2{xtOHt45i$^eei@f
z-R_eweDc0ga*Tb9b8^l9+#L+%ue#`4M<}gRdi;*QI6R8XNWijMFDJ!5fx%3V$<rdD
z_4UZ!iAacn)ucWb3tyo;qf~8v_~&9sf?S9cAg&ZnifxBB`NBIiO5VOzdw<Z-?%t!7
zA|4cq%>Gtz2#nse*71CNxaWp5D3Q2T#Cz9#wz@2!Up8f(R*``XRE?XD`%`gGP%TN;
z!h#*g<hAliP?jN3#t#r`So;qXwwdv5MjNF8TQF;yJIK~9Fw`>DT(P6am2?bzPcykC
zH~)!(Q2csK<?r(85#T?m73~#py&56vBiBxFBI?%T$^LdH*MtH3;-z;`;#G|&)MZUw
zuLw(m0c{8e6c)QKBcJg$tCTe@w4KRkUOK>iM^fhT5KH&ifu&zt*?A*mr2aDa0;|=(
zizkC^|9Rbjr{$LRWR*41ep#qx&fT8;4P~E{-Y1!^;NmlKv^2|$@R&Fd@XOkD$Pmau
z!Xi^S<lx2r<@%CY9mh1nVz5Y&w~a9_qLZPLRdT-*`r!?-8x7^!TU29yaiWG3T}rSF
zkb%RF-bGQ9W73lFg?`Vfx)0F5!8rGu1De81EqFM&4H*`iQ4`L37XtnH?k77%)&92e
zM@Lbm(7uNuc~Y67`Ut8ybNimayNT2KJ)E&zeNa57n`ypvt1=0hJb-71-4}J5dy&jN
zghC|QPIc(t-b5dI;rI#Va25b>r#MEDb(eC+k5F*b>3r-zM~jNPlKqzRjWj<g*Bi}D
z3H%|uey><NSXXx;7DFqZoer6mPZHsrJQ$umEd6_2reC<<Lk+)fX_Ze?yv-QxpM7%T
zkhOL~&3xpFdK&R8L%OkJR;1!ti8HD*7Q0?JH6h}gM~=X73Vh&uS<b(@)*UW+l_bHB
z{w>eshP8gVPlEgk1_v|E9S^=*^CShnbQ_^yjJF;nO2HDRh^sOW=j?{X+ncWo#T`z(
znygWGfA!amW(Bt97O%EUXgRVim<TsMiZ?S3_KsTVCX4kLC4=T$OpFC`E7penZKzry
zM{juN3nhZXcxc~gw&OpzAYg(RB+&Rqtmj$WCw6tWZrcupEOD8ppHC)O6(=E$X|m;)
zw`f1&za_IG0}m1tq*VV~L!Yh*i$O$Fp|pU@9n8ddh!m7kfG%|nlml%FUDP{UcW@ob
z_8)QE@eMZ`4poZM&nx&X*V6$a%^%-)j}dub4_dvM7on0GtpqA%eL}rlIQv;A(0|cc
zKOhiqo4A8qZoaFi;jF=dga1%1K&3=B{rs>z8l;jt@_BdZTkpg%sYv^0FsM8C=ktiC
zn6+>GR_s371?>d_z^(An#UYDBGzCZbGL9HY5JwVqm3mX-m_^qWXTib}j0qi4Kp!Q;
z*~xl4{V-LENO%2jUMU@)W~|Tj7z|!2+%J_NAHqjsFHCE#<we9$$Q|neV%p>{Mu%#U
zr(ImmkLLxQDMBP$LBp}DDplx-@c$Tbhs!^Nh~jN_N>V>-Rk@PK2{bxuq6(UHnr20`
z9vF#-VT3)80QZ`W$s%sD8d)8R!@v@~a=Z-G{l(aw#>_Z-$}jy?Bh?;w<1w;*qa46E
zM|{hz+OWn3=oO8dTUzg_Dik6%T+K<;v`ztJ^;dN_=I%JS>=X0236RH>8}_yDzxY6`
z^p60S?Mxj&WlX|z+~bB}j=WUMap|g*^!-!8yT;O}>-UI>nYje!;H0zItZ<e9taYci
z4JRUo`&H#j0_6%e_FnZ7ol>#WzC(Tj?V83}lGw=2IPymn(<|hYHjPEMYi-4#0negc
zl}c>RN0|e9wdt1z8_{0a#l-{J9@=Dmp;ONht2GeCfp*|S6@L#qZK^!T`-w&Jj|fq-
zb?>*Mrf@QaPQJXX!(Q6A`|G5DtERQK0eQaI5OliqMi)tZ`|V7O#2e|F8{DXTQr%ZP
zmYawJkopgcA_k&PZ_Q^>(It${i;I9&-S_c!Z^I)>_nPBBrnK^e{a*SaUHrG=%*qkZ
z6I39f^Ok*bzm6=2C<;~1z_7N2cc6Z{mjv)5;?tJQS<U+V6hvCQBJXamvtBoA4BOuq
z?fP8ADw=|!zbeSdrj19(HslW6sqD`^H~)i|NSej}zT6Yviu*rQqS84Wb(P?#Y}MZJ
z%J++(@{j%<Nlv>i7!J6|d?_$ua3Z~Y`D7o=h~|s3xfv3JQ#%OPo!$!k5w)EP(yT#>
za>1uQ@?a8V3423%|4mc|r7+o^)>q-k8y1h=7*Z6YmIEKV#A5f?w8H*=GgokH7n;PJ
zquzdP21(^C{2;HM*7gTe2~`^QWA#xBOFYzrgNF0#u9mc%a7uB-wDs(<_R0A=qpsdr
zjX`k!qUlU&$rgX2MzyVL1>V@y#qT>0df}}(nR#Dl5Tt6()4sIYUK|UApFmAA(yDvB
z5BA9?S?=a{M|}=2n<l`5Imm-TeDm0z{!pE%QPg+GNK~ly*n!1kTwSsG;!y9856hp3
zIjx`ZvgLbS314~xH6zH&9A(z@3u+9k^-25+D<hMw-xqJ`E}?n?^R<~NA|f&U6fEl;
zxX)IRWBssDR=m0~P*oALqKQ<36-*zJ_FlXn%opzlCb{ylLgMorS8k)PPM8QD7Crux
z;&+qXCzhS9cldQdBcwzQ+Oo8|IBOen$4;IQ)BLQ5xQ?%r0wtU!-VZM$_NfXxNcnPA
z{A&^zOmN8p$V~I?2!QIFhyvz}K;>_A{dSky$iX41u{nCM8@Wt0b(OTf(l>BO;kPYx
z?BZY0LHP5E=-+H>2;rG(pec*tPVFk4jIHNB%aqk6_=cvqr|sIH<w|DfO+d1=hY}oE
zSW-ZMK7oQXYkdUIJbkZ5bBa|VCK!pW5z`_vd@`yJcM$M6@w|;+0gLj+?>31KKb?9}
z9h7^;I#TaH)*|j65;D+AN_d@BUMAFvN}5YS6_tKhpOD<KYUm45uN>X8-%Ap$AH`Yx
zxTrIO$O<%GiPw$FzioV1KwV8eiyO`!TuL!jqcM!x@au-F&E~~3a_lw3NEW3QZ$G<H
z`_5QObPLZJ{S)Q-RF2fU-Orb+M2<rx<hs2ugRXKM7d+zKej-hIEi%f3vq)gs`{{QT
zGHfNEOI^%5_h=h*m&F`aHhMZPP<#-{*f*dE;hvjoaR@jqG_tL6JeltL_vM)jTh<pj
z27IEb6T$oZYxo=JHcU;_=*{Mf5lNtqd0kh0FtRD~`+ZMTMWr_$^c#CP+&{1E)L|;m
zUqdC?qZamDLE@*&@ew)!0<tpr+5$@*NQnw-WEBRdyy*^pd~}Awh>ebF*z#vS#{=Sd
zBL2_++`_y<myNLh$mPRrD)2(%u48>~Lpz#_*PewCY3r1lN2!JxzPV)QSMA)*6yBwq
zfn-QeO`nAr%)1#wpxs0@E#?Y-7FQV*D{H7!?Oje(@F*#-|G1*H+%#*q+6c3aNgyE;
zw2}Z`9~qv(L_hy-#2fy`^47?JF$r%!7Z%f=hNY=c(?ZEN!SRzXS}BZ|<q-S6s$0J6
z&=P2<w}ZAaEFxI(q_#|U|NZp!F*o5MVKQKe&<>_G_Z-Xn<FgILGCLR%{IK;9{a&R#
z8yE%uZ}7Z`WUznuc31=1<Y9O(e6*n>B0-GqDo!6iuT|Y^;kwy$aQUveNG~|P*E`w(
z=<b<~JZ+@+`DDe^fCYJ!dRQ+@Q$9W62ysfw{WE*D_)Vcr{5m}M*aw{p{sk#fm2TJv
zcU%iq6AzMyf5HHi`d81yS8JLtjE}<1GlHBq7_;82Oj0Ee7Sb8HQ+Ayl#N?|WO8@AS
z_iRQ34T>4-{P&)dAsWZKZe?m&bchG|YR^A0$Tyqs<~B40p(jN)XDPFp-{P-~0OfXQ
z*Ek*7rCa4J+ua51rBV4j<dIJ>R;VlnT!dvIQ8a^6i&vuSg>QrPfidcS#!TRpOhyR#
z*`R=!rV+`x=_Y&RxYAPWu>IuAK^uNz==|{_+do^k^Fim>uvWktqZrdWcRyaq*kVAH
zzdAarvmk+4)(lF}>DGbdjA_Y_Z8@SQZF@jaGAVLl*LjpqMm|cf-lBx4$6YRKiJcQF
zD}(mN@c5T(#~O2Bm-lt5pMI~Kjwg3Xl`wxafpOLQDlU}+@|!;Lp9IabS%Qlac}QQK
z3;82sS{MG7*uUp3{qjUVpL?i!+7+dfco@EyTdBXn?{Hgqhl}0bqlF|+?-6jDG~^7;
z{OBELb~_v0e!7*h#qdLot?^!}Lys=;?Mn-^CeU_$S~qp2iiA9=@bB~oYDxZ|X$21G
z?uQ;xhP084@lx^dm2eSUJ{zGWP-|vkhr7oy8E>!X1Lj1MMhUkxr)x|PT6fkPOo|}_
zDDWeH@2g82JN~iEWXpi2OU)zF{y`7GVp?snE43!U?2DO4j2;G4#jmPutXe`LJBn=n
z-6f!xIMplUZ$dF7utJZr6RU&Fy=EMY=lg~kALmqo<2SrxD&bMG?m@>0<q}I;M3Ng&
zgdsW)vEfu9&-*UJe1n1g<f-9ENb?Sgrtsx5v~vXe27RdHu<i`9s^uqcXCs)^OQyC{
z+v}yHb?^LS;CVKlGNHkVX#Vuy?czln=5?GpZ_Bun3h;cy{-;VheU1wi-eoFvw2}5Q
zTBA)!C%2dTJ@r-rmW>n!N_o{3@3|!*jlhe#e|j=mbKmb6Wl^8ggeyrJR3UeLbddf5
zT@uzqY10RGnu!|K>K4m%`h+*WWjl<@s}a(NcFPbl0^qhi9k0iO(E4JC57F9@B$08R
z_J0RmtRQJK+3A~u8;yH9SKpp6)1ngoFZJV&a~Z{rQ3MSA#A45Uygmub0`z}K3Z{Y2
zhf~*UAlZ;mEwr5;CW%)4giZ!b86>4~aMzljXQAc#8<?HO0PO3Cy$egiHzm~b@g|!D
zJnW8@R3ZF!b}9F|rrY6x*-+IbKWD(-cWF;F(VX)i$5iR#h%JnLuxZYM^6l99PO%gr
z>CaPUauV!)&`(Zwg!IpHq7nXr>H42YD4XQwWKYPXf8`TwGerLY?;hAAo@%3^`Gv}J
zRg<KbfX%B_8o3^qE<?6ea!dKQX_x87l^h%eS)ekk#X9rflsS$2d%;F`J*BGGgqbe&
z+<^o~__B#>vMGqvyFA$x;lg-;wR#-E_SG}u@qNmT(lDBk45^*X;a=tEzIX<`5)PAx
z?;%d*S!!dZw8F0B1Y{qOh)!qQiBa`9I&H4(Y%XaqX(VM+KD4}jG)lj4A54Jv2wSiu
z36W~9gc~k4XBWe~^a+cQz3j;kprTE&7HKn%8L)_JrwNtH{WyzzY^C>Qt6?m154GX7
zuR1wCDMM)0&bFS6S&;5SI&t5fzyFm?etOQ&DnO{jd3yuV9p{d0rLETj?#9~Duse>;
zJ?bcRRilqapW`NhM#m(HB@pD<7FH=}$a_ozjX_UOT}JXjB%jkAVhD-<9JsFz`<2RO
zH05+bWUEljO}b7OxJJW0srjh}`n|=rL01OCx+pCx2=k3c*yMHq_ac`7J?t;tT*6iU
zk?^5~y$EwU_9M3veV>?;dNT@>A=V&2^fp1DSr|-5s(ivNN}o7FeRrzsEe(aKaAf%0
z1UdNI1kq$;TTtQ@(HovaVTh%pHo&*GPo{R2)@Ej2JbYDgWzU(QUR#bfS}oi^kbWc$
zi*$}Tw7EVJ^`FFVEfmW$#!A%|UP>=^?%;*WZ@=FuiZ^QC1<@h93LNBkO)2qS)suIS
zK2AH+Ur@o8V#u(O+X_RA8LS09dY1~*oY#b%+4(6Y)`)2*R@?$kmSsq_*5Wkwdhpb~
zqY>PP`>EL6<Qs`W6oN>iwQ;D#wwqLYBf!rhULXAHoOFYKacCKe5sg-kFVbz$?c}vR
zo-079U8L{>c&!S7cZ^gWnQ=}egRjEkizm@tYvpb(FJAE2#?<|fb;os|vf>4vZ7DKb
zQMsqMN$mLU9)2+EjJ$iY0vU)bTh^?0!fBTS+cbr<cc!^d*5VQxF>h%im;~d6v<gj~
zEpNaVXA%3iQT(*RPHtsti#{1|Z&c7Yrj|T@mUxf~?=EA=Sa=I6MSjofo||VXGsdf^
z&83sQEVf4`w^qfaMR4&&*9W!ue1W5s2Kc|YEHtj#O`abkFFZiZYTQJSt=gG6C!a!l
zajCXC8>Q%83>n)%%f1XS@xjj}ZeSDMj38}VOJA`#O=ZPPJlT}cnn$h*seQf^@M8}a
z>g+1@BY!IjzjafZH^Myr<ZF-O_44Dlch?NHz!?fz*&#`H3vV#xb;O;jN$gOFQ2EW#
zfrYi(*G)-0HGu$jY!u_%>=as>bc0a4g(|ewyF7dMi7@+Gw}KcE2YMdZ7JrKwvZa9`
zz~B;lEN6M!&)alO)u}B;>tB$)rk9Ff-0{JypwrT5BqLMySsLRPdoz}qUhYWAi=HD8
z`pFe8lsAPcY$eu6uxRO4<QzYIY!x&xVASs6Rt3#=k!ch9*cZ2N6RhYROH-%&@~WK!
zKMF`K@Wk&6jdicE<9-rQC!I<*K>xlnhAiI(Lu0~SHYbCdL7R6U<74)th-ep+F?pmS
z@zPT0U#4G5{?RLw>wWwDp{hyI2r<49(AlMd*_*P*S4%|@WXMSxTB-Sc7x)<ZWm_yV
zXJN@QD~^l3fUa^LNBZyBe0S&GZTNQKZLCTwAm5?nmqTvf&|2JpYfNs}YmG!UrMe{h
zsgoxf6F>tGn%iIi4LCD@_^XgO)+0qX?Z=fz_C1WCOjrB&e7}=rHT&<M%zt8(nA>~c
zCVQ^W+!LFN`y?QS?D5z43H*}&eg&UMw>@DkC|OU2YSL!VKi#{bMd?ZkM_@_U_lGu(
zeVCUPQ6Dw|<wiiLj|(1|+j{kJBb`ZQBTb+WLlK7t`3lx-(x2OwLggZzG<c%J+!z6I
zQ0EKAMFqqMdJ!^plkb1_^pVR+swjlQa499)h{Z$`k6_g0q_Q96*<5XD)q;Eg^*m+H
z){qvL34WxG1+9cSZ=cDgd}hGxtiZ>f%gakBN4TWz^4H@4rv^^R+JlcmyuLG?gtKDL
z{01#JN;x~7#qBj1u0Z^Ft2~=UupV&9!4FLls{^`8`{Pz0O|{RajU$<uF+baJIhIBj
z)ylPc?<YJ4VWk>yDy1w#M&z(JJWwZG@buCR7Go9JcG8-3u!4^DO210@G7|{iYej~*
z5afil#do)j#GarqsB8j1U2@8%bYOg+Teb#k!G^0Ub`G|#XbiA6@sCYfTO=)(m&mw%
z8dG;X)RqK>nuPRp421^njGV*&cxfGx%6ISKFageDBdfVdtz3zK*{FRgKOQgkCO_aS
zmXJ;m{X3so`IVcn1V)}rBd3n7J-6Xy4(YAwze{aNK?nPFQW7KAXH!#)ip~Wp6x^zu
z@(NDcWfP}EJj4Lbw@ntK@jLrbY_b(W@3Kn(S=e#F4ZI|{ns3`s!d{Oc1*;>{bTHue
zF52x3t-U-dt|AqM&$xY8qzEA-385UfdXnr!Q!jHYCT$QOn{6PFU~#_xtWdV@LbDDn
z90}Ko*57R67PG53T~Qy9SVd%fVe~%=otR8Jb3^{>F=TJqcav<EEgc};dbE2&nm7LU
zg?sCnf~!~Bk7h*WK4mnMg7{y1r@QSG#wB>tf>c#m+%@kl0bY?N(E92Td}XX^)(UJa
zKEU}e?+D*svT`#qHIJ39Zce{4TA_az;54^~<@JLJ#m*>I_B)Hal=G7|&p&tr?v>x`
zxa<(63`L-01KN0WtR(@Otl5M2o0;gkkUs|kihYg0;Z#Xgaa!SX7CeFmkoiiBUtf|a
zM#K#|6i~{oK6Y{)BvGL*6(cR<YG|S+K7jdIT*LI%vWUF3lJNCNB><&?iUrb^)ao2J
zTlWZC-Rot+jOlJi(FaG#e{J-dEw$d$0i=;FY41t#sW{iww{OXjR<%V|elq>dfOSVK
zh<MXuA6A!6f$&8m27!CTC-JFmWY{4!=G!^pQ&~6l7t18iPtRoX_6~~u<)-2ZSY$SU
zOVa)d8Aan=kMKsAuA|;@WwnB?8}0SCgC=?sUo{G*F_EzqMaNcTsK?2t8#$fm_n;Ae
z9Y<oy?7qTVlpN93faaM>MjZ{wu0S59`;~dh(^d=xS6ka60`elNaG|IiEFbC7p>48{
z_1gGv2?`sDqJw`=<0~gl6J)~CQiM6%$~{8OSZ_k~8tutNj<DS}I&s@*g&F|-y}h4r
zvLyl$KmLaN3Q3&2%2XChw97rg?Qh13S}55vD*6KR&eo6F$7q;y!ws%hlp|~1Ann~^
zi9lkD&Y+hsZfjI>oQse)&e<?fsKe5`?^<}rI1QnQNgkY*Tt)DiG@(^hdF8^Wjr|q`
z3n?iH+wkeHSGX#5PtY%Fq*AN`GE19B5PSb=%G=gD3@>_$oM{bHQ$_WlolUR0s(07w
zdqJ*qeb+zU*8k+E1jLw27TMC|BX-DBt5U6U1)G{OBvp*3-fQMgF|*UU>9II{#qm!%
z97r+XU_9JUO@6cqOFs4i_1*n<HEQtIT!oYD?O3_4;!MY4;!8vv;gm0vIX(7AFbn(I
zRM0Y_#pgsm--RXH2P0Gern7<4#bn2{Ku~9}b7egcAJO+x(haOBo#fmd@v}*`3BQ2Q
zms#HpyeAO%0%X2sGzE{d8BssOBp?1AARx_29)#*tHh#<2WO!E(lI|{l@}eA0*msIN
ziuB>S{a1@l?g;ckw(DSGx=I_X#l25FhQ}*yl95blzr3V3fKh+D6$S>okD9v)zFAg>
zR$?$d=UPC=>`^Ehf82${EWWtBWT?3@?FnS*<am*CFilXC>Yj9m^RkpyXDJFNRr#62
zLLhTh;8%aJyCPa#RDD3{xqAK(>=;6yF#$k6F>9h~V@2x{1Hrn-moFkMjnBE8NvNKF
zIq&bo_X6OR+}zhI3JghWx;mf`XOa>Z;`fFb%Wm<n@g2K<KjTLx%0l#dDG-%hr`6TK
zbenYKLY9?VDt6Zxdj)7!qUVKI7fLykMg|bw6JfBCSFM8O>LUX+EMi6pj1&*DrQ^na
zTdf7^(mjt&Zp-f+l3xHE$y#u)pSWrR|6Av*l*V1T48crS*>Qk}BG=<f7$H`)b&Fgg
z=$nuUiAp!c$N^Ik3O^erjy{@Wv~`KR_g?Y}^Di0C^Qz8Ze73X!TG#E&KOpZe?^^T-
z@BMv(r2QEi@XX`w^~900&Wf|ylaP=^T=E`7+vMxY*(F-bZn2<_w&C}K{>-GsUBkYN
zAh$$R&HVD;$06X+>U$FA`^|FEC8?oEoTkOg7mj0fWNzNrtm)*8`ZZYB6qK&bQY=C9
zI!~_JeM^Tg%H&*Cv1}pFISmjq61HV}ww3)~ojtWdiN0{C`6G|O)#f+cAZ#@OEB5xE
zmz`rs%sFHw1mWm;vXgTce0M*@<lv5I4QGW6civAKlZ`k^zWjULc=~@Z8;pNL`&#xX
z{%X1Z>T`(pR3DQyhFq8wM0)Q}J#7Z!sF?w9+>l6N#G3Nn9TDL9NYTw+xVd&8S?otg
z1C-1;$t*+ytj7~1q5-(6=asVRrUCU&1EEYqmP?m6S5zctV23y9`VI@fWHG`b5BaUg
zSe~%e=C<b+)PJD%#OvxzdQVmmmF~`pm-Auz3@VXpB#CY3artK_>;+L0@m`lg@Bt8g
z#I4L*ksu51BznCCjSp-p-tZrgWbre%%$?7zFTpd`Wl_V}ZvxkT=mUM3Bgi|mF@_XL
z@)&A8lQIGpB}yf=1D$DV-Jk`Mc?i44RcSa(Wx(~nrosOv?4;6_&;2EgywBZQC7%su
z&rR6nDE7B+Aj!zTW9we)_O%!Xx!R~?2}@5SM#V(?cY9t~!E*oJHK}1lZIIsSSQ!h6
zG5S*@5eXR|XGJ>`YF=?igm0aOX}|Q^JFI~+Q+`@W^5s2uc8GLcLPGFTjEiSdJ!u~k
zs2<hUMeXuLoX6*a8fb7gDdUXi?l;_Q=i^<x3_mDD76(uwiby(qDsf=2M|LxE=Gpx^
z^~i}A@foMK+qvr*E_TeD3NWI*V>2*)NG*mMH28?An+E(FUCOs9z($vl8Xy(u5oudz
z?w%_<^RRxS`RPAhmS=ASEIy&23+CG-DM-jQq^+Z{T-@zMff`HE)lwV7>x&x`@-vtV
z5L8E6gWqQ^Q~@kLRID$urpe)2za_#(Df^o7?dbj8Wms1ST1>82H9aR^<LX?(YpU9P
zD%-7PqW{KEqcH`o-F(=w)-VmVnJvw4$*+2^b9HtCOPzo&gf}fjtY#Jb{Ur3*$NPYt
zP8M@F%dFv3!6CrjY7Vy3cgKtyHr;1H3(KE?o@^aid$8kAbhfl+dvS1*Ua#>kmEN~s
zoT%5GZ0fM&nB#!r|7|+ms1eAWC%KKjD>7|icw*r4Gso#0?mcI0@{rS(l|d#d)eDwB
z7}pc%V4qLed-Q(BV$oxatZ$m%^9r8o-T0|whHmrKjOYGE>;ru0qj_)VF2K<a-k53(
zhb5++S5Crv82seeWbnnZ=r+MmUpPCh5vT(RCU?TA)t`(o4D%BP^0S6yPatd(S;xF*
zAhxtO&-_D2h9&4OxshRm&SkdDn69<LO`QsI!&R(-BG_B|MD6(*!io;d$0^=C$))!k
zl5XhfuBM9gKAztiL!3=Tfp~Z*m3yyszd_J1GFpgqz5x^2Lt6?aLNbnF5aZbK?a~R?
zqNQbA*WVP2K&NDvo#yIVIwU%9gQk%Zt3<a`)6sC!r<%b|K+;UJxROuDJHfwS{&J|H
zbYX71y3A`KpJMao34*M(au=d7|78ZiDnI=_&twu-q<xbEL&o#B=&4cMj^k&`r-_n@
z?-3KjW@KuK#GsP#%r|gbX^6QXdbb`8=C+{(7GIaO*)8TE$@9gH+gl!Opc{#bHR_4L
zDqwdHhuKZYg@(fS;_FxaRA7$2*C5h3t8z?+@EyN*Y5cOb?eiiILn@u4I-9R%^59}B
z(dOGe6@2T>hQ8IW^0Dj~{m6ay;3LV#QojQuU{HnJN~!o?G+?QRk?%l_d2MoeBLt(A
zNe;IYEt>g<Am7~=lCjTSlxwL8CrnDEyWf6OD6V%<>JvPMZkW3Q2FA-meu_OL#}rb-
zdIG6mqWJ<A!^!hbY>Mh8L~EZe?VVqTyZmKL)|t^G6?L!Ck_;oNhr_9G^R9fd&g{6^
zh8jHt`l<9Qe?#W>Bd|B*ZnDhzdWL>2UQMoiv<OR+VW10GMOaFJ-Ao;93fmBeioE7V
zd(^ubLLS0bolR*Jo2^l6q0ny!K9P|!qE=Y+x`{u;=j6(<#78$NL;LuWPJS{K#wV}B
z{JUkJQ>J-42I1M(hVy|>FFD%Qw&*rrly$!0rX<mGOY<vG2f6a0!wCJJHkOa1w=)jx
zZS%cazn)KQq_4OOh*6z!s`nMp#u+@8++0-xOWnbbxS6K@*h4=mAmb9zUq5AQJH0kL
zc*mweYddv2cZdD<T3V1C*fBmg_*q*AjCcmJ9vb42P3^kTNqXJw!*z0^Lw5HwsTDI6
z>PqeD1mh#V{hITab=)AeI%^CU`6T7w!dTO{ADLSJ8r}Q@qLX<@Vth(Z5UJfal{xC1
zYllGa<QWtxLDtMZI+b!e2#?4w+U?s};Gc4=v6(#Fu&JhZ(chb*Os%!6)-~fB8(iYL
z_9~&n$xtlRaZ<Nb8p)vk<}|4tYkJl{Cx7;SyBW-Vz1+O^TSY#swBogfM?0ZRy+Emq
z@V!Kgjyma)(pLQ1$p2U{G?I|hK_lGP1AenR4*6&+sCWVr`onZm3Hj1N{$h`DGHhrC
z`!)SSQ9r~JI7I&f8g<_CQ`(DjdfOjf#e1ct@4%@X8x4<XG2gATeOda~$?i9shg8cs
znY#HMsqnFbO-u}D9s($->2;!|&fi?!+n<TFRCm5N(m=eBb}rn<Yj|S00GnxxiM*7M
z6?h+4Le|8co)bi$OakqaflyR0*)`}%L#juA+15L|LR<MvBLBx|7wGT!8Dg|hmGA6O
ztaa$e*N^(*ZMU%;pq1#|_pR-K2>lnQ+S1c1>R|syh<Gkm$!wkTbNA@3_}<S%0QH2C
z_k#@SSOT1Eby3B;vizUaxqjm1gmPB*jIN9!>DNDHn|X;CSqXcHhba}8HzS`=HoAf}
z=a#%E5S;`6q!kUWv$gx7F(LDt!uMOaP@XT;jTt-A2Ky<x2EW#P#K9Hkinj1>$N~6f
zwy0n2RO<a^toux8bC@TpTu}ED2-kOltziKogFD!6(2`&E)HyI)6%JoG5*S;u%Mwt1
zX&o(F1g;soK0D^x`+t*$*5Zp1U>3EF`Ij}&g|>>e6ZQ#Z8FMdNAGoc?-4Ds;M<RN*
zX|W^@zsp1i?y@(x)x0Yh%QQwXS!Hd{+B#owYA?*hje40P-D}WxX4ffU6Y`EMJ-&1!
zE1P5vUwX{nlXTp)avzSDj6AjghM{mo&<>mN{it^LWm>KO|NkUOFal#G`(2h7YZ?3%
z5*nZ^C;jymHM>}d)60b|-#5hfSo@9?KXuxS0VXn#!v2iBs$;hzyw?a1>;{vY$JQg}
zh4z*)WnW3|^p*;qFzz98bDx-x|Bo>&!SlMWikDBLi+w#A%VCLsUF=MXg#O14iQfF5
j2y~{OueXQZ&toa44-!7rf2;l<xK&wRU9LvPB=r9P_<)_e

diff --git a/library/simplepie/demo/for_the_demo/background_menuitem.gif b/library/simplepie/demo/for_the_demo/background_menuitem.gif
deleted file mode 100644
index fa765d670e739793c2ec69e16e6be33618f5425f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 533
zcmV+w0_y!oNk%w1VJrb00K@<Q|NsB~{{H>_{rvp=`}_O)`uh3#`S|$w_xJbq_V)Gl
z_4M@g^Yioa^78TV@$m5Q@9*#K?(XgF?d<IA>+9?4>gws~>FDU_=jZ3<=H}()<>ch#
z<KyGv;^F|AGXMYpA^8LV2LS&7EC2ui04xC<000I5ARvxpX`X1Ru59bRa4gSsZQppV
z?|kq7z@TtQEE<o<q;kn@I-k&}bV{vSuh^`1%k6r<;IMd1E}PHjw0g}J2j1{^drn`*
z?{I;B&llAHfHQb_eS8Clh=>G>j0Ay?kSK!zdx?sTj0KvTng*Vqk)eT;0hWlIou8@)
ztgQ&Iun3~Fb9sG@sI9EAunE4u2@1l)!nDR{c$S-=vA@K^3(?XG4As^R*bT?qV|S(l
zss_Hq*4NqC4(aL-?ClTS@Lq$Mx(CGB>+b9j{QVLC03`^FN03V&RI#S1O9wEZz=skh
zNSsKaV#R_OwIuoktem@u6DL?4S)ruK3Kmk5s?5l;%0^GX&h?vkQl-iZICJ8}z_TZY
zmO!Dr6z9uYyN4!o`t+Hhsnez!qDl=)l?ft_MXRxcX!EJmuTeLM9XpnT*{W!fT=g^z
z+f0cno02VSwys^X9rEf;%Qr^>Egk|39!$8f;lqd%D_+dFvE#>(BTJr4xw7TUm@{kM
X%(=7Y&!9t#9!<Km>C>o9hX4ROX5}q3

diff --git a/library/simplepie/demo/for_the_demo/background_menuitem_off.gif b/library/simplepie/demo/for_the_demo/background_menuitem_off.gif
deleted file mode 100644
index 236cf406dc2528b538ed078628f9f95e3240f9fe..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 533
zcmV+w0_y!oNk%w1VJrb00K@<Q|NsB~{{H>_{rvp=`}_O)`uh3#`S|$w_xJbq_V)Gl
z_4M@g^Yioa^78TV@$m5Q@9*#K?(XgF?d<IA>+9?4>gws~>FDU_=jZ3<=H}()<>ch#
z<KyGv;^H$iGXMYpA^8LV2LS&7EC2ui04xC<000I5ARvxpX`X1Ru59bRa4gSsZQppV
z?|kq7z@TtQEE<o<q;kn@I-k&}bV{vSuh^`1%k6r<;IMd1E}PHjw0g}J2j1{^drn`*
z?{I;B&llAHfHQb_eS8Clh=>G>j0Ay?kSK!zdx?sTj0KvTng*Vqk)eT;0hWlIou8@)
ztgQ&Iun3~Fb9sG@sI9EAunE4u2@1l)!nDR{c$S-=vA@K^3(?XG4As^R*bT?qV|S(l
zss_Hq*4NqC4(aL-?ClTS@Lq$Mx(CGB>+b9j{QVLC03`^FN03V&RI#S1O9wEZz=skh
zNSsKaV#R_OwIuoktem@u6DL?4S)ruK3Kmk5s?5l;%0^GX&h?vkQl-iZICJ8}z_TZY
zmO!Dr6z9uYyN4!o`t+Hhsnez!qDl=)l?ft_MXRxcX!EJmuTeLM9XpnT*{W!fT=g^z
z+f0cno02VSwys^X9rEf;%Qr^>Egk|39!$8f;lqd%D_+dFvE#>(BTJr4xw7TUm@{kM
X%(=7Y&!9t#9!<Km>C>o9hX4RO5uq&s

diff --git a/library/simplepie/demo/for_the_demo/background_menuitem_shadow.gif b/library/simplepie/demo/for_the_demo/background_menuitem_shadow.gif
deleted file mode 100644
index 95cfb820d47f717cc9ddd31d626d497e23f1a38a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 250
zcmV<W00sX?Nk%w1VG00v0J8u9_4W1c?(XgF?d<IA>+9?4>gws~>FDU_=jZ3<=H}()
z<>ch#;^N}q;Naii-`(BaA^8LV2LS&7EC2ui015zj000E1@U2H>RW3WMn{UYnG9*Hl
z=drAdx*AEGz;S`xh>aV3?-RhFFgPe02Y`SwkX$;ON+^`MoJyZntTW4{cCB5nc&v?v
zuir9wYfih{V>Eobj-T)IX<1zFtM_|ye1C6bcy@V*b##Pqeua99jf0SEiI<3(i-D4r
zn2es9laZK@j-!^Mp{9nVsIFn0u&1G*w6~PFq^i1|bF#d-!n>@3#)r1UzG4voJBQbb
A?f?J)

diff --git a/library/simplepie/demo/for_the_demo/favicons/alternate.png b/library/simplepie/demo/for_the_demo/favicons/alternate.png
deleted file mode 100644
index 063fb280549db7a68a47cce157d680ed7af1a8a2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 28621
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

diff --git a/library/simplepie/demo/for_the_demo/favicons/blinklist.png b/library/simplepie/demo/for_the_demo/favicons/blinklist.png
deleted file mode 100644
index 53200b3c62c7a00e21fe30af69961eed389ff41f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4377
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
Tm7TM^00000NkvXXu0mjfB^P<7

diff --git a/library/simplepie/demo/for_the_demo/favicons/blogmarks.png b/library/simplepie/demo/for_the_demo/favicons/blogmarks.png
deleted file mode 100644
index c5372614a4a623d418be15ececf2768a87f70f29..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3823
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

diff --git a/library/simplepie/demo/for_the_demo/favicons/delicious.png b/library/simplepie/demo/for_the_demo/favicons/delicious.png
deleted file mode 100644
index 2e6021d26e2d699ace681e80b4dff96eee0a5830..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3739
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
FV1i(EKivQT

diff --git a/library/simplepie/demo/for_the_demo/favicons/digg.png b/library/simplepie/demo/for_the_demo/favicons/digg.png
deleted file mode 100644
index 3aa96770e80ac18446c0254f37af3d75740cc415..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4004
zcmV;V4_okwP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV000gvX+uL$Nkc;*
zP;zf(X>4Tx0C=30S9dto58wWL&oqzYI96n@aI9mmjL3}ak-f{F8Ie(u%#4&IqmV=>
zQc@v>sH`Lv2~o+ZRK|J!=y~7YAMf>C&-LDa-JkoqKJ%Z?bpx>Rc!h@tqW~ZzG&<5|
zzk!gGvx^XZ5^%r?XdnUA%O@&a-`d&&{v&=)00IE;lHwH}9_;qs17BC{+MnT6iqfks
z)%eeO002OUbaHk9Kx6@c9PpRx0RY+iFSi2#a$IzHGyoC^0A!y)FJAy82>@gx?Q9GI
zkU9V$1pMV406_5m%Lf2}5bF~V4S-Am;7FmqL7@QnRREl>uV0i806`W2e0`&QLI4Q)
z03a6<66Om)=m7vJpYX_N0KyUgP@J4yg#M0vhzUS-4**X7A1zt}ptTY}(D@%t;wk`_
z4Z!t_|7bKDKmY*Y8j13!Dggih!eRh`ou$)h5&-x@fb9Z0eY1*A->wEg&j9oU`@}@X
z{`+1CG7RwF;=eop8)yUo1pr)N0T&T0Vu@6t(5Oh%Dmog2$24GFaNM}J_zs5ij5$ns
z%;#B}Sw{&QL>2Zp(ja*^X9(9Qk3MfBA0K~_0A4U(m?TmxMij4-q)4?%E6EH{tmI}C
z4l6EFgOpcPW7W|b37RzRNS*I{<Mfsd!VEtcIT{a|$e31`<1FGVC#-a>Yi$^8{p=n%
zNI1qjO}ePMRvg-JckpQQV)gd+Y4Jn+odd21(hln#$qAkcl@1FFzZtO^r4bz&b369y
zQHgl}gtElJq^)F1iu>{0)Rwe28R!$@CrwX<W)^4NJw2KIEr*ax$urOQDo8Ipf3~IQ
zZt+;j(mA9ITlVez*oAxL=P#yK9KPgGsd1UF3aMJI9<AxFy>un(YG9ptJ+*=V8v5FD
z<CE*nO~p6jn_XM9Z}Q*VZk=m;*j{lf{kCU^RwqyA?>iG+&3Cizxp%AHC*J?i)BYgq
zq1z*+UR>{Z-}U~a$L0gP1M^RAJxv)j8{!_CAFh8EGom|+jP^WFe4+ee<z>y7*EsL^
zz(m%h-sJjJ{VUID&gsXmkIg8~%)Kd{-9P)|?bUbo?~(V{=RD`x=i5K{EpRT}`{=hw
zSnOExS!P*o{^Y!ZU8!HST%~<3|6=fE;cM=i+S=Q1r`F}yU(-%~SN*>Dqw=TQhTz8X
zuioDsf1YiL?y%D70Kg7fkO(7)G;#`ANBN=V(P0=orWR|BW5V^}^B8;?^_Ya2xmXxk
zQ3NuZAW@OsffUbii9E=;!>z&-#oNA%&TqN9Qea(3Q}~?7Z?Oa7Es`u!NB2y~P-P1!
zG<gSwE+t{=DdkV9dTKT5+nSzQZ8|tz$Guneei@h;=I@&~mfRm_(rd<MZf8+uxnLz>
z9dYokEt{RKeYL}yla_O;OYb2DH#_$VkJnxT-d;YnzH9#S0Y?IF2CW<s4Gst?3w;*O
z6rmd#8dVWJ5<`!ZJ$f)cHK8i8FKH>6B}M7DQ))!o>Gax+hbP{gT+d|95<9J&t$W5g
z$2~VLFF8M~z@yOatU(dASgJ&zlvqkX_o-~+eE)^6@|ugK6(=r5R=Qr+uad6jszKMR
z)DB&_d9|i4v;J^{)isqyp2k1d-!(nBQQ4f?5_Hp~RjQ4#ZMA*)*45kD9f6%jcSO4|
zU5j^z?p^6lyYJOw_(1f*&cmrk?Y+f)@%=83)dx5RXisLI-Wtps3LCb5CO5(|@^y6J
zdHsvbmqBBu<5Ck06U&nWQ#G$rr#)Zm&hXD{znPisd|Ui3;=R?J{5;G2hYwE{sy`lI
z^jOkf=3b_K8d<r%dggP`7vryDU+HVp-)^s$(4xLu|B(O5`t#Gq<6oD5C;xHXRNW$P
zecvA1X{3A8=>Wh4Vqgx(pbJ4G#z-NufYL|RpxMxA=q*etmK9r$qvFQ#2@K*4lZ<&x
zmdxzTGc5J22?T341tK%?C;K$%0Y@YG0%tB)I(IxzC~v?nPd*QR*WC^R2L%rb*$CT-
z*o#_<8Ht-q7)k0$Y3@;#7LgH<Wu@RL8*+>CvkKFSFO-I;1IqVR+ElNpRjZe2<Y}JK
zI<1|dld7A%H$g8-Kght#(0iY!k&Us{esdFJQ!6twb3+R=OM?U2RtDBu2i0tJZ8h!G
z>{T389MzmOoT)BquGB*cZVK*79%`OCUYg!&KI*<&etZ431B?QVgNzUB9MKEb4KWEd
z3ZsS#MGzylBA243qlaSd#9ocdJ{lYEnP8KsktBYMc<fj5Y|4Y<)v38@ap{LL)KBoA
z#GG6_)t_0Lm2)~Md;b}!99+&q?&G|g{L}*XLhZABXMYuq6}Oh;lm?vJS0-{EeSZEz
zclo)CF%|ZgsFj4ukCz`-RaU3h_|@uN;l1+hYF}MRePDxf!_KuQjk(vIo5Y*G+-Pr3
zYB9M<x;fq2)E3vScZ+aq{&s7}iB69@nq8b-w7Zk{TDvRn=k~-t2zcoE$hFs_FStME
zaoRw|lisJFhxmtWpOue%eQx^V+L*+6!=&ca{B-L~&TP!Pw7J0rg~f?aw?8j^tNkgu
zxk{%4{QZ3Z060~EQgr~ABLMd50NF1ABxwMgo&eUY0CpOHIwS=sekni>uKe%+5CcD`
zg%5}@;)awVFHr=PF)9Vsf%=A)M*E^KpvN#Q7(>i4Oef|$mV))iR$*sxd^ks3F>V~s
zj<?3=<3|}d7#tZ&8KxNp7=0KU7{4=VFdb(aWaeb{U~XXk&0@xKo@Iqqhc%b=EkTKp
zP58j3!&bt!Ml>Z>vt!tO*t<!Bq;%3EhZ#pJS(to^Oyl(Ae9EQG)x<5pozH{eN#LRJ
zhVp*g<+1BMpF7_SzbpU5Zs*-^1Uv-h1%m|Fg^md`3tteC7P&2IEc!+)R-9S9T0&Q1
zLNZi}DAl^hX3r1lOETs%YqA$9R&pTMDDR`dr!cNqpkzs9rao0JR&i1lR{g5ht)8Rd
zrb*G<)|%43rE^v{V($Sxd3|2}p9b#@2lw?EH5=FNFEq(Cy=?Zv{Ff#5fR|Oib=Scy
zTQ$2-`)dxfPU6l!E^V%xZhPG`JzjdrcqjRc`bqhp3|I_0aJV6u9Fh^b6z&=EI?6n{
zFV;A2DBdGsE-5aVoYI_Xk@hj8=%m7_xvau$yBtjJV190)b&+K8=hCNTcP`w%*mLR0
z<=*PG+T}W~28BkOru61(Hy7G@Zu@rDb?tP!_FQ<x)93$q=Bd-r=!ntt*)h9`^;bDF
z{Idh^-RCzyRxWF-41aN4dqfld;k^<0+xXABE!}O^9T7T_P6q%v2!gBd0TD$!kxFD1
zwHxJ*Do4FR3!>f7m(X(<5sWXU4zr3?#KvOp;!rqKTt03RFNhDoH{&-M%ovIp-Z9ED
z9%CG2+Qk&Y)Wu9-_F?X1A+iLp+-K!sjbI%jND|Ts@7VO%YKd545OI{9%3e-lAjOd8
zIczx|kyXfboI;#MTufY<+`yf{y}=X1v%#Cl`)5}&AD%CppTu9Xn{Ri$fTBQ`;C{hz
zA%CIY!g(U1BJH9kq6=cF;(X#A5)Kk;lDSe;saJdArG=%R$t1`M$-bbRlv9!WC|{xA
zq{yK-qI8C8u1rv#QYljnP*YLIs*h{bYQ}1rYD?+hbw29$?XA(v(T_54GBn<&X{2l{
zwqMYM)s)?gVs2sKXPI-L$!f^@iw(D}sa=wNlf$GF+1c17#r2*W%H7hV$aB(L&?nLN
zxj$DxWZ=ug3P*B-e}_7U^+%{jmPeCfvf_}VN8{HL6Ow4j$;a`jdFkYgl9QBEkFxAf
z&!0)j70r8C;8sX0DlFMsx>S~UL9TqE;!LI1Wm<K4t;bbT-Ec!jqd^mLqq`-&)w+Gx
zt%Z)ZJ1KXqy2b9(AIv^#>C1h5^ojYP#xVag`smjeZ^uR^?oHKCSIrd77Q8E%%lUBP
z<LRXnpR!i-zLc&tthapc|2h8a-6m?AnN9})3ur*_h%eHO;zPxtUZCaB+2|#V5vB%<
z#rk0TapJhsxHY^3{vLxkLoUN6V<6)clQB~VGljW^g^%SdD=TXzftgUiMr1oj6d^XT
zYq5`!{5TMf60#b3iZh0b#C40?k$a2h3a>5i&aNgtFMbk#&+b?O8G-kL=Y<@Fd4y*~
z%0!*TB*a$5+ayvX^`(eXb9=5yr^z_WN>b32S-EEUJcUrj14?pK0(DJ!Mx|S|QLRk<
zghqtsAuSVaJsmY&%3cvY9(^7ICPSuu%tk!M-1~)0_)KNYEX_kLaxFU#ytRgdGBysj
zXYC%_(;elU!kz0~mJi9hCAvTJ<n;3NZuRByJM7;RC>E4+crn;9q%TY^{7NJ#Dk}yX
zn-;edpO}bA%1CBUsZ5ngYtPU+@%+@0EaddrGnAaMyto3+!loj#;y<PJW&Rgr%4roN
zm337`HQ`rm>kJx{8@ZZ@H<nx8w@$UU-LC9B-Q{sl{XV&8=HZ>*n11R2JZTwpAI3kc
z9F==M^wNE7YQl2z{wvD#x!1HeduKD>4!<YNnaxLjC|T(IIJvmAw7$IjX?A6F^}*++
zFGXJ?*7kkFe|x%~MKh)S`d<CR^2h4W><!6{_Fwycz5H$Ud+?9RpSzo)n^~J*w;Z<W
zwl=o+Z<lN@?5OV4(Ra~v=yZU;ehB~om<+>$!y<(&4EOyPbNBy6NN~*m^gsZB#V^#}
z763>9zz>EH2Eh;pkst&XU<msF{(3b402~pZ+#3L($Bq7f>PGt=jRpWP3=5Bs3<?O0
z7Saz75B3u>3=0X5iS~<>6*3L=k&_itQczF<0QeU?a{Ut552?Wb00A^fL_t(Ijir*Y
z&B8Dcg+CBIL$Cl#WC98{fSHnxE*nr}fJm%>LV-j<gJdMYiF`R4>_4%Q{(@Kf-g|fN
zeDEVC{}IZv)cDO9!*;u!0L=Vjp67w+iyrIsdSp-(1x?fFVzHRaym+(O0MK<EfW{`z
z=M!r!*4lA|Sp0guxZm&W_j~5^d6?jKyJ4-RZCk3U3bm<s8j2r}2LP+pDs=K<Kf!Xj
z#2E9pgQ3`y`o6~)Ls1m*9s`2GP%I(<hzMDh1@dP<;~n@V#)UY)a}MVmB7$>{s;bg)
zVxzJwRaNzRz3Sz1(ewGNr_)J~$D`(Xu1(YEG_^@F>?|T7A`E`PcmEd0iw}oGVvrot
z2ctvsoxNFN0MNEAUDx59OCk(KB0}HysljfyON8HUpswqL_Y>Y%<OUdK%;53>0000<
KMNUMnLSTY_%g(I;

diff --git a/library/simplepie/demo/for_the_demo/favicons/magnolia.png b/library/simplepie/demo/for_the_demo/favicons/magnolia.png
deleted file mode 100644
index da519f5ab92d84c56d4e55f0c74f17d828391960..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4574
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
IM6N<$f?ZhTO8@`>

diff --git a/library/simplepie/demo/for_the_demo/favicons/myweb2.png b/library/simplepie/demo/for_the_demo/favicons/myweb2.png
deleted file mode 100644
index 2a12968d5ea10ae7b39e47855deb2040e35a5881..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4010
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
QS^xk507*qoM6N<$g7XK!pa1{>

diff --git a/library/simplepie/demo/for_the_demo/favicons/newsvine.png b/library/simplepie/demo/for_the_demo/favicons/newsvine.png
deleted file mode 100644
index 5cdbb31c69adf4c0a52bcb93193c7a1f9566c76c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3804
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
S>-qWs0000<MNUMnLSTYECtpnf

diff --git a/library/simplepie/demo/for_the_demo/favicons/reddit.png b/library/simplepie/demo/for_the_demo/favicons/reddit.png
deleted file mode 100644
index 65c38867cd74b61c1720017d13c95264b75d3500..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4239
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

diff --git a/library/simplepie/demo/for_the_demo/favicons/segnalo.png b/library/simplepie/demo/for_the_demo/favicons/segnalo.png
deleted file mode 100644
index 748149b3713b90ee4c3e8e8e85f73d743d0eec38..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4116
zcmV+v5bN)WP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV000gvX+uL$Nkc;*
zP;zf(X>4Tx0C=30S9dto58wWL&oqzYI96n@aI9mmjL3}ak-f{F8Ie(u%#4&IqmV=>
zQc@v>sH`Lv2~o+ZRK|J!=y~7YAMf>C&-LDa-JkoqKJ%Z?bpx>Rc!h@tqW~ZzG&<5|
zzk!gGvx^XZ5^%r?XdnUA%O@&a-`d&&{v&=)00IE;lHwH}9_;qs17BC{+MnT6iqfks
z)%eeO002OUbaHk9Kx6@c9PpRx0RY+iFSi2#a$IzHGyoC^0A!y)FJAy82>@gx?Q9GI
zkU9V$1pMV406_5m%Lf2}5bF~V4S-Am;7FmqL7@QnRREl>uV0i806`W2e0`&QLI4Q)
z03a6<66Om)=m7vJpYX_N0KyUgP@J4yg#M0vhzUS-4**X7A1zt}ptTY}(D@%t;wk`_
z4Z!t_|7bKDKmY*Y8j13!Dggih!eRh`ou$)h5&-x@fb9Z0eY1*A->wEg&j9oU`@}@X
z{`+1CG7RwF;=eop8)yUo1pr)N0T&T0Vu@6t(5Oh%Dmog2$24GFaNM}J_zs5ij5$ns
z%;#B}Sw{&QL>2Zp(ja*^X9(9Qk3MfBA0K~_0A4U(m?TmxMij4-q)4?%E6EH{tmI}C
z4l6EFgOpcPW7W|b37RzRNS*I{<Mfsd!VEtcIT{a|$e31`<1FGVC#-a>Yi$^8{p=n%
zNI1qjO}ePMRvg-JckpQQV)gd+Y4Jn+odd21(hln#$qAkcl@1FFzZtO^r4bz&b369y
zQHgl}gtElJq^)F1iu>{0)Rwe28R!$@CrwX<W)^4NJw2KIEr*ax$urOQDo8Ipf3~IQ
zZt+;j(mA9ITlVez*oAxL=P#yK9KPgGsd1UF3aMJI9<AxFy>un(YG9ptJ+*=V8v5FD
z<CE*nO~p6jn_XM9Z}Q*VZk=m;*j{lf{kCU^RwqyA?>iG+&3Cizxp%AHC*J?i)BYgq
zq1z*+UR>{Z-}U~a$L0gP1M^RAJxv)j8{!_CAFh8EGom|+jP^WFe4+ee<z>y7*EsL^
zz(m%h-sJjJ{VUID&gsXmkIg8~%)Kd{-9P)|?bUbo?~(V{=RD`x=i5K{EpRT}`{=hw
zSnOExS!P*o{^Y!ZU8!HST%~<3|6=fE;cM=i+S=Q1r`F}yU(-%~SN*>Dqw=TQhTz8X
zuioDsf1YiL?y%D70Kg7fkO(7)G;#`ANBN=V(P0=orWR|BW5V^}^B8;?^_Ya2xmXxk
zQ3NuZAW@OsffUbii9E=;!>z&-#oNA%&TqN9Qea(3Q}~?7Z?Oa7Es`u!NB2y~P-P1!
zG<gSwE+t{=DdkV9dTKT5+nSzQZ8|tz$Guneei@h;=I@&~mfRm_(rd<MZf8+uxnLz>
z9dYokEt{RKeYL}yla_O;OYb2DH#_$VkJnxT-d;YnzH9#S0Y?IF2CW<s4Gst?3w;*O
z6rmd#8dVWJ5<`!ZJ$f)cHK8i8FKH>6B}M7DQ))!o>Gax+hbP{gT+d|95<9J&t$W5g
z$2~VLFF8M~z@yOatU(dASgJ&zlvqkX_o-~+eE)^6@|ugK6(=r5R=Qr+uad6jszKMR
z)DB&_d9|i4v;J^{)isqyp2k1d-!(nBQQ4f?5_Hp~RjQ4#ZMA*)*45kD9f6%jcSO4|
zU5j^z?p^6lyYJOw_(1f*&cmrk?Y+f)@%=83)dx5RXisLI-Wtps3LCb5CO5(|@^y6J
zdHsvbmqBBu<5Ck06U&nWQ#G$rr#)Zm&hXD{znPisd|Ui3;=R?J{5;G2hYwE{sy`lI
z^jOkf=3b_K8d<r%dggP`7vryDU+HVp-)^s$(4xLu|B(O5`t#Gq<6oD5C;xHXRNW$P
zecvA1X{3A8=>Wh4Vqgx(pbJ4G#z-NufYL|RpxMxA=q*etmK9r$qvFQ#2@K*4lZ<&x
zmdxzTGc5J22?T341tK%?C;K$%0Y@YG0%tB)I(IxzC~v?nPd*QR*WC^R2L%rb*$CT-
z*o#_<8Ht-q7)k0$Y3@;#7LgH<Wu@RL8*+>CvkKFSFO-I;1IqVR+ElNpRjZe2<Y}JK
zI<1|dld7A%H$g8-Kght#(0iY!k&Us{esdFJQ!6twb3+R=OM?U2RtDBu2i0tJZ8h!G
z>{T389MzmOoT)BquGB*cZVK*79%`OCUYg!&KI*<&etZ431B?QVgNzUB9MKEb4KWEd
z3ZsS#MGzylBA243qlaSd#9ocdJ{lYEnP8KsktBYMc<fj5Y|4Y<)v38@ap{LL)KBoA
z#GG6_)t_0Lm2)~Md;b}!99+&q?&G|g{L}*XLhZABXMYuq6}Oh;lm?vJS0-{EeSZEz
zclo)CF%|ZgsFj4ukCz`-RaU3h_|@uN;l1+hYF}MRePDxf!_KuQjk(vIo5Y*G+-Pr3
zYB9M<x;fq2)E3vScZ+aq{&s7}iB69@nq8b-w7Zk{TDvRn=k~-t2zcoE$hFs_FStME
zaoRw|lisJFhxmtWpOue%eQx^V+L*+6!=&ca{B-L~&TP!Pw7J0rg~f?aw?8j^tNkgu
zxk{%4{QZ3Z060~EQgr~ABLMd50NF1ABxwMgo&eUY0CpOHIwS=sekni>uKe%+5CcD`
zg%5}@;)awVFHr=PF)9Vsf%=A)M*E^KpvN#Q7(>i4Oef|$mV))iR$*sxd^ks3F>V~s
zj<?3=<3|}d7#tZ&8KxNp7=0KU7{4=VFdb(aWaeb{U~XXk&0@xKo@Iqqhc%b=EkTKp
zP58j3!&bt!Ml>Z>vt!tO*t<!Bq;%3EhZ#pJS(to^Oyl(Ae9EQG)x<5pozH{eN#LRJ
zhVp*g<+1BMpF7_SzbpU5Zs*-^1Uv-h1%m|Fg^md`3tteC7P&2IEc!+)R-9S9T0&Q1
zLNZi}DAl^hX3r1lOETs%YqA$9R&pTMDDR`dr!cNqpkzs9rao0JR&i1lR{g5ht)8Rd
zrb*G<)|%43rE^v{V($Sxd3|2}p9b#@2lw?EH5=FNFEq(Cy=?Zv{Ff#5fR|Oib=Scy
zTQ$2-`)dxfPU6l!E^V%xZhPG`JzjdrcqjRc`bqhp3|I_0aJV6u9Fh^b6z&=EI?6n{
zFV;A2DBdGsE-5aVoYI_Xk@hj8=%m7_xvau$yBtjJV190)b&+K8=hCNTcP`w%*mLR0
z<=*PG+T}W~28BkOru61(Hy7G@Zu@rDb?tP!_FQ<x)93$q=Bd-r=!ntt*)h9`^;bDF
z{Idh^-RCzyRxWF-41aN4dqfld;k^<0+xXABE!}O^9T7T_P6q%v2!gBd0TD$!kxFD1
zwHxJ*Do4FR3!>f7m(X(<5sWXU4zr3?#KvOp;!rqKTt03RFNhDoH{&-M%ovIp-Z9ED
z9%CG2+Qk&Y)Wu9-_F?X1A+iLp+-K!sjbI%jND|Ts@7VO%YKd545OI{9%3e-lAjOd8
zIczx|kyXfboI;#MTufY<+`yf{y}=X1v%#Cl`)5}&AD%CppTu9Xn{Ri$fTBQ`;C{hz
zA%CIY!g(U1BJH9kq6=cF;(X#A5)Kk;lDSe;saJdArG=%R$t1`M$-bbRlv9!WC|{xA
zq{yK-qI8C8u1rv#QYljnP*YLIs*h{bYQ}1rYD?+hbw29$?XA(v(T_54GBn<&X{2l{
zwqMYM)s)?gVs2sKXPI-L$!f^@iw(D}sa=wNlf$GF+1c17#r2*W%H7hV$aB(L&?nLN
zxj$DxWZ=ug3P*B-e}_7U^+%{jmPeCfvf_}VN8{HL6Ow4j$;a`jdFkYgl9QBEkFxAf
z&!0)j70r8C;8sX0DlFMsx>S~UL9TqE;!LI1Wm<K4t;bbT-Ec!jqd^mLqq`-&)w+Gx
zt%Z)ZJ1KXqy2b9(AIv^#>C1h5^ojYP#xVag`smjeZ^uR^?oHKCSIrd77Q8E%%lUBP
z<LRXnpR!i-zLc&tthapc|2h8a-6m?AnN9})3ur*_h%eHO;zPxtUZCaB+2|#V5vB%<
z#rk0TapJhsxHY^3{vLxkLoUN6V<6)clQB~VGljW^g^%SdD=TXzftgUiMr1oj6d^XT
zYq5`!{5TMf60#b3iZh0b#C40?k$a2h3a>5i&aNgtFMbk#&+b?O8G-kL=Y<@Fd4y*~
z%0!*TB*a$5+ayvX^`(eXb9=5yr^z_WN>b32S-EEUJcUrj14?pK0(DJ!Mx|S|QLRk<
zghqtsAuSVaJsmY&%3cvY9(^7ICPSuu%tk!M-1~)0_)KNYEX_kLaxFU#ytRgdGBysj
zXYC%_(;elU!kz0~mJi9hCAvTJ<n;3NZuRByJM7;RC>E4+crn;9q%TY^{7NJ#Dk}yX
zn-;edpO}bA%1CBUsZ5ngYtPU+@%+@0EaddrGnAaMyto3+!loj#;y<PJW&Rgr%4roN
zm337`HQ`rm>kJx{8@ZZ@H<nx8w@$UU-LC9B-Q{sl{XV&8=HZ>*n11R2JZTwpAI3kc
z9F==M^wNE7YQl2z{wvD#x!1HeduKD>4!<YNnaxLjC|T(IIJvmAw7$IjX?A6F^}*++
zFGXJ?*7kkFe|x%~MKh)S`d<CR^2h4W><!6{_Fwycz5H$Ud+?9RpSzo)n^~J*w;Z<W
zwl=o+Z<lN@?5OV4(Ra~v=yZU;ehB~om<+>$!y<(&4EOyPbNBy6NN~*m^gsZB#V^#}
z763>9zz>EH2Eh;pkst&XU<msF{(3b402~pZ+#3L($Bq7f>PGt=jRpWP3=5Bs3<?O0
z7Saz75B3u>3=0X5iS~<>6*3L=k&_itQczF<0QeU?a{Ut552?Wb00E>)L_t(IjeU~6
zZqz^&g}-ahuD!bwZ-B&8&;$?>;-^W2#0yZQ<sqO+n+Kq#M?w%lL4as!kZ3@3NOX9!
z9*?hQd?}LbCOFRNM(66xckT>~=>Dg>Hs+m`j2U-6Zd;KTyxMxbo_X;3o+V3UWFYY7
z##_n80^Z*`ls2{J0<~9?B|7VfeFVT=hWDiV!__Z4_B%BsODD)eE;$D`-^rkY|2{Fg
z4pG2^tbjVFe3VA3t_}Z73}=vl2IL4h0$GAofL@{4T@HdAfdA>t77<E7a~9V&H-?wa
z$Rp_TLV~RMHa8?f4ordR?A$=P6Xlds_lm*OW@rx`NB~wK^$P!EV$Ik2X1E6o=yX8f
z2!>=}2BIY-kUBuq5e_nADNrSdKpg%pCmt+;D9o;hP4^FTBPbFg=&?^X+=0UjqF^nA
z!<m)ajR2Il{W?td3!_ye<{YDJBmm(B#^m(0pnO=5zWe_YfcE*+Foo=7S-k^wNSi}Q
z;CrS|^}^5$pm?kzzJLm-K>kLg3Q*Nh1*GmTCpas8HZ>xk5lIf1G1;p|EByo0V!yhw
Skr1f>0000<MNUMnLSTX@jQ1u0

diff --git a/library/simplepie/demo/for_the_demo/favicons/simpy.png b/library/simplepie/demo/for_the_demo/favicons/simpy.png
deleted file mode 100644
index 30b23c1a558369dd1feeaad81c2dca58b2af6bcf..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4256
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
CDMdU0

diff --git a/library/simplepie/demo/for_the_demo/favicons/spurl.png b/library/simplepie/demo/for_the_demo/favicons/spurl.png
deleted file mode 100644
index f5be3963dc0f2ca78e875cfccc5d021af76ba8d4..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3970
zcmV-|4}I{7P)<h;3K|Lk000e1NJLTq000mG000mO0ssI2kdbIM000gvX+uL$Nkc;*
zP;zf(X>4Tx0C=30S9dto58wWL&oqzYI96n@aI9mmjL3}ak-f{F8Ie(u%#4&IqmV=>
zQc@v>sH`Lv2~o+ZRK|J!=y~7YAMf>C&-LDa-JkoqKJ%Z?bpx>Rc!h@tqW~ZzG&<5|
zzk!gGvx^XZ5^%r?XdnUA%O@&a-`d&&{v&=)00IE;lHwH}9_;qs17BC{+MnT6iqfks
z)%eeO002OUbaHk9Kx6@c9PpRx0RY+iFSi2#a$IzHGyoC^0A!y)FJAy82>@gx?Q9GI
zkU9V$1pMV406_5m%Lf2}5bF~V4S-Am;7FmqL7@QnRREl>uV0i806`W2e0`&QLI4Q)
z03a6<66Om)=m7vJpYX_N0KyUgP@J4yg#M0vhzUS-4**X7A1zt}ptTY}(D@%t;wk`_
z4Z!t_|7bKDKmY*Y8j13!Dggih!eRh`ou$)h5&-x@fb9Z0eY1*A->wEg&j9oU`@}@X
z{`+1CG7RwF;=eop8)yUo1pr)N0T&T0Vu@6t(5Oh%Dmog2$24GFaNM}J_zs5ij5$ns
z%;#B}Sw{&QL>2Zp(ja*^X9(9Qk3MfBA0K~_0A4U(m?TmxMij4-q)4?%E6EH{tmI}C
z4l6EFgOpcPW7W|b37RzRNS*I{<Mfsd!VEtcIT{a|$e31`<1FGVC#-a>Yi$^8{p=n%
zNI1qjO}ePMRvg-JckpQQV)gd+Y4Jn+odd21(hln#$qAkcl@1FFzZtO^r4bz&b369y
zQHgl}gtElJq^)F1iu>{0)Rwe28R!$@CrwX<W)^4NJw2KIEr*ax$urOQDo8Ipf3~IQ
zZt+;j(mA9ITlVez*oAxL=P#yK9KPgGsd1UF3aMJI9<AxFy>un(YG9ptJ+*=V8v5FD
z<CE*nO~p6jn_XM9Z}Q*VZk=m;*j{lf{kCU^RwqyA?>iG+&3Cizxp%AHC*J?i)BYgq
zq1z*+UR>{Z-}U~a$L0gP1M^RAJxv)j8{!_CAFh8EGom|+jP^WFe4+ee<z>y7*EsL^
zz(m%h-sJjJ{VUID&gsXmkIg8~%)Kd{-9P)|?bUbo?~(V{=RD`x=i5K{EpRT}`{=hw
zSnOExS!P*o{^Y!ZU8!HST%~<3|6=fE;cM=i+S=Q1r`F}yU(-%~SN*>Dqw=TQhTz8X
zuioDsf1YiL?y%D70Kg7fkO(7)G;#`ANBN=V(P0=orWR|BW5V^}^B8;?^_Ya2xmXxk
zQ3NuZAW@OsffUbii9E=;!>z&-#oNA%&TqN9Qea(3Q}~?7Z?Oa7Es`u!NB2y~P-P1!
zG<gSwE+t{=DdkV9dTKT5+nSzQZ8|tz$Guneei@h;=I@&~mfRm_(rd<MZf8+uxnLz>
z9dYokEt{RKeYL}yla_O;OYb2DH#_$VkJnxT-d;YnzH9#S0Y?IF2CW<s4Gst?3w;*O
z6rmd#8dVWJ5<`!ZJ$f)cHK8i8FKH>6B}M7DQ))!o>Gax+hbP{gT+d|95<9J&t$W5g
z$2~VLFF8M~z@yOatU(dASgJ&zlvqkX_o-~+eE)^6@|ugK6(=r5R=Qr+uad6jszKMR
z)DB&_d9|i4v;J^{)isqyp2k1d-!(nBQQ4f?5_Hp~RjQ4#ZMA*)*45kD9f6%jcSO4|
zU5j^z?p^6lyYJOw_(1f*&cmrk?Y+f)@%=83)dx5RXisLI-Wtps3LCb5CO5(|@^y6J
zdHsvbmqBBu<5Ck06U&nWQ#G$rr#)Zm&hXD{znPisd|Ui3;=R?J{5;G2hYwE{sy`lI
z^jOkf=3b_K8d<r%dggP`7vryDU+HVp-)^s$(4xLu|B(O5`t#Gq<6oD5C;xHXRNW$P
zecvA1X{3A8=>Wh4Vqgx(pbJ4G#z-NufYL|RpxMxA=q*etmK9r$qvFQ#2@K*4lZ<&x
zmdxzTGc5J22?T341tK%?C;K$%0Y@YG0%tB)I(IxzC~v?nPd*QR*WC^R2L%rb*$CT-
z*o#_<8Ht-q7)k0$Y3@;#7LgH<Wu@RL8*+>CvkKFSFO-I;1IqVR+ElNpRjZe2<Y}JK
zI<1|dld7A%H$g8-Kght#(0iY!k&Us{esdFJQ!6twb3+R=OM?U2RtDBu2i0tJZ8h!G
z>{T389MzmOoT)BquGB*cZVK*79%`OCUYg!&KI*<&etZ431B?QVgNzUB9MKEb4KWEd
z3ZsS#MGzylBA243qlaSd#9ocdJ{lYEnP8KsktBYMc<fj5Y|4Y<)v38@ap{LL)KBoA
z#GG6_)t_0Lm2)~Md;b}!99+&q?&G|g{L}*XLhZABXMYuq6}Oh;lm?vJS0-{EeSZEz
zclo)CF%|ZgsFj4ukCz`-RaU3h_|@uN;l1+hYF}MRePDxf!_KuQjk(vIo5Y*G+-Pr3
zYB9M<x;fq2)E3vScZ+aq{&s7}iB69@nq8b-w7Zk{TDvRn=k~-t2zcoE$hFs_FStME
zaoRw|lisJFhxmtWpOue%eQx^V+L*+6!=&ca{B-L~&TP!Pw7J0rg~f?aw?8j^tNkgu
zxk{%4{QZ3Z060~EQgr~ABLMd50NF1ABxwMgo&eUY0CpOHIwS=sekni>uKe%+5CcD`
zg%5}@;)awVFHr=PF)9Vsf%=A)M*E^KpvN#Q7(>i4Oef|$mV))iR$*sxd^ks3F>V~s
zj<?3=<3|}d7#tZ&8KxNp7=0KU7{4=VFdb(aWaeb{U~XXk&0@xKo@Iqqhc%b=EkTKp
zP58j3!&bt!Ml>Z>vt!tO*t<!Bq;%3EhZ#pJS(to^Oyl(Ae9EQG)x<5pozH{eN#LRJ
zhVp*g<+1BMpF7_SzbpU5Zs*-^1Uv-h1%m|Fg^md`3tteC7P&2IEc!+)R-9S9T0&Q1
zLNZi}DAl^hX3r1lOETs%YqA$9R&pTMDDR`dr!cNqpkzs9rao0JR&i1lR{g5ht)8Rd
zrb*G<)|%43rE^v{V($Sxd3|2}p9b#@2lw?EH5=FNFEq(Cy=?Zv{Ff#5fR|Oib=Scy
zTQ$2-`)dxfPU6l!E^V%xZhPG`JzjdrcqjRc`bqhp3|I_0aJV6u9Fh^b6z&=EI?6n{
zFV;A2DBdGsE-5aVoYI_Xk@hj8=%m7_xvau$yBtjJV190)b&+K8=hCNTcP`w%*mLR0
z<=*PG+T}W~28BkOru61(Hy7G@Zu@rDb?tP!_FQ<x)93$q=Bd-r=!ntt*)h9`^;bDF
z{Idh^-RCzyRxWF-41aN4dqfld;k^<0+xXABE!}O^9T7T_P6q%v2!gBd0TD$!kxFD1
zwHxJ*Do4FR3!>f7m(X(<5sWXU4zr3?#KvOp;!rqKTt03RFNhDoH{&-M%ovIp-Z9ED
z9%CG2+Qk&Y)Wu9-_F?X1A+iLp+-K!sjbI%jND|Ts@7VO%YKd545OI{9%3e-lAjOd8
zIczx|kyXfboI;#MTufY<+`yf{y}=X1v%#Cl`)5}&AD%CppTu9Xn{Ri$fTBQ`;C{hz
zA%CIY!g(U1BJH9kq6=cF;(X#A5)Kk;lDSe;saJdArG=%R$t1`M$-bbRlv9!WC|{xA
zq{yK-qI8C8u1rv#QYljnP*YLIs*h{bYQ}1rYD?+hbw29$?XA(v(T_54GBn<&X{2l{
zwqMYM)s)?gVs2sKXPI-L$!f^@iw(D}sa=wNlf$GF+1c17#r2*W%H7hV$aB(L&?nLN
zxj$DxWZ=ug3P*B-e}_7U^+%{jmPeCfvf_}VN8{HL6Ow4j$;a`jdFkYgl9QBEkFxAf
z&!0)j70r8C;8sX0DlFMsx>S~UL9TqE;!LI1Wm<K4t;bbT-Ec!jqd^mLqq`-&)w+Gx
zt%Z)ZJ1KXqy2b9(AIv^#>C1h5^ojYP#xVag`smjeZ^uR^?oHKCSIrd77Q8E%%lUBP
z<LRXnpR!i-zLc&tthapc|2h8a-6m?AnN9})3ur*_h%eHO;zPxtUZCaB+2|#V5vB%<
z#rk0TapJhsxHY^3{vLxkLoUN6V<6)clQB~VGljW^g^%SdD=TXzftgUiMr1oj6d^XT
zYq5`!{5TMf60#b3iZh0b#C40?k$a2h3a>5i&aNgtFMbk#&+b?O8G-kL=Y<@Fd4y*~
z%0!*TB*a$5+ayvX^`(eXb9=5yr^z_WN>b32S-EEUJcUrj14?pK0(DJ!Mx|S|QLRk<
zghqtsAuSVaJsmY&%3cvY9(^7ICPSuu%tk!M-1~)0_)KNYEX_kLaxFU#ytRgdGBysj
zXYC%_(;elU!kz0~mJi9hCAvTJ<n;3NZuRByJM7;RC>E4+crn;9q%TY^{7NJ#Dk}yX
zn-;edpO}bA%1CBUsZ5ngYtPU+@%+@0EaddrGnAaMyto3+!loj#;y<PJW&Rgr%4roN
zm337`HQ`rm>kJx{8@ZZ@H<nx8w@$UU-LC9B-Q{sl{XV&8=HZ>*n11R2JZTwpAI3kc
z9F==M^wNE7YQl2z{wvD#x!1HeduKD>4!<YNnaxLjC|T(IIJvmAw7$IjX?A6F^}*++
zFGXJ?*7kkFe|x%~MKh)S`d<CR^2h4W><!6{_Fwycz5H$Ud+?9RpSzo)n^~J*w;Z<W
zwl=o+Z<lN@?5OV4(Ra~v=yZU;ehB~om<+>$!y<(&4EOyPbNBy6NN~*m^gsZB#V^#}
z763>9zz>EH2Eh;pkst&XU<msF{(3b402~pZ+#3L($Bq7f>PGt=jRpWP3=5Bs3<?O0
z7Saz75B3u>3=0X5iS~<>6*3L=k&_itQczF<0QeU?a{Ut552?Wb009z7L_t(2k%f{W
zQYAqUM2jD7G2DPVtY5_uIKz4bfkm+qYp@&vk0N3fmLs5X2n=f8OGNbyU;Ka;6C<*#
zUuM?P-E(U1BvJdLB2g9zpfL8;CS{UHkR(wM1^ajG&9*E;jB$z)Pz{PWHj+QTc2!li
zt3&7d;T05jtxi0s+fExm#`^rUe*5&{v^NzBG#Bc~%w@i?+EXElbW#dIhUoz3g^S<E
z2azuCU(n#N=l$eilMU@|`1k)^#l;D}pe+79KdmZgE{B@t&f1ObQ&rhIbzZ<lg{!lZ
z?~v93JDg>H@1c`Sa&+_fCL8uwj0;<^y(%QpjHXAMY}>MAGOW9sBvm!stC4M~XE#o1
c+3KqL1fvc2iMm!3F#rGn07*qoM6N<$f@o#5;s5{u

diff --git a/library/simplepie/demo/for_the_demo/favicons/technorati.png b/library/simplepie/demo/for_the_demo/favicons/technorati.png
deleted file mode 100644
index 0f19e824e614e7d56638174c33690d77606df22c..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 4087
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

diff --git a/library/simplepie/demo/for_the_demo/favicons/wists.png b/library/simplepie/demo/for_the_demo/favicons/wists.png
deleted file mode 100644
index 2e2d294d1ec6198f50c3a37253cc7252a2d4b3a4..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3974
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

diff --git a/library/simplepie/demo/for_the_demo/feed.png b/library/simplepie/demo/for_the_demo/feed.png
deleted file mode 100644
index e23c50c85b2fc311da507ea1a36b05c859477153..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 715
zcmV;+0yO=JP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt007q5
z)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!T}ebiRCwBq
zlg(=rK^VrL*-cstQMY1@M6@fdv=u*E$e|!;3tqfvi+B(b+rOaZFQ_7(wKs1q^dN}P
z6a;V0NrX~tkXQ>+60z1wux?1B>3(E=W@nR>oP6QkosV~Z^E|V&0*rblG7hKyj7<|R
zpB~c<)A3vFRu=s_()x^_5#I9fB+Bb^NQ^=o902q=7S!4nA9z>D|LDWt0tlH9&YLs8
z#jznnPdxz&cY(cirJ#}Zwze*Sn1Hh);QbKANWE4yq65Rg<~`uZQ=r>ml?9ZRfL|HF
zw%TA+@fV0t?EaQ!YM$2tffqnI4@9{*KFS;i&eO_B0Z2Y11S<E#-18x#bm(aa0KqN}
zCyHs{^AxZ>&%ULAgFM@jEGG>GaYC5e0Jxn25xX4php5d2R%e0NXMy~41aX|Iu4V)2
zsD%J7aa;m+-|uio;=Xh6!~@{m3~+M|xV8x72wI*}kZ!^+K2jEJHDtRwG@BGuLumyb
zTq&n!lic+VK|k4Fd921#gm;;$HUMZ6paXxx3$jMZ3;ZIl#<&yDpp(9@^Dy6W=Soqn
zx-_k78w#Y4CV-a-x3lW-UXH1%IHmVb0v~2ozjwR|2+qKltp?x<CH4?9LI2y7{%KxS
z_T2)$WK{d8*#yY7S|Fv&moJoG89O;uw6Uc6(n>kBAmhRf%I^u9V)cH!U>vs1-eg7H
z^~7Zbka36$PtrooQe!67#W>#Iht0QNVdZm037{z~8ZjHE6IFC{@xDgT%IJZVch1r9
xZQ~TIqV&z5Nj^h}`kntTq@Q$Zp_KV2zyNZ!0q^m>#MuA<002ovPDHLkV1i)rMIQhF

diff --git a/library/simplepie/demo/for_the_demo/logo_simplepie_demo.png b/library/simplepie/demo/for_the_demo/logo_simplepie_demo.png
deleted file mode 100644
index eda2d868b54949e2f4f7c12d21f0ae1f9052f0c8..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 3047
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

diff --git a/library/simplepie/demo/for_the_demo/lucida-grande-bold.swf b/library/simplepie/demo/for_the_demo/lucida-grande-bold.swf
deleted file mode 100644
index 0a41e15eb87253083c1233fbd9e4aff27d438082..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 21159
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
K$o~KoWRaGA5MBiU

diff --git a/library/simplepie/demo/for_the_demo/mediaplayer.swf b/library/simplepie/demo/for_the_demo/mediaplayer.swf
deleted file mode 100644
index bf78fd919a3587c75fd5b2df7ef463a22636aa62..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 32008
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

diff --git a/library/simplepie/demo/for_the_demo/mediaplayer_readme.htm b/library/simplepie/demo/for_the_demo/mediaplayer_readme.htm
deleted file mode 100644
index 56e12c309e..0000000000
--- a/library/simplepie/demo/for_the_demo/mediaplayer_readme.htm
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<head>
-<meta http-equiv="refresh" content="0;url=http://www.jeroenwijering.com/extras/readme.html">
-</head>
-</html>
\ No newline at end of file
diff --git a/library/simplepie/demo/for_the_demo/mini_podcast.png b/library/simplepie/demo/for_the_demo/mini_podcast.png
deleted file mode 100644
index fd6faf2a318701ec923687afd472e5db89ffd651..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1202
zcmV;j1Wo&iP)<h;3K|Lk000e1NJLTq002Y)000vR1^@s6DVVGM00004b3#c}2nYxW
zd<bNS00009a7bBm000XT000XT0n*)m`~Uy|A9O`nbW?9;ba!ELWdKcKV{&h8Wn^h#
zAVz6&Wp{6KYjYqtwP@0K0000MbVXQnLvm$dbZKvHAXI5>WdJZSFEBGNFg8Pc<_`b>
z1P4h(K~z|U<(5%s8+9DVKbKs3UDGUUdPA;ewlJ|+hry<kiq0)#!o+Pl&66)HB1E6;
zgY>}%3F6bRK24+ral#N8EuCdZMQ9>}wTxzKK)a>7uEi{AZ5mtCw9DG&d`NQ1<ucjR
zY~vq}knivN`~H8w@BQxXFQ}@jUSGY%$I&mjem_EdBSGm>EOJ$1N6qbgWIx06^0Qd2
zR!k-n0758rQ$2d~J?g~TZBgi>#Fp1rIG6o^*PnichK2@ACKKk^+oC^_T_&DMfQoi0
z7P;!NO(9EU@is4{Tajg%nwlEK(Aq8H_siU?k%_PWKd^|rKzK4tb8|EG_4SDVmT+W`
zn<IPN)SK(Lu<!%%t;7R`cQO`@MoFbo0GQZ<!ljt=30rXfDL<E<=_R|R^6AW1oNx6L
zboCo}m2!6)mdRw;+}s2}WGnBKRCKSa=_F^A6TI{5Cwv_n2H=g!54rQwFp5~gWvMza
z$Qz<aGV!&NU^e$NG#{W~SWAt<#rdD`HNA=d_kNA49-q(&dan71r00mQC3G?GjUEOU
zMl13QdzZ#M*L(z%p$FoMBoljiM5pDw(Zj%VXAMo3?xC5nW;6ppR77L&fOS9LL@yIO
z*oXhOekNC@`M&*gc8gZRe^29&^lQQZo^c<+rF`+PP2d^#5%Y{_xFX5Kj^+Lr_>t8)
z;+cfT4|Mk74fQZMKdRFSboLqay`dfk+-G&TBIUjuLaal_E9gCp831B=P^pzUH*=B6
z!{1`J)HCG%jNaQ9*ezNCm|ctKp1<0naG<lVcsH*42qtnxlFfhO3VY-yuTivDoXDlj
ziZ+qLa0g1QY|t<8gy9a<Qzesg)n{n5RIkumrG9mW7!uOCgvpg@4$JKTJXyC-<6OEM
z%r%)V3VW{P@Ay6aW{qaMj#t=gX<c7vquE}J=W+G)1fDBCO+T0jq14L6ULDbR!cfk%
z_`QV2FYwCsN_(r+ufdS=;A}dk84~<6L`$6lz>o1UW8<RTAl!8MII$DOXWa9%k4S0`
zfWV>R9rup)FnD(q;g1ef?}UyYTr8WkbaB$u(`E0XJYUyGmf|!&gc$$=-?>#~m+_6;
zy1Rw<_rC>z|CfH2H&RsMRRh*Neu%EFE?h1bqSxVJU@>4wi2OB6_e8H=WVM3u4#)P+
zS&$?NQ4|3%z3V*5t_@4^uu_vxC_TVbDJHIidq%<ObYipFa)!LPubnR*@1}L-v29c6
zqrmpwv2bkc2@Wa;aJgJK91Z}4Y&NSVlS!tgrU-|_M59qMnGDswBuT>QbmDTkXlrZ3
z;cy@b0)m=bq|<4V$t0;%N;}tA^Abf7o6Uy9;lOIOA_xLN&XE7Owr#ck0iew8UF$dq
Q>i_@%07*qoM6N<$f^gwQSO5S3

diff --git a/library/simplepie/demo/for_the_demo/place_audio.png b/library/simplepie/demo/for_the_demo/place_audio.png
deleted file mode 100644
index 560ea0039310545ed1c4dcf7a1004abcd2b780af..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 851
zcmV-Z1FZasP)<h;3K|Lk000e1NJLTq004pj000mO0ssI2RnIWu00003b3#c}2nYz<
z;ZNWI000SaNLh0L02}=P02}=Qm(d3{0000KbVXQnLvm$dbZKvHAXI5>WdJlUH7_tW
zlXA8~0000VbVXQnQ*UN;cVTj608L?Ia&K*AWNBd_Mrm?ocW-iQb09diXwrB900OH?
zL_t(oh3%KWPZMDn$3J(}f=ErHU?>n%8C+ZlR0kcn$-zjh0|O3XOe`yde?b2L`wuXX
zhJ_d%8euf16FM9Ts~z;>k5g1Ea?lD?UWfMDYwzt3VrUcF@AT&TJkR%i-uL_T?y4|9
z%G1wi{dCZL<OCbP2oEaUILF;VE}m|6N9~ID8J>Sp@v0pUT8T@&^mcg|>5)dYfeG!x
z#P-2%!b}=_W|MnsFAVpneERL?<5#2cYtiJl^|-N;xc(%1CDQ!f+6W#+<*b)9?0^Ls
z$ns!hDm<)dujZ29*S8O?@Y-W-Ak^wk{|g*J4h|p-8L(gn(vZbd$oK<54uE}(9n&yP
z0EJ**An`64?$;6@lc>-IAZGM@o${>UkeJqsYd0gNYvsFZoh21j)fgvPSLaw#?##L*
zpe%(Dh}jYYC=2p|_PD8_FAz_yCT_;&U&nyx*xcCp%kyh7?5CHA=tVgZ(UnD8I%`WR
zWrDSDT<U@Qgf(<(+bK<GT&fh!A!c-CIfOvm)0HKge5fmnA#!EcQrdbU1oDs*5*y;F
z)wmX&42%Qu)Cyo&roY=KtuIq|zh%;ng$JPEnNm0^`Kdu-UMZo9Nfl`|GD``|j)WWt
z`vH)($z2fk+OnheDV&ED_Z?%ND?~*^cV{*Ni4BHT_%8By`+~k9VEbS<VI-yXb$zbr
z)tO&+QY3s@vM&2+%B1A_mSbHUpu@_Bop3jwC*2zz<5~cz4S->plYw!+w=Zex;h?s$
z^|t5@)orgf3$@22A8n-Re;Kz1rQBrWn@as?v>$E<m>Q~J{a#-*6xsNZ%0HAkI9a^h
zRJb$5tw5_AX>YtRRW|oq-9_8uLq^5e<E!M4bO%jB%Hou&@MskMCxbnlk-x4xI6>?m
d@n(zJ;9uZFSmaT$)Vu%y002ovPDHLkV1g28gKhu-

diff --git a/library/simplepie/demo/for_the_demo/place_video.png b/library/simplepie/demo/for_the_demo/place_video.png
deleted file mode 100644
index be5ec8219eb952d55d581e40b104d8a74a58af2a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 36713
zcmeEu^;cV6uy$|?q0knW0tJdgaCZvDwMg&+!M#9nN+A?4?oM!b*P_9SOOY0Lm!MzX
z^{x94+@EjOIxATx=bXvxJ@d>nvu7tvT~!_rha3k00N^Qnl+^?PP}Y&hS8P<|8MN;m
zhyT5~Nh@e$V`DG>RYQIUc;Wm}-wgnuc>M1`N&bz+k332A<%8ZA8COfQFE&n&G}<-}
zmH<9ZZV)Gkf8p}J8F>Nqe-~&uLB4pJxmp5L%*<V#94swt%xL6nTrEAFT<zRw1RJcU
zz5)P}00mho?XMY!E1n6Py6&8Je&dKOlm5!maWSC@rk9_wr9YwuqrW2sqH>xaH&C0p
z9ocP=_;%P=?HrsQ_rY&nqa27$(I!Y~38dbU(sN^@f0UL^`%SNsl{HQja22tW@%VJ>
z-XvEmtC=!o9WYm}Q;}7g#WFkEq;^s_@x%oHU<MONW8$KsVV(}J?A(PBNMm~yP#pi=
zxnutCqdnndFadWCQ_c%o3rP*hH_}6ad4cbPf1-RqQNgA~3r9^u-c5+XOB)Pi!m*ad
zCR6{v8~$&U{#T|kA~>%W_|po|2EP?sIqclNHnneTn|z8tEAJh@ihs8wfwZr;x>@jZ
zyE=-o;RZVaRU>DH9Yf};TnY)?6GP9+Y$~B=q=}wehYYp$u3Q;VRH@<fNz|S8|J&k>
z+z^c3NKGZ9m2ELx6&H9=r?7dYl4T1d?Pm1MJ}8nJYS{_h{uC17e-cDt+`9J~5QUvV
z;gaEZWVhyj;`6MbSkgc&t<6F-=px>6t8x`x;`W#@>~#e7vBprzI(nN32LL4jf*Cxr
zmiiB^2bHTGKJ%dx4>c13PyBtLAR3U0+fhyLa8lBzB?zM$Em$hvszfw7z;nK;)BeH|
zfb&YQ3BU$;8Tf--gN{WO)-VI6E$s`9X+QCMu60^NS-aT~?3@-a2=Eze@u%8+_`qs?
zZg1`mIJVsoAX&W`Jn`>?n{0WBzuRc<P5}gprd`B%G1;*<Bq=IX%%<_hpZMQouX?Vn
z-gMr4SBN7#R=rb!L4OJPD{MY61fsN?Js3*hNoRp|uzpcFJaHB^t{OE5JNW*_m=O80
zyQ|xEmsw%Z#77<v00IbH+>bJf>NHd5G)L^WlE-Vyb;^uAS7v2oX6fWrGlYC`ILa~(
zNaV-0va@nuV+my=a`lBGGYw)Y`UjR8>;?x1^NDQIAo@v`i`!%A&kqyN7Dr1BKM=h_
z_|_!}+ALa%EDUvQGBcWrumnwEI5)F<+3eF{a_9MtNEhx~_Pk-Ob*K+h&al@I{uum-
zD!}<Hy>ju~5a2g&bn^)B`qSLpOgMOE%fSjGc=ZYe@T#ig8g}BlBLam&>va&E%&>$K
zO>Vd*EFpngMT_|pWzmXb*UIs#&$C~48{$HK?Q@|)hTCKKFyaSlT87%gq;GD+qfv6Z
z(1fL|>8R-_CV}EG_0#Ei7b3kYJu|b92$8SDLk{qNoOimNHSu%EU1w#0jn=Y_ai?0^
zB*Dy5Hd}nx&~5^*w+)JlCg>G3FGa5g(_1N0<oq~HgoHRXB;zk6>Dc~&T(_KzPtzg>
z_(fTgQO*gCqc{8|ni1P-&(jiqrxJxc=4{V;EJSOUh4V&UTU$`tIQp=>;^`OQieo=~
z(bL6r2>~&`_X?WuTAUE+T=in&h`InS{x_Tua8}*C+PE&^<Yp>7GjtxW<20b_p8yB>
zG63N9%x!)>f?d6Jhyjr8s73kl<L*~jJoVjVXxDXvQ{}*=t?&*TJS~MZ00B4AteQVw
zzK>6rIBVJ4+oM;Y8e}HKnYEpD$q<Y-sL-j0-aI*r&MvkfOeDvhkkZHovt|#Ml?FN<
z$F}%LjKB66tlbT;R<*zGHXPd$P1Akj1+!A+9IVqp9NnLEJv%*LpQvRBx_fZwmd(1h
zME;PEre5i~>3N8a-q2=A%*~};yXgbjH-N{Q-yGG~MTj-Dp?_IT7yW=V1)dO|(8VL3
z)lPdi%dvqd3ct09bgnph{U*mFlZXCnKJq>*qGamMnyJJZ#R^|-{r65CS4vHP&KdeZ
zWwZPLnF^rWeMJ$5R57CeGbuD8BBDZvwRuJ-nYd2Lcf|5MAwTdvTIK4E6KRX<hUV49
zvn%}cbjX%t&?SRDOp^s(>-)iX#hue{zU`^|=CM7erq$M1!J=Zu)(1L5O**JRa7jX9
zfD{;#?(`Iy@ETw^U!hYLC6}+xB&$*1+`M4V?_==QBdp3Jc{0ClWphs&MFmrf?h+|(
zU!bw$^G(_qAP`$0YJwP<mpJ`~Kj^{+8<i)?TwzRJyX{!JKbmjfPE4|_pm%*Tfi;X9
z926vI5Qdt~9AQpRTZvy+QA_w=>Mh_iNH&0}$jF$9BOd(&TwGjiY)ZOTlsUdIB@eeq
zAtfqi!JSr~!j+2n>E4;62BM`zrh2)wtT;aQNjz+jbe?XBMmNk=*HScl=W8-|U1UBl
zf6_I|ojD(lYd7bJp7xgj20iUfPd{JRP{dFRy`P?O$xv(nm+Gi2j~|dC$Mo?C;+@Ot
zNy3bjCySIP)p62gb6MKt7|_oUpH7Abz%&IxP)W<u{jE-JsYJh?az6cg_S((Ow`u}q
zM{)6Uaa|j9T_rgzH_|ICoycdZf<#0vY62c_Z8>y9q2y7}lY28lm24p%F%hK}WlUTQ
zUZK!KefBQl`;zC26O;SiWI(rKc1D9MRhazY)t2SfZ2p1^rQa57Q^4tWYKJBfgszP2
zxR5yz5KQ1DF|fILyRa~n{QTHxE+1X`{1bkGeBt6AsSq627Dr2AzQo}5y4z|o6bH6J
z1=N(4QwqJt_;fqYqMSgH58aphdAEPn#eEdzjMe346o>o!Vd;){mlaJ<_xmKA$?!zQ
zeo!RRk<hSS%4%pkujC@luSA_A-ij2*`n;a`t@>Xhx2?YF{7x5J+YwOYEF_W*KC(4M
z{q*<5#2*o%qdOK8329iOFG?7_=h6v>yFNdmnLPZ{wX)h#na)T}6>?seB!x<2Ph6DF
z?$7*^t<c=NxyOx&aJ#rT8Y@?8QO<gW^c*b*U0#>Rp^GQDr2ysa*{Yh~KCVl~<``Uq
z&{99C&?c+Ri^>b0r1HEG@UXSJtCuydSdvH#X?Q*2YMGLuJWU@y<=8}m{`>H7v~BG%
zYj2Ooivu4IZ_CeBiU2)RwQM%e@co1+5)GJZc_;&BcQ2mdmQJKqygEDPABT@SZaO9I
z@+HR7lXZ87#Y*uu7&u$bjZW@5q;qrJ#aG=L)Ho6~A^PMW6q+c|r386+E^1;{nggD{
zF@;kn!f|nN#~?flEX4t-qFP88Wt<;(K1}SJcwP~6$|&a5x#Iv1C=VpvJQC1`-<^0(
ztoc1%JU^veY?{Ib&P<*UP7M97h>|Q7Qny+tp)LfMZ7WZQhlgE{%Z%4Y%hVrYcf1<F
z6~<K(k1h5PUwRh%21dq;yDhEccKZuAmFXpq>2z<I{gQi`;W})jC1@V*#u!PQKddcZ
z44f&VC1W{}M{ZTPe${!}*5c*`P>TERc0J#8iTmCTsfF!H_XON8KVN(xIokL5PP02P
zKJIsDE+Brp{sb}{-|}7K#129r5RkgXHHfHti+w@)?;DS=2XpsyK60F2$3AeDr1U2i
zWz3sx`rSNko=f=gw7aduKNZDW(IKrz_7)%V=%iw@W%6Y@R6@IIp5T=v2*Ukd$MyQ~
zyMGx;LT{o>;N3;`^FJ){)4v{V@oTi%EXfju>P!i6%Rv{xornlrte2G7eM2{o50s53
z_ei*KbgW#ohvF%ls83BWo2~fP8mG;obSBiiarsi~pbGb15BOV1;d%TA6TqsKn$(3=
zURbAj&iQ;UMveH#2oB&wScu`Bm&=hvF?0osCLhR0WgaxCs2ZE5ZJ#_H2lxz%JY7T>
zU%u<BUjMxz<^m(z_=_M#9A|6p!#F$kr<6Eb_X;O`w|SbjZ}i5tbjq$asGkL~QO8?$
zykuk=*bVlxb}*!naIkFK(2H5f$x^biF<G6p%Zf9mxGh>$Zyq&$8~S|jM;Bp?1a@Mj
z+5II=*soIi<wlj|Mu#{}R8Zi9eDD^Wv@-g>c_UgR=B=2x<J@<C2vHhLHVeHz=)FW$
zotw}}JZ_(J!zWe67PG!PiTk?eMwg8Nd4}_m$-L0E6kUn!qMB)5G3WKk9f{{eNZst-
zm+O<YwSy~CbFXZ}4&xiqs<jhNHn#fZBj1j450ZdALk@;<5UY`KhqIQKt&iV^oj@15
z1{zbvY^UG-)A7j@^U3RB{2x04Pj^+%7VxAf1S)kPTJ@}^@_&A~hRBqN%%fMC7U9fP
z$kP3K{xleG#fl`B*~81p&^7V8I5<h#!59cAlBpU;kGOg)Nbq_(UJF>C_dk;8xP<9;
zUSytF^V)i`?P#>8jVszP^Hh9FDq(}?F#&^$*J6TbM0xz~#zg{(>phG-eSLkct%ok!
zK|m`jE94V-fqM}FsaLMX<?Hu-5`Kei9HcAPBkr8gQ2CHb4+GBZAg{H1agdl;$N89f
z3*xR9*VA#KnqOr)5eJyj;X7`!;n{Wns8v*Wu@!K>ffb0FCQ60`By+cD$eC{8Jg2rm
zbVa&h6UF>z%E1*!0fji<aVzm3yNBW}4;x2K0UOuLU1yC=k45vH*WSyG=i^%sPYCSo
z|9(795EJ%YM8sISxcfy<$NjXR2bI-V3;HUjU^77piM1n-jaNy=pETPT{l^VCn#MM@
z@nb@U_bRE=5^cD|#f_O}R-dk)H==x2vAYSb6eY9$d<|{b11|Hak5=y2^P!t4-4tuL
z`}AQGt=IsX+EBOv*sen2anE3y7cWTC?udHiPHpjCI_uMa+Em9_*-6A1x{XzZm@OQ6
zBqt?#cNmvwFSL8f5Cj*gs!U99ZfbF!d$~H#bx%AD{O6A`0T1zA&-Yy&Ruh)2JBm}F
z$h$`-U>^)N$LM&s`RzZ2T&Rk)*^&kZ9hM#4+mJ!2!<dt7Yf)*$_GVLUV#|B2?BHKz
zFH|gl*^{5&sBR09jTo(<Zr-EoJQ3jMElAjdwz~_rT`$?y>j3QC5$&(5ZLhdjPy9|K
zU^cCH{TIm|e?vt0?e!=IhxNnSy~!%tzoFs374_Ynd^M1gzzysx{iImPBXm}9q!(w!
zjszUi1*!^HFJ<Og+lHj1B#zFn^T>?j21%(syL_x_cB_oqwy&xJt{BD7_H@edVr*vw
z%M>c-ai8|9p00y%J=*s_&Cl7&n2~aFG$K`G#25Ptih2X*#qIxW_Vrh7xnMMM+?Fy`
zn<_W#!fkKT21mDk7w|d)jr5j$ub^TSN?H@tZKQx#MBT2bdDDA;JeCC%VQ~qr-rmC5
zWbCl^zfcnwN`nz#;MSV%xZ?7b*2dcX>J8GzJMT7iogPN2472I?Y{{r}f_yA9qX4JF
zYW^<)f;&(%y`))dUdVN$Y2Nirr^2TGe?|)Zs`$tAUX7#Ua!N3IzRJYy{>Ws<@Nl6f
z-`MG4lTpI!wC8)%%Jr2%=b1ay%=htN4UAZP{%ybfmYjV5suw@tb|4jzIxfwl^m-a(
zI8pYgw9pc!FlEax(qSAxn#YP%aCfoAe!@0I?Nl%2t*tKi36{W0qx-@5?3$lN@{lX+
zUtzkq-|eZ4SMt#Qwnd4y?`)ZItmWRw65{s?iQ+H~_UiK!zSuqm(A@t1n*Cs2O->`B
z$*HO`=M~q4_xR%Pd`4uXYjr<3A46(T$EM{e@OKLtp~H|>ofu2`*uSGCT1DO+$2I2i
zJ{{|0PW~5AJc?*)iR0Ge82?MUK9D1lJf{mdc@K*CA53R=S|W+0*GVK7ycU^ZDNid;
zUp`?`@3J+(5|V791;}SL6-edM3Nuw1vHP4!d&_VUoog0Nyey^huD3~DPhb1lbVNKl
zjH$`Vul>5(%S45QIxXRibt8j-pM#d-<ubJU5Vt)#YQ(Mn7!kZ7S)gO@s`CV9g9<?O
z=_dEFnu~8%H2MGC9Nw#&7J9xd)isKz-y2cdh~ye*Hgg8--sIElx(oM23Ha~do^6!P
zdNISMa0ZTw4l3U5@E}cBk36aTbYn1v2g<0L@u%I(t&=)Mz&@qWh7@z>0htV)1U!ct
zU)PqAnXf%vQ(bxYfg<S@-in@@y45hlHZ$5P4+NtLq)FwPmhtk7C4hbNPD@|Tmhj9E
z{4L>1jq~$PRN!o^<4!-H&}%l`s0-p)dWFKGqUXbjr`^~+pjCtMCXofA>iI70L80;w
zt;Eqk6Tho1h1Xlz<0SWG@SXNPdh8%1Z#=ZkK?~dvY;-tTsBvFztjKU1_}aC0awXhh
z+%&!CE_|d@Mg`R%l^cx7ei#tw!U`;;1@@g9lA!eZORVmSRh*CrsUa!SU}0t1$^C9;
zSlAgGJeo?x<M#BgaTN)APtSL(5CW(fHZ7^SW+|udU%1`8>f^Rk=N29H<H9P|TWv*`
zab&`m49~dmb*3^u+@J5byqoX3`)5SrR9-H0Ffk0rfKxakM@u4G*j+L6gPq^iEN50m
z#uT_h)D)q?n(hO(^SZk%QS<$`JzLf6y}?)Ig<;MXy^$Dqwm+UF{i~hee2X(+3^e-t
z_ixc;v5AO{=Cu<O=bme<w+n6cGqw$2M2PMEqqB#jO=sp8%{8V-Zl^!govsth&s8NF
zcJ+j7?(lnJHHlzArYhFle{>K9$;v2`KZR%8paFJ7Ri>T%4h#xymROPGUUH|RM?U85
zbN2HEbydsuz6yna|3&(m)Gr$Br6UhyZl+TfBK=qF1QAfx{LV?z|5rj}-3^IT*JIhu
zAGedm6&i%!>Uolh7K>$MmG4`frRBF-Qg>ZX^Y;_}+E2f4I?5`&%_!x;cCtfloI2Mp
z$jrN2eri$+Iv0Q|Fr})Sn^OWtYs(Fp1?2W|E1a1pYl_{9z;8Pe=H<$-qL`PLP16jW
zWvd<FH+~a!iXQEI|46VRrZafpwU>9U=a(IyHrtW4*SGS0`wnjgVt=~%Umq{B43O?n
zB0($TLNMB?6X7P}VefO(_I!>ERo7FR%eCbXAo$G8uZyfEEDfFkYA=kQ*{wR&xZ94C
z$I#h<{aK&(^F+?<6w<M#TW5rHO|x*X33ExqQrGk3P1ke&Y*mVcfNcBqQZgwtwJ_Xm
zK!_yBZ9Jc8|EhJxv1-=VQ~0RL|H@#k>!MQm9clF5r^EfUsY=#xItsihkC`e8I#}(-
zJg^U>(#LBw@4{wa%Mh#%PAy!|5Q(<YC)S%w%bbvK9<)Mnwze+zd8gE<MV2P2fyAUU
zv8LCn5_Q7eyN6MHzLYns_wmTuOC?FW=>)~<X)C_p?(-XInt$2P2x<zbUaBkB^BGO{
z++AJv<DcH%fBROtPVH9}P9rxr=YNbHV0z4fOt2YwiMz9hmsvYo3{HbCa&l0Ui?oA=
z0mr75qib-5PSdg-e{!o-h6Mqu`1H7UDi1!1fbk`2+hlb(-aIvTM;-wtsIY$9>+c_4
zV4t&5sM`S91sp?`H~1$vhNKKOZ3?X*w~kRj?2#aN1ewxxc)qBF^#%Wba6Regd)NgI
z$rsdtQ*%%Nh<|q)v3P+0aHX#9g46$OOX9X?Mc44`L5ZW~BXcTeHkm;dZ+$JL&X3k<
zo30(Pfb8c~E6(hyuBWZagI_M_)qnmpE(PW$jKpBP74ayY$3^n*y;et3s2M4y)a2fm
z!oq>h(-2ONpyKS$oW1>(%3l>yi5S8QbuD#LRftsJ6dFv4#8At$LbJ3&8|*&A=%<HL
zjzCN+Wsn&uWy92n3)^5VubvsH^EiQ|E#Iav-PZZ;K*Y}5)+SA={k0l=(|<MreM1N+
zYTAP~pAuW?EN;%`?+o4SS6mX8HQtB!c@Z2-^)_0_XfxN;dA0uiKH$D7;6P*zv1+h-
z4q@gQ_-agu5}2sEIjai1`W@qcsNrrU%SQNsEH^HJfGCo7nIzE{gWLl`0@J*E9&OYQ
z>+%o?1euML&5jUSSYt20ah%P%NmAWYCk{3+^H{8yk!PIKOA77wo&Ve`Z5FH%XOXJT
z5+A2eOe&4b5!{0z-wz6Fm?I~BUqb+Fa5XZ>-Oh+fXkM@G_6u2Gq$J=TgLtd!d!GHP
zxksti<bb~+Er+FgY`(}1d@m8zQt|nrI^9GFg#UTDahi850$9ds&1_ks-MSg4RM~z$
zQWfxcfGqZ2IJImgg@p9)i0=GzKPaqavt(O)>nm8TGuOL+`Zv_E{Y<M2CDTc?wbG{#
zuc}O&1;HptqMzi^w&Kw?z4vA52$?k7dfxlszkOcCzrii~m(aA3E{E$ldmf$`J3PZ=
zsoJBOI9YC3hO$w4KpV)<KHs>1mA7u6Tje*nW45sOCGdi2j1sdK#47{%XqlwQEU0BO
zB2<f=$WJB@D{vrdv{6aQ*(QJejb{=&Hh3}mi(C^Lz`Pw?(fCrXI>}pT=nb;?<WKJI
z?tWNIgpTsgai#Uj!O3Si><uHt%Bt%;v1;?cdPvQH6$60e<jA_9>U900{WgBraceTn
z#y=PzWkHeWeBbh;y4}^p^TY3U+l=HGc6hA=1%MMt41ebjwyii8O*=LSSEv#cG4UPz
zy36(IAjmO!ixO}&cTkCT>{4ctQn-=Y3kr5%{L@4^zfK86QtJV|LeOxnX33_$T+r@|
zK95Dsy0MmOLr$D~sRi>t5%IrV4uei!$e2cIWaMc2_e=v6SR5!sm;XwSUeyol_gR@?
zrUp5pb_cpa@SGZrIF;h%I=F5+@}0+8-L3{=FVHY}5jJ1O*a&^+-Se4R4{PD)EN=O~
znUdjSkc-2>tgNi3W6v&wve`KL#Wv5X1L20H$t<z9czWX_xE`}9XdtO=>*ZU~*U-IR
zzhuS1-Yza&;dwOJ94(js3_35PRB3j=8Y0|2C9oEg@;R11I=65JqI_<B4*XfliFq4B
zEGgo@lRvHQ3i*A*M$Mp>J|ziY^Vu5_vr*t*J=K<7^qMKflu;%@P$qrl!L|1a2*_8;
z6iu}ZiA--~2hxR2Glkp3zfgJ>Xn3;q)dV}FTAJ`KKZ>aGSG9ck!_)tT<TXZ8Ad_mo
z_8nciNYQmtc>iT*^hZezRxB@6WS*iHpOm|XPc`_m&)L!O_#4*S^^6^{afGkM*RPc!
zt4&U8w&{b%E6E>If4OAbQ1J|$f5re<S0HV*Y5C|&Yrus-K*08>a)!lgJi?cCBRV$U
z`BuL&QHi-WV?(~Bi*t%(9Z-0DOCR{0)-T<*CEa1%K#9dypnoXhYu%g&EUOy(_<hGq
zI3DU?Gv1m>GtD;kC5|D=)^bRIrIH|s8Lva|4Ya1ZdI4WXQd<*-U3tL8QLCJ*<DYA~
ztV4jVOsbJlzjPGQR6)fmIgF8<dUNd1D7;nT4)e!UqNNFRNClhOjD5(Q_IXtUE}<X%
z;z?nolJRhkRC@xnl6liD`)k>;%>kao9$Ax`n(Ek;KIrJ5JsY`=3{FS)PlYN6CTHQv
zbU~V>%ST99b@Xgq$(i1(U+VBL_l_0*YJY8^=Q(Gne#HVc;`_r==V#X3TP=lcib^Uk
zJI!k}A;3P(Jxco>i+h|m_|ddvR#8jeeGx|DIHUSFdHGMe%rYfuh6$MO<=v{zkz5Ls
zWu5TMhl~QbNUWJ>o%@9wCPlv3FPWwk*d!ECs$-)>T56^#vcN<q>XhlQQKxHLGv^)-
zQ*#xChC$PjwD$ITRlZM!{V7(j<#5&AbIAI9Ns!JnZ-~8iFNmg7p}m72Tpg8mG{iXp
z0DMHr+WoLH<i%QU4zom&Oe?&<K7z{#sae5m&&kp=cm|qn$bSq8Rm~qDp{=azrsJe(
zxkIOo<UPxeO+y~XYkkgF;Xb1*K^okpZH02a5aEpUZs35>JDy+=-g?lB9t<?v<~gQB
zh_LzS`k#8P8f{K)KRA126<H<WA+g>|p3+2Dksm5D&K$v@W)M(@5cfk*s*Nkb^+$zB
z;<M9?41LWYt^|F~=meceo^gzgKNp5S+H97Xo3(mDK=?WChczxe5H-eF5aXOz3Ft^!
zMk0j$&C||FR+mf>i82vRG?Sib>K|9i<wc7&f66P?*^v^Tm|i>PoMBD|4851T;*!Wo
z5(NDFBhJk2yfCimZt}s-(9lp@aqGJv8+;0^pX5N=%UdB@A3~rJR~YWJ=)M=#w7Lka
zrf_?~pMn88=w%Lb?co(0tWGrpIbxeFHCmD*Nx|}F?>eQPKj1@dlC75^bSee%`c*!N
zi*32qVWMnKE>xwfln|nbAth{|qWOJep~HBh*8b;6ExT+=YNna8b{P?7UN$ZFS$ouK
zYEtWg^>RHGdgKNvfNH*h&A@}Cdit!aGt7l>P|-a9pBFJ_r3ppjbU*Cy_&!F=^9G8|
z4oGo4kZTy#<DQPCVB=cpIqG{z*dq_h)NeYt{4T+C8**sOA`@@&6ZHoQHvk<#&<&`h
zHhGFdr!h)RmZZu+2LMJJIjDP)OsH)3oCA05hHCKa5f${US7%hZtT)_F)-qn8wN9|6
z4aT@EnAKt@>y>Y$@ARoK<2=Qvm<T@W+F)3cU@Ox<pziXy*^s&I!-NYZ9Esi`a)k*x
zIEgx56j|DetQADu195B-cT$uLiVGJ!MYb{@y0l;3xe&_LpbmtXrI7R5Vh80=hjbWs
z%^$Qx<3=*tq}i?lYqleDQL7R~86G?Y2vYXuC=b~2q9U;exJJSg^Y)gQ>rlEuDsaLN
zgDIpe$`cK$<7|{d{*XS471#3oh|)J@NAV#IpZfUBPEvpIFUWo%4KiC0uX*MG9DZs0
zY{ylCWStLe<TMz&XuklqTk$3t2z)+kJOWfe;0sfYz3+f5pcTZs0n85U^KBdm;q>n?
zApH!XjTKgr3c~w?GQCyE2u!C)TF2y3nP@be_b`MvIL!02F9X)GmC>-q$*|GYQ{@2Y
z+T;y#12kR!xzZJUBg!Zn2zpIsSW-AHPrUx5;U&E9g3)UJmSK>e&l@nx8>Lg`KsJ}U
z7@rCWijeCN?wXmymd1wj5|a>*z@!Dprm*?&8>5AJaAE#`lo_n@1l_EwY^vG*{S8A`
z%_@$LigsEcA4t^^<~N(yLxhV_bRqh_k9mAOS$$L0<*{R*+&^U<N<-R=8L3;|0tkPp
zO}S9*KIln+lA}?kvbOTgL1yPpj2?{*<0DG#;M3UP8vQ7Mo5hddr#XZGU5emq){bDb
zxyV7I(LjbKfm>`KvlNO9vZ%p)8-216ZSGyUwM1-g$Ws`LwgE6in<pnA+sWW6{7DM{
zRZ6jjDB7^Y5)>htcCr@waV!-HsIY>mrCK9ANSZANFjZEH)3mUzdgge*_GokA@=&^M
zMQ*?z4sJ4ww;^YkZ@=lp`X{IoCmjdNB8YY<N?np*wCm*33A&Hr#OzQdzYL@x+h<Ft
znJP4r1Z-Z9{*G6&8dr8$WP8sKgYuBnm4xj(b>77pbb5V#&fTL35fkRqcaGeMaH-=g
zgpR5f0B(C)HhW#lY9M7t2!)v{oih33MXWAW6qTp%@=4rpCnom)bteYy0Eh!0i)~^z
zMF$B?4HWE-1f$JJ`=zCvV`YuH1V86h8*<Gt-B&so5O2WcYhJ16O0JWWp^cNt51^1*
zcl)BgCFxE{0y6^u6&frdii#CH6^R4%Vdum5iYykRuA(8PLZf_>jc^yzt9xlnFb<ux
zaarQMMqGhS)BH5JjMru?voRv^tfb-5e*v7r6a1T$>TeJQbcoZNJD&dLI6E^llP3kL
zgWEG*jKQjxRn7j5oIcMcRiF5x+2mY#{#A)~H1nSz34XAkkeJWiX$@Xqh+>2P+Bcrc
zen_%nVxANB3Xb$(<Gk+T>A*_Swf~?CWoLpu)kpZwT@*c<bd`48)kG)f1FC}uISu9y
z6!btmQ%%k6=M)Hl#x|?mpnQTf&~hnKiujrk8{Wt^oo1at$Sn(H?UVV&RY(9J+qBz!
zhzkLdZghWhGgYShm?>X3&RtS4qp46~nZ)2y-XLcIE>VU6MnMjf!qEoC4Wgo-I9rnX
z5r655#&XS;Z+tpVf0ayY_-Mdfidw!3hf~6tbwan@`D^^YYrAeQ<g)Dxyf4fHO%;cL
zmNGp!cfF#cm^#4uZ7C=+RWuPFIDi^#32iH?4cs~oGyKtlg`B`QqCMmoNi+#?)pBkg
zw;Qpq4@6orB=+P&-i0eMZ}9Y32o*a?7#1I=TWcYMB^_&0!HO-EZ^x#Tc5&7w9LZ_W
zK8}}iKKqU@(LV_N9m%G*5jhhb1O)T5+bkOF=P_*A2Ur&mv@mHykN%Dw41|gfmJ=E^
zc&q>HaScm-f!=vXhF<s$<+MFkRe_xdoHQ&Lv!M;qWKC5_g{6+x`tllgmM7^$f9NN1
zgOo$Lx^yVX*%OtDlD*&9$$2xU01K@k>26kcJVllg=8B8aYsItLn2p<`jpb86N2mH1
zdE6LduKWBOR!<{f#!YYPlL!`ee-$vKRLFD%rrIJJ&SLq}Bl_MLHwg33rBGJzmPT8-
zPNv#Xl>7>NtwnPz?%cY5N^{7+EY_wS!JSzc)>D7rjU->fRD&*(3p^4}uiq&$_y{X<
ze3>}&Q5b(=$V@0N(Ux{b`qn)DbcYdz9#C%2n3gcJLjg6U;Ys)#IUl)JJoeOcl<{J~
zi`;{kd!V~UrGyY`5~z;m91S<$2gKT#VgrBDfdGYE)IWdKDcc3pN4@%n`x3~*42wfd
zGE{JN6~(;{v@EeO)Du^V?>zb1{cAWRXHhA|i~=~$#%ooi7IHD2#Dv{etp1`;_Pv%x
z5jgi171?tA6^3pHz4bV93G%6Uc_hzRf-PyplA*3ei_s#<qN6dw#n1lBa^a4{axKU2
z&kKFVpHC>wR?x>UO&74na}K*#_ei@-KeZnj%#US>+LD9Tjz95qShiEX$1o!|Orflw
zQ%$lw5O7#DDGy%JfoY3-Px!OQNVILXJlq-tNOUo7(3^E;4vj0?y84@T*Aol{Z});;
zHGqHvDdEDJW(1ZEwTTL2EtAE3pvjzXHWuWxRd&_@bUi$41`Rs~A{H1Csx4umx}s8v
z`gcv1s`!u0iPC_9=5<U#<KH(LECS=F3&YcPjQeeKvt4I>kB`Ti3&z|V*3C<kqxgC1
zbi##|Nh2$&tg$QGnr<%Fqf@D46N?ua-VFuKNgc4sTAbOxi1<OSsJQ6MP;%oMV5dZ*
z<AxrFoS3zoJ?)Tc<JWu|WfTT17NWXr>4x1u5@pxrW&x+A4r}6~?$2S@*TZoeM7=<Z
zv}<$p$Xfc6q(7PF*J&(WR*x8i$M=mJ3%*=1?#sG<TaM?vh^@i1h-5*39E_h?vxD-p
zF;=3ylb}S}`r&V>MdqyNgD&W3R{Pwhc^X&TAy5KEx_1WA=Dxpr$@rMiVH!42Y;q~)
zidPBRnj?bYwQSSH4O5DHqWKL|03a!RN*hv=RJ&BHJ?DUB<|$&NCE1}9$t@NDS&Fl%
z0fCEwp2AcN47U9!zJvBnt(r<0ik5p*hh#;1d>}EehsXq-KUpdkwnEXF*D6sTCR|5k
z=r-crDpq3=7V`xZ@9%g#vxH}VlT=;VzO=yceZz)ESPS{F60DX$g8^qv2sS$wnN7se
zED`+P-_H=$s(Bfz1jz%$AOF5TnIYex|LxABFJn$Lu7&UxLfu6x=yFa(6nRNAL}$M<
z&|lWN+91PAg@9cx(YVpeG=`R5?NAc9&p2{_-!e<X|0fAB^|svXgtlv<fYB-qd6g8$
z1m)3ZiWB0vm8O;H6iY0Ukj+QT!-2Td^~#K4bOX&Ghk@p}TIznKu}VvW70_dknyS5?
z#3DzFl39jDsrxyhc?MTc%C7w4-*}bf%W%1xh2j_Rj|_yO_qTtwBFPj`F`DQ_lt#|{
zsv=vN^3^%A{EO$QO7XJ=Jrc@{Fk-2Y{b{%yt<{HfEl_0{dRna<Ui<Pe2s##tSz}Q!
zZ9Rl|5N7;uvA0fT{vuBBWqy77qLR{UJCRoefDxGH&9|3^#~IT%aiWV^?ZN|UXM_Q|
zMFswH@Z@&jc?#eD2d^9}()Zlm%@L}2fP}ejKrBiS1YxdD%f^|+XDtZ>e6y)Qk+hjX
z1c8~EVaRR^n~L*md>K8cjZLs|8$$!Pih)96;n|^b+8Dd4!@}n6+dRd8Ur%njL;@b_
zA(qp?`e8D279}J2ETz#}$ye2)Ww(|Fvjd1#vCFc`b7B0<RcN!R8Kr^ZMLC6y(n9nc
z&Hb4FiL+iws1mM(pj){%yMav_$JpgY6b1D5_xp@}$(7J}_E{wthuI(W+J3JJK!z41
zQ93sh^o$}Yiv6UVM7T<ss|x9%E|By-V;3fC&Ll<H>2W@QZs&T8UM;$aAz4?<NWvpC
zbLPGKo|yTrs7(uI)aTKYtNUU;+wSK4SKJ|*v;Z0!RGBDpz&F~wxg3Iexe%ZR>liQU
zyZG0spmSntS;<UY{(3o6`xZ3LcrpQH+)?@{4O&o^Wd_&oL}uDSJxN+D2$(9jrRjCF
z6veEYmG~(FLs^qI1B9&<-IqDFav$T~b{5ll_BgOv+!M_22a|Lr%)nR~tyS*Y#Yu9J
z8Jgkhj%ahK5rizw{rY%xx#v+t1^{79s(s`6!JsYbZ^1Qep~I@@QtAK~oHYZQ&IcPY
zum5g2m1Q*EbvK+4^Y$(=KAVe~Q!Vdko_{I@0p-(eUv9htXNj8cB@+06UA<<fjY$mr
zLOxsSt5^|Yy+K8-ZjT}(_$jrhIE8+mI_`qS_dYE6frdX1%<N)a!N(1wl^`f4vRzlC
zMU4mZyyx9lF653^Jn*&ek|XE^d}nlFo7RJ9(rGDjnZ8cc9<^xP_*}$yuyA~g%aP*b
zX}Gpj@1jy-Xee;_@?O2xv?jvy*Z?db3`s*3YTG$|!2zrS&43Sy!`+$nlOV+n1ckcS
zQ_b13nV(z!;QQ#4Q+S}D@PU}mhGZCDg;!cVuJ>rw#nTNr3`p9ZvU%(!Ty1C#pY^X_
z*3iYrzsc{DQBKk9`x>i~^jKvhm}MCiUe(~(=yOk$Mz>7R8BVU$uj$MbEnmENoGMqr
zmX!T#<ec;09|yzY#J*_C?wsqGZ^6Z>(ophxh$3Dpg250)Qr<!Ga4>a8Uy+u>gdL*+
z;+37DiTH|F_{BJ7o1D~kGUp%tCooF|5+UsXrrj1vC>#DYGY1~83N&BGvJwt8?0}=q
z(o~b69@ukPJC3SEJYTmLpc`J5bi@q2EFjy1*pl3maIWQ0SSQX#WfC@YEab%y#&n#e
zqTNi|+03<JRO^Zgx|{N}4!7kGQ&Q`cM*Z2PDdF4W&XzW{19+p_EKXiGjn=xp?+w_q
z(GKsPVkhm<=NRE)x1#Mee`^mg$5`Mx#vQjuc?4NEfHfigu?`t77`56g*Kc>bBbais
zY0uw5AG{{+#oRGXt@Nuh-dkBQ@IA79eOcjw%>@<i3Z~iaf9X`8QBdR1ChW-b%ReJA
zB07Pb6ipT;MaQOAFb(AUyxNkh!Ra~Y0#FCrgs~>SnD0)R11mCoA|8xQu!Swr)}t;@
z=9^pcR%c_IsX2hV22Kyz-Qk`&>D|Npvb2Zf-%8PN5Lqh6KXG;5ygb3Bn#WsKGDP9-
zX$kwGY*E-FRF~&mqJBwO*Q@=m5E;GSD{G}hZ!M%SD9mK06j!a)Wa@he#H}zb3-5z4
zr7#24&wlB_M2#<^sr+`I?r%PcxeU+65}K+ILBP(gw1?2)B$Wf;bXImM*JJ4+8}L&Z
zR+l^Ws*v}~wNK|f>-sGZ^nAl&E^4;vD{qoXy#FPh7-cBV?hwAC!5$0QhVnN<oSS!k
z{qdkgNsBT5)l5ou{w6HrOgVSzM|Z-EEu#8`iI95`G65@0P}B@7P8_F@P|u$uPn>G@
z{X{H@J}!h^sh(2E$E~?gZ|=r~gPXZ<7QSIlH-zrGVf}`Mznr}f%96kaz@)=CRsO+K
zEo1?$^Li}UNU1dWf_E4iiwOnWvda(JI<+46Hg(wUv<|oaZSAgJZ|la$({ODj=m;9D
z?C{;mQsQTaKqSzn*EcMuxl^p9^8#H!f&j@LBIr?emVQd6fvC_Ld{UI3dKIyLdHVB2
zUvAQtT_roo%tBV_vELjU*;vsZl31=7kc*`(4iUn{MyYk{vhWWsDjhoxgU2uru<n>B
zgLNd12rgvar|l(vs`hx#`gc{eK{HV?O`(Wt0SMsZrZeHpp90g-Y#@5xR7jcok5im;
zyc}p5;k6AJ0+79%5FkYn%;9GbwPE04MxReBVPi`;!2OnCv`fg^5OiV$+QUVz*g7M?
zObY<)Xq2$v@E1z71vtFY^ttvZwiiM^jqdmAb!VZT)DPqM*Jw=}Oc(5kC052Xzf-yP
zWL2Pf0-va<zQ-5-Ytj2ka~>tXhNFL1bz(oX`E|JNYd&WrJ6PYYr-7)0rn-eJUSHc+
z;1hW~udm9O)givOEp_*2;R<96i%r`$_?r1tS}i1TwNv5yqM?NMYu=cmAMByBq5&qB
z&L~p)&&|na0+9?~72n$AEJJegr>8~WcHY1DXOyUca|BHd)05=9@6cuf5#D64>NUYU
z6;jMIfFH`XlS2fO%pIZ*Xvrs$<gdExsc5w`WK-q(s`<D9giO=Q*FH5HKFA(a3Tjt2
z@qayT?{lo#J<quSgMjfKQv$_F>_(J)3`u~N<YKV#i19<7Lz`!mmDKH6n;I$R!3R=H
zWq=+)%*=xTl~;cy9u+z;zeIMJ9ZEBjc66-=`;DgsIOx?dqj26)c#(mBpTSivs7J}M
zsJCq|g8qmVGfF|3EwIJ+FpSU<!-<2iZVyE+5zCOKCiH98xCgwcgawLwj$cKuahk28
z-PxDjha=ZmzT48MMfoDiQ3&{$@NhKf-tiuSfDM}6qyt8>qY0Wn6!Ue!2cpiYIw{l|
z`ZhtBGdUWp7%URAsDK~fd>u_&i_xDfZid-pjTkvvWbzvB#eb|LiR9!(`^e76_+$o>
z$en}V7>yDd3ibvED$5jhH+1uL6HKZ|@(=)DV?_ArMRxO;sl1>>`y*##;kVb{CQtTV
z6+J_07UR3jZ)m^xFET>*U3vmmo%&odOGZdqMGMc3!Ypp@j$<W46%jgknTsgc1vmCM
zp!vSxMP*qK`lM(0+D++q$N_88fwC&`etvg-=l!wyn2x>vr#9XU{vxH2&tGp)0+IU`
z=EULF03qkZt?V@(mK@!``bXZrFu-SZyiJ9?i^VV1e{4em<a~-VsJ=X^p8){bNCQAh
z0S>Z@jSF3auJ|Db2LOWN@Y(_j3F<K$3^Anuk`{^z=<kEo$t}}9JTlOhGaWh@iZt$g
zIGCVE6<hPjOjaScBmn}}Fl8qrg-~~7oPp}(5HzMGkPf;mHV@MxX!(0vA<8R4>4csy
z_{7U%@b!t6^>kFyAUVO=Z?ULMcmR-Qpm47tASp1cR&X)tlL=*HzB$&l&i1%{>w28e
z%drd_sN0xn@v7;lG$3kH=^GCd4<Oj}w>QFV&>@1;GJ|5B%#_s71(qPqn=vrAI>ieh
zj`-lEEO(Hd`n;PZMIc!z`%7{*A;4wgp^Fs(I7Ajg(F1GZ<~PHJ?zg|JZkD?n^Uevo
zd8NGvV0VM|-bs^MVXP&A=_LJwKa}})umJ$1Xan`qGdYBLatwU6?ZQ3va_9sZJd;06
z(~{<VzZBfD&Ks#0x31ld$ZVJ&7b=(=VH9A_0|v~*0g}$jg(%nT-O|+FFH{rsMWC%%
z0MI;ESPpMx31}ivM#UN`sPA4X-iC;duXK30+uFdu)x-!xA2;O+Hlqe~^Ysv_yQK6W
zazF5i^Z&^(oELJ9R2#>e4?U6Kwv*N=(N?DI1^&|}3u?oh#(p0f9P#r^@*5_EX$Y{r
z?Akc%83N-I?i2ajJ^w0Kv$Fnpujg*R#n)=W-0L0ON)uzlO1KLL9RalmOrq|h$g-ko
z40Ga8KZTHUoiu9wc+I-}zHQ|tptLvy?AiNkosE-?Zh!WlT-E^~@|$U-x%f;rStPEh
zA)2n&9yzkc75QS?v{9=J;q=@<0*q<C5NrMyhc_EEh7#?$uKva!gl8fii9h<CA!j>K
zhX4keo-LFt$uX7rDOH+tEcH7`EPj-yr)j<AO?4;ERh|%-e`#es8ae$pTuz8$A5+|q
zgx>FO-_yU=#4y9`!>Dms00nckcsQ8*uJn8_Qb}~kq;xfuh<~loPsV{>nr^KHKm%dW
zNJ5ouF#+U~XuLielplTsg7sx6S_lB@Y{Z*t;GMe)v96DS*g05}sM!9gVYg_<sa-+-
zqGf(G0MqjF@`<(NdkgR8=5N)1o(uUDWl_je%tx|N0f|uQqD<paIo4Ed0HQ#620MkC
zSr+;u@`Wi-<DV;p&UO;#VtOSoM}wy)crV!OWQ4?#s*L<TDJQu{Hnpl`sS?GVB<)qk
zVYe^!oGx;TUm?-oFi`GW8|ElRwbM)0`l;bsXLb%gKy@i@grAo!^Qy4%4~85l$<b=7
z-^EhRJ08Kq;=a%5MXg`IYRrn|A4{)%e?v8-`^)@;j=NdUwVXg?h)-XK=aJtruIE7F
zzuwPq_e?6g()T19r7&WgzsmTcXly7r02D%08Fd`8O$nbsv&5D2uTEzLJFSaqt)g;A
z>RiV!ezLM|S@oPBJb<MnvP4UKSXmEF$tI26qW|g(5F$&IiL1C)?Syi#NT71T1ysM{
zP;4v6*i6zyx@f}XWYJ;g!uC&BDRNQpBP8e0#YB#dD9#q^jeYw+Av-HHXY|Nh^+vOW
zP;IHgoJ7f#o{!&P<mhNJlKmKKK{O%Xm7Gr^TMxc~Z~6@ZYhvU98_wKoSeTOvrWe&$
zz03>014W`)F?@FlI7xx`G#4)k1{(1wu!w1<*Hb|nL1xsHX!dC8MSY*DCW~W~XA(R*
zuQREa-#4i=niVVnHD#(xIY}i;ld@xaAAq9P=ws`bC1knhe(KtaB2f+qeYkY)I;EF)
zkx&MfPL)#aotmJ(P63Z7MREc{V71O}4%7X+=+t@l<d)YxHmev3I2WSc@I8m|(*VI?
z0qc=jrqj#qI)OlxJUPrr=FDt8DL`z@-jEuDt+w!*f(1Ntt{5>8Hu8yc!MPr-1X_da
zP&UTVz{L4mNp=XUuIqu~{$ycVqIvcDMNrQ-3@QtC*V`qQCUgq+9%$Md`XP*r-R@|p
z%c7ujAdiu=gUc2e5SSW$cXsC7XI*12Gm8OO5Q)z`CZiK))t{W2RLLPLfpGFUkl?ko
zLPqLveQx+Zc-pM&4xOcLOAEArh0pwCJ%2B;hAKNGug8klh{tH<!x){-5r!Is`JUi+
ziGx%#9!hwKv`+xF2YBar#Sc2k`m8-sm3Gd#zeuIzHP(thiLzThQ=LV%mKp%9)14GP
z`8S#KssS@Xf#G6L;pZ0sC=ut?H?Gkl7Ftom(V^rKgyL%g$xSQGa|}LnAgS(;X9=H^
zx0Z{3v!4DpPmkjV;-!wCuG(hz=lbI8$y%crD0r%8P=i8y<hXzG(OM)e(MqP6v8Shi
z;y=6=Ad5@wr%MX``2jn6>n!c3X*GjYZFNl)*zSj=ImOZ(yw<YBVBfRj_@I5_q-iI{
z?YP3=Q_~%7LwS;~c$v;kh0p5F3?j?#+DQUjv3}CAG1s3F4B9ZK?QX;bbD)33d--Lz
zYgrx_k7<D2jX+A1rpel?*^=VOW_p$E&|V_}ejx_r_I`ZnziiCLD~a4YD>VM{tk9_0
zA5;1ES2CyXHH8A?bQGu3u5Y^eKu&DP6a)2^JX%^{z@g0mSH;SuffMX=F*be}O_HUL
z^KqQxW=fE`{1*l>xpk{46a)CvfFPe_TTS8$NWx}n7tXz~oZ0n(86(!CEOXv*w}MH|
z{NvUmX(y)Ni0+7I7Dfk=M}oC+9^>J`$wHByKCQOw$m_h%W}kk$V1Dle&{r$WgB5tt
zKvJ^5NX@%H?P=g*>n9Lp)4r1iN|u{JK6Cis#|7#wzzj&%Q5n6@VI;L;R6FY&<9Ir6
z3NUm&1G%v$BV1O15K%oTcu%^=G!Lt_@K+Ba66xEQX)mE<9!<`JjzAt?H=^%^Z3X}W
z@{G4bil5g!@~g;r-eQt{oK)L`z65i)qUnAMoJDUsb`E9rnD=!vdoSo`Ox_6wkBeWW
zcC|mMI63b?sPE@e{Y17M)11)MgJJ0Cw;Y%**DVwNw0of!bt0w}4X7hg)vjqzhn;_?
z-2B%`VrCt8UwQP(RpRB_%%FB)#AgwZ?=@(3mUs2GT|2<Y*~&K;!En@oW&5Op%9F)r
z)^}zJWA(n~TpR+n<wVsXuWLRJgYAM95yU|NW#oozW*Ld`ECWOE@mj0h-x{}b0jtC1
z>pe8LQFOKZqrAPG>Pegx^ekw8HRX3e*-x^1N|1T(w-C%QQ?<5zFgzIg-KtFwyV?_T
zO|SNO;@NY5Gek;2`Q_Ubd`bdSwt8vDvK*U=pTxTi-1DX%Qt-Z>TwkA8e{?<Y1Xl<$
zzrH%$P&@8IZ1>uT1{4Yg7**TJg_4bjPF;WW5%ls0?GE7bh>R3zku6FqqG5ad;nwpe
z4q8lI+_Y1;Ogb4F@zCtFizIA$i`7cFRx|K7ktYAODq0Ti<u_--zMG{7+;ms%M#{PG
zM6AX|sRcDZJ}wc(N@du5nA7=mk5T<@AVm}&F3K7Hhm>xPIOHrHS=E!JSwB<%tdIId
zUWW5SbvH%Rw6qMOb)S2S8IXeS?1mNUv0f;|O9l9WXS}<y_^G_mndsWn87{hwW{siS
z=h=-8Xfwd3M1Q%R_Qkg5=FdgZ1>5p!^)fk)G#u@XV-}X%r@{Pc)56hr0#i}2+}u?1
zvBD;+o8$D#WuYc5v%ewnR-zNH3?8oB9%0yKF9TiI_q6_+oA@b<R5lbco#zczaLpE%
z{16GSTU2OTwEY*>({yIrnK#7rngjh#(v$a>Zp@U)+XhJ!p^epMm~ry>!F+<TlfOI@
z?pR`l)~~h2=ncJBMEc6__we5ITlDM2zT@oUmqjmR8X2J|WJ{O*xbZW!VFPujZj{u#
z{98BS_2}p4HqZ46pFQ^Z3&n6ZnIANxvHF6BnYtCFAH&R|1qW?|X3;wcLvnIs4fJ{t
zw7bX8O8@g;035;AZ41+KeJCh+QT+rW<d+i9Ln>?T7w%H|do9srlV{bh`?Q?NUiRr(
zU@BX;q+D5Z^@il?11%eKg^#*}W*U#&M0OH%Qn~(yxYh9-jV|<0l6PM?Z;wuqP<s`$
zwJU=x+)&E7EP-D7jcOAs<@IRNWs9R-jdx&#*5WU{SS8(az1S*8f!PyMTarN~$YDE&
zc_o=TUBHkX%&;^Bv|M{G{^Be$8RGZt2Oo>^UhE(`cC0q+zTy?DtRXR!m=*YrmLt4Z
zHkO3955yL3*o{hTx6H$He>2Vr6%_du_7=+g(l91Ev>F-G-9R$dUV70e+A?09(vBK>
ze?&vOr8K*-mpF7@XS|g}5A~1&sO49uT>U<Co_2_G$Q1B>^4e(e_5blFD6sdl4_f6w
zNc9~g_uDKw%@R-9IR5B9=*G}<?fB@?to|SK5ebh++a5&!K-$D7aCCydw`aYi3qe7c
zN{#;VqS3)EB7${54@OA<K>a9$*H!0PeVcL6TA#A_No%xZKB&$9;l?Cs#4E8#$HZ<1
z)vsYOXPy*~XFt}ttMyo+^r=ERbrFY9*pc*Q#Vg4#tBi;I?+9=KsCFNK`Uxfkk~y`}
zMwRu`woQq1E5~unKzp-9s}N83KUVPr=Qeshwy5uY&v+eoO~tzxX@%cz`{{jy(*zOO
z<DQPP5dQ6EgNPPj_EGBmBnA<?d}B<ip6tHH6vcRtPL3+N_F=gnf2BAjhqR1~jez2d
zFHOihQYlC*WC+NOrmL~OKWmn@_1nH}c(hcguG+IGed-+18H~YKU0d7kdWV4V6iLo$
zluoC(l)K#_NMzS<zv<!X$TF=}1W{E{vx&35L+-5ed(V38OVpZcN&l<g`bX9FRsr#D
za`t(QAjP9%{w)FD>;FgAS4PFvG~HrBg9Q!l5(am72p-%$=-}=eVDLb2cXxM!yUPT3
zcX#;adGF6VYt8vHXU#cXUA22xbyf8_5LIVxZ>Ab9NL}hXN<aL!iCMO3G#PM{Z5*Nb
zB0)~x=T`Br1EReZvJVXbbsT~l!fQ5D3G_rYCdLHpXYTKRZ7U92NjUm64{0!rsC#1I
zpXsZzKVc<deV(;WCK59@VuXpV7eBQz860qmawcc`mE!0)2GjKE@KN2YeU=Z6eHRx6
zngGow+Ao4-FxvSNJ4$k82qK8vFQ+y=N{;0HD#EgJ1;aNSWARioI^NDJp>J92asy<k
zC_w{>g&tO9HPan62W_zY?gDp-)wvkp8I!2r@uP{NFjvhRG>_F#Y0*;8{ZQ4&flML)
zqD&YK%Ck~|iNGHu1}DQs0QD?~s1o2HtC$)+CsGNvsTPPvE4Chh1&uiDWn!DKua_F}
zw`GJo`n7sc=XWgyOkt*hztKPtF+&I^Z^^JgH{RBjsxfx4{l5*?Ub#M#hYCgHpYT!`
z<`_ntJyDTQP^FtbAc*nnfY|##5ul|wh$DFG{#$^-0!%ARJ4`E;e{;9R3mM2jr^z@Z
zcc^JbHQccQvBL^@3a#*-z(oKs4vc!277kChBl3qGSN*!P&9o^IgUEQ??`_Jza#&>U
zIrs5QIMwx>j^A;wdE6*~!x$J^8Ht=mJBUM+;i5o@tCOg*ypmZ>E9@5U*I$X2u159O
ztp3H}#%AI)c5f#Z;T{5^_|I&WmHsW?o^}3cSO?LRail@xj^%*}+7I&RY&g=m&IwEr
zjGLyd@EPcW1%JtnDZ>q7YYgi^nE-5zQ#cV9<3YdgE7bixUq6jAex6-be+Eu5ikH+h
zZMY|%*ks#&A)mOKK$)p*hk<F-gKDXYKCzf~no*jWa;QVl+}h{00saM>2|NAbjS^ws
zhxH(U66lc)O2iN8k&OtI(o>V!l4UTp;tex_L&L=?2>H9rGnSeN)pfAvnN?JJfZ*^Z
z%4WmmqE!INds}iJn^<XXc8>H*ppn^avBfNFXgxlnqaY*Zz_mNferZ!V-5<@OuM>R6
zarVTa)a{89n%DD&AVQ_eI?Eq3LXT|=zy>q;Od+6xo>MeID@i3kWH=pI?D&O)ApQ>Y
z6N8%nAU(WMf-J9Wh&u%&fh=Yf<@^+jk%-GB(jPH$R(T($Y?CvFVNK!W+YMIrV^6W-
zLKYuu^$-=2XzgJM#^E61AfoyNs$mpa=}{dU256}M;$;g?LQzV5+Gg8P<*wZ3=;{ip
z_*;o`ScvG%V$2(Fi@Gda{EXE58A>4fMx4F^(hY%;k@2aEdC_{v*xdY@$im!iqoR6+
z#xO-UCDj)9la}$*snv*+V+H5W#HfZPoxq@=oZ21K&U&TroEb~1jqi1W%>KbRslSc*
zuT*cWb8rte(RJ4}y>6Lfsa^`3;V1*3`Ef13b=LyO;QQ9rqq=8w$+#pV0D9-G%?3&o
zxNzj;CXsd9@K_9pk&P^54oiC&W^ZUT=Cxc(+X0a*G>G12g4C4TEhGaC0^fazv6J#R
zK6C)!iPl!hp&{8I1Ney_zg8(2YwD50X58WkZ&j#1rTo@@y*g03(6j6`-mno@O%aD%
zAwWcVMD8O}W>R9tbw71=3QmM8M+z;~KN{+zip@jBpkOH%n8MpX7+9uK*l)6(lhy6D
zj^FU;6VgpNXR-45rf~EAgc7(xqf+6aC!PL7C|)9^BP1Q9)z6VWad<_7W~d&>MafIj
z{d>Xfsyss{$MDU@l_3f223Yc;Ubp=gc^$ht4d}%PRj06lmbB$onCr#<DU)uH!68|o
zH%WkE{w0WBIziSQ0Y%12OSiTlg)u5nC1x>Z<ddZ0@~(Wp4ay%G>q-vY$~=}%39sN9
zVMO97&L5qjX;U>sa>^j{ad?59K71bJQV3q^FmagjhUWj)((AU^DxZ4TKj4eZ)#~y2
zqxcZPG6}l@^m1uqe&JKJ{{0m|%OhM9$*@NEITe)p5)9pMeFkdmG^k#)V<=4FWsZ2C
zJzib4Nh>hMH@BL#Yov~>=W!n<%oL~i8&LydOyALQJg`^RNgwARh(3L+|GPd)?ELf(
z$)YwYC=y8S7p;PF3rw#3<!xh<jF&Cl9kbW2W}#MP!SWZ*tcQ$(JP4jM6CekTC}H-t
zx?&pzjbtQBwHS{PXp`u!f8R#|s|C%91Vsl@_#;mri!V{tryO6=YmXN~4%A_1UtH#i
zkSL%-#)JiGycpYythrIjILnpMMc^e(#3+h`$l1U-dvFwog)F#ZeXHtp6=~^K*?Nkh
zrTtc3b|JH?1i*pNGY!)N8>5O0!daFPW|tk&j5{wuin>LvbOlx}W+zO`!XUC~onRKC
z&k_X-)~r`3%o)~PL2l)|!ouFygckKwj(SRDi^%mL91|_fFTfD80xg6U!{kgqJ^IG|
z(DlEM>Q+P=dQpCr!E{}HC7+)8(Oc(Vs`JXM0Exb)awBBW6-`DMJlWvBt!c6E!!-I<
zGFgOQFv2-Qet%&B_2+&5O;e~Hmw@t{W*fi&WqWP&)a!}S$af?3R2AK8Icy-#YZq^R
zwxkVq{X+$fG31z5w5U_aNfxuS>#2h+nPv_H*Ts#vQ`qIinZ@tfG-Ja>7|7ZreAuj8
z88SJ3G+>uy;TVrGZNn8#H+3U%b7SQeK_8LFGeNe9FCNg?w3<Zk1al2QF^3RnN*a97
z_oRaM`wJ{!JkPaYtTwgdvY@xlA13`v3>1f@Q;`ZpZ8?boiGtcQ*G|<~-P&lf?<BEx
zt*OUUhPx5-KE*01E)z5n%H0eoS_ITIh$>{k(F5ihdldph*dZ!9v+9_Hg{>!tvvAxY
zUl+V+U;<0Z^wGba;D6PPDxx!ipRd_)zjI3tf(yqK&BBq)bvv7lQN{mLRH_1*?>xFX
zfNp~Zy`%&bk#sULlSx=#1NeerKs!yurhGwVTvAy=Ce2L7AcbP8adFKq85BhJeXfoG
z_gbJ?a&r7kgF#{LJx3{r?z0R%e1rfNgEF>NWjKqLerjqudY^IqOiFh4*xbBUeTN6R
zo}OC<l!)taP91L*2!v4p$bz$9IT6hc$XT!s@ox;`w=ghkmE+uyvJR|TN@M$5MZid<
ztdSy_C@EgrY9SPp2kGw7z-)qGT<6=RfDb;yfTXbDQq&A;IjAoPO(nV|h-Fz&ge;CC
z+b9E=v(i$5=dE^1C7nE#-%v4Y-H0$pZipb&eiSOZo?ppx6A6;D?*)aG*l8>)$-jge
z$5T;2uFWgzI>|+~ja<yg(kE0h*8-Y4tn6^wNncGzD_K~fG`>x-)0h`tcl@r~%LDBo
z=#)$4i{=y-Qqx@fe7tgJvB^{k8X_ig#G2xi>vP~r$SWQMxCH~y2qBc`AIjfA&He4g
z4uX<TZRP|E-p>+59O58RxX^&VyG-N##rYcL`c#6o1J=Up^}a=)XP}047y@c-Dn-8O
z#(%G<Q9;fT80$}|yUNvKU|BTU^GWHysseAEPBzH2M{77AR5Y_COfQomf*8uZk5<1<
z-K4YE>j23q%*_+ctPFNFsA5b_<-bU3f2q&c7pAMrNR_E&{LGsCrMi*AWXRFx$j^ud
zILCnl6y4=ftY4B>&7_Jmk>+2%(F1-~_eCne<OuD1KfWG4UDfOIaP!!YD%VwMbX3cq
zQ3v6usNE-$V`za~SloSah3Q4|XIN<KUAlD%XE;?$Keg?vRD>*rvq*%ii(xn=vci+G
zwtmaotAa%g#{pJ2EU`$I^{_I*o<`(h$Z2Ss8Y7!VK`SrVNMbWc5^S;Xzx9v2Rd)v-
z5LzW!Xy{Gd5Js<)aV_F{R;3Vw(bH^&5etT?l(gz+zm2h@XaN&dw6k!EYKmAqk%5gT
z&}I%zDFS$yCQXZUg^_tbWa*_>@`h&<w5^7e$Ga}PvxX!JDF<+Qi3*8_@OQkbFtznM
zj4H1PqZ_*GuA^x=UnI=JRiOc*$ypY15_=$WM7qd29by;RY-bF(D|XC#Fma7_kt)PE
zaT7wFzs~m1dFvsGgAgU;tu26;3#y9*EJqy{t6w2G@igga9W0wc4RU7rVgVu%uF$%>
ztr*%s(HggTbSRrbjM@q{f*EHeKj)!9{j*MQJWWpBKmC1lvK?d&M2ry7oY56<J_Z)w
z(3!hg930qp?Mze<4Xh#tu|(AYuuQe+odhxD<01n<kV|a^XFtqxp2J&?OL~DPG6rVy
zP}ZKOGPVwVAqOJr)L9i^;^JQ-)m3kA6IDz+1cjSH@a0OvM<D6tKq!rXvRv+86`$%s
zbU6S@GkjV63SaZ4MXn&D$2%s!lA8#FqcmW$P7bgsRBGl^Aux~}&`YsQp*j1*Gbt%>
zqTZ`T>*r#GirH=$W(__iP2-P(VVK1)NIgkitIBKq<P1^(nbbpb8KaO{IyPDoZ!bSb
z-uk1Ol`!?1+0%vt_lt<_t<j@;E8)9f?Od(~(yHxVaQ4#MS~YhTA&zI(K*Yaq=2NB`
zWU_sMjL2sQHAy%tc^JBu-90h1iv*?(i&ZB&z|>Swf=bm1u4Gliy$^AyI5Xm_xo&@x
zuI-dF^axJ6z?t9&(O2|QhPPW4^LDJ96c9H3H$y6kipFuOJ!hFGS$d#+{>*n$e)aZT
zU{fCMVVc6UM2D@}OVz?QhB}RpI85dquY|~<N2%41H0p63Oc`S`7-h4v&_uEC;@?H&
zC5*I8D>2ETakR;sD)f6OFxX&>Re}b$k4P9Siw8zA<4e*jv%GZ*9EgN10ST4$h*IAT
zdANtqR2?zR9S>Pv&bU4)jHSVuRL;gY5t&F<(Jr$6wF^%8RyR(!15zK?IdS^+gFa;T
zt1`A?{eT3dqG019P)j1g#576;xvKqf{Lhp1p(kTbKmZ67o{C+c&tv(RhO}5ifho&o
z%7}!bOW~F}I@t=z1sRx=aVj^243g_V4dxh3{RI>cF)QQNrY6Isps+eUmT;U$gtV;i
z-RZG4&S>HL5h25h%v!_(FZP+Prt!yM@AsvZ6&NE5ayLOkxItVR?wzhpGCBDyw9%gq
zzzPr!N~JFaQ+X;(;ZBHrTv`yG(j7o0v_>xVh;Kr}T0W`2f_Sf`B7xp%cDbN*&Jsqg
zAbfWD$_Hu>HV72OD)B?sT{Bs?GU=pE89Q<0*Wz;Gp4pUhGqVk>^22=i?Je&HFnO>o
ze`%p2!HJ_i#v0DAeZhf)6{%mUG<*(*&YP5sG{a1N&&8|CLUEvF!M~8nb)r$8ahfyP
z#CMq+GqSE90Jq0Kh)pqj!DOF(bzq)B$JQw-N>vm3x1VYecX64bxffTye-L*tLL||)
zFWfZ|Q?*U7f`x%032|`01`e8Cyg<G_NjVOMg2JRWiJXiw9ymlkYZba!k&O1z>Gv<?
zjKvuj6`DuX2pN_}MBYF|Vl*qzBvqS!k4N!qU1ni89>?qAc&SB}(8ENr+q%!mX^fx@
z2cplEW5WqAO?dtsEuq2Koj@20*m!Couv}l$GYwMZtEWH*QZu%4O<{bfFXJH#512hi
zf*K!}$T}Eoywa=x)F=YB=_$YzRCZL;0`%3f{OPtJf8Mul7sR^L%wM%Rf#W_;6|R4^
zi7TR5j`*AOv;%_@7zh$gZ4?c_p#T;Tg#&howGuJ=F@PwhrPrHc66#mBI20Oi6a`x0
zh^+Jh<TlZ+deT+}j&x1m5q#6mpwxbbZ`kx1rym^UTyU+xm{pG4jNkb{joVa)zvvG=
z;KZG@8T;S$YYJ5ppMCNpL8po~UtYnEjI?=rqHTU!O|flH(;ISbn2mtO*2rtnI>uXL
zfdwV1R1isH)q<%1ipAUej+*-xsui=JwAm$Dl$!|&EU@X<$3Y;7DYiB_-$jZ615?K?
z$!t*vSiiStz+`>Ut5=?jz1M17YsS$)!2kndRMo1$X%f>QE98mPBFDt2Hwha~%WH^9
z1T`)~1yqWO(zr`Qwxy+p|JJz*D)sMr9$RZ3X$Z;Jv*3c~x~lbK1A1n8s|A74#)UUj
zxTccwa}T~7+(kbkX1Auz!&ht?bQKtecY0QBcG`3egxLvGsICtL%-R&XmxgguQPvk(
zKW!IieV$wJi^G$muQI7imHo3y&?lh*H{*$wx#JR7FKPd%XZpegb``;vygEKEJL5Kp
zlhbiN`_C@TYRna|%Cyjan{Z?Tl*ULjgU{pb+yE@#>uhm6lZrx>gy_mqH)JFL=CAP4
zOFk%*N<?+|+JNxX^6?nX{;CBZ!bE>llK|Psj6i?_4ueUjEm*M}t1o6JoDtcCOFL~S
z*GaIjarRpzJX~QT&7K=yebtWC){j2B^z5%HMH4JWLkreZt}9(9uEIt5+SoFi2cB8l
zoy%v!H@&Ti^_ZC9324CmZ+z(Lhwgk5b>E-96fzWP-L+h_RxQf%>%5HeWdf%DP(|-N
z?v5Pf(<wf<8&yYh@o|FjA)2Zefy5kU$q<@DCa-}s<s}m@1{GJ*US}$dPp0u1rM3o+
zK|=yi0aegnCn7Sc6Zwq<Rbm{*fmc>jXNe3_07enV<~&vP#4R!Ctdg2%S%G7$VG_-1
zZe})Mze0f|<89E63RFm<KeHTiY&02IeyqA+FW{ZKCc1LnYLik`loXgVm#*C))6fHb
z&T}#Q4M42}jFm+FJZDT>Ag^VPhZQ6HmoY1u$aL&8(&#H43P{~)t2${xt;E)yV~PNb
z-MkxVVS8eS8e_Y+mzS68n=ASRb5C{zB{%QuK;k%Ql}i}*(ok_`tTr;3nEl2)dMRS`
zI1fo|;&|{&vi2n<E&xIX2{WzG-`}+xqANeem09m0A@%=_r!)C(MXxE?Yo=x&K1ia2
zX>86wp&?R4_ZdsKmW8gqv1eWv=cnHsXSl*hjY8A~pM2WyqXO=3U~|@;uO=|G9MsQ4
zu<fOth8lfN^JKz(T$OQrx|ThJS!Szq<^g3B2b|DzQEw@`xrsUQoOO-!>^kAex?XbB
zQ{|{zWxTfGA;OkSI*{Zc`elqSrHmiyNW>rwtdip2;Te3m0AxE<H~C#~ZlFOpdaJ<b
zuZvkX^%@&Sb_NbNw^=Hrv}li-czmLdLG9|Am>rpn<=&tK)}rxyTo4Wu|A?3bs2s$H
zNz+tg0$^o0i<k(3Qz`UNYgAGWcTwIo<qpHAlx+dbiW*TAE-eG(GE$}TE1ge38kS8&
z$s@`!C%i%-kg!gDLGp_uGnd5_lUHRE$aqnbU?s1nh;9}eMgy=Fft7VvhjZMy*^iet
z>rSi*ByNBO-$_8+mDqe9nLNN)JP&d{i_G?x!@rA%$h_g3)tgQyx;Y(`zq=t{!8pFE
z2*MpViERa(V4?pMG@<sP^_Y#Wm!hJq;`0|l!k>}aWYJs4v*GofUw?vaHzsvbR6v}A
zLD>CCsV*=KMwpZZAR?xLtPw<f7#5MmT{s8r(+$}r3Lm1+2p|o!7YEGR@iY#4^ML{!
zULDV>dx5={m<yh0sj9T)cp43}xr)NXpQRhl7W)ah*pkqg6xV5t8nV28Bq8z+dCp!}
zwMI`jqBE}b>V~O*(FLZQ`D5yRg%luZ(!1Jqb#-5cl+&n;vC+c%wj5H5WQc}h4!)UC
zG&MPm70B@I^-uD6j0tr46aGlvs$Po!4?ol6v``||aU*iInqRl&;lxNP(ULVAPFlT*
z1|;Zi+A0zIL7!rYiOmE;Lq1uN>vFj$FEi+WEn)%2p#3XT`9q;FUXdz8@74$du*t=F
z$~v)j<M6I>A|4noNYF~(^J=vB>NIAqFAa3-pperpP0jSq{HxTPi!WE<;V>zOr~c6p
zGs$~38#Spn<qk`WC~(Fh@hUKu$8&nuuAMaKNQ4$<%!8O;vT;#tg&efQBadA2c~@ZK
zy40dNciNHl!XzwgO{mEm(%izS<z~el6=<M852Nqw85M?{D)RGd-uLewn$8Zd^BJ{p
z)@3%O$?Q2eSU1Cu6OvjIfKg20q%sHLa4kA@*(Q+X5H(8=+pn);g|UGtAQ_j!-k5Tk
zIG%_GG;Hx&w#A~>GxQrf9=-EIGg0MAU7dRHxC>b-9dw42xS4q8Z9zKVDVW{Phl$14
zkU<zxZwkHXWqAopS~-5uD((JxjR)dmN9~k=Pwo)j0Aq6;j)Iz3IzO5?xj5%O|5QkE
zWZB8t$*HWJ3!|Y68k_!{o%>b5dQvxYJuNNzzwwwM_Q#7LX?@2eDh8OM2Tj0N@bx<o
zSEeG$>%j}?#<6Yuf*zY*Osh-yjR_m55;4pcrQwhY(xPAdT=>s9F~2cCw{ccJ!uXS?
zc`sFW4FPl2pr>*pA9MLB^v`JM{xqV|{2mhqJ}?u!!Mg1*ixJji*U6K?3aXnOL!DyA
zpjG_sOS#2Vs5Zfa*ISPR{?LpAkNjLhO2h29Y=49nly;heFtcs6i1A{nJfygShOX?L
z_`@=YrsZ>3S=O$6BOlmC@_(dDUx6PJw?-?7?#m~aRStzQuh%CB^=7=3Vb{djh?L<3
zvx3N3l2Fb73N8tGfNYN$q_2o3@90bfv2?pmYs_rK7*4>5j)Y8C2LYq&j$g_bOu#h-
zGZ3pXBo(6-pJUu9ATZ1>IFvoUwd&+sGw<B2qFiYzU?QF>VrT2vnvDo8o{A)ND`$iB
z^Rr|8zURJYmI{H$ktkOy{k2sz3}^0{QBNfiUcF*rcN8b%{x!lv*p=FZ10tFx7iVnb
z3wYiJvQ3jVW~7i`KI@iOfdP_92_k0KPHW3bMo-FE(gl?)IOuD#4ilJ0u`cRh!UGGn
zF&R{3t%e-+hZbT^tcMn=cIXO4SVAV82nUyBg<EUBX!>e~jJi0&RD8m+l8ox*j?6l1
zDk1$*U1<t-B^2HCh`B(>0*};j$ZP|~l9QPFWw67pjQ){+4h!xfli7wORp#ptQP)I0
zHx*eS%R6h2w<2PjyHF1?RjcmS;+C_e{k+Z12wWU%pm8`l!T0^2lluSENi;z+7Z6EZ
zLxIym!$4+->Ar+-zFyzi*g+6t{0&1FA0s6vRS!G^G2|g-9r^*;z*agc*_%DPhJVp>
z;|c0AqCX2qwUuQP8Q);)PjSXj3E=P_5iJOIA&a9Iq<Zz;4m1706FX$fp{1h*qAx5&
zXz;;w5pA7zNqd91kl9%@E4PJ`G?3^1?HeLuJlRtbTqHH5P1{2#zaw)+T`>`g)JXz#
zY4tcdbZAkzTpm;YAFI_vk}$%ARStkj`8Be_p6%n?I%A2`r=C1dCVSE0o2?-*cir~Z
zG8_$Jr2bAeC>uX=Or~>A9ZZJ+;X?Ro8V><Dx=DMNze`>_?7gAkN#GSSJ-SXjAu)ie
zmFo^$M<N`_II61<lr^51e2BHStek}?<4Y>X_g5WQ@3H)8#Ki#Ge4(9-E#JvG%gJTg
zF=}s~!OeOdr!4N*N<#vw1|n4t{Nhj|nDG+JAG=YBbe_Qd9~jC1#QCC}=+!F`@oz4b
zQ=>uwp6l56y?lza&1|YGvp(YJ_Gx|Ax@9&pNfX`z*IRv$QUwYH6Ev15O(CV6E5E^z
zB)H;iEBqtwg3oSlVHp*M8PScv^co;nUjaTTvcjcR?%s&acYp+0!yqB7{$0y3?L_if
zs5*`@7F+r1QU?Els9<db)W%7mz`cF~AOAZ^0Evt<eQ7%CZfRS`mSLkGmfo22MACmR
zJD}B+WTQQ&h<znS$*fx*5TWW{YWI4z@iG;Au48!@CS(6QVW!6f;QZCxVgMHk_?55d
zLiSL3mmE34xU!=N4=!+L{96`7guvJh#Z*$#vobcdqrm6BEh85E+j@Y~?7y2gw(ZK*
z{-k$g1xu?2;&Dq3j;2;%RXE$C?W`~B5kHB)p*2Izqz?&y%#dMB`^oIDYsJK)5zc%!
zh*u*6fe}qa<)zHgnm{MeS7*O88nYZ1RslKY*H3PpXXAO5-vEg)*6@mpH<4MialzA&
zHne(sR$xaWuw!NnV`S34XZ6ZN9YAIqva0m4e9mVfl2R@pK0B;aO<*LfD;U9jk4Tb|
z%g?RZ%*~yi2L`+DIJU~fUcygZ7lg)`C4(cG6)aB*Fk*#mv>dKqP;bD;di9+DkpwO*
z12l4x-04B}2pGmRed+cpVAQ}RRhMf7VY?Q0Do%P=<o7={CT9>dAUeZ(+DkD=8!+bh
zJ_kS!bBu@Bvq5$8L2K=xE0MXvFFE|-uAr$D_i~n9w(aP}Fs+h1uIpWHAlhDBs=!eT
z)Z*$y$`6Bz<TX^%8iV}i=enf*G&yC6pMXONz+knJ47dDEk*tO<nc3<&G^36u9+6@?
zFrGDAW;~z+jAk|FX;>_<A_(m>s3wKH%#c-DOII-{wKc&MXk*d@@;Ko^RNJddaosG9
z-m)Vk!ru9dRN-ziUBH*07NKx|ttD@jCZhE26(^(WUs>9U4H<j~{x9Vc3QdU^%jBQy
z!p`?Dkce-3`h$-Wkdb0B1uzxK!&QWj7UqbJ3K4mj84?QEG4-nmXAXB`9tM=5I#Z+*
zhy9{9cMP|NZsWR0mWxJ|q-VuIdS)+vC9<w=`=4vRC)7pYxtj7|kr~jMDHuXqs(v|k
zQeln_yFjBlg6y+)1`g9Vp3NyO$ET*+tE8zq4TL|3X(w4|AAb@GrjgU4GCu(|FVfk1
zt*@n|XzFx%bz<26K0=LiP!$KzAUxCPf7MOxOrfbxr#1dVXP>2`>bwLoh8q*Qa+0|C
zaU7t?#@tA^Lp<uW0Kfma4=<=V;T!C4=mOnOWX&8tAz!0C@ld0SmLWa98rB^<))jIW
zS9(>6@dyEXBj|XwakLZ06?jV%s$hj>v0$K8RjU((ID6J2ex+WduYh)~ct0YH6!zj;
z`c{`$5aq#ua61ZWM&&E#wz`5xmpW2dmyN4+<rvVI+(zBM9I)MLl+mPUZsY)WX#K~(
z#iR^k>ViV(@WJsot?PZvtDvcjp?dPVvR)!{qH#+&<QpbFri{BCj~%T@HWE+gGQ>*F
z<B8glbZU=a{ity3u?{~MyRyQL^Y4ZU$l%U$>ncdD4&=XOqv1v4S^}tD^g2w@Rf78|
z>gfRTM`ut0k%hlXtc3PZxvt?iSZU<V<^T0I3{<DQy3PgaEd_S}D&^$V6#LIk(JC)y
z3lMQHTha;;A(0fi(Tp$9i~K=D)by6B3*3!<k9If1>ymndy3zakMMU6Uh_m~j5=RC}
zebkB|B135+>*5xWrcbfWUPl%jE2NF9b`BCQ$JjWSY$7*$tdY;p>$U$kOS5D!aBcH?
z0bkQLp{0zZP+MtjS0dYEYfC@P!^?eTUQ$p#ahfO(gJ_Kbj48iYMUAWxG{f(i?mzMh
zDeD*jR&@|}$?M*^mcm4N`hTkR1!x*-#(s`;Fjzu3wwytDwh=DFcCD?HX}lw4xGV&o
z*IW7TvGGebE7ze&nhi}lE<o#VkF)jj|9v{XKz>wJRdt5!+_@+yC`@q5LWBYNfaxG|
zh1{T*|Nq@UjPPciBY*o_*$O4KM7<%mWLnZAd}|=N8{L)YMlM%qiW6%d=IzYP=cUru
zK)7%I`HBKT$2(^AIc9=>Ub_48A_uXoLP=QJLXl=scd_etvX>^Q<(ZJvnB;?KbUYI9
z%mZoupw%1_`C=9}9RO73UMKxg&i$!fJ^g3ILxPOnz85xH|DyZmfV=wT(C`(KIAUhW
z*Kskius?W@H*-~3+`i<X=I}(lx<G-D*3Mju&ZJqo&dHqiEC81OfpR-GvU^gN*w?<{
z<8hIWZrk3t(}-r*-MG_CdvHb*T%F}l@YlI>j@H{E#?a$g;$!@(&|b~#$hqC~4r-ct
zlU<_cx=;8DA-#CxZKm7*bX;@O!OXP2BSr7{Dt~YL<uBBg&Rl64Lm@;AC#9dB_l(8T
z&@Y~|UhKRN;<!6*w&h%2@AY3Upd9edQ(oUG4Sf%XX+P*^E8+OUX2_NgzkS6b`~~mF
zo66AYkEtim<Aje&V;Ne;FVx9#e51!M3K0q{C2il<+Q!X0zyJHCtGk|8TqW=Ha<p+^
zzkD{)SC*coWk*&33jnHfF)GnuzLF7ZqP*xlcq$+HO|$DdjrGp6DiyM4Uq10Y^Wvk+
z|29k9|KVFjHO8%zgf60s$tD}JXzjpTnpS_2lU^J1l%U``0z2!YC(hUEA6%7Qbyp|A
ztmGE~@c*(N)G<X0@^y#KpMrx|>|4K;Q&ED(b+S)U6Pkfb?LVJC=kHgt5oGwxcs1?O
zz)2a6Dd?#${ljqPBGDjzFrYWpG%&sTyzzdc=UfTdI9}Mfo`2d6QO$mQ%@({3QOed5
za5XtnJHkG1Fh?V4c?%^5pKbW9t=apm=tI73W)YQ!-e+2#j;Bk^aUlFaOo9*#*PWh)
z@YKXgg(fG`rsclm!Q3aXtINq{7I)wFW|Qvz>wRFVAiBW&NPg_Q5Jxw>>7+p}<ngwU
z$Ey!)2a*c3CGuqp_#eNKzE#HhoSRO=O-%m^{pMZlhAHT@Ef*{Bpo#JNEKd4sU~8r8
zVV&Q9cfGlbxTV8Ksdo*%gD^zW5(D@9XXH}7Bve#|MD%BMj&tUK;kS*4uJ-#b&z*vC
z3O0vNB$^Y}hJs=0s?JZ4%#lQlzoVTm7i|ZFeX7NzFUJQPuD5GzE>MO&W{;nfw^(jV
zayfsv-mt?^4k`LR{TpHKd@${HG#V1}Kt9exR^uAcfZIRTOg8=`vC!o6DNGtIFp^{d
z-avb+{&(rcb?HEkNDh=*Wk2&D;1(3^!`9xv=SGJpPR($goa!$W#Km`8q(XeI+qFB{
z-7lmcRC-e4`MDT$kH{o_#&kL;mc)|sec$&Suz8g;q~-d$6L9ngoE#GWY$H_!K!t5x
zE;n)ga<KWH*HeToA>Ux@>u6(ewx6h^FAFDSdF+N2Yz%Fb5CCiBtH+{Hfq*CY7gfKn
zT5XIA-N<fX!|g`MX8k$RNZhVWUe0&fngP#>AbiX_$v)9sUHD7Y7f2E&DjWt;>s}^t
zb*Ja{$W8J3-Mf3A83(owfkJdqnY>QeV&cqiWw+{q<!QsGXm|R+qBusGLQFwf%*BQ)
z)&Tlod*WhO%NNES<(3`1taEd5qlD?<lF;I++Xf@wu!~xj#3ljLwhNDf$>B4XWS}`F
zu2Izd*P4K$Mjv;1flCP^$DGC&5$}gbsMyZSy&1b7ckiqQ_t(TUglN+-YEB*TSCUwP
zo71n1#Lb@~vEJBey)3xw-Xf5bqoozVLc_VX%`U6=j{=6L_}sLOF|lvk$?zv19yE}g
zSdV{6i-LvL1~8C8Qde{wY$_>bI^70t9Gk;(a4r+rA}~ga=#Li=Z?KyNGQph}+HZt?
zoQGLfXi(1Wcly7l4<&ck+I7u5qjR`#cyCsD+Y5B?R@UyuVHpbfZJi8deO%Y78lKYx
zGg3YkQRFvAw8y%wF8;$XP=LR9pBKK^C+8>|A4C=V(U!Gw-xZ8fP1)09+iYj>5ZCAb
za(TAF5Fzu21@zR3{;_|RXfKB8@-&Wxh{oYg+ImME_R#fI<*O<-qvSS4#Q#)iI_3Wq
zNGqhx$kR0R<WzYiepB84@v=^<qWx?F9e^M9aYz~kcDslUi(S2+^tS8rcIvTX^Ef=}
z_SmddBH@2CE15}wv(I$k2(KhD3fs5m?KqeSdsugLcws~^f3R_lLifAbLg>D8XvC2k
z%J#e*@<Y%X1JS#`#Nl=M+|Fzm@}nc`S~nyrb-XpxGM~(R+`kM>`j|D?WNv#bK$0-5
z$($_hBKdb;OA&+~hAingu+s<_ql?6Ha=5h{v4F6a`mFV<VurFgpTZuL;&NlGDe8@?
zPKoo%mivf>{YQ2O+tF4X!GZkiH%Z+O!{N-t@6&ON;%`M~@=u>VF1tT6QN?}Sg)h(T
zsu7Z*LxYdLSvp#-Fscs1OP_8yuDuh3EBWPDMAZJOVg%*E)_bq}A292^LOr<OuYy|-
zx`H2w-U1B;o-ez7H^Y^B&3M#4h3WPG(&Lvu;yF8d;RS5|DCT_GY(LL__BebzdqG=w
z-stfbdVGrQdSLHH(k!bql!BKX0ul?p$~|<PpO^YOsm5OYd>D^I@IU*PS}o$tec`%#
zzn^<5&Tl99oazs2!670xhYX8I=5+Die%^U?`PgnJz;l0#xAg<ZPRTX%ce#{4`ZG0U
zz`*Xt3Dv{LNOy4GrF!8^pjb|su5$Dn;fcRT!gX=0Q*eT5IGzQ=hqw&}&UZ#O-RH*G
zj&oxF8{zjMxw0ERr=A*-Hp#m2+qa$>?vGXYtLHnVw{+83;fQ}^^>}h&SgAr>9+(ut
z#)1FH8l?>$V!EIB{av0ATDt2G`YxWMO@-gWG6h5|e-rFt#qH=S3-M3jI^SL^k`TS{
z`}3%0(t1ukyeSR&pPOb<h^Ud((w$Q4$xwv3tv+Y*`|Zac3yi!^W`)H<&RIBF4>S%e
zY571QT@z5Ewfs+s7pwrx)AK39kq<r(ZOH@ZLf3KDr9P+0<$Vp+X#W9^1e(3^x!~hr
z@fO=_9LJ04)L>x+dzu4^!L{#<9piMasO4|`UEC1C>o#|v$FNw%yF^1cR@^?5F)uR0
zgCw?`y*K-}kdbQA*ArpkXIfGb0djv`My8bihO83VPr)g@agQ$in*Xsai;nSEpSyGK
zk@<ZDy3^F9ZTFhPOD@pw@j%GQ;lVb!{wUbn?&a^s^MVRroPlhPT=z}nHmvY{H?f18
zk(PkRE4!*i%Rv)qe~rk`--_O9ka_h0Kgeq^A4<Kwe4L7dkbmw`xJK+O6u3Ed{DeT7
z!wa^imHR*bS|4Ov)YvWh7ClccgP4}JO1tHGGR|TADnX~qEcEU-FmqkZ&Xmv$>Wc)A
zN8efI{`fMSs9AvF7ic&Hf_84Wh73Kvw{!m&hGE7GWim2beH;mg*WNiZy0IR?W>*4s
z!lG<}hhFCc1G)_^5LrZ99|^Me?xs@5N0nhln_;ZL`(c>y%MdNDQs9xkz3+>!`^T9p
z0wUBu;qC`4;hT2%j~?GOIvA*uV^06EtvbdzshIaeX5!_C=cBnI$6as#?c5y*8t4vf
zqFh%_-FRp@1(_=OZpG1dJ8ZwA&@yGfOj|XeZ@f3XpegbGRW#i{M1N<Nem~51sb4@K
zeL3yixa%V{Z+Y<cE4ay(;*KcaBo&Nn);4k6ZE~%qLHFI8YG=@gE30c^t@~zO1^=H;
zRLB$m<bSWEEhCHIJlKz{RCkeSV%u{PwT>GLTs%jAovv2QEaX4k_y`w%+!Xi!7mcu!
zTdC-L4*^u~$7uWZ2S$5R+wJ%lC`3NRlb(+)cN*J&cK^B`K3<pXx+6s@QHP>~>$tN~
zd%a2D871I5U$?S9hPQM#+KiuJ{qM75{BGU9#TE};;&<`YcyA#1y=Kd=ReOI7Z1^8W
zW``EBNgl>oba~wFJP1EBe7sk2`&@+bqMv!cy$L^elRV8C>Y`ZD>CfttT;Kk=&LVw5
z*qItq5_p<U7D8n}Xu4=WV6?wz;5s%Rc@w@<B7L>U4pG-lO49Eh_)~5X^A7$v>0$P3
zTRF?C`CGDte7UJ9?EO*v-dF4Yp8a6oZPz#ZK=iEpI4vAnEOdQ1#ErrcKxyv_e)~Af
zzx*oHC;vKtOy-o+deU{*m7ni_Tg@Om75X<Zt^7Ym`?V+6c1{(c`+0mPk%ZT$R=FoR
zu`Wi%j?@F(eF~?VMX_dlaSl1)<mwLuA>piF$&M(zE=Q&WANvp1UxpxL=%8zq-PsY2
z<vQ@fe<KvS#PA(mI#&1vu0y%@=_<W{etfV_q35wfVWkKoht|mfLX${ZF1Y!7u+O|9
z?|zUgEv(L)Ce_2PAAbJU>Hm0H{XQiAvQcCF{?c_pO9~O`(B#{lPIB<rR~9{`(q3Ao
zj?426-;LVht{+wzk_Ua#!mn~4ZL%2pQ}4Fk=n&roLeuocasnX>-9z^KGOYidBNc9I
zDai*%j1e>(?d;8k|K&S^-+43lxt8<32=F0%YYE}wd8%F6|7K;xSNKx(!T%ikCvs{C
za7!K^8~38yIdkQh65ao_{|Rri{8;bE$+DI!yPDwc=A4@Huw_m#t6aI8;GFQ|a%^+8
zg^B`!&-=XXh*6bx{VmpS`*DPJi(QAH9&KL_(30X_yJ^zXmk}A`O(7Ut)a3$bN~E;+
zIEY*E_qlG56?m;hc;AK)Uqf|IzW3pk`h`q+wMMk7)FMF~5F#4o4@;|Y9?KKhmwQMd
zN&>9F{lb*+WvXy!pCw%bCm-5A(Rh1`d%NB180kl{YP0_?<AoRx0Ym$D@`T9w38)zV
zlW^|0*;pd)SLKqK+Nr}TtnQb-ZZD^!+j+_Jw<^*yE-y?_O!nI|tf6m-mk=k1`6$YP
z(d0mf?%RqZ$@5}uDFY8nGhT?uWgN4Q&&|9z_o|=e!^v24m1EO9kLC4xI-1ht>t92k
z&m3OTw=G`Mo~i4Y-INedjN19ik%}a25ynIEOXMfqi?<$1Ra&9T(hrx{{_mM%FCCEM
z#TFgQR=Qq`e3b)n|BmLKHTyjhf4uC1hqAq|hY|ce3x4F2R*z3Z*9;)hv;W}eQ)N2~
z5yy9sGLuR}R(Q*5KTmHnBz>LpM;DC0ZW{bAjLE(bW_s}c{8(Dd#q7F){;Gzc&<|f)
zIyhRz0@!+FkKK4<5S~$h2O`Pt_1RCJd5z3`JOryIx1FGFM9%AtBk1QLqV=dQs579K
z2~;&zz1yBtMHDkJN+zn_{KYFqgxHwy<)1&s!aI5?4}M@JC9f(H&(|5qB8wchsgS_r
z;kw}6x(^w=b<Mz<T%xAkEz^f=rVWGpTHQ>v?)AyX!^K}yIAn!rH_tGB^)^%Bc5&&<
zye`dHLX}1J+ve2k`7U^^=A-Ik$08Tf9L3U_16#l~oF|F%fVqc!`M4mF6;v46x7Wul
z?=S3eiIQEW#~mFGYZWEba4W9lYj+$JX5WStE@>{kMWl(FaarZ>R*;Ui8I9KA^Ejaq
z+li3%$gG;o=hAmJd^(^<#8K9s*V^U~9UlA*D@QgL0LxKaC0<6pw`0-m=VTVa=s%Sy
z95k*WJaBkf*>Rw7a-6>LVJHMAnQsi$m{g<Vd{?4$FgE@(;D$lWYQ>;?W)69C_eqsD
zNlE=#ohGN60f!A472q$>rBxRdr}TPyah9!%m+F1d{k((~S-g1bc)Hs1lSr;`Ms1?i
z^I5CMRo&rux{6+zV<^VoZ$e!V%^84zvo`AKdpfUKbl#hLVh}qYB{szL9M2JrC07jI
z-k{BPP8_Kwd0I47(7*iqx-KU%mM~N$6%#UAY)HQYaR*4&Z}$7VH+&x3_|YIX{Y)@e
zi!1*id>u#sQe(Q&iQwN7fk28wB<wWCPcw0V1vxG6vRX(#)4-mhp}Pv;p<arBR1HJ>
zY*FOre>u1ksL2CRlR&ds;Yl!bdQBaYu3A?KlD-G?%xKqW%){u?j^Xn@S3M9J*cbR;
z{_%etHjUL-G7Hoxo=n~Wkq!jdU)ia|P-~p$!)6}Q6Vgt0{~$IhB*PLtq(;jIO)Bc&
zZ@#a@jqwSe;vmK5agsVZyLgQu=!rrp-cGG^+P1=?fc4w<k)kuqB@oOZZb;u&A9&3X
z?E2yFZ9z(+?s{;w!Rt<gMD^>jPQ`#DSL4%9*Al?CT)Ko!<DztsMuW9kN#*mYkTspl
zOA*byohy(bcf}27iOsWV5zj`ZVyfz~#(djOQaQOttmM0~N*+_GZP@Q$RP4@E?~VrN
znW_AL@L*P#FAhd_f}Jl`y(crhyAM`3o;vk5k7N_@CWlQJ+YNQ<chg%5PnaHE<c9o9
zk9>Y(UID7_7nG{W6|r}Zn~=(QoLIU<a)tsuVjsi}lr^gAXERt*&HKOIAl+WL9e@2D
zrRmZNeaPI7_NN*4LC;yY?~b8Ps3OZ-dEl1}(oFGft=0h~mSOR)s7z)ZW^Kt=#5=gf
zyO@7C9DsW<akHWTaF3Wt$&jFIt{T0;bsTc1E<u2&p<~<*>qKxhj_jBT|N5eQm{1Q^
zt0piVkmG&V2CTmrj7>7SI@iCQB`p{je(b`A_dv@oC+xafXtcxPVfhNiC3BVeB_8U9
z4>l7=k>X#+5DbD!*tf1a7BbvxWu0hT7^8NW=frlsf5K4?@qhb!vxF5&?em1%N*XHU
zWjA+LzCZ<jt-bR5#AU@L$Q^HB-=Jr|F?pG9`|0WX$rsgpLn;^je;M`c-!9R5Bzng3
z<1;{mA?`NaPo?=~(iPF)E4zJ1oW0kcvh&Dwt8f?nU(FwiiVQ1h>lGO)r=UH+#8_n0
zJJ7{v2>vIng?8^aGzk7uQky#?h?(-pzwU7g-1Zu4ecPRc4Vx^j-qa1%(wt7cG7b4s
z=gF!N;HSJkc@9zK8u$(hR5+b!jj)Fm8Z$d>Z91iM0p1n+XggqO!s!;5X4bFDUKw0)
zi}cKN)~)1-jz-o<s@{oEi>#*6GF>zp8PGNJsx8iL%sqds#3&}99EA}h-YWNj@PQw1
zgjo=c=nzX~LrHcMOrr8a_w*CGp|s!`T&*pu7w~&TxC<AG4fC0(3!RoWS5_I8C+o9l
z#>WbWj#d2=gFCWP9fUa&zMd837SlAbUyx;C!ND8b$>Vn^vTiym@8paZB5aV{UTe0p
zpZ1beH<ihHQLect;2=H$%ROIl?@>QumpkyKbUkT}<j>)8E1tSSmX!4D9ZL7+dxz`F
zzJz~loltTLwXEe0D>RJnJPU;)qxXscH&grRbJ?FFWwxQS51ucP?jC*y&g%nSUfwSC
z-ji-FZWWJK`3I2h^Caat;T%TgYPLh0$o*(tXHTv5-_tK##O8NLxSCBjsy-VN+rJ@Y
z?q^EVudk^e>Tz-EKUA*9CUaM6UH`>fako=PaUYd7gOeoTQ4ZklUN~+Q^citgH&ab!
z)Y^Wpxf+qqp#CxB3EM*tDfYbe_^b7L`Eqsz7UZsK-SZ=8V9!X3c@b#4LDz33)lf`T
zb{%!O!>yK$j*`je&4-G7onodqBNUu;I=)qC{`mE*>O!Re%SG+F+2^4TI|%ZuhW;hQ
z$88EX%BF!xkymzInk5}gDzNztlTA^9^PrKQW1x?jrOBNZ=lc?~#Nq8yBCXQY`(l@V
z99|a9Al<Oq_sLzdM1)cS9(lQjuYAwv>6!lbEdg80g?Ev?=Sn&TD?}eTayZKDPu;tB
zaf4pXTkAriT%G8c7>D^%)tsD7AN>%;4r1s<Nh+Z)Kq3~(;$|vt($^Ji=2*YP*()de
z802yqjuIR285s1Bcw0AZGGGT9@8tRaAb^}6hc?C%ssrX3(uxGjYD#K*mN>;EeZKaP
z!$`2tR0y%W8BhBu9s6TMw?ppVsYeLUO_UuiMO~@6o0}Ugh4tH=e;IXqICNS;J~AzW
z)hwb<LjrZ0?Q^B{U&TEuc1Ww6i}#;r&L`pR6;p$aOpJ8&YBpmzXqUXA)lsB05Q7WM
z3YB>9lqR)l*?Ae;XDp($N>%oI<o4amC@!Yr<8uFuDAliZGdAUAr|-6Omupp@IYdt_
z5XAQDq&ur**fa~ncg+9(PNF+Zvc>pH(A8prk0A4&Zw6G#cXk`~VKILl)65|DW?`@T
zCTm8MyEsB!_f1(QkKZ8Ne;RUZ6hW|5WJX<JQN7rFnBDcO%8LDM$)>OTR_b{KT-<<~
zk+PNfR+h2x=*rKt6D1Ej_k;Dwu13x_xtAun2hm7QUnlhjJN?_Vp*+`E$>a)Pxh}Zr
zr@qTbTip6_4%vUR!`$@aclE#5P9JYcJMR|1Eynp|l@Rs}34|){p3lln^z_H(K6Phl
z($Z;>OZBc%n8k-#;A`qbtM-S|>5U9==~<57MWQR(6V4xn4F&tWVO+90wZdoGwMXq)
z-nNMT)n$*AiVxD)t8B-&$S`HR7u!*7Z4xuE_7It-q-0=zM-!9roe0TkC=tG(nM$>}
ziBvklm()B<pTX!l^*Zp~kg*^i#?AdRX~6Z6wp#5%a%#QSr2Pc+jvwM`dW@ec$tEl5
zLxIhJ@tMFe9COYX=SDihSbKPndFT|3`#hnWMKh`P%eS_T?I7FB?d}$(OevfB!}{9+
zSZ%Ue$hYf{?YB(f6>NMoh{@#?kpu3F1;@C(`psk(0iEtIg6YTK%GJ+4r$$O6hspT<
z#^(4LM&n;`l$ZEo|F%$6PFkAE>i_uJB4jHHfV;k#`ME8xq2r9y-=O;v_gIcUX<PJ8
zQ(b`CXWzn9E?bSu<>I{kdP<>&qT92|bA=`rO98Oq@}e}a4L?We^<joByh}cvsA@j1
ze`zIq^j%o@w?g@f->GL*(@R#_w@g`BF4TfGS>pG93#fQ&aqa#b_p${F(#BB&x2%6q
z?|^A`U9q7y`YfWE%|Wu1$<_C-vZgnElO?~yChgEkW2aLOxO@x{kdY{K)e;q=nS49^
zdKj}1c>VW@)H&8Vh8*&sfL?bNpS<QhYZ&VGz9QFrK4ITOH#(Ln>*3+0k#-W108tTf
z7Z5jnmv9r(RDE*SM%f6RKC0(t{BYd<uJrN_HeIuqM(;3Q&nX`*hM+Gl-&w}-+<}GC
ziI*w|OPW`JUCL-B)>?C==LvJNzKiWS6AsoG7|_|gb=;o+(sXvXPAQl#u4*1ql%Z<1
zJ%o(@Wt22P8M7E_q5E?BN!4O62^&d$GJN&X$YY1w^)!^zCU7Rn-N3r#c5-!!d-d-7
z;Xt-jQ*%E8+81TZ<BG#BFt}^gXNtCdZdpAc$=>kobvc<Lu32Zt_uV)49SRDqL`FhX
z4S{|DDAYzK@IWwSWs~<X9U*<8S$#>(M7uHLO~2~AVC#xfWwZLqJoB&~_3&XRxwPBn
z%mnP%os_NC399Ynr?e$hR|E^l#DM79=2jY8uWlGlnBL`2?3;dIR==!_p(HQsD7$;V
ztlQR#doPqVGVUt;t82Cuf448a>gx}|MNKAsb%?N0sU{PZ^4uvDA^&fUr=*a=9eL&1
zTJ(PKpI-1-(0_8PPWjR0F_|~ujLR8y`55+xvJ&ACNwbu^SIKwh^=ti2qDfhbmI3#}
zHQ#kfov4IMi;;p@ks)PJ20nG@bF%QuL=%6S;B}9om;P-gn1VlhOe^RnBaclgV?gNN
z9EpEt+c*9TB?!3oHQu3u7so!L&sQ{F{?$DzY*Zp9Ft$IotyXdB`MUQlxF6Vdn?F6A
zm|mP0v867{9Pp3;qs;b7=eSp2r)%1&z0esy{5nS!X@SVzy>#zkRrfKP&L}+?$|X*U
zc303B8VaekZ(Devl6z@Gkehum8KoU&asLndU4LDH%nGc|Fvx0B;gnG});nSnk~jM@
zhi%01QyD2N+;seJKdWB~{Vp8vZtSCNx3>F1kBJcFjdB<>1O1O0-Ehe-u#g+@XSqA>
zrZG=OUf@<1do%0vG(Uq5>Fp|T0`(zOkuUOjZgl_0-{~F@Pr3h<cUG?5SN>%Qajqq7
zzwMKW?)QQ3d<l|y&BbmDu8j5_CC(S05;S7y5q{WQOk!p~{5UH+F}XN*`+~5aF3K*I
z(R-p1ec6R9++}^ooQ8bHYRT`%De<#*QE(kt3Cz|{#^<TnpJZ#&wYbH7vWp;JVHGir
zbEtsuVx;{fTE#+*v96}n2XK{d?O)v;kfrC_fS3VM+b^SadJ=HBcTh$|CESVO`<OkW
z{rhqWLTr!A`ceE|1l~c6lr-NpK|c5D^At{p8nqn5kGfy1by}yf-qzqS6mG2oIMjbX
zQIIb$r@Fg#rQKu7f+0Xys?$Z*cECxC=~h}%z&S|Kebd!oc~&$OwpMv#q<N+(jOXp%
ztat+W#5bk-)kv*>NAO}n$j5nW-PP~%yu)5^VfEf-&i_@ni-np(yLvV%P9j6c4^M%J
zH>2HD^~8(0Ua2P%CjZ6*Dv(4tMJ|g*OAYrsT<pB?$EJ+?gznYFM$FmNN5<~&!xJk{
z+na0BDxRaoRymTVIu#M6@iFr*;@zLp=F4iWPnE-y2j=UVgnmBixy8vK(6YOoKBl(d
z&AA-%M8K-;51F780nIlQbk8IJQYI^{)10_<_!M0HPvg^NQQVg~es<ChpSv63aRzy(
zg~+(ii<V0(TsP}!m(SI>=SCebf0qvyr(S1!FJrr$zTcKRQSFJQ75v#q|G)OG{GAEM
zk8j$DCFP1f<gD4u+(c-E9L>E%NSfB9)aEEhY$#{Uk!$XZ5o)gbxH?9TusL(I$|6^k
zE6MTQ_uu$F-(TLpzMt3odEU?ad0x-!{d)DNm&Q8omi`{tS$%7jcmC($qd~zT)eoix
ziknR&!Xle0H??4>GLqS;!v<k$FMJ}y!#L52##h7*o12dphAP*uCS1Y^xFIM@)e%2C
zXZJUQ8P5#DNL;L$pL_s^lh$zgTWmSz7fCd0!)=_V5?}#dTO}bv&I6S!*XO{{f2HLl
zV}c{lkOp$3GI|$3&%AgwGnO_`lM`{ZgSpE3K>YOiFY$`K|2|UD@AHOV%U{$^G&0Cu
zz_S}()@{FCAx!H&C8U9QUV0(xj5LF;ZxI1ouy?jO0?kZnH?k^|l(@Vtk6&;#`A4Ef
zM<*zF1U96~(=rfVHLXnK&aK1;1y^k8I2S9u#*7grH4LnLfx5tN<}lM}y^Zn;b#yCi
z0d3GheG02{!7&P@9B7=W_m{d39=xpklGlmOqJNK}^;H`B{u}=4I@PEBv+UV*uO*Ry
zD!&7gN~Rh0_}8>O7qGf8x=_sUTH|E=>4{%{EzPQ&h}ZYNr~q?sz_^y(cMPIHj)OG@
zL0*%|i$r~fJz96fE3Phg9CGuzr%Ee&T0n%kxsvc>Mcz`}+r^&_Q7In)+L^IZ(GmCs
zYdB8#e!lO-a=av1O0dMVnVdQ5(kFs0R2!Uj2(S+v8@<%>4yLSLht(*luYea`B+im6
z)5{a<<rRXNA@BEhZa@2b3!`(>Db?n*rloaQUzzHndXH6`=GqhRFV629gj74EQ#&EP
zEF73le*BcKZeeU~NG;jZ5gu2Lf%D;)6XLf$K}iW`KF6R^^qr>tWo0z6Ls9DugGVo(
z%0Q~l^45lM3;s0}-15<B!C%t`fA_)!Hofwc?wbuSYCY!khbT1Ol=>l%(=Dyuag#+O
z)e}t8fnaMcMXd`qT2=yT7^hIwTvkh;>18{2G2gEWWh+#ktp>RtoUzUGtT~y2>ZRWu
z3{n~Qzb`$rQCGi`_3Zv7X8en#!~i47sl9fODk8;h_nIg`IIp<+InRa%J>mo#eTz-^
zi{4>>;(sAJ7UX?FaGj#F;pgg;N7b(r{qZP^fq#AR@RId4n#L@mHRFB!QxfOiUu$O!
zYD_G3lj@Tg=SO?c^5bFBa(&yX*{6^;t8|_qR1q%1Vn*efLyB)((b*9b#Vi@4#Tt}Z
z8JqAu@8`5s09HY?Uj@Z{Wh3Olq%&zxt2#Y<8XowhdI?WuqEA;4g>1`Gr*E`X*|@(9
zFW{TV^dVOVvu0jsGaehf#SVdbeIcWwogVXPXzg#$6&^jA(i6YjADTO8;<OeDLt5MB
zzeTtoKhF)fueqC|pvcH*3eqeWY$VEBRizD&iW<i@8Aw3jHqL`1rgif8(L+fjP7596
zS@6%bC*prpyI}Vns<1u%&!O3g@}Cm=V#Y>szDWscy42o9gnGkH^$<0|A3m#dV?N4w
zx3}jV|HgADR;IDcvLVCa%_EC(!?v$I0l1A){1ErVD6S^*I6fLatIQ|<MF%^7g}GP*
zC>7v~IOG666Bw>>Ox!zTdI6>djB(@Z^Eiw%(jI7~ci@{DT@dH9!<buLql4ZMMzWX=
zaW>kc(Dv{N)8!aboZ8FglOI~eVdeFWGwg>&{SgStyXd>^L}-GRQjGS_w_1gpI=MvM
zN!_&wZE7}&HSCpkHOF+;>Q!a3B2|f)W!cNirLP@y%ta^L^zfzFIBC}caQy)P)$J-I
zk7cWfJGNaN{a=u5M<~tN)cAGp8~Zs;jF-?K)x1&(y3h4w$Vx@eI{R_khD|*e)8OU4
z6#C-MKGSI~hal!8kfopZ-4kee0JNR`CTZ5@&k-!qwM3n;B-rn&rJLJ4J1i;zLGI_{
z<5ESUj$qxy1Kr?p^@*{n#USlfWfiN8S({+6Z#X;RPN{5Xf59aGa%eI}8&S+3jk+G0
zY>ZPD!<4caZ<bZ@$O5Abaj-MWvuk%Pgmue-alt9FH0`{=*m2KkE!}KA;@DQ!#$rXH
zC3apAzZ}r#q2xfh`Q@sCanFQy--v|<R}AWd2<#abhSYK4c}+&?U;lb!xHV1gAPJJ9
z*!~!$&pa4{plvB7IbKjYEXJL4*EaJ9$9eDFuq9#loT6=3uDQ^M-77Gbxg@<pjY7Oc
zn76xKMM!V;)qU4mjQS^gaq+2~i-MN>%-*yWh#euVRy!O>qu)+Br{^J%|2zKI(9F{2
zoLi;N#PPdNsr=ewSu<m5PHNEFMZ~1K6j)0(nOJ*nx!~=HnIgkt2zv4QMp0d}>gu4S
zue7>D)8$U`DzzC|)sQ-;2_%^yv(Jnm{Bq!IH?l?Oz?2AVjk0FKzEKd3@YRPB?Fq(t
zniI}RjaOq+XdoYEb>BkKBrRh_m3uH`#A4kDy^M2%djN>%XHJ~_t$1%41{!yX<e*0k
zVj-jc?&YpmT4@7r0?}aZM*zvBZEN%4rp$@(UMcr5L{0dK?jXDO1QY2H%LgB)jKN18
zG2_DzAprvuX>&i~{qI|jH85mcL+<IwU3uOj^jcHiyJdZ+8b{7Wdb&AM^NB&X7P*ho
zT3z1q-mbU0^ABo7^LsBTKMbAZ1~^Pe!rly${fi~#6Fu~Ras!6v%BjY$Di9NY_{+ey
z5K3bX8k^YFJ76eio#5E?H-?0g0CdK%ewFO<u9ag7vcnr9u>s}IT?iGH>tyF3W!UTj
z8sy0m*&?0X(^nIBt|&$SpbOA@Nkf+6=;P>~+EMZGBC=EKM|{uuuVJ3)CxvZ!Tn)Lg
zrnm#sj}bHFu6cz^kx&OTPGvx4O66U>Zg!Yi6y|*?68-!Lj}0U_QV#dm2eN3|om&kM
zIX`(8AW35Wwv4i3ek(_|A2%Ooa<-OfOOi~If+kX`(--qpBGaz}w!;;pPzUaaTfKj%
zNaHi_W=4Gj?fntUOo$RYW+#>CU){_RK5dFB0!pbmy?o|T_`Ute1@lAY?OmJu5?{VI
zsRIC8Rs4Ly0DuYj|Mh=p0<k&!007|UQSzRg=~mj$O;se%GZ_G|wy-m=G4m$>2R6Ol
ATmS$7

diff --git a/library/simplepie/demo/for_the_demo/sIFR-print.css b/library/simplepie/demo/for_the_demo/sIFR-print.css
deleted file mode 100644
index ec89b1961e..0000000000
--- a/library/simplepie/demo/for_the_demo/sIFR-print.css
+++ /dev/null
@@ -1,35 +0,0 @@
-/*=:project
-    scalable Inman Flash Replacement (sIFR) version 3.
-
-  =:file
-    Copyright: 2006 Mark Wubben.
-    Author: Mark Wubben, <http://novemberborn.net/>
-
-  =:history
-    * IFR: Shaun Inman
-    * sIFR 1: Mike Davidson, Shaun Inman and Tomas Jogin
-    * sIFR 2: Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben
-
-  =:license
-    This software is licensed and provided under the CC-GNU LGPL.
-    See <http://creativecommons.org/licenses/LGPL/2.1/>    
-*/
-
-
-/* This is the print stylesheet to hide the Flash headlines from the browser... regular browser text headlines will now print as normal */
-
-.sIFR-flash {
-	display: none !important;
-	height: 0;
-	width: 0;
-	position: absolute;
-	overflow: hidden;
-}
-
-.sIFR-alternate {
-	visibility: visible !important;
-	display: block !important;
-	position: static !important;
-	left: auto !important;
-	top: auto !important;
-}
\ No newline at end of file
diff --git a/library/simplepie/demo/for_the_demo/sIFR-screen.css b/library/simplepie/demo/for_the_demo/sIFR-screen.css
deleted file mode 100644
index 778e09d2b6..0000000000
--- a/library/simplepie/demo/for_the_demo/sIFR-screen.css
+++ /dev/null
@@ -1,39 +0,0 @@
-/*=:project
-    scalable Inman Flash Replacement (sIFR) version 3.
-
-  =:file
-    Copyright: 2006 Mark Wubben.
-    Author: Mark Wubben, <http://novemberborn.net/>
-
-  =:history
-    * IFR: Shaun Inman
-    * sIFR 1: Mike Davidson, Shaun Inman and Tomas Jogin
-    * sIFR 2: Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben
-
-  =:license
-    This software is licensed and provided under the CC-GNU LGPL.
-    See <http://creativecommons.org/licenses/LGPL/2.1/>    
-*/
-
-/*---- sIFR ---*/
-.sIFR-flash {
-	visibility: visible !important;
-	margin: 0;
-	padding: 0;
-}
-
-.sIFR-replaced {
-	visibility: visible !important;
-}
-
-.sIFR-alternate {
-	position: absolute;
-	left: 0;
-	top: 0;
-	width: 0;
-	height: 0;
-	display: block;
-	overflow: hidden;
-}
-
-/*---- Header styling ---*/
diff --git a/library/simplepie/demo/for_the_demo/sifr-config.js b/library/simplepie/demo/for_the_demo/sifr-config.js
deleted file mode 100644
index e7066b3613..0000000000
--- a/library/simplepie/demo/for_the_demo/sifr-config.js
+++ /dev/null
@@ -1,40 +0,0 @@
-var yanone_kaffeesatz = {
-	src: './for_the_demo/yanone-kaffeesatz-bold.swf'
-};
-
-var lucida_grande = {
-	src: './for_the_demo/lucida-grande-bold.swf'
-};
-
-sIFR.activate(yanone_kaffeesatz);
-//sIFR.activate(lucida_grande);
-
-sIFR.replace(yanone_kaffeesatz, {
-//sIFR.replace(lucida_grande, {
-
-	selector: 'h3.header',
-	wmode: 'transparent',
-	css: {
-		'.sIFR-root': {
-			'text-align': 'center',
-			'color': '#000000',
-			'font-weight': 'bold',
-			'background-color': '#EEFFEE',
-
-			'font-size': '50px', // For Yanone Kaffeesatz
-			//'font-size': '40px', // For Lucida Grande
-
-			'letter-spacing': '0' // For Yanone Kaffeesatz
-			//'letter-spacing': '-4' // For Lucida Grande
-
-		},
-		'a': {
-			'text-decoration': 'none',
-			'color': '#000000'
-		},
-		'a:hover': {
-			'text-decoration': 'none',
-			'color': '#666666'
-		}
-	}
-});
diff --git a/library/simplepie/demo/for_the_demo/sifr.js b/library/simplepie/demo/for_the_demo/sifr.js
deleted file mode 100644
index 0a8b1b6dc0..0000000000
--- a/library/simplepie/demo/for_the_demo/sifr.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/*=:project
-    scalable Inman Flash Replacement (sIFR) version 3, revision 245
-
-  =:file
-    Copyright: 2006 Mark Wubben.
-    Author: Mark Wubben, <http://novemberborn.net/>
-
-  =:history
-    * IFR: Shaun Inman
-    * sIFR 1: Mike Davidson, Shaun Inman and Tomas Jogin
-    * sIFR 2: Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben
-
-  =:license
-    This software is licensed and provided under the CC-GNU LGPL.
-    See <http://creativecommons.org/licenses/LGPL/2.1/>    
-*/
-
-var parseSelector=(function(){var _1=/\s*,\s*/;var _2=/\s*([\s>+~(),]|^|$)\s*/g;var _3=/([\s>+~,]|[^(]\+|^)([#.:@])/g;var _4=/^[^\s>+~]/;var _5=/[\s#.:>+~()@]|[^\s#.:>+~()@]+/g;function parseSelector(_6,_7){_7=_7||document.documentElement;var _8=_6.split(_1),_9=[];for(var i=0;i<_8.length;i++){var _b=[_7],_c=toStream(_8[i]);for(var j=0;j<_c.length;){var _e=_c[j++],_f=_c[j++],_10="";if(_c[j]=="("){while(_c[j++]!=")"&&j<_c.length){_10+=_c[j]}_10=_10.slice(0,-1)}_b=select(_b,_e,_f,_10)}_9=_9.concat(_b)}return _9}function toStream(_11){var _12=_11.replace(_2,"$1").replace(_3,"$1*$2");if(_4.test(_12)){_12=" "+_12}return _12.match(_5)||[]}function select(_13,_14,_15,_16){return (_17[_14])?_17[_14](_13,_15,_16):[]}var _18={toArray:function(_19){var a=[];for(var i=0;i<_19.length;i++){a.push(_19[i])}return a}};var dom={isTag:function(_1d,tag){return (tag=="*")||(tag.toLowerCase()==_1d.nodeName.toLowerCase())},previousSiblingElement:function(_1f){do{_1f=_1f.previousSibling}while(_1f&&_1f.nodeType!=1);return _1f},nextSiblingElement:function(_20){do{_20=_20.nextSibling}while(_20&&_20.nodeType!=1);return _20},hasClass:function(_21,_22){return (_22.className||"").match("(^|\\s)"+_21+"(\\s|$)")},getByTag:function(tag,_24){return _24.getElementsByTagName(tag)}};var _17={"#":function(_25,_26){for(var i=0;i<_25.length;i++){if(_25[i].getAttribute("id")==_26){return [_25[i]]}}return []}," ":function(_28,_29){var _2a=[];for(var i=0;i<_28.length;i++){_2a=_2a.concat(_18.toArray(dom.getByTag(_29,_28[i])))}return _2a},">":function(_2c,_2d){var _2e=[];for(var i=0,_30;i<_2c.length;i++){_30=_2c[i];for(var j=0,_32;j<_30.childNodes.length;j++){_32=_30.childNodes[j];if(_32.nodeType==1&&dom.isTag(_32,_2d)){_2e.push(_32)}}}return _2e},".":function(_33,_34){var _35=[];for(var i=0,_37;i<_33.length;i++){_37=_33[i];if(dom.hasClass([_34],_37)){_35.push(_37)}}return _35},":":function(_38,_39,_3a){return (pseudoClasses[_39])?pseudoClasses[_39](_38,_3a):[]}};parseSelector.selectors=_17;parseSelector.pseudoClasses={};parseSelector.util=_18;parseSelector.dom=dom;return parseSelector})();
-var sIFR=new function(){var _3b=this;var _3c="sIFR-active";var _3d="sIFR-replaced";var _3e="sIFR-replacing";var _3f="sIFR-flash";var _40="sIFR-ignore";var _41="sIFR-alternate";var _42="sIFR-class";var _43="sIFR-layout";var _44=6;var _45=126;var _46=8;var _47="SIFR-PREFETCHED";var _48=[10,1.55,19,1.45,32,1.35,71,1.3,1.25];var _49=5;this.isActive=false;this.isEnabled=true;this.hideElements=true;this.preserveSingleWhitespace=false;this.fixWrap=true;this.fixHover=true;this.registerEvents=true;this.setPrefetchCookie=true;this.cookiePath="/";this.domains=[];this.fromLocal=true;this.forceClear=false;this.forceWidth=false;this.fitExactly=false;this.forceTextTransform=true;this.useDomContentLoaded=true;this.debugMode=false;this.hasFlashClassSet=false;this.delayCss=false;this.callbacks=[];var _4a=0;var _4b=false,_4c=false;var dom=new function(){var _4e="http://www.w3.org/1999/xhtml";this.getBody=function(){var _4f=document.getElementsByTagName("body");if(_4f.length==1){return _4f[0]}return null};this.addClass=function(_50,_51){if(_51){_51.className=((_51.className||"")==""?"":_51.className+" ")+_50}};this.removeClass=function(_52,_53){if(_53){_53.className=_53.className.replace(new RegExp("(^|\\s)"+_52+"(\\s|$)"),"").replace(/^\s+|(\s)\s+/g,"$1")}};this.hasClass=function(_54,_55){return new RegExp("(^|\\s)"+_54+"(\\s|$)").test(_55.className)};this.hasOneOfClassses=function(_56,_57){for(var i=0;i<_56.length;i++){if(this.hasClass(_56[i],_57)){return true}}return false};this.create=function(_59){if(document.createElementNS){return document.createElementNS(_4e,_59)}return document.createElement(_59)};this.setInnerHtml=function(_5a,_5b){if(ua.innerHtmlSupport){_5a.innerHTML=_5b}else{if(ua.xhtmlSupport){_5b=["<root xmlns=\"",_4e,"\">",_5b,"</root>"].join("");var xml=(new DOMParser()).parseFromString(_5b,"text/xml");xml=document.importNode(xml.documentElement,true);while(_5a.firstChild){_5a.removeChild(_5a.firstChild)}while(xml.firstChild){_5a.appendChild(xml.firstChild)}}}};this.nodeFromHtml=function(_5d){var _5e=this.create("div");_5e.innerHTML=_5d;return _5e.firstChild};this.getComputedStyle=function(_5f,_60){var _61;if(document.defaultView&&document.defaultView.getComputedStyle){_61=document.defaultView.getComputedStyle(_5f,null)[_60]}else{if(_5f.currentStyle){_61=_5f.currentStyle[_60]}}return _61||""};this.getStyleAsInt=function(_62,_63,_64){var _65=this.getComputedStyle(_62,_63);if(_64&&!/px$/.test(_65)){return 0}_65=parseInt(_65);return isNaN(_65)?0:_65};this.getZoom=function(){return _66.zoom.getLatest()}};this.dom=dom;var ua=new function(){var ua=navigator.userAgent.toLowerCase();var _69=(navigator.product||"").toLowerCase();this.macintosh=ua.indexOf("mac")>-1;this.windows=ua.indexOf("windows")>-1;this.quicktime=false;this.opera=ua.indexOf("opera")>-1;this.konqueror=_69.indexOf("konqueror")>-1;this.ie=false/*@cc_on || true @*/;this.ieSupported=this.ie&&!/ppc|smartphone|iemobile|msie\s5\.5/.test(ua)/*@cc_on && @_jscript_version >= 5.5 @*/;this.ieWin=this.ie&&this.windows/*@cc_on && @_jscript_version >= 5.1 @*/;this.windows=this.windows&&(!this.ie||this.ieWin);this.ieMac=this.ie&&this.macintosh/*@cc_on && @_jscript_version < 5.1 @*/;this.macintosh=this.macintosh&&(!this.ie||this.ieMac);this.safari=ua.indexOf("safari")>-1;this.webkit=ua.indexOf("applewebkit")>-1&&!this.konqueror;this.khtml=this.webkit||this.konqueror;this.gecko=!this.webkit&&_69=="gecko";this.operaVersion=this.opera&&/.*opera(\s|\/)(\d+\.\d+)/.exec(ua)?parseInt(RegExp.$2):0;this.webkitVersion=this.webkit&&/.*applewebkit\/(\d+).*/.exec(ua)?parseInt(RegExp.$1):0;this.geckoBuildDate=this.gecko&&/.*gecko\/(\d{8}).*/.exec(ua)?parseInt(RegExp.$1):0;this.konquerorVersion=this.konqueror&&/.*konqueror\/(\d\.\d).*/.exec(ua)?parseInt(RegExp.$1):0;this.flashVersion=0;if(this.ieWin){var axo;var _6b=false;try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7")}catch(e){try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");this.flashVersion=6;axo.AllowScriptAccess="always"}catch(e){_6b=this.flashVersion==6}if(!_6b){try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash")}catch(e){}}}if(!_6b&&axo){this.flashVersion=parseFloat(/([\d,?]+)/.exec(axo.GetVariable("$version"))[1].replace(/,/g,"."))}}else{if(navigator.plugins&&navigator.plugins["Shockwave Flash"]){var _6c=navigator.plugins["Shockwave Flash"];this.flashVersion=parseFloat(/(\d+\.?\d*)/.exec(_6c.description)[1]);var i=0;while(this.flashVersion>=_46&&i<navigator.mimeTypes.length){var _6e=navigator.mimeTypes[i];if(_6e.type=="application/x-shockwave-flash"&&_6e.enabledPlugin.description.toLowerCase().indexOf("quicktime")>-1){this.flashVersion=0;this.quicktime=true}i++}}}this.flash=this.flashVersion>=_46;this.transparencySupport=this.macintosh||this.windows;this.computedStyleSupport=this.ie||document.defaultView&&document.defaultView.getComputedStyle&&(!this.gecko||this.geckoBuildDate>=20030624);this.css=true;if(this.computedStyleSupport){try{var _6f=document.getElementsByTagName("head")[0];_6f.style.backgroundColor="#FF0000";var _70=dom.getComputedStyle(_6f,"backgroundColor");this.css=!_70||/\#F{2}0{4}|rgb\(255,\s?0,\s?0\)/i.test(_70);_6f.style.backgroundColor="";_6f=null}catch(e){}}this.xhtmlSupport=!!window.DOMParser&&!!document.importNode;try{var n=dom.create("span");if(!this.ieMac){n.innerHTML="x"}this.innerHtmlSupport=n.innerHTML=="x"}catch(e){this.innerHtmlSupport=false}this.zoomSupport=!!(this.opera&&document.documentElement);this.geckoXml=this.gecko&&(document.contentType||"").indexOf("xml")>-1;this.requiresPrefetch=this.ieWin||this.khtml;this.verifiedKonqueror=false;this.supported=this.flash&&this.css&&(!this.ie||this.ieSupported)&&(!this.opera||this.operaVersion>=8)&&(!this.webkit||this.webkitVersion>=412)&&(!this.konqueror||this.konquerorVersion>3.5)&&this.computedStyleSupport&&(this.innerHtmlSupport||!this.khtml&&this.xhtmlSupport)};this.ua=ua;var _72=new function(){var _73={leading:true,"margin-left":true,"margin-right":true,"text-indent":true};var _74=" ";function capitalize($){return $.toUpperCase()}this.normalize=function(str){if(_3b.preserveSingleWhitespace){return str.replace(/\s/g,_74)}return str.replace(/(\s)\s+/g,"$1").replace(/\xA0/,_74)};this.textTransform=function(_77,str){switch(_77){case "uppercase":str=str.toUpperCase();break;case "lowercase":str=str.toLowerCase();break;case "capitalize":var _79=str;str=str.replace(/^\w|\s\w/g,capitalize);if(str.indexOf("function capitalize")!=-1){var _7a=_79.replace(/(^|\s)(\w)/g,"$1$1$2$2").split(/^\w|\s\w/g);str="";for(var i=0;i<_7a.length;i++){str+=_7a[i].charAt(0).toUpperCase()+_7a[i].substring(1)}}break}return str};this.toHexString=function(str){if(typeof (str)!="string"||!str.charAt(0)=="#"||str.length!=4&&str.length!=7){return str}str=str.replace(/#/,"");if(str.length==3){str=str.replace(/(.)(.)(.)/,"$1$1$2$2$3$3")}return "0x"+str};this.toJson=function(obj){var _7e="";switch(typeof (obj)){case "string":_7e="\""+obj+"\"";break;case "number":case "boolean":_7e=obj.toString();break;case "object":_7e=[];for(var _7f in obj){if(obj[_7f]==Object.prototype[_7f]){continue}_7e.push("\""+_7f+"\":"+_72.toJson(obj[_7f]))}_7e="{"+_7e.join(",")+"}";break}return _7e};this.convertCssArg=function(arg){if(!arg){return {}}if(typeof (arg)=="object"){if(arg.constructor==Array){arg=arg.join("")}else{return arg}}var obj={};var _82=arg.split("}");for(var i=0;i<_82.length;i++){var $=_82[i].match(/([^\s{]+)\s*\{(.+)\s*;?\s*/);if(!$||$.length!=3){continue}if(!obj[$[1]]){obj[$[1]]={}}var _85=$[2].split(";");for(var j=0;j<_85.length;j++){var $2=_85[j].match(/\s*([^:\s]+)\s*\:\s*([^\s;]+)/);if(!$2||$2.length!=3){continue}obj[$[1]][$2[1]]=$2[2]}}return obj};this.extractFromCss=function(css,_89,_8a,_8b){var _8c=null;if(css&&css[_89]&&css[_89][_8a]){_8c=css[_89][_8a];if(_8b){delete css[_89][_8a]}}return _8c};this.cssToString=function(arg){var css=[];for(var _8f in arg){var _90=arg[_8f];if(_90==Object.prototype[_8f]){continue}css.push(_8f,"{");for(var _91 in _90){if(_90[_91]==Object.prototype[_91]){continue}var _92=_90[_91];if(_73[_91]){_92=parseInt(_92,10)}css.push(_91,":",_92,";")}css.push("}")}return escape(css.join(""))};this.bind=function(_93,_94){return function(){_93[_94].apply(_93,arguments)}}};this.util=_72;var _66={};_66.fragmentIdentifier=new function(){this.fix=true;var _95;this.cache=function(){_95=document.title};function doFix(){document.title=_95}this.restore=function(){if(this.fix){setTimeout(doFix,0)}}};_66.synchronizer=new function(){this.isBlocked=false;this.block=function(){this.isBlocked=true};this.unblock=function(){this.isBlocked=false;_96.replaceAll()}};_66.zoom=new function(){var _97=100;this.getLatest=function(){return _97};if(ua.zoomSupport&&ua.opera){var _98=document.createElement("div");_98.style.position="fixed";_98.style.left="-65536px";_98.style.top="0";_98.style.height="100%";_98.style.width="1px";_98.style.zIndex="-32";document.documentElement.appendChild(_98);function updateZoom(){if(!_98){return}var _99=window.innerHeight/_98.offsetHeight;var _9a=Math.round(_99*100)%10;if(_9a>5){_99=Math.round(_99*100)+10-_9a}else{_99=Math.round(_99*100)-_9a}_97=isNaN(_99)?100:_99;_66.synchronizer.unblock();document.documentElement.removeChild(_98);_98=null}_66.synchronizer.block();setTimeout(updateZoom,54)}};this.hacks=_66;var _9b={kwargs:[],replaceAll:function(){for(var i=0;i<this.kwargs.length;i++){_3b.replace(this.kwargs[i])}this.kwargs=[]}};var _96={kwargs:[],replaceAll:_9b.replaceAll};function isValidDomain(){if(_3b.domains.length==0){return true}var _9d="";try{_9d=document.domain}catch(e){}if(_3b.fromLocal&&sIFR.domains[0]!="localhost"){sIFR.domains.unshift("localhost")}for(var i=0;i<_3b.domains.length;i++){var _9f=_3b.domains[i];if(_9f=="*"||_9f==_9d){return true}var _a0=_9f.lastIndexOf("*");if(_a0>-1){_9f=_9f.substr(_a0+1);var _a1=_9d.lastIndexOf(_9f);if(_a1>-1&&(_a1+_9f.length)==_9d.length){return true}}}return false}this.activate=function(){if(!ua.supported||!this.isEnabled||this.isActive||!isValidDomain()){return}if(arguments.length>0){this.prefetch.apply(this,arguments)}this.isActive=true;if(this.hideElements){this.setFlashClass()}if(ua.ieWin&&_66.fragmentIdentifier.fix&&window.location.hash!=""){_66.fragmentIdentifier.cache()}else{_66.fragmentIdentifier.fix=false}if(!this.registerEvents){return}function handler(evt){_3b.initialize();if(evt&&evt.type=="load"){if(document.removeEventListener){document.removeEventListener("DOMContentLoaded",handler,false)}if(window.removeEventListener){window.removeEventListener("load",handler,false)}}}if(window.addEventListener){if(_3b.useDomContentLoaded&&ua.gecko){document.addEventListener("DOMContentLoaded",handler,false)}window.addEventListener("load",handler,false)}else{if(ua.ieWin){if(_3b.useDomContentLoaded){document.write("<scr"+"ipt id=__sifr_ie_onload defer src=//:></script>");document.getElementById("__sifr_ie_onload").onreadystatechange=function(){if(this.readyState=="complete"){handler();this.removeNode()}}}window.attachEvent("onload",handler)}}};this.setFlashClass=function(){if(this.hasFlashClassSet){return}dom.addClass(_3c,dom.getBody()||document.documentElement);this.hasFlashClassSet=true};this.removeFlashClass=function(){if(!this.hasFlashClassSet){return}dom.removeClass(_3c,dom.getBody());dom.removeClass(_3c,document.documentElement);this.hasFlashClassSet=false};this.initialize=function(){if(_4c||!this.isActive||!this.isEnabled){return}_4c=true;_9b.replaceAll();clearPrefetch()};function getSource(src){if(typeof (src)!="string"){if(src.src){src=src.src}if(typeof (src)!="string"){var _a4=[];for(var _a5 in src){if(src[_a5]!=Object.prototype[_a5]){_a4.push(_a5)}}_a4.sort().reverse();var _a6="";var i=-1;while(!_a6&&++i<_a4.length){if(parseFloat(_a4[i])<=ua.flashVersion){_a6=src[_a4[i]]}}src=_a6}}if(!src&&_3b.debugMode){throw new Error("sIFR: Could not determine appropriate source")}if(ua.ie&&src.charAt(0)=="/"){src=window.location.toString().replace(/([^:]+)(:\/?\/?)([^\/]+).*/,"$1$2$3")+src}return src}this.prefetch=function(){if(!ua.requiresPrefetch||!ua.supported||!this.isEnabled||!isValidDomain()){return}if(this.setPrefetchCookie&&new RegExp(";?"+_47+"=true;?").test(document.cookie)){return}try{_4b=true;if(ua.ieWin){prefetchIexplore(arguments)}else{prefetchLight(arguments)}if(this.setPrefetchCookie){document.cookie=_47+"=true;path="+this.cookiePath}}catch(e){if(_3b.debugMode){throw e}}};function prefetchIexplore(_a8){for(var i=0;i<_a8.length;i++){document.write("<script defer type=\"sifr/prefetch\" src=\""+getSource(_a8[i])+"\"></script>")}}function prefetchLight(_aa){for(var i=0;i<_aa.length;i++){new Image().src=getSource(_aa[i])}}function clearPrefetch(){if(!ua.ieWin||!_4b){return}try{var _ac=document.getElementsByTagName("script");for(var i=_ac.length-1;i>=0;i--){var _ae=_ac[i];if(_ae.type=="sifr/prefetch"){_ae.parentNode.removeChild(_ae)}}}catch(e){}}function getRatio(_af,_b0){for(var i=0;i<_b0.length;i+=2){if(_af<=_b0[i]){return _b0[i+1]}}return _b0[_b0.length-1]}function getFilters(obj){var _b3=[];for(var _b4 in obj){if(obj[_b4]==Object.prototype[_b4]){continue}var _b5=obj[_b4];_b4=[_b4.replace(/filter/i,"")+"Filter"];for(var _b6 in _b5){if(_b5[_b6]==Object.prototype[_b6]){continue}_b4.push(_b6+":"+escape(_72.toJson(_72.toHexString(_b5[_b6]))))}_b3.push(_b4.join(","))}return _b3.join(";")}function calculate(_b7){var _b8,_b9;if(!ua.ie){_b8=dom.getStyleAsInt(_b7,"lineHeight");_b9=Math.floor(dom.getStyleAsInt(_b7,"height")/_b8)}else{if(ua.ie){var _ba=_b7.innerHTML;_b7.style.visibility="visible";_b7.style.overflow="visible";_b7.style.position="static";_b7.style.zoom="normal";_b7.style.writingMode="lr-tb";_b7.style.width=_b7.style.height="auto";_b7.style.maxWidth=_b7.style.maxHeight=_b7.style.styleFloat="none";var _bb=_b7;var _bc=_b7.currentStyle.hasLayout;if(_bc){dom.setInnerHtml(_b7,"<div class=\""+_43+"\">X<br />X<br />X</div>");_bb=_b7.firstChild}else{dom.setInnerHtml(_b7,"X<br />X<br />X")}var _bd=_bb.getClientRects();_b8=_bd[1].bottom-_bd[1].top;_b8=Math.ceil(_b8*0.8);if(_bc){dom.setInnerHtml(_b7,"<div class=\""+_43+"\">"+_ba+"</div>");_bb=_b7.firstChild}else{dom.setInnerHtml(_b7,_ba)}_bd=_bb.getClientRects();_b9=_bd.length;if(_bc){dom.setInnerHtml(_b7,_ba)}_b7.style.visibility=_b7.style.width=_b7.style.height=_b7.style.maxWidth=_b7.style.maxHeight=_b7.style.overflow=_b7.style.styleFloat=_b7.style.position=_b7.style.zoom=_b7.style.writingMode=""}}return {lineHeight:_b8,lines:_b9}}this.replace=function(_be,_bf){if(!ua.supported){return}if(_bf){for(var _c0 in _be){if(typeof (_bf[_c0])=="undefined"){_bf[_c0]=_be[_c0]}}_be=_bf}if(!_4c){return _9b.kwargs.push(_be)}if(_66.synchronizer.isBlocked){return _96.kwargs.push(_be)}var _c1=_be.elements;if(!_c1&&parseSelector){_c1=parseSelector(_be.selector)}if(_c1.length==0){return}this.setFlashClass();var src=getSource(_be.src);var css=_72.convertCssArg(_be.css);var _c4=getFilters(_be.filters);var _c5=(_be.forceClear==null)?_3b.forceClear:_be.forceClear;var _c6=(_be.fitExactly==null)?_3b.fitExactly:_be.fitExactly;var _c7=_c6||(_be.forceWidth==null?_3b.forceWidth:_be.forceWidth);var _c8=parseInt(_72.extractFromCss(css,".sIFR-root","leading"))||0;var _c9=_72.extractFromCss(css,".sIFR-root","font-size",true)||0;var _ca=_72.extractFromCss(css,".sIFR-root","background-color",true)||"#FFFFFF";var _cb=_72.extractFromCss(css,".sIFR-root","kerning",true)||"";var _cc=_be.gridFitType||_72.extractFromCss(css,".sIFR-root","text-align")=="right"?"subpixel":"pixel";var _cd=_3b.forceTextTransform?_72.extractFromCss(css,".sIFR-root","text-transform",true)||"none":"none";var _ce=_72.extractFromCss(css,".sIFR-root","opacity",true)||"100";var _cf=_be.pixelFont||false;var _d0=_be.ratios||_48;if(parseInt(_c9).toString()!=_c9&&_c9.indexOf("px")==-1){_c9=0}else{_c9=parseInt(_c9)}if(parseFloat(_ce)<1){_ce=100*parseFloat(_ce)}var _d1=null;var _d2="";if(_c6){_72.extractFromCss(css,".sIFR-root","text-align",true)}if(!_be.modifyCss){_d2=_72.cssToString(css);_d1=_3b.fixHover&&_d2.indexOf("%3Ahover")>-1}var _d3=!ua.opera&&_3b.delayCss;var _d4=_be.wmode||"";if(!_d4){if(_be.transparent){_d4="transparent"}else{if(_be.opaque){_d4="opaque"}}}if(_d4=="transparent"){if(!ua.transparencySupport){_d4="opaque"}else{_ca="transparent"}}for(var i=0;i<_c1.length;i++){var _d6=_c1[i];if(!ua.verifiedKonqueror){if(dom.getComputedStyle(_d6,"lineHeight").match(/e\+08px/)){ua.supported=_3b.isEnabled=false;this.removeFlashClass();return}ua.verifiedKonqueror=true}if(dom.hasOneOfClassses([_3d,_3e,_40,_41],_d6)){continue}var _d7=_d6.offsetHeight;var _d8=_d6.offsetWidth;var _d9=dom.getComputedStyle(_d6,"display");if(!_d7||!_d8||_d9==null||_d9=="none"){continue}if(_c5&&ua.gecko){_d6.style.clear="both"}var _da=null;if(_3b.fixWrap&&ua.ie&&_d9=="block"){_da=_d6.innerHTML;dom.setInnerHtml(_d6,"X")}_d8=dom.getStyleAsInt(_d6,"width",ua.ie);if(_d8==0){var _db=dom.getStyleAsInt(_d6,"paddingRight",true);var _dc=dom.getStyleAsInt(_d6,"paddingLeft",true);var _dd=dom.getStyleAsInt(_d6,"borderRightWidth",true);var _de=dom.getStyleAsInt(_d6,"borderLeftWidth",true);_d8=_d6.offsetWidth-_dc-_db-_de-_dd}if(_da&&_3b.fixWrap&&ua.ie){dom.setInnerHtml(_d6,_da)}var _df,_e0;if(!_c9){var _e1=calculate(_d6);_df=Math.min(_45,Math.max(_44,_e1.lineHeight));if(_cf){_df=Math.max(8,8*Math.round(_df/8))}_e0=_e1.lines;if(isNaN(_e0)||!isFinite(_e0)||_e0==0){_e0=1}if(_e0>1&&_c8){_d7+=Math.round((_e0-1)*_c8)}}else{_df=_c9;_e0=1}_d7=Math.round(_e0*_df);if(_c5&&ua.gecko){_d6.style.clear=""}var _e2=dom.create("span");_e2.className=_41;var _e3=_d6.cloneNode(true);for(var j=0,l=_e3.childNodes.length;j<l;j++){_e2.appendChild(_e3.childNodes[j].cloneNode(true))}if(_be.modifyContent){_be.modifyContent(_e3,_be.selector)}if(_be.modifyCss){_d2=_be.modifyCss(css,_e3,_be.selector)}if(_d1==null){_d1=_3b.fixHover&&_d2.indexOf("%3Ahover")>-1}var _e6=handleContent(_e3,_cd);if(_be.modifyContentString){_e6=_be.modifyContentString(_e6,_be.selector)}if(_e6==""){continue}var _e7=["content="+_e6,"width="+_d8,"height="+_d7,"fitexactly="+(_c6?"true":""),"tunewidth="+(_be.tuneWidth||""),"tuneheight="+(_be.tuneHeight||""),"offsetleft="+(_be.offsetLeft||""),"offsettop="+(_be.offsetTop||""),"thickness="+(_be.thickness||""),"sharpness="+(_be.sharpness||""),"kerning="+_cb,"gridfittype="+_cc,"zoomsupport="+ua.zoomSupport,"flashfilters="+_c4,"opacity="+_ce,"blendmode="+(_be.blendMode||""),"size="+_df,"zoom="+dom.getZoom(),"css="+_d2,"selectable="+(_be.selectable==null?"true":_be.selectable),"lines="+_e0];var _e8=encodeURI(_e7.join("&amp;"));var _e9="sIFR_callback_"+_4a++;var _ea=new CallbackInfo(_e9,_e7,_be.onReplacement,_d1);window[_e9+"_DoFSCommand"]=(function(_eb){return function(_ec,arg){_eb.handle(_ec,arg)}})(_ea);_d7=Math.round(_e0*getRatio(_df,_d0)*_df)+_49;var _ee=_c7?_d8:"100%";var _ef;if(ua.ie){_ef=["<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" id=\"",_e9,"\" sifr=\"true\" width=\"",_ee,"\" height=\"",_d7,"\" class=\"",_3f,"\">","<param name=\"movie\" value=\"",src,"\"></param>","<param name=\"flashvars\" value=\"",_e8,"\"></param>","<param name=\"allowScriptAccess\" value=\"always\"></param>","<param name=\"quality\" value=\"best\"></param>","<param name=\"wmode\" value=\"",_d4,"\"></param>","<param name=\"bgcolor\" value=\"",_ca,"\"></param>","<param name=\"name\" value=\"",_e9,"\"></param>","</object>","<scr","ipt event=FSCommand(info,args) for=",_e9,">",_e9,"_DoFSCommand(info, args);","</","script>"].join("")}else{_ef=["<embed type=\"application/x-shockwave-flash\"",(_d3?" class=\""+_3f+"\"":"")," src=\"",src,"\" quality=\"best\" flashvars=\"",_e8,"\" width=\"",_ee,"\" height=\"",_d7,"\" wmode=\"",_d4,"\" bgcolor=\"",_ca,"\" name=\"",_e9,"\" id=\"",_e9,"\" allowScriptAccess=\"always\" sifr=\"true\"></embed>"].join("")}dom.setInnerHtml(_d6,_ef);_ea.flashNode=_d6.firstChild;_ea.html=_ef;_3b.callbacks.push(_ea);if(_be.selector){if(!_3b.callbacks[_be.selector]){_3b.callbacks[_be.selector]=[_ea]}else{_3b.callbacks[_be.selector].push(_ea)}}_d6.appendChild(_e2);dom.addClass(_d3?_3e:_3d,_d6);_ea.setupFixHover()}_66.fragmentIdentifier.restore()};this.getCallbackByFlashElement=function(_f0){for(var i=0;i<_3b.callbacks.length;i++){if(_3b.callbacks[i].id==_f0.getAttribute("id")){return _3b.callbacks[i]}}};function handleContent(_f2,_f3){var _f4=[],_f5=[];var _f6=_f2.childNodes;var i=0;while(i<_f6.length){var _f8=_f6[i];if(_f8.nodeType==3){var _f9=_72.normalize(_f8.nodeValue);_f9=_72.textTransform(_f3,_f9);_f5.push(_f9.replace(/\%/g,"%25").replace(/\&/g,"%26").replace(/\,/g,"%2C").replace(/\+/g,"%2B"))}if(_f8.nodeType==1){var _fa=[];var _fb=_f8.nodeName.toLowerCase();var _fc=_f8.className||"";if(/\s+/.test(_fc)){if(_fc.indexOf(_42)>-1){_fc=_fc.match("(\\s|^)"+_42+"-([^\\s$]*)(\\s|$)")[2]}else{_fc=_fc.match(/^([^\s]+)/)[1]}}if(_fc!=""){_fa.push("class=\""+_fc+"\"")}if(_fb=="a"){var _fd=_f8.getAttribute("href")||"";var _fe=_f8.getAttribute("target")||"";_fa.push("href=\""+_fd+"\"","target=\""+_fe+"\"")}_f5.push("<"+_fb+(_fa.length>0?" ":"")+escape(_fa.join(" "))+">");if(_f8.hasChildNodes()){_f4.push(i);i=0;_f6=_f8.childNodes;continue}else{if(!/^(br|img)$/i.test(_f8.nodeName)){_f5.push("</",_f8.nodeName.toLowerCase(),">")}}}if(_f4.length>0&&!_f8.nextSibling){do{i=_f4.pop();_f6=_f8.parentNode.parentNode.childNodes;_f8=_f6[i];if(_f8){_f5.push("</",_f8.nodeName.toLowerCase(),">")}}while(i==_f6.length-1&&_f4.length>0)}i++}return _f5.join("").replace(/\n|\r/g,"")}function CallbackInfo(id,vars,_101,_102){this.id=id;this.vars=vars;this._replacementHandler=_101;this._firedReplacementEvent=!(this._replacementHandler!=null);this._fixHover=_102;this._setClasses=!_3b.delayCss;this.html="";this._pings=0}CallbackInfo.prototype.getFlashElement=function(){return document.getElementById(this.id)};CallbackInfo.prototype.handle=function(info,arg){if(/(FSCommand\:)?resize/.test(info)){var _105=this.getFlashElement();var $=arg.split(/\:|,/);_105.setAttribute($[0],$[1]);if($.length>2){_105.setAttribute($[2],$[3])}if(!this._setClasses){if(!ua.ie&&!ua.opera){dom.addClass(_3f,_105)}dom.removeClass(_3e,_105.parentNode);dom.addClass(_3d,_105.parentNode);this._setClasses=true}if(ua.khtml){var _107=_105.offsetHeight}if(!this._firedReplacementEvent){this._replacementHandler(this);this._firedReplacementEvent=true}}else{if(/(FSCommand\:)?resetmovie/.test(info)){this.resetMovie()}else{if(/(FSCommand\:)?ping/.test(info)){if(this._pings>0){this.setupFixHover()}this._pings++}else{if(this.debugHandler&&/(FSCommand\:)?debug/.test(info)){this.debugHandler(info,arg)}}}}};CallbackInfo.prototype.call=function(type,_109){var _10a=this.getFlashElement();if(!_10a){return}_10a.SetVariable("callbackType",type);_10a.SetVariable("callbackValue",_109);_10a.SetVariable("callbackTrigger",true)};CallbackInfo.prototype.replaceText=function(_10b){_10b=escape(_10b);this.call("replacetext",_10b);this.vars[0]="content="+_10b;this.html=this.html.replace(/(flashvars(=|\"\svalue=)\")[^\"]+/,"$1"+encodeURI(this.vars.join("&amp;")))};CallbackInfo.prototype.resetMovie=function(){var _10c=this.getFlashElement();var node=_10c.parentNode;node.replaceChild(dom.nodeFromHtml(this.html),_10c);this.setupFixHover()};CallbackInfo.prototype.setupFixHover=function(){var _10e=this.getFlashElement();if(!this._fixHover||!_10e){return}var node=_10e.parentNode;if(node.addEventListener){node.addEventListener("mouseout",_72.bind(this,"fixHover"),false)}else{if(node.attachEvent){node.attachEvent("onmouseout",_72.bind(this,"fixHover"))}}};CallbackInfo.prototype.fixHover=function(){this.call("resettext")}};
\ No newline at end of file
diff --git a/library/simplepie/demo/for_the_demo/simplepie.css b/library/simplepie/demo/for_the_demo/simplepie.css
deleted file mode 100644
index 3753cb96de..0000000000
--- a/library/simplepie/demo/for_the_demo/simplepie.css
+++ /dev/null
@@ -1,397 +0,0 @@
-/*
-Theme Name: SimplePie
-Theme URI: http://simplepie.org
-Description: A simple, yet beautiful theme inspired by several cleanly designed websites.
-Version: 1.4
-Author: Ryan Parman
-Author URI: http://skyzyx.com
-Updated: 21 June 2007
-*/
-
-
-/*********************************************
-HYPERLINK STYLES
-*********************************************/
-a {
-	color:#369;
-	text-decoration:underline;
-	padding:0 1px;
-}
-
-a:hover {
-	color:#fff !important;
-	background-color:#333;
-	text-decoration:none;
-	padding:0 1px;
-}
-
-a.nohover {
-	text-decoration:none;
-	border:none;
-}
-
-a.nohover:hover {
-	background-color:transparent;
-	border:none;
-}
-
-a.namelink {
-	padding:0;
-	margin:0;
-	overflow:hidden;
-	height:1px;
-}
-
-h4 a,
-.sample_feeds a {
-	color:#000;
-}
-
-
-/*********************************************
-GENERAL STYLES
-*********************************************/
-body {
-	/*font:12px/18px Verdana, sans-serif;*/
-	font:14px/1.5em "Lucida Grande", Tahoma, sans-serif;
-	letter-spacing:0px;
-	color:#333;
-	background-color:#fff;
-	margin:0;
-	padding:0;
-}
-
-div#site {
-	width:600px;
-	margin:50px auto 0 auto;
-}
-
-h1#logo {
-	margin:0;
-	padding:0;
-	text-align:center;
-}
-
-h1#logo a, 
-h1#logo a:hover {
-	background-color:transparent;
-	text-decoration:none;
-	padding:0;
-}
-
-h2.image {
-	margin:0;
-	padding:0;
-	text-align:center;
-}
-
-h3 {
-	margin:20px 0 0 0;
-	padding:0;
-	font-size:1.5em;
-}
-
-h4 {
-	margin:20px 0 0 0;
-	padding:0;
-	font-size:1.2em;
-	letter-spacing:-1px;
-}
-
-h5 {
-	margin:10px 0 0 0;
-	padding:0;
-	font-size:1em;
-	font-weight:bold;
-}
-
-em {
-	font-style:normal;
-	background-color:#ffc;
-}
-
-p {
-	margin:0;
-	padding:5px 0;
-}
-
-ul, ol {
-	margin:10px 0 10px 20px;
-	padding:0 0 0 15px;
-}
-
-ul li, ol li {
-	margin:0 0 7px 0;
-	padding:0 0 0 3px;
-}
-
-form {
-	margin:0;
-	padding:0;
-}
-
-code {
-	font-size:1em;
-	background-color:#f3f3ff;
-	color:#000;
-}
-
-div#site pre {
-	background-color:#f3f3ff;
-	color:#000080;
-	border:1px dotted #000080;
-	overflow:auto;
-	padding:3px 5px;
-}
-
-blockquote {
-	font-size:1em;
-	color:#666;
-	border-left:4px solid #666;
-	margin:10px 0 10px 30px;
-	padding:0 5px 0 10px;
-	background:#f3f3f3 url(background_blockquote.png) repeat top left;
-}
-
-input, select, textarea {
-	font-size:12px;
-	line-height:1.2em;
-	padding:2px;
-}
-
-input[type=text], select, textarea {
-	background-color:#e9f5ff;
-	border:1px solid #333;
-}
-
-input[type=text]:focus, select:focus, textarea:focus {
-	background-color:#ffe;
-}
-
-.clearLeft {clear:left;}
-.clearRight {clear:right;}
-.clearBoth {clear:both;}
-.hide {display:none;}
-
-
-/*********************************************
-NAVIGATION STYLES
-*********************************************/
-div#header {
-	background:#fff url(top_gradient.gif) repeat-x top left;
-	margin:0;
-	padding:0;
-}
-
-div#header form {
-	margin:0;
-	padding:0;
-}
-
-div#header div#headerInner {
-	margin:0;
-	padding:0;
-}
-
-div#header div#headerInner div#logoContainer {}
-
-div#header div#headerInner div#logoContainerInner {
-	width:550px;
-	margin:0 auto;
-	padding:20px;
-}
-
-div#header div#headerInner div#logoContainer div#logo {
-	float:left;
-	width:200px;
-}
-
-div#header div#headerInner div#logoContainer div#logo a,
-div#header div#headerInner div#logoContainer div#logo a:hover {
-	border:none;
-	background:none;
-}
-
-div#header div#headerInner div#logoContainer div#feed {
-	float:right;
-	width:300px;
-	text-align:right;
-	padding:10px 0 0 0;
-}
-
-div#header div#headerInner div#logoContainer div#feed input.text {
-	width:60%;
-}
-
-div#header div#headerInner div#menu {
-	background:#eee url(background_menuitem_shadow.gif) repeat-x top left;
-	border-top:2px solid #ccc;
-	border-bottom:1px solid #ddd;
-	text-align:center;
-}
-
-div#header div#headerInner div#menu table {
-	width:auto;
-	margin:0 auto;
-}
-
-div#header div#headerInner div#menu ul {
-	display:block;
-	width:100%;
-	margin:0 auto;
-	padding:0;
-	font-size:12px;
-}
-
-div#header div#headerInner div#menu ul li {
-	display:block;
-	float:left;
-}
-
-div#header div#headerInner div#menu ul li a {
-	display:block;
-	margin:-2px 0 0 0;
-	padding:5px 7px 8px 7px;
-	text-decoration:none;
-	color:#666 !important;
-	background-color:transparent;
-}
-
-div#header div#headerInner div#menu ul li a:hover {
-	display:block;
-	margin:-2px 0 0 0;
-	padding:5px 7px 8px 7px;
-	text-decoration:none;
-	color:#666;
-	background:#fff url(background_menuitem_off.gif) no-repeat bottom right;
-}
-
-body#bodydemo div#header div#headerInner div#menu ul li#demo a {
-	display:block;
-	margin:-2px 0 0 0;
-	padding:5px 7px 8px 7px;
-	text-decoration:none;
-	color:#333;
-	font-weight:bold;
-	background:#fff url(background_menuitem.gif) no-repeat bottom right;
-}
-
-
-/*********************************************
-CONTENT STYLES
-*********************************************/
-div.chunk {
-	margin:20px 0 0 0;
-	padding:0 0 10px 0;
-	border-bottom:1px solid #ccc;
-}
-
-div.topchunk {
-	margin:0 !important;
-}
-
-.footnote,
-.footnote a {
-	font-size:12px;
-	line-height:1.3em;
-	color:#aaa;
-}
-
-.footnote em {
-	background-color:transparent;
-	font-style:italic;
-}
-
-.footnote code {
-	background-color:transparent;
-	font:11px/14px monospace;
-	color:#aaa;
-}
-
-p.subscribe {
-	background-color:#f3f3f3;
-	font-size:12px;
-	text-align:center;
-}
-
-p.highlight {
-	background-color:#ffc;
-	font-size:12px;
-	text-align:center;
-}
-
-p.sample_feeds {
-	font-size:12px;
-	line-height:1.2em;
-}
-
-div.sp_errors {
-	background-color:#eee;
-	padding:5px;
-	text-align:center;
-	font-size:12px;
-}
-
-.noborder {
-	border:none !important;
-}
-
-img.favicon {
-	margin:0 4px -2px 0;
-	width:16px;
-	height:16px;
-}
-
-p.favicons a,
-p.favicons a:hover {
-	border:none;
-	background-color:transparent;
-}
-
-p.favicons img {
-	border:none;
-}
-
-
-/*********************************************
-DEMO STYLES
-*********************************************/
-div#sp_input {
-	background-color:#ffc;
-	border:2px solid #f90;
-	padding:5px;
-	text-align:center;
-}
-
-div#sp_input input.text {
-	border:1px solid #999;
-	background:#e9f5ff url(feed.png) no-repeat 4px 50%;
-	width:75%;
-	padding:2px 2px 2px 28px;
-	font:18px/22px "Lucida Grande", Verdana, sans-serif;
-	font-weight:bold;
-	letter-spacing:-1px;
-}
-
-form#sp_form {
-	margin:15px 0;
-}
-
-div.focus {
-	margin:0;
-	padding:10px 20px;
-	background-color:#efe;
-}
-
-p.sample_feeds {
-	text-align:justify;
-}
-
-
-/*********************************************
-SIFR STYLES
-*********************************************/
-.sIFR-active h3.header {
-	visibility:hidden;
-	line-height:1em;
-}
diff --git a/library/simplepie/demo/for_the_demo/sleight.js b/library/simplepie/demo/for_the_demo/sleight.js
deleted file mode 100644
index 4b5058e9a6..0000000000
--- a/library/simplepie/demo/for_the_demo/sleight.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**********************************************************
-Sleight
-(c) 2001, Aaron Boodman
-http://www.youngpup.net
-**********************************************************/
-
-if (navigator.platform == "Win32" && navigator.appName == "Microsoft Internet Explorer" && window.attachEvent)
-{
-	document.writeln('<style type="text/css">img { visibility:hidden; } </style>');
-	window.attachEvent("onload", fnLoadPngs);
-}
-
-function fnLoadPngs()
-{
-	var rslt = navigator.appVersion.match(/MSIE (\d+\.\d+)/, '');
-	var itsAllGood = (rslt != null && Number(rslt[1]) >= 5.5);
-
-	for (var i = document.images.length - 1, img = null; (img = document.images[i]); i--)
-	{
-		if (itsAllGood && img.src.match(/\.png$/i) != null)
-		{
-			var src = img.src;
-			var div = document.createElement("DIV");
-			div.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizing='scale')"
-			div.style.width = img.width + "px";
-			div.style.height = img.height + "px";
-			img.replaceNode(div);
-		}
-		img.style.visibility = "visible";
-	}
-}
diff --git a/library/simplepie/demo/for_the_demo/source_files/place_audio_fireworksfile.png b/library/simplepie/demo/for_the_demo/source_files/place_audio_fireworksfile.png
deleted file mode 100644
index 2bfd87d0ce14c424fd3b72377b085bb0b1510bd1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 39177
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

diff --git a/library/simplepie/demo/for_the_demo/source_files/place_video_fireworksfile.png b/library/simplepie/demo/for_the_demo/source_files/place_video_fireworksfile.png
deleted file mode 100644
index d0629769cfec742664ec0b739d93ebf4418d15e9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 115826
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
Y{xKQOm;9p6g#iC3$f!!!Nt%cL4}oKrIsgCw

diff --git a/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/SifrStyleSheet.as b/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/SifrStyleSheet.as
deleted file mode 100644
index 6a98ca5522..0000000000
--- a/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/SifrStyleSheet.as
+++ /dev/null
@@ -1,71 +0,0 @@
-/*=:project
-    scalable Inman Flash Replacement (sIFR) version 3.
-
-  =:file
-    Copyright: 2006 Mark Wubben.
-    Author: Mark Wubben, <http://novemberborn.net/>
-
-  =:history
-    * IFR: Shaun Inman
-    * sIFR 1: Mike Davidson, Shaun Inman and Tomas Jogin
-    * sIFR 2: Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben
-
-  =:license
-    This software is licensed and provided under the CC-GNU LGPL.
-    See <http://creativecommons.org/licenses/LGPL/2.1/>    
-*/
-
-import TextField.StyleSheet;
-
-class SifrStyleSheet extends TextField.StyleSheet {
-  public var fontSize;
-  public var latestLeading = 0;
-  
-  public function parseCSS(cssText:String) {
-    var native = new TextField.StyleSheet();
-    var parsed = native.parseCSS(cssText);
-    
-    if(!parsed) return false;
-    
-    var selectors = native.getStyleNames();
-    for(var i = selectors.length - 1; i >= 0; i--) {
-      var selector = selectors[i];
-      var nativeStyle = native.getStyle(selector);
-      var style = this.getStyle(selector) || nativeStyle;
-      if(style != nativeStyle) {
-        for(var property in nativeStyle) style[property] = nativeStyle[property];
-      }
-      this.setStyle(selector, style);
-    }
-    
-    return true;
-  }
-  
-  // Apply leading to the textFormat. Much thanks to <http://www.blog.lessrain.com/?p=98>.
-  private function applyLeading(format, leading) {
-    this.latestLeading = leading;
-    
-    if(leading >= 0) {
-        format.leading = leading;
-        return format;
-    }
-
-    // Workaround for negative leading, which is ignored otherwise.
-    var newFormat = new TextFormat(null, null, null, null, null, null, null, null, null, null, null, null, leading);
-    for(var property in format) if(property != 'leading') newFormat[property] = format[property];
-
-    return newFormat;
-  }
-  
-  public function transform(style) {
-    var format = super.transform(style);
-    if(style.leading) format = applyLeading(format, style.leading);
-    if(style.letterSpacing) format.letterSpacing = style.letterSpacing;
-    // Support font sizes relative to the size of .sIFR-root.
-    if(this.fontSize && style.fontSize && style.fontSize.indexOf('%')) {
-      format.size = this.fontSize * parseInt(style.fontSize) / 100;
-    }
-    format.kerning = _root.kerning == 'true' || !(_root.kerning == 'false') || sIFR.defaultKerning;
-    return format;
-  }
-}
\ No newline at end of file
diff --git a/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/_README_.txt b/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/_README_.txt
deleted file mode 100644
index 2b9d32d202..0000000000
--- a/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/_README_.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a pre-release nightly of sIFR 3 (r245 to be exact).  We (the SimplePie team) will be updating the 
-sIFR code and font files from time to time as new releases of sIFR 3 are made available.
-
-In this folder you'll find a few Flash 8 files.  The only one of you might want to mess with is sifr.fla.
-  * Open it up
-  * Double-click the rectangle in the middle
-  * Select all
-  * Change the font
-
-More information about sIFR 3 can be found here:
-  * http://dev.novemberborn.net/sifr3/
-  * http://wiki.novemberborn.net/sifr3/
\ No newline at end of file
diff --git a/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/options.as b/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/options.as
deleted file mode 100644
index 4d371954bc..0000000000
--- a/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/options.as
+++ /dev/null
@@ -1,12 +0,0 @@
-// MTASC only parses as-files with class definitions, so here goes...
-class Options {
-	public static function apply() {
-		sIFR.fromLocal = true;
-		sIFR.domains   = ['*'];
-		
-		// Parsing `p.foo` might not work, see: <http://livedocs.macromedia.com/flash/mx2004/main_7_2/wwhelp/wwhimpl/common/html/wwhelp.htm?context=Flash_MX_2004&file=00001766.html>
-		// Appearantly you have to use hex color codes as well, names are not supported!
-
-		sIFR.styles.parseCSS('.foo { text-decoration: underline; }'); 
-	}
-}
diff --git a/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/sIFR.as b/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/sIFR.as
deleted file mode 100644
index 4902e003f3..0000000000
--- a/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/sIFR.as
+++ /dev/null
@@ -1,359 +0,0 @@
-/*=:project
-    scalable Inman Flash Replacement (sIFR) version 3.
-
-  =:file
-    Copyright: 2006 Mark Wubben.
-    Author: Mark Wubben, <http://novemberborn.net/>
-
-  =:history
-    * IFR: Shaun Inman
-    * sIFR 1: Mike Davidson, Shaun Inman and Tomas Jogin
-    * sIFR 2: Mike Davidson, Shaun Inman, Tomas Jogin and Mark Wubben
-
-  =:license
-    This software is licensed and provided under the CC-GNU LGPL.
-    See <http://creativecommons.org/licenses/LGPL/2.1/>    
-*/
-
-import SifrStyleSheet;
-
-class sIFR {
-  public static var DEFAULT_TEXT                 = 'Rendered with sIFR 3, revision 245';
-  public static var CSS_ROOT_CLASS               = 'sIFR-root';
-  public static var DEFAULT_WIDTH                = 300;
-  public static var DEFAULT_HEIGHT               = 100;
-  public static var DEFAULT_ANTI_ALIAS_TYPE      = 'advanced';
-  public static var MARGIN_LEFT                  = -3;
-  public static var PADDING_BOTTOM               = 5; // Extra padding to make sure the movie is high enough in most cases.
-  public static var LEADING_REMAINDER            = 2; // Flash uses the specified leading minus 2 as the applied leading.
-
-  public static var MAX_FONT_SIZE                = 126;
-  public static var ALIASING_MAX_FONT_SIZE       = 48;
-  
-  //= Holds CSS properties and other rendering properties for the Flash movie.
-  //  *Don't overwrite!*
-  public static var styles:SifrStyleSheet        = new SifrStyleSheet();
-  //= Allow sIFR to be run from localhost
-  public static var fromLocal:Boolean            = true;
-  //= Array containing domains for which sIFR may render text. Used to prevent
-  //  hotlinking. Use `*` to allow all domains.
-  public static var domains:Array                = [];
-  //= Whether kerning is enabled by default. This can be overriden from the client side.
-  //  See also <http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002811.html>.
-  public static var defaultKerning:Boolean       = true;
-  //= Default value which can be overriden from the client side.
-  //  See also <http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002788.html>.
-  public static var defaultSharpness:Number      = 0;
-  //= Default value which can be overriden from the client side.
-  //  See also <http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002787.html>.
-  public static var defaultThickness:Number      = 0;
-  //= Default value which can be overriden from the client side.
-  //  See also <http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002732.html>.
-  public static var defaultOpacity:Number        = -1; // Use client settings
-  //= Default value which can be overriden from the client side.
-  //  See also <http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002788.html>.
-  public static var defaultBlendMode:Number      = -1; // Use cliest settings
-  //= Overrides the grid fit type as defined on the client side.
-  //  See also <http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002444.html>.
-  public static var enforcedGridFitType:String   = null;
-  //= If `true` sIFR won't override the anti aliasing set in the Flash IDE when exporting.
-  //  Thickness and sharpness won't be affected either.
-  public static var preserveAntiAlias:Boolean    = false;
-  //= If `true` sIFR will disable anti-aliasing if the font size is larger than `ALIASING_MAX_FONT_SIZE`.
-  //  This setting is *independent* from `preserveAntiAlias`.
-  public static var conditionalAntiAlias:Boolean = true;
-  //= Sets the anti alias type. By default it's `DEFAULT_ANTI_ALIAS_TYPE`.
-  //  See also <http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00002733.html>.
-  public static var antiAliasType:String         = null;
-  //= Flash filters can be added to this array and will be applied to the text field.
-  public static var filters:Array                = [];
-  //= A mapping from the names of the filters to their actual objecs, used when transforming
-  //  filters defined on the client. You can add additional filters here so they'll be supported
-  //  when defined on the client.
-  public static var filterMap:Object             = {
-    DisplacementMapFilter : flash.filters.DisplacementMapFilter,
-    ColorMatrixFilter     : flash.filters.ColorMatrixFilter,
-    ConvolutionFilter     : flash.filters.ConvolutionFilter,
-    GradientBevelFilter   : flash.filters.GradientBevelFilter,
-    GradientGlowFilter    : flash.filters.GradientGlowFilter,
-    BevelFilter           : flash.filters.BevelFilter,
-    GlowFilter            : flash.filters.GlowFilter,
-    BlurFilter            : flash.filters.BlurFilter,
-    DropShadowFilter      : flash.filters.DropShadowFilter
-  };
-
-  private static var instance;
-  
-  private var textField;
-  private var content;
-  private var realHeight;
-  private var originalHeight;
-  private var currentHeight;
-  private var fontSize;
-  private var tuneWidth;
-  private var tuneHeight;
-  
-
-  
-  //= Sets the default styles for `sIFR.styles`. This method is called
-  //  directly in `sifr.fla`, before options are applied.
-  public static function setDefaultStyles() {
-    sIFR.styles.parseCSS([
-      '.', CSS_ROOT_CLASS, ' { color: #000000; }',
-      'strong { display: inline; font-weight: bold; } ',
-      'em { display: inline; font-style: italic; }',
-      'a { color: #0000FF; text-decoration: underline; }',
-      'a:hover { color: #0000FF; text-decoration: none; }'
-    ].join(''));
-  }
-  
-  //= Validates the domain sIFR is being used on.
-  //  Returns `true` if the domain is valid, `false` otherwise.  
-  public static function checkDomain():Boolean {
-    if(sIFR.domains.length == 0) return true;
-
-    var domain = (new LocalConnection()).domain();
-    if(sIFR.fromLocal) sIFR.domains.push('localhost');
-    
-    for(var i = 0; i < sIFR.domains.length; i++) {
-      var match = sIFR.domains[i];
-      if(match == '*' || match == domain) return true;
-
-      var wildcard = match.lastIndexOf('*');
-      if(wildcard > -1) {
-        match = match.substr(wildcard + 1);
-        var matchPosition = domain.lastIndexOf(match);
-        if(matchPosition > -1 && (matchPosition + match.length) == domain.length) return true;
-      }
-    }
-    
-    return false;
-  }
-  
-  //= Runs sIFR. Called automatically.
-  public static function run() {
-    var holder  = _root.holder;
-    var content = checkDomain() ? unescape(_root.content) : DEFAULT_TEXT
-    if(content == 'undefined' || content == '') {
-      content = DEFAULT_TEXT;
-      fscommand('resetmovie', '');
-    } else fscommand('ping', '');
-
-    // Sets stage parameters
-    Stage.scaleMode = 'noscale';
-    Stage.align = 'TL';
-    Stage.showMenu = false;
-    
-    // Other parameters
-    var opacity = parseInt(_root.opacity);
-    if(!isNaN(opacity)) holder._alpha = sIFR.defaultOpacity == -1 ? opacity : sIFR.defaultOpacity;
-    else holder._alpha = 100;
-    _root.blendMode = sIFR.defaultBlendMode == -1 ? _root.blendmode : sIFR.defaultBlendMode;
-
-    sIFR.instance = new sIFR(holder.txtF, content);
-    // This should ignore resizes from the callback. Disabled for now.
-/*    if(_root.zoomsupport == 'true') Stage.addListener({onResize: function() { sIFR.instance.scale() }});*/
-
-    // Setup callbacks
-    _root.watch('callbackTrigger', function() { 
-      sIFR.callback();
-      return false;
-    });
-  }
-  
-  private static function eval(str) {
-    var as;
-    
-    if(str.charAt(0) == '{') { // Ah, we need to create an object
-      as = {};
-      str = str.substring(1, str.length - 1);
-      var $ = str.split(',');
-      for(var i = 0; i < $.length; i++) {
-        var $1 = $[i].split(':');
-        as[$1[0]] = sIFR.eval($1[1]);
-      }
-    } else if(str.charAt(0) == '"') { // String
-      as = str.substring(1, str.length - 1);
-    } else if(str == 'true' || str == 'false') { // Boolean
-      as = str == 'true';
-    } else { // Float
-      as = parseFloat(str);
-    }
-    
-    return as;
-  }
-  
-  private function applyFilters() {
-    var $filters = this.textField.filters;
-    $filters = $filters.concat(sIFR.filters);
-    
-    var $ = _root.flashfilters.split(';'); // name,prop:value,...;
-    for(var i = 0; i < $.length; i++) {
-      var $1 = $[i].split(',');
-      
-      var newFilter = new sIFR.filterMap[$1[0]]();
-      for(var j = 1; j < $1.length; j++) {
-        var $2 = $1[j].split(':');
-        newFilter[$2[0]] = sIFR.eval(unescape($2[1]));
-      }
-      
-      $filters.push(newFilter);
-    }
-
-    this.textField.filters = $filters;
-  }
-  
-  private function sIFR(textField, content) {
-    this.textField = textField;
-    this.content   = content;
-
-    var offsetLeft = parseInt(_root.offsetleft);
-    textField._x = MARGIN_LEFT + (isNaN(offsetLeft) ? 0 : offsetLeft);
-    var offsetTop = parseInt(_root.offsettop);
-    if(!isNaN(offsetTop)) textField._y += offsetTop;
-    
-    tuneWidth = parseInt(_root.tunewidth);
-    if(isNaN(tuneWidth)) tuneWidth = 0;
-    tuneHeight = parseInt(_root.tuneheight);
-    if(isNaN(tuneHeight)) tuneHeight = 0;
-
-    textField._width = tuneWidth + (isNaN(parseInt(_root.width)) ? DEFAULT_WIDTH : parseInt(_root.width));
-    textField._height = tuneHeight + (isNaN(parseInt(_root.height)) ? DEFAULT_HEIGHT : parseInt(_root.height));
-    textField.wordWrap = true;
-    textField.selectable = _root.selectable == 'true';
-    textField.gridFitType = sIFR.enforcedGridFitType || _root.gridfittype;
-    this.applyFilters();
-
-    // Determine font-size and the number of lines
-    this.fontSize = parseInt(_root.size);
-    if(isNaN(this.fontSize)) this.fontSize = 26;
-    styles.fontSize = this.fontSize;
-    
-    if(!sIFR.preserveAntiAlias && (sIFR.conditionalAntiAlias && this.fontSize < ALIASING_MAX_FONT_SIZE
-    || !sIFR.conditionalAntiAlias)) {
-      textField.antiAliasType = sIFR.antiAliasType || DEFAULT_ANTI_ALIAS_TYPE;      
-    }
-
-    if(!sIFR.preserveAntiAlias || !isNaN(parseInt(_root.sharpness))) {
-      textField.sharpness = parseInt(_root.sharpness);
-    }
-    if(isNaN(textField.sharpness)) textField.sharpness = sIFR.defaultSharpness;
-
-    if(!sIFR.preserveAntiAlias || !isNaN(parseInt(_root.thickness))) {
-      textField.thickness = parseInt(_root.thickness);
-    }
-    if(isNaN(textField.thickness)) textField.thickness = sIFR.defaultThickness;
-    
-    // Set font-size and other styles
-    sIFR.styles.parseCSS(unescape(_root.css));
-    
-    var rootStyle = styles.getStyle('.sIFR-root') || {};
-    rootStyle.fontSize = this.fontSize; // won't go higher than 126!
-    styles.setStyle('.sIFR-root', rootStyle);
-    textField.styleSheet = styles;
-    
-    this.write(content);
-    this.repaint();
-  }
-  
-  private function repaint() {
-    var leadingFix = this.isSingleLine() ? sIFR.styles.latestLeading : 0;
-    if(leadingFix > 0) leadingFix -= LEADING_REMAINDER;
-
-    // Flash wants to scroll the movie by one line, by adding the fontSize to the
-    // textField height this is no longer happens. We also add the absolute tuneHeight,
-    // to prevent a negative value from triggering the bug. We won't send the fake
-    // value to the JavaScript side, though.
-    textField._height = textField.textHeight + PADDING_BOTTOM + this.fontSize + Math.abs(tuneHeight) + tuneHeight - leadingFix;
-    this.realHeight = textField._height - this.fontSize - Math.abs(tuneHeight);
-    var arg = 'height:' + this.realHeight;
-    if(_root.fitexactly == 'true') arg += ',width:' + (textField.textWidth + tuneWidth);
-    fscommand('resize', arg);
-        
-    this.originalHeight = textField._height;
-    this.currentHeight = Stage.height;
-
-    textField._xscale = textField._yscale = parseInt(_root.zoom);
-  }
-  
-  private function write(content) {
-    this.textField.htmlText = ['<p class="', CSS_ROOT_CLASS, '">', 
-                                content, '</p>'
-                              ].join('');
-  }
-  
-  private function isSingleLine() {
-    return Math.round((this.textField.textHeight - sIFR.styles.latestLeading) / this.fontSize) == 1;
-  }
-
-  //= Scales the text field to the new scale of the Flash movie itself.
-  public function scale() {
-    this.currentHeight = Stage.height;
-    var scale = 100 * Math.round(this.currentHeight / this.originalHeight);
-    textField._xscale = textField._yscale = scale;
-  }
-  
-  private function calculateRatios() {
-    var strings = ['X', 'X<br>X', 'X<br>X<br>X', 'X<br>X<br>X<br>X'];
-    var results = {};
-
-    for(var i = 1; i <= strings.length; i++) {
-      var size = 6;
-    
-      this.write(strings[i - 1]);
-      while(size < MAX_FONT_SIZE) {
-        var rootStyle = sIFR.styles.getStyle('.sIFR-root') || {};
-        rootStyle.fontSize = size;
-        sIFR.styles.setStyle('.sIFR-root', rootStyle);
-        this.textField.styleSheet = sIFR.styles;
-        this.repaint();
-        var ratio = (this.realHeight - PADDING_BOTTOM) / i / size;
-        if(!results[size]) results[size] = ratio;
-        else results[size] = ((i - 1) * results[size] + ratio) / i;
-        size++;
-      }
-    }
-
-    var sizes = [], ratios = [];
-    var ratiosToSizes = {}, sizesToRatios = {};
-
-    for(var size in results) {
-      if(results[size] == Object.prototype[size]) continue;
-      var ratio = results[size];
-      ratiosToSizes[ratio] = Math.max(ratio, parseInt(size));
-    }
-
-    for(var ratio in ratiosToSizes) {
-      if(ratiosToSizes[ratio] == Object.prototype[ratio]) continue;
-      sizesToRatios[ratiosToSizes[ratio]] = roundDecimals(ratio, 2);
-      sizes.push(ratiosToSizes[ratio]);
-    }
-
-    sizes.sort(function(a, b) { return a - b; });
-    for(var j = 0; j < sizes.length - 1; j++) ratios.push(sizes[j], sizesToRatios[sizes[j]]);
-    ratios.push(sizesToRatios[sizes[sizes.length - 1]]);
-
-    fscommand('debug:ratios', '[' + ratios.join(',') + ']');
-  }
-  
-  private function roundDecimals(value, decimals) {
-    return Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);
-  }
-  
-  public static function callback() {
-    switch(_root.callbackType) {
-      case 'replacetext':
-        sIFR.instance.content = _root.callbackValue;
-        sIFR.instance.write(_root.callbackValue);
-        sIFR.instance.repaint();
-        break;
-      case 'resettext':
-        sIFR.instance.write('');
-        sIFR.instance.write(sIFR.instance.content);
-        break;
-      case 'ratios':
-        sIFR.instance.calculateRatios();
-        break;
-    }
-  }
-}
diff --git a/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/sifr.fla b/library/simplepie/demo/for_the_demo/source_files/sIFR-r245/sifr.fla
deleted file mode 100644
index 2aa3f647f4902e189eba92767e211ed0ee15d8b3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 47104
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
INr#WW0e?>J6951J

diff --git a/library/simplepie/demo/for_the_demo/top_gradient.gif b/library/simplepie/demo/for_the_demo/top_gradient.gif
deleted file mode 100644
index f77bd38f97bb39339a19d79a31dbdb97c279b5b4..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 1378
zcmd6lc~6rE0Eep}#c47U9WWK`hEW7OG8bTRe`s)sfNseg;G)pYMapGdJW#VuCek9{
zqE-vxtPb1Kavv>F4iP9vfudE~(w4rx-lOf?`!2N8Z?PxO2Y8a-@6_p(q;G!t3iA^N
z#9;jXz`EbRw(j?>`#o#x-nDhNZ_VXhb9#LakI(M$+1y^M+iP)o%r1|~<uN+lCa1^X
zaH9^l&hFCNU5L#ITb+>A0a_edi$iU;Ys_|)$)+^f0FzB&v;s!kDr%LZR;j@vGgwyi
zW{J)$)|o_zX&EuShmG$(2%$m<eFLIzA#@2e2(*Sptzki<pV#R5YTcYlH>*NsmB@?|
znFe4U08c5PNd+{afL^ac<E!8+IXLz~nRZmB9g%9dE9&7D&5%SrC{c67ssXWzEmHQ2
zl$ie?UwDEsSWEyD|1s_3CKzm>^z6N|`{hJZ#e>SK>W2@`JbL_u{PY>6hMZnk-_Y39
zOnu&%(ejc;XS6a|^t6u7uI`@RzW(mh1A{}{;gQiX?y1)klT*Cunc1n-`GrNn(wnzJ
zLCUg7ELoAt<f{rmDgRER1tA#G>7kQGli6am*&UW-x5w-I@PvTxe(0{$F6ww$=(g~!
zue+X4kiw$V8r)$OQ&o{i3uH6hmw0<{$(6fK_q5ECqyJ=FnC*GVuQ_swZ8*_OTc}UE
zrjy+!lLXDj%RY%p>mw{hrIKSW&h@nl>FGC88`Juk?^)TsnG56nEKw(ZqB6?&8A;Mh
z5Hc_F*~Ke6uLjg}jp>{YIrmyIEa!7N6=S7ATXts*Tm^PiY>Ug8ALv$3SLLTRWeoOc
z`L##0n#KovApteHYWMniA|hn`$jVt5x}l5gy2Nif!)2q=-duQffy*%|UX{6sCx!<s
z>KSre?q9NU8?^Lqdh^+lJN9sKZ=qswgzGX%&sXgEestJlgM~G@<D(-!ms!nk4&;=t
z``k9YLNIpMza0}21C$1b6M(;iUQmI1TN7ZQEG$I~Y~G$pP?kqtW+;gfb%2tDBgUvI
z_EHF{2QjqlFE_`tVO7-;UW~f>Fa@uEm;^G^|9tDLRfirAIiPuTGCW`NIJuIl2|US2
zKs4kZQY3pr&t>LopJiWe)l#yEfVKutJOI}IM)@4X5@@YpT@f1r>kIGTpoZ(q`B396
z@O&Qj4<`aOmxjc`)Vo*k@bij&O!!50LR}2@QA#Y*@-(vmc}XsyBD98^I)qLouH=Wb
zPzrRd3>s6%r2h)&SY5nWeOur14*jM9kg4w&cIxz<+@EoVuF3F1L-))+mZ4`pp+0`o
zQc4`!_b#&#?H6WJQMT-+9_0W;X?w7SQfM56X)NOqbQUmj&Ad3%uzh*w;b1q&GL5b|
z^`<dj3eNm0IHJfr9=iX6IcRI5!8{RmD&8{r=`p-zY$`IZ&BEJN((ro_juda5*;`X&
zosB+9wa&$J3|9V;X_<B7*P<fZLK4(wTTF}tY=Yz1gZ8D95mDDSrtWXIzs*QQ?ZWhE
zoa5cOtYXLe?7WMP4HrsKhX_wP=oIJf#5*Mfdb@L_h=V$%SEuC(8?K9rUGiH{yKA*1
z0&poxv4`Bi{fOOeOvU~Vx2ihP=vG&4!Fe=Kv#xlwwRt(WF%2a~4@4y$^1{tQcrU`B
PcX)MeoTfWC%(4FfURf4^

diff --git a/library/simplepie/demo/for_the_demo/verdana.swf b/library/simplepie/demo/for_the_demo/verdana.swf
deleted file mode 100644
index baf03504737f3ff25b9a7279ef11b9a5ab06bb90..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 28575
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

diff --git a/library/simplepie/demo/for_the_demo/yanone-kaffeesatz-bold.swf b/library/simplepie/demo/for_the_demo/yanone-kaffeesatz-bold.swf
deleted file mode 100644
index c812a79dcf951f14f4332e8b98ad9dd2b903a179..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 76780
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
KVan(Gss9a8mXT%v

diff --git a/library/simplepie/demo/handler_image.php b/library/simplepie/demo/handler_image.php
deleted file mode 100644
index 49c3ec89b2..0000000000
--- a/library/simplepie/demo/handler_image.php
+++ /dev/null
@@ -1,6 +0,0 @@
-<?php
-// This should be modifed as your own use warrants.
-
-require_once('../simplepie.inc');
-SimplePie_Misc::display_cached_file($_GET['i'], './cache', 'spi');
-?>
diff --git a/library/simplepie/demo/index.php b/library/simplepie/demo/index.php
deleted file mode 100644
index 1481ba9172..0000000000
--- a/library/simplepie/demo/index.php
+++ /dev/null
@@ -1,295 +0,0 @@
-<?php
-// Start counting time for the page load
-$starttime = explode(' ', microtime());
-$starttime = $starttime[1] + $starttime[0];
-
-// Include SimplePie
-// Located in the parent directory
-include_once('../simplepie.inc');
-include_once('../idn/idna_convert.class.php');
-
-// Create a new instance of the SimplePie object
-$feed = new SimplePie();
-
-//$feed->force_fsockopen(true);
-
-// Make sure that page is getting passed a URL
-if (isset($_GET['feed']) && $_GET['feed'] !== '')
-{
-	// Strip slashes if magic quotes is enabled (which automatically escapes certain characters)
-	if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
-	{
-		$_GET['feed'] = stripslashes($_GET['feed']);
-	}
-	
-	// Use the URL that was passed to the page in SimplePie
-	$feed->set_feed_url($_GET['feed']);
-	
-	// XML dump
-	$feed->enable_xml_dump(isset($_GET['xmldump']) ? true : false);
-}
-
-// Allow us to change the input encoding from the URL string if we want to. (optional)
-if (!empty($_GET['input']))
-{
-	$feed->set_input_encoding($_GET['input']);
-}
-
-// Allow us to choose to not re-order the items by date. (optional)
-if (!empty($_GET['orderbydate']) && $_GET['orderbydate'] == 'false')
-{
-	$feed->enable_order_by_date(false);
-}
-
-// Allow us to cache images in feeds.  This will also bypass any hotlink blocking put in place by the website.
-if (!empty($_GET['image']) && $_GET['image'] == 'true')
-{
-	$feed->set_image_handler('./handler_image.php');
-}
-
-// We'll enable the discovering and caching of favicons.
-$feed->set_favicon_handler('./handler_image.php');
-
-// Initialize the whole SimplePie object.  Read the feed, process it, parse it, cache it, and 
-// all that other good stuff.  The feed's information will not be available to SimplePie before 
-// this is called.
-$success = $feed->init();
-
-// We'll make sure that the right content type and character encoding gets set automatically.
-// This function will grab the proper character encoding, as well as set the content type to text/html.
-$feed->handle_content_type();
-
-// When we end our PHP block, we want to make sure our DOCTYPE is on the top line to make 
-// sure that the browser snaps into Standards Mode.
-?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US" lang="en-US">
-<head>
-<title>SimplePie: Demo</title>
-
-<link rel="stylesheet" href="./for_the_demo/sIFR-screen.css" type="text/css" media="screen">
-<link rel="stylesheet" href="./for_the_demo/sIFR-print.css" type="text/css" media="print">
-<link rel="stylesheet" href="./for_the_demo/simplepie.css" type="text/css" media="screen, projector" />
-
-<script type="text/javascript" src="./for_the_demo/sifr.js"></script>
-<script type="text/javascript" src="./for_the_demo/sifr-config.js"></script>
-<script type="text/javascript" src="./for_the_demo/sleight.js"></script>
-
-</head>
-
-<body id="bodydemo">
-
-<div id="header">
-	<div id="headerInner">
-		<div id="logoContainer">
-			<div id="logoContainerInner">
-				<div align="center"><a href="http://simplepie.org"><img src="./for_the_demo/logo_simplepie_demo.png" alt="SimplePie Demo: PHP-based RSS and Atom feed handling" title="SimplePie Demo: PHP-based RSS and Atom feed handling" border="0" /></a></div>
-				<div class="clearLeft"></div>
-			</div>
-
-		</div>
-		<div id="menu">
-		<!-- I know, I know, I know... tables for layout, I know.  If a web standards evangelist (like me) has to resort 
-		to using tables for something, it's because no other possible solution could be found.  This issue?  No way to 
-		do centered floats purely with CSS. The table box model allows for a dynamic width while centered, while the 
-		CSS box model for DIVs doesn't allow for it. :( -->
-		<table cellpadding="0" cellspacing="0" border="0"><tbody><tr><td>
-<ul><li id="demo"><a href="./">SimplePie Demo</a></li><li><a href="http://simplepie.org/wiki/faq/start">FAQ/Troubleshooting</a></li><li><a href="http://simplepie.org/support/">Support Forums</a></li><li><a href="http://simplepie.org/wiki/reference/start">API Reference</a></li><li><a href="http://simplepie.org/blog/">Weblog</a></li><li><a href="../test/test.php">Unit Tests</a></li></ul>
-
-			<div class="clearLeft"></div>
-		</td></tr></tbody></table>
-		</div>
-	</div>
-</div>
-
-<div id="site">
-
-	<div id="content">
-
-		<div class="chunk">
-			<form action="" method="get" name="sp_form" id="sp_form">
-				<div id="sp_input">
-
-
-					<!-- If a feed has already been passed through the form, then make sure that the URL remains in the form field. -->
-					<p><input type="text" name="feed" value="<?php if ($feed->subscribe_url()) echo $feed->subscribe_url(); ?>" class="text" id="feed_input" />&nbsp;<input type="submit" value="Read" class="button" /></p>
-
-
-				</div>
-			</form>
-
-
-			<?php
-			// Check to see if there are more than zero errors (i.e. if there are any errors at all)
-			if ($feed->error())
-			{
-				// If so, start a <div> element with a classname so we can style it.
-				echo '<div class="sp_errors">' . "\r\n";
-
-					// ... and display it.
-					echo '<p>' . htmlspecialchars($feed->error()) . "</p>\r\n";
-
-				// Close the <div> element we opened.
-				echo '</div>' . "\r\n";
-			}
-			?>
-
-			<!-- Here are some sample feeds. -->
-			<p class="sample_feeds"><strong>Or try one of the following:</strong> 
-			<a href="?feed=http://www.詹姆斯.com/atomtests/iri/everything.atom" title="Test: International Domain Name support">詹姆斯.com</a>, 
-			<a href="?feed=http://www.adultswim.com/williams/podcast/tools/xml/video_rss.xml" title="Humor from the people who make [adult swim] cartoons.">adult swim</a>, 
-			<a href="?feed=http://afterdawn.com/news/afterdawn_rss.xml" title="Ripping, Burning, DRM, and the Dark Side of Consumer Electronics Media">Afterdawn</a>, 
-			<a href="?feed=http://feeds.feedburner.com/ajaxian" title="AJAX and Scripting News">Ajaxian</a>, 
-			<a href="?feed=http://www.andybudd.com/index.rdf&amp;image=true" title="Test: Bypass Image Hotlink Blocking">Andy Budd</a>, 
-			<a href="?feed=http://feeds.feedburner.com/AskANinja" title="Test: Embedded Enclosures">Ask a Ninja</a>, 
-			<a href="?feed=http://www.atomenabled.org/atom.xml" title="Test: Atom 1.0 Support">AtomEnabled.org</a>, 
-			<a href="?feed=http://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml" title="World News">BBC News</a>, 
-			<a href="?feed=http://newsrss.bbc.co.uk/rss/arabic/news/rss.xml" title="Test: Windows-1256 Encoding">BBC Arabic</a>, 
-			<a href="?feed=http://newsrss.bbc.co.uk/rss/chinese/simp/news/rss.xml" title="Test: GB2312 Encoding">BBC China</a>, 
-			<a href="?feed=http://newsrss.bbc.co.uk/rss/russian/news/rss.xml" title="Test: Windows-1251 Encoding">BBC Russia</a>, 
-			<a href="?feed=http://inessential.com/xml/rss.xml" title="Developer of NetNewsWire">Brent Simmons</a>, 
-			<a href="?feed=http://www.channelfrederator.com/rss" title="Test: Embedded Enclosures">Channel Frederator</a>, 
-			<a href="?feed=http://rss.cnn.com/rss/cnn_topstories.rss" title="World News">CNN</a>, 
-			<a href="?feed=http://digg.com/rss/index.xml" title="Tech news. Better than Slashdot.">Digg</a>, 
-			<a href="?feed=http://revision3.com/diggnation/feed/quicktime-large" title="Tech and industry videocast.">Diggnation</a>, 
-			<a href="?feed=http://www.flickr.com/services/feeds/photos_public.gne?format=rss2" title="Flickr Photos">Flickr</a>, 
-			<a href="?feed=http://news.google.com/?output=rss" title="World News">Google News</a>, 
-			<a href="?feed=http://video.google.com/videofeed?type=top100new&num=20&output=rss" title="Test: Media RSS Support">Google Video</a>, 
-			<a href="?feed=http://blogs.law.harvard.edu/home/feed/rdf/" title="Test: Tag Stripping">Harvard Law</a>, 
-			<a href="?feed=http://hagada.org.il/hagada/html/backend.php" title="Test: Window-1255 Encoding">Hebrew Language</a>, 
-			<a href="?feed=http://www.infoworld.com/rss/news.xml" title="Test: Ad Stripping">InfoWorld</a>, 
-			<a href="?feed=http://phobos.apple.com/WebObjects/MZStore.woa/wpa/MRSS/topsongs/limit=10/rss.xml&orderbydate=false" title="Test: Tag Stripping">iTunes</a>, 
-			<a href="?feed=http://blog.japan.cnet.com/lessig/index.rdf" title="Test: EUC-JP Encoding">Japanese Language</a>, 
-			<a href="?feed=http://nurapt.kaist.ac.kr/~jamaica/htmls/blog/rss.php&amp;input=EUC-KR" title="Test: EUC-KR Encoding">Korean Language</a>, 
-			<a href="?feed=http://mir.aculo.us/xml/rss/feed.xml" title="Weblog for the developer of Scriptaculous">mir.aculo.us</a>, 
-			<a href="?feed=http://images.apple.com/trailers/rss/newtrailers.rss" title="Apple's QuickTime movie trailer site">Movie Trailers</a>, 
-			<a href="?feed=http://www.newspond.com/rss/main.xml" title="Tech and Science News">Newspond</a>, 
-			<a href="?feed=http://nick.typepad.com/blog/index.rss" title="Developer of TopStyle and FeedDemon">Nick Bradbury</a>, 
-			<a href="?feed=http://feeds.feedburner.com/ok-cancel" title="Usability comics and commentary">OK/Cancel</a>, 
-			<a href="?feed=http://osnews.com/files/recent.rdf" title="News about every OS ever">OS News</a>, 
-			<a href="?feed=http://weblog.philringnalda.com/feed/" title="Test: Atom 1.0 Support">Phil Ringnalda</a>, 
-			<a href="?feed=http://kabili.libsyn.com/rss" title="Test: Improved enclosure type sniffing">Photoshop Videocast</a>, 
-			<a href="?feed=http://www.pariurisportive.com/blog/xmlsrv/rss2.php?blog=2" title="Test: ISO-8859-1 Encoding">Romanian Language</a>, 
-			<a href="?feed=http://www.erased.info/rss2.php" title="Test: KOI8-R Encoding">Russian Language</a>, 
-			<a href="?feed=http://www.upsaid.com/isis/index.rdf" title="Test: BIG5 Encoding">Traditional Chinese Language</a>, 
-			<a href="?feed=http://technorati.com/watchlists/rss.html?wid=29290" title="Technorati watch for SimplePie">Technorati</a>, 
-			<a href="?feed=http://www.tbray.org/ongoing/ongoing.atom" title="Test: Atom 1.0 Support">Tim Bray</a>, 
-			<a href="?feed=http://tuaw.com/rss.xml" title="Apple News">TUAW</a>, 
-			<a href="?feed=http://www.tvgasm.com/atom.xml&amp;image=true" title="Test: Bypass Image Hotlink Blocking">TVgasm</a>, 
-			<a href="?feed=http://uneasysilence.com/feed/" title="Interesting tech randomness">UNEASYsilence</a>, 
-			<a href="?feed=http://feeds.feedburner.com/web20Show" title="Test: Embedded Enclosures">Web 2.0 Show</a>, 
-			<a href="?feed=http://windowsvistablog.com/blogs/MainFeed.aspx" title="Test: Tag Stripping">Windows Vista Blog</a>, 
-			<a href="?feed=http://xkcd.com/rss.xml" title="Test: LightHTTPd and GZipping">XKCD</a>, 
-			<a href="?feed=http://rss.news.yahoo.com/rss/topstories" title="World News">Yahoo! News</a>, 
-			<a href="?feed=http://youtube.com/rss/global/top_favorites.rss" title="Funny user-submitted videos">You Tube</a>, 
-			<a href="?feed=http://zeldman.com/rss/" title="The father of the web standards movement">Zeldman</a></p>
-
-		</div>
-
-		<div id="sp_results">
-
-			<!-- As long as the feed has data to work with... -->
-			<?php if ($success): ?>
-				<div class="chunk focus" align="center">
-
-					<!-- If the feed has a link back to the site that publishes it (which 99% of them do), link the feed's title to it. -->
-					<h3 class="header"><?php if ($feed->get_link()) echo '<a href="' . $feed->get_link() . '">'; echo $feed->get_title(); if ($feed->get_link()) echo '</a>'; ?></h3>
-
-					<!-- If the feed has a description, display it. -->
-					<?php echo $feed->get_description(); ?>
-
-				</div>
-
-				<!-- Add subscribe links for several different aggregation services -->
-				<p class="subscribe"><strong>Subscribe:</strong> <a href="<?php echo $feed->subscribe_bloglines(); ?>">Bloglines</a>, <a href="<?php echo $feed->subscribe_google(); ?>">Google Reader</a>, <a href="<?php echo $feed->subscribe_msn(); ?>">My MSN</a>, <a href="<?php echo $feed->subscribe_netvibes(); ?>">Netvibes</a>, <a href="<?php echo $feed->subscribe_newsburst(); ?>">Newsburst</a><br /><a href="<?php echo $feed->subscribe_newsgator(); ?>">Newsgator</a>, <a href="<?php echo $feed->subscribe_odeo(); ?>">Odeo</a>, <a href="<?php echo $feed->subscribe_podnova(); ?>">Podnova</a>, <a href="<?php echo $feed->subscribe_rojo(); ?>">Rojo</a>, <a href="<?php echo $feed->subscribe_yahoo(); ?>">My Yahoo!</a>, <a href="<?php echo $feed->subscribe_feed(); ?>">Desktop Reader</a></p>
-
-
-				<!-- Let's begin looping through each individual news item in the feed. -->
-				<?php foreach($feed->get_items() as $item): ?>
-					<div class="chunk">
-
-						<?php
-						// Let's add a favicon for each item. If one doesn't exist, we'll use an alternate one.
-						if (!$favicon = $feed->get_favicon())
-						{
-							$favicon = './for_the_demo/favicons/alternate.png';
-						}
-						?>
-
-						<!-- If the item has a permalink back to the original post (which 99% of them do), link the item's title to it. -->
-						<h4><img src="<?php echo $favicon; ?>" alt="Favicon" class="favicon" /><?php if ($item->get_permalink()) echo '<a href="' . $item->get_permalink() . '">'; echo $item->get_title(); if ($item->get_permalink()) echo '</a>'; ?>&nbsp;<span class="footnote"><?php echo $item->get_date('j M Y, g:i a'); ?></span></h4>
-
-						<!-- Display the item's primary content. -->
-						<?php echo $item->get_content(); ?>
-
-						<?php
-						// Check for enclosures.  If an item has any, set the first one to the $enclosure variable.
-						if ($enclosure = $item->get_enclosure(0))
-						{
-							// Use the embed() method to embed the enclosure into the page inline.
-							echo '<div align="center">';
-							echo '<p>' . $enclosure->embed(array(
-								'audio' => './for_the_demo/place_audio.png',
-								'video' => './for_the_demo/place_video.png',
-								'mediaplayer' => './for_the_demo/mediaplayer.swf',
-								'altclass' => 'download'
-							)) . '</p>';
-
-							if ($enclosure->get_link() && $enclosure->get_type())
-							{
-								echo '<p class="footnote" align="center">(' . $enclosure->get_type();
-								if ($enclosure->get_size())
-								{
-									echo '; ' . $enclosure->get_size() . ' MB';								
-								}
-								echo ')</p>';
-							}
-							if ($enclosure->get_thumbnail())
-							{
-								echo '<div><img src="' . $enclosure->get_thumbnail() . '" alt="" /></div>';
-							}
-							echo '</div>';
-						}
-						?>
-
-						<!-- Add links to add this post to one of a handful of services. -->
-						<p class="footnote favicons" align="center">
-							<a href="<?php echo $item->add_to_blinklist(); ?>" title="Add post to Blinklist"><img src="./for_the_demo/favicons/blinklist.png" alt="Blinklist" /></a>
-							<a href="<?php echo $item->add_to_blogmarks(); ?>" title="Add post to Blogmarks"><img src="./for_the_demo/favicons/blogmarks.png" alt="Blogmarks" /></a>
-							<a href="<?php echo $item->add_to_delicious(); ?>" title="Add post to del.icio.us"><img src="./for_the_demo/favicons/delicious.png" alt="del.icio.us" /></a>
-							<a href="<?php echo $item->add_to_digg(); ?>" title="Digg this!"><img src="./for_the_demo/favicons/digg.png" alt="Digg" /></a>
-							<a href="<?php echo $item->add_to_magnolia(); ?>" title="Add post to Ma.gnolia"><img src="./for_the_demo/favicons/magnolia.png" alt="Ma.gnolia" /></a>
-							<a href="<?php echo $item->add_to_myweb20(); ?>" title="Add post to My Web 2.0"><img src="./for_the_demo/favicons/myweb2.png" alt="My Web 2.0" /></a>
-							<a href="<?php echo $item->add_to_newsvine(); ?>" title="Add post to Newsvine"><img src="./for_the_demo/favicons/newsvine.png" alt="Newsvine" /></a>
-							<a href="<?php echo $item->add_to_reddit(); ?>" title="Add post to Reddit"><img src="./for_the_demo/favicons/reddit.png" alt="Reddit" /></a>
-							<a href="<?php echo $item->add_to_segnalo(); ?>" title="Add post to Segnalo"><img src="./for_the_demo/favicons/segnalo.png" alt="Segnalo" /></a>
-							<a href="<?php echo $item->add_to_simpy(); ?>" title="Add post to Simpy"><img src="./for_the_demo/favicons/simpy.png" alt="Simpy" /></a>
-							<a href="<?php echo $item->add_to_spurl(); ?>" title="Add post to Spurl"><img src="./for_the_demo/favicons/spurl.png" alt="Spurl" /></a>
-							<a href="<?php echo $item->add_to_wists(); ?>" title="Add post to Wists"><img src="./for_the_demo/favicons/wists.png" alt="Wists" /></a>
-							<a href="<?php echo $item->search_technorati(); ?>" title="Who's linking to this post?"><img src="./for_the_demo/favicons/technorati.png" alt="Technorati" /></a>
-						</p>
-
-					</div>
-
-				<!-- Stop looping through each item once we've gone through all of them. -->
-				<?php endforeach; ?>
-
-			<!-- From here on, we're no longer using data from the feed. -->
-			<?php endif; ?>
-
-		</div>
-
-		<div>
-			<!-- Display how fast the page was rendered. -->
-			<p class="footnote">Page processed in <?php $mtime = explode(' ', microtime()); echo round($mtime[0] + $mtime[1] - $starttime, 3); ?> seconds.</p>
-
-			<!-- Display the version of SimplePie being loaded. -->
-			<p class="footnote">Powered by <a href="<?php echo SIMPLEPIE_URL; ?>"><?php echo SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . ', Build ' . SIMPLEPIE_BUILD; ?></a>.  Run the <a href="../compatibility_test/sp_compatibility_test.php">SimplePie Compatibility Test</a>.  SimplePie is &copy; 2004&ndash;<?php echo date('Y'); ?>, Ryan Parman and Geoffrey Sneddon, and licensed under the <a href="http://www.opensource.org/licenses/bsd-license.php">BSD License</a>.</p>
-		</div>
-
-	</div>
-
-</div>
-
-</body>
-</html>
diff --git a/library/simplepie/demo/minimalistic.php b/library/simplepie/demo/minimalistic.php
deleted file mode 100644
index 56509c00cb..0000000000
--- a/library/simplepie/demo/minimalistic.php
+++ /dev/null
@@ -1,137 +0,0 @@
-<?php
-
-function microtime_float()
-{
-	if (version_compare(phpversion(), '5.0.0', '>='))
-	{
-		return microtime(true);
-	}
-	else
-	{
-		list($usec, $sec) = explode(' ', microtime());
-		return ((float) $usec + (float) $sec);
-	}
-}
-
-$start = microtime_float();
-
-include('../simplepie.inc');
-
-// Parse it
-$feed = new SimplePie();
-if (!empty($_GET['feed']))
-{
-	if (get_magic_quotes_gpc())
-	{
-		$_GET['feed'] = stripslashes($_GET['feed']);
-	}
-	$feed->set_feed_url($_GET['feed']);
-	$feed->init();
-}
-$feed->handle_content_type();
-
-?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<title><?php echo (empty($_GET['feed'])) ? 'SimplePie' : 'SimplePie: ' . $feed->get_title(); ?></title>
-
-<!-- META HTTP-EQUIV -->
-<meta http-equiv="content-type" content="text/html; charset=<?php echo ($feed->get_encoding()) ? $feed->get_encoding() : 'UTF-8'; ?>" />
-<meta http-equiv="imagetoolbar" content="false" />
-
-<style type="text/css">
-html, body {
-	height:100%;
-	margin:0;
-	padding:0;
-}
-
-h1 {
-	background-color:#333;
-	color:#fff;
-	font-size:3em;
-	margin:0;
-	padding:5px 15px;
-	text-align:center;
-}
-
-div#footer {
-	padding:5px 0;
-}
-
-div#footer,
-div#footer a {
-	text-align:center;
-	font-size:0.7em;
-}
-
-div#footer a {
-	text-decoration:underline;
-}
-
-code {
-	background-color:#f3f3ff;
-	color:#000;
-}
-
-pre {
-	background-color:#f3f3ff;
-	color:#000080;
-	border:1px dotted #000080;
-	padding:3px 5px;
-}
-
-form {
-	margin:0;
-	padding:0;
-}
-
-div.chunk {
-	border-bottom:1px solid #ccc;
-}
-
-form#sp_form {
-	text-align:center;
-	margin:0;
-	padding:0;
-}
-
-form#sp_form input.text {
-	width:85%;
-}
-</style>
-
-</head>
-
-<body>
-	<h1><?php echo (empty($_GET['feed'])) ? 'SimplePie' : 'SimplePie: ' . $feed->get_title(); ?></h1>
-
-	<form action="" method="get" name="sp_form" id="sp_form">
-		<p><input type="text" name="feed" value="<?php echo ($feed->subscribe_url()) ? htmlspecialchars($feed->subscribe_url()) : 'http://'; ?>" class="text" id="feed_input" />&nbsp;<input type="submit" value="Read" class="button" /></p>
-	</form>
-
-	<div id="sp_results">
-		<?php if ($feed->data): ?>
-			<?php $items = $feed->get_items(); ?>
-			<p align="center"><span style="background-color:#ffc;">Displaying <?php echo $feed->get_item_quantity(); ?> most recent entries.</span></p>
-			<?php foreach($items as $item): ?>
-				<div class="chunk" style="padding:0 5px;">
-					<h4><a href="<?php echo $item->get_permalink(); ?>"><?php echo $item->get_title(); ?></a> <?php echo $item->get_date('j M Y'); ?></h4>
-					<?php echo $item->get_content(); ?>
-					<?php
-					if ($enclosure = $item->get_enclosure(0))
-						echo '<p><a href="' . $enclosure->get_link() . '" class="download"><img src="./for_the_demo/mini_podcast.png" alt="Podcast" title="Download the Podcast" border="0" /></a></p>';
-					?>
-				</div>
-			<?php endforeach; ?>
-			</div>
-		<?php endif; ?>
-	</div>
-
-	<div id="footer">
-		Powered by <?php echo SIMPLEPIE_LINKBACK; ?>, a product of <a href="http://www.skyzyx.com">Skyzyx Technologies</a>.<br />
-		Page created in <?php echo round(microtime_float()-$start, 3); ?> seconds.
-	</div>
-</body>
-</html>
diff --git a/library/simplepie/demo/multifeeds.php b/library/simplepie/demo/multifeeds.php
deleted file mode 100644
index b23d792a2f..0000000000
--- a/library/simplepie/demo/multifeeds.php
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-/********************************************************************
-MULTIFEEDS TEST PAGE
-
-Nothing too exciting here.  Just a sample page that demos integrated 
-Multifeeds support as well as cached favicons and perhaps a few other 
-things.
-
-Lots of this code is commented to help explain some of the new stuff.  
-Code was tested in PHP 5.2.2, but *should* also work with earlier 
-versions of PHP, as supported by SimplePie (PHP 4.1).
-
-********************************************************************/
-
-// Include the SimplePie library, and the one that handles internationalized domain names.
-require_once('../simplepie.inc');
-require_once('../idn/idna_convert.class.php');
-
-// Initialize some feeds for use.
-$feed = new SimplePie();
-$feed->set_feed_url(array(
-	'http://rss.news.yahoo.com/rss/topstories',
-	'http://news.google.com/?output=atom',
-	'http://rss.cnn.com/rss/cnn_topstories.rss'
-));
-
-// When we set these, we need to make sure that the handler_image.php file is also trying to read from the same cache directory that we are.
-$feed->set_favicon_handler('./handler_image.php');
-$feed->set_image_handler('./handler_image.php');
-
-// Initialize the feed.
-$feed->init();
-
-// Make sure the page is being served with the UTF-8 headers.
-$feed->handle_content_type();
-
-// Begin the (X)HTML page.
-?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">	
-<head>
-	<title>Multifeeds Test page</title>
-	<link rel="stylesheet" href="../demo/for_the_demo/simplepie.css" type="text/css" media="screen" title="SimplePie Styles" charset="utf-8" />
-	<style type="text/css">
-	div#site {
-		width:600px;
-	}
-	span.footnote {
-		white-space:nowrap;
-	}
-	h1 {
-		line-height:1.4em;
-	}
-	h4 {
-		padding-left:20px;
-		background-color:transparent;
-		background-repeat:no-repeat;
-		background-position:0 1px;
-	}
-	.clearBoth {
-		clear:both;
-	}
-	</style>
-</head>
-<body>
-<div id="site">
-
-	<?php if ($feed->error): ?>
-		<p><?=$feed->error()?></p>
-	<?php endif ?>
-
-	<div class="chunk">
-		<h1>Quick-n-Dirty Multifeeds Demo</a></h1>
-	</div>
-
-	<?php
-	// Let's loop through each item in the feed.
-	foreach($feed->get_items() as $item):
-
-	// Let's give ourselves a reference to the parent $feed object for this particular item.
-	$feed = $item->get_feed();
-	?>
-
-		<div class="chunk">
-			<h4 style="background-image:url(<?php echo $feed->get_favicon(); ?>);"><a href="<?php echo $item->get_permalink(); ?>"><?php echo html_entity_decode($item->get_title(), ENT_QUOTES, 'UTF-8'); ?></a></h4>
-
-			<!-- get_content() prefers full content over summaries -->
-			<?php echo $item->get_content(); ?>
-
-			<?php if ($enclosure = $item->get_enclosure()): ?>
-				<div>
-				<?php echo $enclosure->native_embed(array(
-					// New 'mediaplayer' attribute shows off Flash-based MP3 and FLV playback.
-					'mediaplayer' => '../demo/for_the_demo/mediaplayer.swf'
-				)); ?>
-				</div>
-			<?php endif; ?>
-
-			<p class="footnote">Source: <a href="<?php echo $feed->get_permalink(); ?>"><?php echo $feed->get_title(); ?></a> | <?php echo $item->get_date('j M Y | g:i a'); ?></p>
-		</div>
-
-	<?php endforeach ?>
-
-	<p class="footnote">This is a test of the emergency broadcast system.  This is only a test&hellip; beeeeeeeeeeeeeeeeeeeeeeeeeep!</p>
-
-</div>
-</body>
-</html>
\ No newline at end of file
diff --git a/library/simplepie/demo/test.php b/library/simplepie/demo/test.php
deleted file mode 100644
index 5b9943abbc..0000000000
--- a/library/simplepie/demo/test.php
+++ /dev/null
@@ -1,62 +0,0 @@
-<?php
-include_once('../simplepie.inc');
-include_once('../idn/idna_convert.class.php');
-
-// Parse it
-$feed = new SimplePie();
-if (isset($_GET['feed']) && $_GET['feed'] !== '')
-{
-	if (get_magic_quotes_gpc())
-	{
-		$_GET['feed'] = stripslashes($_GET['feed']);
-	}
-	$feed->set_feed_url($_GET['feed']);
-	$feed->enable_cache(false);
-	$starttime = explode(' ', microtime());
-	$starttime = $starttime[1] + $starttime[0];
-	$feed->init();
-	$endtime = explode(' ', microtime());
-	$endtime = $endtime[1] + $endtime[0];
-	$time = $endtime - $starttime;
-}
-else
-{
-	$time = 'null';
-}
-
-$feed->handle_content_type();
-
-?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
-<title>SimplePie Test</title>
-<pre>
-<?php
-
-// memory_get_peak_usage() only exists on PHP 5.2 and higher if PHP is compiled with the --enable-memory-limit configuration option or on PHP 5.2.1 and higher (which runs as if --enable-memory-limit was on, with no option)
-if (function_exists('memory_get_peak_usage'))
-{
-	var_dump($time, memory_get_usage(), memory_get_peak_usage());
-}
-// memory_get_usage() only exists if PHP is compiled with the --enable-memory-limit configuration option or on PHP 5.2.1 and higher (which runs as if --enable-memory-limit was on, with no option)
-else if (function_exists('memory_get_usage'))
-{
-	var_dump($time, memory_get_usage());
-}
-else
-{
-	var_dump($time);
-}
-
-// Output buffer
-function callable_htmlspecialchars($string)
-{
-	return htmlspecialchars($string);
-}
-ob_start('callable_htmlspecialchars');
-
-// Output
-print_r($feed);
-ob_end_flush();
-
-?>
-</pre>
\ No newline at end of file
diff --git a/library/simplepie/idn/LICENCE b/library/simplepie/idn/LICENCE
deleted file mode 100644
index 25a1d22dfe..0000000000
--- a/library/simplepie/idn/LICENCE
+++ /dev/null
@@ -1,502 +0,0 @@
-                  GNU LESSER GENERAL PUBLIC LICENSE
-                       Version 2.1, February 1999
-
- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
-     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the Lesser GPL.  It also counts
- as the successor of the GNU Library Public License, version 2, hence
- the version number 2.1.]
-
-                            Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Lesser General Public License, applies to some
-specially designated software packages--typically libraries--of the
-Free Software Foundation and other authors who decide to use it.  You
-can use it too, but we suggest you first think carefully about whether
-this license or the ordinary General Public License is the better
-strategy to use in any particular case, based on the explanations below.
-
-  When we speak of free software, we are referring to freedom of use,
-not price.  Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of
-it in new free programs; and that you are informed that you can do
-these things.
-
-  To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights.  These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  To protect each distributor, we want to make it very clear that
-there is no warranty for the free library.  Also, if the library is
-modified by someone else and passed on, the recipients should know
-that what they have is not the original version, so that the original
-author's reputation will not be affected by problems that might be
-introduced by others.
-
-  Finally, software patents pose a constant threat to the existence of
-any free program.  We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder.  Therefore, we insist that
-any patent license obtained for a version of the library must be
-consistent with the full freedom of use specified in this license.
-
-  Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License.  This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and
-is quite different from the ordinary General Public License.  We use
-this license for certain libraries in order to permit linking those
-libraries into non-free programs.
-
-  When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library.  The ordinary
-General Public License therefore permits such linking only if the
-entire combination fits its criteria of freedom.  The Lesser General
-Public License permits more lax criteria for linking other code with
-the library.
-
-  We call this license the "Lesser" General Public License because it
-does Less to protect the user's freedom than the ordinary General
-Public License.  It also provides other free software developers Less
-of an advantage over competing non-free programs.  These disadvantages
-are the reason we use the ordinary General Public License for many
-libraries.  However, the Lesser license provides advantages in certain
-special circumstances.
-
-  For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it becomes
-a de-facto standard.  To achieve this, non-free programs must be
-allowed to use the library.  A more frequent case is that a free
-library does the same job as widely used non-free libraries.  In this
-case, there is little to gain by limiting the free library to free
-software only, so we use the Lesser General Public License.
-
-  In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of
-free software.  For example, permission to use the GNU C Library in
-non-free programs enables many more people to use the whole GNU
-operating system, as well as its variant, the GNU/Linux operating
-system.
-
-  Although the Lesser General Public License is Less protective of the
-users' freedom, it does ensure that the user of a program that is
-linked with the Library has the freedom and the wherewithal to run
-that program using a modified version of the Library.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
-                  GNU LESSER GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library or other
-program which contains a notice placed by the copyright holder or
-other authorized party saying it may be distributed under the terms of
-this Lesser General Public License (also called "this License").
-Each licensee is addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also combine or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Use a suitable shared library mechanism for linking with the
-    Library.  A suitable mechanism is one that (1) uses at run time a
-    copy of the library already present on the user's computer system,
-    rather than copying library functions into the executable, and (2)
-    will operate properly with a modified version of the library, if
-    the user installs one, as long as the modified version is
-    interface-compatible with the version that the work was made with.
-
-    c) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    d) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    e) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the materials to be distributed need not include anything that is
-normally distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties with
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Lesser General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-                            NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-                     END OF TERMS AND CONDITIONS
-
-           How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
diff --git a/library/simplepie/idn/ReadMe.txt b/library/simplepie/idn/ReadMe.txt
deleted file mode 100644
index 7ca8c7e6de..0000000000
--- a/library/simplepie/idn/ReadMe.txt
+++ /dev/null
@@ -1,123 +0,0 @@
-*******************************************************************************
-*                                                                             *
-*                    IDNA Convert (idna_convert.class.php)                    *
-*                                                                             *
-* http://idnaconv.phlymail.de                     mailto:phlymail@phlylabs.de *
-*******************************************************************************
-* (c) 2004-2007 phlyLabs, Berlin                                              *
-* This file is encoded in UTF-8                                               *
-*******************************************************************************
-
-Introduction
-------------
-
-The class idna_convert allows to convert internationalized domain names
-(see RFC 3490, 3491, 3492 and 3454 for detials) as they can be used with various
-registries worldwide to be translated between their original (localized) form
-and their encoded form as it will be used in the DNS (Domain Name System).
-
-The class provides two public methods, encode() and decode(), which do exactly
-what you would expect them to do. You are allowed to use complete domain names,
-simple strings and complete email addresses as well. That means, that you might
-use any of the following notations:
-
-- www.nörgler.com
-- xn--nrgler-wxa
-- xn--brse-5qa.xn--knrz-1ra.info
-
-Errors, incorrectly encoded or invalid strings will lead to either a FALSE
-response (when in strict mode) or to only partially converted strings.
-You can query the occured error by calling the method get_last_error().
-
-Unicode strings are expected to be either UTF-8 strings, UCS-4 strings or UCS-4
-arrays. The default format is UTF-8. For setting different encodings, you can
-call the method setParams() - please see the inline documentation for details.
-ACE strings (the Punycode form) are always 7bit ASCII strings.
-
-ATTENTION: We no longer supply the PHP5 version of the class. It is not
-necessary for achieving a successfull conversion, since the supplied PHP code is
-compatible with both PHP4 and PHP5. We expect to see no compatibility issues
-with the upcoming PHP6, too.
-
-
-Files
------
-
-idna_convert.class.php         - The actual class
-idna_convert.create.npdata.php - Useful for (re)creating the NPData file
-npdata.ser                     - Serialized data for NamePrep
-example.php                    - An example web page for converting
-ReadMe.txt                     - This file
-LICENCE                        - The LGPL licence file
-
-The class is contained in idna_convert.class.php.
-MAKE SURE to copy the npdata.ser file into the same folder as the class file
-itself!
-
-
-Examples
---------
-
-1. Say we wish to encode the domain name nörgler.com:
-
-// Include the class
-include_once('idna_convert.class.php');
-// Instantiate it *
-$IDN = new idna_convert();
-// The input string, if input is not UTF-8 or UCS-4, it must be converted before
-$input = utf8_encode('nörgler.com');
-// Encode it to its punycode presentation
-$output = $IDN->encode($input);
-// Output, what we got now
-echo $output; // This will read: xn--nrgler-wxa.com
-
-
-2. We received an email from a punycoded domain and are willing to learn, how
-   the domain name reads originally
-
-// Include the class
-include_once('idna_convert.class.php');
-// Instantiate it (depending on the version you are using) with
-$IDN = new idna_convert();
-// The input string
-$input = 'andre@xn--brse-5qa.xn--knrz-1ra.info';
-// Encode it to its punycode presentation
-$output = $IDN->decode($input);
-// Output, what we got now, if output should be in a format different to UTF-8
-// or UCS-4, you will have to convert it before outputting it
-echo utf8_decode($output); // This will read: andre@börse.knörz.info
-
-
-3. The input is read from a UCS-4 coded file and encoded line by line. By
-   appending the optional second parameter we tell enode() about the input
-   format to be used
-
-// Include the class
-include_once('idna_convert.class.php');
-// Instantiate it
-$IDN = new dinca_convert();
-// Iterate through the input file line by line
-foreach (file('ucs4-domains.txt') as $line) {
-    echo $IDN->encode(trim($line), 'ucs4_string');
-    echo "\n";
-}
-
-
-NPData
-------
-
-Should you need to recreate the npdata.ser file, which holds all necessary translation
-tables in a serialized format, you can run the file idna_convert.create.npdata.php, which
-creates the file for you and stores it in the same folder, where it is placed.
-Should you need to do changes to the tables you can do so, but beware of the consequences.
-
-
-Contact us
-----------
-
-In case of errors, bugs, questions, wishes, please don't hesitate to contact us
-under the email address above.
-
-The team of phlyLabs
-http://phlylabs.de
-mailto:phlymail@phlylabs.de
\ No newline at end of file
diff --git a/library/simplepie/idn/idna_convert.class.php b/library/simplepie/idn/idna_convert.class.php
deleted file mode 100644
index ed2bae26db..0000000000
--- a/library/simplepie/idn/idna_convert.class.php
+++ /dev/null
@@ -1,969 +0,0 @@
-<?php
-// {{{ license
-
-/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 foldmethod=marker: */
-//
-// +----------------------------------------------------------------------+
-// | This library is free software; you can redistribute it and/or modify |
-// | it under the terms of the GNU Lesser General Public License as       |
-// | published by the Free Software Foundation; either version 2.1 of the |
-// | License, or (at your option) any later version.                      |
-// |                                                                      |
-// | This library is distributed in the hope that it will be useful, but  |
-// | WITHOUT ANY WARRANTY; without even the implied warranty of           |
-// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    |
-// | Lesser General Public License for more details.                      |
-// |                                                                      |
-// | You should have received a copy of the GNU Lesser General Public     |
-// | License along with this library; if not, write to the Free Software  |
-// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 |
-// | USA.                                                                 |
-// +----------------------------------------------------------------------+
-//
-
-// }}}
-
-/**
- * Encode/decode Internationalized Domain Names.
- *
- * The class allows to convert internationalized domain names
- * (see RFC 3490 for details) as they can be used with various registries worldwide
- * to be translated between their original (localized) form and their encoded form
- * as it will be used in the DNS (Domain Name System).
- *
- * The class provides two public methods, encode() and decode(), which do exactly
- * what you would expect them to do. You are allowed to use complete domain names,
- * simple strings and complete email addresses as well. That means, that you might
- * use any of the following notations:
- *
- * - www.nörgler.com
- * - xn--nrgler-wxa
- * - xn--brse-5qa.xn--knrz-1ra.info
- *
- * Unicode input might be given as either UTF-8 string, UCS-4 string or UCS-4
- * array. Unicode output is available in the same formats.
- * You can select your preferred format via {@link set_paramter()}.
- *
- * ACE input and output is always expected to be ASCII.
- *
- * @author  Matthias Sommerfeld <mso@phlylabs.de>
- * @copyright 2004-2007 phlyLabs Berlin, http://phlylabs.de
- * @version 0.5.1
- *
- */
-class idna_convert
-{
-    /**
-     * Holds all relevant mapping tables, loaded from a seperate file on construct
-     * See RFC3454 for details
-     *
-     * @var array
-     * @access private
-     */
-    var $NP = array();
-
-    // Internal settings, do not mess with them
-    var $_punycode_prefix = 'xn--';
-    var $_invalid_ucs =     0x80000000;
-    var $_max_ucs =         0x10FFFF;
-    var $_base =            36;
-    var $_tmin =            1;
-    var $_tmax =            26;
-    var $_skew =            38;
-    var $_damp =            700;
-    var $_initial_bias =    72;
-    var $_initial_n =       0x80;
-    var $_sbase =           0xAC00;
-    var $_lbase =           0x1100;
-    var $_vbase =           0x1161;
-    var $_tbase =           0x11A7;
-    var $_lcount =          19;
-    var $_vcount =          21;
-    var $_tcount =          28;
-    var $_ncount =          588;   // _vcount * _tcount
-    var $_scount =          11172; // _lcount * _tcount * _vcount
-    var $_error =           false;
-
-    // See {@link set_paramter()} for details of how to change the following
-    // settings from within your script / application
-    var $_api_encoding   =  'utf8'; // Default input charset is UTF-8
-    var $_allow_overlong =  false;  // Overlong UTF-8 encodings are forbidden
-    var $_strict_mode    =  false;  // Behave strict or not
-
-    // The constructor
-    function idna_convert($options = false)
-    {
-        $this->slast = $this->_sbase + $this->_lcount * $this->_vcount * $this->_tcount;
-        if (function_exists('file_get_contents')) {
-            $this->NP = unserialize(file_get_contents(dirname(__FILE__).'/npdata.ser'));
-        } else {
-            $this->NP = unserialize(join('', file(dirname(__FILE__).'/npdata.ser')));
-        }
-        // If parameters are given, pass these to the respective method
-        if (is_array($options)) {
-            return $this->set_parameter($options);
-        }
-        return true;
-    }
-
-    /**
-     * Sets a new option value. Available options and values:
-     * [encoding - Use either UTF-8, UCS4 as array or UCS4 as string as input ('utf8' for UTF-8,
-     *         'ucs4_string' and 'ucs4_array' respectively for UCS4); The output is always UTF-8]
-     * [overlong - Unicode does not allow unnecessarily long encodings of chars,
-     *             to allow this, set this parameter to true, else to false;
-     *             default is false.]
-     * [strict - true: strict mode, good for registration purposes - Causes errors
-     *           on failures; false: loose mode, ideal for "wildlife" applications
-     *           by silently ignoring errors and returning the original input instead
-     *
-     * @param    mixed     Parameter to set (string: single parameter; array of Parameter => Value pairs)
-     * @param    string    Value to use (if parameter 1 is a string)
-     * @return   boolean   true on success, false otherwise
-     * @access   public
-     */
-    function set_parameter($option, $value = false)
-    {
-        if (!is_array($option)) {
-            $option = array($option => $value);
-        }
-        foreach ($option as $k => $v) {
-            switch ($k) {
-            case 'encoding':
-                switch ($v) {
-                case 'utf8':
-                case 'ucs4_string':
-                case 'ucs4_array':
-                    $this->_api_encoding = $v;
-                    break;
-                default:
-                    $this->_error('Set Parameter: Unknown parameter '.$v.' for option '.$k);
-                    return false;
-                }
-                break;
-            case 'overlong':
-                $this->_allow_overlong = ($v) ? true : false;
-                break;
-            case 'strict':
-                $this->_strict_mode = ($v) ? true : false;
-                break;
-            default:
-                $this->_error('Set Parameter: Unknown option '.$k);
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Decode a given ACE domain name
-     * @param    string   Domain name (ACE string)
-     * [@param    string   Desired output encoding, see {@link set_parameter}]
-     * @return   string   Decoded Domain name (UTF-8 or UCS-4)
-     * @access   public
-     */
-    function decode($input, $one_time_encoding = false)
-    {
-        // Optionally set
-        if ($one_time_encoding) {
-            switch ($one_time_encoding) {
-            case 'utf8':
-            case 'ucs4_string':
-            case 'ucs4_array':
-                break;
-            default:
-                $this->_error('Unknown encoding '.$one_time_encoding);
-                return false;
-            }
-        }
-        // Make sure to drop any newline characters around
-        $input = trim($input);
-
-        // Negotiate input and try to determine, whether it is a plain string,
-        // an email address or something like a complete URL
-        if (strpos($input, '@')) { // Maybe it is an email address
-            // No no in strict mode
-            if ($this->_strict_mode) {
-                $this->_error('Only simple domain name parts can be handled in strict mode');
-                return false;
-            }
-            list ($email_pref, $input) = explode('@', $input, 2);
-            $arr = explode('.', $input);
-            foreach ($arr as $k => $v) {
-                if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) {
-                    $conv = $this->_decode($v);
-                    if ($conv) $arr[$k] = $conv;
-                }
-            }
-            $input = join('.', $arr);
-            $arr = explode('.', $email_pref);
-            foreach ($arr as $k => $v) {
-                if (preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $v)) {
-                    $conv = $this->_decode($v);
-                    if ($conv) $arr[$k] = $conv;
-                }
-            }
-            $email_pref = join('.', $arr);
-            $return = $email_pref . '@' . $input;
-        } elseif (preg_match('![:\./]!', $input)) { // Or a complete domain name (with or without paths / parameters)
-            // No no in strict mode
-            if ($this->_strict_mode) {
-                $this->_error('Only simple domain name parts can be handled in strict mode');
-                return false;
-            }
-            $parsed = parse_url($input);
-            if (isset($parsed['host'])) {
-                $arr = explode('.', $parsed['host']);
-                foreach ($arr as $k => $v) {
-                    $conv = $this->_decode($v);
-                    if ($conv) $arr[$k] = $conv;
-                }
-                $parsed['host'] = join('.', $arr);
-                $return =
-                        (empty($parsed['scheme']) ? '' : $parsed['scheme'].(strtolower($parsed['scheme']) == 'mailto' ? ':' : '://'))
-                        .(empty($parsed['user']) ? '' : $parsed['user'].(empty($parsed['pass']) ? '' : ':'.$parsed['pass']).'@')
-                        .$parsed['host']
-                        .(empty($parsed['port']) ? '' : ':'.$parsed['port'])
-                        .(empty($parsed['path']) ? '' : $parsed['path'])
-                        .(empty($parsed['query']) ? '' : '?'.$parsed['query'])
-                        .(empty($parsed['fragment']) ? '' : '#'.$parsed['fragment']);
-            } else { // parse_url seems to have failed, try without it
-                $arr = explode('.', $input);
-                foreach ($arr as $k => $v) {
-                    $conv = $this->_decode($v);
-                    $arr[$k] = ($conv) ? $conv : $v;
-                }
-                $return = join('.', $arr);
-            }
-        } else { // Otherwise we consider it being a pure domain name string
-            $return = $this->_decode($input);
-            if (!$return) $return = $input;
-        }
-        // The output is UTF-8 by default, other output formats need conversion here
-        // If one time encoding is given, use this, else the objects property
-        switch (($one_time_encoding) ? $one_time_encoding : $this->_api_encoding) {
-        case 'utf8':
-            return $return;
-            break;
-        case 'ucs4_string':
-           return $this->_ucs4_to_ucs4_string($this->_utf8_to_ucs4($return));
-           break;
-        case 'ucs4_array':
-            return $this->_utf8_to_ucs4($return);
-            break;
-        default:
-            $this->_error('Unsupported output format');
-            return false;
-        }
-    }
-
-    /**
-     * Encode a given UTF-8 domain name
-     * @param    string   Domain name (UTF-8 or UCS-4)
-     * [@param    string   Desired input encoding, see {@link set_parameter}]
-     * @return   string   Encoded Domain name (ACE string)
-     * @access   public
-     */
-    function encode($decoded, $one_time_encoding = false)
-    {
-        // Forcing conversion of input to UCS4 array
-        // If one time encoding is given, use this, else the objects property
-        switch ($one_time_encoding ? $one_time_encoding : $this->_api_encoding) {
-        case 'utf8':
-            $decoded = $this->_utf8_to_ucs4($decoded);
-            break;
-        case 'ucs4_string':
-           $decoded = $this->_ucs4_string_to_ucs4($decoded);
-        case 'ucs4_array':
-           break;
-        default:
-            $this->_error('Unsupported input format: '.($one_time_encoding ? $one_time_encoding : $this->_api_encoding));
-            return false;
-        }
-
-        // No input, no output, what else did you expect?
-        if (empty($decoded)) return '';
-
-        // Anchors for iteration
-        $last_begin = 0;
-        // Output string
-        $output = '';
-        foreach ($decoded as $k => $v) {
-            // Make sure to use just the plain dot
-            switch($v) {
-            case 0x3002:
-            case 0xFF0E:
-            case 0xFF61:
-                $decoded[$k] = 0x2E;
-                // Right, no break here, the above are converted to dots anyway
-            // Stumbling across an anchoring character
-            case 0x2E:
-            case 0x2F:
-            case 0x3A:
-            case 0x3F:
-            case 0x40:
-                // Neither email addresses nor URLs allowed in strict mode
-                if ($this->_strict_mode) {
-                   $this->_error('Neither email addresses nor URLs are allowed in strict mode.');
-                   return false;
-                } else {
-                    // Skip first char
-                    if ($k) {
-                        $encoded = '';
-                        $encoded = $this->_encode(array_slice($decoded, $last_begin, (($k)-$last_begin)));
-                        if ($encoded) {
-                            $output .= $encoded;
-                        } else {
-                            $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($k)-$last_begin)));
-                        }
-                        $output .= chr($decoded[$k]);
-                    }
-                    $last_begin = $k + 1;
-                }
-            }
-        }
-        // Catch the rest of the string
-        if ($last_begin) {
-            $inp_len = sizeof($decoded);
-            $encoded = '';
-            $encoded = $this->_encode(array_slice($decoded, $last_begin, (($inp_len)-$last_begin)));
-            if ($encoded) {
-                $output .= $encoded;
-            } else {
-                $output .= $this->_ucs4_to_utf8(array_slice($decoded, $last_begin, (($inp_len)-$last_begin)));
-            }
-            return $output;
-        } else {
-            if ($output = $this->_encode($decoded)) {
-                return $output;
-            } else {
-                return $this->_ucs4_to_utf8($decoded);
-            }
-        }
-    }
-
-    /**
-     * Use this method to get the last error ocurred
-     * @param    void
-     * @return   string   The last error, that occured
-     * @access   public
-     */
-    function get_last_error()
-    {
-        return $this->_error;
-    }
-
-    /**
-     * The actual decoding algorithm
-     * @access   private
-     */
-    function _decode($encoded)
-    {
-        // We do need to find the Punycode prefix
-        if (!preg_match('!^'.preg_quote($this->_punycode_prefix, '!').'!', $encoded)) {
-            $this->_error('This is not a punycode string');
-            return false;
-        }
-        $encode_test = preg_replace('!^'.preg_quote($this->_punycode_prefix, '!').'!', '', $encoded);
-        // If nothing left after removing the prefix, it is hopeless
-        if (!$encode_test) {
-            $this->_error('The given encoded string was empty');
-            return false;
-        }
-        // Find last occurence of the delimiter
-        $delim_pos = strrpos($encoded, '-');
-        if ($delim_pos > strlen($this->_punycode_prefix)) {
-            for ($k = strlen($this->_punycode_prefix); $k < $delim_pos; ++$k) {
-                $decoded[] = ord($encoded{$k});
-            }
-        } else {
-            $decoded = array();
-        }
-        $deco_len = count($decoded);
-        $enco_len = strlen($encoded);
-
-        // Wandering through the strings; init
-        $is_first = true;
-        $bias     = $this->_initial_bias;
-        $idx      = 0;
-        $char     = $this->_initial_n;
-
-        for ($enco_idx = ($delim_pos) ? ($delim_pos + 1) : 0; $enco_idx < $enco_len; ++$deco_len) {
-            for ($old_idx = $idx, $w = 1, $k = $this->_base; 1 ; $k += $this->_base) {
-                $digit = $this->_decode_digit($encoded{$enco_idx++});
-                $idx += $digit * $w;
-                $t = ($k <= $bias) ? $this->_tmin :
-                        (($k >= $bias + $this->_tmax) ? $this->_tmax : ($k - $bias));
-                if ($digit < $t) break;
-                $w = (int) ($w * ($this->_base - $t));
-            }
-            $bias = $this->_adapt($idx - $old_idx, $deco_len + 1, $is_first);
-            $is_first = false;
-            $char += (int) ($idx / ($deco_len + 1));
-            $idx %= ($deco_len + 1);
-            if ($deco_len > 0) {
-                // Make room for the decoded char
-                for ($i = $deco_len; $i > $idx; $i--) {
-                    $decoded[$i] = $decoded[($i - 1)];
-                }
-            }
-            $decoded[$idx++] = $char;
-        }
-        return $this->_ucs4_to_utf8($decoded);
-    }
-
-    /**
-     * The actual encoding algorithm
-     * @access   private
-     */
-    function _encode($decoded)
-    {
-        // We cannot encode a domain name containing the Punycode prefix
-        $extract = strlen($this->_punycode_prefix);
-        $check_pref = $this->_utf8_to_ucs4($this->_punycode_prefix);
-        $check_deco = array_slice($decoded, 0, $extract);
-
-        if ($check_pref == $check_deco) {
-            $this->_error('This is already a punycode string');
-            return false;
-        }
-        // We will not try to encode strings consisting of basic code points only
-        $encodable = false;
-        foreach ($decoded as $k => $v) {
-            if ($v > 0x7a) {
-                $encodable = true;
-                break;
-            }
-        }
-        if (!$encodable) {
-            $this->_error('The given string does not contain encodable chars');
-            return false;
-        }
-
-        // Do NAMEPREP
-        $decoded = $this->_nameprep($decoded);
-        if (!$decoded || !is_array($decoded)) return false; // NAMEPREP failed
-
-        $deco_len  = count($decoded);
-        if (!$deco_len) return false; // Empty array
-
-        $codecount = 0; // How many chars have been consumed
-
-        $encoded = '';
-        // Copy all basic code points to output
-        for ($i = 0; $i < $deco_len; ++$i) {
-            $test = $decoded[$i];
-            // Will match [-0-9a-zA-Z]
-            if ((0x2F < $test && $test < 0x40) || (0x40 < $test && $test < 0x5B)
-                    || (0x60 < $test && $test <= 0x7B) || (0x2D == $test)) {
-                $encoded .= chr($decoded[$i]);
-                $codecount++;
-            }
-        }
-        if ($codecount == $deco_len) return $encoded; // All codepoints were basic ones
-
-        // Start with the prefix; copy it to output
-        $encoded = $this->_punycode_prefix.$encoded;
-
-        // If we have basic code points in output, add an hyphen to the end
-        if ($codecount) $encoded .= '-';
-
-        // Now find and encode all non-basic code points
-        $is_first  = true;
-        $cur_code  = $this->_initial_n;
-        $bias      = $this->_initial_bias;
-        $delta     = 0;
-        while ($codecount < $deco_len) {
-            // Find the smallest code point >= the current code point and
-            // remember the last ouccrence of it in the input
-            for ($i = 0, $next_code = $this->_max_ucs; $i < $deco_len; $i++) {
-                if ($decoded[$i] >= $cur_code && $decoded[$i] <= $next_code) {
-                    $next_code = $decoded[$i];
-                }
-            }
-
-            $delta += ($next_code - $cur_code) * ($codecount + 1);
-            $cur_code = $next_code;
-
-            // Scan input again and encode all characters whose code point is $cur_code
-            for ($i = 0; $i < $deco_len; $i++) {
-                if ($decoded[$i] < $cur_code) {
-                    $delta++;
-                } elseif ($decoded[$i] == $cur_code) {
-                    for ($q = $delta, $k = $this->_base; 1; $k += $this->_base) {
-                        $t = ($k <= $bias) ? $this->_tmin :
-                                (($k >= $bias + $this->_tmax) ? $this->_tmax : $k - $bias);
-                        if ($q < $t) break;
-                        $encoded .= $this->_encode_digit(intval($t + (($q - $t) % ($this->_base - $t)))); //v0.4.5 Changed from ceil() to intval()
-                        $q = (int) (($q - $t) / ($this->_base - $t));
-                    }
-                    $encoded .= $this->_encode_digit($q);
-                    $bias = $this->_adapt($delta, $codecount+1, $is_first);
-                    $codecount++;
-                    $delta = 0;
-                    $is_first = false;
-                }
-            }
-            $delta++;
-            $cur_code++;
-        }
-        return $encoded;
-    }
-
-    /**
-     * Adapt the bias according to the current code point and position
-     * @access   private
-     */
-    function _adapt($delta, $npoints, $is_first)
-    {
-        $delta = intval($is_first ? ($delta / $this->_damp) : ($delta / 2));
-        $delta += intval($delta / $npoints);
-        for ($k = 0; $delta > (($this->_base - $this->_tmin) * $this->_tmax) / 2; $k += $this->_base) {
-            $delta = intval($delta / ($this->_base - $this->_tmin));
-        }
-        return intval($k + ($this->_base - $this->_tmin + 1) * $delta / ($delta + $this->_skew));
-    }
-
-    /**
-     * Encoding a certain digit
-     * @access   private
-     */
-    function _encode_digit($d)
-    {
-        return chr($d + 22 + 75 * ($d < 26));
-    }
-
-    /**
-     * Decode a certain digit
-     * @access   private
-     */
-    function _decode_digit($cp)
-    {
-        $cp = ord($cp);
-        return ($cp - 48 < 10) ? $cp - 22 : (($cp - 65 < 26) ? $cp - 65 : (($cp - 97 < 26) ? $cp - 97 : $this->_base));
-    }
-
-    /**
-     * Internal error handling method
-     * @access   private
-     */
-    function _error($error = '')
-    {
-        $this->_error = $error;
-    }
-
-    /**
-     * Do Nameprep according to RFC3491 and RFC3454
-     * @param    array    Unicode Characters
-     * @return   string   Unicode Characters, Nameprep'd
-     * @access   private
-     */
-    function _nameprep($input)
-    {
-        $output = array();
-        $error = false;
-        //
-        // Mapping
-        // Walking through the input array, performing the required steps on each of
-        // the input chars and putting the result into the output array
-        // While mapping required chars we apply the cannonical ordering
-        foreach ($input as $v) {
-            // Map to nothing == skip that code point
-            if (in_array($v, $this->NP['map_nothing'])) continue;
-
-            // Try to find prohibited input
-            if (in_array($v, $this->NP['prohibit']) || in_array($v, $this->NP['general_prohibited'])) {
-                $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v));
-                return false;
-            }
-            foreach ($this->NP['prohibit_ranges'] as $range) {
-                if ($range[0] <= $v && $v <= $range[1]) {
-                    $this->_error('NAMEPREP: Prohibited input U+'.sprintf('%08X', $v));
-                    return false;
-                }
-            }
-            //
-            // Hangul syllable decomposition
-            if (0xAC00 <= $v && $v <= 0xD7AF) {
-                foreach ($this->_hangul_decompose($v) as $out) {
-                    $output[] = (int) $out;
-                }
-            // There's a decomposition mapping for that code point
-            } elseif (isset($this->NP['replacemaps'][$v])) {
-                foreach ($this->_apply_cannonical_ordering($this->NP['replacemaps'][$v]) as $out) {
-                    $output[] = (int) $out;
-                }
-            } else {
-                $output[] = (int) $v;
-            }
-        }
-        // Before applying any Combining, try to rearrange any Hangul syllables
-        $output = $this->_hangul_compose($output);
-        //
-        // Combine code points
-        //
-        $last_class   = 0;
-        $last_starter = 0;
-        $out_len      = count($output);
-        for ($i = 0; $i < $out_len; ++$i) {
-            $class = $this->_get_combining_class($output[$i]);
-            if ((!$last_class || $last_class > $class) && $class) {
-                // Try to match
-                $seq_len = $i - $last_starter;
-                $out = $this->_combine(array_slice($output, $last_starter, $seq_len));
-                // On match: Replace the last starter with the composed character and remove
-                // the now redundant non-starter(s)
-                if ($out) {
-                    $output[$last_starter] = $out;
-                    if (count($out) != $seq_len) {
-                        for ($j = $i+1; $j < $out_len; ++$j) {
-                            $output[$j-1] = $output[$j];
-                        }
-                        unset($output[$out_len]);
-                    }
-                    // Rewind the for loop by one, since there can be more possible compositions
-                    $i--;
-                    $out_len--;
-                    $last_class = ($i == $last_starter) ? 0 : $this->_get_combining_class($output[$i-1]);
-                    continue;
-                }
-            }
-            // The current class is 0
-            if (!$class) $last_starter = $i;
-            $last_class = $class;
-        }
-        return $output;
-    }
-
-    /**
-     * Decomposes a Hangul syllable
-     * (see http://www.unicode.org/unicode/reports/tr15/#Hangul
-     * @param    integer  32bit UCS4 code point
-     * @return   array    Either Hangul Syllable decomposed or original 32bit value as one value array
-     * @access   private
-     */
-    function _hangul_decompose($char)
-    {
-        $sindex = (int) $char - $this->_sbase;
-        if ($sindex < 0 || $sindex >= $this->_scount) {
-            return array($char);
-        }
-        $result = array();
-        $result[] = (int) $this->_lbase + $sindex / $this->_ncount;
-        $result[] = (int) $this->_vbase + ($sindex % $this->_ncount) / $this->_tcount;
-        $T = intval($this->_tbase + $sindex % $this->_tcount);
-        if ($T != $this->_tbase) $result[] = $T;
-        return $result;
-    }
-    /**
-     * Ccomposes a Hangul syllable
-     * (see http://www.unicode.org/unicode/reports/tr15/#Hangul
-     * @param    array    Decomposed UCS4 sequence
-     * @return   array    UCS4 sequence with syllables composed
-     * @access   private
-     */
-    function _hangul_compose($input)
-    {
-        $inp_len = count($input);
-        if (!$inp_len) return array();
-        $result = array();
-        $last = (int) $input[0];
-        $result[] = $last; // copy first char from input to output
-
-        for ($i = 1; $i < $inp_len; ++$i) {
-            $char = (int) $input[$i];
-            $sindex = $last - $this->_sbase;
-            $lindex = $last - $this->_lbase;
-            $vindex = $char - $this->_vbase;
-            $tindex = $char - $this->_tbase;
-            // Find out, whether two current characters are LV and T
-            if (0 <= $sindex && $sindex < $this->_scount && ($sindex % $this->_tcount == 0)
-                    && 0 <= $tindex && $tindex <= $this->_tcount) {
-                // create syllable of form LVT
-                $last += $tindex;
-                $result[(count($result) - 1)] = $last; // reset last
-                continue; // discard char
-            }
-            // Find out, whether two current characters form L and V
-            if (0 <= $lindex && $lindex < $this->_lcount && 0 <= $vindex && $vindex < $this->_vcount) {
-                // create syllable of form LV
-                $last = (int) $this->_sbase + ($lindex * $this->_vcount + $vindex) * $this->_tcount;
-                $result[(count($result) - 1)] = $last; // reset last
-                continue; // discard char
-            }
-            // if neither case was true, just add the character
-            $last = $char;
-            $result[] = $char;
-        }
-        return $result;
-    }
-
-    /**
-     * Returns the combining class of a certain wide char
-     * @param    integer    Wide char to check (32bit integer)
-     * @return   integer    Combining class if found, else 0
-     * @access   private
-     */
-    function _get_combining_class($char)
-    {
-        return isset($this->NP['norm_combcls'][$char]) ? $this->NP['norm_combcls'][$char] : 0;
-    }
-
-    /**
-     * Apllies the cannonical ordering of a decomposed UCS4 sequence
-     * @param    array      Decomposed UCS4 sequence
-     * @return   array      Ordered USC4 sequence
-     * @access   private
-     */
-    function _apply_cannonical_ordering($input)
-    {
-        $swap = true;
-        $size = count($input);
-        while ($swap) {
-            $swap = false;
-            $last = $this->_get_combining_class(intval($input[0]));
-            for ($i = 0; $i < $size-1; ++$i) {
-                $next = $this->_get_combining_class(intval($input[$i+1]));
-                if ($next != 0 && $last > $next) {
-                    // Move item leftward until it fits
-                    for ($j = $i + 1; $j > 0; --$j) {
-                        if ($this->_get_combining_class(intval($input[$j-1])) <= $next) break;
-                        $t = intval($input[$j]);
-                        $input[$j] = intval($input[$j-1]);
-                        $input[$j-1] = $t;
-                        $swap = true;
-                    }
-                    // Reentering the loop looking at the old character again
-                    $next = $last;
-                }
-                $last = $next;
-            }
-        }
-        return $input;
-    }
-
-    /**
-     * Do composition of a sequence of starter and non-starter
-     * @param    array      UCS4 Decomposed sequence
-     * @return   array      Ordered USC4 sequence
-     * @access   private
-     */
-    function _combine($input)
-    {
-        $inp_len = count($input);
-        foreach ($this->NP['replacemaps'] as $np_src => $np_target) {
-            if ($np_target[0] != $input[0]) continue;
-            if (count($np_target) != $inp_len) continue;
-            $hit = false;
-            foreach ($input as $k2 => $v2) {
-                if ($v2 == $np_target[$k2]) {
-                    $hit = true;
-                } else {
-                    $hit = false;
-                    break;
-                }
-            }
-            if ($hit) return $np_src;
-        }
-        return false;
-    }
-
-    /**
-     * This converts an UTF-8 encoded string to its UCS-4 representation
-     * By talking about UCS-4 "strings" we mean arrays of 32bit integers representing
-     * each of the "chars". This is due to PHP not being able to handle strings with
-     * bit depth different from 8. This apllies to the reverse method _ucs4_to_utf8(), too.
-     * The following UTF-8 encodings are supported:
-     * bytes bits  representation
-     * 1        7  0xxxxxxx
-     * 2       11  110xxxxx 10xxxxxx
-     * 3       16  1110xxxx 10xxxxxx 10xxxxxx
-     * 4       21  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-     * 5       26  111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
-     * 6       31  1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
-     * Each x represents a bit that can be used to store character data.
-     * The five and six byte sequences are part of Annex D of ISO/IEC 10646-1:2000
-     * @access   private
-     */
-    function _utf8_to_ucs4($input)
-    {
-        $output = array();
-        $out_len = 0;
-        $inp_len = strlen($input);
-        $mode = 'next';
-        $test = 'none';
-        for ($k = 0; $k < $inp_len; ++$k) {
-            $v = ord($input{$k}); // Extract byte from input string
-
-            if ($v < 128) { // We found an ASCII char - put into stirng as is
-                $output[$out_len] = $v;
-                ++$out_len;
-                if ('add' == $mode) {
-                    $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
-                    return false;
-                }
-                continue;
-            }
-            if ('next' == $mode) { // Try to find the next start byte; determine the width of the Unicode char
-                $start_byte = $v;
-                $mode = 'add';
-                $test = 'range';
-                if ($v >> 5 == 6) { // &110xxxxx 10xxxxx
-                    $next_byte = 0; // Tells, how many times subsequent bitmasks must rotate 6bits to the left
-                    $v = ($v - 192) << 6;
-                } elseif ($v >> 4 == 14) { // &1110xxxx 10xxxxxx 10xxxxxx
-                    $next_byte = 1;
-                    $v = ($v - 224) << 12;
-                } elseif ($v >> 3 == 30) { // &11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-                    $next_byte = 2;
-                    $v = ($v - 240) << 18;
-                } elseif ($v >> 2 == 62) { // &111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
-                    $next_byte = 3;
-                    $v = ($v - 248) << 24;
-                } elseif ($v >> 1 == 126) { // &1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
-                    $next_byte = 4;
-                    $v = ($v - 252) << 30;
-                } else {
-                    $this->_error('This might be UTF-8, but I don\'t understand it at byte '.$k);
-                    return false;
-                }
-                if ('add' == $mode) {
-                    $output[$out_len] = (int) $v;
-                    ++$out_len;
-                    continue;
-                }
-            }
-            if ('add' == $mode) {
-                if (!$this->_allow_overlong && $test == 'range') {
-                    $test = 'none';
-                    if (($v < 0xA0 && $start_byte == 0xE0) || ($v < 0x90 && $start_byte == 0xF0) || ($v > 0x8F && $start_byte == 0xF4)) {
-                        $this->_error('Bogus UTF-8 character detected (out of legal range) at byte '.$k);
-                        return false;
-                    }
-                }
-                if ($v >> 6 == 2) { // Bit mask must be 10xxxxxx
-                    $v = ($v - 128) << ($next_byte * 6);
-                    $output[($out_len - 1)] += $v;
-                    --$next_byte;
-                } else {
-                    $this->_error('Conversion from UTF-8 to UCS-4 failed: malformed input at byte '.$k);
-                    return false;
-                }
-                if ($next_byte < 0) {
-                    $mode = 'next';
-                }
-            }
-        } // for
-        return $output;
-    }
-
-    /**
-     * Convert UCS-4 string into UTF-8 string
-     * See _utf8_to_ucs4() for details
-     * @access   private
-     */
-    function _ucs4_to_utf8($input)
-    {
-        $output = '';
-        $k = 0;
-        foreach ($input as $v) {
-            ++$k;
-            // $v = ord($v);
-            if ($v < 128) { // 7bit are transferred literally
-                $output .= chr($v);
-            } elseif ($v < (1 << 11)) { // 2 bytes
-                $output .= chr(192 + ($v >> 6)) . chr(128 + ($v & 63));
-            } elseif ($v < (1 << 16)) { // 3 bytes
-                $output .= chr(224 + ($v >> 12)) . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63));
-            } elseif ($v < (1 << 21)) { // 4 bytes
-                $output .= chr(240 + ($v >> 18)) . chr(128 + (($v >> 12) & 63))
-                         . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63));
-            } elseif ($v < (1 << 26)) { // 5 bytes
-                $output .= chr(248 + ($v >> 24)) . chr(128 + (($v >> 18) & 63))
-                         . chr(128 + (($v >> 12) & 63)) . chr(128 + (($v >> 6) & 63))
-                         . chr(128 + ($v & 63));
-            } elseif ($v < (1 << 31)) { // 6 bytes
-                $output .= chr(252 + ($v >> 30)) . chr(128 + (($v >> 24) & 63))
-                         . chr(128 + (($v >> 18) & 63)) . chr(128 + (($v >> 12) & 63))
-                         . chr(128 + (($v >> 6) & 63)) . chr(128 + ($v & 63));
-            } else {
-                $this->_error('Conversion from UCS-4 to UTF-8 failed: malformed input at byte '.$k);
-                return false;
-            }
-        }
-        return $output;
-    }
-
-    /**
-      * Convert UCS-4 array into UCS-4 string
-      *
-      * @access   private
-      */
-    function _ucs4_to_ucs4_string($input)
-    {
-        $output = '';
-        // Take array values and split output to 4 bytes per value
-        // The bit mask is 255, which reads &11111111
-        foreach ($input as $v) {
-            $output .= chr(($v >> 24) & 255).chr(($v >> 16) & 255).chr(($v >> 8) & 255).chr($v & 255);
-        }
-        return $output;
-    }
-
-    /**
-      * Convert UCS-4 strin into UCS-4 garray
-      *
-      * @access   private
-      */
-    function _ucs4_string_to_ucs4($input)
-    {
-        $output = array();
-        $inp_len = strlen($input);
-        // Input length must be dividable by 4
-        if ($inp_len % 4) {
-            $this->_error('Input UCS4 string is broken');
-            return false;
-        }
-        // Empty input - return empty output
-        if (!$inp_len) return $output;
-        for ($i = 0, $out_len = -1; $i < $inp_len; ++$i) {
-            // Increment output position every 4 input bytes
-            if (!($i % 4)) {
-                $out_len++;
-                $output[$out_len] = 0;
-            }
-            $output[$out_len] += ord($input{$i}) << (8 * (3 - ($i % 4) ) );
-        }
-        return $output;
-    }
-}
-
-/**
-* Adapter class for aligning the API of idna_convert with that of Net_IDNA
-* @author  Matthias Sommerfeld <mso@phlylabs.de>
-*/
-class Net_IDNA_php4 extends idna_convert
-{
-    /**
-     * Sets a new option value. Available options and values:
-     * [encoding - Use either UTF-8, UCS4 as array or UCS4 as string as input ('utf8' for UTF-8,
-     *         'ucs4_string' and 'ucs4_array' respectively for UCS4); The output is always UTF-8]
-     * [overlong - Unicode does not allow unnecessarily long encodings of chars,
-     *             to allow this, set this parameter to true, else to false;
-     *             default is false.]
-     * [strict - true: strict mode, good for registration purposes - Causes errors
-     *           on failures; false: loose mode, ideal for "wildlife" applications
-     *           by silently ignoring errors and returning the original input instead
-     *
-     * @param    mixed     Parameter to set (string: single parameter; array of Parameter => Value pairs)
-     * @param    string    Value to use (if parameter 1 is a string)
-     * @return   boolean   true on success, false otherwise
-     * @access   public
-     */
-    function setParams($option, $param = false)
-    {
-        return $this->IC->set_parameters($option, $param);
-    }
-}
-
-?>
\ No newline at end of file
diff --git a/library/simplepie/idn/npdata.ser b/library/simplepie/idn/npdata.ser
deleted file mode 100644
index d7ce6d03f2..0000000000
--- a/library/simplepie/idn/npdata.ser
+++ /dev/null
@@ -1 +0,0 @@
-a:6:{s:11:"map_nothing";a:27:{i:0;i:173;i:1;i:847;i:2;i:6150;i:3;i:6155;i:4;i:6156;i:5;i:6157;i:6;i:8203;i:7;i:8204;i:8;i:8205;i:9;i:8288;i:10;i:65024;i:11;i:65025;i:12;i:65026;i:13;i:65027;i:14;i:65028;i:15;i:65029;i:16;i:65030;i:17;i:65031;i:18;i:65032;i:19;i:65033;i:20;i:65034;i:21;i:65035;i:22;i:65036;i:23;i:65037;i:24;i:65038;i:25;i:65039;i:26;i:65279;}s:18:"general_prohibited";a:64:{i:0;i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;i:5;i:6;i:6;i:7;i:7;i:8;i:8;i:9;i:9;i:10;i:10;i:11;i:11;i:12;i:12;i:13;i:13;i:14;i:14;i:15;i:15;i:16;i:16;i:17;i:17;i:18;i:18;i:19;i:19;i:20;i:20;i:21;i:21;i:22;i:22;i:23;i:23;i:24;i:24;i:25;i:25;i:26;i:26;i:27;i:27;i:28;i:28;i:29;i:29;i:30;i:30;i:31;i:31;i:32;i:32;i:33;i:33;i:34;i:34;i:35;i:35;i:36;i:36;i:37;i:37;i:38;i:38;i:39;i:39;i:40;i:40;i:41;i:41;i:42;i:42;i:43;i:43;i:44;i:44;i:45;i:47;i:46;i:59;i:47;i:60;i:48;i:61;i:49;i:62;i:50;i:63;i:51;i:64;i:52;i:91;i:53;i:92;i:54;i:93;i:55;i:94;i:56;i:95;i:57;i:96;i:58;i:123;i:59;i:124;i:60;i:125;i:61;i:126;i:62;i:127;i:63;i:12290;}s:8:"prohibit";a:84:{i:0;i:160;i:1;i:5760;i:2;i:8192;i:3;i:8193;i:4;i:8194;i:5;i:8195;i:6;i:8196;i:7;i:8197;i:8;i:8198;i:9;i:8199;i:10;i:8200;i:11;i:8201;i:12;i:8202;i:13;i:8203;i:14;i:8239;i:15;i:8287;i:16;i:12288;i:17;i:1757;i:18;i:1807;i:19;i:6158;i:20;i:8204;i:21;i:8205;i:22;i:8232;i:23;i:8233;i:24;i:65279;i:25;i:65529;i:26;i:65530;i:27;i:65531;i:28;i:65532;i:29;i:65534;i:30;i:65535;i:31;i:131070;i:32;i:131071;i:33;i:196606;i:34;i:196607;i:35;i:262142;i:36;i:262143;i:37;i:327678;i:38;i:327679;i:39;i:393214;i:40;i:393215;i:41;i:458750;i:42;i:458751;i:43;i:524286;i:44;i:524287;i:45;i:589822;i:46;i:589823;i:47;i:655358;i:48;i:655359;i:49;i:720894;i:50;i:720895;i:51;i:786430;i:52;i:786431;i:53;i:851966;i:54;i:851967;i:55;i:917502;i:56;i:917503;i:57;i:983038;i:58;i:983039;i:59;i:1048574;i:60;i:1048575;i:61;i:1114110;i:62;i:1114111;i:63;i:65529;i:64;i:65530;i:65;i:65531;i:66;i:65532;i:67;i:65533;i:68;i:832;i:69;i:833;i:70;i:8206;i:71;i:8207;i:72;i:8234;i:73;i:8235;i:74;i:8236;i:75;i:8237;i:76;i:8238;i:77;i:8298;i:78;i:8299;i:79;i:8300;i:80;i:8301;i:81;i:8302;i:82;i:8303;i:83;i:917505;}s:15:"prohibit_ranges";a:10:{i:0;a:2:{i:0;i:128;i:1;i:159;}i:1;a:2:{i:0;i:8288;i:1;i:8303;}i:2;a:2:{i:0;i:119155;i:1;i:119162;}i:3;a:2:{i:0;i:57344;i:1;i:63743;}i:4;a:2:{i:0;i:983040;i:1;i:1048573;}i:5;a:2:{i:0;i:1048576;i:1;i:1114109;}i:6;a:2:{i:0;i:64976;i:1;i:65007;}i:7;a:2:{i:0;i:55296;i:1;i:57343;}i:8;a:2:{i:0;i:12272;i:1;i:12283;}i:9;a:2:{i:0;i:917536;i:1;i:917631;}}s:11:"replacemaps";a:1401:{i:65;a:1:{i:0;i:97;}i:66;a:1:{i:0;i:98;}i:67;a:1:{i:0;i:99;}i:68;a:1:{i:0;i:100;}i:69;a:1:{i:0;i:101;}i:70;a:1:{i:0;i:102;}i:71;a:1:{i:0;i:103;}i:72;a:1:{i:0;i:104;}i:73;a:1:{i:0;i:105;}i:74;a:1:{i:0;i:106;}i:75;a:1:{i:0;i:107;}i:76;a:1:{i:0;i:108;}i:77;a:1:{i:0;i:109;}i:78;a:1:{i:0;i:110;}i:79;a:1:{i:0;i:111;}i:80;a:1:{i:0;i:112;}i:81;a:1:{i:0;i:113;}i:82;a:1:{i:0;i:114;}i:83;a:1:{i:0;i:115;}i:84;a:1:{i:0;i:116;}i:85;a:1:{i:0;i:117;}i:86;a:1:{i:0;i:118;}i:87;a:1:{i:0;i:119;}i:88;a:1:{i:0;i:120;}i:89;a:1:{i:0;i:121;}i:90;a:1:{i:0;i:122;}i:181;a:1:{i:0;i:956;}i:192;a:1:{i:0;i:224;}i:193;a:1:{i:0;i:225;}i:194;a:1:{i:0;i:226;}i:195;a:1:{i:0;i:227;}i:196;a:1:{i:0;i:228;}i:197;a:1:{i:0;i:229;}i:198;a:1:{i:0;i:230;}i:199;a:1:{i:0;i:231;}i:200;a:1:{i:0;i:232;}i:201;a:1:{i:0;i:233;}i:202;a:1:{i:0;i:234;}i:203;a:1:{i:0;i:235;}i:204;a:1:{i:0;i:236;}i:205;a:1:{i:0;i:237;}i:206;a:1:{i:0;i:238;}i:207;a:1:{i:0;i:239;}i:208;a:1:{i:0;i:240;}i:209;a:1:{i:0;i:241;}i:210;a:1:{i:0;i:242;}i:211;a:1:{i:0;i:243;}i:212;a:1:{i:0;i:244;}i:213;a:1:{i:0;i:245;}i:214;a:1:{i:0;i:246;}i:216;a:1:{i:0;i:248;}i:217;a:1:{i:0;i:249;}i:218;a:1:{i:0;i:250;}i:219;a:1:{i:0;i:251;}i:220;a:1:{i:0;i:252;}i:221;a:1:{i:0;i:253;}i:222;a:1:{i:0;i:254;}i:223;a:2:{i:0;i:115;i:1;i:115;}i:256;a:1:{i:0;i:257;}i:258;a:1:{i:0;i:259;}i:260;a:1:{i:0;i:261;}i:262;a:1:{i:0;i:263;}i:264;a:1:{i:0;i:265;}i:266;a:1:{i:0;i:267;}i:268;a:1:{i:0;i:269;}i:270;a:1:{i:0;i:271;}i:272;a:1:{i:0;i:273;}i:274;a:1:{i:0;i:275;}i:276;a:1:{i:0;i:277;}i:278;a:1:{i:0;i:279;}i:280;a:1:{i:0;i:281;}i:282;a:1:{i:0;i:283;}i:284;a:1:{i:0;i:285;}i:286;a:1:{i:0;i:287;}i:288;a:1:{i:0;i:289;}i:290;a:1:{i:0;i:291;}i:292;a:1:{i:0;i:293;}i:294;a:1:{i:0;i:295;}i:296;a:1:{i:0;i:297;}i:298;a:1:{i:0;i:299;}i:300;a:1:{i:0;i:301;}i:302;a:1:{i:0;i:303;}i:304;a:2:{i:0;i:105;i:1;i:775;}i:306;a:1:{i:0;i:307;}i:308;a:1:{i:0;i:309;}i:310;a:1:{i:0;i:311;}i:313;a:1:{i:0;i:314;}i:315;a:1:{i:0;i:316;}i:317;a:1:{i:0;i:318;}i:319;a:1:{i:0;i:320;}i:321;a:1:{i:0;i:322;}i:323;a:1:{i:0;i:324;}i:325;a:1:{i:0;i:326;}i:327;a:1:{i:0;i:328;}i:329;a:2:{i:0;i:700;i:1;i:110;}i:330;a:1:{i:0;i:331;}i:332;a:1:{i:0;i:333;}i:334;a:1:{i:0;i:335;}i:336;a:1:{i:0;i:337;}i:338;a:1:{i:0;i:339;}i:340;a:1:{i:0;i:341;}i:342;a:1:{i:0;i:343;}i:344;a:1:{i:0;i:345;}i:346;a:1:{i:0;i:347;}i:348;a:1:{i:0;i:349;}i:350;a:1:{i:0;i:351;}i:352;a:1:{i:0;i:353;}i:354;a:1:{i:0;i:355;}i:356;a:1:{i:0;i:357;}i:358;a:1:{i:0;i:359;}i:360;a:1:{i:0;i:361;}i:362;a:1:{i:0;i:363;}i:364;a:1:{i:0;i:365;}i:366;a:1:{i:0;i:367;}i:368;a:1:{i:0;i:369;}i:370;a:1:{i:0;i:371;}i:372;a:1:{i:0;i:373;}i:374;a:1:{i:0;i:375;}i:376;a:1:{i:0;i:255;}i:377;a:1:{i:0;i:378;}i:379;a:1:{i:0;i:380;}i:381;a:1:{i:0;i:382;}i:383;a:1:{i:0;i:115;}i:385;a:1:{i:0;i:595;}i:386;a:1:{i:0;i:387;}i:388;a:1:{i:0;i:389;}i:390;a:1:{i:0;i:596;}i:391;a:1:{i:0;i:392;}i:393;a:1:{i:0;i:598;}i:394;a:1:{i:0;i:599;}i:395;a:1:{i:0;i:396;}i:398;a:1:{i:0;i:477;}i:399;a:1:{i:0;i:601;}i:400;a:1:{i:0;i:603;}i:401;a:1:{i:0;i:402;}i:403;a:1:{i:0;i:608;}i:404;a:1:{i:0;i:611;}i:406;a:1:{i:0;i:617;}i:407;a:1:{i:0;i:616;}i:408;a:1:{i:0;i:409;}i:412;a:1:{i:0;i:623;}i:413;a:1:{i:0;i:626;}i:415;a:1:{i:0;i:629;}i:416;a:1:{i:0;i:417;}i:418;a:1:{i:0;i:419;}i:420;a:1:{i:0;i:421;}i:422;a:1:{i:0;i:640;}i:423;a:1:{i:0;i:424;}i:425;a:1:{i:0;i:643;}i:428;a:1:{i:0;i:429;}i:430;a:1:{i:0;i:648;}i:431;a:1:{i:0;i:432;}i:433;a:1:{i:0;i:650;}i:434;a:1:{i:0;i:651;}i:435;a:1:{i:0;i:436;}i:437;a:1:{i:0;i:438;}i:439;a:1:{i:0;i:658;}i:440;a:1:{i:0;i:441;}i:444;a:1:{i:0;i:445;}i:452;a:1:{i:0;i:454;}i:453;a:1:{i:0;i:454;}i:455;a:1:{i:0;i:457;}i:456;a:1:{i:0;i:457;}i:458;a:1:{i:0;i:460;}i:459;a:1:{i:0;i:460;}i:461;a:1:{i:0;i:462;}i:463;a:1:{i:0;i:464;}i:465;a:1:{i:0;i:466;}i:467;a:1:{i:0;i:468;}i:469;a:1:{i:0;i:470;}i:471;a:1:{i:0;i:472;}i:473;a:1:{i:0;i:474;}i:475;a:1:{i:0;i:476;}i:478;a:1:{i:0;i:479;}i:480;a:1:{i:0;i:481;}i:482;a:1:{i:0;i:483;}i:484;a:1:{i:0;i:485;}i:486;a:1:{i:0;i:487;}i:488;a:1:{i:0;i:489;}i:490;a:1:{i:0;i:491;}i:492;a:1:{i:0;i:493;}i:494;a:1:{i:0;i:495;}i:496;a:2:{i:0;i:106;i:1;i:780;}i:497;a:1:{i:0;i:499;}i:498;a:1:{i:0;i:499;}i:500;a:1:{i:0;i:501;}i:502;a:1:{i:0;i:405;}i:503;a:1:{i:0;i:447;}i:504;a:1:{i:0;i:505;}i:506;a:1:{i:0;i:507;}i:508;a:1:{i:0;i:509;}i:510;a:1:{i:0;i:511;}i:512;a:1:{i:0;i:513;}i:514;a:1:{i:0;i:515;}i:516;a:1:{i:0;i:517;}i:518;a:1:{i:0;i:519;}i:520;a:1:{i:0;i:521;}i:522;a:1:{i:0;i:523;}i:524;a:1:{i:0;i:525;}i:526;a:1:{i:0;i:527;}i:528;a:1:{i:0;i:529;}i:530;a:1:{i:0;i:531;}i:532;a:1:{i:0;i:533;}i:534;a:1:{i:0;i:535;}i:536;a:1:{i:0;i:537;}i:538;a:1:{i:0;i:539;}i:540;a:1:{i:0;i:541;}i:542;a:1:{i:0;i:543;}i:544;a:1:{i:0;i:414;}i:546;a:1:{i:0;i:547;}i:548;a:1:{i:0;i:549;}i:550;a:1:{i:0;i:551;}i:552;a:1:{i:0;i:553;}i:554;a:1:{i:0;i:555;}i:556;a:1:{i:0;i:557;}i:558;a:1:{i:0;i:559;}i:560;a:1:{i:0;i:561;}i:562;a:1:{i:0;i:563;}i:837;a:1:{i:0;i:953;}i:890;a:2:{i:0;i:32;i:1;i:953;}i:902;a:1:{i:0;i:940;}i:904;a:1:{i:0;i:941;}i:905;a:1:{i:0;i:942;}i:906;a:1:{i:0;i:943;}i:908;a:1:{i:0;i:972;}i:910;a:1:{i:0;i:973;}i:911;a:1:{i:0;i:974;}i:912;a:3:{i:0;i:953;i:1;i:776;i:2;i:769;}i:913;a:1:{i:0;i:945;}i:914;a:1:{i:0;i:946;}i:915;a:1:{i:0;i:947;}i:916;a:1:{i:0;i:948;}i:917;a:1:{i:0;i:949;}i:918;a:1:{i:0;i:950;}i:919;a:1:{i:0;i:951;}i:920;a:1:{i:0;i:952;}i:921;a:1:{i:0;i:953;}i:922;a:1:{i:0;i:954;}i:923;a:1:{i:0;i:955;}i:924;a:1:{i:0;i:956;}i:925;a:1:{i:0;i:957;}i:926;a:1:{i:0;i:958;}i:927;a:1:{i:0;i:959;}i:928;a:1:{i:0;i:960;}i:929;a:1:{i:0;i:961;}i:931;a:1:{i:0;i:963;}i:932;a:1:{i:0;i:964;}i:933;a:1:{i:0;i:965;}i:934;a:1:{i:0;i:966;}i:935;a:1:{i:0;i:967;}i:936;a:1:{i:0;i:968;}i:937;a:1:{i:0;i:969;}i:938;a:1:{i:0;i:970;}i:939;a:1:{i:0;i:971;}i:944;a:3:{i:0;i:965;i:1;i:776;i:2;i:769;}i:962;a:1:{i:0;i:963;}i:976;a:1:{i:0;i:946;}i:977;a:1:{i:0;i:952;}i:978;a:1:{i:0;i:965;}i:979;a:1:{i:0;i:973;}i:980;a:1:{i:0;i:971;}i:981;a:1:{i:0;i:966;}i:982;a:1:{i:0;i:960;}i:984;a:1:{i:0;i:985;}i:986;a:1:{i:0;i:987;}i:988;a:1:{i:0;i:989;}i:990;a:1:{i:0;i:991;}i:992;a:1:{i:0;i:993;}i:994;a:1:{i:0;i:995;}i:996;a:1:{i:0;i:997;}i:998;a:1:{i:0;i:999;}i:1000;a:1:{i:0;i:1001;}i:1002;a:1:{i:0;i:1003;}i:1004;a:1:{i:0;i:1005;}i:1006;a:1:{i:0;i:1007;}i:1008;a:1:{i:0;i:954;}i:1009;a:1:{i:0;i:961;}i:1010;a:1:{i:0;i:963;}i:1012;a:1:{i:0;i:952;}i:1013;a:1:{i:0;i:949;}i:1024;a:1:{i:0;i:1104;}i:1025;a:1:{i:0;i:1105;}i:1026;a:1:{i:0;i:1106;}i:1027;a:1:{i:0;i:1107;}i:1028;a:1:{i:0;i:1108;}i:1029;a:1:{i:0;i:1109;}i:1030;a:1:{i:0;i:1110;}i:1031;a:1:{i:0;i:1111;}i:1032;a:1:{i:0;i:1112;}i:1033;a:1:{i:0;i:1113;}i:1034;a:1:{i:0;i:1114;}i:1035;a:1:{i:0;i:1115;}i:1036;a:1:{i:0;i:1116;}i:1037;a:1:{i:0;i:1117;}i:1038;a:1:{i:0;i:1118;}i:1039;a:1:{i:0;i:1119;}i:1040;a:1:{i:0;i:1072;}i:1041;a:1:{i:0;i:1073;}i:1042;a:1:{i:0;i:1074;}i:1043;a:1:{i:0;i:1075;}i:1044;a:1:{i:0;i:1076;}i:1045;a:1:{i:0;i:1077;}i:1046;a:1:{i:0;i:1078;}i:1047;a:1:{i:0;i:1079;}i:1048;a:1:{i:0;i:1080;}i:1049;a:1:{i:0;i:1081;}i:1050;a:1:{i:0;i:1082;}i:1051;a:1:{i:0;i:1083;}i:1052;a:1:{i:0;i:1084;}i:1053;a:1:{i:0;i:1085;}i:1054;a:1:{i:0;i:1086;}i:1055;a:1:{i:0;i:1087;}i:1056;a:1:{i:0;i:1088;}i:1057;a:1:{i:0;i:1089;}i:1058;a:1:{i:0;i:1090;}i:1059;a:1:{i:0;i:1091;}i:1060;a:1:{i:0;i:1092;}i:1061;a:1:{i:0;i:1093;}i:1062;a:1:{i:0;i:1094;}i:1063;a:1:{i:0;i:1095;}i:1064;a:1:{i:0;i:1096;}i:1065;a:1:{i:0;i:1097;}i:1066;a:1:{i:0;i:1098;}i:1067;a:1:{i:0;i:1099;}i:1068;a:1:{i:0;i:1100;}i:1069;a:1:{i:0;i:1101;}i:1070;a:1:{i:0;i:1102;}i:1071;a:1:{i:0;i:1103;}i:1120;a:1:{i:0;i:1121;}i:1122;a:1:{i:0;i:1123;}i:1124;a:1:{i:0;i:1125;}i:1126;a:1:{i:0;i:1127;}i:1128;a:1:{i:0;i:1129;}i:1130;a:1:{i:0;i:1131;}i:1132;a:1:{i:0;i:1133;}i:1134;a:1:{i:0;i:1135;}i:1136;a:1:{i:0;i:1137;}i:1138;a:1:{i:0;i:1139;}i:1140;a:1:{i:0;i:1141;}i:1142;a:1:{i:0;i:1143;}i:1144;a:1:{i:0;i:1145;}i:1146;a:1:{i:0;i:1147;}i:1148;a:1:{i:0;i:1149;}i:1150;a:1:{i:0;i:1151;}i:1152;a:1:{i:0;i:1153;}i:1162;a:1:{i:0;i:1163;}i:1164;a:1:{i:0;i:1165;}i:1166;a:1:{i:0;i:1167;}i:1168;a:1:{i:0;i:1169;}i:1170;a:1:{i:0;i:1171;}i:1172;a:1:{i:0;i:1173;}i:1174;a:1:{i:0;i:1175;}i:1176;a:1:{i:0;i:1177;}i:1178;a:1:{i:0;i:1179;}i:1180;a:1:{i:0;i:1181;}i:1182;a:1:{i:0;i:1183;}i:1184;a:1:{i:0;i:1185;}i:1186;a:1:{i:0;i:1187;}i:1188;a:1:{i:0;i:1189;}i:1190;a:1:{i:0;i:1191;}i:1192;a:1:{i:0;i:1193;}i:1194;a:1:{i:0;i:1195;}i:1196;a:1:{i:0;i:1197;}i:1198;a:1:{i:0;i:1199;}i:1200;a:1:{i:0;i:1201;}i:1202;a:1:{i:0;i:1203;}i:1204;a:1:{i:0;i:1205;}i:1206;a:1:{i:0;i:1207;}i:1208;a:1:{i:0;i:1209;}i:1210;a:1:{i:0;i:1211;}i:1212;a:1:{i:0;i:1213;}i:1214;a:1:{i:0;i:1215;}i:1217;a:1:{i:0;i:1218;}i:1219;a:1:{i:0;i:1220;}i:1221;a:1:{i:0;i:1222;}i:1223;a:1:{i:0;i:1224;}i:1225;a:1:{i:0;i:1226;}i:1227;a:1:{i:0;i:1228;}i:1229;a:1:{i:0;i:1230;}i:1232;a:1:{i:0;i:1233;}i:1234;a:1:{i:0;i:1235;}i:1236;a:1:{i:0;i:1237;}i:1238;a:1:{i:0;i:1239;}i:1240;a:1:{i:0;i:1241;}i:1242;a:1:{i:0;i:1243;}i:1244;a:1:{i:0;i:1245;}i:1246;a:1:{i:0;i:1247;}i:1248;a:1:{i:0;i:1249;}i:1250;a:1:{i:0;i:1251;}i:1252;a:1:{i:0;i:1253;}i:1254;a:1:{i:0;i:1255;}i:1256;a:1:{i:0;i:1257;}i:1258;a:1:{i:0;i:1259;}i:1260;a:1:{i:0;i:1261;}i:1262;a:1:{i:0;i:1263;}i:1264;a:1:{i:0;i:1265;}i:1266;a:1:{i:0;i:1267;}i:1268;a:1:{i:0;i:1269;}i:1272;a:1:{i:0;i:1273;}i:1280;a:1:{i:0;i:1281;}i:1282;a:1:{i:0;i:1283;}i:1284;a:1:{i:0;i:1285;}i:1286;a:1:{i:0;i:1287;}i:1288;a:1:{i:0;i:1289;}i:1290;a:1:{i:0;i:1291;}i:1292;a:1:{i:0;i:1293;}i:1294;a:1:{i:0;i:1295;}i:1329;a:1:{i:0;i:1377;}i:1330;a:1:{i:0;i:1378;}i:1331;a:1:{i:0;i:1379;}i:1332;a:1:{i:0;i:1380;}i:1333;a:1:{i:0;i:1381;}i:1334;a:1:{i:0;i:1382;}i:1335;a:1:{i:0;i:1383;}i:1336;a:1:{i:0;i:1384;}i:1337;a:1:{i:0;i:1385;}i:1338;a:1:{i:0;i:1386;}i:1339;a:1:{i:0;i:1387;}i:1340;a:1:{i:0;i:1388;}i:1341;a:1:{i:0;i:1389;}i:1342;a:1:{i:0;i:1390;}i:1343;a:1:{i:0;i:1391;}i:1344;a:1:{i:0;i:1392;}i:1345;a:1:{i:0;i:1393;}i:1346;a:1:{i:0;i:1394;}i:1347;a:1:{i:0;i:1395;}i:1348;a:1:{i:0;i:1396;}i:1349;a:1:{i:0;i:1397;}i:1350;a:1:{i:0;i:1398;}i:1351;a:1:{i:0;i:1399;}i:1352;a:1:{i:0;i:1400;}i:1353;a:1:{i:0;i:1401;}i:1354;a:1:{i:0;i:1402;}i:1355;a:1:{i:0;i:1403;}i:1356;a:1:{i:0;i:1404;}i:1357;a:1:{i:0;i:1405;}i:1358;a:1:{i:0;i:1406;}i:1359;a:1:{i:0;i:1407;}i:1360;a:1:{i:0;i:1408;}i:1361;a:1:{i:0;i:1409;}i:1362;a:1:{i:0;i:1410;}i:1363;a:1:{i:0;i:1411;}i:1364;a:1:{i:0;i:1412;}i:1365;a:1:{i:0;i:1413;}i:1366;a:1:{i:0;i:1414;}i:1415;a:2:{i:0;i:1381;i:1;i:1410;}i:7680;a:1:{i:0;i:7681;}i:7682;a:1:{i:0;i:7683;}i:7684;a:1:{i:0;i:7685;}i:7686;a:1:{i:0;i:7687;}i:7688;a:1:{i:0;i:7689;}i:7690;a:1:{i:0;i:7691;}i:7692;a:1:{i:0;i:7693;}i:7694;a:1:{i:0;i:7695;}i:7696;a:1:{i:0;i:7697;}i:7698;a:1:{i:0;i:7699;}i:7700;a:1:{i:0;i:7701;}i:7702;a:1:{i:0;i:7703;}i:7704;a:1:{i:0;i:7705;}i:7706;a:1:{i:0;i:7707;}i:7708;a:1:{i:0;i:7709;}i:7710;a:1:{i:0;i:7711;}i:7712;a:1:{i:0;i:7713;}i:7714;a:1:{i:0;i:7715;}i:7716;a:1:{i:0;i:7717;}i:7718;a:1:{i:0;i:7719;}i:7720;a:1:{i:0;i:7721;}i:7722;a:1:{i:0;i:7723;}i:7724;a:1:{i:0;i:7725;}i:7726;a:1:{i:0;i:7727;}i:7728;a:1:{i:0;i:7729;}i:7730;a:1:{i:0;i:7731;}i:7732;a:1:{i:0;i:7733;}i:7734;a:1:{i:0;i:7735;}i:7736;a:1:{i:0;i:7737;}i:7738;a:1:{i:0;i:7739;}i:7740;a:1:{i:0;i:7741;}i:7742;a:1:{i:0;i:7743;}i:7744;a:1:{i:0;i:7745;}i:7746;a:1:{i:0;i:7747;}i:7748;a:1:{i:0;i:7749;}i:7750;a:1:{i:0;i:7751;}i:7752;a:1:{i:0;i:7753;}i:7754;a:1:{i:0;i:7755;}i:7756;a:1:{i:0;i:7757;}i:7758;a:1:{i:0;i:7759;}i:7760;a:1:{i:0;i:7761;}i:7762;a:1:{i:0;i:7763;}i:7764;a:1:{i:0;i:7765;}i:7766;a:1:{i:0;i:7767;}i:7768;a:1:{i:0;i:7769;}i:7770;a:1:{i:0;i:7771;}i:7772;a:1:{i:0;i:7773;}i:7774;a:1:{i:0;i:7775;}i:7776;a:1:{i:0;i:7777;}i:7778;a:1:{i:0;i:7779;}i:7780;a:1:{i:0;i:7781;}i:7782;a:1:{i:0;i:7783;}i:7784;a:1:{i:0;i:7785;}i:7786;a:1:{i:0;i:7787;}i:7788;a:1:{i:0;i:7789;}i:7790;a:1:{i:0;i:7791;}i:7792;a:1:{i:0;i:7793;}i:7794;a:1:{i:0;i:7795;}i:7796;a:1:{i:0;i:7797;}i:7798;a:1:{i:0;i:7799;}i:7800;a:1:{i:0;i:7801;}i:7802;a:1:{i:0;i:7803;}i:7804;a:1:{i:0;i:7805;}i:7806;a:1:{i:0;i:7807;}i:7808;a:1:{i:0;i:7809;}i:7810;a:1:{i:0;i:7811;}i:7812;a:1:{i:0;i:7813;}i:7814;a:1:{i:0;i:7815;}i:7816;a:1:{i:0;i:7817;}i:7818;a:1:{i:0;i:7819;}i:7820;a:1:{i:0;i:7821;}i:7822;a:1:{i:0;i:7823;}i:7824;a:1:{i:0;i:7825;}i:7826;a:1:{i:0;i:7827;}i:7828;a:1:{i:0;i:7829;}i:7830;a:2:{i:0;i:104;i:1;i:817;}i:7831;a:2:{i:0;i:116;i:1;i:776;}i:7832;a:2:{i:0;i:119;i:1;i:778;}i:7833;a:2:{i:0;i:121;i:1;i:778;}i:7834;a:2:{i:0;i:97;i:1;i:702;}i:7835;a:1:{i:0;i:7777;}i:7840;a:1:{i:0;i:7841;}i:7842;a:1:{i:0;i:7843;}i:7844;a:1:{i:0;i:7845;}i:7846;a:1:{i:0;i:7847;}i:7848;a:1:{i:0;i:7849;}i:7850;a:1:{i:0;i:7851;}i:7852;a:1:{i:0;i:7853;}i:7854;a:1:{i:0;i:7855;}i:7856;a:1:{i:0;i:7857;}i:7858;a:1:{i:0;i:7859;}i:7860;a:1:{i:0;i:7861;}i:7862;a:1:{i:0;i:7863;}i:7864;a:1:{i:0;i:7865;}i:7866;a:1:{i:0;i:7867;}i:7868;a:1:{i:0;i:7869;}i:7870;a:1:{i:0;i:7871;}i:7872;a:1:{i:0;i:7873;}i:7874;a:1:{i:0;i:7875;}i:7876;a:1:{i:0;i:7877;}i:7878;a:1:{i:0;i:7879;}i:7880;a:1:{i:0;i:7881;}i:7882;a:1:{i:0;i:7883;}i:7884;a:1:{i:0;i:7885;}i:7886;a:1:{i:0;i:7887;}i:7888;a:1:{i:0;i:7889;}i:7890;a:1:{i:0;i:7891;}i:7892;a:1:{i:0;i:7893;}i:7894;a:1:{i:0;i:7895;}i:7896;a:1:{i:0;i:7897;}i:7898;a:1:{i:0;i:7899;}i:7900;a:1:{i:0;i:7901;}i:7902;a:1:{i:0;i:7903;}i:7904;a:1:{i:0;i:7905;}i:7906;a:1:{i:0;i:7907;}i:7908;a:1:{i:0;i:7909;}i:7910;a:1:{i:0;i:7911;}i:7912;a:1:{i:0;i:7913;}i:7914;a:1:{i:0;i:7915;}i:7916;a:1:{i:0;i:7917;}i:7918;a:1:{i:0;i:7919;}i:7920;a:1:{i:0;i:7921;}i:7922;a:1:{i:0;i:7923;}i:7924;a:1:{i:0;i:7925;}i:7926;a:1:{i:0;i:7927;}i:7928;a:1:{i:0;i:7929;}i:7944;a:1:{i:0;i:7936;}i:7945;a:1:{i:0;i:7937;}i:7946;a:1:{i:0;i:7938;}i:7947;a:1:{i:0;i:7939;}i:7948;a:1:{i:0;i:7940;}i:7949;a:1:{i:0;i:7941;}i:7950;a:1:{i:0;i:7942;}i:7951;a:1:{i:0;i:7943;}i:7960;a:1:{i:0;i:7952;}i:7961;a:1:{i:0;i:7953;}i:7962;a:1:{i:0;i:7954;}i:7963;a:1:{i:0;i:7955;}i:7964;a:1:{i:0;i:7956;}i:7965;a:1:{i:0;i:7957;}i:7976;a:1:{i:0;i:7968;}i:7977;a:1:{i:0;i:7969;}i:7978;a:1:{i:0;i:7970;}i:7979;a:1:{i:0;i:7971;}i:7980;a:1:{i:0;i:7972;}i:7981;a:1:{i:0;i:7973;}i:7982;a:1:{i:0;i:7974;}i:7983;a:1:{i:0;i:7975;}i:7992;a:1:{i:0;i:7984;}i:7993;a:1:{i:0;i:7985;}i:7994;a:1:{i:0;i:7986;}i:7995;a:1:{i:0;i:7987;}i:7996;a:1:{i:0;i:7988;}i:7997;a:1:{i:0;i:7989;}i:7998;a:1:{i:0;i:7990;}i:7999;a:1:{i:0;i:7991;}i:8008;a:1:{i:0;i:8000;}i:8009;a:1:{i:0;i:8001;}i:8010;a:1:{i:0;i:8002;}i:8011;a:1:{i:0;i:8003;}i:8012;a:1:{i:0;i:8004;}i:8013;a:1:{i:0;i:8005;}i:8016;a:2:{i:0;i:965;i:1;i:787;}i:8018;a:3:{i:0;i:965;i:1;i:787;i:2;i:768;}i:8020;a:3:{i:0;i:965;i:1;i:787;i:2;i:769;}i:8022;a:3:{i:0;i:965;i:1;i:787;i:2;i:834;}i:8025;a:1:{i:0;i:8017;}i:8027;a:1:{i:0;i:8019;}i:8029;a:1:{i:0;i:8021;}i:8031;a:1:{i:0;i:8023;}i:8040;a:1:{i:0;i:8032;}i:8041;a:1:{i:0;i:8033;}i:8042;a:1:{i:0;i:8034;}i:8043;a:1:{i:0;i:8035;}i:8044;a:1:{i:0;i:8036;}i:8045;a:1:{i:0;i:8037;}i:8046;a:1:{i:0;i:8038;}i:8047;a:1:{i:0;i:8039;}i:8064;a:2:{i:0;i:7936;i:1;i:953;}i:8065;a:2:{i:0;i:7937;i:1;i:953;}i:8066;a:2:{i:0;i:7938;i:1;i:953;}i:8067;a:2:{i:0;i:7939;i:1;i:953;}i:8068;a:2:{i:0;i:7940;i:1;i:953;}i:8069;a:2:{i:0;i:7941;i:1;i:953;}i:8070;a:2:{i:0;i:7942;i:1;i:953;}i:8071;a:2:{i:0;i:7943;i:1;i:953;}i:8072;a:2:{i:0;i:7936;i:1;i:953;}i:8073;a:2:{i:0;i:7937;i:1;i:953;}i:8074;a:2:{i:0;i:7938;i:1;i:953;}i:8075;a:2:{i:0;i:7939;i:1;i:953;}i:8076;a:2:{i:0;i:7940;i:1;i:953;}i:8077;a:2:{i:0;i:7941;i:1;i:953;}i:8078;a:2:{i:0;i:7942;i:1;i:953;}i:8079;a:2:{i:0;i:7943;i:1;i:953;}i:8080;a:2:{i:0;i:7968;i:1;i:953;}i:8081;a:2:{i:0;i:7969;i:1;i:953;}i:8082;a:2:{i:0;i:7970;i:1;i:953;}i:8083;a:2:{i:0;i:7971;i:1;i:953;}i:8084;a:2:{i:0;i:7972;i:1;i:953;}i:8085;a:2:{i:0;i:7973;i:1;i:953;}i:8086;a:2:{i:0;i:7974;i:1;i:953;}i:8087;a:2:{i:0;i:7975;i:1;i:953;}i:8088;a:2:{i:0;i:7968;i:1;i:953;}i:8089;a:2:{i:0;i:7969;i:1;i:953;}i:8090;a:2:{i:0;i:7970;i:1;i:953;}i:8091;a:2:{i:0;i:7971;i:1;i:953;}i:8092;a:2:{i:0;i:7972;i:1;i:953;}i:8093;a:2:{i:0;i:7973;i:1;i:953;}i:8094;a:2:{i:0;i:7974;i:1;i:953;}i:8095;a:2:{i:0;i:7975;i:1;i:953;}i:8096;a:2:{i:0;i:8032;i:1;i:953;}i:8097;a:2:{i:0;i:8033;i:1;i:953;}i:8098;a:2:{i:0;i:8034;i:1;i:953;}i:8099;a:2:{i:0;i:8035;i:1;i:953;}i:8100;a:2:{i:0;i:8036;i:1;i:953;}i:8101;a:2:{i:0;i:8037;i:1;i:953;}i:8102;a:2:{i:0;i:8038;i:1;i:953;}i:8103;a:2:{i:0;i:8039;i:1;i:953;}i:8104;a:2:{i:0;i:8032;i:1;i:953;}i:8105;a:2:{i:0;i:8033;i:1;i:953;}i:8106;a:2:{i:0;i:8034;i:1;i:953;}i:8107;a:2:{i:0;i:8035;i:1;i:953;}i:8108;a:2:{i:0;i:8036;i:1;i:953;}i:8109;a:2:{i:0;i:8037;i:1;i:953;}i:8110;a:2:{i:0;i:8038;i:1;i:953;}i:8111;a:2:{i:0;i:8039;i:1;i:953;}i:8114;a:2:{i:0;i:8048;i:1;i:953;}i:8115;a:2:{i:0;i:945;i:1;i:953;}i:8116;a:2:{i:0;i:940;i:1;i:953;}i:8118;a:2:{i:0;i:945;i:1;i:834;}i:8119;a:3:{i:0;i:945;i:1;i:834;i:2;i:953;}i:8120;a:1:{i:0;i:8112;}i:8121;a:1:{i:0;i:8113;}i:8122;a:1:{i:0;i:8048;}i:8123;a:1:{i:0;i:8049;}i:8124;a:2:{i:0;i:945;i:1;i:953;}i:8126;a:1:{i:0;i:953;}i:8130;a:2:{i:0;i:8052;i:1;i:953;}i:8131;a:2:{i:0;i:951;i:1;i:953;}i:8132;a:2:{i:0;i:942;i:1;i:953;}i:8134;a:2:{i:0;i:951;i:1;i:834;}i:8135;a:3:{i:0;i:951;i:1;i:834;i:2;i:953;}i:8136;a:1:{i:0;i:8050;}i:8137;a:1:{i:0;i:8051;}i:8138;a:1:{i:0;i:8052;}i:8139;a:1:{i:0;i:8053;}i:8140;a:2:{i:0;i:951;i:1;i:953;}i:8146;a:3:{i:0;i:953;i:1;i:776;i:2;i:768;}i:8147;a:3:{i:0;i:953;i:1;i:776;i:2;i:769;}i:8150;a:2:{i:0;i:953;i:1;i:834;}i:8151;a:3:{i:0;i:953;i:1;i:776;i:2;i:834;}i:8152;a:1:{i:0;i:8144;}i:8153;a:1:{i:0;i:8145;}i:8154;a:1:{i:0;i:8054;}i:8155;a:1:{i:0;i:8055;}i:8162;a:3:{i:0;i:965;i:1;i:776;i:2;i:768;}i:8163;a:3:{i:0;i:965;i:1;i:776;i:2;i:769;}i:8164;a:2:{i:0;i:961;i:1;i:787;}i:8166;a:2:{i:0;i:965;i:1;i:834;}i:8167;a:3:{i:0;i:965;i:1;i:776;i:2;i:834;}i:8168;a:1:{i:0;i:8160;}i:8169;a:1:{i:0;i:8161;}i:8170;a:1:{i:0;i:8058;}i:8171;a:1:{i:0;i:8059;}i:8172;a:1:{i:0;i:8165;}i:8178;a:2:{i:0;i:8060;i:1;i:953;}i:8179;a:2:{i:0;i:969;i:1;i:953;}i:8180;a:2:{i:0;i:974;i:1;i:953;}i:8182;a:2:{i:0;i:969;i:1;i:834;}i:8183;a:3:{i:0;i:969;i:1;i:834;i:2;i:953;}i:8184;a:1:{i:0;i:8056;}i:8185;a:1:{i:0;i:8057;}i:8186;a:1:{i:0;i:8060;}i:8187;a:1:{i:0;i:8061;}i:8188;a:2:{i:0;i:969;i:1;i:953;}i:8360;a:2:{i:0;i:114;i:1;i:115;}i:8450;a:1:{i:0;i:99;}i:8451;a:2:{i:0;i:176;i:1;i:99;}i:8455;a:1:{i:0;i:603;}i:8457;a:2:{i:0;i:176;i:1;i:102;}i:8459;a:1:{i:0;i:104;}i:8460;a:1:{i:0;i:104;}i:8461;a:1:{i:0;i:104;}i:8464;a:1:{i:0;i:105;}i:8465;a:1:{i:0;i:105;}i:8466;a:1:{i:0;i:108;}i:8469;a:1:{i:0;i:110;}i:8470;a:2:{i:0;i:110;i:1;i:111;}i:8473;a:1:{i:0;i:112;}i:8474;a:1:{i:0;i:113;}i:8475;a:1:{i:0;i:114;}i:8476;a:1:{i:0;i:114;}i:8477;a:1:{i:0;i:114;}i:8480;a:2:{i:0;i:115;i:1;i:109;}i:8481;a:3:{i:0;i:116;i:1;i:101;i:2;i:108;}i:8482;a:2:{i:0;i:116;i:1;i:109;}i:8484;a:1:{i:0;i:122;}i:8486;a:1:{i:0;i:969;}i:8488;a:1:{i:0;i:122;}i:8490;a:1:{i:0;i:107;}i:8491;a:1:{i:0;i:229;}i:8492;a:1:{i:0;i:98;}i:8493;a:1:{i:0;i:99;}i:8496;a:1:{i:0;i:101;}i:8497;a:1:{i:0;i:102;}i:8499;a:1:{i:0;i:109;}i:8510;a:1:{i:0;i:947;}i:8511;a:1:{i:0;i:960;}i:8517;a:1:{i:0;i:100;}i:8544;a:1:{i:0;i:8560;}i:8545;a:1:{i:0;i:8561;}i:8546;a:1:{i:0;i:8562;}i:8547;a:1:{i:0;i:8563;}i:8548;a:1:{i:0;i:8564;}i:8549;a:1:{i:0;i:8565;}i:8550;a:1:{i:0;i:8566;}i:8551;a:1:{i:0;i:8567;}i:8552;a:1:{i:0;i:8568;}i:8553;a:1:{i:0;i:8569;}i:8554;a:1:{i:0;i:8570;}i:8555;a:1:{i:0;i:8571;}i:8556;a:1:{i:0;i:8572;}i:8557;a:1:{i:0;i:8573;}i:8558;a:1:{i:0;i:8574;}i:8559;a:1:{i:0;i:8575;}i:9398;a:1:{i:0;i:9424;}i:9399;a:1:{i:0;i:9425;}i:9400;a:1:{i:0;i:9426;}i:9401;a:1:{i:0;i:9427;}i:9402;a:1:{i:0;i:9428;}i:9403;a:1:{i:0;i:9429;}i:9404;a:1:{i:0;i:9430;}i:9405;a:1:{i:0;i:9431;}i:9406;a:1:{i:0;i:9432;}i:9407;a:1:{i:0;i:9433;}i:9408;a:1:{i:0;i:9434;}i:9409;a:1:{i:0;i:9435;}i:9410;a:1:{i:0;i:9436;}i:9411;a:1:{i:0;i:9437;}i:9412;a:1:{i:0;i:9438;}i:9413;a:1:{i:0;i:9439;}i:9414;a:1:{i:0;i:9440;}i:9415;a:1:{i:0;i:9441;}i:9416;a:1:{i:0;i:9442;}i:9417;a:1:{i:0;i:9443;}i:9418;a:1:{i:0;i:9444;}i:9419;a:1:{i:0;i:9445;}i:9420;a:1:{i:0;i:9446;}i:9421;a:1:{i:0;i:9447;}i:9422;a:1:{i:0;i:9448;}i:9423;a:1:{i:0;i:9449;}i:13169;a:3:{i:0;i:104;i:1;i:112;i:2;i:97;}i:13171;a:2:{i:0;i:97;i:1;i:117;}i:13173;a:2:{i:0;i:111;i:1;i:118;}i:13184;a:2:{i:0;i:112;i:1;i:97;}i:13185;a:2:{i:0;i:110;i:1;i:97;}i:13186;a:2:{i:0;i:956;i:1;i:97;}i:13187;a:2:{i:0;i:109;i:1;i:97;}i:13188;a:2:{i:0;i:107;i:1;i:97;}i:13189;a:2:{i:0;i:107;i:1;i:98;}i:13190;a:2:{i:0;i:109;i:1;i:98;}i:13191;a:2:{i:0;i:103;i:1;i:98;}i:13194;a:2:{i:0;i:112;i:1;i:102;}i:13195;a:2:{i:0;i:110;i:1;i:102;}i:13196;a:2:{i:0;i:956;i:1;i:102;}i:13200;a:2:{i:0;i:104;i:1;i:122;}i:13201;a:3:{i:0;i:107;i:1;i:104;i:2;i:122;}i:13202;a:3:{i:0;i:109;i:1;i:104;i:2;i:122;}i:13203;a:3:{i:0;i:103;i:1;i:104;i:2;i:122;}i:13204;a:3:{i:0;i:116;i:1;i:104;i:2;i:122;}i:13225;a:2:{i:0;i:112;i:1;i:97;}i:13226;a:3:{i:0;i:107;i:1;i:112;i:2;i:97;}i:13227;a:3:{i:0;i:109;i:1;i:112;i:2;i:97;}i:13228;a:3:{i:0;i:103;i:1;i:112;i:2;i:97;}i:13236;a:2:{i:0;i:112;i:1;i:118;}i:13237;a:2:{i:0;i:110;i:1;i:118;}i:13238;a:2:{i:0;i:956;i:1;i:118;}i:13239;a:2:{i:0;i:109;i:1;i:118;}i:13240;a:2:{i:0;i:107;i:1;i:118;}i:13241;a:2:{i:0;i:109;i:1;i:118;}i:13242;a:2:{i:0;i:112;i:1;i:119;}i:13243;a:2:{i:0;i:110;i:1;i:119;}i:13244;a:2:{i:0;i:956;i:1;i:119;}i:13245;a:2:{i:0;i:109;i:1;i:119;}i:13246;a:2:{i:0;i:107;i:1;i:119;}i:13247;a:2:{i:0;i:109;i:1;i:119;}i:13248;a:2:{i:0;i:107;i:1;i:969;}i:13249;a:2:{i:0;i:109;i:1;i:969;}i:13251;a:2:{i:0;i:98;i:1;i:113;}i:13254;a:4:{i:0;i:99;i:1;i:8725;i:2;i:107;i:3;i:103;}i:13255;a:3:{i:0;i:99;i:1;i:111;i:2;i:46;}i:13256;a:2:{i:0;i:100;i:1;i:98;}i:13257;a:2:{i:0;i:103;i:1;i:121;}i:13259;a:2:{i:0;i:104;i:1;i:112;}i:13261;a:2:{i:0;i:107;i:1;i:107;}i:13262;a:2:{i:0;i:107;i:1;i:109;}i:13271;a:2:{i:0;i:112;i:1;i:104;}i:13273;a:3:{i:0;i:112;i:1;i:112;i:2;i:109;}i:13274;a:2:{i:0;i:112;i:1;i:114;}i:13276;a:2:{i:0;i:115;i:1;i:118;}i:13277;a:2:{i:0;i:119;i:1;i:98;}i:64256;a:2:{i:0;i:102;i:1;i:102;}i:64257;a:2:{i:0;i:102;i:1;i:105;}i:64258;a:2:{i:0;i:102;i:1;i:108;}i:64259;a:3:{i:0;i:102;i:1;i:102;i:2;i:105;}i:64260;a:3:{i:0;i:102;i:1;i:102;i:2;i:108;}i:64261;a:2:{i:0;i:115;i:1;i:116;}i:64262;a:2:{i:0;i:115;i:1;i:116;}i:64275;a:2:{i:0;i:1396;i:1;i:1398;}i:64276;a:2:{i:0;i:1396;i:1;i:1381;}i:64277;a:2:{i:0;i:1396;i:1;i:1387;}i:64278;a:2:{i:0;i:1406;i:1;i:1398;}i:64279;a:2:{i:0;i:1396;i:1;i:1389;}i:65313;a:1:{i:0;i:65345;}i:65314;a:1:{i:0;i:65346;}i:65315;a:1:{i:0;i:65347;}i:65316;a:1:{i:0;i:65348;}i:65317;a:1:{i:0;i:65349;}i:65318;a:1:{i:0;i:65350;}i:65319;a:1:{i:0;i:65351;}i:65320;a:1:{i:0;i:65352;}i:65321;a:1:{i:0;i:65353;}i:65322;a:1:{i:0;i:65354;}i:65323;a:1:{i:0;i:65355;}i:65324;a:1:{i:0;i:65356;}i:65325;a:1:{i:0;i:65357;}i:65326;a:1:{i:0;i:65358;}i:65327;a:1:{i:0;i:65359;}i:65328;a:1:{i:0;i:65360;}i:65329;a:1:{i:0;i:65361;}i:65330;a:1:{i:0;i:65362;}i:65331;a:1:{i:0;i:65363;}i:65332;a:1:{i:0;i:65364;}i:65333;a:1:{i:0;i:65365;}i:65334;a:1:{i:0;i:65366;}i:65335;a:1:{i:0;i:65367;}i:65336;a:1:{i:0;i:65368;}i:65337;a:1:{i:0;i:65369;}i:65338;a:1:{i:0;i:65370;}i:66560;a:1:{i:0;i:66600;}i:66561;a:1:{i:0;i:66601;}i:66562;a:1:{i:0;i:66602;}i:66563;a:1:{i:0;i:66603;}i:66564;a:1:{i:0;i:66604;}i:66565;a:1:{i:0;i:66605;}i:66566;a:1:{i:0;i:66606;}i:66567;a:1:{i:0;i:66607;}i:66568;a:1:{i:0;i:66608;}i:66569;a:1:{i:0;i:66609;}i:66570;a:1:{i:0;i:66610;}i:66571;a:1:{i:0;i:66611;}i:66572;a:1:{i:0;i:66612;}i:66573;a:1:{i:0;i:66613;}i:66574;a:1:{i:0;i:66614;}i:66575;a:1:{i:0;i:66615;}i:66576;a:1:{i:0;i:66616;}i:66577;a:1:{i:0;i:66617;}i:66578;a:1:{i:0;i:66618;}i:66579;a:1:{i:0;i:66619;}i:66580;a:1:{i:0;i:66620;}i:66581;a:1:{i:0;i:66621;}i:66582;a:1:{i:0;i:66622;}i:66583;a:1:{i:0;i:66623;}i:66584;a:1:{i:0;i:66624;}i:66585;a:1:{i:0;i:66625;}i:66586;a:1:{i:0;i:66626;}i:66587;a:1:{i:0;i:66627;}i:66588;a:1:{i:0;i:66628;}i:66589;a:1:{i:0;i:66629;}i:66590;a:1:{i:0;i:66630;}i:66591;a:1:{i:0;i:66631;}i:66592;a:1:{i:0;i:66632;}i:66593;a:1:{i:0;i:66633;}i:66594;a:1:{i:0;i:66634;}i:66595;a:1:{i:0;i:66635;}i:66596;a:1:{i:0;i:66636;}i:66597;a:1:{i:0;i:66637;}i:119808;a:1:{i:0;i:97;}i:119809;a:1:{i:0;i:98;}i:119810;a:1:{i:0;i:99;}i:119811;a:1:{i:0;i:100;}i:119812;a:1:{i:0;i:101;}i:119813;a:1:{i:0;i:102;}i:119814;a:1:{i:0;i:103;}i:119815;a:1:{i:0;i:104;}i:119816;a:1:{i:0;i:105;}i:119817;a:1:{i:0;i:106;}i:119818;a:1:{i:0;i:107;}i:119819;a:1:{i:0;i:108;}i:119820;a:1:{i:0;i:109;}i:119821;a:1:{i:0;i:110;}i:119822;a:1:{i:0;i:111;}i:119823;a:1:{i:0;i:112;}i:119824;a:1:{i:0;i:113;}i:119825;a:1:{i:0;i:114;}i:119826;a:1:{i:0;i:115;}i:119827;a:1:{i:0;i:116;}i:119828;a:1:{i:0;i:117;}i:119829;a:1:{i:0;i:118;}i:119830;a:1:{i:0;i:119;}i:119831;a:1:{i:0;i:120;}i:119832;a:1:{i:0;i:121;}i:119833;a:1:{i:0;i:122;}i:119860;a:1:{i:0;i:97;}i:119861;a:1:{i:0;i:98;}i:119862;a:1:{i:0;i:99;}i:119863;a:1:{i:0;i:100;}i:119864;a:1:{i:0;i:101;}i:119865;a:1:{i:0;i:102;}i:119866;a:1:{i:0;i:103;}i:119867;a:1:{i:0;i:104;}i:119868;a:1:{i:0;i:105;}i:119869;a:1:{i:0;i:106;}i:119870;a:1:{i:0;i:107;}i:119871;a:1:{i:0;i:108;}i:119872;a:1:{i:0;i:109;}i:119873;a:1:{i:0;i:110;}i:119874;a:1:{i:0;i:111;}i:119875;a:1:{i:0;i:112;}i:119876;a:1:{i:0;i:113;}i:119877;a:1:{i:0;i:114;}i:119878;a:1:{i:0;i:115;}i:119879;a:1:{i:0;i:116;}i:119880;a:1:{i:0;i:117;}i:119881;a:1:{i:0;i:118;}i:119882;a:1:{i:0;i:119;}i:119883;a:1:{i:0;i:120;}i:119884;a:1:{i:0;i:121;}i:119885;a:1:{i:0;i:122;}i:119912;a:1:{i:0;i:97;}i:119913;a:1:{i:0;i:98;}i:119914;a:1:{i:0;i:99;}i:119915;a:1:{i:0;i:100;}i:119916;a:1:{i:0;i:101;}i:119917;a:1:{i:0;i:102;}i:119918;a:1:{i:0;i:103;}i:119919;a:1:{i:0;i:104;}i:119920;a:1:{i:0;i:105;}i:119921;a:1:{i:0;i:106;}i:119922;a:1:{i:0;i:107;}i:119923;a:1:{i:0;i:108;}i:119924;a:1:{i:0;i:109;}i:119925;a:1:{i:0;i:110;}i:119926;a:1:{i:0;i:111;}i:119927;a:1:{i:0;i:112;}i:119928;a:1:{i:0;i:113;}i:119929;a:1:{i:0;i:114;}i:119930;a:1:{i:0;i:115;}i:119931;a:1:{i:0;i:116;}i:119932;a:1:{i:0;i:117;}i:119933;a:1:{i:0;i:118;}i:119934;a:1:{i:0;i:119;}i:119935;a:1:{i:0;i:120;}i:119936;a:1:{i:0;i:121;}i:119937;a:1:{i:0;i:122;}i:119964;a:1:{i:0;i:97;}i:119966;a:1:{i:0;i:99;}i:119967;a:1:{i:0;i:100;}i:119970;a:1:{i:0;i:103;}i:119973;a:1:{i:0;i:106;}i:119974;a:1:{i:0;i:107;}i:119977;a:1:{i:0;i:110;}i:119978;a:1:{i:0;i:111;}i:119979;a:1:{i:0;i:112;}i:119980;a:1:{i:0;i:113;}i:119982;a:1:{i:0;i:115;}i:119983;a:1:{i:0;i:116;}i:119984;a:1:{i:0;i:117;}i:119985;a:1:{i:0;i:118;}i:119986;a:1:{i:0;i:119;}i:119987;a:1:{i:0;i:120;}i:119988;a:1:{i:0;i:121;}i:119989;a:1:{i:0;i:122;}i:120016;a:1:{i:0;i:97;}i:120017;a:1:{i:0;i:98;}i:120018;a:1:{i:0;i:99;}i:120019;a:1:{i:0;i:100;}i:120020;a:1:{i:0;i:101;}i:120021;a:1:{i:0;i:102;}i:120022;a:1:{i:0;i:103;}i:120023;a:1:{i:0;i:104;}i:120024;a:1:{i:0;i:105;}i:120025;a:1:{i:0;i:106;}i:120026;a:1:{i:0;i:107;}i:120027;a:1:{i:0;i:108;}i:120028;a:1:{i:0;i:109;}i:120029;a:1:{i:0;i:110;}i:120030;a:1:{i:0;i:111;}i:120031;a:1:{i:0;i:112;}i:120032;a:1:{i:0;i:113;}i:120033;a:1:{i:0;i:114;}i:120034;a:1:{i:0;i:115;}i:120035;a:1:{i:0;i:116;}i:120036;a:1:{i:0;i:117;}i:120037;a:1:{i:0;i:118;}i:120038;a:1:{i:0;i:119;}i:120039;a:1:{i:0;i:120;}i:120040;a:1:{i:0;i:121;}i:120041;a:1:{i:0;i:122;}i:120068;a:1:{i:0;i:97;}i:120069;a:1:{i:0;i:98;}i:120071;a:1:{i:0;i:100;}i:120072;a:1:{i:0;i:101;}i:120073;a:1:{i:0;i:102;}i:120074;a:1:{i:0;i:103;}i:120077;a:1:{i:0;i:106;}i:120078;a:1:{i:0;i:107;}i:120079;a:1:{i:0;i:108;}i:120080;a:1:{i:0;i:109;}i:120081;a:1:{i:0;i:110;}i:120082;a:1:{i:0;i:111;}i:120083;a:1:{i:0;i:112;}i:120084;a:1:{i:0;i:113;}i:120086;a:1:{i:0;i:115;}i:120087;a:1:{i:0;i:116;}i:120088;a:1:{i:0;i:117;}i:120089;a:1:{i:0;i:118;}i:120090;a:1:{i:0;i:119;}i:120091;a:1:{i:0;i:120;}i:120092;a:1:{i:0;i:121;}i:120120;a:1:{i:0;i:97;}i:120121;a:1:{i:0;i:98;}i:120123;a:1:{i:0;i:100;}i:120124;a:1:{i:0;i:101;}i:120125;a:1:{i:0;i:102;}i:120126;a:1:{i:0;i:103;}i:120128;a:1:{i:0;i:105;}i:120129;a:1:{i:0;i:106;}i:120130;a:1:{i:0;i:107;}i:120131;a:1:{i:0;i:108;}i:120132;a:1:{i:0;i:109;}i:120134;a:1:{i:0;i:111;}i:120138;a:1:{i:0;i:115;}i:120139;a:1:{i:0;i:116;}i:120140;a:1:{i:0;i:117;}i:120141;a:1:{i:0;i:118;}i:120142;a:1:{i:0;i:119;}i:120143;a:1:{i:0;i:120;}i:120144;a:1:{i:0;i:121;}i:120172;a:1:{i:0;i:97;}i:120173;a:1:{i:0;i:98;}i:120174;a:1:{i:0;i:99;}i:120175;a:1:{i:0;i:100;}i:120176;a:1:{i:0;i:101;}i:120177;a:1:{i:0;i:102;}i:120178;a:1:{i:0;i:103;}i:120179;a:1:{i:0;i:104;}i:120180;a:1:{i:0;i:105;}i:120181;a:1:{i:0;i:106;}i:120182;a:1:{i:0;i:107;}i:120183;a:1:{i:0;i:108;}i:120184;a:1:{i:0;i:109;}i:120185;a:1:{i:0;i:110;}i:120186;a:1:{i:0;i:111;}i:120187;a:1:{i:0;i:112;}i:120188;a:1:{i:0;i:113;}i:120189;a:1:{i:0;i:114;}i:120190;a:1:{i:0;i:115;}i:120191;a:1:{i:0;i:116;}i:120192;a:1:{i:0;i:117;}i:120193;a:1:{i:0;i:118;}i:120194;a:1:{i:0;i:119;}i:120195;a:1:{i:0;i:120;}i:120196;a:1:{i:0;i:121;}i:120197;a:1:{i:0;i:122;}i:120224;a:1:{i:0;i:97;}i:120225;a:1:{i:0;i:98;}i:120226;a:1:{i:0;i:99;}i:120227;a:1:{i:0;i:100;}i:120228;a:1:{i:0;i:101;}i:120229;a:1:{i:0;i:102;}i:120230;a:1:{i:0;i:103;}i:120231;a:1:{i:0;i:104;}i:120232;a:1:{i:0;i:105;}i:120233;a:1:{i:0;i:106;}i:120234;a:1:{i:0;i:107;}i:120235;a:1:{i:0;i:108;}i:120236;a:1:{i:0;i:109;}i:120237;a:1:{i:0;i:110;}i:120238;a:1:{i:0;i:111;}i:120239;a:1:{i:0;i:112;}i:120240;a:1:{i:0;i:113;}i:120241;a:1:{i:0;i:114;}i:120242;a:1:{i:0;i:115;}i:120243;a:1:{i:0;i:116;}i:120244;a:1:{i:0;i:117;}i:120245;a:1:{i:0;i:118;}i:120246;a:1:{i:0;i:119;}i:120247;a:1:{i:0;i:120;}i:120248;a:1:{i:0;i:121;}i:120249;a:1:{i:0;i:122;}i:120276;a:1:{i:0;i:97;}i:120277;a:1:{i:0;i:98;}i:120278;a:1:{i:0;i:99;}i:120279;a:1:{i:0;i:100;}i:120280;a:1:{i:0;i:101;}i:120281;a:1:{i:0;i:102;}i:120282;a:1:{i:0;i:103;}i:120283;a:1:{i:0;i:104;}i:120284;a:1:{i:0;i:105;}i:120285;a:1:{i:0;i:106;}i:120286;a:1:{i:0;i:107;}i:120287;a:1:{i:0;i:108;}i:120288;a:1:{i:0;i:109;}i:120289;a:1:{i:0;i:110;}i:120290;a:1:{i:0;i:111;}i:120291;a:1:{i:0;i:112;}i:120292;a:1:{i:0;i:113;}i:120293;a:1:{i:0;i:114;}i:120294;a:1:{i:0;i:115;}i:120295;a:1:{i:0;i:116;}i:120296;a:1:{i:0;i:117;}i:120297;a:1:{i:0;i:118;}i:120298;a:1:{i:0;i:119;}i:120299;a:1:{i:0;i:120;}i:120300;a:1:{i:0;i:121;}i:120301;a:1:{i:0;i:122;}i:120328;a:1:{i:0;i:97;}i:120329;a:1:{i:0;i:98;}i:120330;a:1:{i:0;i:99;}i:120331;a:1:{i:0;i:100;}i:120332;a:1:{i:0;i:101;}i:120333;a:1:{i:0;i:102;}i:120334;a:1:{i:0;i:103;}i:120335;a:1:{i:0;i:104;}i:120336;a:1:{i:0;i:105;}i:120337;a:1:{i:0;i:106;}i:120338;a:1:{i:0;i:107;}i:120339;a:1:{i:0;i:108;}i:120340;a:1:{i:0;i:109;}i:120341;a:1:{i:0;i:110;}i:120342;a:1:{i:0;i:111;}i:120343;a:1:{i:0;i:112;}i:120344;a:1:{i:0;i:113;}i:120345;a:1:{i:0;i:114;}i:120346;a:1:{i:0;i:115;}i:120347;a:1:{i:0;i:116;}i:120348;a:1:{i:0;i:117;}i:120349;a:1:{i:0;i:118;}i:120350;a:1:{i:0;i:119;}i:120351;a:1:{i:0;i:120;}i:120352;a:1:{i:0;i:121;}i:120353;a:1:{i:0;i:122;}i:120380;a:1:{i:0;i:97;}i:120381;a:1:{i:0;i:98;}i:120382;a:1:{i:0;i:99;}i:120383;a:1:{i:0;i:100;}i:120384;a:1:{i:0;i:101;}i:120385;a:1:{i:0;i:102;}i:120386;a:1:{i:0;i:103;}i:120387;a:1:{i:0;i:104;}i:120388;a:1:{i:0;i:105;}i:120389;a:1:{i:0;i:106;}i:120390;a:1:{i:0;i:107;}i:120391;a:1:{i:0;i:108;}i:120392;a:1:{i:0;i:109;}i:120393;a:1:{i:0;i:110;}i:120394;a:1:{i:0;i:111;}i:120395;a:1:{i:0;i:112;}i:120396;a:1:{i:0;i:113;}i:120397;a:1:{i:0;i:114;}i:120398;a:1:{i:0;i:115;}i:120399;a:1:{i:0;i:116;}i:120400;a:1:{i:0;i:117;}i:120401;a:1:{i:0;i:118;}i:120402;a:1:{i:0;i:119;}i:120403;a:1:{i:0;i:120;}i:120404;a:1:{i:0;i:121;}i:120405;a:1:{i:0;i:122;}i:120432;a:1:{i:0;i:97;}i:120433;a:1:{i:0;i:98;}i:120434;a:1:{i:0;i:99;}i:120435;a:1:{i:0;i:100;}i:120436;a:1:{i:0;i:101;}i:120437;a:1:{i:0;i:102;}i:120438;a:1:{i:0;i:103;}i:120439;a:1:{i:0;i:104;}i:120440;a:1:{i:0;i:105;}i:120441;a:1:{i:0;i:106;}i:120442;a:1:{i:0;i:107;}i:120443;a:1:{i:0;i:108;}i:120444;a:1:{i:0;i:109;}i:120445;a:1:{i:0;i:110;}i:120446;a:1:{i:0;i:111;}i:120447;a:1:{i:0;i:112;}i:120448;a:1:{i:0;i:113;}i:120449;a:1:{i:0;i:114;}i:120450;a:1:{i:0;i:115;}i:120451;a:1:{i:0;i:116;}i:120452;a:1:{i:0;i:117;}i:120453;a:1:{i:0;i:118;}i:120454;a:1:{i:0;i:119;}i:120455;a:1:{i:0;i:120;}i:120456;a:1:{i:0;i:121;}i:120457;a:1:{i:0;i:122;}i:120488;a:1:{i:0;i:945;}i:120489;a:1:{i:0;i:946;}i:120490;a:1:{i:0;i:947;}i:120491;a:1:{i:0;i:948;}i:120492;a:1:{i:0;i:949;}i:120493;a:1:{i:0;i:950;}i:120494;a:1:{i:0;i:951;}i:120495;a:1:{i:0;i:952;}i:120496;a:1:{i:0;i:953;}i:120497;a:1:{i:0;i:954;}i:120498;a:1:{i:0;i:955;}i:120499;a:1:{i:0;i:956;}i:120500;a:1:{i:0;i:957;}i:120501;a:1:{i:0;i:958;}i:120502;a:1:{i:0;i:959;}i:120503;a:1:{i:0;i:960;}i:120504;a:1:{i:0;i:961;}i:120505;a:1:{i:0;i:952;}i:120506;a:1:{i:0;i:963;}i:120507;a:1:{i:0;i:964;}i:120508;a:1:{i:0;i:965;}i:120509;a:1:{i:0;i:966;}i:120510;a:1:{i:0;i:967;}i:120511;a:1:{i:0;i:968;}i:120512;a:1:{i:0;i:969;}i:120531;a:1:{i:0;i:963;}i:120546;a:1:{i:0;i:945;}i:120547;a:1:{i:0;i:946;}i:120548;a:1:{i:0;i:947;}i:120549;a:1:{i:0;i:948;}i:120550;a:1:{i:0;i:949;}i:120551;a:1:{i:0;i:950;}i:120552;a:1:{i:0;i:951;}i:120553;a:1:{i:0;i:952;}i:120554;a:1:{i:0;i:953;}i:120555;a:1:{i:0;i:954;}i:120556;a:1:{i:0;i:955;}i:120557;a:1:{i:0;i:956;}i:120558;a:1:{i:0;i:957;}i:120559;a:1:{i:0;i:958;}i:120560;a:1:{i:0;i:959;}i:120561;a:1:{i:0;i:960;}i:120562;a:1:{i:0;i:961;}i:120563;a:1:{i:0;i:952;}i:120564;a:1:{i:0;i:963;}i:120565;a:1:{i:0;i:964;}i:120566;a:1:{i:0;i:965;}i:120567;a:1:{i:0;i:966;}i:120568;a:1:{i:0;i:967;}i:120569;a:1:{i:0;i:968;}i:120570;a:1:{i:0;i:969;}i:120589;a:1:{i:0;i:963;}i:120604;a:1:{i:0;i:945;}i:120605;a:1:{i:0;i:946;}i:120606;a:1:{i:0;i:947;}i:120607;a:1:{i:0;i:948;}i:120608;a:1:{i:0;i:949;}i:120609;a:1:{i:0;i:950;}i:120610;a:1:{i:0;i:951;}i:120611;a:1:{i:0;i:952;}i:120612;a:1:{i:0;i:953;}i:120613;a:1:{i:0;i:954;}i:120614;a:1:{i:0;i:955;}i:120615;a:1:{i:0;i:956;}i:120616;a:1:{i:0;i:957;}i:120617;a:1:{i:0;i:958;}i:120618;a:1:{i:0;i:959;}i:120619;a:1:{i:0;i:960;}i:120620;a:1:{i:0;i:961;}i:120621;a:1:{i:0;i:952;}i:120622;a:1:{i:0;i:963;}i:120623;a:1:{i:0;i:964;}i:120624;a:1:{i:0;i:965;}i:120625;a:1:{i:0;i:966;}i:120626;a:1:{i:0;i:967;}i:120627;a:1:{i:0;i:968;}i:120628;a:1:{i:0;i:969;}i:120647;a:1:{i:0;i:963;}i:120662;a:1:{i:0;i:945;}i:120663;a:1:{i:0;i:946;}i:120664;a:1:{i:0;i:947;}i:120665;a:1:{i:0;i:948;}i:120666;a:1:{i:0;i:949;}i:120667;a:1:{i:0;i:950;}i:120668;a:1:{i:0;i:951;}i:120669;a:1:{i:0;i:952;}i:120670;a:1:{i:0;i:953;}i:120671;a:1:{i:0;i:954;}i:120672;a:1:{i:0;i:955;}i:120673;a:1:{i:0;i:956;}i:120674;a:1:{i:0;i:957;}i:120675;a:1:{i:0;i:958;}i:120676;a:1:{i:0;i:959;}i:120677;a:1:{i:0;i:960;}i:120678;a:1:{i:0;i:961;}i:120679;a:1:{i:0;i:952;}i:120680;a:1:{i:0;i:963;}i:120681;a:1:{i:0;i:964;}i:120682;a:1:{i:0;i:965;}i:120683;a:1:{i:0;i:966;}i:120684;a:1:{i:0;i:967;}i:120685;a:1:{i:0;i:968;}i:120686;a:1:{i:0;i:969;}i:120705;a:1:{i:0;i:963;}i:120720;a:1:{i:0;i:945;}i:120721;a:1:{i:0;i:946;}i:120722;a:1:{i:0;i:947;}i:120723;a:1:{i:0;i:948;}i:120724;a:1:{i:0;i:949;}i:120725;a:1:{i:0;i:950;}i:120726;a:1:{i:0;i:951;}i:120727;a:1:{i:0;i:952;}i:120728;a:1:{i:0;i:953;}i:120729;a:1:{i:0;i:954;}i:120730;a:1:{i:0;i:955;}i:120731;a:1:{i:0;i:956;}i:120732;a:1:{i:0;i:957;}i:120733;a:1:{i:0;i:958;}i:120734;a:1:{i:0;i:959;}i:120735;a:1:{i:0;i:960;}i:120736;a:1:{i:0;i:961;}i:120737;a:1:{i:0;i:952;}i:120738;a:1:{i:0;i:963;}i:120739;a:1:{i:0;i:964;}i:120740;a:1:{i:0;i:965;}i:120741;a:1:{i:0;i:966;}i:120742;a:1:{i:0;i:967;}i:120743;a:1:{i:0;i:968;}i:120744;a:1:{i:0;i:969;}i:120763;a:1:{i:0;i:963;}i:1017;a:1:{i:0;i:963;}i:7468;a:1:{i:0;i:97;}i:7469;a:1:{i:0;i:230;}i:7470;a:1:{i:0;i:98;}i:7472;a:1:{i:0;i:100;}i:7473;a:1:{i:0;i:101;}i:7474;a:1:{i:0;i:477;}i:7475;a:1:{i:0;i:103;}i:7476;a:1:{i:0;i:104;}i:7477;a:1:{i:0;i:105;}i:7478;a:1:{i:0;i:106;}i:7479;a:1:{i:0;i:107;}i:7480;a:1:{i:0;i:108;}i:7481;a:1:{i:0;i:109;}i:7482;a:1:{i:0;i:110;}i:7484;a:1:{i:0;i:111;}i:7485;a:1:{i:0;i:547;}i:7486;a:1:{i:0;i:112;}i:7487;a:1:{i:0;i:114;}i:7488;a:1:{i:0;i:116;}i:7489;a:1:{i:0;i:117;}i:7490;a:1:{i:0;i:119;}i:8507;a:3:{i:0;i:102;i:1;i:97;i:2;i:120;}i:12880;a:3:{i:0;i:112;i:1;i:116;i:2;i:101;}i:13004;a:2:{i:0;i:104;i:1;i:103;}i:13006;a:2:{i:0;i:101;i:1;i:118;}i:13007;a:3:{i:0;i:108;i:1;i:116;i:2;i:100;}i:13178;a:2:{i:0;i:105;i:1;i:117;}i:13278;a:3:{i:0;i:118;i:1;i:8725;i:2;i:109;}i:13279;a:3:{i:0;i:97;i:1;i:8725;i:2;i:109;}}s:12:"norm_combcls";a:341:{i:820;i:1;i:821;i:1;i:822;i:1;i:823;i:1;i:824;i:1;i:2364;i:7;i:2492;i:7;i:2620;i:7;i:2748;i:7;i:2876;i:7;i:3260;i:7;i:4151;i:7;i:12441;i:8;i:12442;i:8;i:2381;i:9;i:2509;i:9;i:2637;i:9;i:2765;i:9;i:2893;i:9;i:3021;i:9;i:3149;i:9;i:3277;i:9;i:3405;i:9;i:3530;i:9;i:3642;i:9;i:3972;i:9;i:4153;i:9;i:5908;i:9;i:5940;i:9;i:6098;i:9;i:1456;i:10;i:1457;i:11;i:1458;i:12;i:1459;i:13;i:1460;i:14;i:1461;i:15;i:1462;i:16;i:1463;i:17;i:1464;i:18;i:1465;i:19;i:1467;i:20;i:1468;i:21;i:1469;i:22;i:1471;i:23;i:1473;i:24;i:1474;i:25;i:64286;i:26;i:1611;i:27;i:1612;i:28;i:1613;i:29;i:1614;i:30;i:1615;i:31;i:1616;i:32;i:1617;i:33;i:1618;i:34;i:1648;i:35;i:1809;i:36;i:3157;i:84;i:3158;i:91;i:3640;i:103;i:3641;i:103;i:3656;i:107;i:3657;i:107;i:3658;i:107;i:3659;i:107;i:3768;i:118;i:3769;i:118;i:3784;i:122;i:3785;i:122;i:3786;i:122;i:3787;i:122;i:3953;i:129;i:3954;i:130;i:3962;i:130;i:3963;i:130;i:3964;i:130;i:3965;i:130;i:3968;i:130;i:3956;i:132;i:801;i:202;i:802;i:202;i:807;i:202;i:808;i:202;i:795;i:216;i:3897;i:216;i:119141;i:216;i:119142;i:216;i:119150;i:216;i:119151;i:216;i:119152;i:216;i:119153;i:216;i:119154;i:216;i:12330;i:218;i:790;i:220;i:791;i:220;i:792;i:220;i:793;i:220;i:796;i:220;i:797;i:220;i:798;i:220;i:799;i:220;i:800;i:220;i:803;i:220;i:804;i:220;i:805;i:220;i:806;i:220;i:809;i:220;i:810;i:220;i:811;i:220;i:812;i:220;i:813;i:220;i:814;i:220;i:815;i:220;i:816;i:220;i:817;i:220;i:818;i:220;i:819;i:220;i:825;i:220;i:826;i:220;i:827;i:220;i:828;i:220;i:839;i:220;i:840;i:220;i:841;i:220;i:845;i:220;i:846;i:220;i:851;i:220;i:852;i:220;i:853;i:220;i:854;i:220;i:1425;i:220;i:1430;i:220;i:1435;i:220;i:1443;i:220;i:1444;i:220;i:1445;i:220;i:1446;i:220;i:1447;i:220;i:1450;i:220;i:1621;i:220;i:1622;i:220;i:1763;i:220;i:1770;i:220;i:1773;i:220;i:1841;i:220;i:1844;i:220;i:1847;i:220;i:1848;i:220;i:1849;i:220;i:1851;i:220;i:1852;i:220;i:1854;i:220;i:1858;i:220;i:1860;i:220;i:1862;i:220;i:1864;i:220;i:2386;i:220;i:3864;i:220;i:3865;i:220;i:3893;i:220;i:3895;i:220;i:4038;i:220;i:6459;i:220;i:8424;i:220;i:119163;i:220;i:119164;i:220;i:119165;i:220;i:119166;i:220;i:119167;i:220;i:119168;i:220;i:119169;i:220;i:119170;i:220;i:119178;i:220;i:119179;i:220;i:1434;i:222;i:1453;i:222;i:6441;i:222;i:12333;i:222;i:12334;i:224;i:12335;i:224;i:119149;i:226;i:1454;i:228;i:6313;i:228;i:12331;i:228;i:768;i:230;i:769;i:230;i:770;i:230;i:771;i:230;i:772;i:230;i:773;i:230;i:774;i:230;i:775;i:230;i:776;i:230;i:777;i:230;i:778;i:230;i:779;i:230;i:780;i:230;i:781;i:230;i:782;i:230;i:783;i:230;i:784;i:230;i:785;i:230;i:786;i:230;i:787;i:230;i:788;i:230;i:829;i:230;i:830;i:230;i:831;i:230;i:832;i:230;i:833;i:230;i:834;i:230;i:835;i:230;i:836;i:230;i:838;i:230;i:842;i:230;i:843;i:230;i:844;i:230;i:848;i:230;i:849;i:230;i:850;i:230;i:855;i:230;i:867;i:230;i:868;i:230;i:869;i:230;i:870;i:230;i:871;i:230;i:872;i:230;i:873;i:230;i:874;i:230;i:875;i:230;i:876;i:230;i:877;i:230;i:878;i:230;i:879;i:230;i:1155;i:230;i:1156;i:230;i:1157;i:230;i:1158;i:230;i:1426;i:230;i:1427;i:230;i:1428;i:230;i:1429;i:230;i:1431;i:230;i:1432;i:230;i:1433;i:230;i:1436;i:230;i:1437;i:230;i:1438;i:230;i:1439;i:230;i:1440;i:230;i:1441;i:230;i:1448;i:230;i:1449;i:230;i:1451;i:230;i:1452;i:230;i:1455;i:230;i:1476;i:230;i:1552;i:230;i:1553;i:230;i:1554;i:230;i:1555;i:230;i:1556;i:230;i:1557;i:230;i:1619;i:230;i:1620;i:230;i:1623;i:230;i:1624;i:230;i:1750;i:230;i:1751;i:230;i:1752;i:230;i:1753;i:230;i:1754;i:230;i:1755;i:230;i:1756;i:230;i:1759;i:230;i:1760;i:230;i:1761;i:230;i:1762;i:230;i:1764;i:230;i:1767;i:230;i:1768;i:230;i:1771;i:230;i:1772;i:230;i:1840;i:230;i:1842;i:230;i:1843;i:230;i:1845;i:230;i:1846;i:230;i:1850;i:230;i:1853;i:230;i:1855;i:230;i:1856;i:230;i:1857;i:230;i:1859;i:230;i:1861;i:230;i:1863;i:230;i:1865;i:230;i:1866;i:230;i:2385;i:230;i:2387;i:230;i:2388;i:230;i:3970;i:230;i:3971;i:230;i:3974;i:230;i:3975;i:230;i:5901;i:230;i:6458;i:230;i:8400;i:230;i:8401;i:230;i:8404;i:230;i:8405;i:230;i:8406;i:230;i:8407;i:230;i:8411;i:230;i:8412;i:230;i:8417;i:230;i:8423;i:230;i:8425;i:230;i:65056;i:230;i:65057;i:230;i:65058;i:230;i:65059;i:230;i:119173;i:230;i:119174;i:230;i:119175;i:230;i:119177;i:230;i:119176;i:230;i:119210;i:230;i:119211;i:230;i:119212;i:230;i:119213;i:230;i:789;i:232;i:794;i:232;i:12332;i:232;i:863;i:233;i:866;i:233;i:861;i:234;i:862;i:234;i:864;i:234;i:865;i:234;i:837;i:240;}}
\ No newline at end of file
diff --git a/library/simplepie/simplepie.inc b/library/simplepie/simplepie.inc
deleted file mode 100644
index 96ad06678e..0000000000
--- a/library/simplepie/simplepie.inc
+++ /dev/null
@@ -1,15150 +0,0 @@
-<?php
-/**
- * SimplePie
- *
- * A PHP-Based RSS and Atom Feed Framework.
- * Takes the hard work out of managing a complete RSS/Atom solution.
- *
- * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification, are
- * permitted provided that the following conditions are met:
- *
- * 	* Redistributions of source code must retain the above copyright notice, this list of
- * 	  conditions and the following disclaimer.
- *
- * 	* Redistributions in binary form must reproduce the above copyright notice, this list
- * 	  of conditions and the following disclaimer in the documentation and/or other materials
- * 	  provided with the distribution.
- *
- * 	* Neither the name of the SimplePie Team nor the names of its contributors may be used
- * 	  to endorse or promote products derived from this software without specific prior
- * 	  written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
- * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * @package SimplePie
- * @version 1.2.1-dev
- * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
- * @author Ryan Parman
- * @author Geoffrey Sneddon
- * @link http://simplepie.org/ SimplePie
- * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
- * @license http://www.opensource.org/licenses/bsd-license.php BSD License
- * @todo phpDoc comments
- */
-
-/**
- * SimplePie Name
- */
-define('SIMPLEPIE_NAME', 'SimplePie');
-
-/**
- * SimplePie Version
- */
-define('SIMPLEPIE_VERSION', '1.2.1-dev');
-
-/**
- * SimplePie Build
- * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::parse_date() only every load of simplepie.inc)
- */
-define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) ? SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) : filemtime(__FILE__)));
-
-/**
- * SimplePie Website URL
- */
-define('SIMPLEPIE_URL', 'http://simplepie.org');
-
-/**
- * SimplePie Useragent
- * @see SimplePie::set_useragent()
- */
-define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
-
-/**
- * SimplePie Linkback
- */
-define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
-
-/**
- * No Autodiscovery
- * @see SimplePie::set_autodiscovery_level()
- */
-define('SIMPLEPIE_LOCATOR_NONE', 0);
-
-/**
- * Feed Link Element Autodiscovery
- * @see SimplePie::set_autodiscovery_level()
- */
-define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
-
-/**
- * Local Feed Extension Autodiscovery
- * @see SimplePie::set_autodiscovery_level()
- */
-define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
-
-/**
- * Local Feed Body Autodiscovery
- * @see SimplePie::set_autodiscovery_level()
- */
-define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
-
-/**
- * Remote Feed Extension Autodiscovery
- * @see SimplePie::set_autodiscovery_level()
- */
-define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
-
-/**
- * Remote Feed Body Autodiscovery
- * @see SimplePie::set_autodiscovery_level()
- */
-define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
-
-/**
- * All Feed Autodiscovery
- * @see SimplePie::set_autodiscovery_level()
- */
-define('SIMPLEPIE_LOCATOR_ALL', 31);
-
-/**
- * No known feed type
- */
-define('SIMPLEPIE_TYPE_NONE', 0);
-
-/**
- * RSS 0.90
- */
-define('SIMPLEPIE_TYPE_RSS_090', 1);
-
-/**
- * RSS 0.91 (Netscape)
- */
-define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
-
-/**
- * RSS 0.91 (Userland)
- */
-define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
-
-/**
- * RSS 0.91 (both Netscape and Userland)
- */
-define('SIMPLEPIE_TYPE_RSS_091', 6);
-
-/**
- * RSS 0.92
- */
-define('SIMPLEPIE_TYPE_RSS_092', 8);
-
-/**
- * RSS 0.93
- */
-define('SIMPLEPIE_TYPE_RSS_093', 16);
-
-/**
- * RSS 0.94
- */
-define('SIMPLEPIE_TYPE_RSS_094', 32);
-
-/**
- * RSS 1.0
- */
-define('SIMPLEPIE_TYPE_RSS_10', 64);
-
-/**
- * RSS 2.0
- */
-define('SIMPLEPIE_TYPE_RSS_20', 128);
-
-/**
- * RDF-based RSS
- */
-define('SIMPLEPIE_TYPE_RSS_RDF', 65);
-
-/**
- * Non-RDF-based RSS (truly intended as syndication format)
- */
-define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
-
-/**
- * All RSS
- */
-define('SIMPLEPIE_TYPE_RSS_ALL', 255);
-
-/**
- * Atom 0.3
- */
-define('SIMPLEPIE_TYPE_ATOM_03', 256);
-
-/**
- * Atom 1.0
- */
-define('SIMPLEPIE_TYPE_ATOM_10', 512);
-
-/**
- * All Atom
- */
-define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
-
-/**
- * All feed types
- */
-define('SIMPLEPIE_TYPE_ALL', 1023);
-
-/**
- * No construct
- */
-define('SIMPLEPIE_CONSTRUCT_NONE', 0);
-
-/**
- * Text construct
- */
-define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
-
-/**
- * HTML construct
- */
-define('SIMPLEPIE_CONSTRUCT_HTML', 2);
-
-/**
- * XHTML construct
- */
-define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
-
-/**
- * base64-encoded construct
- */
-define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
-
-/**
- * IRI construct
- */
-define('SIMPLEPIE_CONSTRUCT_IRI', 16);
-
-/**
- * A construct that might be HTML
- */
-define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
-
-/**
- * All constructs
- */
-define('SIMPLEPIE_CONSTRUCT_ALL', 63);
-
-/**
- * Don't change case
- */
-define('SIMPLEPIE_SAME_CASE', 1);
-
-/**
- * Change to lowercase
- */
-define('SIMPLEPIE_LOWERCASE', 2);
-
-/**
- * Change to uppercase
- */
-define('SIMPLEPIE_UPPERCASE', 4);
-
-/**
- * PCRE for HTML attributes
- */
-define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
-
-/**
- * PCRE for XML attributes
- */
-define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
-
-/**
- * XML Namespace
- */
-define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
-
-/**
- * Atom 1.0 Namespace
- */
-define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
-
-/**
- * Atom 0.3 Namespace
- */
-define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
-
-/**
- * RDF Namespace
- */
-define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
-
-/**
- * RSS 0.90 Namespace
- */
-define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
-
-/**
- * RSS 1.0 Namespace
- */
-define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
-
-/**
- * RSS 1.0 Content Module Namespace
- */
-define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
-
-/**
- * RSS 2.0 Namespace
- * (Stupid, I know, but I'm certain it will confuse people less with support.)
- */
-define('SIMPLEPIE_NAMESPACE_RSS_20', '');
-
-/**
- * DC 1.0 Namespace
- */
-define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
-
-/**
- * DC 1.1 Namespace
- */
-define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
-
-/**
- * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
- */
-define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
-
-/**
- * GeoRSS Namespace
- */
-define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
-
-/**
- * Media RSS Namespace
- */
-define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
-
-/**
- * Wrong Media RSS Namespace
- */
-define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
-
-/**
- * iTunes RSS Namespace
- */
-define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
-
-/**
- * XHTML Namespace
- */
-define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
-
-/**
- * IANA Link Relations Registry
- */
-define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
-
-/**
- * Whether we're running on PHP5
- */
-define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
-
-/**
- * No file source
- */
-define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
-
-/**
- * Remote file source
- */
-define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
-
-/**
- * Local file source
- */
-define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
-
-/**
- * fsockopen() file source
- */
-define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
-
-/**
- * cURL file source
- */
-define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
-
-/**
- * file_get_contents() file source
- */
-define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
-
-/**
- * SimplePie
- *
- * @package SimplePie
- */
-class SimplePie
-{
-	/**
-	 * @var array Raw data
-	 * @access private
-	 */
-	var $data = array();
-
-	/**
-	 * @var mixed Error string
-	 * @access private
-	 */
-	var $error;
-
-	/**
-	 * @var object Instance of SimplePie_Sanitize (or other class)
-	 * @see SimplePie::set_sanitize_class()
-	 * @access private
-	 */
-	var $sanitize;
-
-	/**
-	 * @var string SimplePie Useragent
-	 * @see SimplePie::set_useragent()
-	 * @access private
-	 */
-	var $useragent = SIMPLEPIE_USERAGENT;
-
-	/**
-	 * @var string Feed URL
-	 * @see SimplePie::set_feed_url()
-	 * @access private
-	 */
-	var $feed_url;
-
-	/**
-	 * @var object Instance of SimplePie_File to use as a feed
-	 * @see SimplePie::set_file()
-	 * @access private
-	 */
-	var $file;
-
-	/**
-	 * @var string Raw feed data
-	 * @see SimplePie::set_raw_data()
-	 * @access private
-	 */
-	var $raw_data;
-
-	/**
-	 * @var int Timeout for fetching remote files
-	 * @see SimplePie::set_timeout()
-	 * @access private
-	 */
-	var $timeout = 10;
-
-	/**
-	 * @var bool Forces fsockopen() to be used for remote files instead
-	 * of cURL, even if a new enough version is installed
-	 * @see SimplePie::force_fsockopen()
-	 * @access private
-	 */
-	var $force_fsockopen = false;
-
-	/**
-	 * @var bool Force the given data/URL to be treated as a feed no matter what
-	 * it appears like
-	 * @see SimplePie::force_feed()
-	 * @access private
-	 */
-	var $force_feed = false;
-
-	/**
-	 * @var bool Enable/Disable XML dump
-	 * @see SimplePie::enable_xml_dump()
-	 * @access private
-	 */
-	var $xml_dump = false;
-
-	/**
-	 * @var bool Enable/Disable Caching
-	 * @see SimplePie::enable_cache()
-	 * @access private
-	 */
-	var $cache = true;
-
-	/**
-	 * @var int Cache duration (in seconds)
-	 * @see SimplePie::set_cache_duration()
-	 * @access private
-	 */
-	var $cache_duration = 3600;
-
-	/**
-	 * @var int Auto-discovery cache duration (in seconds)
-	 * @see SimplePie::set_autodiscovery_cache_duration()
-	 * @access private
-	 */
-	var $autodiscovery_cache_duration = 604800; // 7 Days.
-
-	/**
-	 * @var string Cache location (relative to executing script)
-	 * @see SimplePie::set_cache_location()
-	 * @access private
-	 */
-	var $cache_location = './cache';
-
-	/**
-	 * @var string Function that creates the cache filename
-	 * @see SimplePie::set_cache_name_function()
-	 * @access private
-	 */
-	var $cache_name_function = 'md5';
-
-	/**
-	 * @var bool Reorder feed by date descending
-	 * @see SimplePie::enable_order_by_date()
-	 * @access private
-	 */
-	var $order_by_date = true;
-
-	/**
-	 * @var mixed Force input encoding to be set to the follow value
-	 * (false, or anything type-cast to false, disables this feature)
-	 * @see SimplePie::set_input_encoding()
-	 * @access private
-	 */
-	var $input_encoding = false;
-
-	/**
-	 * @var int Feed Autodiscovery Level
-	 * @see SimplePie::set_autodiscovery_level()
-	 * @access private
-	 */
-	var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
-
-	/**
-	 * @var string Class used for caching feeds
-	 * @see SimplePie::set_cache_class()
-	 * @access private
-	 */
-	var $cache_class = 'SimplePie_Cache';
-
-	/**
-	 * @var string Class used for locating feeds
-	 * @see SimplePie::set_locator_class()
-	 * @access private
-	 */
-	var $locator_class = 'SimplePie_Locator';
-
-	/**
-	 * @var string Class used for parsing feeds
-	 * @see SimplePie::set_parser_class()
-	 * @access private
-	 */
-	var $parser_class = 'SimplePie_Parser';
-
-	/**
-	 * @var string Class used for fetching feeds
-	 * @see SimplePie::set_file_class()
-	 * @access private
-	 */
-	var $file_class = 'SimplePie_File';
-
-	/**
-	 * @var string Class used for items
-	 * @see SimplePie::set_item_class()
-	 * @access private
-	 */
-	var $item_class = 'SimplePie_Item';
-
-	/**
-	 * @var string Class used for authors
-	 * @see SimplePie::set_author_class()
-	 * @access private
-	 */
-	var $author_class = 'SimplePie_Author';
-
-	/**
-	 * @var string Class used for categories
-	 * @see SimplePie::set_category_class()
-	 * @access private
-	 */
-	var $category_class = 'SimplePie_Category';
-
-	/**
-	 * @var string Class used for enclosures
-	 * @see SimplePie::set_enclosures_class()
-	 * @access private
-	 */
-	var $enclosure_class = 'SimplePie_Enclosure';
-
-	/**
-	 * @var string Class used for Media RSS <media:text> captions
-	 * @see SimplePie::set_caption_class()
-	 * @access private
-	 */
-	var $caption_class = 'SimplePie_Caption';
-
-	/**
-	 * @var string Class used for Media RSS <media:copyright>
-	 * @see SimplePie::set_copyright_class()
-	 * @access private
-	 */
-	var $copyright_class = 'SimplePie_Copyright';
-
-	/**
-	 * @var string Class used for Media RSS <media:credit>
-	 * @see SimplePie::set_credit_class()
-	 * @access private
-	 */
-	var $credit_class = 'SimplePie_Credit';
-
-	/**
-	 * @var string Class used for Media RSS <media:rating>
-	 * @see SimplePie::set_rating_class()
-	 * @access private
-	 */
-	var $rating_class = 'SimplePie_Rating';
-
-	/**
-	 * @var string Class used for Media RSS <media:restriction>
-	 * @see SimplePie::set_restriction_class()
-	 * @access private
-	 */
-	var $restriction_class = 'SimplePie_Restriction';
-
-	/**
-	 * @var string Class used for content-type sniffing
-	 * @see SimplePie::set_content_type_sniffer_class()
-	 * @access private
-	 */
-	var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
-
-	/**
-	 * @var string Class used for item sources.
-	 * @see SimplePie::set_source_class()
-	 * @access private
-	 */
-	var $source_class = 'SimplePie_Source';
-
-	/**
-	 * @var mixed Set javascript query string parameter (false, or
-	 * anything type-cast to false, disables this feature)
-	 * @see SimplePie::set_javascript()
-	 * @access private
-	 */
-	var $javascript = 'js';
-
-	/**
-	 * @var int Maximum number of feeds to check with autodiscovery
-	 * @see SimplePie::set_max_checked_feeds()
-	 * @access private
-	 */
-	var $max_checked_feeds = 10;
-
-	/**
-	 * @var array All the feeds found during the autodiscovery process
-	 * @see SimplePie::get_all_discovered_feeds()
-	 * @access private
-	 */
-	var $all_discovered_feeds = array();
-
-	/**
-	 * @var string Web-accessible path to the handler_favicon.php file.
-	 * @see SimplePie::set_favicon_handler()
-	 * @access private
-	 */
-	var $favicon_handler = '';
-
-	/**
-	 * @var string Web-accessible path to the handler_image.php file.
-	 * @see SimplePie::set_image_handler()
-	 * @access private
-	 */
-	var $image_handler = '';
-
-	/**
-	 * @var array Stores the URLs when multiple feeds are being initialized.
-	 * @see SimplePie::set_feed_url()
-	 * @access private
-	 */
-	var $multifeed_url = array();
-
-	/**
-	 * @var array Stores SimplePie objects when multiple feeds initialized.
-	 * @access private
-	 */
-	var $multifeed_objects = array();
-
-	/**
-	 * @var array Stores the get_object_vars() array for use with multifeeds.
-	 * @see SimplePie::set_feed_url()
-	 * @access private
-	 */
-	var $config_settings = null;
-
-	/**
-	 * @var integer Stores the number of items to return per-feed with multifeeds.
-	 * @see SimplePie::set_item_limit()
-	 * @access private
-	 */
-	var $item_limit = 0;
-
-	/**
-	 * @var array Stores the default attributes to be stripped by strip_attributes().
-	 * @see SimplePie::strip_attributes()
-	 * @access private
-	 */
-	var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
-
-	/**
-	 * @var array Stores the default tags to be stripped by strip_htmltags().
-	 * @see SimplePie::strip_htmltags()
-	 * @access private
-	 */
-	var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
-
-	/**
-	 * The SimplePie class contains feed level data and options
-	 *
-	 * There are two ways that you can create a new SimplePie object. The first
-	 * is by passing a feed URL as a parameter to the SimplePie constructor
-	 * (as well as optionally setting the cache location and cache expiry). This
-	 * will initialise the whole feed with all of the default settings, and you
-	 * can begin accessing methods and properties immediately.
-	 *
-	 * The second way is to create the SimplePie object with no parameters
-	 * at all. This will enable you to set configuration options. After setting
-	 * them, you must initialise the feed using $feed->init(). At that point the
-	 * object's methods and properties will be available to you. This format is
-	 * what is used throughout this documentation.
-	 *
-	 * @access public
-	 * @since 1.0 Preview Release
-	 * @param string $feed_url This is the URL you want to parse.
-	 * @param string $cache_location This is where you want the cache to be stored.
-	 * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
-	 */
-	function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
-	{
-		// Other objects, instances created here so we can set options on them
-		$this->sanitize = new SimplePie_Sanitize;
-
-		// Set options if they're passed to the constructor
-		if ($cache_location !== null)
-		{
-			$this->set_cache_location($cache_location);
-		}
-
-		if ($cache_duration !== null)
-		{
-			$this->set_cache_duration($cache_duration);
-		}
-
-		// Only init the script if we're passed a feed URL
-		if ($feed_url !== null)
-		{
-			$this->set_feed_url($feed_url);
-			$this->init();
-		}
-	}
-
-	/**
-	 * Used for converting object to a string
-	 */
-	function __toString()
-	{
-		return md5(serialize($this->data));
-	}
-
-	/**
-	 * Remove items that link back to this before destroying this object
-	 */
-	function __destruct()
-	{
-		if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
-		{
-			if (!empty($this->data['items']))
-			{
-				foreach ($this->data['items'] as $item)
-				{
-					$item->__destruct();
-				}
-				unset($item, $this->data['items']);
-			}
-			if (!empty($this->data['ordered_items']))
-			{
-				foreach ($this->data['ordered_items'] as $item)
-				{
-					$item->__destruct();
-				}
-				unset($item, $this->data['ordered_items']);
-			}
-		}
-	}
-
-	/**
-	 * Force the given data/URL to be treated as a feed no matter what it
-	 * appears like
-	 *
-	 * @access public
-	 * @since 1.1
-	 * @param bool $enable Force the given data/URL to be treated as a feed
-	 */
-	function force_feed($enable = false)
-	{
-		$this->force_feed = (bool) $enable;
-	}
-
-	/**
-	 * This is the URL of the feed you want to parse.
-	 *
-	 * This allows you to enter the URL of the feed you want to parse, or the
-	 * website you want to try to use auto-discovery on. This takes priority
-	 * over any set raw data.
-	 *
-	 * You can set multiple feeds to mash together by passing an array instead
-	 * of a string for the $url. Remember that with each additional feed comes
-	 * additional processing and resources.
-	 *
-	 * @access public
-	 * @since 1.0 Preview Release
-	 * @param mixed $url This is the URL (or array of URLs) that you want to parse.
-	 * @see SimplePie::set_raw_data()
-	 */
-	function set_feed_url($url)
-	{
-		if (is_array($url))
-		{
-			$this->multifeed_url = array();
-			foreach ($url as $value)
-			{
-				$this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
-			}
-		}
-		else
-		{
-			$this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
-		}
-	}
-
-	/**
-	 * Provides an instance of SimplePie_File to use as a feed
-	 *
-	 * @access public
-	 * @param object &$file Instance of SimplePie_File (or subclass)
-	 * @return bool True on success, false on failure
-	 */
-	function set_file(&$file)
-	{
-		if (is_a($file, 'SimplePie_File'))
-		{
-			$this->feed_url = $file->url;
-			$this->file =& $file;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to use a string of RSS/Atom data instead of a remote feed.
-	 *
-	 * If you have a feed available as a string in PHP, you can tell SimplePie
-	 * to parse that data string instead of a remote feed. Any set feed URL
-	 * takes precedence.
-	 *
-	 * @access public
-	 * @since 1.0 Beta 3
-	 * @param string $data RSS or Atom data as a string.
-	 * @see SimplePie::set_feed_url()
-	 */
-	function set_raw_data($data)
-	{
-		$this->raw_data = $data;
-	}
-
-	/**
-	 * Allows you to override the default timeout for fetching remote feeds.
-	 *
-	 * This allows you to change the maximum time the feed's server to respond
-	 * and send the feed back.
-	 *
-	 * @access public
-	 * @since 1.0 Beta 3
-	 * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
-	 */
-	function set_timeout($timeout = 10)
-	{
-		$this->timeout = (int) $timeout;
-	}
-
-	/**
-	 * Forces SimplePie to use fsockopen() instead of the preferred cURL
-	 * functions.
-	 *
-	 * @access public
-	 * @since 1.0 Beta 3
-	 * @param bool $enable Force fsockopen() to be used
-	 */
-	function force_fsockopen($enable = false)
-	{
-		$this->force_fsockopen = (bool) $enable;
-	}
-
-	/**
-	 * Outputs the raw XML content of the feed, after it has gone through
-	 * SimplePie's filters.
-	 *
-	 * Used only for debugging, this function will output the XML content as
-	 * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
-	 * before trying to parse it. Many parts of the feed are re-written in
-	 * memory, and in the end, you have a parsable feed. XML dump shows you the
-	 * actual XML that SimplePie tries to parse, which may or may not be very
-	 * different from the original feed.
-	 *
-	 * @access public
-	 * @since 1.0 Preview Release
-	 * @param bool $enable Enable XML dump
-	 */
-	function enable_xml_dump($enable = false)
-	{
-		$this->xml_dump = (bool) $enable;
-	}
-
-	/**
-	 * Enables/disables caching in SimplePie.
-	 *
-	 * This option allows you to disable caching all-together in SimplePie.
-	 * However, disabling the cache can lead to longer load times.
-	 *
-	 * @access public
-	 * @since 1.0 Preview Release
-	 * @param bool $enable Enable caching
-	 */
-	function enable_cache($enable = true)
-	{
-		$this->cache = (bool) $enable;
-	}
-
-	/**
-	 * Set the length of time (in seconds) that the contents of a feed
-	 * will be cached.
-	 *
-	 * @access public
-	 * @param int $seconds The feed content cache duration.
-	 */
-	function set_cache_duration($seconds = 3600)
-	{
-		$this->cache_duration = (int) $seconds;
-	}
-
-	/**
-	 * Set the length of time (in seconds) that the autodiscovered feed
-	 * URL will be cached.
-	 *
-	 * @access public
-	 * @param int $seconds The autodiscovered feed URL cache duration.
-	 */
-	function set_autodiscovery_cache_duration($seconds = 604800)
-	{
-		$this->autodiscovery_cache_duration = (int) $seconds;
-	}
-
-	/**
-	 * Set the file system location where the cached files should be stored.
-	 *
-	 * @access public
-	 * @param string $location The file system location.
-	 */
-	function set_cache_location($location = './cache')
-	{
-		$this->cache_location = (string) $location;
-	}
-
-	/**
-	 * Determines whether feed items should be sorted into reverse chronological order.
-	 *
-	 * @access public
-	 * @param bool $enable Sort as reverse chronological order.
-	 */
-	function enable_order_by_date($enable = true)
-	{
-		$this->order_by_date = (bool) $enable;
-	}
-
-	/**
-	 * Allows you to override the character encoding reported by the feed.
-	 *
-	 * @access public
-	 * @param string $encoding Character encoding.
-	 */
-	function set_input_encoding($encoding = false)
-	{
-		if ($encoding)
-		{
-			$this->input_encoding = (string) $encoding;
-		}
-		else
-		{
-			$this->input_encoding = false;
-		}
-	}
-
-	/**
-	 * Set how much feed autodiscovery to do
-	 *
-	 * @access public
-	 * @see SIMPLEPIE_LOCATOR_NONE
-	 * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
-	 * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
-	 * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
-	 * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
-	 * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
-	 * @see SIMPLEPIE_LOCATOR_ALL
-	 * @param int $level Feed Autodiscovery Level (level can be a
-	 * combination of the above constants, see bitwise OR operator)
-	 */
-	function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
-	{
-		$this->autodiscovery = (int) $level;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for caching.
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_cache_class($class = 'SimplePie_Cache')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
-		{
-			$this->cache_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for auto-discovery.
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_locator_class($class = 'SimplePie_Locator')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
-		{
-			$this->locator_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for XML parsing.
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_parser_class($class = 'SimplePie_Parser')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
-		{
-			$this->parser_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for remote file fetching.
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_file_class($class = 'SimplePie_File')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
-		{
-			$this->file_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for data sanitization.
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_sanitize_class($class = 'SimplePie_Sanitize')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
-		{
-			$this->sanitize = new $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for handling feed items.
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_item_class($class = 'SimplePie_Item')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
-		{
-			$this->item_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for handling author data.
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_author_class($class = 'SimplePie_Author')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
-		{
-			$this->author_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for handling category data.
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_category_class($class = 'SimplePie_Category')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
-		{
-			$this->category_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for feed enclosures.
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_enclosure_class($class = 'SimplePie_Enclosure')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
-		{
-			$this->enclosure_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for <media:text> captions
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_caption_class($class = 'SimplePie_Caption')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
-		{
-			$this->caption_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for <media:copyright>
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_copyright_class($class = 'SimplePie_Copyright')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
-		{
-			$this->copyright_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for <media:credit>
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_credit_class($class = 'SimplePie_Credit')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
-		{
-			$this->credit_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for <media:rating>
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_rating_class($class = 'SimplePie_Rating')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
-		{
-			$this->rating_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for <media:restriction>
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_restriction_class($class = 'SimplePie_Restriction')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
-		{
-			$this->restriction_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses for content-type sniffing.
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
-		{
-			$this->content_type_sniffer_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to change which class SimplePie uses item sources.
-	 * Useful when you are overloading or extending SimplePie's default classes.
-	 *
-	 * @access public
-	 * @param string $class Name of custom class.
-	 * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
-	 * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
-	 */
-	function set_source_class($class = 'SimplePie_Source')
-	{
-		if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
-		{
-			$this->source_class = $class;
-			return true;
-		}
-		return false;
-	}
-
-	/**
-	 * Allows you to override the default user agent string.
-	 *
-	 * @access public
-	 * @param string $ua New user agent string.
-	 */
-	function set_useragent($ua = SIMPLEPIE_USERAGENT)
-	{
-		$this->useragent = (string) $ua;
-	}
-
-	/**
-	 * Set callback function to create cache filename with
-	 *
-	 * @access public
-	 * @param mixed $function Callback function
-	 */
-	function set_cache_name_function($function = 'md5')
-	{
-		if (is_callable($function))
-		{
-			$this->cache_name_function = $function;
-		}
-	}
-
-	/**
-	 * Set javascript query string parameter
-	 *
-	 * @access public
-	 * @param mixed $get Javascript query string parameter
-	 */
-	function set_javascript($get = 'js')
-	{
-		if ($get)
-		{
-			$this->javascript = (string) $get;
-		}
-		else
-		{
-			$this->javascript = false;
-		}
-	}
-
-	/**
-	 * Set options to make SP as fast as possible.  Forgoes a
-	 * substantial amount of data sanitization in favor of speed.
-	 *
-	 * @access public
-	 * @param bool $set Whether to set them or not
-	 */
-	function set_stupidly_fast($set = false)
-	{
-		if ($set)
-		{
-			$this->enable_order_by_date(false);
-			$this->remove_div(false);
-			$this->strip_comments(false);
-			$this->strip_htmltags(false);
-			$this->strip_attributes(false);
-			$this->set_image_handler(false);
-		}
-	}
-
-	/**
-	 * Set maximum number of feeds to check with autodiscovery
-	 *
-	 * @access public
-	 * @param int $max Maximum number of feeds to check
-	 */
-	function set_max_checked_feeds($max = 10)
-	{
-		$this->max_checked_feeds = (int) $max;
-	}
-
-	function remove_div($enable = true)
-	{
-		$this->sanitize->remove_div($enable);
-	}
-
-	function strip_htmltags($tags = '', $encode = null)
-	{
-		if ($tags === '')
-		{
-			$tags = $this->strip_htmltags;
-		}
-		$this->sanitize->strip_htmltags($tags);
-		if ($encode !== null)
-		{
-			$this->sanitize->encode_instead_of_strip($tags);
-		}
-	}
-
-	function encode_instead_of_strip($enable = true)
-	{
-		$this->sanitize->encode_instead_of_strip($enable);
-	}
-
-	function strip_attributes($attribs = '')
-	{
-		if ($attribs === '')
-		{
-			$attribs = $this->strip_attributes;
-		}
-		$this->sanitize->strip_attributes($attribs);
-	}
-
-	function set_output_encoding($encoding = 'UTF-8')
-	{
-		$this->sanitize->set_output_encoding($encoding);
-	}
-
-	function strip_comments($strip = false)
-	{
-		$this->sanitize->strip_comments($strip);
-	}
-
-	/**
-	 * Set element/attribute key/value pairs of HTML attributes
-	 * containing URLs that need to be resolved relative to the feed
-	 *
-	 * @access public
-	 * @since 1.0
-	 * @param array $element_attribute Element/attribute key/value pairs
-	 */
-	function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
-	{
-		$this->sanitize->set_url_replacements($element_attribute);
-	}
-
-	/**
-	 * Set the handler to enable the display of cached favicons.
-	 *
-	 * @access public
-	 * @param str $page Web-accessible path to the handler_favicon.php file.
-	 * @param str $qs The query string that the value should be passed to.
-	 */
-	function set_favicon_handler($page = false, $qs = 'i')
-	{
-		if ($page !== false)
-		{
-			$this->favicon_handler = $page . '?' . $qs . '=';
-		}
-		else
-		{
-			$this->favicon_handler = '';
-		}
-	}
-
-	/**
-	 * Set the handler to enable the display of cached images.
-	 *
-	 * @access public
-	 * @param str $page Web-accessible path to the handler_image.php file.
-	 * @param str $qs The query string that the value should be passed to.
-	 */
-	function set_image_handler($page = false, $qs = 'i')
-	{
-		if ($page !== false)
-		{
-			$this->sanitize->set_image_handler($page . '?' . $qs . '=');
-		}
-		else
-		{
-			$this->image_handler = '';
-		}
-	}
-
-	/**
-	 * Set the limit for items returned per-feed with multifeeds.
-	 *
-	 * @access public
-	 * @param integer $limit The maximum number of items to return.
-	 */
-	function set_item_limit($limit = 0)
-	{
-		$this->item_limit = (int) $limit;
-	}
-
-	function init()
-	{
-		// Check absolute bare minimum requirements.
-		if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
-		{
-			return false;
-		}
-		// Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
-		elseif (!extension_loaded('xmlreader'))
-		{
-			static $xml_is_sane = null;
-			if ($xml_is_sane === null)
-			{
-				$parser_check = xml_parser_create();
-				xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
-				xml_parser_free($parser_check);
-				$xml_is_sane = isset($values[0]['value']);
-			}
-			if (!$xml_is_sane)
-			{
-				return false;
-			}
-		}
-
-		if (isset($_GET[$this->javascript]))
-		{
-			SimplePie_Misc::output_javascript();
-			exit;
-		}
-
-		// Pass whatever was set with config options over to the sanitizer.
-		$this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
-		$this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
-
-		if ($this->feed_url !== null || $this->raw_data !== null)
-		{
-			$this->data = array();
-			$this->multifeed_objects = array();
-			$cache = false;
-
-			if ($this->feed_url !== null)
-			{
-				$parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
-				// Decide whether to enable caching
-				if ($this->cache && $parsed_feed_url['scheme'] !== '')
-				{
-					$cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
-				}
-				// If it's enabled and we don't want an XML dump, use the cache
-				if ($cache && !$this->xml_dump)
-				{
-					// Load the Cache
-					$this->data = $cache->load();
-					if (!empty($this->data))
-					{
-						// If the cache is for an outdated build of SimplePie
-						if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
-						{
-							$cache->unlink();
-							$this->data = array();
-						}
-						// If we've hit a collision just rerun it with caching disabled
-						elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
-						{
-							$cache = false;
-							$this->data = array();
-						}
-						// If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
-						elseif (isset($this->data['feed_url']))
-						{
-							// If the autodiscovery cache is still valid use it.
-							if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
-							{
-								// Do not need to do feed autodiscovery yet.
-								if ($this->data['feed_url'] === $this->data['url'])
-								{
-									$cache->unlink();
-									$this->data = array();
-								}
-								else
-								{
-									$this->set_feed_url($this->data['feed_url']);
-									return $this->init();
-								}
-							}
-						}
-						// Check if the cache has been updated
-						elseif ($cache->mtime() + $this->cache_duration < time())
-						{
-							// If we have last-modified and/or etag set
-							if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
-							{
-								$headers = array();
-								if (isset($this->data['headers']['last-modified']))
-								{
-									$headers['if-modified-since'] = $this->data['headers']['last-modified'];
-								}
-								if (isset($this->data['headers']['etag']))
-								{
-									$headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
-								}
-								$file = new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
-								if ($file->success)
-								{
-									if ($file->status_code === 304)
-									{
-										$cache->touch();
-										return true;
-									}
-									else
-									{
-										$headers = $file->headers;
-									}
-								}
-								else
-								{
-									unset($file);
-								}
-							}
-						}
-						// If the cache is still valid, just return true
-						else
-						{
-							return true;
-						}
-					}
-					// If the cache is empty, delete it
-					else
-					{
-						$cache->unlink();
-						$this->data = array();
-					}
-				}
-				// If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
-				if (!isset($file))
-				{
-					if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
-					{
-						$file =& $this->file;
-					}
-					else
-					{
-						$file = new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
-					}
-				}
-				// If the file connection has an error, set SimplePie::error to that and quit
-				if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
-				{
-					$this->error = $file->error;
-					if (!empty($this->data))
-					{
-						return true;
-					}
-					else
-					{
-						return false;
-					}
-				}
-
-				if (!$this->force_feed)
-				{
-					// Check if the supplied URL is a feed, if it isn't, look for it.
-					$locate = new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
-					if (!$locate->is_feed($file))
-					{
-						// We need to unset this so that if SimplePie::set_file() has been called that object is untouched
-						unset($file);
-						if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
-						{
-							if ($cache)
-							{
-								$this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
-								if (!$cache->save($this))
-								{
-									trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
-								}
-								$cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
-							}
-							$this->feed_url = $file->url;
-						}
-						else
-						{
-							$this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
-							SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
-							return false;
-						}
-					}
-					$locate = null;
-				}
-
-				$headers = $file->headers;
-				$data = $file->body;
-				$sniffer = new $this->content_type_sniffer_class($file);
-				$sniffed = $sniffer->get_type();
-			}
-			else
-			{
-				$data = $this->raw_data;
-			}
-
-			// Set up array of possible encodings
-			$encodings = array();
-
-			// First check to see if input has been overridden.
-			if ($this->input_encoding !== false)
-			{
-				$encodings[] = $this->input_encoding;
-			}
-
-			$application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
-			$text_types = array('text/xml', 'text/xml-external-parsed-entity');
-
-			// RFC 3023 (only applies to sniffed content)
-			if (isset($sniffed))
-			{
-				if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
-				{
-					if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
-					{
-						$encodings[] = strtoupper($charset[1]);
-					}
-					$encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
-					$encodings[] = 'UTF-8';
-				}
-				elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
-				{
-					if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
-					{
-						$encodings[] = $charset[1];
-					}
-					$encodings[] = 'US-ASCII';
-				}
-				// Text MIME-type default
-				elseif (substr($sniffed, 0, 5) === 'text/')
-				{
-					$encodings[] = 'US-ASCII';
-				}
-			}
-
-			// Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
-			$encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
-			$encodings[] = 'UTF-8';
-			$encodings[] = 'ISO-8859-1';
-
-			// There's no point in trying an encoding twice
-			$encodings = array_unique($encodings);
-
-			// If we want the XML, just output that with the most likely encoding and quit
-			if ($this->xml_dump)
-			{
-				header('Content-type: text/xml; charset=' . $encodings[0]);
-				echo $data;
-				exit;
-			}
-
-			// Loop through each possible encoding, till we return something, or run out of possibilities
-			foreach ($encodings as $encoding)
-			{
-				// Change the encoding to UTF-8 (as we always use UTF-8 internally)
-				if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
-				{
-					// Create new parser
-					$parser = new $this->parser_class();
-
-					// If it's parsed fine
-					if ($parser->parse($utf8_data, 'UTF-8'))
-					{
-						$this->data = $parser->get_data();
-						if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
-						{
-							if (isset($headers))
-							{
-								$this->data['headers'] = $headers;
-							}
-							$this->data['build'] = SIMPLEPIE_BUILD;
-
-							// Cache the file if caching is enabled
-							if ($cache && !$cache->save($this))
-							{
-								trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
-							}
-							return true;
-						}
-						else
-						{
-							$this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
-							SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
-							return false;
-						}
-					}
-				}
-			}
-			if (isset($parser))
-			{
-				// We have an error, just set SimplePie_Misc::error to it and quit
-				$this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
-			}
-			else
-			{
-				$this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
-			}
-			SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
-			return false;
-		}
-		elseif (!empty($this->multifeed_url))
-		{
-			$i = 0;
-			$success = 0;
-			$this->multifeed_objects = array();
-			foreach ($this->multifeed_url as $url)
-			{
-				if (SIMPLEPIE_PHP5)
-				{
-					// This keyword needs to defy coding standards for PHP4 compatibility
-					$this->multifeed_objects[$i] = clone($this);
-				}
-				else
-				{
-					$this->multifeed_objects[$i] = $this;
-				}
-				$this->multifeed_objects[$i]->set_feed_url($url);
-				$success |= $this->multifeed_objects[$i]->init();
-				$i++;
-			}
-			return (bool) $success;
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	/**
-	 * Return the error message for the occured error
-	 *
-	 * @access public
-	 * @return string Error message
-	 */
-	function error()
-	{
-		return $this->error;
-	}
-
-	function get_encoding()
-	{
-		return $this->sanitize->output_encoding;
-	}
-
-	function handle_content_type($mime = 'text/html')
-	{
-		if (!headers_sent())
-		{
-			$header = "Content-type: $mime;";
-			if ($this->get_encoding())
-			{
-				$header .= ' charset=' . $this->get_encoding();
-			}
-			else
-			{
-				$header .= ' charset=UTF-8';
-			}
-			header($header);
-		}
-	}
-
-	function get_type()
-	{
-		if (!isset($this->data['type']))
-		{
-			$this->data['type'] = SIMPLEPIE_TYPE_ALL;
-			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
-			{
-				$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
-			}
-			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
-			{
-				$this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
-			}
-			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
-			{
-				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
-				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
-				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
-				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
-				{
-					$this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
-				}
-				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
-				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
-				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
-				|| isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
-				{
-					$this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
-				}
-			}
-			elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
-			{
-				$this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
-				if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
-				{
-					switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
-					{
-						case '0.91':
-							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
-							if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
-							{
-								switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
-								{
-									case '0':
-										$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
-										break;
-
-									case '24':
-										$this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
-										break;
-								}
-							}
-							break;
-
-						case '0.92':
-							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
-							break;
-
-						case '0.93':
-							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
-							break;
-
-						case '0.94':
-							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
-							break;
-
-						case '2.0':
-							$this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
-							break;
-					}
-				}
-			}
-			else
-			{
-				$this->data['type'] = SIMPLEPIE_TYPE_NONE;
-			}
-		}
-		return $this->data['type'];
-	}
-
-	/**
-	 * Returns the URL for the favicon of the feed's website.
-	 *
-	 * @todo Cache atom:icon
-	 * @access public
-	 * @since 1.0
-	 */
-	function get_favicon()
-	{
-		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
-		}
-		elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
-		{
-			$favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
-
-			if ($this->cache && $this->favicon_handler)
-			{
-				$favicon_filename = call_user_func($this->cache_name_function, $favicon);
-				$cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
-
-				if ($cache->load())
-				{
-					return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
-				}
-				else
-				{
-					$file = new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
-
-					if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
-					{
-						$sniffer = new $this->content_type_sniffer_class($file);
-						if (substr($sniffer->get_type(), 0, 6) === 'image/')
-						{
-							if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
-							{
-								return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
-							}
-							else
-							{
-								trigger_error("$cache->name is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
-								return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
-							}
-						}
-						// not an image
-						else
-						{
-							return false;
-						}
-					}
-				}
-			}
-			else
-			{
-				return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * @todo If we have a perm redirect we should return the new URL
-	 * @todo When we make the above change, let's support <itunes:new-feed-url> as well
-	 * @todo Also, |atom:link|@rel=self
-	 */
-	function subscribe_url()
-	{
-		if ($this->feed_url !== null)
-		{
-			return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function subscribe_feed()
-	{
-		if ($this->feed_url !== null)
-		{
-			return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function subscribe_outlook()
-	{
-		if ($this->feed_url !== null)
-		{
-			return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function subscribe_podcast()
-	{
-		if ($this->feed_url !== null)
-		{
-			return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function subscribe_itunes()
-	{
-		if ($this->feed_url !== null)
-		{
-			return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	/**
-	 * Creates the subscribe_* methods' return data
-	 *
-	 * @access private
-	 * @param string $feed_url String to prefix to the feed URL
-	 * @param string $site_url String to prefix to the site URL (and
-	 * suffix to the feed URL)
-	 * @return mixed URL if feed exists, false otherwise
-	 */
-	function subscribe_service($feed_url, $site_url = null)
-	{
-		if ($this->subscribe_url())
-		{
-			$return = $feed_url . rawurlencode($this->feed_url);
-			if ($site_url !== null && $this->get_link() !== null)
-			{
-				$return .= $site_url . rawurlencode($this->get_link());
-			}
-			return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function subscribe_aol()
-	{
-		return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
-	}
-
-	function subscribe_bloglines()
-	{
-		return $this->subscribe_service('http://www.bloglines.com/sub/');
-	}
-
-	function subscribe_eskobo()
-	{
-		return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
-	}
-
-	function subscribe_feedfeeds()
-	{
-		return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
-	}
-
-	function subscribe_feedster()
-	{
-		return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
-	}
-
-	function subscribe_google()
-	{
-		return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
-	}
-
-	function subscribe_gritwire()
-	{
-		return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
-	}
-
-	function subscribe_msn()
-	{
-		return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
-	}
-
-	function subscribe_netvibes()
-	{
-		return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
-	}
-
-	function subscribe_newsburst()
-	{
-		return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
-	}
-
-	function subscribe_newsgator()
-	{
-		return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
-	}
-
-	function subscribe_odeo()
-	{
-		return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
-	}
-
-	function subscribe_podnova()
-	{
-		return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
-	}
-
-	function subscribe_rojo()
-	{
-		return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
-	}
-
-	function subscribe_yahoo()
-	{
-		return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
-	}
-
-	function get_feed_tags($namespace, $tag)
-	{
-		$type = $this->get_type();
-		if ($type & SIMPLEPIE_TYPE_ATOM_10)
-		{
-			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
-			{
-				return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
-			}
-		}
-		if ($type & SIMPLEPIE_TYPE_ATOM_03)
-		{
-			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
-			{
-				return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
-			}
-		}
-		if ($type & SIMPLEPIE_TYPE_RSS_RDF)
-		{
-			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
-			{
-				return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
-			}
-		}
-		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
-		{
-			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
-			{
-				return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
-			}
-		}
-		return null;
-	}
-
-	function get_channel_tags($namespace, $tag)
-	{
-		$type = $this->get_type();
-		if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
-		{
-			if ($return = $this->get_feed_tags($namespace, $tag))
-			{
-				return $return;
-			}
-		}
-		if ($type & SIMPLEPIE_TYPE_RSS_10)
-		{
-			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
-			{
-				if (isset($channel[0]['child'][$namespace][$tag]))
-				{
-					return $channel[0]['child'][$namespace][$tag];
-				}
-			}
-		}
-		if ($type & SIMPLEPIE_TYPE_RSS_090)
-		{
-			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
-			{
-				if (isset($channel[0]['child'][$namespace][$tag]))
-				{
-					return $channel[0]['child'][$namespace][$tag];
-				}
-			}
-		}
-		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
-		{
-			if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
-			{
-				if (isset($channel[0]['child'][$namespace][$tag]))
-				{
-					return $channel[0]['child'][$namespace][$tag];
-				}
-			}
-		}
-		return null;
-	}
-
-	function get_image_tags($namespace, $tag)
-	{
-		$type = $this->get_type();
-		if ($type & SIMPLEPIE_TYPE_RSS_10)
-		{
-			if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
-			{
-				if (isset($image[0]['child'][$namespace][$tag]))
-				{
-					return $image[0]['child'][$namespace][$tag];
-				}
-			}
-		}
-		if ($type & SIMPLEPIE_TYPE_RSS_090)
-		{
-			if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
-			{
-				if (isset($image[0]['child'][$namespace][$tag]))
-				{
-					return $image[0]['child'][$namespace][$tag];
-				}
-			}
-		}
-		if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
-		{
-			if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
-			{
-				if (isset($image[0]['child'][$namespace][$tag]))
-				{
-					return $image[0]['child'][$namespace][$tag];
-				}
-			}
-		}
-		return null;
-	}
-
-	function get_base($element = array())
-	{
-		if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
-		{
-			return $element['xml_base'];
-		}
-		elseif ($this->get_link() !== null)
-		{
-			return $this->get_link();
-		}
-		else
-		{
-			return $this->subscribe_url();
-		}
-	}
-
-	function sanitize($data, $type, $base = '')
-	{
-		return $this->sanitize->sanitize($data, $type, $base);
-	}
-
-	function get_title()
-	{
-		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_category($key = 0)
-	{
-		$categories = $this->get_categories();
-		if (isset($categories[$key]))
-		{
-			return $categories[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_categories()
-	{
-		$categories = array();
-
-		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
-		{
-			$term = null;
-			$scheme = null;
-			$label = null;
-			if (isset($category['attribs']['']['term']))
-			{
-				$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($category['attribs']['']['scheme']))
-			{
-				$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($category['attribs']['']['label']))
-			{
-				$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			$categories[] = new $this->category_class($term, $scheme, $label);
-		}
-		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
-		{
-			// This is really the label, but keep this as the term also for BC.
-			// Label will also work on retrieving because that falls back to term.
-			$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			if (isset($category['attribs']['']['domain']))
-			{
-				$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			else
-			{
-				$scheme = null;
-			}
-			$categories[] = new $this->category_class($term, $scheme, null);
-		}
-		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
-		{
-			$categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
-		{
-			$categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-
-		if (!empty($categories))
-		{
-			return SimplePie_Misc::array_unique($categories);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_author($key = 0)
-	{
-		$authors = $this->get_authors();
-		if (isset($authors[$key]))
-		{
-			return $authors[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_authors()
-	{
-		$authors = array();
-		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
-		{
-			$name = null;
-			$uri = null;
-			$email = null;
-			$avatar = null;
-			$name_date = null;
-			$uri_date = null;
-			$avatar_date = null;
-
-			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
-			{
-				$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
-			{
-				$uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
-			}
-			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
-			{
-				$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
-			{
-				$avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
-			{
-				$name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
-			{
-				$uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
-			{
-				$avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
-			}
-
-			if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
-			{
-				$authors[] = new $this->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
-			}
-		}
-		if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
-		{
-			$name = null;
-			$url = null;
-			$email = null;
-			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
-			{
-				$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
-			{
-				$url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
-			}
-			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
-			{
-				$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if ($name !== null || $email !== null || $url !== null)
-			{
-				$authors[] = new $this->author_class($name, $url, $email);
-			}
-		}
-		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
-		{
-			$authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
-		{
-			$authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
-		{
-			$authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-
-		if (!empty($authors))
-		{
-			return SimplePie_Misc::array_unique($authors);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_contributor($key = 0)
-	{
-		$contributors = $this->get_contributors();
-		if (isset($contributors[$key]))
-		{
-			return $contributors[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_contributors()
-	{
-		$contributors = array();
-		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
-		{
-			$name = null;
-			$uri = null;
-			$email = null;
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
-			{
-				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
-			{
-				$uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
-			{
-				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if ($name !== null || $email !== null || $uri !== null)
-			{
-				$contributors[] = new $this->author_class($name, $uri, $email);
-			}
-		}
-		foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
-		{
-			$name = null;
-			$url = null;
-			$email = null;
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
-			{
-				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
-			{
-				$url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
-			{
-				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if ($name !== null || $email !== null || $url !== null)
-			{
-				$contributors[] = new $this->author_class($name, $url, $email);
-			}
-		}
-
-		if (!empty($contributors))
-		{
-			return SimplePie_Misc::array_unique($contributors);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_link($key = 0, $rel = 'alternate')
-	{
-		$links = $this->get_links($rel);
-		if (isset($links[$key]))
-		{
-			return $links[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	/**
-	 * Added for parity between the parent-level and the item/entry-level.
-	 */
-	function get_permalink()
-	{
-		return $this->get_link(0);
-	}
-
-	function get_links($rel = 'alternate')
-	{
-		if (!isset($this->data['links']))
-		{
-			$this->data['links'] = array();
-			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
-			{
-				foreach ($links as $link)
-				{
-					if (isset($link['attribs']['']['href']))
-					{
-						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
-						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
-					}
-				}
-			}
-			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
-			{
-				foreach ($links as $link)
-				{
-					if (isset($link['attribs']['']['href']))
-					{
-						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
-						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
-
-					}
-				}
-			}
-			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
-			{
-				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
-			}
-			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
-			{
-				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
-			}
-			if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
-			{
-				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
-			}
-
-			$keys = array_keys($this->data['links']);
-			foreach ($keys as $key)
-			{
-				if (SimplePie_Misc::is_isegment_nz_nc($key))
-				{
-					if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
-					{
-						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
-						$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
-					}
-					else
-					{
-						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
-					}
-				}
-				elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
-				{
-					$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
-				}
-				$this->data['links'][$key] = array_unique($this->data['links'][$key]);
-			}
-		}
-
-		if (isset($this->data['links'][$rel]))
-		{
-			return $this->data['links'][$rel];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_all_discovered_feeds()
-	{
-		return $this->all_discovered_feeds;
-	}
-
-	function get_description()
-	{
-		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_copyright()
-	{
-		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_language()
-	{
-		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
-		{
-			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
-		{
-			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
-		{
-			return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif (isset($this->data['headers']['content-language']))
-		{
-			return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_latitude()
-	{
-		
-		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
-		{
-			return (float) $return[0]['data'];
-		}
-		elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
-		{
-			return (float) $match[1];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_longitude()
-	{
-		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
-		{
-			return (float) $return[0]['data'];
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
-		{
-			return (float) $return[0]['data'];
-		}
-		elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
-		{
-			return (float) $match[2];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_image_title()
-	{
-		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_image_url()
-	{
-		if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
-		{
-			return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_image_link()
-	{
-		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_image_width()
-	{
-		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
-		{
-			return round($return[0]['data']);
-		}
-		elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
-		{
-			return 88.0;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_image_height()
-	{
-		if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
-		{
-			return round($return[0]['data']);
-		}
-		elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
-		{
-			return 31.0;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_item_quantity($max = 0)
-	{
-		$max = (int) $max;
-		$qty = count($this->get_items());
-		if ($max === 0)
-		{
-			return $qty;
-		}
-		else
-		{
-			return ($qty > $max) ? $max : $qty;
-		}
-	}
-
-	function get_item($key = 0)
-	{
-		$items = $this->get_items();
-		if (isset($items[$key]))
-		{
-			return $items[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_items($start = 0, $end = 0)
-	{
-		if (!isset($this->data['items']))
-		{
-			if (!empty($this->multifeed_objects))
-			{
-				$this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
-			}
-			else
-			{
-				$this->data['items'] = array();
-				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
-				{
-					$keys = array_keys($items);
-					foreach ($keys as $key)
-					{
-						$this->data['items'][] = new $this->item_class($this, $items[$key]);
-					}
-				}
-				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
-				{
-					$keys = array_keys($items);
-					foreach ($keys as $key)
-					{
-						$this->data['items'][] = new $this->item_class($this, $items[$key]);
-					}
-				}
-				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
-				{
-					$keys = array_keys($items);
-					foreach ($keys as $key)
-					{
-						$this->data['items'][] = new $this->item_class($this, $items[$key]);
-					}
-				}
-				if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
-				{
-					$keys = array_keys($items);
-					foreach ($keys as $key)
-					{
-						$this->data['items'][] = new $this->item_class($this, $items[$key]);
-					}
-				}
-				if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
-				{
-					$keys = array_keys($items);
-					foreach ($keys as $key)
-					{
-						$this->data['items'][] = new $this->item_class($this, $items[$key]);
-					}
-				}
-			}
-		}
-
-		if (!empty($this->data['items']))
-		{
-			// If we want to order it by date, check if all items have a date, and then sort it
-			if ($this->order_by_date && empty($this->multifeed_objects))
-			{
-				if (!isset($this->data['ordered_items']))
-				{
-					$do_sort = true;
-					foreach ($this->data['items'] as $item)
-					{
-						if (!$item->get_date('U'))
-						{
-							$do_sort = false;
-							break;
-						}
-					}
-					$item = null;
-					$this->data['ordered_items'] = $this->data['items'];
-					if ($do_sort)
-					{
-						usort($this->data['ordered_items'], array(&$this, 'sort_items'));
-					}
-				}
-				$items = $this->data['ordered_items'];
-			}
-			else
-			{
-				$items = $this->data['items'];
-			}
-
-			// Slice the data as desired
-			if ($end === 0)
-			{
-				return array_slice($items, $start);
-			}
-			else
-			{
-				return array_slice($items, $start, $end);
-			}
-		}
-		else
-		{
-			return array();
-		}
-	}
-
-	/**
-	 * @static
-	 */
-	function sort_items($a, $b)
-	{
-		return $a->get_date('U') <= $b->get_date('U');
-	}
-
-	/**
-	 * @static
-	 */
-	function merge_items($urls, $start = 0, $end = 0, $limit = 0)
-	{
-		if (is_array($urls) && sizeof($urls) > 0)
-		{
-			$items = array();
-			foreach ($urls as $arg)
-			{
-				if (is_a($arg, 'SimplePie'))
-				{
-					$items = array_merge($items, $arg->get_items(0, $limit));
-				}
-				else
-				{
-					trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
-				}
-			}
-
-			$do_sort = true;
-			foreach ($items as $item)
-			{
-				if (!$item->get_date('U'))
-				{
-					$do_sort = false;
-					break;
-				}
-			}
-			$item = null;
-			if ($do_sort)
-			{
-				usort($items, array('SimplePie', 'sort_items'));
-			}
-
-			if ($end === 0)
-			{
-				return array_slice($items, $start);
-			}
-			else
-			{
-				return array_slice($items, $start, $end);
-			}
-		}
-		else
-		{
-			trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
-			return array();
-		}
-	}
-}
-
-class SimplePie_Item
-{
-	var $feed;
-	var $data = array();
-
-	function SimplePie_Item($feed, $data)
-	{
-		$this->feed = $feed;
-		$this->data = $data;
-	}
-
-	function __toString()
-	{
-		return md5(serialize($this->data));
-	}
-
-	/**
-	 * Remove items that link back to this before destroying this object
-	 */
-	function __destruct()
-	{
-		if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
-		{
-			unset($this->feed);
-		}
-	}
-
-	function get_item_tags($namespace, $tag)
-	{
-		if (isset($this->data['child'][$namespace][$tag]))
-		{
-			return $this->data['child'][$namespace][$tag];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_base($element = array())
-	{
-		return $this->feed->get_base($element);
-	}
-
-	function sanitize($data, $type, $base = '')
-	{
-		return $this->feed->sanitize($data, $type, $base);
-	}
-
-	function get_feed()
-	{
-		return $this->feed;
-	}
-
-	function get_id($hash = false)
-	{
-		if (!$hash)
-		{
-			if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
-			{
-				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
-			{
-				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
-			{
-				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
-			{
-				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
-			{
-				return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			elseif (($return = $this->get_permalink()) !== null)
-			{
-				return $return;
-			}
-			elseif (($return = $this->get_title()) !== null)
-			{
-				return $return;
-			}
-		}
-		if ($this->get_permalink() !== null || $this->get_title() !== null)
-		{
-			return md5($this->get_permalink() . $this->get_title());
-		}
-		else
-		{
-			return md5(serialize($this->data));
-		}
-	}
-
-	function get_title()
-	{
-		if (!isset($this->data['title']))
-		{
-			if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
-			{
-				$this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
-			{
-				$this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
-			{
-				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
-			{
-				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
-			{
-				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
-			{
-				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
-			{
-				$this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			else
-			{
-				$this->data['title'] = null;
-			}
-		}
-		return $this->data['title'];
-	}
-
-	function get_description($description_only = false)
-	{
-		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif (!$description_only)
-		{
-			return $this->get_content(true);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_content($content_only = false)
-	{
-		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
-		}
-		elseif (!$content_only)
-		{
-			return $this->get_description(true);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_category($key = 0)
-	{
-		$categories = $this->get_categories();
-		if (isset($categories[$key]))
-		{
-			return $categories[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_categories()
-	{
-		$categories = array();
-
-		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
-		{
-			$term = null;
-			$scheme = null;
-			$label = null;
-			if (isset($category['attribs']['']['term']))
-			{
-				$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($category['attribs']['']['scheme']))
-			{
-				$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($category['attribs']['']['label']))
-			{
-				$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			$categories[] = new $this->feed->category_class($term, $scheme, $label);
-		}
-		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
-		{
-			// This is really the label, but keep this as the term also for BC.
-			// Label will also work on retrieving because that falls back to term.
-			$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			if (isset($category['attribs']['']['domain']))
-			{
-				$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			else
-			{
-				$scheme = null;
-			}
-			$categories[] = new $this->feed->category_class($term, $scheme, null);
-		}
-		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
-		{
-			$categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
-		{
-			$categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-
-		if (!empty($categories))
-		{
-			return SimplePie_Misc::array_unique($categories);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_author($key = 0)
-	{
-		$authors = $this->get_authors();
-		if (isset($authors[$key]))
-		{
-			return $authors[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_contributor($key = 0)
-	{
-		$contributors = $this->get_contributors();
-		if (isset($contributors[$key]))
-		{
-			return $contributors[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_contributors()
-	{
-		$contributors = array();
-		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
-		{
-			$name = null;
-			$uri = null;
-			$email = null;
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
-			{
-				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
-			{
-				$uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
-			{
-				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if ($name !== null || $email !== null || $uri !== null)
-			{
-				$contributors[] = new $this->feed->author_class($name, $uri, $email);
-			}
-		}
-		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
-		{
-			$name = null;
-			$url = null;
-			$email = null;
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
-			{
-				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
-			{
-				$url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
-			{
-				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if ($name !== null || $email !== null || $url !== null)
-			{
-				$contributors[] = new $this->feed->author_class($name, $url, $email);
-			}
-		}
-
-		if (!empty($contributors))
-		{
-			return SimplePie_Misc::array_unique($contributors);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_authors()
-	{
-		$authors = array();
-		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
-		{
-			$name = null;
-			$uri = null;
-			$email = null;
-			$avatar = null;
-			$name_date = null;
-			$uri_date = null;
-			$avatar_date = null;
-			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
-			{
-				$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
-			{
-				$uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
-			}
-			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
-			{
-				$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
-			{
-				$avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
-			{
-				$name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
-			{
-				$uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
-			{
-				$avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
-			}
-
-			if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
-			{
-				$authors[] = new $this->feed->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
-			}
-		}
-		if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
-		{
-			$name = null;
-			$url = null;
-			$email = null;
-			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
-			{
-				$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
-			{
-				$url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
-			}
-			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
-			{
-				$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if ($name !== null || $email !== null || $url !== null)
-			{
-				$authors[] = new $this->feed->author_class($name, $url, $email);
-			}
-		}
-		if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
-		{
-			$authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
-		}
-		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
-		{
-			$authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
-		{
-			$authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-		foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
-		{
-			$authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-
-		if (!empty($authors))
-		{
-			return SimplePie_Misc::array_unique($authors);
-		}
-		elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
-		{
-			return $authors;
-		}
-		elseif ($authors = $this->feed->get_authors())
-		{
-			return $authors;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_copyright()
-	{
-		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_date($date_format = 'j F Y, g:i a')
-	{
-		if (!isset($this->data['date']))
-		{
-			if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
-			{
-				$this->data['date']['raw'] = $return[0]['data'];
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
-			{
-				$this->data['date']['raw'] = $return[0]['data'];
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
-			{
-				$this->data['date']['raw'] = $return[0]['data'];
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
-			{
-				$this->data['date']['raw'] = $return[0]['data'];
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
-			{
-				$this->data['date']['raw'] = $return[0]['data'];
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
-			{
-				$this->data['date']['raw'] = $return[0]['data'];
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
-			{
-				$this->data['date']['raw'] = $return[0]['data'];
-			}
-			elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
-			{
-				$this->data['date']['raw'] = $return[0]['data'];
-			}
-
-			if (!empty($this->data['date']['raw']))
-			{
-				$parser = SimplePie_Parse_Date::get();
-				$this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
-			}
-			else
-			{
-				$this->data['date'] = null;
-			}
-		}
-		if ($this->data['date'])
-		{
-			$date_format = (string) $date_format;
-			switch ($date_format)
-			{
-				case '':
-					return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
-
-				case 'U':
-					return $this->data['date']['parsed'];
-
-				default:
-					return date($date_format, $this->data['date']['parsed']);
-			}
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_local_date($date_format = '%c')
-	{
-		if (!$date_format)
-		{
-			return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif (($date = $this->get_date('U')) !== null)
-		{
-			return strftime($date_format, $date);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_permalink()
-	{
-		$link = $this->get_link();
-		$enclosure = $this->get_enclosure(0);
-		if ($link !== null)
-		{
-			return $link;
-		}
-		elseif ($enclosure !== null)
-		{
-			return $enclosure->get_link();
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_link($key = 0, $rel = 'alternate')
-	{
-		$links = $this->get_links($rel);
-		if ($links[$key] !== null)
-		{
-			return $links[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_links($rel = 'alternate')
-	{
-		if (!isset($this->data['links']))
-		{
-			$this->data['links'] = array();
-			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
-			{
-				if (isset($link['attribs']['']['href']))
-				{
-					$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
-					$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
-
-				}
-			}
-			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
-			{
-				if (isset($link['attribs']['']['href']))
-				{
-					$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
-					$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
-				}
-			}
-			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
-			{
-				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
-			}
-			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
-			{
-				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
-			}
-			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
-			{
-				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
-			}
-			if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
-			{
-				if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
-				{
-					$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
-				}
-			}
-
-			$keys = array_keys($this->data['links']);
-			foreach ($keys as $key)
-			{
-				if (SimplePie_Misc::is_isegment_nz_nc($key))
-				{
-					if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
-					{
-						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
-						$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
-					}
-					else
-					{
-						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
-					}
-				}
-				elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
-				{
-					$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
-				}
-				$this->data['links'][$key] = array_unique($this->data['links'][$key]);
-			}
-		}
-		if (isset($this->data['links'][$rel]))
-		{
-			return $this->data['links'][$rel];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	/**
-	 * @todo Add ability to prefer one type of content over another (in a media group).
-	 */
-	function get_enclosure($key = 0, $prefer = null)
-	{
-		$enclosures = $this->get_enclosures();
-		if (isset($enclosures[$key]))
-		{
-			return $enclosures[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	/**
-	 * Grabs all available enclosures (podcasts, etc.)
-	 *
-	 * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
-	 *
-	 * At this point, we're pretty much assuming that all enclosures for an item are the same content.  Anything else is too complicated to properly support.
-	 *
-	 * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
-	 * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists).
-	 */
-	function get_enclosures()
-	{
-		if (!isset($this->data['enclosures']))
-		{
-			$this->data['enclosures'] = array();
-
-			// Elements
-			$captions_parent = null;
-			$categories_parent = null;
-			$copyrights_parent = null;
-			$credits_parent = null;
-			$description_parent = null;
-			$duration_parent = null;
-			$hashes_parent = null;
-			$keywords_parent = null;
-			$player_parent = null;
-			$ratings_parent = null;
-			$restrictions_parent = null;
-			$thumbnails_parent = null;
-			$title_parent = null;
-
-			// Let's do the channel and item-level ones first, and just re-use them if we need to.
-			$parent = $this->get_feed();
-
-			// CAPTIONS
-			if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
-			{
-				foreach ($captions as $caption)
-				{
-					$caption_type = null;
-					$caption_lang = null;
-					$caption_startTime = null;
-					$caption_endTime = null;
-					$caption_text = null;
-					if (isset($caption['attribs']['']['type']))
-					{
-						$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($caption['attribs']['']['lang']))
-					{
-						$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($caption['attribs']['']['start']))
-					{
-						$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($caption['attribs']['']['end']))
-					{
-						$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($caption['data']))
-					{
-						$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					$captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
-				}
-			}
-			elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
-			{
-				foreach ($captions as $caption)
-				{
-					$caption_type = null;
-					$caption_lang = null;
-					$caption_startTime = null;
-					$caption_endTime = null;
-					$caption_text = null;
-					if (isset($caption['attribs']['']['type']))
-					{
-						$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($caption['attribs']['']['lang']))
-					{
-						$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($caption['attribs']['']['start']))
-					{
-						$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($caption['attribs']['']['end']))
-					{
-						$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($caption['data']))
-					{
-						$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					$captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
-				}
-			}
-			if (is_array($captions_parent))
-			{
-				$captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
-			}
-
-			// CATEGORIES
-			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
-			{
-				$term = null;
-				$scheme = null;
-				$label = null;
-				if (isset($category['data']))
-				{
-					$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-				if (isset($category['attribs']['']['scheme']))
-				{
-					$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-				else
-				{
-					$scheme = 'http://search.yahoo.com/mrss/category_schema';
-				}
-				if (isset($category['attribs']['']['label']))
-				{
-					$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-				$categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
-			}
-			foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
-			{
-				$term = null;
-				$scheme = null;
-				$label = null;
-				if (isset($category['data']))
-				{
-					$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-				if (isset($category['attribs']['']['scheme']))
-				{
-					$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-				else
-				{
-					$scheme = 'http://search.yahoo.com/mrss/category_schema';
-				}
-				if (isset($category['attribs']['']['label']))
-				{
-					$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-				$categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
-			}
-			foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
-			{
-				$term = null;
-				$scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
-				$label = null;
-				if (isset($category['attribs']['']['text']))
-				{
-					$label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-				$categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
-
-				if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
-				{
-					foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
-					{
-						if (isset($subcategory['attribs']['']['text']))
-						{
-							$label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						$categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
-					}
-				}
-			}
-			if (is_array($categories_parent))
-			{
-				$categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
-			}
-
-			// COPYRIGHT
-			if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
-			{
-				$copyright_url = null;
-				$copyright_label = null;
-				if (isset($copyright[0]['attribs']['']['url']))
-				{
-					$copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-				if (isset($copyright[0]['data']))
-				{
-					$copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-				$copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
-			}
-			elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
-			{
-				$copyright_url = null;
-				$copyright_label = null;
-				if (isset($copyright[0]['attribs']['']['url']))
-				{
-					$copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-				if (isset($copyright[0]['data']))
-				{
-					$copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-				$copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
-			}
-
-			// CREDITS
-			if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
-			{
-				foreach ($credits as $credit)
-				{
-					$credit_role = null;
-					$credit_scheme = null;
-					$credit_name = null;
-					if (isset($credit['attribs']['']['role']))
-					{
-						$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($credit['attribs']['']['scheme']))
-					{
-						$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					else
-					{
-						$credit_scheme = 'urn:ebu';
-					}
-					if (isset($credit['data']))
-					{
-						$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					$credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
-				}
-			}
-			elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
-			{
-				foreach ($credits as $credit)
-				{
-					$credit_role = null;
-					$credit_scheme = null;
-					$credit_name = null;
-					if (isset($credit['attribs']['']['role']))
-					{
-						$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($credit['attribs']['']['scheme']))
-					{
-						$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					else
-					{
-						$credit_scheme = 'urn:ebu';
-					}
-					if (isset($credit['data']))
-					{
-						$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					$credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
-				}
-			}
-			if (is_array($credits_parent))
-			{
-				$credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
-			}
-
-			// DESCRIPTION
-			if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
-			{
-				if (isset($description_parent[0]['data']))
-				{
-					$description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-			}
-			elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
-			{
-				if (isset($description_parent[0]['data']))
-				{
-					$description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-			}
-
-			// DURATION
-			if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
-			{
-				$seconds = null;
-				$minutes = null;
-				$hours = null;
-				if (isset($duration_parent[0]['data']))
-				{
-					$temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
-					if (sizeof($temp) > 0)
-					{
-						(int) $seconds = array_pop($temp);
-					}
-					if (sizeof($temp) > 0)
-					{
-						(int) $minutes = array_pop($temp);
-						$seconds += $minutes * 60;
-					}
-					if (sizeof($temp) > 0)
-					{
-						(int) $hours = array_pop($temp);
-						$seconds += $hours * 3600;
-					}
-					unset($temp);
-					$duration_parent = $seconds;
-				}
-			}
-
-			// HASHES
-			if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
-			{
-				foreach ($hashes_iterator as $hash)
-				{
-					$value = null;
-					$algo = null;
-					if (isset($hash['data']))
-					{
-						$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($hash['attribs']['']['algo']))
-					{
-						$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					else
-					{
-						$algo = 'md5';
-					}
-					$hashes_parent[] = $algo.':'.$value;
-				}
-			}
-			elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
-			{
-				foreach ($hashes_iterator as $hash)
-				{
-					$value = null;
-					$algo = null;
-					if (isset($hash['data']))
-					{
-						$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($hash['attribs']['']['algo']))
-					{
-						$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					else
-					{
-						$algo = 'md5';
-					}
-					$hashes_parent[] = $algo.':'.$value;
-				}
-			}
-			if (is_array($hashes_parent))
-			{
-				$hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
-			}
-
-			// KEYWORDS
-			if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
-			{
-				if (isset($keywords[0]['data']))
-				{
-					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
-					foreach ($temp as $word)
-					{
-						$keywords_parent[] = trim($word);
-					}
-				}
-				unset($temp);
-			}
-			elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
-			{
-				if (isset($keywords[0]['data']))
-				{
-					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
-					foreach ($temp as $word)
-					{
-						$keywords_parent[] = trim($word);
-					}
-				}
-				unset($temp);
-			}
-			elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
-			{
-				if (isset($keywords[0]['data']))
-				{
-					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
-					foreach ($temp as $word)
-					{
-						$keywords_parent[] = trim($word);
-					}
-				}
-				unset($temp);
-			}
-			elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
-			{
-				if (isset($keywords[0]['data']))
-				{
-					$temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
-					foreach ($temp as $word)
-					{
-						$keywords_parent[] = trim($word);
-					}
-				}
-				unset($temp);
-			}
-			if (is_array($keywords_parent))
-			{
-				$keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
-			}
-
-			// PLAYER
-			if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
-			{
-				if (isset($player_parent[0]['attribs']['']['url']))
-				{
-					$player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-				}
-			}
-			elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
-			{
-				if (isset($player_parent[0]['attribs']['']['url']))
-				{
-					$player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-				}
-			}
-
-			// RATINGS
-			if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
-			{
-				foreach ($ratings as $rating)
-				{
-					$rating_scheme = null;
-					$rating_value = null;
-					if (isset($rating['attribs']['']['scheme']))
-					{
-						$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					else
-					{
-						$rating_scheme = 'urn:simple';
-					}
-					if (isset($rating['data']))
-					{
-						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					$ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
-				}
-			}
-			elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
-			{
-				foreach ($ratings as $rating)
-				{
-					$rating_scheme = 'urn:itunes';
-					$rating_value = null;
-					if (isset($rating['data']))
-					{
-						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					$ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
-				}
-			}
-			elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
-			{
-				foreach ($ratings as $rating)
-				{
-					$rating_scheme = null;
-					$rating_value = null;
-					if (isset($rating['attribs']['']['scheme']))
-					{
-						$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					else
-					{
-						$rating_scheme = 'urn:simple';
-					}
-					if (isset($rating['data']))
-					{
-						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					$ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
-				}
-			}
-			elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
-			{
-				foreach ($ratings as $rating)
-				{
-					$rating_scheme = 'urn:itunes';
-					$rating_value = null;
-					if (isset($rating['data']))
-					{
-						$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					$ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
-				}
-			}
-			if (is_array($ratings_parent))
-			{
-				$ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
-			}
-
-			// RESTRICTIONS
-			if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
-			{
-				foreach ($restrictions as $restriction)
-				{
-					$restriction_relationship = null;
-					$restriction_type = null;
-					$restriction_value = null;
-					if (isset($restriction['attribs']['']['relationship']))
-					{
-						$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($restriction['attribs']['']['type']))
-					{
-						$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($restriction['data']))
-					{
-						$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					$restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
-				}
-			}
-			elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
-			{
-				foreach ($restrictions as $restriction)
-				{
-					$restriction_relationship = 'allow';
-					$restriction_type = null;
-					$restriction_value = 'itunes';
-					if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
-					{
-						$restriction_relationship = 'deny';
-					}
-					$restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
-				}
-			}
-			elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
-			{
-				foreach ($restrictions as $restriction)
-				{
-					$restriction_relationship = null;
-					$restriction_type = null;
-					$restriction_value = null;
-					if (isset($restriction['attribs']['']['relationship']))
-					{
-						$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($restriction['attribs']['']['type']))
-					{
-						$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($restriction['data']))
-					{
-						$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					$restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
-				}
-			}
-			elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
-			{
-				foreach ($restrictions as $restriction)
-				{
-					$restriction_relationship = 'allow';
-					$restriction_type = null;
-					$restriction_value = 'itunes';
-					if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
-					{
-						$restriction_relationship = 'deny';
-					}
-					$restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
-				}
-			}
-			if (is_array($restrictions_parent))
-			{
-				$restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
-			}
-
-			// THUMBNAILS
-			if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
-			{
-				foreach ($thumbnails as $thumbnail)
-				{
-					if (isset($thumbnail['attribs']['']['url']))
-					{
-						$thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-					}
-				}
-			}
-			elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
-			{
-				foreach ($thumbnails as $thumbnail)
-				{
-					if (isset($thumbnail['attribs']['']['url']))
-					{
-						$thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-					}
-				}
-			}
-
-			// TITLES
-			if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
-			{
-				if (isset($title_parent[0]['data']))
-				{
-					$title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-			}
-			elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
-			{
-				if (isset($title_parent[0]['data']))
-				{
-					$title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-				}
-			}
-
-			// Clear the memory
-			unset($parent);
-
-			// Attributes
-			$bitrate = null;
-			$channels = null;
-			$duration = null;
-			$expression = null;
-			$framerate = null;
-			$height = null;
-			$javascript = null;
-			$lang = null;
-			$length = null;
-			$medium = null;
-			$samplingrate = null;
-			$type = null;
-			$url = null;
-			$width = null;
-
-			// Elements
-			$captions = null;
-			$categories = null;
-			$copyrights = null;
-			$credits = null;
-			$description = null;
-			$hashes = null;
-			$keywords = null;
-			$player = null;
-			$ratings = null;
-			$restrictions = null;
-			$thumbnails = null;
-			$title = null;
-
-			// If we have media:group tags, loop through them.
-			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
-			{
-				if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
-				{
-					// If we have media:content tags, loop through them.
-					foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
-					{
-						if (isset($content['attribs']['']['url']))
-						{
-							// Attributes
-							$bitrate = null;
-							$channels = null;
-							$duration = null;
-							$expression = null;
-							$framerate = null;
-							$height = null;
-							$javascript = null;
-							$lang = null;
-							$length = null;
-							$medium = null;
-							$samplingrate = null;
-							$type = null;
-							$url = null;
-							$width = null;
-
-							// Elements
-							$captions = null;
-							$categories = null;
-							$copyrights = null;
-							$credits = null;
-							$description = null;
-							$hashes = null;
-							$keywords = null;
-							$player = null;
-							$ratings = null;
-							$restrictions = null;
-							$thumbnails = null;
-							$title = null;
-
-							// Start checking the attributes of media:content
-							if (isset($content['attribs']['']['bitrate']))
-							{
-								$bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							if (isset($content['attribs']['']['channels']))
-							{
-								$channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							if (isset($content['attribs']['']['duration']))
-							{
-								$duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							else
-							{
-								$duration = $duration_parent;
-							}
-							if (isset($content['attribs']['']['expression']))
-							{
-								$expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							if (isset($content['attribs']['']['framerate']))
-							{
-								$framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							if (isset($content['attribs']['']['height']))
-							{
-								$height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							if (isset($content['attribs']['']['lang']))
-							{
-								$lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							if (isset($content['attribs']['']['fileSize']))
-							{
-								$length = ceil($content['attribs']['']['fileSize']);
-							}
-							if (isset($content['attribs']['']['medium']))
-							{
-								$medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							if (isset($content['attribs']['']['samplingrate']))
-							{
-								$samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							if (isset($content['attribs']['']['type']))
-							{
-								$type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							if (isset($content['attribs']['']['width']))
-							{
-								$width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							$url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-
-							// Checking the other optional media: elements. Priority: media:content, media:group, item, channel
-
-							// CAPTIONS
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
-							{
-								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
-								{
-									$caption_type = null;
-									$caption_lang = null;
-									$caption_startTime = null;
-									$caption_endTime = null;
-									$caption_text = null;
-									if (isset($caption['attribs']['']['type']))
-									{
-										$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($caption['attribs']['']['lang']))
-									{
-										$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($caption['attribs']['']['start']))
-									{
-										$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($caption['attribs']['']['end']))
-									{
-										$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($caption['data']))
-									{
-										$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									$captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
-								}
-								if (is_array($captions))
-								{
-									$captions = array_values(SimplePie_Misc::array_unique($captions));
-								}
-							}
-							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
-							{
-								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
-								{
-									$caption_type = null;
-									$caption_lang = null;
-									$caption_startTime = null;
-									$caption_endTime = null;
-									$caption_text = null;
-									if (isset($caption['attribs']['']['type']))
-									{
-										$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($caption['attribs']['']['lang']))
-									{
-										$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($caption['attribs']['']['start']))
-									{
-										$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($caption['attribs']['']['end']))
-									{
-										$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($caption['data']))
-									{
-										$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									$captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
-								}
-								if (is_array($captions))
-								{
-									$captions = array_values(SimplePie_Misc::array_unique($captions));
-								}
-							}
-							else
-							{
-								$captions = $captions_parent;
-							}
-
-							// CATEGORIES
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
-							{
-								foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
-								{
-									$term = null;
-									$scheme = null;
-									$label = null;
-									if (isset($category['data']))
-									{
-										$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($category['attribs']['']['scheme']))
-									{
-										$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									else
-									{
-										$scheme = 'http://search.yahoo.com/mrss/category_schema';
-									}
-									if (isset($category['attribs']['']['label']))
-									{
-										$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									$categories[] = new $this->feed->category_class($term, $scheme, $label);
-								}
-							}
-							if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
-							{
-								foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
-								{
-									$term = null;
-									$scheme = null;
-									$label = null;
-									if (isset($category['data']))
-									{
-										$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($category['attribs']['']['scheme']))
-									{
-										$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									else
-									{
-										$scheme = 'http://search.yahoo.com/mrss/category_schema';
-									}
-									if (isset($category['attribs']['']['label']))
-									{
-										$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									$categories[] = new $this->feed->category_class($term, $scheme, $label);
-								}
-							}
-							if (is_array($categories) && is_array($categories_parent))
-							{
-								$categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
-							}
-							elseif (is_array($categories))
-							{
-								$categories = array_values(SimplePie_Misc::array_unique($categories));
-							}
-							elseif (is_array($categories_parent))
-							{
-								$categories = array_values(SimplePie_Misc::array_unique($categories_parent));
-							}
-
-							// COPYRIGHTS
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
-							{
-								$copyright_url = null;
-								$copyright_label = null;
-								if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
-								{
-									$copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
-								{
-									$copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								$copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
-							}
-							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
-							{
-								$copyright_url = null;
-								$copyright_label = null;
-								if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
-								{
-									$copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
-								{
-									$copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								$copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
-							}
-							else
-							{
-								$copyrights = $copyrights_parent;
-							}
-
-							// CREDITS
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
-							{
-								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
-								{
-									$credit_role = null;
-									$credit_scheme = null;
-									$credit_name = null;
-									if (isset($credit['attribs']['']['role']))
-									{
-										$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($credit['attribs']['']['scheme']))
-									{
-										$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									else
-									{
-										$credit_scheme = 'urn:ebu';
-									}
-									if (isset($credit['data']))
-									{
-										$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									$credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
-								}
-								if (is_array($credits))
-								{
-									$credits = array_values(SimplePie_Misc::array_unique($credits));
-								}
-							}
-							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
-							{
-								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
-								{
-									$credit_role = null;
-									$credit_scheme = null;
-									$credit_name = null;
-									if (isset($credit['attribs']['']['role']))
-									{
-										$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($credit['attribs']['']['scheme']))
-									{
-										$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									else
-									{
-										$credit_scheme = 'urn:ebu';
-									}
-									if (isset($credit['data']))
-									{
-										$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									$credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
-								}
-								if (is_array($credits))
-								{
-									$credits = array_values(SimplePie_Misc::array_unique($credits));
-								}
-							}
-							else
-							{
-								$credits = $credits_parent;
-							}
-
-							// DESCRIPTION
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
-							{
-								$description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
-							{
-								$description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							else
-							{
-								$description = $description_parent;
-							}
-
-							// HASHES
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
-							{
-								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
-								{
-									$value = null;
-									$algo = null;
-									if (isset($hash['data']))
-									{
-										$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($hash['attribs']['']['algo']))
-									{
-										$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									else
-									{
-										$algo = 'md5';
-									}
-									$hashes[] = $algo.':'.$value;
-								}
-								if (is_array($hashes))
-								{
-									$hashes = array_values(SimplePie_Misc::array_unique($hashes));
-								}
-							}
-							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
-							{
-								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
-								{
-									$value = null;
-									$algo = null;
-									if (isset($hash['data']))
-									{
-										$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($hash['attribs']['']['algo']))
-									{
-										$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									else
-									{
-										$algo = 'md5';
-									}
-									$hashes[] = $algo.':'.$value;
-								}
-								if (is_array($hashes))
-								{
-									$hashes = array_values(SimplePie_Misc::array_unique($hashes));
-								}
-							}
-							else
-							{
-								$hashes = $hashes_parent;
-							}
-
-							// KEYWORDS
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
-							{
-								if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
-								{
-									$temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
-									foreach ($temp as $word)
-									{
-										$keywords[] = trim($word);
-									}
-									unset($temp);
-								}
-								if (is_array($keywords))
-								{
-									$keywords = array_values(SimplePie_Misc::array_unique($keywords));
-								}
-							}
-							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
-							{
-								if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
-								{
-									$temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
-									foreach ($temp as $word)
-									{
-										$keywords[] = trim($word);
-									}
-									unset($temp);
-								}
-								if (is_array($keywords))
-								{
-									$keywords = array_values(SimplePie_Misc::array_unique($keywords));
-								}
-							}
-							else
-							{
-								$keywords = $keywords_parent;
-							}
-
-							// PLAYER
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
-							{
-								$player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-							}
-							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
-							{
-								$player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-							}
-							else
-							{
-								$player = $player_parent;
-							}
-
-							// RATINGS
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
-							{
-								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
-								{
-									$rating_scheme = null;
-									$rating_value = null;
-									if (isset($rating['attribs']['']['scheme']))
-									{
-										$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									else
-									{
-										$rating_scheme = 'urn:simple';
-									}
-									if (isset($rating['data']))
-									{
-										$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									$ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
-								}
-								if (is_array($ratings))
-								{
-									$ratings = array_values(SimplePie_Misc::array_unique($ratings));
-								}
-							}
-							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
-							{
-								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
-								{
-									$rating_scheme = null;
-									$rating_value = null;
-									if (isset($rating['attribs']['']['scheme']))
-									{
-										$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									else
-									{
-										$rating_scheme = 'urn:simple';
-									}
-									if (isset($rating['data']))
-									{
-										$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									$ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
-								}
-								if (is_array($ratings))
-								{
-									$ratings = array_values(SimplePie_Misc::array_unique($ratings));
-								}
-							}
-							else
-							{
-								$ratings = $ratings_parent;
-							}
-
-							// RESTRICTIONS
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
-							{
-								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
-								{
-									$restriction_relationship = null;
-									$restriction_type = null;
-									$restriction_value = null;
-									if (isset($restriction['attribs']['']['relationship']))
-									{
-										$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($restriction['attribs']['']['type']))
-									{
-										$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($restriction['data']))
-									{
-										$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									$restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
-								}
-								if (is_array($restrictions))
-								{
-									$restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
-								}
-							}
-							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
-							{
-								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
-								{
-									$restriction_relationship = null;
-									$restriction_type = null;
-									$restriction_value = null;
-									if (isset($restriction['attribs']['']['relationship']))
-									{
-										$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($restriction['attribs']['']['type']))
-									{
-										$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									if (isset($restriction['data']))
-									{
-										$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-									}
-									$restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
-								}
-								if (is_array($restrictions))
-								{
-									$restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
-								}
-							}
-							else
-							{
-								$restrictions = $restrictions_parent;
-							}
-
-							// THUMBNAILS
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
-							{
-								foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
-								{
-									$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-								}
-								if (is_array($thumbnails))
-								{
-									$thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
-								}
-							}
-							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
-							{
-								foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
-								{
-									$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-								}
-								if (is_array($thumbnails))
-								{
-									$thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
-								}
-							}
-							else
-							{
-								$thumbnails = $thumbnails_parent;
-							}
-
-							// TITLES
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
-							{
-								$title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
-							{
-								$title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							else
-							{
-								$title = $title_parent;
-							}
-
-							$this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
-						}
-					}
-				}
-			}
-
-			// If we have standalone media:content tags, loop through them.
-			if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
-			{
-				foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
-				{
-					if (isset($content['attribs']['']['url']))
-					{
-						// Attributes
-						$bitrate = null;
-						$channels = null;
-						$duration = null;
-						$expression = null;
-						$framerate = null;
-						$height = null;
-						$javascript = null;
-						$lang = null;
-						$length = null;
-						$medium = null;
-						$samplingrate = null;
-						$type = null;
-						$url = null;
-						$width = null;
-
-						// Elements
-						$captions = null;
-						$categories = null;
-						$copyrights = null;
-						$credits = null;
-						$description = null;
-						$hashes = null;
-						$keywords = null;
-						$player = null;
-						$ratings = null;
-						$restrictions = null;
-						$thumbnails = null;
-						$title = null;
-
-						// Start checking the attributes of media:content
-						if (isset($content['attribs']['']['bitrate']))
-						{
-							$bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						if (isset($content['attribs']['']['channels']))
-						{
-							$channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						if (isset($content['attribs']['']['duration']))
-						{
-							$duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						else
-						{
-							$duration = $duration_parent;
-						}
-						if (isset($content['attribs']['']['expression']))
-						{
-							$expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						if (isset($content['attribs']['']['framerate']))
-						{
-							$framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						if (isset($content['attribs']['']['height']))
-						{
-							$height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						if (isset($content['attribs']['']['lang']))
-						{
-							$lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						if (isset($content['attribs']['']['fileSize']))
-						{
-							$length = ceil($content['attribs']['']['fileSize']);
-						}
-						if (isset($content['attribs']['']['medium']))
-						{
-							$medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						if (isset($content['attribs']['']['samplingrate']))
-						{
-							$samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						if (isset($content['attribs']['']['type']))
-						{
-							$type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						if (isset($content['attribs']['']['width']))
-						{
-							$width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						$url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-
-						// Checking the other optional media: elements. Priority: media:content, media:group, item, channel
-
-						// CAPTIONS
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
-						{
-							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
-							{
-								$caption_type = null;
-								$caption_lang = null;
-								$caption_startTime = null;
-								$caption_endTime = null;
-								$caption_text = null;
-								if (isset($caption['attribs']['']['type']))
-								{
-									$caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								if (isset($caption['attribs']['']['lang']))
-								{
-									$caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								if (isset($caption['attribs']['']['start']))
-								{
-									$caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								if (isset($caption['attribs']['']['end']))
-								{
-									$caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								if (isset($caption['data']))
-								{
-									$caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								$captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
-							}
-							if (is_array($captions))
-							{
-								$captions = array_values(SimplePie_Misc::array_unique($captions));
-							}
-						}
-						else
-						{
-							$captions = $captions_parent;
-						}
-
-						// CATEGORIES
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
-						{
-							foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
-							{
-								$term = null;
-								$scheme = null;
-								$label = null;
-								if (isset($category['data']))
-								{
-									$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								if (isset($category['attribs']['']['scheme']))
-								{
-									$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								else
-								{
-									$scheme = 'http://search.yahoo.com/mrss/category_schema';
-								}
-								if (isset($category['attribs']['']['label']))
-								{
-									$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								$categories[] = new $this->feed->category_class($term, $scheme, $label);
-							}
-						}
-						if (is_array($categories) && is_array($categories_parent))
-						{
-							$categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
-						}
-						elseif (is_array($categories))
-						{
-							$categories = array_values(SimplePie_Misc::array_unique($categories));
-						}
-						elseif (is_array($categories_parent))
-						{
-							$categories = array_values(SimplePie_Misc::array_unique($categories_parent));
-						}
-						else
-						{
-							$categories = null;
-						}
-
-						// COPYRIGHTS
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
-						{
-							$copyright_url = null;
-							$copyright_label = null;
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
-							{
-								$copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
-							{
-								$copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-							}
-							$copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
-						}
-						else
-						{
-							$copyrights = $copyrights_parent;
-						}
-
-						// CREDITS
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
-						{
-							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
-							{
-								$credit_role = null;
-								$credit_scheme = null;
-								$credit_name = null;
-								if (isset($credit['attribs']['']['role']))
-								{
-									$credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								if (isset($credit['attribs']['']['scheme']))
-								{
-									$credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								else
-								{
-									$credit_scheme = 'urn:ebu';
-								}
-								if (isset($credit['data']))
-								{
-									$credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								$credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
-							}
-							if (is_array($credits))
-							{
-								$credits = array_values(SimplePie_Misc::array_unique($credits));
-							}
-						}
-						else
-						{
-							$credits = $credits_parent;
-						}
-
-						// DESCRIPTION
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
-						{
-							$description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						else
-						{
-							$description = $description_parent;
-						}
-
-						// HASHES
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
-						{
-							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
-							{
-								$value = null;
-								$algo = null;
-								if (isset($hash['data']))
-								{
-									$value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								if (isset($hash['attribs']['']['algo']))
-								{
-									$algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								else
-								{
-									$algo = 'md5';
-								}
-								$hashes[] = $algo.':'.$value;
-							}
-							if (is_array($hashes))
-							{
-								$hashes = array_values(SimplePie_Misc::array_unique($hashes));
-							}
-						}
-						else
-						{
-							$hashes = $hashes_parent;
-						}
-
-						// KEYWORDS
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
-						{
-							if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
-							{
-								$temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
-								foreach ($temp as $word)
-								{
-									$keywords[] = trim($word);
-								}
-								unset($temp);
-							}
-							if (is_array($keywords))
-							{
-								$keywords = array_values(SimplePie_Misc::array_unique($keywords));
-							}
-						}
-						else
-						{
-							$keywords = $keywords_parent;
-						}
-
-						// PLAYER
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
-						{
-							$player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-						}
-						else
-						{
-							$player = $player_parent;
-						}
-
-						// RATINGS
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
-						{
-							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
-							{
-								$rating_scheme = null;
-								$rating_value = null;
-								if (isset($rating['attribs']['']['scheme']))
-								{
-									$rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								else
-								{
-									$rating_scheme = 'urn:simple';
-								}
-								if (isset($rating['data']))
-								{
-									$rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								$ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
-							}
-							if (is_array($ratings))
-							{
-								$ratings = array_values(SimplePie_Misc::array_unique($ratings));
-							}
-						}
-						else
-						{
-							$ratings = $ratings_parent;
-						}
-
-						// RESTRICTIONS
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
-						{
-							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
-							{
-								$restriction_relationship = null;
-								$restriction_type = null;
-								$restriction_value = null;
-								if (isset($restriction['attribs']['']['relationship']))
-								{
-									$restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								if (isset($restriction['attribs']['']['type']))
-								{
-									$restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								if (isset($restriction['data']))
-								{
-									$restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-								}
-								$restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
-							}
-							if (is_array($restrictions))
-							{
-								$restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
-							}
-						}
-						else
-						{
-							$restrictions = $restrictions_parent;
-						}
-
-						// THUMBNAILS
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
-						{
-							foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
-							{
-								$thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
-							}
-							if (is_array($thumbnails))
-							{
-								$thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
-							}
-						}
-						else
-						{
-							$thumbnails = $thumbnails_parent;
-						}
-
-						// TITLES
-						if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
-						{
-							$title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-						}
-						else
-						{
-							$title = $title_parent;
-						}
-
-						$this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
-					}
-				}
-			}
-
-			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
-			{
-				if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
-				{
-					// Attributes
-					$bitrate = null;
-					$channels = null;
-					$duration = null;
-					$expression = null;
-					$framerate = null;
-					$height = null;
-					$javascript = null;
-					$lang = null;
-					$length = null;
-					$medium = null;
-					$samplingrate = null;
-					$type = null;
-					$url = null;
-					$width = null;
-					$title = $title_parent;
-
-					$url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
-					if (isset($link['attribs']['']['type']))
-					{
-						$type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($link['attribs']['']['length']))
-					{
-						$length = ceil($link['attribs']['']['length']);
-					}
-					if (isset($link['attribs']['']['title']))
-					{
-						$title = $this->sanitize($link['attribs']['']['title'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-
-					// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
-					$this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title, $width);
-				}
-			}
-
-			foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
-			{
-				if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
-				{
-					// Attributes
-					$bitrate = null;
-					$channels = null;
-					$duration = null;
-					$expression = null;
-					$framerate = null;
-					$height = null;
-					$javascript = null;
-					$lang = null;
-					$length = null;
-					$medium = null;
-					$samplingrate = null;
-					$type = null;
-					$url = null;
-					$width = null;
-
-					$url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
-					if (isset($link['attribs']['']['type']))
-					{
-						$type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($link['attribs']['']['length']))
-					{
-						$length = ceil($link['attribs']['']['length']);
-					}
-
-					// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
-					$this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
-				}
-			}
-
-			if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
-			{
-				if (isset($enclosure[0]['attribs']['']['url']))
-				{
-					// Attributes
-					$bitrate = null;
-					$channels = null;
-					$duration = null;
-					$expression = null;
-					$framerate = null;
-					$height = null;
-					$javascript = null;
-					$lang = null;
-					$length = null;
-					$medium = null;
-					$samplingrate = null;
-					$type = null;
-					$url = null;
-					$width = null;
-
-					$url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
-					if (isset($enclosure[0]['attribs']['']['type']))
-					{
-						$type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
-					}
-					if (isset($enclosure[0]['attribs']['']['length']))
-					{
-						$length = ceil($enclosure[0]['attribs']['']['length']);
-					}
-
-					// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
-					$this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
-				}
-			}
-
-			if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width))
-			{
-				// Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
-				$this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
-			}
-
-			$this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
-		}
-		if (!empty($this->data['enclosures']))
-		{
-			return $this->data['enclosures'];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_latitude()
-	{
-		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
-		{
-			return (float) $return[0]['data'];
-		}
-		elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
-		{
-			return (float) $match[1];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_longitude()
-	{
-		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
-		{
-			return (float) $return[0]['data'];
-		}
-		elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
-		{
-			return (float) $return[0]['data'];
-		}
-		elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
-		{
-			return (float) $match[2];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_source()
-	{
-		if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
-		{
-			return new $this->feed->source_class($this, $return[0]);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	/**
-	 * Creates the add_to_* methods' return data
-	 *
-	 * @access private
-	 * @param string $item_url String to prefix to the item permalink
-	 * @param string $title_url String to prefix to the item title
-	 * (and suffix to the item permalink)
-	 * @return mixed URL if feed exists, false otherwise
-	 */
-	function add_to_service($item_url, $title_url = null, $summary_url = null)
-	{
-		if ($this->get_permalink() !== null)
-		{
-			$return = $item_url . rawurlencode($this->get_permalink());
-			if ($title_url !== null && $this->get_title() !== null)
-			{
-				$return .= $title_url . rawurlencode($this->get_title());
-			}
-			if ($summary_url !== null && $this->get_description() !== null)
-			{
-				$return .= $summary_url . rawurlencode($this->get_description());
-			}
-			return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function add_to_blinklist()
-	{
-		return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
-	}
-
-	function add_to_blogmarks()
-	{
-		return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
-	}
-
-	function add_to_delicious()
-	{
-		return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
-	}
-
-	function add_to_digg()
-	{
-		return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
-	}
-
-	function add_to_furl()
-	{
-		return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
-	}
-
-	function add_to_magnolia()
-	{
-		return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
-	}
-
-	function add_to_myweb20()
-	{
-		return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
-	}
-
-	function add_to_newsvine()
-	{
-		return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
-	}
-
-	function add_to_reddit()
-	{
-		return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
-	}
-
-	function add_to_segnalo()
-	{
-		return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
-	}
-
-	function add_to_simpy()
-	{
-		return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
-	}
-
-	function add_to_spurl()
-	{
-		return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
-	}
-
-	function add_to_wists()
-	{
-		return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
-	}
-
-	function search_technorati()
-	{
-		return $this->add_to_service('http://www.technorati.com/search/');
-	}
-}
-
-class SimplePie_Source
-{
-	var $item;
-	var $data = array();
-
-	function SimplePie_Source($item, $data)
-	{
-		$this->item = $item;
-		$this->data = $data;
-	}
-
-	function __toString()
-	{
-		return md5(serialize($this->data));
-	}
-
-	function get_source_tags($namespace, $tag)
-	{
-		if (isset($this->data['child'][$namespace][$tag]))
-		{
-			return $this->data['child'][$namespace][$tag];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_base($element = array())
-	{
-		return $this->item->get_base($element);
-	}
-
-	function sanitize($data, $type, $base = '')
-	{
-		return $this->item->sanitize($data, $type, $base);
-	}
-
-	function get_item()
-	{
-		return $this->item;
-	}
-
-	function get_title()
-	{
-		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_category($key = 0)
-	{
-		$categories = $this->get_categories();
-		if (isset($categories[$key]))
-		{
-			return $categories[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_categories()
-	{
-		$categories = array();
-
-		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
-		{
-			$term = null;
-			$scheme = null;
-			$label = null;
-			if (isset($category['attribs']['']['term']))
-			{
-				$term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($category['attribs']['']['scheme']))
-			{
-				$scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($category['attribs']['']['label']))
-			{
-				$label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			$categories[] = new $this->item->feed->category_class($term, $scheme, $label);
-		}
-		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
-		{
-			// This is really the label, but keep this as the term also for BC.
-			// Label will also work on retrieving because that falls back to term.
-			$term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			if (isset($category['attribs']['']['domain']))
-			{
-				$scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			else
-			{
-				$scheme = null;
-			}
-			$categories[] = new $this->item->feed->category_class($term, $scheme, null);
-		}
-		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
-		{
-			$categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
-		{
-			$categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-
-		if (!empty($categories))
-		{
-			return SimplePie_Misc::array_unique($categories);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_author($key = 0)
-	{
-		$authors = $this->get_authors();
-		if (isset($authors[$key]))
-		{
-			return $authors[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_authors()
-	{
-		$authors = array();
-		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
-		{
-			$name = null;
-			$uri = null;
-			$email = null;
-			$avatar = null;
-			$name_date = null;
-			$uri_date = null;
-			$avatar_date = null;
-
-			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
-			{
-				$name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
-			{
-				$uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
-			}
-			if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
-			{
-				$email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data']))
-			{
-				$avatar = $this->sanitize($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar'][0]));
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data']))
-			{
-				$name_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['name-updated'][0]['data'];
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data']))
-			{
-				$uri_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['uri-updated'][0]['data'];
-			}
-			if (isset($author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data']))
-			{
-				$avatar_date = $author['child']['http://purl.org/macgirvin/dfrn/1.0']['avatar-updated'][0]['data'];
-			}
-
-			if ($name !== null || $email !== null || $uri !== null || $avatar !== null || $name_date !== null || $uri_date !== null || $avatar_date !== null )
-			{
-				$authors[] = new $this->item->feed->author_class($name, $uri, $email, $avatar, $name_date, $uri_date, $avatar_date);
-			}
-		}
-		if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
-		{
-			$name = null;
-			$url = null;
-			$email = null;
-			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
-			{
-				$name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
-			{
-				$url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
-			}
-			if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
-			{
-				$email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if ($name !== null || $email !== null || $url !== null)
-			{
-				$authors[] = new $this->item->feed->author_class($name, $url, $email);
-			}
-		}
-		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
-		{
-			$authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
-		{
-			$authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
-		{
-			$authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
-		}
-
-		if (!empty($authors))
-		{
-			return SimplePie_Misc::array_unique($authors);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_contributor($key = 0)
-	{
-		$contributors = $this->get_contributors();
-		if (isset($contributors[$key]))
-		{
-			return $contributors[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_contributors()
-	{
-		$contributors = array();
-		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
-		{
-			$name = null;
-			$uri = null;
-			$email = null;
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
-			{
-				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
-			{
-				$uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
-			{
-				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if ($name !== null || $email !== null || $uri !== null)
-			{
-				$contributors[] = new $this->item->feed->author_class($name, $uri, $email);
-			}
-		}
-		foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
-		{
-			$name = null;
-			$url = null;
-			$email = null;
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
-			{
-				$name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
-			{
-				$url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
-			}
-			if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
-			{
-				$email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-			}
-			if ($name !== null || $email !== null || $url !== null)
-			{
-				$contributors[] = new $this->item->feed->author_class($name, $url, $email);
-			}
-		}
-
-		if (!empty($contributors))
-		{
-			return SimplePie_Misc::array_unique($contributors);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_link($key = 0, $rel = 'alternate')
-	{
-		$links = $this->get_links($rel);
-		if (isset($links[$key]))
-		{
-			return $links[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	/**
-	 * Added for parity between the parent-level and the item/entry-level.
-	 */
-	function get_permalink()
-	{
-		return $this->get_link(0);
-	}
-
-	function get_links($rel = 'alternate')
-	{
-		if (!isset($this->data['links']))
-		{
-			$this->data['links'] = array();
-			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
-			{
-				foreach ($links as $link)
-				{
-					if (isset($link['attribs']['']['href']))
-					{
-						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
-						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
-					}
-				}
-			}
-			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
-			{
-				foreach ($links as $link)
-				{
-					if (isset($link['attribs']['']['href']))
-					{
-						$link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
-						$this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
-
-					}
-				}
-			}
-			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
-			{
-				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
-			}
-			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
-			{
-				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
-			}
-			if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
-			{
-				$this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
-			}
-
-			$keys = array_keys($this->data['links']);
-			foreach ($keys as $key)
-			{
-				if (SimplePie_Misc::is_isegment_nz_nc($key))
-				{
-					if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
-					{
-						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
-						$this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
-					}
-					else
-					{
-						$this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
-					}
-				}
-				elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
-				{
-					$this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
-				}
-				$this->data['links'][$key] = array_unique($this->data['links'][$key]);
-			}
-		}
-
-		if (isset($this->data['links'][$rel]))
-		{
-			return $this->data['links'][$rel];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_description()
-	{
-		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_copyright()
-	{
-		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
-		{
-			return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_language()
-	{
-		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		elseif (isset($this->data['xml_lang']))
-		{
-			return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_latitude()
-	{
-		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
-		{
-			return (float) $return[0]['data'];
-		}
-		elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
-		{
-			return (float) $match[1];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_longitude()
-	{
-		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
-		{
-			return (float) $return[0]['data'];
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
-		{
-			return (float) $return[0]['data'];
-		}
-		elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
-		{
-			return (float) $match[2];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_image_url()
-	{
-		if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
-		{
-			return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
-		}
-		elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
-		{
-			return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
-		}
-		else
-		{
-			return null;
-		}
-	}
-}
-
-class SimplePie_Author
-{
-	var $name;
-	var $link;
-	var $email;
-	var $avatar;
-	var $name_date;
-	var $uri_date;
-	var $avatar_date;
-
-	// Constructor, used to input the data
-	function SimplePie_Author($name = null, $link = null, $email = null, $avatar = null, $name_date = null, $uri_date = null, $avatar_date = null)
-	{
-		$this->name = $name;
-		$this->link = $link;
-		$this->email = $email;
-		$this->avatar = $avatar;
-		$this->name_date = $name_date;
-		$this->uri_date = $uri_date;
-		$this->avatar_date = $avatar_date;
-	}
-
-	function __toString()
-	{
-		// There is no $this->data here
-		return md5(serialize($this));
-	}
-
-	function get_name()
-	{
-		if ($this->name !== null)
-		{
-			return $this->name;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_link()
-	{
-		if ($this->link !== null)
-		{
-			return $this->link;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_email()
-	{
-		if ($this->email !== null)
-		{
-			return $this->email;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_avatar()
-	{
-		if ($this->avatar !== null)
-		{
-			return $this->avatar;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_name_date()
-	{
-		if ($this->name_date !== null)
-		{
-			return $this->name_date;
-		}
-		else
-		{
-			return null;
-		}
-	}
-	function get_uri_date()
-	{
-		if ($this->uri_date !== null)
-		{
-			return $this->uri_date;
-		}
-		else
-		{
-			return null;
-		}
-	}
-	function get_avatar_date()
-	{
-		if ($this->avatar_date !== null)
-		{
-			return $this->avatar_date;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-
-}
-
-class SimplePie_Category
-{
-	var $term;
-	var $scheme;
-	var $label;
-
-	// Constructor, used to input the data
-	function SimplePie_Category($term = null, $scheme = null, $label = null)
-	{
-		$this->term = $term;
-		$this->scheme = $scheme;
-		$this->label = $label;
-	}
-
-	function __toString()
-	{
-		// There is no $this->data here
-		return md5(serialize($this));
-	}
-
-	function get_term()
-	{
-		if ($this->term !== null)
-		{
-			return $this->term;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_scheme()
-	{
-		if ($this->scheme !== null)
-		{
-			return $this->scheme;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_label()
-	{
-		if ($this->label !== null)
-		{
-			return $this->label;
-		}
-		else
-		{
-			return $this->get_term();
-		}
-	}
-}
-
-class SimplePie_Enclosure
-{
-	var $bitrate;
-	var $captions;
-	var $categories;
-	var $channels;
-	var $copyright;
-	var $credits;
-	var $description;
-	var $duration;
-	var $expression;
-	var $framerate;
-	var $handler;
-	var $hashes;
-	var $height;
-	var $javascript;
-	var $keywords;
-	var $lang;
-	var $length;
-	var $link;
-	var $medium;
-	var $player;
-	var $ratings;
-	var $restrictions;
-	var $samplingrate;
-	var $thumbnails;
-	var $title;
-	var $type;
-	var $width;
-
-	// Constructor, used to input the data
-	function SimplePie_Enclosure($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)
-	{
-		$this->bitrate = $bitrate;
-		$this->captions = $captions;
-		$this->categories = $categories;
-		$this->channels = $channels;
-		$this->copyright = $copyright;
-		$this->credits = $credits;
-		$this->description = $description;
-		$this->duration = $duration;
-		$this->expression = $expression;
-		$this->framerate = $framerate;
-		$this->hashes = $hashes;
-		$this->height = $height;
-		$this->javascript = $javascript;
-		$this->keywords = $keywords;
-		$this->lang = $lang;
-		$this->length = $length;
-		$this->link = $link;
-		$this->medium = $medium;
-		$this->player = $player;
-		$this->ratings = $ratings;
-		$this->restrictions = $restrictions;
-		$this->samplingrate = $samplingrate;
-		$this->thumbnails = $thumbnails;
-		$this->title = $title;
-		$this->type = $type;
-		$this->width = $width;
-		if (class_exists('idna_convert'))
-		{
-			$idn = new idna_convert;
-			$parsed = SimplePie_Misc::parse_url($link);
-			$this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
-		}
-		$this->handler = $this->get_handler(); // Needs to load last
-	}
-
-	function __toString()
-	{
-		// There is no $this->data here
-		return md5(serialize($this));
-	}
-
-	function get_bitrate()
-	{
-		if ($this->bitrate !== null)
-		{
-			return $this->bitrate;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_caption($key = 0)
-	{
-		$captions = $this->get_captions();
-		if (isset($captions[$key]))
-		{
-			return $captions[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_captions()
-	{
-		if ($this->captions !== null)
-		{
-			return $this->captions;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_category($key = 0)
-	{
-		$categories = $this->get_categories();
-		if (isset($categories[$key]))
-		{
-			return $categories[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_categories()
-	{
-		if ($this->categories !== null)
-		{
-			return $this->categories;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_channels()
-	{
-		if ($this->channels !== null)
-		{
-			return $this->channels;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_copyright()
-	{
-		if ($this->copyright !== null)
-		{
-			return $this->copyright;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_credit($key = 0)
-	{
-		$credits = $this->get_credits();
-		if (isset($credits[$key]))
-		{
-			return $credits[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_credits()
-	{
-		if ($this->credits !== null)
-		{
-			return $this->credits;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_description()
-	{
-		if ($this->description !== null)
-		{
-			return $this->description;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_duration($convert = false)
-	{
-		if ($this->duration !== null)
-		{
-			if ($convert)
-			{
-				$time = SimplePie_Misc::time_hms($this->duration);
-				return $time;
-			}
-			else
-			{
-				return $this->duration;
-			}
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_expression()
-	{
-		if ($this->expression !== null)
-		{
-			return $this->expression;
-		}
-		else
-		{
-			return 'full';
-		}
-	}
-
-	function get_extension()
-	{
-		if ($this->link !== null)
-		{
-			$url = SimplePie_Misc::parse_url($this->link);
-			if ($url['path'] !== '')
-			{
-				return pathinfo($url['path'], PATHINFO_EXTENSION);
-			}
-		}
-		return null;
-	}
-
-	function get_framerate()
-	{
-		if ($this->framerate !== null)
-		{
-			return $this->framerate;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_handler()
-	{
-		return $this->get_real_type(true);
-	}
-
-	function get_hash($key = 0)
-	{
-		$hashes = $this->get_hashes();
-		if (isset($hashes[$key]))
-		{
-			return $hashes[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_hashes()
-	{
-		if ($this->hashes !== null)
-		{
-			return $this->hashes;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_height()
-	{
-		if ($this->height !== null)
-		{
-			return $this->height;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_language()
-	{
-		if ($this->lang !== null)
-		{
-			return $this->lang;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_keyword($key = 0)
-	{
-		$keywords = $this->get_keywords();
-		if (isset($keywords[$key]))
-		{
-			return $keywords[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_keywords()
-	{
-		if ($this->keywords !== null)
-		{
-			return $this->keywords;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_length()
-	{
-		if ($this->length !== null)
-		{
-			return $this->length;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_link()
-	{
-		if ($this->link !== null)
-		{
-			return urldecode($this->link);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_medium()
-	{
-		if ($this->medium !== null)
-		{
-			return $this->medium;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_player()
-	{
-		if ($this->player !== null)
-		{
-			return $this->player;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_rating($key = 0)
-	{
-		$ratings = $this->get_ratings();
-		if (isset($ratings[$key]))
-		{
-			return $ratings[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_ratings()
-	{
-		if ($this->ratings !== null)
-		{
-			return $this->ratings;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_restriction($key = 0)
-	{
-		$restrictions = $this->get_restrictions();
-		if (isset($restrictions[$key]))
-		{
-			return $restrictions[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_restrictions()
-	{
-		if ($this->restrictions !== null)
-		{
-			return $this->restrictions;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_sampling_rate()
-	{
-		if ($this->samplingrate !== null)
-		{
-			return $this->samplingrate;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_size()
-	{
-		$length = $this->get_length();
-		if ($length !== null)
-		{
-			return round($length/1048576, 2);
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_thumbnail($key = 0)
-	{
-		$thumbnails = $this->get_thumbnails();
-		if (isset($thumbnails[$key]))
-		{
-			return $thumbnails[$key];
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_thumbnails()
-	{
-		if ($this->thumbnails !== null)
-		{
-			return $this->thumbnails;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_title()
-	{
-		if ($this->title !== null)
-		{
-			return $this->title;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_type()
-	{
-		if ($this->type !== null)
-		{
-			return $this->type;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_width()
-	{
-		if ($this->width !== null)
-		{
-			return $this->width;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function native_embed($options='')
-	{
-		return $this->embed($options, true);
-	}
-
-	/**
-	 * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
-	 */
-	function embed($options = '', $native = false)
-	{
-		// Set up defaults
-		$audio = '';
-		$video = '';
-		$alt = '';
-		$altclass = '';
-		$loop = 'false';
-		$width = 'auto';
-		$height = 'auto';
-		$bgcolor = '#ffffff';
-		$mediaplayer = '';
-		$widescreen = false;
-		$handler = $this->get_handler();
-		$type = $this->get_real_type();
-
-		// Process options and reassign values as necessary
-		if (is_array($options))
-		{
-			extract($options);
-		}
-		else
-		{
-			$options = explode(',', $options);
-			foreach($options as $option)
-			{
-				$opt = explode(':', $option, 2);
-				if (isset($opt[0], $opt[1]))
-				{
-					$opt[0] = trim($opt[0]);
-					$opt[1] = trim($opt[1]);
-					switch ($opt[0])
-					{
-						case 'audio':
-							$audio = $opt[1];
-							break;
-
-						case 'video':
-							$video = $opt[1];
-							break;
-
-						case 'alt':
-							$alt = $opt[1];
-							break;
-
-						case 'altclass':
-							$altclass = $opt[1];
-							break;
-
-						case 'loop':
-							$loop = $opt[1];
-							break;
-
-						case 'width':
-							$width = $opt[1];
-							break;
-
-						case 'height':
-							$height = $opt[1];
-							break;
-
-						case 'bgcolor':
-							$bgcolor = $opt[1];
-							break;
-
-						case 'mediaplayer':
-							$mediaplayer = $opt[1];
-							break;
-
-						case 'widescreen':
-							$widescreen = $opt[1];
-							break;
-					}
-				}
-			}
-		}
-
-		$mime = explode('/', $type, 2);
-		$mime = $mime[0];
-
-		// Process values for 'auto'
-		if ($width === 'auto')
-		{
-			if ($mime === 'video')
-			{
-				if ($height === 'auto')
-				{
-					$width = 480;
-				}
-				elseif ($widescreen)
-				{
-					$width = round((intval($height)/9)*16);
-				}
-				else
-				{
-					$width = round((intval($height)/3)*4);
-				}
-			}
-			else
-			{
-				$width = '100%';
-			}
-		}
-
-		if ($height === 'auto')
-		{
-			if ($mime === 'audio')
-			{
-				$height = 0;
-			}
-			elseif ($mime === 'video')
-			{
-				if ($width === 'auto')
-				{
-					if ($widescreen)
-					{
-						$height = 270;
-					}
-					else
-					{
-						$height = 360;
-					}
-				}
-				elseif ($widescreen)
-				{
-					$height = round((intval($width)/16)*9);
-				}
-				else
-				{
-					$height = round((intval($width)/4)*3);
-				}
-			}
-			else
-			{
-				$height = 376;
-			}
-		}
-		elseif ($mime === 'audio')
-		{
-			$height = 0;
-		}
-
-		// Set proper placeholder value
-		if ($mime === 'audio')
-		{
-			$placeholder = $audio;
-		}
-		elseif ($mime === 'video')
-		{
-			$placeholder = $video;
-		}
-
-		$embed = '';
-
-		// Make sure the JS library is included
-		if (!$native)
-		{
-			static $javascript_outputted = null;
-			if (!$javascript_outputted && $this->javascript)
-			{
-				$embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
-				$javascript_outputted = true;
-			}
-		}
-
-		// Odeo Feed MP3's
-		if ($handler === 'odeo')
-		{
-			if ($native)
-			{
-				$embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://adobe.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url=' . $this->get_link() . '"></embed>';
-			}
-			else
-			{
-				$embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
-			}
-		}
-
-		// Flash
-		elseif ($handler === 'flash')
-		{
-			if ($native)
-			{
-				$embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
-			}
-			else
-			{
-				$embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
-			}
-		}
-
-		// Flash Media Player file types.
-		// Preferred handler for MP3 file types.
-		elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
-		{
-			$height += 20;
-			if ($native)
-			{
-				$embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
-			}
-			else
-			{
-				$embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
-			}
-		}
-
-		// QuickTime 7 file types.  Need to test with QuickTime 6.
-		// Only handle MP3's if the Flash Media Player is not present.
-		elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
-		{
-			$height += 16;
-			if ($native)
-			{
-				if ($placeholder !== '')
-				{
-					$embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
-				}
-				else
-				{
-					$embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
-				}
-			}
-			else
-			{
-				$embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
-			}
-		}
-
-		// Windows Media
-		elseif ($handler === 'wmedia')
-		{
-			$height += 45;
-			if ($native)
-			{
-				$embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
-			}
-			else
-			{
-				$embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
-			}
-		}
-
-		// Everything else
-		else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
-
-		return $embed;
-	}
-
-	function get_real_type($find_handler = false)
-	{
-		// If it's Odeo, let's get it out of the way.
-		if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
-		{
-			return 'odeo';
-		}
-
-		// Mime-types by handler.
-		$types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
-		$types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
-		$types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime
-		$types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media
-		$types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
-
-		if ($this->get_type() !== null)
-		{
-			$type = strtolower($this->type);
-		}
-		else
-		{
-			$type = null;
-		}
-
-		// If we encounter an unsupported mime-type, check the file extension and guess intelligently.
-		if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
-		{
-			switch (strtolower($this->get_extension()))
-			{
-				// Audio mime-types
-				case 'aac':
-				case 'adts':
-					$type = 'audio/acc';
-					break;
-
-				case 'aif':
-				case 'aifc':
-				case 'aiff':
-				case 'cdda':
-					$type = 'audio/aiff';
-					break;
-
-				case 'bwf':
-					$type = 'audio/wav';
-					break;
-
-				case 'kar':
-				case 'mid':
-				case 'midi':
-				case 'smf':
-					$type = 'audio/midi';
-					break;
-
-				case 'm4a':
-					$type = 'audio/x-m4a';
-					break;
-
-				case 'mp3':
-				case 'swa':
-					$type = 'audio/mp3';
-					break;
-
-				case 'wav':
-					$type = 'audio/wav';
-					break;
-
-				case 'wax':
-					$type = 'audio/x-ms-wax';
-					break;
-
-				case 'wma':
-					$type = 'audio/x-ms-wma';
-					break;
-
-				// Video mime-types
-				case '3gp':
-				case '3gpp':
-					$type = 'video/3gpp';
-					break;
-
-				case '3g2':
-				case '3gp2':
-					$type = 'video/3gpp2';
-					break;
-
-				case 'asf':
-					$type = 'video/x-ms-asf';
-					break;
-
-				case 'flv':
-					$type = 'video/x-flv';
-					break;
-
-				case 'm1a':
-				case 'm1s':
-				case 'm1v':
-				case 'm15':
-				case 'm75':
-				case 'mp2':
-				case 'mpa':
-				case 'mpeg':
-				case 'mpg':
-				case 'mpm':
-				case 'mpv':
-					$type = 'video/mpeg';
-					break;
-
-				case 'm4v':
-					$type = 'video/x-m4v';
-					break;
-
-				case 'mov':
-				case 'qt':
-					$type = 'video/quicktime';
-					break;
-
-				case 'mp4':
-				case 'mpg4':
-					$type = 'video/mp4';
-					break;
-
-				case 'sdv':
-					$type = 'video/sd-video';
-					break;
-
-				case 'wm':
-					$type = 'video/x-ms-wm';
-					break;
-
-				case 'wmv':
-					$type = 'video/x-ms-wmv';
-					break;
-
-				case 'wvx':
-					$type = 'video/x-ms-wvx';
-					break;
-
-				// Flash mime-types
-				case 'spl':
-					$type = 'application/futuresplash';
-					break;
-
-				case 'swf':
-					$type = 'application/x-shockwave-flash';
-					break;
-			}
-		}
-
-		if ($find_handler)
-		{
-			if (in_array($type, $types_flash))
-			{
-				return 'flash';
-			}
-			elseif (in_array($type, $types_fmedia))
-			{
-				return 'fmedia';
-			}
-			elseif (in_array($type, $types_quicktime))
-			{
-				return 'quicktime';
-			}
-			elseif (in_array($type, $types_wmedia))
-			{
-				return 'wmedia';
-			}
-			elseif (in_array($type, $types_mp3))
-			{
-				return 'mp3';
-			}
-			else
-			{
-				return null;
-			}
-		}
-		else
-		{
-			return $type;
-		}
-	}
-}
-
-class SimplePie_Caption
-{
-	var $type;
-	var $lang;
-	var $startTime;
-	var $endTime;
-	var $text;
-
-	// Constructor, used to input the data
-	function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
-	{
-		$this->type = $type;
-		$this->lang = $lang;
-		$this->startTime = $startTime;
-		$this->endTime = $endTime;
-		$this->text = $text;
-	}
-
-	function __toString()
-	{
-		// There is no $this->data here
-		return md5(serialize($this));
-	}
-
-	function get_endtime()
-	{
-		if ($this->endTime !== null)
-		{
-			return $this->endTime;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_language()
-	{
-		if ($this->lang !== null)
-		{
-			return $this->lang;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_starttime()
-	{
-		if ($this->startTime !== null)
-		{
-			return $this->startTime;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_text()
-	{
-		if ($this->text !== null)
-		{
-			return $this->text;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_type()
-	{
-		if ($this->type !== null)
-		{
-			return $this->type;
-		}
-		else
-		{
-			return null;
-		}
-	}
-}
-
-class SimplePie_Credit
-{
-	var $role;
-	var $scheme;
-	var $name;
-
-	// Constructor, used to input the data
-	function SimplePie_Credit($role = null, $scheme = null, $name = null)
-	{
-		$this->role = $role;
-		$this->scheme = $scheme;
-		$this->name = $name;
-	}
-
-	function __toString()
-	{
-		// There is no $this->data here
-		return md5(serialize($this));
-	}
-
-	function get_role()
-	{
-		if ($this->role !== null)
-		{
-			return $this->role;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_scheme()
-	{
-		if ($this->scheme !== null)
-		{
-			return $this->scheme;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_name()
-	{
-		if ($this->name !== null)
-		{
-			return $this->name;
-		}
-		else
-		{
-			return null;
-		}
-	}
-}
-
-class SimplePie_Copyright
-{
-	var $url;
-	var $label;
-
-	// Constructor, used to input the data
-	function SimplePie_Copyright($url = null, $label = null)
-	{
-		$this->url = $url;
-		$this->label = $label;
-	}
-
-	function __toString()
-	{
-		// There is no $this->data here
-		return md5(serialize($this));
-	}
-
-	function get_url()
-	{
-		if ($this->url !== null)
-		{
-			return $this->url;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_attribution()
-	{
-		if ($this->label !== null)
-		{
-			return $this->label;
-		}
-		else
-		{
-			return null;
-		}
-	}
-}
-
-class SimplePie_Rating
-{
-	var $scheme;
-	var $value;
-
-	// Constructor, used to input the data
-	function SimplePie_Rating($scheme = null, $value = null)
-	{
-		$this->scheme = $scheme;
-		$this->value = $value;
-	}
-
-	function __toString()
-	{
-		// There is no $this->data here
-		return md5(serialize($this));
-	}
-
-	function get_scheme()
-	{
-		if ($this->scheme !== null)
-		{
-			return $this->scheme;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_value()
-	{
-		if ($this->value !== null)
-		{
-			return $this->value;
-		}
-		else
-		{
-			return null;
-		}
-	}
-}
-
-class SimplePie_Restriction
-{
-	var $relationship;
-	var $type;
-	var $value;
-
-	// Constructor, used to input the data
-	function SimplePie_Restriction($relationship = null, $type = null, $value = null)
-	{
-		$this->relationship = $relationship;
-		$this->type = $type;
-		$this->value = $value;
-	}
-
-	function __toString()
-	{
-		// There is no $this->data here
-		return md5(serialize($this));
-	}
-
-	function get_relationship()
-	{
-		if ($this->relationship !== null)
-		{
-			return $this->relationship;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_type()
-	{
-		if ($this->type !== null)
-		{
-			return $this->type;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	function get_value()
-	{
-		if ($this->value !== null)
-		{
-			return $this->value;
-		}
-		else
-		{
-			return null;
-		}
-	}
-}
-
-/**
- * @todo Move to properly supporting RFC2616 (HTTP/1.1)
- */
-class SimplePie_File
-{
-	var $url;
-	var $useragent;
-	var $success = true;
-	var $headers = array();
-	var $body;
-	var $status_code;
-	var $redirects = 0;
-	var $error;
-	var $method = SIMPLEPIE_FILE_SOURCE_NONE;
-
-	function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
-	{
-		if (class_exists('idna_convert'))
-		{
-			$idn = new idna_convert;
-			$parsed = SimplePie_Misc::parse_url($url);
-			$url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
-		}
-		$this->url = $url;
-		$this->useragent = $useragent;
-		if (preg_match('/^http(s)?:\/\//i', $url))
-		{
-			if ($useragent === null)
-			{
-				$useragent = ini_get('user_agent');
-				$this->useragent = $useragent;
-			}
-			if (!is_array($headers))
-			{
-				$headers = array();
-			}
-			if (!$force_fsockopen && function_exists('curl_exec'))
-			{
-				$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
-				$fp = curl_init();
-				$headers2 = array();
-				foreach ($headers as $key => $value)
-				{
-					$headers2[] = "$key: $value";
-				}
-				if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
-				{
-					curl_setopt($fp, CURLOPT_ENCODING, '');
-				}
-				curl_setopt($fp, CURLOPT_URL, $url);
-				curl_setopt($fp, CURLOPT_HEADER, 1);
-				curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
-				curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
-				curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
-				curl_setopt($fp, CURLOPT_REFERER, $url);
-				curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
-				curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
-				if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
-				{
-					curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
-					curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
-				}
-
-				$this->headers = curl_exec($fp);
-				if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
-				{
-					curl_setopt($fp, CURLOPT_ENCODING, 'none');
-					$this->headers = curl_exec($fp);
-				}
-				if (curl_errno($fp))
-				{
-					$this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
-					$this->success = false;
-				}
-				else
-				{
-					$info = curl_getinfo($fp);
-					curl_close($fp);
-					$this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
-					$this->headers = array_pop($this->headers);
-					$parser = new SimplePie_HTTP_Parser($this->headers);
-					if ($parser->parse())
-					{
-						$this->headers = $parser->headers;
-						$this->body = $parser->body;
-						$this->status_code = $parser->status_code;
-						if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
-						{
-							$this->redirects++;
-							$location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
-							return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
-						}
-					}
-				}
-			}
-			else
-			{
-				$this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
-				$url_parts = parse_url($url);
-				if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
-				{
-					$url_parts['host'] = "ssl://$url_parts[host]";
-					$url_parts['port'] = 443;
-				}
-				if (!isset($url_parts['port']))
-				{
-					$url_parts['port'] = 80;
-				}
-				$fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
-				if (!$fp)
-				{
-					$this->error = 'fsockopen error: ' . $errstr;
-					$this->success = false;
-				}
-				else
-				{
-					stream_set_timeout($fp, $timeout);
-					if (isset($url_parts['path']))
-					{
-						if (isset($url_parts['query']))
-						{
-							$get = "$url_parts[path]?$url_parts[query]";
-						}
-						else
-						{
-							$get = $url_parts['path'];
-						}
-					}
-					else
-					{
-						$get = '/';
-					}
-					$out = "GET $get HTTP/1.0\r\n";
-					$out .= "Host: $url_parts[host]\r\n";
-					$out .= "User-Agent: $useragent\r\n";
-					if (extension_loaded('zlib'))
-					{
-						$out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
-					}
-
-					if (isset($url_parts['user']) && isset($url_parts['pass']))
-					{
-						$out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
-					}
-					foreach ($headers as $key => $value)
-					{
-						$out .= "$key: $value\r\n";
-					}
-					$out .= "Connection: Close\r\n\r\n";
-					fwrite($fp, $out);
-
-					$info = stream_get_meta_data($fp);
-
-					$this->headers = '';
-					while (!$info['eof'] && !$info['timed_out'])
-					{
-						$this->headers .= fread($fp, 1160);
-						$info = stream_get_meta_data($fp);
-					}
-					if (!$info['timed_out'])
-					{
-						$parser = new SimplePie_HTTP_Parser($this->headers);
-						if ($parser->parse())
-						{
-							$this->headers = $parser->headers;
-							$this->body = $parser->body;
-							$this->status_code = $parser->status_code;
-							if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
-							{
-								$this->redirects++;
-								$location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
-								return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
-							}
-							if (isset($this->headers['content-encoding']))
-							{
-								// Hey, we act dumb elsewhere, so let's do that here too
-								switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
-								{
-									case 'gzip':
-									case 'x-gzip':
-										$decoder = new SimplePie_gzdecode($this->body);
-										if (!$decoder->parse())
-										{
-											$this->error = 'Unable to decode HTTP "gzip" stream';
-											$this->success = false;
-										}
-										else
-										{
-											$this->body = $decoder->data;
-										}
-										break;
-
-									case 'deflate':
-										if (($body = gzuncompress($this->body)) === false)
-										{
-											if (($body = gzinflate($this->body)) === false)
-											{
-												$this->error = 'Unable to decode HTTP "deflate" stream';
-												$this->success = false;
-											}
-										}
-										$this->body = $body;
-										break;
-
-									default:
-										$this->error = 'Unknown content coding';
-										$this->success = false;
-								}
-							}
-						}
-					}
-					else
-					{
-						$this->error = 'fsocket timed out';
-						$this->success = false;
-					}
-					fclose($fp);
-				}
-			}
-		}
-		else
-		{
-			$this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
-			if (!$this->body = file_get_contents($url))
-			{
-				$this->error = 'file_get_contents could not read the file';
-				$this->success = false;
-			}
-		}
-	}
-}
-
-/**
- * HTTP Response Parser
- *
- * @package SimplePie
- */
-class SimplePie_HTTP_Parser
-{
-	/**
-	 * HTTP Version
-	 *
-	 * @access public
-	 * @var float
-	 */
-	var $http_version = 0.0;
-
-	/**
-	 * Status code
-	 *
-	 * @access public
-	 * @var int
-	 */
-	var $status_code = 0;
-
-	/**
-	 * Reason phrase
-	 *
-	 * @access public
-	 * @var string
-	 */
-	var $reason = '';
-
-	/**
-	 * Key/value pairs of the headers
-	 *
-	 * @access public
-	 * @var array
-	 */
-	var $headers = array();
-
-	/**
-	 * Body of the response
-	 *
-	 * @access public
-	 * @var string
-	 */
-	var $body = '';
-
-	/**
-	 * Current state of the state machine
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $state = 'http_version';
-
-	/**
-	 * Input data
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $data = '';
-
-	/**
-	 * Input data length (to avoid calling strlen() everytime this is needed)
-	 *
-	 * @access private
-	 * @var int
-	 */
-	var $data_length = 0;
-
-	/**
-	 * Current position of the pointer
-	 *
-	 * @var int
-	 * @access private
-	 */
-	var $position = 0;
-
-	/**
-	 * Name of the hedaer currently being parsed
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $name = '';
-
-	/**
-	 * Value of the hedaer currently being parsed
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $value = '';
-
-	/**
-	 * Create an instance of the class with the input data
-	 *
-	 * @access public
-	 * @param string $data Input data
-	 */
-	function SimplePie_HTTP_Parser($data)
-	{
-		$this->data = $data;
-		$this->data_length = strlen($this->data);
-	}
-
-	/**
-	 * Parse the input data
-	 *
-	 * @access public
-	 * @return bool true on success, false on failure
-	 */
-	function parse()
-	{
-		while ($this->state && $this->state !== 'emit' && $this->has_data())
-		{
-			$state = $this->state;
-			$this->$state();
-		}
-		$this->data = '';
-		if ($this->state === 'emit' || $this->state === 'body')
-		{
-			return true;
-		}
-		else
-		{
-			$this->http_version = '';
-			$this->status_code = '';
-			$this->reason = '';
-			$this->headers = array();
-			$this->body = '';
-			return false;
-		}
-	}
-
-	/**
-	 * Check whether there is data beyond the pointer
-	 *
-	 * @access private
-	 * @return bool true if there is further data, false if not
-	 */
-	function has_data()
-	{
-		return (bool) ($this->position < $this->data_length);
-	}
-
-	/**
-	 * See if the next character is LWS
-	 *
-	 * @access private
-	 * @return bool true if the next character is LWS, false if not
-	 */
-	function is_linear_whitespace()
-	{
-		return (bool) ($this->data[$this->position] === "\x09"
-			|| $this->data[$this->position] === "\x20"
-			|| ($this->data[$this->position] === "\x0A"
-				&& isset($this->data[$this->position + 1])
-				&& ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
-	}
-
-	/**
-	 * Parse the HTTP version
-	 *
-	 * @access private
-	 */
-	function http_version()
-	{
-		if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
-		{
-			$len = strspn($this->data, '0123456789.', 5);
-			$this->http_version = substr($this->data, 5, $len);
-			$this->position += 5 + $len;
-			if (substr_count($this->http_version, '.') <= 1)
-			{
-				$this->http_version = (float) $this->http_version;
-				$this->position += strspn($this->data, "\x09\x20", $this->position);
-				$this->state = 'status';
-			}
-			else
-			{
-				$this->state = false;
-			}
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-
-	/**
-	 * Parse the status code
-	 *
-	 * @access private
-	 */
-	function status()
-	{
-		if ($len = strspn($this->data, '0123456789', $this->position))
-		{
-			$this->status_code = (int) substr($this->data, $this->position, $len);
-			$this->position += $len;
-			$this->state = 'reason';
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-
-	/**
-	 * Parse the reason phrase
-	 *
-	 * @access private
-	 */
-	function reason()
-	{
-		$len = strcspn($this->data, "\x0A", $this->position);
-		$this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
-		$this->position += $len + 1;
-		$this->state = 'new_line';
-	}
-
-	/**
-	 * Deal with a new line, shifting data around as needed
-	 *
-	 * @access private
-	 */
-	function new_line()
-	{
-		$this->value = trim($this->value, "\x0D\x20");
-		if ($this->name !== '' && $this->value !== '')
-		{
-			$this->name = strtolower($this->name);
-			if (isset($this->headers[$this->name]))
-			{
-				$this->headers[$this->name] .= ', ' . $this->value;
-			}
-			else
-			{
-				$this->headers[$this->name] = $this->value;
-			}
-		}
-		$this->name = '';
-		$this->value = '';
-		if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
-		{
-			$this->position += 2;
-			$this->state = 'body';
-		}
-		elseif ($this->data[$this->position] === "\x0A")
-		{
-			$this->position++;
-			$this->state = 'body';
-		}
-		else
-		{
-			$this->state = 'name';
-		}
-	}
-
-	/**
-	 * Parse a header name
-	 *
-	 * @access private
-	 */
-	function name()
-	{
-		$len = strcspn($this->data, "\x0A:", $this->position);
-		if (isset($this->data[$this->position + $len]))
-		{
-			if ($this->data[$this->position + $len] === "\x0A")
-			{
-				$this->position += $len;
-				$this->state = 'new_line';
-			}
-			else
-			{
-				$this->name = substr($this->data, $this->position, $len);
-				$this->position += $len + 1;
-				$this->state = 'value';
-			}
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-
-	/**
-	 * Parse LWS, replacing consecutive LWS characters with a single space
-	 *
-	 * @access private
-	 */
-	function linear_whitespace()
-	{
-		do
-		{
-			if (substr($this->data, $this->position, 2) === "\x0D\x0A")
-			{
-				$this->position += 2;
-			}
-			elseif ($this->data[$this->position] === "\x0A")
-			{
-				$this->position++;
-			}
-			$this->position += strspn($this->data, "\x09\x20", $this->position);
-		} while ($this->has_data() && $this->is_linear_whitespace());
-		$this->value .= "\x20";
-	}
-
-	/**
-	 * See what state to move to while within non-quoted header values
-	 *
-	 * @access private
-	 */
-	function value()
-	{
-		if ($this->is_linear_whitespace())
-		{
-			$this->linear_whitespace();
-		}
-		else
-		{
-			switch ($this->data[$this->position])
-			{
-				case '"':
-					$this->position++;
-					$this->state = 'quote';
-					break;
-
-				case "\x0A":
-					$this->position++;
-					$this->state = 'new_line';
-					break;
-
-				default:
-					$this->state = 'value_char';
-					break;
-			}
-		}
-	}
-
-	/**
-	 * Parse a header value while outside quotes
-	 *
-	 * @access private
-	 */
-	function value_char()
-	{
-		$len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
-		$this->value .= substr($this->data, $this->position, $len);
-		$this->position += $len;
-		$this->state = 'value';
-	}
-
-	/**
-	 * See what state to move to while within quoted header values
-	 *
-	 * @access private
-	 */
-	function quote()
-	{
-		if ($this->is_linear_whitespace())
-		{
-			$this->linear_whitespace();
-		}
-		else
-		{
-			switch ($this->data[$this->position])
-			{
-				case '"':
-					$this->position++;
-					$this->state = 'value';
-					break;
-
-				case "\x0A":
-					$this->position++;
-					$this->state = 'new_line';
-					break;
-
-				case '\\':
-					$this->position++;
-					$this->state = 'quote_escaped';
-					break;
-
-				default:
-					$this->state = 'quote_char';
-					break;
-			}
-		}
-	}
-
-	/**
-	 * Parse a header value while within quotes
-	 *
-	 * @access private
-	 */
-	function quote_char()
-	{
-		$len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
-		$this->value .= substr($this->data, $this->position, $len);
-		$this->position += $len;
-		$this->state = 'value';
-	}
-
-	/**
-	 * Parse an escaped character within quotes
-	 *
-	 * @access private
-	 */
-	function quote_escaped()
-	{
-		$this->value .= $this->data[$this->position];
-		$this->position++;
-		$this->state = 'quote';
-	}
-
-	/**
-	 * Parse the body
-	 *
-	 * @access private
-	 */
-	function body()
-	{
-		$this->body = substr($this->data, $this->position);
-		$this->state = 'emit';
-	}
-}
-
-/**
- * gzdecode
- *
- * @package SimplePie
- */
-class SimplePie_gzdecode
-{
-	/**
-	 * Compressed data
-	 *
-	 * @access private
-	 * @see gzdecode::$data
-	 */
-	var $compressed_data;
-
-	/**
-	 * Size of compressed data
-	 *
-	 * @access private
-	 */
-	var $compressed_size;
-
-	/**
-	 * Minimum size of a valid gzip string
-	 *
-	 * @access private
-	 */
-	var $min_compressed_size = 18;
-
-	/**
-	 * Current position of pointer
-	 *
-	 * @access private
-	 */
-	var $position = 0;
-
-	/**
-	 * Flags (FLG)
-	 *
-	 * @access private
-	 */
-	var $flags;
-
-	/**
-	 * Uncompressed data
-	 *
-	 * @access public
-	 * @see gzdecode::$compressed_data
-	 */
-	var $data;
-
-	/**
-	 * Modified time
-	 *
-	 * @access public
-	 */
-	var $MTIME;
-
-	/**
-	 * Extra Flags
-	 *
-	 * @access public
-	 */
-	var $XFL;
-
-	/**
-	 * Operating System
-	 *
-	 * @access public
-	 */
-	var $OS;
-
-	/**
-	 * Subfield ID 1
-	 *
-	 * @access public
-	 * @see gzdecode::$extra_field
-	 * @see gzdecode::$SI2
-	 */
-	var $SI1;
-
-	/**
-	 * Subfield ID 2
-	 *
-	 * @access public
-	 * @see gzdecode::$extra_field
-	 * @see gzdecode::$SI1
-	 */
-	var $SI2;
-
-	/**
-	 * Extra field content
-	 *
-	 * @access public
-	 * @see gzdecode::$SI1
-	 * @see gzdecode::$SI2
-	 */
-	var $extra_field;
-
-	/**
-	 * Original filename
-	 *
-	 * @access public
-	 */
-	var $filename;
-
-	/**
-	 * Human readable comment
-	 *
-	 * @access public
-	 */
-	var $comment;
-
-	/**
-	 * Don't allow anything to be set
-	 *
-	 * @access public
-	 */
-	function __set($name, $value)
-	{
-		trigger_error("Cannot write property $name", E_USER_ERROR);
-	}
-
-	/**
-	 * Set the compressed string and related properties
-	 *
-	 * @access public
-	 */
-	function SimplePie_gzdecode($data)
-	{
-		$this->compressed_data = $data;
-		$this->compressed_size = strlen($data);
-	}
-
-	/**
-	 * Decode the GZIP stream
-	 *
-	 * @access public
-	 */
-	function parse()
-	{
-		if ($this->compressed_size >= $this->min_compressed_size)
-		{
-			// Check ID1, ID2, and CM
-			if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
-			{
-				return false;
-			}
-
-			// Get the FLG (FLaGs)
-			$this->flags = ord($this->compressed_data[3]);
-
-			// FLG bits above (1 << 4) are reserved
-			if ($this->flags > 0x1F)
-			{
-				return false;
-			}
-
-			// Advance the pointer after the above
-			$this->position += 4;
-
-			// MTIME
-			$mtime = substr($this->compressed_data, $this->position, 4);
-			// Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
-			if (current(unpack('S', "\x00\x01")) === 1)
-			{
-				$mtime = strrev($mtime);
-			}
-			$this->MTIME = current(unpack('l', $mtime));
-			$this->position += 4;
-
-			// Get the XFL (eXtra FLags)
-			$this->XFL = ord($this->compressed_data[$this->position++]);
-
-			// Get the OS (Operating System)
-			$this->OS = ord($this->compressed_data[$this->position++]);
-
-			// Parse the FEXTRA
-			if ($this->flags & 4)
-			{
-				// Read subfield IDs
-				$this->SI1 = $this->compressed_data[$this->position++];
-				$this->SI2 = $this->compressed_data[$this->position++];
-
-				// SI2 set to zero is reserved for future use
-				if ($this->SI2 === "\x00")
-				{
-					return false;
-				}
-
-				// Get the length of the extra field
-				$len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
-				$position += 2;
-
-				// Check the length of the string is still valid
-				$this->min_compressed_size += $len + 4;
-				if ($this->compressed_size >= $this->min_compressed_size)
-				{
-					// Set the extra field to the given data
-					$this->extra_field = substr($this->compressed_data, $this->position, $len);
-					$this->position += $len;
-				}
-				else
-				{
-					return false;
-				}
-			}
-
-			// Parse the FNAME
-			if ($this->flags & 8)
-			{
-				// Get the length of the filename
-				$len = strcspn($this->compressed_data, "\x00", $this->position);
-
-				// Check the length of the string is still valid
-				$this->min_compressed_size += $len + 1;
-				if ($this->compressed_size >= $this->min_compressed_size)
-				{
-					// Set the original filename to the given string
-					$this->filename = substr($this->compressed_data, $this->position, $len);
-					$this->position += $len + 1;
-				}
-				else
-				{
-					return false;
-				}
-			}
-
-			// Parse the FCOMMENT
-			if ($this->flags & 16)
-			{
-				// Get the length of the comment
-				$len = strcspn($this->compressed_data, "\x00", $this->position);
-
-				// Check the length of the string is still valid
-				$this->min_compressed_size += $len + 1;
-				if ($this->compressed_size >= $this->min_compressed_size)
-				{
-					// Set the original comment to the given string
-					$this->comment = substr($this->compressed_data, $this->position, $len);
-					$this->position += $len + 1;
-				}
-				else
-				{
-					return false;
-				}
-			}
-
-			// Parse the FHCRC
-			if ($this->flags & 2)
-			{
-				// Check the length of the string is still valid
-				$this->min_compressed_size += $len + 2;
-				if ($this->compressed_size >= $this->min_compressed_size)
-				{
-					// Read the CRC
-					$crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
-
-					// Check the CRC matches
-					if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
-					{
-						$this->position += 2;
-					}
-					else
-					{
-						return false;
-					}
-				}
-				else
-				{
-					return false;
-				}
-			}
-
-			// Decompress the actual data
-			if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
-			{
-				return false;
-			}
-			else
-			{
-				$this->position = $this->compressed_size - 8;
-			}
-
-			// Check CRC of data
-			$crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
-			$this->position += 4;
-			/*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
-			{
-				return false;
-			}*/
-
-			// Check ISIZE of data
-			$isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
-			$this->position += 4;
-			if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
-			{
-				return false;
-			}
-
-			// Wow, against all odds, we've actually got a valid gzip string
-			return true;
-		}
-		else
-		{
-			return false;
-		}
-	}
-}
-
-class SimplePie_Cache
-{
-	/**
-	 * Don't call the constructor. Please.
-	 *
-	 * @access private
-	 */
-	function SimplePie_Cache()
-	{
-		trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
-	}
-
-	/**
-	 * Create a new SimplePie_Cache object
-	 *
-	 * @static
-	 * @access public
-	 */
-	function create($location, $filename, $extension)
-	{
-		$location_iri = new SimplePie_IRI($location);
-		switch ($location_iri->get_scheme())
-		{
-			case 'mysql':
-				if (extension_loaded('mysql'))
-				{
-					return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
-				}
-				break;
-
-			default:
-				return new SimplePie_Cache_File($location, $filename, $extension);
-		}
-	}
-}
-
-class SimplePie_Cache_File
-{
-	var $location;
-	var $filename;
-	var $extension;
-	var $name;
-
-	function SimplePie_Cache_File($location, $filename, $extension)
-	{
-		$this->location = $location;
-		$this->filename = $filename;
-		$this->extension = $extension;
-		$this->name = "$this->location/$this->filename.$this->extension";
-	}
-
-	function save($data)
-	{
-		if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
-		{
-			if (is_a($data, 'SimplePie'))
-			{
-				$data = $data->data;
-			}
-
-			$data = serialize($data);
-
-			if (function_exists('file_put_contents'))
-			{
-				return (bool) file_put_contents($this->name, $data);
-			}
-			else
-			{
-				$fp = fopen($this->name, 'wb');
-				if ($fp)
-				{
-					fwrite($fp, $data);
-					fclose($fp);
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-
-	function load()
-	{
-		if (file_exists($this->name) && is_readable($this->name))
-		{
-			return unserialize(file_get_contents($this->name));
-		}
-		return false;
-	}
-
-	function mtime()
-	{
-		if (file_exists($this->name))
-		{
-			return filemtime($this->name);
-		}
-		return false;
-	}
-
-	function touch()
-	{
-		if (file_exists($this->name))
-		{
-			return touch($this->name);
-		}
-		return false;
-	}
-
-	function unlink()
-	{
-		if (file_exists($this->name))
-		{
-			return unlink($this->name);
-		}
-		return false;
-	}
-}
-
-class SimplePie_Cache_DB
-{
-	function prepare_simplepie_object_for_cache($data)
-	{
-		$items = $data->get_items();
-		$items_by_id = array();
-
-		if (!empty($items))
-		{
-			foreach ($items as $item)
-			{
-				$items_by_id[$item->get_id()] = $item;
-			}
-
-			if (count($items_by_id) !== count($items))
-			{
-				$items_by_id = array();
-				foreach ($items as $item)
-				{
-					$items_by_id[$item->get_id(true)] = $item;
-				}
-			}
-
-			if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
-			{
-				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
-			}
-			elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
-			{
-				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
-			}
-			elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
-			{
-				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
-			}
-			elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
-			{
-				$channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
-			}
-			else
-			{
-				$channel = null;
-			}
-
-			if ($channel !== null)
-			{
-				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
-				{
-					unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
-				}
-				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
-				{
-					unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
-				}
-				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
-				{
-					unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
-				}
-				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
-				{
-					unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
-				}
-				if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
-				{
-					unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
-				}
-			}
-			if (isset($data->data['items']))
-			{
-				unset($data->data['items']);
-			}
-			if (isset($data->data['ordered_items']))
-			{
-				unset($data->data['ordered_items']);
-			}
-		}
-		return array(serialize($data->data), $items_by_id);
-	}
-}
-
-class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
-{
-	var $mysql;
-	var $options;
-	var $id;
-
-	function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
-	{
-		$host = $mysql_location->get_host();
-		if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
-		{
-			$server = ':' . substr($host, 5, -1);
-		}
-		else
-		{
-			$server = $host;
-			if ($mysql_location->get_port() !== null)
-			{
-				$server .= ':' . $mysql_location->get_port();
-			}
-		}
-
-		if (strpos($mysql_location->get_userinfo(), ':') !== false)
-		{
-			list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
-		}
-		else
-		{
-			$username = $mysql_location->get_userinfo();
-			$password = null;
-		}
-
-		if ($this->mysql = mysql_connect($server, $username, $password))
-		{
-			$this->id = $name . $extension;
-			$this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
-			if (!isset($this->options['prefix'][0]))
-			{
-				$this->options['prefix'][0] = '';
-			}
-
-			if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
-				&& mysql_query('SET NAMES utf8')
-				&& ($query = mysql_unbuffered_query('SHOW TABLES')))
-			{
-				$db = array();
-				while ($row = mysql_fetch_row($query))
-				{
-					$db[] = $row[0];
-				}
-
-				if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
-				{
-					if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))'))
-					{
-						$this->mysql = null;
-					}
-				}
-
-				if (!in_array($this->options['prefix'][0] . 'items', $db))
-				{
-					if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))'))
-					{
-						$this->mysql = null;
-					}
-				}
-			}
-			else
-			{
-				$this->mysql = null;
-			}
-		}
-	}
-
-	function save($data)
-	{
-		if ($this->mysql)
-		{
-			$feed_id = "'" . mysql_real_escape_string($this->id) . "'";
-
-			if (is_a($data, 'SimplePie'))
-			{
-				if (SIMPLEPIE_PHP5)
-				{
-					// This keyword needs to defy coding standards for PHP4 compatibility
-					$data = clone($data);
-				}
-
-				$prepared = $this->prepare_simplepie_object_for_cache($data);
-
-				if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
-				{
-					if (mysql_num_rows($query))
-					{
-						$items = count($prepared[1]);
-						if ($items)
-						{
-							$sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
-						}
-						else
-						{
-							$sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
-						}
-
-						if (!mysql_query($sql, $this->mysql))
-						{
-							return false;
-						}
-					}
-					elseif (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(' . $feed_id . ', ' . count($prepared[1]) . ', \'' . mysql_real_escape_string($prepared[0]) . '\', ' . time() . ')', $this->mysql))
-					{
-						return false;
-					}
-
-					$ids = array_keys($prepared[1]);
-					if (!empty($ids))
-					{
-						foreach ($ids as $id)
-						{
-							$database_ids[] = mysql_real_escape_string($id);
-						}
-
-						if ($query = mysql_unbuffered_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'items` WHERE `id` = \'' . implode('\' OR `id` = \'', $database_ids) . '\' AND `feed_id` = ' . $feed_id, $this->mysql))
-						{
-							$existing_ids = array();
-							while ($row = mysql_fetch_row($query))
-							{
-								$existing_ids[] = $row[0];
-							}
-
-							$new_ids = array_diff($ids, $existing_ids);
-
-							foreach ($new_ids as $new_id)
-							{
-								if (!($date = $prepared[1][$new_id]->get_date('U')))
-								{
-									$date = time();
-								}
-
-								if (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(' . $feed_id . ', \'' . mysql_real_escape_string($new_id) . '\', \'' . mysql_real_escape_string(serialize($prepared[1][$new_id]->data)) . '\', ' . $date . ')', $this->mysql))
-								{
-									return false;
-								}
-							}
-							return true;
-						}
-					}
-					else
-					{
-						return true;
-					}
-				}
-			}
-			elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
-			{
-				if (mysql_num_rows($query))
-				{
-					if (mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = 0, `data` = \'' . mysql_real_escape_string(serialize($data)) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id, $this->mysql))
-					{
-						return true;
-					}
-				}
-				elseif (mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(\'' . mysql_real_escape_string($this->id) . '\', 0, \'' . mysql_real_escape_string(serialize($data)) . '\', ' . time() . ')', $this->mysql))
-				{
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-
-	function load()
-	{
-		if ($this->mysql && ($query = mysql_query('SELECT `items`, `data` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
-		{
-			$data = unserialize($row[1]);
-
-			if (isset($this->options['items'][0]))
-			{
-				$items = (int) $this->options['items'][0];
-			}
-			else
-			{
-				$items = (int) $row[0];
-			}
-
-			if ($items !== 0)
-			{
-				if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
-				{
-					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
-				}
-				elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
-				{
-					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
-				}
-				elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
-				{
-					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
-				}
-				elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
-				{
-					$feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
-				}
-				else
-				{
-					$feed = null;
-				}
-
-				if ($feed !== null)
-				{
-					$sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
-					if ($items > 0)
-					{
-						$sql .= ' LIMIT ' . $items;
-					}
-
-					if ($query = mysql_unbuffered_query($sql, $this->mysql))
-					{
-						while ($row = mysql_fetch_row($query))
-						{
-							$feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
-						}
-					}
-					else
-					{
-						return false;
-					}
-				}
-			}
-			return $data;
-		}
-		return false;
-	}
-
-	function mtime()
-	{
-		if ($this->mysql && ($query = mysql_query('SELECT `mtime` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
-		{
-			return $row[0];
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	function touch()
-	{
-		if ($this->mysql && ($query = mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `mtime` = ' . time() . ' WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && mysql_affected_rows($this->mysql))
-		{
-			return true;
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	function unlink()
-	{
-		if ($this->mysql && ($query = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($query2 = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)))
-		{
-			return true;
-		}
-		else
-		{
-			return false;
-		}
-	}
-}
-
-class SimplePie_Misc
-{
-	function time_hms($seconds)
-	{
-		$time = '';
-
-		$hours = floor($seconds / 3600);
-		$remainder = $seconds % 3600;
-		if ($hours > 0)
-		{
-			$time .= $hours.':';
-		}
-
-		$minutes = floor($remainder / 60);
-		$seconds = $remainder % 60;
-		if ($minutes < 10 && $hours > 0)
-		{
-			$minutes = '0' . $minutes;
-		}
-		if ($seconds < 10)
-		{
-			$seconds = '0' . $seconds;
-		}
-
-		$time .= $minutes.':';
-		$time .= $seconds;
-
-		return $time;
-	}
-
-	function absolutize_url($relative, $base)
-	{
-return $relative;
-		$iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
-		return $iri->get_iri();
-	}
-
-	function remove_dot_segments($input)
-	{
-		$output = '';
-		while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
-		{
-			// A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
-			if (strpos($input, '../') === 0)
-			{
-				$input = substr($input, 3);
-			}
-			elseif (strpos($input, './') === 0)
-			{
-				$input = substr($input, 2);
-			}
-			// B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
-			elseif (strpos($input, '/./') === 0)
-			{
-				$input = substr_replace($input, '/', 0, 3);
-			}
-			elseif ($input === '/.')
-			{
-				$input = '/';
-			}
-			// C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
-			elseif (strpos($input, '/../') === 0)
-			{
-				$input = substr_replace($input, '/', 0, 4);
-				$output = substr_replace($output, '', strrpos($output, '/'));
-			}
-			elseif ($input === '/..')
-			{
-				$input = '/';
-				$output = substr_replace($output, '', strrpos($output, '/'));
-			}
-			// D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
-			elseif ($input === '.' || $input === '..')
-			{
-				$input = '';
-			}
-			// E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
-			elseif (($pos = strpos($input, '/', 1)) !== false)
-			{
-				$output .= substr($input, 0, $pos);
-				$input = substr_replace($input, '', 0, $pos);
-			}
-			else
-			{
-				$output .= $input;
-				$input = '';
-			}
-		}
-		return $output . $input;
-	}
-
-	function get_element($realname, $string)
-	{
-		$return = array();
-		$name = preg_quote($realname, '/');
-		if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
-		{
-			for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
-			{
-				$return[$i]['tag'] = $realname;
-				$return[$i]['full'] = $matches[$i][0][0];
-				$return[$i]['offset'] = $matches[$i][0][1];
-				if (strlen($matches[$i][3][0]) <= 2)
-				{
-					$return[$i]['self_closing'] = true;
-				}
-				else
-				{
-					$return[$i]['self_closing'] = false;
-					$return[$i]['content'] = $matches[$i][4][0];
-				}
-				$return[$i]['attribs'] = array();
-				if (isset($matches[$i][2][0]) && preg_match_all('/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*)(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER))
-				{
-					for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
-					{
-						if (count($attribs[$j]) === 2)
-						{
-							$attribs[$j][2] = $attribs[$j][1];
-						}
-						$return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
-					}
-				}
-			}
-		}
-		return $return;
-	}
-
-	function element_implode($element)
-	{
-		$full = "<$element[tag]";
-		foreach ($element['attribs'] as $key => $value)
-		{
-			$key = strtolower($key);
-			$full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
-		}
-		if ($element['self_closing'])
-		{
-			$full .= ' />';
-		}
-		else
-		{
-			$full .= ">$element[content]</$element[tag]>";
-		}
-		return $full;
-	}
-
-	function error($message, $level, $file, $line)
-	{
-		if ((ini_get('error_reporting') & $level) > 0)
-		{
-			switch ($level)
-			{
-				case E_USER_ERROR:
-					$note = 'PHP Error';
-					break;
-				case E_USER_WARNING:
-					$note = 'PHP Warning';
-					break;
-				case E_USER_NOTICE:
-					$note = 'PHP Notice';
-					break;
-				default:
-					$note = 'Unknown Error';
-					break;
-			}
-
-			$log_error = true;
-			if (!function_exists('error_log'))
-			{
-				$log_error = false;
-			}
-
-			$log_file = @ini_get('error_log');
-			if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
-			{
-				$log_error = false;
-			}
-
-			if ($log_error)
-			{
-				@error_log("$note: $message in $file on line $line", 0);
-			}
-		}
-
-		return $message;
-	}
-
-	/**
-	 * If a file has been cached, retrieve and display it.
-	 *
-	 * This is most useful for caching images (get_favicon(), etc.),
-	 * however it works for all cached files.  This WILL NOT display ANY
-	 * file/image/page/whatever, but rather only display what has already
-	 * been cached by SimplePie.
-	 *
-	 * @access public
-	 * @see SimplePie::get_favicon()
-	 * @param str $identifier_url URL that is used to identify the content.
-	 * This may or may not be the actual URL of the live content.
-	 * @param str $cache_location Location of SimplePie's cache.  Defaults
-	 * to './cache'.
-	 * @param str $cache_extension The file extension that the file was
-	 * cached with.  Defaults to 'spc'.
-	 * @param str $cache_class Name of the cache-handling class being used
-	 * in SimplePie.  Defaults to 'SimplePie_Cache', and should be left
-	 * as-is unless you've overloaded the class.
-	 * @param str $cache_name_function Obsolete. Exists for backwards
-	 * compatibility reasons only.
-	 */
-	function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
-	{
-		$cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
-
-		if ($file = $cache->load())
-		{
-			if (isset($file['headers']['content-type']))
-			{
-				header('Content-type:' . $file['headers']['content-type']);
-			}
-			else
-			{
-				header('Content-type: application/octet-stream');
-			}
-			header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
-			echo $file['body'];
-			exit;
-		}
-
-		die('Cached file for ' . $identifier_url . ' cannot be found.');
-	}
-
-	function fix_protocol($url, $http = 1)
-	{
-		$url = SimplePie_Misc::normalize_url($url);
-		$parsed = SimplePie_Misc::parse_url($url);
-		if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
-		{
-			return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
-		}
-
-		if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
-		{
-			return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
-		}
-
-		if ($http === 2 && $parsed['scheme'] !== '')
-		{
-			return "feed:$url";
-		}
-		elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
-		{
-			return substr_replace($url, 'podcast', 0, 4);
-		}
-		elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
-		{
-			return substr_replace($url, 'itpc', 0, 4);
-		}
-		else
-		{
-			return $url;
-		}
-	}
-
-	function parse_url($url)
-	{
-		$iri = new SimplePie_IRI($url);
-		return array(
-			'scheme' => (string) $iri->get_scheme(),
-			'authority' => (string) $iri->get_authority(),
-			'path' => (string) $iri->get_path(),
-			'query' => (string) $iri->get_query(),
-			'fragment' => (string) $iri->get_fragment()
-		);
-	}
-
-	function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
-	{
-		$iri = new SimplePie_IRI('');
-		$iri->set_scheme($scheme);
-		$iri->set_authority($authority);
-		$iri->set_path($path);
-		$iri->set_query($query);
-		$iri->set_fragment($fragment);
-		return $iri->get_iri();
-	}
-
-	function normalize_url($url)
-	{
-		$iri = new SimplePie_IRI($url);
-		return $iri->get_iri();
-	}
-
-	function percent_encoding_normalization($match)
-	{
-		$integer = hexdec($match[1]);
-		if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
-		{
-			return chr($integer);
-		}
-		else
-		{
-			return strtoupper($match[0]);
-		}
-	}
-
-	/**
-	 * Remove bad UTF-8 bytes
-	 *
-	 * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
-	 * FAQ: Multilingual Forms (modified to include full ASCII range)
-	 *
-	 * @author Geoffrey Sneddon
-	 * @see http://www.w3.org/International/questions/qa-forms-utf-8
-	 * @param string $str String to remove bad UTF-8 bytes from
-	 * @return string UTF-8 string
-	 */
-	function utf8_bad_replace($str)
-	{
-		if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
-		{
-			return $return;
-		}
-		elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
-		{
-			return $return;
-		}
-		elseif (preg_match_all('/(?:[\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})+/', $str, $matches))
-		{
-			return implode("\xEF\xBF\xBD", $matches[0]);
-		}
-		elseif ($str !== '')
-		{
-			return "\xEF\xBF\xBD";
-		}
-		else
-		{
-			return '';
-		}
-	}
-
-	/**
-	 * Converts a Windows-1252 encoded string to a UTF-8 encoded string
-	 *
-	 * @static
-	 * @access public
-	 * @param string $string Windows-1252 encoded string
-	 * @return string UTF-8 encoded string
-	 */
-	function windows_1252_to_utf8($string)
-	{
-		static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF");
-
-		return strtr($string, $convert_table);
-	}
-
-	function change_encoding($data, $input, $output)
-	{
-		$input = SimplePie_Misc::encoding($input);
-		$output = SimplePie_Misc::encoding($output);
-
-		// We fail to fail on non US-ASCII bytes
-		if ($input === 'US-ASCII')
-		{
-			static $non_ascii_octects = '';
-			if (!$non_ascii_octects)
-			{
-				for ($i = 0x80; $i <= 0xFF; $i++)
-				{
-					$non_ascii_octects .= chr($i);
-				}
-			}
-			$data = substr($data, 0, strcspn($data, $non_ascii_octects));
-		}
-
-		// This is first, as behaviour of this is completely predictable
-		if ($input === 'Windows-1252' && $output === 'UTF-8')
-		{
-			return SimplePie_Misc::windows_1252_to_utf8($data);
-		}
-		// This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
-		elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
-		{
-			return $return;
-		}
-		// This is last, as behaviour of this varies with OS userland and PHP version
-		elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
-		{
-			return $return;
-		}
-		// If we can't do anything, just fail
-		else
-		{
-			return false;
-		}
-	}
-
-	function encoding($charset)
-	{
-		// Normalization from UTS #22
-		switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
-		{
-			case 'adobestandardencoding':
-			case 'csadobestandardencoding':
-				return 'Adobe-Standard-Encoding';
-
-			case 'adobesymbolencoding':
-			case 'cshppsmath':
-				return 'Adobe-Symbol-Encoding';
-
-			case 'ami1251':
-			case 'amiga1251':
-				return 'Amiga-1251';
-
-			case 'ansix31101983':
-			case 'csat5001983':
-			case 'csiso99naplps':
-			case 'isoir99':
-			case 'naplps':
-				return 'ANSI_X3.110-1983';
-
-			case 'arabic7':
-			case 'asmo449':
-			case 'csiso89asmo449':
-			case 'iso9036':
-			case 'isoir89':
-				return 'ASMO_449';
-
-			case 'big5':
-			case 'csbig5':
-			case 'xxbig5':
-				return 'Big5';
-
-			case 'big5hkscs':
-				return 'Big5-HKSCS';
-
-			case 'bocu1':
-			case 'csbocu1':
-				return 'BOCU-1';
-
-			case 'brf':
-			case 'csbrf':
-				return 'BRF';
-
-			case 'bs4730':
-			case 'csiso4unitedkingdom':
-			case 'gb':
-			case 'iso646gb':
-			case 'isoir4':
-			case 'uk':
-				return 'BS_4730';
-
-			case 'bsviewdata':
-			case 'csiso47bsviewdata':
-			case 'isoir47':
-				return 'BS_viewdata';
-
-			case 'cesu8':
-			case 'cscesu8':
-				return 'CESU-8';
-
-			case 'ca':
-			case 'csa71':
-			case 'csaz243419851':
-			case 'csiso121canadian1':
-			case 'iso646ca':
-			case 'isoir121':
-				return 'CSA_Z243.4-1985-1';
-
-			case 'csa72':
-			case 'csaz243419852':
-			case 'csiso122canadian2':
-			case 'iso646ca2':
-			case 'isoir122':
-				return 'CSA_Z243.4-1985-2';
-
-			case 'csaz24341985gr':
-			case 'csiso123csaz24341985gr':
-			case 'isoir123':
-				return 'CSA_Z243.4-1985-gr';
-
-			case 'csiso139csn369103':
-			case 'csn369103':
-			case 'isoir139':
-				return 'CSN_369103';
-
-			case 'csdecmcs':
-			case 'dec':
-			case 'decmcs':
-				return 'DEC-MCS';
-
-			case 'csiso21german':
-			case 'de':
-			case 'din66003':
-			case 'iso646de':
-			case 'isoir21':
-				return 'DIN_66003';
-
-			case 'csdkus':
-			case 'dkus':
-				return 'dk-us';
-
-			case 'csiso646danish':
-			case 'dk':
-			case 'ds2089':
-			case 'iso646dk':
-				return 'DS_2089';
-
-			case 'csibmebcdicatde':
-			case 'ebcdicatde':
-				return 'EBCDIC-AT-DE';
-
-			case 'csebcdicatdea':
-			case 'ebcdicatdea':
-				return 'EBCDIC-AT-DE-A';
-
-			case 'csebcdiccafr':
-			case 'ebcdiccafr':
-				return 'EBCDIC-CA-FR';
-
-			case 'csebcdicdkno':
-			case 'ebcdicdkno':
-				return 'EBCDIC-DK-NO';
-
-			case 'csebcdicdknoa':
-			case 'ebcdicdknoa':
-				return 'EBCDIC-DK-NO-A';
-
-			case 'csebcdices':
-			case 'ebcdices':
-				return 'EBCDIC-ES';
-
-			case 'csebcdicesa':
-			case 'ebcdicesa':
-				return 'EBCDIC-ES-A';
-
-			case 'csebcdicess':
-			case 'ebcdicess':
-				return 'EBCDIC-ES-S';
-
-			case 'csebcdicfise':
-			case 'ebcdicfise':
-				return 'EBCDIC-FI-SE';
-
-			case 'csebcdicfisea':
-			case 'ebcdicfisea':
-				return 'EBCDIC-FI-SE-A';
-
-			case 'csebcdicfr':
-			case 'ebcdicfr':
-				return 'EBCDIC-FR';
-
-			case 'csebcdicit':
-			case 'ebcdicit':
-				return 'EBCDIC-IT';
-
-			case 'csebcdicpt':
-			case 'ebcdicpt':
-				return 'EBCDIC-PT';
-
-			case 'csebcdicuk':
-			case 'ebcdicuk':
-				return 'EBCDIC-UK';
-
-			case 'csebcdicus':
-			case 'ebcdicus':
-				return 'EBCDIC-US';
-
-			case 'csiso111ecmacyrillic':
-			case 'ecmacyrillic':
-			case 'isoir111':
-			case 'koi8e':
-				return 'ECMA-cyrillic';
-
-			case 'csiso17spanish':
-			case 'es':
-			case 'iso646es':
-			case 'isoir17':
-				return 'ES';
-
-			case 'csiso85spanish2':
-			case 'es2':
-			case 'iso646es2':
-			case 'isoir85':
-				return 'ES2';
-
-			case 'cseucfixwidjapanese':
-			case 'extendedunixcodefixedwidthforjapanese':
-				return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
-
-			case 'cseucpkdfmtjapanese':
-			case 'eucjp':
-			case 'extendedunixcodepackedformatforjapanese':
-				return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
-
-			case 'gb18030':
-				return 'GB18030';
-
-			case 'chinese':
-			case 'cp936':
-			case 'csgb2312':
-			case 'csiso58gb231280':
-			case 'gb2312':
-			case 'gb231280':
-			case 'gbk':
-			case 'isoir58':
-			case 'ms936':
-			case 'windows936':
-				return 'GBK';
-
-			case 'cn':
-			case 'csiso57gb1988':
-			case 'gb198880':
-			case 'iso646cn':
-			case 'isoir57':
-				return 'GB_1988-80';
-
-			case 'csiso153gost1976874':
-			case 'gost1976874':
-			case 'isoir153':
-			case 'stsev35888':
-				return 'GOST_19768-74';
-
-			case 'csiso150':
-			case 'csiso150greekccitt':
-			case 'greekccitt':
-			case 'isoir150':
-				return 'greek-ccitt';
-
-			case 'csiso88greek7':
-			case 'greek7':
-			case 'isoir88':
-				return 'greek7';
-
-			case 'csiso18greek7old':
-			case 'greek7old':
-			case 'isoir18':
-				return 'greek7-old';
-
-			case 'cshpdesktop':
-			case 'hpdesktop':
-				return 'HP-DeskTop';
-
-			case 'cshplegal':
-			case 'hplegal':
-				return 'HP-Legal';
-
-			case 'cshpmath8':
-			case 'hpmath8':
-				return 'HP-Math8';
-
-			case 'cshppifont':
-			case 'hppifont':
-				return 'HP-Pi-font';
-
-			case 'cshproman8':
-			case 'hproman8':
-			case 'r8':
-			case 'roman8':
-				return 'hp-roman8';
-
-			case 'hzgb2312':
-				return 'HZ-GB-2312';
-
-			case 'csibmsymbols':
-			case 'ibmsymbols':
-				return 'IBM-Symbols';
-
-			case 'csibmthai':
-			case 'ibmthai':
-				return 'IBM-Thai';
-
-			case 'ccsid858':
-			case 'cp858':
-			case 'ibm858':
-			case 'pcmultilingual850euro':
-				return 'IBM00858';
-
-			case 'ccsid924':
-			case 'cp924':
-			case 'ebcdiclatin9euro':
-			case 'ibm924':
-				return 'IBM00924';
-
-			case 'ccsid1140':
-			case 'cp1140':
-			case 'ebcdicus37euro':
-			case 'ibm1140':
-				return 'IBM01140';
-
-			case 'ccsid1141':
-			case 'cp1141':
-			case 'ebcdicde273euro':
-			case 'ibm1141':
-				return 'IBM01141';
-
-			case 'ccsid1142':
-			case 'cp1142':
-			case 'ebcdicdk277euro':
-			case 'ebcdicno277euro':
-			case 'ibm1142':
-				return 'IBM01142';
-
-			case 'ccsid1143':
-			case 'cp1143':
-			case 'ebcdicfi278euro':
-			case 'ebcdicse278euro':
-			case 'ibm1143':
-				return 'IBM01143';
-
-			case 'ccsid1144':
-			case 'cp1144':
-			case 'ebcdicit280euro':
-			case 'ibm1144':
-				return 'IBM01144';
-
-			case 'ccsid1145':
-			case 'cp1145':
-			case 'ebcdices284euro':
-			case 'ibm1145':
-				return 'IBM01145';
-
-			case 'ccsid1146':
-			case 'cp1146':
-			case 'ebcdicgb285euro':
-			case 'ibm1146':
-				return 'IBM01146';
-
-			case 'ccsid1147':
-			case 'cp1147':
-			case 'ebcdicfr297euro':
-			case 'ibm1147':
-				return 'IBM01147';
-
-			case 'ccsid1148':
-			case 'cp1148':
-			case 'ebcdicinternational500euro':
-			case 'ibm1148':
-				return 'IBM01148';
-
-			case 'ccsid1149':
-			case 'cp1149':
-			case 'ebcdicis871euro':
-			case 'ibm1149':
-				return 'IBM01149';
-
-			case 'cp37':
-			case 'csibm37':
-			case 'ebcdiccpca':
-			case 'ebcdiccpnl':
-			case 'ebcdiccpus':
-			case 'ebcdiccpwt':
-			case 'ibm37':
-				return 'IBM037';
-
-			case 'cp38':
-			case 'csibm38':
-			case 'ebcdicint':
-			case 'ibm38':
-				return 'IBM038';
-
-			case 'cp273':
-			case 'csibm273':
-			case 'ibm273':
-				return 'IBM273';
-
-			case 'cp274':
-			case 'csibm274':
-			case 'ebcdicbe':
-			case 'ibm274':
-				return 'IBM274';
-
-			case 'cp275':
-			case 'csibm275':
-			case 'ebcdicbr':
-			case 'ibm275':
-				return 'IBM275';
-
-			case 'csibm277':
-			case 'ebcdiccpdk':
-			case 'ebcdiccpno':
-			case 'ibm277':
-				return 'IBM277';
-
-			case 'cp278':
-			case 'csibm278':
-			case 'ebcdiccpfi':
-			case 'ebcdiccpse':
-			case 'ibm278':
-				return 'IBM278';
-
-			case 'cp280':
-			case 'csibm280':
-			case 'ebcdiccpit':
-			case 'ibm280':
-				return 'IBM280';
-
-			case 'cp281':
-			case 'csibm281':
-			case 'ebcdicjpe':
-			case 'ibm281':
-				return 'IBM281';
-
-			case 'cp284':
-			case 'csibm284':
-			case 'ebcdiccpes':
-			case 'ibm284':
-				return 'IBM284';
-
-			case 'cp285':
-			case 'csibm285':
-			case 'ebcdiccpgb':
-			case 'ibm285':
-				return 'IBM285';
-
-			case 'cp290':
-			case 'csibm290':
-			case 'ebcdicjpkana':
-			case 'ibm290':
-				return 'IBM290';
-
-			case 'cp297':
-			case 'csibm297':
-			case 'ebcdiccpfr':
-			case 'ibm297':
-				return 'IBM297';
-
-			case 'cp420':
-			case 'csibm420':
-			case 'ebcdiccpar1':
-			case 'ibm420':
-				return 'IBM420';
-
-			case 'cp423':
-			case 'csibm423':
-			case 'ebcdiccpgr':
-			case 'ibm423':
-				return 'IBM423';
-
-			case 'cp424':
-			case 'csibm424':
-			case 'ebcdiccphe':
-			case 'ibm424':
-				return 'IBM424';
-
-			case '437':
-			case 'cp437':
-			case 'cspc8codepage437':
-			case 'ibm437':
-				return 'IBM437';
-
-			case 'cp500':
-			case 'csibm500':
-			case 'ebcdiccpbe':
-			case 'ebcdiccpch':
-			case 'ibm500':
-				return 'IBM500';
-
-			case 'cp775':
-			case 'cspc775baltic':
-			case 'ibm775':
-				return 'IBM775';
-
-			case '850':
-			case 'cp850':
-			case 'cspc850multilingual':
-			case 'ibm850':
-				return 'IBM850';
-
-			case '851':
-			case 'cp851':
-			case 'csibm851':
-			case 'ibm851':
-				return 'IBM851';
-
-			case '852':
-			case 'cp852':
-			case 'cspcp852':
-			case 'ibm852':
-				return 'IBM852';
-
-			case '855':
-			case 'cp855':
-			case 'csibm855':
-			case 'ibm855':
-				return 'IBM855';
-
-			case '857':
-			case 'cp857':
-			case 'csibm857':
-			case 'ibm857':
-				return 'IBM857';
-
-			case '860':
-			case 'cp860':
-			case 'csibm860':
-			case 'ibm860':
-				return 'IBM860';
-
-			case '861':
-			case 'cp861':
-			case 'cpis':
-			case 'csibm861':
-			case 'ibm861':
-				return 'IBM861';
-
-			case '862':
-			case 'cp862':
-			case 'cspc862latinhebrew':
-			case 'ibm862':
-				return 'IBM862';
-
-			case '863':
-			case 'cp863':
-			case 'csibm863':
-			case 'ibm863':
-				return 'IBM863';
-
-			case 'cp864':
-			case 'csibm864':
-			case 'ibm864':
-				return 'IBM864';
-
-			case '865':
-			case 'cp865':
-			case 'csibm865':
-			case 'ibm865':
-				return 'IBM865';
-
-			case '866':
-			case 'cp866':
-			case 'csibm866':
-			case 'ibm866':
-				return 'IBM866';
-
-			case 'cp868':
-			case 'cpar':
-			case 'csibm868':
-			case 'ibm868':
-				return 'IBM868';
-
-			case '869':
-			case 'cp869':
-			case 'cpgr':
-			case 'csibm869':
-			case 'ibm869':
-				return 'IBM869';
-
-			case 'cp870':
-			case 'csibm870':
-			case 'ebcdiccproece':
-			case 'ebcdiccpyu':
-			case 'ibm870':
-				return 'IBM870';
-
-			case 'cp871':
-			case 'csibm871':
-			case 'ebcdiccpis':
-			case 'ibm871':
-				return 'IBM871';
-
-			case 'cp880':
-			case 'csibm880':
-			case 'ebcdiccyrillic':
-			case 'ibm880':
-				return 'IBM880';
-
-			case 'cp891':
-			case 'csibm891':
-			case 'ibm891':
-				return 'IBM891';
-
-			case 'cp903':
-			case 'csibm903':
-			case 'ibm903':
-				return 'IBM903';
-
-			case '904':
-			case 'cp904':
-			case 'csibbm904':
-			case 'ibm904':
-				return 'IBM904';
-
-			case 'cp905':
-			case 'csibm905':
-			case 'ebcdiccptr':
-			case 'ibm905':
-				return 'IBM905';
-
-			case 'cp918':
-			case 'csibm918':
-			case 'ebcdiccpar2':
-			case 'ibm918':
-				return 'IBM918';
-
-			case 'cp1026':
-			case 'csibm1026':
-			case 'ibm1026':
-				return 'IBM1026';
-
-			case 'ibm1047':
-				return 'IBM1047';
-
-			case 'csiso143iecp271':
-			case 'iecp271':
-			case 'isoir143':
-				return 'IEC_P27-1';
-
-			case 'csiso49inis':
-			case 'inis':
-			case 'isoir49':
-				return 'INIS';
-
-			case 'csiso50inis8':
-			case 'inis8':
-			case 'isoir50':
-				return 'INIS-8';
-
-			case 'csiso51iniscyrillic':
-			case 'iniscyrillic':
-			case 'isoir51':
-				return 'INIS-cyrillic';
-
-			case 'csinvariant':
-			case 'invariant':
-				return 'INVARIANT';
-
-			case 'iso2022cn':
-				return 'ISO-2022-CN';
-
-			case 'iso2022cnext':
-				return 'ISO-2022-CN-EXT';
-
-			case 'csiso2022jp':
-			case 'iso2022jp':
-				return 'ISO-2022-JP';
-
-			case 'csiso2022jp2':
-			case 'iso2022jp2':
-				return 'ISO-2022-JP-2';
-
-			case 'csiso2022kr':
-			case 'iso2022kr':
-				return 'ISO-2022-KR';
-
-			case 'cswindows30latin1':
-			case 'iso88591windows30latin1':
-				return 'ISO-8859-1-Windows-3.0-Latin-1';
-
-			case 'cswindows31latin1':
-			case 'iso88591windows31latin1':
-				return 'ISO-8859-1-Windows-3.1-Latin-1';
-
-			case 'csisolatin2':
-			case 'iso88592':
-			case 'iso885921987':
-			case 'isoir101':
-			case 'l2':
-			case 'latin2':
-				return 'ISO-8859-2';
-
-			case 'cswindows31latin2':
-			case 'iso88592windowslatin2':
-				return 'ISO-8859-2-Windows-Latin-2';
-
-			case 'csisolatin3':
-			case 'iso88593':
-			case 'iso885931988':
-			case 'isoir109':
-			case 'l3':
-			case 'latin3':
-				return 'ISO-8859-3';
-
-			case 'csisolatin4':
-			case 'iso88594':
-			case 'iso885941988':
-			case 'isoir110':
-			case 'l4':
-			case 'latin4':
-				return 'ISO-8859-4';
-
-			case 'csisolatincyrillic':
-			case 'cyrillic':
-			case 'iso88595':
-			case 'iso885951988':
-			case 'isoir144':
-				return 'ISO-8859-5';
-
-			case 'arabic':
-			case 'asmo708':
-			case 'csisolatinarabic':
-			case 'ecma114':
-			case 'iso88596':
-			case 'iso885961987':
-			case 'isoir127':
-				return 'ISO-8859-6';
-
-			case 'csiso88596e':
-			case 'iso88596e':
-				return 'ISO-8859-6-E';
-
-			case 'csiso88596i':
-			case 'iso88596i':
-				return 'ISO-8859-6-I';
-
-			case 'csisolatingreek':
-			case 'ecma118':
-			case 'elot928':
-			case 'greek':
-			case 'greek8':
-			case 'iso88597':
-			case 'iso885971987':
-			case 'isoir126':
-				return 'ISO-8859-7';
-
-			case 'csisolatinhebrew':
-			case 'hebrew':
-			case 'iso88598':
-			case 'iso885981988':
-			case 'isoir138':
-				return 'ISO-8859-8';
-
-			case 'csiso88598e':
-			case 'iso88598e':
-				return 'ISO-8859-8-E';
-
-			case 'csiso88598i':
-			case 'iso88598i':
-				return 'ISO-8859-8-I';
-
-			case 'cswindows31latin5':
-			case 'iso88599windowslatin5':
-				return 'ISO-8859-9-Windows-Latin-5';
-
-			case 'csisolatin6':
-			case 'iso885910':
-			case 'iso8859101992':
-			case 'isoir157':
-			case 'l6':
-			case 'latin6':
-				return 'ISO-8859-10';
-
-			case 'iso885913':
-				return 'ISO-8859-13';
-
-			case 'iso885914':
-			case 'iso8859141998':
-			case 'isoceltic':
-			case 'isoir199':
-			case 'l8':
-			case 'latin8':
-				return 'ISO-8859-14';
-
-			case 'iso885915':
-			case 'latin9':
-				return 'ISO-8859-15';
-
-			case 'iso885916':
-			case 'iso8859162001':
-			case 'isoir226':
-			case 'l10':
-			case 'latin10':
-				return 'ISO-8859-16';
-
-			case 'iso10646j1':
-				return 'ISO-10646-J-1';
-
-			case 'csunicode':
-			case 'iso10646ucs2':
-				return 'ISO-10646-UCS-2';
-
-			case 'csucs4':
-			case 'iso10646ucs4':
-				return 'ISO-10646-UCS-4';
-
-			case 'csunicodeascii':
-			case 'iso10646ucsbasic':
-				return 'ISO-10646-UCS-Basic';
-
-			case 'csunicodelatin1':
-			case 'iso10646':
-			case 'iso10646unicodelatin1':
-				return 'ISO-10646-Unicode-Latin1';
-
-			case 'csiso10646utf1':
-			case 'iso10646utf1':
-				return 'ISO-10646-UTF-1';
-
-			case 'csiso115481':
-			case 'iso115481':
-			case 'isotr115481':
-				return 'ISO-11548-1';
-
-			case 'csiso90':
-			case 'isoir90':
-				return 'iso-ir-90';
-
-			case 'csunicodeibm1261':
-			case 'isounicodeibm1261':
-				return 'ISO-Unicode-IBM-1261';
-
-			case 'csunicodeibm1264':
-			case 'isounicodeibm1264':
-				return 'ISO-Unicode-IBM-1264';
-
-			case 'csunicodeibm1265':
-			case 'isounicodeibm1265':
-				return 'ISO-Unicode-IBM-1265';
-
-			case 'csunicodeibm1268':
-			case 'isounicodeibm1268':
-				return 'ISO-Unicode-IBM-1268';
-
-			case 'csunicodeibm1276':
-			case 'isounicodeibm1276':
-				return 'ISO-Unicode-IBM-1276';
-
-			case 'csiso646basic1983':
-			case 'iso646basic1983':
-			case 'ref':
-				return 'ISO_646.basic:1983';
-
-			case 'csiso2intlrefversion':
-			case 'irv':
-			case 'iso646irv1983':
-			case 'isoir2':
-				return 'ISO_646.irv:1983';
-
-			case 'csiso2033':
-			case 'e13b':
-			case 'iso20331983':
-			case 'isoir98':
-				return 'ISO_2033-1983';
-
-			case 'csiso5427cyrillic':
-			case 'iso5427':
-			case 'isoir37':
-				return 'ISO_5427';
-
-			case 'iso5427cyrillic1981':
-			case 'iso54271981':
-			case 'isoir54':
-				return 'ISO_5427:1981';
-
-			case 'csiso5428greek':
-			case 'iso54281980':
-			case 'isoir55':
-				return 'ISO_5428:1980';
-
-			case 'csiso6937add':
-			case 'iso6937225':
-			case 'isoir152':
-				return 'ISO_6937-2-25';
-
-			case 'csisotextcomm':
-			case 'iso69372add':
-			case 'isoir142':
-				return 'ISO_6937-2-add';
-
-			case 'csiso8859supp':
-			case 'iso8859supp':
-			case 'isoir154':
-			case 'latin125':
-				return 'ISO_8859-supp';
-
-			case 'csiso10367box':
-			case 'iso10367box':
-			case 'isoir155':
-				return 'ISO_10367-box';
-
-			case 'csiso15italian':
-			case 'iso646it':
-			case 'isoir15':
-			case 'it':
-				return 'IT';
-
-			case 'csiso13jisc6220jp':
-			case 'isoir13':
-			case 'jisc62201969':
-			case 'jisc62201969jp':
-			case 'katakana':
-			case 'x2017':
-				return 'JIS_C6220-1969-jp';
-
-			case 'csiso14jisc6220ro':
-			case 'iso646jp':
-			case 'isoir14':
-			case 'jisc62201969ro':
-			case 'jp':
-				return 'JIS_C6220-1969-ro';
-
-			case 'csiso42jisc62261978':
-			case 'isoir42':
-			case 'jisc62261978':
-				return 'JIS_C6226-1978';
-
-			case 'csiso87jisx208':
-			case 'isoir87':
-			case 'jisc62261983':
-			case 'jisx2081983':
-			case 'x208':
-				return 'JIS_C6226-1983';
-
-			case 'csiso91jisc62291984a':
-			case 'isoir91':
-			case 'jisc62291984a':
-			case 'jpocra':
-				return 'JIS_C6229-1984-a';
-
-			case 'csiso92jisc62991984b':
-			case 'iso646jpocrb':
-			case 'isoir92':
-			case 'jisc62291984b':
-			case 'jpocrb':
-				return 'JIS_C6229-1984-b';
-
-			case 'csiso93jis62291984badd':
-			case 'isoir93':
-			case 'jisc62291984badd':
-			case 'jpocrbadd':
-				return 'JIS_C6229-1984-b-add';
-
-			case 'csiso94jis62291984hand':
-			case 'isoir94':
-			case 'jisc62291984hand':
-			case 'jpocrhand':
-				return 'JIS_C6229-1984-hand';
-
-			case 'csiso95jis62291984handadd':
-			case 'isoir95':
-			case 'jisc62291984handadd':
-			case 'jpocrhandadd':
-				return 'JIS_C6229-1984-hand-add';
-
-			case 'csiso96jisc62291984kana':
-			case 'isoir96':
-			case 'jisc62291984kana':
-				return 'JIS_C6229-1984-kana';
-
-			case 'csjisencoding':
-			case 'jisencoding':
-				return 'JIS_Encoding';
-
-			case 'cshalfwidthkatakana':
-			case 'jisx201':
-			case 'x201':
-				return 'JIS_X0201';
-
-			case 'csiso159jisx2121990':
-			case 'isoir159':
-			case 'jisx2121990':
-			case 'x212':
-				return 'JIS_X0212-1990';
-
-			case 'csiso141jusib1002':
-			case 'iso646yu':
-			case 'isoir141':
-			case 'js':
-			case 'jusib1002':
-			case 'yu':
-				return 'JUS_I.B1.002';
-
-			case 'csiso147macedonian':
-			case 'isoir147':
-			case 'jusib1003mac':
-			case 'macedonian':
-				return 'JUS_I.B1.003-mac';
-
-			case 'csiso146serbian':
-			case 'isoir146':
-			case 'jusib1003serb':
-			case 'serbian':
-				return 'JUS_I.B1.003-serb';
-
-			case 'koi7switched':
-				return 'KOI7-switched';
-
-			case 'cskoi8r':
-			case 'koi8r':
-				return 'KOI8-R';
-
-			case 'koi8u':
-				return 'KOI8-U';
-
-			case 'csksc5636':
-			case 'iso646kr':
-			case 'ksc5636':
-				return 'KSC5636';
-
-			case 'cskz1048':
-			case 'kz1048':
-			case 'rk1048':
-			case 'strk10482002':
-				return 'KZ-1048';
-
-			case 'csiso19latingreek':
-			case 'isoir19':
-			case 'latingreek':
-				return 'latin-greek';
-
-			case 'csiso27latingreek1':
-			case 'isoir27':
-			case 'latingreek1':
-				return 'Latin-greek-1';
-
-			case 'csiso158lap':
-			case 'isoir158':
-			case 'lap':
-			case 'latinlap':
-				return 'latin-lap';
-
-			case 'csmacintosh':
-			case 'mac':
-			case 'macintosh':
-				return 'macintosh';
-
-			case 'csmicrosoftpublishing':
-			case 'microsoftpublishing':
-				return 'Microsoft-Publishing';
-
-			case 'csmnem':
-			case 'mnem':
-				return 'MNEM';
-
-			case 'csmnemonic':
-			case 'mnemonic':
-				return 'MNEMONIC';
-
-			case 'csiso86hungarian':
-			case 'hu':
-			case 'iso646hu':
-			case 'isoir86':
-			case 'msz77953':
-				return 'MSZ_7795.3';
-
-			case 'csnatsdano':
-			case 'isoir91':
-			case 'natsdano':
-				return 'NATS-DANO';
-
-			case 'csnatsdanoadd':
-			case 'isoir92':
-			case 'natsdanoadd':
-				return 'NATS-DANO-ADD';
-
-			case 'csnatssefi':
-			case 'isoir81':
-			case 'natssefi':
-				return 'NATS-SEFI';
-
-			case 'csnatssefiadd':
-			case 'isoir82':
-			case 'natssefiadd':
-				return 'NATS-SEFI-ADD';
-
-			case 'csiso151cuba':
-			case 'cuba':
-			case 'iso646cu':
-			case 'isoir151':
-			case 'ncnc1081':
-				return 'NC_NC00-10:81';
-
-			case 'csiso69french':
-			case 'fr':
-			case 'iso646fr':
-			case 'isoir69':
-			case 'nfz62010':
-				return 'NF_Z_62-010';
-
-			case 'csiso25french':
-			case 'iso646fr1':
-			case 'isoir25':
-			case 'nfz620101973':
-				return 'NF_Z_62-010_(1973)';
-
-			case 'csiso60danishnorwegian':
-			case 'csiso60norwegian1':
-			case 'iso646no':
-			case 'isoir60':
-			case 'no':
-			case 'ns45511':
-				return 'NS_4551-1';
-
-			case 'csiso61norwegian2':
-			case 'iso646no2':
-			case 'isoir61':
-			case 'no2':
-			case 'ns45512':
-				return 'NS_4551-2';
-
-			case 'osdebcdicdf3irv':
-				return 'OSD_EBCDIC_DF03_IRV';
-
-			case 'osdebcdicdf41':
-				return 'OSD_EBCDIC_DF04_1';
-
-			case 'osdebcdicdf415':
-				return 'OSD_EBCDIC_DF04_15';
-
-			case 'cspc8danishnorwegian':
-			case 'pc8danishnorwegian':
-				return 'PC8-Danish-Norwegian';
-
-			case 'cspc8turkish':
-			case 'pc8turkish':
-				return 'PC8-Turkish';
-
-			case 'csiso16portuguese':
-			case 'iso646pt':
-			case 'isoir16':
-			case 'pt':
-				return 'PT';
-
-			case 'csiso84portuguese2':
-			case 'iso646pt2':
-			case 'isoir84':
-			case 'pt2':
-				return 'PT2';
-
-			case 'cp154':
-			case 'csptcp154':
-			case 'cyrillicasian':
-			case 'pt154':
-			case 'ptcp154':
-				return 'PTCP154';
-
-			case 'scsu':
-				return 'SCSU';
-
-			case 'csiso10swedish':
-			case 'fi':
-			case 'iso646fi':
-			case 'iso646se':
-			case 'isoir10':
-			case 'se':
-			case 'sen850200b':
-				return 'SEN_850200_B';
-
-			case 'csiso11swedishfornames':
-			case 'iso646se2':
-			case 'isoir11':
-			case 'se2':
-			case 'sen850200c':
-				return 'SEN_850200_C';
-
-			case 'csshiftjis':
-			case 'mskanji':
-			case 'shiftjis':
-				return 'Shift_JIS';
-
-			case 'csiso102t617bit':
-			case 'isoir102':
-			case 't617bit':
-				return 'T.61-7bit';
-
-			case 'csiso103t618bit':
-			case 'isoir103':
-			case 't61':
-			case 't618bit':
-				return 'T.61-8bit';
-
-			case 'csiso128t101g2':
-			case 'isoir128':
-			case 't101g2':
-				return 'T.101-G2';
-
-			case 'cstscii':
-			case 'tscii':
-				return 'TSCII';
-
-			case 'csunicode11':
-			case 'unicode11':
-				return 'UNICODE-1-1';
-
-			case 'csunicode11utf7':
-			case 'unicode11utf7':
-				return 'UNICODE-1-1-UTF-7';
-
-			case 'csunknown8bit':
-			case 'unknown8bit':
-				return 'UNKNOWN-8BIT';
-
-			case 'ansix341968':
-			case 'ansix341986':
-			case 'ascii':
-			case 'cp367':
-			case 'csascii':
-			case 'ibm367':
-			case 'iso646irv1991':
-			case 'iso646us':
-			case 'isoir6':
-			case 'us':
-			case 'usascii':
-				return 'US-ASCII';
-
-			case 'csusdk':
-			case 'usdk':
-				return 'us-dk';
-
-			case 'utf7':
-				return 'UTF-7';
-
-			case 'utf8':
-				return 'UTF-8';
-
-			case 'utf16':
-				return 'UTF-16';
-
-			case 'utf16be':
-				return 'UTF-16BE';
-
-			case 'utf16le':
-				return 'UTF-16LE';
-
-			case 'utf32':
-				return 'UTF-32';
-
-			case 'utf32be':
-				return 'UTF-32BE';
-
-			case 'utf32le':
-				return 'UTF-32LE';
-
-			case 'csventurainternational':
-			case 'venturainternational':
-				return 'Ventura-International';
-
-			case 'csventuramath':
-			case 'venturamath':
-				return 'Ventura-Math';
-
-			case 'csventuraus':
-			case 'venturaus':
-				return 'Ventura-US';
-
-			case 'csiso70videotexsupp1':
-			case 'isoir70':
-			case 'videotexsuppl':
-				return 'videotex-suppl';
-
-			case 'csviqr':
-			case 'viqr':
-				return 'VIQR';
-
-			case 'csviscii':
-			case 'viscii':
-				return 'VISCII';
-
-			case 'cswindows31j':
-			case 'windows31j':
-				return 'Windows-31J';
-
-			case 'iso885911':
-			case 'tis620':
-				return 'windows-874';
-
-			case 'cseuckr':
-			case 'csksc56011987':
-			case 'euckr':
-			case 'isoir149':
-			case 'korean':
-			case 'ksc5601':
-			case 'ksc56011987':
-			case 'ksc56011989':
-			case 'windows949':
-				return 'windows-949';
-
-			case 'windows1250':
-				return 'windows-1250';
-
-			case 'windows1251':
-				return 'windows-1251';
-
-			case 'cp819':
-			case 'csisolatin1':
-			case 'ibm819':
-			case 'iso88591':
-			case 'iso885911987':
-			case 'isoir100':
-			case 'l1':
-			case 'latin1':
-			case 'windows1252':
-				return 'windows-1252';
-
-			case 'windows1253':
-				return 'windows-1253';
-
-			case 'csisolatin5':
-			case 'iso88599':
-			case 'iso885991989':
-			case 'isoir148':
-			case 'l5':
-			case 'latin5':
-			case 'windows1254':
-				return 'windows-1254';
-
-			case 'windows1255':
-				return 'windows-1255';
-
-			case 'windows1256':
-				return 'windows-1256';
-
-			case 'windows1257':
-				return 'windows-1257';
-
-			case 'windows1258':
-				return 'windows-1258';
-
-			default:
-				return $charset;
-		}
-	}
-
-	function get_curl_version()
-	{
-		if (is_array($curl = curl_version()))
-		{
-			$curl = $curl['version'];
-		}
-		elseif (substr($curl, 0, 5) === 'curl/')
-		{
-			$curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
-		}
-		elseif (substr($curl, 0, 8) === 'libcurl/')
-		{
-			$curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
-		}
-		else
-		{
-			$curl = 0;
-		}
-		return $curl;
-	}
-
-	function is_subclass_of($class1, $class2)
-	{
-		if (func_num_args() !== 2)
-		{
-			trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
-		}
-		elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
-		{
-			return is_subclass_of($class1, $class2);
-		}
-		elseif (is_string($class1) && is_string($class2))
-		{
-			if (class_exists($class1))
-			{
-				if (class_exists($class2))
-				{
-					$class2 = strtolower($class2);
-					while ($class1 = strtolower(get_parent_class($class1)))
-					{
-						if ($class1 === $class2)
-						{
-							return true;
-						}
-					}
-				}
-			}
-			else
-			{
-				trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * Strip HTML comments
-	 *
-	 * @access public
-	 * @param string $data Data to strip comments from
-	 * @return string Comment stripped string
-	 */
-	function strip_comments($data)
-	{
-		$output = '';
-		while (($start = strpos($data, '<!--')) !== false)
-		{
-			$output .= substr($data, 0, $start);
-			if (($end = strpos($data, '-->', $start)) !== false)
-			{
-				$data = substr_replace($data, '', 0, $end + 3);
-			}
-			else
-			{
-				$data = '';
-			}
-		}
-		return $output . $data;
-	}
-
-	function parse_date($dt)
-	{
-		$parser = SimplePie_Parse_Date::get();
-		return $parser->parse($dt);
-	}
-
-	/**
-	 * Decode HTML entities
-	 *
-	 * @static
-	 * @access public
-	 * @param string $data Input data
-	 * @return string Output data
-	 */
-	function entities_decode($data)
-	{
-		$decoder = new SimplePie_Decode_HTML_Entities($data);
-		return $decoder->parse();
-	}
-
-	/**
-	 * Remove RFC822 comments
-	 *
-	 * @access public
-	 * @param string $data Data to strip comments from
-	 * @return string Comment stripped string
-	 */
-	function uncomment_rfc822($string)
-	{
-		$string = (string) $string;
-		$position = 0;
-		$length = strlen($string);
-		$depth = 0;
-
-		$output = '';
-
-		while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
-		{
-			$output .= substr($string, $position, $pos - $position);
-			$position = $pos + 1;
-			if ($string[$pos - 1] !== '\\')
-			{
-				$depth++;
-				while ($depth && $position < $length)
-				{
-					$position += strcspn($string, '()', $position);
-					if ($string[$position - 1] === '\\')
-					{
-						$position++;
-						continue;
-					}
-					elseif (isset($string[$position]))
-					{
-						switch ($string[$position])
-						{
-							case '(':
-								$depth++;
-								break;
-
-							case ')':
-								$depth--;
-								break;
-						}
-						$position++;
-					}
-					else
-					{
-						break;
-					}
-				}
-			}
-			else
-			{
-				$output .= '(';
-			}
-		}
-		$output .= substr($string, $position);
-
-		return $output;
-	}
-
-	function parse_mime($mime)
-	{
-		if (($pos = strpos($mime, ';')) === false)
-		{
-			return trim($mime);
-		}
-		else
-		{
-			return trim(substr($mime, 0, $pos));
-		}
-	}
-
-	function htmlspecialchars_decode($string, $quote_style)
-	{
-		if (function_exists('htmlspecialchars_decode'))
-		{
-			return htmlspecialchars_decode($string, $quote_style);
-		}
-		else
-		{
-			return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
-		}
-	}
-
-	function atom_03_construct_type($attribs)
-	{
-		if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
-		{
-			$mode = SIMPLEPIE_CONSTRUCT_BASE64;
-		}
-		else
-		{
-			$mode = SIMPLEPIE_CONSTRUCT_NONE;
-		}
-		if (isset($attribs['']['type']))
-		{
-			switch (strtolower(trim($attribs['']['type'])))
-			{
-				case 'text':
-				case 'text/plain':
-					return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
-
-				case 'html':
-				case 'text/html':
-					return SIMPLEPIE_CONSTRUCT_HTML | $mode;
-
-				case 'xhtml':
-				case 'application/xhtml+xml':
-					return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
-
-				default:
-					return SIMPLEPIE_CONSTRUCT_NONE | $mode;
-			}
-		}
-		else
-		{
-			return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
-		}
-	}
-
-	function atom_10_construct_type($attribs)
-	{
-		if (isset($attribs['']['type']))
-		{
-			switch (strtolower(trim($attribs['']['type'])))
-			{
-				case 'text':
-					return SIMPLEPIE_CONSTRUCT_TEXT;
-
-				case 'html':
-					return SIMPLEPIE_CONSTRUCT_HTML;
-
-				case 'xhtml':
-					return SIMPLEPIE_CONSTRUCT_XHTML;
-
-				default:
-					return SIMPLEPIE_CONSTRUCT_NONE;
-			}
-		}
-		return SIMPLEPIE_CONSTRUCT_TEXT;
-	}
-
-	function atom_10_content_construct_type($attribs)
-	{
-		if (isset($attribs['']['type']))
-		{
-			$type = strtolower(trim($attribs['']['type']));
-			switch ($type)
-			{
-				case 'text':
-					return SIMPLEPIE_CONSTRUCT_TEXT;
-
-				case 'html':
-					return SIMPLEPIE_CONSTRUCT_HTML;
-
-				case 'xhtml':
-					return SIMPLEPIE_CONSTRUCT_XHTML;
-			}
-			if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
-			{
-				return SIMPLEPIE_CONSTRUCT_NONE;
-			}
-			else
-			{
-				return SIMPLEPIE_CONSTRUCT_BASE64;
-			}
-		}
-		else
-		{
-			return SIMPLEPIE_CONSTRUCT_TEXT;
-		}
-	}
-
-	function is_isegment_nz_nc($string)
-	{
-		return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string);
-	}
-
-	function space_seperated_tokens($string)
-	{
-		$space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
-		$string_length = strlen($string);
-
-		$position = strspn($string, $space_characters);
-		$tokens = array();
-
-		while ($position < $string_length)
-		{
-			$len = strcspn($string, $space_characters, $position);
-			$tokens[] = substr($string, $position, $len);
-			$position += $len;
-			$position += strspn($string, $space_characters, $position);
-		}
-
-		return $tokens;
-	}
-
-	function array_unique($array)
-	{
-		if (version_compare(PHP_VERSION, '5.2', '>='))
-		{
-			return array_unique($array);
-		}
-		else
-		{
-			$array = (array) $array;
-			$new_array = array();
-			$new_array_strings = array();
-			foreach ($array as $key => $value)
-			{
-				if (is_object($value))
-				{
-					if (method_exists($value, '__toString'))
-					{
-						$cmp = $value->__toString();
-					}
-					else
-					{
-						trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
-					}
-				}
-				elseif (is_array($value))
-				{
-					$cmp = (string) reset($value);
-				}
-				else
-				{
-					$cmp = (string) $value;
-				}
-				if (!in_array($cmp, $new_array_strings))
-				{
-					$new_array[$key] = $value;
-					$new_array_strings[] = $cmp;
-				}
-			}
-			return $new_array;
-		}
-	}
-
-	/**
-	 * Converts a unicode codepoint to a UTF-8 character
-	 *
-	 * @static
-	 * @access public
-	 * @param int $codepoint Unicode codepoint
-	 * @return string UTF-8 character
-	 */
-	function codepoint_to_utf8($codepoint)
-	{
-		$codepoint = (int) $codepoint;
-		if ($codepoint < 0)
-		{
-			return false;
-		}
-		else if ($codepoint <= 0x7f)
-		{
-			return chr($codepoint);
-		}
-		else if ($codepoint <= 0x7ff)
-		{
-			return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
-		}
-		else if ($codepoint <= 0xffff)
-		{
-			return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
-		}
-		else if ($codepoint <= 0x10ffff)
-		{
-			return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
-		}
-		else
-		{
-			// U+FFFD REPLACEMENT CHARACTER
-			return "\xEF\xBF\xBD";
-		}
-	}
-
-	/**
-	 * Re-implementation of PHP 5's stripos()
-	 *
-	 * Returns the numeric position of the first occurrence of needle in the
-	 * haystack string.
-	 *
-	 * @static
-	 * @access string
-	 * @param object $haystack
-	 * @param string $needle Note that the needle may be a string of one or more
-	 *     characters. If needle is not a string, it is converted to an integer
-	 *     and applied as the ordinal value of a character.
-	 * @param int $offset The optional offset parameter allows you to specify which
-	 *     character in haystack to start searching. The position returned is still
-	 *     relative to the beginning of haystack.
-	 * @return bool If needle is not found, stripos() will return boolean false.
-	 */
-	function stripos($haystack, $needle, $offset = 0)
-	{
-		if (function_exists('stripos'))
-		{
-			return stripos($haystack, $needle, $offset);
-		}
-		else
-		{
-			if (is_string($needle))
-			{
-				$needle = strtolower($needle);
-			}
-			elseif (is_int($needle) || is_bool($needle) || is_double($needle))
-			{
-				$needle = strtolower(chr($needle));
-			}
-			else
-			{
-				trigger_error('needle is not a string or an integer', E_USER_WARNING);
-				return false;
-			}
-
-			return strpos(strtolower($haystack), $needle, $offset);
-		}
-	}
-
-	/**
-	 * Similar to parse_str()
-	 *
-	 * Returns an associative array of name/value pairs, where the value is an
-	 * array of values that have used the same name
-	 *
-	 * @static
-	 * @access string
-	 * @param string $str The input string.
-	 * @return array
-	 */
-	function parse_str($str)
-	{
-		$return = array();
-		$str = explode('&', $str);
-
-		foreach ($str as $section)
-		{
-			if (strpos($section, '=') !== false)
-			{
-				list($name, $value) = explode('=', $section, 2);
-				$return[urldecode($name)][] = urldecode($value);
-			}
-			else
-			{
-				$return[urldecode($section)][] = null;
-			}
-		}
-
-		return $return;
-	}
-
-	/**
-	 * Detect XML encoding, as per XML 1.0 Appendix F.1
-	 *
-	 * @todo Add support for EBCDIC
-	 * @param string $data XML data
-	 * @return array Possible encodings
-	 */
-	function xml_encoding($data)
-	{
-		// UTF-32 Big Endian BOM
-		if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
-		{
-			$encoding[] = 'UTF-32BE';
-		}
-		// UTF-32 Little Endian BOM
-		elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
-		{
-			$encoding[] = 'UTF-32LE';
-		}
-		// UTF-16 Big Endian BOM
-		elseif (substr($data, 0, 2) === "\xFE\xFF")
-		{
-			$encoding[] = 'UTF-16BE';
-		}
-		// UTF-16 Little Endian BOM
-		elseif (substr($data, 0, 2) === "\xFF\xFE")
-		{
-			$encoding[] = 'UTF-16LE';
-		}
-		// UTF-8 BOM
-		elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
-		{
-			$encoding[] = 'UTF-8';
-		}
-		// UTF-32 Big Endian Without BOM
-		elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C")
-		{
-			if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
-			{
-				$parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
-				if ($parser->parse())
-				{
-					$encoding[] = $parser->encoding;
-				}
-			}
-			$encoding[] = 'UTF-32BE';
-		}
-		// UTF-32 Little Endian Without BOM
-		elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00")
-		{
-			if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
-			{
-				$parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
-				if ($parser->parse())
-				{
-					$encoding[] = $parser->encoding;
-				}
-			}
-			$encoding[] = 'UTF-32LE';
-		}
-		// UTF-16 Big Endian Without BOM
-		elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
-		{
-			if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
-			{
-				$parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
-				if ($parser->parse())
-				{
-					$encoding[] = $parser->encoding;
-				}
-			}
-			$encoding[] = 'UTF-16BE';
-		}
-		// UTF-16 Little Endian Without BOM
-		elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
-		{
-			if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
-			{
-				$parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
-				if ($parser->parse())
-				{
-					$encoding[] = $parser->encoding;
-				}
-			}
-			$encoding[] = 'UTF-16LE';
-		}
-		// US-ASCII (or superset)
-		elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
-		{
-			if ($pos = strpos($data, "\x3F\x3E"))
-			{
-				$parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
-				if ($parser->parse())
-				{
-					$encoding[] = $parser->encoding;
-				}
-			}
-			$encoding[] = 'UTF-8';
-		}
-		// Fallback to UTF-8
-		else
-		{
-			$encoding[] = 'UTF-8';
-		}
-		return $encoding;
-	}
-
-	function output_javascript()
-	{
-		if (function_exists('ob_gzhandler'))
-		{
-			ob_start('ob_gzhandler');
-		}
-		header('Content-type: text/javascript; charset: UTF-8');
-		header('Cache-Control: must-revalidate');
-		header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
-		?>
-function embed_odeo(link) {
-	document.writeln('<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url='+link+'"></embed>');
-}
-
-function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
-	if (placeholder != '') {
-		document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
-	}
-	else {
-		document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
-	}
-}
-
-function embed_flash(bgcolor, width, height, link, loop, type) {
-	document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
-}
-
-function embed_flv(width, height, link, placeholder, loop, player) {
-	document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>');
-}
-
-function embed_wmedia(width, height, link) {
-	document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
-}
-		<?php
-	}
-}
-
-/**
- * Decode HTML Entities
- *
- * This implements HTML5 as of revision 967 (2007-06-28)
- *
- * @package SimplePie
- */
-class SimplePie_Decode_HTML_Entities
-{
-	/**
-	 * Data to be parsed
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $data = '';
-
-	/**
-	 * Currently consumed bytes
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $consumed = '';
-
-	/**
-	 * Position of the current byte being parsed
-	 *
-	 * @access private
-	 * @var int
-	 */
-	var $position = 0;
-
-	/**
-	 * Create an instance of the class with the input data
-	 *
-	 * @access public
-	 * @param string $data Input data
-	 */
-	function SimplePie_Decode_HTML_Entities($data)
-	{
-		$this->data = $data;
-	}
-
-	/**
-	 * Parse the input data
-	 *
-	 * @access public
-	 * @return string Output data
-	 */
-	function parse()
-	{
-		while (($this->position = strpos($this->data, '&', $this->position)) !== false)
-		{
-			$this->consume();
-			$this->entity();
-			$this->consumed = '';
-		}
-		return $this->data;
-	}
-
-	/**
-	 * Consume the next byte
-	 *
-	 * @access private
-	 * @return mixed The next byte, or false, if there is no more data
-	 */
-	function consume()
-	{
-		if (isset($this->data[$this->position]))
-		{
-			$this->consumed .= $this->data[$this->position];
-			return $this->data[$this->position++];
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	/**
-	 * Consume a range of characters
-	 *
-	 * @access private
-	 * @param string $chars Characters to consume
-	 * @return mixed A series of characters that match the range, or false
-	 */
-	function consume_range($chars)
-	{
-		if ($len = strspn($this->data, $chars, $this->position))
-		{
-			$data = substr($this->data, $this->position, $len);
-			$this->consumed .= $data;
-			$this->position += $len;
-			return $data;
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	/**
-	 * Unconsume one byte
-	 *
-	 * @access private
-	 */
-	function unconsume()
-	{
-		$this->consumed = substr($this->consumed, 0, -1);
-		$this->position--;
-	}
-
-	/**
-	 * Decode an entity
-	 *
-	 * @access private
-	 */
-	function entity()
-	{
-		switch ($this->consume())
-		{
-			case "\x09":
-			case "\x0A":
-			case "\x0B":
-			case "\x0B":
-			case "\x0C":
-			case "\x20":
-			case "\x3C":
-			case "\x26":
-			case false:
-				break;
-
-			case "\x23":
-				switch ($this->consume())
-				{
-					case "\x78":
-					case "\x58":
-						$range = '0123456789ABCDEFabcdef';
-						$hex = true;
-						break;
-
-					default:
-						$range = '0123456789';
-						$hex = false;
-						$this->unconsume();
-						break;
-				}
-
-				if ($codepoint = $this->consume_range($range))
-				{
-					static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8");
-
-					if ($hex)
-					{
-						$codepoint = hexdec($codepoint);
-					}
-					else
-					{
-						$codepoint = intval($codepoint);
-					}
-
-					if (isset($windows_1252_specials[$codepoint]))
-					{
-						$replacement = $windows_1252_specials[$codepoint];
-					}
-					else
-					{
-						$replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
-					}
-
-					if (!in_array($this->consume(), array(';', false), true))
-					{
-						$this->unconsume();
-					}
-
-					$consumed_length = strlen($this->consumed);
-					$this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
-					$this->position += strlen($replacement) - $consumed_length;
-				}
-				break;
-
-			default:
-				static $entities = array('Aacute' => "\xC3\x81", 'aacute' => "\xC3\xA1", 'Aacute;' => "\xC3\x81", 'aacute;' => "\xC3\xA1", 'Acirc' => "\xC3\x82", 'acirc' => "\xC3\xA2", 'Acirc;' => "\xC3\x82", 'acirc;' => "\xC3\xA2", 'acute' => "\xC2\xB4", 'acute;' => "\xC2\xB4", 'AElig' => "\xC3\x86", 'aelig' => "\xC3\xA6", 'AElig;' => "\xC3\x86", 'aelig;' => "\xC3\xA6", 'Agrave' => "\xC3\x80", 'agrave' => "\xC3\xA0", 'Agrave;' => "\xC3\x80", 'agrave;' => "\xC3\xA0", 'alefsym;' => "\xE2\x84\xB5", 'Alpha;' => "\xCE\x91", 'alpha;' => "\xCE\xB1", 'AMP' => "\x26", 'amp' => "\x26", 'AMP;' => "\x26", 'amp;' => "\x26", 'and;' => "\xE2\x88\xA7", 'ang;' => "\xE2\x88\xA0", 'apos;' => "\x27", 'Aring' => "\xC3\x85", 'aring' => "\xC3\xA5", 'Aring;' => "\xC3\x85", 'aring;' => "\xC3\xA5", 'asymp;' => "\xE2\x89\x88", 'Atilde' => "\xC3\x83", 'atilde' => "\xC3\xA3", 'Atilde;' => "\xC3\x83", 'atilde;' => "\xC3\xA3", 'Auml' => "\xC3\x84", 'auml' => "\xC3\xA4", 'Auml;' => "\xC3\x84", 'auml;' => "\xC3\xA4", 'bdquo;' => "\xE2\x80\x9E", 'Beta;' => "\xCE\x92", 'beta;' => "\xCE\xB2", 'brvbar' => "\xC2\xA6", 'brvbar;' => "\xC2\xA6", 'bull;' => "\xE2\x80\xA2", 'cap;' => "\xE2\x88\xA9", 'Ccedil' => "\xC3\x87", 'ccedil' => "\xC3\xA7", 'Ccedil;' => "\xC3\x87", 'ccedil;' => "\xC3\xA7", 'cedil' => "\xC2\xB8", 'cedil;' => "\xC2\xB8", 'cent' => "\xC2\xA2", 'cent;' => "\xC2\xA2", 'Chi;' => "\xCE\xA7", 'chi;' => "\xCF\x87", 'circ;' => "\xCB\x86", 'clubs;' => "\xE2\x99\xA3", 'cong;' => "\xE2\x89\x85", 'COPY' => "\xC2\xA9", 'copy' => "\xC2\xA9", 'COPY;' => "\xC2\xA9", 'copy;' => "\xC2\xA9", 'crarr;' => "\xE2\x86\xB5", 'cup;' => "\xE2\x88\xAA", 'curren' => "\xC2\xA4", 'curren;' => "\xC2\xA4", 'Dagger;' => "\xE2\x80\xA1", 'dagger;' => "\xE2\x80\xA0", 'dArr;' => "\xE2\x87\x93", 'darr;' => "\xE2\x86\x93", 'deg' => "\xC2\xB0", 'deg;' => "\xC2\xB0", 'Delta;' => "\xCE\x94", 'delta;' => "\xCE\xB4", 'diams;' => "\xE2\x99\xA6", 'divide' => "\xC3\xB7", 'divide;' => "\xC3\xB7", 'Eacute' => "\xC3\x89", 'eacute' => "\xC3\xA9", 'Eacute;' => "\xC3\x89", 'eacute;' => "\xC3\xA9", 'Ecirc' => "\xC3\x8A", 'ecirc' => "\xC3\xAA", 'Ecirc;' => "\xC3\x8A", 'ecirc;' => "\xC3\xAA", 'Egrave' => "\xC3\x88", 'egrave' => "\xC3\xA8", 'Egrave;' => "\xC3\x88", 'egrave;' => "\xC3\xA8", 'empty;' => "\xE2\x88\x85", 'emsp;' => "\xE2\x80\x83", 'ensp;' => "\xE2\x80\x82", 'Epsilon;' => "\xCE\x95", 'epsilon;' => "\xCE\xB5", 'equiv;' => "\xE2\x89\xA1", 'Eta;' => "\xCE\x97", 'eta;' => "\xCE\xB7", 'ETH' => "\xC3\x90", 'eth' => "\xC3\xB0", 'ETH;' => "\xC3\x90", 'eth;' => "\xC3\xB0", 'Euml' => "\xC3\x8B", 'euml' => "\xC3\xAB", 'Euml;' => "\xC3\x8B", 'euml;' => "\xC3\xAB", 'euro;' => "\xE2\x82\xAC", 'exist;' => "\xE2\x88\x83", 'fnof;' => "\xC6\x92", 'forall;' => "\xE2\x88\x80", 'frac12' => "\xC2\xBD", 'frac12;' => "\xC2\xBD", 'frac14' => "\xC2\xBC", 'frac14;' => "\xC2\xBC", 'frac34' => "\xC2\xBE", 'frac34;' => "\xC2\xBE", 'frasl;' => "\xE2\x81\x84", 'Gamma;' => "\xCE\x93", 'gamma;' => "\xCE\xB3", 'ge;' => "\xE2\x89\xA5", 'GT' => "\x3E", 'gt' => "\x3E", 'GT;' => "\x3E", 'gt;' => "\x3E", 'hArr;' => "\xE2\x87\x94", 'harr;' => "\xE2\x86\x94", 'hearts;' => "\xE2\x99\xA5", 'hellip;' => "\xE2\x80\xA6", 'Iacute' => "\xC3\x8D", 'iacute' => "\xC3\xAD", 'Iacute;' => "\xC3\x8D", 'iacute;' => "\xC3\xAD", 'Icirc' => "\xC3\x8E", 'icirc' => "\xC3\xAE", 'Icirc;' => "\xC3\x8E", 'icirc;' => "\xC3\xAE", 'iexcl' => "\xC2\xA1", 'iexcl;' => "\xC2\xA1", 'Igrave' => "\xC3\x8C", 'igrave' => "\xC3\xAC", 'Igrave;' => "\xC3\x8C", 'igrave;' => "\xC3\xAC", 'image;' => "\xE2\x84\x91", 'infin;' => "\xE2\x88\x9E", 'int;' => "\xE2\x88\xAB", 'Iota;' => "\xCE\x99", 'iota;' => "\xCE\xB9", 'iquest' => "\xC2\xBF", 'iquest;' => "\xC2\xBF", 'isin;' => "\xE2\x88\x88", 'Iuml' => "\xC3\x8F", 'iuml' => "\xC3\xAF", 'Iuml;' => "\xC3\x8F", 'iuml;' => "\xC3\xAF", 'Kappa;' => "\xCE\x9A", 'kappa;' => "\xCE\xBA", 'Lambda;' => "\xCE\x9B", 'lambda;' => "\xCE\xBB", 'lang;' => "\xE3\x80\x88", 'laquo' => "\xC2\xAB", 'laquo;' => "\xC2\xAB", 'lArr;' => "\xE2\x87\x90", 'larr;' => "\xE2\x86\x90", 'lceil;' => "\xE2\x8C\x88", 'ldquo;' => "\xE2\x80\x9C", 'le;' => "\xE2\x89\xA4", 'lfloor;' => "\xE2\x8C\x8A", 'lowast;' => "\xE2\x88\x97", 'loz;' => "\xE2\x97\x8A", 'lrm;' => "\xE2\x80\x8E", 'lsaquo;' => "\xE2\x80\xB9", 'lsquo;' => "\xE2\x80\x98", 'LT' => "\x3C", 'lt' => "\x3C", 'LT;' => "\x3C", 'lt;' => "\x3C", 'macr' => "\xC2\xAF", 'macr;' => "\xC2\xAF", 'mdash;' => "\xE2\x80\x94", 'micro' => "\xC2\xB5", 'micro;' => "\xC2\xB5", 'middot' => "\xC2\xB7", 'middot;' => "\xC2\xB7", 'minus;' => "\xE2\x88\x92", 'Mu;' => "\xCE\x9C", 'mu;' => "\xCE\xBC", 'nabla;' => "\xE2\x88\x87", 'nbsp' => "\xC2\xA0", 'nbsp;' => "\xC2\xA0", 'ndash;' => "\xE2\x80\x93", 'ne;' => "\xE2\x89\xA0", 'ni;' => "\xE2\x88\x8B", 'not' => "\xC2\xAC", 'not;' => "\xC2\xAC", 'notin;' => "\xE2\x88\x89", 'nsub;' => "\xE2\x8A\x84", 'Ntilde' => "\xC3\x91", 'ntilde' => "\xC3\xB1", 'Ntilde;' => "\xC3\x91", 'ntilde;' => "\xC3\xB1", 'Nu;' => "\xCE\x9D", 'nu;' => "\xCE\xBD", 'Oacute' => "\xC3\x93", 'oacute' => "\xC3\xB3", 'Oacute;' => "\xC3\x93", 'oacute;' => "\xC3\xB3", 'Ocirc' => "\xC3\x94", 'ocirc' => "\xC3\xB4", 'Ocirc;' => "\xC3\x94", 'ocirc;' => "\xC3\xB4", 'OElig;' => "\xC5\x92", 'oelig;' => "\xC5\x93", 'Ograve' => "\xC3\x92", 'ograve' => "\xC3\xB2", 'Ograve;' => "\xC3\x92", 'ograve;' => "\xC3\xB2", 'oline;' => "\xE2\x80\xBE", 'Omega;' => "\xCE\xA9", 'omega;' => "\xCF\x89", 'Omicron;' => "\xCE\x9F", 'omicron;' => "\xCE\xBF", 'oplus;' => "\xE2\x8A\x95", 'or;' => "\xE2\x88\xA8", 'ordf' => "\xC2\xAA", 'ordf;' => "\xC2\xAA", 'ordm' => "\xC2\xBA", 'ordm;' => "\xC2\xBA", 'Oslash' => "\xC3\x98", 'oslash' => "\xC3\xB8", 'Oslash;' => "\xC3\x98", 'oslash;' => "\xC3\xB8", 'Otilde' => "\xC3\x95", 'otilde' => "\xC3\xB5", 'Otilde;' => "\xC3\x95", 'otilde;' => "\xC3\xB5", 'otimes;' => "\xE2\x8A\x97", 'Ouml' => "\xC3\x96", 'ouml' => "\xC3\xB6", 'Ouml;' => "\xC3\x96", 'ouml;' => "\xC3\xB6", 'para' => "\xC2\xB6", 'para;' => "\xC2\xB6", 'part;' => "\xE2\x88\x82", 'permil;' => "\xE2\x80\xB0", 'perp;' => "\xE2\x8A\xA5", 'Phi;' => "\xCE\xA6", 'phi;' => "\xCF\x86", 'Pi;' => "\xCE\xA0", 'pi;' => "\xCF\x80", 'piv;' => "\xCF\x96", 'plusmn' => "\xC2\xB1", 'plusmn;' => "\xC2\xB1", 'pound' => "\xC2\xA3", 'pound;' => "\xC2\xA3", 'Prime;' => "\xE2\x80\xB3", 'prime;' => "\xE2\x80\xB2", 'prod;' => "\xE2\x88\x8F", 'prop;' => "\xE2\x88\x9D", 'Psi;' => "\xCE\xA8", 'psi;' => "\xCF\x88", 'QUOT' => "\x22", 'quot' => "\x22", 'QUOT;' => "\x22", 'quot;' => "\x22", 'radic;' => "\xE2\x88\x9A", 'rang;' => "\xE3\x80\x89", 'raquo' => "\xC2\xBB", 'raquo;' => "\xC2\xBB", 'rArr;' => "\xE2\x87\x92", 'rarr;' => "\xE2\x86\x92", 'rceil;' => "\xE2\x8C\x89", 'rdquo;' => "\xE2\x80\x9D", 'real;' => "\xE2\x84\x9C", 'REG' => "\xC2\xAE", 'reg' => "\xC2\xAE", 'REG;' => "\xC2\xAE", 'reg;' => "\xC2\xAE", 'rfloor;' => "\xE2\x8C\x8B", 'Rho;' => "\xCE\xA1", 'rho;' => "\xCF\x81", 'rlm;' => "\xE2\x80\x8F", 'rsaquo;' => "\xE2\x80\xBA", 'rsquo;' => "\xE2\x80\x99", 'sbquo;' => "\xE2\x80\x9A", 'Scaron;' => "\xC5\xA0", 'scaron;' => "\xC5\xA1", 'sdot;' => "\xE2\x8B\x85", 'sect' => "\xC2\xA7", 'sect;' => "\xC2\xA7", 'shy' => "\xC2\xAD", 'shy;' => "\xC2\xAD", 'Sigma;' => "\xCE\xA3", 'sigma;' => "\xCF\x83", 'sigmaf;' => "\xCF\x82", 'sim;' => "\xE2\x88\xBC", 'spades;' => "\xE2\x99\xA0", 'sub;' => "\xE2\x8A\x82", 'sube;' => "\xE2\x8A\x86", 'sum;' => "\xE2\x88\x91", 'sup;' => "\xE2\x8A\x83", 'sup1' => "\xC2\xB9", 'sup1;' => "\xC2\xB9", 'sup2' => "\xC2\xB2", 'sup2;' => "\xC2\xB2", 'sup3' => "\xC2\xB3", 'sup3;' => "\xC2\xB3", 'supe;' => "\xE2\x8A\x87", 'szlig' => "\xC3\x9F", 'szlig;' => "\xC3\x9F", 'Tau;' => "\xCE\xA4", 'tau;' => "\xCF\x84", 'there4;' => "\xE2\x88\xB4", 'Theta;' => "\xCE\x98", 'theta;' => "\xCE\xB8", 'thetasym;' => "\xCF\x91", 'thinsp;' => "\xE2\x80\x89", 'THORN' => "\xC3\x9E", 'thorn' => "\xC3\xBE", 'THORN;' => "\xC3\x9E", 'thorn;' => "\xC3\xBE", 'tilde;' => "\xCB\x9C", 'times' => "\xC3\x97", 'times;' => "\xC3\x97", 'TRADE;' => "\xE2\x84\xA2", 'trade;' => "\xE2\x84\xA2", 'Uacute' => "\xC3\x9A", 'uacute' => "\xC3\xBA", 'Uacute;' => "\xC3\x9A", 'uacute;' => "\xC3\xBA", 'uArr;' => "\xE2\x87\x91", 'uarr;' => "\xE2\x86\x91", 'Ucirc' => "\xC3\x9B", 'ucirc' => "\xC3\xBB", 'Ucirc;' => "\xC3\x9B", 'ucirc;' => "\xC3\xBB", 'Ugrave' => "\xC3\x99", 'ugrave' => "\xC3\xB9", 'Ugrave;' => "\xC3\x99", 'ugrave;' => "\xC3\xB9", 'uml' => "\xC2\xA8", 'uml;' => "\xC2\xA8", 'upsih;' => "\xCF\x92", 'Upsilon;' => "\xCE\xA5", 'upsilon;' => "\xCF\x85", 'Uuml' => "\xC3\x9C", 'uuml' => "\xC3\xBC", 'Uuml;' => "\xC3\x9C", 'uuml;' => "\xC3\xBC", 'weierp;' => "\xE2\x84\x98", 'Xi;' => "\xCE\x9E", 'xi;' => "\xCE\xBE", 'Yacute' => "\xC3\x9D", 'yacute' => "\xC3\xBD", 'Yacute;' => "\xC3\x9D", 'yacute;' => "\xC3\xBD", 'yen' => "\xC2\xA5", 'yen;' => "\xC2\xA5", 'yuml' => "\xC3\xBF", 'Yuml;' => "\xC5\xB8", 'yuml;' => "\xC3\xBF", 'Zeta;' => "\xCE\x96", 'zeta;' => "\xCE\xB6", 'zwj;' => "\xE2\x80\x8D", 'zwnj;' => "\xE2\x80\x8C");
-
-				for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
-				{
-					$consumed = substr($this->consumed, 1);
-					if (isset($entities[$consumed]))
-					{
-						$match = $consumed;
-					}
-				}
-
-				if ($match !== null)
-				{
- 					$this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
-					$this->position += strlen($entities[$match]) - strlen($consumed) - 1;
-				}
-				break;
-		}
-	}
-}
-
-/**
- * IRI parser/serialiser
- *
- * @package SimplePie
- */
-class SimplePie_IRI
-{
-	/**
-	 * Scheme
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $scheme;
-
-	/**
-	 * User Information
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $userinfo;
-
-	/**
-	 * Host
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $host;
-
-	/**
-	 * Port
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $port;
-
-	/**
-	 * Path
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $path;
-
-	/**
-	 * Query
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $query;
-
-	/**
-	 * Fragment
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $fragment;
-
-	/**
-	 * Whether the object represents a valid IRI
-	 *
-	 * @access private
-	 * @var array
-	 */
-	var $valid = array();
-
-	/**
-	 * Return the entire IRI when you try and read the object as a string
-	 *
-	 * @access public
-	 * @return string
-	 */
-	function __toString()
-	{
-		return $this->get_iri();
-	}
-
-	/**
-	 * Create a new IRI object, from a specified string
-	 *
-	 * @access public
-	 * @param string $iri
-	 * @return SimplePie_IRI
-	 */
-	function SimplePie_IRI($iri)
-	{
-		$iri = (string) $iri;
-		if ($iri !== '')
-		{
-			$parsed = $this->parse_iri($iri);
-			$this->set_scheme($parsed['scheme']);
-			$this->set_authority($parsed['authority']);
-			$this->set_path($parsed['path']);
-			$this->set_query($parsed['query']);
-			$this->set_fragment($parsed['fragment']);
-		}
-	}
-
-	/**
-	 * Create a new IRI object by resolving a relative IRI
-	 *
-	 * @static
-	 * @access public
-	 * @param SimplePie_IRI $base Base IRI
-	 * @param string $relative Relative IRI
-	 * @return SimplePie_IRI
-	 */
-	function absolutize($base, $relative)
-	{
-		$relative = (string) $relative;
-		if ($relative !== '')
-		{
-			$relative = new SimplePie_IRI($relative);
-			if ($relative->get_scheme() !== null)
-			{
-				$target = $relative;
-			}
-			elseif ($base->get_iri() !== null)
-			{
-				if ($relative->get_authority() !== null)
-				{
-					$target = $relative;
-					$target->set_scheme($base->get_scheme());
-				}
-				else
-				{
-					$target = new SimplePie_IRI('');
-					$target->set_scheme($base->get_scheme());
-					$target->set_userinfo($base->get_userinfo());
-					$target->set_host($base->get_host());
-					$target->set_port($base->get_port());
-					if ($relative->get_path() !== null)
-					{
-						if (strpos($relative->get_path(), '/') === 0)
-						{
-							$target->set_path($relative->get_path());
-						}
-						elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
-						{
-							$target->set_path('/' . $relative->get_path());
-						}
-						elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
-						{
-							$target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
-						}
-						else
-						{
-							$target->set_path($relative->get_path());
-						}
-						$target->set_query($relative->get_query());
-					}
-					else
-					{
-						$target->set_path($base->get_path());
-						if ($relative->get_query() !== null)
-						{
-							$target->set_query($relative->get_query());
-						}
-						elseif ($base->get_query() !== null)
-						{
-							$target->set_query($base->get_query());
-						}
-					}
-				}
-				$target->set_fragment($relative->get_fragment());
-			}
-			else
-			{
-				// No base URL, just return the relative URL
-				$target = $relative;
-			}
-		}
-		else
-		{
-			$target = $base;
-		}
-		return $target;
-	}
-
-	/**
-	 * Parse an IRI into scheme/authority/path/query/fragment segments
-	 *
-	 * @access private
-	 * @param string $iri
-	 * @return array
-	 */
-	function parse_iri($iri)
-	{
-		preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
-		for ($i = count($match); $i <= 9; $i++)
-		{
-			$match[$i] = '';
-		}
-		return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
-	}
-
-	/**
-	 * Remove dot segments from a path
-	 *
-	 * @access private
-	 * @param string $input
-	 * @return string
-	 */
-	function remove_dot_segments($input)
-	{
-		$output = '';
-		while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
-		{
-			// A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
-			if (strpos($input, '../') === 0)
-			{
-				$input = substr($input, 3);
-			}
-			elseif (strpos($input, './') === 0)
-			{
-				$input = substr($input, 2);
-			}
-			// B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
-			elseif (strpos($input, '/./') === 0)
-			{
-				$input = substr_replace($input, '/', 0, 3);
-			}
-			elseif ($input === '/.')
-			{
-				$input = '/';
-			}
-			// C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
-			elseif (strpos($input, '/../') === 0)
-			{
-				$input = substr_replace($input, '/', 0, 4);
-				$output = substr_replace($output, '', strrpos($output, '/'));
-			}
-			elseif ($input === '/..')
-			{
-				$input = '/';
-				$output = substr_replace($output, '', strrpos($output, '/'));
-			}
-			// D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
-			elseif ($input === '.' || $input === '..')
-			{
-				$input = '';
-			}
-			// E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
-			elseif (($pos = strpos($input, '/', 1)) !== false)
-			{
-				$output .= substr($input, 0, $pos);
-				$input = substr_replace($input, '', 0, $pos);
-			}
-			else
-			{
-				$output .= $input;
-				$input = '';
-			}
-		}
-		return $output . $input;
-	}
-
-	/**
-	 * Replace invalid character with percent encoding
-	 *
-	 * @access private
-	 * @param string $string Input string
-	 * @param string $valid_chars Valid characters
-	 * @param int $case Normalise case
-	 * @return string
-	 */
-	function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
-	{
-		// Normalise case
-		if ($case & SIMPLEPIE_LOWERCASE)
-		{
-			$string = strtolower($string);
-		}
-		elseif ($case & SIMPLEPIE_UPPERCASE)
-		{
-			$string = strtoupper($string);
-		}
-
-		// Store position and string length (to avoid constantly recalculating this)
-		$position = 0;
-		$strlen = strlen($string);
-
-		// Loop as long as we have invalid characters, advancing the position to the next invalid character
-		while (($position += strspn($string, $valid_chars, $position)) < $strlen)
-		{
-			// If we have a % character
-			if ($string[$position] === '%')
-			{
-				// If we have a pct-encoded section
-				if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
-				{
-					// Get the the represented character
-					$chr = chr(hexdec(substr($string, $position + 1, 2)));
-
-					// If the character is valid, replace the pct-encoded with the actual character while normalising case
-					if (strpos($valid_chars, $chr) !== false)
-					{
-						if ($case & SIMPLEPIE_LOWERCASE)
-						{
-							$chr = strtolower($chr);
-						}
-						elseif ($case & SIMPLEPIE_UPPERCASE)
-						{
-							$chr = strtoupper($chr);
-						}
-						$string = substr_replace($string, $chr, $position, 3);
-						$strlen -= 2;
-						$position++;
-					}
-
-					// Otherwise just normalise the pct-encoded to uppercase
-					else
-					{
-						$string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
-						$position += 3;
-					}
-				}
-				// If we don't have a pct-encoded section, just replace the % with its own esccaped form
-				else
-				{
-					$string = substr_replace($string, '%25', $position, 1);
-					$strlen += 2;
-					$position += 3;
-				}
-			}
-			// If we have an invalid character, change into its pct-encoded form
-			else
-			{
-				$replacement = sprintf("%%%02X", ord($string[$position]));
-				$string = str_replace($string[$position], $replacement, $string);
-				$strlen = strlen($string);
-			}
-		}
-		return $string;
-	}
-
-	/**
-	 * Check if the object represents a valid IRI
-	 *
-	 * @access public
-	 * @return bool
-	 */
-	function is_valid()
-	{
-		return array_sum($this->valid) === count($this->valid);
-	}
-
-	/**
-	 * Set the scheme. Returns true on success, false on failure (if there are
-	 * any invalid characters).
-	 *
-	 * @access public
-	 * @param string $scheme
-	 * @return bool
-	 */
-	function set_scheme($scheme)
-	{
-		if ($scheme === null || $scheme === '')
-		{
-			$this->scheme = null;
-		}
-		else
-		{
-			$len = strlen($scheme);
-			switch (true)
-			{
-				case $len > 1:
-					if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
-					{
-						$this->scheme = null;
-						$this->valid[__FUNCTION__] = false;
-						return false;
-					}
-
-				case $len > 0:
-					if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
-					{
-						$this->scheme = null;
-						$this->valid[__FUNCTION__] = false;
-						return false;
-					}
-			}
-			$this->scheme = strtolower($scheme);
-		}
-		$this->valid[__FUNCTION__] = true;
-		return true;
-	}
-
-	/**
-	 * Set the authority. Returns true on success, false on failure (if there are
-	 * any invalid characters).
-	 *
-	 * @access public
-	 * @param string $authority
-	 * @return bool
-	 */
-	function set_authority($authority)
-	{
-		if (($userinfo_end = strrpos($authority, '@')) !== false)
-		{
-			$userinfo = substr($authority, 0, $userinfo_end);
-			$authority = substr($authority, $userinfo_end + 1);
-		}
-		else
-		{
-			$userinfo = null;
-		}
-
-		if (($port_start = strpos($authority, ':')) !== false)
-		{
-			$port = substr($authority, $port_start + 1);
-			$authority = substr($authority, 0, $port_start);
-		}
-		else
-		{
-			$port = null;
-		}
-
-		return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
-	}
-
-	/**
-	 * Set the userinfo.
-	 *
-	 * @access public
-	 * @param string $userinfo
-	 * @return bool
-	 */
-	function set_userinfo($userinfo)
-	{
-		if ($userinfo === null || $userinfo === '')
-		{
-			$this->userinfo = null;
-		}
-		else
-		{
-			$this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
-		}
-		$this->valid[__FUNCTION__] = true;
-		return true;
-	}
-
-	/**
-	 * Set the host. Returns true on success, false on failure (if there are
-	 * any invalid characters).
-	 *
-	 * @access public
-	 * @param string $host
-	 * @return bool
-	 */
-	function set_host($host)
-	{
-		if ($host === null || $host === '')
-		{
-			$this->host = null;
-			$this->valid[__FUNCTION__] = true;
-			return true;
-		}
-		elseif ($host[0] === '[' && substr($host, -1) === ']')
-		{
-			if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
-			{
-				$this->host = $host;
-				$this->valid[__FUNCTION__] = true;
-				return true;
-			}
-			else
-			{
-				$this->host = null;
-				$this->valid[__FUNCTION__] = false;
-				return false;
-			}
-		}
-		else
-		{
-			$this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
-			$this->valid[__FUNCTION__] = true;
-			return true;
-		}
-	}
-
-	/**
-	 * Set the port. Returns true on success, false on failure (if there are
-	 * any invalid characters).
-	 *
-	 * @access public
-	 * @param string $port
-	 * @return bool
-	 */
-	function set_port($port)
-	{
-		if ($port === null || $port === '')
-		{
-			$this->port = null;
-			$this->valid[__FUNCTION__] = true;
-			return true;
-		}
-		elseif (strspn($port, '0123456789') === strlen($port))
-		{
-			$this->port = (int) $port;
-			$this->valid[__FUNCTION__] = true;
-			return true;
-		}
-		else
-		{
-			$this->port = null;
-			$this->valid[__FUNCTION__] = false;
-			return false;
-		}
-	}
-
-	/**
-	 * Set the path.
-	 *
-	 * @access public
-	 * @param string $path
-	 * @return bool
-	 */
-	function set_path($path)
-	{
-		if ($path === null || $path === '')
-		{
-			$this->path = null;
-			$this->valid[__FUNCTION__] = true;
-			return true;
-		}
-		elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
-		{
-			$this->path = null;
-			$this->valid[__FUNCTION__] = false;
-			return false;
-		}
-		else
-		{
-			$this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
-			if ($this->scheme !== null)
-			{
-				$this->path = $this->remove_dot_segments($this->path);
-			}
-			$this->valid[__FUNCTION__] = true;
-			return true;
-		}
-	}
-
-	/**
-	 * Set the query.
-	 *
-	 * @access public
-	 * @param string $query
-	 * @return bool
-	 */
-	function set_query($query)
-	{
-		if ($query === null || $query === '')
-		{
-			$this->query = null;
-		}
-		else
-		{
-			$this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?');
-		}
-		$this->valid[__FUNCTION__] = true;
-		return true;
-	}
-
-	/**
-	 * Set the fragment.
-	 *
-	 * @access public
-	 * @param string $fragment
-	 * @return bool
-	 */
-	function set_fragment($fragment)
-	{
-		if ($fragment === null || $fragment === '')
-		{
-			$this->fragment = null;
-		}
-		else
-		{
-			$this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
-		}
-		$this->valid[__FUNCTION__] = true;
-		return true;
-	}
-
-	/**
-	 * Get the complete IRI
-	 *
-	 * @access public
-	 * @return string
-	 */
-	function get_iri()
-	{
-		$iri = '';
-		if ($this->scheme !== null)
-		{
-			$iri .= $this->scheme . ':';
-		}
-		if (($authority = $this->get_authority()) !== null)
-		{
-			$iri .= '//' . $authority;
-		}
-		if ($this->path !== null)
-		{
-			$iri .= $this->path;
-		}
-		if ($this->query !== null)
-		{
-			$iri .= '?' . $this->query;
-		}
-		if ($this->fragment !== null)
-		{
-			$iri .= '#' . $this->fragment;
-		}
-
-		if ($iri !== '')
-		{
-			return $iri;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	/**
-	 * Get the scheme
-	 *
-	 * @access public
-	 * @return string
-	 */
-	function get_scheme()
-	{
-		return $this->scheme;
-	}
-
-	/**
-	 * Get the complete authority
-	 *
-	 * @access public
-	 * @return string
-	 */
-	function get_authority()
-	{
-		$authority = '';
-		if ($this->userinfo !== null)
-		{
-			$authority .= $this->userinfo . '@';
-		}
-		if ($this->host !== null)
-		{
-			$authority .= $this->host;
-		}
-		if ($this->port !== null)
-		{
-			$authority .= ':' . $this->port;
-		}
-
-		if ($authority !== '')
-		{
-			return $authority;
-		}
-		else
-		{
-			return null;
-		}
-	}
-
-	/**
-	 * Get the user information
-	 *
-	 * @access public
-	 * @return string
-	 */
-	function get_userinfo()
-	{
-		return $this->userinfo;
-	}
-
-	/**
-	 * Get the host
-	 *
-	 * @access public
-	 * @return string
-	 */
-	function get_host()
-	{
-		return $this->host;
-	}
-
-	/**
-	 * Get the port
-	 *
-	 * @access public
-	 * @return string
-	 */
-	function get_port()
-	{
-		return $this->port;
-	}
-
-	/**
-	 * Get the path
-	 *
-	 * @access public
-	 * @return string
-	 */
-	function get_path()
-	{
-		return $this->path;
-	}
-
-	/**
-	 * Get the query
-	 *
-	 * @access public
-	 * @return string
-	 */
-	function get_query()
-	{
-		return $this->query;
-	}
-
-	/**
-	 * Get the fragment
-	 *
-	 * @access public
-	 * @return string
-	 */
-	function get_fragment()
-	{
-		return $this->fragment;
-	}
-}
-
-/**
- * Class to validate and to work with IPv6 addresses.
- *
- * @package SimplePie
- * @copyright 2003-2005 The PHP Group
- * @license http://www.opensource.org/licenses/bsd-license.php
- * @link http://pear.php.net/package/Net_IPv6
- * @author Alexander Merz <alexander.merz@web.de>
- * @author elfrink at introweb dot nl
- * @author Josh Peck <jmp at joshpeck dot org>
- * @author Geoffrey Sneddon <geoffers@gmail.com>
- */
-class SimplePie_Net_IPv6
-{
-	/**
-	 * Removes a possible existing netmask specification of an IP address.
-	 *
-	 * @param string $ip the (compressed) IP as Hex representation
-	 * @return string the IP the without netmask
-	 * @since 1.1.0
-	 * @access public
-	 * @static
-	 */
-	function removeNetmaskSpec($ip)
-	{
-		if (strpos($ip, '/') !== false)
-		{
-			list($addr, $nm) = explode('/', $ip);
-		}
-		else
-		{
-			$addr = $ip;
-		}
-		return $addr;
-	}
-
-	/**
-	 * Uncompresses an IPv6 address
-	 *
-	 * RFC 2373 allows you to compress zeros in an address to '::'. This
-	 * function expects an valid IPv6 address and expands the '::' to
-	 * the required zeros.
-	 *
-	 * Example:	 FF01::101	->	FF01:0:0:0:0:0:0:101
-	 *			 ::1		->	0:0:0:0:0:0:0:1
-	 *
-	 * @access public
-	 * @static
-	 * @param string $ip a valid IPv6-address (hex format)
-	 * @return string the uncompressed IPv6-address (hex format)
-	 */
-	function Uncompress($ip)
-	{
-		$uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
-		$c1 = -1;
-		$c2 = -1;
-		if (strpos($ip, '::') !== false)
-		{
-			list($ip1, $ip2) = explode('::', $ip);
-			if ($ip1 === '')
-			{
-				$c1 = -1;
-			}
-			else
-			{
-				$pos = 0;
-				if (($pos = substr_count($ip1, ':')) > 0)
-				{
-					$c1 = $pos;
-				}
-				else
-				{
-					$c1 = 0;
-				}
-			}
-			if ($ip2 === '')
-			{
-				$c2 = -1;
-			}
-			else
-			{
-				$pos = 0;
-				if (($pos = substr_count($ip2, ':')) > 0)
-				{
-					$c2 = $pos;
-				}
-				else
-				{
-					$c2 = 0;
-				}
-			}
-			if (strstr($ip2, '.'))
-			{
-				$c2++;
-			}
-			// ::
-			if ($c1 === -1 && $c2 === -1)
-			{
-				$uip = '0:0:0:0:0:0:0:0';
-			}
-			// ::xxx
-			else if ($c1 === -1)
-			{
-				$fill = str_repeat('0:', 7 - $c2);
-				$uip =	str_replace('::', $fill, $uip);
-			}
-			// xxx::
-			else if ($c2 === -1)
-			{
-				$fill = str_repeat(':0', 7 - $c1);
-				$uip =	str_replace('::', $fill, $uip);
-			}
-			// xxx::xxx
-			else
-			{
-				$fill = str_repeat(':0:', 6 - $c2 - $c1);
-				$uip =	str_replace('::', $fill, $uip);
-				$uip =	str_replace('::', ':', $uip);
-			}
-		}
-		return $uip;
-	}
-
-	/**
-	 * Splits an IPv6 address into the IPv6 and a possible IPv4 part
-	 *
-	 * RFC 2373 allows you to note the last two parts of an IPv6 address as
-	 * an IPv4 compatible address
-	 *
-	 * Example:	 0:0:0:0:0:0:13.1.68.3
-	 *			 0:0:0:0:0:FFFF:129.144.52.38
-	 *
-	 * @access public
-	 * @static
-	 * @param string $ip a valid IPv6-address (hex format)
-	 * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
-	 */
-	function SplitV64($ip)
-	{
-		$ip = SimplePie_Net_IPv6::Uncompress($ip);
-		if (strstr($ip, '.'))
-		{
-			$pos = strrpos($ip, ':');
-			$ip[$pos] = '_';
-			$ipPart = explode('_', $ip);
-			return $ipPart;
-		}
-		else
-		{
-			return array($ip, '');
-		}
-	}
-
-	/**
-	 * Checks an IPv6 address
-	 *
-	 * Checks if the given IP is IPv6-compatible
-	 *
-	 * @access public
-	 * @static
-	 * @param string $ip a valid IPv6-address
-	 * @return bool true if $ip is an IPv6 address
-	 */
-	function checkIPv6($ip)
-	{
-		$ipPart = SimplePie_Net_IPv6::SplitV64($ip);
-		$count = 0;
-		if (!empty($ipPart[0]))
-		{
-			$ipv6 = explode(':', $ipPart[0]);
-			for ($i = 0; $i < count($ipv6); $i++)
-			{
-				$dec = hexdec($ipv6[$i]);
-				$hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
-				if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
-				{
-					$count++;
-				}
-			}
-			if ($count === 8)
-			{
-				return true;
-			}
-			elseif ($count === 6 && !empty($ipPart[1]))
-			{
-				$ipv4 = explode('.', $ipPart[1]);
-				$count = 0;
-				foreach ($ipv4 as $ipv4_part)
-				{
-					if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
-					{
-						$count++;
-					}
-				}
-				if ($count === 4)
-				{
-					return true;
-				}
-			}
-			else
-			{
-				return false;
-			}
-
-		}
-		else
-		{
-			return false;
-		}
-	}
-}
-
-/**
- * Date Parser
- *
- * @package SimplePie
- */
-class SimplePie_Parse_Date
-{
-	/**
-	 * Input data
-	 *
-	 * @access protected
-	 * @var string
-	 */
-	var $date;
-
-	/**
-	 * List of days, calendar day name => ordinal day number in the week
-	 *
-	 * @access protected
-	 * @var array
-	 */
-	var $day = array(
-		// English
-		'mon' => 1,
-		'monday' => 1,
-		'tue' => 2,
-		'tuesday' => 2,
-		'wed' => 3,
-		'wednesday' => 3,
-		'thu' => 4,
-		'thursday' => 4,
-		'fri' => 5,
-		'friday' => 5,
-		'sat' => 6,
-		'saturday' => 6,
-		'sun' => 7,
-		'sunday' => 7,
-		// Dutch
-		'maandag' => 1,
-		'dinsdag' => 2,
-		'woensdag' => 3,
-		'donderdag' => 4,
-		'vrijdag' => 5,
-		'zaterdag' => 6,
-		'zondag' => 7,
-		// French
-		'lundi' => 1,
-		'mardi' => 2,
-		'mercredi' => 3,
-		'jeudi' => 4,
-		'vendredi' => 5,
-		'samedi' => 6,
-		'dimanche' => 7,
-		// German
-		'montag' => 1,
-		'dienstag' => 2,
-		'mittwoch' => 3,
-		'donnerstag' => 4,
-		'freitag' => 5,
-		'samstag' => 6,
-		'sonnabend' => 6,
-		'sonntag' => 7,
-		// Italian
-		'lunedì' => 1,
-		'martedì' => 2,
-		'mercoledì' => 3,
-		'giovedì' => 4,
-		'venerdì' => 5,
-		'sabato' => 6,
-		'domenica' => 7,
-		// Spanish
-		'lunes' => 1,
-		'martes' => 2,
-		'miércoles' => 3,
-		'jueves' => 4,
-		'viernes' => 5,
-		'sábado' => 6,
-		'domingo' => 7,
-		// Finnish
-		'maanantai' => 1,
-		'tiistai' => 2,
-		'keskiviikko' => 3,
-		'torstai' => 4,
-		'perjantai' => 5,
-		'lauantai' => 6,
-		'sunnuntai' => 7,
-		// Hungarian
-		'hétfő' => 1,
-		'kedd' => 2,
-		'szerda' => 3,
-		'csütörtok' => 4,
-		'péntek' => 5,
-		'szombat' => 6,
-		'vasárnap' => 7,
-		// Greek
-		'Δευ' => 1,
-		'Τρι' => 2,
-		'Τετ' => 3,
-		'Πεμ' => 4,
-		'Παρ' => 5,
-		'Σαβ' => 6,
-		'Κυρ' => 7,
-	);
-
-	/**
-	 * List of months, calendar month name => calendar month number
-	 *
-	 * @access protected
-	 * @var array
-	 */
-	var $month = array(
-		// English
-		'jan' => 1,
-		'january' => 1,
-		'feb' => 2,
-		'february' => 2,
-		'mar' => 3,
-		'march' => 3,
-		'apr' => 4,
-		'april' => 4,
-		'may' => 5,
-		// No long form of May
-		'jun' => 6,
-		'june' => 6,
-		'jul' => 7,
-		'july' => 7,
-		'aug' => 8,
-		'august' => 8,
-		'sep' => 9,
-		'september' => 8,
-		'oct' => 10,
-		'october' => 10,
-		'nov' => 11,
-		'november' => 11,
-		'dec' => 12,
-		'december' => 12,
-		// Dutch
-		'januari' => 1,
-		'februari' => 2,
-		'maart' => 3,
-		'april' => 4,
-		'mei' => 5,
-		'juni' => 6,
-		'juli' => 7,
-		'augustus' => 8,
-		'september' => 9,
-		'oktober' => 10,
-		'november' => 11,
-		'december' => 12,
-		// French
-		'janvier' => 1,
-		'février' => 2,
-		'mars' => 3,
-		'avril' => 4,
-		'mai' => 5,
-		'juin' => 6,
-		'juillet' => 7,
-		'août' => 8,
-		'septembre' => 9,
-		'octobre' => 10,
-		'novembre' => 11,
-		'décembre' => 12,
-		// German
-		'januar' => 1,
-		'februar' => 2,
-		'märz' => 3,
-		'april' => 4,
-		'mai' => 5,
-		'juni' => 6,
-		'juli' => 7,
-		'august' => 8,
-		'september' => 9,
-		'oktober' => 10,
-		'november' => 11,
-		'dezember' => 12,
-		// Italian
-		'gennaio' => 1,
-		'febbraio' => 2,
-		'marzo' => 3,
-		'aprile' => 4,
-		'maggio' => 5,
-		'giugno' => 6,
-		'luglio' => 7,
-		'agosto' => 8,
-		'settembre' => 9,
-		'ottobre' => 10,
-		'novembre' => 11,
-		'dicembre' => 12,
-		// Spanish
-		'enero' => 1,
-		'febrero' => 2,
-		'marzo' => 3,
-		'abril' => 4,
-		'mayo' => 5,
-		'junio' => 6,
-		'julio' => 7,
-		'agosto' => 8,
-		'septiembre' => 9,
-		'setiembre' => 9,
-		'octubre' => 10,
-		'noviembre' => 11,
-		'diciembre' => 12,
-		// Finnish
-		'tammikuu' => 1,
-		'helmikuu' => 2,
-		'maaliskuu' => 3,
-		'huhtikuu' => 4,
-		'toukokuu' => 5,
-		'kesäkuu' => 6,
-		'heinäkuu' => 7,
-		'elokuu' => 8,
-		'suuskuu' => 9,
-		'lokakuu' => 10,
-		'marras' => 11,
-		'joulukuu' => 12,
-		// Hungarian
-		'január' => 1,
-		'február' => 2,
-		'március' => 3,
-		'április' => 4,
-		'május' => 5,
-		'június' => 6,
-		'július' => 7,
-		'augusztus' => 8,
-		'szeptember' => 9,
-		'október' => 10,
-		'november' => 11,
-		'december' => 12,
-		// Greek
-		'Ιαν' => 1,
-		'Φεβ' => 2,
-		'Μάώ' => 3,
-		'Μαώ' => 3,
-		'Απρ' => 4,
-		'Μάι' => 5,
-		'Μαϊ' => 5,
-		'Μαι' => 5,
-		'Ιούν' => 6,
-		'Ιον' => 6,
-		'Ιούλ' => 7,
-		'Ιολ' => 7,
-		'Αύγ' => 8,
-		'Αυγ' => 8,
-		'Σεπ' => 9,
-		'Οκτ' => 10,
-		'Νοέ' => 11,
-		'Δεκ' => 12,
-	);
-
-	/**
-	 * List of timezones, abbreviation => offset from UTC
-	 *
-	 * @access protected
-	 * @var array
-	 */
-	var $timezone = array(
-		'ACDT' => 37800,
-		'ACIT' => 28800,
-		'ACST' => 34200,
-		'ACT' => -18000,
-		'ACWDT' => 35100,
-		'ACWST' => 31500,
-		'AEDT' => 39600,
-		'AEST' => 36000,
-		'AFT' => 16200,
-		'AKDT' => -28800,
-		'AKST' => -32400,
-		'AMDT' => 18000,
-		'AMT' => -14400,
-		'ANAST' => 46800,
-		'ANAT' => 43200,
-		'ART' => -10800,
-		'AZOST' => -3600,
-		'AZST' => 18000,
-		'AZT' => 14400,
-		'BIOT' => 21600,
-		'BIT' => -43200,
-		'BOT' => -14400,
-		'BRST' => -7200,
-		'BRT' => -10800,
-		'BST' => 3600,
-		'BTT' => 21600,
-		'CAST' => 18000,
-		'CAT' => 7200,
-		'CCT' => 23400,
-		'CDT' => -18000,
-		'CEDT' => 7200,
-		'CET' => 3600,
-		'CGST' => -7200,
-		'CGT' => -10800,
-		'CHADT' => 49500,
-		'CHAST' => 45900,
-		'CIST' => -28800,
-		'CKT' => -36000,
-		'CLDT' => -10800,
-		'CLST' => -14400,
-		'COT' => -18000,
-		'CST' => -21600,
-		'CVT' => -3600,
-		'CXT' => 25200,
-		'DAVT' => 25200,
-		'DTAT' => 36000,
-		'EADT' => -18000,
-		'EAST' => -21600,
-		'EAT' => 10800,
-		'ECT' => -18000,
-		'EDT' => -14400,
-		'EEST' => 10800,
-		'EET' => 7200,
-		'EGT' => -3600,
-		'EKST' => 21600,
-		'EST' => -18000,
-		'FJT' => 43200,
-		'FKDT' => -10800,
-		'FKST' => -14400,
-		'FNT' => -7200,
-		'GALT' => -21600,
-		'GEDT' => 14400,
-		'GEST' => 10800,
-		'GFT' => -10800,
-		'GILT' => 43200,
-		'GIT' => -32400,
-		'GST' => 14400,
-		'GST' => -7200,
-		'GYT' => -14400,
-		'HAA' => -10800,
-		'HAC' => -18000,
-		'HADT' => -32400,
-		'HAE' => -14400,
-		'HAP' => -25200,
-		'HAR' => -21600,
-		'HAST' => -36000,
-		'HAT' => -9000,
-		'HAY' => -28800,
-		'HKST' => 28800,
-		'HMT' => 18000,
-		'HNA' => -14400,
-		'HNC' => -21600,
-		'HNE' => -18000,
-		'HNP' => -28800,
-		'HNR' => -25200,
-		'HNT' => -12600,
-		'HNY' => -32400,
-		'IRDT' => 16200,
-		'IRKST' => 32400,
-		'IRKT' => 28800,
-		'IRST' => 12600,
-		'JFDT' => -10800,
-		'JFST' => -14400,
-		'JST' => 32400,
-		'KGST' => 21600,
-		'KGT' => 18000,
-		'KOST' => 39600,
-		'KOVST' => 28800,
-		'KOVT' => 25200,
-		'KRAST' => 28800,
-		'KRAT' => 25200,
-		'KST' => 32400,
-		'LHDT' => 39600,
-		'LHST' => 37800,
-		'LINT' => 50400,
-		'LKT' => 21600,
-		'MAGST' => 43200,
-		'MAGT' => 39600,
-		'MAWT' => 21600,
-		'MDT' => -21600,
-		'MESZ' => 7200,
-		'MEZ' => 3600,
-		'MHT' => 43200,
-		'MIT' => -34200,
-		'MNST' => 32400,
-		'MSDT' => 14400,
-		'MSST' => 10800,
-		'MST' => -25200,
-		'MUT' => 14400,
-		'MVT' => 18000,
-		'MYT' => 28800,
-		'NCT' => 39600,
-		'NDT' => -9000,
-		'NFT' => 41400,
-		'NMIT' => 36000,
-		'NOVST' => 25200,
-		'NOVT' => 21600,
-		'NPT' => 20700,
-		'NRT' => 43200,
-		'NST' => -12600,
-		'NUT' => -39600,
-		'NZDT' => 46800,
-		'NZST' => 43200,
-		'OMSST' => 25200,
-		'OMST' => 21600,
-		'PDT' => -25200,
-		'PET' => -18000,
-		'PETST' => 46800,
-		'PETT' => 43200,
-		'PGT' => 36000,
-		'PHOT' => 46800,
-		'PHT' => 28800,
-		'PKT' => 18000,
-		'PMDT' => -7200,
-		'PMST' => -10800,
-		'PONT' => 39600,
-		'PST' => -28800,
-		'PWT' => 32400,
-		'PYST' => -10800,
-		'PYT' => -14400,
-		'RET' => 14400,
-		'ROTT' => -10800,
-		'SAMST' => 18000,
-		'SAMT' => 14400,
-		'SAST' => 7200,
-		'SBT' => 39600,
-		'SCDT' => 46800,
-		'SCST' => 43200,
-		'SCT' => 14400,
-		'SEST' => 3600,
-		'SGT' => 28800,
-		'SIT' => 28800,
-		'SRT' => -10800,
-		'SST' => -39600,
-		'SYST' => 10800,
-		'SYT' => 7200,
-		'TFT' => 18000,
-		'THAT' => -36000,
-		'TJT' => 18000,
-		'TKT' => -36000,
-		'TMT' => 18000,
-		'TOT' => 46800,
-		'TPT' => 32400,
-		'TRUT' => 36000,
-		'TVT' => 43200,
-		'TWT' => 28800,
-		'UYST' => -7200,
-		'UYT' => -10800,
-		'UZT' => 18000,
-		'VET' => -14400,
-		'VLAST' => 39600,
-		'VLAT' => 36000,
-		'VOST' => 21600,
-		'VUT' => 39600,
-		'WAST' => 7200,
-		'WAT' => 3600,
-		'WDT' => 32400,
-		'WEST' => 3600,
-		'WFT' => 43200,
-		'WIB' => 25200,
-		'WIT' => 32400,
-		'WITA' => 28800,
-		'WKST' => 18000,
-		'WST' => 28800,
-		'YAKST' => 36000,
-		'YAKT' => 32400,
-		'YAPT' => 36000,
-		'YEKST' => 21600,
-		'YEKT' => 18000,
-	);
-
-	/**
-	 * Cached PCRE for SimplePie_Parse_Date::$day
-	 *
-	 * @access protected
-	 * @var string
-	 */
-	var $day_pcre;
-
-	/**
-	 * Cached PCRE for SimplePie_Parse_Date::$month
-	 *
-	 * @access protected
-	 * @var string
-	 */
-	var $month_pcre;
-
-	/**
-	 * Array of user-added callback methods
-	 *
-	 * @access private
-	 * @var array
-	 */
-	var $built_in = array();
-
-	/**
-	 * Array of user-added callback methods
-	 *
-	 * @access private
-	 * @var array
-	 */
-	var $user = array();
-
-	/**
-	 * Create new SimplePie_Parse_Date object, and set self::day_pcre,
-	 * self::month_pcre, and self::built_in
-	 *
-	 * @access private
-	 */
-	function SimplePie_Parse_Date()
-	{
-		$this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
-		$this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
-
-		static $cache;
-		if (!isset($cache[get_class($this)]))
-		{
-			$all_methods = get_class_methods($this);
-
-			foreach ($all_methods as $method)
-			{
-				if (strtolower(substr($method, 0, 5)) === 'date_')
-				{
-					$cache[get_class($this)][] = $method;
-				}
-			}
-		}
-
-		foreach ($cache[get_class($this)] as $method)
-		{
-			$this->built_in[] = $method;
-		}
-	}
-
-	/**
-	 * Get the object
-	 *
-	 * @access public
-	 */
-	function get()
-	{
-		static $object;
-		if (!$object)
-		{
-			$object = new SimplePie_Parse_Date;
-		}
-		return $object;
-	}
-
-	/**
-	 * Parse a date
-	 *
-	 * @final
-	 * @access public
-	 * @param string $date Date to parse
-	 * @return int Timestamp corresponding to date string, or false on failure
-	 */
-	function parse($date)
-	{
-		foreach ($this->user as $method)
-		{
-			if (($returned = call_user_func($method, $date)) !== false)
-			{
-				return $returned;
-			}
-		}
-
-		foreach ($this->built_in as $method)
-		{
-			if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
-			{
-				return $returned;
-			}
-		}
-
-		return false;
-	}
-
-	/**
-	 * Add a callback method to parse a date
-	 *
-	 * @final
-	 * @access public
-	 * @param callback $callback
-	 */
-	function add_callback($callback)
-	{
-		if (is_callable($callback))
-		{
-			$this->user[] = $callback;
-		}
-		else
-		{
-			trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
-		}
-	}
-
-	/**
-	 * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
-	 * well as allowing any of upper or lower case "T", horizontal tabs, or
-	 * spaces to be used as the time seperator (including more than one))
-	 *
-	 * @access protected
-	 * @return int Timestamp
-	 */
-	function date_w3cdtf($date)
-	{
-		static $pcre;
-		if (!$pcre)
-		{
-			$year = '([0-9]{4})';
-			$month = $day = $hour = $minute = $second = '([0-9]{2})';
-			$decimal = '([0-9]*)';
-			$zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
-			$pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
-		}
-		if (preg_match($pcre, $date, $match))
-		{
-			/*
-			Capturing subpatterns:
-			1: Year
-			2: Month
-			3: Day
-			4: Hour
-			5: Minute
-			6: Second
-			7: Decimal fraction of a second
-			8: Zulu
-			9: Timezone ±
-			10: Timezone hours
-			11: Timezone minutes
-			*/
-
-			// Fill in empty matches
-			for ($i = count($match); $i <= 3; $i++)
-			{
-				$match[$i] = '1';
-			}
-
-			for ($i = count($match); $i <= 7; $i++)
-			{
-				$match[$i] = '0';
-			}
-
-			// Numeric timezone
-			if (isset($match[9]) && $match[9] !== '')
-			{
-				$timezone = $match[10] * 3600;
-				$timezone += $match[11] * 60;
-				if ($match[9] === '-')
-				{
-					$timezone = 0 - $timezone;
-				}
-			}
-			else
-			{
-				$timezone = 0;
-			}
-
-			// Convert the number of seconds to an integer, taking decimals into account
-			$second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
-
-			return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	/**
-	 * Remove RFC822 comments
-	 *
-	 * @access protected
-	 * @param string $data Data to strip comments from
-	 * @return string Comment stripped string
-	 */
-	function remove_rfc2822_comments($string)
-	{
-		$string = (string) $string;
-		$position = 0;
-		$length = strlen($string);
-		$depth = 0;
-
-		$output = '';
-
-		while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
-		{
-			$output .= substr($string, $position, $pos - $position);
-			$position = $pos + 1;
-			if ($string[$pos - 1] !== '\\')
-			{
-				$depth++;
-				while ($depth && $position < $length)
-				{
-					$position += strcspn($string, '()', $position);
-					if ($string[$position - 1] === '\\')
-					{
-						$position++;
-						continue;
-					}
-					elseif (isset($string[$position]))
-					{
-						switch ($string[$position])
-						{
-							case '(':
-								$depth++;
-								break;
-
-							case ')':
-								$depth--;
-								break;
-						}
-						$position++;
-					}
-					else
-					{
-						break;
-					}
-				}
-			}
-			else
-			{
-				$output .= '(';
-			}
-		}
-		$output .= substr($string, $position);
-
-		return $output;
-	}
-
-	/**
-	 * Parse RFC2822's date format
-	 *
-	 * @access protected
-	 * @return int Timestamp
-	 */
-	function date_rfc2822($date)
-	{
-		static $pcre;
-		if (!$pcre)
-		{
-			$wsp = '[\x09\x20]';
-			$fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
-			$optional_fws = $fws . '?';
-			$day_name = $this->day_pcre;
-			$month = $this->month_pcre;
-			$day = '([0-9]{1,2})';
-			$hour = $minute = $second = '([0-9]{2})';
-			$year = '([0-9]{2,4})';
-			$num_zone = '([+\-])([0-9]{2})([0-9]{2})';
-			$character_zone = '([A-Z]{1,5})';
-			$zone = '(?:' . $num_zone . '|' . $character_zone . ')';
-			$pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
-		}
-		if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
-		{
-			/*
-			Capturing subpatterns:
-			1: Day name
-			2: Day
-			3: Month
-			4: Year
-			5: Hour
-			6: Minute
-			7: Second
-			8: Timezone ±
-			9: Timezone hours
-			10: Timezone minutes
-			11: Alphabetic timezone
-			*/
-
-			// Find the month number
-			$month = $this->month[strtolower($match[3])];
-
-			// Numeric timezone
-			if ($match[8] !== '')
-			{
-				$timezone = $match[9] * 3600;
-				$timezone += $match[10] * 60;
-				if ($match[8] === '-')
-				{
-					$timezone = 0 - $timezone;
-				}
-			}
-			// Character timezone
-			elseif (isset($this->timezone[strtoupper($match[11])]))
-			{
-				$timezone = $this->timezone[strtoupper($match[11])];
-			}
-			// Assume everything else to be -0000
-			else
-			{
-				$timezone = 0;
-			}
-
-			// Deal with 2/3 digit years
-			if ($match[4] < 50)
-			{
-				$match[4] += 2000;
-			}
-			elseif ($match[4] < 1000)
-			{
-				$match[4] += 1900;
-			}
-
-			// Second is optional, if it is empty set it to zero
-			if ($match[7] !== '')
-			{
-				$second = $match[7];
-			}
-			else
-			{
-				$second = 0;
-			}
-
-			return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	/**
-	 * Parse RFC850's date format
-	 *
-	 * @access protected
-	 * @return int Timestamp
-	 */
-	function date_rfc850($date)
-	{
-		static $pcre;
-		if (!$pcre)
-		{
-			$space = '[\x09\x20]+';
-			$day_name = $this->day_pcre;
-			$month = $this->month_pcre;
-			$day = '([0-9]{1,2})';
-			$year = $hour = $minute = $second = '([0-9]{2})';
-			$zone = '([A-Z]{1,5})';
-			$pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
-		}
-		if (preg_match($pcre, $date, $match))
-		{
-			/*
-			Capturing subpatterns:
-			1: Day name
-			2: Day
-			3: Month
-			4: Year
-			5: Hour
-			6: Minute
-			7: Second
-			8: Timezone
-			*/
-
-			// Month
-			$month = $this->month[strtolower($match[3])];
-
-			// Character timezone
-			if (isset($this->timezone[strtoupper($match[8])]))
-			{
-				$timezone = $this->timezone[strtoupper($match[8])];
-			}
-			// Assume everything else to be -0000
-			else
-			{
-				$timezone = 0;
-			}
-
-			// Deal with 2 digit year
-			if ($match[4] < 50)
-			{
-				$match[4] += 2000;
-			}
-			else
-			{
-				$match[4] += 1900;
-			}
-
-			return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	/**
-	 * Parse C99's asctime()'s date format
-	 *
-	 * @access protected
-	 * @return int Timestamp
-	 */
-	function date_asctime($date)
-	{
-		static $pcre;
-		if (!$pcre)
-		{
-			$space = '[\x09\x20]+';
-			$wday_name = $this->day_pcre;
-			$mon_name = $this->month_pcre;
-			$day = '([0-9]{1,2})';
-			$hour = $sec = $min = '([0-9]{2})';
-			$year = '([0-9]{4})';
-			$terminator = '\x0A?\x00?';
-			$pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
-		}
-		if (preg_match($pcre, $date, $match))
-		{
-			/*
-			Capturing subpatterns:
-			1: Day name
-			2: Month
-			3: Day
-			4: Hour
-			5: Minute
-			6: Second
-			7: Year
-			*/
-
-			$month = $this->month[strtolower($match[2])];
-			return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	/**
-	 * Parse dates using strtotime()
-	 *
-	 * @access protected
-	 * @return int Timestamp
-	 */
-	function date_strtotime($date)
-	{
-		$strtotime = strtotime($date);
-		if ($strtotime === -1 || $strtotime === false)
-		{
-			return false;
-		}
-		else
-		{
-			return $strtotime;
-		}
-	}
-}
-
-/**
- * Content-type sniffing
- *
- * @package SimplePie
- */
-class SimplePie_Content_Type_Sniffer
-{
-	/**
-	 * File object
-	 *
-	 * @var SimplePie_File
-	 * @access private
-	 */
-	var $file;
-
-	/**
-	 * Create an instance of the class with the input file
-	 *
-	 * @access public
-	 * @param SimplePie_Content_Type_Sniffer $file Input file
-	 */
-	function SimplePie_Content_Type_Sniffer($file)
-	{
-		$this->file = $file;
-	}
-
-	/**
-	 * Get the Content-Type of the specified file
-	 *
-	 * @access public
-	 * @return string Actual Content-Type
-	 */
-	function get_type()
-	{
-		if (isset($this->file->headers['content-type']))
-		{
-			if (!isset($this->file->headers['content-encoding'])
-				&& ($this->file->headers['content-type'] === 'text/plain'
-					|| $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
-					|| $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
-			{
-				return $this->text_or_binary();
-			}
-
-			if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
-			{
-				$official = substr($this->file->headers['content-type'], 0, $pos);
-			}
-			else
-			{
-				$official = $this->file->headers['content-type'];
-			}
-			$official = strtolower($official);
-
-			if ($official === 'unknown/unknown'
-				|| $official === 'application/unknown')
-			{
-				return $this->unknown();
-			}
-			elseif (substr($official, -4) === '+xml'
-				|| $official === 'text/xml'
-				|| $official === 'application/xml')
-			{
-				return $official;
-			}
-			elseif (substr($official, 0, 6) === 'image/')
-			{
-				if ($return = $this->image())
-				{
-					return $return;
-				}
-				else
-				{
-					return $official;
-				}
-			}
-			elseif ($official === 'text/html')
-			{
-				return $this->feed_or_html();
-			}
-			else
-			{
-				return $official;
-			}
-		}
-		else
-		{
-			return $this->unknown();
-		}
-	}
-
-	/**
-	 * Sniff text or binary
-	 *
-	 * @access private
-	 * @return string Actual Content-Type
-	 */
-	function text_or_binary()
-	{
-		if (substr($this->file->body, 0, 2) === "\xFE\xFF"
-			|| substr($this->file->body, 0, 2) === "\xFF\xFE"
-			|| substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
-			|| substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
-		{
-			return 'text/plain';
-		}
-		elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
-		{
-			return 'application/octect-stream';
-		}
-		else
-		{
-			return 'text/plain';
-		}
-	}
-
-	/**
-	 * Sniff unknown
-	 *
-	 * @access private
-	 * @return string Actual Content-Type
-	 */
-	function unknown()
-	{
-		$ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
-		if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
-			|| strtolower(substr($this->file->body, $ws, 5)) === '<html'
-			|| strtolower(substr($this->file->body, $ws, 7)) === '<script')
-		{
-			return 'text/html';
-		}
-		elseif (substr($this->file->body, 0, 5) === '%PDF-')
-		{
-			return 'application/pdf';
-		}
-		elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
-		{
-			return 'application/postscript';
-		}
-		elseif (substr($this->file->body, 0, 6) === 'GIF87a'
-			|| substr($this->file->body, 0, 6) === 'GIF89a')
-		{
-			return 'image/gif';
-		}
-		elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
-		{
-			return 'image/png';
-		}
-		elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
-		{
-			return 'image/jpeg';
-		}
-		elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
-		{
-			return 'image/bmp';
-		}
-		else
-		{
-			return $this->text_or_binary();
-		}
-	}
-
-	/**
-	 * Sniff images
-	 *
-	 * @access private
-	 * @return string Actual Content-Type
-	 */
-	function image()
-	{
-		if (substr($this->file->body, 0, 6) === 'GIF87a'
-			|| substr($this->file->body, 0, 6) === 'GIF89a')
-		{
-			return 'image/gif';
-		}
-		elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
-		{
-			return 'image/png';
-		}
-		elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
-		{
-			return 'image/jpeg';
-		}
-		elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
-		{
-			return 'image/bmp';
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	/**
-	 * Sniff HTML
-	 *
-	 * @access private
-	 * @return string Actual Content-Type
-	 */
-	function feed_or_html()
-	{
-		$len = strlen($this->file->body);
-		$pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
-
-		while ($pos < $len)
-		{
-			switch ($this->file->body[$pos])
-			{
-				case "\x09":
-				case "\x0A":
-				case "\x0D":
-				case "\x20":
-					$pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
-					continue 2;
-
-				case '<':
-					$pos++;
-					break;
-
-				default:
-					return 'text/html';
-			}
-
-			if (substr($this->file->body, $pos, 3) === '!--')
-			{
-				$pos += 3;
-				if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
-				{
-					$pos += 3;
-				}
-				else
-				{
-					return 'text/html';
-				}
-			}
-			elseif (substr($this->file->body, $pos, 1) === '!')
-			{
-				if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
-				{
-					$pos++;
-				}
-				else
-				{
-					return 'text/html';
-				}
-			}
-			elseif (substr($this->file->body, $pos, 1) === '?')
-			{
-				if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
-				{
-					$pos += 2;
-				}
-				else
-				{
-					return 'text/html';
-				}
-			}
-			elseif (substr($this->file->body, $pos, 3) === 'rss'
-				|| substr($this->file->body, $pos, 7) === 'rdf:RDF')
-			{
-				return 'application/rss+xml';
-			}
-			elseif (substr($this->file->body, $pos, 4) === 'feed')
-			{
-				return 'application/atom+xml';
-			}
-			else
-			{
-				return 'text/html';
-			}
-		}
-
-		return 'text/html';
-	}
-}
-
-/**
- * Parses the XML Declaration
- *
- * @package SimplePie
- */
-class SimplePie_XML_Declaration_Parser
-{
-	/**
-	 * XML Version
-	 *
-	 * @access public
-	 * @var string
-	 */
-	var $version = '1.0';
-
-	/**
-	 * Encoding
-	 *
-	 * @access public
-	 * @var string
-	 */
-	var $encoding = 'UTF-8';
-
-	/**
-	 * Standalone
-	 *
-	 * @access public
-	 * @var bool
-	 */
-	var $standalone = false;
-
-	/**
-	 * Current state of the state machine
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $state = 'before_version_name';
-
-	/**
-	 * Input data
-	 *
-	 * @access private
-	 * @var string
-	 */
-	var $data = '';
-
-	/**
-	 * Input data length (to avoid calling strlen() everytime this is needed)
-	 *
-	 * @access private
-	 * @var int
-	 */
-	var $data_length = 0;
-
-	/**
-	 * Current position of the pointer
-	 *
-	 * @var int
-	 * @access private
-	 */
-	var $position = 0;
-
-	/**
-	 * Create an instance of the class with the input data
-	 *
-	 * @access public
-	 * @param string $data Input data
-	 */
-	function SimplePie_XML_Declaration_Parser($data)
-	{
-		$this->data = $data;
-		$this->data_length = strlen($this->data);
-	}
-
-	/**
-	 * Parse the input data
-	 *
-	 * @access public
-	 * @return bool true on success, false on failure
-	 */
-	function parse()
-	{
-		while ($this->state && $this->state !== 'emit' && $this->has_data())
-		{
-			$state = $this->state;
-			$this->$state();
-		}
-		$this->data = '';
-		if ($this->state === 'emit')
-		{
-			return true;
-		}
-		else
-		{
-			$this->version = '';
-			$this->encoding = '';
-			$this->standalone = '';
-			return false;
-		}
-	}
-
-	/**
-	 * Check whether there is data beyond the pointer
-	 *
-	 * @access private
-	 * @return bool true if there is further data, false if not
-	 */
-	function has_data()
-	{
-		return (bool) ($this->position < $this->data_length);
-	}
-
-	/**
-	 * Advance past any whitespace
-	 *
-	 * @return int Number of whitespace characters passed
-	 */
-	function skip_whitespace()
-	{
-		$whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
-		$this->position += $whitespace;
-		return $whitespace;
-	}
-
-	/**
-	 * Read value
-	 */
-	function get_value()
-	{
-		$quote = substr($this->data, $this->position, 1);
-		if ($quote === '"' || $quote === "'")
-		{
-			$this->position++;
-			$len = strcspn($this->data, $quote, $this->position);
-			if ($this->has_data())
-			{
-				$value = substr($this->data, $this->position, $len);
-				$this->position += $len + 1;
-				return $value;
-			}
-		}
-		return false;
-	}
-
-	function before_version_name()
-	{
-		if ($this->skip_whitespace())
-		{
-			$this->state = 'version_name';
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-
-	function version_name()
-	{
-		if (substr($this->data, $this->position, 7) === 'version')
-		{
-			$this->position += 7;
-			$this->skip_whitespace();
-			$this->state = 'version_equals';
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-
-	function version_equals()
-	{
-		if (substr($this->data, $this->position, 1) === '=')
-		{
-			$this->position++;
-			$this->skip_whitespace();
-			$this->state = 'version_value';
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-
-	function version_value()
-	{
-		if ($this->version = $this->get_value())
-		{
-			$this->skip_whitespace();
-			if ($this->has_data())
-			{
-				$this->state = 'encoding_name';
-			}
-			else
-			{
-				$this->state = 'emit';
-			}
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-
-	function encoding_name()
-	{
-		if (substr($this->data, $this->position, 8) === 'encoding')
-		{
-			$this->position += 8;
-			$this->skip_whitespace();
-			$this->state = 'encoding_equals';
-		}
-		else
-		{
-			$this->state = 'standalone_name';
-		}
-	}
-
-	function encoding_equals()
-	{
-		if (substr($this->data, $this->position, 1) === '=')
-		{
-			$this->position++;
-			$this->skip_whitespace();
-			$this->state = 'encoding_value';
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-
-	function encoding_value()
-	{
-		if ($this->encoding = $this->get_value())
-		{
-			$this->skip_whitespace();
-			if ($this->has_data())
-			{
-				$this->state = 'standalone_name';
-			}
-			else
-			{
-				$this->state = 'emit';
-			}
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-
-	function standalone_name()
-	{
-		if (substr($this->data, $this->position, 10) === 'standalone')
-		{
-			$this->position += 10;
-			$this->skip_whitespace();
-			$this->state = 'standalone_equals';
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-
-	function standalone_equals()
-	{
-		if (substr($this->data, $this->position, 1) === '=')
-		{
-			$this->position++;
-			$this->skip_whitespace();
-			$this->state = 'standalone_value';
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-
-	function standalone_value()
-	{
-		if ($standalone = $this->get_value())
-		{
-			switch ($standalone)
-			{
-				case 'yes':
-					$this->standalone = true;
-					break;
-
-				case 'no':
-					$this->standalone = false;
-					break;
-
-				default:
-					$this->state = false;
-					return;
-			}
-
-			$this->skip_whitespace();
-			if ($this->has_data())
-			{
-				$this->state = false;
-			}
-			else
-			{
-				$this->state = 'emit';
-			}
-		}
-		else
-		{
-			$this->state = false;
-		}
-	}
-}
-
-class SimplePie_Locator
-{
-	var $useragent;
-	var $timeout;
-	var $file;
-	var $local = array();
-	var $elsewhere = array();
-	var $file_class = 'SimplePie_File';
-	var $cached_entities = array();
-	var $http_base;
-	var $base;
-	var $base_location = 0;
-	var $checked_feeds = 0;
-	var $max_checked_feeds = 10;
-	var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
-
-	function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
-	{
-		$this->file =& $file;
-		$this->file_class = $file_class;
-		$this->useragent = $useragent;
-		$this->timeout = $timeout;
-		$this->max_checked_feeds = $max_checked_feeds;
-		$this->content_type_sniffer_class = $content_type_sniffer_class;
-	}
-
-	function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
-	{
-		if ($this->is_feed($this->file))
-		{
-			return $this->file;
-		}
-
-		if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
-		{
-			$sniffer = new $this->content_type_sniffer_class($this->file);
-			if ($sniffer->get_type() !== 'text/html')
-			{
-				return null;
-			}
-		}
-
-		if ($type & ~SIMPLEPIE_LOCATOR_NONE)
-		{
-			$this->get_base();
-		}
-
-		if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
-		{
-			return $working[0];
-		}
-
-		if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
-		{
-			if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
-			{
-				return $working;
-			}
-
-			if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
-			{
-				return $working;
-			}
-
-			if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
-			{
-				return $working;
-			}
-
-			if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
-			{
-				return $working;
-			}
-		}
-		return null;
-	}
-
-	function is_feed(&$file)
-	{
-		if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
-		{
-			$sniffer = new $this->content_type_sniffer_class($file);
-			$sniffed = $sniffer->get_type();
-			if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
-			{
-				return true;
-			}
-			else
-			{
-				return false;
-			}
-		}
-		elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
-		{
-			return true;
-		}
-		else
-		{
-			return false;
-		}
-	}
-
-	function get_base()
-	{
-		$this->http_base = $this->file->url;
-		$this->base = $this->http_base;
-		$elements = SimplePie_Misc::get_element('base', $this->file->body);
-		foreach ($elements as $element)
-		{
-			if ($element['attribs']['href']['data'] !== '')
-			{
-				$this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
-				$this->base_location = $element['offset'];
-				break;
-			}
-		}
-	}
-
-	function autodiscovery()
-	{
-		$links = array_merge(SimplePie_Misc::get_element('link', $this->file->body), SimplePie_Misc::get_element('a', $this->file->body), SimplePie_Misc::get_element('area', $this->file->body));
-		$done = array();
-		$feeds = array();
-		foreach ($links as $link)
-		{
-			if ($this->checked_feeds === $this->max_checked_feeds)
-			{
-				break;
-			}
-			if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
-			{
-				$rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
-
-				if ($this->base_location < $link['offset'])
-				{
-					$href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
-				}
-				else
-				{
-					$href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
-				}
-
-				if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !empty($link['attribs']['type']['data']) && in_array(strtolower(SimplePie_Misc::parse_mime($link['attribs']['type']['data'])), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
-				{
-					$this->checked_feeds++;
-					$feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
-					if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
-					{
-						$feeds[$href] = $feed;
-					}
-				}
-				$done[] = $href;
-			}
-		}
-
-		if (!empty($feeds))
-		{
-			return array_values($feeds);
-		}
-		else {
-			return null;
-		}
-	}
-
-	function get_links()
-	{
-		$links = SimplePie_Misc::get_element('a', $this->file->body);
-		foreach ($links as $link)
-		{
-			if (isset($link['attribs']['href']['data']))
-			{
-				$href = trim($link['attribs']['href']['data']);
-				$parsed = SimplePie_Misc::parse_url($href);
-				if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
-				{
-					if ($this->base_location < $link['offset'])
-					{
-						$href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
-					}
-					else
-					{
-						$href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
-					}
-
-					$current = SimplePie_Misc::parse_url($this->file->url);
-
-					if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
-					{
-						$this->local[] = $href;
-					}
-					else
-					{
-						$this->elsewhere[] = $href;
-					}
-				}
-			}
-		}
-		$this->local = array_unique($this->local);
-		$this->elsewhere = array_unique($this->elsewhere);
-		if (!empty($this->local) || !empty($this->elsewhere))
-		{
-			return true;
-		}
-		return null;
-	}
-
-	function extension(&$array)
-	{
-		foreach ($array as $key => $value)
-		{
-			if ($this->checked_feeds === $this->max_checked_feeds)
-			{
-				break;
-			}
-			if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
-			{
-				$this->checked_feeds++;
-				$feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
-				if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
-				{
-					return $feed;
-				}
-				else
-				{
-					unset($array[$key]);
-				}
-			}
-		}
-		return null;
-	}
-
-	function body(&$array)
-	{
-		foreach ($array as $key => $value)
-		{
-			if ($this->checked_feeds === $this->max_checked_feeds)
-			{
-				break;
-			}
-			if (preg_match('/(rss|rdf|atom|xml)/i', $value))
-			{
-				$this->checked_feeds++;
-				$feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
-				if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
-				{
-					return $feed;
-				}
-				else
-				{
-					unset($array[$key]);
-				}
-			}
-		}
-		return null;
-	}
-}
-
-class SimplePie_Parser
-{
-	var $error_code;
-	var $error_string;
-	var $current_line;
-	var $current_column;
-	var $current_byte;
-	var $separator = ' ';
-	var $namespace = array('');
-	var $element = array('');
-	var $xml_base = array('');
-	var $xml_base_explicit = array(false);
-	var $xml_lang = array('');
-	var $data = array();
-	var $datas = array(array());
-	var $current_xhtml_construct = -1;
-	var $encoding;
-
-	function parse(&$data, $encoding)
-	{
-		// Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
-		if (strtoupper($encoding) === 'US-ASCII')
-		{
-			$this->encoding = 'UTF-8';
-		}
-		else
-		{
-			$this->encoding = $encoding;
-		}
-
-		// Strip BOM:
-		// UTF-32 Big Endian BOM
-		if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
-		{
-			$data = substr($data, 4);
-		}
-		// UTF-32 Little Endian BOM
-		elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
-		{
-			$data = substr($data, 4);
-		}
-		// UTF-16 Big Endian BOM
-		elseif (substr($data, 0, 2) === "\xFE\xFF")
-		{
-			$data = substr($data, 2);
-		}
-		// UTF-16 Little Endian BOM
-		elseif (substr($data, 0, 2) === "\xFF\xFE")
-		{
-			$data = substr($data, 2);
-		}
-		// UTF-8 BOM
-		elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
-		{
-			$data = substr($data, 3);
-		}
-
-		if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
-		{
-			$declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
-			if ($declaration->parse())
-			{
-				$data = substr($data, $pos + 2);
-				$data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
-			}
-			else
-			{
-				$this->error_string = 'SimplePie bug! Please report this!';
-				return false;
-			}
-		}
-
-		$return = true;
-
-		static $xml_is_sane = null;
-		if ($xml_is_sane === null)
-		{
-			$parser_check = xml_parser_create();
-			xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
-			xml_parser_free($parser_check);
-			$xml_is_sane = isset($values[0]['value']);
-		}
-
-		// Create the parser
-		if ($xml_is_sane)
-		{
-			$xml = xml_parser_create_ns($this->encoding, $this->separator);
-			xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
-			xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
-			xml_set_object($xml, $this);
-			xml_set_character_data_handler($xml, 'cdata');
-			xml_set_element_handler($xml, 'tag_open', 'tag_close');
-
-			// Parse!
-			if (!xml_parse($xml, $data, true))
-			{
-				$this->error_code = xml_get_error_code($xml);
-				$this->error_string = xml_error_string($this->error_code);
-				$return = false;
-			}
-			$this->current_line = xml_get_current_line_number($xml);
-			$this->current_column = xml_get_current_column_number($xml);
-			$this->current_byte = xml_get_current_byte_index($xml);
-			xml_parser_free($xml);
-			return $return;
-		}
-		else
-		{
-			libxml_clear_errors();
-			$xml = new XMLReader();
-			$xml->xml($data);
-			while (@$xml->read())
-			{
-				switch ($xml->nodeType)
-				{
-
-					case constant('XMLReader::END_ELEMENT'):
-						if ($xml->namespaceURI !== '')
-						{
-							$tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
-						}
-						else
-						{
-							$tagName = $xml->localName;
-						}
-						$this->tag_close(null, $tagName);
-						break;
-					case constant('XMLReader::ELEMENT'):
-						$empty = $xml->isEmptyElement;
-						if ($xml->namespaceURI !== '')
-						{
-							$tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
-						}
-						else
-						{
-							$tagName = $xml->localName;
-						}
-						$attributes = array();
-						while ($xml->moveToNextAttribute())
-						{
-							if ($xml->namespaceURI !== '')
-							{
-								$attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
-							}
-							else
-							{
-								$attrName = $xml->localName;
-							}
-							$attributes[$attrName] = $xml->value;
-						}
-						$this->tag_open(null, $tagName, $attributes);
-						if ($empty)
-						{
-							$this->tag_close(null, $tagName);
-						}
-						break;
-					case constant('XMLReader::TEXT'):
-
-					case constant('XMLReader::CDATA'):
-						$this->cdata(null, $xml->value);
-						break;
-				}
-			}
-			if ($error = libxml_get_last_error())
-			{
-				$this->error_code = $error->code;
-				$this->error_string = $error->message;
-				$this->current_line = $error->line;
-				$this->current_column = $error->column;
-				return false;
-			}
-			else
-			{
-				return true;
-			}
-		}
-	}
-
-	function get_error_code()
-	{
-		return $this->error_code;
-	}
-
-	function get_error_string()
-	{
-		return $this->error_string;
-	}
-
-	function get_current_line()
-	{
-		return $this->current_line;
-	}
-
-	function get_current_column()
-	{
-		return $this->current_column;
-	}
-
-	function get_current_byte()
-	{
-		return $this->current_byte;
-	}
-
-	function get_data()
-	{
-		return $this->data;
-	}
-
-	function tag_open($parser, $tag, $attributes)
-	{
-		list($this->namespace[], $this->element[]) = $this->split_ns($tag);
-
-		$attribs = array();
-		foreach ($attributes as $name => $value)
-		{
-			list($attrib_namespace, $attribute) = $this->split_ns($name);
-			$attribs[$attrib_namespace][$attribute] = $value;
-		}
-
-		if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
-		{
-			$this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
-			$this->xml_base_explicit[] = true;
-		}
-		else
-		{
-			$this->xml_base[] = end($this->xml_base);
-			$this->xml_base_explicit[] = end($this->xml_base_explicit);
-		}
-
-		if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
-		{
-			$this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
-		}
-		else
-		{
-			$this->xml_lang[] = end($this->xml_lang);
-		}
-
-		if ($this->current_xhtml_construct >= 0)
-		{
-			$this->current_xhtml_construct++;
-			if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
-			{
-				$this->data['data'] .= '<' . end($this->element);
-				if (isset($attribs['']))
-				{
-					foreach ($attribs[''] as $name => $value)
-					{
-						$this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
-					}
-				}
-				$this->data['data'] .= '>';
-			}
-		}
-		else
-		{
-			$this->datas[] =& $this->data;
-			$this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
-			$this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang));
-			if ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml')
-			|| (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml'))
-			{
-				$this->current_xhtml_construct = 0;
-			}
-		}
-	}
-
-	function cdata($parser, $cdata)
-	{
-		if ($this->current_xhtml_construct >= 0)
-		{
-			$this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
-		}
-		else
-		{
-			$this->data['data'] .= $cdata;
-		}
-	}
-
-	function tag_close($parser, $tag)
-	{
-		if ($this->current_xhtml_construct >= 0)
-		{
-			$this->current_xhtml_construct--;
-			if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))
-			{
-				$this->data['data'] .= '</' . end($this->element) . '>';
-			}
-		}
-		if ($this->current_xhtml_construct === -1)
-		{
-			$this->data =& $this->datas[count($this->datas) - 1];
-			array_pop($this->datas);
-		}
-
-		array_pop($this->element);
-		array_pop($this->namespace);
-		array_pop($this->xml_base);
-		array_pop($this->xml_base_explicit);
-		array_pop($this->xml_lang);
-	}
-
-	function split_ns($string)
-	{
-		static $cache = array();
-		if (!isset($cache[$string]))
-		{
-			if ($pos = strpos($string, $this->separator))
-			{
-				static $separator_length;
-				if (!$separator_length)
-				{
-					$separator_length = strlen($this->separator);
-				}
-				$namespace = substr($string, 0, $pos);
-				$local_name = substr($string, $pos + $separator_length);
-				if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
-				{
-					$namespace = SIMPLEPIE_NAMESPACE_ITUNES;
-				}
-
-				// Normalize the Media RSS namespaces
-				if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
-				{
-					$namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
-				}
-				$cache[$string] = array($namespace, $local_name);
-			}
-			else
-			{
-				$cache[$string] = array('', $string);
-			}
-		}
-		return $cache[$string];
-	}
-}
-
-/**
- * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags
- */
-class SimplePie_Sanitize
-{
-	// Private vars
-	var $base;
-
-	// Options
-	var $remove_div = true;
-	var $image_handler = '';
-	var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
-	var $encode_instead_of_strip = false;
-	var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
-	var $strip_comments = false;
-	var $output_encoding = 'UTF-8';
-	var $enable_cache = true;
-	var $cache_location = './cache';
-	var $cache_name_function = 'md5';
-	var $cache_class = 'SimplePie_Cache';
-	var $file_class = 'SimplePie_File';
-	var $timeout = 10;
-	var $useragent = '';
-	var $force_fsockopen = false;
-
-	var $replace_url_attributes = array(
-		'a' => 'href',
-		'area' => 'href',
-		'blockquote' => 'cite',
-		'del' => 'cite',
-		'form' => 'action',
-		'img' => array('longdesc', 'src'),
-		'input' => 'src',
-		'ins' => 'cite',
-		'q' => 'cite'
-	);
-
-	function remove_div($enable = true)
-	{
-		$this->remove_div = (bool) $enable;
-	}
-
-	function set_image_handler($page = false)
-	{
-		if ($page)
-		{
-			$this->image_handler = (string) $page;
-		}
-		else
-		{
-			$this->image_handler = false;
-		}
-	}
-
-	function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
-	{
-		if (isset($enable_cache))
-		{
-			$this->enable_cache = (bool) $enable_cache;
-		}
-
-		if ($cache_location)
-		{
-			$this->cache_location = (string) $cache_location;
-		}
-
-		if ($cache_name_function)
-		{
-			$this->cache_name_function = (string) $cache_name_function;
-		}
-
-		if ($cache_class)
-		{
-			$this->cache_class = (string) $cache_class;
-		}
-	}
-
-	function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
-	{
-		if ($file_class)
-		{
-			$this->file_class = (string) $file_class;
-		}
-
-		if ($timeout)
-		{
-			$this->timeout = (string) $timeout;
-		}
-
-		if ($useragent)
-		{
-			$this->useragent = (string) $useragent;
-		}
-
-		if ($force_fsockopen)
-		{
-			$this->force_fsockopen = (string) $force_fsockopen;
-		}
-	}
-
-	function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
-	{
-		if ($tags)
-		{
-			if (is_array($tags))
-			{
-				$this->strip_htmltags = $tags;
-			}
-			else
-			{
-				$this->strip_htmltags = explode(',', $tags);
-			}
-		}
-		else
-		{
-			$this->strip_htmltags = false;
-		}
-	}
-
-	function encode_instead_of_strip($encode = false)
-	{
-		$this->encode_instead_of_strip = (bool) $encode;
-	}
-
-	function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
-	{
-		if ($attribs)
-		{
-			if (is_array($attribs))
-			{
-				$this->strip_attributes = $attribs;
-			}
-			else
-			{
-				$this->strip_attributes = explode(',', $attribs);
-			}
-		}
-		else
-		{
-			$this->strip_attributes = false;
-		}
-	}
-
-	function strip_comments($strip = false)
-	{
-		$this->strip_comments = (bool) $strip;
-	}
-
-	function set_output_encoding($encoding = 'UTF-8')
-	{
-		$this->output_encoding = (string) $encoding;
-	}
-
-	/**
-	 * Set element/attribute key/value pairs of HTML attributes
-	 * containing URLs that need to be resolved relative to the feed
-	 *
-	 * @access public
-	 * @since 1.0
-	 * @param array $element_attribute Element/attribute key/value pairs
-	 */
-	function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
-	{
-		$this->replace_url_attributes = (array) $element_attribute;
-	}
-
-	function sanitize($data, $type, $base = '')
-	{
-		$data = trim($data);
-		if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
-		{
-			if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
-			{
-				if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))
-				{
-					$type |= SIMPLEPIE_CONSTRUCT_HTML;
-				}
-				else
-				{
-					$type |= SIMPLEPIE_CONSTRUCT_TEXT;
-				}
-			}
-
-			if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
-			{
-				$data = base64_decode($data);
-			}
-
-			if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
-			{
-				if ($this->remove_div)
-				{
-					$data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
-					$data = preg_replace('/<\/div>$/', '', $data);
-				}
-				else
-				{
-					$data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
-				}
-			}
-
-			if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
-			{
-				// Strip comments
-				if ($this->strip_comments)
-				{
-					$data = SimplePie_Misc::strip_comments($data);
-				}
-
-				// Strip out HTML tags and attributes that might cause various security problems.
-				// Based on recommendations by Mark Pilgrim at:
-				// http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
-				if ($this->strip_htmltags)
-				{
-					foreach ($this->strip_htmltags as $tag)
-					{
-						$pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
-						while (preg_match($pcre, $data))
-						{
-							$data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
-						}
-					}
-				}
-
-				if ($this->strip_attributes)
-				{
-					foreach ($this->strip_attributes as $attrib)
-					{
-						$data = preg_replace('/(<[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*)' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . trim($attrib) . '(?:\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>/', '\1\2\3>', $data);
-					}
-				}
-
-				// Replace relative URLs
-				$this->base = $base;
-				foreach ($this->replace_url_attributes as $element => $attributes)
-				{
-					$data = $this->replace_urls($data, $element, $attributes);
-				}
-
-				// If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
-				if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
-				{
-					$images = SimplePie_Misc::get_element('img', $data);
-					foreach ($images as $img)
-					{
-						if (isset($img['attribs']['src']['data']))
-						{
-							$image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
-							$cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
-
-							if ($cache->load())
-							{
-								$img['attribs']['src']['data'] = $this->image_handler . $image_url;
-								$data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
-							}
-							else
-							{
-								$file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
-								$headers = $file->headers;
-
-								if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
-								{
-									if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
-									{
-										$img['attribs']['src']['data'] = $this->image_handler . $image_url;
-										$data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
-									}
-									else
-									{
-										trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
-									}
-								}
-							}
-						}
-					}
-				}
-
-				// Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
-				$data = trim($data);
-			}
-
-			if ($type & SIMPLEPIE_CONSTRUCT_IRI)
-			{
-				$data = SimplePie_Misc::absolutize_url($data, $base);
-			}
-
-			if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
-			{
-				$data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
-			}
-
-			if ($this->output_encoding !== 'UTF-8')
-			{
-				$data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
-			}
-		}
-		return $data;
-	}
-
-	function replace_urls($data, $tag, $attributes)
-	{
-		if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
-		{
-			$elements = SimplePie_Misc::get_element($tag, $data);
-			foreach ($elements as $element)
-			{
-				if (is_array($attributes))
-				{
-					foreach ($attributes as $attribute)
-					{
-						if (isset($element['attribs'][$attribute]['data']))
-						{
-							$element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
-							$new_element = SimplePie_Misc::element_implode($element);
-							$data = str_replace($element['full'], $new_element, $data);
-							$element['full'] = $new_element;
-						}
-					}
-				}
-				elseif (isset($element['attribs'][$attributes]['data']))
-				{
-					$element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
-					$data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
-				}
-			}
-		}
-		return $data;
-	}
-
-	function do_strip_htmltags($match)
-	{
-		if ($this->encode_instead_of_strip)
-		{
-			if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
-			{
-				$match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
-				$match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
-				return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
-			}
-			else
-			{
-				return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
-			}
-		}
-		elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
-		{
-			return $match[4];
-		}
-		else
-		{
-			return '';
-		}
-	}
-}
-
-?>
diff --git a/util/README b/util/README
index 20a539215e..fad1270d47 100644
--- a/util/README
+++ b/util/README
@@ -10,7 +10,7 @@ Internationalisation
 
 extract.php - extracts translatable strings from our project files. It 
 currently doesn't pick up strings in other libraries we might be using such as 
-tinymce, simplepie, and the HTML parsers.
+tinymce and the HTML parsers.
 
 In order for extract to do its job, every use of the t() translation function 
 must be preceded by one space. The string also can not contain parentheses. If

From a18fde458c9b8d8d1b575de4420f301610e5ca9c Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 16 Feb 2016 08:06:55 +0100
Subject: [PATCH 108/273] Added documentation.

---
 include/feed.php | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/include/feed.php b/include/feed.php
index 184b784c72..04cfba75a6 100644
--- a/include/feed.php
+++ b/include/feed.php
@@ -2,6 +2,17 @@
 require_once("include/html2bbcode.php");
 require_once("include/items.php");
 
+/**
+ * @brief Read a RSS/RDF/Atom feed and create an item entry for it
+ *
+ * @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
+ */
 function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
 
 	$a = get_app();
@@ -102,7 +113,7 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
 		$entries = $xpath->query('/rss/channel/item');
 	}
 
-	if (is_array($contact)) {
+	if (!$simulate) {
 		$author["author-link"] = $contact["url"];
 
 		if ($author["author-name"] == "")
@@ -113,6 +124,9 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
 		$author["owner-link"] = $contact["url"];
 		$author["owner-name"] = $contact["name"];
 		$author["owner-avatar"] = $contact["thumb"];
+
+		// This is no field in the item table. So we have to unset it.
+		unset($author["author-nick"]);
 	}
 
 	$header = array();

From a9f80d435b475f4f23414b06ecc2b6af591dd1b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Saka=C5=82o=C5=AD=20Alaksiej?= <nullbsd@gmail.com>
Date: Tue, 16 Feb 2016 20:57:15 +0300
Subject: [PATCH 109/273] Complemented and improved russian translation

---
 view/ru/messages.po | 6800 +++++++++++++++++++++++++------------------
 view/ru/strings.php |  637 ++--
 2 files changed, 4326 insertions(+), 3111 deletions(-)

diff --git a/view/ru/messages.po b/view/ru/messages.po
index 4b0e372dd6..7f65e8f1be 100644
--- a/view/ru/messages.po
+++ b/view/ru/messages.po
@@ -1,8 +1,9 @@
 # FRIENDICA Distributed Social Network
 # Copyright (C) 2010, 2011, 2012, 2013 the Friendica Project
 # This file is distributed under the same license as the Friendica package.
-# 
+#
 # Translators:
+# Aliaksei Sakalou <nullbsd@gmail.com>, 2016
 # Alex <info@pixelbits.de>, 2013
 # vislav <bizadmin@list.ru>, 2014
 # Alex <info@pixelbits.de>, 2013
@@ -15,1151 +16,1317 @@ msgid ""
 msgstr ""
 "Project-Id-Version: friendica\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2015-02-09 08:57+0100\n"
-"PO-Revision-Date: 2015-02-09 09:46+0000\n"
-"Last-Translator: fabrixxm <fabrix.xm@gmail.com>\n"
-"Language-Team: Russian (http://www.transifex.com/projects/p/friendica/language/ru/)\n"
+"POT-Creation-Date: 2016-01-24 06:49+0100\n"
+"PO-Revision-Date: 2016-02-16 18:28+0300\n"
+"Last-Translator: Aliaksei Sakalou <nullbsd@gmail.com>\n"
+"Language-Team: Russian (http://www.transifex.com/Friendica/friendica/"
+"language/ru/)\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Language: ru\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n"
+"%100>=11 && n%100<=14)? 2 : 3);\n"
+"X-Generator: Poedit 1.5.4\n"
 
-#: ../../mod/contacts.php:108
+#: mod/contacts.php:50 include/identity.php:395
+msgid "Network:"
+msgstr "Сеть:"
+
+#: mod/contacts.php:51 mod/contacts.php:961 mod/videos.php:37
+#: mod/viewcontacts.php:105 mod/dirfind.php:214 mod/network.php:598
+#: mod/allfriends.php:77 mod/match.php:82 mod/directory.php:172
+#: mod/common.php:123 mod/suggest.php:95 mod/photos.php:41
+#: include/identity.php:298
+msgid "Forum"
+msgstr "Форум"
+
+#: mod/contacts.php:128
 #, php-format
 msgid "%d contact edited."
-msgid_plural "%d contacts edited"
-msgstr[0] "%d контакт изменён."
-msgstr[1] "%d контакты изменены"
-msgstr[2] "%d контакты изменены"
+msgid_plural "%d contacts edited."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
 
-#: ../../mod/contacts.php:139 ../../mod/contacts.php:272
+#: mod/contacts.php:159 mod/contacts.php:383
 msgid "Could not access contact record."
 msgstr "Не удалось получить доступ к записи контакта."
 
-#: ../../mod/contacts.php:153
+#: mod/contacts.php:173
 msgid "Could not locate selected profile."
 msgstr "Не удалось найти выбранный профиль."
 
-#: ../../mod/contacts.php:186
+#: mod/contacts.php:206
 msgid "Contact updated."
 msgstr "Контакт обновлен."
 
-#: ../../mod/contacts.php:188 ../../mod/dfrn_request.php:576
+#: mod/contacts.php:208 mod/dfrn_request.php:575
 msgid "Failed to update contact record."
 msgstr "Не удалось обновить запись контакта."
 
-#: ../../mod/contacts.php:254 ../../mod/manage.php:96
-#: ../../mod/display.php:499 ../../mod/profile_photo.php:19
-#: ../../mod/profile_photo.php:169 ../../mod/profile_photo.php:180
-#: ../../mod/profile_photo.php:193 ../../mod/follow.php:9
-#: ../../mod/item.php:168 ../../mod/item.php:184 ../../mod/group.php:19
-#: ../../mod/dfrn_confirm.php:55 ../../mod/fsuggest.php:78
-#: ../../mod/wall_upload.php:66 ../../mod/viewcontacts.php:24
-#: ../../mod/notifications.php:66 ../../mod/message.php:38
-#: ../../mod/message.php:174 ../../mod/crepair.php:119
-#: ../../mod/nogroup.php:25 ../../mod/network.php:4 ../../mod/allfriends.php:9
-#: ../../mod/events.php:140 ../../mod/install.php:151
-#: ../../mod/wallmessage.php:9 ../../mod/wallmessage.php:33
-#: ../../mod/wallmessage.php:79 ../../mod/wallmessage.php:103
-#: ../../mod/wall_attach.php:55 ../../mod/settings.php:102
-#: ../../mod/settings.php:596 ../../mod/settings.php:601
-#: ../../mod/register.php:42 ../../mod/delegate.php:12 ../../mod/mood.php:114
-#: ../../mod/suggest.php:58 ../../mod/profiles.php:165
-#: ../../mod/profiles.php:618 ../../mod/editpost.php:10 ../../mod/api.php:26
-#: ../../mod/api.php:31 ../../mod/notes.php:20 ../../mod/poke.php:135
-#: ../../mod/invite.php:15 ../../mod/invite.php:101 ../../mod/photos.php:134
-#: ../../mod/photos.php:1050 ../../mod/regmod.php:110 ../../mod/uimport.php:23
-#: ../../mod/attach.php:33 ../../include/items.php:4712 ../../index.php:369
+#: mod/contacts.php:365 mod/manage.php:96 mod/display.php:509
+#: mod/profile_photo.php:19 mod/profile_photo.php:175
+#: mod/profile_photo.php:186 mod/profile_photo.php:199
+#: mod/ostatus_subscribe.php:9 mod/follow.php:11 mod/follow.php:73
+#: mod/follow.php:155 mod/item.php:180 mod/item.php:192 mod/group.php:19
+#: mod/dfrn_confirm.php:55 mod/fsuggest.php:78 mod/wall_upload.php:77
+#: mod/wall_upload.php:80 mod/viewcontacts.php:40 mod/notifications.php:69
+#: mod/message.php:45 mod/message.php:181 mod/crepair.php:117
+#: mod/dirfind.php:11 mod/nogroup.php:25 mod/network.php:4
+#: mod/allfriends.php:12 mod/events.php:165 mod/wallmessage.php:9
+#: mod/wallmessage.php:33 mod/wallmessage.php:79 mod/wallmessage.php:103
+#: mod/wall_attach.php:67 mod/wall_attach.php:70 mod/settings.php:20
+#: mod/settings.php:126 mod/settings.php:646 mod/register.php:42
+#: mod/delegate.php:12 mod/common.php:18 mod/mood.php:114 mod/suggest.php:58
+#: mod/profiles.php:165 mod/profiles.php:615 mod/editpost.php:10
+#: mod/api.php:26 mod/api.php:31 mod/notes.php:22 mod/poke.php:149
+#: mod/repair_ostatus.php:9 mod/invite.php:15 mod/invite.php:101
+#: mod/photos.php:171 mod/photos.php:1105 mod/regmod.php:110
+#: mod/uimport.php:23 mod/attach.php:33 include/items.php:5096 index.php:383
 msgid "Permission denied."
 msgstr "Нет разрешения."
 
-#: ../../mod/contacts.php:287
+#: mod/contacts.php:404
 msgid "Contact has been blocked"
 msgstr "Контакт заблокирован"
 
-#: ../../mod/contacts.php:287
+#: mod/contacts.php:404
 msgid "Contact has been unblocked"
 msgstr "Контакт разблокирован"
 
-#: ../../mod/contacts.php:298
+#: mod/contacts.php:415
 msgid "Contact has been ignored"
 msgstr "Контакт проигнорирован"
 
-#: ../../mod/contacts.php:298
+#: mod/contacts.php:415
 msgid "Contact has been unignored"
 msgstr "У контакта отменено игнорирование"
 
-#: ../../mod/contacts.php:310
+#: mod/contacts.php:427
 msgid "Contact has been archived"
 msgstr "Контакт заархивирован"
 
-#: ../../mod/contacts.php:310
+#: mod/contacts.php:427
 msgid "Contact has been unarchived"
 msgstr "Контакт разархивирован"
 
-#: ../../mod/contacts.php:335 ../../mod/contacts.php:711
+#: mod/contacts.php:454 mod/contacts.php:802
 msgid "Do you really want to delete this contact?"
 msgstr "Вы действительно хотите удалить этот контакт?"
 
-#: ../../mod/contacts.php:337 ../../mod/message.php:209
-#: ../../mod/settings.php:1010 ../../mod/settings.php:1016
-#: ../../mod/settings.php:1024 ../../mod/settings.php:1028
-#: ../../mod/settings.php:1033 ../../mod/settings.php:1039
-#: ../../mod/settings.php:1045 ../../mod/settings.php:1051
-#: ../../mod/settings.php:1081 ../../mod/settings.php:1082
-#: ../../mod/settings.php:1083 ../../mod/settings.php:1084
-#: ../../mod/settings.php:1085 ../../mod/dfrn_request.php:830
-#: ../../mod/register.php:233 ../../mod/suggest.php:29
-#: ../../mod/profiles.php:661 ../../mod/profiles.php:664 ../../mod/api.php:105
-#: ../../include/items.php:4557
+#: mod/contacts.php:456 mod/follow.php:110 mod/message.php:216
+#: mod/settings.php:1103 mod/settings.php:1109 mod/settings.php:1117
+#: mod/settings.php:1121 mod/settings.php:1126 mod/settings.php:1132
+#: mod/settings.php:1138 mod/settings.php:1144 mod/settings.php:1170
+#: mod/settings.php:1171 mod/settings.php:1172 mod/settings.php:1173
+#: mod/settings.php:1174 mod/dfrn_request.php:857 mod/register.php:238
+#: mod/suggest.php:29 mod/profiles.php:658 mod/profiles.php:661
+#: mod/profiles.php:687 mod/api.php:105 include/items.php:4928
 msgid "Yes"
 msgstr "Да"
 
-#: ../../mod/contacts.php:340 ../../mod/tagrm.php:11 ../../mod/tagrm.php:94
-#: ../../mod/message.php:212 ../../mod/fbrowser.php:81
-#: ../../mod/fbrowser.php:116 ../../mod/settings.php:615
-#: ../../mod/settings.php:641 ../../mod/dfrn_request.php:844
-#: ../../mod/suggest.php:32 ../../mod/editpost.php:148
-#: ../../mod/photos.php:203 ../../mod/photos.php:292
-#: ../../include/conversation.php:1129 ../../include/items.php:4560
+#: mod/contacts.php:459 mod/tagrm.php:11 mod/tagrm.php:94 mod/follow.php:121
+#: mod/videos.php:131 mod/message.php:219 mod/fbrowser.php:93
+#: mod/fbrowser.php:128 mod/settings.php:660 mod/settings.php:686
+#: mod/dfrn_request.php:871 mod/suggest.php:32 mod/editpost.php:148
+#: mod/photos.php:247 mod/photos.php:336 include/conversation.php:1220
+#: include/items.php:4931
 msgid "Cancel"
 msgstr "Отмена"
 
-#: ../../mod/contacts.php:352
+#: mod/contacts.php:471
 msgid "Contact has been removed."
 msgstr "Контакт удален."
 
-#: ../../mod/contacts.php:390
+#: mod/contacts.php:512
 #, php-format
 msgid "You are mutual friends with %s"
 msgstr "У Вас взаимная дружба с %s"
 
-#: ../../mod/contacts.php:394
+#: mod/contacts.php:516
 #, php-format
 msgid "You are sharing with %s"
 msgstr "Вы делитесь с %s"
 
-#: ../../mod/contacts.php:399
+#: mod/contacts.php:521
 #, php-format
 msgid "%s is sharing with you"
 msgstr "%s делитса с Вами"
 
-#: ../../mod/contacts.php:416
+#: mod/contacts.php:541
 msgid "Private communications are not available for this contact."
 msgstr "Личные коммуникации недоступны для этого контакта."
 
-#: ../../mod/contacts.php:419 ../../mod/admin.php:569
+#: mod/contacts.php:544 mod/admin.php:822
 msgid "Never"
 msgstr "Никогда"
 
-#: ../../mod/contacts.php:423
+#: mod/contacts.php:548
 msgid "(Update was successful)"
 msgstr "(Обновление было успешно)"
 
-#: ../../mod/contacts.php:423
+#: mod/contacts.php:548
 msgid "(Update was not successful)"
 msgstr "(Обновление не удалось)"
 
-#: ../../mod/contacts.php:425
+#: mod/contacts.php:550
 msgid "Suggest friends"
 msgstr "Предложить друзей"
 
-#: ../../mod/contacts.php:429
+#: mod/contacts.php:554
 #, php-format
 msgid "Network type: %s"
 msgstr "Сеть: %s"
 
-#: ../../mod/contacts.php:432 ../../include/contact_widgets.php:200
-#, php-format
-msgid "%d contact in common"
-msgid_plural "%d contacts in common"
-msgstr[0] "%d Контакт"
-msgstr[1] "%d Контактов"
-msgstr[2] "%d Контактов"
-
-#: ../../mod/contacts.php:437
-msgid "View all contacts"
-msgstr "Показать все контакты"
-
-#: ../../mod/contacts.php:442 ../../mod/contacts.php:501
-#: ../../mod/contacts.php:714 ../../mod/admin.php:1009
-msgid "Unblock"
-msgstr "Разблокировать"
-
-#: ../../mod/contacts.php:442 ../../mod/contacts.php:501
-#: ../../mod/contacts.php:714 ../../mod/admin.php:1008
-msgid "Block"
-msgstr "Заблокировать"
-
-#: ../../mod/contacts.php:445
-msgid "Toggle Blocked status"
-msgstr "Изменить статус блокированности (заблокировать/разблокировать)"
-
-#: ../../mod/contacts.php:448 ../../mod/contacts.php:502
-#: ../../mod/contacts.php:715
-msgid "Unignore"
-msgstr "Не игнорировать"
-
-#: ../../mod/contacts.php:448 ../../mod/contacts.php:502
-#: ../../mod/contacts.php:715 ../../mod/notifications.php:51
-#: ../../mod/notifications.php:164 ../../mod/notifications.php:210
-msgid "Ignore"
-msgstr "Игнорировать"
-
-#: ../../mod/contacts.php:451
-msgid "Toggle Ignored status"
-msgstr "Изменить статус игнорирования"
-
-#: ../../mod/contacts.php:455 ../../mod/contacts.php:716
-msgid "Unarchive"
-msgstr "Разархивировать"
-
-#: ../../mod/contacts.php:455 ../../mod/contacts.php:716
-msgid "Archive"
-msgstr "Архивировать"
-
-#: ../../mod/contacts.php:458
-msgid "Toggle Archive status"
-msgstr "Сменить статус архивации (архивирова/не архивировать)"
-
-#: ../../mod/contacts.php:461
-msgid "Repair"
-msgstr "Восстановить"
-
-#: ../../mod/contacts.php:464
-msgid "Advanced Contact Settings"
-msgstr "Дополнительные Настройки Контакта"
-
-#: ../../mod/contacts.php:470
+#: mod/contacts.php:567
 msgid "Communications lost with this contact!"
 msgstr "Связь с контактом утеряна!"
 
-#: ../../mod/contacts.php:473
-msgid "Contact Editor"
-msgstr "Редактор контакта"
+#: mod/contacts.php:570
+msgid "Fetch further information for feeds"
+msgstr ""
 
-#: ../../mod/contacts.php:475 ../../mod/manage.php:110
-#: ../../mod/fsuggest.php:107 ../../mod/message.php:335
-#: ../../mod/message.php:564 ../../mod/crepair.php:186
-#: ../../mod/events.php:478 ../../mod/content.php:710
-#: ../../mod/install.php:248 ../../mod/install.php:286 ../../mod/mood.php:137
-#: ../../mod/profiles.php:686 ../../mod/localtime.php:45
-#: ../../mod/poke.php:199 ../../mod/invite.php:140 ../../mod/photos.php:1084
-#: ../../mod/photos.php:1203 ../../mod/photos.php:1514
-#: ../../mod/photos.php:1565 ../../mod/photos.php:1609
-#: ../../mod/photos.php:1697 ../../object/Item.php:678
-#: ../../view/theme/cleanzero/config.php:80
-#: ../../view/theme/dispy/config.php:70 ../../view/theme/quattro/config.php:64
-#: ../../view/theme/diabook/config.php:148
-#: ../../view/theme/diabook/theme.php:633 ../../view/theme/vier/config.php:53
-#: ../../view/theme/duepuntozero/config.php:59
+#: mod/contacts.php:571 mod/admin.php:831
+msgid "Disabled"
+msgstr "Отключенный"
+
+#: mod/contacts.php:571
+msgid "Fetch information"
+msgstr ""
+
+#: mod/contacts.php:571
+msgid "Fetch information and keywords"
+msgstr ""
+
+#: mod/contacts.php:587 mod/manage.php:143 mod/fsuggest.php:107
+#: mod/message.php:342 mod/message.php:525 mod/crepair.php:196
+#: mod/events.php:574 mod/content.php:712 mod/install.php:261
+#: mod/install.php:299 mod/mood.php:137 mod/profiles.php:696
+#: mod/localtime.php:45 mod/poke.php:198 mod/invite.php:140
+#: mod/photos.php:1137 mod/photos.php:1261 mod/photos.php:1579
+#: mod/photos.php:1630 mod/photos.php:1678 mod/photos.php:1766
+#: object/Item.php:710 view/theme/cleanzero/config.php:80
+#: view/theme/dispy/config.php:70 view/theme/quattro/config.php:64
+#: view/theme/diabook/config.php:148 view/theme/diabook/theme.php:633
+#: view/theme/vier/config.php:107 view/theme/duepuntozero/config.php:59
 msgid "Submit"
-msgstr "Подтвердить"
+msgstr "Добавить"
 
-#: ../../mod/contacts.php:476
+#: mod/contacts.php:588
 msgid "Profile Visibility"
 msgstr "Видимость профиля"
 
-#: ../../mod/contacts.php:477
+#: mod/contacts.php:589
 #, php-format
 msgid ""
 "Please choose the profile you would like to display to %s when viewing your "
 "profile securely."
-msgstr "Пожалуйста, выберите профиль, который вы хотите отображать %s, когда просмотр вашего профиля безопасен."
+msgstr ""
+"Пожалуйста, выберите профиль, который вы хотите отображать %s, когда "
+"просмотр вашего профиля безопасен."
 
-#: ../../mod/contacts.php:478
+#: mod/contacts.php:590
 msgid "Contact Information / Notes"
 msgstr "Информация о контакте / Заметки"
 
-#: ../../mod/contacts.php:479
+#: mod/contacts.php:591
 msgid "Edit contact notes"
 msgstr "Редактировать заметки контакта"
 
-#: ../../mod/contacts.php:484 ../../mod/contacts.php:679
-#: ../../mod/viewcontacts.php:64 ../../mod/nogroup.php:40
+#: mod/contacts.php:596 mod/contacts.php:952 mod/viewcontacts.php:97
+#: mod/nogroup.php:41
 #, php-format
 msgid "Visit %s's profile [%s]"
 msgstr "Посетить профиль %s [%s]"
 
-#: ../../mod/contacts.php:485
+#: mod/contacts.php:597
 msgid "Block/Unblock contact"
 msgstr "Блокировать / Разблокировать контакт"
 
-#: ../../mod/contacts.php:486
+#: mod/contacts.php:598
 msgid "Ignore contact"
 msgstr "Игнорировать контакт"
 
-#: ../../mod/contacts.php:487
+#: mod/contacts.php:599
 msgid "Repair URL settings"
 msgstr "Восстановить настройки URL"
 
-#: ../../mod/contacts.php:488
+#: mod/contacts.php:600
 msgid "View conversations"
 msgstr "Просмотр бесед"
 
-#: ../../mod/contacts.php:490
+#: mod/contacts.php:602
 msgid "Delete contact"
 msgstr "Удалить контакт"
 
-#: ../../mod/contacts.php:494
+#: mod/contacts.php:606
 msgid "Last update:"
 msgstr "Последнее обновление: "
 
-#: ../../mod/contacts.php:496
+#: mod/contacts.php:608
 msgid "Update public posts"
 msgstr "Обновить публичные сообщения"
 
-#: ../../mod/contacts.php:498 ../../mod/admin.php:1503
+#: mod/contacts.php:610
 msgid "Update now"
 msgstr "Обновить сейчас"
 
-#: ../../mod/contacts.php:505
+#: mod/contacts.php:612 mod/follow.php:103 mod/dirfind.php:196
+#: mod/allfriends.php:65 mod/match.php:71 mod/suggest.php:82
+#: include/contact_widgets.php:32 include/Contact.php:297
+#: include/conversation.php:924
+msgid "Connect/Follow"
+msgstr "Подключиться/Следовать"
+
+#: mod/contacts.php:615 mod/contacts.php:806 mod/contacts.php:865
+#: mod/admin.php:1312
+msgid "Unblock"
+msgstr "Разблокировать"
+
+#: mod/contacts.php:615 mod/contacts.php:806 mod/contacts.php:865
+#: mod/admin.php:1311
+msgid "Block"
+msgstr "Заблокировать"
+
+#: mod/contacts.php:616 mod/contacts.php:807 mod/contacts.php:872
+msgid "Unignore"
+msgstr "Не игнорировать"
+
+#: mod/contacts.php:616 mod/contacts.php:807 mod/contacts.php:872
+#: mod/notifications.php:54 mod/notifications.php:179
+#: mod/notifications.php:259
+msgid "Ignore"
+msgstr "Игнорировать"
+
+#: mod/contacts.php:619
 msgid "Currently blocked"
 msgstr "В настоящее время заблокирован"
 
-#: ../../mod/contacts.php:506
+#: mod/contacts.php:620
 msgid "Currently ignored"
 msgstr "В настоящее время игнорируется"
 
-#: ../../mod/contacts.php:507
+#: mod/contacts.php:621
 msgid "Currently archived"
 msgstr "В данный момент архивирован"
 
-#: ../../mod/contacts.php:508 ../../mod/notifications.php:157
-#: ../../mod/notifications.php:204
+#: mod/contacts.php:622 mod/notifications.php:172 mod/notifications.php:251
 msgid "Hide this contact from others"
 msgstr "Скрыть этот контакт от других"
 
-#: ../../mod/contacts.php:508
+#: mod/contacts.php:622
 msgid ""
 "Replies/likes to your public posts <strong>may</strong> still be visible"
 msgstr "Ответы/лайки ваших публичных сообщений <strong>будут</strong> видимы."
 
-#: ../../mod/contacts.php:509
+#: mod/contacts.php:623
 msgid "Notification for new posts"
 msgstr ""
 
-#: ../../mod/contacts.php:509
+#: mod/contacts.php:623
 msgid "Send a notification of every new post of this contact"
 msgstr ""
 
-#: ../../mod/contacts.php:510
-msgid "Fetch further information for feeds"
-msgstr ""
-
-#: ../../mod/contacts.php:511
-msgid "Disabled"
-msgstr ""
-
-#: ../../mod/contacts.php:511
-msgid "Fetch information"
-msgstr ""
-
-#: ../../mod/contacts.php:511
-msgid "Fetch information and keywords"
-msgstr ""
-
-#: ../../mod/contacts.php:513
+#: mod/contacts.php:626
 msgid "Blacklisted keywords"
 msgstr ""
 
-#: ../../mod/contacts.php:513
+#: mod/contacts.php:626
 msgid ""
 "Comma separated list of keywords that should not be converted to hashtags, "
 "when \"Fetch information and keywords\" is selected"
 msgstr ""
 
-#: ../../mod/contacts.php:564
+#: mod/contacts.php:633 mod/follow.php:126 mod/notifications.php:255
+msgid "Profile URL"
+msgstr "URL профиля"
+
+#: mod/contacts.php:636 mod/notifications.php:244 mod/events.php:566
+#: mod/directory.php:145 include/identity.php:308 include/bb2diaspora.php:170
+#: include/event.php:36 include/event.php:60
+msgid "Location:"
+msgstr "Откуда:"
+
+#: mod/contacts.php:638 mod/notifications.php:246 mod/directory.php:153
+#: include/identity.php:317 include/identity.php:631
+msgid "About:"
+msgstr "О себе:"
+
+#: mod/contacts.php:640 mod/follow.php:134 mod/notifications.php:248
+#: include/identity.php:625
+msgid "Tags:"
+msgstr "Ключевые слова: "
+
+#: mod/contacts.php:685
 msgid "Suggestions"
 msgstr "Предложения"
 
-#: ../../mod/contacts.php:567
+#: mod/contacts.php:688
 msgid "Suggest potential friends"
 msgstr "Предложить потенциального знакомого"
 
-#: ../../mod/contacts.php:570 ../../mod/group.php:194
+#: mod/contacts.php:693 mod/group.php:192
 msgid "All Contacts"
 msgstr "Все контакты"
 
-#: ../../mod/contacts.php:573
+#: mod/contacts.php:696
 msgid "Show all contacts"
 msgstr "Показать все контакты"
 
-#: ../../mod/contacts.php:576
+#: mod/contacts.php:701
 msgid "Unblocked"
 msgstr "Не блокирован"
 
-#: ../../mod/contacts.php:579
+#: mod/contacts.php:704
 msgid "Only show unblocked contacts"
 msgstr "Показать только не блокированные контакты"
 
-#: ../../mod/contacts.php:583
+#: mod/contacts.php:710
 msgid "Blocked"
 msgstr "Заблокирован"
 
-#: ../../mod/contacts.php:586
+#: mod/contacts.php:713
 msgid "Only show blocked contacts"
 msgstr "Показать только блокированные контакты"
 
-#: ../../mod/contacts.php:590
+#: mod/contacts.php:719
 msgid "Ignored"
 msgstr "Игнорирован"
 
-#: ../../mod/contacts.php:593
+#: mod/contacts.php:722
 msgid "Only show ignored contacts"
 msgstr "Показать только игнорируемые контакты"
 
-#: ../../mod/contacts.php:597
+#: mod/contacts.php:728
 msgid "Archived"
 msgstr "Архивированные"
 
-#: ../../mod/contacts.php:600
+#: mod/contacts.php:731
 msgid "Only show archived contacts"
 msgstr "Показывать только архивные контакты"
 
-#: ../../mod/contacts.php:604
+#: mod/contacts.php:737
 msgid "Hidden"
 msgstr "Скрытые"
 
-#: ../../mod/contacts.php:607
+#: mod/contacts.php:740
 msgid "Only show hidden contacts"
 msgstr "Показывать только скрытые контакты"
 
-#: ../../mod/contacts.php:655
-msgid "Mutual Friendship"
-msgstr "Взаимная дружба"
-
-#: ../../mod/contacts.php:659
-msgid "is a fan of yours"
-msgstr "является вашим поклонником"
-
-#: ../../mod/contacts.php:663
-msgid "you are a fan of"
-msgstr "Вы - поклонник"
-
-#: ../../mod/contacts.php:680 ../../mod/nogroup.php:41
-msgid "Edit contact"
-msgstr "Редактировать контакт"
-
-#: ../../mod/contacts.php:702 ../../include/nav.php:177
-#: ../../view/theme/diabook/theme.php:125
+#: mod/contacts.php:793 mod/contacts.php:841 mod/viewcontacts.php:116
+#: include/identity.php:741 include/identity.php:744 include/text.php:1012
+#: include/nav.php:123 include/nav.php:187 view/theme/diabook/theme.php:125
 msgid "Contacts"
 msgstr "Контакты"
 
-#: ../../mod/contacts.php:706
+#: mod/contacts.php:797
 msgid "Search your contacts"
 msgstr "Поиск ваших контактов"
 
-#: ../../mod/contacts.php:707 ../../mod/directory.php:61
+#: mod/contacts.php:798
 msgid "Finding: "
 msgstr "Результат поиска: "
 
-#: ../../mod/contacts.php:708 ../../mod/directory.php:63
-#: ../../include/contact_widgets.php:34
+#: mod/contacts.php:799 mod/directory.php:210 include/contact_widgets.php:34
 msgid "Find"
 msgstr "Найти"
 
-#: ../../mod/contacts.php:713 ../../mod/settings.php:132
-#: ../../mod/settings.php:640
+#: mod/contacts.php:805 mod/settings.php:156 mod/settings.php:685
 msgid "Update"
 msgstr "Обновление"
 
-#: ../../mod/contacts.php:717 ../../mod/group.php:171 ../../mod/admin.php:1007
-#: ../../mod/content.php:438 ../../mod/content.php:741
-#: ../../mod/settings.php:677 ../../mod/photos.php:1654
-#: ../../object/Item.php:130 ../../include/conversation.php:614
+#: mod/contacts.php:808 mod/contacts.php:879
+msgid "Archive"
+msgstr "Архивировать"
+
+#: mod/contacts.php:808 mod/contacts.php:879
+msgid "Unarchive"
+msgstr "Разархивировать"
+
+#: mod/contacts.php:809 mod/group.php:171 mod/admin.php:1310
+#: mod/content.php:440 mod/content.php:743 mod/settings.php:722
+#: mod/photos.php:1723 object/Item.php:134 include/conversation.php:635
 msgid "Delete"
 msgstr "Удалить"
 
-#: ../../mod/hcard.php:10
+#: mod/contacts.php:822 include/identity.php:686 include/nav.php:75
+msgid "Status"
+msgstr "Посты"
+
+#: mod/contacts.php:825 mod/follow.php:143 include/identity.php:689
+msgid "Status Messages and Posts"
+msgstr "Ваши посты"
+
+#: mod/contacts.php:830 mod/profperm.php:104 mod/newmember.php:32
+#: include/identity.php:579 include/identity.php:665 include/identity.php:694
+#: include/nav.php:76 view/theme/diabook/theme.php:124
+msgid "Profile"
+msgstr "Информация"
+
+#: mod/contacts.php:833 include/identity.php:697
+msgid "Profile Details"
+msgstr "Информация о вас"
+
+#: mod/contacts.php:844
+msgid "View all contacts"
+msgstr "Показать все контакты"
+
+#: mod/contacts.php:850 mod/common.php:134
+msgid "Common Friends"
+msgstr "Общие друзья"
+
+#: mod/contacts.php:853
+msgid "View all common friends"
+msgstr ""
+
+#: mod/contacts.php:857
+msgid "Repair"
+msgstr "Восстановить"
+
+#: mod/contacts.php:860
+msgid "Advanced Contact Settings"
+msgstr "Дополнительные Настройки Контакта"
+
+#: mod/contacts.php:868
+msgid "Toggle Blocked status"
+msgstr "Изменить статус блокированности (заблокировать/разблокировать)"
+
+#: mod/contacts.php:875
+msgid "Toggle Ignored status"
+msgstr "Изменить статус игнорирования"
+
+#: mod/contacts.php:882
+msgid "Toggle Archive status"
+msgstr "Сменить статус архивации (архивирова/не архивировать)"
+
+#: mod/contacts.php:924
+msgid "Mutual Friendship"
+msgstr "Взаимная дружба"
+
+#: mod/contacts.php:928
+msgid "is a fan of yours"
+msgstr "является вашим поклонником"
+
+#: mod/contacts.php:932
+msgid "you are a fan of"
+msgstr "Вы - поклонник"
+
+#: mod/contacts.php:953 mod/nogroup.php:42
+msgid "Edit contact"
+msgstr "Редактировать контакт"
+
+#: mod/hcard.php:10
 msgid "No profile"
 msgstr "Нет профиля"
 
-#: ../../mod/manage.php:106
+#: mod/manage.php:139
 msgid "Manage Identities and/or Pages"
 msgstr "Управление идентификацией и / или страницами"
 
-#: ../../mod/manage.php:107
+#: mod/manage.php:140
 msgid ""
 "Toggle between different identities or community/group pages which share "
 "your account details or which you have been granted \"manage\" permissions"
 msgstr ""
 
-#: ../../mod/manage.php:108
+#: mod/manage.php:141
 msgid "Select an identity to manage: "
 msgstr "Выберите идентификацию для управления: "
 
-#: ../../mod/oexchange.php:25
+#: mod/oexchange.php:25
 msgid "Post successful."
 msgstr "Успешно добавлено."
 
-#: ../../mod/profperm.php:19 ../../mod/group.php:72 ../../index.php:368
+#: mod/profperm.php:19 mod/group.php:72 index.php:382
 msgid "Permission denied"
 msgstr "Доступ запрещен"
 
-#: ../../mod/profperm.php:25 ../../mod/profperm.php:55
+#: mod/profperm.php:25 mod/profperm.php:56
 msgid "Invalid profile identifier."
 msgstr "Недопустимый идентификатор профиля."
 
-#: ../../mod/profperm.php:101
+#: mod/profperm.php:102
 msgid "Profile Visibility Editor"
 msgstr "Редактор видимости профиля"
 
-#: ../../mod/profperm.php:103 ../../mod/newmember.php:32 ../../boot.php:2119
-#: ../../include/profile_advanced.php:7 ../../include/profile_advanced.php:87
-#: ../../include/nav.php:77 ../../view/theme/diabook/theme.php:124
-msgid "Profile"
-msgstr "Профиль"
-
-#: ../../mod/profperm.php:105 ../../mod/group.php:224
+#: mod/profperm.php:106 mod/group.php:223
 msgid "Click on a contact to add or remove."
 msgstr "Нажмите на контакт, чтобы добавить или удалить."
 
-#: ../../mod/profperm.php:114
+#: mod/profperm.php:115
 msgid "Visible To"
 msgstr "Видимый для"
 
-#: ../../mod/profperm.php:130
+#: mod/profperm.php:131
 msgid "All Contacts (with secure profile access)"
 msgstr "Все контакты (с безопасным доступом к профилю)"
 
-#: ../../mod/display.php:82 ../../mod/display.php:284
-#: ../../mod/display.php:503 ../../mod/viewsrc.php:15 ../../mod/admin.php:169
-#: ../../mod/admin.php:1052 ../../mod/admin.php:1265 ../../mod/notice.php:15
-#: ../../include/items.php:4516
+#: mod/display.php:82 mod/display.php:291 mod/display.php:513
+#: mod/viewsrc.php:15 mod/admin.php:234 mod/admin.php:1365 mod/admin.php:1599
+#: mod/notice.php:15 include/items.php:4887
 msgid "Item not found."
 msgstr "Пункт не найден."
 
-#: ../../mod/display.php:212 ../../mod/videos.php:115
-#: ../../mod/viewcontacts.php:19 ../../mod/community.php:18
-#: ../../mod/dfrn_request.php:762 ../../mod/search.php:89
-#: ../../mod/directory.php:33 ../../mod/photos.php:920
+#: mod/display.php:220 mod/videos.php:197 mod/viewcontacts.php:35
+#: mod/community.php:22 mod/dfrn_request.php:786 mod/search.php:93
+#: mod/search.php:99 mod/directory.php:37 mod/photos.php:976
 msgid "Public access denied."
 msgstr "Свободный доступ закрыт."
 
-#: ../../mod/display.php:332 ../../mod/profile.php:155
+#: mod/display.php:339 mod/profile.php:155
 msgid "Access to this profile has been restricted."
 msgstr "Доступ к этому профилю ограничен."
 
-#: ../../mod/display.php:496
+#: mod/display.php:506
 msgid "Item has been removed."
 msgstr "Пункт был удален."
 
-#: ../../mod/newmember.php:6
+#: mod/newmember.php:6
 msgid "Welcome to Friendica"
 msgstr "Добро пожаловать в Friendica"
 
-#: ../../mod/newmember.php:8
+#: mod/newmember.php:8
 msgid "New Member Checklist"
 msgstr "Новый контрольный список участников"
 
-#: ../../mod/newmember.php:12
+#: mod/newmember.php:12
 msgid ""
 "We would like to offer some tips and links to help make your experience "
 "enjoyable. Click any item to visit the relevant page. A link to this page "
 "will be visible from your home page for two weeks after your initial "
 "registration and then will quietly disappear."
-msgstr "Мы хотели бы предложить некоторые советы и ссылки, помогающие сделать вашу работу приятнее. Нажмите на любой элемент, чтобы посетить соответствующую страницу. Ссылка на эту страницу будет видна на  вашей домашней странице в течение двух недель после первоначальной регистрации, а затем она исчезнет."
+msgstr ""
+"Мы хотели бы предложить некоторые советы и ссылки, помогающие сделать вашу "
+"работу приятнее. Нажмите на любой элемент, чтобы посетить соответствующую "
+"страницу. Ссылка на эту страницу будет видна на  вашей домашней странице в "
+"течение двух недель после первоначальной регистрации, а затем она исчезнет."
 
-#: ../../mod/newmember.php:14
+#: mod/newmember.php:14
 msgid "Getting Started"
 msgstr "Начало работы"
 
-#: ../../mod/newmember.php:18
+#: mod/newmember.php:18
 msgid "Friendica Walk-Through"
 msgstr "Friendica тур"
 
-#: ../../mod/newmember.php:18
+#: mod/newmember.php:18
 msgid ""
 "On your <em>Quick Start</em> page - find a brief introduction to your "
-"profile and network tabs, make some new connections, and find some groups to"
-" join."
-msgstr "На вашей странице <em>Быстрый старт</em> - можно найти краткое введение в ваш профиль и сетевые закладки, создать новые связи, и найти группы, чтобы присоединиться к ним."
+"profile and network tabs, make some new connections, and find some groups to "
+"join."
+msgstr ""
+"На вашей странице <em>Быстрый старт</em> - можно найти краткое введение в "
+"ваш профиль и сетевые закладки, создать новые связи, и найти группы, чтобы "
+"присоединиться к ним."
 
-#: ../../mod/newmember.php:22 ../../mod/admin.php:1104
-#: ../../mod/admin.php:1325 ../../mod/settings.php:85
-#: ../../include/nav.php:172 ../../view/theme/diabook/theme.php:544
-#: ../../view/theme/diabook/theme.php:648
+#: mod/newmember.php:22 mod/admin.php:1418 mod/admin.php:1676
+#: mod/settings.php:109 include/nav.php:182 view/theme/diabook/theme.php:544
+#: view/theme/diabook/theme.php:648
 msgid "Settings"
 msgstr "Настройки"
 
-#: ../../mod/newmember.php:26
+#: mod/newmember.php:26
 msgid "Go to Your Settings"
 msgstr "Перейти к вашим настройкам"
 
-#: ../../mod/newmember.php:26
+#: mod/newmember.php:26
 msgid ""
 "On your <em>Settings</em> page -  change your initial password. Also make a "
 "note of your Identity Address. This looks just like an email address - and "
 "will be useful in making friends on the free social web."
-msgstr "На вашей странице <em>Настройки</em> - вы можете изменить свой первоначальный пароль. Также обратите внимание на ваш личный адрес. Он выглядит так же, как адрес электронной почты - и будет полезен для поиска друзей в свободной социальной сети."
+msgstr ""
+"На вашей странице <em>Настройки</em> - вы можете изменить свой "
+"первоначальный пароль. Также обратите внимание на ваш личный адрес. Он "
+"выглядит так же, как адрес электронной почты - и будет полезен для поиска "
+"друзей в свободной социальной сети."
 
-#: ../../mod/newmember.php:28
+#: mod/newmember.php:28
 msgid ""
-"Review the other settings, particularly the privacy settings. An unpublished"
-" directory listing is like having an unlisted phone number. In general, you "
+"Review the other settings, particularly the privacy settings. An unpublished "
+"directory listing is like having an unlisted phone number. In general, you "
 "should probably publish your listing - unless all of your friends and "
 "potential friends know exactly how to find you."
-msgstr "Просмотрите другие установки, в частности, параметры конфиденциальности. Неопубликованные пункты каталога с частными номерами телефона. В общем, вам, вероятно, следует опубликовать свою информацию - если все ваши друзья и потенциальные друзья точно знают, как вас найти."
+msgstr ""
+"Просмотрите другие установки, в частности, параметры конфиденциальности. "
+"Неопубликованные пункты каталога с частными номерами телефона. В общем, вам, "
+"вероятно, следует опубликовать свою информацию - если все ваши друзья и "
+"потенциальные друзья точно знают, как вас найти."
 
-#: ../../mod/newmember.php:36 ../../mod/profile_photo.php:244
-#: ../../mod/profiles.php:699
+#: mod/newmember.php:36 mod/profile_photo.php:250 mod/profiles.php:709
 msgid "Upload Profile Photo"
 msgstr "Загрузить фото профиля"
 
-#: ../../mod/newmember.php:36
+#: mod/newmember.php:36
 msgid ""
 "Upload a profile photo if you have not done so already. Studies have shown "
-"that people with real photos of themselves are ten times more likely to make"
-" friends than people who do not."
-msgstr "Загрузите фотографию профиля, если вы еще не сделали это. Исследования показали, что люди с реальными фотографиями имеют в десять раз больше шансов подружиться, чем люди, которые этого не делают."
+"that people with real photos of themselves are ten times more likely to make "
+"friends than people who do not."
+msgstr ""
+"Загрузите фотографию профиля, если вы еще не сделали это. Исследования "
+"показали, что люди с реальными фотографиями имеют в десять раз больше шансов "
+"подружиться, чем люди, которые этого не делают."
 
-#: ../../mod/newmember.php:38
+#: mod/newmember.php:38
 msgid "Edit Your Profile"
 msgstr "Редактировать профиль"
 
-#: ../../mod/newmember.php:38
+#: mod/newmember.php:38
 msgid ""
 "Edit your <strong>default</strong> profile to your liking. Review the "
-"settings for hiding your list of friends and hiding the profile from unknown"
-" visitors."
-msgstr "Отредактируйте профиль <strong>по умолчанию</strong> на свой ​​вкус. Просмотрите установки для сокрытия вашего списка друзей и сокрытия профиля от неизвестных посетителей."
+"settings for hiding your list of friends and hiding the profile from unknown "
+"visitors."
+msgstr ""
+"Отредактируйте профиль <strong>по умолчанию</strong> на свой ​​вкус. "
+"Просмотрите установки для сокрытия вашего списка друзей и сокрытия профиля "
+"от неизвестных посетителей."
 
-#: ../../mod/newmember.php:40
+#: mod/newmember.php:40
 msgid "Profile Keywords"
 msgstr "Ключевые слова профиля"
 
-#: ../../mod/newmember.php:40
+#: mod/newmember.php:40
 msgid ""
 "Set some public keywords for your default profile which describe your "
 "interests. We may be able to find other people with similar interests and "
 "suggest friendships."
-msgstr "Установите некоторые публичные ключевые слова для вашего профиля по умолчанию, которые описывают ваши интересы. Мы можем быть в состоянии найти других людей со схожими интересами и предложить дружбу."
+msgstr ""
+"Установите некоторые публичные ключевые слова для вашего профиля по "
+"умолчанию, которые описывают ваши интересы. Мы можем быть в состоянии найти "
+"других людей со схожими интересами и предложить дружбу."
 
-#: ../../mod/newmember.php:44
+#: mod/newmember.php:44
 msgid "Connecting"
 msgstr "Подключение"
 
-#: ../../mod/newmember.php:49 ../../mod/newmember.php:51
-#: ../../include/contact_selectors.php:81
-msgid "Facebook"
-msgstr "Facebook"
-
-#: ../../mod/newmember.php:49
-msgid ""
-"Authorise the Facebook Connector if you currently have a Facebook account "
-"and we will (optionally) import all your Facebook friends and conversations."
-msgstr "Авторизуйте Facebook Connector , если у вас уже есть аккаунт на Facebook, и мы (по желанию) импортируем всех ваших друзей и беседы с Facebook."
-
-#: ../../mod/newmember.php:51
-msgid ""
-"<em>If</em> this is your own personal server, installing the Facebook addon "
-"may ease your transition to the free social web."
-msgstr "<em>Если</em> это ваш личный сервер, установите дополнение Facebook, это может облегчить ваш переход на свободную социальную сеть."
-
-#: ../../mod/newmember.php:56
+#: mod/newmember.php:51
 msgid "Importing Emails"
 msgstr "Импортирование Email-ов"
 
-#: ../../mod/newmember.php:56
+#: mod/newmember.php:51
 msgid ""
 "Enter your email access information on your Connector Settings page if you "
 "wish to import and interact with friends or mailing lists from your email "
 "INBOX"
-msgstr "Введите информацию о доступе к вашему email на странице настроек вашего коннектора, если вы хотите импортировать, и общаться с друзьями или получать рассылки на ваш ящик электронной почты"
+msgstr ""
+"Введите информацию о доступе к вашему email на странице настроек вашего "
+"коннектора, если вы хотите импортировать, и общаться с друзьями или получать "
+"рассылки на ваш ящик электронной почты"
 
-#: ../../mod/newmember.php:58
+#: mod/newmember.php:53
 msgid "Go to Your Contacts Page"
 msgstr "Перейти на страницу ваших контактов"
 
-#: ../../mod/newmember.php:58
+#: mod/newmember.php:53
 msgid ""
 "Your Contacts page is your gateway to managing friendships and connecting "
 "with friends on other networks. Typically you enter their address or site "
 "URL in the <em>Add New Contact</em> dialog."
-msgstr "Ваша страница контактов - это ваш шлюз к управлению дружбой и общением с друзьями в других сетях. Обычно вы вводите свой ​​адрес или адрес сайта в диалог <em>Добавить новый контакт</em>."
+msgstr ""
+"Ваша страница контактов - это ваш шлюз к управлению дружбой и общением с "
+"друзьями в других сетях. Обычно вы вводите свой ​​адрес или адрес сайта в "
+"диалог <em>Добавить новый контакт</em>."
 
-#: ../../mod/newmember.php:60
+#: mod/newmember.php:55
 msgid "Go to Your Site's Directory"
 msgstr "Перейти в каталог вашего сайта"
 
-#: ../../mod/newmember.php:60
+#: mod/newmember.php:55
 msgid ""
 "The Directory page lets you find other people in this network or other "
 "federated sites. Look for a <em>Connect</em> or <em>Follow</em> link on "
 "their profile page. Provide your own Identity Address if requested."
-msgstr "На странице каталога вы можете найти других людей в этой сети или на других похожих сайтах. Ищите ссылки <em>Подключить</em> или <em>Следовать</em> на страницах их профилей. Укажите свой собственный адрес идентификации, если требуется."
+msgstr ""
+"На странице каталога вы можете найти других людей в этой сети или на других "
+"похожих сайтах. Ищите ссылки <em>Подключить</em> или <em>Следовать</em> на "
+"страницах их профилей. Укажите свой собственный адрес идентификации, если "
+"требуется."
 
-#: ../../mod/newmember.php:62
+#: mod/newmember.php:57
 msgid "Finding New People"
 msgstr "Поиск людей"
 
-#: ../../mod/newmember.php:62
+#: mod/newmember.php:57
 msgid ""
 "On the side panel of the Contacts page are several tools to find new "
 "friends. We can match people by interest, look up people by name or "
-"interest, and provide suggestions based on network relationships. On a brand"
-" new site, friend suggestions will usually begin to be populated within 24 "
+"interest, and provide suggestions based on network relationships. On a brand "
+"new site, friend suggestions will usually begin to be populated within 24 "
 "hours."
-msgstr "На боковой панели страницы Контакты есть несколько инструментов, чтобы найти новых друзей. Мы можем  искать по соответствию интересам, посмотреть людей по имени или интересам, и внести предложения на основе сетевых отношений. На новом сайте, предложения дружбы, как правило, начинают заполняться в течение 24 часов."
+msgstr ""
+"На боковой панели страницы Контакты есть несколько инструментов, чтобы найти "
+"новых друзей. Мы можем  искать по соответствию интересам, посмотреть людей "
+"по имени или интересам, и внести предложения на основе сетевых отношений. На "
+"новом сайте, предложения дружбы, как правило, начинают заполняться в течение "
+"24 часов."
 
-#: ../../mod/newmember.php:66 ../../include/group.php:270
+#: mod/newmember.php:61 include/group.php:283
 msgid "Groups"
 msgstr "Группы"
 
-#: ../../mod/newmember.php:70
+#: mod/newmember.php:65
 msgid "Group Your Contacts"
 msgstr "Группа \"ваши контакты\""
 
-#: ../../mod/newmember.php:70
+#: mod/newmember.php:65
 msgid ""
 "Once you have made some friends, organize them into private conversation "
-"groups from the sidebar of your Contacts page and then you can interact with"
-" each group privately on your Network page."
-msgstr "После того, как вы найдете несколько друзей, организуйте их в группы частных бесед в боковой панели на странице Контакты, а затем вы можете взаимодействовать с каждой группой приватно или на вашей странице Сеть."
+"groups from the sidebar of your Contacts page and then you can interact with "
+"each group privately on your Network page."
+msgstr ""
+"После того, как вы найдете несколько друзей, организуйте их в группы частных "
+"бесед в боковой панели на странице Контакты, а затем вы можете "
+"взаимодействовать с каждой группой приватно или на вашей странице Сеть."
 
-#: ../../mod/newmember.php:73
+#: mod/newmember.php:68
 msgid "Why Aren't My Posts Public?"
 msgstr "Почему мои посты не публичные?"
 
-#: ../../mod/newmember.php:73
+#: mod/newmember.php:68
 msgid ""
-"Friendica respects your privacy. By default, your posts will only show up to"
-" people you've added as friends. For more information, see the help section "
+"Friendica respects your privacy. By default, your posts will only show up to "
+"people you've added as friends. For more information, see the help section "
 "from the link above."
-msgstr "Friendica уважает вашу приватность. По умолчанию, ваши сообщения будут показываться только для людей, которых вы добавили в список друзей. Для получения дополнительной информации см. раздел справки по ссылке выше."
+msgstr ""
+"Friendica уважает вашу приватность. По умолчанию, ваши сообщения будут "
+"показываться только для людей, которых вы добавили в список друзей. Для "
+"получения дополнительной информации см. раздел справки по ссылке выше."
 
-#: ../../mod/newmember.php:78
+#: mod/newmember.php:73
 msgid "Getting Help"
 msgstr "Получить помощь"
 
-#: ../../mod/newmember.php:82
+#: mod/newmember.php:77
 msgid "Go to the Help Section"
 msgstr "Перейти в раздел справки"
 
-#: ../../mod/newmember.php:82
+#: mod/newmember.php:77
 msgid ""
-"Our <strong>help</strong> pages may be consulted for detail on other program"
-" features and resources."
-msgstr "Наши страницы <strong>помощи</strong> могут проконсультировать о подробностях и возможностях программы и ресурса."
+"Our <strong>help</strong> pages may be consulted for detail on other program "
+"features and resources."
+msgstr ""
+"Наши страницы <strong>помощи</strong> могут проконсультировать о "
+"подробностях и возможностях программы и ресурса."
 
-#: ../../mod/openid.php:24
+#: mod/openid.php:24
 msgid "OpenID protocol error. No ID returned."
 msgstr "Ошибка протокола OpenID. Не возвращён ID."
 
-#: ../../mod/openid.php:53
+#: mod/openid.php:53
 msgid ""
 "Account not found and OpenID registration is not permitted on this site."
 msgstr "Аккаунт не найден и OpenID регистрация не допускается на этом сайте."
 
-#: ../../mod/openid.php:93 ../../include/auth.php:112
-#: ../../include/auth.php:175
+#: mod/openid.php:93 include/auth.php:118 include/auth.php:181
 msgid "Login failed."
 msgstr "Войти не удалось."
 
-#: ../../mod/profile_photo.php:44
+#: mod/profile_photo.php:44
 msgid "Image uploaded but image cropping failed."
 msgstr "Изображение загружено, но обрезка изображения не удалась."
 
-#: ../../mod/profile_photo.php:74 ../../mod/profile_photo.php:81
-#: ../../mod/profile_photo.php:88 ../../mod/profile_photo.php:204
-#: ../../mod/profile_photo.php:296 ../../mod/profile_photo.php:305
-#: ../../mod/photos.php:155 ../../mod/photos.php:731 ../../mod/photos.php:1187
-#: ../../mod/photos.php:1210 ../../include/user.php:335
-#: ../../include/user.php:342 ../../include/user.php:349
-#: ../../view/theme/diabook/theme.php:500
+#: mod/profile_photo.php:74 mod/profile_photo.php:81 mod/profile_photo.php:88
+#: mod/profile_photo.php:210 mod/profile_photo.php:302
+#: mod/profile_photo.php:311 mod/photos.php:78 mod/photos.php:192
+#: mod/photos.php:775 mod/photos.php:1245 mod/photos.php:1268
+#: mod/photos.php:1862 include/user.php:345 include/user.php:352
+#: include/user.php:359 view/theme/diabook/theme.php:500
 msgid "Profile Photos"
 msgstr "Фотографии профиля"
 
-#: ../../mod/profile_photo.php:77 ../../mod/profile_photo.php:84
-#: ../../mod/profile_photo.php:91 ../../mod/profile_photo.php:308
+#: mod/profile_photo.php:77 mod/profile_photo.php:84 mod/profile_photo.php:91
+#: mod/profile_photo.php:314
 #, php-format
 msgid "Image size reduction [%s] failed."
 msgstr "Уменьшение размера изображения [%s] не удалось."
 
-#: ../../mod/profile_photo.php:118
+#: mod/profile_photo.php:124
 msgid ""
 "Shift-reload the page or clear browser cache if the new photo does not "
 "display immediately."
-msgstr "Перезагрузите страницу с зажатой клавишей \"Shift\" для того, чтобы увидеть свое новое фото немедленно."
+msgstr ""
+"Перезагрузите страницу с зажатой клавишей \"Shift\" для того, чтобы увидеть "
+"свое новое фото немедленно."
 
-#: ../../mod/profile_photo.php:128
+#: mod/profile_photo.php:134
 msgid "Unable to process image"
 msgstr "Не удается обработать изображение"
 
-#: ../../mod/profile_photo.php:144 ../../mod/wall_upload.php:122
+#: mod/profile_photo.php:150 mod/wall_upload.php:151 mod/photos.php:811
 #, php-format
-msgid "Image exceeds size limit of %d"
-msgstr "Изображение превышает предельный размер %d"
+msgid "Image exceeds size limit of %s"
+msgstr ""
 
-#: ../../mod/profile_photo.php:153 ../../mod/wall_upload.php:144
-#: ../../mod/photos.php:807
+#: mod/profile_photo.php:159 mod/wall_upload.php:183 mod/photos.php:851
 msgid "Unable to process image."
 msgstr "Невозможно обработать фото."
 
-#: ../../mod/profile_photo.php:242
+#: mod/profile_photo.php:248
 msgid "Upload File:"
 msgstr "Загрузить файл:"
 
-#: ../../mod/profile_photo.php:243
+#: mod/profile_photo.php:249
 msgid "Select a profile:"
 msgstr "Выбрать этот профиль:"
 
-#: ../../mod/profile_photo.php:245
+#: mod/profile_photo.php:251
 msgid "Upload"
 msgstr "Загрузить"
 
-#: ../../mod/profile_photo.php:248 ../../mod/settings.php:1062
+#: mod/profile_photo.php:254
 msgid "or"
 msgstr "или"
 
-#: ../../mod/profile_photo.php:248
+#: mod/profile_photo.php:254
 msgid "skip this step"
 msgstr "пропустить этот шаг"
 
-#: ../../mod/profile_photo.php:248
+#: mod/profile_photo.php:254
 msgid "select a photo from your photo albums"
 msgstr "выберите фото из ваших фотоальбомов"
 
-#: ../../mod/profile_photo.php:262
+#: mod/profile_photo.php:268
 msgid "Crop Image"
 msgstr "Обрезать изображение"
 
-#: ../../mod/profile_photo.php:263
+#: mod/profile_photo.php:269
 msgid "Please adjust the image cropping for optimum viewing."
 msgstr "Пожалуйста, настройте обрезку изображения для оптимального просмотра."
 
-#: ../../mod/profile_photo.php:265
+#: mod/profile_photo.php:271
 msgid "Done Editing"
 msgstr "Редактирование выполнено"
 
-#: ../../mod/profile_photo.php:299
+#: mod/profile_photo.php:305
 msgid "Image uploaded successfully."
 msgstr "Изображение загружено успешно."
 
-#: ../../mod/profile_photo.php:301 ../../mod/wall_upload.php:172
-#: ../../mod/photos.php:834
+#: mod/profile_photo.php:307 mod/wall_upload.php:216 mod/photos.php:878
 msgid "Image upload failed."
 msgstr "Загрузка фото неудачная."
 
-#: ../../mod/subthread.php:87 ../../mod/tagger.php:62 ../../mod/like.php:149
-#: ../../include/conversation.php:126 ../../include/conversation.php:254
-#: ../../include/text.php:1968 ../../include/diaspora.php:2087
-#: ../../view/theme/diabook/theme.php:471
+#: mod/subthread.php:87 mod/tagger.php:62 include/like.php:165
+#: include/conversation.php:130 include/conversation.php:266
+#: include/text.php:2000 include/diaspora.php:2169
+#: view/theme/diabook/theme.php:471
 msgid "photo"
 msgstr "фото"
 
-#: ../../mod/subthread.php:87 ../../mod/tagger.php:62 ../../mod/like.php:149
-#: ../../mod/like.php:319 ../../include/conversation.php:121
-#: ../../include/conversation.php:130 ../../include/conversation.php:249
-#: ../../include/conversation.php:258 ../../include/diaspora.php:2087
-#: ../../view/theme/diabook/theme.php:466
-#: ../../view/theme/diabook/theme.php:475
+#: mod/subthread.php:87 mod/tagger.php:62 include/like.php:165
+#: include/like.php:334 include/conversation.php:125
+#: include/conversation.php:134 include/conversation.php:261
+#: include/conversation.php:270 include/diaspora.php:2169
+#: view/theme/diabook/theme.php:466 view/theme/diabook/theme.php:475
 msgid "status"
 msgstr "статус"
 
-#: ../../mod/subthread.php:103
+#: mod/subthread.php:103
 #, php-format
 msgid "%1$s is following %2$s's %3$s"
 msgstr ""
 
-#: ../../mod/tagrm.php:41
+#: mod/tagrm.php:41
 msgid "Tag removed"
 msgstr "Ключевое слово удалено"
 
-#: ../../mod/tagrm.php:79
+#: mod/tagrm.php:79
 msgid "Remove Item Tag"
 msgstr "Удалить ключевое слово"
 
-#: ../../mod/tagrm.php:81
+#: mod/tagrm.php:81
 msgid "Select a tag to remove: "
 msgstr "Выберите ключевое слово для удаления: "
 
-#: ../../mod/tagrm.php:93 ../../mod/delegate.php:139
+#: mod/tagrm.php:93 mod/delegate.php:139
 msgid "Remove"
 msgstr "Удалить"
 
-#: ../../mod/filer.php:30 ../../include/conversation.php:1006
-#: ../../include/conversation.php:1024
+#: mod/ostatus_subscribe.php:14
+msgid "Subscribing to OStatus contacts"
+msgstr ""
+
+#: mod/ostatus_subscribe.php:25
+msgid "No contact provided."
+msgstr ""
+
+#: mod/ostatus_subscribe.php:30
+msgid "Couldn't fetch information for contact."
+msgstr ""
+
+#: mod/ostatus_subscribe.php:38
+msgid "Couldn't fetch friends for contact."
+msgstr ""
+
+#: mod/ostatus_subscribe.php:51 mod/repair_ostatus.php:44
+msgid "Done"
+msgstr "Готово"
+
+#: mod/ostatus_subscribe.php:65
+msgid "success"
+msgstr "удачно"
+
+#: mod/ostatus_subscribe.php:67
+msgid "failed"
+msgstr "неудача"
+
+#: mod/ostatus_subscribe.php:69 object/Item.php:235
+msgid "ignored"
+msgstr ""
+
+#: mod/ostatus_subscribe.php:73 mod/repair_ostatus.php:50
+msgid "Keep this window open until done."
+msgstr ""
+
+#: mod/filer.php:30 include/conversation.php:1132
+#: include/conversation.php:1150
 msgid "Save to Folder:"
 msgstr "Сохранить в папку:"
 
-#: ../../mod/filer.php:30
+#: mod/filer.php:30
 msgid "- select -"
 msgstr "- выбрать -"
 
-#: ../../mod/filer.php:31 ../../mod/editpost.php:109 ../../mod/notes.php:63
-#: ../../include/text.php:956
+#: mod/filer.php:31 mod/editpost.php:109 mod/notes.php:61
+#: include/text.php:1004
 msgid "Save"
 msgstr "Сохранить"
 
-#: ../../mod/follow.php:27
+#: mod/follow.php:19 mod/dfrn_request.php:870
+msgid "Submit Request"
+msgstr "Отправить запрос"
+
+#: mod/follow.php:30
+msgid "You already added this contact."
+msgstr ""
+
+#: mod/follow.php:39
+msgid "Diaspora support isn't enabled. Contact can't be added."
+msgstr ""
+
+#: mod/follow.php:46
+msgid "OStatus support is disabled. Contact can't be added."
+msgstr ""
+
+#: mod/follow.php:53
+msgid "The network type couldn't be detected. Contact can't be added."
+msgstr ""
+
+#: mod/follow.php:109 mod/dfrn_request.php:856
+msgid "Please answer the following:"
+msgstr "Пожалуйста, ответьте следующее:"
+
+#: mod/follow.php:110 mod/dfrn_request.php:857
+#, php-format
+msgid "Does %s know you?"
+msgstr "%s знает вас?"
+
+#: mod/follow.php:110 mod/settings.php:1103 mod/settings.php:1109
+#: mod/settings.php:1117 mod/settings.php:1121 mod/settings.php:1126
+#: mod/settings.php:1132 mod/settings.php:1138 mod/settings.php:1144
+#: mod/settings.php:1170 mod/settings.php:1171 mod/settings.php:1172
+#: mod/settings.php:1173 mod/settings.php:1174 mod/dfrn_request.php:857
+#: mod/register.php:239 mod/profiles.php:658 mod/profiles.php:662
+#: mod/profiles.php:687 mod/api.php:106
+msgid "No"
+msgstr "Нет"
+
+#: mod/follow.php:111 mod/dfrn_request.php:861
+msgid "Add a personal note:"
+msgstr "Добавить личную заметку:"
+
+#: mod/follow.php:117 mod/dfrn_request.php:867
+msgid "Your Identity Address:"
+msgstr "Ваш идентификационный адрес:"
+
+#: mod/follow.php:180
 msgid "Contact added"
 msgstr "Контакт добавлен"
 
-#: ../../mod/item.php:113
+#: mod/item.php:114
 msgid "Unable to locate original post."
 msgstr "Не удалось найти оригинальный пост."
 
-#: ../../mod/item.php:345
+#: mod/item.php:329
 msgid "Empty post discarded."
 msgstr "Пустое сообщение отбрасывается."
 
-#: ../../mod/item.php:484 ../../mod/wall_upload.php:169
-#: ../../mod/wall_upload.php:178 ../../mod/wall_upload.php:185
-#: ../../include/Photo.php:916 ../../include/Photo.php:931
-#: ../../include/Photo.php:938 ../../include/Photo.php:960
-#: ../../include/message.php:144
+#: mod/item.php:467 mod/wall_upload.php:213 mod/wall_upload.php:227
+#: mod/wall_upload.php:234 include/Photo.php:958 include/Photo.php:973
+#: include/Photo.php:980 include/Photo.php:1002 include/message.php:145
 msgid "Wall Photos"
 msgstr "Фото стены"
 
-#: ../../mod/item.php:938
+#: mod/item.php:842
 msgid "System error. Post not saved."
 msgstr "Системная ошибка. Сообщение не сохранено."
 
-#: ../../mod/item.php:964
+#: mod/item.php:971
 #, php-format
 msgid ""
-"This message was sent to you by %s, a member of the Friendica social "
-"network."
-msgstr "Это сообщение было отправлено вам %s, участником социальной сети Friendica."
+"This message was sent to you by %s, a member of the Friendica social network."
+msgstr ""
+"Это сообщение было отправлено вам %s, участником социальной сети Friendica."
 
-#: ../../mod/item.php:966
+#: mod/item.php:973
 #, php-format
 msgid "You may visit them online at %s"
 msgstr "Вы можете посетить их в онлайне на %s"
 
-#: ../../mod/item.php:967
+#: mod/item.php:974
 msgid ""
 "Please contact the sender by replying to this post if you do not wish to "
 "receive these messages."
-msgstr "Пожалуйста, свяжитесь с отправителем, ответив на это сообщение, если вы не хотите получать эти сообщения."
+msgstr ""
+"Пожалуйста, свяжитесь с отправителем, ответив на это сообщение, если вы не "
+"хотите получать эти сообщения."
 
-#: ../../mod/item.php:971
+#: mod/item.php:978
 #, php-format
 msgid "%s posted an update."
 msgstr "%s отправил/а/ обновление."
 
-#: ../../mod/group.php:29
+#: mod/group.php:29
 msgid "Group created."
 msgstr "Группа создана."
 
-#: ../../mod/group.php:35
+#: mod/group.php:35
 msgid "Could not create group."
 msgstr "Не удалось создать группу."
 
-#: ../../mod/group.php:47 ../../mod/group.php:140
+#: mod/group.php:47 mod/group.php:140
 msgid "Group not found."
 msgstr "Группа не найдена."
 
-#: ../../mod/group.php:60
+#: mod/group.php:60
 msgid "Group name changed."
 msgstr "Название группы изменено."
 
-#: ../../mod/group.php:87
+#: mod/group.php:87
 msgid "Save Group"
 msgstr "Сохранить группу"
 
-#: ../../mod/group.php:93
+#: mod/group.php:93
 msgid "Create a group of contacts/friends."
 msgstr "Создать группу контактов / друзей."
 
-#: ../../mod/group.php:94 ../../mod/group.php:180
+#: mod/group.php:94 mod/group.php:178 include/group.php:289
 msgid "Group Name: "
 msgstr "Название группы: "
 
-#: ../../mod/group.php:113
+#: mod/group.php:113
 msgid "Group removed."
 msgstr "Группа удалена."
 
-#: ../../mod/group.php:115
+#: mod/group.php:115
 msgid "Unable to remove group."
 msgstr "Не удается удалить группу."
 
-#: ../../mod/group.php:179
+#: mod/group.php:177
 msgid "Group Editor"
 msgstr "Редактор групп"
 
-#: ../../mod/group.php:192
+#: mod/group.php:190
 msgid "Members"
 msgstr "Участники"
 
-#: ../../mod/apps.php:7 ../../index.php:212
+#: mod/group.php:193 mod/network.php:576 mod/content.php:130
+msgid "Group is empty"
+msgstr "Группа пуста"
+
+#: mod/apps.php:7 index.php:226
 msgid "You must be logged in to use addons. "
 msgstr "Вы должны войти в систему, чтобы использовать аддоны."
 
-#: ../../mod/apps.php:11
+#: mod/apps.php:11
 msgid "Applications"
 msgstr "Приложения"
 
-#: ../../mod/apps.php:14
+#: mod/apps.php:14
 msgid "No installed applications."
 msgstr "Нет установленных приложений."
 
-#: ../../mod/dfrn_confirm.php:64 ../../mod/profiles.php:18
-#: ../../mod/profiles.php:133 ../../mod/profiles.php:179
-#: ../../mod/profiles.php:630
+#: mod/dfrn_confirm.php:64 mod/profiles.php:18 mod/profiles.php:133
+#: mod/profiles.php:179 mod/profiles.php:627
 msgid "Profile not found."
 msgstr "Профиль не найден."
 
-#: ../../mod/dfrn_confirm.php:120 ../../mod/fsuggest.php:20
-#: ../../mod/fsuggest.php:92 ../../mod/crepair.php:133
+#: mod/dfrn_confirm.php:120 mod/fsuggest.php:20 mod/fsuggest.php:92
+#: mod/crepair.php:131
 msgid "Contact not found."
 msgstr "Контакт не найден."
 
-#: ../../mod/dfrn_confirm.php:121
+#: mod/dfrn_confirm.php:121
 msgid ""
-"This may occasionally happen if contact was requested by both persons and it"
-" has already been approved."
-msgstr "Это может иногда происходить, если контакт запрашивали двое людей, и он был уже одобрен."
+"This may occasionally happen if contact was requested by both persons and it "
+"has already been approved."
+msgstr ""
+"Это может иногда происходить, если контакт запрашивали двое людей, и он был "
+"уже одобрен."
 
-#: ../../mod/dfrn_confirm.php:240
+#: mod/dfrn_confirm.php:240
 msgid "Response from remote site was not understood."
 msgstr "Ответ от удаленного сайта не был понят."
 
-#: ../../mod/dfrn_confirm.php:249 ../../mod/dfrn_confirm.php:254
+#: mod/dfrn_confirm.php:249 mod/dfrn_confirm.php:254
 msgid "Unexpected response from remote site: "
 msgstr "Неожиданный ответ от удаленного сайта: "
 
-#: ../../mod/dfrn_confirm.php:263
+#: mod/dfrn_confirm.php:263
 msgid "Confirmation completed successfully."
 msgstr "Подтверждение успешно завершено."
 
-#: ../../mod/dfrn_confirm.php:265 ../../mod/dfrn_confirm.php:279
-#: ../../mod/dfrn_confirm.php:286
+#: mod/dfrn_confirm.php:265 mod/dfrn_confirm.php:279 mod/dfrn_confirm.php:286
 msgid "Remote site reported: "
 msgstr "Удаленный сайт сообщил: "
 
-#: ../../mod/dfrn_confirm.php:277
+#: mod/dfrn_confirm.php:277
 msgid "Temporary failure. Please wait and try again."
 msgstr "Временные неудачи. Подождите и попробуйте еще раз."
 
-#: ../../mod/dfrn_confirm.php:284
+#: mod/dfrn_confirm.php:284
 msgid "Introduction failed or was revoked."
 msgstr "Запрос ошибочен или был отозван."
 
-#: ../../mod/dfrn_confirm.php:429
+#: mod/dfrn_confirm.php:430
 msgid "Unable to set contact photo."
 msgstr "Не удается установить фото контакта."
 
-#: ../../mod/dfrn_confirm.php:486 ../../include/conversation.php:172
-#: ../../include/diaspora.php:620
+#: mod/dfrn_confirm.php:487 include/conversation.php:185
+#: include/diaspora.php:637
 #, php-format
 msgid "%1$s is now friends with %2$s"
 msgstr "%1$s и %2$s теперь друзья"
 
-#: ../../mod/dfrn_confirm.php:571
+#: mod/dfrn_confirm.php:572
 #, php-format
 msgid "No user record found for '%s' "
 msgstr "Не найдено записи пользователя для '%s' "
 
-#: ../../mod/dfrn_confirm.php:581
+#: mod/dfrn_confirm.php:582
 msgid "Our site encryption key is apparently messed up."
 msgstr "Наш ключ шифрования сайта, по-видимому, перепутался."
 
-#: ../../mod/dfrn_confirm.php:592
+#: mod/dfrn_confirm.php:593
 msgid "Empty site URL was provided or URL could not be decrypted by us."
-msgstr "Был предоставлен пустой URL сайта ​​или URL не может быть расшифрован нами."
+msgstr ""
+"Был предоставлен пустой URL сайта ​​или URL не может быть расшифрован нами."
 
-#: ../../mod/dfrn_confirm.php:613
+#: mod/dfrn_confirm.php:614
 msgid "Contact record was not found for you on our site."
 msgstr "Запись контакта не найдена для вас на нашем сайте."
 
-#: ../../mod/dfrn_confirm.php:627
+#: mod/dfrn_confirm.php:628
 #, php-format
 msgid "Site public key not available in contact record for URL %s."
 msgstr "Публичный ключ недоступен в записи о контакте по ссылке %s"
 
-#: ../../mod/dfrn_confirm.php:647
+#: mod/dfrn_confirm.php:648
 msgid ""
 "The ID provided by your system is a duplicate on our system. It should work "
 "if you try again."
-msgstr "ID, предложенный вашей системой, является дубликатом в нашей системе. Он должен работать, если вы повторите попытку."
+msgstr ""
+"ID, предложенный вашей системой, является дубликатом в нашей системе. Он "
+"должен работать, если вы повторите попытку."
 
-#: ../../mod/dfrn_confirm.php:658
+#: mod/dfrn_confirm.php:659
 msgid "Unable to set your contact credentials on our system."
 msgstr "Не удалось установить ваши учетные данные контакта в нашей системе."
 
-#: ../../mod/dfrn_confirm.php:725
+#: mod/dfrn_confirm.php:726
 msgid "Unable to update your contact profile details on our system"
 msgstr "Не удается обновить ваши контактные детали профиля в нашей системе"
 
-#: ../../mod/dfrn_confirm.php:752 ../../mod/dfrn_request.php:717
-#: ../../include/items.php:4008
+#: mod/dfrn_confirm.php:753 mod/dfrn_request.php:741 include/items.php:4299
 msgid "[Name Withheld]"
 msgstr "[Имя не разглашается]"
 
-#: ../../mod/dfrn_confirm.php:797
+#: mod/dfrn_confirm.php:798
 #, php-format
 msgid "%1$s has joined %2$s"
 msgstr "%1$s присоединился %2$s"
 
-#: ../../mod/profile.php:21 ../../boot.php:1458
+#: mod/profile.php:21 include/identity.php:51
 msgid "Requested profile is not available."
 msgstr "Запрашиваемый профиль недоступен."
 
-#: ../../mod/profile.php:180
+#: mod/profile.php:179
 msgid "Tips for New Members"
 msgstr "Советы для новых участников"
 
-#: ../../mod/videos.php:125
+#: mod/videos.php:123
+msgid "Do you really want to delete this video?"
+msgstr ""
+
+#: mod/videos.php:128
+msgid "Delete Video"
+msgstr "Удалить видео"
+
+#: mod/videos.php:207
 msgid "No videos selected"
 msgstr "Видео не выбрано"
 
-#: ../../mod/videos.php:226 ../../mod/photos.php:1031
+#: mod/videos.php:308 mod/photos.php:1087
 msgid "Access to this item is restricted."
 msgstr "Доступ к этому пункту ограничен."
 
-#: ../../mod/videos.php:301 ../../include/text.php:1405
+#: mod/videos.php:383 include/text.php:1472
 msgid "View Video"
 msgstr "Просмотреть видео"
 
-#: ../../mod/videos.php:308 ../../mod/photos.php:1808
+#: mod/videos.php:390 mod/photos.php:1890
 msgid "View Album"
 msgstr "Просмотреть альбом"
 
-#: ../../mod/videos.php:317
+#: mod/videos.php:399
 msgid "Recent Videos"
 msgstr "Последние видео"
 
-#: ../../mod/videos.php:319
+#: mod/videos.php:401
 msgid "Upload New Videos"
 msgstr "Загрузить новые видео"
 
-#: ../../mod/tagger.php:95 ../../include/conversation.php:266
+#: mod/tagger.php:95 include/conversation.php:278
 #, php-format
 msgid "%1$s tagged %2$s's %3$s with %4$s"
 msgstr "%1$s tagged %2$s's %3$s в %4$s"
 
-#: ../../mod/fsuggest.php:63
+#: mod/fsuggest.php:63
 msgid "Friend suggestion sent."
 msgstr "Приглашение в друзья отправлено."
 
-#: ../../mod/fsuggest.php:97
+#: mod/fsuggest.php:97
 msgid "Suggest Friends"
 msgstr "Предложить друзей"
 
-#: ../../mod/fsuggest.php:99
+#: mod/fsuggest.php:99
 #, php-format
 msgid "Suggest a friend for %s"
 msgstr "Предложить друга для %s."
 
-#: ../../mod/lostpass.php:19
+#: mod/wall_upload.php:20 mod/wall_upload.php:33 mod/wall_upload.php:86
+#: mod/wall_upload.php:122 mod/wall_upload.php:125 mod/wall_attach.php:17
+#: mod/wall_attach.php:25 mod/wall_attach.php:76 include/api.php:1781
+msgid "Invalid request."
+msgstr "Неверный запрос."
+
+#: mod/lostpass.php:19
 msgid "No valid account found."
 msgstr "Не найдено действительного аккаунта."
 
-#: ../../mod/lostpass.php:35
+#: mod/lostpass.php:35
 msgid "Password reset request issued. Check your email."
 msgstr "Запрос на сброс пароля принят. Проверьте вашу электронную почту."
 
-#: ../../mod/lostpass.php:42
+#: mod/lostpass.php:42
 #, php-format
 msgid ""
 "\n"
 "\t\tDear %1$s,\n"
 "\t\t\tA request was recently received at \"%2$s\" to reset your account\n"
-"\t\tpassword. In order to confirm this request, please select the verification link\n"
+"\t\tpassword. In order to confirm this request, please select the "
+"verification link\n"
 "\t\tbelow or paste it into your web browser address bar.\n"
 "\n"
 "\t\tIf you did NOT request this change, please DO NOT follow the link\n"
@@ -1169,7 +1336,7 @@ msgid ""
 "\t\tissued this request."
 msgstr ""
 
-#: ../../mod/lostpass.php:53
+#: mod/lostpass.php:53
 #, php-format
 msgid ""
 "\n"
@@ -1178,7 +1345,8 @@ msgid ""
 "\t\t%1$s\n"
 "\n"
 "\t\tYou will then receive a follow-up message containing the new password.\n"
-"\t\tYou may change that password from your account settings page after logging in.\n"
+"\t\tYou may change that password from your account settings page after "
+"logging in.\n"
 "\n"
 "\t\tThe login details are as follows:\n"
 "\n"
@@ -1186,55 +1354,60 @@ msgid ""
 "\t\tLogin Name:\t%3$s"
 msgstr ""
 
-#: ../../mod/lostpass.php:72
+#: mod/lostpass.php:72
 #, php-format
 msgid "Password reset requested at %s"
 msgstr "Запрос на сброс пароля получен %s"
 
-#: ../../mod/lostpass.php:92
+#: mod/lostpass.php:92
 msgid ""
 "Request could not be verified. (You may have previously submitted it.) "
 "Password reset failed."
-msgstr "Запрос не может быть проверен. (Вы, возможно, ранее представляли его.) Попытка сброса пароля неудачная."
+msgstr ""
+"Запрос не может быть проверен. (Вы, возможно, ранее представляли его.) "
+"Попытка сброса пароля неудачная."
 
-#: ../../mod/lostpass.php:109 ../../boot.php:1280
+#: mod/lostpass.php:109 boot.php:1444
 msgid "Password Reset"
 msgstr "Сброс пароля"
 
-#: ../../mod/lostpass.php:110
+#: mod/lostpass.php:110
 msgid "Your password has been reset as requested."
 msgstr "Ваш пароль был сброшен по требованию."
 
-#: ../../mod/lostpass.php:111
+#: mod/lostpass.php:111
 msgid "Your new password is"
 msgstr "Ваш новый пароль"
 
-#: ../../mod/lostpass.php:112
+#: mod/lostpass.php:112
 msgid "Save or copy your new password - and then"
 msgstr "Сохраните или скопируйте новый пароль - и затем"
 
-#: ../../mod/lostpass.php:113
+#: mod/lostpass.php:113
 msgid "click here to login"
 msgstr "нажмите здесь для входа"
 
-#: ../../mod/lostpass.php:114
+#: mod/lostpass.php:114
 msgid ""
 "Your password may be changed from the <em>Settings</em> page after "
 "successful login."
-msgstr "Ваш пароль может быть изменен на странице <em>Настройки</em> после успешного входа."
+msgstr ""
+"Ваш пароль может быть изменен на странице <em>Настройки</em> после успешного "
+"входа."
 
-#: ../../mod/lostpass.php:125
+#: mod/lostpass.php:125
 #, php-format
 msgid ""
 "\n"
 "\t\t\t\tDear %1$s,\n"
 "\t\t\t\t\tYour password has been changed as requested. Please retain this\n"
-"\t\t\t\tinformation for your records (or change your password immediately to\n"
+"\t\t\t\tinformation for your records (or change your password immediately "
+"to\n"
 "\t\t\t\tsomething that you will remember).\n"
 "\t\t\t"
 msgstr ""
 
-#: ../../mod/lostpass.php:131
+#: mod/lostpass.php:131
 #, php-format
 msgid ""
 "\n"
@@ -1244,1379 +1417,1693 @@ msgid ""
 "\t\t\t\tLogin Name:\t%2$s\n"
 "\t\t\t\tPassword:\t%3$s\n"
 "\n"
-"\t\t\t\tYou may change that password from your account settings page after logging in.\n"
+"\t\t\t\tYou may change that password from your account settings page after "
+"logging in.\n"
 "\t\t\t"
 msgstr ""
 
-#: ../../mod/lostpass.php:147
+#: mod/lostpass.php:147
 #, php-format
 msgid "Your password has been changed at %s"
 msgstr "Ваш пароль был изменен %s"
 
-#: ../../mod/lostpass.php:159
+#: mod/lostpass.php:159
 msgid "Forgot your Password?"
 msgstr "Забыли пароль?"
 
-#: ../../mod/lostpass.php:160
+#: mod/lostpass.php:160
 msgid ""
 "Enter your email address and submit to have your password reset. Then check "
 "your email for further instructions."
-msgstr "Введите адрес электронной почты и подтвердите, что вы хотите сбросить ваш пароль. Затем проверьте свою электронную почту для получения дальнейших инструкций."
+msgstr ""
+"Введите адрес электронной почты и подтвердите, что вы хотите сбросить ваш "
+"пароль. Затем проверьте свою электронную почту для получения дальнейших "
+"инструкций."
 
-#: ../../mod/lostpass.php:161
+#: mod/lostpass.php:161
 msgid "Nickname or Email: "
 msgstr "Ник или E-mail: "
 
-#: ../../mod/lostpass.php:162
+#: mod/lostpass.php:162
 msgid "Reset"
 msgstr "Сброс"
 
-#: ../../mod/like.php:166 ../../include/conversation.php:137
-#: ../../include/diaspora.php:2103 ../../view/theme/diabook/theme.php:480
-#, php-format
-msgid "%1$s likes %2$s's %3$s"
-msgstr "%1$s нравится %3$s от %2$s "
-
-#: ../../mod/like.php:168 ../../include/conversation.php:140
-#, php-format
-msgid "%1$s doesn't like %2$s's %3$s"
-msgstr "%1$s не нравится %3$s от %2$s "
-
-#: ../../mod/ping.php:240
+#: mod/ping.php:265
 msgid "{0} wants to be your friend"
 msgstr "{0} хочет стать Вашим другом"
 
-#: ../../mod/ping.php:245
+#: mod/ping.php:280
 msgid "{0} sent you a message"
 msgstr "{0} отправил Вам сообщение"
 
-#: ../../mod/ping.php:250
+#: mod/ping.php:295
 msgid "{0} requested registration"
 msgstr "{0} требуемая регистрация"
 
-#: ../../mod/ping.php:256
-#, php-format
-msgid "{0} commented %s's post"
-msgstr "{0} прокомментировал сообщение от %s"
-
-#: ../../mod/ping.php:261
-#, php-format
-msgid "{0} liked %s's post"
-msgstr "{0} нравится сообщение от %s"
-
-#: ../../mod/ping.php:266
-#, php-format
-msgid "{0} disliked %s's post"
-msgstr "{0} не нравится сообщение от %s"
-
-#: ../../mod/ping.php:271
-#, php-format
-msgid "{0} is now friends with %s"
-msgstr "{0} теперь друзья с %s"
-
-#: ../../mod/ping.php:276
-msgid "{0} posted"
-msgstr "{0} опубликовано"
-
-#: ../../mod/ping.php:281
-#, php-format
-msgid "{0} tagged %s's post with #%s"
-msgstr "{0} пометил сообщение %s с #%s"
-
-#: ../../mod/ping.php:287
-msgid "{0} mentioned you in a post"
-msgstr "{0} упоменул Вас в сообщение"
-
-#: ../../mod/viewcontacts.php:41
+#: mod/viewcontacts.php:72
 msgid "No contacts."
 msgstr "Нет контактов."
 
-#: ../../mod/viewcontacts.php:78 ../../include/text.php:876
-msgid "View Contacts"
-msgstr "Просмотр контактов"
-
-#: ../../mod/notifications.php:26
+#: mod/notifications.php:29
 msgid "Invalid request identifier."
 msgstr "Неверный идентификатор запроса."
 
-#: ../../mod/notifications.php:35 ../../mod/notifications.php:165
-#: ../../mod/notifications.php:211
+#: mod/notifications.php:38 mod/notifications.php:180
+#: mod/notifications.php:260
 msgid "Discard"
 msgstr "Отказаться"
 
-#: ../../mod/notifications.php:78
+#: mod/notifications.php:81
 msgid "System"
 msgstr "Система"
 
-#: ../../mod/notifications.php:83 ../../include/nav.php:145
+#: mod/notifications.php:87 mod/admin.php:390 include/nav.php:154
 msgid "Network"
-msgstr "Сеть"
+msgstr "Новости"
 
-#: ../../mod/notifications.php:88 ../../mod/network.php:371
+#: mod/notifications.php:93 mod/network.php:384
 msgid "Personal"
 msgstr "Персонал"
 
-#: ../../mod/notifications.php:93 ../../include/nav.php:105
-#: ../../include/nav.php:148 ../../view/theme/diabook/theme.php:123
+#: mod/notifications.php:99 include/nav.php:104 include/nav.php:157
+#: view/theme/diabook/theme.php:123
 msgid "Home"
-msgstr "Главная"
+msgstr "Мой профиль"
 
-#: ../../mod/notifications.php:98 ../../include/nav.php:154
+#: mod/notifications.php:105 include/nav.php:162
 msgid "Introductions"
 msgstr "Запросы"
 
-#: ../../mod/notifications.php:122
+#: mod/notifications.php:130
 msgid "Show Ignored Requests"
 msgstr "Показать проигнорированные запросы"
 
-#: ../../mod/notifications.php:122
+#: mod/notifications.php:130
 msgid "Hide Ignored Requests"
 msgstr "Скрыть проигнорированные запросы"
 
-#: ../../mod/notifications.php:149 ../../mod/notifications.php:195
+#: mod/notifications.php:164 mod/notifications.php:234
 msgid "Notification type: "
 msgstr "Тип уведомления: "
 
-#: ../../mod/notifications.php:150
+#: mod/notifications.php:165
 msgid "Friend Suggestion"
 msgstr "Предложение в друзья"
 
-#: ../../mod/notifications.php:152
+#: mod/notifications.php:167
 #, php-format
 msgid "suggested by %s"
 msgstr "предложено юзером %s"
 
-#: ../../mod/notifications.php:158 ../../mod/notifications.php:205
+#: mod/notifications.php:173 mod/notifications.php:252
 msgid "Post a new friend activity"
 msgstr "Настроение"
 
-#: ../../mod/notifications.php:158 ../../mod/notifications.php:205
+#: mod/notifications.php:173 mod/notifications.php:252
 msgid "if applicable"
 msgstr "если требуется"
 
-#: ../../mod/notifications.php:161 ../../mod/notifications.php:208
-#: ../../mod/admin.php:1005
+#: mod/notifications.php:176 mod/notifications.php:257 mod/admin.php:1308
 msgid "Approve"
 msgstr "Одобрить"
 
-#: ../../mod/notifications.php:181
+#: mod/notifications.php:196
 msgid "Claims to be known to you: "
 msgstr "Утверждения, о которых должно быть вам известно: "
 
-#: ../../mod/notifications.php:181
+#: mod/notifications.php:196
 msgid "yes"
 msgstr "да"
 
-#: ../../mod/notifications.php:181
+#: mod/notifications.php:196
 msgid "no"
 msgstr "нет"
 
-#: ../../mod/notifications.php:188
-msgid "Approve as: "
-msgstr "Утвердить как: "
+#: mod/notifications.php:197
+msgid ""
+"Shall your connection be bidirectional or not? \"Friend\" implies that you "
+"allow to read and you subscribe to their posts. \"Fan/Admirer\" means that "
+"you allow to read but you do not want to read theirs. Approve as: "
+msgstr ""
 
-#: ../../mod/notifications.php:189
+#: mod/notifications.php:200
+msgid ""
+"Shall your connection be bidirectional or not? \"Friend\" implies that you "
+"allow to read and you subscribe to their posts. \"Sharer\" means that you "
+"allow to read but you do not want to read theirs. Approve as: "
+msgstr ""
+
+#: mod/notifications.php:208
 msgid "Friend"
 msgstr "Друг"
 
-#: ../../mod/notifications.php:190
+#: mod/notifications.php:209
 msgid "Sharer"
 msgstr "Участник"
 
-#: ../../mod/notifications.php:190
+#: mod/notifications.php:209
 msgid "Fan/Admirer"
 msgstr "Фанат / Поклонник"
 
-#: ../../mod/notifications.php:196
+#: mod/notifications.php:235
 msgid "Friend/Connect Request"
 msgstr "Запрос в друзья / на подключение"
 
-#: ../../mod/notifications.php:196
+#: mod/notifications.php:235
 msgid "New Follower"
 msgstr "Новый фолловер"
 
-#: ../../mod/notifications.php:217
+#: mod/notifications.php:250 mod/directory.php:147 include/identity.php:310
+#: include/identity.php:590
+msgid "Gender:"
+msgstr "Пол:"
+
+#: mod/notifications.php:266
 msgid "No introductions."
 msgstr "Запросов нет."
 
-#: ../../mod/notifications.php:220 ../../include/nav.php:155
+#: mod/notifications.php:269 include/nav.php:165
 msgid "Notifications"
 msgstr "Уведомления"
 
-#: ../../mod/notifications.php:258 ../../mod/notifications.php:387
-#: ../../mod/notifications.php:478
+#: mod/notifications.php:307 mod/notifications.php:436
+#: mod/notifications.php:527
 #, php-format
 msgid "%s liked %s's post"
 msgstr "%s нравится %s сообшение"
 
-#: ../../mod/notifications.php:268 ../../mod/notifications.php:397
-#: ../../mod/notifications.php:488
+#: mod/notifications.php:317 mod/notifications.php:446
+#: mod/notifications.php:537
 #, php-format
 msgid "%s disliked %s's post"
 msgstr "%s не нравится %s сообшение"
 
-#: ../../mod/notifications.php:283 ../../mod/notifications.php:412
-#: ../../mod/notifications.php:503
+#: mod/notifications.php:332 mod/notifications.php:461
+#: mod/notifications.php:552
 #, php-format
 msgid "%s is now friends with %s"
 msgstr "%s теперь друзья с %s"
 
-#: ../../mod/notifications.php:290 ../../mod/notifications.php:419
+#: mod/notifications.php:339 mod/notifications.php:468
 #, php-format
 msgid "%s created a new post"
 msgstr "%s написал новое сообщение"
 
-#: ../../mod/notifications.php:291 ../../mod/notifications.php:420
-#: ../../mod/notifications.php:513
+#: mod/notifications.php:340 mod/notifications.php:469
+#: mod/notifications.php:562
 #, php-format
 msgid "%s commented on %s's post"
 msgstr "%s прокомментировал %s сообщение"
 
-#: ../../mod/notifications.php:306
+#: mod/notifications.php:355
 msgid "No more network notifications."
 msgstr "Уведомлений из сети больше нет."
 
-#: ../../mod/notifications.php:310
+#: mod/notifications.php:359
 msgid "Network Notifications"
 msgstr "Уведомления сети"
 
-#: ../../mod/notifications.php:336 ../../mod/notify.php:75
+#: mod/notifications.php:385 mod/notify.php:72
 msgid "No more system notifications."
 msgstr "Системных уведомлений больше нет."
 
-#: ../../mod/notifications.php:340 ../../mod/notify.php:79
+#: mod/notifications.php:389 mod/notify.php:76
 msgid "System Notifications"
 msgstr "Уведомления системы"
 
-#: ../../mod/notifications.php:435
+#: mod/notifications.php:484
 msgid "No more personal notifications."
 msgstr "Персональных уведомлений больше нет."
 
-#: ../../mod/notifications.php:439
+#: mod/notifications.php:488
 msgid "Personal Notifications"
 msgstr "Личные уведомления"
 
-#: ../../mod/notifications.php:520
+#: mod/notifications.php:569
 msgid "No more home notifications."
 msgstr "Уведомлений больше нет."
 
-#: ../../mod/notifications.php:524
+#: mod/notifications.php:573
 msgid "Home Notifications"
 msgstr "Уведомления"
 
-#: ../../mod/babel.php:17
+#: mod/babel.php:17
 msgid "Source (bbcode) text:"
 msgstr "Код (bbcode):"
 
-#: ../../mod/babel.php:23
+#: mod/babel.php:23
 msgid "Source (Diaspora) text to convert to BBcode:"
 msgstr "Код (Diaspora) для конвертации в BBcode:"
 
-#: ../../mod/babel.php:31
+#: mod/babel.php:31
 msgid "Source input: "
 msgstr "Ввести код:"
 
-#: ../../mod/babel.php:35
+#: mod/babel.php:35
 msgid "bb2html (raw HTML): "
 msgstr "bb2html (raw HTML): "
 
-#: ../../mod/babel.php:39
+#: mod/babel.php:39
 msgid "bb2html: "
 msgstr "bb2html: "
 
-#: ../../mod/babel.php:43
+#: mod/babel.php:43
 msgid "bb2html2bb: "
 msgstr "bb2html2bb: "
 
-#: ../../mod/babel.php:47
+#: mod/babel.php:47
 msgid "bb2md: "
 msgstr "bb2md: "
 
-#: ../../mod/babel.php:51
+#: mod/babel.php:51
 msgid "bb2md2html: "
 msgstr "bb2md2html: "
 
-#: ../../mod/babel.php:55
+#: mod/babel.php:55
 msgid "bb2dia2bb: "
 msgstr "bb2dia2bb: "
 
-#: ../../mod/babel.php:59
+#: mod/babel.php:59
 msgid "bb2md2html2bb: "
 msgstr "bb2md2html2bb: "
 
-#: ../../mod/babel.php:69
+#: mod/babel.php:69
 msgid "Source input (Diaspora format): "
 msgstr "Ввод кода (формат Diaspora):"
 
-#: ../../mod/babel.php:74
+#: mod/babel.php:74
 msgid "diaspora2bb: "
 msgstr "diaspora2bb: "
 
-#: ../../mod/navigation.php:20 ../../include/nav.php:34
+#: mod/navigation.php:19 include/nav.php:33
 msgid "Nothing new here"
 msgstr "Ничего нового здесь"
 
-#: ../../mod/navigation.php:24 ../../include/nav.php:38
+#: mod/navigation.php:23 include/nav.php:37
 msgid "Clear notifications"
 msgstr "Стереть уведомления"
 
-#: ../../mod/message.php:9 ../../include/nav.php:164
+#: mod/message.php:15 include/nav.php:174
 msgid "New Message"
 msgstr "Новое сообщение"
 
-#: ../../mod/message.php:63 ../../mod/wallmessage.php:56
+#: mod/message.php:70 mod/wallmessage.php:56
 msgid "No recipient selected."
 msgstr "Не выбран получатель."
 
-#: ../../mod/message.php:67
+#: mod/message.php:74
 msgid "Unable to locate contact information."
 msgstr "Не удалось найти контактную информацию."
 
-#: ../../mod/message.php:70 ../../mod/wallmessage.php:62
+#: mod/message.php:77 mod/wallmessage.php:62
 msgid "Message could not be sent."
 msgstr "Сообщение не может быть отправлено."
 
-#: ../../mod/message.php:73 ../../mod/wallmessage.php:65
+#: mod/message.php:80 mod/wallmessage.php:65
 msgid "Message collection failure."
 msgstr "Неудача коллекции сообщения."
 
-#: ../../mod/message.php:76 ../../mod/wallmessage.php:68
+#: mod/message.php:83 mod/wallmessage.php:68
 msgid "Message sent."
 msgstr "Сообщение отправлено."
 
-#: ../../mod/message.php:182 ../../include/nav.php:161
+#: mod/message.php:189 include/nav.php:171
 msgid "Messages"
 msgstr "Сообщения"
 
-#: ../../mod/message.php:207
+#: mod/message.php:214
 msgid "Do you really want to delete this message?"
 msgstr "Вы действительно хотите удалить это сообщение?"
 
-#: ../../mod/message.php:227
+#: mod/message.php:234
 msgid "Message deleted."
 msgstr "Сообщение удалено."
 
-#: ../../mod/message.php:258
+#: mod/message.php:265
 msgid "Conversation removed."
 msgstr "Беседа удалена."
 
-#: ../../mod/message.php:283 ../../mod/message.php:291
-#: ../../mod/message.php:466 ../../mod/message.php:474
-#: ../../mod/wallmessage.php:127 ../../mod/wallmessage.php:135
-#: ../../include/conversation.php:1002 ../../include/conversation.php:1020
+#: mod/message.php:290 mod/message.php:298 mod/message.php:427
+#: mod/message.php:435 mod/wallmessage.php:127 mod/wallmessage.php:135
+#: include/conversation.php:1128 include/conversation.php:1146
 msgid "Please enter a link URL:"
 msgstr "Пожалуйста, введите URL ссылки:"
 
-#: ../../mod/message.php:319 ../../mod/wallmessage.php:142
+#: mod/message.php:326 mod/wallmessage.php:142
 msgid "Send Private Message"
 msgstr "Отправить личное сообщение"
 
-#: ../../mod/message.php:320 ../../mod/message.php:553
-#: ../../mod/wallmessage.php:144
+#: mod/message.php:327 mod/message.php:514 mod/wallmessage.php:144
 msgid "To:"
 msgstr "Кому:"
 
-#: ../../mod/message.php:325 ../../mod/message.php:555
-#: ../../mod/wallmessage.php:145
+#: mod/message.php:332 mod/message.php:516 mod/wallmessage.php:145
 msgid "Subject:"
 msgstr "Тема:"
 
-#: ../../mod/message.php:329 ../../mod/message.php:558
-#: ../../mod/wallmessage.php:151 ../../mod/invite.php:134
+#: mod/message.php:336 mod/message.php:519 mod/wallmessage.php:151
+#: mod/invite.php:134
 msgid "Your message:"
 msgstr "Ваше сообщение:"
 
-#: ../../mod/message.php:332 ../../mod/message.php:562
-#: ../../mod/wallmessage.php:154 ../../mod/editpost.php:110
-#: ../../include/conversation.php:1091
+#: mod/message.php:339 mod/message.php:523 mod/wallmessage.php:154
+#: mod/editpost.php:110 include/conversation.php:1183
 msgid "Upload photo"
 msgstr "Загрузить фото"
 
-#: ../../mod/message.php:333 ../../mod/message.php:563
-#: ../../mod/wallmessage.php:155 ../../mod/editpost.php:114
-#: ../../include/conversation.php:1095
+#: mod/message.php:340 mod/message.php:524 mod/wallmessage.php:155
+#: mod/editpost.php:114 include/conversation.php:1187
 msgid "Insert web link"
 msgstr "Вставить веб-ссылку"
 
-#: ../../mod/message.php:334 ../../mod/message.php:565
-#: ../../mod/content.php:499 ../../mod/content.php:883
-#: ../../mod/wallmessage.php:156 ../../mod/editpost.php:124
-#: ../../mod/photos.php:1545 ../../object/Item.php:364
-#: ../../include/conversation.php:692 ../../include/conversation.php:1109
+#: mod/message.php:341 mod/message.php:526 mod/content.php:501
+#: mod/content.php:885 mod/wallmessage.php:156 mod/editpost.php:124
+#: mod/photos.php:1610 object/Item.php:396 include/conversation.php:713
+#: include/conversation.php:1201
 msgid "Please wait"
 msgstr "Пожалуйста, подождите"
 
-#: ../../mod/message.php:371
+#: mod/message.php:368
 msgid "No messages."
 msgstr "Нет сообщений."
 
-#: ../../mod/message.php:378
+#: mod/message.php:411
+msgid "Message not available."
+msgstr "Сообщение не доступно."
+
+#: mod/message.php:481
+msgid "Delete message"
+msgstr "Удалить сообщение"
+
+#: mod/message.php:507 mod/message.php:584
+msgid "Delete conversation"
+msgstr "Удалить историю общения"
+
+#: mod/message.php:509
+msgid ""
+"No secure communications available. You <strong>may</strong> be able to "
+"respond from the sender's profile page."
+msgstr ""
+"Невозможно защищённое соединение. Вы <strong>имеете</strong> возможность "
+"ответить со страницы профиля отправителя."
+
+#: mod/message.php:513
+msgid "Send Reply"
+msgstr "Отправить ответ"
+
+#: mod/message.php:557
 #, php-format
 msgid "Unknown sender - %s"
 msgstr "Неизвестный отправитель - %s"
 
-#: ../../mod/message.php:381
+#: mod/message.php:560
 #, php-format
 msgid "You and %s"
 msgstr "Вы и %s"
 
-#: ../../mod/message.php:384
+#: mod/message.php:563
 #, php-format
 msgid "%s and You"
 msgstr "%s и Вы"
 
-#: ../../mod/message.php:405 ../../mod/message.php:546
-msgid "Delete conversation"
-msgstr "Удалить историю общения"
-
-#: ../../mod/message.php:408
+#: mod/message.php:587
 msgid "D, d M Y - g:i A"
 msgstr "D, d M Y - g:i A"
 
-#: ../../mod/message.php:411
+#: mod/message.php:590
 #, php-format
 msgid "%d message"
 msgid_plural "%d messages"
 msgstr[0] "%d сообщение"
 msgstr[1] "%d сообщений"
 msgstr[2] "%d сообщений"
+msgstr[3] "%d сообщений"
 
-#: ../../mod/message.php:450
-msgid "Message not available."
-msgstr "Сообщение не доступно."
-
-#: ../../mod/message.php:520
-msgid "Delete message"
-msgstr "Удалить сообщение"
-
-#: ../../mod/message.php:548
-msgid ""
-"No secure communications available. You <strong>may</strong> be able to "
-"respond from the sender's profile page."
-msgstr "Невозможно защищённое соединение. Вы <strong>имеете</strong> возможность ответить со страницы профиля отправителя."
-
-#: ../../mod/message.php:552
-msgid "Send Reply"
-msgstr "Отправить ответ"
-
-#: ../../mod/update_display.php:22 ../../mod/update_community.php:18
-#: ../../mod/update_notes.php:37 ../../mod/update_profile.php:41
-#: ../../mod/update_network.php:25
+#: mod/update_display.php:22 mod/update_community.php:18
+#: mod/update_notes.php:37 mod/update_profile.php:41 mod/update_network.php:25
 msgid "[Embedded content - reload page to view]"
 msgstr "[Встроенное содержание - перезагрузите страницу для просмотра]"
 
-#: ../../mod/crepair.php:106
+#: mod/crepair.php:104
 msgid "Contact settings applied."
 msgstr "Установки контакта приняты."
 
-#: ../../mod/crepair.php:108
+#: mod/crepair.php:106
 msgid "Contact update failed."
 msgstr "Обновление контакта неудачное."
 
-#: ../../mod/crepair.php:139
-msgid "Repair Contact Settings"
-msgstr "Восстановить установки контакта"
-
-#: ../../mod/crepair.php:141
+#: mod/crepair.php:137
 msgid ""
-"<strong>WARNING: This is highly advanced</strong> and if you enter incorrect"
-" information your communications with this contact may stop working."
-msgstr "<strong>ВНИМАНИЕ: Это крайне важно!</strong> Если вы введете неверную информацию, ваша связь с этим контактом перестанет работать."
+"<strong>WARNING: This is highly advanced</strong> and if you enter incorrect "
+"information your communications with this contact may stop working."
+msgstr ""
+"<strong>ВНИМАНИЕ: Это крайне важно!</strong> Если вы введете неверную "
+"информацию, ваша связь с этим контактом перестанет работать."
 
-#: ../../mod/crepair.php:142
+#: mod/crepair.php:138
 msgid ""
 "Please use your browser 'Back' button <strong>now</strong> if you are "
 "uncertain what to do on this page."
-msgstr "Пожалуйста, нажмите клавишу вашего браузера 'Back' или 'Назад' <strong>сейчас</strong>, если вы не уверены, что делаете на этой странице."
+msgstr ""
+"Пожалуйста, нажмите клавишу вашего браузера 'Back' или 'Назад' "
+"<strong>сейчас</strong>, если вы не уверены, что делаете на этой странице."
 
-#: ../../mod/crepair.php:148
-msgid "Return to contact editor"
-msgstr "Возврат к редактору контакта"
-
-#: ../../mod/crepair.php:159 ../../mod/crepair.php:161
+#: mod/crepair.php:151 mod/crepair.php:153
 msgid "No mirroring"
 msgstr ""
 
-#: ../../mod/crepair.php:159
+#: mod/crepair.php:151
 msgid "Mirror as forwarded posting"
 msgstr ""
 
-#: ../../mod/crepair.php:159 ../../mod/crepair.php:161
+#: mod/crepair.php:151 mod/crepair.php:153
 msgid "Mirror as my own posting"
 msgstr ""
 
-#: ../../mod/crepair.php:165 ../../mod/admin.php:1003 ../../mod/admin.php:1015
-#: ../../mod/admin.php:1016 ../../mod/admin.php:1029
-#: ../../mod/settings.php:616 ../../mod/settings.php:642
+#: mod/crepair.php:167
+msgid "Return to contact editor"
+msgstr "Возврат к редактору контакта"
+
+#: mod/crepair.php:169
+msgid "Refetch contact data"
+msgstr ""
+
+#: mod/crepair.php:170 mod/admin.php:1306 mod/admin.php:1318
+#: mod/admin.php:1319 mod/admin.php:1332 mod/settings.php:661
+#: mod/settings.php:687
 msgid "Name"
 msgstr "Имя"
 
-#: ../../mod/crepair.php:166
+#: mod/crepair.php:171
 msgid "Account Nickname"
 msgstr "Ник аккаунта"
 
-#: ../../mod/crepair.php:167
+#: mod/crepair.php:172
 msgid "@Tagname - overrides Name/Nickname"
 msgstr ""
 
-#: ../../mod/crepair.php:168
+#: mod/crepair.php:173
 msgid "Account URL"
 msgstr "URL аккаунта"
 
-#: ../../mod/crepair.php:169
+#: mod/crepair.php:174
 msgid "Friend Request URL"
 msgstr "URL запроса в друзья"
 
-#: ../../mod/crepair.php:170
+#: mod/crepair.php:175
 msgid "Friend Confirm URL"
 msgstr "URL подтверждения друга"
 
-#: ../../mod/crepair.php:171
+#: mod/crepair.php:176
 msgid "Notification Endpoint URL"
 msgstr "URL эндпоинта уведомления"
 
-#: ../../mod/crepair.php:172
+#: mod/crepair.php:177
 msgid "Poll/Feed URL"
 msgstr "URL опроса/ленты"
 
-#: ../../mod/crepair.php:173
+#: mod/crepair.php:178
 msgid "New photo from this URL"
 msgstr "Новое фото из этой URL"
 
-#: ../../mod/crepair.php:174
+#: mod/crepair.php:179
 msgid "Remote Self"
 msgstr ""
 
-#: ../../mod/crepair.php:176
+#: mod/crepair.php:182
 msgid "Mirror postings from this contact"
 msgstr ""
 
-#: ../../mod/crepair.php:176
+#: mod/crepair.php:184
 msgid ""
 "Mark this contact as remote_self, this will cause friendica to repost new "
 "entries from this contact."
 msgstr ""
 
-#: ../../mod/bookmarklet.php:12 ../../boot.php:1266 ../../include/nav.php:92
+#: mod/bookmarklet.php:12 boot.php:1430 include/nav.php:91
 msgid "Login"
 msgstr "Вход"
 
-#: ../../mod/bookmarklet.php:41
+#: mod/bookmarklet.php:41
 msgid "The post was created"
 msgstr ""
 
-#: ../../mod/viewsrc.php:7
+#: mod/viewsrc.php:7
 msgid "Access denied."
 msgstr "Доступ запрещен."
 
-#: ../../mod/dirfind.php:26
-msgid "People Search"
-msgstr "Поиск людей"
+#: mod/dirfind.php:194 mod/allfriends.php:80 mod/match.php:85
+#: mod/suggest.php:98 include/contact_widgets.php:10 include/identity.php:212
+msgid "Connect"
+msgstr "Подключить"
 
-#: ../../mod/dirfind.php:60 ../../mod/match.php:65
+#: mod/dirfind.php:195 mod/allfriends.php:64 mod/match.php:70
+#: mod/directory.php:162 mod/suggest.php:81 include/Contact.php:283
+#: include/Contact.php:296 include/Contact.php:338
+#: include/conversation.php:912 include/conversation.php:926
+msgid "View Profile"
+msgstr "Просмотреть профиль"
+
+#: mod/dirfind.php:224
+#, php-format
+msgid "People Search - %s"
+msgstr ""
+
+#: mod/dirfind.php:231 mod/match.php:105
 msgid "No matches"
 msgstr "Нет соответствий"
 
-#: ../../mod/fbrowser.php:25 ../../boot.php:2126 ../../include/nav.php:78
-#: ../../view/theme/diabook/theme.php:126
+#: mod/fbrowser.php:32 include/identity.php:702 include/nav.php:77
+#: view/theme/diabook/theme.php:126
 msgid "Photos"
 msgstr "Фото"
 
-#: ../../mod/fbrowser.php:113
+#: mod/fbrowser.php:41 mod/fbrowser.php:62 mod/photos.php:62
+#: mod/photos.php:192 mod/photos.php:1119 mod/photos.php:1245
+#: mod/photos.php:1268 mod/photos.php:1838 mod/photos.php:1850
+#: view/theme/diabook/theme.php:499
+msgid "Contact Photos"
+msgstr "Фотографии контакта"
+
+#: mod/fbrowser.php:125
 msgid "Files"
 msgstr "Файлы"
 
-#: ../../mod/nogroup.php:59
+#: mod/nogroup.php:63
 msgid "Contacts who are not members of a group"
 msgstr "Контакты, которые не являются членами группы"
 
-#: ../../mod/admin.php:57
+#: mod/admin.php:92
 msgid "Theme settings updated."
 msgstr "Настройки темы обновлены."
 
-#: ../../mod/admin.php:104 ../../mod/admin.php:619
+#: mod/admin.php:156 mod/admin.php:888
 msgid "Site"
 msgstr "Сайт"
 
-#: ../../mod/admin.php:105 ../../mod/admin.php:998 ../../mod/admin.php:1013
+#: mod/admin.php:157 mod/admin.php:832 mod/admin.php:1301 mod/admin.php:1316
 msgid "Users"
 msgstr "Пользователи"
 
-#: ../../mod/admin.php:106 ../../mod/admin.php:1102 ../../mod/admin.php:1155
-#: ../../mod/settings.php:57
+#: mod/admin.php:158 mod/admin.php:1416 mod/admin.php:1476 mod/settings.php:72
 msgid "Plugins"
 msgstr "Плагины"
 
-#: ../../mod/admin.php:107 ../../mod/admin.php:1323 ../../mod/admin.php:1357
+#: mod/admin.php:159 mod/admin.php:1674 mod/admin.php:1724
 msgid "Themes"
 msgstr "Темы"
 
-#: ../../mod/admin.php:108
+#: mod/admin.php:160 mod/settings.php:50
+msgid "Additional features"
+msgstr "Дополнительные возможности"
+
+#: mod/admin.php:161
 msgid "DB updates"
 msgstr "Обновление БД"
 
-#: ../../mod/admin.php:123 ../../mod/admin.php:132 ../../mod/admin.php:1444
+#: mod/admin.php:162 mod/admin.php:385
+msgid "Inspect Queue"
+msgstr ""
+
+#: mod/admin.php:163 mod/admin.php:354
+msgid "Federation Statistics"
+msgstr ""
+
+#: mod/admin.php:177 mod/admin.php:188 mod/admin.php:1792
 msgid "Logs"
 msgstr "Журналы"
 
-#: ../../mod/admin.php:124
+#: mod/admin.php:178 mod/admin.php:1859
+msgid "View Logs"
+msgstr "Просмотр логов"
+
+#: mod/admin.php:179
 msgid "probe address"
 msgstr ""
 
-#: ../../mod/admin.php:125
+#: mod/admin.php:180
 msgid "check webfinger"
 msgstr ""
 
-#: ../../mod/admin.php:130 ../../include/nav.php:184
+#: mod/admin.php:186 include/nav.php:194
 msgid "Admin"
 msgstr "Администратор"
 
-#: ../../mod/admin.php:131
+#: mod/admin.php:187
 msgid "Plugin Features"
 msgstr "Возможности плагина"
 
-#: ../../mod/admin.php:133
+#: mod/admin.php:189
 msgid "diagnostics"
-msgstr ""
+msgstr "Диагностика"
 
-#: ../../mod/admin.php:134
+#: mod/admin.php:190
 msgid "User registrations waiting for confirmation"
 msgstr "Регистрации пользователей, ожидающие подтверждения"
 
-#: ../../mod/admin.php:193 ../../mod/admin.php:952
-msgid "Normal Account"
-msgstr "Обычный аккаунт"
+#: mod/admin.php:347
+msgid ""
+"This page offers you some numbers to the known part of the federated social "
+"network your Friendica node is part of. These numbers are not complete but "
+"only reflect the part of the network your node is aware of."
+msgstr ""
 
-#: ../../mod/admin.php:194 ../../mod/admin.php:953
-msgid "Soapbox Account"
-msgstr "Аккаунт Витрина"
+#: mod/admin.php:348
+msgid ""
+"The <em>Auto Discovered Contact Directory</em> feature is not enabled, it "
+"will improve the data displayed here."
+msgstr ""
 
-#: ../../mod/admin.php:195 ../../mod/admin.php:954
-msgid "Community/Celebrity Account"
-msgstr "Аккаунт Сообщество / Знаменитость"
-
-#: ../../mod/admin.php:196 ../../mod/admin.php:955
-msgid "Automatic Friend Account"
-msgstr "\"Автоматический друг\" Аккаунт"
-
-#: ../../mod/admin.php:197
-msgid "Blog Account"
-msgstr "Аккаунт блога"
-
-#: ../../mod/admin.php:198
-msgid "Private Forum"
-msgstr "Личный форум"
-
-#: ../../mod/admin.php:217
-msgid "Message queues"
-msgstr "Очереди сообщений"
-
-#: ../../mod/admin.php:222 ../../mod/admin.php:618 ../../mod/admin.php:997
-#: ../../mod/admin.php:1101 ../../mod/admin.php:1154 ../../mod/admin.php:1322
-#: ../../mod/admin.php:1356 ../../mod/admin.php:1443
+#: mod/admin.php:353 mod/admin.php:384 mod/admin.php:441 mod/admin.php:887
+#: mod/admin.php:1300 mod/admin.php:1415 mod/admin.php:1475 mod/admin.php:1673
+#: mod/admin.php:1723 mod/admin.php:1791 mod/admin.php:1858
 msgid "Administration"
 msgstr "Администрация"
 
-#: ../../mod/admin.php:223
+#: mod/admin.php:360
+#, php-format
+msgid "Currently this node is aware of %d nodes from the following platforms:"
+msgstr ""
+
+#: mod/admin.php:387
+msgid "ID"
+msgstr ""
+
+#: mod/admin.php:388
+msgid "Recipient Name"
+msgstr ""
+
+#: mod/admin.php:389
+msgid "Recipient Profile"
+msgstr ""
+
+#: mod/admin.php:391
+msgid "Created"
+msgstr ""
+
+#: mod/admin.php:392
+msgid "Last Tried"
+msgstr ""
+
+#: mod/admin.php:393
+msgid ""
+"This page lists the content of the queue for outgoing postings. These are "
+"postings the initial delivery failed for. They will be resend later and "
+"eventually deleted if the delivery fails permanently."
+msgstr ""
+
+#: mod/admin.php:412 mod/admin.php:1254
+msgid "Normal Account"
+msgstr "Обычный аккаунт"
+
+#: mod/admin.php:413 mod/admin.php:1255
+msgid "Soapbox Account"
+msgstr "Аккаунт Витрина"
+
+#: mod/admin.php:414 mod/admin.php:1256
+msgid "Community/Celebrity Account"
+msgstr "Аккаунт Сообщество / Знаменитость"
+
+#: mod/admin.php:415 mod/admin.php:1257
+msgid "Automatic Friend Account"
+msgstr "\"Автоматический друг\" Аккаунт"
+
+#: mod/admin.php:416
+msgid "Blog Account"
+msgstr "Аккаунт блога"
+
+#: mod/admin.php:417
+msgid "Private Forum"
+msgstr "Личный форум"
+
+#: mod/admin.php:436
+msgid "Message queues"
+msgstr "Очереди сообщений"
+
+#: mod/admin.php:442
 msgid "Summary"
 msgstr "Резюме"
 
-#: ../../mod/admin.php:225
+#: mod/admin.php:444
 msgid "Registered users"
 msgstr "Зарегистрированные пользователи"
 
-#: ../../mod/admin.php:227
+#: mod/admin.php:446
 msgid "Pending registrations"
 msgstr "Ожидающие регистрации"
 
-#: ../../mod/admin.php:228
+#: mod/admin.php:447
 msgid "Version"
 msgstr "Версия"
 
-#: ../../mod/admin.php:232
+#: mod/admin.php:452
 msgid "Active plugins"
 msgstr "Активные плагины"
 
-#: ../../mod/admin.php:255
+#: mod/admin.php:475
 msgid "Can not parse base url. Must have at least <scheme>://<domain>"
-msgstr "Невозможно определить базовый URL. Он должен иметь следующий вид - <scheme>://<domain>"
+msgstr ""
+"Невозможно определить базовый URL. Он должен иметь следующий вид - "
+"<scheme>://<domain>"
 
-#: ../../mod/admin.php:516
+#: mod/admin.php:760
+msgid "RINO2 needs mcrypt php extension to work."
+msgstr "Для функционирования RINO2 необходим пакет php5-mcrypt"
+
+#: mod/admin.php:768
 msgid "Site settings updated."
 msgstr "Установки сайта обновлены."
 
-#: ../../mod/admin.php:545 ../../mod/settings.php:828
+#: mod/admin.php:796 mod/settings.php:912
 msgid "No special theme for mobile devices"
 msgstr "Нет специальной темы для мобильных устройств"
 
-#: ../../mod/admin.php:562
+#: mod/admin.php:815
 msgid "No community page"
 msgstr ""
 
-#: ../../mod/admin.php:563
+#: mod/admin.php:816
 msgid "Public postings from users of this site"
 msgstr ""
 
-#: ../../mod/admin.php:564
+#: mod/admin.php:817
 msgid "Global community page"
 msgstr ""
 
-#: ../../mod/admin.php:570
+#: mod/admin.php:823
 msgid "At post arrival"
 msgstr ""
 
-#: ../../mod/admin.php:571 ../../include/contact_selectors.php:56
+#: mod/admin.php:824 include/contact_selectors.php:56
 msgid "Frequently"
 msgstr "Часто"
 
-#: ../../mod/admin.php:572 ../../include/contact_selectors.php:57
+#: mod/admin.php:825 include/contact_selectors.php:57
 msgid "Hourly"
 msgstr "Раз в час"
 
-#: ../../mod/admin.php:573 ../../include/contact_selectors.php:58
+#: mod/admin.php:826 include/contact_selectors.php:58
 msgid "Twice daily"
 msgstr "Два раза в день"
 
-#: ../../mod/admin.php:574 ../../include/contact_selectors.php:59
+#: mod/admin.php:827 include/contact_selectors.php:59
 msgid "Daily"
 msgstr "Ежедневно"
 
-#: ../../mod/admin.php:579
+#: mod/admin.php:833
+msgid "Users, Global Contacts"
+msgstr ""
+
+#: mod/admin.php:834
+msgid "Users, Global Contacts/fallback"
+msgstr ""
+
+#: mod/admin.php:838
+msgid "One month"
+msgstr "Один месяц"
+
+#: mod/admin.php:839
+msgid "Three months"
+msgstr "Три месяца"
+
+#: mod/admin.php:840
+msgid "Half a year"
+msgstr "Пол года"
+
+#: mod/admin.php:841
+msgid "One year"
+msgstr "Один год"
+
+#: mod/admin.php:846
 msgid "Multi user instance"
 msgstr "Многопользовательский вид"
 
-#: ../../mod/admin.php:602
+#: mod/admin.php:869
 msgid "Closed"
 msgstr "Закрыто"
 
-#: ../../mod/admin.php:603
+#: mod/admin.php:870
 msgid "Requires approval"
 msgstr "Требуется подтверждение"
 
-#: ../../mod/admin.php:604
+#: mod/admin.php:871
 msgid "Open"
 msgstr "Открыто"
 
-#: ../../mod/admin.php:608
+#: mod/admin.php:875
 msgid "No SSL policy, links will track page SSL state"
 msgstr "Нет режима SSL, состояние SSL не будет отслеживаться"
 
-#: ../../mod/admin.php:609
+#: mod/admin.php:876
 msgid "Force all links to use SSL"
 msgstr "Заставить все ссылки использовать SSL"
 
-#: ../../mod/admin.php:610
+#: mod/admin.php:877
 msgid "Self-signed certificate, use SSL for local links only (discouraged)"
-msgstr "Само-подписанный сертификат, использовать SSL только локально (не рекомендуется)"
+msgstr ""
+"Само-подписанный сертификат, использовать SSL только локально (не "
+"рекомендуется)"
 
-#: ../../mod/admin.php:620 ../../mod/admin.php:1156 ../../mod/admin.php:1358
-#: ../../mod/admin.php:1445 ../../mod/settings.php:614
-#: ../../mod/settings.php:724 ../../mod/settings.php:798
-#: ../../mod/settings.php:880 ../../mod/settings.php:1113
+#: mod/admin.php:889 mod/admin.php:1477 mod/admin.php:1725 mod/admin.php:1793
+#: mod/admin.php:1942 mod/settings.php:659 mod/settings.php:769
+#: mod/settings.php:813 mod/settings.php:882 mod/settings.php:969
+#: mod/settings.php:1204
 msgid "Save Settings"
 msgstr "Сохранить настройки"
 
-#: ../../mod/admin.php:621 ../../mod/register.php:255
+#: mod/admin.php:890 mod/register.php:263
 msgid "Registration"
 msgstr "Регистрация"
 
-#: ../../mod/admin.php:622
+#: mod/admin.php:891
 msgid "File upload"
 msgstr "Загрузка файлов"
 
-#: ../../mod/admin.php:623
+#: mod/admin.php:892
 msgid "Policies"
 msgstr "Политики"
 
-#: ../../mod/admin.php:624
+#: mod/admin.php:893
 msgid "Advanced"
 msgstr "Расширенный"
 
-#: ../../mod/admin.php:625
+#: mod/admin.php:894
+msgid "Auto Discovered Contact Directory"
+msgstr ""
+
+#: mod/admin.php:895
 msgid "Performance"
 msgstr "Производительность"
 
-#: ../../mod/admin.php:626
+#: mod/admin.php:896
 msgid ""
 "Relocate - WARNING: advanced function. Could make this server unreachable."
-msgstr "Переместить - ПРЕДУПРЕЖДЕНИЕ: расширеная функция. Может сделать этот сервер недоступным."
+msgstr ""
+"Переместить - ПРЕДУПРЕЖДЕНИЕ: расширеная функция. Может сделать этот сервер "
+"недоступным."
 
-#: ../../mod/admin.php:629
+#: mod/admin.php:899
 msgid "Site name"
 msgstr "Название сайта"
 
-#: ../../mod/admin.php:630
+#: mod/admin.php:900
 msgid "Host name"
-msgstr ""
+msgstr "Имя хоста"
 
-#: ../../mod/admin.php:631
+#: mod/admin.php:901
 msgid "Sender Email"
-msgstr ""
+msgstr "Системный Email"
 
-#: ../../mod/admin.php:632
+#: mod/admin.php:901
+msgid ""
+"The email address your server shall use to send notification emails from."
+msgstr "Адрес с которого будут приходить письма пользователям."
+
+#: mod/admin.php:902
 msgid "Banner/Logo"
 msgstr "Баннер/Логотип"
 
-#: ../../mod/admin.php:633
+#: mod/admin.php:903
 msgid "Shortcut icon"
 msgstr ""
 
-#: ../../mod/admin.php:634
+#: mod/admin.php:903
+msgid "Link to an icon that will be used for browsers."
+msgstr ""
+
+#: mod/admin.php:904
 msgid "Touch icon"
 msgstr ""
 
-#: ../../mod/admin.php:635
+#: mod/admin.php:904
+msgid "Link to an icon that will be used for tablets and mobiles."
+msgstr ""
+
+#: mod/admin.php:905
 msgid "Additional Info"
 msgstr "Дополнительная информация"
 
-#: ../../mod/admin.php:635
+#: mod/admin.php:905
+#, php-format
 msgid ""
 "For public servers: you can add additional information here that will be "
-"listed at dir.friendica.com/siteinfo."
-msgstr "Для публичных серверов: вы можете добавить дополнительную информацию, которая будет перечислена в dir.friendica.com/siteinfo."
+"listed at %s/siteinfo."
+msgstr ""
 
-#: ../../mod/admin.php:636
+#: mod/admin.php:906
 msgid "System language"
 msgstr "Системный язык"
 
-#: ../../mod/admin.php:637
+#: mod/admin.php:907
 msgid "System theme"
 msgstr "Системная тема"
 
-#: ../../mod/admin.php:637
+#: mod/admin.php:907
 msgid ""
 "Default system theme - may be over-ridden by user profiles - <a href='#' "
 "id='cnftheme'>change theme settings</a>"
-msgstr "Тема системы по умолчанию - может быть переопределена пользователем - <a href='#' id='cnftheme'>изменить настройки темы</a>"
+msgstr ""
+"Тема системы по умолчанию - может быть переопределена пользователем - <a "
+"href='#' id='cnftheme'>изменить настройки темы</a>"
 
-#: ../../mod/admin.php:638
+#: mod/admin.php:908
 msgid "Mobile system theme"
 msgstr "Мобильная тема системы"
 
-#: ../../mod/admin.php:638
+#: mod/admin.php:908
 msgid "Theme for mobile devices"
 msgstr "Тема для мобильных устройств"
 
-#: ../../mod/admin.php:639
+#: mod/admin.php:909
 msgid "SSL link policy"
 msgstr "Политика SSL"
 
-#: ../../mod/admin.php:639
+#: mod/admin.php:909
 msgid "Determines whether generated links should be forced to use SSL"
 msgstr "Ссылки должны быть вынуждены использовать SSL"
 
-#: ../../mod/admin.php:640
+#: mod/admin.php:910
 msgid "Force SSL"
-msgstr ""
+msgstr "SSL принудительно"
 
-#: ../../mod/admin.php:640
+#: mod/admin.php:910
 msgid ""
-"Force all Non-SSL requests to SSL - Attention: on some systems it could lead"
-" to endless loops."
+"Force all Non-SSL requests to SSL - Attention: on some systems it could lead "
+"to endless loops."
 msgstr ""
 
-#: ../../mod/admin.php:641
+#: mod/admin.php:911
 msgid "Old style 'Share'"
 msgstr "Старый стиль 'Share'"
 
-#: ../../mod/admin.php:641
+#: mod/admin.php:911
 msgid "Deactivates the bbcode element 'share' for repeating items."
 msgstr "Отключение BBCode элемента 'share' для повторяющихся элементов."
 
-#: ../../mod/admin.php:642
+#: mod/admin.php:912
 msgid "Hide help entry from navigation menu"
 msgstr "Скрыть пункт \"помощь\" в меню навигации"
 
-#: ../../mod/admin.php:642
+#: mod/admin.php:912
 msgid ""
 "Hides the menu entry for the Help pages from the navigation menu. You can "
 "still access it calling /help directly."
-msgstr "Скрывает элемент меню для страницы справки из меню навигации. Вы все еще можете получить доступ к нему через вызов/помощь напрямую."
+msgstr ""
+"Скрывает элемент меню для страницы справки из меню навигации. Вы все еще "
+"можете получить доступ к нему через вызов/помощь напрямую."
 
-#: ../../mod/admin.php:643
+#: mod/admin.php:913
 msgid "Single user instance"
 msgstr "Однопользовательский режим"
 
-#: ../../mod/admin.php:643
+#: mod/admin.php:913
 msgid "Make this instance multi-user or single-user for the named user"
-msgstr "Сделать этот экземпляр многопользовательским, или однопользовательским для названного пользователя"
+msgstr ""
+"Сделать этот экземпляр многопользовательским, или однопользовательским для "
+"названного пользователя"
 
-#: ../../mod/admin.php:644
+#: mod/admin.php:914
 msgid "Maximum image size"
 msgstr "Максимальный размер изображения"
 
-#: ../../mod/admin.php:644
+#: mod/admin.php:914
 msgid ""
 "Maximum size in bytes of uploaded images. Default is 0, which means no "
 "limits."
-msgstr "Максимальный размер в байтах для загружаемых изображений. По умолчанию 0, что означает отсутствие ограничений."
+msgstr ""
+"Максимальный размер в байтах для загружаемых изображений. По умолчанию 0, "
+"что означает отсутствие ограничений."
 
-#: ../../mod/admin.php:645
+#: mod/admin.php:915
 msgid "Maximum image length"
 msgstr "Максимальная длина картинки"
 
-#: ../../mod/admin.php:645
+#: mod/admin.php:915
 msgid ""
 "Maximum length in pixels of the longest side of uploaded images. Default is "
 "-1, which means no limits."
-msgstr "Максимальная длина в пикселях для длинной стороны загруженных изображений. По умолчанию равно -1, что означает отсутствие ограничений."
+msgstr ""
+"Максимальная длина в пикселях для длинной стороны загруженных изображений. "
+"По умолчанию равно -1, что означает отсутствие ограничений."
 
-#: ../../mod/admin.php:646
+#: mod/admin.php:916
 msgid "JPEG image quality"
 msgstr "Качество JPEG изображения"
 
-#: ../../mod/admin.php:646
+#: mod/admin.php:916
 msgid ""
 "Uploaded JPEGS will be saved at this quality setting [0-100]. Default is "
 "100, which is full quality."
-msgstr "Загруженные изображения JPEG будут сохранены в этом качестве [0-100]. По умолчанию 100, что означает полное качество."
+msgstr ""
+"Загруженные изображения JPEG будут сохранены в этом качестве [0-100]. По "
+"умолчанию 100, что означает полное качество."
 
-#: ../../mod/admin.php:648
+#: mod/admin.php:918
 msgid "Register policy"
 msgstr "Политика регистрация"
 
-#: ../../mod/admin.php:649
+#: mod/admin.php:919
 msgid "Maximum Daily Registrations"
 msgstr "Максимальное число регистраций в день"
 
-#: ../../mod/admin.php:649
+#: mod/admin.php:919
 msgid ""
-"If registration is permitted above, this sets the maximum number of new user"
-" registrations to accept per day.  If register is set to closed, this "
-"setting has no effect."
-msgstr "Если регистрация разрешена, этот параметр устанавливает максимальное количество новых регистраций пользователей в день. Если регистрация закрыта, эта опция не имеет никакого эффекта."
+"If registration is permitted above, this sets the maximum number of new user "
+"registrations to accept per day.  If register is set to closed, this setting "
+"has no effect."
+msgstr ""
+"Если регистрация разрешена, этот параметр устанавливает максимальное "
+"количество новых регистраций пользователей в день. Если регистрация закрыта, "
+"эта опция не имеет никакого эффекта."
 
-#: ../../mod/admin.php:650
+#: mod/admin.php:920
 msgid "Register text"
 msgstr "Текст регистрации"
 
-#: ../../mod/admin.php:650
+#: mod/admin.php:920
 msgid "Will be displayed prominently on the registration page."
 msgstr "Будет находиться на видном месте на странице регистрации."
 
-#: ../../mod/admin.php:651
+#: mod/admin.php:921
 msgid "Accounts abandoned after x days"
 msgstr "Аккаунт считается после x дней не воспользованным"
 
-#: ../../mod/admin.php:651
+#: mod/admin.php:921
 msgid ""
 "Will not waste system resources polling external sites for abandonded "
 "accounts. Enter 0 for no time limit."
-msgstr "Не будет тратить ресурсы для опроса сайтов для бесхозных контактов. Введите 0 для отключения лимита времени."
+msgstr ""
+"Не будет тратить ресурсы для опроса сайтов для бесхозных контактов. Введите "
+"0 для отключения лимита времени."
 
-#: ../../mod/admin.php:652
+#: mod/admin.php:922
 msgid "Allowed friend domains"
 msgstr "Разрешенные домены друзей"
 
-#: ../../mod/admin.php:652
+#: mod/admin.php:922
 msgid ""
 "Comma separated list of domains which are allowed to establish friendships "
 "with this site. Wildcards are accepted. Empty to allow any domains"
-msgstr "Разделенный запятыми список доменов, которые разрешены для установления связей. Групповые символы принимаются. Оставьте пустым для разрешения связи со всеми доменами."
+msgstr ""
+"Разделенный запятыми список доменов, которые разрешены для установления "
+"связей. Групповые символы принимаются. Оставьте пустым для разрешения связи "
+"со всеми доменами."
 
-#: ../../mod/admin.php:653
+#: mod/admin.php:923
 msgid "Allowed email domains"
 msgstr "Разрешенные почтовые домены"
 
-#: ../../mod/admin.php:653
+#: mod/admin.php:923
 msgid ""
 "Comma separated list of domains which are allowed in email addresses for "
 "registrations to this site. Wildcards are accepted. Empty to allow any "
 "domains"
-msgstr "Разделенный запятыми список доменов, которые разрешены для установления связей. Групповые символы принимаются. Оставьте пустым для разрешения связи со всеми доменами."
+msgstr ""
+"Разделенный запятыми список доменов, которые разрешены для установления "
+"связей. Групповые символы принимаются. Оставьте пустым для разрешения связи "
+"со всеми доменами."
 
-#: ../../mod/admin.php:654
+#: mod/admin.php:924
 msgid "Block public"
 msgstr "Блокировать общественный доступ"
 
-#: ../../mod/admin.php:654
+#: mod/admin.php:924
 msgid ""
 "Check to block public access to all otherwise public personal pages on this "
 "site unless you are currently logged in."
-msgstr "Отметьте, чтобы заблокировать публичный доступ ко всем иным публичным персональным страницам на этом сайте, если вы не вошли на сайт."
+msgstr ""
+"Отметьте, чтобы заблокировать публичный доступ ко всем иным публичным "
+"персональным страницам на этом сайте, если вы не вошли на сайт."
 
-#: ../../mod/admin.php:655
+#: mod/admin.php:925
 msgid "Force publish"
 msgstr "Принудительная публикация"
 
-#: ../../mod/admin.php:655
+#: mod/admin.php:925
 msgid ""
 "Check to force all profiles on this site to be listed in the site directory."
-msgstr "Отметьте, чтобы принудительно заставить все профили на этом сайте, быть перечислеными в каталоге сайта."
+msgstr ""
+"Отметьте, чтобы принудительно заставить все профили на этом сайте, быть "
+"перечислеными в каталоге сайта."
 
-#: ../../mod/admin.php:656
-msgid "Global directory update URL"
-msgstr "URL обновления глобального каталога"
+#: mod/admin.php:926
+msgid "Global directory URL"
+msgstr ""
 
-#: ../../mod/admin.php:656
+#: mod/admin.php:926
 msgid ""
-"URL to update the global directory. If this is not set, the global directory"
-" is completely unavailable to the application."
-msgstr "URL для обновления глобального каталога. Если он не установлен, глобальный каталог полностью недоступен для приложения."
+"URL to the global directory. If this is not set, the global directory is "
+"completely unavailable to the application."
+msgstr ""
 
-#: ../../mod/admin.php:657
+#: mod/admin.php:927
 msgid "Allow threaded items"
 msgstr "Разрешить темы в обсуждении"
 
-#: ../../mod/admin.php:657
+#: mod/admin.php:927
 msgid "Allow infinite level threading for items on this site."
 msgstr "Разрешить бесконечный уровень для тем на этом сайте."
 
-#: ../../mod/admin.php:658
+#: mod/admin.php:928
 msgid "Private posts by default for new users"
 msgstr "Частные сообщения по умолчанию для новых пользователей"
 
-#: ../../mod/admin.php:658
+#: mod/admin.php:928
 msgid ""
 "Set default post permissions for all new members to the default privacy "
 "group rather than public."
-msgstr "Установить права на создание постов по умолчанию для всех участников в дефолтной приватной группе, а не для публичных участников."
+msgstr ""
+"Установить права на создание постов по умолчанию для всех участников в "
+"дефолтной приватной группе, а не для публичных участников."
 
-#: ../../mod/admin.php:659
+#: mod/admin.php:929
 msgid "Don't include post content in email notifications"
 msgstr "Не включать текст сообщения в email-оповещение."
 
-#: ../../mod/admin.php:659
+#: mod/admin.php:929
 msgid ""
 "Don't include the content of a post/comment/private message/etc. in the "
 "email notifications that are sent out from this site, as a privacy measure."
-msgstr "Не включать содержание сообщения/комментария/личного сообщения  и т.д.. в уведомления электронной почты, отправленных с сайта, в качестве меры конфиденциальности."
+msgstr ""
+"Не включать содержание сообщения/комментария/личного сообщения  и т.д.. в "
+"уведомления электронной почты, отправленных с сайта, в качестве меры "
+"конфиденциальности."
 
-#: ../../mod/admin.php:660
+#: mod/admin.php:930
 msgid "Disallow public access to addons listed in the apps menu."
 msgstr "Запретить публичный доступ к аддонам, перечисленным в меню приложений."
 
-#: ../../mod/admin.php:660
+#: mod/admin.php:930
 msgid ""
 "Checking this box will restrict addons listed in the apps menu to members "
 "only."
-msgstr "При установке этого флажка, будут ограничены аддоны, перечисленные в меню приложений, только для участников."
+msgstr ""
+"При установке этого флажка, будут ограничены аддоны, перечисленные в меню "
+"приложений, только для участников."
 
-#: ../../mod/admin.php:661
+#: mod/admin.php:931
 msgid "Don't embed private images in posts"
 msgstr "Не вставлять личные картинки в постах"
 
-#: ../../mod/admin.php:661
+#: mod/admin.php:931
 msgid ""
 "Don't replace locally-hosted private photos in posts with an embedded copy "
 "of the image. This means that contacts who receive posts containing private "
-"photos will have to authenticate and load each image, which may take a "
-"while."
-msgstr "Не заменяйте локально расположенные фотографии в постах на внедрённые копии изображений. Это означает, что контакты, которые получают сообщения, содержащие личные фотографии, будут вынуждены идентефицироваться и грузить каждое изображение, что может занять некоторое время."
+"photos will have to authenticate and load each image, which may take a while."
+msgstr ""
+"Не заменяйте локально расположенные фотографии в постах на внедрённые копии "
+"изображений. Это означает, что контакты, которые получают сообщения, "
+"содержащие личные фотографии, будут вынуждены идентефицироваться и грузить "
+"каждое изображение, что может занять некоторое время."
 
-#: ../../mod/admin.php:662
+#: mod/admin.php:932
 msgid "Allow Users to set remote_self"
 msgstr "Разрешить пользователям установить remote_self"
 
-#: ../../mod/admin.php:662
+#: mod/admin.php:932
 msgid ""
 "With checking this, every user is allowed to mark every contact as a "
 "remote_self in the repair contact dialog. Setting this flag on a contact "
 "causes mirroring every posting of that contact in the users stream."
 msgstr ""
 
-#: ../../mod/admin.php:663
+#: mod/admin.php:933
 msgid "Block multiple registrations"
 msgstr "Блокировать множественные регистрации"
 
-#: ../../mod/admin.php:663
+#: mod/admin.php:933
 msgid "Disallow users to register additional accounts for use as pages."
-msgstr "Запретить пользователям регистрировать дополнительные аккаунты для использования в качестве страниц."
+msgstr ""
+"Запретить пользователям регистрировать дополнительные аккаунты для "
+"использования в качестве страниц."
 
-#: ../../mod/admin.php:664
+#: mod/admin.php:934
 msgid "OpenID support"
 msgstr "Поддержка OpenID"
 
-#: ../../mod/admin.php:664
+#: mod/admin.php:934
 msgid "OpenID support for registration and logins."
 msgstr "OpenID поддержка для регистрации и входа в систему."
 
-#: ../../mod/admin.php:665
+#: mod/admin.php:935
 msgid "Fullname check"
 msgstr "Проверка полного имени"
 
-#: ../../mod/admin.php:665
+#: mod/admin.php:935
 msgid ""
 "Force users to register with a space between firstname and lastname in Full "
 "name, as an antispam measure"
-msgstr "Принудить пользователей регистрироваться с пробелом между именем и фамилией в строке \"полное имя\". Антиспам мера."
+msgstr ""
+"Принудить пользователей регистрироваться с пробелом между именем и фамилией "
+"в строке \"полное имя\". Антиспам мера."
 
-#: ../../mod/admin.php:666
+#: mod/admin.php:936
 msgid "UTF-8 Regular expressions"
 msgstr "UTF-8 регулярные выражения"
 
-#: ../../mod/admin.php:666
+#: mod/admin.php:936
 msgid "Use PHP UTF8 regular expressions"
 msgstr "Используйте PHP UTF-8 для регулярных выражений"
 
-#: ../../mod/admin.php:667
+#: mod/admin.php:937
 msgid "Community Page Style"
 msgstr ""
 
-#: ../../mod/admin.php:667
+#: mod/admin.php:937
 msgid ""
 "Type of community page to show. 'Global community' shows every public "
 "posting from an open distributed network that arrived on this server."
 msgstr ""
 
-#: ../../mod/admin.php:668
+#: mod/admin.php:938
 msgid "Posts per user on community page"
 msgstr ""
 
-#: ../../mod/admin.php:668
+#: mod/admin.php:938
 msgid ""
 "The maximum number of posts per user on the community page. (Not valid for "
 "'Global Community')"
 msgstr ""
 
-#: ../../mod/admin.php:669
+#: mod/admin.php:939
 msgid "Enable OStatus support"
 msgstr "Включить поддержку OStatus"
 
-#: ../../mod/admin.php:669
+#: mod/admin.php:939
 msgid ""
 "Provide built-in OStatus (StatusNet, GNU Social etc.) compatibility. All "
 "communications in OStatus are public, so privacy warnings will be "
 "occasionally displayed."
 msgstr ""
 
-#: ../../mod/admin.php:670
+#: mod/admin.php:940
 msgid "OStatus conversation completion interval"
 msgstr ""
 
-#: ../../mod/admin.php:670
+#: mod/admin.php:940
 msgid ""
 "How often shall the poller check for new entries in OStatus conversations? "
 "This can be a very ressource task."
-msgstr "Как часто процессы должны проверять наличие новых записей в OStatus разговорах? Это может быть очень ресурсоёмкой задачей."
+msgstr ""
+"Как часто процессы должны проверять наличие новых записей в OStatus "
+"разговорах? Это может быть очень ресурсоёмкой задачей."
 
-#: ../../mod/admin.php:671
+#: mod/admin.php:941
+msgid "OStatus support can only be enabled if threading is enabled."
+msgstr ""
+
+#: mod/admin.php:943
+msgid ""
+"Diaspora support can't be enabled because Friendica was installed into a sub "
+"directory."
+msgstr ""
+
+#: mod/admin.php:944
 msgid "Enable Diaspora support"
 msgstr "Включить поддержку Diaspora"
 
-#: ../../mod/admin.php:671
+#: mod/admin.php:944
 msgid "Provide built-in Diaspora network compatibility."
 msgstr "Обеспечить встроенную поддержку сети Diaspora."
 
-#: ../../mod/admin.php:672
+#: mod/admin.php:945
 msgid "Only allow Friendica contacts"
 msgstr "Позвольть только  Friendica контакты"
 
-#: ../../mod/admin.php:672
+#: mod/admin.php:945
 msgid ""
 "All contacts must use Friendica protocols. All other built-in communication "
 "protocols disabled."
-msgstr "Все контакты должны использовать только Friendica протоколы. Все другие встроенные коммуникационные протоколы отключены."
+msgstr ""
+"Все контакты должны использовать только Friendica протоколы. Все другие "
+"встроенные коммуникационные протоколы отключены."
 
-#: ../../mod/admin.php:673
+#: mod/admin.php:946
 msgid "Verify SSL"
 msgstr "Проверка SSL"
 
-#: ../../mod/admin.php:673
+#: mod/admin.php:946
 msgid ""
-"If you wish, you can turn on strict certificate checking. This will mean you"
-" cannot connect (at all) to self-signed SSL sites."
-msgstr "Если хотите, вы можете включить строгую проверку сертификатов. Это будет означать, что вы не сможете соединиться (вообще) с сайтами, имеющими само-подписанный SSL сертификат."
+"If you wish, you can turn on strict certificate checking. This will mean you "
+"cannot connect (at all) to self-signed SSL sites."
+msgstr ""
+"Если хотите, вы можете включить строгую проверку сертификатов. Это будет "
+"означать, что вы не сможете соединиться (вообще) с сайтами, имеющими само-"
+"подписанный SSL сертификат."
 
-#: ../../mod/admin.php:674
+#: mod/admin.php:947
 msgid "Proxy user"
 msgstr "Прокси пользователь"
 
-#: ../../mod/admin.php:675
+#: mod/admin.php:948
 msgid "Proxy URL"
 msgstr "Прокси URL"
 
-#: ../../mod/admin.php:676
+#: mod/admin.php:949
 msgid "Network timeout"
 msgstr "Тайм-аут сети"
 
-#: ../../mod/admin.php:676
+#: mod/admin.php:949
 msgid "Value is in seconds. Set to 0 for unlimited (not recommended)."
-msgstr "Значение указывается в секундах. Установите 0 для снятия ограничений (не рекомендуется)."
+msgstr ""
+"Значение указывается в секундах. Установите 0 для снятия ограничений (не "
+"рекомендуется)."
 
-#: ../../mod/admin.php:677
+#: mod/admin.php:950
 msgid "Delivery interval"
 msgstr "Интервал поставки"
 
-#: ../../mod/admin.php:677
+#: mod/admin.php:950
 msgid ""
 "Delay background delivery processes by this many seconds to reduce system "
 "load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 "
 "for large dedicated servers."
-msgstr "Установите задержку выполнения фоновых процессов доставки до указанного количества секунд, чтобы уменьшить нагрузку на систему. Рекомендация: 4-5 для обычного shared хостинга, 2-3 для виртуальных частных серверов. 0-1 для мощных выделенных серверов."
+msgstr ""
+"Установите задержку выполнения фоновых процессов доставки до указанного "
+"количества секунд, чтобы уменьшить нагрузку на систему. Рекомендация: 4-5 "
+"для обычного shared хостинга, 2-3 для виртуальных частных серверов. 0-1 для "
+"мощных выделенных серверов."
 
-#: ../../mod/admin.php:678
+#: mod/admin.php:951
 msgid "Poll interval"
 msgstr "Интервал опроса"
 
-#: ../../mod/admin.php:678
+#: mod/admin.php:951
 msgid ""
 "Delay background polling processes by this many seconds to reduce system "
 "load. If 0, use delivery interval."
-msgstr "Установить задержку фоновых процессов опросов путем ограничения количества секунд, чтобы уменьшить нагрузку на систему. Если 0, используется интервал доставки."
+msgstr ""
+"Установить задержку фоновых процессов опросов путем ограничения количества "
+"секунд, чтобы уменьшить нагрузку на систему. Если 0, используется интервал "
+"доставки."
 
-#: ../../mod/admin.php:679
+#: mod/admin.php:952
 msgid "Maximum Load Average"
 msgstr "Средняя максимальная нагрузка"
 
-#: ../../mod/admin.php:679
+#: mod/admin.php:952
 msgid ""
 "Maximum system load before delivery and poll processes are deferred - "
 "default 50."
-msgstr "Максимальная нагрузка на систему перед приостановкой процессов доставки и опросов - по умолчанию 50."
+msgstr ""
+"Максимальная нагрузка на систему перед приостановкой процессов доставки и "
+"опросов - по умолчанию 50."
 
-#: ../../mod/admin.php:681
+#: mod/admin.php:953
+msgid "Maximum Load Average (Frontend)"
+msgstr ""
+
+#: mod/admin.php:953
+msgid "Maximum system load before the frontend quits service - default 50."
+msgstr ""
+
+#: mod/admin.php:954
+msgid "Maximum table size for optimization"
+msgstr ""
+
+#: mod/admin.php:954
+msgid ""
+"Maximum table size (in MB) for the automatic optimization - default 100 MB. "
+"Enter -1 to disable it."
+msgstr ""
+
+#: mod/admin.php:955
+msgid "Minimum level of fragmentation"
+msgstr ""
+
+#: mod/admin.php:955
+msgid ""
+"Minimum fragmenation level to start the automatic optimization - default "
+"value is 30%."
+msgstr ""
+
+#: mod/admin.php:957
+msgid "Periodical check of global contacts"
+msgstr ""
+
+#: mod/admin.php:957
+msgid ""
+"If enabled, the global contacts are checked periodically for missing or "
+"outdated data and the vitality of the contacts and servers."
+msgstr ""
+
+#: mod/admin.php:958
+msgid "Days between requery"
+msgstr ""
+
+#: mod/admin.php:958
+msgid "Number of days after which a server is requeried for his contacts."
+msgstr ""
+
+#: mod/admin.php:959
+msgid "Discover contacts from other servers"
+msgstr ""
+
+#: mod/admin.php:959
+msgid ""
+"Periodically query other servers for contacts. You can choose between "
+"'users': the users on the remote system, 'Global Contacts': active contacts "
+"that are known on the system. The fallback is meant for Redmatrix servers "
+"and older friendica servers, where global contacts weren't available. The "
+"fallback increases the server load, so the recommened setting is 'Users, "
+"Global Contacts'."
+msgstr ""
+
+#: mod/admin.php:960
+msgid "Timeframe for fetching global contacts"
+msgstr ""
+
+#: mod/admin.php:960
+msgid ""
+"When the discovery is activated, this value defines the timeframe for the "
+"activity of the global contacts that are fetched from other servers."
+msgstr ""
+
+#: mod/admin.php:961
+msgid "Search the local directory"
+msgstr ""
+
+#: mod/admin.php:961
+msgid ""
+"Search the local directory instead of the global directory. When searching "
+"locally, every search will be executed on the global directory in the "
+"background. This improves the search results when the search is repeated."
+msgstr ""
+
+#: mod/admin.php:963
+msgid "Publish server information"
+msgstr ""
+
+#: mod/admin.php:963
+msgid ""
+"If enabled, general server and usage data will be published. The data "
+"contains the name and version of the server, number of users with public "
+"profiles, number of posts and the activated protocols and connectors. See <a "
+"href='http://the-federation.info/'>the-federation.info</a> for details."
+msgstr ""
+
+#: mod/admin.php:965
 msgid "Use MySQL full text engine"
 msgstr "Использовать систему полнотексного поиска MySQL"
 
-#: ../../mod/admin.php:681
+#: mod/admin.php:965
 msgid ""
 "Activates the full text engine. Speeds up search - but can only search for "
 "four and more characters."
-msgstr "Активизирует систему полнотексного поиска. Ускоряет поиск - но может искать только при указании четырех и более символов."
+msgstr ""
+"Активизирует систему полнотексного поиска. Ускоряет поиск - но может искать "
+"только при указании четырех и более символов."
 
-#: ../../mod/admin.php:682
+#: mod/admin.php:966
 msgid "Suppress Language"
 msgstr ""
 
-#: ../../mod/admin.php:682
+#: mod/admin.php:966
 msgid "Suppress language information in meta information about a posting."
 msgstr ""
 
-#: ../../mod/admin.php:683
+#: mod/admin.php:967
 msgid "Suppress Tags"
 msgstr ""
 
-#: ../../mod/admin.php:683
+#: mod/admin.php:967
 msgid "Suppress showing a list of hashtags at the end of the posting."
 msgstr ""
 
-#: ../../mod/admin.php:684
+#: mod/admin.php:968
 msgid "Path to item cache"
 msgstr "Путь к элементам кэша"
 
-#: ../../mod/admin.php:685
+#: mod/admin.php:968
+msgid "The item caches buffers generated bbcode and external images."
+msgstr ""
+
+#: mod/admin.php:969
 msgid "Cache duration in seconds"
 msgstr "Время жизни кэша в секундах"
 
-#: ../../mod/admin.php:685
+#: mod/admin.php:969
 msgid ""
-"How long should the cache files be hold? Default value is 86400 seconds (One"
-" day). To disable the item cache, set the value to -1."
+"How long should the cache files be hold? Default value is 86400 seconds (One "
+"day). To disable the item cache, set the value to -1."
 msgstr ""
 
-#: ../../mod/admin.php:686
+#: mod/admin.php:970
 msgid "Maximum numbers of comments per post"
 msgstr ""
 
-#: ../../mod/admin.php:686
+#: mod/admin.php:970
 msgid "How much comments should be shown for each post? Default value is 100."
 msgstr ""
 
-#: ../../mod/admin.php:687
+#: mod/admin.php:971
 msgid "Path for lock file"
 msgstr "Путь к файлу блокировки"
 
-#: ../../mod/admin.php:688
+#: mod/admin.php:971
+msgid ""
+"The lock file is used to avoid multiple pollers at one time. Only define a "
+"folder here."
+msgstr ""
+
+#: mod/admin.php:972
 msgid "Temp path"
 msgstr "Временная папка"
 
-#: ../../mod/admin.php:689
+#: mod/admin.php:972
+msgid ""
+"If you have a restricted system where the webserver can't access the system "
+"temp path, enter another path here."
+msgstr ""
+
+#: mod/admin.php:973
 msgid "Base path to installation"
 msgstr "Путь для установки"
 
-#: ../../mod/admin.php:690
+#: mod/admin.php:973
+msgid ""
+"If the system cannot detect the correct path to your installation, enter the "
+"correct path here. This setting should only be set if you are using a "
+"restricted system and symbolic links to your webroot."
+msgstr ""
+
+#: mod/admin.php:974
 msgid "Disable picture proxy"
 msgstr ""
 
-#: ../../mod/admin.php:690
+#: mod/admin.php:974
 msgid ""
-"The picture proxy increases performance and privacy. It shouldn't be used on"
-" systems with very low bandwith."
+"The picture proxy increases performance and privacy. It shouldn't be used on "
+"systems with very low bandwith."
 msgstr ""
 
-#: ../../mod/admin.php:691
+#: mod/admin.php:975
 msgid "Enable old style pager"
 msgstr ""
 
-#: ../../mod/admin.php:691
+#: mod/admin.php:975
 msgid ""
-"The old style pager has page numbers but slows down massively the page "
-"speed."
+"The old style pager has page numbers but slows down massively the page speed."
 msgstr ""
 
-#: ../../mod/admin.php:692
+#: mod/admin.php:976
 msgid "Only search in tags"
 msgstr ""
 
-#: ../../mod/admin.php:692
+#: mod/admin.php:976
 msgid "On large systems the text search can slow down the system extremely."
 msgstr ""
 
-#: ../../mod/admin.php:694
+#: mod/admin.php:978
 msgid "New base url"
 msgstr "Новый базовый url"
 
-#: ../../mod/admin.php:711
+#: mod/admin.php:978
+msgid ""
+"Change base url for this server. Sends relocate message to all DFRN contacts "
+"of all users."
+msgstr ""
+
+#: mod/admin.php:980
+msgid "RINO Encryption"
+msgstr "RINO шифрование"
+
+#: mod/admin.php:980
+msgid "Encryption layer between nodes."
+msgstr "Слой шифрования между узлами."
+
+#: mod/admin.php:981
+msgid "Embedly API key"
+msgstr ""
+
+#: mod/admin.php:981
+msgid ""
+"<a href='http://embed.ly'>Embedly</a> is used to fetch additional data for "
+"web pages. This is an optional parameter."
+msgstr ""
+
+#: mod/admin.php:1010
 msgid "Update has been marked successful"
 msgstr "Обновление было успешно отмечено"
 
-#: ../../mod/admin.php:719
+#: mod/admin.php:1018
 #, php-format
 msgid "Database structure update %s was successfully applied."
 msgstr ""
 
-#: ../../mod/admin.php:722
+#: mod/admin.php:1021
 #, php-format
 msgid "Executing of database structure update %s failed with error: %s"
 msgstr ""
 
-#: ../../mod/admin.php:734
+#: mod/admin.php:1033
 #, php-format
 msgid "Executing %s failed with error: %s"
 msgstr ""
 
-#: ../../mod/admin.php:737
+#: mod/admin.php:1036
 #, php-format
 msgid "Update %s was successfully applied."
 msgstr "Обновление %s успешно применено."
 
-#: ../../mod/admin.php:741
+#: mod/admin.php:1040
 #, php-format
 msgid "Update %s did not return a status. Unknown if it succeeded."
-msgstr "Процесс обновления %s не вернул статус. Не известно, выполнено, или нет."
+msgstr ""
+"Процесс обновления %s не вернул статус. Не известно, выполнено, или нет."
 
-#: ../../mod/admin.php:743
+#: mod/admin.php:1042
 #, php-format
 msgid "There was no additional update function %s that needed to be called."
 msgstr ""
 
-#: ../../mod/admin.php:762
+#: mod/admin.php:1061
 msgid "No failed updates."
 msgstr "Неудавшихся обновлений нет."
 
-#: ../../mod/admin.php:763
+#: mod/admin.php:1062
 msgid "Check database structure"
 msgstr ""
 
-#: ../../mod/admin.php:768
+#: mod/admin.php:1067
 msgid "Failed Updates"
 msgstr "Неудавшиеся обновления"
 
-#: ../../mod/admin.php:769
+#: mod/admin.php:1068
 msgid ""
 "This does not include updates prior to 1139, which did not return a status."
-msgstr "Эта цифра не включает обновления до 1139, которое не возвращает статус."
+msgstr ""
+"Эта цифра не включает обновления до 1139, которое не возвращает статус."
 
-#: ../../mod/admin.php:770
+#: mod/admin.php:1069
 msgid "Mark success (if update was manually applied)"
 msgstr "Отмечено успешно (если обновление было применено вручную)"
 
-#: ../../mod/admin.php:771
+#: mod/admin.php:1070
 msgid "Attempt to execute this update step automatically"
 msgstr "Попытаться выполнить этот шаг обновления автоматически"
 
-#: ../../mod/admin.php:803
+#: mod/admin.php:1102
 #, php-format
 msgid ""
 "\n"
@@ -2624,7 +3111,7 @@ msgid ""
 "\t\t\t\tthe administrator of %2$s has set up an account for you."
 msgstr ""
 
-#: ../../mod/admin.php:806
+#: mod/admin.php:1105
 #, php-format
 msgid ""
 "\n"
@@ -2634,310 +3121,354 @@ msgid ""
 "\t\t\tLogin Name:\t\t%2$s\n"
 "\t\t\tPassword:\t\t%3$s\n"
 "\n"
-"\t\t\tYou may change your password from your account \"Settings\" page after logging\n"
+"\t\t\tYou may change your password from your account \"Settings\" page after "
+"logging\n"
 "\t\t\tin.\n"
 "\n"
-"\t\t\tPlease take a few moments to review the other account settings on that page.\n"
+"\t\t\tPlease take a few moments to review the other account settings on that "
+"page.\n"
 "\n"
-"\t\t\tYou may also wish to add some basic information to your default profile\n"
+"\t\t\tYou may also wish to add some basic information to your default "
+"profile\n"
 "\t\t\t(on the \"Profiles\" page) so that other people can easily find you.\n"
 "\n"
 "\t\t\tWe recommend setting your full name, adding a profile photo,\n"
-"\t\t\tadding some profile \"keywords\" (very useful in making new friends) - and\n"
-"\t\t\tperhaps what country you live in; if you do not wish to be more specific\n"
+"\t\t\tadding some profile \"keywords\" (very useful in making new friends) - "
+"and\n"
+"\t\t\tperhaps what country you live in; if you do not wish to be more "
+"specific\n"
 "\t\t\tthan that.\n"
 "\n"
-"\t\t\tWe fully respect your right to privacy, and none of these items are necessary.\n"
+"\t\t\tWe fully respect your right to privacy, and none of these items are "
+"necessary.\n"
 "\t\t\tIf you are new and do not know anybody here, they may help\n"
 "\t\t\tyou to make some new and interesting friends.\n"
 "\n"
 "\t\t\tThank you and welcome to %4$s."
 msgstr ""
 
-#: ../../mod/admin.php:838 ../../include/user.php:413
+#: mod/admin.php:1137 include/user.php:423
 #, php-format
 msgid "Registration details for %s"
 msgstr "Подробности регистрации для %s"
 
-#: ../../mod/admin.php:850
+#: mod/admin.php:1149
 #, php-format
 msgid "%s user blocked/unblocked"
 msgid_plural "%s users blocked/unblocked"
 msgstr[0] "%s пользователь заблокирован/разблокирован"
 msgstr[1] "%s пользователей заблокировано/разблокировано"
 msgstr[2] "%s пользователей заблокировано/разблокировано"
+msgstr[3] "%s пользователей заблокировано/разблокировано"
 
-#: ../../mod/admin.php:857
+#: mod/admin.php:1156
 #, php-format
 msgid "%s user deleted"
 msgid_plural "%s users deleted"
 msgstr[0] "%s человек удален"
 msgstr[1] "%s чел. удалено"
 msgstr[2] "%s чел. удалено"
+msgstr[3] "%s чел. удалено"
 
-#: ../../mod/admin.php:896
+#: mod/admin.php:1203
 #, php-format
 msgid "User '%s' deleted"
 msgstr "Пользователь '%s' удален"
 
-#: ../../mod/admin.php:904
+#: mod/admin.php:1211
 #, php-format
 msgid "User '%s' unblocked"
 msgstr "Пользователь '%s' разблокирован"
 
-#: ../../mod/admin.php:904
+#: mod/admin.php:1211
 #, php-format
 msgid "User '%s' blocked"
 msgstr "Пользователь '%s' блокирован"
 
-#: ../../mod/admin.php:999
+#: mod/admin.php:1302
 msgid "Add User"
 msgstr "Добавить пользователя"
 
-#: ../../mod/admin.php:1000
+#: mod/admin.php:1303
 msgid "select all"
 msgstr "выбрать все"
 
-#: ../../mod/admin.php:1001
+#: mod/admin.php:1304
 msgid "User registrations waiting for confirm"
 msgstr "Регистрации пользователей, ожидающие подтверждения"
 
-#: ../../mod/admin.php:1002
+#: mod/admin.php:1305
 msgid "User waiting for permanent deletion"
 msgstr "Пользователь ожидает окончательного удаления"
 
-#: ../../mod/admin.php:1003
+#: mod/admin.php:1306
 msgid "Request date"
 msgstr "Запрос даты"
 
-#: ../../mod/admin.php:1003 ../../mod/admin.php:1015 ../../mod/admin.php:1016
-#: ../../mod/admin.php:1031 ../../include/contact_selectors.php:79
-#: ../../include/contact_selectors.php:86
+#: mod/admin.php:1306 mod/admin.php:1318 mod/admin.php:1319 mod/admin.php:1334
+#: include/contact_selectors.php:79 include/contact_selectors.php:86
 msgid "Email"
 msgstr "Эл. почта"
 
-#: ../../mod/admin.php:1004
+#: mod/admin.php:1307
 msgid "No registrations."
 msgstr "Нет регистраций."
 
-#: ../../mod/admin.php:1006
+#: mod/admin.php:1309
 msgid "Deny"
 msgstr "Отклонить"
 
-#: ../../mod/admin.php:1010
+#: mod/admin.php:1313
 msgid "Site admin"
 msgstr "Админ сайта"
 
-#: ../../mod/admin.php:1011
+#: mod/admin.php:1314
 msgid "Account expired"
 msgstr "Аккаунт просрочен"
 
-#: ../../mod/admin.php:1014
+#: mod/admin.php:1317
 msgid "New User"
 msgstr "Новый пользователь"
 
-#: ../../mod/admin.php:1015 ../../mod/admin.php:1016
+#: mod/admin.php:1318 mod/admin.php:1319
 msgid "Register date"
 msgstr "Дата регистрации"
 
-#: ../../mod/admin.php:1015 ../../mod/admin.php:1016
+#: mod/admin.php:1318 mod/admin.php:1319
 msgid "Last login"
 msgstr "Последний вход"
 
-#: ../../mod/admin.php:1015 ../../mod/admin.php:1016
+#: mod/admin.php:1318 mod/admin.php:1319
 msgid "Last item"
 msgstr "Последний пункт"
 
-#: ../../mod/admin.php:1015
+#: mod/admin.php:1318
 msgid "Deleted since"
 msgstr "Удалён с"
 
-#: ../../mod/admin.php:1016 ../../mod/settings.php:36
+#: mod/admin.php:1319 mod/settings.php:41
 msgid "Account"
 msgstr "Аккаунт"
 
-#: ../../mod/admin.php:1018
+#: mod/admin.php:1321
 msgid ""
 "Selected users will be deleted!\\n\\nEverything these users had posted on "
 "this site will be permanently deleted!\\n\\nAre you sure?"
-msgstr "Выбранные пользователи будут удалены!\\n\\nВсе, что эти пользователи написали на этом сайте, будет удалено!\\n\\nВы уверены в вашем действии?"
+msgstr ""
+"Выбранные пользователи будут удалены!\\n\\nВсе, что эти пользователи "
+"написали на этом сайте, будет удалено!\\n\\nВы уверены в вашем действии?"
 
-#: ../../mod/admin.php:1019
+#: mod/admin.php:1322
 msgid ""
 "The user {0} will be deleted!\\n\\nEverything this user has posted on this "
 "site will be permanently deleted!\\n\\nAre you sure?"
-msgstr "Пользователь {0} будет удален!\\n\\nВсе, что этот пользователь написал на этом сайте, будет удалено!\\n\\nВы уверены в вашем действии?"
+msgstr ""
+"Пользователь {0} будет удален!\\n\\nВсе, что этот пользователь написал на "
+"этом сайте, будет удалено!\\n\\nВы уверены в вашем действии?"
 
-#: ../../mod/admin.php:1029
+#: mod/admin.php:1332
 msgid "Name of the new user."
 msgstr "Имя нового пользователя."
 
-#: ../../mod/admin.php:1030
+#: mod/admin.php:1333
 msgid "Nickname"
 msgstr "Ник"
 
-#: ../../mod/admin.php:1030
+#: mod/admin.php:1333
 msgid "Nickname of the new user."
 msgstr "Ник нового пользователя."
 
-#: ../../mod/admin.php:1031
+#: mod/admin.php:1334
 msgid "Email address of the new user."
 msgstr "Email адрес нового пользователя."
 
-#: ../../mod/admin.php:1064
+#: mod/admin.php:1377
 #, php-format
 msgid "Plugin %s disabled."
 msgstr "Плагин %s отключен."
 
-#: ../../mod/admin.php:1068
+#: mod/admin.php:1381
 #, php-format
 msgid "Plugin %s enabled."
 msgstr "Плагин %s включен."
 
-#: ../../mod/admin.php:1078 ../../mod/admin.php:1294
+#: mod/admin.php:1392 mod/admin.php:1628
 msgid "Disable"
 msgstr "Отключить"
 
-#: ../../mod/admin.php:1080 ../../mod/admin.php:1296
+#: mod/admin.php:1394 mod/admin.php:1630
 msgid "Enable"
 msgstr "Включить"
 
-#: ../../mod/admin.php:1103 ../../mod/admin.php:1324
+#: mod/admin.php:1417 mod/admin.php:1675
 msgid "Toggle"
 msgstr "Переключить"
 
-#: ../../mod/admin.php:1111 ../../mod/admin.php:1334
+#: mod/admin.php:1425 mod/admin.php:1684
 msgid "Author: "
 msgstr "Автор:"
 
-#: ../../mod/admin.php:1112 ../../mod/admin.php:1335
+#: mod/admin.php:1426 mod/admin.php:1685
 msgid "Maintainer: "
 msgstr "Программа обслуживания: "
 
-#: ../../mod/admin.php:1254
+#: mod/admin.php:1478
+msgid "Reload active plugins"
+msgstr ""
+
+#: mod/admin.php:1483
+#, php-format
+msgid ""
+"There are currently no plugins available on your node. You can find the "
+"official plugin repository at %1$s and might find other interesting plugins "
+"in the open plugin registry at %2$s"
+msgstr ""
+
+#: mod/admin.php:1588
 msgid "No themes found."
 msgstr "Темы не найдены."
 
-#: ../../mod/admin.php:1316
+#: mod/admin.php:1666
 msgid "Screenshot"
 msgstr "Скриншот"
 
-#: ../../mod/admin.php:1362
+#: mod/admin.php:1726
+msgid "Reload active themes"
+msgstr ""
+
+#: mod/admin.php:1731
+#, php-format
+msgid "No themes found on the system. They should be paced in %1$s"
+msgstr ""
+
+#: mod/admin.php:1732
 msgid "[Experimental]"
 msgstr "[экспериментально]"
 
-#: ../../mod/admin.php:1363
+#: mod/admin.php:1733
 msgid "[Unsupported]"
 msgstr "[Неподдерживаемое]"
 
-#: ../../mod/admin.php:1390
+#: mod/admin.php:1757
 msgid "Log settings updated."
 msgstr "Настройки журнала обновлены."
 
-#: ../../mod/admin.php:1446
+#: mod/admin.php:1794
 msgid "Clear"
 msgstr "Очистить"
 
-#: ../../mod/admin.php:1452
+#: mod/admin.php:1799
 msgid "Enable Debugging"
 msgstr "Включить отладку"
 
-#: ../../mod/admin.php:1453
+#: mod/admin.php:1800
 msgid "Log file"
 msgstr "Лог-файл"
 
-#: ../../mod/admin.php:1453
+#: mod/admin.php:1800
 msgid ""
 "Must be writable by web server. Relative to your Friendica top-level "
 "directory."
-msgstr "Должно быть доступно для записи в веб-сервере. Относительно вашего Friendica каталога верхнего уровня."
+msgstr ""
+"Должно быть доступно для записи в веб-сервере. Относительно вашего Friendica "
+"каталога верхнего уровня."
 
-#: ../../mod/admin.php:1454
+#: mod/admin.php:1801
 msgid "Log level"
 msgstr "Уровень лога"
 
-#: ../../mod/admin.php:1504
-msgid "Close"
-msgstr "Закрыть"
+#: mod/admin.php:1804
+msgid "PHP logging"
+msgstr "PHP логирование"
 
-#: ../../mod/admin.php:1510
-msgid "FTP Host"
-msgstr "FTP хост"
+#: mod/admin.php:1805
+msgid ""
+"To enable logging of PHP errors and warnings you can add the following to "
+"the .htconfig.php file of your installation. The filename set in the "
+"'error_log' line is relative to the friendica top-level directory and must "
+"be writeable by the web server. The option '1' for 'log_errors' and "
+"'display_errors' is to enable these options, set to '0' to disable them."
+msgstr ""
 
-#: ../../mod/admin.php:1511
-msgid "FTP Path"
-msgstr "Путь FTP"
+#: mod/admin.php:1931 mod/admin.php:1932 mod/settings.php:759
+msgid "Off"
+msgstr "Выкл."
 
-#: ../../mod/admin.php:1512
-msgid "FTP User"
-msgstr "FTP пользователь"
+#: mod/admin.php:1931 mod/admin.php:1932 mod/settings.php:759
+msgid "On"
+msgstr "Вкл."
 
-#: ../../mod/admin.php:1513
-msgid "FTP Password"
-msgstr "FTP пароль"
+#: mod/admin.php:1932
+#, php-format
+msgid "Lock feature %s"
+msgstr ""
 
-#: ../../mod/network.php:142
-msgid "Search Results For:"
-msgstr "Результаты поиска для:"
+#: mod/admin.php:1940
+msgid "Manage Additional Features"
+msgstr ""
 
-#: ../../mod/network.php:185 ../../mod/search.php:21
+#: mod/network.php:146
+#, php-format
+msgid "Search Results For: %s"
+msgstr ""
+
+#: mod/network.php:191 mod/search.php:25
 msgid "Remove term"
 msgstr "Удалить элемент"
 
-#: ../../mod/network.php:194 ../../mod/search.php:30
-#: ../../include/features.php:42
+#: mod/network.php:200 mod/search.php:34 include/features.php:84
 msgid "Saved Searches"
 msgstr "запомненные поиски"
 
-#: ../../mod/network.php:195 ../../include/group.php:275
+#: mod/network.php:201 include/group.php:293
 msgid "add"
 msgstr "добавить"
 
-#: ../../mod/network.php:356
+#: mod/network.php:365
 msgid "Commented Order"
-msgstr "Прокомментированный запрос"
+msgstr "Последние комментарии"
 
-#: ../../mod/network.php:359
+#: mod/network.php:368
 msgid "Sort by Comment Date"
 msgstr "Сортировать по дате комментария"
 
-#: ../../mod/network.php:362
+#: mod/network.php:373
 msgid "Posted Order"
-msgstr "Отправленный запрос"
+msgstr "Лента записей"
 
-#: ../../mod/network.php:365
+#: mod/network.php:376
 msgid "Sort by Post Date"
 msgstr "Сортировать по дате отправки"
 
-#: ../../mod/network.php:374
+#: mod/network.php:387
 msgid "Posts that mention or involve you"
 msgstr ""
 
-#: ../../mod/network.php:380
+#: mod/network.php:395
 msgid "New"
 msgstr "Новый"
 
-#: ../../mod/network.php:383
+#: mod/network.php:398
 msgid "Activity Stream - by date"
 msgstr "Лента активности - по дате"
 
-#: ../../mod/network.php:389
+#: mod/network.php:406
 msgid "Shared Links"
 msgstr "Ссылки, которыми поделились"
 
-#: ../../mod/network.php:392
+#: mod/network.php:409
 msgid "Interesting Links"
 msgstr "Интересные ссылки"
 
-#: ../../mod/network.php:398
+#: mod/network.php:417
 msgid "Starred"
 msgstr "Помеченный"
 
-#: ../../mod/network.php:401
+#: mod/network.php:420
 msgid "Favourite Posts"
 msgstr "Избранные посты"
 
-#: ../../mod/network.php:463
+#: mod/network.php:479
 #, php-format
 msgid "Warning: This group contains %s member from an insecure network."
 msgid_plural ""
@@ -2945,4152 +3476,4632 @@ msgid_plural ""
 msgstr[0] "Внимание: Эта группа содержит %s участника с незащищенной сети."
 msgstr[1] "Внимание: Эта группа содержит %s участников с незащищенной сети."
 msgstr[2] "Внимание: Эта группа содержит %s участников с незащищенной сети."
+msgstr[3] "Внимание: Эта группа содержит %s участников с незащищенной сети."
 
-#: ../../mod/network.php:466
+#: mod/network.php:482
 msgid "Private messages to this group are at risk of public disclosure."
 msgstr "Личные сообщения к этой группе находятся под угрозой обнародования."
 
-#: ../../mod/network.php:520 ../../mod/content.php:119
+#: mod/network.php:549 mod/content.php:119
 msgid "No such group"
 msgstr "Нет такой группы"
 
-#: ../../mod/network.php:537 ../../mod/content.php:130
-msgid "Group is empty"
-msgstr "Группа пуста"
+#: mod/network.php:580 mod/content.php:135
+#, php-format
+msgid "Group: %s"
+msgstr "Группа: %s"
 
-#: ../../mod/network.php:544 ../../mod/content.php:134
-msgid "Group: "
-msgstr "Группа: "
-
-#: ../../mod/network.php:554
-msgid "Contact: "
-msgstr "Контакт: "
-
-#: ../../mod/network.php:556
+#: mod/network.php:608
 msgid "Private messages to this person are at risk of public disclosure."
 msgstr "Личные сообщения этому человеку находятся под угрозой обнародования."
 
-#: ../../mod/network.php:561
+#: mod/network.php:613
 msgid "Invalid contact."
 msgstr "Недопустимый контакт."
 
-#: ../../mod/allfriends.php:34
-#, php-format
-msgid "Friends of %s"
-msgstr "%s Друзья"
-
-#: ../../mod/allfriends.php:40
+#: mod/allfriends.php:43
 msgid "No friends to display."
 msgstr "Нет друзей."
 
-#: ../../mod/events.php:66
+#: mod/events.php:71 mod/events.php:73
+msgid "Event can not end before it has started."
+msgstr ""
+
+#: mod/events.php:80 mod/events.php:82
 msgid "Event title and start time are required."
 msgstr "Название мероприятия и время начала обязательны для заполнения."
 
-#: ../../mod/events.php:291
+#: mod/events.php:201
+msgid "Sun"
+msgstr "Вс"
+
+#: mod/events.php:202
+msgid "Mon"
+msgstr "Пн"
+
+#: mod/events.php:203
+msgid "Tue"
+msgstr "Вт"
+
+#: mod/events.php:204
+msgid "Wed"
+msgstr "Ср"
+
+#: mod/events.php:205
+msgid "Thu"
+msgstr "Чт"
+
+#: mod/events.php:206
+msgid "Fri"
+msgstr "Пт"
+
+#: mod/events.php:207
+msgid "Sat"
+msgstr "Сб"
+
+#: mod/events.php:208 mod/settings.php:948 include/text.php:1274
+msgid "Sunday"
+msgstr "Воскресенье"
+
+#: mod/events.php:209 mod/settings.php:948 include/text.php:1274
+msgid "Monday"
+msgstr "Понедельник"
+
+#: mod/events.php:210 include/text.php:1274
+msgid "Tuesday"
+msgstr "Вторник"
+
+#: mod/events.php:211 include/text.php:1274
+msgid "Wednesday"
+msgstr "Среда"
+
+#: mod/events.php:212 include/text.php:1274
+msgid "Thursday"
+msgstr "Четверг"
+
+#: mod/events.php:213 include/text.php:1274
+msgid "Friday"
+msgstr "Пятница"
+
+#: mod/events.php:214 include/text.php:1274
+msgid "Saturday"
+msgstr "Суббота"
+
+#: mod/events.php:215
+msgid "Jan"
+msgstr "Янв"
+
+#: mod/events.php:216
+msgid "Feb"
+msgstr "Фев"
+
+#: mod/events.php:217
+msgid "Mar"
+msgstr "Мрт"
+
+#: mod/events.php:218
+msgid "Apr"
+msgstr "Апр"
+
+#: mod/events.php:219 mod/events.php:231 include/text.php:1278
+msgid "May"
+msgstr "Май"
+
+#: mod/events.php:220
+msgid "Jun"
+msgstr "Июн"
+
+#: mod/events.php:221
+msgid "Jul"
+msgstr "Июл"
+
+#: mod/events.php:222
+msgid "Aug"
+msgstr "Авг"
+
+#: mod/events.php:223
+msgid "Sept"
+msgstr "Сен"
+
+#: mod/events.php:224
+msgid "Oct"
+msgstr "Окт"
+
+#: mod/events.php:225
+msgid "Nov"
+msgstr "Нбр"
+
+#: mod/events.php:226
+msgid "Dec"
+msgstr "Дек"
+
+#: mod/events.php:227 include/text.php:1278
+msgid "January"
+msgstr "Январь"
+
+#: mod/events.php:228 include/text.php:1278
+msgid "February"
+msgstr "Февраль"
+
+#: mod/events.php:229 include/text.php:1278
+msgid "March"
+msgstr "Март"
+
+#: mod/events.php:230 include/text.php:1278
+msgid "April"
+msgstr "Апрель"
+
+#: mod/events.php:232 include/text.php:1278
+msgid "June"
+msgstr "Июнь"
+
+#: mod/events.php:233 include/text.php:1278
+msgid "July"
+msgstr "Июль"
+
+#: mod/events.php:234 include/text.php:1278
+msgid "August"
+msgstr "Август"
+
+#: mod/events.php:235 include/text.php:1278
+msgid "September"
+msgstr "Сентябрь"
+
+#: mod/events.php:236 include/text.php:1278
+msgid "October"
+msgstr "Октябрь"
+
+#: mod/events.php:237 include/text.php:1278
+msgid "November"
+msgstr "Ноябрь"
+
+#: mod/events.php:238 include/text.php:1278
+msgid "December"
+msgstr "Декабрь"
+
+#: mod/events.php:239
+msgid "today"
+msgstr "сегодня"
+
+#: mod/events.php:240 include/datetime.php:288
+msgid "month"
+msgstr "мес."
+
+#: mod/events.php:241 include/datetime.php:289
+msgid "week"
+msgstr "неделя"
+
+#: mod/events.php:242 include/datetime.php:290
+msgid "day"
+msgstr "день"
+
+#: mod/events.php:377
 msgid "l, F j"
 msgstr "l, j F"
 
-#: ../../mod/events.php:313
+#: mod/events.php:399
 msgid "Edit event"
 msgstr "Редактировать мероприятие"
 
-#: ../../mod/events.php:335 ../../include/text.php:1647
-#: ../../include/text.php:1657
+#: mod/events.php:421 include/text.php:1728 include/text.php:1735
 msgid "link to source"
-msgstr "ссылка на источник"
+msgstr "ссылка на сообщение"
 
-#: ../../mod/events.php:370 ../../boot.php:2143 ../../include/nav.php:80
-#: ../../view/theme/diabook/theme.php:127
+#: mod/events.php:456 include/identity.php:722 include/nav.php:79
+#: include/nav.php:140 view/theme/diabook/theme.php:127
 msgid "Events"
 msgstr "Мероприятия"
 
-#: ../../mod/events.php:371
+#: mod/events.php:457
 msgid "Create New Event"
 msgstr "Создать новое мероприятие"
 
-#: ../../mod/events.php:372
+#: mod/events.php:458
 msgid "Previous"
 msgstr "Назад"
 
-#: ../../mod/events.php:373 ../../mod/install.php:207
+#: mod/events.php:459 mod/install.php:220
 msgid "Next"
 msgstr "Далее"
 
-#: ../../mod/events.php:446
-msgid "hour:minute"
-msgstr "час:минута"
-
-#: ../../mod/events.php:456
+#: mod/events.php:554
 msgid "Event details"
 msgstr "Сведения о мероприятии"
 
-#: ../../mod/events.php:457
-#, php-format
-msgid "Format is %s %s. Starting date and Title are required."
-msgstr "Формат %s %s. Необхлдима дата старта и заголовок."
+#: mod/events.php:555
+msgid "Starting date and Title are required."
+msgstr ""
 
-#: ../../mod/events.php:459
+#: mod/events.php:556
 msgid "Event Starts:"
 msgstr "Начало мероприятия:"
 
-#: ../../mod/events.php:459 ../../mod/events.php:473
+#: mod/events.php:556 mod/events.php:568
 msgid "Required"
 msgstr "Требуется"
 
-#: ../../mod/events.php:462
+#: mod/events.php:558
 msgid "Finish date/time is not known or not relevant"
 msgstr "Дата/время окончания не известны, или не указаны"
 
-#: ../../mod/events.php:464
+#: mod/events.php:560
 msgid "Event Finishes:"
 msgstr "Окончание мероприятия:"
 
-#: ../../mod/events.php:467
+#: mod/events.php:562
 msgid "Adjust for viewer timezone"
 msgstr "Настройка часового пояса"
 
-#: ../../mod/events.php:469
+#: mod/events.php:564
 msgid "Description:"
 msgstr "Описание:"
 
-#: ../../mod/events.php:471 ../../mod/directory.php:136 ../../boot.php:1648
-#: ../../include/bb2diaspora.php:170 ../../include/event.php:40
-msgid "Location:"
-msgstr "Откуда:"
-
-#: ../../mod/events.php:473
+#: mod/events.php:568
 msgid "Title:"
 msgstr "Титул:"
 
-#: ../../mod/events.php:475
+#: mod/events.php:570
 msgid "Share this event"
 msgstr "Поделитесь этим мероприятием"
 
-#: ../../mod/content.php:437 ../../mod/content.php:740
-#: ../../mod/photos.php:1653 ../../object/Item.php:129
-#: ../../include/conversation.php:613
+#: mod/events.php:572 mod/content.php:721 mod/editpost.php:145
+#: mod/photos.php:1631 mod/photos.php:1679 mod/photos.php:1767
+#: object/Item.php:719 include/conversation.php:1216
+msgid "Preview"
+msgstr "Предварительный просмотр"
+
+#: mod/credits.php:16
+msgid "Credits"
+msgstr ""
+
+#: mod/credits.php:17
+msgid ""
+"Friendica is a community project, that would not be possible without the "
+"help of many people. Here is a list of those who have contributed to the "
+"code or the translation of Friendica. Thank you all!"
+msgstr ""
+
+#: mod/content.php:439 mod/content.php:742 mod/photos.php:1722
+#: object/Item.php:133 include/conversation.php:634
 msgid "Select"
 msgstr "Выберите"
 
-#: ../../mod/content.php:471 ../../mod/content.php:852
-#: ../../mod/content.php:853 ../../object/Item.php:326
-#: ../../object/Item.php:327 ../../include/conversation.php:654
+#: mod/content.php:473 mod/content.php:854 mod/content.php:855
+#: object/Item.php:357 object/Item.php:358 include/conversation.php:675
 #, php-format
 msgid "View %s's profile @ %s"
 msgstr "Просмотреть профиль %s [@ %s]"
 
-#: ../../mod/content.php:481 ../../mod/content.php:864
-#: ../../object/Item.php:340 ../../include/conversation.php:674
+#: mod/content.php:483 mod/content.php:866 object/Item.php:371
+#: include/conversation.php:695
 #, php-format
 msgid "%s from %s"
 msgstr "%s с %s"
 
-#: ../../mod/content.php:497 ../../include/conversation.php:690
+#: mod/content.php:499 include/conversation.php:711
 msgid "View in context"
 msgstr "Смотреть в контексте"
 
-#: ../../mod/content.php:603 ../../object/Item.php:387
+#: mod/content.php:605 object/Item.php:419
 #, php-format
 msgid "%d comment"
 msgid_plural "%d comments"
 msgstr[0] "%d комментарий"
 msgstr[1] "%d комментариев"
 msgstr[2] "%d комментариев"
+msgstr[3] "%d комментариев"
 
-#: ../../mod/content.php:605 ../../object/Item.php:389
-#: ../../object/Item.php:402 ../../include/text.php:1972
+#: mod/content.php:607 object/Item.php:421 object/Item.php:434
+#: include/text.php:2004
 msgid "comment"
 msgid_plural "comments"
 msgstr[0] ""
 msgstr[1] ""
 msgstr[2] "комментарий"
+msgstr[3] "комментарий"
 
-#: ../../mod/content.php:606 ../../boot.php:751 ../../object/Item.php:390
-#: ../../include/contact_widgets.php:205
+#: mod/content.php:608 boot.php:870 object/Item.php:422
+#: include/contact_widgets.php:242 include/forums.php:110
+#: include/items.php:5207 view/theme/vier/theme.php:264
 msgid "show more"
 msgstr "показать больше"
 
-#: ../../mod/content.php:620 ../../mod/photos.php:1359
-#: ../../object/Item.php:116
+#: mod/content.php:622 mod/photos.php:1418 object/Item.php:117
 msgid "Private Message"
 msgstr "Личное сообщение"
 
-#: ../../mod/content.php:684 ../../mod/photos.php:1542
-#: ../../object/Item.php:231
+#: mod/content.php:686 mod/photos.php:1607 object/Item.php:253
 msgid "I like this (toggle)"
 msgstr "Нравится"
 
-#: ../../mod/content.php:684 ../../object/Item.php:231
+#: mod/content.php:686 object/Item.php:253
 msgid "like"
 msgstr "нравится"
 
-#: ../../mod/content.php:685 ../../mod/photos.php:1543
-#: ../../object/Item.php:232
+#: mod/content.php:687 mod/photos.php:1608 object/Item.php:254
 msgid "I don't like this (toggle)"
 msgstr "Не нравится"
 
-#: ../../mod/content.php:685 ../../object/Item.php:232
+#: mod/content.php:687 object/Item.php:254
 msgid "dislike"
 msgstr "не нравитса"
 
-#: ../../mod/content.php:687 ../../object/Item.php:234
+#: mod/content.php:689 object/Item.php:256
 msgid "Share this"
 msgstr "Поделитесь этим"
 
-#: ../../mod/content.php:687 ../../object/Item.php:234
+#: mod/content.php:689 object/Item.php:256
 msgid "share"
 msgstr "делиться"
 
-#: ../../mod/content.php:707 ../../mod/photos.php:1562
-#: ../../mod/photos.php:1606 ../../mod/photos.php:1694
-#: ../../object/Item.php:675
+#: mod/content.php:709 mod/photos.php:1627 mod/photos.php:1675
+#: mod/photos.php:1763 object/Item.php:707
 msgid "This is you"
 msgstr "Это вы"
 
-#: ../../mod/content.php:709 ../../mod/photos.php:1564
-#: ../../mod/photos.php:1608 ../../mod/photos.php:1696 ../../boot.php:750
-#: ../../object/Item.php:361 ../../object/Item.php:677
+#: mod/content.php:711 mod/photos.php:1629 mod/photos.php:1677
+#: mod/photos.php:1765 boot.php:869 object/Item.php:393 object/Item.php:709
 msgid "Comment"
-msgstr "Комментарий"
+msgstr "Оставить комментарий"
 
-#: ../../mod/content.php:711 ../../object/Item.php:679
+#: mod/content.php:713 object/Item.php:711
 msgid "Bold"
 msgstr "Жирный"
 
-#: ../../mod/content.php:712 ../../object/Item.php:680
+#: mod/content.php:714 object/Item.php:712
 msgid "Italic"
 msgstr "Kурсивный"
 
-#: ../../mod/content.php:713 ../../object/Item.php:681
+#: mod/content.php:715 object/Item.php:713
 msgid "Underline"
 msgstr "Подчеркнутый"
 
-#: ../../mod/content.php:714 ../../object/Item.php:682
+#: mod/content.php:716 object/Item.php:714
 msgid "Quote"
 msgstr "Цитата"
 
-#: ../../mod/content.php:715 ../../object/Item.php:683
+#: mod/content.php:717 object/Item.php:715
 msgid "Code"
 msgstr "Код"
 
-#: ../../mod/content.php:716 ../../object/Item.php:684
+#: mod/content.php:718 object/Item.php:716
 msgid "Image"
 msgstr "Изображение / Фото"
 
-#: ../../mod/content.php:717 ../../object/Item.php:685
+#: mod/content.php:719 object/Item.php:717
 msgid "Link"
 msgstr "Ссылка"
 
-#: ../../mod/content.php:718 ../../object/Item.php:686
+#: mod/content.php:720 object/Item.php:718
 msgid "Video"
 msgstr "Видео"
 
-#: ../../mod/content.php:719 ../../mod/editpost.php:145
-#: ../../mod/photos.php:1566 ../../mod/photos.php:1610
-#: ../../mod/photos.php:1698 ../../object/Item.php:687
-#: ../../include/conversation.php:1126
-msgid "Preview"
-msgstr "предварительный просмотр"
-
-#: ../../mod/content.php:728 ../../mod/settings.php:676
-#: ../../object/Item.php:120
+#: mod/content.php:730 mod/settings.php:721 object/Item.php:122
+#: object/Item.php:124
 msgid "Edit"
 msgstr "Редактировать"
 
-#: ../../mod/content.php:753 ../../object/Item.php:195
+#: mod/content.php:755 object/Item.php:217
 msgid "add star"
 msgstr "пометить"
 
-#: ../../mod/content.php:754 ../../object/Item.php:196
+#: mod/content.php:756 object/Item.php:218
 msgid "remove star"
 msgstr "убрать метку"
 
-#: ../../mod/content.php:755 ../../object/Item.php:197
+#: mod/content.php:757 object/Item.php:219
 msgid "toggle star status"
 msgstr "переключить статус"
 
-#: ../../mod/content.php:758 ../../object/Item.php:200
+#: mod/content.php:760 object/Item.php:222
 msgid "starred"
 msgstr "помечено"
 
-#: ../../mod/content.php:759 ../../object/Item.php:220
+#: mod/content.php:761 object/Item.php:242
 msgid "add tag"
 msgstr "добавить ключевое слово (таг)"
 
-#: ../../mod/content.php:763 ../../object/Item.php:133
+#: mod/content.php:765 object/Item.php:137
 msgid "save to folder"
 msgstr "сохранить в папке"
 
-#: ../../mod/content.php:854 ../../object/Item.php:328
+#: mod/content.php:856 object/Item.php:359
 msgid "to"
 msgstr "к"
 
-#: ../../mod/content.php:855 ../../object/Item.php:330
+#: mod/content.php:857 object/Item.php:361
 msgid "Wall-to-Wall"
 msgstr "Стена-на-Стену"
 
-#: ../../mod/content.php:856 ../../object/Item.php:331
+#: mod/content.php:858 object/Item.php:362
 msgid "via Wall-To-Wall:"
 msgstr "через Стена-на-Стену:"
 
-#: ../../mod/removeme.php:46 ../../mod/removeme.php:49
+#: mod/removeme.php:46 mod/removeme.php:49
 msgid "Remove My Account"
 msgstr "Удалить мой аккаунт"
 
-#: ../../mod/removeme.php:47
+#: mod/removeme.php:47
 msgid ""
 "This will completely remove your account. Once this has been done it is not "
 "recoverable."
-msgstr "Это позволит полностью удалить ваш аккаунт. Как только это будет сделано, аккаунт восстановлению не подлежит."
+msgstr ""
+"Это позволит полностью удалить ваш аккаунт. Как только это будет сделано, "
+"аккаунт восстановлению не подлежит."
 
-#: ../../mod/removeme.php:48
+#: mod/removeme.php:48
 msgid "Please enter your password for verification:"
 msgstr "Пожалуйста, введите свой пароль для проверки:"
 
-#: ../../mod/install.php:117
+#: mod/install.php:128
 msgid "Friendica Communications Server - Setup"
 msgstr "Коммуникационный сервер Friendica - Доступ"
 
-#: ../../mod/install.php:123
+#: mod/install.php:134
 msgid "Could not connect to database."
 msgstr "Не удалось подключиться к базе данных."
 
-#: ../../mod/install.php:127
+#: mod/install.php:138
 msgid "Could not create table."
 msgstr "Не удалось создать таблицу."
 
-#: ../../mod/install.php:133
+#: mod/install.php:144
 msgid "Your Friendica site database has been installed."
 msgstr "База данных сайта установлена."
 
-#: ../../mod/install.php:138
+#: mod/install.php:149
 msgid ""
 "You may need to import the file \"database.sql\" manually using phpmyadmin "
 "or mysql."
-msgstr "Вам может понадобиться импортировать файл \"database.sql\" вручную с помощью PhpMyAdmin или MySQL."
+msgstr ""
+"Вам может понадобиться импортировать файл \"database.sql\" вручную с помощью "
+"PhpMyAdmin или MySQL."
 
-#: ../../mod/install.php:139 ../../mod/install.php:206
-#: ../../mod/install.php:525
+#: mod/install.php:150 mod/install.php:219 mod/install.php:577
 msgid "Please see the file \"INSTALL.txt\"."
 msgstr "Пожалуйста, смотрите файл \"INSTALL.txt\"."
 
-#: ../../mod/install.php:203
+#: mod/install.php:162
+msgid "Database already in use."
+msgstr ""
+
+#: mod/install.php:216
 msgid "System check"
 msgstr "Проверить систему"
 
-#: ../../mod/install.php:208
+#: mod/install.php:221
 msgid "Check again"
 msgstr "Проверить еще раз"
 
-#: ../../mod/install.php:227
+#: mod/install.php:240
 msgid "Database connection"
 msgstr "Подключение к базе данных"
 
-#: ../../mod/install.php:228
+#: mod/install.php:241
 msgid ""
 "In order to install Friendica we need to know how to connect to your "
 "database."
-msgstr "Для того, чтобы установить Friendica, мы должны знать, как подключиться к базе данных."
+msgstr ""
+"Для того, чтобы установить Friendica, мы должны знать, как подключиться к "
+"базе данных."
 
-#: ../../mod/install.php:229
+#: mod/install.php:242
 msgid ""
 "Please contact your hosting provider or site administrator if you have "
 "questions about these settings."
-msgstr "Пожалуйста, свяжитесь с вашим хостинг-провайдером или администратором сайта, если у вас есть вопросы об этих параметрах."
+msgstr ""
+"Пожалуйста, свяжитесь с вашим хостинг-провайдером или администратором сайта, "
+"если у вас есть вопросы об этих параметрах."
 
-#: ../../mod/install.php:230
+#: mod/install.php:243
 msgid ""
 "The database you specify below should already exist. If it does not, please "
 "create it before continuing."
-msgstr "Базы данных, указанная ниже, должна уже существовать. Если этого нет, пожалуйста, создайте ее перед продолжением."
+msgstr ""
+"Базы данных, указанная ниже, должна уже существовать. Если этого нет, "
+"пожалуйста, создайте ее перед продолжением."
 
-#: ../../mod/install.php:234
+#: mod/install.php:247
 msgid "Database Server Name"
 msgstr "Имя сервера базы данных"
 
-#: ../../mod/install.php:235
+#: mod/install.php:248
 msgid "Database Login Name"
 msgstr "Логин базы данных"
 
-#: ../../mod/install.php:236
+#: mod/install.php:249
 msgid "Database Login Password"
 msgstr "Пароль базы данных"
 
-#: ../../mod/install.php:237
+#: mod/install.php:250
 msgid "Database Name"
 msgstr "Имя базы данных"
 
-#: ../../mod/install.php:238 ../../mod/install.php:277
+#: mod/install.php:251 mod/install.php:290
 msgid "Site administrator email address"
 msgstr "Адрес электронной почты администратора сайта"
 
-#: ../../mod/install.php:238 ../../mod/install.php:277
+#: mod/install.php:251 mod/install.php:290
 msgid ""
 "Your account email address must match this in order to use the web admin "
 "panel."
-msgstr "Ваш адрес электронной почты аккаунта должен соответствовать этому, чтобы использовать веб-панель администратора."
+msgstr ""
+"Ваш адрес электронной почты аккаунта должен соответствовать этому, чтобы "
+"использовать веб-панель администратора."
 
-#: ../../mod/install.php:242 ../../mod/install.php:280
+#: mod/install.php:255 mod/install.php:293
 msgid "Please select a default timezone for your website"
 msgstr "Пожалуйста, выберите часовой пояс по умолчанию для вашего сайта"
 
-#: ../../mod/install.php:267
+#: mod/install.php:280
 msgid "Site settings"
 msgstr "Настройки сайта"
 
-#: ../../mod/install.php:321
+#: mod/install.php:334
 msgid "Could not find a command line version of PHP in the web server PATH."
 msgstr "Не удалось найти PATH веб-сервера в установках PHP."
 
-#: ../../mod/install.php:322
+#: mod/install.php:335
 msgid ""
 "If you don't have a command line version of PHP installed on server, you "
-"will not be able to run background polling via cron. See <a "
-"href='http://friendica.com/node/27'>'Activating scheduled tasks'</a>"
-msgstr "Если на вашем сервере не установлена версия командной строки PHP, вы не будете иметь возможность запускать фоновые опросы через крон. См. <a href='http://friendica.com/node/27'> 'Активация запланированных задачах' </a>"
+"will not be able to run background polling via cron. See <a href='https://"
+"github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-"
+"poller'>'Setup the poller'</a>"
+msgstr ""
 
-#: ../../mod/install.php:326
+#: mod/install.php:339
 msgid "PHP executable path"
 msgstr "PHP executable path"
 
-#: ../../mod/install.php:326
+#: mod/install.php:339
 msgid ""
 "Enter full path to php executable. You can leave this blank to continue the "
 "installation."
-msgstr "Введите полный путь к исполняемому файлу PHP. Вы можете оставить это поле пустым, чтобы продолжить установку."
+msgstr ""
+"Введите полный путь к исполняемому файлу PHP. Вы можете оставить это поле "
+"пустым, чтобы продолжить установку."
 
-#: ../../mod/install.php:331
+#: mod/install.php:344
 msgid "Command line PHP"
 msgstr "Command line PHP"
 
-#: ../../mod/install.php:340
+#: mod/install.php:353
 msgid "PHP executable is not the php cli binary (could be cgi-fgci version)"
 msgstr ""
 
-#: ../../mod/install.php:341
+#: mod/install.php:354
 msgid "Found PHP version: "
 msgstr "Найденная PHP версия: "
 
-#: ../../mod/install.php:343
+#: mod/install.php:356
 msgid "PHP cli binary"
 msgstr "PHP cli binary"
 
-#: ../../mod/install.php:354
+#: mod/install.php:367
 msgid ""
 "The command line version of PHP on your system does not have "
 "\"register_argc_argv\" enabled."
 msgstr "Не включено \"register_argc_argv\" в установках PHP."
 
-#: ../../mod/install.php:355
+#: mod/install.php:368
 msgid "This is required for message delivery to work."
 msgstr "Это необходимо для работы доставки сообщений."
 
-#: ../../mod/install.php:357
+#: mod/install.php:370
 msgid "PHP register_argc_argv"
 msgstr "PHP register_argc_argv"
 
-#: ../../mod/install.php:378
+#: mod/install.php:391
 msgid ""
 "Error: the \"openssl_pkey_new\" function on this system is not able to "
 "generate encryption keys"
-msgstr "Ошибка: функция \"openssl_pkey_new\" в этой системе не в состоянии генерировать ключи шифрования"
+msgstr ""
+"Ошибка: функция \"openssl_pkey_new\" в этой системе не в состоянии "
+"генерировать ключи шифрования"
 
-#: ../../mod/install.php:379
+#: mod/install.php:392
 msgid ""
-"If running under Windows, please see "
-"\"http://www.php.net/manual/en/openssl.installation.php\"."
-msgstr "Если вы работаете под Windows, см. \"http://www.php.net/manual/en/openssl.installation.php\"."
+"If running under Windows, please see \"http://www.php.net/manual/en/openssl."
+"installation.php\"."
+msgstr ""
+"Если вы работаете под Windows, см. \"http://www.php.net/manual/en/openssl."
+"installation.php\"."
 
-#: ../../mod/install.php:381
+#: mod/install.php:394
 msgid "Generate encryption keys"
 msgstr "Генерация шифрованых ключей"
 
-#: ../../mod/install.php:388
+#: mod/install.php:401
 msgid "libCurl PHP module"
 msgstr "libCurl PHP модуль"
 
-#: ../../mod/install.php:389
+#: mod/install.php:402
 msgid "GD graphics PHP module"
 msgstr "GD graphics PHP модуль"
 
-#: ../../mod/install.php:390
+#: mod/install.php:403
 msgid "OpenSSL PHP module"
 msgstr "OpenSSL PHP модуль"
 
-#: ../../mod/install.php:391
+#: mod/install.php:404
 msgid "mysqli PHP module"
 msgstr "mysqli PHP модуль"
 
-#: ../../mod/install.php:392
+#: mod/install.php:405
 msgid "mb_string PHP module"
 msgstr "mb_string PHP модуль"
 
-#: ../../mod/install.php:397 ../../mod/install.php:399
+#: mod/install.php:406
+msgid "mcrypt PHP module"
+msgstr ""
+
+#: mod/install.php:411 mod/install.php:413
 msgid "Apache mod_rewrite module"
 msgstr "Apache mod_rewrite module"
 
-#: ../../mod/install.php:397
+#: mod/install.php:411
 msgid ""
 "Error: Apache webserver mod-rewrite module is required but not installed."
-msgstr "Ошибка: необходим модуль веб-сервера Apache mod-rewrite, но он не установлен."
+msgstr ""
+"Ошибка: необходим модуль веб-сервера Apache mod-rewrite, но он не установлен."
 
-#: ../../mod/install.php:405
+#: mod/install.php:419
 msgid "Error: libCURL PHP module required but not installed."
 msgstr "Ошибка: необходим libCURL PHP модуль, но он не установлен."
 
-#: ../../mod/install.php:409
+#: mod/install.php:423
 msgid ""
 "Error: GD graphics PHP module with JPEG support required but not installed."
-msgstr "Ошибка: необходим PHP модуль GD графики с поддержкой JPEG, но он не установлен."
+msgstr ""
+"Ошибка: необходим PHP модуль GD графики с поддержкой JPEG, но он не "
+"установлен."
 
-#: ../../mod/install.php:413
+#: mod/install.php:427
 msgid "Error: openssl PHP module required but not installed."
 msgstr "Ошибка: необходим PHP модуль OpenSSL, но он не установлен."
 
-#: ../../mod/install.php:417
+#: mod/install.php:431
 msgid "Error: mysqli PHP module required but not installed."
 msgstr "Ошибка: необходим PHP модуль MySQLi, но он не установлен."
 
-#: ../../mod/install.php:421
+#: mod/install.php:435
 msgid "Error: mb_string PHP module required but not installed."
 msgstr "Ошибка: необходим PHP модуль mb_string, но он не установлен."
 
-#: ../../mod/install.php:438
-msgid ""
-"The web installer needs to be able to create a file called \".htconfig.php\""
-" in the top folder of your web server and it is unable to do so."
-msgstr "Веб-инсталлятору требуется создать файл с именем \". htconfig.php\" в верхней папке веб-сервера, но он не в состоянии это сделать."
+#: mod/install.php:439
+msgid "Error: mcrypt PHP module required but not installed."
+msgstr ""
 
-#: ../../mod/install.php:439
+#: mod/install.php:451
+msgid ""
+"Function mcrypt_create_iv() is not defined. This is needed to enable RINO2 "
+"encryption layer."
+msgstr ""
+
+#: mod/install.php:453
+msgid "mcrypt_create_iv() function"
+msgstr ""
+
+#: mod/install.php:469
+msgid ""
+"The web installer needs to be able to create a file called \".htconfig.php\" "
+"in the top folder of your web server and it is unable to do so."
+msgstr ""
+"Веб-инсталлятору требуется создать файл с именем \". htconfig.php\" в "
+"верхней папке веб-сервера, но он не в состоянии это сделать."
+
+#: mod/install.php:470
 msgid ""
 "This is most often a permission setting, as the web server may not be able "
 "to write files in your folder - even if you can."
-msgstr "Это наиболее частые параметры разрешений, когда веб-сервер не может записать файлы в папке - даже если вы можете."
+msgstr ""
+"Это наиболее частые параметры разрешений, когда веб-сервер не может записать "
+"файлы в папке - даже если вы можете."
 
-#: ../../mod/install.php:440
+#: mod/install.php:471
 msgid ""
 "At the end of this procedure, we will give you a text to save in a file "
 "named .htconfig.php in your Friendica top folder."
-msgstr "В конце этой процедуры, мы дадим вам текст, для сохранения в файле с именем .htconfig.php в корневой папке, где установлена Friendica."
+msgstr ""
+"В конце этой процедуры, мы дадим вам текст, для сохранения в файле с именем ."
+"htconfig.php в корневой папке, где установлена Friendica."
 
-#: ../../mod/install.php:441
+#: mod/install.php:472
 msgid ""
-"You can alternatively skip this procedure and perform a manual installation."
-" Please see the file \"INSTALL.txt\" for instructions."
-msgstr "В качестве альтернативы вы можете пропустить эту процедуру и выполнить установку вручную. Пожалуйста, обратитесь к файлу \"INSTALL.txt\" для получения инструкций."
+"You can alternatively skip this procedure and perform a manual installation. "
+"Please see the file \"INSTALL.txt\" for instructions."
+msgstr ""
+"В качестве альтернативы вы можете пропустить эту процедуру и выполнить "
+"установку вручную. Пожалуйста, обратитесь к файлу \"INSTALL.txt\" для "
+"получения инструкций."
 
-#: ../../mod/install.php:444
+#: mod/install.php:475
 msgid ".htconfig.php is writable"
 msgstr ".htconfig.php is writable"
 
-#: ../../mod/install.php:454
+#: mod/install.php:485
 msgid ""
 "Friendica uses the Smarty3 template engine to render its web views. Smarty3 "
 "compiles templates to PHP to speed up rendering."
-msgstr "Friendica использует механизм шаблонов Smarty3 для генерации веб-страниц. Smarty3 компилирует шаблоны в PHP для увеличения скорости загрузки."
+msgstr ""
+"Friendica использует механизм шаблонов Smarty3 для генерации веб-страниц. "
+"Smarty3 компилирует шаблоны в PHP для увеличения скорости загрузки."
 
-#: ../../mod/install.php:455
+#: mod/install.php:486
 msgid ""
 "In order to store these compiled templates, the web server needs to have "
 "write access to the directory view/smarty3/ under the Friendica top level "
 "folder."
-msgstr "Для того чтобы хранить эти скомпилированные шаблоны, веб-сервер должен иметь доступ на запись для папки view/smarty3 в директории, где установлена Friendica."
+msgstr ""
+"Для того чтобы хранить эти скомпилированные шаблоны, веб-сервер должен иметь "
+"доступ на запись для папки view/smarty3 в директории, где установлена "
+"Friendica."
 
-#: ../../mod/install.php:456
+#: mod/install.php:487
 msgid ""
-"Please ensure that the user that your web server runs as (e.g. www-data) has"
-" write access to this folder."
-msgstr "Пожалуйста, убедитесь, что пользователь, под которым работает ваш веб-сервер (например www-data), имеет доступ на запись в этой папке."
+"Please ensure that the user that your web server runs as (e.g. www-data) has "
+"write access to this folder."
+msgstr ""
+"Пожалуйста, убедитесь, что пользователь, под которым работает ваш веб-сервер "
+"(например www-data), имеет доступ на запись в этой папке."
 
-#: ../../mod/install.php:457
+#: mod/install.php:488
 msgid ""
 "Note: as a security measure, you should give the web server write access to "
 "view/smarty3/ only--not the template files (.tpl) that it contains."
-msgstr "Примечание: в качестве меры безопасности, вы должны дать вебсерверу доступ на запись только в view/smarty3 - но не на сами файлы шаблонов (.tpl)., Которые содержатся в этой папке."
+msgstr ""
+"Примечание: в качестве меры безопасности, вы должны дать вебсерверу доступ "
+"на запись только в view/smarty3 - но не на сами файлы шаблонов (.tpl)., "
+"Которые содержатся в этой папке."
 
-#: ../../mod/install.php:460
+#: mod/install.php:491
 msgid "view/smarty3 is writable"
 msgstr "view/smarty3 доступен для записи"
 
-#: ../../mod/install.php:472
+#: mod/install.php:507
 msgid ""
 "Url rewrite in .htaccess is not working. Check your server configuration."
-msgstr "Url rewrite в .htaccess не работает. Проверьте конфигурацию вашего сервера.."
+msgstr ""
+"Url rewrite в .htaccess не работает. Проверьте конфигурацию вашего сервера.."
 
-#: ../../mod/install.php:474
+#: mod/install.php:509
 msgid "Url rewrite is working"
 msgstr "Url rewrite работает"
 
-#: ../../mod/install.php:484
+#: mod/install.php:526
+msgid "ImageMagick PHP extension is installed"
+msgstr ""
+
+#: mod/install.php:528
+msgid "ImageMagick supports GIF"
+msgstr ""
+
+#: mod/install.php:536
 msgid ""
 "The database configuration file \".htconfig.php\" could not be written. "
 "Please use the enclosed text to create a configuration file in your web "
 "server root."
-msgstr "Файл конфигурации базы данных \".htconfig.php\" не могла быть записан. Пожалуйста, используйте приложенный текст, чтобы создать конфигурационный файл в корневом каталоге веб-сервера."
+msgstr ""
+"Файл конфигурации базы данных \".htconfig.php\" не могла быть записан. "
+"Пожалуйста, используйте приложенный текст, чтобы создать конфигурационный "
+"файл в корневом каталоге веб-сервера."
 
-#: ../../mod/install.php:523
+#: mod/install.php:575
 msgid "<h1>What next</h1>"
 msgstr "<h1>Что далее</h1>"
 
-#: ../../mod/install.php:524
+#: mod/install.php:576
 msgid ""
-"IMPORTANT: You will need to [manually] setup a scheduled task for the "
-"poller."
-msgstr "ВАЖНО: Вам нужно будет [вручную] установить запланированное задание для регистратора."
+"IMPORTANT: You will need to [manually] setup a scheduled task for the poller."
+msgstr ""
+"ВАЖНО: Вам нужно будет [вручную] установить запланированное задание для "
+"регистратора."
 
-#: ../../mod/wallmessage.php:42 ../../mod/wallmessage.php:112
+#: mod/wallmessage.php:42 mod/wallmessage.php:112
 #, php-format
 msgid "Number of daily wall messages for %s exceeded. Message failed."
-msgstr "Количество ежедневных сообщений на стене %s превышено. Сообщение отменено.."
+msgstr ""
+"Количество ежедневных сообщений на стене %s превышено. Сообщение отменено.."
 
-#: ../../mod/wallmessage.php:59
+#: mod/wallmessage.php:59
 msgid "Unable to check your home location."
 msgstr "Невозможно проверить местоположение."
 
-#: ../../mod/wallmessage.php:86 ../../mod/wallmessage.php:95
+#: mod/wallmessage.php:86 mod/wallmessage.php:95
 msgid "No recipient."
 msgstr "Без адресата."
 
-#: ../../mod/wallmessage.php:143
+#: mod/wallmessage.php:143
 #, php-format
 msgid ""
 "If you wish for %s to respond, please check that the privacy settings on "
 "your site allow private mail from unknown senders."
-msgstr "Если Вы хотите ответить %s, пожалуйста, проверьте, позволяют ли настройки конфиденциальности на Вашем сайте принимать персональную почту от неизвестных отправителей."
+msgstr ""
+"Если Вы хотите ответить %s, пожалуйста, проверьте, позволяют ли настройки "
+"конфиденциальности на Вашем сайте принимать персональную почту от "
+"неизвестных отправителей."
 
-#: ../../mod/help.php:79
+#: mod/help.php:41
 msgid "Help:"
 msgstr "Помощь:"
 
-#: ../../mod/help.php:84 ../../include/nav.php:114
+#: mod/help.php:47 include/nav.php:113 view/theme/vier/theme.php:302
 msgid "Help"
 msgstr "Помощь"
 
-#: ../../mod/help.php:90 ../../index.php:256
+#: mod/help.php:53 mod/p.php:16 mod/p.php:25 index.php:270
 msgid "Not Found"
 msgstr "Не найдено"
 
-#: ../../mod/help.php:93 ../../index.php:259
+#: mod/help.php:56 index.php:273
 msgid "Page not found."
 msgstr "Страница не найдена."
 
-#: ../../mod/dfrn_poll.php:103 ../../mod/dfrn_poll.php:536
+#: mod/dfrn_poll.php:103 mod/dfrn_poll.php:536
 #, php-format
 msgid "%1$s welcomes %2$s"
 msgstr "%1$s добро пожаловать %2$s"
 
-#: ../../mod/home.php:35
+#: mod/home.php:35
 #, php-format
 msgid "Welcome to %s"
 msgstr "Добро пожаловать на %s!"
 
-#: ../../mod/wall_attach.php:75
+#: mod/wall_attach.php:94
 msgid "Sorry, maybe your upload is bigger than the PHP configuration allows"
 msgstr ""
 
-#: ../../mod/wall_attach.php:75
+#: mod/wall_attach.php:94
 msgid "Or - did you try to upload an empty file?"
 msgstr ""
 
-#: ../../mod/wall_attach.php:81
+#: mod/wall_attach.php:105
 #, php-format
-msgid "File exceeds size limit of %d"
-msgstr "Файл превышает предельный размер %d"
+msgid "File exceeds size limit of %s"
+msgstr ""
 
-#: ../../mod/wall_attach.php:122 ../../mod/wall_attach.php:133
+#: mod/wall_attach.php:156 mod/wall_attach.php:172
 msgid "File upload failed."
 msgstr "Загрузка файла не удалась."
 
-#: ../../mod/match.php:12
-msgid "Profile Match"
-msgstr "Похожие профили"
-
-#: ../../mod/match.php:20
+#: mod/match.php:33
 msgid "No keywords to match. Please add keywords to your default profile."
-msgstr "Нет соответствующих ключевых слов. Пожалуйста, добавьте ключевые слова для вашего профиля по умолчанию."
+msgstr ""
+"Нет соответствующих ключевых слов. Пожалуйста, добавьте ключевые слова для "
+"вашего профиля по умолчанию."
 
-#: ../../mod/match.php:57
+#: mod/match.php:84
 msgid "is interested in:"
 msgstr "интересуется:"
 
-#: ../../mod/match.php:58 ../../mod/suggest.php:90 ../../boot.php:1568
-#: ../../include/contact_widgets.php:10
-msgid "Connect"
-msgstr "Подключить"
+#: mod/match.php:98
+msgid "Profile Match"
+msgstr "Похожие профили"
 
-#: ../../mod/share.php:44
+#: mod/share.php:38
 msgid "link"
 msgstr "ссылка"
 
-#: ../../mod/community.php:23
+#: mod/community.php:27
 msgid "Not available."
 msgstr "Недоступно."
 
-#: ../../mod/community.php:32 ../../include/nav.php:129
-#: ../../include/nav.php:131 ../../view/theme/diabook/theme.php:129
+#: mod/community.php:36 include/nav.php:136 include/nav.php:138
+#: view/theme/diabook/theme.php:129
 msgid "Community"
 msgstr "Сообщество"
 
-#: ../../mod/community.php:62 ../../mod/community.php:71
-#: ../../mod/search.php:168 ../../mod/search.php:192
+#: mod/community.php:66 mod/community.php:75 mod/search.php:228
 msgid "No results."
 msgstr "Нет результатов."
 
-#: ../../mod/settings.php:29 ../../mod/photos.php:80
+#: mod/settings.php:34 mod/photos.php:117
 msgid "everybody"
 msgstr "каждый"
 
-#: ../../mod/settings.php:41
-msgid "Additional features"
-msgstr "Дополнительные возможности"
-
-#: ../../mod/settings.php:46
+#: mod/settings.php:58
 msgid "Display"
-msgstr ""
+msgstr "Внешний вид"
 
-#: ../../mod/settings.php:52 ../../mod/settings.php:780
+#: mod/settings.php:65 mod/settings.php:864
 msgid "Social Networks"
-msgstr ""
+msgstr "Социальные сети"
 
-#: ../../mod/settings.php:62 ../../include/nav.php:170
+#: mod/settings.php:79 include/nav.php:180
 msgid "Delegations"
-msgstr ""
+msgstr "Делегирование"
 
-#: ../../mod/settings.php:67
+#: mod/settings.php:86
 msgid "Connected apps"
 msgstr "Подключенные приложения"
 
-#: ../../mod/settings.php:72 ../../mod/uexport.php:85
+#: mod/settings.php:93 mod/uexport.php:85
 msgid "Export personal data"
 msgstr "Экспорт личных данных"
 
-#: ../../mod/settings.php:77
+#: mod/settings.php:100
 msgid "Remove account"
 msgstr "Удалить аккаунт"
 
-#: ../../mod/settings.php:129
+#: mod/settings.php:153
 msgid "Missing some important data!"
 msgstr "Не хватает важных данных!"
 
-#: ../../mod/settings.php:238
+#: mod/settings.php:266
 msgid "Failed to connect with email account using the settings provided."
-msgstr "Не удалось подключиться к аккаунту e-mail, используя указанные настройки."
+msgstr ""
+"Не удалось подключиться к аккаунту e-mail, используя указанные настройки."
 
-#: ../../mod/settings.php:243
+#: mod/settings.php:271
 msgid "Email settings updated."
 msgstr "Настройки эл. почты обновлены."
 
-#: ../../mod/settings.php:258
+#: mod/settings.php:286
 msgid "Features updated"
 msgstr "Настройки обновлены"
 
-#: ../../mod/settings.php:321
+#: mod/settings.php:353
 msgid "Relocate message has been send to your contacts"
 msgstr "Перемещённое сообщение было отправлено списку контактов"
 
-#: ../../mod/settings.php:335
+#: mod/settings.php:367 include/user.php:39
 msgid "Passwords do not match. Password unchanged."
 msgstr "Пароли не совпадают. Пароль не изменен."
 
-#: ../../mod/settings.php:340
+#: mod/settings.php:372
 msgid "Empty passwords are not allowed. Password unchanged."
 msgstr "Пустые пароли не допускаются. Пароль не изменен."
 
-#: ../../mod/settings.php:348
+#: mod/settings.php:380
 msgid "Wrong password."
 msgstr "Неверный пароль."
 
-#: ../../mod/settings.php:359
+#: mod/settings.php:391
 msgid "Password changed."
 msgstr "Пароль изменен."
 
-#: ../../mod/settings.php:361
+#: mod/settings.php:393
 msgid "Password update failed. Please try again."
 msgstr "Обновление пароля не удалось. Пожалуйста, попробуйте еще раз."
 
-#: ../../mod/settings.php:428
+#: mod/settings.php:462
 msgid " Please use a shorter name."
 msgstr " Пожалуйста, используйте более короткое имя."
 
-#: ../../mod/settings.php:430
+#: mod/settings.php:464
 msgid " Name too short."
 msgstr " Имя слишком короткое."
 
-#: ../../mod/settings.php:439
+#: mod/settings.php:473
 msgid "Wrong Password"
 msgstr "Неверный пароль."
 
-#: ../../mod/settings.php:444
+#: mod/settings.php:478
 msgid " Not valid email."
 msgstr " Неверный e-mail."
 
-#: ../../mod/settings.php:450
+#: mod/settings.php:484
 msgid " Cannot change to that email."
 msgstr " Невозможно изменить на этот e-mail."
 
-#: ../../mod/settings.php:506
+#: mod/settings.php:540
 msgid "Private forum has no privacy permissions. Using default privacy group."
-msgstr "Частный форум не имеет настроек приватности. Используется группа конфиденциальности по умолчанию."
+msgstr ""
+"Частный форум не имеет настроек приватности. Используется группа "
+"конфиденциальности по умолчанию."
 
-#: ../../mod/settings.php:510
+#: mod/settings.php:544
 msgid "Private forum has no privacy permissions and no default privacy group."
-msgstr "Частный форум не имеет настроек приватности и не имеет групп приватности по умолчанию."
+msgstr ""
+"Частный форум не имеет настроек приватности и не имеет групп приватности по "
+"умолчанию."
 
-#: ../../mod/settings.php:540
+#: mod/settings.php:583
 msgid "Settings updated."
 msgstr "Настройки обновлены."
 
-#: ../../mod/settings.php:613 ../../mod/settings.php:639
-#: ../../mod/settings.php:675
+#: mod/settings.php:658 mod/settings.php:684 mod/settings.php:720
 msgid "Add application"
 msgstr "Добавить приложения"
 
-#: ../../mod/settings.php:617 ../../mod/settings.php:643
+#: mod/settings.php:662 mod/settings.php:688
 msgid "Consumer Key"
 msgstr "Consumer Key"
 
-#: ../../mod/settings.php:618 ../../mod/settings.php:644
+#: mod/settings.php:663 mod/settings.php:689
 msgid "Consumer Secret"
 msgstr "Consumer Secret"
 
-#: ../../mod/settings.php:619 ../../mod/settings.php:645
+#: mod/settings.php:664 mod/settings.php:690
 msgid "Redirect"
 msgstr "Перенаправление"
 
-#: ../../mod/settings.php:620 ../../mod/settings.php:646
+#: mod/settings.php:665 mod/settings.php:691
 msgid "Icon url"
 msgstr "URL символа"
 
-#: ../../mod/settings.php:631
+#: mod/settings.php:676
 msgid "You can't edit this application."
 msgstr "Вы не можете изменить это приложение."
 
-#: ../../mod/settings.php:674
+#: mod/settings.php:719
 msgid "Connected Apps"
 msgstr "Подключенные приложения"
 
-#: ../../mod/settings.php:678
+#: mod/settings.php:723
 msgid "Client key starts with"
 msgstr "Ключ клиента начинается с"
 
-#: ../../mod/settings.php:679
+#: mod/settings.php:724
 msgid "No name"
 msgstr "Нет имени"
 
-#: ../../mod/settings.php:680
+#: mod/settings.php:725
 msgid "Remove authorization"
 msgstr "Удалить авторизацию"
 
-#: ../../mod/settings.php:692
+#: mod/settings.php:737
 msgid "No Plugin settings configured"
 msgstr "Нет сконфигурированных настроек плагина"
 
-#: ../../mod/settings.php:700
+#: mod/settings.php:745
 msgid "Plugin Settings"
 msgstr "Настройки плагина"
 
-#: ../../mod/settings.php:714
-msgid "Off"
-msgstr ""
-
-#: ../../mod/settings.php:714
-msgid "On"
-msgstr ""
-
-#: ../../mod/settings.php:722
+#: mod/settings.php:767
 msgid "Additional Features"
 msgstr "Дополнительные возможности"
 
-#: ../../mod/settings.php:736 ../../mod/settings.php:737
+#: mod/settings.php:777 mod/settings.php:781
+msgid "General Social Media Settings"
+msgstr ""
+
+#: mod/settings.php:787
+msgid "Disable intelligent shortening"
+msgstr ""
+
+#: mod/settings.php:789
+msgid ""
+"Normally the system tries to find the best link to add to shortened posts. "
+"If this option is enabled then every shortened post will always point to the "
+"original friendica post."
+msgstr ""
+
+#: mod/settings.php:795
+msgid "Automatically follow any GNU Social (OStatus) followers/mentioners"
+msgstr ""
+
+#: mod/settings.php:797
+msgid ""
+"If you receive a message from an unknown OStatus user, this option decides "
+"what to do. If it is checked, a new contact will be created for every "
+"unknown user."
+msgstr ""
+
+#: mod/settings.php:806
+msgid "Your legacy GNU Social account"
+msgstr ""
+
+#: mod/settings.php:808
+msgid ""
+"If you enter your old GNU Social/Statusnet account name here (in the format "
+"user@domain.tld), your contacts will be added automatically. The field will "
+"be emptied when done."
+msgstr ""
+
+#: mod/settings.php:811
+msgid "Repair OStatus subscriptions"
+msgstr ""
+
+#: mod/settings.php:820 mod/settings.php:821
 #, php-format
 msgid "Built-in support for %s connectivity is %s"
 msgstr "Встроенная  поддержка для %s подключение %s"
 
-#: ../../mod/settings.php:736 ../../mod/dfrn_request.php:838
-#: ../../include/contact_selectors.php:80
+#: mod/settings.php:820 mod/dfrn_request.php:865
+#: include/contact_selectors.php:80
 msgid "Diaspora"
 msgstr "Diaspora"
 
-#: ../../mod/settings.php:736 ../../mod/settings.php:737
+#: mod/settings.php:820 mod/settings.php:821
 msgid "enabled"
 msgstr "подключено"
 
-#: ../../mod/settings.php:736 ../../mod/settings.php:737
+#: mod/settings.php:820 mod/settings.php:821
 msgid "disabled"
 msgstr "отключено"
 
-#: ../../mod/settings.php:737
-msgid "StatusNet"
-msgstr "StatusNet"
+#: mod/settings.php:821
+msgid "GNU Social (OStatus)"
+msgstr ""
 
-#: ../../mod/settings.php:773
+#: mod/settings.php:857
 msgid "Email access is disabled on this site."
 msgstr "Доступ эл. почты отключен на этом сайте."
 
-#: ../../mod/settings.php:785
+#: mod/settings.php:869
 msgid "Email/Mailbox Setup"
 msgstr "Настройка эл. почты / почтового ящика"
 
-#: ../../mod/settings.php:786
+#: mod/settings.php:870
 msgid ""
 "If you wish to communicate with email contacts using this service "
 "(optional), please specify how to connect to your mailbox."
-msgstr "Если вы хотите общаться с Email контактами, используя этот сервис (по желанию), пожалуйста, уточните, как подключиться к вашему почтовому ящику."
+msgstr ""
+"Если вы хотите общаться с Email контактами, используя этот сервис (по "
+"желанию), пожалуйста, уточните, как подключиться к вашему почтовому ящику."
 
-#: ../../mod/settings.php:787
+#: mod/settings.php:871
 msgid "Last successful email check:"
 msgstr "Последняя успешная проверка электронной почты:"
 
-#: ../../mod/settings.php:789
+#: mod/settings.php:873
 msgid "IMAP server name:"
 msgstr "Имя IMAP сервера:"
 
-#: ../../mod/settings.php:790
+#: mod/settings.php:874
 msgid "IMAP port:"
 msgstr "Порт IMAP:"
 
-#: ../../mod/settings.php:791
+#: mod/settings.php:875
 msgid "Security:"
 msgstr "Безопасность:"
 
-#: ../../mod/settings.php:791 ../../mod/settings.php:796
+#: mod/settings.php:875 mod/settings.php:880
 msgid "None"
 msgstr "Ничего"
 
-#: ../../mod/settings.php:792
+#: mod/settings.php:876
 msgid "Email login name:"
 msgstr "Логин эл. почты:"
 
-#: ../../mod/settings.php:793
+#: mod/settings.php:877
 msgid "Email password:"
 msgstr "Пароль эл. почты:"
 
-#: ../../mod/settings.php:794
+#: mod/settings.php:878
 msgid "Reply-to address:"
 msgstr "Адрес для ответа:"
 
-#: ../../mod/settings.php:795
+#: mod/settings.php:879
 msgid "Send public posts to all email contacts:"
 msgstr "Отправлять открытые сообщения на все контакты электронной почты:"
 
-#: ../../mod/settings.php:796
+#: mod/settings.php:880
 msgid "Action after import:"
 msgstr "Действие после импорта:"
 
-#: ../../mod/settings.php:796
+#: mod/settings.php:880
 msgid "Mark as seen"
 msgstr "Отметить, как прочитанное"
 
-#: ../../mod/settings.php:796
+#: mod/settings.php:880
 msgid "Move to folder"
 msgstr "Переместить в папку"
 
-#: ../../mod/settings.php:797
+#: mod/settings.php:881
 msgid "Move to folder:"
 msgstr "Переместить в папку:"
 
-#: ../../mod/settings.php:878
+#: mod/settings.php:967
 msgid "Display Settings"
 msgstr "Параметры дисплея"
 
-#: ../../mod/settings.php:884 ../../mod/settings.php:899
+#: mod/settings.php:973 mod/settings.php:991
 msgid "Display Theme:"
 msgstr "Показать тему:"
 
-#: ../../mod/settings.php:885
+#: mod/settings.php:974
 msgid "Mobile Theme:"
 msgstr "Мобильная тема:"
 
-#: ../../mod/settings.php:886
+#: mod/settings.php:975
 msgid "Update browser every xx seconds"
 msgstr "Обновление браузера каждые хх секунд"
 
-#: ../../mod/settings.php:886
-msgid "Minimum of 10 seconds, no maximum"
-msgstr "Минимум 10 секунд, максимума нет"
+#: mod/settings.php:975
+msgid "Minimum of 10 seconds. Enter -1 to disable it."
+msgstr ""
 
-#: ../../mod/settings.php:887
+#: mod/settings.php:976
 msgid "Number of items to display per page:"
 msgstr "Количество элементов, отображаемых на одной странице:"
 
-#: ../../mod/settings.php:887 ../../mod/settings.php:888
+#: mod/settings.php:976 mod/settings.php:977
 msgid "Maximum of 100 items"
 msgstr "Максимум 100 элементов"
 
-#: ../../mod/settings.php:888
+#: mod/settings.php:977
 msgid "Number of items to display per page when viewed from mobile device:"
-msgstr "Количество элементов на странице, когда просмотр осуществляется с мобильных устройств:"
+msgstr ""
+"Количество элементов на странице, когда просмотр осуществляется с мобильных "
+"устройств:"
 
-#: ../../mod/settings.php:889
+#: mod/settings.php:978
 msgid "Don't show emoticons"
 msgstr "не показывать emoticons"
 
-#: ../../mod/settings.php:890
+#: mod/settings.php:979
+msgid "Calendar"
+msgstr ""
+
+#: mod/settings.php:980
+msgid "Beginning of week:"
+msgstr ""
+
+#: mod/settings.php:981
 msgid "Don't show notices"
 msgstr ""
 
-#: ../../mod/settings.php:891
+#: mod/settings.php:982
 msgid "Infinite scroll"
 msgstr "Бесконечная прокрутка"
 
-#: ../../mod/settings.php:892
+#: mod/settings.php:983
 msgid "Automatic updates only at the top of the network page"
 msgstr ""
 
-#: ../../mod/settings.php:969
+#: mod/settings.php:985 view/theme/cleanzero/config.php:82
+#: view/theme/dispy/config.php:72 view/theme/quattro/config.php:66
+#: view/theme/diabook/config.php:150 view/theme/vier/config.php:109
+#: view/theme/duepuntozero/config.php:61
+msgid "Theme settings"
+msgstr "Настройки темы"
+
+#: mod/settings.php:1062
 msgid "User Types"
 msgstr ""
 
-#: ../../mod/settings.php:970
+#: mod/settings.php:1063
 msgid "Community Types"
 msgstr ""
 
-#: ../../mod/settings.php:971
+#: mod/settings.php:1064
 msgid "Normal Account Page"
 msgstr "Стандартная страница аккаунта"
 
-#: ../../mod/settings.php:972
+#: mod/settings.php:1065
 msgid "This account is a normal personal profile"
 msgstr "Этот аккаунт является обычным персональным профилем"
 
-#: ../../mod/settings.php:975
+#: mod/settings.php:1068
 msgid "Soapbox Page"
 msgstr ""
 
-#: ../../mod/settings.php:976
+#: mod/settings.php:1069
 msgid "Automatically approve all connection/friend requests as read-only fans"
-msgstr "Автоматически одобряются все подключения / запросы в друзья, \"только для чтения\" поклонниками"
+msgstr ""
+"Автоматически одобряются все подключения / запросы в друзья, \"только для "
+"чтения\" поклонниками"
 
-#: ../../mod/settings.php:979
+#: mod/settings.php:1072
 msgid "Community Forum/Celebrity Account"
 msgstr "Аккаунт сообщества Форум/Знаменитость"
 
-#: ../../mod/settings.php:980
-msgid ""
-"Automatically approve all connection/friend requests as read-write fans"
-msgstr "Автоматически одобряются все подключения / запросы в друзья, \"для чтения и записей\" поклонников"
+#: mod/settings.php:1073
+msgid "Automatically approve all connection/friend requests as read-write fans"
+msgstr ""
+"Автоматически одобряются все подключения / запросы в друзья, \"для чтения и "
+"записей\" поклонников"
 
-#: ../../mod/settings.php:983
+#: mod/settings.php:1076
 msgid "Automatic Friend Page"
 msgstr "\"Автоматический друг\" страница"
 
-#: ../../mod/settings.php:984
+#: mod/settings.php:1077
 msgid "Automatically approve all connection/friend requests as friends"
-msgstr "Автоматически одобряются все подключения / запросы в друзья, расширяется список друзей"
+msgstr ""
+"Автоматически одобряются все подключения / запросы в друзья, расширяется "
+"список друзей"
 
-#: ../../mod/settings.php:987
+#: mod/settings.php:1080
 msgid "Private Forum [Experimental]"
 msgstr "Личный форум [экспериментально]"
 
-#: ../../mod/settings.php:988
+#: mod/settings.php:1081
 msgid "Private forum - approved members only"
 msgstr "Приватный форум - разрешено только участникам"
 
-#: ../../mod/settings.php:1000
+#: mod/settings.php:1093
 msgid "OpenID:"
 msgstr "OpenID:"
 
-#: ../../mod/settings.php:1000
+#: mod/settings.php:1093
 msgid "(Optional) Allow this OpenID to login to this account."
 msgstr "(Необязательно) Разрешить этому OpenID входить в этот аккаунт"
 
-#: ../../mod/settings.php:1010
+#: mod/settings.php:1103
 msgid "Publish your default profile in your local site directory?"
-msgstr "Публиковать ваш профиль по умолчанию в вашем локальном каталоге на сайте?"
+msgstr ""
+"Публиковать ваш профиль по умолчанию в вашем локальном каталоге на сайте?"
 
-#: ../../mod/settings.php:1010 ../../mod/settings.php:1016
-#: ../../mod/settings.php:1024 ../../mod/settings.php:1028
-#: ../../mod/settings.php:1033 ../../mod/settings.php:1039
-#: ../../mod/settings.php:1045 ../../mod/settings.php:1051
-#: ../../mod/settings.php:1081 ../../mod/settings.php:1082
-#: ../../mod/settings.php:1083 ../../mod/settings.php:1084
-#: ../../mod/settings.php:1085 ../../mod/dfrn_request.php:830
-#: ../../mod/register.php:234 ../../mod/profiles.php:661
-#: ../../mod/profiles.php:665 ../../mod/api.php:106
-msgid "No"
-msgstr "Нет"
-
-#: ../../mod/settings.php:1016
+#: mod/settings.php:1109
 msgid "Publish your default profile in the global social directory?"
 msgstr "Публиковать ваш профиль по умолчанию в глобальном социальном каталоге?"
 
-#: ../../mod/settings.php:1024
+#: mod/settings.php:1117
 msgid "Hide your contact/friend list from viewers of your default profile?"
-msgstr "Скрывать ваш список контактов/друзей от посетителей вашего профиля по умолчанию?"
+msgstr ""
+"Скрывать ваш список контактов/друзей от посетителей вашего профиля по "
+"умолчанию?"
 
-#: ../../mod/settings.php:1028 ../../include/conversation.php:1057
+#: mod/settings.php:1121 include/acl_selectors.php:331
 msgid "Hide your profile details from unknown viewers?"
 msgstr "Скрыть данные профиля из неизвестных зрителей?"
 
-#: ../../mod/settings.php:1028
+#: mod/settings.php:1121
 msgid ""
 "If enabled, posting public messages to Diaspora and other networks isn't "
 "possible."
 msgstr ""
 
-#: ../../mod/settings.php:1033
+#: mod/settings.php:1126
 msgid "Allow friends to post to your profile page?"
 msgstr "Разрешить друзьям оставлять сообщения на страницу вашего профиля?"
 
-#: ../../mod/settings.php:1039
+#: mod/settings.php:1132
 msgid "Allow friends to tag your posts?"
 msgstr "Разрешить друзьям отмечять ваши сообщения?"
 
-#: ../../mod/settings.php:1045
+#: mod/settings.php:1138
 msgid "Allow us to suggest you as a potential friend to new members?"
 msgstr "Позвольть предлогать Вам потенциальных друзей?"
 
-#: ../../mod/settings.php:1051
+#: mod/settings.php:1144
 msgid "Permit unknown people to send you private mail?"
 msgstr "Разрешить незнакомым людям отправлять вам личные сообщения?"
 
-#: ../../mod/settings.php:1059
+#: mod/settings.php:1152
 msgid "Profile is <strong>not published</strong>."
 msgstr "Профиль <strong>не публикуется</strong>."
 
-#: ../../mod/settings.php:1067
-msgid "Your Identity Address is"
-msgstr "Ваш идентификационный адрес"
+#: mod/settings.php:1160
+#, php-format
+msgid "Your Identity Address is <strong>'%s'</strong> or '%s'."
+msgstr ""
 
-#: ../../mod/settings.php:1078
+#: mod/settings.php:1167
 msgid "Automatically expire posts after this many days:"
 msgstr "Автоматическое истекание срока действия сообщения после стольких дней:"
 
-#: ../../mod/settings.php:1078
+#: mod/settings.php:1167
 msgid "If empty, posts will not expire. Expired posts will be deleted"
-msgstr "Если пусто, срок действия сообщений не будет ограничен. Сообщения с истекшим сроком действия будут удалены"
+msgstr ""
+"Если пусто, срок действия сообщений не будет ограничен. Сообщения с истекшим "
+"сроком действия будут удалены"
 
-#: ../../mod/settings.php:1079
+#: mod/settings.php:1168
 msgid "Advanced expiration settings"
 msgstr "Настройки расширенного окончания срока действия"
 
-#: ../../mod/settings.php:1080
+#: mod/settings.php:1169
 msgid "Advanced Expiration"
 msgstr "Расширенное окончание срока действия"
 
-#: ../../mod/settings.php:1081
+#: mod/settings.php:1170
 msgid "Expire posts:"
 msgstr "Срок хранения сообщений:"
 
-#: ../../mod/settings.php:1082
+#: mod/settings.php:1171
 msgid "Expire personal notes:"
 msgstr "Срок хранения личных заметок:"
 
-#: ../../mod/settings.php:1083
+#: mod/settings.php:1172
 msgid "Expire starred posts:"
 msgstr "Срок хранения усеянных сообщений:"
 
-#: ../../mod/settings.php:1084
+#: mod/settings.php:1173
 msgid "Expire photos:"
 msgstr "Срок хранения фотографий:"
 
-#: ../../mod/settings.php:1085
+#: mod/settings.php:1174
 msgid "Only expire posts by others:"
 msgstr "Только устаревшие посты других:"
 
-#: ../../mod/settings.php:1111
+#: mod/settings.php:1202
 msgid "Account Settings"
 msgstr "Настройки аккаунта"
 
-#: ../../mod/settings.php:1119
+#: mod/settings.php:1210
 msgid "Password Settings"
-msgstr "Настройка пароля"
+msgstr "Смена пароля"
 
-#: ../../mod/settings.php:1120
+#: mod/settings.php:1211 mod/register.php:274
 msgid "New Password:"
 msgstr "Новый пароль:"
 
-#: ../../mod/settings.php:1121
+#: mod/settings.php:1212 mod/register.php:275
 msgid "Confirm:"
 msgstr "Подтвердите:"
 
-#: ../../mod/settings.php:1121
+#: mod/settings.php:1212
 msgid "Leave password fields blank unless changing"
 msgstr "Оставьте поля пароля пустыми, если он не изменяется"
 
-#: ../../mod/settings.php:1122
+#: mod/settings.php:1213
 msgid "Current Password:"
 msgstr "Текущий пароль:"
 
-#: ../../mod/settings.php:1122 ../../mod/settings.php:1123
+#: mod/settings.php:1213 mod/settings.php:1214
 msgid "Your current password to confirm the changes"
 msgstr "Ваш текущий пароль, для подтверждения изменений"
 
-#: ../../mod/settings.php:1123
+#: mod/settings.php:1214
 msgid "Password:"
 msgstr "Пароль:"
 
-#: ../../mod/settings.php:1127
+#: mod/settings.php:1218
 msgid "Basic Settings"
 msgstr "Основные параметры"
 
-#: ../../mod/settings.php:1128 ../../include/profile_advanced.php:15
+#: mod/settings.php:1219 include/identity.php:588
 msgid "Full Name:"
 msgstr "Полное имя:"
 
-#: ../../mod/settings.php:1129
+#: mod/settings.php:1220
 msgid "Email Address:"
 msgstr "Адрес электронной почты:"
 
-#: ../../mod/settings.php:1130
+#: mod/settings.php:1221
 msgid "Your Timezone:"
 msgstr "Ваш часовой пояс:"
 
-#: ../../mod/settings.php:1131
+#: mod/settings.php:1222
+msgid "Your Language:"
+msgstr ""
+
+#: mod/settings.php:1222
+msgid ""
+"Set the language we use to show you friendica interface and to send you "
+"emails"
+msgstr ""
+
+#: mod/settings.php:1223
 msgid "Default Post Location:"
 msgstr "Местонахождение по умолчанию:"
 
-#: ../../mod/settings.php:1132
+#: mod/settings.php:1224
 msgid "Use Browser Location:"
 msgstr "Использовать определение местоположения браузером:"
 
-#: ../../mod/settings.php:1135
+#: mod/settings.php:1227
 msgid "Security and Privacy Settings"
 msgstr "Параметры безопасности и конфиденциальности"
 
-#: ../../mod/settings.php:1137
+#: mod/settings.php:1229
 msgid "Maximum Friend Requests/Day:"
 msgstr "Максимум запросов в друзья в день:"
 
-#: ../../mod/settings.php:1137 ../../mod/settings.php:1167
+#: mod/settings.php:1229 mod/settings.php:1259
 msgid "(to prevent spam abuse)"
 msgstr "(для предотвращения спама)"
 
-#: ../../mod/settings.php:1138
+#: mod/settings.php:1230
 msgid "Default Post Permissions"
 msgstr "Разрешение на сообщения по умолчанию"
 
-#: ../../mod/settings.php:1139
+#: mod/settings.php:1231
 msgid "(click to open/close)"
 msgstr "(нажмите, чтобы открыть / закрыть)"
 
-#: ../../mod/settings.php:1148 ../../mod/photos.php:1146
-#: ../../mod/photos.php:1519
+#: mod/settings.php:1240 mod/photos.php:1199 mod/photos.php:1584
 msgid "Show to Groups"
 msgstr "Показать в группах"
 
-#: ../../mod/settings.php:1149 ../../mod/photos.php:1147
-#: ../../mod/photos.php:1520
+#: mod/settings.php:1241 mod/photos.php:1200 mod/photos.php:1585
 msgid "Show to Contacts"
 msgstr "Показывать контактам"
 
-#: ../../mod/settings.php:1150
+#: mod/settings.php:1242
 msgid "Default Private Post"
 msgstr "Личное сообщение по умолчанию"
 
-#: ../../mod/settings.php:1151
+#: mod/settings.php:1243
 msgid "Default Public Post"
 msgstr "Публичное сообщение по умолчанию"
 
-#: ../../mod/settings.php:1155
+#: mod/settings.php:1247
 msgid "Default Permissions for New Posts"
 msgstr "Права для новых записей по умолчанию"
 
-#: ../../mod/settings.php:1167
+#: mod/settings.php:1259
 msgid "Maximum private messages per day from unknown people:"
 msgstr "Максимальное количество личных сообщений от незнакомых людей в день:"
 
-#: ../../mod/settings.php:1170
+#: mod/settings.php:1262
 msgid "Notification Settings"
 msgstr "Настройка уведомлений"
 
-#: ../../mod/settings.php:1171
+#: mod/settings.php:1263
 msgid "By default post a status message when:"
 msgstr "Отправить состояние о статусе по умолчанию, если:"
 
-#: ../../mod/settings.php:1172
+#: mod/settings.php:1264
 msgid "accepting a friend request"
 msgstr "принятие запроса на добавление в друзья"
 
-#: ../../mod/settings.php:1173
+#: mod/settings.php:1265
 msgid "joining a forum/community"
 msgstr "вступление в сообщество/форум"
 
-#: ../../mod/settings.php:1174
+#: mod/settings.php:1266
 msgid "making an <em>interesting</em> profile change"
 msgstr "сделать изменения в <em>настройках интересов</em> профиля"
 
-#: ../../mod/settings.php:1175
+#: mod/settings.php:1267
 msgid "Send a notification email when:"
 msgstr "Отправлять уведомление по электронной почте, когда:"
 
-#: ../../mod/settings.php:1176
+#: mod/settings.php:1268
 msgid "You receive an introduction"
 msgstr "Вы получили запрос"
 
-#: ../../mod/settings.php:1177
+#: mod/settings.php:1269
 msgid "Your introductions are confirmed"
 msgstr "Ваши запросы подтверждены"
 
-#: ../../mod/settings.php:1178
+#: mod/settings.php:1270
 msgid "Someone writes on your profile wall"
 msgstr "Кто-то пишет на стене вашего профиля"
 
-#: ../../mod/settings.php:1179
+#: mod/settings.php:1271
 msgid "Someone writes a followup comment"
 msgstr "Кто-то пишет последующий комментарий"
 
-#: ../../mod/settings.php:1180
+#: mod/settings.php:1272
 msgid "You receive a private message"
 msgstr "Вы получаете личное сообщение"
 
-#: ../../mod/settings.php:1181
+#: mod/settings.php:1273
 msgid "You receive a friend suggestion"
 msgstr "Вы полулили предложение о добавлении в друзья"
 
-#: ../../mod/settings.php:1182
+#: mod/settings.php:1274
 msgid "You are tagged in a post"
 msgstr "Вы отмечены в посте"
 
-#: ../../mod/settings.php:1183
+#: mod/settings.php:1275
 msgid "You are poked/prodded/etc. in a post"
 msgstr ""
 
-#: ../../mod/settings.php:1185
+#: mod/settings.php:1277
+msgid "Activate desktop notifications"
+msgstr ""
+
+#: mod/settings.php:1277
+msgid "Show desktop popup on new notifications"
+msgstr ""
+
+#: mod/settings.php:1279
 msgid "Text-only notification emails"
 msgstr ""
 
-#: ../../mod/settings.php:1187
+#: mod/settings.php:1281
 msgid "Send text only notification emails, without the html part"
 msgstr ""
 
-#: ../../mod/settings.php:1189
+#: mod/settings.php:1283
 msgid "Advanced Account/Page Type Settings"
-msgstr "Расширенные настройки типа аккаунта/страницы"
+msgstr "Расширенные настройки учётной записи"
 
-#: ../../mod/settings.php:1190
+#: mod/settings.php:1284
 msgid "Change the behaviour of this account for special situations"
 msgstr "Измените поведение этого аккаунта в специальных ситуациях"
 
-#: ../../mod/settings.php:1193
+#: mod/settings.php:1287
 msgid "Relocate"
-msgstr "Переместить"
+msgstr "Перемещение"
 
-#: ../../mod/settings.php:1194
+#: mod/settings.php:1288
 msgid ""
 "If you have moved this profile from another server, and some of your "
 "contacts don't receive your updates, try pushing this button."
-msgstr "Если вы переместили эту анкету с другого сервера, и некоторые из ваших контактов не получили ваши обновления, попробуйте нажать эту кнопку."
+msgstr ""
+"Если вы переместили эту анкету с другого сервера, и некоторые из ваших "
+"контактов не получили ваши обновления, попробуйте нажать эту кнопку."
 
-#: ../../mod/settings.php:1195
+#: mod/settings.php:1289
 msgid "Resend relocate message to contacts"
 msgstr "Отправить перемещённые сообщения контактам"
 
-#: ../../mod/dfrn_request.php:95
+#: mod/dfrn_request.php:96
 msgid "This introduction has already been accepted."
 msgstr "Этот запрос был уже принят."
 
-#: ../../mod/dfrn_request.php:120 ../../mod/dfrn_request.php:518
+#: mod/dfrn_request.php:119 mod/dfrn_request.php:516
 msgid "Profile location is not valid or does not contain profile information."
-msgstr "Местоположение профиля является недопустимым или не содержит информацию о профиле."
+msgstr ""
+"Местоположение профиля является недопустимым или не содержит информацию о "
+"профиле."
 
-#: ../../mod/dfrn_request.php:125 ../../mod/dfrn_request.php:523
+#: mod/dfrn_request.php:124 mod/dfrn_request.php:521
 msgid "Warning: profile location has no identifiable owner name."
-msgstr "Внимание: местоположение профиля не имеет идентифицируемого имени владельца."
+msgstr ""
+"Внимание: местоположение профиля не имеет идентифицируемого имени владельца."
 
-#: ../../mod/dfrn_request.php:127 ../../mod/dfrn_request.php:525
+#: mod/dfrn_request.php:126 mod/dfrn_request.php:523
 msgid "Warning: profile location has no profile photo."
 msgstr "Внимание: местоположение профиля не имеет еще фотографии профиля."
 
-#: ../../mod/dfrn_request.php:130 ../../mod/dfrn_request.php:528
+#: mod/dfrn_request.php:129 mod/dfrn_request.php:526
 #, php-format
 msgid "%d required parameter was not found at the given location"
 msgid_plural "%d required parameters were not found at the given location"
 msgstr[0] "%d требуемый параметр не был найден в заданном месте"
 msgstr[1] "%d требуемых параметров не были найдены в заданном месте"
 msgstr[2] "%d требуемых параметров не были найдены в заданном месте"
+msgstr[3] "%d требуемых параметров не были найдены в заданном месте"
 
-#: ../../mod/dfrn_request.php:172
+#: mod/dfrn_request.php:172
 msgid "Introduction complete."
 msgstr "Запрос создан."
 
-#: ../../mod/dfrn_request.php:214
+#: mod/dfrn_request.php:214
 msgid "Unrecoverable protocol error."
 msgstr "Неисправимая ошибка протокола."
 
-#: ../../mod/dfrn_request.php:242
+#: mod/dfrn_request.php:242
 msgid "Profile unavailable."
 msgstr "Профиль недоступен."
 
-#: ../../mod/dfrn_request.php:267
+#: mod/dfrn_request.php:267
 #, php-format
 msgid "%s has received too many connection requests today."
 msgstr "К %s пришло сегодня слишком много запросов на подключение."
 
-#: ../../mod/dfrn_request.php:268
+#: mod/dfrn_request.php:268
 msgid "Spam protection measures have been invoked."
 msgstr "Были применены меры защиты от спама."
 
-#: ../../mod/dfrn_request.php:269
+#: mod/dfrn_request.php:269
 msgid "Friends are advised to please try again in 24 hours."
 msgstr "Друзья советуют попробовать еще раз в ближайшие 24 часа."
 
-#: ../../mod/dfrn_request.php:331
+#: mod/dfrn_request.php:331
 msgid "Invalid locator"
 msgstr "Недопустимый локатор"
 
-#: ../../mod/dfrn_request.php:340
+#: mod/dfrn_request.php:340
 msgid "Invalid email address."
 msgstr "Неверный адрес электронной почты."
 
-#: ../../mod/dfrn_request.php:367
+#: mod/dfrn_request.php:367
 msgid "This account has not been configured for email. Request failed."
 msgstr "Этот аккаунт не настроен для электронной почты. Запрос не удался."
 
-#: ../../mod/dfrn_request.php:463
-msgid "Unable to resolve your name at the provided location."
-msgstr "Не удается установить ваше имя на предложенном местоположении."
-
-#: ../../mod/dfrn_request.php:476
+#: mod/dfrn_request.php:474
 msgid "You have already introduced yourself here."
 msgstr "Вы уже ввели информацию о себе здесь."
 
-#: ../../mod/dfrn_request.php:480
+#: mod/dfrn_request.php:478
 #, php-format
 msgid "Apparently you are already friends with %s."
 msgstr "Похоже, что вы уже друзья с %s."
 
-#: ../../mod/dfrn_request.php:501
+#: mod/dfrn_request.php:499
 msgid "Invalid profile URL."
 msgstr "Неверный URL профиля."
 
-#: ../../mod/dfrn_request.php:507 ../../include/follow.php:27
+#: mod/dfrn_request.php:505 include/follow.php:72
 msgid "Disallowed profile URL."
 msgstr "Запрещенный URL профиля."
 
-#: ../../mod/dfrn_request.php:597
+#: mod/dfrn_request.php:596
 msgid "Your introduction has been sent."
 msgstr "Ваш запрос отправлен."
 
-#: ../../mod/dfrn_request.php:650
+#: mod/dfrn_request.php:636
+msgid ""
+"Remote subscription can't be done for your network. Please subscribe "
+"directly on your system."
+msgstr ""
+
+#: mod/dfrn_request.php:659
 msgid "Please login to confirm introduction."
 msgstr "Для подтверждения запроса войдите пожалуйста с паролем."
 
-#: ../../mod/dfrn_request.php:660
+#: mod/dfrn_request.php:669
 msgid ""
-"Incorrect identity currently logged in. Please login to "
-"<strong>this</strong> profile."
-msgstr "Неверно идентифицирован вход. Пожалуйста, войдите в <strong>этот</strong> профиль."
+"Incorrect identity currently logged in. Please login to <strong>this</"
+"strong> profile."
+msgstr ""
+"Неверно идентифицирован вход. Пожалуйста, войдите в <strong>этот</strong> "
+"профиль."
 
-#: ../../mod/dfrn_request.php:671
+#: mod/dfrn_request.php:683 mod/dfrn_request.php:700
+msgid "Confirm"
+msgstr "Подтвердить"
+
+#: mod/dfrn_request.php:695
 msgid "Hide this contact"
 msgstr "Скрыть этот контакт"
 
-#: ../../mod/dfrn_request.php:674
+#: mod/dfrn_request.php:698
 #, php-format
 msgid "Welcome home %s."
 msgstr "Добро пожаловать домой, %s!"
 
-#: ../../mod/dfrn_request.php:675
+#: mod/dfrn_request.php:699
 #, php-format
 msgid "Please confirm your introduction/connection request to %s."
-msgstr "Пожалуйста, подтвердите краткую информацию / запрос на подключение к %s."
+msgstr ""
+"Пожалуйста, подтвердите краткую информацию / запрос на подключение к %s."
 
-#: ../../mod/dfrn_request.php:676
-msgid "Confirm"
-msgstr "Подтвердить"
-
-#: ../../mod/dfrn_request.php:804
+#: mod/dfrn_request.php:828
 msgid ""
 "Please enter your 'Identity Address' from one of the following supported "
 "communications networks:"
-msgstr "Пожалуйста, введите ваш 'идентификационный адрес' одной из следующих поддерживаемых социальных сетей:"
+msgstr ""
+"Пожалуйста, введите ваш 'идентификационный адрес' одной из следующих "
+"поддерживаемых социальных сетей:"
 
-#: ../../mod/dfrn_request.php:824
+#: mod/dfrn_request.php:849
+#, php-format
 msgid ""
-"If you are not yet a member of the free social web, <a "
-"href=\"http://dir.friendica.com/siteinfo\">follow this link to find a public"
-" Friendica site and join us today</a>."
-msgstr "Если вы еще не являетесь членом свободной социальной сети, перейдите по <a href=\"http://dir.friendica.com/siteinfo\"> этой ссылке, чтобы найти публичный сервер Friendica и присоединиться к нам сейчас </a>."
+"If you are not yet a member of the free social web, <a href=\"%s/siteinfo"
+"\">follow this link to find a public Friendica site and join us today</a>."
+msgstr ""
 
-#: ../../mod/dfrn_request.php:827
+#: mod/dfrn_request.php:854
 msgid "Friend/Connection Request"
 msgstr "Запрос в друзья / на подключение"
 
-#: ../../mod/dfrn_request.php:828
+#: mod/dfrn_request.php:855
 msgid ""
 "Examples: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, "
 "testuser@identi.ca"
-msgstr "Примеры: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, testuser@identi.ca"
+msgstr ""
+"Примеры: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, "
+"testuser@identi.ca"
 
-#: ../../mod/dfrn_request.php:829
-msgid "Please answer the following:"
-msgstr "Пожалуйста, ответьте следующее:"
-
-#: ../../mod/dfrn_request.php:830
-#, php-format
-msgid "Does %s know you?"
-msgstr "%s знает вас?"
-
-#: ../../mod/dfrn_request.php:834
-msgid "Add a personal note:"
-msgstr "Добавить личную заметку:"
-
-#: ../../mod/dfrn_request.php:836 ../../include/contact_selectors.php:76
+#: mod/dfrn_request.php:863 include/contact_selectors.php:76
 msgid "Friendica"
 msgstr "Friendica"
 
-#: ../../mod/dfrn_request.php:837
+#: mod/dfrn_request.php:864
 msgid "StatusNet/Federated Social Web"
 msgstr "StatusNet / Federated Social Web"
 
-#: ../../mod/dfrn_request.php:839
+#: mod/dfrn_request.php:866
 #, php-format
 msgid ""
-" - please do not use this form.  Instead, enter %s into your Diaspora search"
-" bar."
-msgstr "Участники сети Diaspora: пожалуйста, не пользуйтесь этой формой. Вместо этого введите  %s в строке поиска Diaspora"
+" - please do not use this form.  Instead, enter %s into your Diaspora search "
+"bar."
+msgstr ""
+"Участники сети Diaspora: пожалуйста, не пользуйтесь этой формой. Вместо "
+"этого введите  %s в строке поиска Diaspora"
 
-#: ../../mod/dfrn_request.php:840
-msgid "Your Identity Address:"
-msgstr "Ваш идентификационный адрес:"
-
-#: ../../mod/dfrn_request.php:843
-msgid "Submit Request"
-msgstr "Отправить запрос"
-
-#: ../../mod/register.php:90
+#: mod/register.php:92
 msgid ""
 "Registration successful. Please check your email for further instructions."
-msgstr "Регистрация успешна. Пожалуйста, проверьте свою электронную почту для получения дальнейших инструкций."
+msgstr ""
+"Регистрация успешна. Пожалуйста, проверьте свою электронную почту для "
+"получения дальнейших инструкций."
 
-#: ../../mod/register.php:96
+#: mod/register.php:97
 #, php-format
 msgid ""
 "Failed to send email message. Here your accout details:<br> login: %s<br> "
 "password: %s<br><br>You can change your password after login."
 msgstr ""
 
-#: ../../mod/register.php:105
+#: mod/register.php:104
+msgid "Registration successful."
+msgstr ""
+
+#: mod/register.php:110
 msgid "Your registration can not be processed."
 msgstr "Ваша регистрация не может быть обработана."
 
-#: ../../mod/register.php:148
+#: mod/register.php:153
 msgid "Your registration is pending approval by the site owner."
 msgstr "Ваша регистрация в ожидании одобрения владельцем сайта."
 
-#: ../../mod/register.php:186 ../../mod/uimport.php:50
+#: mod/register.php:191 mod/uimport.php:50
 msgid ""
 "This site has exceeded the number of allowed daily account registrations. "
 "Please try again tomorrow."
-msgstr "Этот сайт превысил допустимое количество ежедневных регистраций. Пожалуйста, повторите попытку завтра."
+msgstr ""
+"Этот сайт превысил допустимое количество ежедневных регистраций. Пожалуйста, "
+"повторите попытку завтра."
 
-#: ../../mod/register.php:214
+#: mod/register.php:219
 msgid ""
 "You may (optionally) fill in this form via OpenID by supplying your OpenID "
 "and clicking 'Register'."
-msgstr "Вы можете (по желанию), заполнить эту форму с помощью OpenID, поддерживая ваш OpenID и нажав клавишу \"Регистрация\"."
+msgstr ""
+"Вы можете (по желанию), заполнить эту форму с помощью OpenID, поддерживая "
+"ваш OpenID и нажав клавишу \"Регистрация\"."
 
-#: ../../mod/register.php:215
+#: mod/register.php:220
 msgid ""
 "If you are not familiar with OpenID, please leave that field blank and fill "
 "in the rest of the items."
-msgstr "Если вы не знакомы с OpenID, пожалуйста, оставьте это поле пустым и заполните остальные элементы."
+msgstr ""
+"Если вы не знакомы с OpenID, пожалуйста, оставьте это поле пустым и "
+"заполните остальные элементы."
 
-#: ../../mod/register.php:216
+#: mod/register.php:221
 msgid "Your OpenID (optional): "
 msgstr "Ваш OpenID (необязательно):"
 
-#: ../../mod/register.php:230
+#: mod/register.php:235
 msgid "Include your profile in member directory?"
 msgstr "Включить ваш профиль в каталог участников?"
 
-#: ../../mod/register.php:251
+#: mod/register.php:259
 msgid "Membership on this site is by invitation only."
 msgstr "Членство на сайте только по приглашению."
 
-#: ../../mod/register.php:252
+#: mod/register.php:260
 msgid "Your invitation ID: "
 msgstr "ID вашего приглашения:"
 
-#: ../../mod/register.php:263
-msgid "Your Full Name (e.g. Joe Smith): "
-msgstr "Ваше полное имя (например, Joe Smith): "
+#: mod/register.php:271
+msgid "Your Full Name (e.g. Joe Smith, real or real-looking): "
+msgstr ""
 
-#: ../../mod/register.php:264
+#: mod/register.php:272
 msgid "Your Email Address: "
 msgstr "Ваш адрес электронной почты: "
 
-#: ../../mod/register.php:265
+#: mod/register.php:274
+msgid "Leave empty for an auto generated password."
+msgstr ""
+
+#: mod/register.php:276
 msgid ""
 "Choose a profile nickname. This must begin with a text character. Your "
-"profile address on this site will then be "
-"'<strong>nickname@$sitename</strong>'."
-msgstr "Выбор псевдонима профиля. Он должен начинаться с буквы. Адрес вашего профиля на данном сайте будет в этом случае '<strong>nickname@$sitename</strong>'."
+"profile address on this site will then be '<strong>nickname@$sitename</"
+"strong>'."
+msgstr ""
+"Выбор псевдонима профиля. Он должен начинаться с буквы. Адрес вашего профиля "
+"на данном сайте будет в этом случае '<strong>nickname@$sitename</strong>'."
 
-#: ../../mod/register.php:266
+#: mod/register.php:277
 msgid "Choose a nickname: "
 msgstr "Выберите псевдоним: "
 
-#: ../../mod/register.php:269 ../../boot.php:1241 ../../include/nav.php:109
+#: mod/register.php:280 boot.php:1405 include/nav.php:108
 msgid "Register"
 msgstr "Регистрация"
 
-#: ../../mod/register.php:275 ../../mod/uimport.php:64
+#: mod/register.php:286 mod/uimport.php:64
 msgid "Import"
 msgstr "Импорт"
 
-#: ../../mod/register.php:276
+#: mod/register.php:287
 msgid "Import your profile to this friendica instance"
 msgstr "Импорт своего профиля в этот экземпляр friendica"
 
-#: ../../mod/maintenance.php:5
+#: mod/maintenance.php:5
 msgid "System down for maintenance"
 msgstr "Система закрыта на техническое обслуживание"
 
-#: ../../mod/search.php:99 ../../include/text.php:953
-#: ../../include/text.php:954 ../../include/nav.php:119
+#: mod/search.php:100
+msgid "Only logged in users are permitted to perform a search."
+msgstr ""
+
+#: mod/search.php:124
+msgid "Too Many Requests"
+msgstr ""
+
+#: mod/search.php:125
+msgid "Only one search per minute is permitted for not logged in users."
+msgstr ""
+
+#: mod/search.php:136 include/text.php:1003 include/nav.php:118
 msgid "Search"
 msgstr "Поиск"
 
-#: ../../mod/directory.php:51 ../../view/theme/diabook/theme.php:525
-msgid "Global Directory"
-msgstr "Глобальный каталог"
+#: mod/search.php:234
+#, php-format
+msgid "Items tagged with: %s"
+msgstr ""
 
-#: ../../mod/directory.php:59
-msgid "Find on this site"
-msgstr "Найти на этом сайте"
+#: mod/search.php:236
+#, php-format
+msgid "Search results for: %s"
+msgstr ""
 
-#: ../../mod/directory.php:62
-msgid "Site Directory"
-msgstr "Каталог сайта"
-
-#: ../../mod/directory.php:113 ../../mod/profiles.php:750
-msgid "Age: "
-msgstr "Возраст: "
-
-#: ../../mod/directory.php:116
-msgid "Gender: "
-msgstr "Пол: "
-
-#: ../../mod/directory.php:138 ../../boot.php:1650
-#: ../../include/profile_advanced.php:17
-msgid "Gender:"
-msgstr "Пол:"
-
-#: ../../mod/directory.php:140 ../../boot.php:1653
-#: ../../include/profile_advanced.php:37
+#: mod/directory.php:149 include/identity.php:313 include/identity.php:610
 msgid "Status:"
 msgstr "Статус:"
 
-#: ../../mod/directory.php:142 ../../boot.php:1655
-#: ../../include/profile_advanced.php:48
+#: mod/directory.php:151 include/identity.php:315 include/identity.php:621
 msgid "Homepage:"
 msgstr "Домашняя страничка:"
 
-#: ../../mod/directory.php:144 ../../boot.php:1657
-#: ../../include/profile_advanced.php:58
-msgid "About:"
-msgstr "О себе:"
+#: mod/directory.php:203 view/theme/diabook/theme.php:525
+#: view/theme/vier/theme.php:205
+msgid "Global Directory"
+msgstr "Глобальный каталог"
 
-#: ../../mod/directory.php:189
+#: mod/directory.php:205
+msgid "Find on this site"
+msgstr "Найти на этом сайте"
+
+#: mod/directory.php:207
+msgid "Finding:"
+msgstr ""
+
+#: mod/directory.php:209
+msgid "Site Directory"
+msgstr "Каталог сайта"
+
+#: mod/directory.php:216
 msgid "No entries (some entries may be hidden)."
 msgstr "Нет записей (некоторые записи могут быть скрыты)."
 
-#: ../../mod/delegate.php:101
+#: mod/delegate.php:101
 msgid "No potential page delegates located."
 msgstr ""
 
-#: ../../mod/delegate.php:130 ../../include/nav.php:170
+#: mod/delegate.php:130 include/nav.php:180
 msgid "Delegate Page Management"
 msgstr "Делегировать управление страницей"
 
-#: ../../mod/delegate.php:132
+#: mod/delegate.php:132
 msgid ""
 "Delegates are able to manage all aspects of this account/page except for "
 "basic account settings. Please do not delegate your personal account to "
 "anybody that you do not trust completely."
-msgstr "Доверенные лица могут управлять всеми аспектами этого аккаунта/страницы, за исключением основных настроек аккаунта. Пожалуйста, не предоставляйте доступ в личный кабинет тому, кому вы не полностью доверяете."
+msgstr ""
+"Доверенные лица могут управлять всеми аспектами этого аккаунта/страницы, за "
+"исключением основных настроек аккаунта. Пожалуйста, не предоставляйте доступ "
+"в личный кабинет тому, кому вы не полностью доверяете."
 
-#: ../../mod/delegate.php:133
+#: mod/delegate.php:133
 msgid "Existing Page Managers"
 msgstr "Существующие менеджеры страницы"
 
-#: ../../mod/delegate.php:135
+#: mod/delegate.php:135
 msgid "Existing Page Delegates"
 msgstr "Существующие уполномоченные страницы"
 
-#: ../../mod/delegate.php:137
+#: mod/delegate.php:137
 msgid "Potential Delegates"
 msgstr "Возможные доверенные лица"
 
-#: ../../mod/delegate.php:140
+#: mod/delegate.php:140
 msgid "Add"
 msgstr "Добавить"
 
-#: ../../mod/delegate.php:141
+#: mod/delegate.php:141
 msgid "No entries."
 msgstr "Нет записей."
 
-#: ../../mod/common.php:42
-msgid "Common Friends"
-msgstr "Общие друзья"
-
-#: ../../mod/common.php:78
+#: mod/common.php:86
 msgid "No contacts in common."
 msgstr "Нет общих контактов."
 
-#: ../../mod/uexport.php:77
+#: mod/uexport.php:77
 msgid "Export account"
 msgstr "Экспорт аккаунта"
 
-#: ../../mod/uexport.php:77
+#: mod/uexport.php:77
 msgid ""
 "Export your account info and contacts. Use this to make a backup of your "
 "account and/or to move it to another server."
-msgstr "Экспорт ваших регистрационных данные и контактов. Используйте, чтобы создать резервную копию вашего аккаунта и/или переместить его на другой сервер."
+msgstr ""
+"Экспорт ваших регистрационных данные и контактов. Используйте, чтобы создать "
+"резервную копию вашего аккаунта и/или переместить его на другой сервер."
 
-#: ../../mod/uexport.php:78
+#: mod/uexport.php:78
 msgid "Export all"
 msgstr "Экспорт всего"
 
-#: ../../mod/uexport.php:78
+#: mod/uexport.php:78
 msgid ""
 "Export your accout info, contacts and all your items as json. Could be a "
 "very big file, and could take a lot of time. Use this to make a full backup "
 "of your account (photos are not exported)"
-msgstr "Экспорт информации вашего аккаунта, контактов и всех ваших пунктов, как JSON. Может получиться очень большой файл и это может занять много времени. Используйте, чтобы создать полную резервную копию вашего аккаунта (фото не экспортируются)"
+msgstr ""
+"Экспорт информации вашего аккаунта, контактов и всех ваших пунктов, как "
+"JSON. Может получиться очень большой файл и это может занять много времени. "
+"Используйте, чтобы создать полную резервную копию вашего аккаунта (фото не "
+"экспортируются)"
 
-#: ../../mod/mood.php:62 ../../include/conversation.php:227
+#: mod/mood.php:62 include/conversation.php:239
 #, php-format
 msgid "%1$s is currently %2$s"
 msgstr ""
 
-#: ../../mod/mood.php:133
+#: mod/mood.php:133
 msgid "Mood"
 msgstr "Настроение"
 
-#: ../../mod/mood.php:134
+#: mod/mood.php:134
 msgid "Set your current mood and tell your friends"
 msgstr "Напишите о вашем настроении и расскажите своим друзьям"
 
-#: ../../mod/suggest.php:27
+#: mod/suggest.php:27
 msgid "Do you really want to delete this suggestion?"
 msgstr "Вы действительно хотите удалить это предложение?"
 
-#: ../../mod/suggest.php:68 ../../include/contact_widgets.php:35
-#: ../../view/theme/diabook/theme.php:527
-msgid "Friend Suggestions"
-msgstr "Предложения друзей"
-
-#: ../../mod/suggest.php:74
+#: mod/suggest.php:71
 msgid ""
 "No suggestions available. If this is a new site, please try again in 24 "
 "hours."
-msgstr "Нет предложений. Если это новый сайт, пожалуйста, попробуйте снова через 24 часа."
+msgstr ""
+"Нет предложений. Если это новый сайт, пожалуйста, попробуйте снова через 24 "
+"часа."
 
-#: ../../mod/suggest.php:92
+#: mod/suggest.php:83 mod/suggest.php:101
 msgid "Ignore/Hide"
 msgstr "Проигнорировать/Скрыть"
 
-#: ../../mod/profiles.php:37
+#: mod/suggest.php:111 include/contact_widgets.php:35
+#: view/theme/diabook/theme.php:527 view/theme/vier/theme.php:207
+msgid "Friend Suggestions"
+msgstr "Предложения друзей"
+
+#: mod/profiles.php:37
 msgid "Profile deleted."
 msgstr "Профиль удален."
 
-#: ../../mod/profiles.php:55 ../../mod/profiles.php:89
+#: mod/profiles.php:55 mod/profiles.php:89
 msgid "Profile-"
 msgstr "Профиль-"
 
-#: ../../mod/profiles.php:74 ../../mod/profiles.php:117
+#: mod/profiles.php:74 mod/profiles.php:117
 msgid "New profile created."
 msgstr "Новый профиль создан."
 
-#: ../../mod/profiles.php:95
+#: mod/profiles.php:95
 msgid "Profile unavailable to clone."
 msgstr "Профиль недоступен для клонирования."
 
-#: ../../mod/profiles.php:189
+#: mod/profiles.php:189
 msgid "Profile Name is required."
 msgstr "Необходимо имя профиля."
 
-#: ../../mod/profiles.php:340
+#: mod/profiles.php:336
 msgid "Marital Status"
 msgstr "Семейное положение"
 
-#: ../../mod/profiles.php:344
+#: mod/profiles.php:340
 msgid "Romantic Partner"
 msgstr "Любимый человек"
 
-#: ../../mod/profiles.php:348
+#: mod/profiles.php:344 mod/photos.php:1647 include/conversation.php:508
 msgid "Likes"
 msgstr "Лайки"
 
-#: ../../mod/profiles.php:352
+#: mod/profiles.php:348 mod/photos.php:1647 include/conversation.php:508
 msgid "Dislikes"
 msgstr "Дизлайк"
 
-#: ../../mod/profiles.php:356
+#: mod/profiles.php:352
 msgid "Work/Employment"
 msgstr "Работа/Занятость"
 
-#: ../../mod/profiles.php:359
+#: mod/profiles.php:355
 msgid "Religion"
 msgstr "Религия"
 
-#: ../../mod/profiles.php:363
+#: mod/profiles.php:359
 msgid "Political Views"
 msgstr "Политические взгляды"
 
-#: ../../mod/profiles.php:367
+#: mod/profiles.php:363
 msgid "Gender"
 msgstr "Пол"
 
-#: ../../mod/profiles.php:371
+#: mod/profiles.php:367
 msgid "Sexual Preference"
 msgstr "Сексуальные предпочтения"
 
-#: ../../mod/profiles.php:375
+#: mod/profiles.php:371
 msgid "Homepage"
 msgstr "Домашняя страница"
 
-#: ../../mod/profiles.php:379 ../../mod/profiles.php:698
+#: mod/profiles.php:375 mod/profiles.php:708
 msgid "Interests"
 msgstr "Хобби / Интересы"
 
-#: ../../mod/profiles.php:383
+#: mod/profiles.php:379
 msgid "Address"
 msgstr "Адрес"
 
-#: ../../mod/profiles.php:390 ../../mod/profiles.php:694
+#: mod/profiles.php:386 mod/profiles.php:704
 msgid "Location"
 msgstr "Местонахождение"
 
-#: ../../mod/profiles.php:473
+#: mod/profiles.php:469
 msgid "Profile updated."
 msgstr "Профиль обновлен."
 
-#: ../../mod/profiles.php:568
+#: mod/profiles.php:565
 msgid " and "
 msgstr "и"
 
-#: ../../mod/profiles.php:576
+#: mod/profiles.php:573
 msgid "public profile"
 msgstr "публичный профиль"
 
-#: ../../mod/profiles.php:579
+#: mod/profiles.php:576
 #, php-format
 msgid "%1$s changed %2$s to &ldquo;%3$s&rdquo;"
 msgstr "%1$s изменились с %2$s на &ldquo;%3$s&rdquo;"
 
-#: ../../mod/profiles.php:580
+#: mod/profiles.php:577
 #, php-format
 msgid " - Visit %1$s's %2$s"
 msgstr " - Посетить профиль %1$s [%2$s]"
 
-#: ../../mod/profiles.php:583
+#: mod/profiles.php:580
 #, php-format
 msgid "%1$s has an updated %2$s, changing %3$s."
 msgstr ""
 
-#: ../../mod/profiles.php:658
+#: mod/profiles.php:655
 msgid "Hide contacts and friends:"
 msgstr ""
 
-#: ../../mod/profiles.php:663
+#: mod/profiles.php:660
 msgid "Hide your contact/friend list from viewers of this profile?"
 msgstr "Скрывать ваш список контактов / друзей от посетителей этого профиля?"
 
-#: ../../mod/profiles.php:685
+#: mod/profiles.php:684
+msgid "Show more profile fields:"
+msgstr ""
+
+#: mod/profiles.php:695
 msgid "Edit Profile Details"
 msgstr "Редактировать детали профиля"
 
-#: ../../mod/profiles.php:687
+#: mod/profiles.php:697
 msgid "Change Profile Photo"
 msgstr "Изменить фото профиля"
 
-#: ../../mod/profiles.php:688
+#: mod/profiles.php:698
 msgid "View this profile"
 msgstr "Просмотреть этот профиль"
 
-#: ../../mod/profiles.php:689
+#: mod/profiles.php:699
 msgid "Create a new profile using these settings"
 msgstr "Создать новый профиль, используя эти настройки"
 
-#: ../../mod/profiles.php:690
+#: mod/profiles.php:700
 msgid "Clone this profile"
 msgstr "Клонировать этот профиль"
 
-#: ../../mod/profiles.php:691
+#: mod/profiles.php:701
 msgid "Delete this profile"
 msgstr "Удалить этот профиль"
 
-#: ../../mod/profiles.php:692
+#: mod/profiles.php:702
 msgid "Basic information"
 msgstr ""
 
-#: ../../mod/profiles.php:693
+#: mod/profiles.php:703
 msgid "Profile picture"
 msgstr ""
 
-#: ../../mod/profiles.php:695
+#: mod/profiles.php:705
 msgid "Preferences"
 msgstr ""
 
-#: ../../mod/profiles.php:696
+#: mod/profiles.php:706
 msgid "Status information"
 msgstr ""
 
-#: ../../mod/profiles.php:697
+#: mod/profiles.php:707
 msgid "Additional information"
 msgstr ""
 
-#: ../../mod/profiles.php:700
+#: mod/profiles.php:710
 msgid "Profile Name:"
 msgstr "Имя профиля:"
 
-#: ../../mod/profiles.php:701
+#: mod/profiles.php:711
 msgid "Your Full Name:"
 msgstr "Ваше полное имя:"
 
-#: ../../mod/profiles.php:702
+#: mod/profiles.php:712
 msgid "Title/Description:"
 msgstr "Заголовок / Описание:"
 
-#: ../../mod/profiles.php:703
+#: mod/profiles.php:713
 msgid "Your Gender:"
 msgstr "Ваш пол:"
 
-#: ../../mod/profiles.php:704
-#, php-format
-msgid "Birthday (%s):"
-msgstr "День рождения (%s):"
+#: mod/profiles.php:714
+msgid "Birthday :"
+msgstr ""
 
-#: ../../mod/profiles.php:705
+#: mod/profiles.php:715
 msgid "Street Address:"
 msgstr "Адрес:"
 
-#: ../../mod/profiles.php:706
+#: mod/profiles.php:716
 msgid "Locality/City:"
 msgstr "Город / Населенный пункт:"
 
-#: ../../mod/profiles.php:707
+#: mod/profiles.php:717
 msgid "Postal/Zip Code:"
 msgstr "Почтовый индекс:"
 
-#: ../../mod/profiles.php:708
+#: mod/profiles.php:718
 msgid "Country:"
 msgstr "Страна:"
 
-#: ../../mod/profiles.php:709
+#: mod/profiles.php:719
 msgid "Region/State:"
 msgstr "Район / Область:"
 
-#: ../../mod/profiles.php:710
+#: mod/profiles.php:720
 msgid "<span class=\"heart\">&hearts;</span> Marital Status:"
 msgstr "<span class=\"heart\">&hearts;</span> Семейное положение:"
 
-#: ../../mod/profiles.php:711
+#: mod/profiles.php:721
 msgid "Who: (if applicable)"
 msgstr "Кто: (если требуется)"
 
-#: ../../mod/profiles.php:712
+#: mod/profiles.php:722
 msgid "Examples: cathy123, Cathy Williams, cathy@example.com"
 msgstr "Примеры: cathy123, Кэти Уильямс, cathy@example.com"
 
-#: ../../mod/profiles.php:713
+#: mod/profiles.php:723
 msgid "Since [date]:"
 msgstr "С какого времени [дата]:"
 
-#: ../../mod/profiles.php:714 ../../include/profile_advanced.php:46
+#: mod/profiles.php:724 include/identity.php:619
 msgid "Sexual Preference:"
 msgstr "Сексуальные предпочтения:"
 
-#: ../../mod/profiles.php:715
+#: mod/profiles.php:725
 msgid "Homepage URL:"
 msgstr "Адрес домашней странички:"
 
-#: ../../mod/profiles.php:716 ../../include/profile_advanced.php:50
+#: mod/profiles.php:726 include/identity.php:623
 msgid "Hometown:"
 msgstr "Родной город:"
 
-#: ../../mod/profiles.php:717 ../../include/profile_advanced.php:54
+#: mod/profiles.php:727 include/identity.php:627
 msgid "Political Views:"
 msgstr "Политические взгляды:"
 
-#: ../../mod/profiles.php:718
+#: mod/profiles.php:728
 msgid "Religious Views:"
 msgstr "Религиозные взгляды:"
 
-#: ../../mod/profiles.php:719
+#: mod/profiles.php:729
 msgid "Public Keywords:"
 msgstr "Общественные ключевые слова:"
 
-#: ../../mod/profiles.php:720
+#: mod/profiles.php:730
 msgid "Private Keywords:"
 msgstr "Личные ключевые слова:"
 
-#: ../../mod/profiles.php:721 ../../include/profile_advanced.php:62
+#: mod/profiles.php:731 include/identity.php:635
 msgid "Likes:"
 msgstr "Нравится:"
 
-#: ../../mod/profiles.php:722 ../../include/profile_advanced.php:64
+#: mod/profiles.php:732 include/identity.php:637
 msgid "Dislikes:"
 msgstr "Не нравится:"
 
-#: ../../mod/profiles.php:723
+#: mod/profiles.php:733
 msgid "Example: fishing photography software"
 msgstr "Пример: рыбалка фотографии программное обеспечение"
 
-#: ../../mod/profiles.php:724
+#: mod/profiles.php:734
 msgid "(Used for suggesting potential friends, can be seen by others)"
-msgstr "(Используется для предложения потенциальным друзьям, могут увидеть другие)"
+msgstr ""
+"(Используется для предложения потенциальным друзьям, могут увидеть другие)"
 
-#: ../../mod/profiles.php:725
+#: mod/profiles.php:735
 msgid "(Used for searching profiles, never shown to others)"
 msgstr "(Используется для поиска профилей, никогда не показывается другим)"
 
-#: ../../mod/profiles.php:726
+#: mod/profiles.php:736
 msgid "Tell us about yourself..."
 msgstr "Расскажите нам о себе ..."
 
-#: ../../mod/profiles.php:727
+#: mod/profiles.php:737
 msgid "Hobbies/Interests"
 msgstr "Хобби / Интересы"
 
-#: ../../mod/profiles.php:728
+#: mod/profiles.php:738
 msgid "Contact information and Social Networks"
 msgstr "Контактная информация и социальные сети"
 
-#: ../../mod/profiles.php:729
+#: mod/profiles.php:739
 msgid "Musical interests"
 msgstr "Музыкальные интересы"
 
-#: ../../mod/profiles.php:730
+#: mod/profiles.php:740
 msgid "Books, literature"
 msgstr "Книги, литература"
 
-#: ../../mod/profiles.php:731
+#: mod/profiles.php:741
 msgid "Television"
 msgstr "Телевидение"
 
-#: ../../mod/profiles.php:732
+#: mod/profiles.php:742
 msgid "Film/dance/culture/entertainment"
 msgstr "Кино / танцы / культура / развлечения"
 
-#: ../../mod/profiles.php:733
+#: mod/profiles.php:743
 msgid "Love/romance"
 msgstr "Любовь / романтика"
 
-#: ../../mod/profiles.php:734
+#: mod/profiles.php:744
 msgid "Work/employment"
 msgstr "Работа / занятость"
 
-#: ../../mod/profiles.php:735
+#: mod/profiles.php:745
 msgid "School/education"
 msgstr "Школа / образование"
 
-#: ../../mod/profiles.php:740
+#: mod/profiles.php:750
 msgid ""
 "This is your <strong>public</strong> profile.<br />It <strong>may</strong> "
 "be visible to anybody using the internet."
-msgstr "Это ваш <strong>публичный</strong> профиль. <br /> Он <strong>может</strong> быть виден каждому через Интернет."
+msgstr ""
+"Это ваш <strong>публичный</strong> профиль. <br /> Он <strong>может</strong> "
+"быть виден каждому через Интернет."
 
-#: ../../mod/profiles.php:803
+#: mod/profiles.php:760
+msgid "Age: "
+msgstr "Возраст: "
+
+#: mod/profiles.php:813
 msgid "Edit/Manage Profiles"
 msgstr "Редактировать профиль"
 
-#: ../../mod/profiles.php:804 ../../boot.php:1611 ../../boot.php:1637
+#: mod/profiles.php:814 include/identity.php:260 include/identity.php:286
 msgid "Change profile photo"
 msgstr "Изменить фото профиля"
 
-#: ../../mod/profiles.php:805 ../../boot.php:1612
+#: mod/profiles.php:815 include/identity.php:261
 msgid "Create New Profile"
 msgstr "Создать новый профиль"
 
-#: ../../mod/profiles.php:816 ../../boot.php:1622
+#: mod/profiles.php:826 include/identity.php:271
 msgid "Profile Image"
 msgstr "Фото профиля"
 
-#: ../../mod/profiles.php:818 ../../boot.php:1625
+#: mod/profiles.php:828 include/identity.php:274
 msgid "visible to everybody"
 msgstr "видимый всем"
 
-#: ../../mod/profiles.php:819 ../../boot.php:1626
+#: mod/profiles.php:829 include/identity.php:275
 msgid "Edit visibility"
 msgstr "Редактировать видимость"
 
-#: ../../mod/editpost.php:17 ../../mod/editpost.php:27
+#: mod/editpost.php:17 mod/editpost.php:27
 msgid "Item not found"
 msgstr "Элемент не найден"
 
-#: ../../mod/editpost.php:39
+#: mod/editpost.php:40
 msgid "Edit post"
 msgstr "Редактировать сообщение"
 
-#: ../../mod/editpost.php:111 ../../include/conversation.php:1092
+#: mod/editpost.php:111 include/conversation.php:1184
 msgid "upload photo"
 msgstr "загрузить фото"
 
-#: ../../mod/editpost.php:112 ../../include/conversation.php:1093
+#: mod/editpost.php:112 include/conversation.php:1185
 msgid "Attach file"
-msgstr "Приложить файл"
+msgstr "Прикрепить файл"
 
-#: ../../mod/editpost.php:113 ../../include/conversation.php:1094
+#: mod/editpost.php:113 include/conversation.php:1186
 msgid "attach file"
 msgstr "приложить файл"
 
-#: ../../mod/editpost.php:115 ../../include/conversation.php:1096
+#: mod/editpost.php:115 include/conversation.php:1188
 msgid "web link"
 msgstr "веб-ссылка"
 
-#: ../../mod/editpost.php:116 ../../include/conversation.php:1097
+#: mod/editpost.php:116 include/conversation.php:1189
 msgid "Insert video link"
 msgstr "Вставить ссылку видео"
 
-#: ../../mod/editpost.php:117 ../../include/conversation.php:1098
+#: mod/editpost.php:117 include/conversation.php:1190
 msgid "video link"
 msgstr "видео-ссылка"
 
-#: ../../mod/editpost.php:118 ../../include/conversation.php:1099
+#: mod/editpost.php:118 include/conversation.php:1191
 msgid "Insert audio link"
 msgstr "Вставить ссылку аудио"
 
-#: ../../mod/editpost.php:119 ../../include/conversation.php:1100
+#: mod/editpost.php:119 include/conversation.php:1192
 msgid "audio link"
 msgstr "аудио-ссылка"
 
-#: ../../mod/editpost.php:120 ../../include/conversation.php:1101
+#: mod/editpost.php:120 include/conversation.php:1193
 msgid "Set your location"
 msgstr "Задать ваше местоположение"
 
-#: ../../mod/editpost.php:121 ../../include/conversation.php:1102
+#: mod/editpost.php:121 include/conversation.php:1194
 msgid "set location"
 msgstr "установить местонахождение"
 
-#: ../../mod/editpost.php:122 ../../include/conversation.php:1103
+#: mod/editpost.php:122 include/conversation.php:1195
 msgid "Clear browser location"
 msgstr "Очистить местонахождение браузера"
 
-#: ../../mod/editpost.php:123 ../../include/conversation.php:1104
+#: mod/editpost.php:123 include/conversation.php:1196
 msgid "clear location"
 msgstr "убрать местонахождение"
 
-#: ../../mod/editpost.php:125 ../../include/conversation.php:1110
+#: mod/editpost.php:125 include/conversation.php:1202
 msgid "Permission settings"
 msgstr "Настройки разрешений"
 
-#: ../../mod/editpost.php:133 ../../include/conversation.php:1119
+#: mod/editpost.php:133 include/acl_selectors.php:344
 msgid "CC: email addresses"
 msgstr "Копии на email адреса"
 
-#: ../../mod/editpost.php:134 ../../include/conversation.php:1120
+#: mod/editpost.php:134 include/conversation.php:1211
 msgid "Public post"
 msgstr "Публичное сообщение"
 
-#: ../../mod/editpost.php:137 ../../include/conversation.php:1106
+#: mod/editpost.php:137 include/conversation.php:1198
 msgid "Set title"
 msgstr "Установить заголовок"
 
-#: ../../mod/editpost.php:139 ../../include/conversation.php:1108
+#: mod/editpost.php:139 include/conversation.php:1200
 msgid "Categories (comma-separated list)"
 msgstr "Категории (список через запятую)"
 
-#: ../../mod/editpost.php:140 ../../include/conversation.php:1122
+#: mod/editpost.php:140 include/acl_selectors.php:345
 msgid "Example: bob@example.com, mary@example.com"
 msgstr "Пример: bob@example.com, mary@example.com"
 
-#: ../../mod/friendica.php:59
+#: mod/friendica.php:70
 msgid "This is Friendica, version"
 msgstr "Это Friendica, версия"
 
-#: ../../mod/friendica.php:60
+#: mod/friendica.php:71
 msgid "running at web location"
 msgstr "работает на веб-узле"
 
-#: ../../mod/friendica.php:62
+#: mod/friendica.php:73
 msgid ""
 "Please visit <a href=\"http://friendica.com\">Friendica.com</a> to learn "
 "more about the Friendica project."
-msgstr "Пожалуйста, посетите сайт <a href=\"http://friendica.com\">Friendica.com</a>, чтобы узнать больше о проекте Friendica."
+msgstr ""
+"Пожалуйста, посетите сайт <a href=\"http://friendica.com\">Friendica.com</"
+"a>, чтобы узнать больше о проекте Friendica."
 
-#: ../../mod/friendica.php:64
+#: mod/friendica.php:75
 msgid "Bug reports and issues: please visit"
 msgstr "Отчет об ошибках и проблемах: пожалуйста, посетите"
 
-#: ../../mod/friendica.php:65
+#: mod/friendica.php:75
+msgid "the bugtracker at github"
+msgstr ""
+
+#: mod/friendica.php:76
 msgid ""
 "Suggestions, praise, donations, etc. - please email \"Info\" at Friendica - "
 "dot com"
-msgstr "Предложения, похвала, пожертвования? Пишите на \"info\" на Friendica - точка com"
+msgstr ""
+"Предложения, похвала, пожертвования? Пишите на \"info\" на Friendica - точка "
+"com"
 
-#: ../../mod/friendica.php:79
+#: mod/friendica.php:90
 msgid "Installed plugins/addons/apps:"
 msgstr "Установленные плагины / добавки / приложения:"
 
-#: ../../mod/friendica.php:92
+#: mod/friendica.php:103
 msgid "No installed plugins/addons/apps"
 msgstr "Нет установленных плагинов / добавок / приложений"
 
-#: ../../mod/api.php:76 ../../mod/api.php:102
+#: mod/api.php:76 mod/api.php:102
 msgid "Authorize application connection"
 msgstr "Разрешить связь с приложением"
 
-#: ../../mod/api.php:77
+#: mod/api.php:77
 msgid "Return to your app and insert this Securty Code:"
 msgstr "Вернитесь в ваше приложение и задайте этот код:"
 
-#: ../../mod/api.php:89
+#: mod/api.php:89
 msgid "Please login to continue."
 msgstr "Пожалуйста, войдите для продолжения."
 
-#: ../../mod/api.php:104
+#: mod/api.php:104
 msgid ""
-"Do you want to authorize this application to access your posts and contacts,"
-" and/or create new posts for you?"
-msgstr "Вы действительно хотите разрешить этому приложению доступ к своим постам и контактам, а также создавать новые записи от вашего имени?"
+"Do you want to authorize this application to access your posts and contacts, "
+"and/or create new posts for you?"
+msgstr ""
+"Вы действительно хотите разрешить этому приложению доступ к своим постам и "
+"контактам, а также создавать новые записи от вашего имени?"
 
-#: ../../mod/lockview.php:31 ../../mod/lockview.php:39
+#: mod/lockview.php:31 mod/lockview.php:39
 msgid "Remote privacy information not available."
 msgstr "Личная информация удаленно недоступна."
 
-#: ../../mod/lockview.php:48
+#: mod/lockview.php:48
 msgid "Visible to:"
 msgstr "Кто может видеть:"
 
-#: ../../mod/notes.php:44 ../../boot.php:2150
+#: mod/notes.php:46 include/identity.php:730
 msgid "Personal Notes"
 msgstr "Личные заметки"
 
-#: ../../mod/localtime.php:12 ../../include/bb2diaspora.php:148
-#: ../../include/event.php:11
+#: mod/localtime.php:12 include/bb2diaspora.php:148 include/event.php:13
 msgid "l F d, Y \\@ g:i A"
 msgstr "l F d, Y \\@ g:i A"
 
-#: ../../mod/localtime.php:24
+#: mod/localtime.php:24
 msgid "Time Conversion"
 msgstr "История общения"
 
-#: ../../mod/localtime.php:26
+#: mod/localtime.php:26
 msgid ""
 "Friendica provides this service for sharing events with other networks and "
 "friends in unknown timezones."
-msgstr "Friendica предоставляет этот сервис для обмена событиями с другими сетями и друзьями, находящимися в неопределённых часовых поясах."
+msgstr ""
+"Friendica предоставляет этот сервис для обмена событиями с другими сетями и "
+"друзьями, находящимися в неопределённых часовых поясах."
 
-#: ../../mod/localtime.php:30
+#: mod/localtime.php:30
 #, php-format
 msgid "UTC time: %s"
 msgstr "UTC время: %s"
 
-#: ../../mod/localtime.php:33
+#: mod/localtime.php:33
 #, php-format
 msgid "Current timezone: %s"
 msgstr "Ваш часовой пояс: %s"
 
-#: ../../mod/localtime.php:36
+#: mod/localtime.php:36
 #, php-format
 msgid "Converted localtime: %s"
 msgstr "Ваше изменённое время: %s"
 
-#: ../../mod/localtime.php:41
+#: mod/localtime.php:41
 msgid "Please select your timezone:"
 msgstr "Выберите пожалуйста ваш часовой пояс:"
 
-#: ../../mod/poke.php:192
+#: mod/poke.php:191
 msgid "Poke/Prod"
 msgstr ""
 
-#: ../../mod/poke.php:193
+#: mod/poke.php:192
 msgid "poke, prod or do other things to somebody"
 msgstr ""
 
-#: ../../mod/poke.php:194
+#: mod/poke.php:193
 msgid "Recipient"
 msgstr "Получатель"
 
-#: ../../mod/poke.php:195
+#: mod/poke.php:194
 msgid "Choose what you wish to do to recipient"
 msgstr "Выберите действия для получателя"
 
-#: ../../mod/poke.php:198
+#: mod/poke.php:197
 msgid "Make this post private"
 msgstr "Сделать эту запись личной"
 
-#: ../../mod/invite.php:27
+#: mod/repair_ostatus.php:14
+msgid "Resubscribing to OStatus contacts"
+msgstr ""
+
+#: mod/repair_ostatus.php:30
+msgid "Error"
+msgstr "Ошибка"
+
+#: mod/invite.php:27
 msgid "Total invitation limit exceeded."
 msgstr "Превышен общий лимит приглашений."
 
-#: ../../mod/invite.php:49
+#: mod/invite.php:49
 #, php-format
 msgid "%s : Not a valid email address."
 msgstr "%s: Неверный адрес электронной почты."
 
-#: ../../mod/invite.php:73
+#: mod/invite.php:73
 msgid "Please join us on Friendica"
 msgstr "Пожалуйста, присоединяйтесь к нам на Friendica"
 
-#: ../../mod/invite.php:84
+#: mod/invite.php:84
 msgid "Invitation limit exceeded. Please contact your site administrator."
-msgstr "Лимит приглашений превышен. Пожалуйста, свяжитесь с администратором сайта."
+msgstr ""
+"Лимит приглашений превышен. Пожалуйста, свяжитесь с администратором сайта."
 
-#: ../../mod/invite.php:89
+#: mod/invite.php:89
 #, php-format
 msgid "%s : Message delivery failed."
 msgstr "%s: Доставка сообщения не удалась."
 
-#: ../../mod/invite.php:93
+#: mod/invite.php:93
 #, php-format
 msgid "%d message sent."
 msgid_plural "%d messages sent."
 msgstr[0] "%d сообщение отправлено."
 msgstr[1] "%d сообщений отправлено."
 msgstr[2] "%d сообщений отправлено."
+msgstr[3] "%d сообщений отправлено."
 
-#: ../../mod/invite.php:112
+#: mod/invite.php:112
 msgid "You have no more invitations available"
 msgstr "У вас нет больше приглашений"
 
-#: ../../mod/invite.php:120
+#: mod/invite.php:120
 #, php-format
 msgid ""
 "Visit %s for a list of public sites that you can join. Friendica members on "
-"other sites can all connect with each other, as well as with members of many"
-" other social networks."
-msgstr "Посетите %s со списком общедоступных сайтов, к которым вы можете присоединиться. Все участники Friendica на других сайтах могут соединиться друг с другом, а также с участниками многих других социальных сетей."
+"other sites can all connect with each other, as well as with members of many "
+"other social networks."
+msgstr ""
+"Посетите %s со списком общедоступных сайтов, к которым вы можете "
+"присоединиться. Все участники Friendica на других сайтах могут соединиться "
+"друг с другом, а также с участниками многих других социальных сетей."
 
-#: ../../mod/invite.php:122
+#: mod/invite.php:122
 #, php-format
 msgid ""
 "To accept this invitation, please visit and register at %s or any other "
 "public Friendica website."
-msgstr "Для одобрения этого приглашения, пожалуйста, посетите и зарегистрируйтесь на %s ,или любом другом публичном сервере Friendica"
+msgstr ""
+"Для одобрения этого приглашения, пожалуйста, посетите и зарегистрируйтесь на "
+"%s ,или любом другом публичном сервере Friendica"
 
-#: ../../mod/invite.php:123
+#: mod/invite.php:123
 #, php-format
 msgid ""
 "Friendica sites all inter-connect to create a huge privacy-enhanced social "
 "web that is owned and controlled by its members. They can also connect with "
 "many traditional social networks. See %s for a list of alternate Friendica "
 "sites you can join."
-msgstr "Сайты Friendica, подключившись между собой, могут создать сеть с повышенной безопасностью, которая принадлежит и управляется её членами. Они также могут подключаться ко многим традиционным социальным сетям. См. %s  со списком альтернативных сайтов Friendica, к которым вы можете присоединиться."
+msgstr ""
+"Сайты Friendica, подключившись между собой, могут создать сеть с повышенной "
+"безопасностью, которая принадлежит и управляется её членами. Они также могут "
+"подключаться ко многим традиционным социальным сетям. См. %s  со списком "
+"альтернативных сайтов Friendica, к которым вы можете присоединиться."
 
-#: ../../mod/invite.php:126
+#: mod/invite.php:126
 msgid ""
-"Our apologies. This system is not currently configured to connect with other"
-" public sites or invite members."
-msgstr "Извините. Эта система в настоящее время не сконфигурирована для соединения с другими общественными сайтами и для приглашения участников."
+"Our apologies. This system is not currently configured to connect with other "
+"public sites or invite members."
+msgstr ""
+"Извините. Эта система в настоящее время не сконфигурирована для соединения с "
+"другими общественными сайтами и для приглашения участников."
 
-#: ../../mod/invite.php:132
+#: mod/invite.php:132
 msgid "Send invitations"
 msgstr "Отправить приглашения"
 
-#: ../../mod/invite.php:133
+#: mod/invite.php:133
 msgid "Enter email addresses, one per line:"
 msgstr "Введите адреса электронной почты, по одному в строке:"
 
-#: ../../mod/invite.php:135
+#: mod/invite.php:135
 msgid ""
 "You are cordially invited to join me and other close friends on Friendica - "
 "and help us to create a better social web."
-msgstr "Приглашаем Вас присоединиться ко мне и другим близким друзьям на Friendica - помочь нам создать лучшую социальную сеть."
+msgstr ""
+"Приглашаем Вас присоединиться ко мне и другим близким друзьям на Friendica - "
+"помочь нам создать лучшую социальную сеть."
 
-#: ../../mod/invite.php:137
+#: mod/invite.php:137
 msgid "You will need to supply this invitation code: $invite_code"
 msgstr "Вам нужно будет предоставить этот код приглашения: $invite_code"
 
-#: ../../mod/invite.php:137
+#: mod/invite.php:137
 msgid ""
 "Once you have registered, please connect with me via my profile page at:"
-msgstr "После того как вы зарегистрировались, пожалуйста, свяжитесь со мной через мою страницу профиля по адресу:"
+msgstr ""
+"После того как вы зарегистрировались, пожалуйста, свяжитесь со мной через "
+"мою страницу профиля по адресу:"
 
-#: ../../mod/invite.php:139
+#: mod/invite.php:139
 msgid ""
 "For more information about the Friendica project and why we feel it is "
 "important, please visit http://friendica.com"
-msgstr "Для получения более подробной информации о проекте Friendica, пожалуйста, посетите http://friendica.com"
+msgstr ""
+"Для получения более подробной информации о проекте Friendica, пожалуйста, "
+"посетите http://friendica.com"
 
-#: ../../mod/photos.php:52 ../../boot.php:2129
+#: mod/photos.php:99 include/identity.php:705
 msgid "Photo Albums"
 msgstr "Фотоальбомы"
 
-#: ../../mod/photos.php:60 ../../mod/photos.php:155 ../../mod/photos.php:1064
-#: ../../mod/photos.php:1187 ../../mod/photos.php:1210
-#: ../../mod/photos.php:1760 ../../mod/photos.php:1772
-#: ../../view/theme/diabook/theme.php:499
-msgid "Contact Photos"
-msgstr "Фотографии контакта"
+#: mod/photos.php:100 mod/photos.php:1899
+msgid "Recent Photos"
+msgstr "Последние фото"
 
-#: ../../mod/photos.php:67 ../../mod/photos.php:1262 ../../mod/photos.php:1819
+#: mod/photos.php:103 mod/photos.php:1320 mod/photos.php:1901
 msgid "Upload New Photos"
 msgstr "Загрузить новые фото"
 
-#: ../../mod/photos.php:144
+#: mod/photos.php:181
 msgid "Contact information unavailable"
 msgstr "Информация о контакте недоступна"
 
-#: ../../mod/photos.php:165
+#: mod/photos.php:202
 msgid "Album not found."
 msgstr "Альбом не найден."
 
-#: ../../mod/photos.php:188 ../../mod/photos.php:200 ../../mod/photos.php:1204
+#: mod/photos.php:232 mod/photos.php:244 mod/photos.php:1262
 msgid "Delete Album"
 msgstr "Удалить альбом"
 
-#: ../../mod/photos.php:198
+#: mod/photos.php:242
 msgid "Do you really want to delete this photo album and all its photos?"
 msgstr "Вы действительно хотите удалить этот альбом и все его фотографии?"
 
-#: ../../mod/photos.php:278 ../../mod/photos.php:289 ../../mod/photos.php:1515
+#: mod/photos.php:322 mod/photos.php:333 mod/photos.php:1580
 msgid "Delete Photo"
 msgstr "Удалить фото"
 
-#: ../../mod/photos.php:287
+#: mod/photos.php:331
 msgid "Do you really want to delete this photo?"
 msgstr "Вы действительно хотите удалить эту фотографию?"
 
-#: ../../mod/photos.php:662
+#: mod/photos.php:706
 #, php-format
 msgid "%1$s was tagged in %2$s by %3$s"
 msgstr "%1$s отмечен/а/ в %2$s by %3$s"
 
-#: ../../mod/photos.php:662
+#: mod/photos.php:706
 msgid "a photo"
 msgstr "фото"
 
-#: ../../mod/photos.php:767
-msgid "Image exceeds size limit of "
-msgstr "Размер фото превышает лимит "
-
-#: ../../mod/photos.php:775
+#: mod/photos.php:819
 msgid "Image file is empty."
 msgstr "Файл изображения пуст."
 
-#: ../../mod/photos.php:930
+#: mod/photos.php:986
 msgid "No photos selected"
 msgstr "Не выбрано фото."
 
-#: ../../mod/photos.php:1094
+#: mod/photos.php:1147
 #, php-format
 msgid "You have used %1$.2f Mbytes of %2$.2f Mbytes photo storage."
-msgstr "Вы использовали %1$.2f мегабайт из %2$.2f возможных для хранения фотографий."
+msgstr ""
+"Вы использовали %1$.2f мегабайт из %2$.2f возможных для хранения фотографий."
 
-#: ../../mod/photos.php:1129
+#: mod/photos.php:1182
 msgid "Upload Photos"
 msgstr "Загрузить фото"
 
-#: ../../mod/photos.php:1133 ../../mod/photos.php:1199
+#: mod/photos.php:1186 mod/photos.php:1257
 msgid "New album name: "
 msgstr "Название нового альбома: "
 
-#: ../../mod/photos.php:1134
+#: mod/photos.php:1187
 msgid "or existing album name: "
 msgstr "или название существующего альбома: "
 
-#: ../../mod/photos.php:1135
+#: mod/photos.php:1188
 msgid "Do not show a status post for this upload"
 msgstr "Не показывать статус-сообщение для этой закачки"
 
-#: ../../mod/photos.php:1137 ../../mod/photos.php:1510
+#: mod/photos.php:1190 mod/photos.php:1575 include/acl_selectors.php:347
 msgid "Permissions"
 msgstr "Разрешения"
 
-#: ../../mod/photos.php:1148
+#: mod/photos.php:1201
 msgid "Private Photo"
 msgstr "Личное фото"
 
-#: ../../mod/photos.php:1149
+#: mod/photos.php:1202
 msgid "Public Photo"
 msgstr "Публичное фото"
 
-#: ../../mod/photos.php:1212
+#: mod/photos.php:1270
 msgid "Edit Album"
 msgstr "Редактировать альбом"
 
-#: ../../mod/photos.php:1218
+#: mod/photos.php:1276
 msgid "Show Newest First"
 msgstr "Показать новые первыми"
 
-#: ../../mod/photos.php:1220
+#: mod/photos.php:1278
 msgid "Show Oldest First"
 msgstr "Показать старые первыми"
 
-#: ../../mod/photos.php:1248 ../../mod/photos.php:1802
+#: mod/photos.php:1306 mod/photos.php:1884
 msgid "View Photo"
 msgstr "Просмотр фото"
 
-#: ../../mod/photos.php:1294
+#: mod/photos.php:1353
 msgid "Permission denied. Access to this item may be restricted."
 msgstr "Нет разрешения. Доступ к этому элементу ограничен."
 
-#: ../../mod/photos.php:1296
+#: mod/photos.php:1355
 msgid "Photo not available"
 msgstr "Фото недоступно"
 
-#: ../../mod/photos.php:1352
+#: mod/photos.php:1411
 msgid "View photo"
 msgstr "Просмотр фото"
 
-#: ../../mod/photos.php:1352
+#: mod/photos.php:1411
 msgid "Edit photo"
 msgstr "Редактировать фото"
 
-#: ../../mod/photos.php:1353
+#: mod/photos.php:1412
 msgid "Use as profile photo"
 msgstr "Использовать как фото профиля"
 
-#: ../../mod/photos.php:1378
+#: mod/photos.php:1437
 msgid "View Full Size"
 msgstr "Просмотреть полный размер"
 
-#: ../../mod/photos.php:1457
+#: mod/photos.php:1523
 msgid "Tags: "
 msgstr "Ключевые слова: "
 
-#: ../../mod/photos.php:1460
+#: mod/photos.php:1526
 msgid "[Remove any tag]"
 msgstr "[Удалить любое ключевое слово]"
 
-#: ../../mod/photos.php:1500
-msgid "Rotate CW (right)"
-msgstr "Поворот по часовой стрелке (направо)"
-
-#: ../../mod/photos.php:1501
-msgid "Rotate CCW (left)"
-msgstr "Поворот против часовой стрелки (налево)"
-
-#: ../../mod/photos.php:1503
+#: mod/photos.php:1566
 msgid "New album name"
 msgstr "Название нового альбома"
 
-#: ../../mod/photos.php:1506
+#: mod/photos.php:1567
 msgid "Caption"
 msgstr "Подпись"
 
-#: ../../mod/photos.php:1508
+#: mod/photos.php:1568
 msgid "Add a Tag"
 msgstr "Добавить ключевое слово (таг)"
 
-#: ../../mod/photos.php:1512
-msgid ""
-"Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
+#: mod/photos.php:1568
+msgid "Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
 msgstr "Пример: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
 
-#: ../../mod/photos.php:1521
+#: mod/photos.php:1569
+msgid "Do not rotate"
+msgstr ""
+
+#: mod/photos.php:1570
+msgid "Rotate CW (right)"
+msgstr "Поворот по часовой стрелке (направо)"
+
+#: mod/photos.php:1571
+msgid "Rotate CCW (left)"
+msgstr "Поворот против часовой стрелки (налево)"
+
+#: mod/photos.php:1586
 msgid "Private photo"
 msgstr "Личное фото"
 
-#: ../../mod/photos.php:1522
+#: mod/photos.php:1587
 msgid "Public photo"
 msgstr "Публичное фото"
 
-#: ../../mod/photos.php:1544 ../../include/conversation.php:1090
+#: mod/photos.php:1609 include/conversation.php:1182
 msgid "Share"
 msgstr "Поделиться"
 
-#: ../../mod/photos.php:1817
-msgid "Recent Photos"
-msgstr "Последние фото"
+#: mod/photos.php:1648 include/conversation.php:509
+#: include/conversation.php:1413
+msgid "Attending"
+msgid_plural "Attending"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
 
-#: ../../mod/regmod.php:55
+#: mod/photos.php:1648 include/conversation.php:509
+msgid "Not attending"
+msgstr ""
+
+#: mod/photos.php:1648 include/conversation.php:509
+msgid "Might attend"
+msgstr ""
+
+#: mod/photos.php:1813
+msgid "Map"
+msgstr "Карта"
+
+#: mod/p.php:9
+msgid "Not Extended"
+msgstr ""
+
+#: mod/regmod.php:55
 msgid "Account approved."
 msgstr "Аккаунт утвержден."
 
-#: ../../mod/regmod.php:92
+#: mod/regmod.php:92
 #, php-format
 msgid "Registration revoked for %s"
 msgstr "Регистрация отменена для %s"
 
-#: ../../mod/regmod.php:104
+#: mod/regmod.php:104
 msgid "Please login."
 msgstr "Пожалуйста, войдите с паролем."
 
-#: ../../mod/uimport.php:66
+#: mod/uimport.php:66
 msgid "Move account"
 msgstr "Удалить аккаунт"
 
-#: ../../mod/uimport.php:67
+#: mod/uimport.php:67
 msgid "You can import an account from another Friendica server."
 msgstr "Вы можете импортировать учетную запись с другого сервера Friendica."
 
-#: ../../mod/uimport.php:68
+#: mod/uimport.php:68
 msgid ""
 "You need to export your account from the old server and upload it here. We "
-"will recreate your old account here with all your contacts. We will try also"
-" to inform your friends that you moved here."
-msgstr "Вам нужно экспортировать свой ​​аккаунт со старого сервера и загрузить его сюда. Мы восстановим ваш ​​старый аккаунт здесь со всеми вашими контактами. Мы постараемся также сообщить друзьям, что вы переехали сюда."
+"will recreate your old account here with all your contacts. We will try also "
+"to inform your friends that you moved here."
+msgstr ""
+"Вам нужно экспортировать свой ​​аккаунт со старого сервера и загрузить его "
+"сюда. Мы восстановим ваш ​​старый аккаунт здесь со всеми вашими контактами. Мы "
+"постараемся также сообщить друзьям, что вы переехали сюда."
 
-#: ../../mod/uimport.php:69
+#: mod/uimport.php:69
 msgid ""
 "This feature is experimental. We can't import contacts from the OStatus "
-"network (statusnet/identi.ca) or from Diaspora"
-msgstr "Это экспериментальная функция. Мы не можем импортировать контакты из сети OStatus (StatusNet / identi.ca) или из Diaspora"
+"network (GNU Social/Statusnet) or from Diaspora"
+msgstr ""
 
-#: ../../mod/uimport.php:70
+#: mod/uimport.php:70
 msgid "Account file"
 msgstr "Файл аккаунта"
 
-#: ../../mod/uimport.php:70
+#: mod/uimport.php:70
 msgid ""
 "To export your account, go to \"Settings->Export your personal data\" and "
 "select \"Export account\""
-msgstr "Для экспорта аккаунта, перейдите в \"Настройки->Экспортировать ваши данные\" и выберите \"Экспорт аккаунта\""
+msgstr ""
+"Для экспорта аккаунта, перейдите в \"Настройки->Экспортировать ваши данные\" "
+"и выберите \"Экспорт аккаунта\""
 
-#: ../../mod/attach.php:8
+#: mod/attach.php:8
 msgid "Item not available."
 msgstr "Пункт не доступен."
 
-#: ../../mod/attach.php:20
+#: mod/attach.php:20
 msgid "Item was not found."
 msgstr "Пункт не был найден."
 
-#: ../../boot.php:749
+#: boot.php:868
 msgid "Delete this item?"
 msgstr "Удалить этот элемент?"
 
-#: ../../boot.php:752
+#: boot.php:871
 msgid "show fewer"
 msgstr "показать меньше"
 
-#: ../../boot.php:1122
+#: boot.php:1292
 #, php-format
 msgid "Update %s failed. See error logs."
 msgstr "Обновление %s не удалось. Смотрите журнал ошибок."
 
-#: ../../boot.php:1240
+#: boot.php:1404
 msgid "Create a New Account"
 msgstr "Создать новый аккаунт"
 
-#: ../../boot.php:1265 ../../include/nav.php:73
+#: boot.php:1429 include/nav.php:72
 msgid "Logout"
 msgstr "Выход"
 
-#: ../../boot.php:1268
+#: boot.php:1432
 msgid "Nickname or Email address: "
 msgstr "Ник или адрес электронной почты: "
 
-#: ../../boot.php:1269
+#: boot.php:1433
 msgid "Password: "
 msgstr "Пароль: "
 
-#: ../../boot.php:1270
+#: boot.php:1434
 msgid "Remember me"
 msgstr "Запомнить"
 
-#: ../../boot.php:1273
+#: boot.php:1437
 msgid "Or login using OpenID: "
 msgstr "Или зайти с OpenID: "
 
-#: ../../boot.php:1279
+#: boot.php:1443
 msgid "Forgot your password?"
 msgstr "Забыли пароль?"
 
-#: ../../boot.php:1282
+#: boot.php:1446
 msgid "Website Terms of Service"
 msgstr "Правила сайта"
 
-#: ../../boot.php:1283
+#: boot.php:1447
 msgid "terms of service"
 msgstr "правила"
 
-#: ../../boot.php:1285
+#: boot.php:1449
 msgid "Website Privacy Policy"
 msgstr "Политика конфиденциальности сервера"
 
-#: ../../boot.php:1286
+#: boot.php:1450
 msgid "privacy policy"
 msgstr "политика конфиденциальности"
 
-#: ../../boot.php:1419
-msgid "Requested account is not available."
-msgstr "Запрашиваемый профиль недоступен."
-
-#: ../../boot.php:1501 ../../boot.php:1635
-#: ../../include/profile_advanced.php:84
-msgid "Edit profile"
-msgstr "Редактировать профиль"
-
-#: ../../boot.php:1600
-msgid "Message"
-msgstr "Сообщение"
-
-#: ../../boot.php:1606 ../../include/nav.php:175
-msgid "Profiles"
-msgstr "Профили"
-
-#: ../../boot.php:1606
-msgid "Manage/edit profiles"
-msgstr "Управление / редактирование профилей"
-
-#: ../../boot.php:1706
-msgid "Network:"
-msgstr ""
-
-#: ../../boot.php:1736 ../../boot.php:1822
-msgid "g A l F d"
-msgstr "g A l F d"
-
-#: ../../boot.php:1737 ../../boot.php:1823
-msgid "F d"
-msgstr "F d"
-
-#: ../../boot.php:1782 ../../boot.php:1863
-msgid "[today]"
-msgstr "[сегодня]"
-
-#: ../../boot.php:1794
-msgid "Birthday Reminders"
-msgstr "Напоминания о днях рождения"
-
-#: ../../boot.php:1795
-msgid "Birthdays this week:"
-msgstr "Дни рождения на этой неделе:"
-
-#: ../../boot.php:1856
-msgid "[No description]"
-msgstr "[без описания]"
-
-#: ../../boot.php:1874
-msgid "Event Reminders"
-msgstr "Напоминания о мероприятиях"
-
-#: ../../boot.php:1875
-msgid "Events this week:"
-msgstr "Мероприятия на этой неделе:"
-
-#: ../../boot.php:2112 ../../include/nav.php:76
-msgid "Status"
-msgstr "Статус"
-
-#: ../../boot.php:2115
-msgid "Status Messages and Posts"
-msgstr "Сообщение статуса и посты"
-
-#: ../../boot.php:2122
-msgid "Profile Details"
-msgstr "Детали профиля"
-
-#: ../../boot.php:2133 ../../boot.php:2136 ../../include/nav.php:79
-msgid "Videos"
-msgstr "Видео"
-
-#: ../../boot.php:2146
-msgid "Events and Calendar"
-msgstr "Календарь и события"
-
-#: ../../boot.php:2153
-msgid "Only You Can See This"
-msgstr "Только вы можете это видеть"
-
-#: ../../object/Item.php:94
+#: object/Item.php:95
 msgid "This entry was edited"
 msgstr "Эта запись была отредактирована"
 
-#: ../../object/Item.php:208
+#: object/Item.php:191
+msgid "I will attend"
+msgstr ""
+
+#: object/Item.php:191
+msgid "I will not attend"
+msgstr ""
+
+#: object/Item.php:191
+msgid "I might attend"
+msgstr ""
+
+#: object/Item.php:230
 msgid "ignore thread"
 msgstr ""
 
-#: ../../object/Item.php:209
+#: object/Item.php:231
 msgid "unignore thread"
 msgstr ""
 
-#: ../../object/Item.php:210
+#: object/Item.php:232
 msgid "toggle ignore status"
 msgstr ""
 
-#: ../../object/Item.php:213
-msgid "ignored"
-msgstr ""
-
-#: ../../object/Item.php:316 ../../include/conversation.php:666
+#: object/Item.php:345 include/conversation.php:687
 msgid "Categories:"
 msgstr "Категории:"
 
-#: ../../object/Item.php:317 ../../include/conversation.php:667
+#: object/Item.php:346 include/conversation.php:688
 msgid "Filed under:"
 msgstr "В рубрике:"
 
-#: ../../object/Item.php:329
+#: object/Item.php:360
 msgid "via"
 msgstr "через"
 
-#: ../../include/dbstructure.php:26
+#: include/dbstructure.php:26
 #, php-format
 msgid ""
 "\n"
 "\t\t\tThe friendica developers released update %s recently,\n"
 "\t\t\tbut when I tried to install it, something went terribly wrong.\n"
 "\t\t\tThis needs to be fixed soon and I can't do it alone. Please contact a\n"
-"\t\t\tfriendica developer if you can not help me on your own. My database might be invalid."
+"\t\t\tfriendica developer if you can not help me on your own. My database "
+"might be invalid."
 msgstr ""
 
-#: ../../include/dbstructure.php:31
+#: include/dbstructure.php:31
 #, php-format
 msgid ""
 "The error message is\n"
 "[pre]%s[/pre]"
 msgstr ""
 
-#: ../../include/dbstructure.php:162
+#: include/dbstructure.php:153
 msgid "Errors encountered creating database tables."
 msgstr "Обнаружены ошибки при создании таблиц базы данных."
 
-#: ../../include/dbstructure.php:220
+#: include/dbstructure.php:230
 msgid "Errors encountered performing database changes."
 msgstr ""
 
-#: ../../include/auth.php:38
+#: include/auth.php:44
 msgid "Logged out."
 msgstr "Выход из системы."
 
-#: ../../include/auth.php:128 ../../include/user.php:67
+#: include/auth.php:134 include/user.php:75
 msgid ""
 "We encountered a problem while logging in with the OpenID you provided. "
 "Please check the correct spelling of the ID."
-msgstr "Мы столкнулись с проблемой при входе с OpenID, который вы указали. Пожалуйста, проверьте правильность написания ID."
+msgstr ""
+"Мы столкнулись с проблемой при входе с OpenID, который вы указали. "
+"Пожалуйста, проверьте правильность написания ID."
 
-#: ../../include/auth.php:128 ../../include/user.php:67
+#: include/auth.php:134 include/user.php:75
 msgid "The error message was:"
 msgstr "Сообщение об ошибке было:"
 
-#: ../../include/contact_widgets.php:6
+#: include/contact_widgets.php:6
 msgid "Add New Contact"
 msgstr "Добавить контакт"
 
-#: ../../include/contact_widgets.php:7
+#: include/contact_widgets.php:7
 msgid "Enter address or web location"
 msgstr "Введите адрес или веб-местонахождение"
 
-#: ../../include/contact_widgets.php:8
+#: include/contact_widgets.php:8
 msgid "Example: bob@example.com, http://example.com/barbara"
 msgstr "Пример: bob@example.com, http://example.com/barbara"
 
-#: ../../include/contact_widgets.php:24
+#: include/contact_widgets.php:24
 #, php-format
 msgid "%d invitation available"
 msgid_plural "%d invitations available"
 msgstr[0] "%d приглашение доступно"
 msgstr[1] "%d приглашений доступно"
 msgstr[2] "%d приглашений доступно"
+msgstr[3] "%d приглашений доступно"
 
-#: ../../include/contact_widgets.php:30
+#: include/contact_widgets.php:30
 msgid "Find People"
 msgstr "Поиск людей"
 
-#: ../../include/contact_widgets.php:31
+#: include/contact_widgets.php:31
 msgid "Enter name or interest"
 msgstr "Введите имя или интерес"
 
-#: ../../include/contact_widgets.php:32
-msgid "Connect/Follow"
-msgstr "Подключиться/Следовать"
-
-#: ../../include/contact_widgets.php:33
+#: include/contact_widgets.php:33
 msgid "Examples: Robert Morgenstein, Fishing"
 msgstr "Примеры: Роберт Morgenstein, Рыбалка"
 
-#: ../../include/contact_widgets.php:36 ../../view/theme/diabook/theme.php:526
+#: include/contact_widgets.php:36 view/theme/diabook/theme.php:526
+#: view/theme/vier/theme.php:206
 msgid "Similar Interests"
 msgstr "Похожие интересы"
 
-#: ../../include/contact_widgets.php:37
+#: include/contact_widgets.php:37
 msgid "Random Profile"
 msgstr "Случайный профиль"
 
-#: ../../include/contact_widgets.php:38 ../../view/theme/diabook/theme.php:528
+#: include/contact_widgets.php:38 view/theme/diabook/theme.php:528
+#: view/theme/vier/theme.php:208
 msgid "Invite Friends"
 msgstr "Пригласить друзей"
 
-#: ../../include/contact_widgets.php:71
+#: include/contact_widgets.php:108
 msgid "Networks"
 msgstr "Сети"
 
-#: ../../include/contact_widgets.php:74
+#: include/contact_widgets.php:111
 msgid "All Networks"
 msgstr "Все сети"
 
-#: ../../include/contact_widgets.php:104 ../../include/features.php:60
+#: include/contact_widgets.php:141 include/features.php:102
 msgid "Saved Folders"
 msgstr "Сохранённые папки"
 
-#: ../../include/contact_widgets.php:107 ../../include/contact_widgets.php:139
+#: include/contact_widgets.php:144 include/contact_widgets.php:176
 msgid "Everything"
 msgstr "Всё"
 
-#: ../../include/contact_widgets.php:136
+#: include/contact_widgets.php:173
 msgid "Categories"
 msgstr "Категории"
 
-#: ../../include/features.php:23
+#: include/contact_widgets.php:237
+#, php-format
+msgid "%d contact in common"
+msgid_plural "%d contacts in common"
+msgstr[0] "%d Контакт"
+msgstr[1] "%d Контактов"
+msgstr[2] "%d Контактов"
+msgstr[3] "%d Контактов"
+
+#: include/features.php:63
 msgid "General Features"
 msgstr "Основные возможности"
 
-#: ../../include/features.php:25
+#: include/features.php:65
 msgid "Multiple Profiles"
 msgstr "Несколько профилей"
 
-#: ../../include/features.php:25
+#: include/features.php:65
 msgid "Ability to create multiple profiles"
 msgstr "Возможность создания нескольких профилей"
 
-#: ../../include/features.php:30
-msgid "Post Composition Features"
+#: include/features.php:66
+msgid "Photo Location"
 msgstr ""
 
-#: ../../include/features.php:31
+#: include/features.php:66
+msgid ""
+"Photo metadata is normally stripped. This extracts the location (if present) "
+"prior to stripping metadata and links it to a map."
+msgstr ""
+
+#: include/features.php:71
+msgid "Post Composition Features"
+msgstr "Составление сообщений"
+
+#: include/features.php:72
 msgid "Richtext Editor"
 msgstr "Редактор RTF"
 
-#: ../../include/features.php:31
+#: include/features.php:72
 msgid "Enable richtext editor"
 msgstr "Включить редактор RTF"
 
-#: ../../include/features.php:32
+#: include/features.php:73
 msgid "Post Preview"
-msgstr "предварительный просмотр"
+msgstr "Предварительный просмотр"
 
-#: ../../include/features.php:32
+#: include/features.php:73
 msgid "Allow previewing posts and comments before publishing them"
 msgstr "Разрешить предпросмотр сообщения и комментария перед их публикацией"
 
-#: ../../include/features.php:33
+#: include/features.php:74
 msgid "Auto-mention Forums"
 msgstr ""
 
-#: ../../include/features.php:33
+#: include/features.php:74
 msgid ""
 "Add/remove mention when a fourm page is selected/deselected in ACL window."
 msgstr ""
 
-#: ../../include/features.php:38
+#: include/features.php:79
 msgid "Network Sidebar Widgets"
 msgstr "Виджет боковой панели \"Сеть\""
 
-#: ../../include/features.php:39
+#: include/features.php:80
 msgid "Search by Date"
 msgstr "Поиск по датам"
 
-#: ../../include/features.php:39
+#: include/features.php:80
 msgid "Ability to select posts by date ranges"
 msgstr "Возможность выбора постов по диапазону дат"
 
-#: ../../include/features.php:40
+#: include/features.php:81 include/features.php:111
+msgid "List Forums"
+msgstr ""
+
+#: include/features.php:81
+msgid "Enable widget to display the forums your are connected with"
+msgstr ""
+
+#: include/features.php:82
 msgid "Group Filter"
 msgstr "Фильтр групп"
 
-#: ../../include/features.php:40
+#: include/features.php:82
 msgid "Enable widget to display Network posts only from selected group"
-msgstr "Включить виджет для отображения сообщений сети только от выбранной группы"
+msgstr ""
+"Включить виджет для отображения сообщений сети только от выбранной группы"
 
-#: ../../include/features.php:41
+#: include/features.php:83
 msgid "Network Filter"
 msgstr "Фильтр сети"
 
-#: ../../include/features.php:41
+#: include/features.php:83
 msgid "Enable widget to display Network posts only from selected network"
-msgstr "Включить виджет для отображения сообщений сети только от выбранной сети"
+msgstr ""
+"Включить виджет для отображения сообщений сети только от выбранной сети"
 
-#: ../../include/features.php:42
+#: include/features.php:84
 msgid "Save search terms for re-use"
 msgstr "Сохранить условия поиска для повторного использования"
 
-#: ../../include/features.php:47
+#: include/features.php:89
 msgid "Network Tabs"
 msgstr "Сетевые вкладки"
 
-#: ../../include/features.php:48
+#: include/features.php:90
 msgid "Network Personal Tab"
 msgstr "Персональные сетевые вкладки"
 
-#: ../../include/features.php:48
+#: include/features.php:90
 msgid "Enable tab to display only Network posts that you've interacted on"
-msgstr "Включить вкладку для отображения только сообщений сети, с которой вы взаимодействовали"
+msgstr ""
+"Включить вкладку для отображения только сообщений сети, с которой вы "
+"взаимодействовали"
 
-#: ../../include/features.php:49
+#: include/features.php:91
 msgid "Network New Tab"
 msgstr "Новая вкладка сеть"
 
-#: ../../include/features.php:49
+#: include/features.php:91
 msgid "Enable tab to display only new Network posts (from the last 12 hours)"
-msgstr "Включить вкладку для отображения только новых сообщений сети (за последние 12 часов)"
+msgstr ""
+"Включить вкладку для отображения только новых сообщений сети (за последние "
+"12 часов)"
 
-#: ../../include/features.php:50
+#: include/features.php:92
 msgid "Network Shared Links Tab"
 msgstr "Вкладка shared ссылок сети"
 
-#: ../../include/features.php:50
+#: include/features.php:92
 msgid "Enable tab to display only Network posts with links in them"
-msgstr "Включить вкладку для отображения только сообщений сети со ссылками на них"
+msgstr ""
+"Включить вкладку для отображения только сообщений сети со ссылками на них"
 
-#: ../../include/features.php:55
+#: include/features.php:97
 msgid "Post/Comment Tools"
 msgstr "Инструменты пост/комментарий"
 
-#: ../../include/features.php:56
+#: include/features.php:98
 msgid "Multiple Deletion"
 msgstr "Множественное удаление"
 
-#: ../../include/features.php:56
+#: include/features.php:98
 msgid "Select and delete multiple posts/comments at once"
 msgstr "Выбрать и удалить несколько постов/комментариев одновременно."
 
-#: ../../include/features.php:57
+#: include/features.php:99
 msgid "Edit Sent Posts"
 msgstr "Редактировать отправленные посты"
 
-#: ../../include/features.php:57
+#: include/features.php:99
 msgid "Edit and correct posts and comments after sending"
 msgstr "Редактировать и править посты и комментарии после отправления"
 
-#: ../../include/features.php:58
+#: include/features.php:100
 msgid "Tagging"
 msgstr "Отмеченное"
 
-#: ../../include/features.php:58
+#: include/features.php:100
 msgid "Ability to tag existing posts"
 msgstr "Возможность отмечать существующие посты"
 
-#: ../../include/features.php:59
+#: include/features.php:101
 msgid "Post Categories"
 msgstr "Категории постов"
 
-#: ../../include/features.php:59
+#: include/features.php:101
 msgid "Add categories to your posts"
 msgstr "Добавить категории вашего поста"
 
-#: ../../include/features.php:60
+#: include/features.php:102
 msgid "Ability to file posts under folders"
 msgstr ""
 
-#: ../../include/features.php:61
+#: include/features.php:103
 msgid "Dislike Posts"
 msgstr "Посты дизлайк"
 
-#: ../../include/features.php:61
+#: include/features.php:103
 msgid "Ability to dislike posts/comments"
 msgstr "Возможность дизлайка постов/комментариев"
 
-#: ../../include/features.php:62
+#: include/features.php:104
 msgid "Star Posts"
 msgstr "Популярные посты"
 
-#: ../../include/features.php:62
+#: include/features.php:104
 msgid "Ability to mark special posts with a star indicator"
 msgstr "Возможность отметить специальные сообщения индикатором популярности"
 
-#: ../../include/features.php:63
+#: include/features.php:105
 msgid "Mute Post Notifications"
 msgstr ""
 
-#: ../../include/features.php:63
+#: include/features.php:105
 msgid "Ability to mute notifications for a thread"
 msgstr ""
 
-#: ../../include/follow.php:32
+#: include/features.php:110
+msgid "Advanced Profile Settings"
+msgstr "Расширенные настройки профиля"
+
+#: include/features.php:111
+msgid "Show visitors public community forums at the Advanced Profile Page"
+msgstr ""
+
+#: include/follow.php:77
 msgid "Connect URL missing."
 msgstr "Connect-URL отсутствует."
 
-#: ../../include/follow.php:59
+#: include/follow.php:104
 msgid ""
 "This site is not configured to allow communications with other networks."
 msgstr "Данный сайт не настроен так, чтобы держать связь с другими сетями."
 
-#: ../../include/follow.php:60 ../../include/follow.php:80
+#: include/follow.php:105 include/follow.php:125
 msgid "No compatible communication protocols or feeds were discovered."
 msgstr "Обнаружены несовместимые протоколы связи или каналы."
 
-#: ../../include/follow.php:78
+#: include/follow.php:123
 msgid "The profile address specified does not provide adequate information."
 msgstr "Указанный адрес профиля не дает адекватной информации."
 
-#: ../../include/follow.php:82
+#: include/follow.php:127
 msgid "An author or name was not found."
 msgstr "Автор или имя не найдены."
 
-#: ../../include/follow.php:84
+#: include/follow.php:129
 msgid "No browser URL could be matched to this address."
 msgstr "Нет URL браузера, который соответствует этому адресу."
 
-#: ../../include/follow.php:86
+#: include/follow.php:131
 msgid ""
 "Unable to match @-style Identity Address with a known protocol or email "
 "contact."
 msgstr ""
 
-#: ../../include/follow.php:87
+#: include/follow.php:132
 msgid "Use mailto: in front of address to force email check."
 msgstr "Bcgjkmpeqnt mailto: перед адресом для быстрого доступа к email."
 
-#: ../../include/follow.php:93
+#: include/follow.php:138
 msgid ""
 "The profile address specified belongs to a network which has been disabled "
 "on this site."
 msgstr "Указанный адрес профиля принадлежит сети, недоступной на этом сайта."
 
-#: ../../include/follow.php:103
+#: include/follow.php:148
 msgid ""
 "Limited profile. This person will be unable to receive direct/personal "
 "notifications from you."
-msgstr "Ограниченный профиль. Этот человек не сможет получить прямые / личные уведомления от вас."
+msgstr ""
+"Ограниченный профиль. Этот человек не сможет получить прямые / личные "
+"уведомления от вас."
 
-#: ../../include/follow.php:205
+#: include/follow.php:249
 msgid "Unable to retrieve contact information."
 msgstr "Невозможно получить контактную информацию."
 
-#: ../../include/follow.php:258
+#: include/follow.php:302
 msgid "following"
 msgstr "следует"
 
-#: ../../include/group.php:25
+#: include/group.php:25
 msgid ""
 "A deleted group with this name was revived. Existing item permissions "
 "<strong>may</strong> apply to this group and any future members. If this is "
 "not what you intended, please create another group with a different name."
-msgstr "Удаленная группа с таким названием была восстановлена. Существующие права доступа <strong>могут</strong> применяться к этой группе и любым будущим участникам. Если это не то, что вы хотели, пожалуйста, создайте еще ​​одну группу с другим названием."
+msgstr ""
+"Удаленная группа с таким названием была восстановлена. Существующие права "
+"доступа <strong>могут</strong> применяться к этой группе и любым будущим "
+"участникам. Если это не то, что вы хотели, пожалуйста, создайте еще ​​одну "
+"группу с другим названием."
 
-#: ../../include/group.php:207
+#: include/group.php:209
 msgid "Default privacy group for new contacts"
 msgstr "Группа доступа по умолчанию для новых контактов"
 
-#: ../../include/group.php:226
+#: include/group.php:239
 msgid "Everybody"
 msgstr "Каждый"
 
-#: ../../include/group.php:249
+#: include/group.php:262
 msgid "edit"
 msgstr "редактировать"
 
-#: ../../include/group.php:271
+#: include/group.php:285
+msgid "Edit groups"
+msgstr ""
+
+#: include/group.php:287
 msgid "Edit group"
 msgstr "Редактировать группу"
 
-#: ../../include/group.php:272
+#: include/group.php:288
 msgid "Create a new group"
 msgstr "Создать новую группу"
 
-#: ../../include/group.php:273
+#: include/group.php:291
 msgid "Contacts not in any group"
 msgstr "Контакты не состоят в группе"
 
-#: ../../include/datetime.php:43 ../../include/datetime.php:45
+#: include/datetime.php:43 include/datetime.php:45
 msgid "Miscellaneous"
 msgstr "Разное"
 
-#: ../../include/datetime.php:153 ../../include/datetime.php:290
-msgid "year"
-msgstr "год"
+#: include/datetime.php:141
+msgid "YYYY-MM-DD or MM-DD"
+msgstr ""
 
-#: ../../include/datetime.php:158 ../../include/datetime.php:291
-msgid "month"
-msgstr "мес."
-
-#: ../../include/datetime.php:163 ../../include/datetime.php:293
-msgid "day"
-msgstr "день"
-
-#: ../../include/datetime.php:276
+#: include/datetime.php:271
 msgid "never"
 msgstr "никогда"
 
-#: ../../include/datetime.php:282
+#: include/datetime.php:277
 msgid "less than a second ago"
 msgstr "менее сек. назад"
 
-#: ../../include/datetime.php:290
+#: include/datetime.php:287
+msgid "year"
+msgstr "год"
+
+#: include/datetime.php:287
 msgid "years"
 msgstr "лет"
 
-#: ../../include/datetime.php:291
+#: include/datetime.php:288
 msgid "months"
 msgstr "мес."
 
-#: ../../include/datetime.php:292
-msgid "week"
-msgstr "неделя"
-
-#: ../../include/datetime.php:292
+#: include/datetime.php:289
 msgid "weeks"
 msgstr "недель"
 
-#: ../../include/datetime.php:293
+#: include/datetime.php:290
 msgid "days"
 msgstr "дней"
 
-#: ../../include/datetime.php:294
+#: include/datetime.php:291
 msgid "hour"
 msgstr "час"
 
-#: ../../include/datetime.php:294
+#: include/datetime.php:291
 msgid "hours"
 msgstr "час."
 
-#: ../../include/datetime.php:295
+#: include/datetime.php:292
 msgid "minute"
 msgstr "минута"
 
-#: ../../include/datetime.php:295
+#: include/datetime.php:292
 msgid "minutes"
 msgstr "мин."
 
-#: ../../include/datetime.php:296
+#: include/datetime.php:293
 msgid "second"
 msgstr "секунда"
 
-#: ../../include/datetime.php:296
+#: include/datetime.php:293
 msgid "seconds"
 msgstr "сек."
 
-#: ../../include/datetime.php:305
+#: include/datetime.php:302
 #, php-format
 msgid "%1$d %2$s ago"
 msgstr "%1$d %2$s назад"
 
-#: ../../include/datetime.php:477 ../../include/items.php:2211
+#: include/datetime.php:474 include/items.php:2500
 #, php-format
 msgid "%s's birthday"
 msgstr "день рождения %s"
 
-#: ../../include/datetime.php:478 ../../include/items.php:2212
+#: include/datetime.php:475 include/items.php:2501
 #, php-format
 msgid "Happy Birthday %s"
 msgstr "С днём рождения %s"
 
-#: ../../include/acl_selectors.php:333
-msgid "Visible to everybody"
-msgstr "Видимо всем"
+#: include/identity.php:42
+msgid "Requested account is not available."
+msgstr "Запрашиваемый профиль недоступен."
 
-#: ../../include/acl_selectors.php:334 ../../view/theme/diabook/config.php:142
-#: ../../view/theme/diabook/theme.php:621
-msgid "show"
-msgstr "показывать"
+#: include/identity.php:95 include/identity.php:284 include/identity.php:662
+msgid "Edit profile"
+msgstr "Редактировать профиль"
 
-#: ../../include/acl_selectors.php:335 ../../view/theme/diabook/config.php:142
-#: ../../view/theme/diabook/theme.php:621
-msgid "don't show"
-msgstr "не показывать"
-
-#: ../../include/message.php:15 ../../include/message.php:172
-msgid "[no subject]"
-msgstr "[без темы]"
-
-#: ../../include/Contact.php:115
-msgid "stopped following"
-msgstr "остановлено следование"
-
-#: ../../include/Contact.php:228 ../../include/conversation.php:882
-msgid "Poke"
+#: include/identity.php:244
+msgid "Atom feed"
 msgstr ""
 
-#: ../../include/Contact.php:229 ../../include/conversation.php:876
-msgid "View Status"
-msgstr "Просмотреть статус"
+#: include/identity.php:249
+msgid "Message"
+msgstr "Сообщение"
 
-#: ../../include/Contact.php:230 ../../include/conversation.php:877
-msgid "View Profile"
-msgstr "Просмотреть профиль"
+#: include/identity.php:255 include/nav.php:185
+msgid "Profiles"
+msgstr "Профили"
 
-#: ../../include/Contact.php:231 ../../include/conversation.php:878
-msgid "View Photos"
-msgstr "Просмотреть фото"
+#: include/identity.php:255
+msgid "Manage/edit profiles"
+msgstr "Управление / редактирование профилей"
 
-#: ../../include/Contact.php:232 ../../include/Contact.php:255
-#: ../../include/conversation.php:879
-msgid "Network Posts"
-msgstr "Посты сети"
+#: include/identity.php:425 include/identity.php:509
+msgid "g A l F d"
+msgstr "g A l F d"
 
-#: ../../include/Contact.php:233 ../../include/Contact.php:255
-#: ../../include/conversation.php:880
-msgid "Edit Contact"
-msgstr "Редактировать контакт"
+#: include/identity.php:426 include/identity.php:510
+msgid "F d"
+msgstr "F d"
 
-#: ../../include/Contact.php:234
-msgid "Drop Contact"
-msgstr "Удалить контакт"
+#: include/identity.php:471 include/identity.php:556
+msgid "[today]"
+msgstr "[сегодня]"
 
-#: ../../include/Contact.php:235 ../../include/Contact.php:255
-#: ../../include/conversation.php:881
-msgid "Send PM"
-msgstr "Отправить ЛС"
+#: include/identity.php:483
+msgid "Birthday Reminders"
+msgstr "Напоминания о днях рождения"
 
-#: ../../include/security.php:22
-msgid "Welcome "
-msgstr "Добро пожаловать, "
+#: include/identity.php:484
+msgid "Birthdays this week:"
+msgstr "Дни рождения на этой неделе:"
 
-#: ../../include/security.php:23
-msgid "Please upload a profile photo."
-msgstr "Пожалуйста, загрузите фотографию профиля."
+#: include/identity.php:543
+msgid "[No description]"
+msgstr "[без описания]"
 
-#: ../../include/security.php:26
-msgid "Welcome back "
-msgstr "Добро пожаловать обратно, "
+#: include/identity.php:567
+msgid "Event Reminders"
+msgstr "Напоминания о мероприятиях"
 
-#: ../../include/security.php:366
-msgid ""
-"The form security token was not correct. This probably happened because the "
-"form has been opened for too long (>3 hours) before submitting it."
-msgstr "Ключ формы безопасности неправильный. Вероятно, это произошло потому, что форма была открыта слишком долго (более 3 часов) до её отправки."
+#: include/identity.php:568
+msgid "Events this week:"
+msgstr "Мероприятия на этой неделе:"
 
-#: ../../include/conversation.php:118 ../../include/conversation.php:246
-#: ../../include/text.php:1966 ../../view/theme/diabook/theme.php:463
+#: include/identity.php:595
+msgid "j F, Y"
+msgstr "j F, Y"
+
+#: include/identity.php:596
+msgid "j F"
+msgstr "j F"
+
+#: include/identity.php:603
+msgid "Birthday:"
+msgstr "День рождения:"
+
+#: include/identity.php:607
+msgid "Age:"
+msgstr "Возраст:"
+
+#: include/identity.php:616
+#, php-format
+msgid "for %1$d %2$s"
+msgstr ""
+
+#: include/identity.php:629
+msgid "Religion:"
+msgstr "Религия:"
+
+#: include/identity.php:633
+msgid "Hobbies/Interests:"
+msgstr "Хобби / Интересы:"
+
+#: include/identity.php:640
+msgid "Contact information and Social Networks:"
+msgstr "Информация о контакте и социальных сетях:"
+
+#: include/identity.php:642
+msgid "Musical interests:"
+msgstr "Музыкальные интересы:"
+
+#: include/identity.php:644
+msgid "Books, literature:"
+msgstr "Книги, литература:"
+
+#: include/identity.php:646
+msgid "Television:"
+msgstr "Телевидение:"
+
+#: include/identity.php:648
+msgid "Film/dance/culture/entertainment:"
+msgstr "Кино / Танцы / Культура / Развлечения:"
+
+#: include/identity.php:650
+msgid "Love/Romance:"
+msgstr "Любовь / Романтика:"
+
+#: include/identity.php:652
+msgid "Work/employment:"
+msgstr "Работа / Занятость:"
+
+#: include/identity.php:654
+msgid "School/education:"
+msgstr "Школа / Образование:"
+
+#: include/identity.php:658
+msgid "Forums:"
+msgstr ""
+
+#: include/identity.php:710 include/identity.php:713 include/nav.php:78
+msgid "Videos"
+msgstr "Видео"
+
+#: include/identity.php:725 include/nav.php:140
+msgid "Events and Calendar"
+msgstr "Календарь и события"
+
+#: include/identity.php:733
+msgid "Only You Can See This"
+msgstr "Только вы можете это видеть"
+
+#: include/like.php:167 include/conversation.php:122
+#: include/conversation.php:258 include/text.php:1998
+#: view/theme/diabook/theme.php:463
 msgid "event"
 msgstr "мероприятие"
 
-#: ../../include/conversation.php:207
+#: include/like.php:184 include/conversation.php:141 include/diaspora.php:2185
+#: view/theme/diabook/theme.php:480
 #, php-format
-msgid "%1$s poked %2$s"
+msgid "%1$s likes %2$s's %3$s"
+msgstr "%1$s нравится %3$s от %2$s "
+
+#: include/like.php:186 include/conversation.php:144
+#, php-format
+msgid "%1$s doesn't like %2$s's %3$s"
+msgstr "%1$s не нравится %3$s от %2$s "
+
+#: include/like.php:188
+#, php-format
+msgid "%1$s is attending %2$s's %3$s"
 msgstr ""
 
-#: ../../include/conversation.php:211 ../../include/text.php:1005
-msgid "poked"
+#: include/like.php:190
+#, php-format
+msgid "%1$s is not attending %2$s's %3$s"
 msgstr ""
 
-#: ../../include/conversation.php:291
-msgid "post/item"
-msgstr "пост/элемент"
-
-#: ../../include/conversation.php:292
+#: include/like.php:192
 #, php-format
-msgid "%1$s marked %2$s's %3$s as favorite"
-msgstr "%1$s пометил %2$s %3$s как Фаворит"
-
-#: ../../include/conversation.php:772
-msgid "remove"
-msgstr "удалить"
-
-#: ../../include/conversation.php:776
-msgid "Delete Selected Items"
-msgstr "Удалить выбранные позиции"
-
-#: ../../include/conversation.php:875
-msgid "Follow Thread"
+msgid "%1$s may attend %2$s's %3$s"
 msgstr ""
 
-#: ../../include/conversation.php:944
-#, php-format
-msgid "%s likes this."
-msgstr "%s нравится это."
-
-#: ../../include/conversation.php:944
-#, php-format
-msgid "%s doesn't like this."
-msgstr "%s не нравится это."
-
-#: ../../include/conversation.php:949
-#, php-format
-msgid "<span  %1$s>%2$d people</span> like this"
-msgstr "<span %1$s>%2$d людям</span> нравится это"
-
-#: ../../include/conversation.php:952
-#, php-format
-msgid "<span  %1$s>%2$d people</span> don't like this"
-msgstr "<span %1$s>%2$d людям</span> не нравится это"
-
-#: ../../include/conversation.php:966
-msgid "and"
-msgstr "и"
-
-#: ../../include/conversation.php:972
-#, php-format
-msgid ", and %d other people"
-msgstr ", и %d других чел."
-
-#: ../../include/conversation.php:974
-#, php-format
-msgid "%s like this."
-msgstr "%s нравится это."
-
-#: ../../include/conversation.php:974
-#, php-format
-msgid "%s don't like this."
-msgstr "%s не нравится это."
-
-#: ../../include/conversation.php:1001 ../../include/conversation.php:1019
-msgid "Visible to <strong>everybody</strong>"
-msgstr "Видимое <strong>всем</strong>"
-
-#: ../../include/conversation.php:1003 ../../include/conversation.php:1021
-msgid "Please enter a video link/URL:"
-msgstr "Введите  ссылку на видео link/URL:"
-
-#: ../../include/conversation.php:1004 ../../include/conversation.php:1022
-msgid "Please enter an audio link/URL:"
-msgstr "Введите ссылку на аудио link/URL:"
-
-#: ../../include/conversation.php:1005 ../../include/conversation.php:1023
-msgid "Tag term:"
-msgstr ""
-
-#: ../../include/conversation.php:1007 ../../include/conversation.php:1025
-msgid "Where are you right now?"
-msgstr "И где вы сейчас?"
-
-#: ../../include/conversation.php:1008
-msgid "Delete item(s)?"
-msgstr "Удалить елемент(ты)?"
-
-#: ../../include/conversation.php:1051
+#: include/acl_selectors.php:325
 msgid "Post to Email"
 msgstr "Отправить на Email"
 
-#: ../../include/conversation.php:1056
+#: include/acl_selectors.php:330
 #, php-format
 msgid "Connectors disabled, since \"%s\" is enabled."
 msgstr ""
 
-#: ../../include/conversation.php:1111
+#: include/acl_selectors.php:336
+msgid "Visible to everybody"
+msgstr "Видимо всем"
+
+#: include/acl_selectors.php:337 view/theme/diabook/config.php:142
+#: view/theme/diabook/theme.php:621 view/theme/vier/config.php:103
+msgid "show"
+msgstr "показывать"
+
+#: include/acl_selectors.php:338 view/theme/diabook/config.php:142
+#: view/theme/diabook/theme.php:621 view/theme/vier/config.php:103
+msgid "don't show"
+msgstr "не показывать"
+
+#: include/acl_selectors.php:348
+msgid "Close"
+msgstr "Закрыть"
+
+#: include/message.php:15 include/message.php:173
+msgid "[no subject]"
+msgstr "[без темы]"
+
+#: include/Contact.php:119
+msgid "stopped following"
+msgstr "остановлено следование"
+
+#: include/Contact.php:337 include/conversation.php:911
+msgid "View Status"
+msgstr "Просмотреть статус"
+
+#: include/Contact.php:339 include/conversation.php:913
+msgid "View Photos"
+msgstr "Просмотреть фото"
+
+#: include/Contact.php:340 include/conversation.php:914
+msgid "Network Posts"
+msgstr "Посты сети"
+
+#: include/Contact.php:341 include/conversation.php:915
+msgid "Edit Contact"
+msgstr "Редактировать контакт"
+
+#: include/Contact.php:342
+msgid "Drop Contact"
+msgstr "Удалить контакт"
+
+#: include/Contact.php:343 include/conversation.php:916
+msgid "Send PM"
+msgstr "Отправить ЛС"
+
+#: include/Contact.php:344 include/conversation.php:920
+msgid "Poke"
+msgstr ""
+
+#: include/security.php:22
+msgid "Welcome "
+msgstr "Добро пожаловать, "
+
+#: include/security.php:23
+msgid "Please upload a profile photo."
+msgstr "Пожалуйста, загрузите фотографию профиля."
+
+#: include/security.php:26
+msgid "Welcome back "
+msgstr "Добро пожаловать обратно, "
+
+#: include/security.php:375
+msgid ""
+"The form security token was not correct. This probably happened because the "
+"form has been opened for too long (>3 hours) before submitting it."
+msgstr ""
+"Ключ формы безопасности неправильный. Вероятно, это произошло потому, что "
+"форма была открыта слишком долго (более 3 часов) до её отправки."
+
+#: include/conversation.php:147
+#, php-format
+msgid "%1$s attends %2$s's %3$s"
+msgstr ""
+
+#: include/conversation.php:150
+#, php-format
+msgid "%1$s doesn't attend %2$s's %3$s"
+msgstr ""
+
+#: include/conversation.php:153
+#, php-format
+msgid "%1$s attends maybe %2$s's %3$s"
+msgstr ""
+
+#: include/conversation.php:219
+#, php-format
+msgid "%1$s poked %2$s"
+msgstr ""
+
+#: include/conversation.php:303
+msgid "post/item"
+msgstr "пост/элемент"
+
+#: include/conversation.php:304
+#, php-format
+msgid "%1$s marked %2$s's %3$s as favorite"
+msgstr "%1$s пометил %2$s %3$s как Фаворит"
+
+#: include/conversation.php:792
+msgid "remove"
+msgstr "удалить"
+
+#: include/conversation.php:796
+msgid "Delete Selected Items"
+msgstr "Удалить выбранные позиции"
+
+#: include/conversation.php:910
+msgid "Follow Thread"
+msgstr ""
+
+#: include/conversation.php:1034
+#, php-format
+msgid "%s likes this."
+msgstr "%s нравится это."
+
+#: include/conversation.php:1037
+#, php-format
+msgid "%s doesn't like this."
+msgstr "%s не нравится это."
+
+#: include/conversation.php:1040
+#, php-format
+msgid "%s attends."
+msgstr ""
+
+#: include/conversation.php:1043
+#, php-format
+msgid "%s doesn't attend."
+msgstr ""
+
+#: include/conversation.php:1046
+#, php-format
+msgid "%s attends maybe."
+msgstr ""
+
+#: include/conversation.php:1056
+msgid "and"
+msgstr "и"
+
+#: include/conversation.php:1062
+#, php-format
+msgid ", and %d other people"
+msgstr ", и %d других чел."
+
+#: include/conversation.php:1071
+#, php-format
+msgid "<span  %1$s>%2$d people</span> like this"
+msgstr "<span %1$s>%2$d людям</span> нравится это"
+
+#: include/conversation.php:1072
+#, php-format
+msgid "%s like this."
+msgstr ""
+
+#: include/conversation.php:1075
+#, php-format
+msgid "<span  %1$s>%2$d people</span> don't like this"
+msgstr "<span %1$s>%2$d людям</span> не нравится это"
+
+#: include/conversation.php:1076
+#, php-format
+msgid "%s don't like this."
+msgstr ""
+
+#: include/conversation.php:1079
+#, php-format
+msgid "<span  %1$s>%2$d people</span> attend"
+msgstr ""
+
+#: include/conversation.php:1080
+#, php-format
+msgid "%s attend."
+msgstr ""
+
+#: include/conversation.php:1083
+#, php-format
+msgid "<span  %1$s>%2$d people</span> don't attend"
+msgstr ""
+
+#: include/conversation.php:1084
+#, php-format
+msgid "%s don't attend."
+msgstr ""
+
+#: include/conversation.php:1087
+#, php-format
+msgid "<span  %1$s>%2$d people</span> anttend maybe"
+msgstr ""
+
+#: include/conversation.php:1088
+#, php-format
+msgid "%s anttend maybe."
+msgstr ""
+
+#: include/conversation.php:1127 include/conversation.php:1145
+msgid "Visible to <strong>everybody</strong>"
+msgstr "Видимое <strong>всем</strong>"
+
+#: include/conversation.php:1129 include/conversation.php:1147
+msgid "Please enter a video link/URL:"
+msgstr "Введите  ссылку на видео link/URL:"
+
+#: include/conversation.php:1130 include/conversation.php:1148
+msgid "Please enter an audio link/URL:"
+msgstr "Введите ссылку на аудио link/URL:"
+
+#: include/conversation.php:1131 include/conversation.php:1149
+msgid "Tag term:"
+msgstr ""
+
+#: include/conversation.php:1133 include/conversation.php:1151
+msgid "Where are you right now?"
+msgstr "И где вы сейчас?"
+
+#: include/conversation.php:1134
+msgid "Delete item(s)?"
+msgstr "Удалить елемент(ты)?"
+
+#: include/conversation.php:1203
 msgid "permissions"
 msgstr "разрешения"
 
-#: ../../include/conversation.php:1135
+#: include/conversation.php:1226
 msgid "Post to Groups"
 msgstr "Пост для групп"
 
-#: ../../include/conversation.php:1136
+#: include/conversation.php:1227
 msgid "Post to Contacts"
 msgstr "Пост для контактов"
 
-#: ../../include/conversation.php:1137
+#: include/conversation.php:1228
 msgid "Private post"
 msgstr "Личное сообщение"
 
-#: ../../include/network.php:895
+#: include/conversation.php:1385
+msgid "View all"
+msgstr ""
+
+#: include/conversation.php:1407
+msgid "Like"
+msgid_plural "Likes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+#: include/conversation.php:1410
+msgid "Dislike"
+msgid_plural "Dislikes"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+#: include/conversation.php:1416
+msgid "Not Attending"
+msgid_plural "Not Attending"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+#: include/conversation.php:1419 include/profile_selectors.php:6
+msgid "Undecided"
+msgid_plural "Undecided"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
+#: include/forums.php:105 include/text.php:1015 include/nav.php:126
+#: view/theme/vier/theme.php:259
+msgid "Forums"
+msgstr ""
+
+#: include/forums.php:107 view/theme/vier/theme.php:261
+msgid "External link to forum"
+msgstr ""
+
+#: include/network.php:967
 msgid "view full size"
 msgstr "посмотреть в полный размер"
 
-#: ../../include/text.php:297
+#: include/text.php:303
 msgid "newer"
 msgstr "новее"
 
-#: ../../include/text.php:299
+#: include/text.php:305
 msgid "older"
 msgstr "старее"
 
-#: ../../include/text.php:304
+#: include/text.php:310
 msgid "prev"
 msgstr "пред."
 
-#: ../../include/text.php:306
+#: include/text.php:312
 msgid "first"
 msgstr "первый"
 
-#: ../../include/text.php:338
+#: include/text.php:344
 msgid "last"
 msgstr "последний"
 
-#: ../../include/text.php:341
+#: include/text.php:347
 msgid "next"
 msgstr "след."
 
-#: ../../include/text.php:855
+#: include/text.php:402
+msgid "Loading more entries..."
+msgstr ""
+
+#: include/text.php:403
+msgid "The end"
+msgstr ""
+
+#: include/text.php:894
 msgid "No contacts"
 msgstr "Нет контактов"
 
-#: ../../include/text.php:864
+#: include/text.php:909
 #, php-format
 msgid "%d Contact"
 msgid_plural "%d Contacts"
 msgstr[0] "%d контакт"
 msgstr[1] "%d контактов"
 msgstr[2] "%d контактов"
+msgstr[3] "%d контактов"
 
-#: ../../include/text.php:1005
+#: include/text.php:921
+msgid "View Contacts"
+msgstr "Просмотр контактов"
+
+#: include/text.php:1010 include/nav.php:121
+msgid "Full Text"
+msgstr "Контент"
+
+#: include/text.php:1011 include/nav.php:122
+msgid "Tags"
+msgstr "Тэги"
+
+#: include/text.php:1066
 msgid "poke"
 msgstr "poke"
 
-#: ../../include/text.php:1006
+#: include/text.php:1066
+msgid "poked"
+msgstr ""
+
+#: include/text.php:1067
 msgid "ping"
 msgstr "пинг"
 
-#: ../../include/text.php:1006
+#: include/text.php:1067
 msgid "pinged"
 msgstr "пингуется"
 
-#: ../../include/text.php:1007
+#: include/text.php:1068
 msgid "prod"
 msgstr ""
 
-#: ../../include/text.php:1007
+#: include/text.php:1068
 msgid "prodded"
 msgstr ""
 
-#: ../../include/text.php:1008
+#: include/text.php:1069
 msgid "slap"
 msgstr ""
 
-#: ../../include/text.php:1008
+#: include/text.php:1069
 msgid "slapped"
 msgstr ""
 
-#: ../../include/text.php:1009
+#: include/text.php:1070
 msgid "finger"
 msgstr ""
 
-#: ../../include/text.php:1009
+#: include/text.php:1070
 msgid "fingered"
 msgstr ""
 
-#: ../../include/text.php:1010
+#: include/text.php:1071
 msgid "rebuff"
 msgstr ""
 
-#: ../../include/text.php:1010
+#: include/text.php:1071
 msgid "rebuffed"
 msgstr ""
 
-#: ../../include/text.php:1024
+#: include/text.php:1085
 msgid "happy"
 msgstr ""
 
-#: ../../include/text.php:1025
+#: include/text.php:1086
 msgid "sad"
 msgstr ""
 
-#: ../../include/text.php:1026
+#: include/text.php:1087
 msgid "mellow"
 msgstr ""
 
-#: ../../include/text.php:1027
+#: include/text.php:1088
 msgid "tired"
 msgstr ""
 
-#: ../../include/text.php:1028
+#: include/text.php:1089
 msgid "perky"
 msgstr ""
 
-#: ../../include/text.php:1029
+#: include/text.php:1090
 msgid "angry"
 msgstr ""
 
-#: ../../include/text.php:1030
+#: include/text.php:1091
 msgid "stupified"
 msgstr ""
 
-#: ../../include/text.php:1031
+#: include/text.php:1092
 msgid "puzzled"
 msgstr ""
 
-#: ../../include/text.php:1032
+#: include/text.php:1093
 msgid "interested"
 msgstr ""
 
-#: ../../include/text.php:1033
+#: include/text.php:1094
 msgid "bitter"
 msgstr ""
 
-#: ../../include/text.php:1034
+#: include/text.php:1095
 msgid "cheerful"
 msgstr ""
 
-#: ../../include/text.php:1035
+#: include/text.php:1096
 msgid "alive"
 msgstr ""
 
-#: ../../include/text.php:1036
+#: include/text.php:1097
 msgid "annoyed"
 msgstr ""
 
-#: ../../include/text.php:1037
+#: include/text.php:1098
 msgid "anxious"
 msgstr ""
 
-#: ../../include/text.php:1038
+#: include/text.php:1099
 msgid "cranky"
 msgstr ""
 
-#: ../../include/text.php:1039
+#: include/text.php:1100
 msgid "disturbed"
 msgstr ""
 
-#: ../../include/text.php:1040
+#: include/text.php:1101
 msgid "frustrated"
 msgstr ""
 
-#: ../../include/text.php:1041
+#: include/text.php:1102
 msgid "motivated"
 msgstr ""
 
-#: ../../include/text.php:1042
+#: include/text.php:1103
 msgid "relaxed"
 msgstr ""
 
-#: ../../include/text.php:1043
+#: include/text.php:1104
 msgid "surprised"
 msgstr ""
 
-#: ../../include/text.php:1213
-msgid "Monday"
-msgstr "Понедельник"
-
-#: ../../include/text.php:1213
-msgid "Tuesday"
-msgstr "Вторник"
-
-#: ../../include/text.php:1213
-msgid "Wednesday"
-msgstr "Среда"
-
-#: ../../include/text.php:1213
-msgid "Thursday"
-msgstr "Четверг"
-
-#: ../../include/text.php:1213
-msgid "Friday"
-msgstr "Пятница"
-
-#: ../../include/text.php:1213
-msgid "Saturday"
-msgstr "Суббота"
-
-#: ../../include/text.php:1213
-msgid "Sunday"
-msgstr "Воскресенье"
-
-#: ../../include/text.php:1217
-msgid "January"
-msgstr "Январь"
-
-#: ../../include/text.php:1217
-msgid "February"
-msgstr "Февраль"
-
-#: ../../include/text.php:1217
-msgid "March"
-msgstr "Март"
-
-#: ../../include/text.php:1217
-msgid "April"
-msgstr "Апрель"
-
-#: ../../include/text.php:1217
-msgid "May"
-msgstr "Май"
-
-#: ../../include/text.php:1217
-msgid "June"
-msgstr "Июнь"
-
-#: ../../include/text.php:1217
-msgid "July"
-msgstr "Июль"
-
-#: ../../include/text.php:1217
-msgid "August"
-msgstr "Август"
-
-#: ../../include/text.php:1217
-msgid "September"
-msgstr "Сентябрь"
-
-#: ../../include/text.php:1217
-msgid "October"
-msgstr "Октябрь"
-
-#: ../../include/text.php:1217
-msgid "November"
-msgstr "Ноябрь"
-
-#: ../../include/text.php:1217
-msgid "December"
-msgstr "Декабрь"
-
-#: ../../include/text.php:1437
+#: include/text.php:1504
 msgid "bytes"
 msgstr "байт"
 
-#: ../../include/text.php:1461 ../../include/text.php:1473
+#: include/text.php:1536 include/text.php:1548
 msgid "Click to open/close"
 msgstr "Нажмите, чтобы открыть / закрыть"
 
-#: ../../include/text.php:1702 ../../include/user.php:247
-#: ../../view/theme/duepuntozero/config.php:44
-msgid "default"
-msgstr "значение по умолчанию"
+#: include/text.php:1722
+msgid "View on separate page"
+msgstr ""
 
-#: ../../include/text.php:1714
-msgid "Select an alternate language"
-msgstr "Выбор альтернативного языка"
+#: include/text.php:1723
+msgid "view on separate page"
+msgstr ""
 
-#: ../../include/text.php:1970
+#: include/text.php:2002
 msgid "activity"
 msgstr "активность"
 
-#: ../../include/text.php:1973
+#: include/text.php:2005
 msgid "post"
 msgstr "сообщение"
 
-#: ../../include/text.php:2141
+#: include/text.php:2173
 msgid "Item filed"
 msgstr ""
 
-#: ../../include/bbcode.php:428 ../../include/bbcode.php:1047
-#: ../../include/bbcode.php:1048
+#: include/bbcode.php:482 include/bbcode.php:1157 include/bbcode.php:1158
 msgid "Image/photo"
 msgstr "Изображение / Фото"
 
-#: ../../include/bbcode.php:528
+#: include/bbcode.php:595
 #, php-format
 msgid "<a href=\"%1$s\" target=\"_blank\">%2$s</a> %3$s"
 msgstr ""
 
-#: ../../include/bbcode.php:562
+#: include/bbcode.php:629
 #, php-format
 msgid ""
-"<span><a href=\"%s\" target=\"_blank\">%s</a> wrote the following <a "
-"href=\"%s\" target=\"_blank\">post</a>"
+"<span><a href=\"%s\" target=\"_blank\">%s</a> wrote the following <a href="
+"\"%s\" target=\"_blank\">post</a>"
 msgstr ""
 
-#: ../../include/bbcode.php:1011 ../../include/bbcode.php:1031
+#: include/bbcode.php:1117 include/bbcode.php:1137
 msgid "$1 wrote:"
 msgstr "$1 написал:"
 
-#: ../../include/bbcode.php:1056 ../../include/bbcode.php:1057
+#: include/bbcode.php:1166 include/bbcode.php:1167
 msgid "Encrypted content"
 msgstr "Зашифрованный контент"
 
-#: ../../include/notifier.php:786 ../../include/delivery.php:456
-msgid "(no subject)"
-msgstr "(без темы)"
-
-#: ../../include/notifier.php:796 ../../include/delivery.php:467
-#: ../../include/enotify.php:33
-msgid "noreply"
-msgstr "без ответа"
-
-#: ../../include/dba_pdo.php:72 ../../include/dba.php:56
+#: include/dba_pdo.php:72 include/dba.php:55
 #, php-format
 msgid "Cannot locate DNS info for database server '%s'"
 msgstr "Не могу найти информацию для DNS-сервера базы данных '%s'"
 
-#: ../../include/contact_selectors.php:32
+#: include/contact_selectors.php:32
 msgid "Unknown | Not categorised"
 msgstr "Неизвестно | Не определено"
 
-#: ../../include/contact_selectors.php:33
+#: include/contact_selectors.php:33
 msgid "Block immediately"
 msgstr "Блокировать немедленно"
 
-#: ../../include/contact_selectors.php:34
+#: include/contact_selectors.php:34
 msgid "Shady, spammer, self-marketer"
 msgstr "Тролль, спаммер, рассылает рекламу"
 
-#: ../../include/contact_selectors.php:35
+#: include/contact_selectors.php:35
 msgid "Known to me, but no opinion"
 msgstr "Известные мне, но нет определенного мнения"
 
-#: ../../include/contact_selectors.php:36
+#: include/contact_selectors.php:36
 msgid "OK, probably harmless"
 msgstr "Хорошо, наверное, безвредные"
 
-#: ../../include/contact_selectors.php:37
+#: include/contact_selectors.php:37
 msgid "Reputable, has my trust"
 msgstr "Уважаемые, есть мое доверие"
 
-#: ../../include/contact_selectors.php:60
+#: include/contact_selectors.php:60
 msgid "Weekly"
 msgstr "Еженедельно"
 
-#: ../../include/contact_selectors.php:61
+#: include/contact_selectors.php:61
 msgid "Monthly"
 msgstr "Ежемесячно"
 
-#: ../../include/contact_selectors.php:77
+#: include/contact_selectors.php:77
 msgid "OStatus"
 msgstr "OStatus"
 
-#: ../../include/contact_selectors.php:78
+#: include/contact_selectors.php:78
 msgid "RSS/Atom"
 msgstr "RSS/Atom"
 
-#: ../../include/contact_selectors.php:82
+#: include/contact_selectors.php:81
+msgid "Facebook"
+msgstr "Facebook"
+
+#: include/contact_selectors.php:82
 msgid "Zot!"
 msgstr "Zot!"
 
-#: ../../include/contact_selectors.php:83
+#: include/contact_selectors.php:83
 msgid "LinkedIn"
 msgstr "LinkedIn"
 
-#: ../../include/contact_selectors.php:84
+#: include/contact_selectors.php:84
 msgid "XMPP/IM"
 msgstr "XMPP/IM"
 
-#: ../../include/contact_selectors.php:85
+#: include/contact_selectors.php:85
 msgid "MySpace"
 msgstr "MySpace"
 
-#: ../../include/contact_selectors.php:87
+#: include/contact_selectors.php:87
 msgid "Google+"
 msgstr "Google+"
 
-#: ../../include/contact_selectors.php:88
+#: include/contact_selectors.php:88
 msgid "pump.io"
 msgstr "pump.io"
 
-#: ../../include/contact_selectors.php:89
+#: include/contact_selectors.php:89
 msgid "Twitter"
 msgstr "Twitter"
 
-#: ../../include/contact_selectors.php:90
+#: include/contact_selectors.php:90
 msgid "Diaspora Connector"
 msgstr ""
 
-#: ../../include/contact_selectors.php:91
-msgid "Statusnet"
+#: include/contact_selectors.php:91
+msgid "GNU Social"
 msgstr ""
 
-#: ../../include/contact_selectors.php:92
+#: include/contact_selectors.php:92
 msgid "App.net"
 msgstr ""
 
-#: ../../include/Scrape.php:614
+#: include/contact_selectors.php:103
+msgid "Redmatrix"
+msgstr ""
+
+#: include/Scrape.php:624
 msgid " on Last.fm"
 msgstr "на Last.fm"
 
-#: ../../include/bb2diaspora.php:154 ../../include/event.php:20
+#: include/bb2diaspora.php:154 include/event.php:30 include/event.php:48
 msgid "Starts:"
 msgstr "Начало:"
 
-#: ../../include/bb2diaspora.php:162 ../../include/event.php:30
+#: include/bb2diaspora.php:162 include/event.php:33 include/event.php:54
 msgid "Finishes:"
 msgstr "Окончание:"
 
-#: ../../include/profile_advanced.php:22
-msgid "j F, Y"
-msgstr "j F, Y"
-
-#: ../../include/profile_advanced.php:23
-msgid "j F"
-msgstr "j F"
-
-#: ../../include/profile_advanced.php:30
-msgid "Birthday:"
-msgstr "День рождения:"
-
-#: ../../include/profile_advanced.php:34
-msgid "Age:"
-msgstr "Возраст:"
-
-#: ../../include/profile_advanced.php:43
-#, php-format
-msgid "for %1$d %2$s"
-msgstr ""
-
-#: ../../include/profile_advanced.php:52
-msgid "Tags:"
-msgstr "Ключевые слова: "
-
-#: ../../include/profile_advanced.php:56
-msgid "Religion:"
-msgstr "Религия:"
-
-#: ../../include/profile_advanced.php:60
-msgid "Hobbies/Interests:"
-msgstr "Хобби / Интересы:"
-
-#: ../../include/profile_advanced.php:67
-msgid "Contact information and Social Networks:"
-msgstr "Информация о контакте и социальных сетях:"
-
-#: ../../include/profile_advanced.php:69
-msgid "Musical interests:"
-msgstr "Музыкальные интересы:"
-
-#: ../../include/profile_advanced.php:71
-msgid "Books, literature:"
-msgstr "Книги, литература:"
-
-#: ../../include/profile_advanced.php:73
-msgid "Television:"
-msgstr "Телевидение:"
-
-#: ../../include/profile_advanced.php:75
-msgid "Film/dance/culture/entertainment:"
-msgstr "Кино / Танцы / Культура / Развлечения:"
-
-#: ../../include/profile_advanced.php:77
-msgid "Love/Romance:"
-msgstr "Любовь / Романтика:"
-
-#: ../../include/profile_advanced.php:79
-msgid "Work/employment:"
-msgstr "Работа / Занятость:"
-
-#: ../../include/profile_advanced.php:81
-msgid "School/education:"
-msgstr "Школа / Образование:"
-
-#: ../../include/plugin.php:455 ../../include/plugin.php:457
+#: include/plugin.php:522 include/plugin.php:524
 msgid "Click here to upgrade."
 msgstr "Нажмите для обновления."
 
-#: ../../include/plugin.php:463
+#: include/plugin.php:530
 msgid "This action exceeds the limits set by your subscription plan."
 msgstr "Это действие превышает лимиты, установленные вашим тарифным планом."
 
-#: ../../include/plugin.php:468
+#: include/plugin.php:535
 msgid "This action is not available under your subscription plan."
 msgstr "Это действие не доступно в соответствии с вашим планом подписки."
 
-#: ../../include/nav.php:73
+#: include/nav.php:72
 msgid "End this session"
-msgstr "Конец этой сессии"
+msgstr "Завершить эту сессию"
 
-#: ../../include/nav.php:76 ../../include/nav.php:148
-#: ../../view/theme/diabook/theme.php:123
+#: include/nav.php:75 include/nav.php:157 view/theme/diabook/theme.php:123
 msgid "Your posts and conversations"
-msgstr "Ваши сообщения и беседы"
+msgstr "Данные вашей учётной записи"
 
-#: ../../include/nav.php:77 ../../view/theme/diabook/theme.php:124
+#: include/nav.php:76 view/theme/diabook/theme.php:124
 msgid "Your profile page"
-msgstr "Страница Вашего профиля"
+msgstr "Информация о вас"
 
-#: ../../include/nav.php:78 ../../view/theme/diabook/theme.php:126
+#: include/nav.php:77 view/theme/diabook/theme.php:126
 msgid "Your photos"
 msgstr "Ваши фотографии"
 
-#: ../../include/nav.php:79
+#: include/nav.php:78
 msgid "Your videos"
 msgstr ""
 
-#: ../../include/nav.php:80 ../../view/theme/diabook/theme.php:127
+#: include/nav.php:79 view/theme/diabook/theme.php:127
 msgid "Your events"
 msgstr "Ваши события"
 
-#: ../../include/nav.php:81 ../../view/theme/diabook/theme.php:128
+#: include/nav.php:80 view/theme/diabook/theme.php:128
 msgid "Personal notes"
 msgstr "Личные заметки"
 
-#: ../../include/nav.php:81
+#: include/nav.php:80
 msgid "Your personal notes"
 msgstr ""
 
-#: ../../include/nav.php:92
+#: include/nav.php:91
 msgid "Sign in"
 msgstr "Вход"
 
-#: ../../include/nav.php:105
+#: include/nav.php:104
 msgid "Home Page"
 msgstr "Главная страница"
 
-#: ../../include/nav.php:109
+#: include/nav.php:108
 msgid "Create an account"
 msgstr "Создать аккаунт"
 
-#: ../../include/nav.php:114
+#: include/nav.php:113
 msgid "Help and documentation"
 msgstr "Помощь и документация"
 
-#: ../../include/nav.php:117
+#: include/nav.php:116
 msgid "Apps"
 msgstr "Приложения"
 
-#: ../../include/nav.php:117
+#: include/nav.php:116
 msgid "Addon applications, utilities, games"
 msgstr "Дополнительные приложения, утилиты, игры"
 
-#: ../../include/nav.php:119
+#: include/nav.php:118
 msgid "Search site content"
 msgstr "Поиск по сайту"
 
-#: ../../include/nav.php:129
+#: include/nav.php:136
 msgid "Conversations on this site"
 msgstr "Беседы на этом сайте"
 
-#: ../../include/nav.php:131
+#: include/nav.php:138
 msgid "Conversations on the network"
 msgstr ""
 
-#: ../../include/nav.php:133
+#: include/nav.php:142
 msgid "Directory"
 msgstr "Каталог"
 
-#: ../../include/nav.php:133
+#: include/nav.php:142
 msgid "People directory"
 msgstr "Каталог участников"
 
-#: ../../include/nav.php:135
+#: include/nav.php:144
 msgid "Information"
-msgstr ""
+msgstr "Информация"
 
-#: ../../include/nav.php:135
+#: include/nav.php:144
 msgid "Information about this friendica instance"
 msgstr ""
 
-#: ../../include/nav.php:145
+#: include/nav.php:154
 msgid "Conversations from your friends"
-msgstr "Беседы с друзьями"
+msgstr "Посты ваших друзей"
 
-#: ../../include/nav.php:146
+#: include/nav.php:155
 msgid "Network Reset"
 msgstr "Перезагрузка сети"
 
-#: ../../include/nav.php:146
+#: include/nav.php:155
 msgid "Load Network page with no filters"
 msgstr "Загрузить страницу сети без фильтров"
 
-#: ../../include/nav.php:154
+#: include/nav.php:162
 msgid "Friend Requests"
 msgstr "Запросы на добавление в список друзей"
 
-#: ../../include/nav.php:156
+#: include/nav.php:166
 msgid "See all notifications"
 msgstr "Посмотреть все уведомления"
 
-#: ../../include/nav.php:157
+#: include/nav.php:167
 msgid "Mark all system notifications seen"
 msgstr "Отметить все системные уведомления, как прочитанные"
 
-#: ../../include/nav.php:161
+#: include/nav.php:171
 msgid "Private mail"
 msgstr "Личная почта"
 
-#: ../../include/nav.php:162
+#: include/nav.php:172
 msgid "Inbox"
 msgstr "Входящие"
 
-#: ../../include/nav.php:163
+#: include/nav.php:173
 msgid "Outbox"
 msgstr "Исходящие"
 
-#: ../../include/nav.php:167
+#: include/nav.php:177
 msgid "Manage"
 msgstr "Управлять"
 
-#: ../../include/nav.php:167
+#: include/nav.php:177
 msgid "Manage other pages"
 msgstr "Управление другими страницами"
 
-#: ../../include/nav.php:172
+#: include/nav.php:182
 msgid "Account settings"
 msgstr "Настройки аккаунта"
 
-#: ../../include/nav.php:175
+#: include/nav.php:185
 msgid "Manage/Edit Profiles"
 msgstr "Управление/редактирование профилей"
 
-#: ../../include/nav.php:177
+#: include/nav.php:187
 msgid "Manage/edit friends and contacts"
 msgstr "Управление / редактирование друзей и контактов"
 
-#: ../../include/nav.php:184
+#: include/nav.php:194
 msgid "Site setup and configuration"
-msgstr "Установка и конфигурация сайта"
+msgstr "Конфигурация сайта"
 
-#: ../../include/nav.php:188
+#: include/nav.php:198
 msgid "Navigation"
 msgstr "Навигация"
 
-#: ../../include/nav.php:188
+#: include/nav.php:198
 msgid "Site map"
 msgstr "Карта сайта"
 
-#: ../../include/api.php:304 ../../include/api.php:315
-#: ../../include/api.php:416 ../../include/api.php:1063
-#: ../../include/api.php:1065
-msgid "User not found."
-msgstr "Пользователь не найден."
-
-#: ../../include/api.php:771
+#: include/api.php:878
 #, php-format
 msgid "Daily posting limit of %d posts reached. The post was rejected."
 msgstr ""
 
-#: ../../include/api.php:790
+#: include/api.php:897
 #, php-format
 msgid "Weekly posting limit of %d posts reached. The post was rejected."
 msgstr ""
 
-#: ../../include/api.php:809
+#: include/api.php:916
 #, php-format
 msgid "Monthly posting limit of %d posts reached. The post was rejected."
 msgstr ""
 
-#: ../../include/api.php:1272
-msgid "There is no status with this id."
-msgstr "Нет статуса с таким id."
-
-#: ../../include/api.php:1342
-msgid "There is no conversation with this id."
-msgstr ""
-
-#: ../../include/api.php:1614
-msgid "Invalid request."
-msgstr ""
-
-#: ../../include/api.php:1625
-msgid "Invalid item."
-msgstr ""
-
-#: ../../include/api.php:1635
-msgid "Invalid action. "
-msgstr ""
-
-#: ../../include/api.php:1643
-msgid "DB error"
-msgstr ""
-
-#: ../../include/user.php:40
+#: include/user.php:48
 msgid "An invitation is required."
 msgstr "Требуется приглашение."
 
-#: ../../include/user.php:45
+#: include/user.php:53
 msgid "Invitation could not be verified."
 msgstr "Приглашение не может быть проверено."
 
-#: ../../include/user.php:53
+#: include/user.php:61
 msgid "Invalid OpenID url"
 msgstr "Неверный URL OpenID"
 
-#: ../../include/user.php:74
+#: include/user.php:82
 msgid "Please enter the required information."
 msgstr "Пожалуйста, введите необходимую информацию."
 
-#: ../../include/user.php:88
+#: include/user.php:96
 msgid "Please use a shorter name."
 msgstr "Пожалуйста, используйте более короткое имя."
 
-#: ../../include/user.php:90
+#: include/user.php:98
 msgid "Name too short."
 msgstr "Имя слишком короткое."
 
-#: ../../include/user.php:105
+#: include/user.php:113
 msgid "That doesn't appear to be your full (First Last) name."
 msgstr "Кажется, что это ваше неполное (Имя Фамилия) имя."
 
-#: ../../include/user.php:110
+#: include/user.php:118
 msgid "Your email domain is not among those allowed on this site."
-msgstr "Домен вашего адреса электронной почты не относится к числу разрешенных на этом сайте."
+msgstr ""
+"Домен вашего адреса электронной почты не относится к числу разрешенных на "
+"этом сайте."
 
-#: ../../include/user.php:113
+#: include/user.php:121
 msgid "Not a valid email address."
 msgstr "Неверный адрес электронной почты."
 
-#: ../../include/user.php:126
+#: include/user.php:134
 msgid "Cannot use that email."
 msgstr "Нельзя использовать этот Email."
 
-#: ../../include/user.php:132
-msgid ""
-"Your \"nickname\" can only contain \"a-z\", \"0-9\", \"-\", and \"_\", and "
-"must also begin with a letter."
-msgstr "Ваш \"ник\" может содержать только \"a-z\", \"0-9\", \"-\", и \"_\", а также должен начинаться с буквы."
+#: include/user.php:140
+msgid "Your \"nickname\" can only contain \"a-z\", \"0-9\" and \"_\"."
+msgstr ""
 
-#: ../../include/user.php:138 ../../include/user.php:236
+#: include/user.php:147 include/user.php:245
 msgid "Nickname is already registered. Please choose another."
 msgstr "Такой ник уже зарегистрирован. Пожалуйста, выберите другой."
 
-#: ../../include/user.php:148
+#: include/user.php:157
 msgid ""
 "Nickname was once registered here and may not be re-used. Please choose "
 "another."
-msgstr "Ник уже зарегистрирован на этом сайте и не может быть изменён. Пожалуйста, выберите другой ник."
+msgstr ""
+"Ник уже зарегистрирован на этом сайте и не может быть изменён. Пожалуйста, "
+"выберите другой ник."
 
-#: ../../include/user.php:164
+#: include/user.php:173
 msgid "SERIOUS ERROR: Generation of security keys failed."
 msgstr "СЕРЬЕЗНАЯ ОШИБКА: генерация ключей безопасности не удалась."
 
-#: ../../include/user.php:222
+#: include/user.php:231
 msgid "An error occurred during registration. Please try again."
 msgstr "Ошибка при регистрации. Пожалуйста, попробуйте еще раз."
 
-#: ../../include/user.php:257
+#: include/user.php:256 view/theme/duepuntozero/config.php:44
+msgid "default"
+msgstr "значение по умолчанию"
+
+#: include/user.php:266
 msgid "An error occurred creating your default profile. Please try again."
 msgstr "Ошибка создания вашего профиля. Пожалуйста, попробуйте еще раз."
 
-#: ../../include/user.php:289 ../../include/user.php:293
-#: ../../include/profile_selectors.php:42
+#: include/user.php:299 include/user.php:303 include/profile_selectors.php:42
 msgid "Friends"
 msgstr "Друзья"
 
-#: ../../include/user.php:377
+#: include/user.php:387
 #, php-format
 msgid ""
 "\n"
@@ -7099,7 +8110,7 @@ msgid ""
 "\t"
 msgstr ""
 
-#: ../../include/user.php:381
+#: include/user.php:391
 #, php-format
 msgid ""
 "\n"
@@ -7108,20 +8119,25 @@ msgid ""
 "\t\t\tLogin Name:\t%1$s\n"
 "\t\t\tPassword:\t%5$s\n"
 "\n"
-"\t\tYou may change your password from your account \"Settings\" page after logging\n"
+"\t\tYou may change your password from your account \"Settings\" page after "
+"logging\n"
 "\t\tin.\n"
 "\n"
-"\t\tPlease take a few moments to review the other account settings on that page.\n"
+"\t\tPlease take a few moments to review the other account settings on that "
+"page.\n"
 "\n"
 "\t\tYou may also wish to add some basic information to your default profile\n"
 "\t\t(on the \"Profiles\" page) so that other people can easily find you.\n"
 "\n"
 "\t\tWe recommend setting your full name, adding a profile photo,\n"
-"\t\tadding some profile \"keywords\" (very useful in making new friends) - and\n"
-"\t\tperhaps what country you live in; if you do not wish to be more specific\n"
+"\t\tadding some profile \"keywords\" (very useful in making new friends) - "
+"and\n"
+"\t\tperhaps what country you live in; if you do not wish to be more "
+"specific\n"
 "\t\tthan that.\n"
 "\n"
-"\t\tWe fully respect your right to privacy, and none of these items are necessary.\n"
+"\t\tWe fully respect your right to privacy, and none of these items are "
+"necessary.\n"
 "\t\tIf you are new and do not know anybody here, they may help\n"
 "\t\tyou to make some new and interesting friends.\n"
 "\n"
@@ -7129,495 +8145,504 @@ msgid ""
 "\t\tThank you and welcome to %2$s."
 msgstr ""
 
-#: ../../include/diaspora.php:703
+#: include/diaspora.php:720
 msgid "Sharing notification from Diaspora network"
 msgstr "Делиться уведомлениями из сети Diaspora"
 
-#: ../../include/diaspora.php:2520
+#: include/diaspora.php:2625
 msgid "Attachments:"
 msgstr "Вложения:"
 
-#: ../../include/items.php:4555
+#: include/delivery.php:533
+msgid "(no subject)"
+msgstr "(без темы)"
+
+#: include/delivery.php:544 include/enotify.php:37
+msgid "noreply"
+msgstr "без ответа"
+
+#: include/items.php:4926
 msgid "Do you really want to delete this item?"
 msgstr "Вы действительно хотите удалить этот элемент?"
 
-#: ../../include/items.php:4778
+#: include/items.php:5201
 msgid "Archives"
 msgstr "Архивы"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Male"
 msgstr "Мужчина"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Female"
 msgstr "Женщина"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Currently Male"
 msgstr "В данный момент мужчина"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Currently Female"
 msgstr "В настоящее время женщина"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Mostly Male"
 msgstr "В основном мужчина"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Mostly Female"
 msgstr "В основном женщина"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Transgender"
 msgstr "Транссексуал"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Intersex"
 msgstr "Интерсексуал"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Transsexual"
 msgstr "Транссексуал"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Hermaphrodite"
 msgstr "Гермафродит"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Neuter"
 msgstr "Средний род"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Non-specific"
 msgstr "Не определен"
 
-#: ../../include/profile_selectors.php:6
+#: include/profile_selectors.php:6
 msgid "Other"
 msgstr "Другой"
 
-#: ../../include/profile_selectors.php:6
-msgid "Undecided"
-msgstr "Не решено"
-
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Males"
 msgstr "Мужчины"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Females"
 msgstr "Женщины"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Gay"
 msgstr "Гей"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Lesbian"
 msgstr "Лесбиянка"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "No Preference"
 msgstr "Без предпочтений"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Bisexual"
 msgstr "Бисексуал"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Autosexual"
 msgstr "Автосексуал"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Abstinent"
 msgstr "Воздержанный"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Virgin"
 msgstr "Девственница"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Deviant"
 msgstr "Deviant"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Fetish"
 msgstr "Фетиш"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Oodles"
 msgstr "Групповой"
 
-#: ../../include/profile_selectors.php:23
+#: include/profile_selectors.php:23
 msgid "Nonsexual"
 msgstr "Нет интереса к сексу"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Single"
 msgstr "Без пары"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Lonely"
 msgstr "Пока никого нет"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Available"
 msgstr "Доступный"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Unavailable"
 msgstr "Не ищу никого"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Has crush"
 msgstr "Имеет ошибку"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Infatuated"
 msgstr "Влюблён"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Dating"
 msgstr "Свидания"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Unfaithful"
 msgstr "Изменяю супругу"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Sex Addict"
 msgstr "Люблю секс"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Friends/Benefits"
 msgstr "Друзья / Предпочтения"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Casual"
 msgstr "Обычный"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Engaged"
 msgstr "Занят"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Married"
 msgstr "Женат / Замужем"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Imaginarily married"
 msgstr ""
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Partners"
 msgstr "Партнеры"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Cohabiting"
 msgstr "Партнерство"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Common law"
 msgstr ""
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Happy"
 msgstr "Счастлив/а/"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Not looking"
 msgstr "Не в поиске"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Swinger"
 msgstr "Свинг"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Betrayed"
 msgstr "Преданный"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Separated"
 msgstr "Разделенный"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Unstable"
 msgstr "Нестабильный"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Divorced"
 msgstr "Разведен(а)"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Imaginarily divorced"
 msgstr ""
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Widowed"
 msgstr "Овдовевший"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Uncertain"
 msgstr "Неопределенный"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "It's complicated"
 msgstr "влишком сложно"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Don't care"
 msgstr "Не беспокоить"
 
-#: ../../include/profile_selectors.php:42
+#: include/profile_selectors.php:42
 msgid "Ask me"
 msgstr "Спросите меня"
 
-#: ../../include/enotify.php:18
+#: include/enotify.php:18
 msgid "Friendica Notification"
 msgstr "Friendica уведомления"
 
-#: ../../include/enotify.php:21
+#: include/enotify.php:21
 msgid "Thank You,"
 msgstr "Спасибо,"
 
-#: ../../include/enotify.php:23
+#: include/enotify.php:24
 #, php-format
 msgid "%s Administrator"
 msgstr "%s администратор"
 
-#: ../../include/enotify.php:64
+#: include/enotify.php:26
+#, php-format
+msgid "%1$s, %2$s Administrator"
+msgstr ""
+
+#: include/enotify.php:68
 #, php-format
 msgid "%s <!item_type!>"
 msgstr "%s <!item_type!>"
 
-#: ../../include/enotify.php:68
+#: include/enotify.php:82
 #, php-format
 msgid "[Friendica:Notify] New mail received at %s"
 msgstr "[Friendica: Оповещение] Новое сообщение, пришедшее на %s"
 
-#: ../../include/enotify.php:70
+#: include/enotify.php:84
 #, php-format
 msgid "%1$s sent you a new private message at %2$s."
 msgstr "%1$s отправил вам новое личное сообщение на %2$s."
 
-#: ../../include/enotify.php:71
+#: include/enotify.php:85
 #, php-format
 msgid "%1$s sent you %2$s."
 msgstr "%1$s послал вам %2$s."
 
-#: ../../include/enotify.php:71
+#: include/enotify.php:85
 msgid "a private message"
 msgstr "личное сообщение"
 
-#: ../../include/enotify.php:72
+#: include/enotify.php:86
 #, php-format
 msgid "Please visit %s to view and/or reply to your private messages."
-msgstr "Пожалуйста, посетите %s для просмотра и/или ответа на личные сообщения."
+msgstr ""
+"Пожалуйста, посетите %s для просмотра и/или ответа на личные сообщения."
 
-#: ../../include/enotify.php:124
+#: include/enotify.php:138
 #, php-format
 msgid "%1$s commented on [url=%2$s]a %3$s[/url]"
 msgstr "%1$s прокомментировал [url=%2$s]a %3$s[/url]"
 
-#: ../../include/enotify.php:131
+#: include/enotify.php:145
 #, php-format
 msgid "%1$s commented on [url=%2$s]%3$s's %4$s[/url]"
 msgstr "%1$s прокомментировал [url=%2$s]%3$s's %4$s[/url]"
 
-#: ../../include/enotify.php:139
+#: include/enotify.php:153
 #, php-format
 msgid "%1$s commented on [url=%2$s]your %3$s[/url]"
 msgstr "%1$s прокомментировал [url=%2$s]your %3$s[/url]"
 
-#: ../../include/enotify.php:149
+#: include/enotify.php:163
 #, php-format
 msgid "[Friendica:Notify] Comment to conversation #%1$d by %2$s"
 msgstr ""
 
-#: ../../include/enotify.php:150
+#: include/enotify.php:164
 #, php-format
 msgid "%s commented on an item/conversation you have been following."
 msgstr ""
 
-#: ../../include/enotify.php:153 ../../include/enotify.php:168
-#: ../../include/enotify.php:181 ../../include/enotify.php:194
-#: ../../include/enotify.php:212 ../../include/enotify.php:225
+#: include/enotify.php:167 include/enotify.php:182 include/enotify.php:195
+#: include/enotify.php:208 include/enotify.php:226 include/enotify.php:239
 #, php-format
 msgid "Please visit %s to view and/or reply to the conversation."
 msgstr ""
 
-#: ../../include/enotify.php:160
+#: include/enotify.php:174
 #, php-format
 msgid "[Friendica:Notify] %s posted to your profile wall"
 msgstr "[Friendica:Оповещение] %s написал на стене вашего профиля"
 
-#: ../../include/enotify.php:162
+#: include/enotify.php:176
 #, php-format
 msgid "%1$s posted to your profile wall at %2$s"
 msgstr ""
 
-#: ../../include/enotify.php:164
+#: include/enotify.php:178
 #, php-format
 msgid "%1$s posted to [url=%2$s]your wall[/url]"
 msgstr ""
 
-#: ../../include/enotify.php:175
+#: include/enotify.php:189
 #, php-format
 msgid "[Friendica:Notify] %s tagged you"
 msgstr ""
 
-#: ../../include/enotify.php:176
+#: include/enotify.php:190
 #, php-format
 msgid "%1$s tagged you at %2$s"
 msgstr ""
 
-#: ../../include/enotify.php:177
+#: include/enotify.php:191
 #, php-format
 msgid "%1$s [url=%2$s]tagged you[/url]."
 msgstr ""
 
-#: ../../include/enotify.php:188
+#: include/enotify.php:202
 #, php-format
 msgid "[Friendica:Notify] %s shared a new post"
 msgstr ""
 
-#: ../../include/enotify.php:189
+#: include/enotify.php:203
 #, php-format
 msgid "%1$s shared a new post at %2$s"
 msgstr ""
 
-#: ../../include/enotify.php:190
+#: include/enotify.php:204
 #, php-format
 msgid "%1$s [url=%2$s]shared a post[/url]."
 msgstr ""
 
-#: ../../include/enotify.php:202
+#: include/enotify.php:216
 #, php-format
 msgid "[Friendica:Notify] %1$s poked you"
 msgstr ""
 
-#: ../../include/enotify.php:203
+#: include/enotify.php:217
 #, php-format
 msgid "%1$s poked you at %2$s"
 msgstr ""
 
-#: ../../include/enotify.php:204
+#: include/enotify.php:218
 #, php-format
 msgid "%1$s [url=%2$s]poked you[/url]."
 msgstr ""
 
-#: ../../include/enotify.php:219
+#: include/enotify.php:233
 #, php-format
 msgid "[Friendica:Notify] %s tagged your post"
 msgstr ""
 
-#: ../../include/enotify.php:220
+#: include/enotify.php:234
 #, php-format
 msgid "%1$s tagged your post at %2$s"
 msgstr ""
 
-#: ../../include/enotify.php:221
+#: include/enotify.php:235
 #, php-format
 msgid "%1$s tagged [url=%2$s]your post[/url]"
 msgstr ""
 
-#: ../../include/enotify.php:232
+#: include/enotify.php:246
 msgid "[Friendica:Notify] Introduction received"
 msgstr "[Friendica:Сообщение] получен запрос"
 
-#: ../../include/enotify.php:233
+#: include/enotify.php:247
 #, php-format
 msgid "You've received an introduction from '%1$s' at %2$s"
 msgstr ""
 
-#: ../../include/enotify.php:234
+#: include/enotify.php:248
 #, php-format
 msgid "You've received [url=%1$s]an introduction[/url] from %2$s."
 msgstr ""
 
-#: ../../include/enotify.php:237 ../../include/enotify.php:279
+#: include/enotify.php:251 include/enotify.php:293
 #, php-format
 msgid "You may visit their profile at %s"
 msgstr "Вы можете посмотреть его профиль здесь %s"
 
-#: ../../include/enotify.php:239
+#: include/enotify.php:253
 #, php-format
 msgid "Please visit %s to approve or reject the introduction."
 msgstr "Посетите %s для подтверждения или отказа запроса."
 
-#: ../../include/enotify.php:247
+#: include/enotify.php:261
 msgid "[Friendica:Notify] A new person is sharing with you"
 msgstr ""
 
-#: ../../include/enotify.php:248 ../../include/enotify.php:249
+#: include/enotify.php:262 include/enotify.php:263
 #, php-format
 msgid "%1$s is sharing with you at %2$s"
 msgstr ""
 
-#: ../../include/enotify.php:255
+#: include/enotify.php:269
 msgid "[Friendica:Notify] You have a new follower"
 msgstr ""
 
-#: ../../include/enotify.php:256 ../../include/enotify.php:257
+#: include/enotify.php:270 include/enotify.php:271
 #, php-format
 msgid "You have a new follower at %2$s : %1$s"
 msgstr ""
 
-#: ../../include/enotify.php:270
+#: include/enotify.php:284
 msgid "[Friendica:Notify] Friend suggestion received"
 msgstr "[Friendica: Оповещение] получено предложение дружбы"
 
-#: ../../include/enotify.php:271
+#: include/enotify.php:285
 #, php-format
 msgid "You've received a friend suggestion from '%1$s' at %2$s"
 msgstr "Вы получили предложение дружбы от '%1$s' на %2$s"
 
-#: ../../include/enotify.php:272
+#: include/enotify.php:286
 #, php-format
-msgid ""
-"You've received [url=%1$s]a friend suggestion[/url] for %2$s from %3$s."
+msgid "You've received [url=%1$s]a friend suggestion[/url] for %2$s from %3$s."
 msgstr ""
 
-#: ../../include/enotify.php:277
+#: include/enotify.php:291
 msgid "Name:"
 msgstr "Имя:"
 
-#: ../../include/enotify.php:278
+#: include/enotify.php:292
 msgid "Photo:"
 msgstr "Фото:"
 
-#: ../../include/enotify.php:281
+#: include/enotify.php:295
 #, php-format
 msgid "Please visit %s to approve or reject the suggestion."
 msgstr "Пожалуйста, посетите %s для подтверждения, или отказа запроса."
 
-#: ../../include/enotify.php:289 ../../include/enotify.php:302
+#: include/enotify.php:303 include/enotify.php:316
 msgid "[Friendica:Notify] Connection accepted"
 msgstr ""
 
-#: ../../include/enotify.php:290 ../../include/enotify.php:303
+#: include/enotify.php:304 include/enotify.php:317
 #, php-format
-msgid "'%1$s' has acepted your connection request at %2$s"
+msgid "'%1$s' has accepted your connection request at %2$s"
 msgstr ""
 
-#: ../../include/enotify.php:291 ../../include/enotify.php:304
+#: include/enotify.php:305 include/enotify.php:318
 #, php-format
 msgid "%2$s has accepted your [url=%1$s]connection request[/url]."
 msgstr ""
 
-#: ../../include/enotify.php:294
+#: include/enotify.php:308
 msgid ""
-"You are now mutual friends and may exchange status updates, photos, and email\n"
+"You are now mutual friends and may exchange status updates, photos, and "
+"email\n"
 "\twithout restriction."
 msgstr ""
 
-#: ../../include/enotify.php:297 ../../include/enotify.php:311
+#: include/enotify.php:311 include/enotify.php:325
 #, php-format
 msgid "Please visit %s  if you wish to make any changes to this relationship."
 msgstr ""
 
-#: ../../include/enotify.php:307
+#: include/enotify.php:321
 #, php-format
 msgid ""
 "'%1$s' has chosen to accept you a \"fan\", which restricts some forms of "
@@ -7626,266 +8651,261 @@ msgid ""
 "automatically."
 msgstr ""
 
-#: ../../include/enotify.php:309
+#: include/enotify.php:323
 #, php-format
 msgid ""
 "'%1$s' may choose to extend this into a two-way or more permissive "
 "relationship in the future. "
 msgstr ""
 
-#: ../../include/enotify.php:322
+#: include/enotify.php:336
 msgid "[Friendica System:Notify] registration request"
 msgstr ""
 
-#: ../../include/enotify.php:323
+#: include/enotify.php:337
 #, php-format
 msgid "You've received a registration request from '%1$s' at %2$s"
 msgstr ""
 
-#: ../../include/enotify.php:324
+#: include/enotify.php:338
 #, php-format
 msgid "You've received a [url=%1$s]registration request[/url] from %2$s."
 msgstr ""
 
-#: ../../include/enotify.php:327
+#: include/enotify.php:341
 #, php-format
 msgid "Full Name:\t%1$s\\nSite Location:\t%2$s\\nLogin Name:\t%3$s (%4$s)"
 msgstr ""
 
-#: ../../include/enotify.php:330
+#: include/enotify.php:344
 #, php-format
 msgid "Please visit %s to approve or reject the request."
 msgstr ""
 
-#: ../../include/oembed.php:212
+#: include/oembed.php:226
 msgid "Embedded content"
 msgstr "Встроенное содержание"
 
-#: ../../include/oembed.php:221
+#: include/oembed.php:235
 msgid "Embedding disabled"
 msgstr "Встраивание отключено"
 
-#: ../../include/uimport.php:94
+#: include/uimport.php:94
 msgid "Error decoding account file"
 msgstr "Ошибка расшифровки файла аккаунта"
 
-#: ../../include/uimport.php:100
+#: include/uimport.php:100
 msgid "Error! No version data in file! This is not a Friendica account file?"
-msgstr "Ошибка! Неправильная версия данных в файле! Это не файл аккаунта Friendica?"
+msgstr ""
+"Ошибка! Неправильная версия данных в файле! Это не файл аккаунта Friendica?"
 
-#: ../../include/uimport.php:116 ../../include/uimport.php:127
+#: include/uimport.php:116 include/uimport.php:127
 msgid "Error! Cannot check nickname"
 msgstr "Ошибка! Невозможно проверить никнейм"
 
-#: ../../include/uimport.php:120 ../../include/uimport.php:131
+#: include/uimport.php:120 include/uimport.php:131
 #, php-format
 msgid "User '%s' already exists on this server!"
 msgstr "Пользователь '%s' уже существует на этом сервере!"
 
-#: ../../include/uimport.php:153
+#: include/uimport.php:153
 msgid "User creation error"
 msgstr "Ошибка создания пользователя"
 
-#: ../../include/uimport.php:171
+#: include/uimport.php:173
 msgid "User profile creation error"
 msgstr "Ошибка создания профиля пользователя"
 
-#: ../../include/uimport.php:220
+#: include/uimport.php:222
 #, php-format
 msgid "%d contact not imported"
 msgid_plural "%d contacts not imported"
 msgstr[0] "%d контакт не импортирован"
 msgstr[1] "%d контакты не импортированы"
 msgstr[2] "%d контакты не импортированы"
+msgstr[3] "%d контакты не импортированы"
 
-#: ../../include/uimport.php:290
+#: include/uimport.php:292
 msgid "Done. You can now login with your username and password"
 msgstr "Завершено. Теперь вы можете войти с вашим логином и паролем"
 
-#: ../../index.php:428
+#: index.php:442
 msgid "toggle mobile"
 msgstr "мобильная версия"
 
-#: ../../view/theme/cleanzero/config.php:82
-#: ../../view/theme/dispy/config.php:72 ../../view/theme/quattro/config.php:66
-#: ../../view/theme/diabook/config.php:150 ../../view/theme/vier/config.php:55
-#: ../../view/theme/duepuntozero/config.php:61
-msgid "Theme settings"
-msgstr "Настройки темы"
-
-#: ../../view/theme/cleanzero/config.php:83
+#: view/theme/cleanzero/config.php:83
 msgid "Set resize level for images in posts and comments (width and height)"
-msgstr "Установить уровень изменения размера изображений в постах и ​​комментариях (ширина и высота)"
+msgstr ""
+"Установить уровень изменения размера изображений в постах и ​​комментариях "
+"(ширина и высота)"
 
-#: ../../view/theme/cleanzero/config.php:84
-#: ../../view/theme/dispy/config.php:73
-#: ../../view/theme/diabook/config.php:151
+#: view/theme/cleanzero/config.php:84 view/theme/dispy/config.php:73
+#: view/theme/diabook/config.php:151
 msgid "Set font-size for posts and comments"
 msgstr "Установить шрифт-размер для постов и комментариев"
 
-#: ../../view/theme/cleanzero/config.php:85
+#: view/theme/cleanzero/config.php:85
 msgid "Set theme width"
 msgstr "Установить ширину темы"
 
-#: ../../view/theme/cleanzero/config.php:86
-#: ../../view/theme/quattro/config.php:68
+#: view/theme/cleanzero/config.php:86 view/theme/quattro/config.php:68
 msgid "Color scheme"
 msgstr "Цветовая схема"
 
-#: ../../view/theme/dispy/config.php:74
-#: ../../view/theme/diabook/config.php:152
+#: view/theme/dispy/config.php:74 view/theme/diabook/config.php:152
 msgid "Set line-height for posts and comments"
 msgstr "Установить высоту строки для постов и комментариев"
 
-#: ../../view/theme/dispy/config.php:75
+#: view/theme/dispy/config.php:75
 msgid "Set colour scheme"
 msgstr "Установить цветовую схему"
 
-#: ../../view/theme/quattro/config.php:67
+#: view/theme/quattro/config.php:67
 msgid "Alignment"
 msgstr "Выравнивание"
 
-#: ../../view/theme/quattro/config.php:67
+#: view/theme/quattro/config.php:67
 msgid "Left"
 msgstr ""
 
-#: ../../view/theme/quattro/config.php:67
+#: view/theme/quattro/config.php:67
 msgid "Center"
 msgstr "Центр"
 
-#: ../../view/theme/quattro/config.php:69
+#: view/theme/quattro/config.php:69
 msgid "Posts font size"
 msgstr "Размер шрифта постов"
 
-#: ../../view/theme/quattro/config.php:70
+#: view/theme/quattro/config.php:70
 msgid "Textareas font size"
 msgstr "Размер шрифта текстовых полей"
 
-#: ../../view/theme/diabook/config.php:153
+#: view/theme/diabook/config.php:153
 msgid "Set resolution for middle column"
 msgstr "Установить разрешение для средней колонки"
 
-#: ../../view/theme/diabook/config.php:154
+#: view/theme/diabook/config.php:154
 msgid "Set color scheme"
 msgstr "Установить цветовую схему"
 
-#: ../../view/theme/diabook/config.php:155
+#: view/theme/diabook/config.php:155
 msgid "Set zoomfactor for Earth Layer"
 msgstr "Установить масштаб карты"
 
-#: ../../view/theme/diabook/config.php:156
-#: ../../view/theme/diabook/theme.php:585
+#: view/theme/diabook/config.php:156 view/theme/diabook/theme.php:585
 msgid "Set longitude (X) for Earth Layers"
 msgstr "Установить длину (X) карты"
 
-#: ../../view/theme/diabook/config.php:157
-#: ../../view/theme/diabook/theme.php:586
+#: view/theme/diabook/config.php:157 view/theme/diabook/theme.php:586
 msgid "Set latitude (Y) for Earth Layers"
 msgstr "Установить ширину (Y) карты"
 
-#: ../../view/theme/diabook/config.php:158
-#: ../../view/theme/diabook/theme.php:130
-#: ../../view/theme/diabook/theme.php:544
-#: ../../view/theme/diabook/theme.php:624
+#: view/theme/diabook/config.php:158 view/theme/diabook/theme.php:130
+#: view/theme/diabook/theme.php:544 view/theme/diabook/theme.php:624
+#: view/theme/vier/config.php:111
 msgid "Community Pages"
 msgstr "Страницы сообщества"
 
-#: ../../view/theme/diabook/config.php:159
-#: ../../view/theme/diabook/theme.php:579
-#: ../../view/theme/diabook/theme.php:625
+#: view/theme/diabook/config.php:159 view/theme/diabook/theme.php:579
+#: view/theme/diabook/theme.php:625
 msgid "Earth Layers"
 msgstr "Карта"
 
-#: ../../view/theme/diabook/config.php:160
-#: ../../view/theme/diabook/theme.php:391
-#: ../../view/theme/diabook/theme.php:626
+#: view/theme/diabook/config.php:160 view/theme/diabook/theme.php:391
+#: view/theme/diabook/theme.php:626 view/theme/vier/config.php:112
+#: view/theme/vier/theme.php:156
 msgid "Community Profiles"
 msgstr "Профили сообщества"
 
-#: ../../view/theme/diabook/config.php:161
-#: ../../view/theme/diabook/theme.php:599
-#: ../../view/theme/diabook/theme.php:627
+#: view/theme/diabook/config.php:161 view/theme/diabook/theme.php:599
+#: view/theme/diabook/theme.php:627 view/theme/vier/config.php:113
 msgid "Help or @NewHere ?"
 msgstr "Помощь"
 
-#: ../../view/theme/diabook/config.php:162
-#: ../../view/theme/diabook/theme.php:606
-#: ../../view/theme/diabook/theme.php:628
+#: view/theme/diabook/config.php:162 view/theme/diabook/theme.php:606
+#: view/theme/diabook/theme.php:628 view/theme/vier/config.php:114
+#: view/theme/vier/theme.php:377
 msgid "Connect Services"
 msgstr "Подключить службы"
 
-#: ../../view/theme/diabook/config.php:163
-#: ../../view/theme/diabook/theme.php:523
-#: ../../view/theme/diabook/theme.php:629
+#: view/theme/diabook/config.php:163 view/theme/diabook/theme.php:523
+#: view/theme/diabook/theme.php:629 view/theme/vier/config.php:115
+#: view/theme/vier/theme.php:203
 msgid "Find Friends"
 msgstr "Найти друзей"
 
-#: ../../view/theme/diabook/config.php:164
-#: ../../view/theme/diabook/theme.php:412
-#: ../../view/theme/diabook/theme.php:630
+#: view/theme/diabook/config.php:164 view/theme/diabook/theme.php:412
+#: view/theme/diabook/theme.php:630 view/theme/vier/config.php:116
+#: view/theme/vier/theme.php:185
 msgid "Last users"
 msgstr "Последние пользователи"
 
-#: ../../view/theme/diabook/config.php:165
-#: ../../view/theme/diabook/theme.php:486
-#: ../../view/theme/diabook/theme.php:631
+#: view/theme/diabook/config.php:165 view/theme/diabook/theme.php:486
+#: view/theme/diabook/theme.php:631
 msgid "Last photos"
 msgstr "Последние фото"
 
-#: ../../view/theme/diabook/config.php:166
-#: ../../view/theme/diabook/theme.php:441
-#: ../../view/theme/diabook/theme.php:632
+#: view/theme/diabook/config.php:166 view/theme/diabook/theme.php:441
+#: view/theme/diabook/theme.php:632
 msgid "Last likes"
 msgstr "Последние likes"
 
-#: ../../view/theme/diabook/theme.php:125
+#: view/theme/diabook/theme.php:125
 msgid "Your contacts"
 msgstr "Ваши контакты"
 
-#: ../../view/theme/diabook/theme.php:128
+#: view/theme/diabook/theme.php:128
 msgid "Your personal photos"
 msgstr "Ваши личные фотографии"
 
-#: ../../view/theme/diabook/theme.php:524
+#: view/theme/diabook/theme.php:524 view/theme/vier/theme.php:204
 msgid "Local Directory"
 msgstr "Локальный каталог"
 
-#: ../../view/theme/diabook/theme.php:584
+#: view/theme/diabook/theme.php:584
 msgid "Set zoomfactor for Earth Layers"
 msgstr "Установить масштаб карты"
 
-#: ../../view/theme/diabook/theme.php:622
+#: view/theme/diabook/theme.php:622
 msgid "Show/hide boxes at right-hand column:"
 msgstr "Показать/скрыть блоки в правой колонке:"
 
-#: ../../view/theme/vier/config.php:56
+#: view/theme/vier/config.php:64
+msgid "Comma separated list of helper forums"
+msgstr ""
+
+#: view/theme/vier/config.php:110
 msgid "Set style"
 msgstr ""
 
-#: ../../view/theme/duepuntozero/config.php:45
+#: view/theme/vier/theme.php:295
+msgid "Quick Start"
+msgstr "Быстрый запуск"
+
+#: view/theme/duepuntozero/config.php:45
 msgid "greenzero"
 msgstr ""
 
-#: ../../view/theme/duepuntozero/config.php:46
+#: view/theme/duepuntozero/config.php:46
 msgid "purplezero"
 msgstr ""
 
-#: ../../view/theme/duepuntozero/config.php:47
+#: view/theme/duepuntozero/config.php:47
 msgid "easterbunny"
 msgstr ""
 
-#: ../../view/theme/duepuntozero/config.php:48
+#: view/theme/duepuntozero/config.php:48
 msgid "darkzero"
 msgstr ""
 
-#: ../../view/theme/duepuntozero/config.php:49
+#: view/theme/duepuntozero/config.php:49
 msgid "comix"
 msgstr ""
 
-#: ../../view/theme/duepuntozero/config.php:50
+#: view/theme/duepuntozero/config.php:50
 msgid "slackr"
 msgstr ""
 
-#: ../../view/theme/duepuntozero/config.php:62
+#: view/theme/duepuntozero/config.php:62
 msgid "Variations"
 msgstr ""
diff --git a/view/ru/strings.php b/view/ru/strings.php
index 09755ca7bb..81600c48f3 100644
--- a/view/ru/strings.php
+++ b/view/ru/strings.php
@@ -2,13 +2,16 @@
 
 if(! function_exists("string_plural_select_ru")) {
 function string_plural_select_ru($n){
-	return ($n%10==1 && $n%100!=11 ? 0 : $n%10>=2 && $n%10<=4 && ($n%100<10 || $n%100>=20) ? 1 : 2);;
+	return ;
 }}
 ;
+$a->strings["Network:"] = "Сеть:";
+$a->strings["Forum"] = "Форум";
 $a->strings["%d contact edited."] = array(
-	0 => "%d контакт изменён.",
-	1 => "%d контакты изменены",
-	2 => "%d контакты изменены",
+	0 => "",
+	1 => "",
+	2 => "",
+	3 => "",
 );
 $a->strings["Could not access contact record."] = "Не удалось получить доступ к записи контакта.";
 $a->strings["Could not locate selected profile."] = "Не удалось найти выбранный профиль.";
@@ -34,26 +37,12 @@ $a->strings["(Update was successful)"] = "(Обновление было усп
 $a->strings["(Update was not successful)"] = "(Обновление не удалось)";
 $a->strings["Suggest friends"] = "Предложить друзей";
 $a->strings["Network type: %s"] = "Сеть: %s";
-$a->strings["%d contact in common"] = array(
-	0 => "%d Контакт",
-	1 => "%d Контактов",
-	2 => "%d Контактов",
-);
-$a->strings["View all contacts"] = "Показать все контакты";
-$a->strings["Unblock"] = "Разблокировать";
-$a->strings["Block"] = "Заблокировать";
-$a->strings["Toggle Blocked status"] = "Изменить статус блокированности (заблокировать/разблокировать)";
-$a->strings["Unignore"] = "Не игнорировать";
-$a->strings["Ignore"] = "Игнорировать";
-$a->strings["Toggle Ignored status"] = "Изменить статус игнорирования";
-$a->strings["Unarchive"] = "Разархивировать";
-$a->strings["Archive"] = "Архивировать";
-$a->strings["Toggle Archive status"] = "Сменить статус архивации (архивирова/не архивировать)";
-$a->strings["Repair"] = "Восстановить";
-$a->strings["Advanced Contact Settings"] = "Дополнительные Настройки Контакта";
 $a->strings["Communications lost with this contact!"] = "Связь с контактом утеряна!";
-$a->strings["Contact Editor"] = "Редактор контакта";
-$a->strings["Submit"] = "Подтвердить";
+$a->strings["Fetch further information for feeds"] = "";
+$a->strings["Disabled"] = "Отключенный";
+$a->strings["Fetch information"] = "";
+$a->strings["Fetch information and keywords"] = "";
+$a->strings["Submit"] = "Добавить";
 $a->strings["Profile Visibility"] = "Видимость профиля";
 $a->strings["Please choose the profile you would like to display to %s when viewing your profile securely."] = "Пожалуйста, выберите профиль, который вы хотите отображать %s, когда просмотр вашего профиля безопасен.";
 $a->strings["Contact Information / Notes"] = "Информация о контакте / Заметки";
@@ -67,6 +56,11 @@ $a->strings["Delete contact"] = "Удалить контакт";
 $a->strings["Last update:"] = "Последнее обновление: ";
 $a->strings["Update public posts"] = "Обновить публичные сообщения";
 $a->strings["Update now"] = "Обновить сейчас";
+$a->strings["Connect/Follow"] = "Подключиться/Следовать";
+$a->strings["Unblock"] = "Разблокировать";
+$a->strings["Block"] = "Заблокировать";
+$a->strings["Unignore"] = "Не игнорировать";
+$a->strings["Ignore"] = "Игнорировать";
 $a->strings["Currently blocked"] = "В настоящее время заблокирован";
 $a->strings["Currently ignored"] = "В настоящее время игнорируется";
 $a->strings["Currently archived"] = "В данный момент архивирован";
@@ -74,12 +68,12 @@ $a->strings["Hide this contact from others"] = "Скрыть этот конта
 $a->strings["Replies/likes to your public posts <strong>may</strong> still be visible"] = "Ответы/лайки ваших публичных сообщений <strong>будут</strong> видимы.";
 $a->strings["Notification for new posts"] = "";
 $a->strings["Send a notification of every new post of this contact"] = "";
-$a->strings["Fetch further information for feeds"] = "";
-$a->strings["Disabled"] = "";
-$a->strings["Fetch information"] = "";
-$a->strings["Fetch information and keywords"] = "";
 $a->strings["Blacklisted keywords"] = "";
 $a->strings["Comma separated list of keywords that should not be converted to hashtags, when \"Fetch information and keywords\" is selected"] = "";
+$a->strings["Profile URL"] = "URL профиля";
+$a->strings["Location:"] = "Откуда:";
+$a->strings["About:"] = "О себе:";
+$a->strings["Tags:"] = "Ключевые слова: ";
 $a->strings["Suggestions"] = "Предложения";
 $a->strings["Suggest potential friends"] = "Предложить потенциального знакомого";
 $a->strings["All Contacts"] = "Все контакты";
@@ -94,16 +88,30 @@ $a->strings["Archived"] = "Архивированные";
 $a->strings["Only show archived contacts"] = "Показывать только архивные контакты";
 $a->strings["Hidden"] = "Скрытые";
 $a->strings["Only show hidden contacts"] = "Показывать только скрытые контакты";
-$a->strings["Mutual Friendship"] = "Взаимная дружба";
-$a->strings["is a fan of yours"] = "является вашим поклонником";
-$a->strings["you are a fan of"] = "Вы - поклонник";
-$a->strings["Edit contact"] = "Редактировать контакт";
 $a->strings["Contacts"] = "Контакты";
 $a->strings["Search your contacts"] = "Поиск ваших контактов";
 $a->strings["Finding: "] = "Результат поиска: ";
 $a->strings["Find"] = "Найти";
 $a->strings["Update"] = "Обновление";
+$a->strings["Archive"] = "Архивировать";
+$a->strings["Unarchive"] = "Разархивировать";
 $a->strings["Delete"] = "Удалить";
+$a->strings["Status"] = "Посты";
+$a->strings["Status Messages and Posts"] = "Ваши посты";
+$a->strings["Profile"] = "Информация";
+$a->strings["Profile Details"] = "Информация о вас";
+$a->strings["View all contacts"] = "Показать все контакты";
+$a->strings["Common Friends"] = "Общие друзья";
+$a->strings["View all common friends"] = "";
+$a->strings["Repair"] = "Восстановить";
+$a->strings["Advanced Contact Settings"] = "Дополнительные Настройки Контакта";
+$a->strings["Toggle Blocked status"] = "Изменить статус блокированности (заблокировать/разблокировать)";
+$a->strings["Toggle Ignored status"] = "Изменить статус игнорирования";
+$a->strings["Toggle Archive status"] = "Сменить статус архивации (архивирова/не архивировать)";
+$a->strings["Mutual Friendship"] = "Взаимная дружба";
+$a->strings["is a fan of yours"] = "является вашим поклонником";
+$a->strings["you are a fan of"] = "Вы - поклонник";
+$a->strings["Edit contact"] = "Редактировать контакт";
 $a->strings["No profile"] = "Нет профиля";
 $a->strings["Manage Identities and/or Pages"] = "Управление идентификацией и / или страницами";
 $a->strings["Toggle between different identities or community/group pages which share your account details or which you have been granted \"manage\" permissions"] = "";
@@ -112,7 +120,6 @@ $a->strings["Post successful."] = "Успешно добавлено.";
 $a->strings["Permission denied"] = "Доступ запрещен";
 $a->strings["Invalid profile identifier."] = "Недопустимый идентификатор профиля.";
 $a->strings["Profile Visibility Editor"] = "Редактор видимости профиля";
-$a->strings["Profile"] = "Профиль";
 $a->strings["Click on a contact to add or remove."] = "Нажмите на контакт, чтобы добавить или удалить.";
 $a->strings["Visible To"] = "Видимый для";
 $a->strings["All Contacts (with secure profile access)"] = "Все контакты (с безопасным доступом к профилю)";
@@ -137,9 +144,6 @@ $a->strings["Edit your <strong>default</strong> profile to your liking. Review t
 $a->strings["Profile Keywords"] = "Ключевые слова профиля";
 $a->strings["Set some public keywords for your default profile which describe your interests. We may be able to find other people with similar interests and suggest friendships."] = "Установите некоторые публичные ключевые слова для вашего профиля по умолчанию, которые описывают ваши интересы. Мы можем быть в состоянии найти других людей со схожими интересами и предложить дружбу.";
 $a->strings["Connecting"] = "Подключение";
-$a->strings["Facebook"] = "Facebook";
-$a->strings["Authorise the Facebook Connector if you currently have a Facebook account and we will (optionally) import all your Facebook friends and conversations."] = "Авторизуйте Facebook Connector , если у вас уже есть аккаунт на Facebook, и мы (по желанию) импортируем всех ваших друзей и беседы с Facebook.";
-$a->strings["<em>If</em> this is your own personal server, installing the Facebook addon may ease your transition to the free social web."] = "<em>Если</em> это ваш личный сервер, установите дополнение Facebook, это может облегчить ваш переход на свободную социальную сеть.";
 $a->strings["Importing Emails"] = "Импортирование Email-ов";
 $a->strings["Enter your email access information on your Connector Settings page if you wish to import and interact with friends or mailing lists from your email INBOX"] = "Введите информацию о доступе к вашему email на странице настроек вашего коннектора, если вы хотите импортировать, и общаться с друзьями или получать рассылки на ваш ящик электронной почты";
 $a->strings["Go to Your Contacts Page"] = "Перейти на страницу ваших контактов";
@@ -164,7 +168,7 @@ $a->strings["Profile Photos"] = "Фотографии профиля";
 $a->strings["Image size reduction [%s] failed."] = "Уменьшение размера изображения [%s] не удалось.";
 $a->strings["Shift-reload the page or clear browser cache if the new photo does not display immediately."] = "Перезагрузите страницу с зажатой клавишей \"Shift\" для того, чтобы увидеть свое новое фото немедленно.";
 $a->strings["Unable to process image"] = "Не удается обработать изображение";
-$a->strings["Image exceeds size limit of %d"] = "Изображение превышает предельный размер %d";
+$a->strings["Image exceeds size limit of %s"] = "";
 $a->strings["Unable to process image."] = "Невозможно обработать фото.";
 $a->strings["Upload File:"] = "Загрузить файл:";
 $a->strings["Select a profile:"] = "Выбрать этот профиль:";
@@ -184,9 +188,28 @@ $a->strings["Tag removed"] = "Ключевое слово удалено";
 $a->strings["Remove Item Tag"] = "Удалить ключевое слово";
 $a->strings["Select a tag to remove: "] = "Выберите ключевое слово для удаления: ";
 $a->strings["Remove"] = "Удалить";
+$a->strings["Subscribing to OStatus contacts"] = "";
+$a->strings["No contact provided."] = "";
+$a->strings["Couldn't fetch information for contact."] = "";
+$a->strings["Couldn't fetch friends for contact."] = "";
+$a->strings["Done"] = "Готово";
+$a->strings["success"] = "удачно";
+$a->strings["failed"] = "неудача";
+$a->strings["ignored"] = "";
+$a->strings["Keep this window open until done."] = "";
 $a->strings["Save to Folder:"] = "Сохранить в папку:";
 $a->strings["- select -"] = "- выбрать -";
 $a->strings["Save"] = "Сохранить";
+$a->strings["Submit Request"] = "Отправить запрос";
+$a->strings["You already added this contact."] = "";
+$a->strings["Diaspora support isn't enabled. Contact can't be added."] = "";
+$a->strings["OStatus support is disabled. Contact can't be added."] = "";
+$a->strings["The network type couldn't be detected. Contact can't be added."] = "";
+$a->strings["Please answer the following:"] = "Пожалуйста, ответьте следующее:";
+$a->strings["Does %s know you?"] = "%s знает вас?";
+$a->strings["No"] = "Нет";
+$a->strings["Add a personal note:"] = "Добавить личную заметку:";
+$a->strings["Your Identity Address:"] = "Ваш идентификационный адрес:";
 $a->strings["Contact added"] = "Контакт добавлен";
 $a->strings["Unable to locate original post."] = "Не удалось найти оригинальный пост.";
 $a->strings["Empty post discarded."] = "Пустое сообщение отбрасывается.";
@@ -207,6 +230,7 @@ $a->strings["Group removed."] = "Группа удалена.";
 $a->strings["Unable to remove group."] = "Не удается удалить группу.";
 $a->strings["Group Editor"] = "Редактор групп";
 $a->strings["Members"] = "Участники";
+$a->strings["Group is empty"] = "Группа пуста";
 $a->strings["You must be logged in to use addons. "] = "Вы должны войти в систему, чтобы использовать аддоны.";
 $a->strings["Applications"] = "Приложения";
 $a->strings["No installed applications."] = "Нет установленных приложений.";
@@ -233,6 +257,8 @@ $a->strings["[Name Withheld]"] = "[Имя не разглашается]";
 $a->strings["%1\$s has joined %2\$s"] = "%1\$s присоединился %2\$s";
 $a->strings["Requested profile is not available."] = "Запрашиваемый профиль недоступен.";
 $a->strings["Tips for New Members"] = "Советы для новых участников";
+$a->strings["Do you really want to delete this video?"] = "";
+$a->strings["Delete Video"] = "Удалить видео";
 $a->strings["No videos selected"] = "Видео не выбрано";
 $a->strings["Access to this item is restricted."] = "Доступ к этому пункту ограничен.";
 $a->strings["View Video"] = "Просмотреть видео";
@@ -243,6 +269,7 @@ $a->strings["%1\$s tagged %2\$s's %3\$s with %4\$s"] = "%1\$s tagged %2\$s's %3\
 $a->strings["Friend suggestion sent."] = "Приглашение в друзья отправлено.";
 $a->strings["Suggest Friends"] = "Предложить друзей";
 $a->strings["Suggest a friend for %s"] = "Предложить друга для %s.";
+$a->strings["Invalid request."] = "Неверный запрос.";
 $a->strings["No valid account found."] = "Не найдено действительного аккаунта.";
 $a->strings["Password reset request issued. Check your email."] = "Запрос на сброс пароля принят. Проверьте вашу электронную почту.";
 $a->strings["\n\t\tDear %1\$s,\n\t\t\tA request was recently received at \"%2\$s\" to reset your account\n\t\tpassword. In order to confirm this request, please select the verification link\n\t\tbelow or paste it into your web browser address bar.\n\n\t\tIf you did NOT request this change, please DO NOT follow the link\n\t\tprovided and ignore and/or delete this email.\n\n\t\tYour password will not be changed unless we can verify that you\n\t\tissued this request."] = "";
@@ -262,26 +289,16 @@ $a->strings["Forgot your Password?"] = "Забыли пароль?";
 $a->strings["Enter your email address and submit to have your password reset. Then check your email for further instructions."] = "Введите адрес электронной почты и подтвердите, что вы хотите сбросить ваш пароль. Затем проверьте свою электронную почту для получения дальнейших инструкций.";
 $a->strings["Nickname or Email: "] = "Ник или E-mail: ";
 $a->strings["Reset"] = "Сброс";
-$a->strings["%1\$s likes %2\$s's %3\$s"] = "%1\$s нравится %3\$s от %2\$s ";
-$a->strings["%1\$s doesn't like %2\$s's %3\$s"] = "%1\$s не нравится %3\$s от %2\$s ";
 $a->strings["{0} wants to be your friend"] = "{0} хочет стать Вашим другом";
 $a->strings["{0} sent you a message"] = "{0} отправил Вам сообщение";
 $a->strings["{0} requested registration"] = "{0} требуемая регистрация";
-$a->strings["{0} commented %s's post"] = "{0} прокомментировал сообщение от %s";
-$a->strings["{0} liked %s's post"] = "{0} нравится сообщение от %s";
-$a->strings["{0} disliked %s's post"] = "{0} не нравится сообщение от %s";
-$a->strings["{0} is now friends with %s"] = "{0} теперь друзья с %s";
-$a->strings["{0} posted"] = "{0} опубликовано";
-$a->strings["{0} tagged %s's post with #%s"] = "{0} пометил сообщение %s с #%s";
-$a->strings["{0} mentioned you in a post"] = "{0} упоменул Вас в сообщение";
 $a->strings["No contacts."] = "Нет контактов.";
-$a->strings["View Contacts"] = "Просмотр контактов";
 $a->strings["Invalid request identifier."] = "Неверный идентификатор запроса.";
 $a->strings["Discard"] = "Отказаться";
 $a->strings["System"] = "Система";
-$a->strings["Network"] = "Сеть";
+$a->strings["Network"] = "Новости";
 $a->strings["Personal"] = "Персонал";
-$a->strings["Home"] = "Главная";
+$a->strings["Home"] = "Мой профиль";
 $a->strings["Introductions"] = "Запросы";
 $a->strings["Show Ignored Requests"] = "Показать проигнорированные запросы";
 $a->strings["Hide Ignored Requests"] = "Скрыть проигнорированные запросы";
@@ -294,12 +311,14 @@ $a->strings["Approve"] = "Одобрить";
 $a->strings["Claims to be known to you: "] = "Утверждения, о которых должно быть вам известно: ";
 $a->strings["yes"] = "да";
 $a->strings["no"] = "нет";
-$a->strings["Approve as: "] = "Утвердить как: ";
+$a->strings["Shall your connection be bidirectional or not? \"Friend\" implies that you allow to read and you subscribe to their posts. \"Fan/Admirer\" means that you allow to read but you do not want to read theirs. Approve as: "] = "";
+$a->strings["Shall your connection be bidirectional or not? \"Friend\" implies that you allow to read and you subscribe to their posts. \"Sharer\" means that you allow to read but you do not want to read theirs. Approve as: "] = "";
 $a->strings["Friend"] = "Друг";
 $a->strings["Sharer"] = "Участник";
 $a->strings["Fan/Admirer"] = "Фанат / Поклонник";
 $a->strings["Friend/Connect Request"] = "Запрос в друзья / на подключение";
 $a->strings["New Follower"] = "Новый фолловер";
+$a->strings["Gender:"] = "Пол:";
 $a->strings["No introductions."] = "Запросов нет.";
 $a->strings["Notifications"] = "Уведомления";
 $a->strings["%s liked %s's post"] = "%s нравится %s сообшение";
@@ -348,30 +367,31 @@ $a->strings["Upload photo"] = "Загрузить фото";
 $a->strings["Insert web link"] = "Вставить веб-ссылку";
 $a->strings["Please wait"] = "Пожалуйста, подождите";
 $a->strings["No messages."] = "Нет сообщений.";
+$a->strings["Message not available."] = "Сообщение не доступно.";
+$a->strings["Delete message"] = "Удалить сообщение";
+$a->strings["Delete conversation"] = "Удалить историю общения";
+$a->strings["No secure communications available. You <strong>may</strong> be able to respond from the sender's profile page."] = "Невозможно защищённое соединение. Вы <strong>имеете</strong> возможность ответить со страницы профиля отправителя.";
+$a->strings["Send Reply"] = "Отправить ответ";
 $a->strings["Unknown sender - %s"] = "Неизвестный отправитель - %s";
 $a->strings["You and %s"] = "Вы и %s";
 $a->strings["%s and You"] = "%s и Вы";
-$a->strings["Delete conversation"] = "Удалить историю общения";
 $a->strings["D, d M Y - g:i A"] = "D, d M Y - g:i A";
 $a->strings["%d message"] = array(
 	0 => "%d сообщение",
 	1 => "%d сообщений",
 	2 => "%d сообщений",
+	3 => "%d сообщений",
 );
-$a->strings["Message not available."] = "Сообщение не доступно.";
-$a->strings["Delete message"] = "Удалить сообщение";
-$a->strings["No secure communications available. You <strong>may</strong> be able to respond from the sender's profile page."] = "Невозможно защищённое соединение. Вы <strong>имеете</strong> возможность ответить со страницы профиля отправителя.";
-$a->strings["Send Reply"] = "Отправить ответ";
 $a->strings["[Embedded content - reload page to view]"] = "[Встроенное содержание - перезагрузите страницу для просмотра]";
 $a->strings["Contact settings applied."] = "Установки контакта приняты.";
 $a->strings["Contact update failed."] = "Обновление контакта неудачное.";
-$a->strings["Repair Contact Settings"] = "Восстановить установки контакта";
 $a->strings["<strong>WARNING: This is highly advanced</strong> and if you enter incorrect information your communications with this contact may stop working."] = "<strong>ВНИМАНИЕ: Это крайне важно!</strong> Если вы введете неверную информацию, ваша связь с этим контактом перестанет работать.";
 $a->strings["Please use your browser 'Back' button <strong>now</strong> if you are uncertain what to do on this page."] = "Пожалуйста, нажмите клавишу вашего браузера 'Back' или 'Назад' <strong>сейчас</strong>, если вы не уверены, что делаете на этой странице.";
-$a->strings["Return to contact editor"] = "Возврат к редактору контакта";
 $a->strings["No mirroring"] = "";
 $a->strings["Mirror as forwarded posting"] = "";
 $a->strings["Mirror as my own posting"] = "";
+$a->strings["Return to contact editor"] = "Возврат к редактору контакта";
+$a->strings["Refetch contact data"] = "";
 $a->strings["Name"] = "Имя";
 $a->strings["Account Nickname"] = "Ник аккаунта";
 $a->strings["@Tagname - overrides Name/Nickname"] = "";
@@ -387,9 +407,12 @@ $a->strings["Mark this contact as remote_self, this will cause friendica to repo
 $a->strings["Login"] = "Вход";
 $a->strings["The post was created"] = "";
 $a->strings["Access denied."] = "Доступ запрещен.";
-$a->strings["People Search"] = "Поиск людей";
+$a->strings["Connect"] = "Подключить";
+$a->strings["View Profile"] = "Просмотреть профиль";
+$a->strings["People Search - %s"] = "";
 $a->strings["No matches"] = "Нет соответствий";
 $a->strings["Photos"] = "Фото";
+$a->strings["Contact Photos"] = "Фотографии контакта";
 $a->strings["Files"] = "Файлы";
 $a->strings["Contacts who are not members of a group"] = "Контакты, которые не являются членами группы";
 $a->strings["Theme settings updated."] = "Настройки темы обновлены.";
@@ -397,14 +420,28 @@ $a->strings["Site"] = "Сайт";
 $a->strings["Users"] = "Пользователи";
 $a->strings["Plugins"] = "Плагины";
 $a->strings["Themes"] = "Темы";
+$a->strings["Additional features"] = "Дополнительные возможности";
 $a->strings["DB updates"] = "Обновление БД";
+$a->strings["Inspect Queue"] = "";
+$a->strings["Federation Statistics"] = "";
 $a->strings["Logs"] = "Журналы";
+$a->strings["View Logs"] = "Просмотр логов";
 $a->strings["probe address"] = "";
 $a->strings["check webfinger"] = "";
 $a->strings["Admin"] = "Администратор";
 $a->strings["Plugin Features"] = "Возможности плагина";
-$a->strings["diagnostics"] = "";
+$a->strings["diagnostics"] = "Диагностика";
 $a->strings["User registrations waiting for confirmation"] = "Регистрации пользователей, ожидающие подтверждения";
+$a->strings["This page offers you some numbers to the known part of the federated social network your Friendica node is part of. These numbers are not complete but only reflect the part of the network your node is aware of."] = "";
+$a->strings["The <em>Auto Discovered Contact Directory</em> feature is not enabled, it will improve the data displayed here."] = "";
+$a->strings["Administration"] = "Администрация";
+$a->strings["Currently this node is aware of %d nodes from the following platforms:"] = "";
+$a->strings["ID"] = "";
+$a->strings["Recipient Name"] = "";
+$a->strings["Recipient Profile"] = "";
+$a->strings["Created"] = "";
+$a->strings["Last Tried"] = "";
+$a->strings["This page lists the content of the queue for outgoing postings. These are postings the initial delivery failed for. They will be resend later and eventually deleted if the delivery fails permanently."] = "";
 $a->strings["Normal Account"] = "Обычный аккаунт";
 $a->strings["Soapbox Account"] = "Аккаунт Витрина";
 $a->strings["Community/Celebrity Account"] = "Аккаунт Сообщество / Знаменитость";
@@ -412,13 +449,13 @@ $a->strings["Automatic Friend Account"] = "\"Автоматический дру
 $a->strings["Blog Account"] = "Аккаунт блога";
 $a->strings["Private Forum"] = "Личный форум";
 $a->strings["Message queues"] = "Очереди сообщений";
-$a->strings["Administration"] = "Администрация";
 $a->strings["Summary"] = "Резюме";
 $a->strings["Registered users"] = "Зарегистрированные пользователи";
 $a->strings["Pending registrations"] = "Ожидающие регистрации";
 $a->strings["Version"] = "Версия";
 $a->strings["Active plugins"] = "Активные плагины";
 $a->strings["Can not parse base url. Must have at least <scheme>://<domain>"] = "Невозможно определить базовый URL. Он должен иметь следующий вид - <scheme>://<domain>";
+$a->strings["RINO2 needs mcrypt php extension to work."] = "Для функционирования RINO2 необходим пакет php5-mcrypt";
 $a->strings["Site settings updated."] = "Установки сайта обновлены.";
 $a->strings["No special theme for mobile devices"] = "Нет специальной темы для мобильных устройств";
 $a->strings["No community page"] = "";
@@ -429,6 +466,12 @@ $a->strings["Frequently"] = "Часто";
 $a->strings["Hourly"] = "Раз в час";
 $a->strings["Twice daily"] = "Два раза в день";
 $a->strings["Daily"] = "Ежедневно";
+$a->strings["Users, Global Contacts"] = "";
+$a->strings["Users, Global Contacts/fallback"] = "";
+$a->strings["One month"] = "Один месяц";
+$a->strings["Three months"] = "Три месяца";
+$a->strings["Half a year"] = "Пол года";
+$a->strings["One year"] = "Один год";
 $a->strings["Multi user instance"] = "Многопользовательский вид";
 $a->strings["Closed"] = "Закрыто";
 $a->strings["Requires approval"] = "Требуется подтверждение";
@@ -441,16 +484,20 @@ $a->strings["Registration"] = "Регистрация";
 $a->strings["File upload"] = "Загрузка файлов";
 $a->strings["Policies"] = "Политики";
 $a->strings["Advanced"] = "Расширенный";
+$a->strings["Auto Discovered Contact Directory"] = "";
 $a->strings["Performance"] = "Производительность";
 $a->strings["Relocate - WARNING: advanced function. Could make this server unreachable."] = "Переместить - ПРЕДУПРЕЖДЕНИЕ: расширеная функция. Может сделать этот сервер недоступным.";
 $a->strings["Site name"] = "Название сайта";
-$a->strings["Host name"] = "";
-$a->strings["Sender Email"] = "";
+$a->strings["Host name"] = "Имя хоста";
+$a->strings["Sender Email"] = "Системный Email";
+$a->strings["The email address your server shall use to send notification emails from."] = "Адрес с которого будут приходить письма пользователям.";
 $a->strings["Banner/Logo"] = "Баннер/Логотип";
 $a->strings["Shortcut icon"] = "";
+$a->strings["Link to an icon that will be used for browsers."] = "";
 $a->strings["Touch icon"] = "";
+$a->strings["Link to an icon that will be used for tablets and mobiles."] = "";
 $a->strings["Additional Info"] = "Дополнительная информация";
-$a->strings["For public servers: you can add additional information here that will be listed at dir.friendica.com/siteinfo."] = "Для публичных серверов: вы можете добавить дополнительную информацию, которая будет перечислена в dir.friendica.com/siteinfo.";
+$a->strings["For public servers: you can add additional information here that will be listed at %s/siteinfo."] = "";
 $a->strings["System language"] = "Системный язык";
 $a->strings["System theme"] = "Системная тема";
 $a->strings["Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"] = "Тема системы по умолчанию - может быть переопределена пользователем - <a href='#' id='cnftheme'>изменить настройки темы</a>";
@@ -458,7 +505,7 @@ $a->strings["Mobile system theme"] = "Мобильная тема системы
 $a->strings["Theme for mobile devices"] = "Тема для мобильных устройств";
 $a->strings["SSL link policy"] = "Политика SSL";
 $a->strings["Determines whether generated links should be forced to use SSL"] = "Ссылки должны быть вынуждены использовать SSL";
-$a->strings["Force SSL"] = "";
+$a->strings["Force SSL"] = "SSL принудительно";
 $a->strings["Force all Non-SSL requests to SSL - Attention: on some systems it could lead to endless loops."] = "";
 $a->strings["Old style 'Share'"] = "Старый стиль 'Share'";
 $a->strings["Deactivates the bbcode element 'share' for repeating items."] = "Отключение BBCode элемента 'share' для повторяющихся элементов.";
@@ -487,8 +534,8 @@ $a->strings["Block public"] = "Блокировать общественный 
 $a->strings["Check to block public access to all otherwise public personal pages on this site unless you are currently logged in."] = "Отметьте, чтобы заблокировать публичный доступ ко всем иным публичным персональным страницам на этом сайте, если вы не вошли на сайт.";
 $a->strings["Force publish"] = "Принудительная публикация";
 $a->strings["Check to force all profiles on this site to be listed in the site directory."] = "Отметьте, чтобы принудительно заставить все профили на этом сайте, быть перечислеными в каталоге сайта.";
-$a->strings["Global directory update URL"] = "URL обновления глобального каталога";
-$a->strings["URL to update the global directory. If this is not set, the global directory is completely unavailable to the application."] = "URL для обновления глобального каталога. Если он не установлен, глобальный каталог полностью недоступен для приложения.";
+$a->strings["Global directory URL"] = "";
+$a->strings["URL to the global directory. If this is not set, the global directory is completely unavailable to the application."] = "";
 $a->strings["Allow threaded items"] = "Разрешить темы в обсуждении";
 $a->strings["Allow infinite level threading for items on this site."] = "Разрешить бесконечный уровень для тем на этом сайте.";
 $a->strings["Private posts by default for new users"] = "Частные сообщения по умолчанию для новых пользователей";
@@ -517,6 +564,8 @@ $a->strings["Enable OStatus support"] = "Включить поддержку OSt
 $a->strings["Provide built-in OStatus (StatusNet, GNU Social etc.) compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed."] = "";
 $a->strings["OStatus conversation completion interval"] = "";
 $a->strings["How often shall the poller check for new entries in OStatus conversations? This can be a very ressource task."] = "Как часто процессы должны проверять наличие новых записей в OStatus разговорах? Это может быть очень ресурсоёмкой задачей.";
+$a->strings["OStatus support can only be enabled if threading is enabled."] = "";
+$a->strings["Diaspora support can't be enabled because Friendica was installed into a sub directory."] = "";
 $a->strings["Enable Diaspora support"] = "Включить поддержку Diaspora";
 $a->strings["Provide built-in Diaspora network compatibility."] = "Обеспечить встроенную поддержку сети Diaspora.";
 $a->strings["Only allow Friendica contacts"] = "Позвольть только  Friendica контакты";
@@ -533,6 +582,24 @@ $a->strings["Poll interval"] = "Интервал опроса";
 $a->strings["Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval."] = "Установить задержку фоновых процессов опросов путем ограничения количества секунд, чтобы уменьшить нагрузку на систему. Если 0, используется интервал доставки.";
 $a->strings["Maximum Load Average"] = "Средняя максимальная нагрузка";
 $a->strings["Maximum system load before delivery and poll processes are deferred - default 50."] = "Максимальная нагрузка на систему перед приостановкой процессов доставки и опросов - по умолчанию 50.";
+$a->strings["Maximum Load Average (Frontend)"] = "";
+$a->strings["Maximum system load before the frontend quits service - default 50."] = "";
+$a->strings["Maximum table size for optimization"] = "";
+$a->strings["Maximum table size (in MB) for the automatic optimization - default 100 MB. Enter -1 to disable it."] = "";
+$a->strings["Minimum level of fragmentation"] = "";
+$a->strings["Minimum fragmenation level to start the automatic optimization - default value is 30%."] = "";
+$a->strings["Periodical check of global contacts"] = "";
+$a->strings["If enabled, the global contacts are checked periodically for missing or outdated data and the vitality of the contacts and servers."] = "";
+$a->strings["Days between requery"] = "";
+$a->strings["Number of days after which a server is requeried for his contacts."] = "";
+$a->strings["Discover contacts from other servers"] = "";
+$a->strings["Periodically query other servers for contacts. You can choose between 'users': the users on the remote system, 'Global Contacts': active contacts that are known on the system. The fallback is meant for Redmatrix servers and older friendica servers, where global contacts weren't available. The fallback increases the server load, so the recommened setting is 'Users, Global Contacts'."] = "";
+$a->strings["Timeframe for fetching global contacts"] = "";
+$a->strings["When the discovery is activated, this value defines the timeframe for the activity of the global contacts that are fetched from other servers."] = "";
+$a->strings["Search the local directory"] = "";
+$a->strings["Search the local directory instead of the global directory. When searching locally, every search will be executed on the global directory in the background. This improves the search results when the search is repeated."] = "";
+$a->strings["Publish server information"] = "";
+$a->strings["If enabled, general server and usage data will be published. The data contains the name and version of the server, number of users with public profiles, number of posts and the activated protocols and connectors. See <a href='http://the-federation.info/'>the-federation.info</a> for details."] = "";
 $a->strings["Use MySQL full text engine"] = "Использовать систему полнотексного поиска MySQL";
 $a->strings["Activates the full text engine. Speeds up search - but can only search for four and more characters."] = "Активизирует систему полнотексного поиска. Ускоряет поиск - но может искать только при указании четырех и более символов.";
 $a->strings["Suppress Language"] = "";
@@ -540,13 +607,17 @@ $a->strings["Suppress language information in meta information about a posting."
 $a->strings["Suppress Tags"] = "";
 $a->strings["Suppress showing a list of hashtags at the end of the posting."] = "";
 $a->strings["Path to item cache"] = "Путь к элементам кэша";
+$a->strings["The item caches buffers generated bbcode and external images."] = "";
 $a->strings["Cache duration in seconds"] = "Время жизни кэша в секундах";
 $a->strings["How long should the cache files be hold? Default value is 86400 seconds (One day). To disable the item cache, set the value to -1."] = "";
 $a->strings["Maximum numbers of comments per post"] = "";
 $a->strings["How much comments should be shown for each post? Default value is 100."] = "";
 $a->strings["Path for lock file"] = "Путь к файлу блокировки";
+$a->strings["The lock file is used to avoid multiple pollers at one time. Only define a folder here."] = "";
 $a->strings["Temp path"] = "Временная папка";
+$a->strings["If you have a restricted system where the webserver can't access the system temp path, enter another path here."] = "";
 $a->strings["Base path to installation"] = "Путь для установки";
+$a->strings["If the system cannot detect the correct path to your installation, enter the correct path here. This setting should only be set if you are using a restricted system and symbolic links to your webroot."] = "";
 $a->strings["Disable picture proxy"] = "";
 $a->strings["The picture proxy increases performance and privacy. It shouldn't be used on systems with very low bandwith."] = "";
 $a->strings["Enable old style pager"] = "";
@@ -554,6 +625,11 @@ $a->strings["The old style pager has page numbers but slows down massively the p
 $a->strings["Only search in tags"] = "";
 $a->strings["On large systems the text search can slow down the system extremely."] = "";
 $a->strings["New base url"] = "Новый базовый url";
+$a->strings["Change base url for this server. Sends relocate message to all DFRN contacts of all users."] = "";
+$a->strings["RINO Encryption"] = "RINO шифрование";
+$a->strings["Encryption layer between nodes."] = "Слой шифрования между узлами.";
+$a->strings["Embedly API key"] = "";
+$a->strings["<a href='http://embed.ly'>Embedly</a> is used to fetch additional data for web pages. This is an optional parameter."] = "";
 $a->strings["Update has been marked successful"] = "Обновление было успешно отмечено";
 $a->strings["Database structure update %s was successfully applied."] = "";
 $a->strings["Executing of database structure update %s failed with error: %s"] = "";
@@ -574,11 +650,13 @@ $a->strings["%s user blocked/unblocked"] = array(
 	0 => "%s пользователь заблокирован/разблокирован",
 	1 => "%s пользователей заблокировано/разблокировано",
 	2 => "%s пользователей заблокировано/разблокировано",
+	3 => "%s пользователей заблокировано/разблокировано",
 );
 $a->strings["%s user deleted"] = array(
 	0 => "%s человек удален",
 	1 => "%s чел. удалено",
 	2 => "%s чел. удалено",
+	3 => "%s чел. удалено",
 );
 $a->strings["User '%s' deleted"] = "Пользователь '%s' удален";
 $a->strings["User '%s' unblocked"] = "Пользователь '%s' разблокирован";
@@ -612,8 +690,12 @@ $a->strings["Enable"] = "Включить";
 $a->strings["Toggle"] = "Переключить";
 $a->strings["Author: "] = "Автор:";
 $a->strings["Maintainer: "] = "Программа обслуживания: ";
+$a->strings["Reload active plugins"] = "";
+$a->strings["There are currently no plugins available on your node. You can find the official plugin repository at %1\$s and might find other interesting plugins in the open plugin registry at %2\$s"] = "";
 $a->strings["No themes found."] = "Темы не найдены.";
 $a->strings["Screenshot"] = "Скриншот";
+$a->strings["Reload active themes"] = "";
+$a->strings["No themes found on the system. They should be paced in %1\$s"] = "";
 $a->strings["[Experimental]"] = "[экспериментально]";
 $a->strings["[Unsupported]"] = "[Неподдерживаемое]";
 $a->strings["Log settings updated."] = "Настройки журнала обновлены.";
@@ -622,18 +704,19 @@ $a->strings["Enable Debugging"] = "Включить отладку";
 $a->strings["Log file"] = "Лог-файл";
 $a->strings["Must be writable by web server. Relative to your Friendica top-level directory."] = "Должно быть доступно для записи в веб-сервере. Относительно вашего Friendica каталога верхнего уровня.";
 $a->strings["Log level"] = "Уровень лога";
-$a->strings["Close"] = "Закрыть";
-$a->strings["FTP Host"] = "FTP хост";
-$a->strings["FTP Path"] = "Путь FTP";
-$a->strings["FTP User"] = "FTP пользователь";
-$a->strings["FTP Password"] = "FTP пароль";
-$a->strings["Search Results For:"] = "Результаты поиска для:";
+$a->strings["PHP logging"] = "PHP логирование";
+$a->strings["To enable logging of PHP errors and warnings you can add the following to the .htconfig.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."] = "";
+$a->strings["Off"] = "Выкл.";
+$a->strings["On"] = "Вкл.";
+$a->strings["Lock feature %s"] = "";
+$a->strings["Manage Additional Features"] = "";
+$a->strings["Search Results For: %s"] = "";
 $a->strings["Remove term"] = "Удалить элемент";
 $a->strings["Saved Searches"] = "запомненные поиски";
 $a->strings["add"] = "добавить";
-$a->strings["Commented Order"] = "Прокомментированный запрос";
+$a->strings["Commented Order"] = "Последние комментарии";
 $a->strings["Sort by Comment Date"] = "Сортировать по дате комментария";
-$a->strings["Posted Order"] = "Отправленный запрос";
+$a->strings["Posted Order"] = "Лента записей";
 $a->strings["Sort by Post Date"] = "Сортировать по дате отправки";
 $a->strings["Posts that mention or involve you"] = "";
 $a->strings["New"] = "Новый";
@@ -646,36 +729,77 @@ $a->strings["Warning: This group contains %s member from an insecure network."]
 	0 => "Внимание: Эта группа содержит %s участника с незащищенной сети.",
 	1 => "Внимание: Эта группа содержит %s участников с незащищенной сети.",
 	2 => "Внимание: Эта группа содержит %s участников с незащищенной сети.",
+	3 => "Внимание: Эта группа содержит %s участников с незащищенной сети.",
 );
 $a->strings["Private messages to this group are at risk of public disclosure."] = "Личные сообщения к этой группе находятся под угрозой обнародования.";
 $a->strings["No such group"] = "Нет такой группы";
-$a->strings["Group is empty"] = "Группа пуста";
-$a->strings["Group: "] = "Группа: ";
-$a->strings["Contact: "] = "Контакт: ";
+$a->strings["Group: %s"] = "Группа: %s";
 $a->strings["Private messages to this person are at risk of public disclosure."] = "Личные сообщения этому человеку находятся под угрозой обнародования.";
 $a->strings["Invalid contact."] = "Недопустимый контакт.";
-$a->strings["Friends of %s"] = "%s Друзья";
 $a->strings["No friends to display."] = "Нет друзей.";
+$a->strings["Event can not end before it has started."] = "";
 $a->strings["Event title and start time are required."] = "Название мероприятия и время начала обязательны для заполнения.";
+$a->strings["Sun"] = "Вс";
+$a->strings["Mon"] = "Пн";
+$a->strings["Tue"] = "Вт";
+$a->strings["Wed"] = "Ср";
+$a->strings["Thu"] = "Чт";
+$a->strings["Fri"] = "Пт";
+$a->strings["Sat"] = "Сб";
+$a->strings["Sunday"] = "Воскресенье";
+$a->strings["Monday"] = "Понедельник";
+$a->strings["Tuesday"] = "Вторник";
+$a->strings["Wednesday"] = "Среда";
+$a->strings["Thursday"] = "Четверг";
+$a->strings["Friday"] = "Пятница";
+$a->strings["Saturday"] = "Суббота";
+$a->strings["Jan"] = "Янв";
+$a->strings["Feb"] = "Фев";
+$a->strings["Mar"] = "Мрт";
+$a->strings["Apr"] = "Апр";
+$a->strings["May"] = "Май";
+$a->strings["Jun"] = "Июн";
+$a->strings["Jul"] = "Июл";
+$a->strings["Aug"] = "Авг";
+$a->strings["Sept"] = "Сен";
+$a->strings["Oct"] = "Окт";
+$a->strings["Nov"] = "Нбр";
+$a->strings["Dec"] = "Дек";
+$a->strings["January"] = "Январь";
+$a->strings["February"] = "Февраль";
+$a->strings["March"] = "Март";
+$a->strings["April"] = "Апрель";
+$a->strings["June"] = "Июнь";
+$a->strings["July"] = "Июль";
+$a->strings["August"] = "Август";
+$a->strings["September"] = "Сентябрь";
+$a->strings["October"] = "Октябрь";
+$a->strings["November"] = "Ноябрь";
+$a->strings["December"] = "Декабрь";
+$a->strings["today"] = "сегодня";
+$a->strings["month"] = "мес.";
+$a->strings["week"] = "неделя";
+$a->strings["day"] = "день";
 $a->strings["l, F j"] = "l, j F";
 $a->strings["Edit event"] = "Редактировать мероприятие";
-$a->strings["link to source"] = "ссылка на источник";
+$a->strings["link to source"] = "ссылка на сообщение";
 $a->strings["Events"] = "Мероприятия";
 $a->strings["Create New Event"] = "Создать новое мероприятие";
 $a->strings["Previous"] = "Назад";
 $a->strings["Next"] = "Далее";
-$a->strings["hour:minute"] = "час:минута";
 $a->strings["Event details"] = "Сведения о мероприятии";
-$a->strings["Format is %s %s. Starting date and Title are required."] = "Формат %s %s. Необхлдима дата старта и заголовок.";
+$a->strings["Starting date and Title are required."] = "";
 $a->strings["Event Starts:"] = "Начало мероприятия:";
 $a->strings["Required"] = "Требуется";
 $a->strings["Finish date/time is not known or not relevant"] = "Дата/время окончания не известны, или не указаны";
 $a->strings["Event Finishes:"] = "Окончание мероприятия:";
 $a->strings["Adjust for viewer timezone"] = "Настройка часового пояса";
 $a->strings["Description:"] = "Описание:";
-$a->strings["Location:"] = "Откуда:";
 $a->strings["Title:"] = "Титул:";
 $a->strings["Share this event"] = "Поделитесь этим мероприятием";
+$a->strings["Preview"] = "Предварительный просмотр";
+$a->strings["Credits"] = "";
+$a->strings["Friendica is a community project, that would not be possible without the help of many people. Here is a list of those who have contributed to the code or the translation of Friendica. Thank you all!"] = "";
 $a->strings["Select"] = "Выберите";
 $a->strings["View %s's profile @ %s"] = "Просмотреть профиль %s [@ %s]";
 $a->strings["%s from %s"] = "%s с %s";
@@ -684,11 +808,13 @@ $a->strings["%d comment"] = array(
 	0 => "%d комментарий",
 	1 => "%d комментариев",
 	2 => "%d комментариев",
+	3 => "%d комментариев",
 );
 $a->strings["comment"] = array(
 	0 => "",
 	1 => "",
 	2 => "комментарий",
+	3 => "комментарий",
 );
 $a->strings["show more"] = "показать больше";
 $a->strings["Private Message"] = "Личное сообщение";
@@ -699,7 +825,7 @@ $a->strings["dislike"] = "не нравитса";
 $a->strings["Share this"] = "Поделитесь этим";
 $a->strings["share"] = "делиться";
 $a->strings["This is you"] = "Это вы";
-$a->strings["Comment"] = "Комментарий";
+$a->strings["Comment"] = "Оставить комментарий";
 $a->strings["Bold"] = "Жирный";
 $a->strings["Italic"] = "Kурсивный";
 $a->strings["Underline"] = "Подчеркнутый";
@@ -708,7 +834,6 @@ $a->strings["Code"] = "Код";
 $a->strings["Image"] = "Изображение / Фото";
 $a->strings["Link"] = "Ссылка";
 $a->strings["Video"] = "Видео";
-$a->strings["Preview"] = "предварительный просмотр";
 $a->strings["Edit"] = "Редактировать";
 $a->strings["add star"] = "пометить";
 $a->strings["remove star"] = "убрать метку";
@@ -728,6 +853,7 @@ $a->strings["Could not create table."] = "Не удалось создать т
 $a->strings["Your Friendica site database has been installed."] = "База данных сайта установлена.";
 $a->strings["You may need to import the file \"database.sql\" manually using phpmyadmin or mysql."] = "Вам может понадобиться импортировать файл \"database.sql\" вручную с помощью PhpMyAdmin или MySQL.";
 $a->strings["Please see the file \"INSTALL.txt\"."] = "Пожалуйста, смотрите файл \"INSTALL.txt\".";
+$a->strings["Database already in use."] = "";
 $a->strings["System check"] = "Проверить систему";
 $a->strings["Check again"] = "Проверить еще раз";
 $a->strings["Database connection"] = "Подключение к базе данных";
@@ -743,7 +869,7 @@ $a->strings["Your account email address must match this in order to use the web
 $a->strings["Please select a default timezone for your website"] = "Пожалуйста, выберите часовой пояс по умолчанию для вашего сайта";
 $a->strings["Site settings"] = "Настройки сайта";
 $a->strings["Could not find a command line version of PHP in the web server PATH."] = "Не удалось найти PATH веб-сервера в установках PHP.";
-$a->strings["If you don't have a command line version of PHP installed on server, you will not be able to run background polling via cron. See <a href='http://friendica.com/node/27'>'Activating scheduled tasks'</a>"] = "Если на вашем сервере не установлена версия командной строки PHP, вы не будете иметь возможность запускать фоновые опросы через крон. См. <a href='http://friendica.com/node/27'> 'Активация запланированных задачах' </a>";
+$a->strings["If you don't have a command line version of PHP installed on server, you will not be able to run background polling via cron. See <a href='https://github.com/friendica/friendica/blob/master/doc/Install.md#set-up-the-poller'>'Setup the poller'</a>"] = "";
 $a->strings["PHP executable path"] = "PHP executable path";
 $a->strings["Enter full path to php executable. You can leave this blank to continue the installation."] = "Введите полный путь к исполняемому файлу PHP. Вы можете оставить это поле пустым, чтобы продолжить установку.";
 $a->strings["Command line PHP"] = "Command line PHP";
@@ -761,6 +887,7 @@ $a->strings["GD graphics PHP module"] = "GD graphics PHP модуль";
 $a->strings["OpenSSL PHP module"] = "OpenSSL PHP модуль";
 $a->strings["mysqli PHP module"] = "mysqli PHP модуль";
 $a->strings["mb_string PHP module"] = "mb_string PHP модуль";
+$a->strings["mcrypt PHP module"] = "";
 $a->strings["Apache mod_rewrite module"] = "Apache mod_rewrite module";
 $a->strings["Error: Apache webserver mod-rewrite module is required but not installed."] = "Ошибка: необходим модуль веб-сервера Apache mod-rewrite, но он не установлен.";
 $a->strings["Error: libCURL PHP module required but not installed."] = "Ошибка: необходим libCURL PHP модуль, но он не установлен.";
@@ -768,6 +895,9 @@ $a->strings["Error: GD graphics PHP module with JPEG support required but not in
 $a->strings["Error: openssl PHP module required but not installed."] = "Ошибка: необходим PHP модуль OpenSSL, но он не установлен.";
 $a->strings["Error: mysqli PHP module required but not installed."] = "Ошибка: необходим PHP модуль MySQLi, но он не установлен.";
 $a->strings["Error: mb_string PHP module required but not installed."] = "Ошибка: необходим PHP модуль mb_string, но он не установлен.";
+$a->strings["Error: mcrypt PHP module required but not installed."] = "";
+$a->strings["Function mcrypt_create_iv() is not defined. This is needed to enable RINO2 encryption layer."] = "";
+$a->strings["mcrypt_create_iv() function"] = "";
 $a->strings["The web installer needs to be able to create a file called \".htconfig.php\" in the top folder of your web server and it is unable to do so."] = "Веб-инсталлятору требуется создать файл с именем \". htconfig.php\" в верхней папке веб-сервера, но он не в состоянии это сделать.";
 $a->strings["This is most often a permission setting, as the web server may not be able to write files in your folder - even if you can."] = "Это наиболее частые параметры разрешений, когда веб-сервер не может записать файлы в папке - даже если вы можете.";
 $a->strings["At the end of this procedure, we will give you a text to save in a file named .htconfig.php in your Friendica top folder."] = "В конце этой процедуры, мы дадим вам текст, для сохранения в файле с именем .htconfig.php в корневой папке, где установлена Friendica.";
@@ -780,6 +910,8 @@ $a->strings["Note: as a security measure, you should give the web server write a
 $a->strings["view/smarty3 is writable"] = "view/smarty3 доступен для записи";
 $a->strings["Url rewrite in .htaccess is not working. Check your server configuration."] = "Url rewrite в .htaccess не работает. Проверьте конфигурацию вашего сервера..";
 $a->strings["Url rewrite is working"] = "Url rewrite работает";
+$a->strings["ImageMagick PHP extension is installed"] = "";
+$a->strings["ImageMagick supports GIF"] = "";
 $a->strings["The database configuration file \".htconfig.php\" could not be written. Please use the enclosed text to create a configuration file in your web server root."] = "Файл конфигурации базы данных \".htconfig.php\" не могла быть записан. Пожалуйста, используйте приложенный текст, чтобы создать конфигурационный файл в корневом каталоге веб-сервера.";
 $a->strings["<h1>What next</h1>"] = "<h1>Что далее</h1>";
 $a->strings["IMPORTANT: You will need to [manually] setup a scheduled task for the poller."] = "ВАЖНО: Вам нужно будет [вручную] установить запланированное задание для регистратора.";
@@ -795,21 +927,19 @@ $a->strings["%1\$s welcomes %2\$s"] = "%1\$s добро пожаловать %2\
 $a->strings["Welcome to %s"] = "Добро пожаловать на %s!";
 $a->strings["Sorry, maybe your upload is bigger than the PHP configuration allows"] = "";
 $a->strings["Or - did you try to upload an empty file?"] = "";
-$a->strings["File exceeds size limit of %d"] = "Файл превышает предельный размер %d";
+$a->strings["File exceeds size limit of %s"] = "";
 $a->strings["File upload failed."] = "Загрузка файла не удалась.";
-$a->strings["Profile Match"] = "Похожие профили";
 $a->strings["No keywords to match. Please add keywords to your default profile."] = "Нет соответствующих ключевых слов. Пожалуйста, добавьте ключевые слова для вашего профиля по умолчанию.";
 $a->strings["is interested in:"] = "интересуется:";
-$a->strings["Connect"] = "Подключить";
+$a->strings["Profile Match"] = "Похожие профили";
 $a->strings["link"] = "ссылка";
 $a->strings["Not available."] = "Недоступно.";
 $a->strings["Community"] = "Сообщество";
 $a->strings["No results."] = "Нет результатов.";
 $a->strings["everybody"] = "каждый";
-$a->strings["Additional features"] = "Дополнительные возможности";
-$a->strings["Display"] = "";
-$a->strings["Social Networks"] = "";
-$a->strings["Delegations"] = "";
+$a->strings["Display"] = "Внешний вид";
+$a->strings["Social Networks"] = "Социальные сети";
+$a->strings["Delegations"] = "Делегирование";
 $a->strings["Connected apps"] = "Подключенные приложения";
 $a->strings["Export personal data"] = "Экспорт личных данных";
 $a->strings["Remove account"] = "Удалить аккаунт";
@@ -843,14 +973,20 @@ $a->strings["No name"] = "Нет имени";
 $a->strings["Remove authorization"] = "Удалить авторизацию";
 $a->strings["No Plugin settings configured"] = "Нет сконфигурированных настроек плагина";
 $a->strings["Plugin Settings"] = "Настройки плагина";
-$a->strings["Off"] = "";
-$a->strings["On"] = "";
 $a->strings["Additional Features"] = "Дополнительные возможности";
+$a->strings["General Social Media Settings"] = "";
+$a->strings["Disable intelligent shortening"] = "";
+$a->strings["Normally the system tries to find the best link to add to shortened posts. If this option is enabled then every shortened post will always point to the original friendica post."] = "";
+$a->strings["Automatically follow any GNU Social (OStatus) followers/mentioners"] = "";
+$a->strings["If you receive a message from an unknown OStatus user, this option decides what to do. If it is checked, a new contact will be created for every unknown user."] = "";
+$a->strings["Your legacy GNU Social account"] = "";
+$a->strings["If you enter your old GNU Social/Statusnet account name here (in the format user@domain.tld), your contacts will be added automatically. The field will be emptied when done."] = "";
+$a->strings["Repair OStatus subscriptions"] = "";
 $a->strings["Built-in support for %s connectivity is %s"] = "Встроенная  поддержка для %s подключение %s";
 $a->strings["Diaspora"] = "Diaspora";
 $a->strings["enabled"] = "подключено";
 $a->strings["disabled"] = "отключено";
-$a->strings["StatusNet"] = "StatusNet";
+$a->strings["GNU Social (OStatus)"] = "";
 $a->strings["Email access is disabled on this site."] = "Доступ эл. почты отключен на этом сайте.";
 $a->strings["Email/Mailbox Setup"] = "Настройка эл. почты / почтового ящика";
 $a->strings["If you wish to communicate with email contacts using this service (optional), please specify how to connect to your mailbox."] = "Если вы хотите общаться с Email контактами, используя этот сервис (по желанию), пожалуйста, уточните, как подключиться к вашему почтовому ящику.";
@@ -871,14 +1007,17 @@ $a->strings["Display Settings"] = "Параметры дисплея";
 $a->strings["Display Theme:"] = "Показать тему:";
 $a->strings["Mobile Theme:"] = "Мобильная тема:";
 $a->strings["Update browser every xx seconds"] = "Обновление браузера каждые хх секунд";
-$a->strings["Minimum of 10 seconds, no maximum"] = "Минимум 10 секунд, максимума нет";
+$a->strings["Minimum of 10 seconds. Enter -1 to disable it."] = "";
 $a->strings["Number of items to display per page:"] = "Количество элементов, отображаемых на одной странице:";
 $a->strings["Maximum of 100 items"] = "Максимум 100 элементов";
 $a->strings["Number of items to display per page when viewed from mobile device:"] = "Количество элементов на странице, когда просмотр осуществляется с мобильных устройств:";
 $a->strings["Don't show emoticons"] = "не показывать emoticons";
+$a->strings["Calendar"] = "";
+$a->strings["Beginning of week:"] = "";
 $a->strings["Don't show notices"] = "";
 $a->strings["Infinite scroll"] = "Бесконечная прокрутка";
 $a->strings["Automatic updates only at the top of the network page"] = "";
+$a->strings["Theme settings"] = "Настройки темы";
 $a->strings["User Types"] = "";
 $a->strings["Community Types"] = "";
 $a->strings["Normal Account Page"] = "Стандартная страница аккаунта";
@@ -894,7 +1033,6 @@ $a->strings["Private forum - approved members only"] = "Приватный фо
 $a->strings["OpenID:"] = "OpenID:";
 $a->strings["(Optional) Allow this OpenID to login to this account."] = "(Необязательно) Разрешить этому OpenID входить в этот аккаунт";
 $a->strings["Publish your default profile in your local site directory?"] = "Публиковать ваш профиль по умолчанию в вашем локальном каталоге на сайте?";
-$a->strings["No"] = "Нет";
 $a->strings["Publish your default profile in the global social directory?"] = "Публиковать ваш профиль по умолчанию в глобальном социальном каталоге?";
 $a->strings["Hide your contact/friend list from viewers of your default profile?"] = "Скрывать ваш список контактов/друзей от посетителей вашего профиля по умолчанию?";
 $a->strings["Hide your profile details from unknown viewers?"] = "Скрыть данные профиля из неизвестных зрителей?";
@@ -904,7 +1042,7 @@ $a->strings["Allow friends to tag your posts?"] = "Разрешить друзь
 $a->strings["Allow us to suggest you as a potential friend to new members?"] = "Позвольть предлогать Вам потенциальных друзей?";
 $a->strings["Permit unknown people to send you private mail?"] = "Разрешить незнакомым людям отправлять вам личные сообщения?";
 $a->strings["Profile is <strong>not published</strong>."] = "Профиль <strong>не публикуется</strong>.";
-$a->strings["Your Identity Address is"] = "Ваш идентификационный адрес";
+$a->strings["Your Identity Address is <strong>'%s'</strong> or '%s'."] = "";
 $a->strings["Automatically expire posts after this many days:"] = "Автоматическое истекание срока действия сообщения после стольких дней:";
 $a->strings["If empty, posts will not expire. Expired posts will be deleted"] = "Если пусто, срок действия сообщений не будет ограничен. Сообщения с истекшим сроком действия будут удалены";
 $a->strings["Advanced expiration settings"] = "Настройки расширенного окончания срока действия";
@@ -915,7 +1053,7 @@ $a->strings["Expire starred posts:"] = "Срок хранения усеянны
 $a->strings["Expire photos:"] = "Срок хранения фотографий:";
 $a->strings["Only expire posts by others:"] = "Только устаревшие посты других:";
 $a->strings["Account Settings"] = "Настройки аккаунта";
-$a->strings["Password Settings"] = "Настройка пароля";
+$a->strings["Password Settings"] = "Смена пароля";
 $a->strings["New Password:"] = "Новый пароль:";
 $a->strings["Confirm:"] = "Подтвердите:";
 $a->strings["Leave password fields blank unless changing"] = "Оставьте поля пароля пустыми, если он не изменяется";
@@ -926,6 +1064,8 @@ $a->strings["Basic Settings"] = "Основные параметры";
 $a->strings["Full Name:"] = "Полное имя:";
 $a->strings["Email Address:"] = "Адрес электронной почты:";
 $a->strings["Your Timezone:"] = "Ваш часовой пояс:";
+$a->strings["Your Language:"] = "";
+$a->strings["Set the language we use to show you friendica interface and to send you emails"] = "";
 $a->strings["Default Post Location:"] = "Местонахождение по умолчанию:";
 $a->strings["Use Browser Location:"] = "Использовать определение местоположения браузером:";
 $a->strings["Security and Privacy Settings"] = "Параметры безопасности и конфиденциальности";
@@ -953,11 +1093,13 @@ $a->strings["You receive a private message"] = "Вы получаете личн
 $a->strings["You receive a friend suggestion"] = "Вы полулили предложение о добавлении в друзья";
 $a->strings["You are tagged in a post"] = "Вы отмечены в посте";
 $a->strings["You are poked/prodded/etc. in a post"] = "";
+$a->strings["Activate desktop notifications"] = "";
+$a->strings["Show desktop popup on new notifications"] = "";
 $a->strings["Text-only notification emails"] = "";
 $a->strings["Send text only notification emails, without the html part"] = "";
-$a->strings["Advanced Account/Page Type Settings"] = "Расширенные настройки типа аккаунта/страницы";
+$a->strings["Advanced Account/Page Type Settings"] = "Расширенные настройки учётной записи";
 $a->strings["Change the behaviour of this account for special situations"] = "Измените поведение этого аккаунта в специальных ситуациях";
-$a->strings["Relocate"] = "Переместить";
+$a->strings["Relocate"] = "Перемещение";
 $a->strings["If you have moved this profile from another server, and some of your contacts don't receive your updates, try pushing this button."] = "Если вы переместили эту анкету с другого сервера, и некоторые из ваших контактов не получили ваши обновления, попробуйте нажать эту кнопку.";
 $a->strings["Resend relocate message to contacts"] = "Отправить перемещённые сообщения контактам";
 $a->strings["This introduction has already been accepted."] = "Этот запрос был уже принят.";
@@ -968,6 +1110,7 @@ $a->strings["%d required parameter was not found at the given location"] = array
 	0 => "%d требуемый параметр не был найден в заданном месте",
 	1 => "%d требуемых параметров не были найдены в заданном месте",
 	2 => "%d требуемых параметров не были найдены в заданном месте",
+	3 => "%d требуемых параметров не были найдены в заданном месте",
 );
 $a->strings["Introduction complete."] = "Запрос создан.";
 $a->strings["Unrecoverable protocol error."] = "Неисправимая ошибка протокола.";
@@ -978,32 +1121,28 @@ $a->strings["Friends are advised to please try again in 24 hours."] = "Друз
 $a->strings["Invalid locator"] = "Недопустимый локатор";
 $a->strings["Invalid email address."] = "Неверный адрес электронной почты.";
 $a->strings["This account has not been configured for email. Request failed."] = "Этот аккаунт не настроен для электронной почты. Запрос не удался.";
-$a->strings["Unable to resolve your name at the provided location."] = "Не удается установить ваше имя на предложенном местоположении.";
 $a->strings["You have already introduced yourself here."] = "Вы уже ввели информацию о себе здесь.";
 $a->strings["Apparently you are already friends with %s."] = "Похоже, что вы уже друзья с %s.";
 $a->strings["Invalid profile URL."] = "Неверный URL профиля.";
 $a->strings["Disallowed profile URL."] = "Запрещенный URL профиля.";
 $a->strings["Your introduction has been sent."] = "Ваш запрос отправлен.";
+$a->strings["Remote subscription can't be done for your network. Please subscribe directly on your system."] = "";
 $a->strings["Please login to confirm introduction."] = "Для подтверждения запроса войдите пожалуйста с паролем.";
 $a->strings["Incorrect identity currently logged in. Please login to <strong>this</strong> profile."] = "Неверно идентифицирован вход. Пожалуйста, войдите в <strong>этот</strong> профиль.";
+$a->strings["Confirm"] = "Подтвердить";
 $a->strings["Hide this contact"] = "Скрыть этот контакт";
 $a->strings["Welcome home %s."] = "Добро пожаловать домой, %s!";
 $a->strings["Please confirm your introduction/connection request to %s."] = "Пожалуйста, подтвердите краткую информацию / запрос на подключение к %s.";
-$a->strings["Confirm"] = "Подтвердить";
 $a->strings["Please enter your 'Identity Address' from one of the following supported communications networks:"] = "Пожалуйста, введите ваш 'идентификационный адрес' одной из следующих поддерживаемых социальных сетей:";
-$a->strings["If you are not yet a member of the free social web, <a href=\"http://dir.friendica.com/siteinfo\">follow this link to find a public Friendica site and join us today</a>."] = "Если вы еще не являетесь членом свободной социальной сети, перейдите по <a href=\"http://dir.friendica.com/siteinfo\"> этой ссылке, чтобы найти публичный сервер Friendica и присоединиться к нам сейчас </a>.";
+$a->strings["If you are not yet a member of the free social web, <a href=\"%s/siteinfo\">follow this link to find a public Friendica site and join us today</a>."] = "";
 $a->strings["Friend/Connection Request"] = "Запрос в друзья / на подключение";
 $a->strings["Examples: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, testuser@identi.ca"] = "Примеры: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, testuser@identi.ca";
-$a->strings["Please answer the following:"] = "Пожалуйста, ответьте следующее:";
-$a->strings["Does %s know you?"] = "%s знает вас?";
-$a->strings["Add a personal note:"] = "Добавить личную заметку:";
 $a->strings["Friendica"] = "Friendica";
 $a->strings["StatusNet/Federated Social Web"] = "StatusNet / Federated Social Web";
 $a->strings[" - please do not use this form.  Instead, enter %s into your Diaspora search bar."] = "Участники сети Diaspora: пожалуйста, не пользуйтесь этой формой. Вместо этого введите  %s в строке поиска Diaspora";
-$a->strings["Your Identity Address:"] = "Ваш идентификационный адрес:";
-$a->strings["Submit Request"] = "Отправить запрос";
 $a->strings["Registration successful. Please check your email for further instructions."] = "Регистрация успешна. Пожалуйста, проверьте свою электронную почту для получения дальнейших инструкций.";
 $a->strings["Failed to send email message. Here your accout details:<br> login: %s<br> password: %s<br><br>You can change your password after login."] = "";
+$a->strings["Registration successful."] = "";
 $a->strings["Your registration can not be processed."] = "Ваша регистрация не может быть обработана.";
 $a->strings["Your registration is pending approval by the site owner."] = "Ваша регистрация в ожидании одобрения владельцем сайта.";
 $a->strings["This site has exceeded the number of allowed daily account registrations. Please try again tomorrow."] = "Этот сайт превысил допустимое количество ежедневных регистраций. Пожалуйста, повторите попытку завтра.";
@@ -1013,24 +1152,27 @@ $a->strings["Your OpenID (optional): "] = "Ваш OpenID (необязатель
 $a->strings["Include your profile in member directory?"] = "Включить ваш профиль в каталог участников?";
 $a->strings["Membership on this site is by invitation only."] = "Членство на сайте только по приглашению.";
 $a->strings["Your invitation ID: "] = "ID вашего приглашения:";
-$a->strings["Your Full Name (e.g. Joe Smith): "] = "Ваше полное имя (например, Joe Smith): ";
+$a->strings["Your Full Name (e.g. Joe Smith, real or real-looking): "] = "";
 $a->strings["Your Email Address: "] = "Ваш адрес электронной почты: ";
+$a->strings["Leave empty for an auto generated password."] = "";
 $a->strings["Choose a profile nickname. This must begin with a text character. Your profile address on this site will then be '<strong>nickname@\$sitename</strong>'."] = "Выбор псевдонима профиля. Он должен начинаться с буквы. Адрес вашего профиля на данном сайте будет в этом случае '<strong>nickname@\$sitename</strong>'.";
 $a->strings["Choose a nickname: "] = "Выберите псевдоним: ";
 $a->strings["Register"] = "Регистрация";
 $a->strings["Import"] = "Импорт";
 $a->strings["Import your profile to this friendica instance"] = "Импорт своего профиля в этот экземпляр friendica";
 $a->strings["System down for maintenance"] = "Система закрыта на техническое обслуживание";
+$a->strings["Only logged in users are permitted to perform a search."] = "";
+$a->strings["Too Many Requests"] = "";
+$a->strings["Only one search per minute is permitted for not logged in users."] = "";
 $a->strings["Search"] = "Поиск";
-$a->strings["Global Directory"] = "Глобальный каталог";
-$a->strings["Find on this site"] = "Найти на этом сайте";
-$a->strings["Site Directory"] = "Каталог сайта";
-$a->strings["Age: "] = "Возраст: ";
-$a->strings["Gender: "] = "Пол: ";
-$a->strings["Gender:"] = "Пол:";
+$a->strings["Items tagged with: %s"] = "";
+$a->strings["Search results for: %s"] = "";
 $a->strings["Status:"] = "Статус:";
 $a->strings["Homepage:"] = "Домашняя страничка:";
-$a->strings["About:"] = "О себе:";
+$a->strings["Global Directory"] = "Глобальный каталог";
+$a->strings["Find on this site"] = "Найти на этом сайте";
+$a->strings["Finding:"] = "";
+$a->strings["Site Directory"] = "Каталог сайта";
 $a->strings["No entries (some entries may be hidden)."] = "Нет записей (некоторые записи могут быть скрыты).";
 $a->strings["No potential page delegates located."] = "";
 $a->strings["Delegate Page Management"] = "Делегировать управление страницей";
@@ -1040,7 +1182,6 @@ $a->strings["Existing Page Delegates"] = "Существующие уполно
 $a->strings["Potential Delegates"] = "Возможные доверенные лица";
 $a->strings["Add"] = "Добавить";
 $a->strings["No entries."] = "Нет записей.";
-$a->strings["Common Friends"] = "Общие друзья";
 $a->strings["No contacts in common."] = "Нет общих контактов.";
 $a->strings["Export account"] = "Экспорт аккаунта";
 $a->strings["Export your account info and contacts. Use this to make a backup of your account and/or to move it to another server."] = "Экспорт ваших регистрационных данные и контактов. Используйте, чтобы создать резервную копию вашего аккаунта и/или переместить его на другой сервер.";
@@ -1050,9 +1191,9 @@ $a->strings["%1\$s is currently %2\$s"] = "";
 $a->strings["Mood"] = "Настроение";
 $a->strings["Set your current mood and tell your friends"] = "Напишите о вашем настроении и расскажите своим друзьям";
 $a->strings["Do you really want to delete this suggestion?"] = "Вы действительно хотите удалить это предложение?";
-$a->strings["Friend Suggestions"] = "Предложения друзей";
 $a->strings["No suggestions available. If this is a new site, please try again in 24 hours."] = "Нет предложений. Если это новый сайт, пожалуйста, попробуйте снова через 24 часа.";
 $a->strings["Ignore/Hide"] = "Проигнорировать/Скрыть";
+$a->strings["Friend Suggestions"] = "Предложения друзей";
 $a->strings["Profile deleted."] = "Профиль удален.";
 $a->strings["Profile-"] = "Профиль-";
 $a->strings["New profile created."] = "Новый профиль создан.";
@@ -1079,6 +1220,7 @@ $a->strings[" - Visit %1\$s's %2\$s"] = " - Посетить профиль %1\$
 $a->strings["%1\$s has an updated %2\$s, changing %3\$s."] = "";
 $a->strings["Hide contacts and friends:"] = "";
 $a->strings["Hide your contact/friend list from viewers of this profile?"] = "Скрывать ваш список контактов / друзей от посетителей этого профиля?";
+$a->strings["Show more profile fields:"] = "";
 $a->strings["Edit Profile Details"] = "Редактировать детали профиля";
 $a->strings["Change Profile Photo"] = "Изменить фото профиля";
 $a->strings["View this profile"] = "Просмотреть этот профиль";
@@ -1094,7 +1236,7 @@ $a->strings["Profile Name:"] = "Имя профиля:";
 $a->strings["Your Full Name:"] = "Ваше полное имя:";
 $a->strings["Title/Description:"] = "Заголовок / Описание:";
 $a->strings["Your Gender:"] = "Ваш пол:";
-$a->strings["Birthday (%s):"] = "День рождения (%s):";
+$a->strings["Birthday :"] = "";
 $a->strings["Street Address:"] = "Адрес:";
 $a->strings["Locality/City:"] = "Город / Населенный пункт:";
 $a->strings["Postal/Zip Code:"] = "Почтовый индекс:";
@@ -1127,6 +1269,7 @@ $a->strings["Love/romance"] = "Любовь / романтика";
 $a->strings["Work/employment"] = "Работа / занятость";
 $a->strings["School/education"] = "Школа / образование";
 $a->strings["This is your <strong>public</strong> profile.<br />It <strong>may</strong> be visible to anybody using the internet."] = "Это ваш <strong>публичный</strong> профиль. <br /> Он <strong>может</strong> быть виден каждому через Интернет.";
+$a->strings["Age: "] = "Возраст: ";
 $a->strings["Edit/Manage Profiles"] = "Редактировать профиль";
 $a->strings["Change profile photo"] = "Изменить фото профиля";
 $a->strings["Create New Profile"] = "Создать новый профиль";
@@ -1136,7 +1279,7 @@ $a->strings["Edit visibility"] = "Редактировать видимость"
 $a->strings["Item not found"] = "Элемент не найден";
 $a->strings["Edit post"] = "Редактировать сообщение";
 $a->strings["upload photo"] = "загрузить фото";
-$a->strings["Attach file"] = "Приложить файл";
+$a->strings["Attach file"] = "Прикрепить файл";
 $a->strings["attach file"] = "приложить файл";
 $a->strings["web link"] = "веб-ссылка";
 $a->strings["Insert video link"] = "Вставить ссылку видео";
@@ -1157,6 +1300,7 @@ $a->strings["This is Friendica, version"] = "Это Friendica, версия";
 $a->strings["running at web location"] = "работает на веб-узле";
 $a->strings["Please visit <a href=\"http://friendica.com\">Friendica.com</a> to learn more about the Friendica project."] = "Пожалуйста, посетите сайт <a href=\"http://friendica.com\">Friendica.com</a>, чтобы узнать больше о проекте Friendica.";
 $a->strings["Bug reports and issues: please visit"] = "Отчет об ошибках и проблемах: пожалуйста, посетите";
+$a->strings["the bugtracker at github"] = "";
 $a->strings["Suggestions, praise, donations, etc. - please email \"Info\" at Friendica - dot com"] = "Предложения, похвала, пожертвования? Пишите на \"info\" на Friendica - точка com";
 $a->strings["Installed plugins/addons/apps:"] = "Установленные плагины / добавки / приложения:";
 $a->strings["No installed plugins/addons/apps"] = "Нет установленных плагинов / добавок / приложений";
@@ -1179,6 +1323,8 @@ $a->strings["poke, prod or do other things to somebody"] = "";
 $a->strings["Recipient"] = "Получатель";
 $a->strings["Choose what you wish to do to recipient"] = "Выберите действия для получателя";
 $a->strings["Make this post private"] = "Сделать эту запись личной";
+$a->strings["Resubscribing to OStatus contacts"] = "";
+$a->strings["Error"] = "Ошибка";
 $a->strings["Total invitation limit exceeded."] = "Превышен общий лимит приглашений.";
 $a->strings["%s : Not a valid email address."] = "%s: Неверный адрес электронной почты.";
 $a->strings["Please join us on Friendica"] = "Пожалуйста, присоединяйтесь к нам на Friendica";
@@ -1188,6 +1334,7 @@ $a->strings["%d message sent."] = array(
 	0 => "%d сообщение отправлено.",
 	1 => "%d сообщений отправлено.",
 	2 => "%d сообщений отправлено.",
+	3 => "%d сообщений отправлено.",
 );
 $a->strings["You have no more invitations available"] = "У вас нет больше приглашений";
 $a->strings["Visit %s for a list of public sites that you can join. Friendica members on other sites can all connect with each other, as well as with members of many other social networks."] = "Посетите %s со списком общедоступных сайтов, к которым вы можете присоединиться. Все участники Friendica на других сайтах могут соединиться друг с другом, а также с участниками многих других социальных сетей.";
@@ -1201,7 +1348,7 @@ $a->strings["You will need to supply this invitation code: \$invite_code"] = "В
 $a->strings["Once you have registered, please connect with me via my profile page at:"] = "После того как вы зарегистрировались, пожалуйста, свяжитесь со мной через мою страницу профиля по адресу:";
 $a->strings["For more information about the Friendica project and why we feel it is important, please visit http://friendica.com"] = "Для получения более подробной информации о проекте Friendica, пожалуйста, посетите http://friendica.com";
 $a->strings["Photo Albums"] = "Фотоальбомы";
-$a->strings["Contact Photos"] = "Фотографии контакта";
+$a->strings["Recent Photos"] = "Последние фото";
 $a->strings["Upload New Photos"] = "Загрузить новые фото";
 $a->strings["Contact information unavailable"] = "Информация о контакте недоступна";
 $a->strings["Album not found."] = "Альбом не найден.";
@@ -1211,7 +1358,6 @@ $a->strings["Delete Photo"] = "Удалить фото";
 $a->strings["Do you really want to delete this photo?"] = "Вы действительно хотите удалить эту фотографию?";
 $a->strings["%1\$s was tagged in %2\$s by %3\$s"] = "%1\$s отмечен/а/ в %2\$s by %3\$s";
 $a->strings["a photo"] = "фото";
-$a->strings["Image exceeds size limit of "] = "Размер фото превышает лимит ";
 $a->strings["Image file is empty."] = "Файл изображения пуст.";
 $a->strings["No photos selected"] = "Не выбрано фото.";
 $a->strings["You have used %1$.2f Mbytes of %2$.2f Mbytes photo storage."] = "Вы использовали %1$.2f мегабайт из %2$.2f возможных для хранения фотографий.";
@@ -1234,23 +1380,33 @@ $a->strings["Use as profile photo"] = "Использовать как фото
 $a->strings["View Full Size"] = "Просмотреть полный размер";
 $a->strings["Tags: "] = "Ключевые слова: ";
 $a->strings["[Remove any tag]"] = "[Удалить любое ключевое слово]";
-$a->strings["Rotate CW (right)"] = "Поворот по часовой стрелке (направо)";
-$a->strings["Rotate CCW (left)"] = "Поворот против часовой стрелки (налево)";
 $a->strings["New album name"] = "Название нового альбома";
 $a->strings["Caption"] = "Подпись";
 $a->strings["Add a Tag"] = "Добавить ключевое слово (таг)";
 $a->strings["Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"] = "Пример: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping";
+$a->strings["Do not rotate"] = "";
+$a->strings["Rotate CW (right)"] = "Поворот по часовой стрелке (направо)";
+$a->strings["Rotate CCW (left)"] = "Поворот против часовой стрелки (налево)";
 $a->strings["Private photo"] = "Личное фото";
 $a->strings["Public photo"] = "Публичное фото";
 $a->strings["Share"] = "Поделиться";
-$a->strings["Recent Photos"] = "Последние фото";
+$a->strings["Attending"] = array(
+	0 => "",
+	1 => "",
+	2 => "",
+	3 => "",
+);
+$a->strings["Not attending"] = "";
+$a->strings["Might attend"] = "";
+$a->strings["Map"] = "Карта";
+$a->strings["Not Extended"] = "";
 $a->strings["Account approved."] = "Аккаунт утвержден.";
 $a->strings["Registration revoked for %s"] = "Регистрация отменена для %s";
 $a->strings["Please login."] = "Пожалуйста, войдите с паролем.";
 $a->strings["Move account"] = "Удалить аккаунт";
 $a->strings["You can import an account from another Friendica server."] = "Вы можете импортировать учетную запись с другого сервера Friendica.";
 $a->strings["You need to export your account from the old server and upload it here. We will recreate your old account here with all your contacts. We will try also to inform your friends that you moved here."] = "Вам нужно экспортировать свой ​​аккаунт со старого сервера и загрузить его сюда. Мы восстановим ваш ​​старый аккаунт здесь со всеми вашими контактами. Мы постараемся также сообщить друзьям, что вы переехали сюда.";
-$a->strings["This feature is experimental. We can't import contacts from the OStatus network (statusnet/identi.ca) or from Diaspora"] = "Это экспериментальная функция. Мы не можем импортировать контакты из сети OStatus (StatusNet / identi.ca) или из Diaspora";
+$a->strings["This feature is experimental. We can't import contacts from the OStatus network (GNU Social/Statusnet) or from Diaspora"] = "";
 $a->strings["Account file"] = "Файл аккаунта";
 $a->strings["To export your account, go to \"Settings->Export your personal data\" and select \"Export account\""] = "Для экспорта аккаунта, перейдите в \"Настройки->Экспортировать ваши данные\" и выберите \"Экспорт аккаунта\"";
 $a->strings["Item not available."] = "Пункт не доступен.";
@@ -1269,31 +1425,13 @@ $a->strings["Website Terms of Service"] = "Правила сайта";
 $a->strings["terms of service"] = "правила";
 $a->strings["Website Privacy Policy"] = "Политика конфиденциальности сервера";
 $a->strings["privacy policy"] = "политика конфиденциальности";
-$a->strings["Requested account is not available."] = "Запрашиваемый профиль недоступен.";
-$a->strings["Edit profile"] = "Редактировать профиль";
-$a->strings["Message"] = "Сообщение";
-$a->strings["Profiles"] = "Профили";
-$a->strings["Manage/edit profiles"] = "Управление / редактирование профилей";
-$a->strings["Network:"] = "";
-$a->strings["g A l F d"] = "g A l F d";
-$a->strings["F d"] = "F d";
-$a->strings["[today]"] = "[сегодня]";
-$a->strings["Birthday Reminders"] = "Напоминания о днях рождения";
-$a->strings["Birthdays this week:"] = "Дни рождения на этой неделе:";
-$a->strings["[No description]"] = "[без описания]";
-$a->strings["Event Reminders"] = "Напоминания о мероприятиях";
-$a->strings["Events this week:"] = "Мероприятия на этой неделе:";
-$a->strings["Status"] = "Статус";
-$a->strings["Status Messages and Posts"] = "Сообщение статуса и посты";
-$a->strings["Profile Details"] = "Детали профиля";
-$a->strings["Videos"] = "Видео";
-$a->strings["Events and Calendar"] = "Календарь и события";
-$a->strings["Only You Can See This"] = "Только вы можете это видеть";
 $a->strings["This entry was edited"] = "Эта запись была отредактирована";
+$a->strings["I will attend"] = "";
+$a->strings["I will not attend"] = "";
+$a->strings["I might attend"] = "";
 $a->strings["ignore thread"] = "";
 $a->strings["unignore thread"] = "";
 $a->strings["toggle ignore status"] = "";
-$a->strings["ignored"] = "";
 $a->strings["Categories:"] = "Категории:";
 $a->strings["Filed under:"] = "В рубрике:";
 $a->strings["via"] = "через";
@@ -1311,10 +1449,10 @@ $a->strings["%d invitation available"] = array(
 	0 => "%d приглашение доступно",
 	1 => "%d приглашений доступно",
 	2 => "%d приглашений доступно",
+	3 => "%d приглашений доступно",
 );
 $a->strings["Find People"] = "Поиск людей";
 $a->strings["Enter name or interest"] = "Введите имя или интерес";
-$a->strings["Connect/Follow"] = "Подключиться/Следовать";
 $a->strings["Examples: Robert Morgenstein, Fishing"] = "Примеры: Роберт Morgenstein, Рыбалка";
 $a->strings["Similar Interests"] = "Похожие интересы";
 $a->strings["Random Profile"] = "Случайный профиль";
@@ -1324,19 +1462,29 @@ $a->strings["All Networks"] = "Все сети";
 $a->strings["Saved Folders"] = "Сохранённые папки";
 $a->strings["Everything"] = "Всё";
 $a->strings["Categories"] = "Категории";
+$a->strings["%d contact in common"] = array(
+	0 => "%d Контакт",
+	1 => "%d Контактов",
+	2 => "%d Контактов",
+	3 => "%d Контактов",
+);
 $a->strings["General Features"] = "Основные возможности";
 $a->strings["Multiple Profiles"] = "Несколько профилей";
 $a->strings["Ability to create multiple profiles"] = "Возможность создания нескольких профилей";
-$a->strings["Post Composition Features"] = "";
+$a->strings["Photo Location"] = "";
+$a->strings["Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map."] = "";
+$a->strings["Post Composition Features"] = "Составление сообщений";
 $a->strings["Richtext Editor"] = "Редактор RTF";
 $a->strings["Enable richtext editor"] = "Включить редактор RTF";
-$a->strings["Post Preview"] = "предварительный просмотр";
+$a->strings["Post Preview"] = "Предварительный просмотр";
 $a->strings["Allow previewing posts and comments before publishing them"] = "Разрешить предпросмотр сообщения и комментария перед их публикацией";
 $a->strings["Auto-mention Forums"] = "";
 $a->strings["Add/remove mention when a fourm page is selected/deselected in ACL window."] = "";
 $a->strings["Network Sidebar Widgets"] = "Виджет боковой панели \"Сеть\"";
 $a->strings["Search by Date"] = "Поиск по датам";
 $a->strings["Ability to select posts by date ranges"] = "Возможность выбора постов по диапазону дат";
+$a->strings["List Forums"] = "";
+$a->strings["Enable widget to display the forums your are connected with"] = "";
 $a->strings["Group Filter"] = "Фильтр групп";
 $a->strings["Enable widget to display Network posts only from selected group"] = "Включить виджет для отображения сообщений сети только от выбранной группы";
 $a->strings["Network Filter"] = "Фильтр сети";
@@ -1365,6 +1513,8 @@ $a->strings["Star Posts"] = "Популярные посты";
 $a->strings["Ability to mark special posts with a star indicator"] = "Возможность отметить специальные сообщения индикатором популярности";
 $a->strings["Mute Post Notifications"] = "";
 $a->strings["Ability to mute notifications for a thread"] = "";
+$a->strings["Advanced Profile Settings"] = "Расширенные настройки профиля";
+$a->strings["Show visitors public community forums at the Advanced Profile Page"] = "";
 $a->strings["Connect URL missing."] = "Connect-URL отсутствует.";
 $a->strings["This site is not configured to allow communications with other networks."] = "Данный сайт не настроен так, чтобы держать связь с другими сетями.";
 $a->strings["No compatible communication protocols or feeds were discovered."] = "Обнаружены несовместимые протоколы связи или каналы.";
@@ -1381,18 +1531,17 @@ $a->strings["A deleted group with this name was revived. Existing item permissio
 $a->strings["Default privacy group for new contacts"] = "Группа доступа по умолчанию для новых контактов";
 $a->strings["Everybody"] = "Каждый";
 $a->strings["edit"] = "редактировать";
+$a->strings["Edit groups"] = "";
 $a->strings["Edit group"] = "Редактировать группу";
 $a->strings["Create a new group"] = "Создать новую группу";
 $a->strings["Contacts not in any group"] = "Контакты не состоят в группе";
 $a->strings["Miscellaneous"] = "Разное";
-$a->strings["year"] = "год";
-$a->strings["month"] = "мес.";
-$a->strings["day"] = "день";
+$a->strings["YYYY-MM-DD or MM-DD"] = "";
 $a->strings["never"] = "никогда";
 $a->strings["less than a second ago"] = "менее сек. назад";
+$a->strings["year"] = "год";
 $a->strings["years"] = "лет";
 $a->strings["months"] = "мес.";
-$a->strings["week"] = "неделя";
 $a->strings["weeks"] = "недель";
 $a->strings["days"] = "дней";
 $a->strings["hour"] = "час";
@@ -1404,26 +1553,68 @@ $a->strings["seconds"] = "сек.";
 $a->strings["%1\$d %2\$s ago"] = "%1\$d %2\$s назад";
 $a->strings["%s's birthday"] = "день рождения %s";
 $a->strings["Happy Birthday %s"] = "С днём рождения %s";
+$a->strings["Requested account is not available."] = "Запрашиваемый профиль недоступен.";
+$a->strings["Edit profile"] = "Редактировать профиль";
+$a->strings["Atom feed"] = "";
+$a->strings["Message"] = "Сообщение";
+$a->strings["Profiles"] = "Профили";
+$a->strings["Manage/edit profiles"] = "Управление / редактирование профилей";
+$a->strings["g A l F d"] = "g A l F d";
+$a->strings["F d"] = "F d";
+$a->strings["[today]"] = "[сегодня]";
+$a->strings["Birthday Reminders"] = "Напоминания о днях рождения";
+$a->strings["Birthdays this week:"] = "Дни рождения на этой неделе:";
+$a->strings["[No description]"] = "[без описания]";
+$a->strings["Event Reminders"] = "Напоминания о мероприятиях";
+$a->strings["Events this week:"] = "Мероприятия на этой неделе:";
+$a->strings["j F, Y"] = "j F, Y";
+$a->strings["j F"] = "j F";
+$a->strings["Birthday:"] = "День рождения:";
+$a->strings["Age:"] = "Возраст:";
+$a->strings["for %1\$d %2\$s"] = "";
+$a->strings["Religion:"] = "Религия:";
+$a->strings["Hobbies/Interests:"] = "Хобби / Интересы:";
+$a->strings["Contact information and Social Networks:"] = "Информация о контакте и социальных сетях:";
+$a->strings["Musical interests:"] = "Музыкальные интересы:";
+$a->strings["Books, literature:"] = "Книги, литература:";
+$a->strings["Television:"] = "Телевидение:";
+$a->strings["Film/dance/culture/entertainment:"] = "Кино / Танцы / Культура / Развлечения:";
+$a->strings["Love/Romance:"] = "Любовь / Романтика:";
+$a->strings["Work/employment:"] = "Работа / Занятость:";
+$a->strings["School/education:"] = "Школа / Образование:";
+$a->strings["Forums:"] = "";
+$a->strings["Videos"] = "Видео";
+$a->strings["Events and Calendar"] = "Календарь и события";
+$a->strings["Only You Can See This"] = "Только вы можете это видеть";
+$a->strings["event"] = "мероприятие";
+$a->strings["%1\$s likes %2\$s's %3\$s"] = "%1\$s нравится %3\$s от %2\$s ";
+$a->strings["%1\$s doesn't like %2\$s's %3\$s"] = "%1\$s не нравится %3\$s от %2\$s ";
+$a->strings["%1\$s is attending %2\$s's %3\$s"] = "";
+$a->strings["%1\$s is not attending %2\$s's %3\$s"] = "";
+$a->strings["%1\$s may attend %2\$s's %3\$s"] = "";
+$a->strings["Post to Email"] = "Отправить на Email";
+$a->strings["Connectors disabled, since \"%s\" is enabled."] = "";
 $a->strings["Visible to everybody"] = "Видимо всем";
 $a->strings["show"] = "показывать";
 $a->strings["don't show"] = "не показывать";
+$a->strings["Close"] = "Закрыть";
 $a->strings["[no subject]"] = "[без темы]";
 $a->strings["stopped following"] = "остановлено следование";
-$a->strings["Poke"] = "";
 $a->strings["View Status"] = "Просмотреть статус";
-$a->strings["View Profile"] = "Просмотреть профиль";
 $a->strings["View Photos"] = "Просмотреть фото";
 $a->strings["Network Posts"] = "Посты сети";
 $a->strings["Edit Contact"] = "Редактировать контакт";
 $a->strings["Drop Contact"] = "Удалить контакт";
 $a->strings["Send PM"] = "Отправить ЛС";
+$a->strings["Poke"] = "";
 $a->strings["Welcome "] = "Добро пожаловать, ";
 $a->strings["Please upload a profile photo."] = "Пожалуйста, загрузите фотографию профиля.";
 $a->strings["Welcome back "] = "Добро пожаловать обратно, ";
 $a->strings["The form security token was not correct. This probably happened because the form has been opened for too long (>3 hours) before submitting it."] = "Ключ формы безопасности неправильный. Вероятно, это произошло потому, что форма была открыта слишком долго (более 3 часов) до её отправки.";
-$a->strings["event"] = "мероприятие";
+$a->strings["%1\$s attends %2\$s's %3\$s"] = "";
+$a->strings["%1\$s doesn't attend %2\$s's %3\$s"] = "";
+$a->strings["%1\$s attends maybe %2\$s's %3\$s"] = "";
 $a->strings["%1\$s poked %2\$s"] = "";
-$a->strings["poked"] = "";
 $a->strings["post/item"] = "пост/элемент";
 $a->strings["%1\$s marked %2\$s's %3\$s as favorite"] = "%1\$s пометил %2\$s %3\$s как Фаворит";
 $a->strings["remove"] = "удалить";
@@ -1431,24 +1622,58 @@ $a->strings["Delete Selected Items"] = "Удалить выбранные поз
 $a->strings["Follow Thread"] = "";
 $a->strings["%s likes this."] = "%s нравится это.";
 $a->strings["%s doesn't like this."] = "%s не нравится это.";
-$a->strings["<span  %1\$s>%2\$d people</span> like this"] = "<span %1\$s>%2\$d людям</span> нравится это";
-$a->strings["<span  %1\$s>%2\$d people</span> don't like this"] = "<span %1\$s>%2\$d людям</span> не нравится это";
+$a->strings["%s attends."] = "";
+$a->strings["%s doesn't attend."] = "";
+$a->strings["%s attends maybe."] = "";
 $a->strings["and"] = "и";
 $a->strings[", and %d other people"] = ", и %d других чел.";
-$a->strings["%s like this."] = "%s нравится это.";
-$a->strings["%s don't like this."] = "%s не нравится это.";
+$a->strings["<span  %1\$s>%2\$d people</span> like this"] = "<span %1\$s>%2\$d людям</span> нравится это";
+$a->strings["%s like this."] = "";
+$a->strings["<span  %1\$s>%2\$d people</span> don't like this"] = "<span %1\$s>%2\$d людям</span> не нравится это";
+$a->strings["%s don't like this."] = "";
+$a->strings["<span  %1\$s>%2\$d people</span> attend"] = "";
+$a->strings["%s attend."] = "";
+$a->strings["<span  %1\$s>%2\$d people</span> don't attend"] = "";
+$a->strings["%s don't attend."] = "";
+$a->strings["<span  %1\$s>%2\$d people</span> anttend maybe"] = "";
+$a->strings["%s anttend maybe."] = "";
 $a->strings["Visible to <strong>everybody</strong>"] = "Видимое <strong>всем</strong>";
 $a->strings["Please enter a video link/URL:"] = "Введите  ссылку на видео link/URL:";
 $a->strings["Please enter an audio link/URL:"] = "Введите ссылку на аудио link/URL:";
 $a->strings["Tag term:"] = "";
 $a->strings["Where are you right now?"] = "И где вы сейчас?";
 $a->strings["Delete item(s)?"] = "Удалить елемент(ты)?";
-$a->strings["Post to Email"] = "Отправить на Email";
-$a->strings["Connectors disabled, since \"%s\" is enabled."] = "";
 $a->strings["permissions"] = "разрешения";
 $a->strings["Post to Groups"] = "Пост для групп";
 $a->strings["Post to Contacts"] = "Пост для контактов";
 $a->strings["Private post"] = "Личное сообщение";
+$a->strings["View all"] = "";
+$a->strings["Like"] = array(
+	0 => "",
+	1 => "",
+	2 => "",
+	3 => "",
+);
+$a->strings["Dislike"] = array(
+	0 => "",
+	1 => "",
+	2 => "",
+	3 => "",
+);
+$a->strings["Not Attending"] = array(
+	0 => "",
+	1 => "",
+	2 => "",
+	3 => "",
+);
+$a->strings["Undecided"] = array(
+	0 => "",
+	1 => "",
+	2 => "",
+	3 => "",
+);
+$a->strings["Forums"] = "";
+$a->strings["External link to forum"] = "";
 $a->strings["view full size"] = "посмотреть в полный размер";
 $a->strings["newer"] = "новее";
 $a->strings["older"] = "старее";
@@ -1456,13 +1681,20 @@ $a->strings["prev"] = "пред.";
 $a->strings["first"] = "первый";
 $a->strings["last"] = "последний";
 $a->strings["next"] = "след.";
+$a->strings["Loading more entries..."] = "";
+$a->strings["The end"] = "";
 $a->strings["No contacts"] = "Нет контактов";
 $a->strings["%d Contact"] = array(
 	0 => "%d контакт",
 	1 => "%d контактов",
 	2 => "%d контактов",
+	3 => "%d контактов",
 );
+$a->strings["View Contacts"] = "Просмотр контактов";
+$a->strings["Full Text"] = "Контент";
+$a->strings["Tags"] = "Тэги";
 $a->strings["poke"] = "poke";
+$a->strings["poked"] = "";
 $a->strings["ping"] = "пинг";
 $a->strings["pinged"] = "пингуется";
 $a->strings["prod"] = "";
@@ -1493,29 +1725,10 @@ $a->strings["frustrated"] = "";
 $a->strings["motivated"] = "";
 $a->strings["relaxed"] = "";
 $a->strings["surprised"] = "";
-$a->strings["Monday"] = "Понедельник";
-$a->strings["Tuesday"] = "Вторник";
-$a->strings["Wednesday"] = "Среда";
-$a->strings["Thursday"] = "Четверг";
-$a->strings["Friday"] = "Пятница";
-$a->strings["Saturday"] = "Суббота";
-$a->strings["Sunday"] = "Воскресенье";
-$a->strings["January"] = "Январь";
-$a->strings["February"] = "Февраль";
-$a->strings["March"] = "Март";
-$a->strings["April"] = "Апрель";
-$a->strings["May"] = "Май";
-$a->strings["June"] = "Июнь";
-$a->strings["July"] = "Июль";
-$a->strings["August"] = "Август";
-$a->strings["September"] = "Сентябрь";
-$a->strings["October"] = "Октябрь";
-$a->strings["November"] = "Ноябрь";
-$a->strings["December"] = "Декабрь";
 $a->strings["bytes"] = "байт";
 $a->strings["Click to open/close"] = "Нажмите, чтобы открыть / закрыть";
-$a->strings["default"] = "значение по умолчанию";
-$a->strings["Select an alternate language"] = "Выбор альтернативного языка";
+$a->strings["View on separate page"] = "";
+$a->strings["view on separate page"] = "";
 $a->strings["activity"] = "активность";
 $a->strings["post"] = "сообщение";
 $a->strings["Item filed"] = "";
@@ -1524,8 +1737,6 @@ $a->strings["<a href=\"%1\$s\" target=\"_blank\">%2\$s</a> %3\$s"] = "";
 $a->strings["<span><a href=\"%s\" target=\"_blank\">%s</a> wrote the following <a href=\"%s\" target=\"_blank\">post</a>"] = "";
 $a->strings["$1 wrote:"] = "$1 написал:";
 $a->strings["Encrypted content"] = "Зашифрованный контент";
-$a->strings["(no subject)"] = "(без темы)";
-$a->strings["noreply"] = "без ответа";
 $a->strings["Cannot locate DNS info for database server '%s'"] = "Не могу найти информацию для DNS-сервера базы данных '%s'";
 $a->strings["Unknown | Not categorised"] = "Неизвестно | Не определено";
 $a->strings["Block immediately"] = "Блокировать немедленно";
@@ -1537,6 +1748,7 @@ $a->strings["Weekly"] = "Еженедельно";
 $a->strings["Monthly"] = "Ежемесячно";
 $a->strings["OStatus"] = "OStatus";
 $a->strings["RSS/Atom"] = "RSS/Atom";
+$a->strings["Facebook"] = "Facebook";
 $a->strings["Zot!"] = "Zot!";
 $a->strings["LinkedIn"] = "LinkedIn";
 $a->strings["XMPP/IM"] = "XMPP/IM";
@@ -1545,33 +1757,18 @@ $a->strings["Google+"] = "Google+";
 $a->strings["pump.io"] = "pump.io";
 $a->strings["Twitter"] = "Twitter";
 $a->strings["Diaspora Connector"] = "";
-$a->strings["Statusnet"] = "";
+$a->strings["GNU Social"] = "";
 $a->strings["App.net"] = "";
+$a->strings["Redmatrix"] = "";
 $a->strings[" on Last.fm"] = "на Last.fm";
 $a->strings["Starts:"] = "Начало:";
 $a->strings["Finishes:"] = "Окончание:";
-$a->strings["j F, Y"] = "j F, Y";
-$a->strings["j F"] = "j F";
-$a->strings["Birthday:"] = "День рождения:";
-$a->strings["Age:"] = "Возраст:";
-$a->strings["for %1\$d %2\$s"] = "";
-$a->strings["Tags:"] = "Ключевые слова: ";
-$a->strings["Religion:"] = "Религия:";
-$a->strings["Hobbies/Interests:"] = "Хобби / Интересы:";
-$a->strings["Contact information and Social Networks:"] = "Информация о контакте и социальных сетях:";
-$a->strings["Musical interests:"] = "Музыкальные интересы:";
-$a->strings["Books, literature:"] = "Книги, литература:";
-$a->strings["Television:"] = "Телевидение:";
-$a->strings["Film/dance/culture/entertainment:"] = "Кино / Танцы / Культура / Развлечения:";
-$a->strings["Love/Romance:"] = "Любовь / Романтика:";
-$a->strings["Work/employment:"] = "Работа / Занятость:";
-$a->strings["School/education:"] = "Школа / Образование:";
 $a->strings["Click here to upgrade."] = "Нажмите для обновления.";
 $a->strings["This action exceeds the limits set by your subscription plan."] = "Это действие превышает лимиты, установленные вашим тарифным планом.";
 $a->strings["This action is not available under your subscription plan."] = "Это действие не доступно в соответствии с вашим планом подписки.";
-$a->strings["End this session"] = "Конец этой сессии";
-$a->strings["Your posts and conversations"] = "Ваши сообщения и беседы";
-$a->strings["Your profile page"] = "Страница Вашего профиля";
+$a->strings["End this session"] = "Завершить эту сессию";
+$a->strings["Your posts and conversations"] = "Данные вашей учётной записи";
+$a->strings["Your profile page"] = "Информация о вас";
 $a->strings["Your photos"] = "Ваши фотографии";
 $a->strings["Your videos"] = "";
 $a->strings["Your events"] = "Ваши события";
@@ -1588,9 +1785,9 @@ $a->strings["Conversations on this site"] = "Беседы на этом сайт
 $a->strings["Conversations on the network"] = "";
 $a->strings["Directory"] = "Каталог";
 $a->strings["People directory"] = "Каталог участников";
-$a->strings["Information"] = "";
+$a->strings["Information"] = "Информация";
 $a->strings["Information about this friendica instance"] = "";
-$a->strings["Conversations from your friends"] = "Беседы с друзьями";
+$a->strings["Conversations from your friends"] = "Посты ваших друзей";
 $a->strings["Network Reset"] = "Перезагрузка сети";
 $a->strings["Load Network page with no filters"] = "Загрузить страницу сети без фильтров";
 $a->strings["Friend Requests"] = "Запросы на добавление в список друзей";
@@ -1604,19 +1801,12 @@ $a->strings["Manage other pages"] = "Управление другими стр
 $a->strings["Account settings"] = "Настройки аккаунта";
 $a->strings["Manage/Edit Profiles"] = "Управление/редактирование профилей";
 $a->strings["Manage/edit friends and contacts"] = "Управление / редактирование друзей и контактов";
-$a->strings["Site setup and configuration"] = "Установка и конфигурация сайта";
+$a->strings["Site setup and configuration"] = "Конфигурация сайта";
 $a->strings["Navigation"] = "Навигация";
 $a->strings["Site map"] = "Карта сайта";
-$a->strings["User not found."] = "Пользователь не найден.";
 $a->strings["Daily posting limit of %d posts reached. The post was rejected."] = "";
 $a->strings["Weekly posting limit of %d posts reached. The post was rejected."] = "";
 $a->strings["Monthly posting limit of %d posts reached. The post was rejected."] = "";
-$a->strings["There is no status with this id."] = "Нет статуса с таким id.";
-$a->strings["There is no conversation with this id."] = "";
-$a->strings["Invalid request."] = "";
-$a->strings["Invalid item."] = "";
-$a->strings["Invalid action. "] = "";
-$a->strings["DB error"] = "";
 $a->strings["An invitation is required."] = "Требуется приглашение.";
 $a->strings["Invitation could not be verified."] = "Приглашение не может быть проверено.";
 $a->strings["Invalid OpenID url"] = "Неверный URL OpenID";
@@ -1627,17 +1817,20 @@ $a->strings["That doesn't appear to be your full (First Last) name."] = "Каж
 $a->strings["Your email domain is not among those allowed on this site."] = "Домен вашего адреса электронной почты не относится к числу разрешенных на этом сайте.";
 $a->strings["Not a valid email address."] = "Неверный адрес электронной почты.";
 $a->strings["Cannot use that email."] = "Нельзя использовать этот Email.";
-$a->strings["Your \"nickname\" can only contain \"a-z\", \"0-9\", \"-\", and \"_\", and must also begin with a letter."] = "Ваш \"ник\" может содержать только \"a-z\", \"0-9\", \"-\", и \"_\", а также должен начинаться с буквы.";
+$a->strings["Your \"nickname\" can only contain \"a-z\", \"0-9\" and \"_\"."] = "";
 $a->strings["Nickname is already registered. Please choose another."] = "Такой ник уже зарегистрирован. Пожалуйста, выберите другой.";
 $a->strings["Nickname was once registered here and may not be re-used. Please choose another."] = "Ник уже зарегистрирован на этом сайте и не может быть изменён. Пожалуйста, выберите другой ник.";
 $a->strings["SERIOUS ERROR: Generation of security keys failed."] = "СЕРЬЕЗНАЯ ОШИБКА: генерация ключей безопасности не удалась.";
 $a->strings["An error occurred during registration. Please try again."] = "Ошибка при регистрации. Пожалуйста, попробуйте еще раз.";
+$a->strings["default"] = "значение по умолчанию";
 $a->strings["An error occurred creating your default profile. Please try again."] = "Ошибка создания вашего профиля. Пожалуйста, попробуйте еще раз.";
 $a->strings["Friends"] = "Друзья";
 $a->strings["\n\t\tDear %1\$s,\n\t\t\tThank you for registering at %2\$s. Your account has been created.\n\t"] = "";
 $a->strings["\n\t\tThe login details are as follows:\n\t\t\tSite Location:\t%3\$s\n\t\t\tLogin Name:\t%1\$s\n\t\t\tPassword:\t%5\$s\n\n\t\tYou may change your password from your account \"Settings\" page after logging\n\t\tin.\n\n\t\tPlease take a few moments to review the other account settings on that page.\n\n\t\tYou may also wish to add some basic information to your default profile\n\t\t(on the \"Profiles\" page) so that other people can easily find you.\n\n\t\tWe recommend setting your full name, adding a profile photo,\n\t\tadding some profile \"keywords\" (very useful in making new friends) - and\n\t\tperhaps what country you live in; if you do not wish to be more specific\n\t\tthan that.\n\n\t\tWe fully respect your right to privacy, and none of these items are necessary.\n\t\tIf you are new and do not know anybody here, they may help\n\t\tyou to make some new and interesting friends.\n\n\n\t\tThank you and welcome to %2\$s."] = "";
 $a->strings["Sharing notification from Diaspora network"] = "Делиться уведомлениями из сети Diaspora";
 $a->strings["Attachments:"] = "Вложения:";
+$a->strings["(no subject)"] = "(без темы)";
+$a->strings["noreply"] = "без ответа";
 $a->strings["Do you really want to delete this item?"] = "Вы действительно хотите удалить этот элемент?";
 $a->strings["Archives"] = "Архивы";
 $a->strings["Male"] = "Мужчина";
@@ -1653,7 +1846,6 @@ $a->strings["Hermaphrodite"] = "Гермафродит";
 $a->strings["Neuter"] = "Средний род";
 $a->strings["Non-specific"] = "Не определен";
 $a->strings["Other"] = "Другой";
-$a->strings["Undecided"] = "Не решено";
 $a->strings["Males"] = "Мужчины";
 $a->strings["Females"] = "Женщины";
 $a->strings["Gay"] = "Гей";
@@ -1700,6 +1892,7 @@ $a->strings["Ask me"] = "Спросите меня";
 $a->strings["Friendica Notification"] = "Friendica уведомления";
 $a->strings["Thank You,"] = "Спасибо,";
 $a->strings["%s Administrator"] = "%s администратор";
+$a->strings["%1\$s, %2\$s Administrator"] = "";
 $a->strings["%s <!item_type!>"] = "%s <!item_type!>";
 $a->strings["[Friendica:Notify] New mail received at %s"] = "[Friendica: Оповещение] Новое сообщение, пришедшее на %s";
 $a->strings["%1\$s sent you a new private message at %2\$s."] = "%1\$s отправил вам новое личное сообщение на %2\$s.";
@@ -1743,7 +1936,7 @@ $a->strings["Name:"] = "Имя:";
 $a->strings["Photo:"] = "Фото:";
 $a->strings["Please visit %s to approve or reject the suggestion."] = "Пожалуйста, посетите %s для подтверждения, или отказа запроса.";
 $a->strings["[Friendica:Notify] Connection accepted"] = "";
-$a->strings["'%1\$s' has acepted your connection request at %2\$s"] = "";
+$a->strings["'%1\$s' has accepted your connection request at %2\$s"] = "";
 $a->strings["%2\$s has accepted your [url=%1\$s]connection request[/url]."] = "";
 $a->strings["You are now mutual friends and may exchange status updates, photos, and email\n\twithout restriction."] = "";
 $a->strings["Please visit %s  if you wish to make any changes to this relationship."] = "";
@@ -1766,10 +1959,10 @@ $a->strings["%d contact not imported"] = array(
 	0 => "%d контакт не импортирован",
 	1 => "%d контакты не импортированы",
 	2 => "%d контакты не импортированы",
+	3 => "%d контакты не импортированы",
 );
 $a->strings["Done. You can now login with your username and password"] = "Завершено. Теперь вы можете войти с вашим логином и паролем";
 $a->strings["toggle mobile"] = "мобильная версия";
-$a->strings["Theme settings"] = "Настройки темы";
 $a->strings["Set resize level for images in posts and comments (width and height)"] = "Установить уровень изменения размера изображений в постах и ​​комментариях (ширина и высота)";
 $a->strings["Set font-size for posts and comments"] = "Установить шрифт-размер для постов и комментариев";
 $a->strings["Set theme width"] = "Установить ширину темы";
@@ -1800,7 +1993,9 @@ $a->strings["Your personal photos"] = "Ваши личные фотографи
 $a->strings["Local Directory"] = "Локальный каталог";
 $a->strings["Set zoomfactor for Earth Layers"] = "Установить масштаб карты";
 $a->strings["Show/hide boxes at right-hand column:"] = "Показать/скрыть блоки в правой колонке:";
+$a->strings["Comma separated list of helper forums"] = "";
 $a->strings["Set style"] = "";
+$a->strings["Quick Start"] = "Быстрый запуск";
 $a->strings["greenzero"] = "";
 $a->strings["purplezero"] = "";
 $a->strings["easterbunny"] = "";

From f7537c9e90fa1b35618abd523d0d00f9658085a9 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 17 Feb 2016 00:01:24 +0100
Subject: [PATCH 110/273] Remove the baseurl where possible to avoid mixed
 content

---
 boot.php                  |  4 ++++
 include/ForumManager.php  | 10 +++++-----
 include/nav.php           |  2 +-
 mod/network.php           | 22 ++++++++++----------
 object/Item.php           |  2 +-
 view/templates/head.tpl   | 42 +++++++++++++++++++--------------------
 view/theme/vier/theme.php |  8 +++-----
 7 files changed, 46 insertions(+), 44 deletions(-)

diff --git a/boot.php b/boot.php
index d9d7c62dc7..0217750136 100644
--- a/boot.php
+++ b/boot.php
@@ -920,6 +920,10 @@ class App {
 	}
 
 	function get_cached_avatar_image($avatar_image){
+		// Just remove the base url. This avoid mixed content
+		$avatar_image = normalise_link($avatar_image);
+		$base = normalise_link($this->get_baseurl());
+		$avatar_image = str_replace($base."/", "", $avatar_image);
 		return $avatar_image;
 
 		// The following code is deactivated. It doesn't seem to make any sense and it slows down the system.
diff --git a/include/ForumManager.php b/include/ForumManager.php
index 49417d1831..73eb511de6 100644
--- a/include/ForumManager.php
+++ b/include/ForumManager.php
@@ -89,18 +89,18 @@ class ForumManager {
 		if(count($contacts)) {
 
 			$id = 0;
-
+$a = get_app();
 			foreach($contacts as $contact) {
 
 				$selected = (($cid == $contact['id']) ? ' forum-selected' : '');
 
 				$entry = array(
-					'url' => z_root() . '/network?f=&cid=' . $contact['id'],
-					'external_url' => z_root() . '/redir/' . $contact['id'],
+					'url' => 'network?f=&cid=' . $contact['id'],
+					'external_url' => 'redir/' . $contact['id'],
 					'name' => $contact['name'],
 					'cid' => $contact['id'],
 					'selected' 	=> $selected,
-					'micro' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO),
+					'micro' => $a->get_cached_avatar_image(proxy_url($contact['micro'], false, PROXY_SIZE_MICRO)),
 					'id' => ++$id,
 				);
 				$entries[] = $entry;
@@ -187,4 +187,4 @@ class ForumManager {
 		return $r;
 	}
 
-}
\ No newline at end of file
+}
diff --git a/include/nav.php b/include/nav.php
index 6512d35609..fb7225af92 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -107,7 +107,7 @@ function nav_info(&$a) {
 	if(($a->config['register_policy'] == REGISTER_OPEN) && (! local_user()) && (! remote_user()))
 		$nav['register'] = array('register',t('Register'), "", t('Create an account'));
 
-	$help_url = $a->get_baseurl($ssl_state) . '/help';
+	$help_url = 'help';
 
 	if(! get_config('system','hide_help'))
 		$nav['help'] = array($help_url, t('Help'), "", t('Help and documentation'));
diff --git a/mod/network.php b/mod/network.php
index 0010a3d824..a9f369a894 100644
--- a/mod/network.php
+++ b/mod/network.php
@@ -149,10 +149,10 @@ function network_init(&$a) {
 
 	$a->page['aside'] .= (feature_enabled(local_user(),'groups') ? group_side('network/0','network','standard',$group_id) : '');
 	$a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? ForumManager::widget(local_user(),$cid) : '');
-	$a->page['aside'] .= posted_date_widget($a->get_baseurl() . '/network',local_user(),false);
-	$a->page['aside'] .= networks_widget($a->get_baseurl(true) . '/network',(x($_GET, 'nets') ? $_GET['nets'] : ''));
+	$a->page['aside'] .= posted_date_widget('network',local_user(),false);
+	$a->page['aside'] .= networks_widget('network',(x($_GET, 'nets') ? $_GET['nets'] : ''));
 	$a->page['aside'] .= saved_searches($search);
-	$a->page['aside'] .= fileas_widget($a->get_baseurl(true) . '/network',(x($_GET, 'file') ? $_GET['file'] : ''));
+	$a->page['aside'] .= fileas_widget('network',(x($_GET, 'file') ? $_GET['file'] : ''));
 
 }
 
@@ -363,7 +363,7 @@ function network_content(&$a, $update = 0) {
 	$tabs = array(
 		array(
 			'label'	=> t('Commented Order'),
-			'url'	=> $a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : ''),
+			'url'	=> str_replace('/new', '', $cmd) . '?f=&order=comment' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : ''),
 			'sel'	=> $all_active,
 			'title'	=> t('Sort by Comment Date'),
 			'id'	=> 'commented-order-tab',
@@ -371,7 +371,7 @@ function network_content(&$a, $update = 0) {
 		),
 		array(
 			'label'	=> t('Posted Order'),
-			'url'	=> $a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : ''),
+			'url'	=> str_replace('/new', '', $cmd) . '?f=&order=post' . ((x($_GET,'cid')) ? '&cid=' . $_GET['cid'] : ''),
 			'sel'	=> $postord_active,
 			'title'	=> t('Sort by Post Date'),
 			'id'	=> 'posted-order-tab',
@@ -382,7 +382,7 @@ function network_content(&$a, $update = 0) {
 	if(feature_enabled(local_user(),'personal_tab')) {
 		$tabs[] = array(
 			'label'	=> t('Personal'),
-			'url'	=> $a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&conv=1',
+			'url'	=> str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&conv=1',
 			'sel'	=> $conv_active,
 			'title'	=> t('Posts that mention or involve you'),
 			'id'	=> 'personal-tab',
@@ -393,7 +393,7 @@ function network_content(&$a, $update = 0) {
 	if(feature_enabled(local_user(),'new_tab')) {
 		$tabs[] = array(
 			'label'	=> t('New'),
-			'url'	=> $a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . ($len_naked_cmd ? '/' : '') . 'new' . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : ''),
+			'url'	=> str_replace('/new', '', $cmd) . ($len_naked_cmd ? '/' : '') . 'new' . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : ''),
 			'sel'	=> $new_active,
 			'title'	=> t('Activity Stream - by date'),
 			'id'	=> 'activitiy-by-date-tab',
@@ -404,7 +404,7 @@ function network_content(&$a, $update = 0) {
 	if(feature_enabled(local_user(),'link_tab')) {
 		$tabs[] = array(
 			'label'	=> t('Shared Links'),
-			'url'	=> $a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&bmark=1',
+			'url'	=> str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&bmark=1',
 			'sel'	=> $bookmarked_active,
 			'title'	=> t('Interesting Links'),
 			'id'	=> 'shared-links-tab',
@@ -415,7 +415,7 @@ function network_content(&$a, $update = 0) {
 	if(feature_enabled(local_user(),'star_posts')) {
 		$tabs[] = array(
 			'label'	=> t('Starred'),
-			'url'	=> $a->get_baseurl(true) . '/' . str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&star=1',
+			'url'	=> str_replace('/new', '', $cmd) . ((x($_GET,'cid')) ? '/?f=&cid=' . $_GET['cid'] : '/?f=') . '&star=1',
 			'sel'	=> $starred_active,
 			'title'	=> t('Favourite Posts'),
 			'id'	=> 'starred-posts-tab',
@@ -547,7 +547,7 @@ function network_content(&$a, $update = 0) {
 			if($update)
 				killme();
 			notice( t('No such group') . EOL );
-			goaway($a->get_baseurl(true) . '/network/0');
+			goaway('network/0');
 			// NOTREACHED
 		}
 
@@ -611,7 +611,7 @@ function network_content(&$a, $update = 0) {
 		}
 		else {
 			notice( t('Invalid contact.') . EOL);
-			goaway($a->get_baseurl(true) . '/network');
+			goaway('network');
 			// NOTREACHED
 		}
 	}
diff --git a/object/Item.php b/object/Item.php
index 04c1a707e3..7b542c4724 100644
--- a/object/Item.php
+++ b/object/Item.php
@@ -705,7 +705,7 @@ class Item extends BaseObject {
 				'$profile_uid' =>  $conv->get_profile_owner(),
 				'$mylink' => $a->contact['url'],
 				'$mytitle' => t('This is you'),
-				'$myphoto' => $a->contact['thumb'],
+				'$myphoto' => $a->get_cached_avatar_image($a->contact['thumb']),
 				'$comment' => t('Comment'),
 				'$submit' => t('Submit'),
 				'$edbold' => t('Bold'),
diff --git a/view/templates/head.tpl b/view/templates/head.tpl
index 17c459c4d8..fdf9a7716e 100644
--- a/view/templates/head.tpl
+++ b/view/templates/head.tpl
@@ -2,17 +2,17 @@
 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
 <base href="{{$baseurl}}/" />
 <meta name="generator" content="{{$generator}}" />
-<link rel="stylesheet" href="{{$baseurl}}/view/global.css" type="text/css" media="all" />
-<link rel="stylesheet" href="{{$baseurl}}/library/colorbox/colorbox.css" type="text/css" media="screen" />
-<link rel="stylesheet" href="{{$baseurl}}/library/jgrowl/jquery.jgrowl.css" type="text/css" media="screen" />
-<link rel="stylesheet" href="{{$baseurl}}/library/datetimepicker/jquery.datetimepicker.css" type="text/css" media="screen" />
-<link rel="stylesheet" href="{{$baseurl}}/library/perfect-scrollbar/perfect-scrollbar.min.css" type="text/css" media="screen" />
+<link rel="stylesheet" href="view/global.css" type="text/css" media="all" />
+<link rel="stylesheet" href="library/colorbox/colorbox.css" type="text/css" media="screen" />
+<link rel="stylesheet" href="library/jgrowl/jquery.jgrowl.css" type="text/css" media="screen" />
+<link rel="stylesheet" href="library/datetimepicker/jquery.datetimepicker.css" type="text/css" media="screen" />
+<link rel="stylesheet" href="library/perfect-scrollbar/perfect-scrollbar.min.css" type="text/css" media="screen" />
 
 <link rel="stylesheet" type="text/css" href="{{$stylesheet}}" media="all" />
 
 <!--
-<link rel="shortcut icon" href="{{$baseurl}}/images/friendica-32.png" />
-<link rel="apple-touch-icon" href="{{$baseurl}}/images/friendica-128.png"/>
+<link rel="shortcut icon" href="images/friendica-32.png" />
+<link rel="apple-touch-icon" href="images/friendica-128.png"/>
 -->
 <link rel="shortcut icon" href="{{$shortcut_icon}}" />
 <link rel="apple-touch-icon" href="{{$touch_icon}}"/>
@@ -28,20 +28,20 @@
 <!--[if IE]>
 <script type="text/javascript" src="https://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 <![endif]-->
-<script type="text/javascript" src="{{$baseurl}}/js/modernizr.js" ></script>
-<script type="text/javascript" src="{{$baseurl}}/js/jquery.js" ></script>
-<!-- <script type="text/javascript" src="{{$baseurl}}/js/jquery-migrate.js" ></script>-->
-<script type="text/javascript" src="{{$baseurl}}/js/jquery-migrate.js" ></script>
-<script type="text/javascript" src="{{$baseurl}}/js/jquery.textinputs.js" ></script>
-<script type="text/javascript" src="{{$baseurl}}/js/fk.autocomplete.js" ></script>
-<script type="text/javascript" src="{{$baseurl}}/library/colorbox/jquery.colorbox-min.js"></script>
-<script type="text/javascript" src="{{$baseurl}}/library/jgrowl/jquery.jgrowl_minimized.js"></script>
-<script type="text/javascript" src="{{$baseurl}}/library/datetimepicker/jquery.datetimepicker.js"></script>
-<script type="text/javascript" src="{{$baseurl}}/library/tinymce/jscripts/tiny_mce/tiny_mce_src.js" ></script>
-<script type="text/javascript" src="{{$baseurl}}/library/perfect-scrollbar/perfect-scrollbar.jquery.js" ></script>
-<script type="text/javascript" src="{{$baseurl}}/js/acl.js" ></script>
-<script type="text/javascript" src="{{$baseurl}}/js/webtoolkit.base64.js" ></script>
-<script type="text/javascript" src="{{$baseurl}}/js/main.js" ></script>
+<script type="text/javascript" src="js/modernizr.js" ></script>
+<script type="text/javascript" src="js/jquery.js" ></script>
+<!-- <script type="text/javascript" src="js/jquery-migrate.js" ></script>-->
+<script type="text/javascript" src="js/jquery-migrate.js" ></script>
+<script type="text/javascript" src="js/jquery.textinputs.js" ></script>
+<script type="text/javascript" src="js/fk.autocomplete.js" ></script>
+<script type="text/javascript" src="library/colorbox/jquery.colorbox-min.js"></script>
+<script type="text/javascript" src="library/jgrowl/jquery.jgrowl_minimized.js"></script>
+<script type="text/javascript" src="library/datetimepicker/jquery.datetimepicker.js"></script>
+<script type="text/javascript" src="library/tinymce/jscripts/tiny_mce/tiny_mce_src.js" ></script>
+<script type="text/javascript" src="library/perfect-scrollbar/perfect-scrollbar.jquery.js" ></script>
+<script type="text/javascript" src="js/acl.js" ></script>
+<script type="text/javascript" src="js/webtoolkit.base64.js" ></script>
+<script type="text/javascript" src="js/main.js" ></script>
 <script>
 
 	var updateInterval = {{$update_interval}};
diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php
index c2669f5a93..25954350f9 100644
--- a/view/theme/vier/theme.php
+++ b/view/theme/vier/theme.php
@@ -19,8 +19,6 @@ function vier_init(&$a) {
 
 	set_template_engine($a, 'smarty3');
 
-	$baseurl = $a->get_baseurl();
-
 	$a->theme_info = array();
 
 	if ($a->argv[0].$a->argv[1] === "profile".$a->user['nickname'] or $a->argv[0] === "network" && local_user()) {
@@ -160,7 +158,7 @@ function vier_community_info() {
 				$entry = replace_macros($tpl,array(
 					'$id' => $rr['id'],
 					//'$profile_link' => zrl($rr['url']),
-					'$profile_link' => $a->get_baseurl().'/follow/?url='.urlencode($rr['url']),
+					'$profile_link' => 'follow/?url='.urlencode($rr['url']),
 					'$photo' => proxy_url($rr['photo'], false, PROXY_SIZE_MICRO),
 					'$alt_text' => $rr['name'],
 				));
@@ -186,7 +184,7 @@ function vier_community_info() {
 			$aside['$lastusers_items'] = array();
 
 			foreach($r as $rr) {
-				$profile_link = $a->get_baseurl() . '/profile/' . ((strlen($rr['nickname'])) ? $rr['nickname'] : $rr['profile_uid']);
+				$profile_link = 'profile/' . ((strlen($rr['nickname'])) ? $rr['nickname'] : $rr['profile_uid']);
 				$entry = replace_macros($tpl,array(
 					'$id' => $rr['id'],
 					'$profile_link' => $profile_link,
@@ -207,7 +205,7 @@ function vier_community_info() {
 		$nv['suggest'] = Array('suggest', t('Friend Suggestions'), "", "");
 		$nv['invite'] = Array('invite', t('Invite Friends'), "", "");
 
-		$nv['search'] = '<form name="simple_bar" method="get" action="'.$a->get_baseurl().'/dirfind">
+		$nv['search'] = '<form name="simple_bar" method="get" action="dirfind">
 						<span class="sbox_l"></span>
 						<span class="sbox">
 						<input type="text" name="search" size="13" maxlength="50">

From b21275ee9c59a9f9d184b4f1f4cb7421b04e0f1c Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Wed, 17 Feb 2016 08:00:38 +0100
Subject: [PATCH 111/273] handle exception with non-existing addon directory

---
 util/make_credits.py | 25 ++++++++++++++-----------
 1 file changed, 14 insertions(+), 11 deletions(-)

diff --git a/util/make_credits.py b/util/make_credits.py
index 404b059133..eacb8707f4 100755
--- a/util/make_credits.py
+++ b/util/make_credits.py
@@ -46,17 +46,20 @@ for i in c:
 n1 = len(contributors)
 print('  > found %d contributors' % n1)
 #  get the contributors to the addons
-os.chdir(path+'/addon')
-#  get the contributors
-print('> getting contributors to the addons')
-p = subprocess.Popen(['git', 'shortlog', '--no-merges', '-s'],
-                         stdout=subprocess.PIPE,
-                         stderr=subprocess.STDOUT)
-c = iter(p.stdout.readline, b'')
-for i in c:
-    name = i.decode().split('\t')[1].split('\n')[0]
-    if not name in contributors and name not in dontinclude:
-        contributors.append(name)
+try:
+    os.chdir(path+'/addon')
+    #  get the contributors
+    print('> getting contributors to the addons')
+    p = subprocess.Popen(['git', 'shortlog', '--no-merges', '-s'],
+                             stdout=subprocess.PIPE,
+                             stderr=subprocess.STDOUT)
+    c = iter(p.stdout.readline, b'')
+    for i in c:
+        name = i.decode().split('\t')[1].split('\n')[0]
+        if not name in contributors and name not in dontinclude:
+            contributors.append(name)
+except FileNotFoundError:
+    print('  > no addon directory found ( THE LIST OF CONTRIBUTORS WILL BE INCOMPLETE )')
 n2 = len(contributors)
 print('  > found %d new contributors' % (n2-n1))
 print('> total of %d contributors to the repositories of friendica' % n2)

From c5b724828a12a215d66e8086ed0ffdabfad5e928 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 17 Feb 2016 08:08:28 +0100
Subject: [PATCH 112/273] Just some more removed baseurls ...

---
 boot.php                  | 23 +++++++++++++++++++----
 include/ForumManager.php  |  4 ++--
 include/conversation.php  |  2 +-
 include/identity.php      |  6 +++---
 include/nav.php           |  2 +-
 index.php                 |  6 +++---
 mod/content.php           |  4 ++--
 mod/directory.php         |  4 ++--
 mod/profiles.php          | 28 ++++++++++------------------
 object/Item.php           |  4 ++--
 view/theme/vier/theme.php |  2 +-
 11 files changed, 46 insertions(+), 39 deletions(-)

diff --git a/boot.php b/boot.php
index 0217750136..851008aef5 100644
--- a/boot.php
+++ b/boot.php
@@ -920,10 +920,6 @@ class App {
 	}
 
 	function get_cached_avatar_image($avatar_image){
-		// Just remove the base url. This avoid mixed content
-		$avatar_image = normalise_link($avatar_image);
-		$base = normalise_link($this->get_baseurl());
-		$avatar_image = str_replace($base."/", "", $avatar_image);
 		return $avatar_image;
 
 		// The following code is deactivated. It doesn't seem to make any sense and it slows down the system.
@@ -951,6 +947,25 @@ class App {
 	}
 
 
+	/**
+	 * @brief Removes the baseurl from an url. This avoids some mixed content problems.
+	 *
+	 * @param string $url
+	 *
+	 * @return string The cleaned url
+	 */
+	function remove_baseurl($url){
+
+		// Is the function called statically?
+		if (!is_object($this))
+			return(self::$a->remove_baseurl($ssl));
+
+		$url = normalise_link($url);
+		$base = normalise_link($this->get_baseurl());
+		$url = str_replace($base."/", "", $url);
+		return $url;
+	}
+
 	/**
 	 * @brief Register template engine class
 	 * 
diff --git a/include/ForumManager.php b/include/ForumManager.php
index 73eb511de6..6fede0204d 100644
--- a/include/ForumManager.php
+++ b/include/ForumManager.php
@@ -89,7 +89,7 @@ class ForumManager {
 		if(count($contacts)) {
 
 			$id = 0;
-$a = get_app();
+
 			foreach($contacts as $contact) {
 
 				$selected = (($cid == $contact['id']) ? ' forum-selected' : '');
@@ -100,7 +100,7 @@ $a = get_app();
 					'name' => $contact['name'],
 					'cid' => $contact['id'],
 					'selected' 	=> $selected,
-					'micro' => $a->get_cached_avatar_image(proxy_url($contact['micro'], false, PROXY_SIZE_MICRO)),
+					'micro' => App::remove_baseurl(proxy_url($contact['micro'], false, PROXY_SIZE_MICRO)),
 					'id' => ++$id,
 				);
 				$entries[] = $entry;
diff --git a/include/conversation.php b/include/conversation.php
index 6c33be84fb..53a7b3d1ed 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -614,7 +614,7 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
 				if(($normalised != 'mailbox') && (x($a->contacts[$normalised])))
 					$profile_avatar = $a->contacts[$normalised]['thumb'];
 				else
-					$profile_avatar = ((strlen($item['author-avatar'])) ? $a->get_cached_avatar_image($item['author-avatar']) : $item['thumb']);
+					$profile_avatar = $a->remove_baseurl(((strlen($item['author-avatar'])) ? $item['author-avatar'] : $item['thumb']));
 
 				$locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
 				call_hooks('render_location',$locate);
diff --git a/include/identity.php b/include/identity.php
index ec66225d0f..aba69bae49 100644
--- a/include/identity.php
+++ b/include/identity.php
@@ -332,9 +332,9 @@ function profile_sidebar($profile, $block = 0) {
 		'fullname' => $profile['name'],
 		'firstname' => $firstname,
 		'lastname' => $lastname,
-		'photo300' => $a->get_cached_avatar_image($a->get_baseurl() . '/photo/custom/300/' . $profile['uid'] . '.jpg'),
-		'photo100' => $a->get_cached_avatar_image($a->get_baseurl() . '/photo/custom/100/' . $profile['uid'] . '.jpg'),
-		'photo50' => $a->get_cached_avatar_image($a->get_baseurl() . '/photo/custom/50/'  . $profile['uid'] . '.jpg'),
+		'photo300' => $a->get_baseurl() . '/photo/custom/300/' . $profile['uid'] . '.jpg',
+		'photo100' => $a->get_baseurl() . '/photo/custom/100/' . $profile['uid'] . '.jpg',
+		'photo50' => $a->get_baseurl() . '/photo/custom/50/'  . $profile['uid'] . '.jpg',
 	);
 
 	if (!$block){
diff --git a/include/nav.php b/include/nav.php
index fb7225af92..0fa671a27d 100644
--- a/include/nav.php
+++ b/include/nav.php
@@ -82,7 +82,7 @@ function nav_info(&$a) {
 		// user info
 		$r = q("SELECT micro FROM contact WHERE uid=%d AND self=1", intval($a->user['uid']));
 		$userinfo = array(
-			'icon' => (count($r) ? $a->get_cached_avatar_image($r[0]['micro']) : $a->get_baseurl($ssl_state)."/images/person-48.jpg"),
+			'icon' => (count($r) ? $a->remove_baseurl($r[0]['micro']) : "images/person-48.jpg"),
 			'name' => $a->user['username'],
 		);
 
diff --git a/index.php b/index.php
index 8471735d01..e364389b2c 100644
--- a/index.php
+++ b/index.php
@@ -371,7 +371,7 @@ $a->init_page_end();
 if(x($_SESSION,'visitor_home'))
 	$homebase = $_SESSION['visitor_home'];
 elseif(local_user())
-	$homebase = $a->get_baseurl() . '/profile/' . $a->user['nickname'];
+	$homebase = 'profile/' . $a->user['nickname'];
 
 if(isset($homebase))
 	$a->page['content'] .= '<script>var homebase="' . $homebase . '" ; </script>';
@@ -423,10 +423,10 @@ if($a->module != 'install' && $a->module != 'maintenance') {
 
 if($a->is_mobile || $a->is_tablet) {
 	if(isset($_SESSION['show-mobile']) && !$_SESSION['show-mobile']) {
-		$link = $a->get_baseurl() . '/toggle_mobile?address=' . curPageURL();
+		$link = 'toggle_mobile?address=' . curPageURL();
 	}
 	else {
-		$link = $a->get_baseurl() . '/toggle_mobile?off=1&address=' . curPageURL();
+		$link = 'toggle_mobile?off=1&address=' . curPageURL();
 	}
 	$a->page['footer'] = replace_macros(get_markup_template("toggle_mobile_footer.tpl"), array(
 	                     	'$toggle_link' => $link,
diff --git a/mod/content.php b/mod/content.php
index c5a5556116..c2b1546bf1 100644
--- a/mod/content.php
+++ b/mod/content.php
@@ -420,7 +420,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 				if(($normalised != 'mailbox') && (x($a->contacts[$normalised])))
 					$profile_avatar = $a->contacts[$normalised]['thumb'];
 				else
-					$profile_avatar = ((strlen($item['author-avatar'])) ? $a->get_cached_avatar_image($item['author-avatar']) : $item['thumb']);
+					$profile_avatar = $a->remove_baseurl(((strlen($item['author-avatar'])) ? $item['author-avatar'] : $item['thumb']));
 
 				$locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
 				call_hooks('render_location',$locate);
@@ -791,7 +791,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 				if(($normalised != 'mailbox') && (x($a->contacts,$normalised)))
 					$profile_avatar = $a->contacts[$normalised]['thumb'];
 				else
-					$profile_avatar = (((strlen($item['author-avatar'])) && $diff_author) ? $item['author-avatar'] : $a->get_cached_avatar_image($thumb));
+					$profile_avatar = $a->remove_baseurl(((strlen($item['author-avatar']) && $diff_author) ? $item['author-avatar'] : $thumb));
 
 				$like    = ((x($alike,$item['uri'])) ? format_like($alike[$item['uri']],$alike[$item['uri'] . '-l'],'like',$item['uri']) : '');
 				$dislike = ((x($dlike,$item['uri'])) ? format_like($dlike[$item['uri']],$dlike[$item['uri'] . '-l'],'dislike',$item['uri']) : '');
diff --git a/mod/directory.php b/mod/directory.php
index 294a55585d..be09dd37f6 100644
--- a/mod/directory.php
+++ b/mod/directory.php
@@ -158,14 +158,14 @@ function directory_content(&$a) {
 			else {
 				$location_e = $location;
 			}
-			
+
 			$photo_menu = array(array(t("View Profile"), zrl($profile_link)));
 
 			$entry = array(
 				'id' => $rr['id'],
 				'url' => $profile_link,
 				'itemurl' => $itemurl,
-				'thumb' => proxy_url($a->get_cached_avatar_image($rr[$photo]), false, PROXY_SIZE_THUMB),
+				'thumb' => proxy_url($rr[$photo], false, PROXY_SIZE_THUMB),
 				'img_hover' => $rr['name'],
 				'name' => $rr['name'],
 				'details' => $details,
diff --git a/mod/profiles.php b/mod/profiles.php
index 5c372de8ee..0b8261422f 100644
--- a/mod/profiles.php
+++ b/mod/profiles.php
@@ -16,7 +16,7 @@ function profiles_init(&$a) {
 		);
 		if(! count($r)) {
 			notice( t('Profile not found.') . EOL);
-			goaway($a->get_baseurl(true) . '/profiles');
+			goaway('profiles');
 			return; // NOTREACHED
 		}
 
@@ -34,9 +34,9 @@ function profiles_init(&$a) {
 			intval(local_user())
 		);
 		if($r)
-			info( t('Profile deleted.') . EOL);
+			info(t('Profile deleted.').EOL);
 
-		goaway($a->get_baseurl(true) . '/profiles');
+		goaway('profiles');
 		return; // NOTREACHED
 	}
 
@@ -73,9 +73,9 @@ function profiles_init(&$a) {
 
 		info( t('New profile created.') . EOL);
 		if(count($r3) == 1)
-			goaway($a->get_baseurl(true) . '/profiles/' . $r3[0]['id']);
+			goaway('profiles/'.$r3[0]['id']);
 
-		goaway($a->get_baseurl(true) . '/profiles');
+		goaway('profiles');
 	}
 
 	if(($a->argc > 2) && ($a->argv[1] === 'clone')) {
@@ -116,9 +116,9 @@ function profiles_init(&$a) {
 		);
 		info( t('New profile created.') . EOL);
 		if(count($r3) == 1)
-			goaway($a->get_baseurl(true) . '/profiles/' . $r3[0]['id']);
+			goaway('profiles/'.$r3[0]['id']);
 
-		goaway($a->get_baseurl(true) . '/profiles');
+		goaway('profiles');
 
 		return; // NOTREACHED
 	}
@@ -582,15 +582,7 @@ function profile_activity($changed, $value) {
 
 	$i = item_store($arr);
 	if($i) {
-
-		// give it a permanent link
-		//q("update item set plink = '%s' where id = %d",
-		//	dbesc($a->get_baseurl() . '/display/' . $a->user['nickname'] . '/' . $i),
-		//	intval($i)
-		//);
-
 	   	proc_run('php',"include/notifier.php","activity","$i");
-
 	}
 }
 
@@ -786,7 +778,7 @@ function profiles_content(&$a) {
 			);
 			if(count($r)){
 				//Go to the default profile.
-				goaway($a->get_baseurl(true) . '/profiles/'.$r[0]['id']);
+				goaway('profiles/'.$r[0]['id']);
 			}
 		}
 
@@ -807,12 +799,12 @@ function profiles_content(&$a) {
 
 			foreach($r as $rr) {
 				$o .= replace_macros($tpl, array(
-					'$photo' => $a->get_cached_avatar_image($rr['thumb']),
+					'$photo' => $a->remove_baseurl($rr['thumb']),
 					'$id' => $rr['id'],
 					'$alt' => t('Profile Image'),
 					'$profile_name' => $rr['profile-name'],
 					'$visible' => (($rr['is-default']) ? '<strong>' . t('visible to everybody') . '</strong>'
-						: '<a href="' . $a->get_baseurl(true) . '/profperm/' . $rr['id'] . '" />' . t('Edit visibility') . '</a>')
+						: '<a href="'.'profperm/'.$rr['id'].'" />' . t('Edit visibility') . '</a>')
 				));
 			}
 		}
diff --git a/object/Item.php b/object/Item.php
index 7b542c4724..9daf44648e 100644
--- a/object/Item.php
+++ b/object/Item.php
@@ -154,7 +154,7 @@ class Item extends BaseObject {
 		if(($normalised != 'mailbox') && (x($a->contacts,$normalised)))
 			$profile_avatar = $a->contacts[$normalised]['thumb'];
 		else
-			$profile_avatar = (((strlen($item['author-avatar'])) && $diff_author) ? $item['author-avatar'] : $a->get_cached_avatar_image($this->get_data_value('thumb')));
+			$profile_avatar = (((strlen($item['author-avatar'])) && $diff_author) ? $item['author-avatar'] : $a->remove_baseurl($this->get_data_value('thumb')));
 
 		$locate = array('location' => $item['location'], 'coord' => $item['coord'], 'html' => '');
 		call_hooks('render_location',$locate);
@@ -705,7 +705,7 @@ class Item extends BaseObject {
 				'$profile_uid' =>  $conv->get_profile_owner(),
 				'$mylink' => $a->contact['url'],
 				'$mytitle' => t('This is you'),
-				'$myphoto' => $a->get_cached_avatar_image($a->contact['thumb']),
+				'$myphoto' => $a->remove_baseurl($a->contact['thumb']),
 				'$comment' => t('Comment'),
 				'$submit' => t('Submit'),
 				'$edbold' => t('Bold'),
diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php
index 25954350f9..f33a9178ac 100644
--- a/view/theme/vier/theme.php
+++ b/view/theme/vier/theme.php
@@ -188,7 +188,7 @@ function vier_community_info() {
 				$entry = replace_macros($tpl,array(
 					'$id' => $rr['id'],
 					'$profile_link' => $profile_link,
-					'$photo' => $a->get_cached_avatar_image($rr['thumb']),
+					'$photo' => $a->remove_baseurl($rr['thumb']),
 					'$alt_text' => $rr['name']));
 				$aside['$lastusers_items'][] = $entry;
 			}

From 8af8567567e67af97871d12333d6d55c79c5a67d Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 17 Feb 2016 12:18:36 +0100
Subject: [PATCH 113/273] Some more ...

---
 boot.php | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/boot.php b/boot.php
index 851008aef5..69440e69d2 100644
--- a/boot.php
+++ b/boot.php
@@ -864,11 +864,11 @@ class App {
 
 		$shortcut_icon = get_config("system", "shortcut_icon");
 		if ($shortcut_icon == "")
-			$shortcut_icon = $this->get_baseurl()."/images/friendica-32.png";
+			$shortcut_icon = "images/friendica-32.png";
 
 		$touch_icon = get_config("system", "touch_icon");
 		if ($touch_icon == "")
-			$touch_icon = $this->get_baseurl()."/images/friendica-128.png";
+			$touch_icon = "images/friendica-128.png";
 
 		$tpl = get_markup_template('head.tpl');
 		$this->page['htmlhead'] = replace_macros($tpl,array(
@@ -1447,7 +1447,7 @@ function login($register = false, $hiddens=false) {
 
 	$noid = get_config('system','no_openid');
 
-	$dest_url = $a->get_baseurl(true) . '/' . $a->query_string;
+	$dest_url = $a->query_string;
 
 	if(local_user()) {
 		$tpl = get_markup_template("logout.tpl");
@@ -1766,9 +1766,9 @@ function current_theme_url() {
 
 	$opts = (($a->profile_uid) ? '?f=&puid=' . $a->profile_uid : '');
 	if (file_exists('view/theme/' . $t . '/style.php'))
-		return($a->get_baseurl() . '/view/theme/' . $t . '/style.pcss' . $opts);
+		return('view/theme/'.$t.'/style.pcss'.$opts);
 
-	return($a->get_baseurl() . '/view/theme/' . $t . '/style.css');
+	return('view/theme/'.$t.'/style.css');
 }
 
 function feed_birthday($uid,$tz) {

From e22d980e91c846bb9f3b3f09de4b1b830e256a13 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Wed, 17 Feb 2016 15:13:45 +0100
Subject: [PATCH 114/273] IT update to the strings

---
 view/it/messages.po | 14 +++++++-------
 view/it/strings.php | 12 ++++++------
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/view/it/messages.po b/view/it/messages.po
index b2b88bc72f..a9df298ca9 100644
--- a/view/it/messages.po
+++ b/view/it/messages.po
@@ -16,7 +16,7 @@ msgstr ""
 "Project-Id-Version: friendica\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2016-01-24 06:49+0100\n"
-"PO-Revision-Date: 2016-01-30 08:43+0000\n"
+"PO-Revision-Date: 2016-02-16 10:29+0000\n"
 "Last-Translator: Sandro Santilli <strk@keybit.net>\n"
 "Language-Team: Italian (http://www.transifex.com/Friendica/friendica/language/it/)\n"
 "MIME-Version: 1.0\n"
@@ -41,8 +41,8 @@ msgstr "Forum"
 #, php-format
 msgid "%d contact edited."
 msgid_plural "%d contacts edited."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d contatto modificato."
+msgstr[1] "%d contatti modificati"
 
 #: mod/contacts.php:159 mod/contacts.php:383
 msgid "Could not access contact record."
@@ -887,7 +887,7 @@ msgstr "Rimuovi"
 
 #: mod/ostatus_subscribe.php:14
 msgid "Subscribing to OStatus contacts"
-msgstr ""
+msgstr "Iscrizione a contatti OStatus"
 
 #: mod/ostatus_subscribe.php:25
 msgid "No contact provided."
@@ -1943,7 +1943,7 @@ msgstr "Ispeziona Coda di invio"
 
 #: mod/admin.php:163 mod/admin.php:354
 msgid "Federation Statistics"
-msgstr ""
+msgstr "Statistiche sulla Federazione"
 
 #: mod/admin.php:177 mod/admin.php:188 mod/admin.php:1792
 msgid "Logs"
@@ -1951,7 +1951,7 @@ msgstr "Log"
 
 #: mod/admin.php:178 mod/admin.php:1859
 msgid "View Logs"
-msgstr ""
+msgstr "Vedi i log"
 
 #: mod/admin.php:179
 msgid "probe address"
@@ -1982,7 +1982,7 @@ msgid ""
 "This page offers you some numbers to the known part of the federated social "
 "network your Friendica node is part of. These numbers are not complete but "
 "only reflect the part of the network your node is aware of."
-msgstr ""
+msgstr "Questa pagina offre alcuni numeri riguardo la porzione del social network federato di cui il tuo nodo Friendica fa parte. Questi numeri non sono completi ma riflettono esclusivamente la porzione di rete di cui il tuo nodo e' a conoscenza."
 
 #: mod/admin.php:348
 msgid ""
diff --git a/view/it/strings.php b/view/it/strings.php
index 606ae1e16c..131e03080b 100644
--- a/view/it/strings.php
+++ b/view/it/strings.php
@@ -8,8 +8,8 @@ function string_plural_select_it($n){
 $a->strings["Network:"] = "Rete:";
 $a->strings["Forum"] = "Forum";
 $a->strings["%d contact edited."] = array(
-	0 => "",
-	1 => "",
+	0 => "%d contatto modificato.",
+	1 => "%d contatti modificati",
 );
 $a->strings["Could not access contact record."] = "Non è possibile accedere al contatto.";
 $a->strings["Could not locate selected profile."] = "Non riesco a trovare il profilo selezionato.";
@@ -186,7 +186,7 @@ $a->strings["Tag removed"] = "Tag rimosso";
 $a->strings["Remove Item Tag"] = "Rimuovi il tag";
 $a->strings["Select a tag to remove: "] = "Seleziona un tag da rimuovere: ";
 $a->strings["Remove"] = "Rimuovi";
-$a->strings["Subscribing to OStatus contacts"] = "";
+$a->strings["Subscribing to OStatus contacts"] = "Iscrizione a contatti OStatus";
 $a->strings["No contact provided."] = "Nessun contatto disponibile.";
 $a->strings["Couldn't fetch information for contact."] = "Non è stato possibile recuperare le informazioni del contatto.";
 $a->strings["Couldn't fetch friends for contact."] = "Non è stato possibile recuperare gli amici del contatto.";
@@ -419,16 +419,16 @@ $a->strings["Themes"] = "Temi";
 $a->strings["Additional features"] = "Funzionalità aggiuntive";
 $a->strings["DB updates"] = "Aggiornamenti Database";
 $a->strings["Inspect Queue"] = "Ispeziona Coda di invio";
-$a->strings["Federation Statistics"] = "";
+$a->strings["Federation Statistics"] = "Statistiche sulla Federazione";
 $a->strings["Logs"] = "Log";
-$a->strings["View Logs"] = "";
+$a->strings["View Logs"] = "Vedi i log";
 $a->strings["probe address"] = "controlla indirizzo";
 $a->strings["check webfinger"] = "verifica webfinger";
 $a->strings["Admin"] = "Amministrazione";
 $a->strings["Plugin Features"] = "Impostazioni Plugins";
 $a->strings["diagnostics"] = "diagnostiche";
 $a->strings["User registrations waiting for confirmation"] = "Utenti registrati in attesa di conferma";
-$a->strings["This page offers you some numbers to the known part of the federated social network your Friendica node is part of. These numbers are not complete but only reflect the part of the network your node is aware of."] = "";
+$a->strings["This page offers you some numbers to the known part of the federated social network your Friendica node is part of. These numbers are not complete but only reflect the part of the network your node is aware of."] = "Questa pagina offre alcuni numeri riguardo la porzione del social network federato di cui il tuo nodo Friendica fa parte. Questi numeri non sono completi ma riflettono esclusivamente la porzione di rete di cui il tuo nodo e' a conoscenza.";
 $a->strings["The <em>Auto Discovered Contact Directory</em> feature is not enabled, it will improve the data displayed here."] = "";
 $a->strings["Administration"] = "Amministrazione";
 $a->strings["Currently this node is aware of %d nodes from the following platforms:"] = "";

From 7d4c99ebbc0ab4bd548fdd89680d5e75af4f85b9 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 17 Feb 2016 23:47:32 +0100
Subject: [PATCH 115/273] "get_baseurl" and "z_root" are disappearing ...

---
 boot.php                   |   2 +-
 include/conversation.php   |  22 ++---
 include/text.php           |  24 ++---
 mod/admin.php              | 186 ++++++++++++++++++-------------------
 mod/common.php             |   2 +-
 mod/contacts.php           |  52 +++++------
 mod/content.php            |   2 +-
 mod/directory.php          |   2 +-
 mod/message.php            |  18 ++--
 mod/notifications.php      |  16 ++--
 mod/photos.php             |  78 +++++++---------
 mod/search.php             |   2 +-
 mod/settings.php           |  26 +++---
 mod/uexport.php            |  62 ++-----------
 object/Item.php            |  10 +-
 view/templates/uexport.tpl |  18 ++--
 view/theme/vier/style.css  |   4 +-
 view/theme/vier/theme.php  |   6 +-
 18 files changed, 235 insertions(+), 297 deletions(-)

diff --git a/boot.php b/boot.php
index df4a1fdea2..d82669f231 100644
--- a/boot.php
+++ b/boot.php
@@ -949,7 +949,7 @@ class App {
 
 		// Is the function called statically?
 		if (!is_object($this))
-			return(self::$a->remove_baseurl($ssl));
+			return(self::$a->remove_baseurl($url));
 
 		$url = normalise_link($url);
 		$base = normalise_link($this->get_baseurl());
diff --git a/include/conversation.php b/include/conversation.php
index 53a7b3d1ed..a52502ec39 100644
--- a/include/conversation.php
+++ b/include/conversation.php
@@ -707,8 +707,8 @@ function conversation(&$a, $items, $mode, $update, $preview = false) {
 					'like' => '',
 					'dislike' => '',
 					'comment' => '',
-					//'conv' => (($preview) ? '' : array('href'=> $a->get_baseurl($ssl_state) . '/display/' . $nickname . '/' . $item['id'], 'title'=> t('View in context'))),
-					'conv' => (($preview) ? '' : array('href'=> $a->get_baseurl($ssl_state) . '/display/'.$item['guid'], 'title'=> t('View in context'))),
+					//'conv' => (($preview) ? '' : array('href'=> 'display/' . $nickname . '/' . $item['id'], 'title'=> t('View in context'))),
+					'conv' => (($preview) ? '' : array('href'=> 'display/'.$item['guid'], 'title'=> t('View in context'))),
 					'previewing' => $previewing,
 					'wait' => t('Please wait'),
 					'thread_level' => 1,
@@ -868,7 +868,7 @@ function item_photo_menu($item){
 		$status_link = $profile_link . "?url=status";
 		$photos_link = $profile_link . "?url=photos";
 		$profile_link = $profile_link . "?url=profile";
-		$pm_url = $a->get_baseurl($ssl_state) . '/message/new/' . $cid;
+		$pm_url = 'message/new/' . $cid;
 		$zurl = '';
 	}
 	else {
@@ -882,23 +882,23 @@ function item_photo_menu($item){
 				$cid = $r[0]["id"];
 
 				if ($r[0]["network"] == NETWORK_DIASPORA)
-					$pm_url = $a->get_baseurl($ssl_state) . '/message/new/' . $cid;
+					$pm_url = 'message/new/' . $cid;
 
 			} else
 				$cid = 0;
 		}
 	}
 	if(($cid) && (! $item['self'])) {
-		$poke_link = $a->get_baseurl($ssl_state) . '/poke/?f=&c=' . $cid;
-		$contact_url = $a->get_baseurl($ssl_state) . '/contacts/' . $cid;
-		$posts_link = $a->get_baseurl($ssl_state) . '/contacts/' . $cid . '/posts';
+		$poke_link = 'poke/?f=&c=' . $cid;
+		$contact_url = 'contacts/' . $cid;
+		$posts_link = 'contacts/' . $cid . '/posts';
 
 		$clean_url = normalise_link($item['author-link']);
 
 		if((local_user()) && (local_user() == $item['uid'])) {
 			if(isset($a->contacts) && x($a->contacts,$clean_url)) {
 				if($a->contacts[$clean_url]['network'] === NETWORK_DIASPORA) {
-					$pm_url = $a->get_baseurl($ssl_state) . '/message/new/' . $cid;
+					$pm_url = 'message/new/' . $cid;
 				}
 			}
 		}
@@ -921,7 +921,7 @@ function item_photo_menu($item){
 
 		if ((($cid == 0) OR ($a->contacts[$clean_url]['rel'] == CONTACT_IS_FOLLOWER)) AND
 			in_array($item['network'], array(NETWORK_DFRN, NETWORK_OSTATUS, NETWORK_DIASPORA)))
-			$menu[t("Connect/Follow")] = $a->get_baseurl($ssl_state)."/follow?url=".urlencode($item['author-link']);
+			$menu[t("Connect/Follow")] = "follow?url=".urlencode($item['author-link']);
 	} else
 		$menu = array(t("View Profile") => $item['author-link']);
 
@@ -980,7 +980,7 @@ function builtin_activity_puller($item, &$conv_responses) {
 		if((activity_match($item['verb'], $verb)) && ($item['id'] != $item['parent'])) {
 			$url = $item['author-link'];
 			if((local_user()) && (local_user() == $item['uid']) && ($item['network'] === NETWORK_DFRN) && (! $item['self']) && (link_compare($item['author-link'],$item['url']))) {
-				$url = z_root(true) . '/redir/' . $item['contact-id'];
+				$url = 'redir/' . $item['contact-id'];
 				$sparkle = ' class="sparkle" ';
 			}
 			else
@@ -1178,7 +1178,7 @@ function status_editor($a,$x, $notes_cid = 0, $popup=false) {
 
 	$o .= replace_macros($tpl,array(
 		'$return_path' => $query_str,
-		'$action' =>  $a->get_baseurl(true) . '/item',
+		'$action' =>  'item',
 		'$share' => (x($x,'button') ? $x['button'] : t('Share')),
 		'$upload' => t('Upload photo'),
 		'$shortupload' => t('upload photo'),
diff --git a/include/text.php b/include/text.php
index c7681a4d58..07524e851d 100644
--- a/include/text.php
+++ b/include/text.php
@@ -285,7 +285,7 @@ function paginate_data(&$a, $count=null) {
 	if (($a->page_offset != "") AND !preg_match('/[?&].offset=/', $stripped))
 		$stripped .= "&offset=".urlencode($a->page_offset);
 
-	$url = z_root() . '/' . $stripped;
+	$url = $stripped;
 
 	$data = array();
 	function _l(&$d, $name, $url, $text, $class="") {
@@ -923,7 +923,7 @@ function micropro($contact, $redirect = false, $class = '', $textmode = false) {
 
 	if($redirect) {
 		$a = get_app();
-		$redirect_url = z_root() . '/redir/' . $contact['id'];
+		$redirect_url = 'redir/' . $contact['id'];
 		if(local_user() && ($contact['uid'] == local_user()) && ($contact['network'] === NETWORK_DFRN)) {
 			$redir = true;
 			$url = $redirect_url;
@@ -964,13 +964,13 @@ if(! function_exists('search')) {
  * @param string $url search url
  * @param boolean $savedsearch show save search button
  */
-function search($s,$id='search-box',$url='/search',$save = false, $aside = true) {
+function search($s,$id='search-box',$url='search',$save = false, $aside = true) {
 	$a = get_app();
 
 	$values = array(
 			'$s' => $s,
 			'$id' => $id,
-			'$action_url' => $a->get_baseurl((stristr($url,'network')) ? true : false) . $url,
+			'$action_url' => $url,
 			'$search_label' => t('Search'),
 			'$save_label' => t('Save'),
 			'$savedsearch' => feature_enabled(local_user(),'savedsearch'),
@@ -1305,7 +1305,7 @@ function redir_private_images($a, &$item) {
 
 			if((local_user() == $item['uid']) && ($item['private'] != 0) && ($item['contact-id'] != $a->contact['id']) && ($item['network'] == NETWORK_DFRN)) {
 				//logger("redir_private_images: redir");
-				$img_url = z_root() . '/redir?f=1&quiet=1&url=' . $mtch[1] . '&conurl=' . $item['author-link'];
+				$img_url = 'redir?f=1&quiet=1&url=' . $mtch[1] . '&conurl=' . $item['author-link'];
 				$item['body'] = str_replace($mtch[0], "[img]".$img_url."[/img]", $item['body']);
 			}
 		}
@@ -1421,7 +1421,7 @@ function prepare_body(&$item,$attach = false, $preview = false) {
 					$mime = $mtch[3];
 
 					if((local_user() == $item['uid']) && ($item['contact-id'] != $a->contact['id']) && ($item['network'] == NETWORK_DFRN))
-						$the_url = z_root() . '/redir/' . $item['contact-id'] . '?f=1&url=' . $mtch[1];
+						$the_url = 'redir/' . $item['contact-id'] . '?f=1&url=' . $mtch[1];
 					else
 						$the_url = $mtch[1];
 
@@ -1596,7 +1596,7 @@ function get_cats_and_terms($item) {
 			$categories[] = array(
 				'name' => xmlify(file_tag_decode($mtch[1])),
 				'url' =>  "#",
-				'removeurl' => ((local_user() == $item['uid'])?z_root() . '/filerm/' . $item['id'] . '?f=&cat=' . xmlify(file_tag_decode($mtch[1])):""),
+				'removeurl' => ((local_user() == $item['uid'])?'filerm/' . $item['id'] . '?f=&cat=' . xmlify(file_tag_decode($mtch[1])):""),
 				'first' => $first,
 				'last' => false
 			);
@@ -1614,7 +1614,7 @@ function get_cats_and_terms($item) {
 				$folders[] = array(
 					'name' => xmlify(file_tag_decode($mtch[1])),
 					'url' =>  "#",
-					'removeurl' => ((local_user() == $item['uid'])?z_root() . '/filerm/' . $item['id'] . '?f=&term=' . xmlify(file_tag_decode($mtch[1])):""),
+					'removeurl' => ((local_user() == $item['uid'])?'filerm/' . $item['id'] . '?f=&term=' . xmlify(file_tag_decode($mtch[1])):""),
 					'first' => $first,
 					'last' => false
 				);
@@ -1639,15 +1639,15 @@ function get_plink($item) {
 
 	if ($a->user['nickname'] != "") {
 		$ret = array(
-				//'href' => z_root()."/display/".$a->user['nickname']."/".$item['id'],
-				'href' => z_root()."/display/".$item['guid'],
-				'orig' => z_root()."/display/".$item['guid'],
+				//'href' => "display/".$a->user['nickname']."/".$item['id'],
+				'href' => "display/".$item['guid'],
+				'orig' => "display/".$item['guid'],
 				'title' => t('View on separate page'),
 				'orig_title' => t('view on separate page'),
 			);
 
 		if (x($item,'plink')) {
-			$ret["href"] = $item['plink'];
+			$ret["href"] = $a->remove_baseurl($item['plink']);
 			$ret["title"] = t('link to source');
 		}
 
diff --git a/mod/admin.php b/mod/admin.php
index 7f9000807b..ecd08bbe00 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -55,13 +55,13 @@ function admin_post(&$a){
 							$func($a);
 						}
 				}
-				goaway($a->get_baseurl(true) . '/admin/plugins/' . $a->argv[2] );
+				goaway('admin/plugins/'.$a->argv[2]);
 				return; // NOTREACHED
 				break;
 			case 'themes':
 				if($a->argc < 2) {
 					if(is_ajax()) return;
-					goaway($a->get_baseurl(true) . '/admin/' );
+					goaway('admin/');
 					return;
 				}
 
@@ -92,7 +92,7 @@ function admin_post(&$a){
 				info(t('Theme settings updated.'));
 				if(is_ajax()) return;
 
-				goaway($a->get_baseurl(true) . '/admin/themes/' . $theme );
+				goaway('admin/themes/'.$theme);
 				return;
 				break;
 			case 'features':
@@ -107,7 +107,7 @@ function admin_post(&$a){
 		}
 	}
 
-	goaway($a->get_baseurl(true) . '/admin' );
+	goaway('admin');
 	return; // NOTREACHED
 }
 
@@ -150,17 +150,17 @@ function admin_content(&$a) {
 	 * Side bar links
 	 */
 	$aside_tools = array();
-	// array( url, name, extra css classes )
+	// array(url, name, extra css classes)
 	// not part of $aside to make the template more adjustable
 	$aside_sub = array(
-		'site'	 =>	array($a->get_baseurl(true)."/admin/site/", t("Site") , "site"),
-		'users'	 =>	array($a->get_baseurl(true)."/admin/users/", t("Users") , "users"),
-		'plugins'=>	array($a->get_baseurl(true)."/admin/plugins/", t("Plugins") , "plugins"),
-		'themes' =>	array($a->get_baseurl(true)."/admin/themes/", t("Themes") , "themes"),
-		'features' =>	array($a->get_baseurl(true)."/admin/features/", t("Additional features") , "features"),
-		'dbsync' => 	array($a->get_baseurl(true)."/admin/dbsync/", t('DB updates'), "dbsync"),
-		'queue'	 =>	array($a->get_baseurl(true)."/admin/queue/", t('Inspect Queue'), "queue"),
-		'federation' => array($a->get_baseurl(true)."/admin/federation/", t('Federation Statistics'), "federation"),
+		'site'	 =>	array("admin/site/", t("Site") , "site"),
+		'users'	 =>	array("admin/users/", t("Users") , "users"),
+		'plugins'=>	array("admin/plugins/", t("Plugins") , "plugins"),
+		'themes' =>	array("admin/themes/", t("Themes") , "themes"),
+		'features' =>	array("admin/features/", t("Additional features") , "features"),
+		'dbsync' => 	array("admin/dbsync/", t('DB updates'), "dbsync"),
+		'queue'	 =>	array("admin/queue/", t('Inspect Queue'), "queue"),
+		'federation' => array("admin/federation/", t('Federation Statistics'), "federation"),
 	);
 
 	/* get plugins admin page */
@@ -169,18 +169,18 @@ function admin_content(&$a) {
 	$aside_tools['plugins_admin']=array();
 	foreach ($r as $h){
 		$plugin =$h['name'];
-		$aside_tools['plugins_admin'][] = array($a->get_baseurl(true)."/admin/plugins/".$plugin, $plugin, "plugin");
+		$aside_tools['plugins_admin'][] = array("admin/plugins/".$plugin, $plugin, "plugin");
 		// temp plugins with admin
 		$a->plugins_admin[] = $plugin;
 	}
 
-	$aside_tools['logs'] = array($a->get_baseurl(true)."/admin/logs/", t("Logs"), "logs");
-	$aside_tools['viewlogs'] = array($a->get_baseurl(true)."/admin/viewlogs/", t("View Logs"), 'viewlogs');
-	$aside_tools['diagnostics_probe'] = array($a->get_baseurl(true).'/probe/', t('probe address'), 'probe');
-	$aside_tools['diagnostics_webfinger'] = array($a->get_baseurl(true).'/webfinger/', t('check webfinger'), 'webfinger');
+	$aside_tools['logs'] = array("admin/logs/", t("Logs"), "logs");
+	$aside_tools['viewlogs'] = array("admin/viewlogs/", t("View Logs"), 'viewlogs');
+	$aside_tools['diagnostics_probe'] = array('probe/', t('probe address'), 'probe');
+	$aside_tools['diagnostics_webfinger'] = array('webfinger/', t('check webfinger'), 'webfinger');
 
 	$t = get_markup_template("admin_aside.tpl");
-	$a->page['aside'] .= replace_macros( $t, array(
+	$a->page['aside'] .= replace_macros($t, array(
 		'$admin' => $aside_tools,
 		'$subpages' => $aside_sub,
 		'$admtxt' => t('Admin'),
@@ -188,7 +188,7 @@ function admin_content(&$a) {
 		'$logtxt' => t('Logs'),
 		'$diagnosticstxt' => t('diagnostics'),
 		'$h_pending' => t('User registrations waiting for confirmation'),
-		'$admurl'=> $a->get_baseurl(true)."/admin/"
+		'$admurl'=> "admin/"
 	));
 
 
@@ -231,7 +231,7 @@ function admin_content(&$a) {
 				$o = admin_page_federation($a);
 				break;
 			default:
-				notice( t("Item not found.") );
+				notice(t("Item not found."));
 		}
 	} else {
 		$o = admin_page_summary($a);
@@ -409,18 +409,18 @@ function admin_page_queue(&$a) {
 function admin_page_summary(&$a) {
 	$r = q("SELECT `page-flags`, COUNT(uid) as `count` FROM `user` GROUP BY `page-flags`");
 	$accounts = array(
-		array( t('Normal Account'), 0),
-		array( t('Soapbox Account'), 0),
-		array( t('Community/Celebrity Account'), 0),
-		array( t('Automatic Friend Account'), 0),
-		array( t('Blog Account'), 0),
-		array( t('Private Forum'), 0)
+		array(t('Normal Account'), 0),
+		array(t('Soapbox Account'), 0),
+		array(t('Community/Celebrity Account'), 0),
+		array(t('Automatic Friend Account'), 0),
+		array(t('Blog Account'), 0),
+		array(t('Private Forum'), 0)
 	);
 
 	$users=0;
 	foreach ($r as $u){ $accounts[$u['page-flags']][1] = $u['count']; $users+= $u['count']; }
 
-	logger('accounts: ' . print_r($accounts,true),LOGGER_DATA);
+	logger('accounts: '.print_r($accounts,true),LOGGER_DATA);
 
 	$r = q("SELECT COUNT(id) as `count` FROM `register`");
 	$pending = $r[0]['count'];
@@ -433,7 +433,7 @@ function admin_page_summary(&$a) {
 
 	// We can do better, but this is a quick queue status
 
-	$queues = array( 'label' => t('Message queues'), 'deliverq' => $deliverq, 'queue' => $queue );
+	$queues = array('label' => t('Message queues'), 'deliverq' => $deliverq, 'queue' => $queue);
 
 
 	$t = get_markup_template("admin_summary.tpl");
@@ -441,15 +441,15 @@ function admin_page_summary(&$a) {
 		'$title' => t('Administration'),
 		'$page' => t('Summary'),
 		'$queues' => $queues,
-		'$users' => array( t('Registered users'), $users),
+		'$users' => array(t('Registered users'), $users),
 		'$accounts' => $accounts,
-		'$pending' => array( t('Pending registrations'), $pending),
-		'$version' => array( t('Version'), FRIENDICA_VERSION),
+		'$pending' => array(t('Pending registrations'), $pending),
+		'$version' => array(t('Version'), FRIENDICA_VERSION),
 		'$baseurl' => $a->get_baseurl(),
 		'$platform' => FRIENDICA_PLATFORM,
 		'$codename' => FRIENDICA_CODENAME,
 		'$build' =>  get_config('system','build'),
-		'$plugins' => array( t('Active plugins'), $a->plugins )
+		'$plugins' => array(t('Active plugins'), $a->plugins)
 	));
 }
 
@@ -473,7 +473,7 @@ function admin_page_site_post(&$a) {
 		$parsed = @parse_url($new_url);
 		if(!$parsed || (!x($parsed,'host') || !x($parsed,'scheme'))) {
 			notice(t("Can not parse base url. Must have at least <scheme>://<domain>"));
-			goaway($a->get_baseurl(true) . '/admin/site' );
+			goaway('admin/site');
 		}
 
 		/* steps:
@@ -501,8 +501,8 @@ function admin_page_site_post(&$a) {
 			$q = sprintf("UPDATE %s SET %s;", $table_name, $upds);
 			$r = q($q);
 			if(!$r) {
-				notice( "Failed updating '$table_name': " . $db->error );
-				goaway($a->get_baseurl(true) . '/admin/site' );
+				notice("Failed updating '$table_name': ".$db->error);
+				goaway('admin/site');
 			}
 		}
 
@@ -526,7 +526,7 @@ function admin_page_site_post(&$a) {
 
 		info("Relocation started. Could take a while to complete.");
 
-		goaway($a->get_baseurl(true) . '/admin/site' );
+		goaway('admin/site');
 	}
 	// end relocate
 
@@ -695,12 +695,12 @@ function admin_page_site_post(&$a) {
 	set_config('system','language', $language);
 	set_config('system','theme', $theme);
 
-	if( $theme_mobile === '---' ) {
+	if($theme_mobile === '---') {
 		del_config('system','mobile-theme');
 	} else {
 		set_config('system','mobile-theme', $theme_mobile);
 		}
-		if( $singleuser === '---' ) {
+		if($singleuser === '---') {
 			del_config('system','singleuser');
 		} else {
 			set_config('system','singleuser', $singleuser);
@@ -765,8 +765,8 @@ function admin_page_site_post(&$a) {
 	set_config('system','embedly', $embedly);
 
 
-	info( t('Site settings updated.') . EOL);
-	goaway($a->get_baseurl(true) . '/admin/site' );
+	info(t('Site settings updated.').EOL);
+	goaway('admin/site');
 	return; // NOTREACHED
 
 }
@@ -797,12 +797,12 @@ function admin_page_site(&$a) {
 	$files = glob('view/theme/*');
 	if($files) {
 		foreach($files as $file) {
-			if(intval(file_exists($file . '/unsupported')))
+			if(intval(file_exists($file.'/unsupported')))
 				continue;
 
 			$f = basename($file);
-			$theme_name = ((file_exists($file . '/experimental')) ?  sprintf("%s - \x28Experimental\x29", $f) : $f);
-			if(file_exists($file . '/mobile')) {
+			$theme_name = ((file_exists($file.'/experimental')) ?  sprintf("%s - \x28Experimental\x29", $f) : $f);
+			if(file_exists($file.'/mobile')) {
 				$theme_choices_mobile[$f] = $theme_name;
 			} else {
 				$theme_choices[$f] = $theme_name;
@@ -1003,12 +1003,12 @@ function admin_page_dbsync(&$a) {
 	$o = '';
 
 	if($a->argc > 3 && intval($a->argv[3]) && $a->argv[2] === 'mark') {
-		set_config('database', 'update_' . intval($a->argv[3]), 'success');
+		set_config('database', 'update_'.intval($a->argv[3]), 'success');
 		$curr = get_config('system','build');
 		if(intval($curr) == intval($a->argv[3]))
 			set_config('system','build',intval($curr) + 1);
-		info( t('Update has been marked successful') . EOL);
-		goaway($a->get_baseurl(true) . '/admin/dbsync');
+		info(t('Update has been marked successful').EOL);
+		goaway('admin/dbsync');
 	}
 
 	if(($a->argc > 2) AND (intval($a->argv[2]) OR ($a->argv[2] === 'check'))) {
@@ -1026,7 +1026,7 @@ function admin_page_dbsync(&$a) {
 
 	if($a->argc > 2 && intval($a->argv[2])) {
 		require_once('update.php');
-		$func = 'update_' . intval($a->argv[2]);
+		$func = 'update_'.intval($a->argv[2]);
 		if(function_exists($func)) {
 			$retval = $func();
 			if($retval === UPDATE_FAILED) {
@@ -1082,18 +1082,18 @@ function admin_page_dbsync(&$a) {
  * @param App $a
  */
 function admin_page_users_post(&$a){
-	$pending	=	( x($_POST, 'pending')			? $_POST['pending']		: array() );
-	$users		=	( x($_POST, 'user')			? $_POST['user']		: array() );
-	$nu_name	=	( x($_POST, 'new_user_name')		? $_POST['new_user_name']	: '');
-	$nu_nickname	=	( x($_POST, 'new_user_nickname')	? $_POST['new_user_nickname']	: '');
-	$nu_email	=	( x($_POST, 'new_user_email')		? $_POST['new_user_email']	: '');
+	$pending	=	(x($_POST, 'pending')			? $_POST['pending']		: array());
+	$users		=	(x($_POST, 'user')			? $_POST['user']		: array());
+	$nu_name	=	(x($_POST, 'new_user_name')		? $_POST['new_user_name']	: '');
+	$nu_nickname	=	(x($_POST, 'new_user_nickname')	? $_POST['new_user_nickname']	: '');
+	$nu_email	=	(x($_POST, 'new_user_email')		? $_POST['new_user_email']	: '');
 
 	check_form_security_token_redirectOnErr('/admin/users', 'admin_users');
 
 	if(!($nu_name==="") && !($nu_email==="") && !($nu_nickname==="")) {
 		require_once('include/user.php');
 
-		$result = create_user( array('username'=>$nu_name, 'email'=>$nu_email, 'nickname'=>$nu_nickname, 'verified'=>1)  );
+		$result = create_user(array('username'=>$nu_name, 'email'=>$nu_email, 'nickname'=>$nu_nickname, 'verified'=>1));
 		if(! $result['success']) {
 			notice($result['message']);
 			return;
@@ -1134,7 +1134,7 @@ function admin_page_users_post(&$a){
 		notification(array(
 			'type' => "SYSTEM_EMAIL",
 			'to_email' => $nu['email'],
-			'subject'=> sprintf( t('Registration details for %s'), $a->config['sitename']),
+			'subject'=> sprintf(t('Registration details for %s'), $a->config['sitename']),
 			'preamble'=> $preamble,
 			'body' => $body));
 
@@ -1143,17 +1143,17 @@ function admin_page_users_post(&$a){
 	if(x($_POST,'page_users_block')) {
 		foreach($users as $uid){
 			q("UPDATE `user` SET `blocked`=1-`blocked` WHERE `uid`=%s",
-				intval( $uid )
+				intval($uid)
 			);
 		}
-		notice( sprintf( tt("%s user blocked/unblocked", "%s users blocked/unblocked", count($users)), count($users)) );
+		notice(sprintf(tt("%s user blocked/unblocked", "%s users blocked/unblocked", count($users)), count($users)));
 	}
 	if(x($_POST,'page_users_delete')) {
 		require_once("include/Contact.php");
 		foreach($users as $uid){
 			user_remove($uid);
 		}
-		notice( sprintf( tt("%s user deleted", "%s users deleted", count($users)), count($users)) );
+		notice(sprintf(tt("%s user deleted", "%s users deleted", count($users)), count($users)));
 	}
 
 	if(x($_POST,'page_users_approve')) {
@@ -1168,7 +1168,7 @@ function admin_page_users_post(&$a){
 			user_deny($hash);
 		}
 	}
-	goaway($a->get_baseurl(true) . '/admin/users' );
+	goaway('admin/users');
 	return; // NOTREACHED
 }
 
@@ -1189,8 +1189,8 @@ function admin_page_users(&$a){
 		$uid = $a->argv[3];
 		$user = q("SELECT username, blocked FROM `user` WHERE `uid`=%d", intval($uid));
 		if(count($user)==0) {
-			notice( 'User not found' . EOL);
-			goaway($a->get_baseurl(true) . '/admin/users' );
+			notice('User not found'.EOL);
+			goaway('admin/users');
 			return ''; // NOTREACHED
 		}
 		switch($a->argv[2]){
@@ -1200,18 +1200,18 @@ function admin_page_users(&$a){
 				require_once("include/Contact.php");
 				user_remove($uid);
 
-				notice( sprintf(t("User '%s' deleted"), $user[0]['username']) . EOL);
+				notice(sprintf(t("User '%s' deleted"), $user[0]['username']).EOL);
 			}; break;
 			case "block":{
 				check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't');
 				q("UPDATE `user` SET `blocked`=%d WHERE `uid`=%s",
-					intval( 1-$user[0]['blocked'] ),
-					intval( $uid )
+					intval(1-$user[0]['blocked']),
+					intval($uid)
 				);
-				notice( sprintf( ($user[0]['blocked']?t("User '%s' unblocked"):t("User '%s' blocked")) , $user[0]['username']) . EOL);
+				notice(sprintf(($user[0]['blocked']?t("User '%s' unblocked"):t("User '%s' blocked")) , $user[0]['username']).EOL);
 			}; break;
 		}
-		goaway($a->get_baseurl(true) . '/admin/users' );
+		goaway('admin/users');
 		return ''; // NOTREACHED
 
 	}
@@ -1230,7 +1230,7 @@ function admin_page_users(&$a){
 		$a->set_pager_itemspage(100);
 	}
 
-	$users = q("SELECT `user` . * , `contact`.`name` , `contact`.`url` , `contact`.`micro`, `lastitem`.`lastitem_date`, `user`.`account_expired`
+	$users = q("SELECT `user`.* , `contact`.`name` , `contact`.`url` , `contact`.`micro`, `lastitem`.`lastitem_date`, `user`.`account_expired`
 				FROM
 					(SELECT MAX(`item`.`changed`) as `lastitem_date`, `item`.`uid`
 					FROM `item`
@@ -1277,7 +1277,7 @@ function admin_page_users(&$a){
 
 	while(count($users)) {
 		$new_user = array();
-		foreach( array_pop($users) as $k => $v) {
+		foreach(array_pop($users) as $k => $v) {
 			$k = str_replace('-','_',$k);
 			$new_user[$k] = $v;
 		}
@@ -1303,7 +1303,7 @@ function admin_page_users(&$a){
 		'$select_all' => t('select all'),
 		'$h_pending' => t('User registrations waiting for confirm'),
 		'$h_deleted' => t('User waiting for permanent deletion'),
-		'$th_pending' => array( t('Request date'), t('Name'), t('Email') ),
+		'$th_pending' => array(t('Request date'), t('Name'), t('Email')),
 		'$no_pending' =>  t('No registrations.'),
 		'$approve' => t('Approve'),
 		'$deny' => t('Deny'),
@@ -1315,8 +1315,8 @@ function admin_page_users(&$a){
 
 		'$h_users' => t('Users'),
 		'$h_newuser' => t('New User'),
-		'$th_deleted' => array( t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'), t('Deleted since') ),
-		'$th_users' => array( t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'),  t('Account') ),
+		'$th_deleted' => array(t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'), t('Deleted since')),
+		'$th_users' => array(t('Name'), t('Email'), t('Register date'), t('Last login'), t('Last item'),  t('Account')),
 
 		'$confirm_delete_multi' => t('Selected users will be deleted!\n\nEverything these users had posted on this site will be permanently deleted!\n\nAre you sure?'),
 		'$confirm_delete' => t('The user {0} will be deleted!\n\nEverything this user has posted on this site will be permanently deleted!\n\nAre you sure?'),
@@ -1362,7 +1362,7 @@ function admin_page_plugins(&$a){
 	if($a->argc == 3) {
 		$plugin = $a->argv[2];
 		if(!is_file("addon/$plugin/$plugin.php")) {
-			notice( t("Item not found.") );
+			notice(t("Item not found."));
 			return '';
 		}
 
@@ -1374,14 +1374,14 @@ function admin_page_plugins(&$a){
 			if($idx !== false) {
 				unset($a->plugins[$idx]);
 				uninstall_plugin($plugin);
-				info( sprintf( t("Plugin %s disabled."), $plugin ) );
+				info(sprintf(t("Plugin %s disabled."), $plugin));
 			} else {
 				$a->plugins[] = $plugin;
 				install_plugin($plugin);
-				info( sprintf( t("Plugin %s enabled."), $plugin ) );
+				info(sprintf(t("Plugin %s enabled."), $plugin));
 			}
 			set_config("system","addon", implode(", ",$a->plugins));
-			goaway($a->get_baseurl(true) . '/admin/plugins' );
+			goaway('admin/plugins');
 			return ''; // NOTREACHED
 		}
 
@@ -1480,7 +1480,7 @@ function admin_page_plugins(&$a){
 		'$function' => 'plugins',
 		'$plugins' => $plugins,
 		'$pcount' => count($plugins), 
-		'$noplugshint' => sprintf( t('There are currently no plugins available on your node. You can find the official plugin repository at %1$s and might find other interesting plugins in the open plugin registry at %2$s'), 'https://github.com/friendica/friendica-addons', 'http://addons.friendi.ca'),
+		'$noplugshint' => sprintf(t('There are currently no plugins available on your node. You can find the official plugin repository at %1$s and might find other interesting plugins in the open plugin registry at %2$s'), 'https://github.com/friendica/friendica-addons', 'http://addons.friendi.ca'),
 		'$form_security_token' => get_form_security_token("admin_themes"),
 	));
 }
@@ -1575,8 +1575,8 @@ function admin_page_themes(&$a){
 	if($files) {
 		foreach($files as $file) {
 			$f = basename($file);
-			$is_experimental = intval(file_exists($file . '/experimental'));
-			$is_supported = 1-(intval(file_exists($file . '/unsupported')));
+			$is_experimental = intval(file_exists($file.'/experimental'));
+			$is_supported = 1-(intval(file_exists($file.'/unsupported')));
 			$is_allowed = intval(in_array($f,$allowed_themes));
 
 			if($is_allowed OR $is_supported OR get_config("system", "show_unsupported_themes"))
@@ -1585,7 +1585,7 @@ function admin_page_themes(&$a){
 	}
 
 	if(! count($themes)) {
-		notice( t('No themes found.'));
+		notice(t('No themes found.'));
 		return '';
 	}
 
@@ -1596,7 +1596,7 @@ function admin_page_themes(&$a){
 	if($a->argc == 3) {
 		$theme = $a->argv[2];
 		if(! is_dir("view/theme/$theme")) {
-			notice( t("Item not found.") );
+			notice(t("Item not found."));
 			return '';
 		}
 
@@ -1609,15 +1609,15 @@ function admin_page_themes(&$a){
 			$s = rebuild_theme_table($themes);
 			if($result) {
 				install_theme($theme);
-				info( sprintf('Theme %s enabled.',$theme));
+				info(sprintf('Theme %s enabled.',$theme));
 			}
 			else {
 				uninstall_theme($theme);
-				info( sprintf('Theme %s disabled.',$theme));
+				info(sprintf('Theme %s disabled.',$theme));
 			}
 
 			set_config('system','allowed_themes',$s);
-			goaway($a->get_baseurl(true) . '/admin/themes' );
+			goaway('admin/themes');
 			return ''; // NOTREACHED
 		}
 
@@ -1663,7 +1663,7 @@ function admin_page_themes(&$a){
 			$admin_form = __get_theme_admin_form($a, $theme);
 		}
 
-		$screenshot = array( get_theme_screenshot($theme), t('Screenshot'));
+		$screenshot = array(get_theme_screenshot($theme), t('Screenshot'));
 		if(! stristr($screenshot[0],$theme))
 			$screenshot = null;
 
@@ -1754,8 +1754,8 @@ function admin_page_logs_post(&$a) {
 		set_config('system','loglevel', $loglevel);
 	}
 
-	info( t("Log settings updated.") );
-	goaway($a->get_baseurl(true) . '/admin/logs' );
+	info(t("Log settings updated."));
+	goaway('admin/logs');
 	return; // NOTREACHED
 }
 
@@ -1803,7 +1803,7 @@ function admin_page_logs(&$a){
 		'$form_security_token' => get_form_security_token("admin_logs"),
 		'$phpheader' => t("PHP logging"),
 		'$phphint' => t("To enable logging of PHP errors and warnings you can add the following to the .htconfig.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."),
-		'$phplogcode' => "error_reporting(E_ERROR | E_WARNING | E_PARSE );\nini_set('error_log','php.out');\nini_set('log_errors','1');\nini_set('display_errors', '1');",
+		'$phplogcode' => "error_reporting(E_ERROR | E_WARNING | E_PARSE);\nini_set('error_log','php.out');\nini_set('log_errors','1');\nini_set('display_errors', '1');",
 	));
 }
 
@@ -1871,7 +1871,7 @@ function admin_page_features_post(&$a) {
 
 	check_form_security_token_redirectOnErr('/admin/features', 'admin_manage_features');
 
-	logger('postvars: ' . print_r($_POST,true),LOGGER_DATA);
+	logger('postvars: '.print_r($_POST,true),LOGGER_DATA);
 
 	$arr = array();
 	$features = get_features(false);
@@ -1879,11 +1879,11 @@ function admin_page_features_post(&$a) {
 	foreach($features as $fname => $fdata) {
 		foreach(array_slice($fdata,1) as $f) {
 			$feature = $f[0];
-			$feature_state = 'feature_' . $feature;
-			$featurelock = 'featurelock_' . $feature;
+			$feature_state = 'feature_'.$feature;
+			$featurelock = 'featurelock_'.$feature;
 
 			if(x($_POST[$feature_state]))
-				$val = intval($_POST['feature_' . $feature]);
+				$val = intval($_POST['feature_'.$feature]);
 			else
 				$val = 0;
 			set_config('feature',$feature,$val);
@@ -1895,7 +1895,7 @@ function admin_page_features_post(&$a) {
 		}
 	}
 
-	goaway($a->get_baseurl(true) . '/admin/features' );
+	goaway('admin/features');
 	return; // NOTREACHED
 }
 
@@ -1929,7 +1929,7 @@ function admin_page_features(&$a) {
 					$set = $f[3];
 				$arr[$fname][1][] = array(
 					array('feature_' .$f[0],$f[1],$set,$f[2],array(t('Off'),t('On'))),
-					array('featurelock_' .$f[0],sprintf( t('Lock feature %s'),$f[1]),(($f[4] !== false) ? "1" : ''),'',array(t('Off'),t('On')))
+					array('featurelock_' .$f[0],sprintf(t('Lock feature %s'),$f[1]),(($f[4] !== false) ? "1" : ''),'',array(t('Off'),t('On')))
 				);
 			}
 		}
diff --git a/mod/common.php b/mod/common.php
index c9409b3ef1..62a5185fed 100644
--- a/mod/common.php
+++ b/mod/common.php
@@ -40,7 +40,7 @@ function common_content(&$a) {
 		$vcard_widget .= replace_macros(get_markup_template("vcard-widget.tpl"),array(
 			'$name' => htmlentities($c[0]['name']),
 			'$photo' => $c[0]['photo'],
-			'url' => z_root() . '/contacts/' . $cid
+			'url' => 'contacts/' . $cid
 		));
 
 		if(! x($a->page,'aside'))
diff --git a/mod/contacts.php b/mod/contacts.php
index 0b421433e0..7f758b43c5 100644
--- a/mod/contacts.php
+++ b/mod/contacts.php
@@ -44,7 +44,7 @@ function contacts_init(&$a) {
 			$vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"),array(
 				'$name' => htmlentities($a->data['contact']['name']),
 				'$photo' => $a->data['contact']['photo'],
-				'$url' => ($a->data['contact']['network'] == NETWORK_DFRN) ? z_root()."/redir/".$a->data['contact']['id'] : $a->data['contact']['url'],
+				'$url' => ($a->data['contact']['network'] == NETWORK_DFRN) ? "redir/".$a->data['contact']['id'] : $a->data['contact']['url'],
 				'$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""),
 				'$network_name' => $networkname,
 				'$network' => t('Network:'),
@@ -129,9 +129,9 @@ function contacts_batch_actions(&$a){
 	}
 
 	if(x($_SESSION,'return_url'))
-		goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']);
+		goaway('' . $_SESSION['return_url']);
 	else
-		goaway($a->get_baseurl(true) . '/contacts');
+		goaway('contacts');
 
 }
 
@@ -157,7 +157,7 @@ function contacts_post(&$a) {
 
 	if(! count($orig_record)) {
 		notice( t('Could not access contact record.') . EOL);
-		goaway($a->get_baseurl(true) . '/contacts');
+		goaway('contacts');
 		return; // NOTREACHED
 	}
 
@@ -366,19 +366,19 @@ function contacts_content(&$a) {
 
 		if(! count($orig_record)) {
 			notice( t('Could not access contact record.') . EOL);
-			goaway($a->get_baseurl(true) . '/contacts');
+			goaway('contacts');
 			return; // NOTREACHED
 		}
 
 		if($cmd === 'update') {
 			_contact_update($contact_id);
-			goaway($a->get_baseurl(true) . '/contacts/' . $contact_id);
+			goaway('contacts/' . $contact_id);
 			// NOTREACHED
 		}
 
 		if($cmd === 'updateprofile') {
 			_contact_update_profile($contact_id);
-			goaway($a->get_baseurl(true) . '/crepair/' . $contact_id);
+			goaway('crepair/' . $contact_id);
 			// NOTREACHED
 		}
 
@@ -389,7 +389,7 @@ function contacts_content(&$a) {
 				info((($blocked) ? t('Contact has been blocked') : t('Contact has been unblocked')).EOL);
 			}
 
-			goaway($a->get_baseurl(true) . '/contacts/' . $contact_id);
+			goaway('contacts/' . $contact_id);
 			return; // NOTREACHED
 		}
 
@@ -400,7 +400,7 @@ function contacts_content(&$a) {
 				info((($readonly) ? t('Contact has been ignored') : t('Contact has been unignored')).EOL);
 			}
 
-			goaway($a->get_baseurl(true) . '/contacts/' . $contact_id);
+			goaway('contacts/' . $contact_id);
 			return; // NOTREACHED
 		}
 
@@ -412,7 +412,7 @@ function contacts_content(&$a) {
 				info((($archived) ? t('Contact has been archived') : t('Contact has been unarchived')).EOL);
 			}
 
-			goaway($a->get_baseurl(true) . '/contacts/' . $contact_id);
+			goaway('contacts/' . $contact_id);
 			return; // NOTREACHED
 		}
 
@@ -447,17 +447,17 @@ function contacts_content(&$a) {
 			// Now check how the user responded to the confirmation query
 			if($_REQUEST['canceled']) {
 				if(x($_SESSION,'return_url'))
-					goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']);
+					goaway('' . $_SESSION['return_url']);
 				else
-					goaway($a->get_baseurl(true) . '/contacts');
+					goaway('contacts');
 			}
 
 			_contact_drop($contact_id, $orig_record[0]);
 			info( t('Contact has been removed.') . EOL );
 			if(x($_SESSION,'return_url'))
-				goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']);
+				goaway('' . $_SESSION['return_url']);
 			else
-				goaway($a->get_baseurl(true) . '/contacts');
+				goaway('contacts');
 			return; // NOTREACHED
 		}
 		if($cmd === 'posts') {
@@ -575,7 +575,7 @@ function contacts_content(&$a) {
 			'$lbl_info1' => t('Contact Information / Notes'),
 			'$infedit' => t('Edit contact notes'),
 			'$common_text' => $common_text,
-			'$common_link' => $a->get_baseurl(true) . '/common/loc/' . local_user() . '/' . $contact['id'],
+			'$common_link' => 'common/loc/' . local_user() . '/' . $contact['id'],
 			'$all_friends' => $all_friends,
 			'$relation_text' => $relation_text,
 			'$visit' => sprintf( t('Visit %s\'s profile [%s]'),$contact['name'],$contact['url']),
@@ -668,7 +668,7 @@ function contacts_content(&$a) {
 	$tabs = array(
 		array(
 			'label' => t('Suggestions'),
-			'url'   => $a->get_baseurl(true) . '/suggest',
+			'url'   => 'suggest',
 			'sel'   => '',
 			'title' => t('Suggest potential friends'),
 			'id'	=> 'suggestions-tab',
@@ -676,7 +676,7 @@ function contacts_content(&$a) {
 		),
 		array(
 			'label' => t('All Contacts'),
-			'url'   => $a->get_baseurl(true) . '/contacts/all',
+			'url'   => 'contacts/all',
 			'sel'   => ($all) ? 'active' : '',
 			'title' => t('Show all contacts'),
 			'id'	=> 'showall-tab',
@@ -684,7 +684,7 @@ function contacts_content(&$a) {
 		),
 		array(
 			'label' => t('Unblocked'),
-			'url'   => $a->get_baseurl(true) . '/contacts',
+			'url'   => 'contacts',
 			'sel'   => ((! $all) && (! $blocked) && (! $hidden) && (! $search) && (! $nets) && (! $ignored) && (! $archived)) ? 'active' : '',
 			'title' => t('Only show unblocked contacts'),
 			'id'	=> 'showunblocked-tab',
@@ -693,7 +693,7 @@ function contacts_content(&$a) {
 
 		array(
 			'label' => t('Blocked'),
-			'url'   => $a->get_baseurl(true) . '/contacts/blocked',
+			'url'   => 'contacts/blocked',
 			'sel'   => ($blocked) ? 'active' : '',
 			'title' => t('Only show blocked contacts'),
 			'id'	=> 'showblocked-tab',
@@ -702,7 +702,7 @@ function contacts_content(&$a) {
 
 		array(
 			'label' => t('Ignored'),
-			'url'   => $a->get_baseurl(true) . '/contacts/ignored',
+			'url'   => 'contacts/ignored',
 			'sel'   => ($ignored) ? 'active' : '',
 			'title' => t('Only show ignored contacts'),
 			'id'	=> 'showignored-tab',
@@ -711,7 +711,7 @@ function contacts_content(&$a) {
 
 		array(
 			'label' => t('Archived'),
-			'url'   => $a->get_baseurl(true) . '/contacts/archived',
+			'url'   => 'contacts/archived',
 			'sel'   => ($archived) ? 'active' : '',
 			'title' => t('Only show archived contacts'),
 			'id'	=> 'showarchived-tab',
@@ -720,7 +720,7 @@ function contacts_content(&$a) {
 
 		array(
 			'label' => t('Hidden'),
-			'url'   => $a->get_baseurl(true) . '/contacts/hidden',
+			'url'   => 'contacts/hidden',
 			'sel'   => ($hidden) ? 'active' : '',
 			'title' => t('Only show hidden contacts'),
 			'id'	=> 'showhidden-tab',
@@ -840,7 +840,7 @@ function contacts_tab($a, $contact_id, $active_tab) {
 				'accesskey' => 'd');
 
 	$tabs[] = array('label' => t('Repair'),
-			'url'   => $a->get_baseurl(true) . '/crepair/' . $contact_id,
+			'url'   => 'crepair/' . $contact_id,
 			'sel' => (($active_tab == 5)?'active':''),
 			'title' => t('Advanced Contact Settings'),
 			'id'	=> 'repair-tab',
@@ -848,21 +848,21 @@ function contacts_tab($a, $contact_id, $active_tab) {
 
 
 	$tabs[] = array('label' => (($contact['blocked']) ? t('Unblock') : t('Block') ),
-			'url'   => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/block',
+			'url'   => 'contacts/' . $contact_id . '/block',
 			'sel'   => '',
 			'title' => t('Toggle Blocked status'),
 			'id'	=> 'toggle-block-tab',
 			'accesskey' => 'b');
 
 	$tabs[] = array('label' => (($contact['readonly']) ? t('Unignore') : t('Ignore') ),
-			'url'   => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/ignore',
+			'url'   => 'contacts/' . $contact_id . '/ignore',
 			'sel'   => '',
 			'title' => t('Toggle Ignored status'),
 			'id'	=> 'toggle-ignore-tab',
 			'accesskey' => 'i');
 
 	$tabs[] = array('label' => (($contact['archive']) ? t('Unarchive') : t('Archive') ),
-			'url'   => $a->get_baseurl(true) . '/contacts/' . $contact_id . '/archive',
+			'url'   => 'contacts/' . $contact_id . '/archive',
 			'sel'   => '',
 			'title' => t('Toggle Archive status'),
 			'id'	=> 'toggle-archive-tab',
diff --git a/mod/content.php b/mod/content.php
index c2b1546bf1..49cff74d2d 100644
--- a/mod/content.php
+++ b/mod/content.php
@@ -615,7 +615,7 @@ function render_content(&$a, $items, $mode, $update, $preview = false) {
 					$comment_lastcollapsed = true;
 				}
 
-				$redirect_url = $a->get_baseurl($ssl_state) . '/redir/' . $item['cid'] ;
+				$redirect_url = 'redir/' . $item['cid'] ;
 
 				$lock = ((($item['private'] == 1) || (($item['uid'] == local_user()) && (strlen($item['allow_cid']) || strlen($item['allow_gid']) 
 					|| strlen($item['deny_cid']) || strlen($item['deny_gid']))))
diff --git a/mod/directory.php b/mod/directory.php
index be09dd37f6..625f6c95ac 100644
--- a/mod/directory.php
+++ b/mod/directory.php
@@ -104,7 +104,7 @@ function directory_content(&$a) {
 
 			$itemurl = (($rr['addr'] != "") ? $rr['addr'] : $rr['profile_url']);
 
-			$profile_link = z_root() . '/profile/' . ((strlen($rr['nickname'])) ? $rr['nickname'] : $rr['profile_uid']);
+			$profile_link = 'profile/' . ((strlen($rr['nickname'])) ? $rr['nickname'] : $rr['profile_uid']);
 
 			$pdesc = (($rr['pdesc']) ? $rr['pdesc'] . '<br />' : '');
 
diff --git a/mod/message.php b/mod/message.php
index 1724ebc424..734bf34710 100644
--- a/mod/message.php
+++ b/mod/message.php
@@ -13,7 +13,7 @@ function message_init(&$a) {
 
 	$new = array(
 		'label' => t('New Message'),
-		'url' => $a->get_baseurl(true) . '/message/new',
+		'url' => 'message/new',
 		'sel'=> ($a->argv[1] == 'new'),
 		'accesskey' => 'm',
 	);
@@ -90,7 +90,7 @@ function message_post(&$a) {
 		$a->argv[1] = 'new';
 	}
 	else
-		goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']);
+		goaway($_SESSION['return_url']);
 
 }
 
@@ -182,7 +182,7 @@ function message_content(&$a) {
 		return;
 	}
 
-	$myprofile = $a->get_baseurl(true) . '/profile/' . $a->user['nickname'];
+	$myprofile = 'profile/' . $a->user['nickname'];
 
 	$tpl = get_markup_template('mail_head.tpl');
 	$header = replace_macros($tpl, array(
@@ -221,7 +221,7 @@ function message_content(&$a) {
 		}
 		// Now check how the user responded to the confirmation query
 		if($_REQUEST['canceled']) {
-			goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']);
+			goaway($_SESSION['return_url']);
 		}
 
 		$cmd = $a->argv[1];
@@ -234,7 +234,7 @@ function message_content(&$a) {
 				info( t('Message deleted.') . EOL );
 			}
 			//goaway($a->get_baseurl(true) . '/message' );
-			goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']);
+			goaway($_SESSION['return_url']);
 		}
 		else {
 			$r = q("SELECT `parent-uri`,`convid` FROM `mail` WHERE `id` = %d AND `uid` = %d LIMIT 1",
@@ -265,7 +265,7 @@ function message_content(&$a) {
 					info( t('Conversation removed.') . EOL );
 			}
 			//goaway($a->get_baseurl(true) . '/message' );
-			goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']);
+			goaway($_SESSION['return_url']);
 		}
 
 	}
@@ -448,7 +448,7 @@ function message_content(&$a) {
 				$sparkle = '';
 			}
 			else {
-				$from_url = $a->get_baseurl(true) . '/redir/' . $message['contact-id'];
+				$from_url = 'redir/' . $message['contact-id'];
 				$sparkle = ' sparkle';
 			}
 
@@ -549,7 +549,7 @@ function render_messages($msg, $t) {
 	$tpl = get_markup_template($t);
 	$rslt = '';
 
-	$myprofile = $a->get_baseurl(true) . '/profile/' . $a->user['nickname'];
+	$myprofile = 'profile/' . $a->user['nickname'];
 
 	foreach($msg as $rr) {
 
@@ -577,7 +577,7 @@ function render_messages($msg, $t) {
 		$rslt .= replace_macros($tpl, array(
 			'$id' => $rr['id'],
 			'$from_name' => $participants,
-			'$from_url' => (($rr['network'] === NETWORK_DFRN) ? $a->get_baseurl(true) . '/redir/' . $rr['contact-id'] : $rr['url']),
+			'$from_url' => (($rr['network'] === NETWORK_DFRN) ? 'redir/' . $rr['contact-id'] : $rr['url']),
 			'$sparkle' => ' sparkle',
 			'$from_photo' => (($rr['thumb']) ? $rr['thumb'] : $rr['from-photo']),
 			'$subject' => $subject_e,
diff --git a/mod/notifications.php b/mod/notifications.php
index a267b7c958..f6c4e8f51f 100644
--- a/mod/notifications.php
+++ b/mod/notifications.php
@@ -49,12 +49,12 @@ function notifications_post(&$a) {
 					intval(local_user())
 				);
 			}
-			goaway($a->get_baseurl(true) . '/notifications/intros');
+			goaway('notifications/intros');
 		}
 		if($_POST['submit'] == t('Ignore')) {
 			$r = q("UPDATE `intro` SET `ignore` = 1 WHERE `id` = %d",
 				intval($intro_id));
-			goaway($a->get_baseurl(true) . '/notifications/intros');
+			goaway('notifications/intros');
 		}
 	}
 }
@@ -79,37 +79,37 @@ function notifications_content(&$a) {
 	$tabs = array(
 		array(
 			'label' => t('System'),
-			'url'=>$a->get_baseurl(true) . '/notifications/system',
+			'url'=>'notifications/system',
 			'sel'=> (($a->argv[1] == 'system') ? 'active' : ''),
 			'accesskey' => 'y',
 		),
 		array(
 			'label' => t('Network'),
-			'url'=>$a->get_baseurl(true) . '/notifications/network',
+			'url'=>'notifications/network',
 			'sel'=> (($a->argv[1] == 'network') ? 'active' : ''),
 			'accesskey' => 'w',
 		),
 		array(
 			'label' => t('Personal'),
-			'url'=>$a->get_baseurl(true) . '/notifications/personal',
+			'url'=>'notifications/personal',
 			'sel'=> (($a->argv[1] == 'personal') ? 'active' : ''),
 			'accesskey' => 'r',
 		),
 		array(
 			'label' => t('Home'),
-			'url' => $a->get_baseurl(true) . '/notifications/home',
+			'url' => 'notifications/home',
 			'sel'=> (($a->argv[1] == 'home') ? 'active' : ''),
 			'accesskey' => 'h',
 		),
 		array(
 			'label' => t('Introductions'),
-			'url' => $a->get_baseurl(true) . '/notifications/intros',
+			'url' => 'notifications/intros',
 			'sel'=> (($a->argv[1] == 'intros') ? 'active' : ''),
 			'accesskey' => 'i',
 		),
 		/*array(
 			'label' => t('Messages'),
-			'url' => $a->get_baseurl(true) . '/message',
+			'url' => 'message',
 			'sel'=> '',
 		),*/ /*while I can have notifications for messages, this tablist is not place for message page link */
 	);
diff --git a/mod/photos.php b/mod/photos.php
index a9dade6a81..2257a96653 100644
--- a/mod/photos.php
+++ b/mod/photos.php
@@ -80,7 +80,7 @@ function photos_init(&$a) {
 				$entry = array(
 					'text'      => $album['album'],
 					'total'     => $album['total'],
-					'url'       => z_root() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album['album']),
+					'url'       => 'photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album['album']),
 					'urlencode' => urlencode($album['album']),
 					'bin2hex'   => bin2hex($album['album'])
 				);
@@ -100,7 +100,7 @@ function photos_init(&$a) {
 				'$recent'    => t('Recent Photos'),
 				'$albums'   => $albums['albums'],
 				'$baseurl'  => z_root(),
-				'$upload'   => array( t('Upload New Photos'), $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/upload'),
+				'$upload'   => array( t('Upload New Photos'), 'photos/' . $a->data['user']['nickname'] . '/upload'),
 				'$can_post' => $can_post
 			));
 		}
@@ -190,7 +190,7 @@ function photos_post(&$a) {
 		$album = hex2bin($a->argv[3]);
 
 		if($album === t('Profile Photos') || $album === 'Contact Photos' || $album === t('Contact Photos')) {
-			goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
+			goaway($_SESSION['photo_return']);
 			return; // NOTREACHED
 		}
 
@@ -200,13 +200,13 @@ function photos_post(&$a) {
 		);
 		if(! count($r)) {
 			notice( t('Album not found.') . EOL);
-			goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
+			goaway($_SESSION['photo_return']);
 			return; // NOTREACHED
 		}
 
 		// Check if the user has responded to a delete confirmation query
 		if($_REQUEST['canceled']) {
-			goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
+			goaway($_SESSION['photo_return']);
 		}
 
 		/*
@@ -221,7 +221,7 @@ function photos_post(&$a) {
 				intval($page_owner_uid)
 			);
 			$newurl = str_replace(bin2hex($album),bin2hex($newalbum),$_SESSION['photo_return']);
-			goaway($a->get_baseurl() . '/' . $newurl);
+			goaway($newurl);
 			return; // NOTREACHED
 		}
 
@@ -273,7 +273,7 @@ function photos_post(&$a) {
 				}
 			}
 			else {
-				goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
+				goaway($_SESSION['photo_return']);
 				return; // NOTREACHED
 			}
 
@@ -309,14 +309,14 @@ function photos_post(&$a) {
 				}
 			}
 		}
-		goaway($a->get_baseurl() . '/photos/' . $a->data['user']['nickname']);
+		goaway('photos/' . $a->data['user']['nickname']);
 		return; // NOTREACHED
 	}
 
 
 	// Check if the user has responded to a delete confirmation query for a single photo
 	if(($a->argc > 2) && $_REQUEST['canceled']) {
-		goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
+		goaway($_SESSION['photo_return']);
 	}
 
 	if(($a->argc > 2) && (x($_POST,'delete')) && ($_POST['delete'] == t('Delete Photo'))) {
@@ -379,7 +379,7 @@ function photos_post(&$a) {
 			}
 		}
 
-		goaway($a->get_baseurl() . '/photos/' . $a->data['user']['nickname']);
+		goaway('photos/' . $a->data['user']['nickname']);
 		return; // NOTREACHED
 	}
 
@@ -718,12 +718,6 @@ function photos_post(&$a) {
 
 					$item_id = item_store($arr);
 					if($item_id) {
-						//q("UPDATE `item` SET `plink` = '%s' WHERE `uid` = %d AND `id` = %d",
-						//	dbesc($a->get_baseurl() . '/display/' . $owner_record['nickname'] . '/' . $item_id),
-						//	intval($page_owner_uid),
-						//	intval($item_id)
-						//);
-
 						proc_run('php',"include/notifier.php","tag","$item_id");
 					}
 				}
@@ -731,7 +725,7 @@ function photos_post(&$a) {
 			}
 
 		}
-		goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
+		goaway($_SESSION['photo_return']);
 		return; // NOTREACHED
 	}
 
@@ -938,14 +932,6 @@ function photos_post(&$a) {
 
 	$item_id = item_store($arr);
 
-	//if($item_id) {
-	//	q("UPDATE `item` SET `plink` = '%s' WHERE `uid` = %d AND `id` = %d",
-	//		dbesc($a->get_baseurl() . '/display/' . $owner_record['nickname'] . '/' . $item_id),
-	//		intval($page_owner_uid),
-	//		intval($item_id)
-	//	);
-	//}
-
 	if($visible)
 		proc_run('php', "include/notifier.php", 'wall-new', $item_id);
 
@@ -954,7 +940,7 @@ function photos_post(&$a) {
 	// addon uploaders should call "killme()" [e.g. exit] within the photo_post_end hook
 	// if they do not wish to be redirected
 
-	goaway($a->get_baseurl() . '/' . $_SESSION['photo_return']);
+	goaway($_SESSION['photo_return']);
 	// NOTREACHED
 }
 
@@ -1125,7 +1111,7 @@ function photos_content(&$a) {
 
 		$uploader = '';
 
-		$ret = array('post_url' => $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'],
+		$ret = array('post_url' => 'photos/' . $a->data['user']['nickname'],
 				'addon_text' => $uploader,
 				'default_upload' => true);
 
@@ -1267,15 +1253,15 @@ function photos_content(&$a) {
 		else {
 			if(($album !== t('Profile Photos')) && ($album !== 'Contact Photos') && ($album !== t('Contact Photos'))) {
 				if($can_post) {
-					$edit = array(t('Edit Album'), $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album) . '/edit');
+					$edit = array(t('Edit Album'), 'photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album) . '/edit');
  				}
 			}
 		}
 
 		if($_GET['order'] === 'posted')
-			$order =  array(t('Show Newest First'), $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album));
+			$order =  array(t('Show Newest First'), 'photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album));
 		else
-			$order = array(t('Show Oldest First'), $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album) . '?f=&order=posted');
+			$order = array(t('Show Oldest First'), 'photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($album) . '?f=&order=posted');
 
 		$photos = array();
 
@@ -1301,10 +1287,10 @@ function photos_content(&$a) {
 				$photos[] = array(
 					'id' => $rr['id'],
 					'twist' => ' ' . $twist . rand(2,4),
-					'link' => $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $rr['resource-id']
+					'link' => 'photos/' . $a->data['user']['nickname'] . '/image/' . $rr['resource-id']
 						. (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''),
 					'title' => t('View Photo'),
-					'src' => $a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['scale'] . '.' .$ext,
+					'src' => 'photo/' . $rr['resource-id'] . '-' . $rr['scale'] . '.' .$ext,
 					'alt' => $imgalt_e,
 					'desc'=> $desc_e,
 					'ext' => $ext,
@@ -1317,7 +1303,7 @@ function photos_content(&$a) {
 				'$photos' => $photos,
 				'$album' => $album,
 				'$can_post' => $can_post,
-				'$upload' => array(t('Upload New Photos'), $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/upload/' . bin2hex($album)),
+				'$upload' => array(t('Upload New Photos'), 'photos/' . $a->data['user']['nickname'] . '/upload/' . bin2hex($album)),
 				'$order' => $order,
 				'$edit' => $edit
 			));
@@ -1384,8 +1370,8 @@ function photos_content(&$a) {
 				}
 			}
 			$edit_suffix = ((($cmd === 'edit') && ($can_post)) ? '/edit' : '');
-			$prevlink = $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $prvnxt[$prv]['resource-id'] . $edit_suffix . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
-			$nextlink = $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $prvnxt[$nxt]['resource-id'] . $edit_suffix . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
+			$prevlink = 'photos/' . $a->data['user']['nickname'] . '/image/' . $prvnxt[$prv]['resource-id'] . $edit_suffix . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
+			$nextlink = 'photos/' . $a->data['user']['nickname'] . '/image/' . $prvnxt[$nxt]['resource-id'] . $edit_suffix . (($_GET['order'] === 'posted') ? '?f=&order=posted' : '');
  		}
 
 
@@ -1402,14 +1388,14 @@ function photos_content(&$a) {
 			}
 		}
 
-		$album_link = $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($ph[0]['album']);
+		$album_link = 'photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($ph[0]['album']);
  		$tools = Null;
  		$lock = Null;
 
 		if($can_post && ($ph[0]['uid'] == $owner_uid)) {
 			$tools = array(
-				'edit'	=> array($a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $datum . (($cmd === 'edit') ? '' : '/edit'), (($cmd === 'edit') ? t('View photo') : t('Edit photo'))),
-				'profile'=>array($a->get_baseurl() . '/profile_photo/use/'.$ph[0]['resource-id'], t('Use as profile photo')),
+				'edit'	=> array('photos/' . $a->data['user']['nickname'] . '/image/' . $datum . (($cmd === 'edit') ? '' : '/edit'), (($cmd === 'edit') ? t('View photo') : t('Edit photo'))),
+				'profile'=>array('profile_photo/use/'.$ph[0]['resource-id'], t('Use as profile photo')),
 			);
 
 			// lock
@@ -1433,9 +1419,9 @@ function photos_content(&$a) {
 			$prevlink = array($prevlink, '<div class="icon prev"></div>') ;
 
 		$photo = array(
-			'href' => $a->get_baseurl() . '/photo/' . $hires['resource-id'] . '-' . $hires['scale'] . '.' . $phototypes[$hires['type']],
+			'href' => 'photo/' . $hires['resource-id'] . '-' . $hires['scale'] . '.' . $phototypes[$hires['type']],
 			'title'=> t('View Full Size'),
-			'src'  => $a->get_baseurl() . '/photo/' . $lores['resource-id'] . '-' . $lores['scale'] . '.' . $phototypes[$lores['type']] . '?f=&_u=' . datetime_convert('','','','ymdhis'),
+			'src'  => 'photo/' . $lores['resource-id'] . '-' . $lores['scale'] . '.' . $phototypes[$lores['type']] . '?f=&_u=' . datetime_convert('','','','ymdhis'),
 			'height' => $hires['height'],
 			'width' => $hires['width'],
 			'album' => $hires['album'],
@@ -1522,7 +1508,7 @@ function photos_content(&$a) {
 			}
 			$tags = array(t('Tags: '), $tag_str);
 			if($cmd === 'edit') {
-				$tags[] = $a->get_baseurl() . '/tagrm/' . $link_item['id'];
+				$tags[] = 'tagrm/' . $link_item['id'];
 				$tags[] = t('[Remove any tag]');
 			}
 		}
@@ -1693,7 +1679,7 @@ function photos_content(&$a) {
 					if(((activity_match($item['verb'],ACTIVITY_LIKE)) || (activity_match($item['verb'],ACTIVITY_DISLIKE))) && ($item['id'] != $item['parent']))
 						continue;
 
-					$redirect_url = $a->get_baseurl() . '/redir/' . $item['cid'] ;
+					$redirect_url = 'redir/' . $item['cid'] ;
 
 
 					if(local_user() && ($item['contact-uid'] == local_user())
@@ -1880,12 +1866,12 @@ function photos_content(&$a) {
 			$photos[] = array(
 				'id'		=> $rr['id'],
 				'twist'		=> ' ' . $twist . rand(2,4),
-				'link'  	=> $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $rr['resource-id'],
+				'link'  	=> 'photos/' . $a->data['user']['nickname'] . '/image/' . $rr['resource-id'],
 				'title' 	=> t('View Photo'),
-				'src'     	=> $a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . ((($rr['scale']) == 6) ? 4 : $rr['scale']) . '.' . $ext,
+				'src'     	=> 'photo/' . $rr['resource-id'] . '-' . ((($rr['scale']) == 6) ? 4 : $rr['scale']) . '.' . $ext,
 				'alt'     	=> $alt_e,
 				'album'	=> array(
-					'link'  => $a->get_baseurl() . '/photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($rr['album']),
+					'link'  => 'photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($rr['album']),
 					'name'  => $name_e,
 					'alt'   => t('View Album'),
 				),
@@ -1898,7 +1884,7 @@ function photos_content(&$a) {
 	$o .= replace_macros($tpl, array(
 		'$title' => t('Recent Photos'),
 		'$can_post' => $can_post,
-		'$upload' => array(t('Upload New Photos'), $a->get_baseurl().'/photos/'.$a->data['user']['nickname'].'/upload'),
+		'$upload' => array(t('Upload New Photos'), 'photos/'.$a->data['user']['nickname'].'/upload'),
 		'$photos' => $photos,
 	));
 
diff --git a/mod/search.php b/mod/search.php
index 7c78339c70..1776a92552 100644
--- a/mod/search.php
+++ b/mod/search.php
@@ -147,7 +147,7 @@ function search_content(&$a) {
 	}
 
 
-	$o .= search($search,'search-box','/search',((local_user()) ? true : false), false);
+	$o .= search($search,'search-box','search',((local_user()) ? true : false), false);
 
 	if(strpos($search,'#') === 0) {
 		$tag = true;
diff --git a/mod/settings.php b/mod/settings.php
index 3efdbf6bde..905a5ed08d 100644
--- a/mod/settings.php
+++ b/mod/settings.php
@@ -39,7 +39,7 @@ function settings_init(&$a) {
 	$tabs = array(
 		array(
 			'label'	=> t('Account'),
-			'url' 	=> $a->get_baseurl(true).'/settings',
+			'url' 	=> 'settings',
 			'selected'	=>  (($a->argc == 1) && ($a->argv[0] === 'settings')?'active':''),
 			'accesskey' => 'o',
 		),
@@ -48,7 +48,7 @@ function settings_init(&$a) {
 	if(get_features()) {
 		$tabs[] =	array(
 					'label'	=> t('Additional features'),
-					'url' 	=> $a->get_baseurl(true).'/settings/features',
+					'url' 	=> 'settings/features',
 					'selected'	=> (($a->argc > 1) && ($a->argv[1] === 'features') ? 'active' : ''),
 					'accesskey' => 't',
 				);
@@ -56,49 +56,49 @@ function settings_init(&$a) {
 
 	$tabs[] =	array(
 		'label'	=> t('Display'),
-		'url' 	=> $a->get_baseurl(true).'/settings/display',
+		'url' 	=> 'settings/display',
 		'selected'	=> (($a->argc > 1) && ($a->argv[1] === 'display')?'active':''),
 		'accesskey' => 'i',
 	);
 
 	$tabs[] =	array(
 		'label'	=> t('Social Networks'),
-		'url' 	=> $a->get_baseurl(true).'/settings/connectors',
+		'url' 	=> 'settings/connectors',
 		'selected'	=> (($a->argc > 1) && ($a->argv[1] === 'connectors')?'active':''),
 		'accesskey' => 'w',
 	);
 
 	$tabs[] =	array(
 		'label'	=> t('Plugins'),
-		'url' 	=> $a->get_baseurl(true).'/settings/addon',
+		'url' 	=> 'settings/addon',
 		'selected'	=> (($a->argc > 1) && ($a->argv[1] === 'addon')?'active':''),
 		'accesskey' => 'l',
 	);
 
 	$tabs[] =	array(
 		'label'	=> t('Delegations'),
-		'url' 	=> $a->get_baseurl(true).'/delegate',
+		'url' 	=> 'delegate',
 		'selected'	=> (($a->argc == 1) && ($a->argv[0] === 'delegate')?'active':''),
 		'accesskey' => 'd',
 	);
 
 	$tabs[] =	array(
 		'label' => t('Connected apps'),
-		'url' => $a->get_baseurl(true) . '/settings/oauth',
+		'url' => 'settings/oauth',
 		'selected' => (($a->argc > 1) && ($a->argv[1] === 'oauth')?'active':''),
 		'accesskey' => 'b',
 	);
 
 	$tabs[] =	array(
 		'label' => t('Export personal data'),
-		'url' => $a->get_baseurl(true) . '/uexport',
+		'url' => 'uexport',
 		'selected' => (($a->argc == 1) && ($a->argv[0] === 'uexport')?'active':''),
 		'accesskey' => 'e',
 	);
 
 	$tabs[] =	array(
 		'label' => t('Remove account'),
-		'url' => $a->get_baseurl(true) . '/removeme',
+		'url' => 'removeme',
 		'selected' => (($a->argc == 1) && ($a->argv[0] === 'removeme')?'active':''),
 		'accesskey' => 'r',
 	);
@@ -342,7 +342,7 @@ function settings_post(&$a) {
 		);
 
 		call_hooks('display_settings_post', $_POST);
-		goaway($a->get_baseurl(true) . '/settings/display' );
+		goaway('settings/display' );
 		return; // NOTREACHED
 	}
 
@@ -351,7 +351,7 @@ function settings_post(&$a) {
 	if (x($_POST,'resend_relocate')) {
 		proc_run('php', 'include/notifier.php', 'relocate', local_user());
 		info(t("Relocate message has been send to your contacts"));
-		goaway($a->get_baseurl(true) . '/settings');
+		goaway('settings');
 	}
 
 	call_hooks('settings_post', $_POST);
@@ -627,7 +627,7 @@ function settings_post(&$a) {
 
 	}
 
-	goaway($a->get_baseurl(true) . '/settings' );
+	goaway('settings' );
 	return; // NOTREACHED
 }
 
@@ -1152,7 +1152,7 @@ function settings_content(&$a) {
 		info( t('Profile is <strong>not published</strong>.') . EOL );
 
 
-	//$subdir = ((strlen($a->get_path())) ? '<br />' . t('or') . ' ' . $a->get_baseurl(true) . '/profile/' . $nickname : '');
+	//$subdir = ((strlen($a->get_path())) ? '<br />' . t('or') . ' ' . 'profile/' . $nickname : '');
 
 	$tpl_addr = get_markup_template("settings_nick_set.tpl");
 
diff --git a/mod/uexport.php b/mod/uexport.php
index a44620a976..3114add7e4 100644
--- a/mod/uexport.php
+++ b/mod/uexport.php
@@ -6,54 +6,6 @@ function uexport_init(&$a){
 
 	require_once("mod/settings.php");
         settings_init($a);
-
-/*
-	$tabs = array(
-		array(
-			'label'	=> t('Account settings'),
-			'url' 	=> $a->get_baseurl(true).'/settings',
-			'selected'	=> '',
-		),
-		array(
-			'label'	=> t('Display settings'),
-			'url' 	=> $a->get_baseurl(true).'/settings/display',
-			'selected'	=>'',
-		),
-
-		array(
-			'label'	=> t('Connector settings'),
-			'url' 	=> $a->get_baseurl(true).'/settings/connectors',
-			'selected'	=> '',
-		),
-		array(
-			'label'	=> t('Plugin settings'),
-			'url' 	=> $a->get_baseurl(true).'/settings/addon',
-			'selected'	=> '',
-		),
-		array(
-			'label' => t('Connected apps'),
-			'url' => $a->get_baseurl(true) . '/settings/oauth',
-			'selected' => '',
-		),
-		array(
-			'label' => t('Export personal data'),
-			'url' => $a->get_baseurl(true) . '/uexport',
-			'selected' => 'active'
-		),
-		array(
-			'label' => t('Remove account'),
-			'url' => $a->get_baseurl(true) . '/removeme',
-			'selected' => ''
-		)
-	);
-
-	$tabtpl = get_markup_template("generic_links_widget.tpl");
-	$a->page['aside'] = replace_macros($tabtpl, array(
-		'$title' => t('Settings'),
-		'$class' => 'settings-widget',
-		'$items' => $tabs,
-	));
-*/
 }
 
 function uexport_content(&$a){
@@ -74,8 +26,8 @@ function uexport_content(&$a){
       * list of array( 'link url', 'link text', 'help text' )
       */
     $options = array(
-            array('/uexport/account',t('Export account'),t('Export your account info and contacts. Use this to make a backup of your account and/or to move it to another server.')),
-            array('/uexport/backup',t('Export all'),t('Export your accout info, contacts and all your items as json. Could be a very big file, and could take a lot of time. Use this to make a full backup of your account (photos are not exported)')),
+            array('uexport/account',t('Export account'),t('Export your account info and contacts. Use this to make a backup of your account and/or to move it to another server.')),
+            array('uexport/backup',t('Export all'),t('Export your accout info, contacts and all your items as json. Could be a very big file, and could take a lot of time. Use this to make a full backup of your account (photos are not exported)')),
     );
     call_hooks('uexport_options', $options);
 
@@ -153,9 +105,9 @@ function uexport_account($a){
         'version' => FRIENDICA_VERSION,
         'schema' => DB_UPDATE_VERSION,
         'baseurl' => $a->get_baseurl(),
-        'user' => $user, 
-        'contact' => $contact, 
-        'profile' => $profile, 
+        'user' => $user,
+        'contact' => $contact,
+        'profile' => $profile,
         'photo' => $photo,
         'pconfig' => $pconfig,
         'group' => $group,
@@ -171,8 +123,8 @@ function uexport_account($a){
  * echoes account data and items as separated json, one per line
  */
 function uexport_all(&$a) {
-    
-    uexport_account($a);
+
+	uexport_account($a);
 	echo "\n";
 
 	$r = q("SELECT count(*) as `total` FROM `item` WHERE `uid` = %d ",
diff --git a/object/Item.php b/object/Item.php
index 9daf44648e..e9c96cf159 100644
--- a/object/Item.php
+++ b/object/Item.php
@@ -50,7 +50,7 @@ class Item extends BaseObject {
 		$this->writable = ($this->get_data_value('writable') || $this->get_data_value('self'));
 
 		$ssl_state = ((local_user()) ? true : false);
-		$this->redirect_url = $a->get_baseurl($ssl_state) . '/redir/' . $this->get_data_value('cid') ;
+		$this->redirect_url = 'redir/' . $this->get_data_value('cid') ;
 
 		if(get_config('system','thread_allow') && $a->theme_thread_allow && !$this->is_toplevel())
 			$this->threaded = true;
@@ -119,9 +119,9 @@ class Item extends BaseObject {
 		$shareable = ((($conv->get_profile_owner() == local_user()) && ($item['private'] != 1)) ? true : false);
 		if(local_user() && link_compare($a->contact['url'],$item['author-link'])) {
 			if ($item["event-id"] != 0)
-				$edpost = array($a->get_baseurl($ssl_state)."/events/event/".$item['event-id'], t("Edit"));
+				$edpost = array("events/event/".$item['event-id'], t("Edit"));
 			else
-				$edpost = array($a->get_baseurl($ssl_state)."/editpost/".$item['id'], t("Edit"));
+				$edpost = array("editpost/".$item['id'], t("Edit"));
 		} else
 			$edpost = false;
 		if(($this->get_data_value('uid') == local_user()) || $this->is_visiting())
@@ -160,7 +160,7 @@ class Item extends BaseObject {
 		call_hooks('render_location',$locate);
 		$location = ((strlen($locate['html'])) ? $locate['html'] : render_location_dummy($locate));
 
-		$searchpath = $a->get_baseurl()."/search?tag=";
+		$searchpath = "search?tag=";
 		$tags=array();
 		$hashtags = array();
 		$mentions = array();
@@ -703,7 +703,7 @@ class Item extends BaseObject {
 				'$parent' => $this->get_id(),
 				'$qcomment' => $qcomment,
 				'$profile_uid' =>  $conv->get_profile_owner(),
-				'$mylink' => $a->contact['url'],
+				'$mylink' => $a->remove_baseurl($a->contact['url']),
 				'$mytitle' => t('This is you'),
 				'$myphoto' => $a->remove_baseurl($a->contact['thumb']),
 				'$comment' => t('Comment'),
diff --git a/view/templates/uexport.tpl b/view/templates/uexport.tpl
index 382c7fc6a3..b9e177af26 100644
--- a/view/templates/uexport.tpl
+++ b/view/templates/uexport.tpl
@@ -1,10 +1,10 @@
 
-<h3>{{$title}}</h3>
-
-
-{{foreach $options as $o}}
-<dl>
-    <dt><a href="{{$baseurl}}/{{$o.0}}">{{$o.1}}</a></dt>
-    <dd>{{$o.2}}</dd>
-</dl>
-{{/foreach}}
\ No newline at end of file
+<h3>{{$title}}</h3>
+
+
+{{foreach $options as $o}}
+<dl>
+    <dt><a href="{{$o.0}}">{{$o.1}}</a></dt>
+    <dd>{{$o.2}}</dd>
+</dl>
+{{/foreach}}
diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css
index e35556f541..3e91d61246 100644
--- a/view/theme/vier/style.css
+++ b/view/theme/vier/style.css
@@ -1432,8 +1432,8 @@ section.minimal {
 }
 .children .wall-item-container .wall-item-item .wall-item-content img {
   /* max-width: 650px; */
-  /* max-width: 580px; */
-  max-width: 100%;
+  max-width: 520px;
+  /* max-width: 100%; */
 }
 .wall-item-container .wall-item-links, .wall-item-container .wall-item-actions {
   display: table-cell;
diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php
index f33a9178ac..7f6ead079f 100644
--- a/view/theme/vier/theme.php
+++ b/view/theme/vier/theme.php
@@ -239,12 +239,12 @@ function vier_community_info() {
 				$selected = (($cid == $contact['id']) ? ' forum-selected' : '');
 
 				$entry = array(
-					'url' => z_root() . '/network?f=&cid=' . $contact['id'],
-					'external_url' => z_root() . '/redir/' . $contact['id'],
+					'url' => 'network?f=&cid=' . $contact['id'],
+					'external_url' => 'redir/' . $contact['id'],
 					'name' => $contact['name'],
 					'cid' => $contact['id'],
 					'selected' 	=> $selected,
-					'micro' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO),
+					'micro' => App::remove_baseurl(proxy_url($contact['micro'], false, PROXY_SIZE_MICRO)),
 					'id' => ++$id,
 				);
 				$entries[] = $entry;

From 9619829b4ab693bdbe2e24071e3d39d840d855b0 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 18 Feb 2016 07:41:08 +0100
Subject: [PATCH 116/273] Avoid "array_merge" warning.

---
 include/socgraph.php | 73 +++++++++++++++++++++++---------------------
 1 file changed, 38 insertions(+), 35 deletions(-)

diff --git a/include/socgraph.php b/include/socgraph.php
index bd5b1817f0..186326f42d 100644
--- a/include/socgraph.php
+++ b/include/socgraph.php
@@ -438,44 +438,47 @@ function poco_last_updated($profile, $force = false) {
 
 				$noscrape = json_decode($noscraperet["body"], true);
 
-				$contact = array("url" => $profile,
-						"network" => $server[0]["network"],
-						"generation" => $gcontacts[0]["generation"]);
+				if (is_array($noscrape)) {
+					$contact = array("url" => $profile,
+							"network" => $server[0]["network"],
+							"generation" => $gcontacts[0]["generation"]);
 
-				$contact["name"] = $noscrape["fn"];
-				$contact["community"] = $noscrape["comm"];
+					$contact["name"] = $noscrape["fn"];
+					$contact["community"] = $noscrape["comm"];
 
-				if (isset($noscrape["tags"])) {
-					$keywords = implode(" ", $noscrape["tags"]);
-					if ($keywords != "")
-						$contact["keywords"] = $keywords;
+					if (isset($noscrape["tags"])) {
+						$keywords = implode(" ", $noscrape["tags"]);
+						if ($keywords != "")
+							$contact["keywords"] = $keywords;
+					}
+
+					$location = formatted_location($noscrape);
+					if ($location)
+						$contact["location"] = $location;
+
+					$contact["notify"] = $noscrape["dfrn-notify"];
+
+					// Remove all fields that are not present in the gcontact table
+					unset($noscrape["fn"]);
+					unset($noscrape["key"]);
+					unset($noscrape["homepage"]);
+					unset($noscrape["comm"]);
+					unset($noscrape["tags"]);
+					unset($noscrape["locality"]);
+					unset($noscrape["region"]);
+					unset($noscrape["country-name"]);
+					unset($noscrape["contacts"]);
+					unset($noscrape["dfrn-request"]);
+					unset($noscrape["dfrn-confirm"]);
+					unset($noscrape["dfrn-notify"]);
+					unset($noscrape["dfrn-poll"]);
+
+					$contact = array_merge($contact, $noscrape);
+
+					update_gcontact($contact);
+
+					return $noscrape["updated"];
 				}
-
-				$location = formatted_location($noscrape);
-				if ($location)
-					$contact["location"] = $location;
-
-				$contact["notify"] = $noscrape["dfrn-notify"];
-
-				// Remove all fields that are not present in the gcontact table
-				unset($noscrape["fn"]);
-				unset($noscrape["key"]);
-				unset($noscrape["homepage"]);
-				unset($noscrape["comm"]);
-				unset($noscrape["tags"]);
-				unset($noscrape["locality"]);
-				unset($noscrape["region"]);
-				unset($noscrape["country-name"]);
-				unset($noscrape["contacts"]);
-				unset($noscrape["dfrn-request"]);
-				unset($noscrape["dfrn-confirm"]);
-				unset($noscrape["dfrn-notify"]);
-				unset($noscrape["dfrn-poll"]);
-
-				$contact = array_merge($contact, $noscrape);
-				update_gcontact($contact);
-
-				return $noscrape["updated"];
 			}
 		}
 	}

From 8a3de7b1868b93fe61c9dac4e0b3a2c0cb1021d3 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 19 Feb 2016 07:30:28 +0100
Subject: [PATCH 117/273] Issue 2367: The data for the gserver table is now
 sanitized.

---
 include/socgraph.php | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/include/socgraph.php b/include/socgraph.php
index 186326f42d..33d62dc5b9 100644
--- a/include/socgraph.php
+++ b/include/socgraph.php
@@ -722,7 +722,8 @@ function poco_check_server($server_url, $network = "", $force = false) {
 		// Will also return data for Friendica and GNU Social - but it will be overwritten later
 		// The "not implemented" is a special treatment for really, really old Friendica versions
 		$serverret = z_fetch_url($server_url."/api/statusnet/version.json");
-		if ($serverret["success"] AND ($serverret["body"] != '{"error":"not implemented"}') AND ($serverret["body"] != '') AND (strlen($serverret["body"]) < 250)) {
+		if ($serverret["success"] AND ($serverret["body"] != '{"error":"not implemented"}') AND
+			($serverret["body"] != '') AND (strlen($serverret["body"]) < 30)) {
 			$platform = "StatusNet";
 			$version = trim($serverret["body"], '"');
 			$network = NETWORK_OSTATUS;
@@ -730,7 +731,8 @@ function poco_check_server($server_url, $network = "", $force = false) {
 
 		// Test for GNU Social
 		$serverret = z_fetch_url($server_url."/api/gnusocial/version.json");
-		if ($serverret["success"] AND ($serverret["body"] != '{"error":"not implemented"}') AND ($serverret["body"] != '') AND (strlen($serverret["body"]) < 250)) {
+		if ($serverret["success"] AND ($serverret["body"] != '{"error":"not implemented"}') AND
+			($serverret["body"] != '') AND (strlen($serverret["body"]) < 30)) {
 			$platform = "GNU Social";
 			$version = trim($serverret["body"], '"');
 			$network = NETWORK_OSTATUS;
@@ -857,6 +859,11 @@ function poco_check_server($server_url, $network = "", $force = false) {
 	// Check again if the server exists
 	$servers = q("SELECT `nurl` FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url)));
 
+	$version = strip_tags($version);
+	$site_name = strip_tags($site_name);
+	$info = strip_tags($info);
+	$platform = strip_tags($platform);
+
 	if ($servers)
 		 q("UPDATE `gserver` SET `url` = '%s', `version` = '%s', `site_name` = '%s', `info` = '%s', `register_policy` = %d, `poco` = '%s', `noscrape` = '%s',
 			`network` = '%s', `platform` = '%s', `last_contact` = '%s', `last_failure` = '%s' WHERE `nurl` = '%s'",

From 8ec833f8087b0bba2f167471c430543c271602dc Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 22 Feb 2016 23:20:59 +0100
Subject: [PATCH 118/273] New BBCode element "abstract" for network depending
 messages.

---
 include/bbcode.php    | 42 ++++++++++++++++++++++++++++++++++++++++++
 include/dfrn.php      |  4 ++++
 include/plaintext.php | 43 ++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/include/bbcode.php b/include/bbcode.php
index 6a44e19ec4..eb009477cf 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -851,6 +851,9 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
 
 	$a = get_app();
 
+	// Remove the abstract element. It is a non visible element.
+	$Text = remove_abstract($Text);
+
 	// Hide all [noparse] contained bbtags by spacefying them
 	// POSSIBLE BUG --> Will the 'preg' functions crash if there's an embedded image?
 
@@ -1300,4 +1303,43 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
 
 	return trim($Text);
 }
+
+/**
+ * @brief Removes the "abstract" element from the text
+ *
+ * @param string $text The text with BBCode
+ * @return string The same text - but without "abstract" element
+ */
+function remove_abstract($text) {
+	$text = preg_replace("/[\s|\n]*\[abstract\].*?\[\/abstract\][\s|\n]*/ism", '', $text);
+	$text = preg_replace("/[\s|\n]*\[abstract=.*?\].*?\[\/abstract][\s|\n]*/ism", '', $text);
+
+	return $text;
+}
+
+/**
+ * @brief Returns the value of the "abstract" element
+ *
+ * @param string $text The text that maybe contains the element
+ * @param string $addon The addon for which the abstract is meant for
+ * @return string The abstract
+ */
+function fetch_abstract($text, $addon = "") {
+	$abstract = "";
+	$abstracts = array();
+	$addon = strtolower($addon);
+
+	if (preg_match_all("/\[abstract=(.*?)\](.*?)\[\/abstract\]/ism",$text, $results, PREG_SET_ORDER))
+		foreach ($results AS $result)
+			$abstracts[strtolower($result[1])] = $result[2];
+
+	if (isset($abstracts[$addon]))
+		$abstract = $abstracts[$addon];
+
+	if ($abstract == "")
+		if (preg_match("/\[abstract\](.*?)\[\/abstract\]/ism",$text, $result))
+			$abstract = $result[1];
+
+	return $abstract;
+}
 ?>
diff --git a/include/dfrn.php b/include/dfrn.php
index f7a05bdb63..ad04a91295 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -18,6 +18,7 @@ require_once("include/event.php");
 require_once("include/text.php");
 require_once("include/oembed.php");
 require_once("include/html2bbcode.php");
+require_once("include/bbcode.php");
 
 /**
  * @brief This class contain functions to create and send DFRN XML files
@@ -720,6 +721,9 @@ class dfrn {
 		else
 			$body = $item['body'];
 
+		// Remove the abstract element. It is only locally important.
+		$body = remove_abstract($body);
+
 		if ($type == 'html') {
 			$htmlbody = $body;
 
diff --git a/include/plaintext.php b/include/plaintext.php
index 05431bee2d..199abcbb31 100644
--- a/include/plaintext.php
+++ b/include/plaintext.php
@@ -132,7 +132,7 @@ function shortenmsg($msg, $limit, $twitter = false) {
 	return($msg);
 }
 
-function plaintext($a, $b, $limit = 0, $includedlinks = false, $htmlmode = 2) {
+function plaintext($a, $b, $limit = 0, $includedlinks = false, $htmlmode = 2, $target_network = "") {
 	require_once("include/bbcode.php");
 	require_once("include/html2plain.php");
 	require_once("include/network.php");
@@ -144,6 +144,9 @@ function plaintext($a, $b, $limit = 0, $includedlinks = false, $htmlmode = 2) {
 	// Add an URL element if the text contains a raw link
 	$body = preg_replace("/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", '$1[url]$2[/url]', $body);
 
+	// Remove the abstract
+	$body = remove_abstract($body);
+
 	// At first look at data that is attached via "type-..." stuff
 	// This will hopefully replaced with a dedicated bbcode later
 	//$post = get_attached_data($b["body"]);
@@ -154,6 +157,44 @@ function plaintext($a, $b, $limit = 0, $includedlinks = false, $htmlmode = 2) {
 	elseif ($b["title"] != "")
 		$post["text"] = trim($b["title"]);
 
+	$abstract = "";
+
+	// Fetch the abstract from the given target network
+	if ($target_network != "") {
+		$default_abstract = fetch_abstract($b["body"]);
+		$abstract = fetch_abstract($b["body"], $target_network);
+
+		// If we post to a network with no limit we only fetch
+		// an abstract exactly for this network
+		if (($limit == 0) AND ($abstract == $default_abstract))
+			$abstract = "";
+
+	} else // Try to guess the correct target network
+		switch ($htmlmode) {
+			case 8:
+				$abstract = fetch_abstract($b["body"], NETWORK_TWITTER);
+				break;
+			case 7:
+				$abstract = fetch_abstract($b["body"], NETWORK_STATUSNET);
+				break;
+			case 6:
+				$abstract = fetch_abstract($b["body"], NETWORK_APPNET);
+				break;
+			default: // We don't know the exact target.
+				 // We fetch an abstract since there is a posting limit.
+				if ($limit > 0)
+					$abstract = fetch_abstract($b["body"]);
+		}
+
+	if ($abstract != "") {
+		$post["text"] = $abstract;
+
+		if ($post["type"] == "text") {
+			$post["type"] = "link";
+			$post["url"] = $b["plink"];
+		}
+	}
+
 	$html = bbcode($post["text"], false, false, $htmlmode);
 	$msg = html2plain($html, 0, true);
 	$msg = trim(html_entity_decode($msg,ENT_QUOTES,'UTF-8'));

From bc283a5316e7f58edd26a93d8811b30527d8100c Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 23 Feb 2016 07:21:40 +0100
Subject: [PATCH 119/273] The "abstract" has moved after the "nobb" part in
 bbcode.

---
 include/bbcode.php | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/include/bbcode.php b/include/bbcode.php
index eb009477cf..c1156e3afe 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -851,9 +851,6 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
 
 	$a = get_app();
 
-	// Remove the abstract element. It is a non visible element.
-	$Text = remove_abstract($Text);
-
 	// Hide all [noparse] contained bbtags by spacefying them
 	// POSSIBLE BUG --> Will the 'preg' functions crash if there's an embedded image?
 
@@ -861,6 +858,8 @@ function bbcode($Text,$preserve_nl = false, $tryoembed = true, $simplehtml = fal
 	$Text = preg_replace_callback("/\[nobb\](.*?)\[\/nobb\]/ism", 'bb_spacefy',$Text);
 	$Text = preg_replace_callback("/\[pre\](.*?)\[\/pre\]/ism", 'bb_spacefy',$Text);
 
+	// Remove the abstract element. It is a non visible element.
+	$Text = remove_abstract($Text);
 
 	// Move all spaces out of the tags
 	$Text = preg_replace("/\[(\w*)\](\s*)/ism", '$2[$1]', $Text);

From 148c89a20d3fa75904f87d4b7fc0e70077ace85a Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 23 Feb 2016 07:56:49 +0100
Subject: [PATCH 120/273] Added documentation

---
 include/plaintext.php | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/include/plaintext.php b/include/plaintext.php
index 199abcbb31..a2b2c56522 100644
--- a/include/plaintext.php
+++ b/include/plaintext.php
@@ -132,6 +132,18 @@ function shortenmsg($msg, $limit, $twitter = false) {
 	return($msg);
 }
 
+/**
+ * @brief Convert a message into plaintext for connectors to other networks
+ *
+ * @param App $a The application class
+ * @param array $b The message array that is about to be posted
+ * @param int $limit The maximum number of characters when posting to that network
+ * @param bool $includedlinks Has an attached link to be included into the message?
+ * @param int $htmlmode This triggers the behaviour of the bbcode conversion
+ * @param string $target_network Name of the network where the post should go to.
+ *
+ * @return string The converted message
+ */
 function plaintext($a, $b, $limit = 0, $includedlinks = false, $htmlmode = 2, $target_network = "") {
 	require_once("include/bbcode.php");
 	require_once("include/html2plain.php");

From b93326bb23747bbe03c84119447f429009829e49 Mon Sep 17 00:00:00 2001
From: rabuzarus <>
Date: Tue, 23 Feb 2016 19:26:03 +0100
Subject: [PATCH 121/273] contactedit-actions-button: use internal links
 instead of full links

---
 mod/contacts.php | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/mod/contacts.php b/mod/contacts.php
index 991b59885c..4897663a05 100644
--- a/mod/contacts.php
+++ b/mod/contacts.php
@@ -970,7 +970,7 @@ function contact_actions($contact) {
 	if($contact['network'] === NETWORK_DFRN) {
 		$contact_actions['suggest'] = array(
 							'label' => t('Suggest friends'),
-							'url'	=> app::get_baseurl(true) . '/fsuggest/' . $contact['id'],
+							'url'	=> 'fsuggest/' . $contact['id'],
 							'title'	=> '',
 							'sel'	=> '',
 							'id'	=>  'suggest',
@@ -980,7 +980,7 @@ function contact_actions($contact) {
 	if($poll_enabled) {
 		$contact_actions['update'] = array(
 							'label'	=> t('Update now'),
-							'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/update',
+							'url'	=> 'contacts/' . $contact['id'] . '/update',
 							'title'	=> '',
 							'sel'	=> '',
 							'id'	=> 'update',
@@ -989,7 +989,7 @@ function contact_actions($contact) {
 
 	$contact_actions['block'] = array(
 						'label'	=> (intval($contact['blocked']) ? t('Unblock') : t('Block') ),
-						'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/block',
+						'url'	=> 'contacts/' . $contact['id'] . '/block',
 						'title' => t('Toggle Blocked status'),
 						'sel'	=> (intval($contact['blocked']) ? 'active' : ''),
 						'id'	=> 'toggle-block',
@@ -997,7 +997,7 @@ function contact_actions($contact) {
 
 	$contact_actions['ignore'] = array(
 						'label'	=> (intval($contact['readonly']) ? t('Unignore') : t('Ignore') ),
-						'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/ignore',
+						'url'	=> 'contacts/' . $contact['id'] . '/ignore',
 						'title' => t('Toggle Ignored status'),
 						'sel'	=> (intval($contact['readonly']) ? 'active' : ''),
 						'id'	=> 'toggle-ignore',
@@ -1005,7 +1005,7 @@ function contact_actions($contact) {
 
 	$contact_actions['archive'] = array(
 						'label'	=> (intval($contact['archive']) ? t('Unarchive') : t('Archive') ),
-						'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/archive',
+						'url'	=> 'contacts/' . $contact['id'] . '/archive',
 						'title' => t('Toggle Archive status'),
 						'sel'	=> (intval($contact['archive']) ? 'active' : ''),
 						'id'	=> 'toggle-archive',
@@ -1013,7 +1013,7 @@ function contact_actions($contact) {
 
 	$contact_actions['delete'] = array(
 						'label'	=> t('Delete'),
-						'url'	=> app::get_baseurl(true) . '/contacts/' . $contact['id'] . '/drop', 
+						'url'	=> 'contacts/' . $contact['id'] . '/drop', 
 						'title'	=> t('Delete contact'),
 						'sel'	=> '',
 						'id'	=> 'delete',

From 86339cdb976f4ca28499b61e849cbcaa3f245e8b Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 23 Feb 2016 22:45:06 +0100
Subject: [PATCH 122/273] Some documentation for the usage of the "abstract"
 element.

---
 doc/BBCode.md    | 58 ++++++++++++++++++++++++++++++++++++++++++++++--
 doc/de/BBCode.md | 58 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/doc/BBCode.md b/doc/BBCode.md
index fe7c1481f6..a45431f586 100644
--- a/doc/BBCode.md
+++ b/doc/BBCode.md
@@ -143,6 +143,62 @@ Map
 You can embed maps from coordinates or addresses. 
 This require "openstreetmap" addon version 1.3 or newer.
 
+-----------------------------------------------------------
+
+Abstract for longer posts
+-------------------------
+
+If you want to spread your post to several third party networks you can 
+have the problem that these networks have (for example) a length 
+limitation. (Like on Twitter)
+
+Friendica is using a semi intelligent mechanism to generate a fitting 
+abstract. But it can be interesting to define an own abstract that will 
+only be displayed on the external network. This is done with the 
+[abstract]-element. Example:
+
+<pre>[abstract]Totally interesting! A must-see! Please click the link![/abstract]
+I want to tell you a really boring story that you really never wanted 
+to hear.</pre>
+
+Twitter would display the text "Totally interesting! A must-see! Please 
+click the link!". On Friendica you would only see the text after "I 
+want to tell you a really ..."
+
+It is even possible to define abstracts for separate networks:
+
+<pre>
+[abstract]Hi friends Here are my newest pictures![abstract]
+[abstract=twit]Hi my dear Twitter followers. Do you want to see my new 
+pictures?[abstract]
+[abstract=apdn]Helly my dear followers on ADN. I made sone new pictures 
+that I wanted to share with you.[abstract]
+Today I was in the woods and took some real cool pictures ...
+</pre>
+
+For Twitter and App.net the system will use the defined abstracts. For 
+other networks (e.g. when you are using the Statusnet connector) the 
+general abstract element will be used.
+
+If you use (for example) the "buffer" connector to post to Facebook or 
+Google+ you can use this element to define an abstract for a longer 
+blogpost that you don't want to post completely to these networks.
+
+Networks like Facebook or Google+ aren't length limited. For this reason 
+the [abstract] element isn't used. Instead you have to name the explicit 
+network:
+
+<pre>
+[abstract]These days I had a strange encounter ...[abstract]
+[abstract=goog]Helly my dear Google+ followers. You have to read my 
+newest blog post![abstract]
+[abstract=face]Hello my Facebook friends. These days happened something 
+really cool.[abstract]
+While taking pictures in the woods I had a really strange encounter ... </pre>
+
+The [abstract] element isn't working with the native OStatus connection 
+or with connectors where we post the HTML. (Like Tumblr, Wordpress or 
+Pump.io)
 
 Special
 -------
@@ -150,5 +206,3 @@ Special
 If you need to put literal bbcode in a message, [noparse], [nobb] or [pre] are used to escape bbcode:
 
 <pre>[noparse][b]bold[/b][/noparse]</pre> : [b]bold[/b]
-
-
diff --git a/doc/de/BBCode.md b/doc/de/BBCode.md
index d3e205f0fa..0856c30e50 100644
--- a/doc/de/BBCode.md
+++ b/doc/de/BBCode.md
@@ -145,6 +145,64 @@ eine Karte von [OpenStreetmap](http://openstreetmap.org) eingebettet werden. Zur
 
 oder eine Adresse in obiger Form verwendet werden.
 
+Zusammenfassung für längere Beiträge
+------------------------------------
+
+Wenn man seine Beiträge über mehrere Netzwerke verbreiten möchte, hat 
+man häufig das Problem, dass diese Netzwerke z.B. eine 
+Längenbeschränkung haben. (Z.B. Twitter).
+
+Friendica benutzt zum Erzeugen eines Anreißtextes eine halbwegs 
+intelligente Logik. Es kann aber dennoch von Interesse sein, eine eigene 
+Zusammenfassung zu erstellen, die nur auf dem Fremdnetzwerk dargestellt 
+wird. Dies geschieht mit dem [abstract]-Element. Beispiel:
+
+<pre>[abstract]Total spannend! Unbedingt diesen Link anklicken![/abstract]
+Hier erzähle ich euch eine total langweilige Geschichte, die ihr noch 
+nie hören wolltet.</pre>
+
+Auf Twitter würde das "Total spannend! Unbedingt diesen Link anklicken!" 
+stehen, auf Friendica würde nur der Text nach "Hier erzähle ..." 
+erscheinen.
+
+Es ist sogar möglich, für einzelne Netzwerke eigene Zusammenfassungen zu 
+erstellen:
+
+<pre>
+[abstract]Hallo Leute, hier meine neuesten Bilder![abstract]
+[abstract=twit]Hallo Twitter-User, hier meine neuesten Bilder![abstract]
+[abstract=apdn]Hallo App.net-User, hier meine neuesten Bilder![abstract]
+Ich war heute wieder im Wald unterwegs und habe tolle Bilder geschossen ...
+</pre>
+
+Für Twitter und App.net nimmt das System die entsprechenden Texte. Bei 
+anderen Netzwerken, bei denen der Inhalt gekürzt wird (z.B. beim 
+Statusnet-Connector) wird dann die Zusammenfassung unter [abstract] 
+verwendet.
+
+Wenn man z.B. den "buffer"-Connector verwendet, um nach Facebook oder 
+Google+ zu posten, kann man dieses Element ebenfalls verwenden, wenn man 
+z.B. einen längeren Blogbeitrag erstellt hat, aber ihn nicht komplett in 
+diese Netzwerke posten möchte.
+
+Netzwerke wie Facebook oder Google+ sind nicht in der Postinglänge 
+beschränkt. Aus diesem Grund greift nicht die 
+[abstract]-Zusammenfassung. Stattdessen muss man das Netzwerk explizit 
+angeben:
+
+<pre>
+[abstract]Ich habe neulich wieder etwas erlebt, was ich euch mitteilen möchte.[abstract]
+[abstract=goog]Hallo meine Google+-Kreislinge. Ich habe neulich wieder 
+etwas erlebt, was ich euch mitteilen möchte.[abstract]
+[abstract=face]Hallo Facebook-Freunde! Ich habe neulich wieder etwas 
+erlebt, was ich euch mitteilen möchte.[abstract]
+Beim Bildermachen im Wald habe ich neulich eine interessante Person 
+getroffen ... </pre>
+
+Das [abstract]-Element greift nicht bei der nativen OStatus-Verbindung 
+oder bei Connectoren, die den HTML-Text posten wie z.B. die Connectoren 
+zu Tumblr, Wordpress oder Pump.io.
+
 Spezielle Tags
 -------
 

From a153f49920b2f563cd7d8f8eed36e94fa8d55a11 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Fri, 5 Feb 2016 06:47:17 +0100
Subject: [PATCH 123/273] clarification to the docs

---
 doc/Bugs-and-Issues.md | 2 ++
 doc/Connectors.md      | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/doc/Bugs-and-Issues.md b/doc/Bugs-and-Issues.md
index 366b2ed662..0ece265a24 100644
--- a/doc/Bugs-and-Issues.md
+++ b/doc/Bugs-and-Issues.md
@@ -6,6 +6,8 @@ Bugs and Issues
 If your server has a support page, you should report any bugs/issues you encounter there first.
 Reporting to your support page before reporting to the developers makes their job easier, as they don't have to deal with bug reports that might not have anything to do with them.
 This helps us get new features faster.
+You can also contact the [friendica support forum](https://helpers.pyxis.uberspace.de/profile/helpers) and report your problem there.
+Maybe someone from another node encountered the problem as well and can help you.
 
 If you're a technical user, or your site doesn't have a support page, you'll need to use the [Bug Tracker](http://bugs.friendica.com/).
 Please perform a search to see if there's already an open bug that matches yours before submitting anything.
diff --git a/doc/Connectors.md b/doc/Connectors.md
index cd4b643f14..148352c552 100644
--- a/doc/Connectors.md
+++ b/doc/Connectors.md
@@ -57,13 +57,15 @@ All that the pages need to have is a discoverable feed using either the RSS or A
 Twitter
 ---
 
-To follow a Twitter member, put the URL of the Twitter member's main page into the Connect box on your [Contacts](contacts) page.
+To follow a Twitter member, the Twitter-Connector (Addon) needs to be configured on your node.
+If this is the case put the URL of the Twitter member's main page into the Connect box on your [Contacts](contacts) page.
 To reply, you must have the Twitter connector installed, and reply using your own status editor.
 Begin the message with @twitterperson replacing with the Twitter username.
 
 Email
 ---
 
+If the php module for IMAP support is available on your server, Friendica can connect to email contacts as well.
 Configure the email connector from your [Settings](settings) page.
 Once this has been done, you may enter an email address to connect with using the Connect box on your [Contacts](contacts) page.
 They must be the sender of a message which is currently in your INBOX for the connection to succeed.

From eec0dbf7387db818fbee4f4cd8c2e96af73c8418 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 24 Feb 2016 07:20:23 +0100
Subject: [PATCH 124/273] Bugfix: Resharing on the display page works again.

---
 mod/display.php | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/mod/display.php b/mod/display.php
index 4e33927072..e088b2fbbd 100644
--- a/mod/display.php
+++ b/mod/display.php
@@ -347,10 +347,8 @@ function display_content(&$a, $update = 0) {
 		return;
 	}
 
-	// Why do we need this on the display page? We don't have the possibility to write new content here.
-	// Ad editing of posts work without this as well.
-	// We should remove this completely for the 3.5.1 release.
-	/*
+	// We meed the editor here if we want to reshare an item.
+
 	if ($is_owner) {
 		$x = array(
 			'is_owner' => true,
@@ -366,7 +364,6 @@ function display_content(&$a, $update = 0) {
 		);
 		$o .= status_editor($a,$x,0,true);
 	}
-	*/
 
 	$sql_extra = item_permissions_sql($a->profile['uid'],$remote_contact,$groups);
 

From 99bac3a4d8cc75651b3efaf6fe55f2b7eb4fc95b Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 24 Feb 2016 07:22:32 +0100
Subject: [PATCH 125/273] Corrected explanation

---
 mod/display.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mod/display.php b/mod/display.php
index e088b2fbbd..97261e267d 100644
--- a/mod/display.php
+++ b/mod/display.php
@@ -347,7 +347,7 @@ function display_content(&$a, $update = 0) {
 		return;
 	}
 
-	// We meed the editor here if we want to reshare an item.
+	// We need the editor here to be able to reshare an item.
 
 	if ($is_owner) {
 		$x = array(

From db9266346675b164a37c1ff3ea393f02d37af47f Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 24 Feb 2016 07:33:20 +0100
Subject: [PATCH 126/273] One line, one sentence

---
 doc/BBCode.md    | 29 +++++++----------------------
 doc/de/BBCode.md | 40 +++++++++-------------------------------
 2 files changed, 16 insertions(+), 53 deletions(-)

diff --git a/doc/BBCode.md b/doc/BBCode.md
index a45431f586..75cad5d96f 100644
--- a/doc/BBCode.md
+++ b/doc/BBCode.md
@@ -148,22 +148,15 @@ This require "openstreetmap" addon version 1.3 or newer.
 Abstract for longer posts
 -------------------------
 
-If you want to spread your post to several third party networks you can 
-have the problem that these networks have (for example) a length 
-limitation. (Like on Twitter)
+If you want to spread your post to several third party networks you can have the problem that these networks have (for example) a length limitation. (Like on Twitter)
 
-Friendica is using a semi intelligent mechanism to generate a fitting 
-abstract. But it can be interesting to define an own abstract that will 
-only be displayed on the external network. This is done with the 
-[abstract]-element. Example:
+Friendica is using a semi intelligent mechanism to generate a fitting abstract. But it can be interesting to define an own abstract that will only be displayed on the external network. This is done with the [abstract]-element. Example:
 
 <pre>[abstract]Totally interesting! A must-see! Please click the link![/abstract]
 I want to tell you a really boring story that you really never wanted 
 to hear.</pre>
 
-Twitter would display the text "Totally interesting! A must-see! Please 
-click the link!". On Friendica you would only see the text after "I 
-want to tell you a really ..."
+Twitter would display the text "Totally interesting! A must-see! Please click the link!". On Friendica you would only see the text after "I want to tell you a really ..."
 
 It is even possible to define abstracts for separate networks:
 
@@ -176,17 +169,11 @@ that I wanted to share with you.[abstract]
 Today I was in the woods and took some real cool pictures ...
 </pre>
 
-For Twitter and App.net the system will use the defined abstracts. For 
-other networks (e.g. when you are using the Statusnet connector) the 
-general abstract element will be used.
+For Twitter and App.net the system will use the defined abstracts. For other networks (e.g. when you are using the Statusnet connector) the general abstract element will be used.
 
-If you use (for example) the "buffer" connector to post to Facebook or 
-Google+ you can use this element to define an abstract for a longer 
-blogpost that you don't want to post completely to these networks.
+If you use (for example) the "buffer" connector to post to Facebook or Google+ you can use this element to define an abstract for a longer blogpost that you don't want to post completely to these networks.
 
-Networks like Facebook or Google+ aren't length limited. For this reason 
-the [abstract] element isn't used. Instead you have to name the explicit 
-network:
+Networks like Facebook or Google+ aren't length limited. For this reason the [abstract] element isn't used. Instead you have to name the explicit network:
 
 <pre>
 [abstract]These days I had a strange encounter ...[abstract]
@@ -196,9 +183,7 @@ newest blog post![abstract]
 really cool.[abstract]
 While taking pictures in the woods I had a really strange encounter ... </pre>
 
-The [abstract] element isn't working with the native OStatus connection 
-or with connectors where we post the HTML. (Like Tumblr, Wordpress or 
-Pump.io)
+The [abstract] element isn't working with the native OStatus connection or with connectors where we post the HTML. (Like Tumblr, Wordpress or Pump.io)
 
 Special
 -------
diff --git a/doc/de/BBCode.md b/doc/de/BBCode.md
index 0856c30e50..d299072d61 100644
--- a/doc/de/BBCode.md
+++ b/doc/de/BBCode.md
@@ -131,8 +131,7 @@ Au&szlig;erdem kann *url* die genaue url zu einer ogg Datei sein, die dann per H
 
 <pre>[url]*url*[/url]</pre>
 
-Wenn *url* entweder oembed oder opengraph unterstützt wird das eingebettete
-Objekt (z.B. ein Dokument von scribd) eingebunden.
+Wenn *url* entweder oembed oder opengraph unterstützt wird das eingebettete Objekt (z.B. ein Dokument von scribd) eingebunden.
 Der Titel der Seite mit einem Link zur *url* wird ebenfalls angezeigt.
 
 Um eine Karte in einen Beitrag einzubinden, muss das *openstreetmap* Addon aktiviert werden. Ist dies der Fall, kann mit
@@ -148,25 +147,17 @@ oder eine Adresse in obiger Form verwendet werden.
 Zusammenfassung für längere Beiträge
 ------------------------------------
 
-Wenn man seine Beiträge über mehrere Netzwerke verbreiten möchte, hat 
-man häufig das Problem, dass diese Netzwerke z.B. eine 
-Längenbeschränkung haben. (Z.B. Twitter).
+Wenn man seine Beiträge über mehrere Netzwerke verbreiten möchte, hat man häufig das Problem, dass diese Netzwerke z.B. eine Längenbeschränkung haben. (Z.B. Twitter).
 
-Friendica benutzt zum Erzeugen eines Anreißtextes eine halbwegs 
-intelligente Logik. Es kann aber dennoch von Interesse sein, eine eigene 
-Zusammenfassung zu erstellen, die nur auf dem Fremdnetzwerk dargestellt 
-wird. Dies geschieht mit dem [abstract]-Element. Beispiel:
+Friendica benutzt zum Erzeugen eines Anreißtextes eine halbwegs intelligente Logik. Es kann aber dennoch von Interesse sein, eine eigene Zusammenfassung zu erstellen, die nur auf dem Fremdnetzwerk dargestellt wird. Dies geschieht mit dem [abstract]-Element. Beispiel:
 
 <pre>[abstract]Total spannend! Unbedingt diesen Link anklicken![/abstract]
 Hier erzähle ich euch eine total langweilige Geschichte, die ihr noch 
 nie hören wolltet.</pre>
 
-Auf Twitter würde das "Total spannend! Unbedingt diesen Link anklicken!" 
-stehen, auf Friendica würde nur der Text nach "Hier erzähle ..." 
-erscheinen.
+Auf Twitter würde das "Total spannend! Unbedingt diesen Link anklicken!" stehen, auf Friendica würde nur der Text nach "Hier erzähle ..." erscheinen.
 
-Es ist sogar möglich, für einzelne Netzwerke eigene Zusammenfassungen zu 
-erstellen:
+Es ist sogar möglich, für einzelne Netzwerke eigene Zusammenfassungen zu erstellen:
 
 <pre>
 [abstract]Hallo Leute, hier meine neuesten Bilder![abstract]
@@ -175,20 +166,11 @@ erstellen:
 Ich war heute wieder im Wald unterwegs und habe tolle Bilder geschossen ...
 </pre>
 
-Für Twitter und App.net nimmt das System die entsprechenden Texte. Bei 
-anderen Netzwerken, bei denen der Inhalt gekürzt wird (z.B. beim 
-Statusnet-Connector) wird dann die Zusammenfassung unter [abstract] 
-verwendet.
+Für Twitter und App.net nimmt das System die entsprechenden Texte. Bei anderen Netzwerken, bei denen der Inhalt gekürzt wird (z.B. beim Statusnet-Connector) wird dann die Zusammenfassung unter [abstract] verwendet.
 
-Wenn man z.B. den "buffer"-Connector verwendet, um nach Facebook oder 
-Google+ zu posten, kann man dieses Element ebenfalls verwenden, wenn man 
-z.B. einen längeren Blogbeitrag erstellt hat, aber ihn nicht komplett in 
-diese Netzwerke posten möchte.
+Wenn man z.B. den "buffer"-Connector verwendet, um nach Facebook oder Google+ zu posten, kann man dieses Element ebenfalls verwenden, wenn man z.B. einen längeren Blogbeitrag erstellt hat, aber ihn nicht komplett in diese Netzwerke posten möchte.
 
-Netzwerke wie Facebook oder Google+ sind nicht in der Postinglänge 
-beschränkt. Aus diesem Grund greift nicht die 
-[abstract]-Zusammenfassung. Stattdessen muss man das Netzwerk explizit 
-angeben:
+Netzwerke wie Facebook oder Google+ sind nicht in der Postinglänge beschränkt. Aus diesem Grund greift nicht die [abstract]-Zusammenfassung. Stattdessen muss man das Netzwerk explizit angeben:
 
 <pre>
 [abstract]Ich habe neulich wieder etwas erlebt, was ich euch mitteilen möchte.[abstract]
@@ -199,9 +181,7 @@ erlebt, was ich euch mitteilen möchte.[abstract]
 Beim Bildermachen im Wald habe ich neulich eine interessante Person 
 getroffen ... </pre>
 
-Das [abstract]-Element greift nicht bei der nativen OStatus-Verbindung 
-oder bei Connectoren, die den HTML-Text posten wie z.B. die Connectoren 
-zu Tumblr, Wordpress oder Pump.io.
+Das [abstract]-Element greift nicht bei der nativen OStatus-Verbindung oder bei Connectoren, die den HTML-Text posten wie z.B. die Connectoren zu Tumblr, Wordpress oder Pump.io.
 
 Spezielle Tags
 -------
@@ -209,5 +189,3 @@ Spezielle Tags
 Wenn Du &uuml;ber BBCode Tags in einer Nachricht schreiben m&ouml;chtest, kannst Du [noparse], [nobb] oder [pre] verwenden um den BBCode Tags vor der Evaluierung zu sch&uuml;tzen:
 
 <pre>[noparse][b]fett[/b][/noparse]</pre> : [b]fett[/b]
-
-

From 8369e6ce596b766745ccae3e70b74d2b0a6b50ae Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 24 Feb 2016 07:37:18 +0100
Subject: [PATCH 127/273] Clarification between statusnet and GNU Social.

---
 doc/BBCode.md    | 2 +-
 doc/de/BBCode.md | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/doc/BBCode.md b/doc/BBCode.md
index 75cad5d96f..5aa33fd81b 100644
--- a/doc/BBCode.md
+++ b/doc/BBCode.md
@@ -169,7 +169,7 @@ that I wanted to share with you.[abstract]
 Today I was in the woods and took some real cool pictures ...
 </pre>
 
-For Twitter and App.net the system will use the defined abstracts. For other networks (e.g. when you are using the Statusnet connector) the general abstract element will be used.
+For Twitter and App.net the system will use the defined abstracts. For other networks (e.g. when you are using the "statusnet" connector that is used to post to GNU Social) the general abstract element will be used.
 
 If you use (for example) the "buffer" connector to post to Facebook or Google+ you can use this element to define an abstract for a longer blogpost that you don't want to post completely to these networks.
 
diff --git a/doc/de/BBCode.md b/doc/de/BBCode.md
index d299072d61..5f24fa2b61 100644
--- a/doc/de/BBCode.md
+++ b/doc/de/BBCode.md
@@ -166,7 +166,7 @@ Es ist sogar möglich, für einzelne Netzwerke eigene Zusammenfassungen zu erste
 Ich war heute wieder im Wald unterwegs und habe tolle Bilder geschossen ...
 </pre>
 
-Für Twitter und App.net nimmt das System die entsprechenden Texte. Bei anderen Netzwerken, bei denen der Inhalt gekürzt wird (z.B. beim Statusnet-Connector) wird dann die Zusammenfassung unter [abstract] verwendet.
+Für Twitter und App.net nimmt das System die entsprechenden Texte. Bei anderen Netzwerken, bei denen der Inhalt gekürzt wird (z.B. beim "statusnet"-Connector, der für das Posten nach GNU Social verwendet wird) wird dann die Zusammenfassung unter [abstract] verwendet.
 
 Wenn man z.B. den "buffer"-Connector verwendet, um nach Facebook oder Google+ zu posten, kann man dieses Element ebenfalls verwenden, wenn man z.B. einen längeren Blogbeitrag erstellt hat, aber ihn nicht komplett in diese Netzwerke posten möchte.
 

From 68d7beb2981c22e4251542c835fac0ac40421390 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 24 Feb 2016 07:43:13 +0100
Subject: [PATCH 128/273] Welcome to the live editing and commenting of the
 pull request ;-)

---
 doc/BBCode.md    | 18 +++++++++++++-----
 doc/de/BBCode.md | 14 ++++++++++----
 2 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/doc/BBCode.md b/doc/BBCode.md
index 5aa33fd81b..803f716aeb 100644
--- a/doc/BBCode.md
+++ b/doc/BBCode.md
@@ -148,15 +148,20 @@ This require "openstreetmap" addon version 1.3 or newer.
 Abstract for longer posts
 -------------------------
 
-If you want to spread your post to several third party networks you can have the problem that these networks have (for example) a length limitation. (Like on Twitter)
+If you want to spread your post to several third party networks you can have the problem that these networks have (for example) a length limitation. 
+(Like on Twitter)
 
-Friendica is using a semi intelligent mechanism to generate a fitting abstract. But it can be interesting to define an own abstract that will only be displayed on the external network. This is done with the [abstract]-element. Example:
+Friendica is using a semi intelligent mechanism to generate a fitting abstract. 
+But it can be interesting to define an own abstract that will only be displayed on the external network. 
+This is done with the [abstract]-element. 
+Example:
 
 <pre>[abstract]Totally interesting! A must-see! Please click the link![/abstract]
 I want to tell you a really boring story that you really never wanted 
 to hear.</pre>
 
-Twitter would display the text "Totally interesting! A must-see! Please click the link!". On Friendica you would only see the text after "I want to tell you a really ..."
+Twitter would display the text "Totally interesting! A must-see! Please click the link!". 
+On Friendica you would only see the text after "I want to tell you a really ..."
 
 It is even possible to define abstracts for separate networks:
 
@@ -173,7 +178,9 @@ For Twitter and App.net the system will use the defined abstracts. For other net
 
 If you use (for example) the "buffer" connector to post to Facebook or Google+ you can use this element to define an abstract for a longer blogpost that you don't want to post completely to these networks.
 
-Networks like Facebook or Google+ aren't length limited. For this reason the [abstract] element isn't used. Instead you have to name the explicit network:
+Networks like Facebook or Google+ aren't length limited. 
+For this reason the [abstract] element isn't used. 
+Instead you have to name the explicit network:
 
 <pre>
 [abstract]These days I had a strange encounter ...[abstract]
@@ -183,7 +190,8 @@ newest blog post![abstract]
 really cool.[abstract]
 While taking pictures in the woods I had a really strange encounter ... </pre>
 
-The [abstract] element isn't working with the native OStatus connection or with connectors where we post the HTML. (Like Tumblr, Wordpress or Pump.io)
+The [abstract] element isn't working with the native OStatus connection or with connectors where we post the HTML. 
+(Like Tumblr, Wordpress or Pump.io)
 
 Special
 -------
diff --git a/doc/de/BBCode.md b/doc/de/BBCode.md
index 5f24fa2b61..cd9fa7673e 100644
--- a/doc/de/BBCode.md
+++ b/doc/de/BBCode.md
@@ -147,9 +147,13 @@ oder eine Adresse in obiger Form verwendet werden.
 Zusammenfassung für längere Beiträge
 ------------------------------------
 
-Wenn man seine Beiträge über mehrere Netzwerke verbreiten möchte, hat man häufig das Problem, dass diese Netzwerke z.B. eine Längenbeschränkung haben. (Z.B. Twitter).
+Wenn man seine Beiträge über mehrere Netzwerke verbreiten möchte, hat man häufig das Problem, dass diese Netzwerke z.B. eine Längenbeschränkung haben. 
+(Z.B. Twitter).
 
-Friendica benutzt zum Erzeugen eines Anreißtextes eine halbwegs intelligente Logik. Es kann aber dennoch von Interesse sein, eine eigene Zusammenfassung zu erstellen, die nur auf dem Fremdnetzwerk dargestellt wird. Dies geschieht mit dem [abstract]-Element. Beispiel:
+Friendica benutzt zum Erzeugen eines Anreißtextes eine halbwegs intelligente Logik. 
+Es kann aber dennoch von Interesse sein, eine eigene Zusammenfassung zu erstellen, die nur auf dem Fremdnetzwerk dargestellt wird. 
+Dies geschieht mit dem [abstract]-Element. 
+Beispiel:
 
 <pre>[abstract]Total spannend! Unbedingt diesen Link anklicken![/abstract]
 Hier erzähle ich euch eine total langweilige Geschichte, die ihr noch 
@@ -166,11 +170,13 @@ Es ist sogar möglich, für einzelne Netzwerke eigene Zusammenfassungen zu erste
 Ich war heute wieder im Wald unterwegs und habe tolle Bilder geschossen ...
 </pre>
 
-Für Twitter und App.net nimmt das System die entsprechenden Texte. Bei anderen Netzwerken, bei denen der Inhalt gekürzt wird (z.B. beim "statusnet"-Connector, der für das Posten nach GNU Social verwendet wird) wird dann die Zusammenfassung unter [abstract] verwendet.
+Für Twitter und App.net nimmt das System die entsprechenden Texte. 
+Bei anderen Netzwerken, bei denen der Inhalt gekürzt wird (z.B. beim "statusnet"-Connector, der für das Posten nach GNU Social verwendet wird) wird dann die Zusammenfassung unter [abstract] verwendet.
 
 Wenn man z.B. den "buffer"-Connector verwendet, um nach Facebook oder Google+ zu posten, kann man dieses Element ebenfalls verwenden, wenn man z.B. einen längeren Blogbeitrag erstellt hat, aber ihn nicht komplett in diese Netzwerke posten möchte.
 
-Netzwerke wie Facebook oder Google+ sind nicht in der Postinglänge beschränkt. Aus diesem Grund greift nicht die [abstract]-Zusammenfassung. Stattdessen muss man das Netzwerk explizit angeben:
+Netzwerke wie Facebook oder Google+ sind nicht in der Postinglänge beschränkt. 
+Aus diesem Grund greift nicht die [abstract]-Zusammenfassung. Stattdessen muss man das Netzwerk explizit angeben:
 
 <pre>
 [abstract]Ich habe neulich wieder etwas erlebt, was ich euch mitteilen möchte.[abstract]

From 1b14b22b76e26bd5bdee728321dd79f6c8b9913b Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Wed, 24 Feb 2016 20:46:06 +0100
Subject: [PATCH 129/273] Client section in DeveloperIntro docs

---
 doc/Developers-Intro.md | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/doc/Developers-Intro.md b/doc/Developers-Intro.md
index 10bbd5632a..8e3cd03b18 100644
--- a/doc/Developers-Intro.md
+++ b/doc/Developers-Intro.md
@@ -83,11 +83,11 @@ Ask us to find out whom to talk to about their experiences.
 Do not worry about cross-posting.
 
 ###Client software
-There are free software clients that do somehow work with Friendica but most of them need love and maintenance.
-Also, they were mostly made for other platforms using the GNU Social API.
-This means they lack the features that are really specific to Friendica.
-Popular clients you might want to have a look at are:
+As Friendica is using a [Twitter/GNU Social compatible API](help/api) any of the clients for those platforms should work with Friendica as well.
+Furthermore there are several client projects, especially for use with Friendica.
+If you are interested in improving those clients, please contact the developers of the clients directly.
 
-* [Hotot (Linux)](http://hotot.org/) - abandoned
-* [Friendica for Android](https://github.com/max-weller/friendica-for-android) - abandoned
-* You can find more working client software in [Wikipedia](https://en.wikipedia.org/wiki/Friendica).
+* Android / CynogenMod: **Friendica for Android** [src](https://github.com/max-weller/friendica-for-android), [homepage](http://friendica.android.max-weller.de/) - abandoned
+* iOS: *currently no client*
+* SailfishOS: **Friendiy** [src](https://kirgroup.com/projects/fabrixxm/harbour-friendly) - developed by [Fabio](https://kirgroup.com/profile/fabrixxm/?tab=profile)
+* Windows: **Friendica Mobile** for Windows versions [before 8.1](http://windowsphone.com/s?appid=e3257730-c9cf-4935-9620-5261e3505c67) and [Windows 10](https://www.microsoft.com/store/apps/9nblggh0fhmn) - developed by [Gerhard Seeber](http://mozartweg.dyndns.org/friendica/profile/gerhard/?tab=profile)

From f4b0e9316eb77ac1acd28bc34ccf87bca9283059 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Thu, 25 Feb 2016 21:37:37 +0100
Subject: [PATCH 130/273] a missing break

---
 doc/BBCode.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/doc/BBCode.md b/doc/BBCode.md
index 803f716aeb..186b1cda93 100644
--- a/doc/BBCode.md
+++ b/doc/BBCode.md
@@ -174,7 +174,8 @@ that I wanted to share with you.[abstract]
 Today I was in the woods and took some real cool pictures ...
 </pre>
 
-For Twitter and App.net the system will use the defined abstracts. For other networks (e.g. when you are using the "statusnet" connector that is used to post to GNU Social) the general abstract element will be used.
+For Twitter and App.net the system will use the defined abstracts.
+For other networks (e.g. when you are using the "statusnet" connector that is used to post to GNU Social) the general abstract element will be used.
 
 If you use (for example) the "buffer" connector to post to Facebook or Google+ you can use this element to define an abstract for a longer blogpost that you don't want to post completely to these networks.
 

From a3960bda371c8083bad2ed422169282fed004d24 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 27 Feb 2016 23:54:17 +0100
Subject: [PATCH 131/273] New Diaspora code

---
 include/diaspora.php  |  37 +++
 include/diaspora2.php | 638 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 675 insertions(+)
 create mode 100644 include/diaspora2.php

diff --git a/include/diaspora.php b/include/diaspora.php
index 93fe2a472f..9dbbeabbcf 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -58,6 +58,8 @@ function diaspora_dispatch($importer,$msg,$attempt=1) {
 		return;
 	}
 
+	$data = $msg;
+
 	// php doesn't like dashes in variable names
 
 	$msg['message'] = str_replace(
@@ -74,48 +76,83 @@ function diaspora_dispatch($importer,$msg,$attempt=1) {
 
 
 	if($xmlbase->request) {
+		$tempfile = tempnam(get_temppath(), "diaspora-request");
+		file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_request($importer,$xmlbase->request);
 	}
 	elseif($xmlbase->status_message) {
+		//$tempfile = tempnam(get_temppath(), "diaspora-status_message");
+		//file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_post($importer,$xmlbase->status_message,$msg);
 	}
 	elseif($xmlbase->profile) {
+		//$tempfile = tempnam(get_temppath(), "diaspora-profile");
+		//file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_profile($importer,$xmlbase->profile,$msg);
 	}
 	elseif($xmlbase->comment) {
+		//$tempfile = tempnam(get_temppath(), "diaspora-comment");
+		//file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_comment($importer,$xmlbase->comment,$msg);
 	}
 	elseif($xmlbase->like) {
+		//$tempfile = tempnam(get_temppath(), "diaspora-like");
+		//file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_like($importer,$xmlbase->like,$msg);
 	}
 	elseif($xmlbase->asphoto) {
+		$tempfile = tempnam(get_temppath(), "diaspora-asphoto");
+		file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_asphoto($importer,$xmlbase->asphoto,$msg);
 	}
 	elseif($xmlbase->reshare) {
+		//$tempfile = tempnam(get_temppath(), "diaspora-reshare");
+		//file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_reshare($importer,$xmlbase->reshare,$msg);
 	}
 	elseif($xmlbase->retraction) {
+		$tempfile = tempnam(get_temppath(), "diaspora-retraction");
+		file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_retraction($importer,$xmlbase->retraction,$msg);
 	}
 	elseif($xmlbase->signed_retraction) {
+		$tempfile = tempnam(get_temppath(), "diaspora-signed_retraction");
+		file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_signed_retraction($importer,$xmlbase->signed_retraction,$msg);
 	}
 	elseif($xmlbase->relayable_retraction) {
+		//$tempfile = tempnam(get_temppath(), "diaspora-relayable_retraction");
+		//file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_signed_retraction($importer,$xmlbase->relayable_retraction,$msg);
 	}
 	elseif($xmlbase->photo) {
+		//$tempfile = tempnam(get_temppath(), "diaspora-photo");
+		//file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_photo($importer,$xmlbase->photo,$msg,$attempt);
 	}
 	elseif($xmlbase->conversation) {
+		$tempfile = tempnam(get_temppath(), "diaspora-conversation");
+		file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_conversation($importer,$xmlbase->conversation,$msg);
 	}
 	elseif($xmlbase->message) {
+		$tempfile = tempnam(get_temppath(), "diaspora-message");
+		file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_message($importer,$xmlbase->message,$msg);
 	}
 	elseif($xmlbase->participation) {
+		//$tempfile = tempnam(get_temppath(), "diaspora-participation");
+		//file_put_contents($tempfile, json_encode($data));
+		$ret = diaspora_participation($importer,$xmlbase->participation);
+	}
+	elseif($xmlbase->poll_participation) {
+		$tempfile = tempnam(get_temppath(), "diaspora-poll_participation");
+		file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_participation($importer,$xmlbase->participation);
 	}
 	else {
+		$tempfile = tempnam(get_temppath(), "diaspora-unknown");
+		file_put_contents($tempfile, json_encode($data));
 		logger('diaspora_dispatch: unknown message type: ' . print_r($xmlbase,true));
 	}
 	return $ret;
diff --git a/include/diaspora2.php b/include/diaspora2.php
new file mode 100644
index 0000000000..690e54aa41
--- /dev/null
+++ b/include/diaspora2.php
@@ -0,0 +1,638 @@
+<?php
+/**
+ * @file include/diaspora.php
+ * @brief The implementation of the diaspora protocol
+ */
+
+require_once("include/diaspora.php");
+require_once("include/Scrape.php");
+
+function array_to_xml($array, &$xml) {
+
+	if (!is_object($xml)) {
+		foreach($array as $key => $value) {
+			$root = new SimpleXMLElement('<'.$key.'/>');
+			array_to_xml($value, $root);
+
+			$dom = dom_import_simplexml($root)->ownerDocument;
+			$dom->formatOutput = true;
+			return $dom->saveXML();
+		}
+	}
+
+	foreach($array as $key => $value) {
+		if (!is_array($value) AND !is_numeric($key))
+			$xml->addChild($key, $value);
+		elseif (is_array($value))
+			array_to_xml($value, $xml->addChild($key));
+	}
+}
+
+/**
+ * @brief This class contain functions to create and send DFRN XML files
+ *
+ */
+class diaspora {
+
+	public static function dispatch_public($msg) {
+
+		$enabled = intval(get_config("system", "diaspora_enabled"));
+		if (!$enabled) {
+			logger('diaspora is disabled');
+			return false;
+		}
+
+		// Use a dummy importer to import the data for the public copy
+		$importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE);
+		self::dispatch($importer,$msg);
+
+		// Now distribute it to the followers
+		$r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN
+			(SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s')
+			AND NOT `account_expired` AND NOT `account_removed`",
+			dbesc(NETWORK_DIASPORA),
+			dbesc($msg["author"])
+		);
+		if(count($r)) {
+			foreach($r as $rr) {
+				logger("delivering to: ".$rr["username"]);
+				self::dispatch($rr,$msg);
+			}
+		} else
+			logger("No subscribers for ".$msg["author"]." ".print_r($msg, true));
+	}
+
+	public static function dispatch($importer, $msg) {
+
+		// The sender is the handle of the contact that sent the message.
+		// This will often be different with relayed messages (for example "like" and "comment")
+		$sender = $msg->author;
+
+		if (!diaspora::valid_posting($msg, $fields)) {
+			logger("Invalid posting");
+			return false;
+		}
+
+		$type = $fields->getName();
+
+		switch ($type) {
+			case "account_deletion":
+				return self::import_account_deletion($importer, $fields);
+
+			case "comment":
+				return self::import_comment($importer, $sender, $fields);
+
+			case "conversation":
+				return self::import_conversation($importer, $fields);
+
+			case "like":
+				return self::import_like($importer, $sender, $fields);
+
+			case "message":
+				return self::import_message($importer, $fields);
+
+			case "participation":
+				return self::import_participation($importer, $fields);
+
+			case "photo":
+				return self::import_photo($importer, $fields);
+
+			case "poll_participation":
+				return self::import_poll_participation($importer, $fields);
+
+			case "profile":
+				return self::import_profile($importer, $fields);
+
+			case "request":
+				return self::import_request($importer, $fields);
+
+			case "reshare":
+				return self::import_reshare($importer, $fields);
+
+			case "retraction":
+				return self::import_retraction($importer, $fields);
+
+			case "status_message":
+				return self::import_status_message($importer, $fields);
+
+			default:
+				logger("Unknown message type ".$type);
+				return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * @brief Checks if a posting is valid and fetches the data fields.
+	 *
+	 * This function does not only check the signature.
+	 * It also does the conversion between the old and the new diaspora format.
+	 *
+	 * @param array $msg Array with the XML, the sender handle and the sender signature
+	 * @param object $fields SimpleXML object that contains the posting
+	 *
+	 * @return bool Is the posting valid?
+	 */
+	private function valid_posting($msg, &$fields) {
+
+		$data = parse_xml_string($msg->message, false);
+
+		$first_child = $data->getName();
+
+		if ($data->getName() == "XML") {
+			$oldXML = true;
+			foreach ($data->post->children() as $child)
+				$element = $child;
+		} else {
+			$oldXML = false;
+			$element = $data;
+		}
+
+		$type = $element->getName();
+
+		if (in_array($type, array("signed_retraction", "relayable_retraction")))
+			$type = "retraction";
+
+		$fields = new SimpleXMLElement("<".$type."/>");
+
+		$signed_data = "";
+
+		foreach ($element->children() AS $fieldname => $data) {
+
+			if ($oldXML) {
+				// Translation for the old XML structure
+				if ($fieldname == "diaspora_handle")
+					$fieldname = "author";
+
+				if ($fieldname == "participant_handles")
+					$fieldname = "participants";
+
+				if (in_array($type, array("like", "participation"))) {
+					if ($fieldname == "target_type")
+						$fieldname = "parent_type";
+				}
+
+				if ($fieldname == "sender_handle")
+					$fieldname = "author";
+
+				if ($fieldname == "recipient_handle")
+					$fieldname = "recipient";
+
+				if ($fieldname == "root_diaspora_id")
+					$fieldname = "root_author";
+
+				if ($type == "retraction") {
+					if ($fieldname == "post_guid")
+						$fieldname = "target_guid";
+
+					if ($fieldname == "type")
+						$fieldname = "target_type";
+				}
+			}
+
+			if ($fieldname == "author_signature")
+				$author_signature = base64_decode($data);
+			elseif ($fieldname == "parent_author_signature")
+				$parent_author_signature = base64_decode($data);
+			elseif ($fieldname != "target_author_signature") {
+				if ($signed_data != "") {
+					$signed_data .= ";";
+					$signed_data_parent .= ";";
+				}
+
+				$signed_data .= $data;
+				$fields->$fieldname = $data;
+			}
+		}
+
+		if (in_array($type, array("status_message", "reshare")))
+			if ($msg->author != $fields->author) {
+				logger("Message handle is not the same as envelope sender. Quitting this message.");
+				return false;
+			}
+
+		if (!in_array($type, array("comment", "conversation", "message", "like")))
+			return true;
+
+		if (!isset($author_signature))
+			return false;
+
+		if (isset($parent_author_signature)) {
+			$key = self::get_key($msg->author);
+
+			if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256"))
+				return false;
+		}
+
+		$key = self::get_key($fields->author);
+
+		return rsa_verify($signed_data, $author_signature, $key, "sha256");
+	}
+
+	private function get_key($handle) {
+		logger("Fetching diaspora key for: ".$handle);
+
+		$r = self::get_person_by_handle($handle);
+		if($r)
+			return $r["pubkey"];
+
+		return "";
+	}
+
+	private function get_person_by_handle($handle) {
+
+		$r = q("SELECT * FROM `fcontact` WHERE `network` = '%s' AND `addr` = '%s' LIMIT 1",
+			dbesc(NETWORK_DIASPORA),
+			dbesc($handle)
+		);
+		if (count($r)) {
+			$person = $r[0];
+			logger("In cache ".print_r($r,true), LOGGER_DEBUG);
+
+			// update record occasionally so it doesn't get stale
+			$d = strtotime($person["updated"]." +00:00");
+			if ($d < strtotime("now - 14 days"))
+				$update = true;
+		}
+
+		if (!$person OR $update) {
+			logger("create or refresh", LOGGER_DEBUG);
+			$r = probe_url($handle, PROBE_DIASPORA);
+
+			// Note that Friendica contacts will return a "Diaspora person"
+			// if Diaspora connectivity is enabled on their server
+			if (count($r) AND ($r["network"] === NETWORK_DIASPORA)) {
+				self::add_fcontact($r, $update);
+				$person = $r;
+			}
+		}
+		return $person;
+	}
+
+	private function add_fcontact($arr, $update = false) {
+		/// @todo Remove this function from include/network.php
+
+		if($update) {
+			$r = q("UPDATE `fcontact` SET
+					`name` = '%s',
+					`photo` = '%s',
+					`request` = '%s',
+					`nick` = '%s',
+					`addr` = '%s',
+					`batch` = '%s',
+					`notify` = '%s',
+					`poll` = '%s',
+					`confirm` = '%s',
+					`alias` = '%s',
+					`pubkey` = '%s',
+					`updated` = '%s'
+				WHERE `url` = '%s' AND `network` = '%s'",
+					dbesc($arr["name"]),
+					dbesc($arr["photo"]),
+					dbesc($arr["request"]),
+					dbesc($arr["nick"]),
+					dbesc($arr["addr"]),
+					dbesc($arr["batch"]),
+					dbesc($arr["notify"]),
+					dbesc($arr["poll"]),
+					dbesc($arr["confirm"]),
+					dbesc($arr["alias"]),
+					dbesc($arr["pubkey"]),
+					dbesc(datetime_convert()),
+					dbesc($arr["url"]),
+					dbesc($arr["network"])
+				);
+		} else {
+			$r = q("INSERT INTO `fcontact` (`url`,`name`,`photo`,`request`,`nick`,`addr`,
+					`batch`, `notify`,`poll`,`confirm`,`network`,`alias`,`pubkey`,`updated`)
+				VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')",
+					dbesc($arr["url"]),
+					dbesc($arr["name"]),
+					dbesc($arr["photo"]),
+					dbesc($arr["request"]),
+					dbesc($arr["nick"]),
+					dbesc($arr["addr"]),
+					dbesc($arr["batch"]),
+					dbesc($arr["notify"]),
+					dbesc($arr["poll"]),
+					dbesc($arr["confirm"]),
+					dbesc($arr["network"]),
+					dbesc($arr["alias"]),
+					dbesc($arr["pubkey"]),
+					dbesc(datetime_convert())
+				);
+		}
+
+		return $r;
+	}
+
+	private function get_contact_by_handle($uid, $handle) {
+		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `addr` = '%s' LIMIT 1",
+			intval($uid),
+			dbesc($handle)
+		);
+
+		if ($r AND count($r))
+			return $r[0];
+
+		$handle_parts = explode("@", $handle);
+		$nurl_sql = '%%://' . $handle_parts[1] . '%%/profile/' . $handle_parts[0];
+		$r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` LIKE '%s' LIMIT 1",
+			dbesc(NETWORK_DFRN),
+			intval($uid),
+			dbesc($nurl_sql)
+		);
+		if($r AND count($r))
+			return $r[0];
+
+		return false;
+	}
+
+/*
+function DiasporaFetchGuid($item) {
+        preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi",
+                function ($match) use ($item){
+                        return(DiasporaFetchGuidSub($match, $item));
+                },$item["body"]);
+}
+
+function DiasporaFetchGuidSub($match, $item) {
+        $a = get_app();
+
+        if (!diaspora_store_by_guid($match[1], $item["author-link"]))
+                diaspora_store_by_guid($match[1], $item["owner-link"]);
+}
+
+function diaspora_store_by_guid($guid, $server, $uid = 0) {
+        require_once("include/Contact.php");
+
+        $serverparts = parse_url($server);
+        $server = $serverparts["scheme"]."://".$serverparts["host"];
+
+        logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG);
+
+        $item = diaspora_fetch_message($guid, $server);
+
+        if (!$item)
+                return false;
+
+        logger("Successfully fetched item ".$guid." from ".$server, LOGGER_DEBUG);
+
+        $body = $item["body"];
+        $str_tags = $item["tag"];
+        $app = $item["app"];
+        $created = $item["created"];
+        $author = $item["author"];
+        $guid = $item["guid"];
+        $private = $item["private"];
+        $object = $item["object"];
+        $objecttype = $item["object-type"];
+
+        $message_id = $author.':'.$guid;
+        $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+                intval($uid),
+                dbesc($guid)
+        );
+        if(count($r))
+                return $r[0]["id"];
+
+        $person = find_diaspora_person_by_handle($author);
+
+        $contact_id = get_contact($person['url'], $uid);
+
+        $contacts = q("SELECT * FROM `contact` WHERE `id` = %d", intval($contact_id));
+        $importers = q("SELECT * FROM `user` WHERE `uid` = %d", intval($uid));
+
+        if ($contacts AND $importers)
+                if(!diaspora_post_allow($importers[0],$contacts[0], false)) {
+                        logger('Ignoring author '.$person['url'].' for uid '.$uid);
+                        return false;
+                } else
+                        logger('Author '.$person['url'].' is allowed for uid '.$uid);
+
+        $datarray = array();
+        $datarray['uid'] = $uid;
+        $datarray['contact-id'] = $contact_id;
+        $datarray['wall'] = 0;
+        $datarray['network'] = NETWORK_DIASPORA;
+        $datarray['guid'] = $guid;
+        $datarray['uri'] = $datarray['parent-uri'] = $message_id;
+        $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created);
+        $datarray['private'] = $private;
+        $datarray['parent'] = 0;
+        $datarray['plink'] = diaspora_plink($author, $guid);
+        $datarray['author-name'] = $person['name'];
+        $datarray['author-link'] = $person['url'];
+        $datarray['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']);
+        $datarray['owner-name'] = $datarray['author-name'];
+        $datarray['owner-link'] = $datarray['author-link'];
+        $datarray['owner-avatar'] = $datarray['author-avatar'];
+        $datarray['body'] = $body;
+        $datarray['tag'] = $str_tags;
+        $datarray['app']  = $app;
+        $datarray['visible'] = ((strlen($body)) ? 1 : 0);
+        $datarray['object'] = $object;
+        $datarray['object-type'] = $objecttype;
+
+        if ($datarray['contact-id'] == 0)
+                return false;
+
+        DiasporaFetchGuid($datarray);
+        $message_id = item_store($datarray);
+
+        /// @TODO
+        /// Looking if there is some subscribe mechanism in Diaspora to get all comments for this post
+
+        return $message_id;
+}
+*/
+
+	private function import_account_deletion($importer, $data) {
+		return true;
+	}
+
+	private function import_comment($importer, $sender, $data) {
+		$guid = notags(unxmlify($data->guid));
+		$parent_guid = notags(unxmlify($data->parent_guid));
+		$text = unxmlify($data->text);
+		$author = notags(unxmlify($data->author));
+
+		$contact = self::get_contact_by_handle($importer["uid"], $sender);
+		if (!$contact) {
+			logger("cannot find contact for sender: ".$sender);
+			return false;
+		}
+/*
+        if(! diaspora_post_allow($importer,$contact, true)) {
+                logger('diaspora_comment: Ignoring this author.');
+                return 202;
+        }
+
+        $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+                intval($importer['uid']),
+                dbesc($guid)
+        );
+        if(count($r)) {
+                logger('diaspora_comment: our comment just got relayed back to us (or there was a guid collision) : ' . $guid);
+                return;
+        }
+
+        $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+                intval($importer['uid']),
+                dbesc($parent_guid)
+        );
+
+        if(!count($r)) {
+                $result = diaspora_store_by_guid($parent_guid, $contact['url'], $importer['uid']);
+
+                if (!$result) {
+                        $person = find_diaspora_person_by_handle($diaspora_handle);
+                        $result = diaspora_store_by_guid($parent_guid, $person['url'], $importer['uid']);
+                }
+
+                if ($result) {
+                        logger("Fetched missing item ".$parent_guid." - result: ".$result, LOGGER_DEBUG);
+
+                        $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+                                intval($importer['uid']),
+                                dbesc($parent_guid)
+                        );
+                }
+        }
+
+        if(! count($r)) {
+                logger('diaspora_comment: parent item not found: parent: ' . $parent_guid . ' item: ' . $guid);
+                return;
+        }
+        $parent_item = $r[0];
+
+        // Find the original comment author information.
+        // We need this to make sure we display the comment author
+        // information (name and avatar) correctly.
+        if(strcasecmp($diaspora_handle,$msg['author']) == 0)
+                $person = $contact;
+        else {
+                $person = find_diaspora_person_by_handle($diaspora_handle);
+
+                if(! is_array($person)) {
+                        logger('diaspora_comment: unable to find author details');
+                        return;
+                }
+        }
+
+        // Fetch the contact id - if we know this contact
+        $r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
+                dbesc(normalise_link($person['url'])), intval($importer['uid']));
+        if ($r) {
+                $cid = $r[0]['id'];
+                $network = $r[0]['network'];
+        } else {
+                $cid = $contact['id'];
+                $network = NETWORK_DIASPORA;
+        }
+
+        $body = diaspora2bb($text);
+        $message_id = $diaspora_handle . ':' . $guid;
+
+        $datarray = array();
+
+        $datarray['uid'] = $importer['uid'];
+        $datarray['contact-id'] = $cid;
+        $datarray['type'] = 'remote-comment';
+        $datarray['wall'] = $parent_item['wall'];
+        $datarray['network']  = $network;
+        $datarray['verb'] = ACTIVITY_POST;
+        $datarray['gravity'] = GRAVITY_COMMENT;
+        $datarray['guid'] = $guid;
+        $datarray['uri'] = $message_id;
+        $datarray['parent-uri'] = $parent_item['uri'];
+
+        // No timestamps for comments? OK, we'll the use current time.
+        $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert();
+        $datarray['private'] = $parent_item['private'];
+
+        $datarray['owner-name'] = $parent_item['owner-name'];
+        $datarray['owner-link'] = $parent_item['owner-link'];
+        $datarray['owner-avatar'] = $parent_item['owner-avatar'];
+
+        $datarray['author-name'] = $person['name'];
+        $datarray['author-link'] = $person['url'];
+        $datarray['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']);
+        $datarray['body'] = $body;
+        $datarray["object"] = json_encode($xml);
+        $datarray["object-type"] = ACTIVITY_OBJ_COMMENT;
+
+        // We can't be certain what the original app is if the message is relayed.
+        if(($parent_item['origin']) && (! $parent_author_signature))
+                $datarray['app']  = 'Diaspora';
+
+        DiasporaFetchGuid($datarray);
+        $message_id = item_store($datarray);
+
+        $datarray['id'] = $message_id;
+
+        // If we are the origin of the parent we store the original signature and notify our followers
+        if($parent_item['origin']) {
+                $author_signature_base64 = base64_encode($author_signature);
+                $author_signature_base64 = diaspora_repair_signature($author_signature_base64, $diaspora_handle);
+
+                q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
+                        intval($message_id),
+                        dbesc($signed_data),
+                        dbesc($author_signature_base64),
+                        dbesc($diaspora_handle)
+                );
+
+                // notify others
+                proc_run('php','include/notifier.php','comment-import',$message_id);
+        }
+*/
+		return true;
+	}
+
+	private function import_conversation($importer, $data) {
+		return true;
+	}
+
+	private function import_like($importer, $sender, $data) {
+		return true;
+	}
+
+	private function import_message($importer, $data) {
+		return true;
+	}
+
+	private function import_participation($importer, $data) {
+		return true;
+	}
+
+	private function import_photo($importer, $data) {
+		return true;
+	}
+
+	private function import_poll_participation($importer, $data) {
+		return true;
+	}
+
+	private function import_profile($importer, $data) {
+		return true;
+	}
+
+	private function import_request($importer, $data) {
+		return true;
+	}
+
+	private function import_reshare($importer, $data) {
+		return true;
+	}
+
+	private function import_retraction($importer, $data) {
+		return true;
+	}
+
+	private function import_status_message($importer, $data) {
+		return true;
+	}
+}
+?>

From 08a780211211c79053a710866fa2057f648a6d51 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Sun, 28 Feb 2016 08:30:45 +0100
Subject: [PATCH 132/273] old location might vanish, vinzv moved the GS API
 docs over here

---
 doc/api.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/api.md b/doc/api.md
index c020f403ff..bf287585d3 100644
--- a/doc/api.md
+++ b/doc/api.md
@@ -1,6 +1,6 @@
 Friendica API
 ===
-The Friendica API aims to be compatible to the [GNU Social API](http://skilledtests.com/wiki/Twitter-compatible_API) and the [Twitter API](https://dev.twitter.com/rest/public).
+The Friendica API aims to be compatible to the [GNU Social API](http://wiki.gnusocial.de/gnusocial:api) and the [Twitter API](https://dev.twitter.com/rest/public).
 
 Please refer to the linked documentation for further information.
 

From c02b54997e84667f195ee3ddf0c809a863fab294 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 28 Feb 2016 19:05:23 +0100
Subject: [PATCH 133/273] Like and Comment could work (partially)

---
 include/diaspora2.php | 589 ++++++++++++++++++++++++++----------------
 1 file changed, 372 insertions(+), 217 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 690e54aa41..e6e2d74bf6 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -4,8 +4,9 @@
  * @brief The implementation of the diaspora protocol
  */
 
-require_once("include/diaspora.php");
+require_once("include/bb2diaspora.php");
 require_once("include/Scrape.php");
+require_once("include/Contact.php");
 
 function array_to_xml($array, &$xml) {
 
@@ -66,7 +67,7 @@ class diaspora {
 
 		// The sender is the handle of the contact that sent the message.
 		// This will often be different with relayed messages (for example "like" and "comment")
-		$sender = $msg->author;
+		$sender = $msg["author"];
 
 		if (!diaspora::valid_posting($msg, $fields)) {
 			logger("Invalid posting");
@@ -80,12 +81,14 @@ class diaspora {
 				return self::import_account_deletion($importer, $fields);
 
 			case "comment":
-				return self::import_comment($importer, $sender, $fields);
+				return true;
+			//	return self::import_comment($importer, $sender, $fields);
 
 			case "conversation":
 				return self::import_conversation($importer, $fields);
 
 			case "like":
+			//	return true;
 				return self::import_like($importer, $sender, $fields);
 
 			case "message":
@@ -136,7 +139,7 @@ class diaspora {
 	 */
 	private function valid_posting($msg, &$fields) {
 
-		$data = parse_xml_string($msg->message, false);
+		$data = parse_xml_string($msg["message"], false);
 
 		$first_child = $data->getName();
 
@@ -202,12 +205,13 @@ class diaspora {
 				}
 
 				$signed_data .= $data;
-				$fields->$fieldname = $data;
 			}
+			if (!in_array($fieldname, array("parent_author_signature", "target_author_signature")))
+				$fields->$fieldname = $data;
 		}
 
 		if (in_array($type, array("status_message", "reshare")))
-			if ($msg->author != $fields->author) {
+			if ($msg["author"] != $fields->author) {
 				logger("Message handle is not the same as envelope sender. Quitting this message.");
 				return false;
 			}
@@ -219,7 +223,7 @@ class diaspora {
 			return false;
 
 		if (isset($parent_author_signature)) {
-			$key = self::get_key($msg->author);
+			$key = self::get_key($msg["author"]);
 
 			if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256"))
 				return false;
@@ -349,104 +353,166 @@ class diaspora {
 		return false;
 	}
 
+	private function fetch_guid($item) {
+		preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi",
+			function ($match) use ($item){
+				return(self::fetch_guid_sub($match, $item));
+			},$item["body"]);
+	}
+
+	private function fetch_guid_sub($match, $item) {
+		$a = get_app();
+
+		if (!self::store_by_guid($match[1], $item["author-link"]))
+			self::store_by_guid($match[1], $item["owner-link"]);
+	}
+
+	private function store_by_guid($guid, $server, $uid = 0) {
+		$serverparts = parse_url($server);
+		$server = $serverparts["scheme"]."://".$serverparts["host"];
+
+		logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG);
+
+/// @todo		$item = self::fetch_message($guid, $server);
+
+		if (!$item)
+			return false;
+
+		logger("Successfully fetched item ".$guid." from ".$server, LOGGER_DEBUG);
+
+// @todo - neue Funktion import_status... nutzen
+print_r($item);
+die();
+		return self::import_status_message($importer, $data);
+
 /*
-function DiasporaFetchGuid($item) {
-        preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi",
-                function ($match) use ($item){
-                        return(DiasporaFetchGuidSub($match, $item));
-                },$item["body"]);
-}
+		$body = $item["body"];
+		$str_tags = $item["tag"];
+		$app = $item["app"];
+		$created = $item["created"];
+		$author = $item["author"];
+		$guid = $item["guid"];
+		$private = $item["private"];
+		$object = $item["object"];
+		$objecttype = $item["object-type"];
 
-function DiasporaFetchGuidSub($match, $item) {
-        $a = get_app();
+		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($uid),
+			dbesc($guid)
+		);
+		if(count($r))
+			return $r[0]["id"];
 
-        if (!diaspora_store_by_guid($match[1], $item["author-link"]))
-                diaspora_store_by_guid($match[1], $item["owner-link"]);
-}
+		$person = self::get_person_by_handle($author);
 
-function diaspora_store_by_guid($guid, $server, $uid = 0) {
-        require_once("include/Contact.php");
+		$contact_id = get_contact($person["url"], $uid);
 
-        $serverparts = parse_url($server);
-        $server = $serverparts["scheme"]."://".$serverparts["host"];
+		$contacts = q("SELECT * FROM `contact` WHERE `id` = %d", intval($contact_id));
+		$importers = q("SELECT * FROM `user` WHERE `uid` = %d", intval($uid));
 
-        logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG);
+		if ($contacts AND $importers)
+			if (!self::post_allow($importers[0],$contacts[0], false)) {
+				logger("Ignoring author ".$person["url"]." for uid ".$uid);
+				return false;
+			} else
+				logger("Author ".$person["url"]." is allowed for uid ".$uid);
 
-        $item = diaspora_fetch_message($guid, $server);
+		$datarray = array();
+		$datarray["uid"] = $uid;
+		$datarray["contact-id"] = $contact_id;
+		$datarray["wall"] = 0;
+		$datarray["network"] = NETWORK_DIASPORA;
+		$datarray["guid"] = $guid;
+		$datarray["uri"] = $datarray["parent-uri"] = $author.":".$guid;
+		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert('UTC','UTC',$created);
+		$datarray["private"] = $private;
+		$datarray["parent"] = 0;
+		$datarray["plink"] = self::plink($author, $guid);
+		$datarray["author-name"] = $person["name"];
+		$datarray["author-link"] = $person["url"];
+		$datarray["author-avatar"] = ((x($person,'thumb')) ? $person["thumb"] : $person["photo"]);
+		$datarray["owner-name"] = $datarray["author-name"];
+		$datarray["owner-link"] = $datarray["author-link"];
+		$datarray["owner-avatar"] = $datarray["author-avatar"];
+		$datarray["body"] = $body;
+		$datarray["tag"] = $str_tags;
+		$datarray["app"]  = $app;
+		$datarray["visible"] = ((strlen($body)) ? 1 : 0);
+		$datarray["object"] = $object;
+		$datarray["object-type"] = $objecttype;
 
-        if (!$item)
-                return false;
+		if ($datarray["contact-id"] == 0)
+			return false;
 
-        logger("Successfully fetched item ".$guid." from ".$server, LOGGER_DEBUG);
+		self::fetch_guid($datarray);
+		$message_id = item_store($datarray);
 
-        $body = $item["body"];
-        $str_tags = $item["tag"];
-        $app = $item["app"];
-        $created = $item["created"];
-        $author = $item["author"];
-        $guid = $item["guid"];
-        $private = $item["private"];
-        $object = $item["object"];
-        $objecttype = $item["object-type"];
+		/// @TODO
+		/// Looking if there is some subscribe mechanism in Diaspora to get all comments for this post
 
-        $message_id = $author.':'.$guid;
-        $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-                intval($uid),
-                dbesc($guid)
-        );
-        if(count($r))
-                return $r[0]["id"];
-
-        $person = find_diaspora_person_by_handle($author);
-
-        $contact_id = get_contact($person['url'], $uid);
-
-        $contacts = q("SELECT * FROM `contact` WHERE `id` = %d", intval($contact_id));
-        $importers = q("SELECT * FROM `user` WHERE `uid` = %d", intval($uid));
-
-        if ($contacts AND $importers)
-                if(!diaspora_post_allow($importers[0],$contacts[0], false)) {
-                        logger('Ignoring author '.$person['url'].' for uid '.$uid);
-                        return false;
-                } else
-                        logger('Author '.$person['url'].' is allowed for uid '.$uid);
-
-        $datarray = array();
-        $datarray['uid'] = $uid;
-        $datarray['contact-id'] = $contact_id;
-        $datarray['wall'] = 0;
-        $datarray['network'] = NETWORK_DIASPORA;
-        $datarray['guid'] = $guid;
-        $datarray['uri'] = $datarray['parent-uri'] = $message_id;
-        $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created);
-        $datarray['private'] = $private;
-        $datarray['parent'] = 0;
-        $datarray['plink'] = diaspora_plink($author, $guid);
-        $datarray['author-name'] = $person['name'];
-        $datarray['author-link'] = $person['url'];
-        $datarray['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']);
-        $datarray['owner-name'] = $datarray['author-name'];
-        $datarray['owner-link'] = $datarray['author-link'];
-        $datarray['owner-avatar'] = $datarray['author-avatar'];
-        $datarray['body'] = $body;
-        $datarray['tag'] = $str_tags;
-        $datarray['app']  = $app;
-        $datarray['visible'] = ((strlen($body)) ? 1 : 0);
-        $datarray['object'] = $object;
-        $datarray['object-type'] = $objecttype;
-
-        if ($datarray['contact-id'] == 0)
-                return false;
-
-        DiasporaFetchGuid($datarray);
-        $message_id = item_store($datarray);
-
-        /// @TODO
-        /// Looking if there is some subscribe mechanism in Diaspora to get all comments for this post
-
-        return $message_id;
-}
+		return $message_id;
 */
+	}
+
+	private function post_allow($importer, $contact, $is_comment = false) {
+
+		// perhaps we were already sharing with this person. Now they're sharing with us.
+		// That makes us friends.
+		// Normally this should have handled by getting a request - but this could get lost
+		if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
+			q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
+				intval(CONTACT_IS_FRIEND),
+				intval($contact["id"]),
+				intval($importer["uid"])
+			);
+			$contact["rel"] = CONTACT_IS_FRIEND;
+			logger("defining user ".$contact["nick"]." as friend");
+		}
+
+		if(($contact["blocked"]) || ($contact["readonly"]) || ($contact["archive"]))
+			return false;
+		if($contact["rel"] == CONTACT_IS_SHARING || $contact["rel"] == CONTACT_IS_FRIEND)
+			return true;
+		if($contact["rel"] == CONTACT_IS_FOLLOWER)
+			if(($importer["page-flags"] == PAGE_COMMUNITY) OR $is_comment)
+				return true;
+
+		// Messages for the global users are always accepted
+		if ($importer["uid"] == 0)
+			return true;
+
+		return false;
+	}
+
+	private function fetch_parent_item($uid, $guid, $author, $contact) {
+		$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `owner-name`, `owner-link`, `owner-avatar`, `origin`
+			FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($uid), dbesc($guid));
+
+		if(!count($r)) {
+			$result = self::store_by_guid($guid, $contact["url"], $uid);
+
+			if (!$result) {
+				$person = self::get_person_by_handle($author);
+				$result = self::store_by_guid($guid, $person["url"], $uid);
+			}
+
+			if ($result) {
+				logger("Fetched missing item ".$guid." - result: ".$result, LOGGER_DEBUG);
+
+				$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`,
+						`owner-name`, `owner-link`, `owner-avatar`, `origin`
+					FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+					intval($uid), dbesc($guid));
+			}
+		}
+
+		if (!count($r)) {
+			logger("parent item not found: parent: ".$guid." item: ".$guid);
+			return false;
+		} else
+			return $r[0];
+	}
 
 	private function import_account_deletion($importer, $data) {
 		return true;
@@ -463,132 +529,93 @@ function diaspora_store_by_guid($guid, $server, $uid = 0) {
 			logger("cannot find contact for sender: ".$sender);
 			return false;
 		}
+
+		if (!self::post_allow($importer,$contact, true)) {
+			logger("Ignoring the author ".$sender);
+			return false;
+		}
 /*
-        if(! diaspora_post_allow($importer,$contact, true)) {
-                logger('diaspora_comment: Ignoring this author.');
-                return 202;
-        }
-
-        $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-                intval($importer['uid']),
-                dbesc($guid)
-        );
-        if(count($r)) {
-                logger('diaspora_comment: our comment just got relayed back to us (or there was a guid collision) : ' . $guid);
-                return;
-        }
-
-        $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-                intval($importer['uid']),
-                dbesc($parent_guid)
-        );
-
-        if(!count($r)) {
-                $result = diaspora_store_by_guid($parent_guid, $contact['url'], $importer['uid']);
-
-                if (!$result) {
-                        $person = find_diaspora_person_by_handle($diaspora_handle);
-                        $result = diaspora_store_by_guid($parent_guid, $person['url'], $importer['uid']);
-                }
-
-                if ($result) {
-                        logger("Fetched missing item ".$parent_guid." - result: ".$result, LOGGER_DEBUG);
-
-                        $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-                                intval($importer['uid']),
-                                dbesc($parent_guid)
-                        );
-                }
-        }
-
-        if(! count($r)) {
-                logger('diaspora_comment: parent item not found: parent: ' . $parent_guid . ' item: ' . $guid);
-                return;
-        }
-        $parent_item = $r[0];
-
-        // Find the original comment author information.
-        // We need this to make sure we display the comment author
-        // information (name and avatar) correctly.
-        if(strcasecmp($diaspora_handle,$msg['author']) == 0)
-                $person = $contact;
-        else {
-                $person = find_diaspora_person_by_handle($diaspora_handle);
-
-                if(! is_array($person)) {
-                        logger('diaspora_comment: unable to find author details');
-                        return;
-                }
-        }
-
-        // Fetch the contact id - if we know this contact
-        $r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
-                dbesc(normalise_link($person['url'])), intval($importer['uid']));
-        if ($r) {
-                $cid = $r[0]['id'];
-                $network = $r[0]['network'];
-        } else {
-                $cid = $contact['id'];
-                $network = NETWORK_DIASPORA;
-        }
-
-        $body = diaspora2bb($text);
-        $message_id = $diaspora_handle . ':' . $guid;
-
-        $datarray = array();
-
-        $datarray['uid'] = $importer['uid'];
-        $datarray['contact-id'] = $cid;
-        $datarray['type'] = 'remote-comment';
-        $datarray['wall'] = $parent_item['wall'];
-        $datarray['network']  = $network;
-        $datarray['verb'] = ACTIVITY_POST;
-        $datarray['gravity'] = GRAVITY_COMMENT;
-        $datarray['guid'] = $guid;
-        $datarray['uri'] = $message_id;
-        $datarray['parent-uri'] = $parent_item['uri'];
-
-        // No timestamps for comments? OK, we'll the use current time.
-        $datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert();
-        $datarray['private'] = $parent_item['private'];
-
-        $datarray['owner-name'] = $parent_item['owner-name'];
-        $datarray['owner-link'] = $parent_item['owner-link'];
-        $datarray['owner-avatar'] = $parent_item['owner-avatar'];
-
-        $datarray['author-name'] = $person['name'];
-        $datarray['author-link'] = $person['url'];
-        $datarray['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']);
-        $datarray['body'] = $body;
-        $datarray["object"] = json_encode($xml);
-        $datarray["object-type"] = ACTIVITY_OBJ_COMMENT;
-
-        // We can't be certain what the original app is if the message is relayed.
-        if(($parent_item['origin']) && (! $parent_author_signature))
-                $datarray['app']  = 'Diaspora';
-
-        DiasporaFetchGuid($datarray);
-        $message_id = item_store($datarray);
-
-        $datarray['id'] = $message_id;
-
-        // If we are the origin of the parent we store the original signature and notify our followers
-        if($parent_item['origin']) {
-                $author_signature_base64 = base64_encode($author_signature);
-                $author_signature_base64 = diaspora_repair_signature($author_signature_base64, $diaspora_handle);
-
-                q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
-                        intval($message_id),
-                        dbesc($signed_data),
-                        dbesc($author_signature_base64),
-                        dbesc($diaspora_handle)
-                );
-
-                // notify others
-                proc_run('php','include/notifier.php','comment-import',$message_id);
-        }
+		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($importer["uid"]),
+			dbesc($guid)
+		);
+		if(count($r)) {
+			logger("The comment already exists: ".$guid);
+			return;
+		}
 */
-		return true;
+		$parent_item = self::fetch_parent_item($importer["uid"], $parent_guid, $author, $contact);
+		if (!$parent_item)
+			return false;
+
+		$person = self::get_person_by_handle($author);
+		if (!is_array($person)) {
+			logger("unable to find author details");
+			return false;
+		}
+
+		// Fetch the contact id - if we know this contact
+		$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc(normalise_link($person["url"])), intval($importer["uid"]));
+		if ($r) {
+			$cid = $r[0]["id"];
+			$network = $r[0]["network"];
+		} else {
+			$cid = $contact["id"];
+			$network = NETWORK_DIASPORA;
+		}
+
+		$body = diaspora2bb($text);
+
+		$datarray = array();
+
+		$datarray["uid"] = $importer["uid"];
+		$datarray["contact-id"] = $cid;
+		$datarray["type"] = 'remote-comment';
+		$datarray["wall"] = $parent_item["wall"];
+		$datarray["network"]  = $network;
+		$datarray["verb"] = ACTIVITY_POST;
+		$datarray["gravity"] = GRAVITY_COMMENT;
+		$datarray["guid"] = $guid;
+		$datarray["uri"] = $author.":".$guid;
+		$datarray["parent-uri"] = $parent_item["uri"];
+
+		// The old Diaspora protocol doesn't have a timestamp for comments
+		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert();
+		$datarray["private"] = $parent_item["private"];
+
+		$datarray["owner-name"] = $contact["name"];
+		$datarray["owner-link"] = $contact["url"];
+		$datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
+
+		$datarray["author-name"] = $person["name"];
+		$datarray["author-link"] = $person["url"];
+		$datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]);
+		$datarray["body"] = $body;
+		$datarray["object"] = json_encode($data);
+		$datarray["object-type"] = ACTIVITY_OBJ_COMMENT;
+
+		self::fetch_guid($datarray);
+
+//		$message_id = item_store($datarray);
+print_r($datarray);
+		$datarray["id"] = $message_id;
+
+		// 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.
+			q("INSERT INTO `sign` (`iid`,`signed_text`) VALUES (%d,'%s')",
+				intval($message_id),
+				dbesc(json_encode($data))
+			);
+
+			// notify others
+			proc_run("php", "include/notifier.php", "comment-import", $message_id);
+		}
+
+		return $message_id;
 	}
 
 	private function import_conversation($importer, $data) {
@@ -596,6 +623,134 @@ function diaspora_store_by_guid($guid, $server, $uid = 0) {
 	}
 
 	private function import_like($importer, $sender, $data) {
+		$positive = notags(unxmlify($data->positive));
+		$guid = notags(unxmlify($data->guid));
+		$parent_type = notags(unxmlify($data->parent_type));
+		$parent_guid = notags(unxmlify($data->parent_guid));
+		$author = notags(unxmlify($data->author));
+
+		// likes on comments aren't supported by Diaspora - only on posts
+		if ($parent_type !== "Post")
+			return false;
+
+		// "positive" = "false" doesn't seem to be supported by Diaspora
+		if ($positive === "false") {
+			logger("Received a like with positive set to 'false' - this shouldn't exist at all");
+			return false;
+		}
+
+		$contact = self::get_contact_by_handle($importer["uid"], $sender);
+		if (!$contact) {
+			logger("cannot find contact for sender: ".$sender);
+			return false;
+		}
+
+		if (!self::post_allow($importer,$contact, true)) {
+			logger("Ignoring the author ".$sender);
+			return false;
+		}
+/*
+		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($importer["uid"]),
+			dbesc($guid)
+		);
+		if(count($r)) {
+			logger("The like already exists: ".$guid);
+			return false;
+		}
+*/
+		$parent_item = self::fetch_parent_item($importer["uid"], $parent_guid, $author, $contact);
+		if (!$parent_item)
+			return false;
+
+		$person = self::get_person_by_handle($author);
+		if (!is_array($person)) {
+			logger("unable to find author details");
+			return false;
+		}
+
+		// Fetch the contact id - if we know this contact
+		$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc(normalise_link($person["url"])), intval($importer["uid"]));
+		if ($r) {
+			$cid = $r[0]["id"];
+			$network = $r[0]["network"];
+		} else {
+			$cid = $contact["id"];
+			$network = NETWORK_DIASPORA;
+		}
+
+// ------------------------------------------------
+		$objtype = ACTIVITY_OBJ_NOTE;
+		$link = xmlify('<link rel="alternate" type="text/html" href="'.App::get_baseurl()."/display/".$importer["nickname"]."/".$parent_item["id"].'" />'."\n") ;
+		$parent_body = $parent_item["body"];
+
+		$obj = <<< EOT
+
+		<object>
+			<type>$objtype</type>
+			<local>1</local>
+			<id>{$parent_item["uri"]}</id>
+			<link>$link</link>
+			<title></title>
+			<content>$parent_body</content>
+		</object>
+EOT;
+		$bodyverb = t('%1$s likes %2$s\'s %3$s');
+
+		$ulink = "[url=".$contact["url"]."]".$contact["name"]."[/url]";
+		$alink = "[url=".$parent_item["author-link"]."]".$parent_item["author-name"]."[/url]";
+		$plink = "[url=".App::get_baseurl()."/display/".urlencode($guid)."]".t("status")."[/url]";
+		$body = sprintf($bodyverb, $ulink, $alink, $plink);
+// ------------------------------------------------
+
+		$datarray = array();
+
+		$datarray["uri"] = $author.":".$guid;
+		$datarray["uid"] = $importer["uid"];
+		$datarray["guid"] = $guid;
+		$datarray["network"]  = $network;
+		$datarray["contact-id"] = $cid;
+		$datarray["type"] = "activity";
+		$datarray["wall"] = $parent_item["wall"];
+		$datarray["gravity"] = GRAVITY_LIKE;
+		$datarray["parent"] = $parent_item["id"];
+		$datarray["parent-uri"] = $parent_item["uri"];
+
+		$datarray["owner-name"] = $contact["name"];
+		$datarray["owner-link"] = $contact["url"];
+		$datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
+
+		$datarray["author-name"] = $person["name"];
+		$datarray["author-link"] = $person["url"];
+		$datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]);
+
+		$datarray["body"] = $body;
+		$datarray["private"] = $parent_item["private"];
+		$datarray["verb"] = ACTIVITY_LIKE;
+		$datarray["object-type"] = $objtype;
+		$datarray["object"] = $obj;
+		$datarray["visible"] = 1;
+		$datarray["unseen"] = 1;
+		$datarray["last-child"] = 0;
+
+print_r($datarray);
+//		$message_id = item_store($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.
+			q("INSERT INTO `sign` (`iid`,`signed_text`) VALUES (%d,'%s')",
+				intval($message_id),
+				dbesc(json_encode($data))
+			);
+
+			// notify others
+			proc_run("php", "include/notifier.php", "comment-import", $message_id);
+		}
+
 		return true;
 	}
 

From 6d3581dac8dc5a27a18a39709fa3ae38c080c490 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 29 Feb 2016 08:02:50 +0100
Subject: [PATCH 134/273] "profile". "like" and "comment" could work, status
 messages only partly.

---
 include/diaspora.php  |    4 +-
 include/diaspora2.php | 1055 +++++++++++++++++++++++++++++++++--------
 2 files changed, 856 insertions(+), 203 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 9dbbeabbcf..4ec7489ca4 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -116,8 +116,8 @@ function diaspora_dispatch($importer,$msg,$attempt=1) {
 		$ret = diaspora_retraction($importer,$xmlbase->retraction,$msg);
 	}
 	elseif($xmlbase->signed_retraction) {
-		$tempfile = tempnam(get_temppath(), "diaspora-signed_retraction");
-		file_put_contents($tempfile, json_encode($data));
+		//$tempfile = tempnam(get_temppath(), "diaspora-signed_retraction");
+		//file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_signed_retraction($importer,$xmlbase->signed_retraction,$msg);
 	}
 	elseif($xmlbase->relayable_retraction) {
diff --git a/include/diaspora2.php b/include/diaspora2.php
index e6e2d74bf6..578a496c0a 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -7,30 +7,43 @@
 require_once("include/bb2diaspora.php");
 require_once("include/Scrape.php");
 require_once("include/Contact.php");
+require_once("include/Photo.php");
+require_once("include/socgraph.php");
 
-function array_to_xml($array, &$xml) {
+class xml {
+	function from_array($array, &$xml) {
+
+		if (!is_object($xml)) {
+			foreach($array as $key => $value) {
+				$root = new SimpleXMLElement('<'.$key.'/>');
+				array_to_xml($value, $root);
+
+				$dom = dom_import_simplexml($root)->ownerDocument;
+				$dom->formatOutput = true;
+				return $dom->saveXML();
+			}
+		}
 
-	if (!is_object($xml)) {
 		foreach($array as $key => $value) {
-			$root = new SimpleXMLElement('<'.$key.'/>');
-			array_to_xml($value, $root);
-
-			$dom = dom_import_simplexml($root)->ownerDocument;
-			$dom->formatOutput = true;
-			return $dom->saveXML();
+			if (!is_array($value) AND !is_numeric($key))
+				$xml->addChild($key, $value);
+			elseif (is_array($value))
+				array_to_xml($value, $xml->addChild($key));
 		}
 	}
 
-	foreach($array as $key => $value) {
-		if (!is_array($value) AND !is_numeric($key))
-			$xml->addChild($key, $value);
-		elseif (is_array($value))
-			array_to_xml($value, $xml->addChild($key));
+	function copy(&$source, &$target, $elementname) {
+		if (count($source->children()) == 0)
+			$target->addChild($elementname, $source);
+		else {
+			$child = $target->addChild($elementname);
+			foreach ($source->children() AS $childfield => $childentry)
+				self::copy($childentry, $child, $childfield);
+		}
 	}
 }
-
 /**
- * @brief This class contain functions to create and send DFRN XML files
+ * @brief This class contain functions to create and send Diaspora XML files
  *
  */
 class diaspora {
@@ -39,7 +52,7 @@ class diaspora {
 
 		$enabled = intval(get_config("system", "diaspora_enabled"));
 		if (!$enabled) {
-			logger('diaspora is disabled');
+			logger("diaspora is disabled");
 			return false;
 		}
 
@@ -69,7 +82,7 @@ class diaspora {
 		// This will often be different with relayed messages (for example "like" and "comment")
 		$sender = $msg["author"];
 
-		if (!diaspora::valid_posting($msg, $fields)) {
+		if (!diaspora::valid_posting($msg, $fields, $data2)) {
 			logger("Invalid posting");
 			return false;
 		}
@@ -77,34 +90,36 @@ class diaspora {
 		$type = $fields->getName();
 
 		switch ($type) {
-			case "account_deletion":
+			case "account_deletion": // Not implemented
 				return self::import_account_deletion($importer, $fields);
 
 			case "comment":
 				return true;
-			//	return self::import_comment($importer, $sender, $fields);
+				//return self::import_comment($importer, $sender, $fields);
 
 			case "conversation":
 				return self::import_conversation($importer, $fields);
 
 			case "like":
-			//	return true;
-				return self::import_like($importer, $sender, $fields);
+				return true;
+				//return self::import_like($importer, $sender, $fields);
 
 			case "message":
-				return self::import_message($importer, $fields);
+				return true;
+				//return self::import_message($importer, $fields);
 
-			case "participation":
+			case "participation": // Not implemented
 				return self::import_participation($importer, $fields);
 
 			case "photo":
 				return self::import_photo($importer, $fields);
 
-			case "poll_participation":
+			case "poll_participation": // Not implemented
 				return self::import_poll_participation($importer, $fields);
 
 			case "profile":
-				return self::import_profile($importer, $fields);
+				return true;
+				//return self::import_profile($importer, $fields);
 
 			case "request":
 				return self::import_request($importer, $fields);
@@ -116,7 +131,7 @@ class diaspora {
 				return self::import_retraction($importer, $fields);
 
 			case "status_message":
-				return self::import_status_message($importer, $fields);
+				return self::import_status_message($importer, $fields, $msg, $data2);
 
 			default:
 				logger("Unknown message type ".$type);
@@ -133,16 +148,20 @@ class diaspora {
 	 * It also does the conversion between the old and the new diaspora format.
 	 *
 	 * @param array $msg Array with the XML, the sender handle and the sender signature
-	 * @param object $fields SimpleXML object that contains the posting
+	 * @param object $fields SimpleXML object that contains the posting when it is valid
 	 *
 	 * @return bool Is the posting valid?
 	 */
-	private function valid_posting($msg, &$fields) {
+	private function valid_posting($msg, &$fields, &$element) {
 
 		$data = parse_xml_string($msg["message"], false);
 
+		if (!is_object($data))
+			return false;
+
 		$first_child = $data->getName();
 
+		// Is this the new or the old version?
 		if ($data->getName() == "XML") {
 			$oldXML = true;
 			foreach ($data->post->children() as $child)
@@ -154,6 +173,8 @@ class diaspora {
 
 		$type = $element->getName();
 
+		// All retractions are handled identically from now on.
+		// In the new version there will only be "retraction".
 		if (in_array($type, array("signed_retraction", "relayable_retraction")))
 			$type = "retraction";
 
@@ -161,8 +182,7 @@ class diaspora {
 
 		$signed_data = "";
 
-		foreach ($element->children() AS $fieldname => $data) {
-
+		foreach ($element->children() AS $fieldname => $entry) {
 			if ($oldXML) {
 				// Translation for the old XML structure
 				if ($fieldname == "diaspora_handle")
@@ -195,30 +215,33 @@ class diaspora {
 			}
 
 			if ($fieldname == "author_signature")
-				$author_signature = base64_decode($data);
+				$author_signature = base64_decode($entry);
 			elseif ($fieldname == "parent_author_signature")
-				$parent_author_signature = base64_decode($data);
+				$parent_author_signature = base64_decode($entry);
 			elseif ($fieldname != "target_author_signature") {
 				if ($signed_data != "") {
 					$signed_data .= ";";
 					$signed_data_parent .= ";";
 				}
 
-				$signed_data .= $data;
+				$signed_data .= $entry;
 			}
 			if (!in_array($fieldname, array("parent_author_signature", "target_author_signature")))
-				$fields->$fieldname = $data;
+				xml::copy($entry, $fields, $fieldname);
 		}
 
-		if (in_array($type, array("status_message", "reshare")))
+		// This is something that shouldn't happen at all.
+		if (in_array($type, array("status_message", "reshare", "profile")))
 			if ($msg["author"] != $fields->author) {
 				logger("Message handle is not the same as envelope sender. Quitting this message.");
 				return false;
 			}
 
+		// Only some message types have signatures. So we quit here for the other types.
 		if (!in_array($type, array("comment", "conversation", "message", "like")))
 			return true;
 
+		// No author_signature? This is a must, so we quit.
 		if (!isset($author_signature))
 			return false;
 
@@ -373,85 +396,57 @@ class diaspora {
 
 		logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG);
 
-/// @todo		$item = self::fetch_message($guid, $server);
+		$msg = self::fetch_message($guid, $server);
 
-		if (!$item)
+		if (!$msg)
 			return false;
 
 		logger("Successfully fetched item ".$guid." from ".$server, LOGGER_DEBUG);
 
-// @todo - neue Funktion import_status... nutzen
-print_r($item);
-die();
-		return self::import_status_message($importer, $data);
+		// Now call the dispatcher
+		return self::dispatch_public($msg);
+	}
 
-/*
-		$body = $item["body"];
-		$str_tags = $item["tag"];
-		$app = $item["app"];
-		$created = $item["created"];
-		$author = $item["author"];
-		$guid = $item["guid"];
-		$private = $item["private"];
-		$object = $item["object"];
-		$objecttype = $item["object-type"];
+	private function fetch_message($guid, $server, $level = 0) {
 
-		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-			intval($uid),
-			dbesc($guid)
-		);
-		if(count($r))
-			return $r[0]["id"];
-
-		$person = self::get_person_by_handle($author);
-
-		$contact_id = get_contact($person["url"], $uid);
-
-		$contacts = q("SELECT * FROM `contact` WHERE `id` = %d", intval($contact_id));
-		$importers = q("SELECT * FROM `user` WHERE `uid` = %d", intval($uid));
-
-		if ($contacts AND $importers)
-			if (!self::post_allow($importers[0],$contacts[0], false)) {
-				logger("Ignoring author ".$person["url"]." for uid ".$uid);
-				return false;
-			} else
-				logger("Author ".$person["url"]." is allowed for uid ".$uid);
-
-		$datarray = array();
-		$datarray["uid"] = $uid;
-		$datarray["contact-id"] = $contact_id;
-		$datarray["wall"] = 0;
-		$datarray["network"] = NETWORK_DIASPORA;
-		$datarray["guid"] = $guid;
-		$datarray["uri"] = $datarray["parent-uri"] = $author.":".$guid;
-		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert('UTC','UTC',$created);
-		$datarray["private"] = $private;
-		$datarray["parent"] = 0;
-		$datarray["plink"] = self::plink($author, $guid);
-		$datarray["author-name"] = $person["name"];
-		$datarray["author-link"] = $person["url"];
-		$datarray["author-avatar"] = ((x($person,'thumb')) ? $person["thumb"] : $person["photo"]);
-		$datarray["owner-name"] = $datarray["author-name"];
-		$datarray["owner-link"] = $datarray["author-link"];
-		$datarray["owner-avatar"] = $datarray["author-avatar"];
-		$datarray["body"] = $body;
-		$datarray["tag"] = $str_tags;
-		$datarray["app"]  = $app;
-		$datarray["visible"] = ((strlen($body)) ? 1 : 0);
-		$datarray["object"] = $object;
-		$datarray["object-type"] = $objecttype;
-
-		if ($datarray["contact-id"] == 0)
+		if ($level > 5)
 			return false;
 
-		self::fetch_guid($datarray);
-		$message_id = item_store($datarray);
+		// This will not work if the server is not a Diaspora server
+		$source_url = $server."/p/".$guid.".xml";
+		$x = fetch_url($source_url);
+		if(!$x)
+			return false;
 
-		/// @TODO
-		/// Looking if there is some subscribe mechanism in Diaspora to get all comments for this post
+		/// @todo - should maybe solved by the dispatcher
+		$source_xml = parse_xml_string($x, false);
 
-		return $message_id;
-*/
+		if (!is_object($source_xml))
+			return false;
+
+		if ($source_xml->post->reshare) {
+			// Reshare of a reshare - old Diaspora version
+			return self::fetch_message($source_xml->post->reshare->root_guid, $server, ++$level);
+		} elseif ($source_xml->getName() == "reshare") {
+			// Reshare of a reshare - new Diaspora version
+			return self::fetch_message($source_xml->root_guid, $server, ++$level);
+		}
+
+		// Fetch the author - for the old and the new Diaspora version
+		if ($source_xml->post->status_message->diaspora_handle)
+			$author = (string)$source_xml->post->status_message->diaspora_handle;
+		elseif ($source_xml->author)
+			$author = (string)$source_xml->author;
+
+		if (!$author)
+			return false;
+
+		$msg = array("message" => $x, "author" => $author);
+
+		// We don't really need this, but until the work is unfinished we better will keep this
+		$msg["key"] = self::get_key($msg["author"]);
+
+		return $msg;
 	}
 
 	private function post_allow($importer, $contact, $is_comment = false) {
@@ -485,7 +480,9 @@ die();
 	}
 
 	private function fetch_parent_item($uid, $guid, $author, $contact) {
-		$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `owner-name`, `owner-link`, `owner-avatar`, `origin`
+		$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
+				`author-name`, `author-link`, `author-avatar`,
+				`owner-name`, `owner-link`, `owner-avatar`
 			FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
 			intval($uid), dbesc($guid));
 
@@ -500,8 +497,9 @@ die();
 			if ($result) {
 				logger("Fetched missing item ".$guid." - result: ".$result, LOGGER_DEBUG);
 
-				$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`,
-						`owner-name`, `owner-link`, `owner-avatar`, `origin`
+				$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
+						`author-name`, `author-link`, `author-avatar`,
+						`owner-name`, `owner-link`, `owner-avatar`
 					FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
 					intval($uid), dbesc($guid));
 			}
@@ -514,7 +512,49 @@ die();
 			return $r[0];
 	}
 
+	private function get_author_contact_by_url($contact, $person, $uid) {
+
+		$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc(normalise_link($person["url"])), intval($uid));
+		if ($r) {
+			$cid = $r[0]["id"];
+			$network = $r[0]["network"];
+		} else {
+			$cid = $contact["id"];
+			$network = NETWORK_DIASPORA;
+		}
+
+		return (array("cid" => $cid, "network" => $network));
+	}
+
+	public static function is_redmatrix($url) {
+		return(strstr($url, "/channel/"));
+	}
+
+	private function plink($addr, $guid) {
+	        $r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr));
+
+	        // Fallback
+	        if (!$r)
+	                return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
+
+	        // Friendica contacts are often detected as Diaspora contacts in the "fcontact" table
+	        // So we try another way as well.
+	        $s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"])));
+	        if ($s)
+	                $r[0]["network"] = $s[0]["network"];
+
+	        if ($r[0]["network"] == NETWORK_DFRN)
+	                return(str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/"));
+
+	        if (self::is_redmatrix($r[0]["url"]))
+	                return $r[0]["url"]."/?f=&mid=".$guid;
+
+	        return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
+	}
+
 	private function import_account_deletion($importer, $data) {
+		// Not supported by now. We are waiting for sample data
 		return true;
 	}
 
@@ -534,16 +574,16 @@ die();
 			logger("Ignoring the author ".$sender);
 			return false;
 		}
-/*
+
 		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
 			intval($importer["uid"]),
 			dbesc($guid)
 		);
 		if(count($r)) {
 			logger("The comment already exists: ".$guid);
-			return;
+			return false;
 		}
-*/
+
 		$parent_item = self::fetch_parent_item($importer["uid"], $parent_guid, $author, $contact);
 		if (!$parent_item)
 			return false;
@@ -555,51 +595,39 @@ die();
 		}
 
 		// Fetch the contact id - if we know this contact
-		$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
-			dbesc(normalise_link($person["url"])), intval($importer["uid"]));
-		if ($r) {
-			$cid = $r[0]["id"];
-			$network = $r[0]["network"];
-		} else {
-			$cid = $contact["id"];
-			$network = NETWORK_DIASPORA;
-		}
-
-		$body = diaspora2bb($text);
+		$author_contact = self::get_author_contact_by_url($contact, $person, $importer["uid"]);
 
 		$datarray = array();
 
 		$datarray["uid"] = $importer["uid"];
-		$datarray["contact-id"] = $cid;
-		$datarray["type"] = 'remote-comment';
-		$datarray["wall"] = $parent_item["wall"];
-		$datarray["network"]  = $network;
-		$datarray["verb"] = ACTIVITY_POST;
-		$datarray["gravity"] = GRAVITY_COMMENT;
-		$datarray["guid"] = $guid;
-		$datarray["uri"] = $author.":".$guid;
-		$datarray["parent-uri"] = $parent_item["uri"];
+		$datarray["contact-id"] = $author_contact["cid"];
+		$datarray["network"]  = $author_contact["network"];
 
-		// The old Diaspora protocol doesn't have a timestamp for comments
-		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert();
-		$datarray["private"] = $parent_item["private"];
+		$datarray["author-name"] = $person["name"];
+		$datarray["author-link"] = $person["url"];
+		$datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]);
 
 		$datarray["owner-name"] = $contact["name"];
 		$datarray["owner-link"] = $contact["url"];
 		$datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
 
-		$datarray["author-name"] = $person["name"];
-		$datarray["author-link"] = $person["url"];
-		$datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]);
-		$datarray["body"] = $body;
-		$datarray["object"] = json_encode($data);
+		$datarray["guid"] = $guid;
+		$datarray["uri"] = $author.":".$guid;
+
+		$datarray["type"] = "remote-comment";
+		$datarray["verb"] = ACTIVITY_POST;
+		$datarray["gravity"] = GRAVITY_COMMENT;
+		$datarray["parent-uri"] = $parent_item["uri"];
+
 		$datarray["object-type"] = ACTIVITY_OBJ_COMMENT;
+		$datarray["object"] = json_encode($data);
+
+		$datarray["body"] = diaspora2bb($text);
 
 		self::fetch_guid($datarray);
 
-//		$message_id = item_store($datarray);
-print_r($datarray);
-		$datarray["id"] = $message_id;
+		$message_id = item_store($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"]) {
@@ -622,6 +650,36 @@ print_r($datarray);
 		return true;
 	}
 
+	private function construct_like_body($contact, $parent_item, $guid) {
+		$bodyverb = t('%1$s likes %2$s\'s %3$s');
+
+		$ulink = "[url=".$contact["url"]."]".$contact["name"]."[/url]";
+		$alink = "[url=".$parent_item["author-link"]."]".$parent_item["author-name"]."[/url]";
+		$plink = "[url=".App::get_baseurl()."/display/".urlencode($guid)."]".t("status")."[/url]";
+
+		return sprintf($bodyverb, $ulink, $alink, $plink);
+	}
+
+	private function construct_like_object($importer, $parent_item) {
+		$objtype = ACTIVITY_OBJ_NOTE;
+		$link = xmlify('<link rel="alternate" type="text/html" href="'.App::get_baseurl()."/display/".$importer["nickname"]."/".$parent_item["id"].'" />'."\n") ;
+		$parent_body = $parent_item["body"];
+
+		$obj = <<< EOT
+
+		<object>
+			<type>$objtype</type>
+			<local>1</local>
+			<id>{$parent_item["uri"]}</id>
+			<link>$link</link>
+			<title></title>
+			<content>$parent_body</content>
+		</object>
+EOT;
+
+		return $obj;
+	}
+
 	private function import_like($importer, $sender, $data) {
 		$positive = notags(unxmlify($data->positive));
 		$guid = notags(unxmlify($data->guid));
@@ -649,7 +707,7 @@ print_r($datarray);
 			logger("Ignoring the author ".$sender);
 			return false;
 		}
-/*
+
 		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
 			intval($importer["uid"]),
 			dbesc($guid)
@@ -658,7 +716,7 @@ print_r($datarray);
 			logger("The like already exists: ".$guid);
 			return false;
 		}
-*/
+
 		$parent_item = self::fetch_parent_item($importer["uid"], $parent_guid, $author, $contact);
 		if (!$parent_item)
 			return false;
@@ -670,72 +728,37 @@ print_r($datarray);
 		}
 
 		// Fetch the contact id - if we know this contact
-		$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
-			dbesc(normalise_link($person["url"])), intval($importer["uid"]));
-		if ($r) {
-			$cid = $r[0]["id"];
-			$network = $r[0]["network"];
-		} else {
-			$cid = $contact["id"];
-			$network = NETWORK_DIASPORA;
-		}
-
-// ------------------------------------------------
-		$objtype = ACTIVITY_OBJ_NOTE;
-		$link = xmlify('<link rel="alternate" type="text/html" href="'.App::get_baseurl()."/display/".$importer["nickname"]."/".$parent_item["id"].'" />'."\n") ;
-		$parent_body = $parent_item["body"];
-
-		$obj = <<< EOT
-
-		<object>
-			<type>$objtype</type>
-			<local>1</local>
-			<id>{$parent_item["uri"]}</id>
-			<link>$link</link>
-			<title></title>
-			<content>$parent_body</content>
-		</object>
-EOT;
-		$bodyverb = t('%1$s likes %2$s\'s %3$s');
-
-		$ulink = "[url=".$contact["url"]."]".$contact["name"]."[/url]";
-		$alink = "[url=".$parent_item["author-link"]."]".$parent_item["author-name"]."[/url]";
-		$plink = "[url=".App::get_baseurl()."/display/".urlencode($guid)."]".t("status")."[/url]";
-		$body = sprintf($bodyverb, $ulink, $alink, $plink);
-// ------------------------------------------------
+		$author_contact = self::get_author_contact_by_url($contact, $person, $importer["uid"]);
 
 		$datarray = array();
 
-		$datarray["uri"] = $author.":".$guid;
 		$datarray["uid"] = $importer["uid"];
-		$datarray["guid"] = $guid;
-		$datarray["network"]  = $network;
-		$datarray["contact-id"] = $cid;
-		$datarray["type"] = "activity";
-		$datarray["wall"] = $parent_item["wall"];
-		$datarray["gravity"] = GRAVITY_LIKE;
-		$datarray["parent"] = $parent_item["id"];
-		$datarray["parent-uri"] = $parent_item["uri"];
-
-		$datarray["owner-name"] = $contact["name"];
-		$datarray["owner-link"] = $contact["url"];
-		$datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
+		$datarray["contact-id"] = $author_contact["cid"];
+		$datarray["network"]  = $author_contact["network"];
 
 		$datarray["author-name"] = $person["name"];
 		$datarray["author-link"] = $person["url"];
 		$datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]);
 
-		$datarray["body"] = $body;
-		$datarray["private"] = $parent_item["private"];
-		$datarray["verb"] = ACTIVITY_LIKE;
-		$datarray["object-type"] = $objtype;
-		$datarray["object"] = $obj;
-		$datarray["visible"] = 1;
-		$datarray["unseen"] = 1;
-		$datarray["last-child"] = 0;
+		$datarray["owner-name"] = $contact["name"];
+		$datarray["owner-link"] = $contact["url"];
+		$datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
 
-print_r($datarray);
-//		$message_id = item_store($datarray);
+		$datarray["guid"] = $guid;
+		$datarray["uri"] = $author.":".$guid;
+
+		$datarray["type"] = "activity";
+		$datarray["verb"] = ACTIVITY_LIKE;
+		$datarray["gravity"] = GRAVITY_LIKE;
+		$datarray["parent-uri"] = $parent_item["uri"];
+
+		$datarray["object-type"] = ACTIVITY_OBJ_NOTE;
+		$datarray["object"] = self::construct_like_object($importer, $parent_item);
+
+		$datarray["body"] = self::construct_like_body($contact, $parent_item, $guid);
+
+		$message_id = item_store($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"]) {
@@ -751,10 +774,86 @@ print_r($datarray);
 			proc_run("php", "include/notifier.php", "comment-import", $message_id);
 		}
 
-		return true;
+		return $message_id;
 	}
 
 	private function import_message($importer, $data) {
+		$guid = notags(unxmlify($data->guid));
+		$parent_guid = notags(unxmlify($data->parent_guid));
+		$text = unxmlify($data->text);
+		$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
+		$author = notags(unxmlify($data->author));
+		$conversation_guid = notags(unxmlify($data->conversation_guid));
+
+		$parent_uri = $author.":".$parent_guid;
+
+		$contact = self::get_contact_by_handle($importer["uid"], $author);
+		if (!$contact) {
+			logger("cannot find contact: ".$author);
+			return false;
+		}
+
+		if(($contact["rel"] == CONTACT_IS_FOLLOWER) || ($contact["blocked"]) || ($contact["readonly"])) {
+			logger("Ignoring this author.");
+			return false;
+		}
+
+		$conversation = null;
+
+		$c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($importer["uid"]),
+			dbesc($conversation_guid)
+		);
+		if(count($c))
+			$conversation = $c[0];
+		else {
+			logger("conversation not available.");
+			return false;
+		}
+
+		$reply = 0;
+
+		$body = diaspora2bb($text);
+		$message_id = $author.":".$guid;
+
+		$person = self::get_person_by_handle($author);
+		if (!$person) {
+			logger("unable to find author details");
+			return false;
+		}
+
+		$r = q("SELECT `id` FROM `mail` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc($message_id),
+			intval($importer["uid"])
+		);
+		if(count($r)) {
+			logger("duplicate message already delivered.", LOGGER_DEBUG);
+			return false;
+		}
+
+		q("INSERT INTO `mail` (`uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`)
+				VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
+			intval($importer["uid"]),
+			dbesc($guid),
+			intval($conversation["id"]),
+			dbesc($person["name"]),
+			dbesc($person["photo"]),
+			dbesc($person["url"]),
+			intval($contact["id"]),
+			dbesc($conversation["subject"]),
+			dbesc($body),
+			0,
+			1,
+			dbesc($message_id),
+			dbesc($parent_uri),
+			dbesc($created_at)
+		);
+
+		q("UPDATE `conv` SET `updated` = '%s' WHERE `id` = %d",
+			dbesc(datetime_convert()),
+			intval($conversation["id"])
+		);
+
 		return true;
 	}
 
@@ -771,14 +870,445 @@ print_r($datarray);
 	}
 
 	private function import_profile($importer, $data) {
+		$author = notags(unxmlify($data->author));
+
+		$contact = self::get_contact_by_handle($importer["uid"], $author);
+		if (!$contact)
+			return;
+
+		$name = unxmlify($data->first_name).((strlen($data->last_name)) ? " ".unxmlify($data->last_name) : "");
+		$image_url = unxmlify($data->image_url);
+		$birthday = unxmlify($data->birthday);
+		$location = diaspora2bb(unxmlify($data->location));
+		$about = diaspora2bb(unxmlify($data->bio));
+		$gender = unxmlify($data->gender);
+		$searchable = (unxmlify($data->searchable) == "true");
+		$nsfw = (unxmlify($data->nsfw) == "true");
+		$tags = unxmlify($data->tag_string);
+
+		$tags = explode("#", $tags);
+
+		$keywords = array();
+		foreach ($tags as $tag) {
+			$tag = trim(strtolower($tag));
+			if ($tag != "")
+				$keywords[] = $tag;
+		}
+
+		$keywords = implode(", ", $keywords);
+
+		$handle_parts = explode("@", $author);
+		$nick = $handle_parts[0];
+
+		if($name === "")
+			$name = $handle_parts[0];
+
+		if( preg_match("|^https?://|", $image_url) === 0)
+			$image_url = "http://".$handle_parts[1].$image_url;
+
+		update_contact_avatar($image_url, $importer["uid"], $contact["id"]);
+
+		// Generic birthday. We don't know the timezone. The year is irrelevant.
+
+		$birthday = str_replace("1000", "1901", $birthday);
+
+		if ($birthday != "")
+			$birthday = datetime_convert("UTC", "UTC", $birthday, "Y-m-d");
+
+		// this is to prevent multiple birthday notifications in a single year
+		// if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year
+
+		if(substr($birthday,5) === substr($contact["bd"],5))
+			$birthday = $contact["bd"];
+
+		$r = q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `name-date` = '%s', `bd` = '%s',
+				`location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d AND `uid` = %d",
+			dbesc($name),
+			dbesc($nick),
+			dbesc($author),
+			dbesc(datetime_convert()),
+			dbesc($birthday),
+			dbesc($location),
+			dbesc($about),
+			dbesc($keywords),
+			dbesc($gender),
+			intval($contact["id"]),
+			intval($importer["uid"])
+		);
+
+		if ($searchable) {
+			poco_check($contact["url"], $name, NETWORK_DIASPORA, $image_url, $about, $location, $gender, $keywords, "",
+				datetime_convert(), 2, $contact["id"], $importer["uid"]);
+		}
+
+		$gcontact = array("url" => $contact["url"], "network" => NETWORK_DIASPORA, "generation" => 2,
+					"photo" => $image_url, "name" => $name, "location" => $location,
+					"about" => $about, "birthday" => $birthday, "gender" => $gender,
+					"addr" => $author, "nick" => $nick, "keywords" => $keywords,
+					"hide" => !$searchable, "nsfw" => $nsfw);
+
+		update_gcontact($gcontact);
+
 		return true;
 	}
 
 	private function import_request($importer, $data) {
+print_r($data);
+/*
+	$author = unxmlify($xml->author);
+	$recipient = unxmlify($xml->recipient);
+
+	if (!$author || !$recipient)
+		return;
+
+	$contact = self::get_contact_by_handle($importer["uid"],$author);
+
+	if($contact) {
+
+		// perhaps we were already sharing with this person. Now they're sharing with us.
+		// That makes us friends.
+
+		if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
+			q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
+				intval(CONTACT_IS_FRIEND),
+				intval($contact["id"]),
+				intval($importer["uid"])
+			);
+		}
+		// send notification
+
+		$r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1",
+			intval($importer["uid"])
+		);
+
+		if((count($r)) && (!$r[0]["hide-friends"]) && (!$contact["hidden"]) && intval(get_pconfig($importer["uid"],'system','post_newfriend'))) {
+			require_once('include/items.php');
+
+			$self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
+				intval($importer["uid"])
+			);
+
+			// they are not CONTACT_IS_FOLLOWER anymore but that's what we have in the array
+
+			if(count($self) && $contact["rel"] == CONTACT_IS_FOLLOWER) {
+
+				$arr = array();
+				$arr["uri"] = $arr["parent-uri"] = item_new_uri($a->get_hostname(), $importer["uid"]);
+				$arr["uid"] = $importer["uid"];
+				$arr["contact-id"] = $self[0]["id"];
+				$arr["wall"] = 1;
+				$arr["type"] = 'wall';
+				$arr["gravity"] = 0;
+				$arr["origin"] = 1;
+				$arr["author-name"] = $arr["owner-name"] = $self[0]["name"];
+				$arr["author-link"] = $arr["owner-link"] = $self[0]["url"];
+				$arr["author-avatar"] = $arr["owner-avatar"] = $self[0]["thumb"];
+				$arr["verb"] = ACTIVITY_FRIEND;
+				$arr["object-type"] = ACTIVITY_OBJ_PERSON;
+
+				$A = '[url=' . $self[0]["url"] . "]' . $self[0]["name"] . '[/url]';
+				$B = '[url=' . $contact["url"] . "]' . $contact["name"] . '[/url]';
+				$BPhoto = '[url=' . $contact["url"] . "]' . '[img]' . $contact["thumb"] . '[/img][/url]';
+				$arr["body"] =  sprintf( t('%1$s is now friends with %2$s'), $A, $B)."\n\n\n".$Bphoto;
+
+				$arr["object"] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $contact["name"] . '</title>'
+					. '<id>' . $contact["url"] . '/' . $contact["name"] . '</id>';
+				$arr["object"] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $contact["url"] . '" />' . "\n")
+;
+				$arr["object"] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $contact["thumb"] . '" />' . "\n");
+				$arr["object"] .= '</link></object>' . "\n";
+				$arr["last-child"] = 1;
+
+				$arr["allow_cid"] = $user[0]["allow_cid"];
+				$arr["allow_gid"] = $user[0]["allow_gid"];
+				$arr["deny_cid"]  = $user[0]["deny_cid"];
+				$arr["deny_gid"]  = $user[0]["deny_gid"];
+
+				$i = item_store($arr);
+				if($i)
+				proc_run('php',"include/notifier.php","activity","$i");
+
+			}
+
+		}
+
+		return;
+	}
+
+	$ret = self::get_person_by_handle($author);
+
+
+	if((! count($ret)) || ($ret["network"] != NETWORK_DIASPORA)) {
+		logger('diaspora_request: Cannot resolve diaspora handle ' . $author . ' for ' . $recipient);
+		return;
+	}
+
+	$batch = (($ret["batch"]) ? $ret["batch"] : implode('/', array_slice(explode('/',$ret["url"]),0,3)) . '/receive/public');
+
+
+
+	$r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`nurl`,`batch`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`)
+		VALUES ( %d, '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s',%d,%d) ",
+		intval($importer["uid"]),
+		dbesc($ret["network"]),
+		dbesc($ret["addr"]),
+		datetime_convert(),
+		dbesc($ret["url"]),
+		dbesc(normalise_link($ret["url"])),
+		dbesc($batch),
+		dbesc($ret["name"]),
+		dbesc($ret["nick"]),
+		dbesc($ret["photo"]),
+		dbesc($ret["pubkey"]),
+		dbesc($ret["notify"]),
+		dbesc($ret["poll"]),
+		1,
+		2
+	);
+
+	// find the contact record we just created
+
+	$contact_record = diaspora_get_contact_by_handle($importer["uid"],$author);
+
+	if(! $contact_record) {
+		logger('diaspora_request: unable to locate newly created contact record.');
+		return;
+	}
+
+	$g = q("select def_gid from user where uid = %d limit 1",
+		intval($importer["uid"])
+	);
+	if($g && intval($g[0]["def_gid"])) {
+		require_once('include/group.php');
+		group_add_member($importer["uid"],'',$contact_record["id"],$g[0]["def_gid"]);
+	}
+
+	if($importer["page-flags"] == PAGE_NORMAL) {
+
+		$hash = random_string() . (string) time();   // Generate a confirm_key
+
+		$ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime` )
+			VALUES ( %d, %d, %d, %d, '%s', '%s', '%s' )",
+			intval($importer["uid"]),
+			intval($contact_record["id"]),
+			0,
+			0,
+			dbesc( t('Sharing notification from Diaspora network')),
+			dbesc($hash),
+			dbesc(datetime_convert())
+		);
+	}
+	else {
+
+		// automatic friend approval
+
+		require_once('include/Photo.php');
+
+		update_contact_avatar($contact_record["photo"],$importer["uid"],$contact_record["id"]);
+
+		// technically they are sharing with us (CONTACT_IS_SHARING),
+		// but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX
+		// we are going to change the relationship and make them a follower.
+
+		if($importer["page-flags"] == PAGE_FREELOVE)
+			$new_relation = CONTACT_IS_FRIEND;
+		else
+			$new_relation = CONTACT_IS_FOLLOWER;
+
+		$r = q("UPDATE `contact` SET `rel` = %d,
+			`name-date` = '%s',
+			`uri-date` = '%s',
+			`blocked` = 0,
+			`pending` = 0,
+			`writable` = 1
+			WHERE `id` = %d
+			",
+			intval($new_relation),
+			dbesc(datetime_convert()),
+			dbesc(datetime_convert()),
+			intval($contact_record["id"])
+		);
+
+		$u = q("select * from user where uid = %d limit 1",intval($importer["uid"]));
+		if($u)
+			$ret = diaspora_share($u[0],$contact_record);
+	}
+*/
 		return true;
 	}
 
 	private function import_reshare($importer, $data) {
+/*
+	$guid = notags(unxmlify($xml->guid));
+	$author = notags(unxmlify($xml->author));
+
+
+	if($author != $msg["author"]) {
+		logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
+		return 202;
+	}
+
+	$contact = diaspora_get_contact_by_handle($importer["uid"],$author);
+	if(! $contact)
+		return;
+
+	if(! diaspora_post_allow($importer,$contact, false)) {
+		logger('diaspora_reshare: Ignoring this author: ' . $author . ' ' . print_r($xml,true));
+		return 202;
+	}
+
+	$message_id = $author . ':' . $guid;
+	$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+		intval($importer["uid"]),
+		dbesc($guid)
+	);
+	if(count($r)) {
+		logger('diaspora_reshare: message exists: ' . $guid);
+		return;
+	}
+
+	$orig_author = notags(unxmlify($xml->root_diaspora_id));
+	$orig_guid = notags(unxmlify($xml->root_guid));
+	$orig_url = $a->get_baseurl()."/display/".$orig_guid;
+
+	$create_original_post = false;
+
+	// Do we already have this item?
+	$r = q("SELECT `body`, `tag`, `app`, `created`, `plink`, `object`, `object-type`, `uri` FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT 
+`deleted` AND `body` != '' LIMIT 1",
+		dbesc($orig_guid),
+		dbesc(NETWORK_DIASPORA)
+	);
+	if(count($r)) {
+		logger('reshared message '.$orig_guid." reshared by ".$guid.' already exists on system.');
+
+		// Maybe it is already a reshared item?
+		// Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
+		require_once('include/api.php');
+		if (api_share_as_retweet($r[0]))
+			$r = array();
+		else {
+			$body = $r[0]["body"];
+			$str_tags = $r[0]["tag"];
+			$app = $r[0]["app"];
+			$orig_created = $r[0]["created"];
+			$orig_plink = $r[0]["plink"];
+			$orig_uri = $r[0]["uri"];
+			$object = $r[0]["object"];
+			$objecttype = $r[0]["object-type"];
+		}
+	}
+
+	if (!count($r)) {
+		$body = "";
+		$str_tags = "";
+		$app = "";
+
+		$server = 'https://'.substr($orig_author,strpos($orig_author,'@')+1);
+		logger('1st try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
+		$item = diaspora_fetch_message($orig_guid, $server);
+
+		if (!$item) {
+			$server = 'https://'.substr($author,strpos($author,'@')+1);
+			logger('2nd try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
+			$item = diaspora_fetch_message($orig_guid, $server);
+		}
+		if (!$item) {
+			$server = 'http://'.substr($orig_author,strpos($orig_author,'@')+1);
+			logger('3rd try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
+			$item = diaspora_fetch_message($orig_guid, $server);
+		}
+		if (!$item) {
+			$server = 'http://'.substr($author,strpos($author,'@')+1);
+			logger('4th try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
+			$item = diaspora_fetch_message($orig_guid, $server);
+		}
+
+		if ($item) {
+			$body = $item["body"];
+			$str_tags = $item["tag"];
+			$app = $item["app"];
+			$orig_created = $item["created"];
+			$orig_author = $item["author"];
+			$orig_guid = $item["guid"];
+			$orig_plink = diaspora_plink($orig_author, $orig_guid);
+			$orig_uri = $orig_author.':'.$orig_guid;
+			$create_original_post = ($body != "");
+			$object = $item["object"];
+			$objecttype = $item["object-type"];
+		}
+	}
+
+	$plink = diaspora_plink($author, $guid);
+
+	$person = find_diaspora_person_by_handle($orig_author);
+
+	$created = unxmlify($xml->created_at);
+	$private = ((unxmlify($xml->public) == 'false') ? 1 : 0);
+
+	$datarray = array();
+
+	$datarray["uid"] = $importer["uid"];
+	$datarray["contact-id"] = $contact["id"];
+	$datarray["wall"] = 0;
+	$datarray["network"]  = NETWORK_DIASPORA;
+	$datarray["guid"] = $guid;
+	$datarray["uri"] = $datarray["parent-uri"] = $message_id;
+	$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert('UTC','UTC',$created);
+	$datarray["private"] = $private;
+	$datarray["parent"] = 0;
+	$datarray["plink"] = $plink;
+	$datarray["owner-name"] = $contact["name"];
+	$datarray["owner-link"] = $contact["url"];
+	$datarray["owner-avatar"] = ((x($contact,'thumb')) ? $contact["thumb"] : $contact["photo"]);
+	      $prefix = share_header($person["name"], $person["url"], ((x($person,'thumb')) ? $person["thumb"] : $person["photo"]), $orig_guid, $orig_created, $orig_url);
+
+		$datarray["author-name"] = $contact["name"];
+		$datarray["author-link"] = $contact["url"];
+		$datarray["author-avatar"] = $contact["thumb"];
+		$datarray["body"] = $prefix.$body."[/share]";
+
+	$datarray["object"] = json_encode($xml);
+	$datarray["object-type"] = $objecttype;
+
+	$datarray["tag"] = $str_tags;
+	$datarray["app"]  = $app;
+
+	// if empty content it might be a photo that hasn't arrived yet. If a photo arrives, we'll make it visible. (testing)
+	$datarray["visible"] = ((strlen($body)) ? 1 : 0);
+
+	// Store the original item of a reshare
+	if ($create_original_post) {
+		require_once("include/Contact.php");
+
+		$datarray2 = $datarray;
+
+		$datarray2["uid"] = 0;
+		$datarray2["contact-id"] = get_contact($person["url"], 0);
+		$datarray2["guid"] = $orig_guid;
+		$datarray2["uri"] = $datarray2["parent-uri"] = $orig_uri;
+		$datarray2["changed"] = $datarray2["created"] = $datarray2["edited"] = $datarray2["commented"] = $datarray2["received"] = datetime_convert('UTC','UTC',$orig_created);
+		$datarray2["parent"] = 0;
+		$datarray2["plink"] = $orig_plink;
+
+		$datarray2["author-name"] = $person["name"];
+		$datarray2["author-link"] = $person["url"];
+		$datarray2["author-avatar"] = ((x($person,'thumb')) ? $person["thumb"] : $person["photo"]);
+		$datarray2["owner-name"] = $datarray2["author-name"];
+		$datarray2["owner-link"] = $datarray2["author-link"];
+		$datarray2["owner-avatar"] = $datarray2["author-avatar"];
+		$datarray2["body"] = $body;
+		$datarray2["object"] = $object;
+
+		DiasporaFetchGuid($datarray2);
+		$message_id = item_store($datarray2);
+
+		logger("Store original item ".$orig_guid." under message id ".$message_id);
+	}
+
+	DiasporaFetchGuid($datarray);
+	$message_id = item_store($datarray);
+*/
 		return true;
 	}
 
@@ -786,8 +1316,131 @@ print_r($datarray);
 		return true;
 	}
 
-	private function import_status_message($importer, $data) {
-		return true;
+	private function import_status_message($importer, $data, $msg, $data2) {
+
+		$raw_message = unxmlify($data->raw_message);
+		$guid = notags(unxmlify($data->guid));
+		$author = notags(unxmlify($data->author));
+		$public = notags(unxmlify($data->public));
+		$created_at = notags(unxmlify($data->created_at));
+		$provider_display_name = notags(unxmlify($data->provider_display_name));
+
+		foreach ($data->children() AS $name => $entry)
+			if (count($entry->children()))
+				if (!in_array($name, array("location", "photo", "poll")))
+					die("Kinder: ".$name."\n");
+/*
+		if ($data->location) {
+			print_r($location);
+			foreach ($data->location->children() AS $fieldname => $data)
+				echo $fieldname." - ".$data."\n";
+			die("Location!\n");
+		}
+*/
+/*
+		if ($data->photo) {
+			print_r($data->photo);
+			foreach ($data->photo->children() AS $fieldname => $data)
+				echo $fieldname." - ".$data."\n";
+			die("Photo!\n");
+		}
+*/
+
+		if ($data->poll) {
+			print_r($data2);
+			print_r($data);
+			die("poll!\n");
+		}
+
+
+		$contact = self::get_contact_by_handle($importer["uid"], $author);
+		if (!$contact) {
+			logger("A Contact for handle ".$author." and user ".$importer["uid"]." was not found");
+			return false;
+		}
+
+		if (!self::post_allow($importer, $contact, false)) {
+			logger("Ignoring this author.");
+			return false;
+		}
+/*
+		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($importer["uid"]),
+			dbesc($guid)
+		);
+		if(count($r)) {
+			logger("message exists: ".$guid);
+			return false;
+		}
+*/
+		$private = (($public == "false") ? 1 : 0);
+
+		$body = diaspora2bb($raw_message);
+
+		$datarray = array();
+
+		if($data->photo->remote_photo_path AND $data->photo->remote_photo_name)
+			$datarray["object-type"] = ACTIVITY_OBJ_PHOTO;
+		else {
+			$datarray["object-type"] = ACTIVITY_OBJ_NOTE;
+			// Add OEmbed and other information to the body
+			if (!self::is_redmatrix($contact["url"]))
+				$body = add_page_info_to_body($body, false, true);
+		}
+
+		$str_tags = "";
+
+		$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]";
+			}
+		}
+		$plink = self::plink($author, $guid);
+
+		$datarray["uid"] = $importer["uid"];
+		$datarray["contact-id"] = $contact["id"];
+		$datarray["network"] = NETWORK_DIASPORA;
+
+		$datarray["author-name"] = $contact["name"];
+		$datarray["author-link"] = $contact["url"];
+		$datarray["author-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
+
+		$datarray["owner-name"] = $datarray["author-name"];
+		$datarray["owner-link"] = $datarray["author-link"];
+		$datarray["owner-avatar"] = $datarray["author-avatar"];
+
+		$datarray["guid"] = $guid;
+		$datarray["uri"] = $datarray["parent-uri"] = $author.":".$guid;
+
+		$datarray["verb"] = ACTIVITY_POST;
+		$datarray["gravity"] = GRAVITY_PARENT;
+
+		$datarray["object"] = json_encode($data);
+
+		$datarray["body"] = $body;
+
+		$datarray["tag"] = $str_tags;
+		if ($provider_display_name != "")
+			$datarray["app"] = $provider_display_name;
+
+		$datarray["plink"] = $plink;
+		$datarray["private"] = $private;
+		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
+
+		// if empty content it might be a photo that hasn't arrived yet. If a photo arrives, we'll make it visible.
+
+		$datarray["visible"] = ((strlen($body)) ? 1 : 0);
+
+		self::fetch_guid($datarray);
+		//$message_id = item_store($datarray);
+		print_r($datarray);
+
+		logger("Stored item with message id ".$message_id, LOGGER_DEBUG);
+
+		return $message_id;
 	}
 }
 ?>

From 09060c0ed30babe65f659a6a3122b8f148217d16 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Mon, 29 Feb 2016 17:24:34 +0100
Subject: [PATCH 135/273] adding some colors to the Federation Statistics page
 of the admin panel

---
 mod/admin.php                       | 8 +++++++-
 view/templates/admin_federation.tpl | 4 ++--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/mod/admin.php b/mod/admin.php
index ecd08bbe00..7a16820c44 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -270,6 +270,12 @@ function admin_page_federation(&$a) {
 	// Add more platforms if you like, when one returns 0 known nodes it is not
 	// displayed on the stats page.
 	$platforms = array('Friendica', 'Diaspora', '%%red%%', 'Hubzilla', 'GNU Social', 'StatusNet');
+	$colors    = array('Friendica' => '#ffc018',     // orange from the logo
+	                   'Diaspora'  => '#a1a1a1',     // logo is black and white, makes a gray
+			   '%%red%%'   => '#c50001',     // fire red from the logo
+			   'Hubzilla'  => '#43488a',     // blue from the logo
+			   'GNU Social'=> '#a22430',     // dark red from the logo
+			   'StatusNet' => '#789240');    // the green from the logo (red and blue have already others
 	$counts = array();
 	$total = 0;
 
@@ -340,7 +346,7 @@ function admin_page_federation(&$a) {
 
 		// the 3rd array item is needed for the JavaScript graphs as JS does
 		// not like some characters in the names of variables...
-		$counts[$p]=array($c[0], $v, str_replace(array(' ','%'),'',$p));
+		$counts[$p]=array($c[0], $v, str_replace(array(' ','%'),'',$p), $colors[$p]);
 	}
 
 	// some helpful text
diff --git a/view/templates/admin_federation.tpl b/view/templates/admin_federation.tpl
index fad87da5b5..ee33df09b2 100644
--- a/view/templates/admin_federation.tpl
+++ b/view/templates/admin_federation.tpl
@@ -19,7 +19,7 @@
 <script>
 var FedData = [
 {{foreach $counts as $c}}
-    { value: {{$c[0]['total']}}, label: "{{$c[0]['platform']}}", color: "#90EE90", highlight: "#EE90A1", },
+    { value: {{$c[0]['total']}}, label: "{{$c[0]['platform']}}", color: '{{$c[3]}}', highlight: "#EE90A1", },
 {{/foreach}}
 ];
 var ctx = document.getElementById("FederationChart").getContext("2d");
@@ -40,7 +40,7 @@ var myDoughnutChart = new Chart(ctx).Doughnut(FedData, { animateRotate : false,
     <script>
     var {{$c[2]}}data = [
     {{foreach $c[1] as $v}}
-	{ value: {{$v['total']}}, label: '{{$v['version']}}', color: "#90EE90", highlight: "#EE90A1",},
+	{ value: {{$v['total']}}, label: '{{$v['version']}}', color: "{{$c[3]}}", highlight: "#EE90A1",},
     {{/foreach}}
     ];
     var ctx = document.getElementById("{{$c[2]}}Chart").getContext("2d");

From 8bcbff30e0984f35bb3d36c22a2edbce437d6369 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 29 Feb 2016 23:54:25 +0100
Subject: [PATCH 136/273] Account deletion should work, status messages works -
 reshares are half done.

---
 include/diaspora2.php | 519 ++++++++++++++++++++++++++----------------
 1 file changed, 328 insertions(+), 191 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 578a496c0a..59514ebc76 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -58,7 +58,7 @@ class diaspora {
 
 		// Use a dummy importer to import the data for the public copy
 		$importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE);
-		self::dispatch($importer,$msg);
+		$item_id = self::dispatch($importer,$msg);
 
 		// Now distribute it to the followers
 		$r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN
@@ -74,6 +74,8 @@ class diaspora {
 			}
 		} else
 			logger("No subscribers for ".$msg["author"]." ".print_r($msg, true));
+
+		return $item_id;
 	}
 
 	public static function dispatch($importer, $msg) {
@@ -82,7 +84,7 @@ class diaspora {
 		// This will often be different with relayed messages (for example "like" and "comment")
 		$sender = $msg["author"];
 
-		if (!diaspora::valid_posting($msg, $fields, $data2)) {
+		if (!diaspora::valid_posting($msg, $fields)) {
 			logger("Invalid posting");
 			return false;
 		}
@@ -90,8 +92,9 @@ class diaspora {
 		$type = $fields->getName();
 
 		switch ($type) {
-			case "account_deletion": // Not implemented
-				return self::import_account_deletion($importer, $fields);
+			case "account_deletion":
+				return true;
+				//return self::import_account_deletion($importer, $fields);
 
 			case "comment":
 				return true;
@@ -131,7 +134,8 @@ class diaspora {
 				return self::import_retraction($importer, $fields);
 
 			case "status_message":
-				return self::import_status_message($importer, $fields, $msg, $data2);
+				return true;
+				//return self::import_status_message($importer, $fields, $msg, $data2);
 
 			default:
 				logger("Unknown message type ".$type);
@@ -152,7 +156,7 @@ class diaspora {
 	 *
 	 * @return bool Is the posting valid?
 	 */
-	private function valid_posting($msg, &$fields, &$element) {
+	private function valid_posting($msg, &$fields) {
 
 		$data = parse_xml_string($msg["message"], false);
 
@@ -554,7 +558,16 @@ class diaspora {
 	}
 
 	private function import_account_deletion($importer, $data) {
-		// Not supported by now. We are waiting for sample data
+		$author = notags(unxmlify($data->author));
+
+		$contact = self::get_contact_by_handle($importer["uid"], $author);
+		if (!$contact) {
+			logger("cannot find contact for sender: ".$sender);
+			return false;
+		}
+
+		// We now remove the contact
+		contact_remove($contact["id"]);
 		return true;
 	}
 
@@ -647,6 +660,167 @@ class diaspora {
 	}
 
 	private function import_conversation($importer, $data) {
+/*
+        $guid = notags(unxmlify($xml->guid));
+        $subject = notags(unxmlify($xml->subject));
+        $diaspora_handle = notags(unxmlify($xml->diaspora_handle));
+        $participant_handles = notags(unxmlify($xml->participant_handles));
+        $created_at = datetime_convert('UTC','UTC',notags(unxmlify($xml->created_at)));
+
+        $parent_uri = $diaspora_handle . ':' . $guid;
+
+        $messages = $xml->message;
+
+        if(! count($messages)) {
+                logger('diaspora_conversation: empty conversation');
+                return;
+        }
+
+        $contact = diaspora_get_contact_by_handle($importer['uid'],$msg['author']);
+        if(! $contact) {
+                logger('diaspora_conversation: cannot find contact: ' . $msg['author']);
+                return;
+        }
+
+        if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) {
+                logger('diaspora_conversation: Ignoring this author.');
+                return 202;
+        }
+
+        $conversation = null;
+
+        $c = q("select * from conv where uid = %d and guid = '%s' limit 1",
+                intval($importer['uid']),
+                dbesc($guid)
+        );
+        if(count($c))
+                $conversation = $c[0];
+        else {
+                $r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ",
+                        intval($importer['uid']),
+                        dbesc($guid),
+                        dbesc($diaspora_handle),
+                        dbesc(datetime_convert('UTC','UTC',$created_at)),
+                        dbesc(datetime_convert()),
+                        dbesc($subject),
+                        dbesc($participant_handles)
+                );
+                if($r)
+                        $c = q("select * from conv where uid = %d and guid = '%s' limit 1",
+                intval($importer['uid']),
+            dbesc($guid)
+        );
+            if(count($c))
+            $conversation = $c[0];
+        }
+        if(! $conversation) {
+                logger('diaspora_conversation: unable to create conversation.');
+                return;
+        }
+
+        foreach($messages as $mesg) {
+
+                $reply = 0;
+
+                $msg_guid = notags(unxmlify($mesg->guid));
+                $msg_parent_guid = notags(unxmlify($mesg->parent_guid));
+                $msg_parent_author_signature = notags(unxmlify($mesg->parent_author_signature));
+                $msg_author_signature = notags(unxmlify($mesg->author_signature));
+                $msg_text = unxmlify($mesg->text);
+                $msg_created_at = datetime_convert('UTC','UTC',notags(unxmlify($mesg->created_at)));
+                $msg_diaspora_handle = notags(unxmlify($mesg->diaspora_handle));
+                $msg_conversation_guid = notags(unxmlify($mesg->conversation_guid));
+                if($msg_conversation_guid != $guid) {
+                        logger('diaspora_conversation: message conversation guid does not belong to the current conversation. ' . $xml);
+                        continue;
+                }
+
+                $body = diaspora2bb($msg_text);
+                $message_id = $msg_diaspora_handle . ':' . $msg_guid;
+
+                $author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
+
+                $author_signature = base64_decode($msg_author_signature);
+
+                if(strcasecmp($msg_diaspora_handle,$msg['author']) == 0) {
+                        $person = $contact;
+                        $key = $msg['key'];
+                }
+                else {
+                        $person = find_diaspora_person_by_handle($msg_diaspora_handle); 
+
+                        if(is_array($person) && x($person,'pubkey'))
+                                $key = $person['pubkey'];
+                        else {
+                                logger('diaspora_conversation: unable to find author details');
+                                continue;
+                        }
+                }
+
+                if(! rsa_verify($author_signed_data,$author_signature,$key,'sha256')) {
+                        logger('diaspora_conversation: verification failed.');
+                        continue;
+                }
+
+                if($msg_parent_author_signature) {
+                        $owner_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
+
+                        $parent_author_signature = base64_decode($msg_parent_author_signature);
+
+                        $key = $msg['key'];
+
+                        if(! rsa_verify($owner_signed_data,$parent_author_signature,$key,'sha256')) {
+                                logger('diaspora_conversation: owner verification failed.');
+                                continue;
+                        }
+                }
+
+                $r = q("select id from mail where `uri` = '%s' limit 1",
+                        dbesc($message_id)
+                );
+                if(count($r)) {
+                        logger('diaspora_conversation: duplicate message already delivered.', LOGGER_DEBUG);
+                        continue;
+                }
+
+                q("insert into mail ( `uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`) values ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
+                        intval($importer['uid']),
+                        dbesc($msg_guid),
+                        intval($conversation['id']),
+                        dbesc($person['name']),
+                        dbesc($person['photo']),
+                        dbesc($person['url']),
+                        intval($contact['id']),
+                        dbesc($subject),
+                        dbesc($body),
+                        0,
+                        0,
+                        dbesc($message_id),
+                        dbesc($parent_uri),
+                        dbesc($msg_created_at)
+                );
+
+                q("update conv set updated = '%s' where id = %d",
+                        dbesc(datetime_convert()),
+                        intval($conversation['id'])
+                );
+
+                notification(array(
+                        'type' => NOTIFY_MAIL,
+                        'notify_flags' => $importer['notify-flags'],
+                        'language' => $importer['language'],
+                        'to_name' => $importer['username'],
+                        'to_email' => $importer['email'],
+                        'uid' =>$importer['uid'],
+                        'item' => array('subject' => $subject, 'body' => $body),
+                        'source_name' => $person['name'],
+                        'source_link' => $person['url'],
+                        'source_photo' => $person['thumb'],
+                        'verb' => ACTIVITY_POST,
+                        'otype' => 'mail'
+                ));
+        }
+*/
 		return true;
 	}
 
@@ -858,14 +1032,17 @@ EOT;
 	}
 
 	private function import_participation($importer, $data) {
+		// I'm not sure if we can fully support this message type
 		return true;
 	}
 
 	private function import_photo($importer, $data) {
+		// There doesn't seem to be a reason for this function, since the photo data is transmitted in the status message as well
 		return true;
 	}
 
 	private function import_poll_participation($importer, $data) {
+		// We don't support polls by now
 		return true;
 	}
 
@@ -1138,185 +1315,156 @@ print_r($data);
 	}
 
 	private function import_reshare($importer, $data) {
+		$root_author = notags(unxmlify($data->root_author));
+		$root_guid = notags(unxmlify($data->root_guid));
+		$guid = notags(unxmlify($data->guid));
+		$author = notags(unxmlify($data->author));
+		$public = notags(unxmlify($data->public));
+		$created_at = notags(unxmlify($data->created_at));
+
+		$contact = self::get_contact_by_handle($importer["uid"], $author);
+		if (!$contact)
+			return false;
+
+		if (!self::post_allow($importer, $contact, false)) {
+			logger("Ignoring this author: ".$author." ".print_r($data,true));
+			return false;
+		}
 /*
-	$guid = notags(unxmlify($xml->guid));
-	$author = notags(unxmlify($xml->author));
-
-
-	if($author != $msg["author"]) {
-		logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
-		return 202;
-	}
-
-	$contact = diaspora_get_contact_by_handle($importer["uid"],$author);
-	if(! $contact)
-		return;
-
-	if(! diaspora_post_allow($importer,$contact, false)) {
-		logger('diaspora_reshare: Ignoring this author: ' . $author . ' ' . print_r($xml,true));
-		return 202;
-	}
-
-	$message_id = $author . ':' . $guid;
-	$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-		intval($importer["uid"]),
-		dbesc($guid)
-	);
-	if(count($r)) {
-		logger('diaspora_reshare: message exists: ' . $guid);
-		return;
-	}
-
-	$orig_author = notags(unxmlify($xml->root_diaspora_id));
-	$orig_guid = notags(unxmlify($xml->root_guid));
-	$orig_url = $a->get_baseurl()."/display/".$orig_guid;
-
-	$create_original_post = false;
-
-	// Do we already have this item?
-	$r = q("SELECT `body`, `tag`, `app`, `created`, `plink`, `object`, `object-type`, `uri` FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT 
-`deleted` AND `body` != '' LIMIT 1",
-		dbesc($orig_guid),
-		dbesc(NETWORK_DIASPORA)
-	);
-	if(count($r)) {
-		logger('reshared message '.$orig_guid." reshared by ".$guid.' already exists on system.');
-
-		// Maybe it is already a reshared item?
-		// Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
-		require_once('include/api.php');
-		if (api_share_as_retweet($r[0]))
-			$r = array();
-		else {
-			$body = $r[0]["body"];
-			$str_tags = $r[0]["tag"];
-			$app = $r[0]["app"];
-			$orig_created = $r[0]["created"];
-			$orig_plink = $r[0]["plink"];
-			$orig_uri = $r[0]["uri"];
-			$object = $r[0]["object"];
-			$objecttype = $r[0]["object-type"];
+		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($importer["uid"]),
+			dbesc($guid)
+		);
+		if(count($r)) {
+			logger("message exists: ".$guid);
+			return;
 		}
-	}
+*/
+		$orig_author = $root_author;
+		$orig_guid = $root_guid;
+		$orig_url = App::get_baseurl()."/display/".$guid;
 
-	if (!count($r)) {
-		$body = "";
-		$str_tags = "";
-		$app = "";
+		$create_original_post = false;
 
-		$server = 'https://'.substr($orig_author,strpos($orig_author,'@')+1);
-		logger('1st try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
-		$item = diaspora_fetch_message($orig_guid, $server);
+		// Do we already have this item?
+		$r = q("SELECT `body`, `tag`, `app`, `created`, `plink`, `object`, `object-type`, `uri` FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
+			dbesc($orig_guid),
+			dbesc(NETWORK_DIASPORA)
+		);
+		if(count($r)) {
+			logger("reshared message ".$orig_guid." reshared by ".$guid." already exists on system.");
 
-		if (!$item) {
-			$server = 'https://'.substr($author,strpos($author,'@')+1);
-			logger('2nd try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
-			$item = diaspora_fetch_message($orig_guid, $server);
-		}
-		if (!$item) {
-			$server = 'http://'.substr($orig_author,strpos($orig_author,'@')+1);
-			logger('3rd try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
-			$item = diaspora_fetch_message($orig_guid, $server);
-		}
-		if (!$item) {
-			$server = 'http://'.substr($author,strpos($author,'@')+1);
-			logger('4th try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
-			$item = diaspora_fetch_message($orig_guid, $server);
+			// Maybe it is already a reshared item?
+			// Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
+			require_once('include/api.php');
+			if (api_share_as_retweet($r[0]))
+				$r = array();
+			else {
+				$body = $r[0]["body"];
+				$str_tags = $r[0]["tag"];
+				$app = $r[0]["app"];
+				$orig_created = $r[0]["created"];
+				$orig_plink = $r[0]["plink"];
+				$orig_uri = $r[0]["uri"];
+				$object = $r[0]["object"];
+				$objecttype = $r[0]["object-type"];
+			}
 		}
 
-		if ($item) {
-			$body = $item["body"];
-			$str_tags = $item["tag"];
-			$app = $item["app"];
-			$orig_created = $item["created"];
-			$orig_author = $item["author"];
-			$orig_guid = $item["guid"];
-			$orig_plink = diaspora_plink($orig_author, $orig_guid);
-			$orig_uri = $orig_author.':'.$orig_guid;
-			$create_original_post = ($body != "");
-			$object = $item["object"];
-			$objecttype = $item["object-type"];
+/* @todo
+		if (!count($r)) {
+			$body = "";
+			$str_tags = "";
+			$app = "";
+
+			$server = 'https://'.substr($orig_author,strpos($orig_author,'@')+1);
+			logger('1st try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
+			$item = self::fetch_message($orig_guid, $server);
+
+			if (!$item) {
+				$server = 'https://'.substr($author,strpos($author,'@')+1);
+				logger('2nd try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
+				$item = diaspora_fetch_message($orig_guid, $server);
+			}
+			if (!$item) {
+				$server = 'http://'.substr($orig_author,strpos($orig_author,'@')+1);
+				logger('3rd try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
+				$item = diaspora_fetch_message($orig_guid, $server);
+			}
+			if (!$item) {
+				$server = 'http://'.substr($author,strpos($author,'@')+1);
+				logger('4th try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
+				$item = diaspora_fetch_message($orig_guid, $server);
+			}
+
+			if ($item) {
+				$body = $item["body"];
+				$str_tags = $item["tag"];
+				$app = $item["app"];
+				$orig_created = $item["created"];
+				$orig_author = $item["author"];
+				$orig_guid = $item["guid"];
+				$orig_plink = diaspora_plink($orig_author, $orig_guid);
+				$orig_uri = $orig_author.":".$orig_guid;
+				$create_original_post = ($body != "");
+				$object = $item["object"];
+				$objecttype = $item["object-type"];
+			}
 		}
-	}
+*/
+		$plink = self::plink($author, $guid);
 
-	$plink = diaspora_plink($author, $guid);
+		$person = self::get_person_by_handle($orig_author);
 
-	$person = find_diaspora_person_by_handle($orig_author);
+		$private = (($public == "false") ? 1 : 0);
 
-	$created = unxmlify($xml->created_at);
-	$private = ((unxmlify($xml->public) == 'false') ? 1 : 0);
+		$datarray = array();
 
-	$datarray = array();
-
-	$datarray["uid"] = $importer["uid"];
-	$datarray["contact-id"] = $contact["id"];
-	$datarray["wall"] = 0;
-	$datarray["network"]  = NETWORK_DIASPORA;
-	$datarray["guid"] = $guid;
-	$datarray["uri"] = $datarray["parent-uri"] = $message_id;
-	$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert('UTC','UTC',$created);
-	$datarray["private"] = $private;
-	$datarray["parent"] = 0;
-	$datarray["plink"] = $plink;
-	$datarray["owner-name"] = $contact["name"];
-	$datarray["owner-link"] = $contact["url"];
-	$datarray["owner-avatar"] = ((x($contact,'thumb')) ? $contact["thumb"] : $contact["photo"]);
-	      $prefix = share_header($person["name"], $person["url"], ((x($person,'thumb')) ? $person["thumb"] : $person["photo"]), $orig_guid, $orig_created, $orig_url);
+		$datarray["uid"] = $importer["uid"];
+		$datarray["contact-id"] = $contact["id"];
+		$datarray["network"]  = NETWORK_DIASPORA;
 
 		$datarray["author-name"] = $contact["name"];
 		$datarray["author-link"] = $contact["url"];
-		$datarray["author-avatar"] = $contact["thumb"];
+		$datarray["author-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
+
+		$datarray["owner-name"] = $datarray["author-name"];
+		$datarray["owner-link"] = $datarray["author-link"];
+		$datarray["owner-avatar"] = $datarray["author-avatar"];
+
+		$datarray["guid"] = $guid;
+		$datarray["uri"] = $datarray["parent-uri"] = $author.":".$guid;
+
+		$datarray["verb"] = ACTIVITY_POST;
+		$datarray["gravity"] = GRAVITY_PARENT;
+
+		$datarray["object"] = json_encode($data);
+
+		$prefix = share_header($person["name"], $person["url"], ((x($person,'thumb')) ? $person["thumb"] : $person["photo"]),
+					$orig_guid, $orig_created, $orig_url);
 		$datarray["body"] = $prefix.$body."[/share]";
 
-	$datarray["object"] = json_encode($xml);
-	$datarray["object-type"] = $objecttype;
+		$datarray["tag"] = $str_tags;
+		$datarray["app"]  = $app;
 
-	$datarray["tag"] = $str_tags;
-	$datarray["app"]  = $app;
+		$datarray["plink"] = $plink;
+		$datarray["private"] = $private;
+		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
 
-	// if empty content it might be a photo that hasn't arrived yet. If a photo arrives, we'll make it visible. (testing)
-	$datarray["visible"] = ((strlen($body)) ? 1 : 0);
+		$datarray["object-type"] = $objecttype;
 
-	// Store the original item of a reshare
-	if ($create_original_post) {
-		require_once("include/Contact.php");
+		self::fetch_guid($datarray);
+		//$message_id = item_store($datarray);
+		print_r($datarray);
 
-		$datarray2 = $datarray;
-
-		$datarray2["uid"] = 0;
-		$datarray2["contact-id"] = get_contact($person["url"], 0);
-		$datarray2["guid"] = $orig_guid;
-		$datarray2["uri"] = $datarray2["parent-uri"] = $orig_uri;
-		$datarray2["changed"] = $datarray2["created"] = $datarray2["edited"] = $datarray2["commented"] = $datarray2["received"] = datetime_convert('UTC','UTC',$orig_created);
-		$datarray2["parent"] = 0;
-		$datarray2["plink"] = $orig_plink;
-
-		$datarray2["author-name"] = $person["name"];
-		$datarray2["author-link"] = $person["url"];
-		$datarray2["author-avatar"] = ((x($person,'thumb')) ? $person["thumb"] : $person["photo"]);
-		$datarray2["owner-name"] = $datarray2["author-name"];
-		$datarray2["owner-link"] = $datarray2["author-link"];
-		$datarray2["owner-avatar"] = $datarray2["author-avatar"];
-		$datarray2["body"] = $body;
-		$datarray2["object"] = $object;
-
-		DiasporaFetchGuid($datarray2);
-		$message_id = item_store($datarray2);
-
-		logger("Store original item ".$orig_guid." under message id ".$message_id);
-	}
-
-	DiasporaFetchGuid($datarray);
-	$message_id = item_store($datarray);
-*/
-		return true;
+		return $message_id;
 	}
 
 	private function import_retraction($importer, $data) {
 		return true;
 	}
 
-	private function import_status_message($importer, $data, $msg, $data2) {
+	private function import_status_message($importer, $data) {
 
 		$raw_message = unxmlify($data->raw_message);
 		$guid = notags(unxmlify($data->guid));
@@ -1325,34 +1473,6 @@ print_r($data);
 		$created_at = notags(unxmlify($data->created_at));
 		$provider_display_name = notags(unxmlify($data->provider_display_name));
 
-		foreach ($data->children() AS $name => $entry)
-			if (count($entry->children()))
-				if (!in_array($name, array("location", "photo", "poll")))
-					die("Kinder: ".$name."\n");
-/*
-		if ($data->location) {
-			print_r($location);
-			foreach ($data->location->children() AS $fieldname => $data)
-				echo $fieldname." - ".$data."\n";
-			die("Location!\n");
-		}
-*/
-/*
-		if ($data->photo) {
-			print_r($data->photo);
-			foreach ($data->photo->children() AS $fieldname => $data)
-				echo $fieldname." - ".$data."\n";
-			die("Photo!\n");
-		}
-*/
-
-		if ($data->poll) {
-			print_r($data2);
-			print_r($data);
-			die("poll!\n");
-		}
-
-
 		$contact = self::get_contact_by_handle($importer["uid"], $author);
 		if (!$contact) {
 			logger("A Contact for handle ".$author." and user ".$importer["uid"]." was not found");
@@ -1363,7 +1483,7 @@ print_r($data);
 			logger("Ignoring this author.");
 			return false;
 		}
-/*
+
 		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
 			intval($importer["uid"]),
 			dbesc($guid)
@@ -1372,11 +1492,26 @@ print_r($data);
 			logger("message exists: ".$guid);
 			return false;
 		}
-*/
+
+		/// @todo enable support for polls
+		// if ($data->poll) {
+		//	print_r($data->poll);
+		//	die("poll!\n");
+		// }
+
+		$address = array();
+		if ($data->location)
+			foreach ($data->location->children() AS $fieldname => $data)
+				$address[$fieldname] = notags(unxmlify($data));
+
 		$private = (($public == "false") ? 1 : 0);
 
 		$body = diaspora2bb($raw_message);
 
+		if ($data->photo)
+			for ($i = 0; $i < count($data->photo); $i++)
+				$body = "[img]".$data->photo[$i]->remote_photo_path.$data->photo[$i]->remote_photo_name."[/img]\n".$body;
+
 		$datarray = array();
 
 		if($data->photo->remote_photo_path AND $data->photo->remote_photo_name)
@@ -1430,9 +1565,11 @@ print_r($data);
 		$datarray["private"] = $private;
 		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
 
-		// if empty content it might be a photo that hasn't arrived yet. If a photo arrives, we'll make it visible.
+		if (isset($address["address"]))
+			$datarray["location"] = $address["address"];
 
-		$datarray["visible"] = ((strlen($body)) ? 1 : 0);
+		if (isset($address["lat"]) AND isset($address["lng"]))
+			$datarray["coord"] = $address["lat"]." ".$address["lng"];
 
 		self::fetch_guid($datarray);
 		//$message_id = item_store($datarray);

From cb900c5742628ad437b7fc2d06d10e9999a06aaf Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 1 Mar 2016 07:57:26 +0100
Subject: [PATCH 137/273] Reshares could work now, code is cleaned

---
 include/diaspora2.php | 356 +++++++++++++++++-------------------------
 1 file changed, 147 insertions(+), 209 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 59514ebc76..a1297c5193 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -4,11 +4,14 @@
  * @brief The implementation of the diaspora protocol
  */
 
+require_once("include/items.php");
 require_once("include/bb2diaspora.php");
 require_once("include/Scrape.php");
 require_once("include/Contact.php");
 require_once("include/Photo.php");
 require_once("include/socgraph.php");
+require_once("include/group.php");
+require_once("include/api.php");
 
 class xml {
 	function from_array($array, &$xml) {
@@ -380,6 +383,64 @@ class diaspora {
 		return false;
 	}
 
+	private function post_allow($importer, $contact, $is_comment = false) {
+
+		// perhaps we were already sharing with this person. Now they're sharing with us.
+		// That makes us friends.
+		// Normally this should have handled by getting a request - but this could get lost
+		if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
+			q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
+				intval(CONTACT_IS_FRIEND),
+				intval($contact["id"]),
+				intval($importer["uid"])
+			);
+			$contact["rel"] = CONTACT_IS_FRIEND;
+			logger("defining user ".$contact["nick"]." as friend");
+		}
+
+		if(($contact["blocked"]) || ($contact["readonly"]) || ($contact["archive"]))
+			return false;
+		if($contact["rel"] == CONTACT_IS_SHARING || $contact["rel"] == CONTACT_IS_FRIEND)
+			return true;
+		if($contact["rel"] == CONTACT_IS_FOLLOWER)
+			if(($importer["page-flags"] == PAGE_COMMUNITY) OR $is_comment)
+				return true;
+
+		// Messages for the global users are always accepted
+		if ($importer["uid"] == 0)
+			return true;
+
+		return false;
+	}
+
+	private function get_allowed_contact_by_handle($importer, $handle, $is_comment = false) {
+		$contact = self::get_contact_by_handle($importer["uid"], $handle);
+		if (!$contact) {
+			logger("A Contact for handle ".$handle." and user ".$importer["uid"]." was not found");
+			return false;
+		}
+
+		if (!self::post_allow($importer, $contact, false)) {
+			logger("The handle: ".$handle." is not allowed to post to user ".$importer["uid"]);
+			return false;
+		}
+		return $contact;
+	}
+
+	private function message_exists($uid, $guid) {
+		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($uid),
+			dbesc($guid)
+		);
+
+		if(count($r)) {
+			logger("message ".$guid." already exists for user ".$uid);
+			return false;
+		}
+
+		return true;
+	}
+
 	private function fetch_guid($item) {
 		preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi",
 			function ($match) use ($item){
@@ -388,8 +449,6 @@ class diaspora {
 	}
 
 	private function fetch_guid_sub($match, $item) {
-		$a = get_app();
-
 		if (!self::store_by_guid($match[1], $item["author-link"]))
 			self::store_by_guid($match[1], $item["owner-link"]);
 	}
@@ -453,36 +512,6 @@ class diaspora {
 		return $msg;
 	}
 
-	private function post_allow($importer, $contact, $is_comment = false) {
-
-		// perhaps we were already sharing with this person. Now they're sharing with us.
-		// That makes us friends.
-		// Normally this should have handled by getting a request - but this could get lost
-		if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
-			q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
-				intval(CONTACT_IS_FRIEND),
-				intval($contact["id"]),
-				intval($importer["uid"])
-			);
-			$contact["rel"] = CONTACT_IS_FRIEND;
-			logger("defining user ".$contact["nick"]." as friend");
-		}
-
-		if(($contact["blocked"]) || ($contact["readonly"]) || ($contact["archive"]))
-			return false;
-		if($contact["rel"] == CONTACT_IS_SHARING || $contact["rel"] == CONTACT_IS_FRIEND)
-			return true;
-		if($contact["rel"] == CONTACT_IS_FOLLOWER)
-			if(($importer["page-flags"] == PAGE_COMMUNITY) OR $is_comment)
-				return true;
-
-		// Messages for the global users are always accepted
-		if ($importer["uid"] == 0)
-			return true;
-
-		return false;
-	}
-
 	private function fetch_parent_item($uid, $guid, $author, $contact) {
 		$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
 				`author-name`, `author-link`, `author-avatar`,
@@ -562,7 +591,7 @@ class diaspora {
 
 		$contact = self::get_contact_by_handle($importer["uid"], $author);
 		if (!$contact) {
-			logger("cannot find contact for sender: ".$sender);
+			logger("cannot find contact for author: ".$author);
 			return false;
 		}
 
@@ -577,25 +606,12 @@ class diaspora {
 		$text = unxmlify($data->text);
 		$author = notags(unxmlify($data->author));
 
-		$contact = self::get_contact_by_handle($importer["uid"], $sender);
-		if (!$contact) {
-			logger("cannot find contact for sender: ".$sender);
+		$contact = self::get_allowed_contact_by_handle($importer, $sender, true);
+		if (!$contact)
 			return false;
-		}
 
-		if (!self::post_allow($importer,$contact, true)) {
-			logger("Ignoring the author ".$sender);
+		if (self::message_exists($importer["uid"], $guid))
 			return false;
-		}
-
-		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-			intval($importer["uid"]),
-			dbesc($guid)
-		);
-		if(count($r)) {
-			logger("The comment already exists: ".$guid);
-			return false;
-		}
 
 		$parent_item = self::fetch_parent_item($importer["uid"], $parent_guid, $author, $contact);
 		if (!$parent_item)
@@ -676,16 +692,9 @@ class diaspora {
                 return;
         }
 
-        $contact = diaspora_get_contact_by_handle($importer['uid'],$msg['author']);
-        if(! $contact) {
-                logger('diaspora_conversation: cannot find contact: ' . $msg['author']);
-                return;
-        }
-
-        if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) {
-                logger('diaspora_conversation: Ignoring this author.');
-                return 202;
-        }
+		$contact = self::get_allowed_contact_by_handle($importer, $sender, true)
+		if (!$contact)
+			return false;
 
         $conversation = null;
 
@@ -871,25 +880,12 @@ EOT;
 			return false;
 		}
 
-		$contact = self::get_contact_by_handle($importer["uid"], $sender);
-		if (!$contact) {
-			logger("cannot find contact for sender: ".$sender);
+		$contact = self::get_allowed_contact_by_handle($importer, $sender, true);
+		if (!$contact)
 			return false;
-		}
 
-		if (!self::post_allow($importer,$contact, true)) {
-			logger("Ignoring the author ".$sender);
+		if (self::message_exists($importer["uid"], $guid))
 			return false;
-		}
-
-		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-			intval($importer["uid"]),
-			dbesc($guid)
-		);
-		if(count($r)) {
-			logger("The like already exists: ".$guid);
-			return false;
-		}
 
 		$parent_item = self::fetch_parent_item($importer["uid"], $parent_guid, $author, $contact);
 		if (!$parent_item)
@@ -961,16 +957,9 @@ EOT;
 
 		$parent_uri = $author.":".$parent_guid;
 
-		$contact = self::get_contact_by_handle($importer["uid"], $author);
-		if (!$contact) {
-			logger("cannot find contact: ".$author);
+		$contact = self::get_allowed_contact_by_handle($importer, $author, true);
+		if (!$contact)
 			return false;
-		}
-
-		if(($contact["rel"] == CONTACT_IS_FOLLOWER) || ($contact["blocked"]) || ($contact["readonly"])) {
-			logger("Ignoring this author.");
-			return false;
-		}
 
 		$conversation = null;
 
@@ -1159,7 +1148,6 @@ print_r($data);
 		);
 
 		if((count($r)) && (!$r[0]["hide-friends"]) && (!$contact["hidden"]) && intval(get_pconfig($importer["uid"],'system','post_newfriend'))) {
-			require_once('include/items.php');
 
 			$self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
 				intval($importer["uid"])
@@ -1170,7 +1158,7 @@ print_r($data);
 			if(count($self) && $contact["rel"] == CONTACT_IS_FOLLOWER) {
 
 				$arr = array();
-				$arr["uri"] = $arr["parent-uri"] = item_new_uri($a->get_hostname(), $importer["uid"]);
+				$arr["uri"] = $arr["parent-uri"] = item_new_uri(App::get_hostname(), $importer["uid"]);
 				$arr["uid"] = $importer["uid"];
 				$arr["contact-id"] = $self[0]["id"];
 				$arr["wall"] = 1;
@@ -1256,7 +1244,6 @@ print_r($data);
 		intval($importer["uid"])
 	);
 	if($g && intval($g[0]["def_gid"])) {
-		require_once('include/group.php');
 		group_add_member($importer["uid"],'',$contact_record["id"],$g[0]["def_gid"]);
 	}
 
@@ -1279,8 +1266,6 @@ print_r($data);
 
 		// automatic friend approval
 
-		require_once('include/Photo.php');
-
 		update_contact_avatar($contact_record["photo"],$importer["uid"],$contact_record["id"]);
 
 		// technically they are sharing with us (CONTACT_IS_SHARING),
@@ -1314,6 +1299,60 @@ print_r($data);
 		return true;
 	}
 
+	private function get_original_item($guid, $orig_author, $author) {
+
+		// Do we already have this item?
+		$r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`,
+				`author-name`, `author-link`, `author-avatar`
+				FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
+			dbesc($guid));
+
+		if(count($r)) {
+			logger("reshared message ".$guid." already exists on system.");
+
+			// Maybe it is already a reshared item?
+			// Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
+			if (api_share_as_retweet($r[0]))
+				$r = array();
+			else
+				return $r[0];
+		}
+
+		if (!count($r)) {
+			$server = 'https://'.substr($orig_author,strpos($orig_author,'@')+1);
+			logger("1st try: reshared message ".$guid." will be fetched from original server: ".$server);
+			$item_id = self::store_by_guid($guid, $server);
+
+			if (!$item_id) {
+				$server = 'https://'.substr($author,strpos($author,'@')+1);
+				logger("2nd try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
+				$item = self::store_by_guid($guid, $server);
+			}
+			if (!$item_id) {
+				$server = 'http://'.substr($orig_author,strpos($orig_author,'@')+1);
+				logger("3rd try: reshared message ".$guid." will be fetched from original server: ".$server);
+				$item = self::store_by_guid($guid, $server);
+			}
+			if (!$item_id) {
+				$server = 'http://'.substr($author,strpos($author,'@')+1);
+				logger("4th try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
+				$item = self::store_by_guid($guid, $server);
+			}
+
+			if ($item_id) {
+				$r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`,
+						`author-name`, `author-link`, `author-avatar`
+					FROM `item` WHERE `id` = %d AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
+					intval($item_id));
+
+				if ($r)
+					return $r[0];
+
+			}
+		}
+		return false;
+	}
+
 	private function import_reshare($importer, $data) {
 		$root_author = notags(unxmlify($data->root_author));
 		$root_guid = notags(unxmlify($data->root_guid));
@@ -1322,101 +1361,16 @@ print_r($data);
 		$public = notags(unxmlify($data->public));
 		$created_at = notags(unxmlify($data->created_at));
 
-		$contact = self::get_contact_by_handle($importer["uid"], $author);
+		$contact = self::get_allowed_contact_by_handle($importer, $author, false);
 		if (!$contact)
 			return false;
 
-		if (!self::post_allow($importer, $contact, false)) {
-			logger("Ignoring this author: ".$author." ".print_r($data,true));
+//		if (self::message_exists($importer["uid"], $guid))
+//			return false;
+
+		$original_item = self::get_original_item($root_guid, $root_author, $author);
+		if (!$original_item)
 			return false;
-		}
-/*
-		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-			intval($importer["uid"]),
-			dbesc($guid)
-		);
-		if(count($r)) {
-			logger("message exists: ".$guid);
-			return;
-		}
-*/
-		$orig_author = $root_author;
-		$orig_guid = $root_guid;
-		$orig_url = App::get_baseurl()."/display/".$guid;
-
-		$create_original_post = false;
-
-		// Do we already have this item?
-		$r = q("SELECT `body`, `tag`, `app`, `created`, `plink`, `object`, `object-type`, `uri` FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
-			dbesc($orig_guid),
-			dbesc(NETWORK_DIASPORA)
-		);
-		if(count($r)) {
-			logger("reshared message ".$orig_guid." reshared by ".$guid." already exists on system.");
-
-			// Maybe it is already a reshared item?
-			// Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
-			require_once('include/api.php');
-			if (api_share_as_retweet($r[0]))
-				$r = array();
-			else {
-				$body = $r[0]["body"];
-				$str_tags = $r[0]["tag"];
-				$app = $r[0]["app"];
-				$orig_created = $r[0]["created"];
-				$orig_plink = $r[0]["plink"];
-				$orig_uri = $r[0]["uri"];
-				$object = $r[0]["object"];
-				$objecttype = $r[0]["object-type"];
-			}
-		}
-
-/* @todo
-		if (!count($r)) {
-			$body = "";
-			$str_tags = "";
-			$app = "";
-
-			$server = 'https://'.substr($orig_author,strpos($orig_author,'@')+1);
-			logger('1st try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
-			$item = self::fetch_message($orig_guid, $server);
-
-			if (!$item) {
-				$server = 'https://'.substr($author,strpos($author,'@')+1);
-				logger('2nd try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
-				$item = diaspora_fetch_message($orig_guid, $server);
-			}
-			if (!$item) {
-				$server = 'http://'.substr($orig_author,strpos($orig_author,'@')+1);
-				logger('3rd try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
-				$item = diaspora_fetch_message($orig_guid, $server);
-			}
-			if (!$item) {
-				$server = 'http://'.substr($author,strpos($author,'@')+1);
-				logger('4th try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
-				$item = diaspora_fetch_message($orig_guid, $server);
-			}
-
-			if ($item) {
-				$body = $item["body"];
-				$str_tags = $item["tag"];
-				$app = $item["app"];
-				$orig_created = $item["created"];
-				$orig_author = $item["author"];
-				$orig_guid = $item["guid"];
-				$orig_plink = diaspora_plink($orig_author, $orig_guid);
-				$orig_uri = $orig_author.":".$orig_guid;
-				$create_original_post = ($body != "");
-				$object = $item["object"];
-				$objecttype = $item["object-type"];
-			}
-		}
-*/
-		$plink = self::plink($author, $guid);
-
-		$person = self::get_person_by_handle($orig_author);
-
-		$private = (($public == "false") ? 1 : 0);
 
 		$datarray = array();
 
@@ -1440,18 +1394,18 @@ print_r($data);
 
 		$datarray["object"] = json_encode($data);
 
-		$prefix = share_header($person["name"], $person["url"], ((x($person,'thumb')) ? $person["thumb"] : $person["photo"]),
-					$orig_guid, $orig_created, $orig_url);
-		$datarray["body"] = $prefix.$body."[/share]";
+		$prefix = share_header($original_item["author-name"], $original_item["author-link"], $original_item["author-avatar"],
+					$original_item["guid"], $original_item["created"], $original_item["uri"]);
+		$datarray["body"] = $prefix.$original_item["body"]."[/share]";
 
-		$datarray["tag"] = $str_tags;
-		$datarray["app"]  = $app;
+		$datarray["tag"] = $original_item["tag"];
+		$datarray["app"]  = $original_item["app"];
 
-		$datarray["plink"] = $plink;
-		$datarray["private"] = $private;
+		$datarray["plink"] = self::plink($author, $guid);
+		$datarray["private"] = (($public == "false") ? 1 : 0);
 		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
 
-		$datarray["object-type"] = $objecttype;
+		$datarray["object-type"] = $original_item["object-type"];
 
 		self::fetch_guid($datarray);
 		//$message_id = item_store($datarray);
@@ -1473,25 +1427,12 @@ print_r($data);
 		$created_at = notags(unxmlify($data->created_at));
 		$provider_display_name = notags(unxmlify($data->provider_display_name));
 
-		$contact = self::get_contact_by_handle($importer["uid"], $author);
-		if (!$contact) {
-			logger("A Contact for handle ".$author." and user ".$importer["uid"]." was not found");
+		$contact = self::get_allowed_contact_by_handle($importer, $author, false);
+		if (!$contact)
 			return false;
-		}
 
-		if (!self::post_allow($importer, $contact, false)) {
-			logger("Ignoring this author.");
+		if (self::message_exists($importer["uid"], $guid))
 			return false;
-		}
-
-		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-			intval($importer["uid"]),
-			dbesc($guid)
-		);
-		if(count($r)) {
-			logger("message exists: ".$guid);
-			return false;
-		}
 
 		/// @todo enable support for polls
 		// if ($data->poll) {
@@ -1504,8 +1445,6 @@ print_r($data);
 			foreach ($data->location->children() AS $fieldname => $data)
 				$address[$fieldname] = notags(unxmlify($data));
 
-		$private = (($public == "false") ? 1 : 0);
-
 		$body = diaspora2bb($raw_message);
 
 		if ($data->photo)
@@ -1533,7 +1472,6 @@ print_r($data);
 				$str_tags .= "@[url=".$mtch[1]."[/url]";
 			}
 		}
-		$plink = self::plink($author, $guid);
 
 		$datarray["uid"] = $importer["uid"];
 		$datarray["contact-id"] = $contact["id"];
@@ -1561,8 +1499,8 @@ print_r($data);
 		if ($provider_display_name != "")
 			$datarray["app"] = $provider_display_name;
 
-		$datarray["plink"] = $plink;
-		$datarray["private"] = $private;
+		$datarray["plink"] = self::plink($author, $guid);
+		$datarray["private"] = (($public == "false") ? 1 : 0);
 		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
 
 		if (isset($address["address"]))

From 04a7d6384ef5ae137019286c3819fef1d5afcf6b Mon Sep 17 00:00:00 2001
From: Roland Haeder <roland@mxchange.org>
Date: Tue, 1 Mar 2016 14:27:38 +0100
Subject: [PATCH 138/273] No need to set $a->theme_info = array() everywhere if
 you can define it in App itself.

Signed-off-by: Roland Haeder <roland@mxchange.org>
---
 boot.php                          | 5 +++--
 view/theme/decaf-mobile/theme.php | 1 -
 view/theme/duepuntozero/theme.php | 1 -
 view/theme/facepark/theme.php     | 1 -
 view/theme/frost-mobile/theme.php | 1 -
 view/theme/frost/theme.php        | 1 -
 view/theme/quattro/theme.php      | 2 --
 view/theme/smoothly/theme.php     | 1 -
 view/theme/vier/theme.php         | 2 --
 9 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/boot.php b/boot.php
index d82669f231..4b2e83f18a 100644
--- a/boot.php
+++ b/boot.php
@@ -465,11 +465,12 @@ class App {
 	public  $plugins;
 	public  $apps = array();
 	public  $identities;
-	public	$is_mobile;
-	public	$is_tablet;
+	public	$is_mobile = false;
+	public	$is_tablet = false;
 	public	$is_friendica_app;
 	public	$performance = array();
 	public	$callstack = array();
+	public	$theme_info = array();
 
 	public $nav_sel;
 
diff --git a/view/theme/decaf-mobile/theme.php b/view/theme/decaf-mobile/theme.php
index 1a32fb724d..9b1c1daa61 100644
--- a/view/theme/decaf-mobile/theme.php
+++ b/view/theme/decaf-mobile/theme.php
@@ -10,7 +10,6 @@
  */
 
 function decaf_mobile_init(&$a) {
-	$a->theme_info = array();
 	$a->sourcename = 'Friendica mobile web';
 	$a->videowidth = 250;
 	$a->videoheight = 200;
diff --git a/view/theme/duepuntozero/theme.php b/view/theme/duepuntozero/theme.php
index ba3f25d3e2..50d57f91e5 100644
--- a/view/theme/duepuntozero/theme.php
+++ b/view/theme/duepuntozero/theme.php
@@ -2,7 +2,6 @@
 
 function duepuntozero_init(&$a) {
 
-$a->theme_info = array();
 set_template_engine($a, 'smarty3');
 
     $colorset = get_pconfig( local_user(), 'duepuntozero','colorset');
diff --git a/view/theme/facepark/theme.php b/view/theme/facepark/theme.php
index e7203c6641..e6255f118a 100644
--- a/view/theme/facepark/theme.php
+++ b/view/theme/facepark/theme.php
@@ -1,7 +1,6 @@
 <?php
 
 function facepark_init(&$a) {
-$a->theme_info = array();
 set_template_engine($a, 'smarty3');
 
 $a->page['htmlhead'] .= <<< EOT
diff --git a/view/theme/frost-mobile/theme.php b/view/theme/frost-mobile/theme.php
index beec924934..29a990f7b8 100644
--- a/view/theme/frost-mobile/theme.php
+++ b/view/theme/frost-mobile/theme.php
@@ -10,7 +10,6 @@
  */
 
 function frost_mobile_init(&$a) {
-	$a->theme_info = array();
 	$a->sourcename = 'Friendica mobile web';
 	$a->videowidth = 250;
 	$a->videoheight = 200;
diff --git a/view/theme/frost/theme.php b/view/theme/frost/theme.php
index 868a840dee..1093a04729 100644
--- a/view/theme/frost/theme.php
+++ b/view/theme/frost/theme.php
@@ -10,7 +10,6 @@
  */
 
 function frost_init(&$a) {
-	$a->theme_info = array();
 	$a->videowidth = 400;
 	$a->videoheight = 330;
 	$a->theme_thread_allow = false;
diff --git a/view/theme/quattro/theme.php b/view/theme/quattro/theme.php
index a1cd29ee72..0b67c6b49a 100644
--- a/view/theme/quattro/theme.php
+++ b/view/theme/quattro/theme.php
@@ -8,8 +8,6 @@
  */
 
 function quattro_init(&$a) {
-	$a->theme_info = array();
-
 	$a->page['htmlhead'] .= '<script src="'.$a->get_baseurl().'/view/theme/quattro/tinycon.min.js"></script>';
 	$a->page['htmlhead'] .= '<script src="'.$a->get_baseurl().'/view/theme/quattro/js/quattro.js"></script>';;
 }
diff --git a/view/theme/smoothly/theme.php b/view/theme/smoothly/theme.php
index d3ebbc1d15..0dae3a6e47 100644
--- a/view/theme/smoothly/theme.php
+++ b/view/theme/smoothly/theme.php
@@ -11,7 +11,6 @@
  */
 
 function smoothly_init(&$a) {
-	$a->theme_info = array();
 	set_template_engine($a, 'smarty3');
 
 	$cssFile = null;
diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php
index 7f6ead079f..925ac76a1f 100644
--- a/view/theme/vier/theme.php
+++ b/view/theme/vier/theme.php
@@ -19,8 +19,6 @@ function vier_init(&$a) {
 
 	set_template_engine($a, 'smarty3');
 
-	$a->theme_info = array();
-
 	if ($a->argv[0].$a->argv[1] === "profile".$a->user['nickname'] or $a->argv[0] === "network" && local_user()) {
 		vier_community_info();
 

From f10d2afca0edfef804aa95affe77bba99a603b3b Mon Sep 17 00:00:00 2001
From: Roland Haeder <roland@mxchange.org>
Date: Tue, 1 Mar 2016 14:32:19 +0100
Subject: [PATCH 139/273] Prevent some E_NOTICE in boot.php

Signed-off-by: Roland Haeder <roland@mxchange.org>
---
 boot.php | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/boot.php b/boot.php
index d82669f231..44fbcda735 100644
--- a/boot.php
+++ b/boot.php
@@ -1046,11 +1046,21 @@ class App {
 	function save_timestamp($stamp, $value) {
 		$duration = (float)(microtime(true)-$stamp);
 
+		if (!isset($this->performance[$value])) {
+			// Prevent ugly E_NOTICE
+			$this->performance[$value] = 0;
+		}
+
 		$this->performance[$value] += (float)$duration;
 		$this->performance["marktime"] += (float)$duration;
 
 		$callstack = $this->callstack();
 
+		if (!isset($this->callstack[$value][$callstack])) {
+			// Prevent ugly E_NOTICE
+			$this->callstack[$value][$callstack] = 0;
+		}
+
 		$this->callstack[$value][$callstack] += (float)$duration;
 
 	}

From 04eacb64703c8d2a590c64da7ed5fae80ac26769 Mon Sep 17 00:00:00 2001
From: Roland Haeder <roland@mxchange.org>
Date: Tue, 1 Mar 2016 14:36:23 +0100
Subject: [PATCH 140/273] Prevent some E_NOTICE in identity.php

Signed-off-by: Roland Haeder <roland@mxchange.org>
---
 include/identity.php | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/include/identity.php b/include/identity.php
index aba69bae49..888a09ee6f 100644
--- a/include/identity.php
+++ b/include/identity.php
@@ -237,6 +237,7 @@ function profile_sidebar($profile, $block = 0) {
 	if ($connect AND ($profile['network'] != NETWORK_DFRN) AND !isset($profile['remoteconnect']))
 		$connect = false;
 
+	$remoteconnect = NULL;
 	if (isset($profile['remoteconnect']))
 		$remoteconnect = $profile['remoteconnect'];
 
@@ -292,9 +293,9 @@ function profile_sidebar($profile, $block = 0) {
 	// check if profile is a forum
 	if((intval($profile['page-flags']) == PAGE_COMMUNITY)
 			|| (intval($profile['page-flags']) == PAGE_PRVGROUP)
-			|| (intval($profile['forum']))
-			|| (intval($profile['prv']))
-			|| (intval($profile['community'])))
+			|| (isset($profile['forum']) && intval($profile['forum']))
+			|| (isset($profile['prv']) && intval($profile['prv']))
+			|| (isset($profile['community']) && intval($profile['community'])))
 		$account_type = t('Forum');
 	else
 		$account_type = "";

From 76b042ddee262aa487839b1d47109a72444cfab2 Mon Sep 17 00:00:00 2001
From: Roland Haeder <roland@mxchange.org>
Date: Tue, 1 Mar 2016 14:42:55 +0100
Subject: [PATCH 141/273] More logging in case of errors + logged network type
 + added TODO (for ugly E_NOTICE).

Signed-off-by: Roland Haeder <roland@mxchange.org>
---
 mod/dfrn_request.php | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php
index 2741ad59b4..82886a6efa 100644
--- a/mod/dfrn_request.php
+++ b/mod/dfrn_request.php
@@ -42,8 +42,10 @@ function dfrn_request_init(&$a) {
 if(! function_exists('dfrn_request_post')) {
 function dfrn_request_post(&$a) {
 
-	if(($a->argc != 2) || (! count($a->profile)))
+	if(($a->argc != 2) || (! count($a->profile))) {
+		logger('Wrong count of argc or profiles: argc=' . $a->argc . ',profile()=' . count($a->profile));
 		return;
+	}
 
 
 	if(x($_POST, 'cancel')) {
@@ -461,7 +463,7 @@ function dfrn_request_post(&$a) {
 				$network = NETWORK_DFRN;
 		}
 
-		logger('dfrn_request: url: ' . $url);
+		logger('dfrn_request: url: ' . $url . ',network=' . $network, LOGGER_DEBUG);
 
 		if($network === NETWORK_DFRN) {
 			$ret = q("SELECT * FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `self` = 0 LIMIT 1",
@@ -825,6 +827,7 @@ function dfrn_request_content(&$a) {
 		else
 			$tpl = get_markup_template('auto_request.tpl');
 
+		// TODO This .= triggers an E_NOTICE, really needed?
 		$page_desc .= t("Please enter your 'Identity Address' from one of the following supported communications networks:");
 
 		// see if we are allowed to have NETWORK_MAIL2 contacts
@@ -850,6 +853,7 @@ function dfrn_request_content(&$a) {
 			get_server()
 		);
 
+		// TODO This .= triggers an E_NOTICE, really needed?
 		$o .= replace_macros($tpl,array(
 			'$header' => t('Friend/Connection Request'),
 			'$desc' => t('Examples: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, testuser@identi.ca'),

From 8616f0cc3526b0f0ca3d16800984e118c5d56d94 Mon Sep 17 00:00:00 2001
From: Roland Haeder <roland@mxchange.org>
Date: Tue, 1 Mar 2016 14:49:07 +0100
Subject: [PATCH 142/273] Don't miss to add exit() after header('Location:
 bla') as header() does *NOT* exit the script quickly enough. Always use an
 explicit exit() or you get real trouble.

Signed-off-by: Roland Haeder <roland@mxchange.org>
---
 index.php | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/index.php b/index.php
index e364389b2c..625c2d82dc 100644
--- a/index.php
+++ b/index.php
@@ -72,7 +72,8 @@ if(!$install) {
 		(intval(get_config('system','ssl_policy')) == SSL_POLICY_FULL) AND
 		(substr($a->get_baseurl(), 0, 8) == "https://")) {
 		header("HTTP/1.1 302 Moved Temporarily");
-		header("location: ".$a->get_baseurl()."/".$a->query_string);
+		header("Location: ".$a->get_baseurl()."/".$a->query_string);
+		exit();
 	}
 
 	require_once("include/session.php");

From 08abdfda684c6b9215109da6f999351f81c00ac3 Mon Sep 17 00:00:00 2001
From: Roland Haeder <roland@mxchange.org>
Date: Tue, 1 Mar 2016 14:49:56 +0100
Subject: [PATCH 143/273] <form> and <html> or <head> are not self-closing
 tags.

Signed-off-by: Roland Haeder <roland@mxchange.org>
---
 view/templates/dfrn_request.tpl | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/view/templates/dfrn_request.tpl b/view/templates/dfrn_request.tpl
index 3b96d3eefd..5225bd60b2 100644
--- a/view/templates/dfrn_request.tpl
+++ b/view/templates/dfrn_request.tpl
@@ -18,13 +18,13 @@
 {{/if}}
 
 {{if $request}}
-<form action="{{$request}}" method="post" />
+<form action="{{$request}}" method="post">
 {{else}}
-<form action="dfrn_request/{{$nickname}}" method="post" />
+<form action="dfrn_request/{{$nickname}}" method="post">
 {{/if}}
 
 {{if $photo}}
-<img src="{{$photo}}" alt="" id="dfrn-request-photo">
+<img src="{{$photo}}" alt="" id="dfrn-request-photo" />
 {{/if}}
 
 {{if $url}}<dl><dt>{{$url_label}}</dt><dd><a target="blank" href="{{$zrl}}">{{$url}}</a></dd></dl>{{/if}}

From 7d5166c9fefd03ec63807813e831017e6ad25382 Mon Sep 17 00:00:00 2001
From: Roland Haeder <roland@mxchange.org>
Date: Tue, 1 Mar 2016 18:28:06 +0100
Subject: [PATCH 144/273] Closed TODO: no .= needed here. #2392

Signed-off-by: Roland Haeder <roland@mxchange.org>
---
 mod/dfrn_request.php | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php
index 82886a6efa..5455996069 100644
--- a/mod/dfrn_request.php
+++ b/mod/dfrn_request.php
@@ -827,8 +827,7 @@ function dfrn_request_content(&$a) {
 		else
 			$tpl = get_markup_template('auto_request.tpl');
 
-		// TODO This .= triggers an E_NOTICE, really needed?
-		$page_desc .= t("Please enter your 'Identity Address' from one of the following supported communications networks:");
+		$page_desc = t("Please enter your 'Identity Address' from one of the following supported communications networks:");
 
 		// see if we are allowed to have NETWORK_MAIL2 contacts
 
@@ -853,8 +852,7 @@ function dfrn_request_content(&$a) {
 			get_server()
 		);
 
-		// TODO This .= triggers an E_NOTICE, really needed?
-		$o .= replace_macros($tpl,array(
+		$o = replace_macros($tpl,array(
 			'$header' => t('Friend/Connection Request'),
 			'$desc' => t('Examples: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, testuser@identi.ca'),
 			'$pls_answer' => t('Please answer the following:'),

From 009cadf63beada12c3e53f5d60a5542321a3f470 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 1 Mar 2016 19:10:35 +0100
Subject: [PATCH 145/273] Just another commit message :-)

---
 include/diaspora.php  | 6 +++---
 include/diaspora2.php | 8 +++++---
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 4ec7489ca4..9db9e6056e 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -146,9 +146,9 @@ function diaspora_dispatch($importer,$msg,$attempt=1) {
 		$ret = diaspora_participation($importer,$xmlbase->participation);
 	}
 	elseif($xmlbase->poll_participation) {
-		$tempfile = tempnam(get_temppath(), "diaspora-poll_participation");
-		file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_participation($importer,$xmlbase->participation);
+		//$tempfile = tempnam(get_temppath(), "diaspora-poll_participation");
+		//file_put_contents($tempfile, json_encode($data));
+		$ret = diaspora_participation($importer,$xmlbase->poll_participation);
 	}
 	else {
 		$tempfile = tempnam(get_temppath(), "diaspora-unknown");
diff --git a/include/diaspora2.php b/include/diaspora2.php
index a1297c5193..e8ed80ee80 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -131,7 +131,8 @@ class diaspora {
 				return self::import_request($importer, $fields);
 
 			case "reshare":
-				return self::import_reshare($importer, $fields);
+				return true;
+				//return self::import_reshare($importer, $fields);
 
 			case "retraction":
 				return self::import_retraction($importer, $fields);
@@ -676,6 +677,8 @@ class diaspora {
 	}
 
 	private function import_conversation($importer, $data) {
+		print_r($data);
+		die();
 /*
         $guid = notags(unxmlify($xml->guid));
         $subject = notags(unxmlify($xml->subject));
@@ -874,9 +877,8 @@ EOT;
 		if ($parent_type !== "Post")
 			return false;
 
-		// "positive" = "false" doesn't seem to be supported by Diaspora
+		// "positive" = "false" would be a Dislike - wich isn't currently supported by Diaspora
 		if ($positive === "false") {
-			logger("Received a like with positive set to 'false' - this shouldn't exist at all");
 			return false;
 		}
 

From ce5f6fae51ac6c246bb0371798994bef7e589d42 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 1 Mar 2016 19:14:45 +0100
Subject: [PATCH 146/273] Small bugfix: Fixes problen when version number
 contains linebreaks

---
 mod/admin.php | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/mod/admin.php b/mod/admin.php
index 7a16820c44..a98f464f81 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -283,14 +283,14 @@ function admin_page_federation(&$a) {
 		// get a total count for the platform, the name and version of the
 		// highest version and the protocol tpe
 		$c = q('SELECT count(*) AS total, platform, network, version FROM gserver
-			WHERE platform LIKE "%s" AND last_contact > last_failure
+			WHERE platform LIKE "%s" AND last_contact > last_failure AND `version` != ""
 			ORDER BY version ASC;', $p);
 		$total = $total + $c[0]['total'];
 
 		// what versions for that platform do we know at all?
 		// again only the active nodes
 		$v = q('SELECT count(*) AS total, version FROM gserver
-			WHERE last_contact > last_failure AND platform LIKE "%s" 
+			WHERE last_contact > last_failure AND platform LIKE "%s"  AND `version` != ""
 			GROUP BY version
 			ORDER BY version;', $p);
 
@@ -344,6 +344,9 @@ function admin_page_federation(&$a) {
 			$v = $newVv;
 		}
 
+		foreach ($v as $key => $vv)
+			$v[$key]["version"] = trim(strip_tags($vv["version"]));
+
 		// the 3rd array item is needed for the JavaScript graphs as JS does
 		// not like some characters in the names of variables...
 		$counts[$p]=array($c[0], $v, str_replace(array(' ','%'),'',$p), $colors[$p]);

From 411566f48b58135e6820b6557794806b077e5444 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 1 Mar 2016 19:17:01 +0100
Subject: [PATCH 147/273] API: Some small speed improvement when calling the
 home timeline.

---
 include/api.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/api.php b/include/api.php
index 55e39e3583..699b066d25 100644
--- a/include/api.php
+++ b/include/api.php
@@ -1691,13 +1691,13 @@
 			`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
 			`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
 			`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
-			FROM `item`, `contact`
+			FROM `item`  FORCE INDEX (`uid_id`), `contact`
 			WHERE `item`.`uid` = %d AND `verb` = '%s'
 			AND NOT (`item`.`author-link` IN ('https://%s', 'http://%s'))
-			AND `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
+			AND `item`.`visible` AND NOT `item`.`moderated` AND NOT `item`.`deleted`
 			AND `contact`.`id` = `item`.`contact-id`
-			AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
-			AND `item`.`parent` IN (SELECT `iid` from thread where uid = %d AND `mention` AND !`ignored`)
+			AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
+			AND `item`.`parent` IN (SELECT `iid` FROM `thread` WHERE `uid` = %d AND `mention` AND !`ignored`)
 			$sql_extra
 			AND `item`.`id`>%d
 			ORDER BY `item`.`id` DESC LIMIT %d ,%d ",

From f1dae26df8a9f46d683716b48b9b739f02824302 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 1 Mar 2016 23:21:56 +0100
Subject: [PATCH 148/273] Likes would now work with unlikes and with likes on
 comments.

---
 include/diaspora2.php | 48 +++++++++++++++++++++++--------------------
 1 file changed, 26 insertions(+), 22 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index e8ed80ee80..97d22b4b97 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -104,7 +104,8 @@ class diaspora {
 				//return self::import_comment($importer, $sender, $fields);
 
 			case "conversation":
-				return self::import_conversation($importer, $fields);
+				return true;
+				//return self::import_conversation($importer, $fields);
 
 			case "like":
 				return true;
@@ -138,8 +139,8 @@ class diaspora {
 				return self::import_retraction($importer, $fields);
 
 			case "status_message":
-				return true;
-				//return self::import_status_message($importer, $fields, $msg, $data2);
+				//return true;
+				return self::import_status_message($importer, $fields);
 
 			default:
 				logger("Unknown message type ".$type);
@@ -246,7 +247,7 @@ class diaspora {
 			}
 
 		// Only some message types have signatures. So we quit here for the other types.
-		if (!in_array($type, array("comment", "conversation", "message", "like")))
+		if (!in_array($type, array("comment", "message", "like")))
 			return true;
 
 		// No author_signature? This is a must, so we quit.
@@ -691,7 +692,7 @@ class diaspora {
         $messages = $xml->message;
 
         if(! count($messages)) {
-                logger('diaspora_conversation: empty conversation');
+                logger('empty conversation');
                 return;
         }
 
@@ -874,14 +875,10 @@ EOT;
 		$author = notags(unxmlify($data->author));
 
 		// likes on comments aren't supported by Diaspora - only on posts
-		if ($parent_type !== "Post")
+		// But maybe this will be supported in the future, so we will accept it.
+		if (!in_array($parent_type, array("Post", "Comment")))
 			return false;
 
-		// "positive" = "false" would be a Dislike - wich isn't currently supported by Diaspora
-		if ($positive === "false") {
-			return false;
-		}
-
 		$contact = self::get_allowed_contact_by_handle($importer, $sender, true);
 		if (!$contact)
 			return false;
@@ -902,6 +899,13 @@ EOT;
 		// Fetch the contact id - if we know this contact
 		$author_contact = self::get_author_contact_by_url($contact, $person, $importer["uid"]);
 
+		// "positive" = "false" would be a Dislike - wich isn't currently supported by Diaspora
+		// We would accept this anyhow.
+		if ($positive === "true")
+			$verb = ACTIVITY_LIKE;
+		else
+			$verb = ACTIVITY_DISLIKE;
+
 		$datarray = array();
 
 		$datarray["uid"] = $importer["uid"];
@@ -920,7 +924,7 @@ EOT;
 		$datarray["uri"] = $author.":".$guid;
 
 		$datarray["type"] = "activity";
-		$datarray["verb"] = ACTIVITY_LIKE;
+		$datarray["verb"] = $verb;
 		$datarray["gravity"] = GRAVITY_LIKE;
 		$datarray["parent-uri"] = $parent_item["uri"];
 
@@ -1429,18 +1433,18 @@ print_r($data);
 		$created_at = notags(unxmlify($data->created_at));
 		$provider_display_name = notags(unxmlify($data->provider_display_name));
 
+		/// @todo enable support for polls
+		if ($data->poll) {
+			foreach ($data->poll AS $poll)
+				print_r($poll);
+			die("poll!\n");
+		}
 		$contact = self::get_allowed_contact_by_handle($importer, $author, false);
 		if (!$contact)
 			return false;
 
-		if (self::message_exists($importer["uid"], $guid))
-			return false;
-
-		/// @todo enable support for polls
-		// if ($data->poll) {
-		//	print_r($data->poll);
-		//	die("poll!\n");
-		// }
+		//if (self::message_exists($importer["uid"], $guid))
+		//	return false;
 
 		$address = array();
 		if ($data->location)
@@ -1450,8 +1454,8 @@ print_r($data);
 		$body = diaspora2bb($raw_message);
 
 		if ($data->photo)
-			for ($i = 0; $i < count($data->photo); $i++)
-				$body = "[img]".$data->photo[$i]->remote_photo_path.$data->photo[$i]->remote_photo_name."[/img]\n".$body;
+			foreach ($data->photo AS $photo)
+				$body = "[img]".$photo->remote_photo_path.$photo->remote_photo_name."[/img]\n".$body;
 
 		$datarray = array();
 

From 66919761ab9ab60f1e6d3cac0810a6846e1e3a47 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 2 Mar 2016 23:28:20 +0100
Subject: [PATCH 149/273] Some work at the retractions.

---
 include/diaspora.php  |   8 +-
 include/diaspora2.php | 381 +++++++++++++++++++++++++-----------------
 2 files changed, 230 insertions(+), 159 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 9db9e6056e..0e0a860311 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -116,13 +116,13 @@ function diaspora_dispatch($importer,$msg,$attempt=1) {
 		$ret = diaspora_retraction($importer,$xmlbase->retraction,$msg);
 	}
 	elseif($xmlbase->signed_retraction) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-signed_retraction");
-		//file_put_contents($tempfile, json_encode($data));
+		$tempfile = tempnam(get_temppath(), "diaspora-signed_retraction");
+		file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_signed_retraction($importer,$xmlbase->signed_retraction,$msg);
 	}
 	elseif($xmlbase->relayable_retraction) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-relayable_retraction");
-		//file_put_contents($tempfile, json_encode($data));
+		$tempfile = tempnam(get_temppath(), "diaspora-relayable_retraction");
+		file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_signed_retraction($importer,$xmlbase->relayable_retraction,$msg);
 	}
 	elseif($xmlbase->photo) {
diff --git a/include/diaspora2.php b/include/diaspora2.php
index 97d22b4b97..baf117b102 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -95,11 +95,11 @@ class diaspora {
 		$type = $fields->getName();
 
 		switch ($type) {
-			case "account_deletion":
+			case "account_deletion": // Done
 				return true;
 				//return self::import_account_deletion($importer, $fields);
 
-			case "comment":
+			case "comment": // Done
 				return true;
 				//return self::import_comment($importer, $sender, $fields);
 
@@ -107,40 +107,40 @@ class diaspora {
 				return true;
 				//return self::import_conversation($importer, $fields);
 
-			case "like":
+			case "like": // Done
 				return true;
 				//return self::import_like($importer, $sender, $fields);
 
-			case "message":
+			case "message": // Done
 				return true;
 				//return self::import_message($importer, $fields);
 
 			case "participation": // Not implemented
 				return self::import_participation($importer, $fields);
 
-			case "photo":
+			case "photo": // Not needed
 				return self::import_photo($importer, $fields);
 
 			case "poll_participation": // Not implemented
 				return self::import_poll_participation($importer, $fields);
 
-			case "profile":
+			case "profile": // Done
 				return true;
 				//return self::import_profile($importer, $fields);
 
 			case "request":
 				return self::import_request($importer, $fields);
 
-			case "reshare":
+			case "reshare": // Done
 				return true;
 				//return self::import_reshare($importer, $fields);
 
 			case "retraction":
 				return self::import_retraction($importer, $fields);
 
-			case "status_message":
-				//return true;
-				return self::import_status_message($importer, $fields);
+			case "status_message": // Done
+				return true;
+				//return self::import_status_message($importer, $fields);
 
 			default:
 				logger("Unknown message type ".$type);
@@ -567,25 +567,25 @@ class diaspora {
 	}
 
 	private function plink($addr, $guid) {
-	        $r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr));
+		$r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr));
 
-	        // Fallback
-	        if (!$r)
-	                return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
+		// Fallback
+		if (!$r)
+			return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
 
-	        // Friendica contacts are often detected as Diaspora contacts in the "fcontact" table
-	        // So we try another way as well.
-	        $s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"])));
-	        if ($s)
-	                $r[0]["network"] = $s[0]["network"];
+		// Friendica contacts are often detected as Diaspora contacts in the "fcontact" table
+		// So we try another way as well.
+		$s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"])));
+		if ($s)
+			$r[0]["network"] = $s[0]["network"];
 
-	        if ($r[0]["network"] == NETWORK_DFRN)
-	                return(str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/"));
+		if ($r[0]["network"] == NETWORK_DFRN)
+			return(str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/"));
 
-	        if (self::is_redmatrix($r[0]["url"]))
-	                return $r[0]["url"]."/?f=&mid=".$guid;
+		if (self::is_redmatrix($r[0]["url"]))
+			return $r[0]["url"]."/?f=&mid=".$guid;
 
-	        return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
+		return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
 	}
 
 	private function import_account_deletion($importer, $data) {
@@ -681,158 +681,158 @@ class diaspora {
 		print_r($data);
 		die();
 /*
-        $guid = notags(unxmlify($xml->guid));
-        $subject = notags(unxmlify($xml->subject));
-        $diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-        $participant_handles = notags(unxmlify($xml->participant_handles));
-        $created_at = datetime_convert('UTC','UTC',notags(unxmlify($xml->created_at)));
+	$guid = notags(unxmlify($xml->guid));
+	$subject = notags(unxmlify($xml->subject));
+	$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
+	$participant_handles = notags(unxmlify($xml->participant_handles));
+	$created_at = datetime_convert('UTC','UTC',notags(unxmlify($xml->created_at)));
 
-        $parent_uri = $diaspora_handle . ':' . $guid;
+	$parent_uri = $diaspora_handle . ':' . $guid;
 
-        $messages = $xml->message;
+	$messages = $xml->message;
 
-        if(! count($messages)) {
-                logger('empty conversation');
-                return;
-        }
+	if(! count($messages)) {
+		logger('empty conversation');
+		return;
+	}
 
 		$contact = self::get_allowed_contact_by_handle($importer, $sender, true)
 		if (!$contact)
 			return false;
 
-        $conversation = null;
+	$conversation = null;
 
-        $c = q("select * from conv where uid = %d and guid = '%s' limit 1",
-                intval($importer['uid']),
-                dbesc($guid)
-        );
-        if(count($c))
-                $conversation = $c[0];
-        else {
-                $r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ",
-                        intval($importer['uid']),
-                        dbesc($guid),
-                        dbesc($diaspora_handle),
-                        dbesc(datetime_convert('UTC','UTC',$created_at)),
-                        dbesc(datetime_convert()),
-                        dbesc($subject),
-                        dbesc($participant_handles)
-                );
-                if($r)
-                        $c = q("select * from conv where uid = %d and guid = '%s' limit 1",
-                intval($importer['uid']),
-            dbesc($guid)
-        );
-            if(count($c))
-            $conversation = $c[0];
-        }
-        if(! $conversation) {
-                logger('diaspora_conversation: unable to create conversation.');
-                return;
-        }
+	$c = q("select * from conv where uid = %d and guid = '%s' limit 1",
+		intval($importer["uid"]),
+		dbesc($guid)
+	);
+	if(count($c))
+		$conversation = $c[0];
+	else {
+		$r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ",
+			intval($importer["uid"]),
+			dbesc($guid),
+			dbesc($diaspora_handle),
+			dbesc(datetime_convert('UTC','UTC',$created_at)),
+			dbesc(datetime_convert()),
+			dbesc($subject),
+			dbesc($participant_handles)
+		);
+		if($r)
+			$c = q("select * from conv where uid = %d and guid = '%s' limit 1",
+		intval($importer["uid"]),
+	    dbesc($guid)
+	);
+	    if(count($c))
+	    $conversation = $c[0];
+	}
+	if(! $conversation) {
+		logger('diaspora_conversation: unable to create conversation.');
+		return;
+	}
 
-        foreach($messages as $mesg) {
+	foreach($messages as $mesg) {
 
-                $reply = 0;
+		$reply = 0;
 
-                $msg_guid = notags(unxmlify($mesg->guid));
-                $msg_parent_guid = notags(unxmlify($mesg->parent_guid));
-                $msg_parent_author_signature = notags(unxmlify($mesg->parent_author_signature));
-                $msg_author_signature = notags(unxmlify($mesg->author_signature));
-                $msg_text = unxmlify($mesg->text);
-                $msg_created_at = datetime_convert('UTC','UTC',notags(unxmlify($mesg->created_at)));
-                $msg_diaspora_handle = notags(unxmlify($mesg->diaspora_handle));
-                $msg_conversation_guid = notags(unxmlify($mesg->conversation_guid));
-                if($msg_conversation_guid != $guid) {
-                        logger('diaspora_conversation: message conversation guid does not belong to the current conversation. ' . $xml);
-                        continue;
-                }
+		$msg_guid = notags(unxmlify($mesg->guid));
+		$msg_parent_guid = notags(unxmlify($mesg->parent_guid));
+		$msg_parent_author_signature = notags(unxmlify($mesg->parent_author_signature));
+		$msg_author_signature = notags(unxmlify($mesg->author_signature));
+		$msg_text = unxmlify($mesg->text);
+		$msg_created_at = datetime_convert('UTC','UTC',notags(unxmlify($mesg->created_at)));
+		$msg_diaspora_handle = notags(unxmlify($mesg->diaspora_handle));
+		$msg_conversation_guid = notags(unxmlify($mesg->conversation_guid));
+		if($msg_conversation_guid != $guid) {
+			logger('diaspora_conversation: message conversation guid does not belong to the current conversation. ' . $xml);
+			continue;
+		}
 
-                $body = diaspora2bb($msg_text);
-                $message_id = $msg_diaspora_handle . ':' . $msg_guid;
+		$body = diaspora2bb($msg_text);
+		$message_id = $msg_diaspora_handle . ':' . $msg_guid;
 
-                $author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
+		$author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
 
-                $author_signature = base64_decode($msg_author_signature);
+		$author_signature = base64_decode($msg_author_signature);
 
-                if(strcasecmp($msg_diaspora_handle,$msg['author']) == 0) {
-                        $person = $contact;
-                        $key = $msg['key'];
-                }
-                else {
-                        $person = find_diaspora_person_by_handle($msg_diaspora_handle); 
+		if(strcasecmp($msg_diaspora_handle,$msg["author"]) == 0) {
+			$person = $contact;
+			$key = $msg["key"];
+		}
+		else {
+			$person = find_diaspora_person_by_handle($msg_diaspora_handle); 
 
-                        if(is_array($person) && x($person,'pubkey'))
-                                $key = $person['pubkey'];
-                        else {
-                                logger('diaspora_conversation: unable to find author details');
-                                continue;
-                        }
-                }
+			if(is_array($person) && x($person,'pubkey'))
+				$key = $person["pubkey"];
+			else {
+				logger('diaspora_conversation: unable to find author details');
+				continue;
+			}
+		}
 
-                if(! rsa_verify($author_signed_data,$author_signature,$key,'sha256')) {
-                        logger('diaspora_conversation: verification failed.');
-                        continue;
-                }
+		if(! rsa_verify($author_signed_data,$author_signature,$key,'sha256')) {
+			logger('diaspora_conversation: verification failed.');
+			continue;
+		}
 
-                if($msg_parent_author_signature) {
-                        $owner_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
+		if($msg_parent_author_signature) {
+			$owner_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
 
-                        $parent_author_signature = base64_decode($msg_parent_author_signature);
+			$parent_author_signature = base64_decode($msg_parent_author_signature);
 
-                        $key = $msg['key'];
+			$key = $msg["key"];
 
-                        if(! rsa_verify($owner_signed_data,$parent_author_signature,$key,'sha256')) {
-                                logger('diaspora_conversation: owner verification failed.');
-                                continue;
-                        }
-                }
+			if(! rsa_verify($owner_signed_data,$parent_author_signature,$key,'sha256')) {
+				logger('diaspora_conversation: owner verification failed.');
+				continue;
+			}
+		}
 
-                $r = q("select id from mail where `uri` = '%s' limit 1",
-                        dbesc($message_id)
-                );
-                if(count($r)) {
-                        logger('diaspora_conversation: duplicate message already delivered.', LOGGER_DEBUG);
-                        continue;
-                }
+		$r = q("select id from mail where `uri` = '%s' limit 1",
+			dbesc($message_id)
+		);
+		if(count($r)) {
+			logger('diaspora_conversation: duplicate message already delivered.', LOGGER_DEBUG);
+			continue;
+		}
 
-                q("insert into mail ( `uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`) values ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
-                        intval($importer['uid']),
-                        dbesc($msg_guid),
-                        intval($conversation['id']),
-                        dbesc($person['name']),
-                        dbesc($person['photo']),
-                        dbesc($person['url']),
-                        intval($contact['id']),
-                        dbesc($subject),
-                        dbesc($body),
-                        0,
-                        0,
-                        dbesc($message_id),
-                        dbesc($parent_uri),
-                        dbesc($msg_created_at)
-                );
+		q("insert into mail ( `uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`) values ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
+			intval($importer["uid"]),
+			dbesc($msg_guid),
+			intval($conversation["id"]),
+			dbesc($person["name"]),
+			dbesc($person["photo"]),
+			dbesc($person["url"]),
+			intval($contact["id"]),
+			dbesc($subject),
+			dbesc($body),
+			0,
+			0,
+			dbesc($message_id),
+			dbesc($parent_uri),
+			dbesc($msg_created_at)
+		);
 
-                q("update conv set updated = '%s' where id = %d",
-                        dbesc(datetime_convert()),
-                        intval($conversation['id'])
-                );
+		q("update conv set updated = '%s' where id = %d",
+			dbesc(datetime_convert()),
+			intval($conversation["id"])
+		);
 
-                notification(array(
-                        'type' => NOTIFY_MAIL,
-                        'notify_flags' => $importer['notify-flags'],
-                        'language' => $importer['language'],
-                        'to_name' => $importer['username'],
-                        'to_email' => $importer['email'],
-                        'uid' =>$importer['uid'],
-                        'item' => array('subject' => $subject, 'body' => $body),
-                        'source_name' => $person['name'],
-                        'source_link' => $person['url'],
-                        'source_photo' => $person['thumb'],
-                        'verb' => ACTIVITY_POST,
-                        'otype' => 'mail'
-                ));
-        }
+		notification(array(
+			'type' => NOTIFY_MAIL,
+			'notify_flags' => $importer["notify-flags"],
+			'language' => $importer["language"],
+			'to_name' => $importer["username"],
+			'to_email' => $importer["email"],
+			'uid' =>$importer["uid"],
+			'item' => array('subject' => $subject, 'body' => $body),
+			'source_name' => $person["name"],
+			'source_link' => $person["url"],
+			'source_photo' => $person["thumb"],
+			'verb' => ACTIVITY_POST,
+			'otype' => 'mail'
+		));
+	}
 */
 		return true;
 	}
@@ -1420,7 +1420,78 @@ print_r($data);
 		return $message_id;
 	}
 
+	private function item_retraction($importer, $contact, $data) {
+		$target_guid = notags(unxmlify($data->target_guid));
+
+		$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),
+			intval($importer["uid"])
+		);
+		if (!$r)
+			return false;
+
+		// Only delete it if the author really fits
+		if (!link_compare($r[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
+		q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', `body` = '' , `title` = '' WHERE `id` = %d",
+			dbesc(datetime_convert()),
+			dbesc(datetime_convert()),
+			intval($r[0]["id"])
+		);
+		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"]) {
+
+	                        // 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))
+	                        );
+
+				// 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"]);
+			}
+		}
+	}
+
 	private function import_retraction($importer, $data) {
+		$target_type = notags(unxmlify($data->target_type));
+		$author = notags(unxmlify($data->author));
+
+		$contact = self::get_contact_by_handle($importer["uid"], $author);
+		if (!$contact) {
+			logger("cannot find contact for author: ".$author);
+			return false;
+		}
+
+		switch ($target_type) {
+			case "Comment": case "Like": case "StatusMessage":
+				self::item_retraction($importer, $contact, $data);
+				break;
+
+			case "Person":
+				contact_remove($contact["id"]);
+				return true;
+
+			default:
+				logger("Unknown target type ".$target_type);
+		}
 		return true;
 	}
 
@@ -1434,11 +1505,11 @@ print_r($data);
 		$provider_display_name = notags(unxmlify($data->provider_display_name));
 
 		/// @todo enable support for polls
-		if ($data->poll) {
-			foreach ($data->poll AS $poll)
-				print_r($poll);
-			die("poll!\n");
-		}
+		//if ($data->poll) {
+		//	foreach ($data->poll AS $poll)
+		//		print_r($poll);
+		//	die("poll!\n");
+		//}
 		$contact = self::get_allowed_contact_by_handle($importer, $author, false);
 		if (!$contact)
 			return false;

From 5adecf5b50e11fb6016cc089426f74b8f930ed0b Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 2 Mar 2016 23:39:50 +0100
Subject: [PATCH 150/273] Some beautification

---
 include/diaspora2.php | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index baf117b102..4d0e4c2cb8 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -1524,16 +1524,16 @@ print_r($data);
 
 		$body = diaspora2bb($raw_message);
 
-		if ($data->photo)
+		$datarray = array();
+
+		if ($data->photo) {
 			foreach ($data->photo AS $photo)
 				$body = "[img]".$photo->remote_photo_path.$photo->remote_photo_name."[/img]\n".$body;
 
-		$datarray = array();
-
-		if($data->photo->remote_photo_path AND $data->photo->remote_photo_name)
 			$datarray["object-type"] = ACTIVITY_OBJ_PHOTO;
-		else {
+		} else {
 			$datarray["object-type"] = ACTIVITY_OBJ_NOTE;
+
 			// Add OEmbed and other information to the body
 			if (!self::is_redmatrix($contact["url"]))
 				$body = add_page_info_to_body($body, false, true);
@@ -1541,6 +1541,7 @@ print_r($data);
 
 		$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) {

From 2edf4548dca3ff2df4765be957766af91c4930d2 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 3 Mar 2016 23:34:17 +0100
Subject: [PATCH 151/273] Retractions could work now.

---
 include/diaspora2.php | 170 ++++++++++++++++++++++++++----------------
 1 file changed, 105 insertions(+), 65 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 4d0e4c2cb8..59a5c372db 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -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);
 

From d5c1ce490b8fb0cd5abfad4db3655016954217d5 Mon Sep 17 00:00:00 2001
From: Roland Haeder <roland@mxchange.org>
Date: Fri, 4 Mar 2016 22:38:18 +0100
Subject: [PATCH 152/273] No processing if error or empty array

Signed-off-by: Roland Haeder <roland@mxchange.org>
---
 include/poller.php | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/poller.php b/include/poller.php
index 90e94ede9e..755862eb6b 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -205,6 +205,12 @@ function poller_max_connections_reached() {
  */
 function poller_kill_stale_workers() {
 	$r = q("SELECT `pid`, `executed` FROM `workerqueue` WHERE `executed` != '0000-00-00 00:00:00'");
+
+	if (!is_array($r) || count($r) == 0) {
+		// No processing here needed
+		return;
+	}
+
 	foreach($r AS $pid)
 		if (!posix_kill($pid["pid"], 0))
 			q("UPDATE `workerqueue` SET `executed` = '0000-00-00 00:00:00', `pid` = 0 WHERE `pid` = %d",

From ef3620c191add50b212fc5479abc0a6d1f04db6c Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 4 Mar 2016 23:28:43 +0100
Subject: [PATCH 153/273] Conversations should work now too.

---
 include/diaspora2.php | 282 +++++++++++++++++++++---------------------
 1 file changed, 141 insertions(+), 141 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 59a5c372db..b834e3deb9 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -22,7 +22,7 @@ class xml {
 
 		if (!is_object($xml)) {
 			foreach($array as $key => $value) {
-				$root = new SimpleXMLElement('<'.$key.'/>');
+				$root = new SimpleXMLElement("<".$key."/>");
 				array_to_xml($value, $root);
 
 				$dom = dom_import_simplexml($root)->ownerDocument;
@@ -82,7 +82,7 @@ class diaspora {
 			dbesc(NETWORK_DIASPORA),
 			dbesc($msg["author"])
 		);
-		if(count($r)) {
+		if($r) {
 			foreach($r as $rr) {
 				logger("delivering to: ".$rr["username"]);
 				self::dispatch($rr,$msg);
@@ -125,7 +125,7 @@ class diaspora {
 
 			case "conversation":
 				//return true;
-				return self::import_conversation($importer, $fields);
+				return self::import_conversation($importer, $msg, $fields);
 
 			case "like": // Done
 				return true;
@@ -320,7 +320,7 @@ class diaspora {
 			dbesc(NETWORK_DIASPORA),
 			dbesc($handle)
 		);
-		if (count($r)) {
+		if ($r) {
 			$person = $r[0];
 			logger("In cache ".print_r($r,true), LOGGER_DEBUG);
 
@@ -336,7 +336,7 @@ class diaspora {
 
 			// Note that Friendica contacts will return a "Diaspora person"
 			// if Diaspora connectivity is enabled on their server
-			if (count($r) AND ($r["network"] === NETWORK_DIASPORA)) {
+			if ($r AND ($r["network"] === NETWORK_DIASPORA)) {
 				self::add_fcontact($r, $update);
 				$person = $r;
 			}
@@ -415,17 +415,17 @@ class diaspora {
 			dbesc($handle)
 		);
 
-		if ($r AND count($r))
+		if ($r)
 			return $r[0];
 
 		$handle_parts = explode("@", $handle);
-		$nurl_sql = '%%://' . $handle_parts[1] . '%%/profile/' . $handle_parts[0];
+		$nurl_sql = "%%://".$handle_parts[1]."%%/profile/".$handle_parts[0];
 		$r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` LIKE '%s' LIMIT 1",
 			dbesc(NETWORK_DFRN),
 			intval($uid),
 			dbesc($nurl_sql)
 		);
-		if($r AND count($r))
+		if($r)
 			return $r[0];
 
 		return false;
@@ -481,7 +481,7 @@ class diaspora {
 			dbesc($guid)
 		);
 
-		if(count($r)) {
+		if($r) {
 			logger("message ".$guid." already exists for user ".$uid);
 			return false;
 		}
@@ -566,7 +566,7 @@ class diaspora {
 			FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
 			intval($uid), dbesc($guid));
 
-		if(!count($r)) {
+		if(!$r) {
 			$result = self::store_by_guid($guid, $contact["url"], $uid);
 
 			if (!$result) {
@@ -585,7 +585,7 @@ class diaspora {
 			}
 		}
 
-		if (!count($r)) {
+		if (!$r) {
 			logger("parent item not found: parent: ".$guid." item: ".$guid);
 			return false;
 		} else
@@ -722,62 +722,10 @@ class diaspora {
 		return $message_id;
 	}
 
-	private function import_conversation($importer, $data) {
-		// @todo
-		print_r($data);
-		die();
-/*
-	$guid = notags(unxmlify($xml->guid));
-	$subject = notags(unxmlify($xml->subject));
-	$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-	$participant_handles = notags(unxmlify($xml->participant_handles));
-	$created_at = datetime_convert('UTC','UTC',notags(unxmlify($xml->created_at)));
-
-	$parent_uri = $diaspora_handle . ':' . $guid;
-
-	$messages = $xml->message;
-
-	if(! count($messages)) {
-		logger('empty conversation');
-		return;
-	}
-
-		$contact = self::get_allowed_contact_by_handle($importer, $sender, true)
-		if (!$contact)
-			return false;
-
-	$conversation = null;
-
-	$c = q("select * from conv where uid = %d and guid = '%s' limit 1",
-		intval($importer["uid"]),
-		dbesc($guid)
-	);
-	if(count($c))
-		$conversation = $c[0];
-	else {
-		$r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ",
-			intval($importer["uid"]),
-			dbesc($guid),
-			dbesc($diaspora_handle),
-			dbesc(datetime_convert('UTC','UTC',$created_at)),
-			dbesc(datetime_convert()),
-			dbesc($subject),
-			dbesc($participant_handles)
-		);
-		if($r)
-			$c = q("select * from conv where uid = %d and guid = '%s' limit 1",
-		intval($importer["uid"]),
-	    dbesc($guid)
-	);
-	    if(count($c))
-	    $conversation = $c[0];
-	}
-	if(! $conversation) {
-		logger('diaspora_conversation: unable to create conversation.');
-		return;
-	}
-
-	foreach($messages as $mesg) {
+	private function import_conversation_message($importer, $contact, $data, $msg, $mesg) {
+		$guid = notags(unxmlify($data->guid));
+		$subject = notags(unxmlify($data->subject));
+		$author = notags(unxmlify($data->author));
 
 		$reply = 0;
 
@@ -786,63 +734,64 @@ class diaspora {
 		$msg_parent_author_signature = notags(unxmlify($mesg->parent_author_signature));
 		$msg_author_signature = notags(unxmlify($mesg->author_signature));
 		$msg_text = unxmlify($mesg->text);
-		$msg_created_at = datetime_convert('UTC','UTC',notags(unxmlify($mesg->created_at)));
-		$msg_diaspora_handle = notags(unxmlify($mesg->diaspora_handle));
+		$msg_created_at = datetime_convert("UTC", "UTC", notags(unxmlify($mesg->created_at)));
+		$msg_author = notags(unxmlify($mesg->diaspora_handle));
 		$msg_conversation_guid = notags(unxmlify($mesg->conversation_guid));
+
 		if($msg_conversation_guid != $guid) {
-			logger('diaspora_conversation: message conversation guid does not belong to the current conversation. ' . $xml);
-			continue;
+			logger("message conversation guid does not belong to the current conversation.");
+			return false;
 		}
 
 		$body = diaspora2bb($msg_text);
-		$message_id = $msg_diaspora_handle . ':' . $msg_guid;
+		$message_uri = $msg_author.":".$msg_guid;
 
-		$author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
+		$author_signed_data = $msg_guid.";".$msg_parent_guid.";".$msg_text.";".unxmlify($mesg->created_at).";".$msg_author.";".$msg_conversation_guid;
 
 		$author_signature = base64_decode($msg_author_signature);
 
-		if(strcasecmp($msg_diaspora_handle,$msg["author"]) == 0) {
+		if(strcasecmp($msg_author,$msg["author"]) == 0) {
 			$person = $contact;
 			$key = $msg["key"];
-		}
-		else {
-			$person = find_diaspora_person_by_handle($msg_diaspora_handle); 
+		} else {
+			$person = self::get_person_by_handle($msg_author);
 
-			if(is_array($person) && x($person,'pubkey'))
+			if (is_array($person) && x($person, "pubkey"))
 				$key = $person["pubkey"];
 			else {
-				logger('diaspora_conversation: unable to find author details');
-				continue;
+				logger("unable to find author details");
+					return false;
 			}
 		}
 
-		if(! rsa_verify($author_signed_data,$author_signature,$key,'sha256')) {
-			logger('diaspora_conversation: verification failed.');
-			continue;
+		if (!rsa_verify($author_signed_data, $author_signature, $key, "sha256")) {
+			logger("verification failed.");
+			return false;
 		}
 
 		if($msg_parent_author_signature) {
-			$owner_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
+			$owner_signed_data = $msg_guid.";".$msg_parent_guid.";".$msg_text.";".unxmlify($mesg->created_at).";".$msg_author.";".$msg_conversation_guid;
 
 			$parent_author_signature = base64_decode($msg_parent_author_signature);
 
 			$key = $msg["key"];
 
-			if(! rsa_verify($owner_signed_data,$parent_author_signature,$key,'sha256')) {
-				logger('diaspora_conversation: owner verification failed.');
-				continue;
+			if (!rsa_verify($owner_signed_data, $parent_author_signature, $key, "sha256")) {
+				logger("owner verification failed.");
+				return false;
 			}
 		}
 
-		$r = q("select id from mail where `uri` = '%s' limit 1",
-			dbesc($message_id)
+		$r = q("SELECT `id` FROM `mail` WHERE `uri` = '%s' LIMIT 1",
+			dbesc($message_uri)
 		);
-		if(count($r)) {
-			logger('diaspora_conversation: duplicate message already delivered.', LOGGER_DEBUG);
-			continue;
+		if($r) {
+			logger("duplicate message already delivered.", LOGGER_DEBUG);
+			return false;
 		}
 
-		q("insert into mail ( `uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`) values ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
+		q("INSERT INTO `mail` (`uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`)
+			VALUES (%d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
 			intval($importer["uid"]),
 			dbesc($msg_guid),
 			intval($conversation["id"]),
@@ -854,32 +803,86 @@ class diaspora {
 			dbesc($body),
 			0,
 			0,
-			dbesc($message_id),
-			dbesc($parent_uri),
+			dbesc($message_uri),
+			dbesc($author.":".$guid),
 			dbesc($msg_created_at)
 		);
 
-		q("update conv set updated = '%s' where id = %d",
+		q("UPDATE `conv` SET `updated` = '%s' WHERE `id` = %d",
 			dbesc(datetime_convert()),
 			intval($conversation["id"])
 		);
 
 		notification(array(
-			'type' => NOTIFY_MAIL,
-			'notify_flags' => $importer["notify-flags"],
-			'language' => $importer["language"],
-			'to_name' => $importer["username"],
-			'to_email' => $importer["email"],
-			'uid' =>$importer["uid"],
-			'item' => array('subject' => $subject, 'body' => $body),
-			'source_name' => $person["name"],
-			'source_link' => $person["url"],
-			'source_photo' => $person["thumb"],
-			'verb' => ACTIVITY_POST,
-			'otype' => 'mail'
+			"type" => NOTIFY_MAIL,
+			"notify_flags" => $importer["notify-flags"],
+			"language" => $importer["language"],
+			"to_name" => $importer["username"],
+			"to_email" => $importer["email"],
+			"uid" =>$importer["uid"],
+			"item" => array("subject" => $subject, "body" => $body),
+			"source_name" => $person["name"],
+			"source_link" => $person["url"],
+			"source_photo" => $person["thumb"],
+			"verb" => ACTIVITY_POST,
+			"otype" => "mail"
 		));
 	}
-*/
+
+	private function import_conversation($importer, $msg, $data) {
+		$guid = notags(unxmlify($data->guid));
+		$subject = notags(unxmlify($data->subject));
+		$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
+		$author = notags(unxmlify($data->author));
+		$participants = notags(unxmlify($data->participants));
+
+		$messages = $data->message;
+
+		if (!count($messages)) {
+			logger("empty conversation");
+			return false;
+		}
+
+		$contact = self::get_allowed_contact_by_handle($importer, $msg["author"], true);
+		if (!$contact)
+			return false;
+
+		$conversation = null;
+
+		$c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($importer["uid"]),
+			dbesc($guid)
+		);
+		if($c)
+			$conversation = $c[0];
+		else {
+			$r = q("INSERT INTO `conv` (`uid`, `guid`, `creator`, `created`, `updated`, `subject`, `recips`)
+				VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s')",
+				intval($importer["uid"]),
+				dbesc($guid),
+				dbesc($author),
+				dbesc(datetime_convert("UTC", "UTC", $created_at)),
+				dbesc(datetime_convert()),
+				dbesc($subject),
+				dbesc($participants)
+			);
+			if($r)
+				$c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+					intval($importer["uid"]),
+					dbesc($guid)
+				);
+
+			if($c)
+				$conversation = $c[0];
+		}
+		if (!$conversation) {
+			logger("unable to create conversation.");
+			return;
+		}
+
+		foreach($messages as $mesg)
+			self::import_conversation_message($importer, $contact, $data, $msg, $mesg);
+
 		return true;
 	}
 
@@ -1007,8 +1010,6 @@ EOT;
 		$author = notags(unxmlify($data->author));
 		$conversation_guid = notags(unxmlify($data->conversation_guid));
 
-		$parent_uri = $author.":".$parent_guid;
-
 		$contact = self::get_allowed_contact_by_handle($importer, $author, true);
 		if (!$contact)
 			return false;
@@ -1019,7 +1020,7 @@ EOT;
 			intval($importer["uid"]),
 			dbesc($conversation_guid)
 		);
-		if(count($c))
+		if($c)
 			$conversation = $c[0];
 		else {
 			logger("conversation not available.");
@@ -1029,7 +1030,7 @@ EOT;
 		$reply = 0;
 
 		$body = diaspora2bb($text);
-		$message_id = $author.":".$guid;
+		$message_uri = $author.":".$guid;
 
 		$person = self::get_person_by_handle($author);
 		if (!$person) {
@@ -1038,10 +1039,10 @@ EOT;
 		}
 
 		$r = q("SELECT `id` FROM `mail` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-			dbesc($message_id),
+			dbesc($message_uri),
 			intval($importer["uid"])
 		);
-		if(count($r)) {
+		if($r) {
 			logger("duplicate message already delivered.", LOGGER_DEBUG);
 			return false;
 		}
@@ -1059,8 +1060,8 @@ EOT;
 			dbesc($body),
 			0,
 			1,
-			dbesc($message_id),
-			dbesc($parent_uri),
+			dbesc($message_uri),
+			dbesc($author.":".$parent_guid),
 			dbesc($created_at)
 		);
 
@@ -1174,8 +1175,8 @@ EOT;
 		// @todo
 		print_r($data);
 /*
-	$author = unxmlify($xml->author);
-	$recipient = unxmlify($xml->recipient);
+	$author = unxmlify($data->author);
+	$recipient = unxmlify($data->recipient);
 
 	if (!$author || !$recipient)
 		return;
@@ -1200,7 +1201,7 @@ EOT;
 			intval($importer["uid"])
 		);
 
-		if((count($r)) && (!$r[0]["hide-friends"]) && (!$contact["hidden"]) && intval(get_pconfig($importer["uid"],'system','post_newfriend'))) {
+		if($r && !$r[0]["hide-friends"] && !$contact["hidden"] && intval(get_pconfig($importer["uid"],'system','post_newfriend'))) {
 
 			$self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
 				intval($importer["uid"])
@@ -1208,7 +1209,7 @@ EOT;
 
 			// they are not CONTACT_IS_FOLLOWER anymore but that's what we have in the array
 
-			if(count($self) && $contact["rel"] == CONTACT_IS_FOLLOWER) {
+			if($self && $contact["rel"] == CONTACT_IS_FOLLOWER) {
 
 				$arr = array();
 				$arr["uri"] = $arr["parent-uri"] = item_new_uri(App::get_hostname(), $importer["uid"]);
@@ -1224,17 +1225,16 @@ EOT;
 				$arr["verb"] = ACTIVITY_FRIEND;
 				$arr["object-type"] = ACTIVITY_OBJ_PERSON;
 
-				$A = '[url=' . $self[0]["url"] . "]' . $self[0]["name"] . '[/url]';
-				$B = '[url=' . $contact["url"] . "]' . $contact["name"] . '[/url]';
-				$BPhoto = '[url=' . $contact["url"] . "]' . '[img]' . $contact["thumb"] . '[/img][/url]';
+				$A = '[url='.$self[0]["url"] . "]'.$self[0]["name"] .'[/url]';
+				$B = '[url='.$contact["url"] . "]'.$contact["name"] .'[/url]';
+				$BPhoto = '[url='.$contact["url"] . "]'.'[img]'.$contact["thumb"] .'[/img][/url]';
 				$arr["body"] =  sprintf( t('%1$s is now friends with %2$s'), $A, $B)."\n\n\n".$Bphoto;
 
-				$arr["object"] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $contact["name"] . '</title>'
-					. '<id>' . $contact["url"] . '/' . $contact["name"] . '</id>';
-				$arr["object"] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $contact["url"] . '" />' . "\n")
-;
-				$arr["object"] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $contact["thumb"] . '" />' . "\n");
-				$arr["object"] .= '</link></object>' . "\n";
+				$arr["object"] = '<object><type>'. ACTIVITY_OBJ_PERSON .'</type><title>'.$contact["name"] .'</title>'
+					.'<id>'.$contact["url"] .'/'.$contact["name"] .'</id>';
+				$arr["object"] .= '<link>'. xmlify('<link rel="alternate" type="text/html" href="'.$contact["url"] .'" />'. "\n");
+				$arr["object"] .= xmlify('<link rel="photo" type="image/jpeg" href="'.$contact["thumb"] .'" />'. "\n");
+				$arr["object"] .= '</link></object>'. "\n";
 				$arr["last-child"] = 1;
 
 				$arr["allow_cid"] = $user[0]["allow_cid"];
@@ -1256,12 +1256,12 @@ EOT;
 	$ret = self::get_person_by_handle($author);
 
 
-	if((! count($ret)) || ($ret["network"] != NETWORK_DIASPORA)) {
-		logger('diaspora_request: Cannot resolve diaspora handle ' . $author . ' for ' . $recipient);
+	if (!$ret || ($ret["network"] != NETWORK_DIASPORA)) {
+		logger('Cannot resolve diaspora handle '.$author .' for '.$recipient);
 		return;
 	}
 
-	$batch = (($ret["batch"]) ? $ret["batch"] : implode('/', array_slice(explode('/',$ret["url"]),0,3)) . '/receive/public');
+	$batch = (($ret["batch"]) ? $ret["batch"] : implode('/', array_slice(explode('/',$ret["url"]),0,3)) .'/receive/public');
 
 
 
@@ -1286,10 +1286,10 @@ EOT;
 
 	// find the contact record we just created
 
-	$contact_record = diaspora_get_contact_by_handle($importer["uid"],$author);
+	$contact_record = self::get_contact_by_handle($importer["uid"],$author);
 
 	if(! $contact_record) {
-		logger('diaspora_request: unable to locate newly created contact record.');
+		logger('unable to locate newly created contact record.');
 		return;
 	}
 
@@ -1360,7 +1360,7 @@ EOT;
 				FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
 			dbesc($guid));
 
-		if(count($r)) {
+		if($r) {
 			logger("reshared message ".$guid." already exists on system.");
 
 			// Maybe it is already a reshared item?
@@ -1371,23 +1371,23 @@ EOT;
 				return $r[0];
 		}
 
-		if (!count($r)) {
-			$server = 'https://'.substr($orig_author,strpos($orig_author,'@')+1);
+		if (!$r) {
+			$server = "https://".substr($orig_author, strpos($orig_author, "@") + 1);
 			logger("1st try: reshared message ".$guid." will be fetched from original server: ".$server);
 			$item_id = self::store_by_guid($guid, $server);
 
 			if (!$item_id) {
-				$server = 'https://'.substr($author,strpos($author,'@')+1);
+				$server = "https://".substr($author, strpos($author, "@") + 1);
 				logger("2nd try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
 				$item = self::store_by_guid($guid, $server);
 			}
 			if (!$item_id) {
-				$server = 'http://'.substr($orig_author,strpos($orig_author,'@')+1);
+				$server = "http://".substr($orig_author, strpos($orig_author, "@") + 1);
 				logger("3rd try: reshared message ".$guid." will be fetched from original server: ".$server);
 				$item = self::store_by_guid($guid, $server);
 			}
 			if (!$item_id) {
-				$server = 'http://'.substr($author,strpos($author,'@')+1);
+				$server = "http://".substr($author, strpos($author, "@") + 1);
 				logger("4th try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
 				$item = self::store_by_guid($guid, $server);
 			}

From 5bbc8a14ceccf40defc37011308d2d549127f2f6 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 5 Mar 2016 00:27:44 +0100
Subject: [PATCH 154/273] "import" is now "receive"

---
 include/diaspora2.php | 311 +++++++++++++++++++++---------------------
 1 file changed, 157 insertions(+), 154 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index b834e3deb9..031058ab75 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -116,53 +116,53 @@ class diaspora {
 
 		switch ($type) {
 			case "account_deletion": // Done
-				return true;
-				//return self::import_account_deletion($importer, $fields);
+				//return true;
+				return self::receive_account_deletion($importer, $fields);
 
 			case "comment": // Done
-				return true;
-				//return self::import_comment($importer, $sender, $fields);
-
-			case "conversation":
 				//return true;
-				return self::import_conversation($importer, $msg, $fields);
+				return self::receive_comment($importer, $sender, $fields);
+
+			case "conversation": // Done
+				//return true;
+				return self::receive_conversation($importer, $msg, $fields);
 
 			case "like": // Done
-				return true;
-				//return self::import_like($importer, $sender, $fields);
+				//return true;
+				return self::receive_like($importer, $sender, $fields);
 
 			case "message": // Done
-				return true;
-				//return self::import_message($importer, $fields);
+				//return true;
+				return self::receive_message($importer, $fields);
 
 			case "participation": // Not implemented
-				return self::import_participation($importer, $fields);
+				return self::receive_participation($importer, $fields);
 
 			case "photo": // Not needed
-				return self::import_photo($importer, $fields);
+				return self::receive_photo($importer, $fields);
 
 			case "poll_participation": // Not implemented
-				return self::import_poll_participation($importer, $fields);
+				return self::receive_poll_participation($importer, $fields);
 
 			case "profile": // Done
-				return true;
-				//return self::import_profile($importer, $fields);
+				//return true;
+				return self::receive_profile($importer, $fields);
 
 			case "request":
 				//return true;
-				return self::import_request($importer, $fields);
+				return self::receive_request($importer, $fields);
 
 			case "reshare": // Done
-				return true;
-				//return self::import_reshare($importer, $fields);
+				//return true;
+				return self::receive_reshare($importer, $fields);
 
 			case "retraction": // Done
-				return true;
-				//return self::import_retraction($importer, $sender, $fields);
-
-			case "status_message":
 				//return true;
-				return self::import_status_message($importer, $fields);
+				return self::receive_retraction($importer, $sender, $fields);
+
+			case "status_message": // Done
+				//return true;
+				return self::receive_status_message($importer, $fields);
 
 			default:
 				logger("Unknown message type ".$type);
@@ -633,7 +633,7 @@ class diaspora {
 		return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
 	}
 
-	private function import_account_deletion($importer, $data) {
+	private function receive_account_deletion($importer, $data) {
 		$author = notags(unxmlify($data->author));
 
 		$contact = self::get_contact_by_handle($importer["uid"], $author);
@@ -647,7 +647,7 @@ class diaspora {
 		return true;
 	}
 
-	private function import_comment($importer, $sender, $data) {
+	private function receive_comment($importer, $sender, $data) {
 		$guid = notags(unxmlify($data->guid));
 		$parent_guid = notags(unxmlify($data->parent_guid));
 		$text = unxmlify($data->text);
@@ -722,7 +722,7 @@ class diaspora {
 		return $message_id;
 	}
 
-	private function import_conversation_message($importer, $contact, $data, $msg, $mesg) {
+	private function receive_conversation_message($importer, $contact, $data, $msg, $mesg) {
 		$guid = notags(unxmlify($data->guid));
 		$subject = notags(unxmlify($data->subject));
 		$author = notags(unxmlify($data->author));
@@ -735,7 +735,14 @@ class diaspora {
 		$msg_author_signature = notags(unxmlify($mesg->author_signature));
 		$msg_text = unxmlify($mesg->text);
 		$msg_created_at = datetime_convert("UTC", "UTC", notags(unxmlify($mesg->created_at)));
-		$msg_author = notags(unxmlify($mesg->diaspora_handle));
+
+		if ($mesg->diaspora_handle)
+			$msg_author = notags(unxmlify($mesg->diaspora_handle));
+		elseif ($mesg->author)
+			$msg_author = notags(unxmlify($mesg->author));
+		else
+			return false;
+
 		$msg_conversation_guid = notags(unxmlify($mesg->conversation_guid));
 
 		if($msg_conversation_guid != $guid) {
@@ -829,7 +836,7 @@ class diaspora {
 		));
 	}
 
-	private function import_conversation($importer, $msg, $data) {
+	private function receive_conversation($importer, $msg, $data) {
 		$guid = notags(unxmlify($data->guid));
 		$subject = notags(unxmlify($data->subject));
 		$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
@@ -881,7 +888,7 @@ class diaspora {
 		}
 
 		foreach($messages as $mesg)
-			self::import_conversation_message($importer, $contact, $data, $msg, $mesg);
+			self::receive_conversation_message($importer, $contact, $data, $msg, $mesg);
 
 		return true;
 	}
@@ -916,7 +923,7 @@ EOT;
 		return $obj;
 	}
 
-	private function import_like($importer, $sender, $data) {
+	private function receive_like($importer, $sender, $data) {
 		$positive = notags(unxmlify($data->positive));
 		$guid = notags(unxmlify($data->guid));
 		$parent_type = notags(unxmlify($data->parent_type));
@@ -1002,7 +1009,7 @@ EOT;
 		return $message_id;
 	}
 
-	private function import_message($importer, $data) {
+	private function receive_message($importer, $data) {
 		$guid = notags(unxmlify($data->guid));
 		$parent_guid = notags(unxmlify($data->parent_guid));
 		$text = unxmlify($data->text);
@@ -1073,22 +1080,22 @@ EOT;
 		return true;
 	}
 
-	private function import_participation($importer, $data) {
+	private function receive_participation($importer, $data) {
 		// I'm not sure if we can fully support this message type
 		return true;
 	}
 
-	private function import_photo($importer, $data) {
+	private function receive_photo($importer, $data) {
 		// There doesn't seem to be a reason for this function, since the photo data is transmitted in the status message as well
 		return true;
 	}
 
-	private function import_poll_participation($importer, $data) {
+	private function receive_poll_participation($importer, $data) {
 		// We don't support polls by now
 		return true;
 	}
 
-	private function import_profile($importer, $data) {
+	private function receive_profile($importer, $data) {
 		$author = notags(unxmlify($data->author));
 
 		$contact = self::get_contact_by_handle($importer["uid"], $author);
@@ -1171,23 +1178,7 @@ EOT;
 		return true;
 	}
 
-	private function import_request($importer, $data) {
-		// @todo
-		print_r($data);
-/*
-	$author = unxmlify($data->author);
-	$recipient = unxmlify($data->recipient);
-
-	if (!$author || !$recipient)
-		return;
-
-	$contact = self::get_contact_by_handle($importer["uid"],$author);
-
-	if($contact) {
-
-		// perhaps we were already sharing with this person. Now they're sharing with us.
-		// That makes us friends.
-
+	private function receive_request_make_friend($importer, $contact) {
 		if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
 			q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
 				intval(CONTACT_IS_FRIEND),
@@ -1201,9 +1192,9 @@ EOT;
 			intval($importer["uid"])
 		);
 
-		if($r && !$r[0]["hide-friends"] && !$contact["hidden"] && intval(get_pconfig($importer["uid"],'system','post_newfriend'))) {
+		if($r && !$r[0]["hide-friends"] && !$contact["hidden"] && intval(get_pconfig($importer["uid"], "system", "post_newfriend"))) {
 
-			$self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
+			$self = q("SELECT * FROM `contact` WHERE `self` AND `uid` = %d LIMIT 1",
 				intval($importer["uid"])
 			);
 
@@ -1225,16 +1216,16 @@ EOT;
 				$arr["verb"] = ACTIVITY_FRIEND;
 				$arr["object-type"] = ACTIVITY_OBJ_PERSON;
 
-				$A = '[url='.$self[0]["url"] . "]'.$self[0]["name"] .'[/url]';
-				$B = '[url='.$contact["url"] . "]'.$contact["name"] .'[/url]';
-				$BPhoto = '[url='.$contact["url"] . "]'.'[img]'.$contact["thumb"] .'[/img][/url]';
-				$arr["body"] =  sprintf( t('%1$s is now friends with %2$s'), $A, $B)."\n\n\n".$Bphoto;
+				$A = "[url=".$self[0]["url"]."]".$self[0]["name"]."[/url]";
+				$B = "[url=".$contact["url"]."]".$contact["name"]."[/url]";
+				$BPhoto = "[url=".$contact["url"]."][img]".$contact["thumb"]."[/img][/url]";
+				$arr["body"] = sprintf(t("%1$s is now friends with %2$s"), $A, $B)."\n\n\n".$Bphoto;
 
-				$arr["object"] = '<object><type>'. ACTIVITY_OBJ_PERSON .'</type><title>'.$contact["name"] .'</title>'
-					.'<id>'.$contact["url"] .'/'.$contact["name"] .'</id>';
-				$arr["object"] .= '<link>'. xmlify('<link rel="alternate" type="text/html" href="'.$contact["url"] .'" />'. "\n");
-				$arr["object"] .= xmlify('<link rel="photo" type="image/jpeg" href="'.$contact["thumb"] .'" />'. "\n");
-				$arr["object"] .= '</link></object>'. "\n";
+				$arr["object"] = "<object><type>".ACTIVITY_OBJ_PERSON."</type><title>".$contact["name"]."</title>"
+					."<id>".$contact["url"]."/".$contact["name"]."</id>";
+				$arr["object"] .= "<link>".xmlify('<link rel="alternate" type="text/html" href="'.$contact["url"].'" />'."\n");
+				$arr["object"] .= xmlify('<link rel="photo" type="image/jpeg" href="'.$contact["thumb"].'" />'."\n");
+				$arr["object"] .= "</link></object>\n";
 				$arr["last-child"] = 1;
 
 				$arr["allow_cid"] = $user[0]["allow_cid"];
@@ -1244,111 +1235,123 @@ EOT;
 
 				$i = item_store($arr);
 				if($i)
-				proc_run('php',"include/notifier.php","activity","$i");
+					proc_run("php", "include/notifier.php", "activity", $i);
 
 			}
 
 		}
-
-		return;
 	}
 
-	$ret = self::get_person_by_handle($author);
+	private function receive_request($importer, $data) {
+		$author = unxmlify($data->author);
+		$recipient = unxmlify($data->recipient);
 
+		if (!$author || !$recipient)
+			return;
 
-	if (!$ret || ($ret["network"] != NETWORK_DIASPORA)) {
-		logger('Cannot resolve diaspora handle '.$author .' for '.$recipient);
-		return;
-	}
+		$contact = self::get_contact_by_handle($importer["uid"],$author);
 
-	$batch = (($ret["batch"]) ? $ret["batch"] : implode('/', array_slice(explode('/',$ret["url"]),0,3)) .'/receive/public');
+		if($contact) {
 
+			// perhaps we were already sharing with this person. Now they're sharing with us.
+			// That makes us friends.
 
+			self::receive_request_make_friend($importer, $contact);
+			return true;
+		}
 
-	$r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`nurl`,`batch`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`)
-		VALUES ( %d, '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s',%d,%d) ",
-		intval($importer["uid"]),
-		dbesc($ret["network"]),
-		dbesc($ret["addr"]),
-		datetime_convert(),
-		dbesc($ret["url"]),
-		dbesc(normalise_link($ret["url"])),
-		dbesc($batch),
-		dbesc($ret["name"]),
-		dbesc($ret["nick"]),
-		dbesc($ret["photo"]),
-		dbesc($ret["pubkey"]),
-		dbesc($ret["notify"]),
-		dbesc($ret["poll"]),
-		1,
-		2
-	);
+		$ret = self::get_person_by_handle($author);
 
-	// find the contact record we just created
+		if (!$ret || ($ret["network"] != NETWORK_DIASPORA)) {
+			logger("Cannot resolve diaspora handle ".$author ." for ".$recipient);
+			return false;
+		}
 
-	$contact_record = self::get_contact_by_handle($importer["uid"],$author);
+		$batch = (($ret["batch"]) ? $ret["batch"] : implode("/", array_slice(explode("/", $ret["url"]), 0, 3))."/receive/public");
 
-	if(! $contact_record) {
-		logger('unable to locate newly created contact record.');
-		return;
-	}
-
-	$g = q("select def_gid from user where uid = %d limit 1",
-		intval($importer["uid"])
-	);
-	if($g && intval($g[0]["def_gid"])) {
-		group_add_member($importer["uid"],'',$contact_record["id"],$g[0]["def_gid"]);
-	}
-
-	if($importer["page-flags"] == PAGE_NORMAL) {
-
-		$hash = random_string() . (string) time();   // Generate a confirm_key
-
-		$ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime` )
-			VALUES ( %d, %d, %d, %d, '%s', '%s', '%s' )",
+		$r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`nurl`,`batch`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`)
+			VALUES (%d, '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s',%d,%d)",
 			intval($importer["uid"]),
-			intval($contact_record["id"]),
-			0,
-			0,
-			dbesc( t('Sharing notification from Diaspora network')),
-			dbesc($hash),
-			dbesc(datetime_convert())
-		);
-	}
-	else {
-
-		// automatic friend approval
-
-		update_contact_avatar($contact_record["photo"],$importer["uid"],$contact_record["id"]);
-
-		// technically they are sharing with us (CONTACT_IS_SHARING),
-		// but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX
-		// we are going to change the relationship and make them a follower.
-
-		if($importer["page-flags"] == PAGE_FREELOVE)
-			$new_relation = CONTACT_IS_FRIEND;
-		else
-			$new_relation = CONTACT_IS_FOLLOWER;
-
-		$r = q("UPDATE `contact` SET `rel` = %d,
-			`name-date` = '%s',
-			`uri-date` = '%s',
-			`blocked` = 0,
-			`pending` = 0,
-			`writable` = 1
-			WHERE `id` = %d
-			",
-			intval($new_relation),
-			dbesc(datetime_convert()),
-			dbesc(datetime_convert()),
-			intval($contact_record["id"])
+			dbesc($ret["network"]),
+			dbesc($ret["addr"]),
+			datetime_convert(),
+			dbesc($ret["url"]),
+			dbesc(normalise_link($ret["url"])),
+			dbesc($batch),
+			dbesc($ret["name"]),
+			dbesc($ret["nick"]),
+			dbesc($ret["photo"]),
+			dbesc($ret["pubkey"]),
+			dbesc($ret["notify"]),
+			dbesc($ret["poll"]),
+			1,
+			2
 		);
 
-		$u = q("select * from user where uid = %d limit 1",intval($importer["uid"]));
-		if($u)
-			$ret = diaspora_share($u[0],$contact_record);
-	}
-*/
+		// find the contact record we just created
+
+		$contact_record = self::get_contact_by_handle($importer["uid"],$author);
+
+		if (!$contact_record) {
+			logger("unable to locate newly created contact record.");
+			return;
+		}
+
+		$g = q("SELECT `def_gid` FROM `user` WHERE `uid` = %d LIMIT 1",
+			intval($importer["uid"])
+		);
+
+		if($g && intval($g[0]["def_gid"]))
+			group_add_member($importer["uid"], "", $contact_record["id"], $g[0]["def_gid"]);
+
+		if($importer["page-flags"] == PAGE_NORMAL) {
+
+			$hash = random_string().(string)time();   // Generate a confirm_key
+
+			$ret = q("INSERT INTO `intro` (`uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime`)
+				VALUES (%d, %d, %d, %d, '%s', '%s', '%s')",
+				intval($importer["uid"]),
+				intval($contact_record["id"]),
+				0,
+				0,
+				dbesc(t("Sharing notification from Diaspora network")),
+				dbesc($hash),
+				dbesc(datetime_convert())
+			);
+		} else {
+
+			// automatic friend approval
+
+			update_contact_avatar($contact_record["photo"],$importer["uid"],$contact_record["id"]);
+
+			// technically they are sharing with us (CONTACT_IS_SHARING),
+			// but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX
+			// we are going to change the relationship and make them a follower.
+
+			if($importer["page-flags"] == PAGE_FREELOVE)
+				$new_relation = CONTACT_IS_FRIEND;
+			else
+				$new_relation = CONTACT_IS_FOLLOWER;
+
+			$r = q("UPDATE `contact` SET `rel` = %d,
+				`name-date` = '%s',
+				`uri-date` = '%s',
+				`blocked` = 0,
+				`pending` = 0,
+				`writable` = 1
+				WHERE `id` = %d
+				",
+				intval($new_relation),
+				dbesc(datetime_convert()),
+				dbesc(datetime_convert()),
+				intval($contact_record["id"])
+			);
+
+			$u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"]));
+			if($u)
+				$ret = diaspora_share($u[0], $contact_record);
+		}
+
 		return true;
 	}
 
@@ -1406,7 +1409,7 @@ EOT;
 		return false;
 	}
 
-	private function import_reshare($importer, $data) {
+	private function receive_reshare($importer, $data) {
 		$root_author = notags(unxmlify($data->root_author));
 		$root_guid = notags(unxmlify($data->root_guid));
 		$guid = notags(unxmlify($data->guid));
@@ -1520,7 +1523,7 @@ EOT;
 		}
 	}
 
-	private function import_retraction($importer, $sender, $data) {
+	private function receive_retraction($importer, $sender, $data) {
 		$target_type = notags(unxmlify($data->target_type));
 
 		$contact = self::get_contact_by_handle($importer["uid"], $sender);
@@ -1548,7 +1551,7 @@ EOT;
 		return true;
 	}
 
-	private function import_status_message($importer, $data) {
+	private function receive_status_message($importer, $data) {
 
 		$raw_message = unxmlify($data->raw_message);
 		$guid = notags(unxmlify($data->guid));

From 2a4ebaa438c0e4c84e20d2567d708e472a7c7192 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 5 Mar 2016 01:30:49 +0100
Subject: [PATCH 155/273] Small cleanup

---
 include/diaspora2.php | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 031058ab75..939a816f40 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -553,7 +553,6 @@ class diaspora {
 
 		$msg = array("message" => $x, "author" => $author);
 
-		// We don't really need this, but until the work is unfinished we better will keep this
 		$msg["key"] = self::get_key($msg["author"]);
 
 		return $msg;
@@ -736,10 +735,12 @@ class diaspora {
 		$msg_text = unxmlify($mesg->text);
 		$msg_created_at = datetime_convert("UTC", "UTC", notags(unxmlify($mesg->created_at)));
 
-		if ($mesg->diaspora_handle)
-			$msg_author = notags(unxmlify($mesg->diaspora_handle));
-		elseif ($mesg->author)
+		// "diaspora_handle" is the element name from the old version
+		// "author" is the element name from the new version
+		if ($mesg->author)
 			$msg_author = notags(unxmlify($mesg->author));
+		elseif ($mesg->diaspora_handle)
+			$msg_author = notags(unxmlify($mesg->diaspora_handle));
 		else
 			return false;
 

From 996cd8c24eb6770320a52d1629ed361d7d690a37 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 5 Mar 2016 13:29:01 +0100
Subject: [PATCH 156/273] The Font Awesome library is now updated, the replxy
 button is changed

---
 view/theme/vier/css/font2.css                 |   1 +
 view/theme/vier/font/FontAwesome.otf          | Bin 85908 -> 109688 bytes
 view/theme/vier/font/fontawesome-webfont.eot  | Bin 56006 -> 70807 bytes
 view/theme/vier/font/fontawesome-webfont.svg  | 169 ++++++++++++++++--
 view/theme/vier/font/fontawesome-webfont.ttf  | Bin 112160 -> 142072 bytes
 view/theme/vier/font/fontawesome-webfont.woff | Bin 65452 -> 83588 bytes
 .../theme/vier/font/fontawesome-webfont.woff2 | Bin 0 -> 66624 bytes
 view/theme/vier/templates/wall_thread.tpl     |   2 +-
 8 files changed, 154 insertions(+), 18 deletions(-)
 mode change 100755 => 100644 view/theme/vier/font/fontawesome-webfont.eot
 mode change 100755 => 100644 view/theme/vier/font/fontawesome-webfont.svg
 mode change 100755 => 100644 view/theme/vier/font/fontawesome-webfont.ttf
 mode change 100755 => 100644 view/theme/vier/font/fontawesome-webfont.woff
 create mode 100644 view/theme/vier/font/fontawesome-webfont.woff2

diff --git a/view/theme/vier/css/font2.css b/view/theme/vier/css/font2.css
index 4300a910c0..a62cffc00c 100644
--- a/view/theme/vier/css/font2.css
+++ b/view/theme/vier/css/font2.css
@@ -228,6 +228,7 @@ li.icon.icon-large:before {
 .icon-key:before                  { content: "\f084"; }
 .icon.gears:before                { content: "\f085"; }
 .icon-comments:before             { content: "\f086"; }
+.icon-commenting:before           { content: "\f27a"; }
 .icon.like:before                 { content: "\f087"; }
 .icon.dislike:before              { content: "\f088"; }
 .icon-star-half:before            { content: "\f089"; }
diff --git a/view/theme/vier/font/FontAwesome.otf b/view/theme/vier/font/FontAwesome.otf
index 81c9ad949b47f64afeca5642ee2494b6e3147f44..3ed7f8b48ad9bfab52eb03822fefcd6b77d2e680 100644
GIT binary patch
delta 55115
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

delta 31586
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

diff --git a/view/theme/vier/font/fontawesome-webfont.eot b/view/theme/vier/font/fontawesome-webfont.eot
old mode 100755
new mode 100644
index 84677bc0c5f37f1fac9d87548c4554b5c91717cf..9b6afaedc0fd7aaf927a07f82da9c11022251b8b
GIT binary patch
literal 70807
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
Ppt>MT0000000000CGV>t

literal 56006
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

diff --git a/view/theme/vier/font/fontawesome-webfont.svg b/view/theme/vier/font/fontawesome-webfont.svg
old mode 100755
new mode 100644
index d907b25ae6..d05688e9e2
--- a/view/theme/vier/font/fontawesome-webfont.svg
+++ b/view/theme/vier/font/fontawesome-webfont.svg
@@ -147,14 +147,14 @@
 <glyph unicode="&#xf077;" horiz-adv-x="1792" d="M1683 205l-166 -165q-19 -19 -45 -19t-45 19l-531 531l-531 -531q-19 -19 -45 -19t-45 19l-166 165q-19 19 -19 45.5t19 45.5l742 741q19 19 45 19t45 -19l742 -741q19 -19 19 -45.5t-19 -45.5z" />
 <glyph unicode="&#xf078;" horiz-adv-x="1792" d="M1683 728l-742 -741q-19 -19 -45 -19t-45 19l-742 741q-19 19 -19 45.5t19 45.5l166 165q19 19 45 19t45 -19l531 -531l531 531q19 19 45 19t45 -19l166 -165q19 -19 19 -45.5t-19 -45.5z" />
 <glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " />
-<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1536 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1664 1088v-512q0 -24 -16.5 -42.5t-40.5 -21.5l-1044 -122q13 -60 13 -70q0 -16 -24 -64h920q26 0 45 -19t19 -45 t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 11 8 31.5t16 36t21.5 40t15.5 29.5l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t19.5 -15.5t13 -24.5t8 -26t5.5 -29.5t4.5 -26h1201q26 0 45 -19t19 -45z" />
 <glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
 <glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
 <glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
 <glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
 <glyph unicode="&#xf080;" horiz-adv-x="2048" d="M640 640v-512h-256v512h256zM1024 1152v-1024h-256v1024h256zM2048 0v-128h-2048v1536h128v-1408h1920zM1408 896v-768h-256v768h256zM1792 1280v-1152h-256v1152h256z" />
 <glyph unicode="&#xf081;" d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4 q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5 t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf082;" d="M1536 160q0 -119 -84.5 -203.5t-203.5 -84.5h-192v608h203l30 224h-233v143q0 54 28 83t96 29l132 1v207q-96 9 -180 9q-136 0 -218 -80.5t-82 -225.5v-166h-224v-224h224v-608h-544q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960 q119 0 203.5 -84.5t84.5 -203.5v-960z" />
+<glyph unicode="&#xf082;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-188v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-532q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960z" />
 <glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" />
 <glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" />
 <glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" />
@@ -219,8 +219,8 @@
 <glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
 <glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
 <glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
-<glyph unicode="&#xf0d4;" d="M829 318q0 -76 -58.5 -112.5t-139.5 -36.5q-41 0 -80.5 9.5t-75.5 28.5t-58 53t-22 78q0 46 25 80t65.5 51.5t82 25t84.5 7.5q20 0 31 -2q2 -1 23 -16.5t26 -19t23 -18t24.5 -22t19 -22.5t17 -26t9 -26.5t4.5 -31.5zM755 863q0 -60 -33 -99.5t-92 -39.5q-53 0 -93 42.5 t-57.5 96.5t-17.5 106q0 61 32 104t92 43q53 0 93.5 -45t58 -101t17.5 -107zM861 1120l88 64h-265q-85 0 -161 -32t-127.5 -98t-51.5 -153q0 -93 64.5 -154.5t158.5 -61.5q22 0 43 3q-13 -29 -13 -54q0 -44 40 -94q-175 -12 -257 -63q-47 -29 -75.5 -73t-28.5 -95 q0 -43 18.5 -77.5t48.5 -56.5t69 -37t77.5 -21t76.5 -6q60 0 120.5 15.5t113.5 46t86 82.5t33 117q0 49 -20 89.5t-49 66.5t-58 47.5t-49 44t-20 44.5t15.5 42.5t37.5 39.5t44 42t37.5 59.5t15.5 82.5q0 60 -22.5 99.5t-72.5 90.5h83zM1152 672h128v64h-128v128h-64v-128 h-128v-64h128v-160h64v160zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
-<glyph unicode="&#xf0d5;" horiz-adv-x="1664" d="M735 740q0 -36 32 -70.5t77.5 -68t90.5 -73.5t77 -104t32 -142q0 -90 -48 -173q-72 -122 -211 -179.5t-298 -57.5q-132 0 -246.5 41.5t-171.5 137.5q-37 60 -37 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 42 -47.5 74t-15.5 73q0 36 21 85q-46 -4 -68 -4 q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q77 66 182.5 98t217.5 32h418l-138 -88h-131q74 -63 112 -133t38 -160q0 -72 -24.5 -129.5t-59 -93t-69.5 -65t-59.5 -61.5t-24.5 -66zM589 836q38 0 78 16.5t66 43.5q53 57 53 159q0 58 -17 125t-48.5 129.5 t-84.5 103.5t-117 41q-42 0 -82.5 -19.5t-65.5 -52.5q-47 -59 -47 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26zM591 -37q58 0 111.5 13t99 39t73 73t27.5 109q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -48 2 q-53 0 -105 -7t-107.5 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -70 35 -123.5t91.5 -83t119 -44t127.5 -14.5zM1401 839h213v-108h-213v-219h-105v219h-212v108h212v217h105v-217z" />
+<glyph unicode="&#xf0d4;" d="M917 631q0 26 -6 64h-362v-132h217q-3 -24 -16.5 -50t-37.5 -53t-66.5 -44.5t-96.5 -17.5q-99 0 -169 71t-70 171t70 171t169 71q92 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585 h109v110h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf0d5;" horiz-adv-x="2304" d="M1437 623q0 -208 -87 -370.5t-248 -254t-369 -91.5q-149 0 -285 58t-234 156t-156 234t-58 285t58 285t156 234t234 156t285 58q286 0 491 -192l-199 -191q-117 113 -292 113q-123 0 -227.5 -62t-165.5 -168.5t-61 -232.5t61 -232.5t165.5 -168.5t227.5 -62 q83 0 152.5 23t114.5 57.5t78.5 78.5t49 83t21.5 74h-416v252h692q12 -63 12 -122zM2304 745v-210h-209v-209h-210v209h-209v210h209v209h210v-209h209z" />
 <glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
 <glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
 <glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
@@ -275,7 +275,7 @@
 <glyph unicode="&#xf10c;" d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103 t279.5 -279.5t103 -385.5z" />
 <glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" />
 <glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" />
-<glyph unicode="&#xf110;" horiz-adv-x="1568" d="M496 192q0 -60 -42.5 -102t-101.5 -42q-60 0 -102 42t-42 102t42 102t102 42q59 0 101.5 -42t42.5 -102zM928 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -66 -47 -113t-113 -47t-113 47t-47 113 t47 113t113 47t113 -47t47 -113zM1360 192q0 -46 -33 -79t-79 -33t-79 33t-33 79t33 79t79 33t79 -33t33 -79zM528 1088q0 -73 -51.5 -124.5t-124.5 -51.5t-124.5 51.5t-51.5 124.5t51.5 124.5t124.5 51.5t124.5 -51.5t51.5 -124.5zM992 1280q0 -80 -56 -136t-136 -56 t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1536 640q0 -40 -28 -68t-68 -28t-68 28t-28 68t28 68t68 28t68 -28t28 -68zM1328 1088q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5z" />
+<glyph unicode="&#xf110;" horiz-adv-x="1792" d="M526 142q0 -53 -37.5 -90.5t-90.5 -37.5q-52 0 -90 38t-38 90q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 -64q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -53 -37.5 -90.5t-90.5 -37.5 t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1522 142q0 -52 -38 -90t-90 -38q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM558 1138q0 -66 -47 -113t-113 -47t-113 47t-47 113t47 113t113 47t113 -47t47 -113z M1728 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1088 1344q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1618 1138q0 -93 -66 -158.5t-158 -65.5q-93 0 -158.5 65.5t-65.5 158.5 q0 92 65.5 158t158.5 66q92 0 158 -66t66 -158z" />
 <glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
 <glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
 <glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" />
@@ -362,7 +362,7 @@
 <glyph unicode="&#xf169;" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
 <glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" />
 <glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
-<glyph unicode="&#xf16c;" horiz-adv-x="1408" d="M928 135v-151l-707 -1v151zM1169 481v-701l-1 -35v-1h-1132l-35 1h-1v736h121v-618h928v618h120zM241 393l704 -65l-13 -150l-705 65zM309 709l683 -183l-39 -146l-683 183zM472 1058l609 -360l-77 -130l-609 360zM832 1389l398 -585l-124 -85l-399 584zM1285 1536 l121 -697l-149 -26l-121 697z" />
+<glyph unicode="&#xf16c;" d="M1289 -96h-1118v480h-160v-640h1438v640h-160v-480zM347 428l33 157l783 -165l-33 -156zM450 802l67 146l725 -339l-67 -145zM651 1158l102 123l614 -513l-102 -123zM1048 1536l477 -641l-128 -96l-477 641zM330 65v159h800v-159h-800z" />
 <glyph unicode="&#xf16d;" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139v1142q0 81 58 139 t139 58h1142q81 0 139 -58t58 -139z" />
 <glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
 <glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
@@ -399,7 +399,7 @@
 <glyph unicode="&#xf191;" d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
 <glyph unicode="&#xf192;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5 t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
 <glyph unicode="&#xf193;" horiz-adv-x="1664" d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128 q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 16 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" />
-<glyph unicode="&#xf194;" d="M1254 899q16 85 -21 132q-52 65 -187 45q-17 -3 -41 -12.5t-57.5 -30.5t-64.5 -48.5t-59.5 -70t-44.5 -91.5q80 7 113.5 -16t26.5 -99q-5 -52 -52 -143q-43 -78 -71 -99q-44 -32 -87 14q-23 24 -37.5 64.5t-19 73t-10 84t-8.5 71.5q-23 129 -34 164q-12 37 -35.5 69 t-50.5 40q-57 16 -127 -25q-54 -32 -136.5 -106t-122.5 -102v-7q16 -8 25.5 -26t21.5 -20q21 -3 54.5 8.5t58 10.5t41.5 -30q11 -18 18.5 -38.5t15 -48t12.5 -40.5q17 -46 53 -187q36 -146 57 -197q42 -99 103 -125q43 -12 85 -1.5t76 31.5q131 77 250 237 q104 139 172.5 292.5t82.5 226.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf194;" d="M1292 898q10 216 -161 222q-231 8 -312 -261q44 19 82 19q85 0 74 -96q-4 -57 -74 -167t-105 -110q-43 0 -82 169q-13 54 -45 255q-30 189 -160 177q-59 -7 -164 -100l-81 -72l-81 -72l52 -67q76 52 87 52q57 0 107 -179q15 -55 45 -164.5t45 -164.5q68 -179 164 -179 q157 0 383 294q220 283 226 444zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
 <glyph unicode="&#xf195;" horiz-adv-x="1152" d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160 q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
 <glyph unicode="&#xf196;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832 q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
 <glyph unicode="&#xf197;" horiz-adv-x="2176" d="M620 416q-110 -64 -268 -64h-128v64h-64q-13 0 -22.5 23.5t-9.5 56.5q0 24 7 49q-58 2 -96.5 10.5t-38.5 20.5t38.5 20.5t96.5 10.5q-7 25 -7 49q0 33 9.5 56.5t22.5 23.5h64v64h128q158 0 268 -64h1113q42 -7 106.5 -18t80.5 -14q89 -15 150 -40.5t83.5 -47.5t22.5 -40 t-22.5 -40t-83.5 -47.5t-150 -40.5q-16 -3 -80.5 -14t-106.5 -18h-1113zM1739 668q53 -36 53 -92t-53 -92l81 -30q68 48 68 122t-68 122zM625 400h1015q-217 -38 -456 -80q-57 0 -113 -24t-83 -48l-28 -24l-288 -288q-26 -26 -70.5 -45t-89.5 -19h-96l-93 464h29 q157 0 273 64zM352 816h-29l93 464h96q46 0 90 -19t70 -45l288 -288q4 -4 11 -10.5t30.5 -23t48.5 -29t61.5 -23t72.5 -10.5l456 -80h-1015q-116 64 -273 64z" />
@@ -410,9 +410,9 @@
 <glyph unicode="&#xf19c;" horiz-adv-x="2048" d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64 q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" />
 <glyph unicode="&#xf19d;" horiz-adv-x="2304" d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433 q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" />
 <glyph unicode="&#xf19e;" d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q43 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0 q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" />
-<glyph unicode="&#xf1a0;" horiz-adv-x="1280" d="M981 197q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -49 2q-53 0 -104.5 -7t-107 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -56 23.5 -102t61 -75.5t87 -50t100 -29t101.5 -8.5q58 0 111.5 13t99 39t73 73t27.5 109zM864 1055 q0 59 -17 125.5t-48 129t-84 103.5t-117 41q-42 0 -82.5 -19.5t-66.5 -52.5q-46 -59 -46 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26q37 0 77.5 16.5t65.5 43.5q53 56 53 159zM752 1536h417l-137 -88h-132q75 -63 113 -133t38 -160q0 -72 -24.5 -129.5 t-59.5 -93t-69.5 -65t-59 -61.5t-24.5 -66q0 -36 32 -70.5t77 -68t90.5 -73.5t77.5 -104t32 -142q0 -91 -49 -173q-71 -122 -209.5 -179.5t-298.5 -57.5q-132 0 -246.5 41.5t-172.5 137.5q-36 59 -36 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 41 -47.5 73.5 t-15.5 73.5q0 40 21 85q-46 -4 -68 -4q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q76 66 182 98t218 32z" />
-<glyph unicode="&#xf1a1;" horiz-adv-x="1984" d="M831 572q0 -56 -40.5 -96t-96.5 -40q-57 0 -98 40t-41 96q0 57 41.5 98t97.5 41t96.5 -41t40.5 -98zM1292 711q56 0 96.5 -41t40.5 -98q0 -56 -40.5 -96t-96.5 -40q-57 0 -98 40t-41 96q0 57 41.5 98t97.5 41zM1984 722q0 -62 -31 -114t-83 -82q5 -33 5 -61 q0 -121 -68.5 -230.5t-197.5 -193.5q-125 -82 -285.5 -125.5t-335.5 -43.5q-176 0 -336.5 43.5t-284.5 125.5q-129 84 -197.5 193t-68.5 231q0 29 5 66q-48 31 -77 81.5t-29 109.5q0 94 66 160t160 66q83 0 148 -55q248 158 592 164l134 423q4 14 17.5 21.5t28.5 4.5 l347 -82q22 50 68.5 81t102.5 31q77 0 131.5 -54.5t54.5 -131.5t-54.5 -132t-131.5 -55q-76 0 -130.5 54t-55.5 131l-315 74l-116 -366q327 -14 560 -166q64 58 151 58q94 0 160 -66t66 -160zM1664 1459q-45 0 -77 -32t-32 -77t32 -77t77 -32t77 32t32 77t-32 77t-77 32z M77 722q0 -67 51 -111q49 131 180 235q-36 25 -82 25q-62 0 -105.5 -43.5t-43.5 -105.5zM1567 105q112 73 171.5 166t59.5 194t-59.5 193.5t-171.5 165.5q-116 75 -265.5 115.5t-313.5 40.5t-313.5 -40.5t-265.5 -115.5q-112 -73 -171.5 -165.5t-59.5 -193.5t59.5 -194 t171.5 -166q116 -75 265.5 -115.5t313.5 -40.5t313.5 40.5t265.5 115.5zM1850 605q57 46 57 117q0 62 -43.5 105.5t-105.5 43.5q-49 0 -86 -28q131 -105 178 -238zM1258 237q11 11 27 11t27 -11t11 -27.5t-11 -27.5q-99 -99 -319 -99h-2q-220 0 -319 99q-11 11 -11 27.5 t11 27.5t27 11t27 -11q77 -77 265 -77h2q188 0 265 77z" />
-<glyph unicode="&#xf1a2;" d="M950 393q7 7 17.5 7t17.5 -7t7 -18t-7 -18q-65 -64 -208 -64h-1h-1q-143 0 -207 64q-8 7 -8 18t8 18q7 7 17.5 7t17.5 -7q49 -51 172 -51h1h1q122 0 173 51zM671 613q0 -37 -26 -64t-63 -27t-63 27t-26 64t26 63t63 26t63 -26t26 -63zM1214 1049q-29 0 -50 21t-21 50 q0 30 21 51t50 21q30 0 51 -21t21 -51q0 -29 -21 -50t-51 -21zM1216 1408q132 0 226 -94t94 -227v-894q0 -133 -94 -227t-226 -94h-896q-132 0 -226 94t-94 227v894q0 133 94 227t226 94h896zM1321 596q35 14 57 45.5t22 70.5q0 51 -36 87.5t-87 36.5q-60 0 -98 -48 q-151 107 -375 115l83 265l206 -49q1 -50 36.5 -85t84.5 -35q50 0 86 35.5t36 85.5t-36 86t-86 36q-36 0 -66 -20.5t-45 -53.5l-227 54q-9 2 -17.5 -2.5t-11.5 -14.5l-95 -302q-224 -4 -381 -113q-36 43 -93 43q-51 0 -87 -36.5t-36 -87.5q0 -37 19.5 -67.5t52.5 -45.5 q-7 -25 -7 -54q0 -98 74 -181.5t201.5 -132t278.5 -48.5q150 0 277.5 48.5t201.5 132t74 181.5q0 27 -6 54zM971 702q37 0 63 -26t26 -63t-26 -64t-63 -27t-63 27t-26 64t26 63t63 26z" />
+<glyph unicode="&#xf1a0;" d="M768 750h725q12 -67 12 -128q0 -217 -91 -387.5t-259.5 -266.5t-386.5 -96q-157 0 -299 60.5t-245 163.5t-163.5 245t-60.5 299t60.5 299t163.5 245t245 163.5t299 60.5q300 0 515 -201l-209 -201q-123 119 -306 119q-129 0 -238.5 -65t-173.5 -176.5t-64 -243.5 t64 -243.5t173.5 -176.5t238.5 -65q87 0 160 24t120 60t82 82t51.5 87t22.5 78h-436v264z" />
+<glyph unicode="&#xf1a1;" horiz-adv-x="1792" d="M1095 369q16 -16 0 -31q-62 -62 -199 -62t-199 62q-16 15 0 31q6 6 15 6t15 -6q48 -49 169 -49q120 0 169 49q6 6 15 6t15 -6zM788 550q0 -37 -26 -63t-63 -26t-63.5 26t-26.5 63q0 38 26.5 64t63.5 26t63 -26.5t26 -63.5zM1183 550q0 -37 -26.5 -63t-63.5 -26t-63 26 t-26 63t26 63.5t63 26.5t63.5 -26t26.5 -64zM1434 670q0 49 -35 84t-85 35t-86 -36q-130 90 -311 96l63 283l200 -45q0 -37 26 -63t63 -26t63.5 26.5t26.5 63.5t-26.5 63.5t-63.5 26.5q-54 0 -80 -50l-221 49q-19 5 -25 -16l-69 -312q-180 -7 -309 -97q-35 37 -87 37 q-50 0 -85 -35t-35 -84q0 -35 18.5 -64t49.5 -44q-6 -27 -6 -56q0 -142 140 -243t337 -101q198 0 338 101t140 243q0 32 -7 57q30 15 48 43.5t18 63.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191 t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf1a2;" d="M939 407q13 -13 0 -26q-53 -53 -171 -53t-171 53q-13 13 0 26q5 6 13 6t13 -6q42 -42 145 -42t145 42q5 6 13 6t13 -6zM676 563q0 -31 -23 -54t-54 -23t-54 23t-23 54q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1014 563q0 -31 -23 -54t-54 -23t-54 23t-23 54 q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1229 666q0 42 -30 72t-73 30q-42 0 -73 -31q-113 78 -267 82l54 243l171 -39q1 -32 23.5 -54t53.5 -22q32 0 54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5q-48 0 -69 -43l-189 42q-17 5 -21 -13l-60 -268q-154 -6 -265 -83 q-30 32 -74 32q-43 0 -73 -30t-30 -72q0 -30 16 -55t42 -38q-5 -25 -5 -48q0 -122 120 -208.5t289 -86.5q170 0 290 86.5t120 208.5q0 25 -6 49q25 13 40.5 37.5t15.5 54.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
 <glyph unicode="&#xf1a3;" d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150 v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103 t385.5 -103t279.5 -279.5t103 -385.5z" />
 <glyph unicode="&#xf1a4;" horiz-adv-x="1920" d="M1062 824v118q0 42 -30 72t-72 30t-72 -30t-30 -72v-612q0 -175 -126 -299t-303 -124q-178 0 -303.5 125.5t-125.5 303.5v266h328v-262q0 -43 30 -72.5t72 -29.5t72 29.5t30 72.5v620q0 171 126.5 292t301.5 121q176 0 302 -122t126 -294v-136l-195 -58zM1592 602h328 v-266q0 -178 -125.5 -303.5t-303.5 -125.5q-177 0 -303 124.5t-126 300.5v268l131 -61l195 58v-270q0 -42 30 -71.5t72 -29.5t72 29.5t30 71.5v275z" />
 <glyph unicode="&#xf1a5;" d="M1472 160v480h-704v704h-480q-93 0 -158.5 -65.5t-65.5 -158.5v-480h704v-704h480q93 0 158.5 65.5t65.5 158.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" />
@@ -438,7 +438,7 @@
 <glyph unicode="&#xf1ba;" horiz-adv-x="2048" d="M1824 640q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-96v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-1024v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5 t179 63.5h128v224q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-224h128q98 0 179 -63.5t104 -157.5l105 -419h28zM320 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM516 640h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5z M1728 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47z" />
 <glyph unicode="&#xf1bb;" d="M1504 64q0 -26 -19 -45t-45 -19h-462q1 -17 6 -87.5t5 -108.5q0 -25 -18 -42.5t-43 -17.5h-320q-25 0 -43 17.5t-18 42.5q0 38 5 108.5t6 87.5h-462q-26 0 -45 19t-19 45t19 45l402 403h-229q-26 0 -45 19t-19 45t19 45l402 403h-197q-26 0 -45 19t-19 45t19 45l384 384 q19 19 45 19t45 -19l384 -384q19 -19 19 -45t-19 -45t-45 -19h-197l402 -403q19 -19 19 -45t-19 -45t-45 -19h-229l402 -403q19 -19 19 -45z" />
 <glyph unicode="&#xf1bc;" d="M1127 326q0 32 -30 51q-193 115 -447 115q-133 0 -287 -34q-42 -9 -42 -52q0 -20 13.5 -34.5t35.5 -14.5q5 0 37 8q132 27 243 27q226 0 397 -103q19 -11 33 -11q19 0 33 13.5t14 34.5zM1223 541q0 40 -35 61q-237 141 -548 141q-153 0 -303 -42q-48 -13 -48 -64 q0 -25 17.5 -42.5t42.5 -17.5q7 0 37 8q122 33 251 33q279 0 488 -124q24 -13 38 -13q25 0 42.5 17.5t17.5 42.5zM1331 789q0 47 -40 70q-126 73 -293 110.5t-343 37.5q-204 0 -364 -47q-23 -7 -38.5 -25.5t-15.5 -48.5q0 -31 20.5 -52t51.5 -21q11 0 40 8q133 37 307 37 q159 0 309.5 -34t253.5 -95q21 -12 40 -12q29 0 50.5 20.5t21.5 51.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
-<glyph unicode="&#xf1bd;" d="M1397 1408q58 0 98.5 -40.5t40.5 -98.5v-1258q0 -58 -40.5 -98.5t-98.5 -40.5h-1258q-58 0 -98.5 40.5t-40.5 98.5v1258q0 58 40.5 98.5t98.5 40.5h1258zM1465 11v1258q0 28 -20 48t-48 20h-1258q-28 0 -48 -20t-20 -48v-1258q0 -28 20 -48t48 -20h1258q28 0 48 20t20 48 zM694 749l188 -387l533 145v-496q0 -7 -5.5 -12.5t-12.5 -5.5h-1258q-7 0 -12.5 5.5t-5.5 12.5v141l711 195l-212 439q4 1 12 2.5t12 1.5q170 32 303.5 21.5t221 -46t143.5 -94.5q27 -28 -25 -42q-64 -16 -256 -62l-97 198q-111 7 -240 -16zM1397 1287q7 0 12.5 -5.5 t5.5 -12.5v-428q-85 30 -188 52q-294 64 -645 12l-18 -3l-65 134h-233l85 -190q-132 -51 -230 -137v560q0 7 5.5 12.5t12.5 5.5h1258zM286 387q-14 -3 -26 4.5t-14 21.5q-24 203 166 305l129 -270z" />
+<glyph unicode="&#xf1bd;" horiz-adv-x="1024" d="M1024 1233l-303 -582l24 -31h279v-415h-507l-44 -30l-142 -273l-30 -30h-301v303l303 583l-24 30h-279v415h507l44 30l142 273l30 30h301v-303z" />
 <glyph unicode="&#xf1be;" horiz-adv-x="2304" d="M784 164l16 241l-16 523q-1 10 -7.5 17t-16.5 7q-9 0 -16 -7t-7 -17l-14 -523l14 -241q1 -10 7.5 -16.5t15.5 -6.5q22 0 24 23zM1080 193l11 211l-12 586q0 16 -13 24q-8 5 -16 5t-16 -5q-13 -8 -13 -24l-1 -6l-10 -579q0 -1 11 -236v-1q0 -10 6 -17q9 -11 23 -11 q11 0 20 9q9 7 9 20zM35 533l20 -128l-20 -126q-2 -9 -9 -9t-9 9l-17 126l17 128q2 9 9 9t9 -9zM121 612l26 -207l-26 -203q-2 -9 -10 -9q-9 0 -9 10l-23 202l23 207q0 9 9 9q8 0 10 -9zM401 159zM213 650l25 -245l-25 -237q0 -11 -11 -11q-10 0 -12 11l-21 237l21 245 q2 12 12 12q11 0 11 -12zM307 657l23 -252l-23 -244q-2 -13 -14 -13q-13 0 -13 13l-21 244l21 252q0 13 13 13q12 0 14 -13zM401 639l21 -234l-21 -246q-2 -16 -16 -16q-6 0 -10.5 4.5t-4.5 11.5l-20 246l20 234q0 6 4.5 10.5t10.5 4.5q14 0 16 -15zM784 164zM495 785 l21 -380l-21 -246q0 -7 -5 -12.5t-12 -5.5q-16 0 -18 18l-18 246l18 380q2 18 18 18q7 0 12 -5.5t5 -12.5zM589 871l19 -468l-19 -244q0 -8 -5.5 -13.5t-13.5 -5.5q-18 0 -20 19l-16 244l16 468q2 19 20 19q8 0 13.5 -5.5t5.5 -13.5zM687 911l18 -506l-18 -242 q-2 -21 -22 -21q-19 0 -21 21l-16 242l16 506q0 9 6.5 15.5t14.5 6.5q9 0 15 -6.5t7 -15.5zM1079 169v0v0zM881 915l15 -510l-15 -239q0 -10 -7.5 -17.5t-17.5 -7.5t-17 7t-8 18l-14 239l14 510q0 11 7.5 18t17.5 7t17.5 -7t7.5 -18zM980 896l14 -492l-14 -236q0 -11 -8 -19 t-19 -8t-19 8t-9 19l-12 236l12 492q1 12 9 20t19 8t18.5 -8t8.5 -20zM1192 404l-14 -231v0q0 -13 -9 -22t-22 -9t-22 9t-10 22l-6 114l-6 117l12 636v3q2 15 12 24q9 7 20 7q8 0 15 -5q14 -8 16 -26zM2304 423q0 -117 -83 -199.5t-200 -82.5h-786q-13 2 -22 11t-9 22v899 q0 23 28 33q85 34 181 34q195 0 338 -131.5t160 -323.5q53 22 110 22q117 0 200 -83t83 -201z" />
 <glyph unicode="&#xf1c0;" d="M768 768q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 0q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127 t443 -43zM768 384q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 1536q208 0 385 -34.5t280 -93.5t103 -128v-128q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5 t-103 128v128q0 69 103 128t280 93.5t385 34.5z" />
 <glyph unicode="&#xf1c1;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M894 465q33 -26 84 -56q59 7 117 7q147 0 177 -49q16 -22 2 -52q0 -1 -1 -2l-2 -2v-1q-6 -38 -71 -38q-48 0 -115 20t-130 53q-221 -24 -392 -83q-153 -262 -242 -262q-15 0 -28 7l-24 12q-1 1 -6 5q-10 10 -6 36q9 40 56 91.5t132 96.5q14 9 23 -6q2 -2 2 -4q52 85 107 197 q68 136 104 262q-24 82 -30.5 159.5t6.5 127.5q11 40 42 40h21h1q23 0 35 -15q18 -21 9 -68q-2 -6 -4 -8q1 -3 1 -8v-30q-2 -123 -14 -192q55 -164 146 -238zM318 54q52 24 137 158q-51 -40 -87.5 -84t-49.5 -74zM716 974q-15 -42 -2 -132q1 7 7 44q0 3 7 43q1 4 4 8 q-1 1 -1 2t-0.5 1.5t-0.5 1.5q-1 22 -13 36q0 -1 -1 -2v-2zM592 313q135 54 284 81q-2 1 -13 9.5t-16 13.5q-76 67 -127 176q-27 -86 -83 -197q-30 -56 -45 -83zM1238 329q-24 24 -140 24q76 -28 124 -28q14 0 18 1q0 1 -2 3z" />
@@ -454,12 +454,12 @@
 <glyph unicode="&#xf1cb;" horiz-adv-x="1792" d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546 q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" />
 <glyph unicode="&#xf1cc;" horiz-adv-x="2048" d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94 q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55 t121.5 -21q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97q14 -16 29.5 -34t34.5 -40t29 -34q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5 t-85 -189.5z" />
 <glyph unicode="&#xf1cd;" horiz-adv-x="1792" d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194 q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5 t271.5 -112.5zM1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" />
-<glyph unicode="&#xf1ce;" horiz-adv-x="1792" d="M1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348q0 222 101 414.5t276.5 317t390.5 155.5v-260q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 q0 230 -145.5 406t-366.5 221v260q215 -31 390.5 -155.5t276.5 -317t101 -414.5z" />
+<glyph unicode="&#xf1ce;" horiz-adv-x="1792" d="M1760 640q0 -176 -68.5 -336t-184 -275.5t-275.5 -184t-336 -68.5t-336 68.5t-275.5 184t-184 275.5t-68.5 336q0 213 97 398.5t265 305.5t374 151v-228q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5 t136.5 204t51 248.5q0 230 -145.5 406t-366.5 221v228q206 -31 374 -151t265 -305.5t97 -398.5z" />
 <glyph unicode="&#xf1d0;" horiz-adv-x="1792" d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41 t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170 t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136 q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" />
 <glyph unicode="&#xf1d1;" horiz-adv-x="1792" d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251 l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162 q-67 77 -98 169l232 80q-14 42 -14 85t14 85l-233 80q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169zM874 1448v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98l-57 33 q106 172 282 275.5t385 109.5zM1705 640q0 -205 -98 -385l-57 33q27 52 49 112l-83 28q36 103 36 212q0 112 -35 212l82 28q-19 56 -49 112l57 33q98 -180 98 -385zM1585 1063l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13v66q209 -6 385 -109.5 t282 -275.5zM1748 640q0 173 -67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331t67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71 t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
 <glyph unicode="&#xf1d2;" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392 q0 -50 -3 -75zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
 <glyph unicode="&#xf1d3;" horiz-adv-x="1792" d="M595 22q0 100 -165 100q-158 0 -158 -104q0 -101 172 -101q151 0 151 105zM536 777q0 61 -30 102t-89 41q-124 0 -124 -145q0 -135 124 -135q119 0 119 137zM805 1101v-202q-36 -12 -79 -22q16 -43 16 -84q0 -127 -73 -216.5t-197 -112.5q-40 -8 -59.5 -27t-19.5 -58 q0 -31 22.5 -51.5t58 -32t78.5 -22t86 -25.5t78.5 -37.5t58 -64t22.5 -98.5q0 -304 -363 -304q-69 0 -130 12.5t-116 41t-87.5 82t-32.5 127.5q0 165 182 225v4q-67 41 -67 126q0 109 63 137v4q-72 24 -119.5 108.5t-47.5 165.5q0 139 95 231.5t235 92.5q96 0 178 -47 q98 0 218 47zM1123 220h-222q4 45 4 134v609q0 94 -4 128h222q-4 -33 -4 -124v-613q0 -89 4 -134zM1724 442v-196q-71 -39 -174 -39q-62 0 -107 20t-70 50t-39.5 78t-18.5 92t-4 103v351h2v4q-7 0 -19 1t-18 1q-21 0 -59 -6v190h96v76q0 54 -6 89h227q-6 -41 -6 -165h171 v-190q-15 0 -43.5 2t-42.5 2h-85v-365q0 -131 87 -131q61 0 109 33zM1148 1389q0 -58 -39 -101.5t-96 -43.5q-58 0 -98 43.5t-40 101.5q0 59 39.5 103t98.5 44q58 0 96.5 -44.5t38.5 -102.5z" />
-<glyph unicode="&#xf1d4;" d="M825 547l343 588h-150q-21 -39 -63.5 -118.5t-68 -128.5t-59.5 -118.5t-60 -128.5h-3q-21 48 -44.5 97t-52 105.5t-46.5 92t-54 104.5t-49 95h-150l323 -589v-435h134v436zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf1d4;" d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
 <glyph unicode="&#xf1d5;" horiz-adv-x="1280" d="M842 964q0 -80 -57 -136.5t-136 -56.5q-60 0 -111 35q-62 -67 -115 -146q-247 -371 -202 -859q1 -22 -12.5 -38.5t-34.5 -18.5h-5q-20 0 -35 13.5t-17 33.5q-14 126 -3.5 247.5t29.5 217t54 186t69 155.5t74 125q61 90 132 165q-16 35 -16 77q0 80 56.5 136.5t136.5 56.5 t136.5 -56.5t56.5 -136.5zM1223 953q0 -158 -78 -292t-212.5 -212t-292.5 -78q-64 0 -131 14q-21 5 -32.5 23.5t-6.5 39.5q5 20 23 31.5t39 7.5q51 -13 108 -13q97 0 186 38t153 102t102 153t38 186t-38 186t-102 153t-153 102t-186 38t-186 -38t-153 -102t-102 -153 t-38 -186q0 -114 52 -218q10 -20 3.5 -40t-25.5 -30t-39.5 -3t-30.5 26q-64 123 -64 265q0 119 46.5 227t124.5 186t186 124t226 46q158 0 292.5 -78t212.5 -212.5t78 -292.5z" />
 <glyph unicode="&#xf1d6;" horiz-adv-x="1792" d="M270 730q-8 19 -8 52q0 20 11 49t24 45q-1 22 7.5 53t22.5 43q0 139 92.5 288.5t217.5 209.5q139 66 324 66q133 0 266 -55q49 -21 90 -48t71 -56t55 -68t42 -74t32.5 -84.5t25.5 -89.5t22 -98l1 -5q55 -83 55 -150q0 -14 -9 -40t-9 -38q0 -1 1.5 -3.5t3.5 -5t2 -3.5 q77 -114 120.5 -214.5t43.5 -208.5q0 -43 -19.5 -100t-55.5 -57q-9 0 -19.5 7.5t-19 17.5t-19 26t-16 26.5t-13.5 26t-9 17.5q-1 1 -3 1l-5 -4q-59 -154 -132 -223q20 -20 61.5 -38.5t69 -41.5t35.5 -65q-2 -4 -4 -16t-7 -18q-64 -97 -302 -97q-53 0 -110.5 9t-98 20 t-104.5 30q-15 5 -23 7q-14 4 -46 4.5t-40 1.5q-41 -45 -127.5 -65t-168.5 -20q-35 0 -69 1.5t-93 9t-101 20.5t-74.5 40t-32.5 64q0 40 10 59.5t41 48.5q11 2 40.5 13t49.5 12q4 0 14 2q2 2 2 4l-2 3q-48 11 -108 105.5t-73 156.5l-5 3q-4 0 -12 -20q-18 -41 -54.5 -74.5 t-77.5 -37.5h-1q-4 0 -6 4.5t-5 5.5q-23 54 -23 100q0 275 252 466z" />
 <glyph unicode="&#xf1d7;" horiz-adv-x="2048" d="M580 1075q0 41 -25 66t-66 25q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 66 24.5t25 65.5zM1323 568q0 28 -25.5 50t-65.5 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q40 0 65.5 22t25.5 51zM1087 1075q0 41 -24.5 66t-65.5 25 q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 65.5 24.5t24.5 65.5zM1722 568q0 28 -26 50t-65 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q39 0 65 22t26 51zM1456 965q-31 4 -70 4q-169 0 -311 -77t-223.5 -208.5t-81.5 -287.5 q0 -78 23 -152q-35 -3 -68 -3q-26 0 -50 1.5t-55 6.5t-44.5 7t-54.5 10.5t-50 10.5l-253 -127l72 218q-290 203 -290 490q0 169 97.5 311t264 223.5t363.5 81.5q176 0 332.5 -66t262 -182.5t136.5 -260.5zM2048 404q0 -117 -68.5 -223.5t-185.5 -193.5l55 -181l-199 109 q-150 -37 -218 -37q-169 0 -311 70.5t-223.5 191.5t-81.5 264t81.5 264t223.5 191.5t311 70.5q161 0 303 -70.5t227.5 -192t85.5 -263.5z" />
@@ -483,13 +483,13 @@
 <glyph unicode="&#xf1ea;" horiz-adv-x="2048" d="M1024 1024h-384v-384h384v384zM1152 384v-128h-640v128h640zM1152 1152v-640h-640v640h640zM1792 384v-128h-512v128h512zM1792 640v-128h-512v128h512zM1792 896v-128h-512v128h512zM1792 1152v-128h-512v128h512zM256 192v960h-128v-960q0 -26 19 -45t45 -19t45 19 t19 45zM1920 192v1088h-1536v-1088q0 -33 -11 -64h1483q26 0 45 19t19 45zM2048 1408v-1216q0 -80 -56 -136t-136 -56h-1664q-80 0 -136 56t-56 136v1088h256v128h1792z" />
 <glyph unicode="&#xf1eb;" horiz-adv-x="2048" d="M1024 13q-20 0 -93 73.5t-73 93.5q0 32 62.5 54t103.5 22t103.5 -22t62.5 -54q0 -20 -73 -93.5t-93 -73.5zM1294 284q-2 0 -40 25t-101.5 50t-128.5 25t-128.5 -25t-101 -50t-40.5 -25q-18 0 -93.5 75t-75.5 93q0 13 10 23q78 77 196 121t233 44t233 -44t196 -121 q10 -10 10 -23q0 -18 -75.5 -93t-93.5 -75zM1567 556q-11 0 -23 8q-136 105 -252 154.5t-268 49.5q-85 0 -170.5 -22t-149 -53t-113.5 -62t-79 -53t-31 -22q-17 0 -92 75t-75 93q0 12 10 22q132 132 320 205t380 73t380 -73t320 -205q10 -10 10 -22q0 -18 -75 -93t-92 -75z M1838 827q-11 0 -22 9q-179 157 -371.5 236.5t-420.5 79.5t-420.5 -79.5t-371.5 -236.5q-11 -9 -22 -9q-17 0 -92.5 75t-75.5 93q0 13 10 23q187 186 445 288t527 102t527 -102t445 -288q10 -10 10 -23q0 -18 -75.5 -93t-92.5 -75z" />
 <glyph unicode="&#xf1ec;" horiz-adv-x="1792" d="M384 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5 t37.5 90.5zM384 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 768q0 53 -37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1536 0v384q0 52 -38 90t-90 38t-90 -38t-38 -90v-384q0 -52 38 -90t90 -38t90 38t38 90zM1152 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z M1536 1088v256q0 26 -19 45t-45 19h-1280q-26 0 -45 -19t-19 -45v-256q0 -26 19 -45t45 -19h1280q26 0 45 19t19 45zM1536 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1408v-1536q0 -52 -38 -90t-90 -38 h-1408q-52 0 -90 38t-38 90v1536q0 52 38 90t90 38h1408q52 0 90 -38t38 -90z" />
-<glyph unicode="&#xf1ed;" horiz-adv-x="1792" d="M1112 1090q0 159 -237 159h-70q-32 0 -59.5 -21.5t-34.5 -52.5l-63 -276q-2 -5 -2 -16q0 -24 17 -39.5t41 -15.5h53q69 0 128.5 13t112.5 41t83.5 81.5t30.5 126.5zM1716 938q0 -265 -220 -428q-219 -161 -612 -161h-61q-32 0 -59 -21.5t-34 -52.5l-73 -316 q-8 -36 -40.5 -61.5t-69.5 -25.5h-213q-31 0 -53 20t-22 51q0 10 13 65h151q34 0 64 23.5t38 56.5l73 316q8 33 37.5 57t63.5 24h61q390 0 607 160t217 421q0 129 -51 207q183 -92 183 -335zM1533 1123q0 -264 -221 -428q-218 -161 -612 -161h-60q-32 0 -59.5 -22t-34.5 -53 l-73 -315q-8 -36 -40 -61.5t-69 -25.5h-214q-31 0 -52.5 19.5t-21.5 51.5q0 8 2 20l300 1301q8 36 40.5 61.5t69.5 25.5h444q68 0 125 -4t120.5 -15t113.5 -30t96.5 -50.5t77.5 -74t49.5 -103.5t18.5 -136z" />
+<glyph unicode="&#xf1ed;" d="M1519 890q18 -84 -4 -204q-87 -444 -565 -444h-44q-25 0 -44 -16.5t-24 -42.5l-4 -19l-55 -346l-2 -15q-5 -26 -24.5 -42.5t-44.5 -16.5h-251q-21 0 -33 15t-9 36q9 56 26.5 168t26.5 168t27 167.5t27 167.5q5 37 43 37h131q133 -2 236 21q175 39 287 144q102 95 155 246 q24 70 35 133q1 6 2.5 7.5t3.5 1t6 -3.5q79 -59 98 -162zM1347 1172q0 -107 -46 -236q-80 -233 -302 -315q-113 -40 -252 -42q0 -1 -90 -1l-90 1q-100 0 -118 -96q-2 -8 -85 -530q-1 -10 -12 -10h-295q-22 0 -36.5 16.5t-11.5 38.5l232 1471q5 29 27.5 48t51.5 19h598 q34 0 97.5 -13t111.5 -32q107 -41 163.5 -123t56.5 -196z" />
 <glyph unicode="&#xf1ee;" horiz-adv-x="1792" d="M602 949q19 -61 31 -123.5t17 -141.5t-14 -159t-62 -145q-21 81 -67 157t-95.5 127t-99 90.5t-78.5 57.5t-33 19q-62 34 -81.5 100t14.5 128t101 81.5t129 -14.5q138 -83 238 -177zM927 1236q11 -25 20.5 -46t36.5 -100.5t42.5 -150.5t25.5 -179.5t0 -205.5t-47.5 -209.5 t-105.5 -208.5q-51 -72 -138 -72q-54 0 -98 31q-57 40 -69 109t28 127q60 85 81 195t13 199.5t-32 180.5t-39 128t-22 52q-31 63 -8.5 129.5t85.5 97.5q34 17 75 17q47 0 88.5 -25t63.5 -69zM1248 567q-17 -160 -72 -311q-17 131 -63 246q25 174 -5 361q-27 178 -94 342 q114 -90 212 -211q9 -37 15 -80q26 -179 7 -347zM1520 1440q9 -17 23.5 -49.5t43.5 -117.5t50.5 -178t34 -227.5t5 -269t-47 -300t-112.5 -323.5q-22 -48 -66 -75.5t-95 -27.5q-39 0 -74 16q-67 31 -92.5 100t4.5 136q58 126 90 257.5t37.5 239.5t-3.5 213.5t-26.5 180.5 t-38.5 138.5t-32.5 90t-15.5 32.5q-34 65 -11.5 135.5t87.5 104.5q37 20 81 20q49 0 91.5 -25.5t66.5 -70.5z" />
 <glyph unicode="&#xf1f0;" horiz-adv-x="2304" d="M1975 546h-138q14 37 66 179l3 9q4 10 10 26t9 26l12 -55zM531 611l-58 295q-11 54 -75 54h-268l-2 -13q311 -79 403 -336zM710 960l-162 -438l-17 89q-26 70 -85 129.5t-131 88.5l135 -510h175l261 641h-176zM849 318h166l104 642h-166zM1617 944q-69 27 -149 27 q-123 0 -201 -59t-79 -153q-1 -102 145 -174q48 -23 67 -41t19 -39q0 -30 -30 -46t-69 -16q-86 0 -156 33l-22 11l-23 -144q74 -34 185 -34q130 -1 208.5 59t80.5 160q0 106 -140 174q-49 25 -71 42t-22 38q0 22 24.5 38.5t70.5 16.5q70 1 124 -24l15 -8zM2042 960h-128 q-65 0 -87 -54l-246 -588h174l35 96h212q5 -22 20 -96h154zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
 <glyph unicode="&#xf1f1;" horiz-adv-x="2304" d="M671 603h-13q-47 0 -47 -32q0 -22 20 -22q17 0 28 15t12 39zM1066 639h62v3q1 4 0.5 6.5t-1 7t-2 8t-4.5 6.5t-7.5 5t-11.5 2q-28 0 -36 -38zM1606 603h-12q-48 0 -48 -32q0 -22 20 -22q17 0 28 15t12 39zM1925 629q0 41 -30 41q-19 0 -31 -20t-12 -51q0 -42 28 -42 q20 0 32.5 20t12.5 52zM480 770h87l-44 -262h-56l32 201l-71 -201h-39l-4 200l-34 -200h-53l44 262h81l2 -163zM733 663q0 -6 -4 -42q-16 -101 -17 -113h-47l1 22q-20 -26 -58 -26q-23 0 -37.5 16t-14.5 42q0 39 26 60.5t73 21.5q14 0 23 -1q0 3 0.5 5.5t1 4.5t0.5 3 q0 20 -36 20q-29 0 -59 -10q0 4 7 48q38 11 67 11q74 0 74 -62zM889 721l-8 -49q-22 3 -41 3q-27 0 -27 -17q0 -8 4.5 -12t21.5 -11q40 -19 40 -60q0 -72 -87 -71q-34 0 -58 6q0 2 7 49q29 -8 51 -8q32 0 32 19q0 7 -4.5 11.5t-21.5 12.5q-43 20 -43 59q0 72 84 72 q30 0 50 -4zM977 721h28l-7 -52h-29q-2 -17 -6.5 -40.5t-7 -38.5t-2.5 -18q0 -16 19 -16q8 0 16 2l-8 -47q-21 -7 -40 -7q-43 0 -45 47q0 12 8 56q3 20 25 146h55zM1180 648q0 -23 -7 -52h-111q-3 -22 10 -33t38 -11q30 0 58 14l-9 -54q-30 -8 -57 -8q-95 0 -95 95 q0 55 27.5 90.5t69.5 35.5q35 0 55.5 -21t20.5 -56zM1319 722q-13 -23 -22 -62q-22 2 -31 -24t-25 -128h-56l3 14q22 130 29 199h51l-3 -33q14 21 25.5 29.5t28.5 4.5zM1506 763l-9 -57q-28 14 -50 14q-31 0 -51 -27.5t-20 -70.5q0 -30 13.5 -47t38.5 -17q21 0 48 13 l-10 -59q-28 -8 -50 -8q-45 0 -71.5 30.5t-26.5 82.5q0 70 35.5 114.5t91.5 44.5q26 0 61 -13zM1668 663q0 -18 -4 -42q-13 -79 -17 -113h-46l1 22q-20 -26 -59 -26q-23 0 -37 16t-14 42q0 39 25.5 60.5t72.5 21.5q15 0 23 -1q2 7 2 13q0 20 -36 20q-29 0 -59 -10q0 4 8 48 q38 11 67 11q73 0 73 -62zM1809 722q-14 -24 -21 -62q-23 2 -31.5 -23t-25.5 -129h-56l3 14q19 104 29 199h52q0 -11 -4 -33q15 21 26.5 29.5t27.5 4.5zM1950 770h56l-43 -262h-53l3 19q-23 -23 -52 -23q-31 0 -49.5 24t-18.5 64q0 53 27.5 92t64.5 39q31 0 53 -29z M2061 640q0 148 -72.5 273t-198 198t-273.5 73q-181 0 -328 -110q127 -116 171 -284h-50q-44 150 -158 253q-114 -103 -158 -253h-50q44 168 171 284q-147 110 -328 110q-148 0 -273.5 -73t-198 -198t-72.5 -273t72.5 -273t198 -198t273.5 -73q181 0 328 110 q-120 111 -165 264h50q46 -138 152 -233q106 95 152 233h50q-45 -153 -165 -264q147 -110 328 -110q148 0 273.5 73t198 198t72.5 273zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
 <glyph unicode="&#xf1f2;" horiz-adv-x="2304" d="M313 759q0 -51 -36 -84q-29 -26 -89 -26h-17v220h17q61 0 89 -27q36 -31 36 -83zM2089 824q0 -52 -64 -52h-19v101h20q63 0 63 -49zM380 759q0 74 -50 120.5t-129 46.5h-95v-333h95q74 0 119 38q60 51 60 128zM410 593h65v333h-65v-333zM730 694q0 40 -20.5 62t-75.5 42 q-29 10 -39.5 19t-10.5 23q0 16 13.5 26.5t34.5 10.5q29 0 53 -27l34 44q-41 37 -98 37q-44 0 -74 -27.5t-30 -67.5q0 -35 18 -55.5t64 -36.5q37 -13 45 -19q19 -12 19 -34q0 -20 -14 -33.5t-36 -13.5q-48 0 -71 44l-42 -40q44 -64 115 -64q51 0 83 30.5t32 79.5zM1008 604 v77q-37 -37 -78 -37q-49 0 -80.5 32.5t-31.5 82.5q0 48 31.5 81.5t77.5 33.5q43 0 81 -38v77q-40 20 -80 20q-74 0 -125.5 -50.5t-51.5 -123.5t51 -123.5t125 -50.5q42 0 81 19zM2240 0v527q-65 -40 -144.5 -84t-237.5 -117t-329.5 -137.5t-417.5 -134.5t-504 -118h1569 q26 0 45 19t19 45zM1389 757q0 75 -53 128t-128 53t-128 -53t-53 -128t53 -128t128 -53t128 53t53 128zM1541 584l144 342h-71l-90 -224l-89 224h-71l142 -342h35zM1714 593h184v56h-119v90h115v56h-115v74h119v57h-184v-333zM2105 593h80l-105 140q76 16 76 94q0 47 -31 73 t-87 26h-97v-333h65v133h9zM2304 1274v-1268q0 -56 -38.5 -95t-93.5 -39h-2040q-55 0 -93.5 39t-38.5 95v1268q0 56 38.5 95t93.5 39h2040q55 0 93.5 -39t38.5 -95z" />
 <glyph unicode="&#xf1f3;" horiz-adv-x="2304" d="M119 854h89l-45 108zM740 328l74 79l-70 79h-163v-49h142v-55h-142v-54h159zM898 406l99 -110v217zM1186 453q0 33 -40 33h-84v-69h83q41 0 41 36zM1475 457q0 29 -42 29h-82v-61h81q43 0 43 32zM1197 923q0 29 -42 29h-82v-60h81q43 0 43 31zM1656 854h89l-44 108z M699 1009v-271h-66v212l-94 -212h-57l-94 212v-212h-132l-25 60h-135l-25 -60h-70l116 271h96l110 -257v257h106l85 -184l77 184h108zM1255 453q0 -20 -5.5 -35t-14 -25t-22.5 -16.5t-26 -10t-31.5 -4.5t-31.5 -1t-32.5 0.5t-29.5 0.5v-91h-126l-80 90l-83 -90h-256v271h260 l80 -89l82 89h207q109 0 109 -89zM964 794v-56h-217v271h217v-57h-152v-49h148v-55h-148v-54h152zM2304 235v-229q0 -55 -38.5 -94.5t-93.5 -39.5h-2040q-55 0 -93.5 39.5t-38.5 94.5v678h111l25 61h55l25 -61h218v46l19 -46h113l20 47v-47h541v99l10 1q10 0 10 -14v-86h279 v23q23 -12 55 -18t52.5 -6.5t63 0.5t51.5 1l25 61h56l25 -61h227v58l34 -58h182v378h-180v-44l-25 44h-185v-44l-23 44h-249q-69 0 -109 -22v22h-172v-22q-24 22 -73 22h-628l-43 -97l-43 97h-198v-44l-22 44h-169l-78 -179v391q0 55 38.5 94.5t93.5 39.5h2040 q55 0 93.5 -39.5t38.5 -94.5v-678h-120q-51 0 -81 -22v22h-177q-55 0 -78 -22v22h-316v-22q-31 22 -87 22h-209v-22q-23 22 -91 22h-234l-54 -58l-50 58h-349v-378h343l55 59l52 -59h211v89h21q59 0 90 13v-102h174v99h8q8 0 10 -2t2 -10v-87h529q57 0 88 24v-24h168 q60 0 95 17zM1546 469q0 -23 -12 -43t-34 -29q25 -9 34 -26t9 -46v-54h-65v45q0 33 -12 43.5t-46 10.5h-69v-99h-65v271h154q48 0 77 -15t29 -58zM1269 936q0 -24 -12.5 -44t-33.5 -29q26 -9 34.5 -25.5t8.5 -46.5v-53h-65q0 9 0.5 26.5t0 25t-3 18.5t-8.5 16t-17.5 8.5 t-29.5 3.5h-70v-98h-64v271l153 -1q49 0 78 -14.5t29 -57.5zM1798 327v-56h-216v271h216v-56h-151v-49h148v-55h-148v-54zM1372 1009v-271h-66v271h66zM2065 357q0 -86 -102 -86h-126v58h126q34 0 34 25q0 16 -17 21t-41.5 5t-49.5 3.5t-42 22.5t-17 55q0 39 26 60t66 21 h130v-57h-119q-36 0 -36 -25q0 -16 17.5 -20.5t42 -4t49 -2.5t42 -21.5t17.5 -54.5zM2304 407v-101q-24 -35 -88 -35h-125v58h125q33 0 33 25q0 13 -12.5 19t-31 5.5t-40 2t-40 8t-31 24t-12.5 48.5q0 39 26.5 60t66.5 21h129v-57h-118q-36 0 -36 -25q0 -20 29 -22t68.5 -5 t56.5 -26zM2139 1008v-270h-92l-122 203v-203h-132l-26 60h-134l-25 -60h-75q-129 0 -129 133q0 138 133 138h63v-59q-7 0 -28 1t-28.5 0.5t-23 -2t-21.5 -6.5t-14.5 -13.5t-11.5 -23t-3 -33.5q0 -38 13.5 -58t49.5 -20h29l92 213h97l109 -256v256h99l114 -188v188h66z" />
-<glyph unicode="&#xf1f4;" horiz-adv-x="2304" d="M322 689h-15q-19 0 -19 18q0 28 19 85q5 15 15 19.5t28 4.5q77 0 77 -49q0 -41 -30.5 -59.5t-74.5 -18.5zM664 528q-47 0 -47 29q0 62 123 62l3 -3q-5 -88 -79 -88zM1438 687h-15q-19 0 -19 19q0 28 19 85q5 15 14.5 19t28.5 4q77 0 77 -49q0 -41 -30.5 -59.5 t-74.5 -18.5zM1780 527q-47 0 -47 30q0 62 123 62l3 -3q-5 -89 -79 -89zM373 894h-128q-8 0 -14.5 -4t-8.5 -7.5t-7 -12.5q-3 -7 -45 -190t-42 -192q0 -7 5.5 -12.5t13.5 -5.5h62q25 0 32.5 34.5l15 69t32.5 34.5q47 0 87.5 7.5t80.5 24.5t63.5 52.5t23.5 84.5 q0 36 -14.5 61t-41 36.5t-53.5 15.5t-62 4zM719 798q-38 0 -74 -6q-2 0 -8.5 -1t-9 -1.5l-7.5 -1.5t-7.5 -2t-6.5 -3t-6.5 -4t-5 -5t-4.5 -7t-4 -9q-9 -29 -9 -39t9 -10q5 0 21.5 5t19.5 6q30 8 58 8q74 0 74 -36q0 -11 -10 -14q-8 -2 -18 -3t-21.5 -1.5t-17.5 -1.5 q-38 -4 -64.5 -10t-56.5 -19.5t-45.5 -39t-15.5 -62.5q0 -38 26 -59.5t64 -21.5q24 0 45.5 6.5t33 13t38.5 23.5q-3 -7 -3 -15t5.5 -13.5t12.5 -5.5h56q1 1 7 3.5t7.5 3.5t5 3.5t5 5.5t2.5 8l45 194q4 13 4 30q0 81 -145 81zM1247 793h-74q-22 0 -39 -23q-5 -7 -29.5 -51 t-46.5 -81.5t-26 -38.5l-5 4q0 77 -27 166q-1 5 -3.5 8.5t-6 6.5t-6.5 5t-8.5 3t-8.5 1.5t-9.5 1t-9 0.5h-10h-8.5q-38 0 -38 -21l1 -5q5 -53 25 -151t25 -143q2 -16 2 -24q0 -19 -30.5 -61.5t-30.5 -58.5q0 -13 40 -13q61 0 76 25l245 415q10 20 10 26q0 9 -8 9zM1489 892 h-129q-18 0 -29 -23q-6 -13 -46.5 -191.5t-40.5 -190.5q0 -20 43 -20h7.5h9h9t9.5 1t8.5 2t8.5 3t6.5 4.5t5.5 6t3 8.5l21 91q2 10 10.5 17t19.5 7q47 0 87.5 7t80.5 24.5t63.5 52.5t23.5 84q0 36 -14.5 61t-41 36.5t-53.5 15.5t-62 4zM1835 798q-26 0 -74 -6 q-38 -6 -48 -16q-7 -8 -11 -19q-8 -24 -8 -39q0 -10 8 -10q1 0 41 12q30 8 58 8q74 0 74 -36q0 -12 -10 -14q-4 -1 -57 -7q-38 -4 -64.5 -10t-56.5 -19.5t-45.5 -39t-15.5 -62.5t26 -58.5t64 -21.5q24 0 45 6t34 13t38 24q-3 -15 -3 -16q0 -5 2 -8.5t6.5 -5.5t8 -3.5 t10.5 -2t9.5 -0.5h9.5h8q42 0 48 25l45 194q3 15 3 31q0 81 -145 81zM2157 889h-55q-25 0 -33 -40q-10 -44 -36.5 -167t-42.5 -190v-5q0 -16 16 -18h1h57q10 0 18.5 6.5t10.5 16.5l83 374h-1l1 5q0 7 -5.5 12.5t-13.5 5.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048 q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf1f4;" horiz-adv-x="2304" d="M745 630q0 -37 -25.5 -61.5t-62.5 -24.5q-29 0 -46.5 16t-17.5 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM1530 779q0 -42 -22 -57t-66 -15l-32 -1l17 107q2 11 13 11h18q22 0 35 -2t25 -12.5t12 -30.5zM1881 630q0 -36 -25.5 -61t-61.5 -25q-29 0 -47 16 t-18 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM513 801q0 59 -38.5 85.5t-100.5 26.5h-160q-19 0 -21 -19l-65 -408q-1 -6 3 -11t10 -5h76q20 0 22 19l18 110q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM822 489l41 261q1 6 -3 11t-10 5h-76 q-14 0 -17 -33q-27 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q28 0 58 12t48 32q-4 -12 -4 -21q0 -16 13 -16h69q19 0 22 19zM1269 752q0 5 -4 9.5t-9 4.5h-77q-11 0 -18 -10l-106 -156l-44 150q-5 16 -22 16h-75q-5 0 -9 -4.5t-4 -9.5q0 -2 19.5 -59 t42 -123t23.5 -70q-82 -112 -82 -120q0 -13 13 -13h77q11 0 18 10l255 368q2 2 2 7zM1649 801q0 59 -38.5 85.5t-100.5 26.5h-159q-20 0 -22 -19l-65 -408q-1 -6 3 -11t10 -5h82q12 0 16 13l18 116q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q86 0 135 48.5t49 134.5zM1958 489 l41 261q1 6 -3 11t-10 5h-76q-14 0 -17 -33q-26 40 -95 40q-72 0 -122.5 -54t-50.5 -127q0 -59 34.5 -94t92.5 -35q29 0 59 12t47 32q0 -1 -2 -9t-2 -12q0 -16 13 -16h69q19 0 22 19zM2176 898v1q0 14 -13 14h-74q-11 0 -13 -11l-65 -416l-1 -2q0 -5 4 -9.5t10 -4.5h66 q19 0 21 19zM392 764q-5 -35 -26 -46t-60 -11l-33 -1l17 107q2 11 13 11h19q40 0 58 -11.5t12 -48.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
 <glyph unicode="&#xf1f5;" horiz-adv-x="2304" d="M1597 633q0 -69 -21 -106q-19 -35 -52 -35q-23 0 -41 9v224q29 30 57 30q57 0 57 -122zM2035 669h-110q6 98 56 98q51 0 54 -98zM476 534q0 59 -33 91.5t-101 57.5q-36 13 -52 24t-16 25q0 26 38 26q58 0 124 -33l18 112q-67 32 -149 32q-77 0 -123 -38q-48 -39 -48 -109 q0 -58 32.5 -90.5t99.5 -56.5q39 -14 54.5 -25.5t15.5 -27.5q0 -31 -48 -31q-29 0 -70 12.5t-72 30.5l-18 -113q72 -41 168 -41q81 0 129 37q51 41 51 117zM771 749l19 111h-96v135l-129 -21l-18 -114l-46 -8l-17 -103h62v-219q0 -84 44 -120q38 -30 111 -30q32 0 79 11v118 q-32 -7 -44 -7q-42 0 -42 50v197h77zM1087 724v139q-15 3 -28 3q-32 0 -55.5 -16t-33.5 -46l-10 56h-131v-471h150v306q26 31 82 31q16 0 26 -2zM1124 389h150v471h-150v-471zM1746 638q0 122 -45 179q-40 52 -111 52q-64 0 -117 -56l-8 47h-132v-645l150 25v151 q36 -11 68 -11q83 0 134 56q61 65 61 202zM1278 986q0 33 -23 56t-56 23t-56 -23t-23 -56t23 -56.5t56 -23.5t56 23.5t23 56.5zM2176 629q0 113 -48 176q-50 64 -144 64q-96 0 -151.5 -66t-55.5 -180q0 -128 63 -188q55 -55 161 -55q101 0 160 40l-16 103q-57 -31 -128 -31 q-43 0 -63 19q-23 19 -28 66h248q2 14 2 52zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
 <glyph unicode="&#xf1f6;" horiz-adv-x="2048" d="M1558 684q61 -356 298 -556q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5zM1024 -176q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5zM2026 1424q8 -10 7.5 -23.5t-10.5 -22.5 l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5 l418 363q10 8 23.5 7t21.5 -11z" />
 <glyph unicode="&#xf1f7;" horiz-adv-x="2048" d="M1040 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM503 315l877 760q-42 88 -132.5 146.5t-223.5 58.5q-93 0 -169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -384 -137 -645zM1856 128 q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5l149 129h757q-166 187 -227 459l111 97q61 -356 298 -556zM1942 1520l84 -96q8 -10 7.5 -23.5t-10.5 -22.5l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161 q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5l418 363q10 8 23.5 7t21.5 -11z" />
@@ -513,8 +513,143 @@
 <glyph unicode="&#xf20a;" horiz-adv-x="2048" d="M785 528h207q-14 -158 -98.5 -248.5t-214.5 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-203q-5 64 -35.5 99t-81.5 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t40 -51.5t66 -18q95 0 109 139zM1497 528h206 q-14 -158 -98 -248.5t-214 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-204q-4 64 -35 99t-81 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t39.5 -51.5t65.5 -18q49 0 76.5 38t33.5 101zM1856 647q0 207 -15.5 307 t-60.5 161q-6 8 -13.5 14t-21.5 15t-16 11q-86 63 -697 63q-625 0 -710 -63q-5 -4 -17.5 -11.5t-21 -14t-14.5 -14.5q-45 -60 -60 -159.5t-15 -308.5q0 -208 15 -307.5t60 -160.5q6 -8 15 -15t20.5 -14t17.5 -12q44 -33 239.5 -49t470.5 -16q610 0 697 65q5 4 17 11t20.5 14 t13.5 16q46 60 61 159t15 309zM2048 1408v-1536h-2048v1536h2048z" />
 <glyph unicode="&#xf20b;" d="M992 912v-496q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v496q0 112 -80 192t-192 80h-272v-1152q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v1344q0 14 9 23t23 9h464q135 0 249 -66.5t180.5 -180.5t66.5 -249zM1376 1376v-880q0 -135 -66.5 -249t-180.5 -180.5 t-249 -66.5h-464q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h160q14 0 23 -9t9 -23v-768h272q112 0 192 80t80 192v880q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
 <glyph unicode="&#xf20c;" d="M1311 694v-114q0 -24 -13.5 -38t-37.5 -14h-202q-24 0 -38 14t-14 38v114q0 24 14 38t38 14h202q24 0 37.5 -14t13.5 -38zM821 464v250q0 53 -32.5 85.5t-85.5 32.5h-133q-68 0 -96 -52q-28 52 -96 52h-130q-53 0 -85.5 -32.5t-32.5 -85.5v-250q0 -22 21 -22h55 q22 0 22 22v230q0 24 13.5 38t38.5 14h94q24 0 38 -14t14 -38v-230q0 -22 21 -22h54q22 0 22 22v230q0 24 14 38t38 14h97q24 0 37.5 -14t13.5 -38v-230q0 -22 22 -22h55q21 0 21 22zM1410 560v154q0 53 -33 85.5t-86 32.5h-264q-53 0 -86 -32.5t-33 -85.5v-410 q0 -21 22 -21h55q21 0 21 21v180q31 -42 94 -42h191q53 0 86 32.5t33 85.5zM1536 1176v-1072q0 -96 -68 -164t-164 -68h-1072q-96 0 -164 68t-68 164v1072q0 96 68 164t164 68h1072q96 0 164 -68t68 -164z" />
-<glyph unicode="&#xf20d;" horiz-adv-x="1792" />
-<glyph unicode="&#xf20e;" horiz-adv-x="1792" />
+<glyph unicode="&#xf20d;" d="M915 450h-294l147 551zM1001 128h311l-324 1024h-440l-324 -1024h311l383 314zM1536 1120v-960q0 -118 -85 -203t-203 -85h-960q-118 0 -203 85t-85 203v960q0 118 85 203t203 85h960q118 0 203 -85t85 -203z" />
+<glyph unicode="&#xf20e;" horiz-adv-x="2048" d="M2048 641q0 -21 -13 -36.5t-33 -19.5l-205 -356q3 -9 3 -18q0 -20 -12.5 -35.5t-32.5 -19.5l-193 -337q3 -8 3 -16q0 -23 -16.5 -40t-40.5 -17q-25 0 -41 18h-400q-17 -20 -43 -20t-43 20h-399q-17 -20 -43 -20q-23 0 -40 16.5t-17 40.5q0 8 4 20l-193 335 q-20 4 -32.5 19.5t-12.5 35.5q0 9 3 18l-206 356q-20 5 -32.5 20.5t-12.5 35.5q0 21 13.5 36.5t33.5 19.5l199 344q0 1 -0.5 3t-0.5 3q0 36 34 51l209 363q-4 10 -4 18q0 24 17 40.5t40 16.5q26 0 44 -21h396q16 21 43 21t43 -21h398q18 21 44 21q23 0 40 -16.5t17 -40.5 q0 -6 -4 -18l207 -358q23 -1 39 -17.5t16 -38.5q0 -13 -7 -27l187 -324q19 -4 31.5 -19.5t12.5 -35.5zM1063 -158h389l-342 354h-143l-342 -354h360q18 16 39 16t39 -16zM112 654q1 -4 1 -13q0 -10 -2 -15l208 -360q2 0 4.5 -1t5.5 -2.5l5 -2.5l188 199v347l-187 194 q-13 -8 -29 -10zM986 1438h-388l190 -200l554 200h-280q-16 -16 -38 -16t-38 16zM1689 226q1 6 5 11l-64 68l-17 -79h76zM1583 226l22 105l-252 266l-296 -307l63 -64h463zM1495 -142l16 28l65 310h-427l333 -343q8 4 13 5zM578 -158h5l342 354h-373v-335l4 -6q14 -5 22 -13 zM552 226h402l64 66l-309 321l-157 -166v-221zM359 226h163v189l-168 -177q4 -8 5 -12zM358 1051q0 -1 0.5 -2t0.5 -2q0 -16 -8 -29l171 -177v269zM552 1121v-311l153 -157l297 314l-223 236zM556 1425l-4 -8v-264l205 74l-191 201q-6 -2 -10 -3zM1447 1438h-16l-621 -224 l213 -225zM1023 946l-297 -315l311 -319l296 307zM688 634l-136 141v-284zM1038 270l-42 -44h85zM1374 618l238 -251l132 624l-3 5l-1 1zM1718 1018q-8 13 -8 29v2l-216 376q-5 1 -13 5l-437 -463l310 -327zM522 1142v223l-163 -282zM522 196h-163l163 -283v283zM1607 196 l-48 -227l130 227h-82zM1729 266l207 361q-2 10 -2 14q0 1 3 16l-171 296l-129 -612l77 -82q5 3 15 7z" />
+<glyph unicode="&#xf210;" d="M0 856q0 131 91.5 226.5t222.5 95.5h742l352 358v-1470q0 -132 -91.5 -227t-222.5 -95h-780q-131 0 -222.5 95t-91.5 227v790zM1232 102l-176 180v425q0 46 -32 79t-78 33h-484q-46 0 -78 -33t-32 -79v-492q0 -46 32.5 -79.5t77.5 -33.5h770z" />
+<glyph unicode="&#xf211;" d="M934 1386q-317 -121 -556 -362.5t-358 -560.5q-20 89 -20 176q0 208 102.5 384.5t278.5 279t384 102.5q82 0 169 -19zM1203 1267q93 -65 164 -155q-389 -113 -674.5 -400.5t-396.5 -676.5q-93 72 -155 162q112 386 395 671t667 399zM470 -67q115 356 379.5 622t619.5 384 q40 -92 54 -195q-292 -120 -516 -345t-343 -518q-103 14 -194 52zM1536 -125q-193 50 -367 115q-135 -84 -290 -107q109 205 274 370.5t369 275.5q-21 -152 -101 -284q65 -175 115 -370z" />
+<glyph unicode="&#xf212;" horiz-adv-x="2048" d="M1893 1144l155 -1272q-131 0 -257 57q-200 91 -393 91q-226 0 -374 -148q-148 148 -374 148q-193 0 -393 -91q-128 -57 -252 -57h-5l155 1272q224 127 482 127q233 0 387 -106q154 106 387 106q258 0 482 -127zM1398 157q129 0 232 -28.5t260 -93.5l-124 1021 q-171 78 -368 78q-224 0 -374 -141q-150 141 -374 141q-197 0 -368 -78l-124 -1021q105 43 165.5 65t148.5 39.5t178 17.5q202 0 374 -108q172 108 374 108zM1438 191l-55 907q-211 -4 -359 -155q-152 155 -374 155q-176 0 -336 -66l-114 -941q124 51 228.5 76t221.5 25 q209 0 374 -102q172 107 374 102z" />
+<glyph unicode="&#xf213;" horiz-adv-x="2048" d="M1500 165v733q0 21 -15 36t-35 15h-93q-20 0 -35 -15t-15 -36v-733q0 -20 15 -35t35 -15h93q20 0 35 15t15 35zM1216 165v531q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-531q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM924 165v429q0 20 -15 35t-35 15h-101 q-20 0 -35 -15t-15 -35v-429q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM632 165v362q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-362q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM2048 311q0 -166 -118 -284t-284 -118h-1244q-166 0 -284 118t-118 284 q0 116 63 214.5t168 148.5q-10 34 -10 73q0 113 80.5 193.5t193.5 80.5q102 0 180 -67q45 183 194 300t338 117q149 0 275 -73.5t199.5 -199.5t73.5 -275q0 -66 -14 -122q135 -33 221 -142.5t86 -247.5z" />
+<glyph unicode="&#xf214;" d="M0 1536h1536v-1392l-776 -338l-760 338v1392zM1436 209v926h-1336v-926l661 -294zM1436 1235v201h-1336v-201h1336zM181 937v-115h-37v115h37zM181 789v-115h-37v115h37zM181 641v-115h-37v115h37zM181 493v-115h-37v115h37zM181 345v-115h-37v115h37zM207 202l15 34 l105 -47l-15 -33zM343 142l15 34l105 -46l-15 -34zM478 82l15 34l105 -46l-15 -34zM614 23l15 33l104 -46l-15 -34zM797 10l105 46l15 -33l-105 -47zM932 70l105 46l15 -34l-105 -46zM1068 130l105 46l15 -34l-105 -46zM1203 189l105 47l15 -34l-105 -46zM259 1389v-36h-114 v36h114zM421 1389v-36h-115v36h115zM583 1389v-36h-115v36h115zM744 1389v-36h-114v36h114zM906 1389v-36h-114v36h114zM1068 1389v-36h-115v36h115zM1230 1389v-36h-115v36h115zM1391 1389v-36h-114v36h114zM181 1049v-79h-37v115h115v-36h-78zM421 1085v-36h-115v36h115z M583 1085v-36h-115v36h115zM744 1085v-36h-114v36h114zM906 1085v-36h-114v36h114zM1068 1085v-36h-115v36h115zM1230 1085v-36h-115v36h115zM1355 970v79h-78v36h115v-115h-37zM1355 822v115h37v-115h-37zM1355 674v115h37v-115h-37zM1355 526v115h37v-115h-37zM1355 378 v115h37v-115h-37zM1355 230v115h37v-115h-37zM760 265q-129 0 -221 91.5t-92 221.5q0 129 92 221t221 92q130 0 221.5 -92t91.5 -221q0 -130 -91.5 -221.5t-221.5 -91.5zM595 646q0 -36 19.5 -56.5t49.5 -25t64 -7t64 -2t49.5 -9t19.5 -30.5q0 -49 -112 -49q-97 0 -123 51 h-3l-31 -63q67 -42 162 -42q29 0 56.5 5t55.5 16t45.5 33t17.5 53q0 46 -27.5 69.5t-67.5 27t-79.5 3t-67 5t-27.5 25.5q0 21 20.5 33t40.5 15t41 3q34 0 70.5 -11t51.5 -34h3l30 58q-3 1 -21 8.5t-22.5 9t-19.5 7t-22 7t-20 4.5t-24 4t-23 1q-29 0 -56.5 -5t-54 -16.5 t-43 -34t-16.5 -53.5z" />
+<glyph unicode="&#xf215;" horiz-adv-x="2048" d="M863 504q0 112 -79.5 191.5t-191.5 79.5t-191 -79.5t-79 -191.5t79 -191t191 -79t191.5 79t79.5 191zM1726 505q0 112 -79 191t-191 79t-191.5 -79t-79.5 -191q0 -113 79.5 -192t191.5 -79t191 79.5t79 191.5zM2048 1314v-1348q0 -44 -31.5 -75.5t-76.5 -31.5h-1832 q-45 0 -76.5 31.5t-31.5 75.5v1348q0 44 31.5 75.5t76.5 31.5h431q44 0 76 -31.5t32 -75.5v-161h754v161q0 44 32 75.5t76 31.5h431q45 0 76.5 -31.5t31.5 -75.5z" />
+<glyph unicode="&#xf216;" horiz-adv-x="2048" d="M1430 953zM1690 749q148 0 253 -98.5t105 -244.5q0 -157 -109 -261.5t-267 -104.5q-85 0 -162 27.5t-138 73.5t-118 106t-109 126.5t-103.5 132.5t-108.5 126t-117 106t-136 73.5t-159 27.5q-154 0 -251.5 -91.5t-97.5 -244.5q0 -157 104 -250t263 -93q100 0 208 37.5 t193 98.5q5 4 21 18.5t30 24t22 9.5q14 0 24.5 -10.5t10.5 -24.5q0 -24 -60 -77q-101 -88 -234.5 -142t-260.5 -54q-133 0 -245.5 58t-180 165t-67.5 241q0 205 141.5 341t347.5 136q120 0 226.5 -43.5t185.5 -113t151.5 -153t139 -167.5t133.5 -153.5t149.5 -113 t172.5 -43.5q102 0 168.5 61.5t66.5 162.5q0 95 -64.5 159t-159.5 64q-30 0 -81.5 -18.5t-68.5 -18.5q-20 0 -35.5 15t-15.5 35q0 18 8.5 57t8.5 59q0 159 -107.5 263t-266.5 104q-58 0 -111.5 -18.5t-84 -40.5t-55.5 -40.5t-33 -18.5q-15 0 -25.5 10.5t-10.5 25.5 q0 19 25 46q59 67 147 103.5t182 36.5q191 0 318 -125.5t127 -315.5q0 -37 -4 -66q57 15 115 15z" />
+<glyph unicode="&#xf217;" horiz-adv-x="1664" d="M1216 832q0 26 -19 45t-45 19h-128v128q0 26 -19 45t-45 19t-45 -19t-19 -45v-128h-128q-26 0 -45 -19t-19 -45t19 -45t45 -19h128v-128q0 -26 19 -45t45 -19t45 19t19 45v128h128q26 0 45 19t19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920 q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf218;" horiz-adv-x="1664" d="M1280 832q0 26 -19 45t-45 19t-45 -19l-147 -146v293q0 26 -19 45t-45 19t-45 -19t-19 -45v-293l-147 146q-19 19 -45 19t-45 -19t-19 -45t19 -45l256 -256q19 -19 45 -19t45 19l256 256q19 19 19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920 q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf219;" horiz-adv-x="2048" d="M212 768l623 -665l-300 665h-323zM1024 -4l349 772h-698zM538 896l204 384h-262l-288 -384h346zM1213 103l623 665h-323zM683 896h682l-204 384h-274zM1510 896h346l-288 384h-262zM1651 1382l384 -512q14 -18 13 -41.5t-17 -40.5l-960 -1024q-18 -20 -47 -20t-47 20 l-960 1024q-16 17 -17 40.5t13 41.5l384 512q18 26 51 26h1152q33 0 51 -26z" />
+<glyph unicode="&#xf21a;" horiz-adv-x="2048" d="M1811 -19q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83 q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83 q19 19 45 19t45 -19l83 -83zM237 19q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -82l83 82q19 19 45 19t45 -19l83 -82l64 64v293l-210 314q-17 26 -7 56.5t40 40.5l177 58v299h128v128h256v128h256v-128h256v-128h128v-299l177 -58q30 -10 40 -40.5t-7 -56.5l-210 -314 v-293l19 18q19 19 45 19t45 -19l83 -82l83 82q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83 q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83zM640 1152v-128l384 128l384 -128v128h-128v128h-512v-128h-128z" />
+<glyph unicode="&#xf21b;" d="M576 0l96 448l-96 128l-128 64zM832 0l128 640l-128 -64l-96 -128zM992 1010q-2 4 -4 6q-10 8 -96 8q-70 0 -167 -19q-7 -2 -21 -2t-21 2q-97 19 -167 19q-86 0 -96 -8q-2 -2 -4 -6q2 -18 4 -27q2 -3 7.5 -6.5t7.5 -10.5q2 -4 7.5 -20.5t7 -20.5t7.5 -17t8.5 -17t9 -14 t12 -13.5t14 -9.5t17.5 -8t20.5 -4t24.5 -2q36 0 59 12.5t32.5 30t14.5 34.5t11.5 29.5t17.5 12.5h12q11 0 17.5 -12.5t11.5 -29.5t14.5 -34.5t32.5 -30t59 -12.5q13 0 24.5 2t20.5 4t17.5 8t14 9.5t12 13.5t9 14t8.5 17t7.5 17t7 20.5t7.5 20.5q2 7 7.5 10.5t7.5 6.5 q2 9 4 27zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 61 4.5 118t19 125.5t37.5 123.5t63.5 103.5t93.5 74.5l-90 220h214q-22 64 -22 128q0 12 2 32q-194 40 -194 96q0 57 210 99q17 62 51.5 134t70.5 114q32 37 76 37q30 0 84 -31t84 -31t84 31 t84 31q44 0 76 -37q36 -42 70.5 -114t51.5 -134q210 -42 210 -99q0 -56 -194 -96q7 -81 -20 -160h214l-82 -225q63 -33 107.5 -96.5t65.5 -143.5t29 -151.5t8 -148.5z" />
+<glyph unicode="&#xf21c;" horiz-adv-x="2304" d="M2301 500q12 -103 -22 -198.5t-99 -163.5t-158.5 -106t-196.5 -31q-161 11 -279.5 125t-134.5 274q-12 111 27.5 210.5t118.5 170.5l-71 107q-96 -80 -151 -194t-55 -244q0 -27 -18.5 -46.5t-45.5 -19.5h-256h-69q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5 t-131.5 316.5t131.5 316.5t316.5 131.5q76 0 152 -27l24 45q-123 110 -304 110h-64q-26 0 -45 19t-19 45t19 45t45 19h128q78 0 145 -13.5t116.5 -38.5t71.5 -39.5t51 -36.5h512h115l-85 128h-222q-30 0 -49 22.5t-14 52.5q4 23 23 38t43 15h253q33 0 53 -28l70 -105 l114 114q19 19 46 19h101q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-179l115 -172q131 63 275 36q143 -26 244 -134.5t118 -253.5zM448 128q115 0 203 72.5t111 183.5h-314q-35 0 -55 31q-18 32 -1 63l147 277q-47 13 -91 13q-132 0 -226 -94t-94 -226t94 -226 t226 -94zM1856 128q132 0 226 94t94 226t-94 226t-226 94q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94z" />
+<glyph unicode="&#xf21d;" d="M1408 0q0 -63 -61.5 -113.5t-164 -81t-225 -46t-253.5 -15.5t-253.5 15.5t-225 46t-164 81t-61.5 113.5q0 49 33 88.5t91 66.5t118 44.5t131 29.5q26 5 48 -10.5t26 -41.5q5 -26 -10.5 -48t-41.5 -26q-58 -10 -106 -23.5t-76.5 -25.5t-48.5 -23.5t-27.5 -19.5t-8.5 -12 q3 -11 27 -26.5t73 -33t114 -32.5t160.5 -25t201.5 -10t201.5 10t160.5 25t114 33t73 33.5t27 27.5q-1 4 -8.5 11t-27.5 19t-48.5 23.5t-76.5 25t-106 23.5q-26 4 -41.5 26t-10.5 48q4 26 26 41.5t48 10.5q71 -12 131 -29.5t118 -44.5t91 -66.5t33 -88.5zM1024 896v-384 q0 -26 -19 -45t-45 -19h-64v-384q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v384h-64q-26 0 -45 19t-19 45v384q0 53 37.5 90.5t90.5 37.5h384q53 0 90.5 -37.5t37.5 -90.5zM928 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5 t158.5 -65.5t65.5 -158.5z" />
+<glyph unicode="&#xf21e;" horiz-adv-x="1792" d="M1280 512h305q-5 -6 -10 -10.5t-9 -7.5l-3 -4l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-5 2 -21 20h369q22 0 39.5 13.5t22.5 34.5l70 281l190 -667q6 -20 23 -33t39 -13q21 0 38 13t23 33l146 485l56 -112q18 -35 57 -35zM1792 940q0 -145 -103 -300h-369l-111 221 q-8 17 -25.5 27t-36.5 8q-45 -5 -56 -46l-129 -430l-196 686q-6 20 -23.5 33t-39.5 13t-39 -13.5t-22 -34.5l-116 -464h-423q-103 155 -103 300q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124 t127 -344z" />
+<glyph unicode="&#xf221;" horiz-adv-x="1280" d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292 q11 134 80.5 249t182 188t245.5 88q170 19 319 -54t236 -212t87 -306zM128 960q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5z" />
+<glyph unicode="&#xf222;" d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-382 -383q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5 q203 0 359 -126l382 382h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf223;" horiz-adv-x="1280" d="M830 1220q145 -72 233.5 -210.5t88.5 -305.5q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5 t-147.5 384.5q0 167 88.5 305.5t233.5 210.5q-165 96 -228 273q-6 16 3.5 29.5t26.5 13.5h69q21 0 29 -20q44 -106 140 -171t214 -65t214 65t140 171q8 20 37 20h61q17 0 26.5 -13.5t3.5 -29.5q-63 -177 -228 -273zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5 t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf224;" d="M1024 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64 q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-149 16 -270.5 103t-186.5 223.5t-53 291.5q16 204 160 353.5t347 172.5q118 14 228 -19t198 -103l255 254h-134q-14 0 -23 9t-9 23v64zM576 256q185 0 316.5 131.5t131.5 316.5t-131.5 316.5 t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf225;" horiz-adv-x="1792" d="M1280 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64 q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5t-147.5 384.5q0 201 126 359l-52 53l-101 -111q-9 -10 -22 -10.5t-23 7.5l-48 44q-10 8 -10.5 21.5t8.5 23.5l105 115l-111 112v-134q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9 t-9 23v288q0 26 19 45t45 19h288q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-133l106 -107l86 94q9 10 22 10.5t23 -7.5l48 -44q10 -8 10.5 -21.5t-8.5 -23.5l-90 -99l57 -56q158 126 359 126t359 -126l255 254h-134q-14 0 -23 9t-9 23v64zM832 256q185 0 316.5 131.5 t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf226;" horiz-adv-x="1792" d="M1790 1007q12 -155 -52.5 -292t-186 -224t-271.5 -103v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-512v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23 t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292q17 206 164.5 356.5t352.5 169.5q206 21 377 -94q171 115 377 94q205 -19 352.5 -169.5t164.5 -356.5zM896 647q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM576 512q115 0 218 57q-154 165 -154 391 q0 224 154 391q-103 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5zM1152 128v260q-137 15 -256 94q-119 -79 -256 -94v-260h512zM1216 512q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5q-115 0 -218 -57q154 -167 154 -391 q0 -226 -154 -391q103 -57 218 -57z" />
+<glyph unicode="&#xf227;" horiz-adv-x="1920" d="M1536 1120q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-31 -182 -166 -312t-318 -156q-210 -29 -384.5 80t-241.5 300q-117 6 -221 57.5t-177.5 133t-113.5 192.5t-32 230 q9 135 78 252t182 191.5t248 89.5q118 14 227.5 -19t198.5 -103l255 254h-134q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q59 -74 93 -169q182 -9 328 -124l255 254h-134q-14 0 -23 9 t-9 23v64zM1024 704q0 20 -4 58q-162 -25 -271 -150t-109 -292q0 -20 4 -58q162 25 271 150t109 292zM128 704q0 -168 111 -294t276 -149q-3 29 -3 59q0 210 135 369.5t338 196.5q-53 120 -163.5 193t-245.5 73q-185 0 -316.5 -131.5t-131.5 -316.5zM1088 -128 q185 0 316.5 131.5t131.5 316.5q0 168 -111 294t-276 149q3 -29 3 -59q0 -210 -135 -369.5t-338 -196.5q53 -120 163.5 -193t245.5 -73z" />
+<glyph unicode="&#xf228;" horiz-adv-x="2048" d="M1664 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-32 -180 -164.5 -310t-313.5 -157q-223 -34 -409 90q-117 -78 -256 -93v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23 t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-155 17 -279.5 109.5t-187 237.5t-39.5 307q25 187 159.5 322.5t320.5 164.5q224 34 410 -90q146 97 320 97q201 0 359 -126l255 254h-134q-14 0 -23 9 t-9 23v64zM896 391q128 131 128 313t-128 313q-128 -131 -128 -313t128 -313zM128 704q0 -185 131.5 -316.5t316.5 -131.5q117 0 218 57q-154 167 -154 391t154 391q-101 57 -218 57q-185 0 -316.5 -131.5t-131.5 -316.5zM1216 256q185 0 316.5 131.5t131.5 316.5 t-131.5 316.5t-316.5 131.5q-117 0 -218 -57q154 -167 154 -391t-154 -391q101 -57 218 -57z" />
+<glyph unicode="&#xf229;" d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-213 -214l140 -140q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-140 141l-78 -79q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5 t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5q203 0 359 -126l78 78l-172 172q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l172 -172l213 213h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5 t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf22a;" horiz-adv-x="1280" d="M640 892q217 -24 364.5 -187.5t147.5 -384.5q0 -167 -87 -306t-236 -212t-319 -54q-133 15 -245.5 88t-182 188t-80.5 249q-12 155 52.5 292t186 224t271.5 103v132h-160q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h160v165l-92 -92q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22 t9 23l202 201q19 19 45 19t45 -19l202 -201q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-92 92v-165h160q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-160v-132zM576 -128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5 t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf22b;" horiz-adv-x="2048" d="M1901 621q19 -19 19 -45t-19 -45l-294 -294q-9 -10 -22.5 -10t-22.5 10l-45 45q-10 9 -10 22.5t10 22.5l185 185h-294v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-132q-24 -217 -187.5 -364.5t-384.5 -147.5q-167 0 -306 87t-212 236t-54 319q15 133 88 245.5 t188 182t249 80.5q155 12 292 -52.5t224 -186t103 -271.5h132v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224h294l-185 185q-10 9 -10 22.5t10 22.5l45 45q9 10 22.5 10t22.5 -10zM576 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5 t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf22c;" horiz-adv-x="1280" d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-612q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v612q-217 24 -364.5 187.5t-147.5 384.5q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM576 512q185 0 316.5 131.5 t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf22d;" horiz-adv-x="1280" d="M1024 576q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1152 576q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123 t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5z" />
+<glyph unicode="&#xf22e;" horiz-adv-x="1792" />
+<glyph unicode="&#xf22f;" horiz-adv-x="1792" />
+<glyph unicode="&#xf230;" d="M1451 1408q35 0 60 -25t25 -60v-1366q0 -35 -25 -60t-60 -25h-391v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-735q-35 0 -60 25t-25 60v1366q0 35 25 60t60 25h1366z" />
+<glyph unicode="&#xf231;" horiz-adv-x="1280" d="M0 939q0 108 37.5 203.5t103.5 166.5t152 123t185 78t202 26q158 0 294 -66.5t221 -193.5t85 -287q0 -96 -19 -188t-60 -177t-100 -149.5t-145 -103t-189 -38.5q-68 0 -135 32t-96 88q-10 -39 -28 -112.5t-23.5 -95t-20.5 -71t-26 -71t-32 -62.5t-46 -77.5t-62 -86.5 l-14 -5l-9 10q-15 157 -15 188q0 92 21.5 206.5t66.5 287.5t52 203q-32 65 -32 169q0 83 52 156t132 73q61 0 95 -40.5t34 -102.5q0 -66 -44 -191t-44 -187q0 -63 45 -104.5t109 -41.5q55 0 102 25t78.5 68t56 95t38 110.5t20 111t6.5 99.5q0 173 -109.5 269.5t-285.5 96.5 q-200 0 -334 -129.5t-134 -328.5q0 -44 12.5 -85t27 -65t27 -45.5t12.5 -30.5q0 -28 -15 -73t-37 -45q-2 0 -17 3q-51 15 -90.5 56t-61 94.5t-32.5 108t-11 106.5z" />
+<glyph unicode="&#xf232;" d="M985 562q13 0 97.5 -44t89.5 -53q2 -5 2 -15q0 -33 -17 -76q-16 -39 -71 -65.5t-102 -26.5q-57 0 -190 62q-98 45 -170 118t-148 185q-72 107 -71 194v8q3 91 74 158q24 22 52 22q6 0 18 -1.5t19 -1.5q19 0 26.5 -6.5t15.5 -27.5q8 -20 33 -88t25 -75q0 -21 -34.5 -57.5 t-34.5 -46.5q0 -7 5 -15q34 -73 102 -137q56 -53 151 -101q12 -7 22 -7q15 0 54 48.5t52 48.5zM782 32q127 0 243.5 50t200.5 134t134 200.5t50 243.5t-50 243.5t-134 200.5t-200.5 134t-243.5 50t-243.5 -50t-200.5 -134t-134 -200.5t-50 -243.5q0 -203 120 -368l-79 -233 l242 77q158 -104 345 -104zM782 1414q153 0 292.5 -60t240.5 -161t161 -240.5t60 -292.5t-60 -292.5t-161 -240.5t-240.5 -161t-292.5 -60q-195 0 -365 94l-417 -134l136 405q-108 178 -108 389q0 153 60 292.5t161 240.5t240.5 161t292.5 60z" />
+<glyph unicode="&#xf233;" horiz-adv-x="1792" d="M128 128h1024v128h-1024v-128zM128 640h1024v128h-1024v-128zM1696 192q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM128 1152h1024v128h-1024v-128zM1696 704q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1696 1216 q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1792 384v-384h-1792v384h1792zM1792 896v-384h-1792v384h1792zM1792 1408v-384h-1792v384h1792z" />
+<glyph unicode="&#xf234;" horiz-adv-x="2048" d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1664 512h352q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5 t-9.5 22.5v352h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352zM928 288q0 -52 38 -90t90 -38h256v-238q-68 -50 -171 -50h-874q-121 0 -194 69t-73 190q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q79 -61 154.5 -91.5t164.5 -30.5t164.5 30.5t154.5 91.5q20 17 39 17q132 0 217 -96h-223q-52 0 -90 -38t-38 -90v-192z" />
+<glyph unicode="&#xf235;" horiz-adv-x="2048" d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1781 320l249 -249q9 -9 9 -23q0 -13 -9 -22l-136 -136q-9 -9 -22 -9q-14 0 -23 9l-249 249l-249 -249q-9 -9 -23 -9q-13 0 -22 9l-136 136 q-9 9 -9 22q0 14 9 23l249 249l-249 249q-9 9 -9 23q0 13 9 22l136 136q9 9 22 9q14 0 23 -9l249 -249l249 249q9 9 23 9q13 0 22 -9l136 -136q9 -9 9 -22q0 -14 -9 -23zM1283 320l-181 -181q-37 -37 -37 -91q0 -53 37 -90l83 -83q-21 -3 -44 -3h-874q-121 0 -194 69 t-73 190q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q19 0 39 -17q154 -122 319 -122t319 122q20 17 39 17q28 0 57 -6q-28 -27 -41 -50t-13 -56q0 -54 37 -91z" />
+<glyph unicode="&#xf236;" horiz-adv-x="2048" d="M256 512h1728q26 0 45 -19t19 -45v-448h-256v256h-1536v-256h-256v1216q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-704zM832 832q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM2048 576v64q0 159 -112.5 271.5t-271.5 112.5h-704 q-26 0 -45 -19t-19 -45v-384h1152z" />
+<glyph unicode="&#xf237;" d="M1536 1536l-192 -448h192v-192h-274l-55 -128h329v-192h-411l-357 -832l-357 832h-411v192h329l-55 128h-274v192h192l-192 448h256l323 -768h378l323 768h256zM768 320l108 256h-216z" />
+<glyph unicode="&#xf238;" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM768 192q80 0 136 56t56 136t-56 136t-136 56 t-136 -56t-56 -136t56 -136t136 -56zM1344 768v512h-1152v-512h1152z" />
+<glyph unicode="&#xf239;" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM288 224q66 0 113 47t47 113t-47 113t-113 47 t-113 -47t-47 -113t47 -113t113 -47zM704 768v512h-544v-512h544zM1248 224q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM1408 768v512h-576v-512h576z" />
+<glyph unicode="&#xf23a;" horiz-adv-x="1792" d="M597 1115v-1173q0 -25 -12.5 -42.5t-36.5 -17.5q-17 0 -33 8l-465 233q-21 10 -35.5 33.5t-14.5 46.5v1140q0 20 10 34t29 14q14 0 44 -15l511 -256q3 -3 3 -5zM661 1014l534 -866l-534 266v600zM1792 996v-1054q0 -25 -14 -40.5t-38 -15.5t-47 13l-441 220zM1789 1116 q0 -3 -256.5 -419.5t-300.5 -487.5l-390 634l324 527q17 28 52 28q14 0 26 -6l541 -270q4 -2 4 -6z" />
+<glyph unicode="&#xf23b;" d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1408v-1536h-1536v1536h1536z" />
+<glyph unicode="&#xf23c;" horiz-adv-x="2296" d="M478 -139q-8 -16 -27 -34.5t-37 -25.5q-25 -9 -51.5 3.5t-28.5 31.5q-1 22 40 55t68 38q23 4 34 -21.5t2 -46.5zM1819 -139q7 -16 26 -34.5t38 -25.5q25 -9 51.5 3.5t27.5 31.5q2 22 -39.5 55t-68.5 38q-22 4 -33 -21.5t-2 -46.5zM1867 -30q13 -27 56.5 -59.5t77.5 -41.5 q45 -13 82 4.5t37 50.5q0 46 -67.5 100.5t-115.5 59.5q-40 5 -63.5 -37.5t-6.5 -76.5zM428 -30q-13 -27 -56 -59.5t-77 -41.5q-45 -13 -82 4.5t-37 50.5q0 46 67.5 100.5t115.5 59.5q40 5 63 -37.5t6 -76.5zM1158 1094h1q-41 0 -76 -15q27 -8 44 -30.5t17 -49.5 q0 -35 -27 -60t-65 -25q-52 0 -80 43q-5 -23 -5 -42q0 -74 56 -126.5t135 -52.5q80 0 136 52.5t56 126.5t-56 126.5t-136 52.5zM1462 1312q-99 109 -220.5 131.5t-245.5 -44.5q27 60 82.5 96.5t118 39.5t121.5 -17t99.5 -74.5t44.5 -131.5zM2212 73q8 -11 -11 -42 q7 -23 7 -40q1 -56 -44.5 -112.5t-109.5 -91.5t-118 -37q-48 -2 -92 21.5t-66 65.5q-687 -25 -1259 0q-23 -41 -66.5 -65t-92.5 -22q-86 3 -179.5 80.5t-92.5 160.5q2 22 7 40q-19 31 -11 42q6 10 31 1q14 22 41 51q-7 29 2 38q11 10 39 -4q29 20 59 34q0 29 13 37 q23 12 51 -16q35 5 61 -2q18 -4 38 -19v73q-11 0 -18 2q-53 10 -97 44.5t-55 87.5q-9 38 0 81q15 62 93 95q2 17 19 35.5t36 23.5t33 -7.5t19 -30.5h13q46 -5 60 -23q3 -3 5 -7q10 1 30.5 3.5t30.5 3.5q-15 11 -30 17q-23 40 -91 43q0 6 1 10q-62 2 -118.5 18.5t-84.5 47.5 q-32 36 -42.5 92t-2.5 112q16 126 90 179q23 16 52 4.5t32 -40.5q0 -1 1.5 -14t2.5 -21t3 -20t5.5 -19t8.5 -10q27 -14 76 -12q48 46 98 74q-40 4 -162 -14l47 46q61 58 163 111q145 73 282 86q-20 8 -41 15.5t-47 14t-42.5 10.5t-47.5 11t-43 10q595 126 904 -139 q98 -84 158 -222q85 -10 121 9h1q5 3 8.5 10t5.5 19t3 19.5t3 21.5l1 14q3 28 32 40t52 -5q73 -52 91 -178q7 -57 -3.5 -113t-42.5 -91q-28 -32 -83.5 -48.5t-115.5 -18.5v-10q-71 -2 -95 -43q-14 -5 -31 -17q11 -1 32 -3.5t30 -3.5q1 4 5 8q16 18 60 23h13q5 18 19 30t33 8 t36 -23t19 -36q79 -32 93 -95q9 -40 1 -81q-12 -53 -56 -88t-97 -44q-10 -2 -17 -2q0 -49 -1 -73q20 15 38 19q26 7 61 2q28 28 51 16q14 -9 14 -37q33 -16 59 -34q27 13 38 4q10 -10 2 -38q28 -30 41 -51q23 8 31 -1zM1937 1025q0 -29 -9 -54q82 -32 112 -132 q4 37 -9.5 98.5t-41.5 90.5q-20 19 -36 17t-16 -20zM1859 925q35 -42 47.5 -108.5t-0.5 -124.5q67 13 97 45q13 14 18 28q-3 64 -31 114.5t-79 66.5q-15 -15 -52 -21zM1822 921q-30 0 -44 1q42 -115 53 -239q21 0 43 3q16 68 1 135t-53 100zM258 839q30 100 112 132 q-9 25 -9 54q0 18 -16.5 20t-35.5 -17q-28 -29 -41.5 -90.5t-9.5 -98.5zM294 737q29 -31 97 -45q-13 58 -0.5 124.5t47.5 108.5v0q-37 6 -52 21q-51 -16 -78.5 -66t-31.5 -115q9 -17 18 -28zM471 683q14 124 73 235q-19 -4 -55 -18l-45 -19v1q-46 -89 -20 -196q25 -3 47 -3z M1434 644q8 -38 16.5 -108.5t11.5 -89.5q3 -18 9.5 -21.5t23.5 4.5q40 20 62 85.5t23 125.5q-24 2 -146 4zM1152 1285q-116 0 -199 -82.5t-83 -198.5q0 -117 83 -199.5t199 -82.5t199 82.5t83 199.5q0 116 -83 198.5t-199 82.5zM1380 646q-106 2 -211 0v1q-1 -27 2.5 -86 t13.5 -66q29 -14 93.5 -14.5t95.5 10.5q9 3 11 39t-0.5 69.5t-4.5 46.5zM1112 447q8 4 9.5 48t-0.5 88t-4 63v1q-212 -3 -214 -3q-4 -20 -7 -62t0 -83t14 -46q34 -15 101 -16t101 10zM718 636q-16 -59 4.5 -118.5t77.5 -84.5q15 -8 24 -5t12 21q3 16 8 90t10 103 q-69 -2 -136 -6zM591 510q3 -23 -34 -36q132 -141 271.5 -240t305.5 -154q172 49 310.5 146t293.5 250q-33 13 -30 34l3 9v1v-1q-17 2 -50 5.5t-48 4.5q-26 -90 -82 -132q-51 -38 -82 1q-5 6 -9 14q-7 13 -17 62q-2 -5 -5 -9t-7.5 -7t-8 -5.5t-9.5 -4l-10 -2.5t-12 -2 l-12 -1.5t-13.5 -1t-13.5 -0.5q-106 -9 -163 11q-4 -17 -10 -26.5t-21 -15t-23 -7t-36 -3.5q-2 0 -3 -0.5t-3 -0.5h-3q-179 -17 -203 40q-2 -63 -56 -54q-47 8 -91 54q-12 13 -20 26q-17 29 -26 65q-58 -6 -87 -10q1 -2 4 -10zM507 -118q3 14 3 30q-17 71 -51 130t-73 70 q-41 12 -101.5 -14.5t-104.5 -80t-39 -107.5q35 -53 100 -93t119 -42q51 -2 94 28t53 79zM510 53q23 -63 27 -119q195 113 392 174q-98 52 -180.5 120t-179.5 165q-6 -4 -29 -13q0 -2 -1 -5t-1 -4q31 -18 22 -37q-12 -23 -56 -34q-10 -13 -29 -24h-1q-2 -83 1 -150 q19 -34 35 -73zM579 -113q532 -21 1145 0q-254 147 -428 196q-76 -35 -156 -57q-8 -3 -16 0q-65 21 -129 49q-208 -60 -416 -188h-1v-1q1 0 1 1zM1763 -67q4 54 28 120q14 38 33 71l-1 -1q3 77 3 153q-15 8 -30 25q-42 9 -56 33q-9 20 22 38q-2 4 -2 9q-16 4 -28 12 q-204 -190 -383 -284q198 -59 414 -176zM2155 -90q5 54 -39 107.5t-104 80t-102 14.5q-38 -11 -72.5 -70.5t-51.5 -129.5q0 -16 3 -30q10 -49 53 -79t94 -28q54 2 119 42t100 93z" />
+<glyph unicode="&#xf23d;" horiz-adv-x="2304" d="M1524 -25q0 -68 -48 -116t-116 -48t-116.5 48t-48.5 116t48.5 116.5t116.5 48.5t116 -48.5t48 -116.5zM775 -25q0 -68 -48.5 -116t-116.5 -48t-116 48t-48 116t48 116.5t116 48.5t116.5 -48.5t48.5 -116.5zM0 1469q57 -60 110.5 -104.5t121 -82t136 -63t166 -45.5 t200 -31.5t250 -18.5t304 -9.5t372.5 -2.5q139 0 244.5 -5t181 -16.5t124 -27.5t71 -39.5t24 -51.5t-19.5 -64t-56.5 -76.5t-89.5 -91t-116 -104.5t-139 -119q-185 -157 -286 -247q29 51 76.5 109t94 105.5t94.5 98.5t83 91.5t54 80.5t13 70t-45.5 55.5t-116.5 41t-204 23.5 t-304 5q-168 -2 -314 6t-256 23t-204.5 41t-159.5 51.5t-122.5 62.5t-91.5 66.5t-68 71.5t-50.5 69.5t-40 68t-36.5 59.5z" />
+<glyph unicode="&#xf23e;" horiz-adv-x="1792" d="M896 1472q-169 0 -323 -66t-265.5 -177.5t-177.5 -265.5t-66 -323t66 -323t177.5 -265.5t265.5 -177.5t323 -66t323 66t265.5 177.5t177.5 265.5t66 323t-66 323t-177.5 265.5t-265.5 177.5t-323 66zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348 t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM496 704q16 0 16 -16v-480q0 -16 -16 -16h-32q-16 0 -16 16v480q0 16 16 16h32zM896 640q53 0 90.5 -37.5t37.5 -90.5q0 -35 -17.5 -64t-46.5 -46v-114q0 -14 -9 -23 t-23 -9h-64q-14 0 -23 9t-9 23v114q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5zM896 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM544 928v-96 q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 93 65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5v-96q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v96q0 146 -103 249t-249 103t-249 -103t-103 -249zM1408 192v512q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-512 q0 -26 19 -45t45 -19h896q26 0 45 19t19 45z" />
+<glyph unicode="&#xf240;" horiz-adv-x="2304" d="M1920 1024v-768h-1664v768h1664zM2048 448h128v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288zM2304 832v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113 v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf241;" horiz-adv-x="2304" d="M256 256v768h1280v-768h-1280zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf242;" horiz-adv-x="2304" d="M256 256v768h896v-768h-896zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf243;" horiz-adv-x="2304" d="M256 256v768h512v-768h-512zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf244;" horiz-adv-x="2304" d="M2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23 v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf245;" horiz-adv-x="1280" d="M1133 493q31 -30 14 -69q-17 -40 -59 -40h-382l201 -476q10 -25 0 -49t-34 -35l-177 -75q-25 -10 -49 0t-35 34l-191 452l-312 -312q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v1504q0 42 40 59q12 5 24 5q27 0 45 -19z" />
+<glyph unicode="&#xf246;" horiz-adv-x="1024" d="M832 1408q-320 0 -320 -224v-416h128v-128h-128v-544q0 -224 320 -224h64v-128h-64q-272 0 -384 146q-112 -146 -384 -146h-64v128h64q320 0 320 224v544h-128v128h128v416q0 224 -320 224h-64v128h64q272 0 384 -146q112 146 384 146h64v-128h-64z" />
+<glyph unicode="&#xf247;" horiz-adv-x="2048" d="M2048 1152h-128v-1024h128v-384h-384v128h-1280v-128h-384v384h128v1024h-128v384h384v-128h1280v128h384v-384zM1792 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 -128v128h-128v-128h128zM1664 0v128h128v1024h-128v128h-1280v-128h-128v-1024h128v-128 h1280zM1920 -128v128h-128v-128h128zM1280 896h384v-768h-896v256h-384v768h896v-256zM512 512h640v512h-640v-512zM1536 256v512h-256v-384h-384v-128h640z" />
+<glyph unicode="&#xf248;" horiz-adv-x="2304" d="M2304 768h-128v-640h128v-384h-384v128h-896v-128h-384v384h128v128h-384v-128h-384v384h128v640h-128v384h384v-128h896v128h384v-384h-128v-128h384v128h384v-384zM2048 1024v-128h128v128h-128zM1408 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 256 v128h-128v-128h128zM1536 384h-128v-128h128v128zM384 384h896v128h128v640h-128v128h-896v-128h-128v-640h128v-128zM896 -128v128h-128v-128h128zM2176 -128v128h-128v-128h128zM2048 128v640h-128v128h-384v-384h128v-384h-384v128h-384v-128h128v-128h896v128h128z" />
+<glyph unicode="&#xf249;" d="M1024 288v-416h-928q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68v-928h-416q-40 0 -68 -28t-28 -68zM1152 256h381q-15 -82 -65 -132l-184 -184q-50 -50 -132 -65v381z" />
+<glyph unicode="&#xf24a;" d="M1400 256h-248v-248q29 10 41 22l185 185q12 12 22 41zM1120 384h288v896h-1280v-1280h896v288q0 40 28 68t68 28zM1536 1312v-1024q0 -40 -20 -88t-48 -76l-184 -184q-28 -28 -76 -48t-88 -20h-1024q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68 z" />
+<glyph unicode="&#xf24b;" horiz-adv-x="2304" d="M1951 538q0 -26 -15.5 -44.5t-38.5 -23.5q-8 -2 -18 -2h-153v140h153q10 0 18 -2q23 -5 38.5 -23.5t15.5 -44.5zM1933 751q0 -25 -15 -42t-38 -21q-3 -1 -15 -1h-139v129h139q3 0 8.5 -0.5t6.5 -0.5q23 -4 38 -21.5t15 -42.5zM728 587v308h-228v-308q0 -58 -38 -94.5 t-105 -36.5q-108 0 -229 59v-112q53 -15 121 -23t109 -9l42 -1q328 0 328 217zM1442 403v113q-99 -52 -200 -59q-108 -8 -169 41t-61 142t61 142t169 41q101 -7 200 -58v112q-48 12 -100 19.5t-80 9.5l-28 2q-127 6 -218.5 -14t-140.5 -60t-71 -88t-22 -106t22 -106t71 -88 t140.5 -60t218.5 -14q101 4 208 31zM2176 518q0 54 -43 88.5t-109 39.5v3q57 8 89 41.5t32 79.5q0 55 -41 88t-107 36q-3 0 -12 0.5t-14 0.5h-455v-510h491q74 0 121.5 36.5t47.5 96.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90 t90 38h2048q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf24c;" horiz-adv-x="2304" d="M858 295v693q-106 -41 -172 -135.5t-66 -211.5t66 -211.5t172 -134.5zM1362 641q0 117 -66 211.5t-172 135.5v-694q106 41 172 135.5t66 211.5zM1577 641q0 -159 -78.5 -294t-213.5 -213.5t-294 -78.5q-119 0 -227.5 46.5t-187 125t-125 187t-46.5 227.5q0 159 78.5 294 t213.5 213.5t294 78.5t294 -78.5t213.5 -213.5t78.5 -294zM1960 634q0 139 -55.5 261.5t-147.5 205.5t-213.5 131t-252.5 48h-301q-176 0 -323.5 -81t-235 -230t-87.5 -335q0 -171 87 -317.5t236 -231.5t323 -85h301q129 0 251.5 50.5t214.5 135t147.5 202.5t55.5 246z M2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf24d;" horiz-adv-x="1792" d="M1664 -96v1088q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5zM1792 992v-1088q0 -66 -47 -113t-113 -47h-1088q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113 zM1408 1376v-160h-128v160q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h160v-128h-160q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf24e;" horiz-adv-x="2304" d="M1728 1088l-384 -704h768zM448 1088l-384 -704h768zM1269 1280q-14 -40 -45.5 -71.5t-71.5 -45.5v-1291h608q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1344q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h608v1291q-40 14 -71.5 45.5t-45.5 71.5h-491q-14 0 -23 9t-9 23v64 q0 14 9 23t23 9h491q21 57 70 92.5t111 35.5t111 -35.5t70 -92.5h491q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-491zM1088 1264q33 0 56.5 23.5t23.5 56.5t-23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5zM2176 384q0 -73 -46.5 -131t-117.5 -91 t-144.5 -49.5t-139.5 -16.5t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81zM896 384q0 -73 -46.5 -131t-117.5 -91t-144.5 -49.5t-139.5 -16.5 t-139.5 16.5t-144.5 49.5t-117.5 91t-46.5 131q0 11 35 81t92 174.5t107 195.5t102 184t56 100q18 33 56 33t56 -33q4 -7 56 -100t102 -184t107 -195.5t92 -174.5t35 -81z" />
+<glyph unicode="&#xf250;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-77 -29 -149 -92.5 t-129.5 -152.5t-92.5 -210t-35 -253h1024q0 132 -35 253t-92.5 210t-129.5 152.5t-149 92.5q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
+<glyph unicode="&#xf251;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -66 9 -128h1006q9 61 9 128zM1280 -128q0 130 -34 249.5t-90.5 208t-126.5 152t-146 94.5h-230q-76 -31 -146 -94.5t-126.5 -152t-90.5 -208t-34 -249.5h1024z" />
+<glyph unicode="&#xf252;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -206 85 -384h854q85 178 85 384zM1223 192q-54 141 -145.5 241.5t-194.5 142.5h-230q-103 -42 -194.5 -142.5t-145.5 -241.5h910z" />
+<glyph unicode="&#xf253;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11.5 -36.5t-30.5 -23.5q-137 -51 -244 -196 h700q-107 145 -244 196q-19 7 -30.5 23.5t-11.5 36.5t11.5 36.5t30.5 23.5z" />
+<glyph unicode="&#xf254;" d="M1504 -64q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472zM130 0q3 55 16 107t30 95t46 87t53.5 76t64.5 69.5t66 60t70.5 55t66.5 47.5t65 43q-43 28 -65 43t-66.5 47.5t-70.5 55t-66 60t-64.5 69.5t-53.5 76t-46 87 t-30 95t-16 107h1276q-3 -55 -16 -107t-30 -95t-46 -87t-53.5 -76t-64.5 -69.5t-66 -60t-70.5 -55t-66.5 -47.5t-65 -43q43 -28 65 -43t66.5 -47.5t70.5 -55t66 -60t64.5 -69.5t53.5 -76t46 -87t30 -95t16 -107h-1276zM1504 1536q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9 h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472z" />
+<glyph unicode="&#xf255;" d="M768 1152q-53 0 -90.5 -37.5t-37.5 -90.5v-128h-32v93q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-429l-32 30v172q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-224q0 -47 35 -82l310 -296q39 -39 39 -102q0 -26 19 -45t45 -19h640q26 0 45 19t19 45v25 q0 41 10 77l108 436q10 36 10 77v246q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-32h-32v125q0 40 -25 72.5t-64 40.5q-14 2 -23 2q-46 0 -79 -33t-33 -79v-128h-32v122q0 51 -32.5 89.5t-82.5 43.5q-5 1 -13 1zM768 1280q84 0 149 -50q57 34 123 34q59 0 111 -27 t86 -76q27 7 59 7q100 0 170 -71.5t70 -171.5v-246q0 -51 -13 -108l-109 -436q-6 -24 -6 -71q0 -80 -56 -136t-136 -56h-640q-84 0 -138 58.5t-54 142.5l-308 296q-76 73 -76 175v224q0 99 70.5 169.5t169.5 70.5q11 0 16 -1q6 95 75.5 160t164.5 65q52 0 98 -21 q72 69 174 69z" />
+<glyph unicode="&#xf256;" horiz-adv-x="1792" d="M880 1408q-46 0 -79 -33t-33 -79v-656h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528v-256l-154 205q-38 51 -102 51q-53 0 -90.5 -37.5t-37.5 -90.5q0 -43 26 -77l384 -512q38 -51 102 -51h688q34 0 61 22t34 56l76 405q5 32 5 59v498q0 46 -33 79t-79 33t-79 -33 t-33 -79v-272h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528h-32v656q0 46 -33 79t-79 33zM880 1536q68 0 125.5 -35.5t88.5 -96.5q19 4 42 4q99 0 169.5 -70.5t70.5 -169.5v-17q105 6 180.5 -64t75.5 -175v-498q0 -40 -8 -83l-76 -404q-14 -79 -76.5 -131t-143.5 -52 h-688q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 106 75 181t181 75q78 0 128 -34v434q0 99 70.5 169.5t169.5 70.5q23 0 42 -4q31 61 88.5 96.5t125.5 35.5z" />
+<glyph unicode="&#xf257;" horiz-adv-x="1792" d="M1073 -128h-177q-163 0 -226 141q-23 49 -23 102v5q-62 30 -98.5 88.5t-36.5 127.5q0 38 5 48h-261q-106 0 -181 75t-75 181t75 181t181 75h113l-44 17q-74 28 -119.5 93.5t-45.5 145.5q0 106 75 181t181 75q46 0 91 -17l628 -239h401q106 0 181 -75t75 -181v-668 q0 -88 -54 -157.5t-140 -90.5l-339 -85q-92 -23 -186 -23zM1024 583l-155 -71l-163 -74q-30 -14 -48 -41.5t-18 -60.5q0 -46 33 -79t79 -33q26 0 46 10l338 154q-49 10 -80.5 50t-31.5 90v55zM1344 272q0 46 -33 79t-79 33q-26 0 -46 -10l-290 -132q-28 -13 -37 -17 t-30.5 -17t-29.5 -23.5t-16 -29t-8 -40.5q0 -50 31.5 -82t81.5 -32q20 0 38 9l352 160q30 14 48 41.5t18 60.5zM1112 1024l-650 248q-24 8 -46 8q-53 0 -90.5 -37.5t-37.5 -90.5q0 -40 22.5 -73t59.5 -47l526 -200v-64h-640q-53 0 -90.5 -37.5t-37.5 -90.5t37.5 -90.5 t90.5 -37.5h535l233 106v198q0 63 46 106l111 102h-69zM1073 0q82 0 155 19l339 85q43 11 70 45.5t27 78.5v668q0 53 -37.5 90.5t-90.5 37.5h-308l-136 -126q-36 -33 -36 -82v-296q0 -46 33 -77t79 -31t79 35t33 81v208h32v-208q0 -70 -57 -114q52 -8 86.5 -48.5t34.5 -93.5 q0 -42 -23 -78t-61 -53l-310 -141h91z" />
+<glyph unicode="&#xf258;" horiz-adv-x="2048" d="M1151 1536q61 0 116 -28t91 -77l572 -781q118 -159 118 -359v-355q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v177l-286 143h-546q-80 0 -136 56t-56 136v32q0 119 84.5 203.5t203.5 84.5h420l42 128h-686q-100 0 -173.5 67.5t-81.5 166.5q-65 79 -65 182v32 q0 80 56 136t136 56h959zM1920 -64v355q0 157 -93 284l-573 781q-39 52 -103 52h-959q-26 0 -45 -19t-19 -45q0 -32 1.5 -49.5t9.5 -40.5t25 -43q10 31 35.5 50t56.5 19h832v-32h-832q-26 0 -45 -19t-19 -45q0 -44 3 -58q8 -44 44 -73t81 -29h640h91q40 0 68 -28t28 -68 q0 -15 -5 -30l-64 -192q-10 -29 -35 -47.5t-56 -18.5h-443q-66 0 -113 -47t-47 -113v-32q0 -26 19 -45t45 -19h561q16 0 29 -7l317 -158q24 -13 38.5 -36t14.5 -50v-197q0 -26 19 -45t45 -19h384q26 0 45 19t19 45z" />
+<glyph unicode="&#xf259;" horiz-adv-x="2048" d="M816 1408q-48 0 -79.5 -34t-31.5 -82q0 -14 3 -28l150 -624h-26l-116 482q-9 38 -39.5 62t-69.5 24q-47 0 -79 -34t-32 -81q0 -11 4 -29q3 -13 39 -161t68 -282t32 -138v-227l-307 230q-34 26 -77 26q-52 0 -89.5 -36.5t-37.5 -88.5q0 -67 56 -110l507 -379 q34 -26 76 -26h694q33 0 59 20.5t34 52.5l100 401q8 30 10 88t9 86l116 478q3 12 3 26q0 46 -33 79t-80 33q-38 0 -69 -25.5t-40 -62.5l-99 -408h-26l132 547q3 14 3 28q0 47 -32 80t-80 33q-38 0 -68.5 -24t-39.5 -62l-145 -602h-127l-164 682q-9 38 -39.5 62t-68.5 24z M1461 -256h-694q-85 0 -153 51l-507 380q-50 38 -78.5 94t-28.5 118q0 105 75 179t180 74q25 0 49.5 -5.5t41.5 -11t41 -20.5t35 -23t38.5 -29.5t37.5 -28.5l-123 512q-7 35 -7 59q0 93 60 162t152 79q14 87 80.5 144.5t155.5 57.5q83 0 148 -51.5t85 -132.5l103 -428 l83 348q20 81 85 132.5t148 51.5q87 0 152.5 -54t82.5 -139q93 -10 155 -78t62 -161q0 -30 -7 -57l-116 -477q-5 -22 -5 -67q0 -51 -13 -108l-101 -401q-19 -75 -79.5 -122.5t-137.5 -47.5z" />
+<glyph unicode="&#xf25a;" horiz-adv-x="1792" d="M640 1408q-53 0 -90.5 -37.5t-37.5 -90.5v-512v-384l-151 202q-41 54 -107 54q-52 0 -89 -38t-37 -90q0 -43 26 -77l384 -512q38 -51 102 -51h718q22 0 39.5 13.5t22.5 34.5l92 368q24 96 24 194v217q0 41 -28 71t-68 30t-68 -28t-28 -68h-32v61q0 48 -32 81.5t-80 33.5 q-46 0 -79 -33t-33 -79v-64h-32v90q0 55 -37 94.5t-91 39.5q-53 0 -90.5 -37.5t-37.5 -90.5v-96h-32v570q0 55 -37 94.5t-91 39.5zM640 1536q107 0 181.5 -77.5t74.5 -184.5v-220q22 2 32 2q99 0 173 -69q47 21 99 21q113 0 184 -87q27 7 56 7q94 0 159 -67.5t65 -161.5 v-217q0 -116 -28 -225l-92 -368q-16 -64 -68 -104.5t-118 -40.5h-718q-60 0 -114.5 27.5t-90.5 74.5l-384 512q-51 68 -51 154q0 105 74.5 180.5t179.5 75.5q71 0 130 -35v547q0 106 75 181t181 75zM768 128v384h-32v-384h32zM1024 128v384h-32v-384h32zM1280 128v384h-32 v-384h32z" />
+<glyph unicode="&#xf25b;" d="M1288 889q60 0 107 -23q141 -63 141 -226v-177q0 -94 -23 -186l-85 -339q-21 -86 -90.5 -140t-157.5 -54h-668q-106 0 -181 75t-75 181v401l-239 628q-17 45 -17 91q0 106 75 181t181 75q80 0 145.5 -45.5t93.5 -119.5l17 -44v113q0 106 75 181t181 75t181 -75t75 -181 v-261q27 5 48 5q69 0 127.5 -36.5t88.5 -98.5zM1072 896q-33 0 -60.5 -18t-41.5 -48l-74 -163l-71 -155h55q50 0 90 -31.5t50 -80.5l154 338q10 20 10 46q0 46 -33 79t-79 33zM1293 761q-22 0 -40.5 -8t-29 -16t-23.5 -29.5t-17 -30.5t-17 -37l-132 -290q-10 -20 -10 -46 q0 -46 33 -79t79 -33q33 0 60.5 18t41.5 48l160 352q9 18 9 38q0 50 -32 81.5t-82 31.5zM128 1120q0 -22 8 -46l248 -650v-69l102 111q43 46 106 46h198l106 233v535q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5v-640h-64l-200 526q-14 37 -47 59.5t-73 22.5 q-53 0 -90.5 -37.5t-37.5 -90.5zM1180 -128q44 0 78.5 27t45.5 70l85 339q19 73 19 155v91l-141 -310q-17 -38 -53 -61t-78 -23q-53 0 -93.5 34.5t-48.5 86.5q-44 -57 -114 -57h-208v32h208q46 0 81 33t35 79t-31 79t-77 33h-296q-49 0 -82 -36l-126 -136v-308 q0 -53 37.5 -90.5t90.5 -37.5h668z" />
+<glyph unicode="&#xf25c;" horiz-adv-x="1973" d="M857 992v-117q0 -13 -9.5 -22t-22.5 -9h-298v-812q0 -13 -9 -22.5t-22 -9.5h-135q-13 0 -22.5 9t-9.5 23v812h-297q-13 0 -22.5 9t-9.5 22v117q0 14 9 23t23 9h793q13 0 22.5 -9.5t9.5 -22.5zM1895 995l77 -961q1 -13 -8 -24q-10 -10 -23 -10h-134q-12 0 -21 8.5 t-10 20.5l-46 588l-189 -425q-8 -19 -29 -19h-120q-20 0 -29 19l-188 427l-45 -590q-1 -12 -10 -20.5t-21 -8.5h-135q-13 0 -23 10q-9 10 -9 24l78 961q1 12 10 20.5t21 8.5h142q20 0 29 -19l220 -520q10 -24 20 -51q3 7 9.5 24.5t10.5 26.5l221 520q9 19 29 19h141 q13 0 22 -8.5t10 -20.5z" />
+<glyph unicode="&#xf25d;" horiz-adv-x="1792" d="M1042 833q0 88 -60 121q-33 18 -117 18h-123v-281h162q66 0 102 37t36 105zM1094 548l205 -373q8 -17 -1 -31q-8 -16 -27 -16h-152q-20 0 -28 17l-194 365h-155v-350q0 -14 -9 -23t-23 -9h-134q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h294q128 0 190 -24q85 -31 134 -109 t49 -180q0 -92 -42.5 -165.5t-115.5 -109.5q6 -10 9 -16zM896 1376q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM1792 640 q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf25e;" horiz-adv-x="1792" d="M605 303q153 0 257 104q14 18 3 36l-45 82q-6 13 -24 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13t-23.5 -14.5t-28.5 -13.5t-33.5 -9.5t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78 q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-148 0 -246 -96.5t-98 -240.5q0 -146 97 -241.5t247 -95.5zM1235 303q153 0 257 104q14 18 4 36l-45 82q-8 14 -25 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13t-23.5 -14.5t-28.5 -13.5t-33.5 -9.5 t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-147 0 -245.5 -96.5t-98.5 -240.5q0 -146 97 -241.5t247 -95.5zM896 1376 q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5 286t-58.5 286t-157 234.5t-234.5 157t-286 58.5zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191 t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71z" />
+<glyph unicode="&#xf260;" horiz-adv-x="2048" d="M736 736l384 -384l-384 -384l-672 672l672 672l168 -168l-96 -96l-72 72l-480 -480l480 -480l193 193l-289 287zM1312 1312l672 -672l-672 -672l-168 168l96 96l72 -72l480 480l-480 480l-193 -193l289 -287l-96 -96l-384 384z" />
+<glyph unicode="&#xf261;" horiz-adv-x="1792" d="M717 182l271 271l-279 279l-88 -88l192 -191l-96 -96l-279 279l279 279l40 -40l87 87l-127 128l-454 -454zM1075 190l454 454l-454 454l-271 -271l279 -279l88 88l-192 191l96 96l279 -279l-279 -279l-40 40l-87 -88zM1792 640q0 -182 -71 -348t-191 -286t-286 -191 t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf262;" horiz-adv-x="2304" d="M651 539q0 -39 -27.5 -66.5t-65.5 -27.5q-39 0 -66.5 27.5t-27.5 66.5q0 38 27.5 65.5t66.5 27.5q38 0 65.5 -27.5t27.5 -65.5zM1805 540q0 -39 -27.5 -66.5t-66.5 -27.5t-66.5 27.5t-27.5 66.5t27.5 66t66.5 27t66.5 -27t27.5 -66zM765 539q0 79 -56.5 136t-136.5 57 t-136.5 -56.5t-56.5 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM1918 540q0 80 -56.5 136.5t-136.5 56.5q-79 0 -136 -56.5t-57 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM850 539q0 -116 -81.5 -197.5t-196.5 -81.5q-116 0 -197.5 82t-81.5 197 t82 196.5t197 81.5t196.5 -81.5t81.5 -196.5zM2004 540q0 -115 -81.5 -196.5t-197.5 -81.5q-115 0 -196.5 81.5t-81.5 196.5t81.5 196.5t196.5 81.5q116 0 197.5 -81.5t81.5 -196.5zM1040 537q0 191 -135.5 326.5t-326.5 135.5q-125 0 -231 -62t-168 -168.5t-62 -231.5 t62 -231.5t168 -168.5t231 -62q191 0 326.5 135.5t135.5 326.5zM1708 1110q-254 111 -556 111q-319 0 -573 -110q117 0 223 -45.5t182.5 -122.5t122 -183t45.5 -223q0 115 43.5 219.5t118 180.5t177.5 123t217 50zM2187 537q0 191 -135 326.5t-326 135.5t-326.5 -135.5 t-135.5 -326.5t135.5 -326.5t326.5 -135.5t326 135.5t135 326.5zM1921 1103h383q-44 -51 -75 -114.5t-40 -114.5q110 -151 110 -337q0 -156 -77 -288t-209 -208.5t-287 -76.5q-133 0 -249 56t-196 155q-47 -56 -129 -179q-11 22 -53.5 82.5t-74.5 97.5 q-80 -99 -196.5 -155.5t-249.5 -56.5q-155 0 -287 76.5t-209 208.5t-77 288q0 186 110 337q-9 51 -40 114.5t-75 114.5h365q149 100 355 156.5t432 56.5q224 0 421 -56t348 -157z" />
+<glyph unicode="&#xf263;" horiz-adv-x="1280" d="M640 629q-188 0 -321 133t-133 320q0 188 133 321t321 133t321 -133t133 -321q0 -187 -133 -320t-321 -133zM640 1306q-92 0 -157.5 -65.5t-65.5 -158.5q0 -92 65.5 -157.5t157.5 -65.5t157.5 65.5t65.5 157.5q0 93 -65.5 158.5t-157.5 65.5zM1163 574q13 -27 15 -49.5 t-4.5 -40.5t-26.5 -38.5t-42.5 -37t-61.5 -41.5q-115 -73 -315 -94l73 -72l267 -267q30 -31 30 -74t-30 -73l-12 -13q-31 -30 -74 -30t-74 30q-67 68 -267 268l-267 -268q-31 -30 -74 -30t-73 30l-12 13q-31 30 -31 73t31 74l267 267l72 72q-203 21 -317 94 q-39 25 -61.5 41.5t-42.5 37t-26.5 38.5t-4.5 40.5t15 49.5q10 20 28 35t42 22t56 -2t65 -35q5 -4 15 -11t43 -24.5t69 -30.5t92 -24t113 -11q91 0 174 25.5t120 50.5l38 25q33 26 65 35t56 2t42 -22t28 -35z" />
+<glyph unicode="&#xf264;" d="M927 956q0 -66 -46.5 -112.5t-112.5 -46.5t-112.5 46.5t-46.5 112.5t46.5 112.5t112.5 46.5t112.5 -46.5t46.5 -112.5zM1141 593q-10 20 -28 32t-47.5 9.5t-60.5 -27.5q-10 -8 -29 -20t-81 -32t-127 -20t-124 18t-86 36l-27 18q-31 25 -60.5 27.5t-47.5 -9.5t-28 -32 q-22 -45 -2 -74.5t87 -73.5q83 -53 226 -67l-51 -52q-142 -142 -191 -190q-22 -22 -22 -52.5t22 -52.5l9 -9q22 -22 52.5 -22t52.5 22l191 191q114 -115 191 -191q22 -22 52.5 -22t52.5 22l9 9q22 22 22 52.5t-22 52.5l-191 190l-52 52q141 14 225 67q67 44 87 73.5t-2 74.5 zM1092 956q0 134 -95 229t-229 95t-229 -95t-95 -229t95 -229t229 -95t229 95t95 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf265;" horiz-adv-x="1720" d="M1565 1408q65 0 110 -45.5t45 -110.5v-519q0 -176 -68 -336t-182.5 -275t-274 -182.5t-334.5 -67.5q-176 0 -335.5 67.5t-274.5 182.5t-183 275t-68 336v519q0 64 46 110t110 46h1409zM861 344q47 0 82 33l404 388q37 35 37 85q0 49 -34.5 83.5t-83.5 34.5q-47 0 -82 -33 l-323 -310l-323 310q-35 33 -81 33q-49 0 -83.5 -34.5t-34.5 -83.5q0 -51 36 -85l405 -388q33 -33 81 -33z" />
+<glyph unicode="&#xf266;" horiz-adv-x="2304" d="M1494 -103l-295 695q-25 -49 -158.5 -305.5t-198.5 -389.5q-1 -1 -27.5 -0.5t-26.5 1.5q-82 193 -255.5 587t-259.5 596q-21 50 -66.5 107.5t-103.5 100.5t-102 43q0 5 -0.5 24t-0.5 27h583v-50q-39 -2 -79.5 -16t-66.5 -43t-10 -64q26 -59 216.5 -499t235.5 -540 q31 61 140 266.5t131 247.5q-19 39 -126 281t-136 295q-38 69 -201 71v50l513 -1v-47q-60 -2 -93.5 -25t-12.5 -69q33 -70 87 -189.5t86 -187.5q110 214 173 363q24 55 -10 79.5t-129 26.5q1 7 1 25v24q64 0 170.5 0.5t180 1t92.5 0.5v-49q-62 -2 -119 -33t-90 -81 l-213 -442q13 -33 127.5 -290t121.5 -274l441 1017q-14 38 -49.5 62.5t-65 31.5t-55.5 8v50l460 -4l1 -2l-1 -44q-139 -4 -201 -145q-526 -1216 -559 -1291h-49z" />
+<glyph unicode="&#xf267;" horiz-adv-x="1792" d="M949 643q0 -26 -16.5 -45t-41.5 -19q-26 0 -45 16.5t-19 41.5q0 26 17 45t42 19t44 -16.5t19 -41.5zM964 585l350 581q-9 -8 -67.5 -62.5t-125.5 -116.5t-136.5 -127t-117 -110.5t-50.5 -51.5l-349 -580q7 7 67 62t126 116.5t136 127t117 111t50 50.5zM1611 640 q0 -201 -104 -371q-3 2 -17 11t-26.5 16.5t-16.5 7.5q-13 0 -13 -13q0 -10 59 -44q-74 -112 -184.5 -190.5t-241.5 -110.5l-16 67q-1 10 -15 10q-5 0 -8 -5.5t-2 -9.5l16 -68q-72 -15 -146 -15q-199 0 -372 105q1 2 13 20.5t21.5 33.5t9.5 19q0 13 -13 13q-6 0 -17 -14.5 t-22.5 -34.5t-13.5 -23q-113 75 -192 187.5t-110 244.5l69 15q10 3 10 15q0 5 -5.5 8t-10.5 2l-68 -15q-14 72 -14 139q0 206 109 379q2 -1 18.5 -12t30 -19t17.5 -8q13 0 13 12q0 6 -12.5 15.5t-32.5 21.5l-20 12q77 112 189 189t244 107l15 -67q2 -10 15 -10q5 0 8 5.5 t2 10.5l-15 66q71 13 134 13q204 0 379 -109q-39 -56 -39 -65q0 -13 12 -13q11 0 48 64q111 -75 187.5 -186t107.5 -241l-56 -12q-10 -2 -10 -16q0 -5 5.5 -8t9.5 -2l57 13q14 -72 14 -140zM1696 640q0 163 -63.5 311t-170.5 255t-255 170.5t-311 63.5t-311 -63.5 t-255 -170.5t-170.5 -255t-63.5 -311t63.5 -311t170.5 -255t255 -170.5t311 -63.5t311 63.5t255 170.5t170.5 255t63.5 311zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191 t191 -286t71 -348z" />
+<glyph unicode="&#xf268;" horiz-adv-x="1792" d="M893 1536q240 2 451 -120q232 -134 352 -372l-742 39q-160 9 -294 -74.5t-185 -229.5l-276 424q128 159 311 245.5t383 87.5zM146 1131l337 -663q72 -143 211 -217t293 -45l-230 -451q-212 33 -385 157.5t-272.5 316t-99.5 411.5q0 267 146 491zM1732 962 q58 -150 59.5 -310.5t-48.5 -306t-153 -272t-246 -209.5q-230 -133 -498 -119l405 623q88 131 82.5 290.5t-106.5 277.5zM896 942q125 0 213.5 -88.5t88.5 -213.5t-88.5 -213.5t-213.5 -88.5t-213.5 88.5t-88.5 213.5t88.5 213.5t213.5 88.5z" />
+<glyph unicode="&#xf269;" horiz-adv-x="1792" d="M903 -256q-283 0 -504.5 150.5t-329.5 398.5q-58 131 -67 301t26 332.5t111 312t179 242.5l-11 -281q11 14 68 15.5t70 -15.5q42 81 160.5 138t234.5 59q-54 -45 -119.5 -148.5t-58.5 -163.5q25 -8 62.5 -13.5t63 -7.5t68 -4t50.5 -3q15 -5 9.5 -45.5t-30.5 -75.5 q-5 -7 -16.5 -18.5t-56.5 -35.5t-101 -34l15 -189l-139 67q-18 -43 -7.5 -81.5t36 -66.5t65.5 -41.5t81 -6.5q51 9 98 34.5t83.5 45t73.5 17.5q61 -4 89.5 -33t19.5 -65q-1 -2 -2.5 -5.5t-8.5 -12.5t-18 -15.5t-31.5 -10.5t-46.5 -1q-60 -95 -144.5 -135.5t-209.5 -29.5 q74 -61 162.5 -82.5t168.5 -6t154.5 52t128 87.5t80.5 104q43 91 39 192.5t-37.5 188.5t-78.5 125q87 -38 137 -79.5t77 -112.5q15 170 -57.5 343t-209.5 284q265 -77 412 -279.5t151 -517.5q2 -127 -40.5 -255t-123.5 -238t-189 -196t-247.5 -135.5t-288.5 -49.5z" />
+<glyph unicode="&#xf26a;" horiz-adv-x="1792" d="M1493 1308q-165 110 -359 110q-155 0 -293 -73t-240 -200q-75 -93 -119.5 -218t-48.5 -266v-42q4 -141 48.5 -266t119.5 -218q102 -127 240 -200t293 -73q194 0 359 110q-121 -108 -274.5 -168t-322.5 -60q-29 0 -43 1q-175 8 -333 82t-272 193t-181 281t-67 339 q0 182 71 348t191 286t286 191t348 71h3q168 -1 320.5 -60.5t273.5 -167.5zM1792 640q0 -192 -77 -362.5t-213 -296.5q-104 -63 -222 -63q-137 0 -255 84q154 56 253.5 233t99.5 405q0 227 -99 404t-253 234q119 83 254 83q119 0 226 -65q135 -125 210.5 -295t75.5 -361z " />
+<glyph unicode="&#xf26b;" horiz-adv-x="1792" d="M1792 599q0 -56 -7 -104h-1151q0 -146 109.5 -244.5t257.5 -98.5q99 0 185.5 46.5t136.5 130.5h423q-56 -159 -170.5 -281t-267.5 -188.5t-321 -66.5q-187 0 -356 83q-228 -116 -394 -116q-237 0 -237 263q0 115 45 275q17 60 109 229q199 360 475 606 q-184 -79 -427 -354q63 274 283.5 449.5t501.5 175.5q30 0 45 -1q255 117 433 117q64 0 116 -13t94.5 -40.5t66.5 -76.5t24 -115q0 -116 -75 -286q101 -182 101 -390zM1722 1239q0 83 -53 132t-137 49q-108 0 -254 -70q121 -47 222.5 -131.5t170.5 -195.5q51 135 51 216z M128 2q0 -86 48.5 -132.5t134.5 -46.5q115 0 266 83q-122 72 -213.5 183t-137.5 245q-98 -205 -98 -332zM632 715h728q-5 142 -113 237t-251 95q-144 0 -251.5 -95t-112.5 -237z" />
+<glyph unicode="&#xf26c;" horiz-adv-x="2048" d="M1792 288v960q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1248v-960q0 -66 -47 -113t-113 -47h-736v-128h352q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23 v64q0 14 9 23t23 9h352v128h-736q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf26d;" horiz-adv-x="1792" d="M138 1408h197q-70 -64 -126 -149q-36 -56 -59 -115t-30 -125.5t-8.5 -120t10.5 -132t21 -126t28 -136.5q4 -19 6 -28q51 -238 81 -329q57 -171 152 -275h-272q-48 0 -82 34t-34 82v1304q0 48 34 82t82 34zM1346 1408h308q48 0 82 -34t34 -82v-1304q0 -48 -34 -82t-82 -34 h-178q212 210 196 565l-469 -101q-2 -45 -12 -82t-31 -72t-59.5 -59.5t-93.5 -36.5q-123 -26 -199 40q-32 27 -53 61t-51.5 129t-64.5 258q-35 163 -45.5 263t-5.5 139t23 77q20 41 62.5 73t102.5 45q45 12 83.5 6.5t67 -17t54 -35t43 -48t34.5 -56.5l468 100 q-68 175 -180 287z" />
+<glyph unicode="&#xf26e;" d="M1401 -11l-6 -6q-113 -114 -259 -175q-154 -64 -317 -64q-165 0 -317 64q-148 63 -259 175q-113 112 -175 258q-42 103 -54 189q-4 28 48 36q51 8 56 -20q1 -1 1 -4q18 -90 46 -159q50 -124 152 -226q98 -98 226 -152q132 -56 276 -56q143 0 276 56q128 55 225 152l6 6 q10 10 25 6q12 -3 33 -22q36 -37 17 -58zM929 604l-66 -66l63 -63q21 -21 -7 -49q-17 -17 -32 -17q-10 0 -19 10l-62 61l-66 -66q-5 -5 -15 -5q-15 0 -31 16l-2 2q-18 15 -18 29q0 7 8 17l66 65l-66 66q-16 16 14 45q18 18 31 18q6 0 13 -5l65 -66l65 65q18 17 48 -13 q27 -27 11 -44zM1400 547q0 -118 -46 -228q-45 -105 -126 -186q-80 -80 -187 -126t-228 -46t-228 46t-187 126q-82 82 -125 186q-15 32 -15 40h-1q-9 27 43 44q50 16 60 -12q37 -99 97 -167h1v339v2q3 136 102 232q105 103 253 103q147 0 251 -103t104 -249 q0 -147 -104.5 -251t-250.5 -104q-58 0 -112 16q-28 11 -13 61q16 51 44 43l14 -3q14 -3 32.5 -6t30.5 -3q104 0 176 71.5t72 174.5q0 101 -72 171q-71 71 -175 71q-107 0 -178 -80q-64 -72 -64 -160v-413q110 -67 242 -67q96 0 185 36.5t156 103.5t103.5 155t36.5 183 q0 198 -141 339q-140 140 -339 140q-200 0 -340 -140q-53 -53 -77 -87l-2 -2q-8 -11 -13 -15.5t-21.5 -9.5t-38.5 3q-21 5 -36.5 16.5t-15.5 26.5v680q0 15 10.5 26.5t27.5 11.5h877q30 0 30 -55t-30 -55h-811v-483h1q40 42 102 84t108 61q109 46 231 46q121 0 228 -46 t187 -126q81 -81 126 -186q46 -112 46 -229zM1369 1128q9 -8 9 -18t-5.5 -18t-16.5 -21q-26 -26 -39 -26q-9 0 -16 7q-106 91 -207 133q-128 56 -276 56q-133 0 -262 -49q-27 -10 -45 37q-9 25 -8 38q3 16 16 20q130 57 299 57q164 0 316 -64q137 -58 235 -152z" />
+<glyph unicode="&#xf270;" horiz-adv-x="1792" d="M1551 60q15 6 26 3t11 -17.5t-15 -33.5q-13 -16 -44 -43.5t-95.5 -68t-141 -74t-188 -58t-229.5 -24.5q-119 0 -238 31t-209 76.5t-172.5 104t-132.5 105t-84 87.5q-8 9 -10 16.5t1 12t8 7t11.5 2t11.5 -4.5q192 -117 300 -166q389 -176 799 -90q190 40 391 135z M1758 175q11 -16 2.5 -69.5t-28.5 -102.5q-34 -83 -85 -124q-17 -14 -26 -9t0 24q21 45 44.5 121.5t6.5 98.5q-5 7 -15.5 11.5t-27 6t-29.5 2.5t-35 0t-31.5 -2t-31 -3t-22.5 -2q-6 -1 -13 -1.5t-11 -1t-8.5 -1t-7 -0.5h-5.5h-4.5t-3 0.5t-2 1.5l-1.5 3q-6 16 47 40t103 30 q46 7 108 1t76 -24zM1364 618q0 -31 13.5 -64t32 -58t37.5 -46t33 -32l13 -11l-227 -224q-40 37 -79 75.5t-58 58.5l-19 20q-11 11 -25 33q-38 -59 -97.5 -102.5t-127.5 -63.5t-140 -23t-137.5 21t-117.5 65.5t-83 113t-31 162.5q0 84 28 154t72 116.5t106.5 83t122.5 57 t130 34.5t119.5 18.5t99.5 6.5v127q0 65 -21 97q-34 53 -121 53q-6 0 -16.5 -1t-40.5 -12t-56 -29.5t-56 -59.5t-48 -96l-294 27q0 60 22 119t67 113t108 95t151.5 65.5t190.5 24.5q100 0 181 -25t129.5 -61.5t81 -83t45 -86t12.5 -73.5v-589zM692 597q0 -86 70 -133 q66 -44 139 -22q84 25 114 123q14 45 14 101v162q-59 -2 -111 -12t-106.5 -33.5t-87 -71t-32.5 -114.5z" />
+<glyph unicode="&#xf271;" horiz-adv-x="1792" d="M1536 1280q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128zM1152 1376v-288q0 -14 9 -23t23 -9 h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 1376v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM1536 -128v1024h-1408v-1024h1408zM896 448h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224 v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224z" />
+<glyph unicode="&#xf272;" horiz-adv-x="1792" d="M1152 416v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23 t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47 t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf273;" horiz-adv-x="1792" d="M1111 151l-46 -46q-9 -9 -22 -9t-23 9l-188 189l-188 -189q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22t9 23l189 188l-189 188q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l188 -188l188 188q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23l-188 -188l188 -188q9 -10 9 -23t-9 -22z M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf274;" horiz-adv-x="1792" d="M1303 572l-512 -512q-10 -9 -23 -9t-23 9l-288 288q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l220 -220l444 444q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23 t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47 t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf275;" horiz-adv-x="1792" d="M448 1536q26 0 45 -19t19 -45v-891l536 429q17 14 40 14q26 0 45 -19t19 -45v-379l536 429q17 14 40 14q26 0 45 -19t19 -45v-1152q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h384z" />
+<glyph unicode="&#xf276;" horiz-adv-x="1024" d="M512 448q66 0 128 15v-655q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v655q61 -15 128 -15zM512 1536q212 0 362 -150t150 -362t-150 -362t-362 -150t-362 150t-150 362t150 362t362 150zM512 1312q14 0 23 9t9 23t-9 23t-23 9q-146 0 -249 -103t-103 -249 q0 -14 9 -23t23 -9t23 9t9 23q0 119 84.5 203.5t203.5 84.5z" />
+<glyph unicode="&#xf277;" horiz-adv-x="1792" d="M1745 1239q10 -10 10 -23t-10 -23l-141 -141q-28 -28 -68 -28h-1344q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h576v64q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-64h512q40 0 68 -28zM768 320h256v-512q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v512zM1600 768 q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1344q-40 0 -68 28l-141 141q-10 10 -10 23t10 23l141 141q28 28 68 28h512v192h256v-192h576z" />
+<glyph unicode="&#xf278;" horiz-adv-x="2048" d="M2020 1525q28 -20 28 -53v-1408q0 -20 -11 -36t-29 -23l-640 -256q-24 -11 -48 0l-616 246l-616 -246q-10 -5 -24 -5q-19 0 -36 11q-28 20 -28 53v1408q0 20 11 36t29 23l640 256q24 11 48 0l616 -246l616 246q32 13 60 -6zM736 1390v-1270l576 -230v1270zM128 1173 v-1270l544 217v1270zM1920 107v1270l-544 -217v-1270z" />
+<glyph unicode="&#xf279;" horiz-adv-x="1792" d="M512 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472q0 20 17 28l480 256q7 4 15 4zM1760 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472 q0 20 17 28l480 256q7 4 15 4zM640 1536q8 0 14 -3l512 -256q18 -10 18 -29v-1472q0 -13 -9.5 -22.5t-22.5 -9.5q-8 0 -14 3l-512 256q-18 10 -18 29v1472q0 13 9.5 22.5t22.5 9.5z" />
+<glyph unicode="&#xf27a;" horiz-adv-x="1792" d="M640 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 640q0 53 -37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-110 0 -211 18q-173 -173 -435 -229q-52 -10 -86 -13q-12 -1 -22 6t-13 18q-4 15 20 37q5 5 23.5 21.5t25.5 23.5t23.5 25.5t24 31.5t20.5 37 t20 48t14.5 57.5t12.5 72.5q-146 90 -229.5 216.5t-83.5 269.5q0 174 120 321.5t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" />
+<glyph unicode="&#xf27b;" horiz-adv-x="1792" d="M640 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 -53 -37.5 -90.5t-90.5 -37.5 t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5 t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51 t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 130 71 248.5t191 204.5t286 136.5t348 50.5t348 -50.5t286 -136.5t191 -204.5t71 -248.5z" />
+<glyph unicode="&#xf27c;" horiz-adv-x="1024" d="M512 345l512 295v-591l-512 -296v592zM0 640v-591l512 296zM512 1527v-591l-512 -296v591zM512 936l512 295v-591z" />
+<glyph unicode="&#xf27d;" horiz-adv-x="1792" d="M1709 1018q-10 -236 -332 -651q-333 -431 -562 -431q-142 0 -240 263q-44 160 -132 482q-72 262 -157 262q-18 0 -127 -76l-77 98q24 21 108 96.5t130 115.5q156 138 241 146q95 9 153 -55.5t81 -203.5q44 -287 66 -373q55 -249 120 -249q51 0 154 161q101 161 109 246 q13 139 -109 139q-57 0 -121 -26q120 393 459 382q251 -8 236 -326z" />
+<glyph unicode="&#xf27e;" d="M0 1408h1536v-1536h-1536v1536zM1085 293l-221 631l221 297h-634l221 -297l-221 -631l317 -304z" />
+<glyph unicode="&#xf280;" d="M0 1408h1536v-1536h-1536v1536zM908 1088l-12 -33l75 -83l-31 -114l25 -25l107 57l107 -57l25 25l-31 114l75 83l-12 33h-95l-53 96h-32l-53 -96h-95zM641 925q32 0 44.5 -16t11.5 -63l174 21q0 55 -17.5 92.5t-50.5 56t-69 25.5t-85 7q-133 0 -199 -57.5t-66 -182.5v-72 h-96v-128h76q20 0 20 -8v-382q0 -14 -5 -20t-18 -7l-73 -7v-88h448v86l-149 14q-6 1 -8.5 1.5t-3.5 2.5t-0.5 4t1 7t0.5 10v387h191l38 128h-231q-6 0 -2 6t4 9v80q0 27 1.5 40.5t7.5 28t19.5 20t36.5 5.5zM1248 96v86l-54 9q-7 1 -9.5 2.5t-2.5 3t1 7.5t1 12v520h-275 l-23 -101l83 -22q23 -7 23 -27v-370q0 -14 -6 -18.5t-20 -6.5l-70 -9v-86h352z" />
+<glyph unicode="&#xf281;" horiz-adv-x="1792" d="M1792 690q0 -58 -29.5 -105.5t-79.5 -72.5q12 -46 12 -96q0 -155 -106.5 -287t-290.5 -208.5t-400 -76.5t-399.5 76.5t-290 208.5t-106.5 287q0 47 11 94q-51 25 -82 73.5t-31 106.5q0 82 58 140.5t141 58.5q85 0 145 -63q218 152 515 162l116 521q3 13 15 21t26 5 l369 -81q18 37 54 59.5t79 22.5q62 0 106 -43.5t44 -105.5t-44 -106t-106 -44t-105.5 43.5t-43.5 105.5l-334 74l-104 -472q300 -9 519 -160q58 61 143 61q83 0 141 -58.5t58 -140.5zM418 491q0 -62 43.5 -106t105.5 -44t106 44t44 106t-44 105.5t-106 43.5q-61 0 -105 -44 t-44 -105zM1228 136q11 11 11 26t-11 26q-10 10 -25 10t-26 -10q-41 -42 -121 -62t-160 -20t-160 20t-121 62q-11 10 -26 10t-25 -10q-11 -10 -11 -25.5t11 -26.5q43 -43 118.5 -68t122.5 -29.5t91 -4.5t91 4.5t122.5 29.5t118.5 68zM1225 341q62 0 105.5 44t43.5 106 q0 61 -44 105t-105 44q-62 0 -106 -43.5t-44 -105.5t44 -106t106 -44z" />
+<glyph unicode="&#xf282;" horiz-adv-x="1792" d="M69 741h1q16 126 58.5 241.5t115 217t167.5 176t223.5 117.5t276.5 43q231 0 414 -105.5t294 -303.5q104 -187 104 -442v-188h-1125q1 -111 53.5 -192.5t136.5 -122.5t189.5 -57t213 -3t208 46.5t173.5 84.5v-377q-92 -55 -229.5 -92t-312.5 -38t-316 53 q-189 73 -311.5 249t-124.5 372q-3 242 111 412t325 268q-48 -60 -78 -125.5t-46 -159.5h635q8 77 -8 140t-47 101.5t-70.5 66.5t-80.5 41t-75 20.5t-56 8.5l-22 1q-135 -5 -259.5 -44.5t-223.5 -104.5t-176 -140.5t-138 -163.5z" />
+<glyph unicode="&#xf283;" horiz-adv-x="2304" d="M0 32v608h2304v-608q0 -66 -47 -113t-113 -47h-1984q-66 0 -113 47t-47 113zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408q66 0 113 -47t47 -113v-224h-2304v224q0 66 47 113t113 47h1984z" />
+<glyph unicode="&#xf284;" horiz-adv-x="1792" d="M1549 857q55 0 85.5 -28.5t30.5 -83.5t-34 -82t-91 -27h-136v-177h-25v398h170zM1710 267l-4 -11l-5 -10q-113 -230 -330.5 -366t-474.5 -136q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71q244 0 454.5 -124t329.5 -338l2 -4l8 -16 q-30 -15 -136.5 -68.5t-163.5 -84.5q-6 -3 -479 -268q384 -183 799 -366zM896 -234q250 0 462.5 132.5t322.5 357.5l-287 129q-72 -140 -206 -222t-292 -82q-151 0 -280 75t-204 204t-75 280t75 280t204 204t280 75t280 -73.5t204 -204.5l280 143q-116 208 -321 329 t-443 121q-119 0 -232.5 -31.5t-209 -87.5t-176.5 -137t-137 -176.5t-87.5 -209t-31.5 -232.5t31.5 -232.5t87.5 -209t137 -176.5t176.5 -137t209 -87.5t232.5 -31.5z" />
+<glyph unicode="&#xf285;" horiz-adv-x="1792" d="M1427 827l-614 386l92 151h855zM405 562l-184 116v858l1183 -743zM1424 697l147 -95v-858l-532 335zM1387 718l-500 -802h-855l356 571z" />
+<glyph unicode="&#xf286;" horiz-adv-x="1792" d="M640 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1152 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1664 496v-752h-640v320q0 80 -56 136t-136 56t-136 -56t-56 -136v-320h-640v752q0 16 16 16h96 q16 0 16 -16v-112h128v624q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h16v393q-32 19 -32 55q0 26 19 45t45 19t45 -19t19 -45q0 -36 -32 -55v-9h272q16 0 16 -16v-224q0 -16 -16 -16h-272v-128h16q16 0 16 -16v-112h128 v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-624h128v112q0 16 16 16h96q16 0 16 -16z" />
+<glyph unicode="&#xf287;" horiz-adv-x="2304" d="M2288 731q16 -8 16 -27t-16 -27l-320 -192q-8 -5 -16 -5q-9 0 -16 4q-16 10 -16 28v128h-858q37 -58 83 -165q16 -37 24.5 -55t24 -49t27 -47t27 -34t31.5 -26t33 -8h96v96q0 14 9 23t23 9h320q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v96h-96 q-32 0 -61 10t-51 23.5t-45 40.5t-37 46t-33.5 57t-28.5 57.5t-28 60.5q-23 53 -37 81.5t-36 65t-44.5 53.5t-46.5 17h-360q-22 -84 -91 -138t-157 -54q-106 0 -181 75t-75 181t75 181t181 75q88 0 157 -54t91 -138h104q24 0 46.5 17t44.5 53.5t36 65t37 81.5q19 41 28 60.5 t28.5 57.5t33.5 57t37 46t45 40.5t51 23.5t61 10h107q21 57 70 92.5t111 35.5q80 0 136 -56t56 -136t-56 -136t-136 -56q-62 0 -111 35.5t-70 92.5h-107q-17 0 -33 -8t-31.5 -26t-27 -34t-27 -47t-24 -49t-24.5 -55q-46 -107 -83 -165h1114v128q0 18 16 28t32 -1z" />
+<glyph unicode="&#xf288;" horiz-adv-x="1792" d="M1150 774q0 -56 -39.5 -95t-95.5 -39h-253v269h253q56 0 95.5 -39.5t39.5 -95.5zM1329 774q0 130 -91.5 222t-222.5 92h-433v-896h180v269h253q130 0 222 91.5t92 221.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348 t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf289;" horiz-adv-x="2304" d="M1645 438q0 59 -34 106.5t-87 68.5q-7 -45 -23 -92q-7 -24 -27.5 -38t-44.5 -14q-12 0 -24 3q-31 10 -45 38.5t-4 58.5q23 71 23 143q0 123 -61 227.5t-166 165.5t-228 61q-134 0 -247 -73t-167 -194q108 -28 188 -106q22 -23 22 -55t-22 -54t-54 -22t-55 22 q-75 75 -180 75q-106 0 -181 -74.5t-75 -180.5t75 -180.5t181 -74.5h1046q79 0 134.5 55.5t55.5 133.5zM1798 438q0 -142 -100.5 -242t-242.5 -100h-1046q-169 0 -289 119.5t-120 288.5q0 153 100 267t249 136q62 184 221 298t354 114q235 0 408.5 -158.5t196.5 -389.5 q116 -25 192.5 -118.5t76.5 -214.5zM2048 438q0 -175 -97 -319q-23 -33 -64 -33q-24 0 -43 13q-26 17 -32 48.5t12 57.5q71 104 71 233t-71 233q-18 26 -12 57t32 49t57.5 11.5t49.5 -32.5q97 -142 97 -318zM2304 438q0 -244 -134 -443q-23 -34 -64 -34q-23 0 -42 13 q-26 18 -32.5 49t11.5 57q108 164 108 358q0 195 -108 357q-18 26 -11.5 57.5t32.5 48.5q26 18 57 12t49 -33q134 -198 134 -442z" />
+<glyph unicode="&#xf28a;" d="M1500 -13q0 -89 -63 -152.5t-153 -63.5t-153.5 63.5t-63.5 152.5q0 90 63.5 153.5t153.5 63.5t153 -63.5t63 -153.5zM1267 268q-115 -15 -192.5 -102.5t-77.5 -205.5q0 -74 33 -138q-146 -78 -379 -78q-109 0 -201 21t-153.5 54.5t-110.5 76.5t-76 85t-44.5 83 t-23.5 66.5t-6 39.5q0 19 4.5 42.5t18.5 56t36.5 58t64 43.5t94.5 18t94 -17.5t63 -41t35.5 -53t17.5 -49t4 -33.5q0 -34 -23 -81q28 -27 82 -42t93 -17l40 -1q115 0 190 51t75 133q0 26 -9 48.5t-31.5 44.5t-49.5 41t-74 44t-93.5 47.5t-119.5 56.5q-28 13 -43 20 q-116 55 -187 100t-122.5 102t-72 125.5t-20.5 162.5q0 78 20.5 150t66 137.5t112.5 114t166.5 77t221.5 28.5q120 0 220 -26t164.5 -67t109.5 -94t64 -105.5t19 -103.5q0 -46 -15 -82.5t-36.5 -58t-48.5 -36t-49 -19.5t-39 -5h-8h-32t-39 5t-44 14t-41 28t-37 46t-24 70.5 t-10 97.5q-15 16 -59 25.5t-81 10.5l-37 1q-68 0 -117.5 -31t-70.5 -70t-21 -76q0 -24 5 -43t24 -46t53 -51t97 -53.5t150 -58.5q76 -25 138.5 -53.5t109 -55.5t83 -59t60.5 -59.5t41 -62.5t26.5 -62t14.5 -63.5t6 -62t1 -62.5z" />
+<glyph unicode="&#xf28b;" d="M704 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1152 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103 t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf28c;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273 t73 -273t198 -198t273 -73zM864 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192z" />
+<glyph unicode="&#xf28d;" d="M1088 352v576q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
+<glyph unicode="&#xf28e;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273 t73 -273t198 -198t273 -73zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h576q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-576z" />
+<glyph unicode="&#xf290;" horiz-adv-x="1792" d="M1757 128l35 -313q3 -28 -16 -50q-19 -21 -48 -21h-1664q-29 0 -48 21q-19 22 -16 50l35 313h1722zM1664 967l86 -775h-1708l86 775q3 24 21 40.5t43 16.5h256v-128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5v128h384v-128q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5v128h256q25 0 43 -16.5t21 -40.5zM1280 1152v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf291;" horiz-adv-x="2048" d="M1920 768q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5h-15l-115 -662q-8 -46 -44 -76t-82 -30h-1280q-46 0 -82 30t-44 76l-115 662h-15q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5h1792zM485 -32q26 2 43.5 22.5t15.5 46.5l-32 416q-2 26 -22.5 43.5 t-46.5 15.5t-43.5 -22.5t-15.5 -46.5l32 -416q2 -25 20.5 -42t43.5 -17h5zM896 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1280 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1632 27l32 416 q2 26 -15.5 46.5t-43.5 22.5t-46.5 -15.5t-22.5 -43.5l-32 -416q-2 -26 15.5 -46.5t43.5 -22.5h5q25 0 43.5 17t20.5 42zM476 1244l-93 -412h-132l101 441q19 88 89 143.5t160 55.5h167q0 26 19 45t45 19h384q26 0 45 -19t19 -45h167q90 0 160 -55.5t89 -143.5l101 -441 h-132l-93 412q-11 44 -45.5 72t-79.5 28h-167q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45h-167q-45 0 -79.5 -28t-45.5 -72z" />
+<glyph unicode="&#xf292;" horiz-adv-x="1792" d="M991 512l64 256h-254l-64 -256h254zM1759 1016l-56 -224q-7 -24 -31 -24h-327l-64 -256h311q15 0 25 -12q10 -14 6 -28l-56 -224q-5 -24 -31 -24h-327l-81 -328q-7 -24 -31 -24h-224q-16 0 -26 12q-9 12 -6 28l78 312h-254l-81 -328q-7 -24 -31 -24h-225q-15 0 -25 12 q-9 12 -6 28l78 312h-311q-15 0 -25 12q-9 12 -6 28l56 224q7 24 31 24h327l64 256h-311q-15 0 -25 12q-10 14 -6 28l56 224q5 24 31 24h327l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h254l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h311 q15 0 25 -12q9 -12 6 -28z" />
+<glyph unicode="&#xf293;" d="M841 483l148 -148l-149 -149zM840 1094l149 -149l-148 -148zM710 -130l464 464l-306 306l306 306l-464 464v-611l-255 255l-93 -93l320 -321l-320 -321l93 -93l255 255v-611zM1429 640q0 -209 -32 -365.5t-87.5 -257t-140.5 -162.5t-181.5 -86.5t-219.5 -24.5 t-219.5 24.5t-181.5 86.5t-140.5 162.5t-87.5 257t-32 365.5t32 365.5t87.5 257t140.5 162.5t181.5 86.5t219.5 24.5t219.5 -24.5t181.5 -86.5t140.5 -162.5t87.5 -257t32 -365.5z" />
+<glyph unicode="&#xf294;" horiz-adv-x="1024" d="M596 113l173 172l-173 172v-344zM596 823l173 172l-173 172v-344zM628 640l356 -356l-539 -540v711l-297 -296l-108 108l372 373l-372 373l108 108l297 -296v711l539 -540z" />
+<glyph unicode="&#xf295;" d="M1280 256q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM512 1024q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5 t112.5 -271.5zM1440 1344q0 -20 -13 -38l-1056 -1408q-19 -26 -51 -26h-160q-26 0 -45 19t-19 45q0 20 13 38l1056 1408q19 26 51 26h160q26 0 45 -19t19 -45zM768 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf296;" horiz-adv-x="1792" />
+<glyph unicode="&#xf297;" horiz-adv-x="1792" />
+<glyph unicode="&#xf298;" horiz-adv-x="1792" />
+<glyph unicode="&#xf299;" horiz-adv-x="1792" />
+<glyph unicode="&#xf29a;" horiz-adv-x="1792" />
+<glyph unicode="&#xf29b;" horiz-adv-x="1792" />
+<glyph unicode="&#xf29c;" horiz-adv-x="1792" />
+<glyph unicode="&#xf29d;" horiz-adv-x="1792" />
+<glyph unicode="&#xf29e;" horiz-adv-x="1792" />
 <glyph unicode="&#xf500;" horiz-adv-x="1792" />
 </font>
 </defs></svg> 
\ No newline at end of file
diff --git a/view/theme/vier/font/fontawesome-webfont.ttf b/view/theme/vier/font/fontawesome-webfont.ttf
old mode 100755
new mode 100644
index 96a3639cdde5e8ab459c6380e3b9524ee81641dc..26dea7951a73079223b50653c455c5adf46a4648
GIT binary patch
delta 34114
zcmce<2Yggj-Zy^FEmJeSrA}rtnVAsMlbK0?Btz(g5;{^t?+|*`J2XWpDp637vLY&C
zLtU|;M%P|gb;T7GjXthrS6!BMeIUsk{@-&afq*>w?EC+`pEt>E=bn4Y@BGfMpOb?>
zs?ML%$Q<D~&d9|$fvfM^cjVx?!lEun`4LBYzutZN@=tLh#}N&lJwrznmTb9hjT_H7
zc&?weU`oRSZ^#SqyoKZVbF-!_ZMb+5C2`_9yw}W{zj~%EuW>P+H*usjZ}yBS(+x>)
zjN-_}$MHTqd-e=@ib>FoN5c0=$ez7m*{a4au3V1ik~mJMo4;t<lsVhK8_n^$WR8=}
z3#P1U;Lq~u9B*O`@GP9NU`A=*&2QkjKgS7M8Wt^G_C{n{PmZ^~&vD6~l{2Q!+>twa
zD97iXMSc|y)?M!1%6tFFuJ6?K-_BaXeYm{pNIN9(9ZNwI2uJuEaYp~~gz{DW$Zed&
ziQ+b~6wfy%uKZGzdQ0P1e0t+lQsMd${b!Y=b0R?_xCSnYZ;Be9AQQ~z+~=y!4LLXI
z+`@A=oZE43f1{C~YCdN^=RFraS9h-dT*JB8x!W2W_<FnP@1~zjKbrn#`m5;&)Ay$D
z3}{H>6k*AeVd1Abxf@_*S7imt!X;w+)n>7))RNO-S9?pGc9qYY6$q78@e#qtvXy#E
z+@cF__}HM?g9gnO-c>H|dXrm!G$admr3M12ZCq-=Y)<2ky~~~mXHGFDiE1JqOAVB<
zZ`%KaCYr@1`-L?<bmpQ!8M5lTWEM+81osAOrX!#Zpw~~nI`UIqA|+0TrSZTRPledL
z^2m{uC*E-XrLgy!>ZMx_z4>PRN0ubTj;w5pt~|nz`2LRaa`H#*!JS9Hk3Vu`rO>qU
z2rKCPnD@Hp0i`a+RGbv!(zqZO0l>?GUPr01y>}(9NWhn+GCNC4!v03j9qIC&D!S{m
zkXAG*JZ;;yX%i}E&%g6vbMwK&?~v;jELeyiVolVWsEA*g8rYOv7WVCUb4T|X)4!sx
zeD&c<mTe)wnYAvF3+(|OTs)-Zq=}r5D?~Hwyy(ly4)A7cIJ?y2QllA0Vt31=w4_Ri
zctc*N-{EukLcUOGsMI0tdz8NT{+;yftIL+XO3Zf>_j_+Fe{AgsYu0?QcEr|ky)sp_
zo_{JynD)VkAAIm3zvzAX{Bf3%<P!6%%bH$VyzW%nsdWW?#t!kdRadh-AAA59F$Cq*
zF^R*hN$2vo9^8|KyBhp*^kP)i1f<t;7A^%1?#h*N-MM}W@&GMDKp(CheLAiLsH5PO
zvm@o|Ya$1}Ed@3iYeQv&YUlEmwR3B0=f<}x7coAlEQH7LwQW5nZJIP`lXy1q`kjV@
z4GjnR4VxxR+_-V#giU{#Tg!6N@7Tw+{Bq?I-@!_(trh;kKAjXllz4d?`?P^BNqo8K
z$vG$PtCCfm{vs#+3td!mdd|ezI2RCvle`w61&2Q(sY!$=hd|U?67o7EZR@=UrTqun
zhI<8*H$Ju(f2vpfmzn&`nWxE_81==U5IpsyIUeI<dHW9E!>8_~kKE2by*7Svt*|yO
z*YoRJes|zN0_aaZ*!q%N_5rFK2?qlLK%zDhUsf;>45(GORlAVnauXL2(`IE;RGF6+
zWkNcoB;C>PhUEoD>BVinu0eyxy`lS@wE1aegY*?8rXHr=_4~g5yrnam3L8FAY3M&~
z^%b8V3BUD1l6qoty)n60*^`maB2SV4Nh9*{9%;m(kwJkj#-y(>VSH$u7j)rTh-!AX
z<Eg;$r;?tgkA1q2esgm5>XRgWAIbak2WyY7|11{!Z2g#>llpp9bP)e@ugcT(XcNmo
zx{>sgtKWKS<%Tcm`7bvV^`9`@5747t3<gGqGXv+cxFOsmG{C7=d4hpRxP(Ch7lnE;
z{FB=8&lxETWT^u|o6GJj3726SsR2Vl#U_->VRyQ45=%?6LuJ7#l5OTyqNjb<c|@n!
z&up%uKUbN}Dyyn!^{Qf(Y^8rH8yE@=Brk;qmf^0o@AT{qzps9iCHljuXKboIPp$Wr
zmGt#zsz~x{uaji8JDbehah5(s@1Ree-Lc~=8ARrjL1)Qgv#F}eWLBw)i&Y<?Fn^$I
zoS&6hHoUlR_Ba(u%lDUs28K$CB?o;|J<i{^*k|ZwO3T>s_S-u=DW;0&cds8!>~aD)
z2`Xk%=HoDKN&+^(7zH*AG=2sV1{$XV8|4nb0YC!52yh7`?%Lo1WWx%0$W?eI95on1
zKguD4K{89ZCvzn;r3F<5`O$nbJaPSVkFL3yi}!?&lKf0he!i#3@q$I{v1gGxuWJua
zs&w|qLuXYfnWVHcE|T3S6=kYaxw)!cnFR&Pm+jYnxjiz6i2n?F@=#0HT**p*v8x7q
zdgQuG3@NTPk36y_CD~9+zS-?fA<pB|g5>Gc;R?!%95BZQl0{rzi&rhEy%rM0UBnjg
ziX8nQnYgHwx5G{UL<*DX4-hJLxJkbFLHxN)I>k-@?k0tNKQ}qxCKfk$JlKo8Ymz+|
zJ*sBu&zu*)wzp$WsLYxjai}<l-OYQd_)r-a3^_%ss`=*cXcIk1o4&jG6;gNd3_UaR
z=ubra>F7*)=FCY__X;0-oV~pHI}&~T6j^#U^P7Bn@Y@Z@fQ%cyCH48=WS*tlQ59#q
z$f<r-amQDTAa6<6=^16x5+86nDENq_^f$xQh3FdgCEIiNt|ICg{GU4mo41pH(l?9p
zCXjM!qbG!0Ix(f=4_-&^w97oF1ugtLz!&8DC}_odF?UQv03qs1vH}q>q;PlQjD(fn
zD&llGgLcp<mD=tLW~o(zLY*SEDgtrA2~?B*Zgq~KS$Qb|NsRDPFs0RzENFe!Y^@a7
zxOvuN4KqW@dLoG8(7Ox9)P1pd>$q{#t^5e0r>C76!uL{s20uDWE}FMkSTk}J?d?sq
z(fduQUbmyXx#7!lKko|8nY_DiwMrmD_b2DA|6zCzPe{Ec{;SUGlwQgRq}saNcf4>B
z`CKRKLD_v=H*N&CklV~1;2!0k<=$fBsY)<1Fe6MHpPKcs1TF8JUKT+2K}(!?RZXh+
z5;jvLTUbeMr!Po}fW#mNr(`#gAbX7@P;Zq(W^W?I|DP6RPn2Z~l_^!L?X2zy0dq*S
z(0TRX^FNgOGkhifbiZK9%kx-xz15kTOeU9RXJjK)_P0DZxay#d?@2VOL3Z9slB{N@
zFnTHpbzvz+A+2}+8GX8?_ppkFJ~r}-MjEVF&&`u8wUQ=?d2YZXcahvMxaxpiDP(w(
z_}fBK`>;YXdRSN?XAA@NO4b@1FJBlS<zgQ4dRtDmddZ-&^IX}WL1h}8`4#?RPrAR<
zyDHaB=IKSpk?a!Xc}Mq<jm}o-Yzs9yfuHg<kyJWw&in!0`zG6yv}WSaX?6GPGHWG%
z$tJNuW6+U?^7c;*%dYyQ3%(&{(M%pDMm=OCNoylEpA+@D$d|23TO@YoxZ}<1h}R)s
z78o%vKx{eUO(S0RtGycZLL>dO@dpy2Cuo0q0`h{)&wXe`TXe-k53LZIRy;&r;e&0v
zMXrq_-T3=2r$5A`E*Il>8b-7RbECNF+&swp%el2Ow}HEf+s56&-3??t#67@0#67}2
z!9CBt$i2+H%AHhDS1o`qs}g5O4PF&H6nu^d1te6KIEN#)GBAXQjd2Bt6JBspFK(Eu
zZ*!Bx89nn6ydg?zi43fbSb{1w@w)sdmxLohwJ#zN7m3)sBrKH@uf^pQyb)p|r6IM`
zVrL(^ED?)~6cV*15>)wplFOmx{XvVQE+sBoAs?tDLLjK+LxRm`BkF3xniSC!S6IWP
z+TRmW>@N%6<P<Y)kS%2vy4aHH$`W6;rwAwQDQWgMNY)2pmMhgtwwc3bvct;W{?X-8
zKW|HE3zE(Bp<C%gWVSW8Z9L)M=Oq<?;(3Fae~_+wk<X>yoAda`h#0lFoo)1!YO>PY
zla3;THEj(N8BMo}Ml0DFrSI%}`Ot$R(a1;Lcatt(eks29l1f-<jyIm7f5yn>#Mf>i
z-{y`Y{+~Aq#Hsm2($HEGZfiP(AF;A%L(U(0;pqCo62IP&DbjniT01U}X*8}ZtKDw*
zCTo(&P%+c4)spE_rX6|6SR#^a6Pc&eBzqnB@g}R1=pGp&m%&I+h?#Bgk*RdQSx6VP
zI*H!J3*-$l{uK>Rn%;cV+&WSv^&UEh=;(V<dRsaP(<7n@`H!h2vZ{vky#LG#$23BS
z@WgC5MhtrT);`kh$1gPW{J^*Pq~@=>(%0zAq|~&Xesd;|Y-!~I3<qFF<W)qZ#q?S7
z>zDM~wwvi+NZNn>S6?zmCt|#F;`a=Pz{fCGf;hq%7-v#s(o0hVgAO6X3;GAdC_TQB
z2V*<FvF(?Q$Hn&_j~3AMf@sftVeH12$jp|SO)tK<Df=mMq@bpzfZ7XsK_P*#b8#c|
zwd*+@XXo4;ObSHg1fYvGyR<}dy4XX|$`LE)PdrEgU~8C*sMJp3e)<QRwbK3`segYs
znLe=}T^oOG(Zs3-K1>fS<t=1dj*)&&qbp|#e|-7ToAxds1K)Mj^_1qWrWy3*>&CoK
zrpWKz(sSJ6_{(%{|8Zmk->tO=na<l+OqjKbR?*Ll_L80>UGI_Fg?DXw40=5p8`E&&
ze{)W#NZrv?8w4^YaN$sOCAP4)1cJN=+N?|HNEfPj%*AjdA)=}UFikwV)HC*Oyy4B4
z<*)C!<Lj5-jIERQHWU7bJ$rs2JpIS|ll#^keXV)duIAT{uA8&^@o{fI{P4NRpYFKp
zi^mTxS@*&64-P;4wz#TQQ!)OIJH}Ut=jFL`Tko&vDa40t-#(;G=$hx7KR-*@D(>D}
z(>9{CWad0b+f3j-tl^~bP=7L^l2&sQIL^O&QH&Jsz9B{|GB}}P3kXNr=?4^5a7fH{
zu*uKe_K9}4a-!e3?K9XtP88|ax|g>6cz<j5{XgC?NB6tMGl%4p+!yX_Yc$^U@L~Rp
z!|is&eXIc9#?JAd*qO+WunQfbJj_+@cj0{h{XhPA|FYLgvVx0$*X#IS8{6)zDffN`
zf*M4Bs#J`iiXhwuXs!;B?+gfUeqd2PSImXD3a*mt2_a_yi0&|u-RroCkfdjU_%7m>
zax1yDoD3o1W^OxoJ15@>5`36D1q}CEw8XERp$FQal)J7zA}+P7(@{-aAaa)vg8bfp
zbFlZNj>r``<jbG9LhQBr8i!wz_!W|_g7tt8gBXJ$_|%Y8m~dJ^R2V#lVoq0SqyRj^
z$g8-v^Kp%IPs^M9o&2GeH;4H<eyUA#Oqn>`>?)gPn}*IY%~^$Gb^Eog=MrLHN*qgx
z9XFTnTc7bSz4z+$vqP446zuoMx2%8Wne`ivAE&2-J$m;DHcUwsGJ8$Vh?M&xbweXv
zavWI$OoCg;*1C<U&ZLY;NcO6@mfPr~WOz?uf7?|0sg(29TlC|lOYi9PcWYLm*O*n1
z#SVkFAS<iDTR5p8tAHI73$qHu53;ZNp$`vTdS%kmq1jiIiSm8NH>{VH_LA$fyJ#h1
za}<|W=jxn!nFWPvqPIJeRZdqoViNR%ir2aF8AoT-U@0clcBrvtE*B}#OjXcIv)L7@
zXvrli*{;WD5HI7*keP+a2b%ZqZx-nO<^u<sNpp4ndHIw4>gs&*SYDJr7tJG&<yVs}
z?B#xzvtjXmvApF(UUhYz)SI1u_dA?XB{MhXfFzy9bsPwi#JD|%y+EB%hncv_2oPi1
zDp;VHw7_9nONtH%8il-Ux`)bSJQ(?eP@y0Yz6eXZh<L|`pY9*EXU&q?vzDy7Ys8*E
zynkT&C!-`!y2j|}F@yd~-u%@~B<<v?Q~Ph<eB<G9GdHiF?4D(@XIlPzpxeC45{=1`
z(*5yCFHx~Vc=p}bcJBKiGGW!`O{*qEj^DlSx!OuG!{#t1hsMqyv+Uy=-y`NRTOW9E
z>zK7OCdd44yLE{D!2A9@zr$op>ouVDMSq5g*|1>YV>YZb#Zom!0en~V3sBF1Q3XTL
z9aIa}flAB+t}!?=;t-nxsWI3cW6WZixQTz;SU)mk7p_cYuj7q(jx2)Bu2WSmkjx--
z3T2E<1U!#%ydWEI7jZ&hSE_MIT%gR>h!PtiiP@momEja`WEG{ciflWHpS6H~w$p~3
z7dabypVhc)WFZ(K@JNvnVT<8GuC*}InZXnT&~vqdH)!)}d9U9qD8i|qI3cq^4kQH-
zR~Sxx#4n;Bksrv!c;B1fr7g5sh$H2NwpaLv-laeDi^w?IOk2oxBxdBzZBc7CYg^RJ
z8%fOS6=PmO=Hj#XyW83XF-BrE*7hBLw{k;bGbv{+w6t+{yU1Aztvr_s)JNOZKY{iR
z;C6Ed!Cb;6nM55_tFj;y{@YW;1=B?)`OQi0Nc6MMJ91fsK)4zza0muc2kf{OD4S}*
za{253txn?bOQ5D+huVh0h>aUD!Wy=Y7=in%PV(hvmg~0}I;FMbx0l6oML)FI-N$0^
z0pK@w%x$-P$f{DZ|C{;}#gQlhlw*{$$u^~RHum8)52aPtd^2J-`*!$nn{9ZM_(`|a
zN?kY7HHII0s++DdmA+0tv*IN({Lh8RBg9npNh}6LROXl>@(Do7Ufc?f^V$jtv6%>g
z$&yJs3Bd<K7_(ZswakhQ&DAa7MiZ&R_%e+<;ad<Q!BWr|CRQkKK#fY6e!|S1ATmyM
zsoE{be6+rv!6H^qIG)#y?mI=DuAb6&w2o&#di)7Vl0k2=x(wL`Hl0DAq&Mhn1=$9d
z)uJ~@Ndn8l^W@&0tJ`+1-l@$f7#14$v6Fx0Lrb4*Po8^zkNNIAPj(;6hp(v9J|13u
zU9Ool#iGo98;$WLvdC*}Ja5zRqE#!X)uLCEs<Eq+L@~vem6DR>OA*B+wH=9GQLPrV
zZHHFha?9$<B{wgelKOcxnq<!@ugI;sE!SUF<<GsXDz~CMXV}oMyz;?Y8KZ!YD-Mb^
z2r^d#sI=3_2Mb_0fU;!-sRE#UGP4I`z5^~1W>A1HhQX6}c}s&J$^aZ5*}TEUnE~K-
zg*F8c5)gPVGYi@nF*iGNNZ8B<$OihLf@mOs6KUc}y*E5R>vunylZFoMSHIAoc9HAj
zYJ2cmdV#2)9W*F;?eC+qLK%nLI4v)O=a!E8!VObSAUW=}_g!L3o55Z_xpd=gx4wP;
zqot3#=<7ba)zVm)x9P+QDMmCWPHgH?`KU?fG&y|MM<<eBX1%m!kXrxE!9{QMn^*VE
zhP2>)pToMogs9W<7lIC^m1H<$`EHjxea;daC~j)t;fd90si)(uw=c@{WI{DLLC>E!
zfr681o2$&I&miLD4Vw}?my=>rGlaXL97w;{Zsa`$kbL053d2qXW4fqzi_E7|AOgmK
zo69Yb#_I>TWVj*PjmT1L?R)>CE&qCNZOyV({ZjKpDKoWOeMJszU`10my!6pa8>SWs
z#FSG}-z_y$67y2~ty)$?V}aCYAoU`=U(wV+ZHUA|we=gH+qm($>KT=pnUyoDi-(4N
zNhk^h>e7;3W>KH%bKC9i?93$5m@K=}bSMf1Ci%icg`pJPW(QnoD4CU3OCDs!ZDd^i
zVoZ&Wg2#c&6R#24m_qFXK`#b8jkv+upzph!1b#g96Sg@$SV0zy1YX9^!Qy#W6=tJT
z;z+Ti6NR{ZyS2<3zfCfe#ZI5p_eE8f(~+gxS#ITnv*@jhG(KCte*LQ|UtX59j9xd3
zHdn1*RF|Dyw`hG;GvzszRuJP4TCMyz-kRnhDe)Qh)Kok9OM{O*eEZ%r7CSF>p~Lw{
z?Wt)FTD14}&(C)q5Y5hx4(NKGi7EU=2Pej)HpRCDa~!9(pm7<b@qMFHwiFN^VoD?|
zTC>fZ2h+eK#^~wO%|@%$*laaMjn>5Nu79pi(r^80^Ft)}QJ7g2l%f~t4x#A`eHOUV
zDXVfzMDwG>y7$I!cbaTF>0hmM2Sa&=hzSoJv|0dJ4k|7>=7VJO3IdUZnMaI#Rsj#h
z!jvSSWR(P9O*D=(OHHW(r3Sj;hVgq({q@w|@whC1=N@tcZDp;F&tkQ(w$Td`#+TN!
zRHCBm?|El=A~*Z!26BVdScv|$#4h)S(F;ZE7STSaFnt)wusQ%UM+eMYa)5)5904_E
z6aj<)=%COBwW_0yLe=fZ07RwYdZn?6+tc*)vD*(<t8A7&4ozOuk4<@+j7p15RUN<Y
za+}3h`_sQYz@WOR)2GVqrexCZ%)keTqksJ|bDDkbh7EJ=Y35_C?NglfSs8GE7R|5W
z2BP^1v9|-hl|&8rUeO(f0nq9(hy6?j?dXHZ0cf5MSl@81?%es$4M}F=d1uAvW4Vhr
z8m;l0F84xeHd+CDoUO(iFYbTq+Wi5J^tJ4LmvnU*Yx+{Fv9-SQSSTZ*VqKXBrSU)L
z3L6<%(TuQ<6_9EY1c6T=RRRd@#2b_;6VuoPGVZyu&(i<iXAI#DWizy?x*{FX&RL`k
z3uuUk^;6zFcXa!kaTWW?&i(&Cp~6P_t^J`zI-<$br0JG60Jfb5W8S3p7t_jbxS=!9
zWH$czkuc{u6_w&#IakHia>KdF43BwL`^;xhX$MUuEU^h7Re}pDGp##Ohyp_i@Hr>^
zrskl^ER-lx1Q;A>1hFtvkOh`_GY5{R$Py}=B(MMHE@i+Igagv+mGlFCqW4Z7J$mvz
z5^QUPywS9D)}B4HmMYAUzi{))l{fRzXW7(!R(T=(eJ}m_QS%kFrBm_k6y_w!w>g$B
zb=c^i<oMeg$^4BQ;U4_8;_%na4^$+m0F4pRG<2wmwn64oXi&ui&0im`VB!|Js8TZw
z>&w-_4Lbi?SO&pY#i>=<!2&@cm5GU>5G5#-oo1E{Hkd#t#6B?b!c|55aEyX2aFGHg
zWdLH(mV(L@bQ9GT=r*X@nMuzb|BxQ)wfz0YI*s<0uWwrM*>wsIbsBxzJ?rV6N+RXN
zdq2frTkMO&0x`Z5lF!@(SPD&mAyVkMcS2{x`p(mE^3SoSX<KT>r!T2y9r|MBO@F=9
zl$dwX&bbCo)-DBF(S!CtO3MSv>A^NvhWkTO?O(N%UT9N8c1fhrmyrS}suT-5l=FcA
z;{<N@zX2l<rxPvhAU=v0UZFn;bW`N9NWjd3MlPY5S?yHCI)efr^U(kP{g=-z-->=(
zjrE-f=H3g}yHbeZx#s6~KKfSsOyq!caiGAn%V+G_Gh_L)f?ScnH|6<Ck_A{jMcdM{
z)(tWJmJVB<C0X}APfQtE>!v7E@Vj=zBa0Z@sd#`iJy6kh3E61$0U%pKxKQ|BcZl{t
z2B+MCJt2$Q<+Ph1X+Vv;k^@G9fwF3%sBZrwFFdtPt1STO**4@#o;c*;MEb+0uFV_e
z4(9mrHeD)8&~6`kC6gTTa3cNTQwnH*%PaYdqQWaHVD1Brfwz{2^v4GS)^H?riK2uQ
z)wH7@9UXO)LNZJcWnK|II5QtRO@fcok009n)mD8H=*dAgt_LS1TJbj2ySEcPnvi&L
z;WEb&)+N(t&pbf?y3=Ob`R$E+iS<!)V&o1_NPP2_&GuHJpb3YS?zGD7L!@v{j1SZ=
zbxgbg=1ZkFcBbeT64vfcWKsp1m)$Nk!Pp0xFQFND+Xu?k!9vvwY&QC-Hcgwa(>+T+
zRjS-{MI+@-tt5eGb-H}yZjD~<6u$snrk^HWJlo8G(F_*!D9OD9p+w@diE7$@`V9kB
zhKHF^60%<hOJuyVO6DQ0b~INJ{FFwbhIY{^u8_+F8BK_K@q1V!`00#EwTn~ncdn`w
zgf%9{puocS#zacxxFprVw2e3cMLv_24{y3G$3Ze9oumjp)Gps8F6e?{gJPm%wlaa(
z{PB4$r4b(!y(1xz3ucOfy#jM3#H@ePQC~@kkFLHVuFcERq*#gUYkA05a#dg(-i-E@
zpyf(s5(n-8ucf7o3H2hIn=GU)XoTNB$OL|ff{NIWH_Y}3HCzOZ2eD^?3rK@1SRmAH
zdieEO`-%CX!0;6h&+2_+hAvz0cIL_@exugZb)4EWyRNeL*m2Rwr0U`{!)K4bNq<Sn
zNO3!PQ|ZvIPT}bMmv+o9+e{DEKl9M~!O`+yW7lb2hYu)`bo(+V{Dq8j_nbXq=dh}p
zma6IzC8K9ApHukA%QXH*-teNX+VpXPY4|)ufF_i<H6TDYLKmolT^>ewn5)rnh)k@R
z=ujjCX%@0B{vg^aT>?|XZ)u4DLw8vL4_hTTn>ymOBCf~E;(YL_#Qcobu<&l`5s9~$
z7Zz4*o_gD${zT}PoUTe%+e{iwNgpYzclqQbovA_o;lb(CAN+y-AU`;L)zEYMLE?$)
z?NzJZra#>Mhll9oE%R5s&6kYTN;+@XV5lm8XT!WPn(@7yg27?mqIL|>sWk(lp&~UM
zs+6J>Ccks|hrzR@nXC|clK$}as!2DJJD>Q|-6)yG*WpLe>zG}Ig`qJUW>5woU~gnm
zfEFAbc4SzKFWp<)ZOb;eB}n@bW3Fa)s66F$<>hrP$(<hXjK8}spq|7LW5$*ET`aX+
z^mN?uEL*6qJnn&b663kc=S%J`V7VF%9D=5M0_L#CX(kXjGRSUEIzjv*aLw!JF!jK!
z+^&k?29v-cOh$y{SETAIK1%8hHk*MSv>BQVHhPdfkb31I?io}@xZbmv-A3*3g!|5@
zwAqL5eq#4fyKU2`FA+KrV?`j?k{-C~YZ+xF3XV6G4f?s{mervd%coE7m1C*IkEMQ4
zSv$hT)c>t?q?8-osUr;Q!0vpC*^-@sKakj!Gw_euTiBW5rliKa%0yl^rOT>VPo18K
zjQ1`@$hzFq-(S#bw`dJU?S%_kqXD<<=Bkvq<M)352#4#6F7F`&_t<Ue8R@D1OFfQ%
z`9BweV&(R7fA0^6{3C?R-CwiDqDm|9hW+j4Cy3*m6{cH8uoQU_sD|GJ*Kl;8oR`rI
zFSBhEP6ZYBBG&?wv|^#*qq{!Zwd*5k^j8Ps(bNEsR2n5RUW>?x2Pb>ID|+B7+{XZ8
zFfzPUJakSautF$xc-1iDY8he&y`fTO%GM%0L&Y^U(Vrt^0G&bi;&%oa5TQReHNm3V
zi>x8NC^!ET6-T2@v8J{rfn7*b9Q^`|l37JCu(emj7>o}+ED;$=hA^WHS2gr7P~q%S
zD+`H(&7RF5kqP;&Pn|NGovqDIv-#9htq{r1D$%1T8q)alo7-X=o{`=*<>Z*&mY&%l
z#5O<Q(xil@lJ_xHSk*Fv>lKwNQ~7^t0N<$rT&MeMH|A?4u$7O-;V4pWNi^PcWxM1{
z4Qo~+Xvr(AVe!rnteKD~F5UvdvjRBaK<F=m;uYsqR?x42hG8+nytF)^hBRiL(ZZ|1
z68TXn$rdv$bY$3VMmM=AM0scYuj0J)A{Xt)%PH}Td2|iwZSfhC_zY1T-#RbFr};rw
z=n|LN(@hBSpVhXX==i>^U#DamJ{SHXw7t}iU&EWyRrDOpLTDI3jj74Pa<2+|^IC+f
zLfu-ps{-6)@u3#r7>mUpc~PagPr8VLSOi!h*BegXHliX{M7#Py+Ix_GWEh!*Sk0B>
z3Gy=egnUopJeChgh`&`aLkg@95;IEU29K(Ua?doSfGUv(92R*<X%<}K37#q^m@Uu>
zs+GEmhe6f}$=R7GQuG@MGeW|p&eYiUb6G;Ab%ok_9rMsZf@Ay*hI7;wEJI<5@4`-(
z-7UDBtO!Je;TLAjY!;ChDXkK!i46ND9+Vhj2aC`{n^~^XD%cj-8}L-vf#J$aRO)cL
z!brp!hC`fL-|!84&FWOCvw}_+qDuo3Dn!@uIZ6R&iXm%2CqUtlI6^9y0x36<VaA9A
zxP-qGUPK|F4#8FGW`@^*gd-SI`HX0<oA{9q&>}y)25P713TH<G)g<Il>Q$lJs6yjY
z1&x9_OO=J2L>g1_okBQ-Yyq@J8I%ZX2>VV}L)<~oFn)b#luPup?Ce7%I7<AiU+Qp(
zl^sBbl(M8Sh6<grCz?sV&;+b0A)X9RL$Auz0b2?JX-1?uofU>LS@{ERD#|HrSz;KS
zxGmt{B3*oGS>Zrgy3{aKu4`y$p7zgmX^XC3F^oT_v8l=USh#4cGd?W-s%uQ~=;sM9
z*)*yYW13p4PtR~0T<N}4t6i@Sjn!+lrXhS*AYC#P7zJL}MQ1X(dXuWf=^ls1JkZrm
z5O`57r4<*I<g6*IoO%1r_S`aWRT2UxLsNT<$|jOpl;QCZy152e!8g+v_2`#uwCHoS
zFiPYZr1U@*Kh&tzB#jN})WmL0^`*Ov-qbX`PLpnM(SK=&yT!D0yJv_m#n8)bkc9G5
z(?GW|SMP9|-4|YT57&Ba>1jC`y$vZozo|4LYM(Q9w`J!Sq^1a`H5NfISaRe%l1!Vw
zzyJR4?+?$NL)5yA^_f~xqUSV%$bZC(DwRI#MtYaIONGfQ2s)|HD}sL$aoztgaqRU9
zf~CfkT3!khyIRMqwCW^{Sz{CDR)|S%b2`t9<jG_{T$q=nv1q$xkYR$Qcd*Oqv662?
zxOB9^CH~>Hsq*0|Di@!rP0G{R2rt-1@pgU&eRNQrM$<F;{`-W82gPKgjR+=Fu2GxG
zo0Hys@^!vm8oMet(8nU^Mwf;+Y&HAU+7z3!MiNUMo$kk`_0$@C-hu^^G%Bmpy;x(?
z<fr*cy1Hxw<vDZinDgm^{9Zi<sB#vxe6G)QS;`mp<@v(gl$0(-ys&qK)0(N*X`LAv
zTAk5u%+MsIW86#wcwL`Rplg-a;@72EC95D3iRe{1f=cAQnb{5HH-yZt43cV2HVQ_*
zAYHT;bPEkIXiNr;QMiHr_sCmxHUUlrlhK%-Y$>~;qQU3!@;bhYl!Ssr5k)3z0v1no
zPM1($Enl2$0xG2^Y17SCgI1UBc4&mhGEzL#{cAI9;)>kO-3%V1F*?I+(vhX>gx)t6
zPxqu`SVddL+O3(!ZkuyeCiC>3mY(YtiGb#H^MqhvyUnWB$o7prcz)yIWy=pAUcQV5
zfR1S^FuC+X|6b3DW5)vW_L0LS6aQxSl_?sP)qF<=zrkhL{(7YNmAefNEg`&`jLXHm
z)EJ5-jY<+w0@2znHod?TOGUL-Q(!P;WCJSkO-6IS75b#myl|+F=X-o!UB0+-aM_kA
zqLv4hx4HBN{fJ&!?>QWe#XhGXIMRC{wkcc_@RGrUfI-Q2t0;+@7bkV!7M>SM(y#1m
zHWs7tb&CAZOG~5|8r>t4W#R@1;Xe^Uhg9k+sQ{Pk0=4u@{gx?Hw#1iC*-~G>B|ffV
z-c2|E0X9TZ@yXUd?Vge^<o27tZt$}+GA2)~?;A)Ox`!TnkbeI83mca9?(Hq?%09y9
z>?{@cxURM|$7PgsE>B^3|6w!c_uMzGblK#Y!|HmJ%9&<?H@nM92X-GBfpP@l8v=%!
zF*z2v)fEn*T7)pI#2b&O!g?YnRyc&A0R^%<G@<qt54I8rL9jeS^eGit1PE+i9adHr
z2f}+qe1@-4hz&X;><0*$klBg?m_ynh%K{!1i+4y!g-qBl35#9mqx9V`H*NZol#$`2
zjNQc-D2pJl9OClAh$UvT$808R=hpf%6pcQ^H;mj%rkp%U570^Uz{!&zD#>tpDc6(q
z^OJ&Hj}>MyCQ%AFOHG@;r0-r;-K(7|X<vO2A7ZAgvSxF%HstGOS;FiCODx@dA))qC
zbz};wp8j0VUe>b}LW#SbCr`HRKwtwCV`X*$a3NGOg$?4J0D%JPnWA=;V!_arzz8XV
z6q5!zbbUoTDsie~7h-DI`mDzDO{_k36rrbFZD>->`KFpllWNq_nn|Hrkz<l<ya_g8
z56jgiBO5Fm2Pqta2U$Kr$$hYvwWo8V(k?YBVgB`9)doij`Au6P*265%T#Z*WqjMW&
zG!hNs_@>&>Rc(mZUuvb&NaFdw(I5eOY^Mgv3Sc_7=>Khlup$c4H~$ty|3?jigxiis
zE=*piCW@{8e;zDIlq{4M(=24s{QG7I|IrW;&<{ym3;L0c>LDxnya*0})*A>4O!bAf
zYk^1#VP9O3X|c$;bi-RZd-AcABK=GBO<QVGQcg}%Qks?g<PPT0Y$Vs>HF*{9BulQ;
zoNJM69IJ#AAju>8k|Q36rPSfG*u6M=f+{b<89gBj&XzLe-WA3hAxfKIl!!*7^lU=|
zJsXXZC_+}`Cft}C8i+Y6#hPh-EZ*E4+qpB=%zI+wpmLjlC@NIq=@V=D7-cNPg3s=X
z&D3Xs>5YX9;ffW04%|x)L=oYzgnSM^TB3woqL~N}a*%{F40Y7vmDxP^Iy9KMG}g+|
z7&Dx}i5|Pi#V#OGg`+ibrATc<E+K~L0+YUoCefG}Yis{X#QXN27JLyyh8SMr26u75
z4D&3;v$@7TK(BOwq70$~Ffu(hsPw566u%c1V<OrC6Z%rWuI!z~*U?APxt}mW`k`od
zbe5p6UL2qdFf}ELf>IvRqD_eT!U6cRbBv%<XguaS>vx=swIET#(TW%71P-2464*EF
z6CuWWllYc>$g}U2XIv6+XvH1-;c>+A%YHE1+6%w~vl+mm5K|OF3tL}}!DzRjCX5zY
zDwmhxt{SGU`keCe94VSpPH`6_*PBY7DH%>Yv_6qqp3_!e-hVg}p;!Xc9p$RPN12Vl
z=Rjy#*pI<h>>!Mco3QXk?o7v}Rp&F3o=u|Xh^LhkV&&w`ob+eX>vP(;j=BkVUWXj}
z1Rw?R<dh2s@va`3a@t#gx;c#J#Ta-A({htBtUbArSOUUf#ViXO4`J##!yWhCVfA!M
zz*@y->u|$M?D2<?5fMR9aG(akN@e6>)s2L)%m{`_u<}4K3mn?gNYZVx`aq^jqr3ZV
zoyKKwyM&~zTLrAVXr1%TpkDJ=hqiRdCH?ugr_GqZX3hK=(~4%Nr_0Bu=H*R2F3%7K
zjIODO4zCfc60IPA8#p<3#rhqrXq5PEy!2Q}mPpnUv6+<7ce@Sf-e58l;$2*()=YhF
zszz3qHYAyNUX@c<zpTD4M<wnE_mKomuYyR8Kqx;z2w$-dhuKdOu#o_rRIUIvVGKJK
zM>`Qn8?=Psj$whTi1D#P!XdEzVuVCkf2|^@WEG^uD|oN$6voZnw27a(Y3^Jyejhz|
zVCCt36Zc_ctB8?LU-ZmBH_|^nPES7u@5Q4efBnCnSwzNm?k5TIzwh$GUthpqm-xUg
z<O7%;&!L3VD-RIkzI}Ai)_>h!e=q&`xuf*6hh`l4QBYmcADe<|+$Dhx%LJsx-yL@}
z{`ibeW`W<A#Rr6`vRH@q=wMaMW@v>u(`FE(23u@WO{>EAMTiNQRUPjRDl!2}tY_KU
zlf}W8GfyH_2M>0<K`|^Zmew*HlsOIN7ABd5_^C<+#KRsBYaIRn9<@agToS-c_?6*;
z4`Ti$9;(2)*v<gVRpt{rj8_SN3JjuHGYH$SC|#YPY65}eE`SmUoJ@Xitj^)<nS|5Q
zq{un-In_q$V7KINj;ZUWI>_JHL%h1Cu&}03ylvu+#!ZboCiY!2eYR*FWEE#mU(&ag
zyH=_gjYs*WcvOg?$d-R85~XsI^r%$1lPmi5t5ELDD7>(yZOVXUHC}JcvH|*SA3Xh>
z+Ur$6_w)zb^w&)7Y|zYyZHXghUhT9d!k8{YtvfNp7sFfHy^cW91jI;{5R$!^wy-*2
zt{Vl17pM#?Pgz)sojQ2%R01kd*8BQP&yoVA_$`BPTiUmc>$~)}!8Vu6#-7BECn-i-
z>7u!F=_1;CxzkVrZ^s0<ok*9{;&P7+`H6FzHl2Gy&QN=Eyy`0-6I2qI0vyT5V)g3(
z!#;K;UOQHtSy;b(=-_YqC12gK<~B|%{H*Q0c-x?F2W?y2`#<kXO;u$}uMK}cCTC{K
z$Ns*7QCUXfFE^eo&$)Vl<o3{#YmQKR>#?8?jVJ2gH2xZGA0><)RS`Zu>)Tn!F^K>B
zFvu8N4DiV(o@g^}e=9flt?gGLRljSr`QJ6!$B^nWPN~%1z`sQ(R{ymz>gIX;iFr2z
zxBioEBzh6Q8ktIOzrB=U)fGcwf){%LNT4zcWJO6*$VmiY!UdY3*QimuH7;BGB<UbF
zEC>Q5LYWLxh19HW#dT%Z<#p|vcU@Usaks2gL2SEL>eS0$MXkmdd%`IinLT=Jv^Kw|
zTTV}R_sp-2jvYNaaw)M>8ViN#_zJz~Fivw|*mE&7ic^=-ZzcFYaRX`yBRTW9LSjeH
zA~tqrS>OO>jJflz9AxXmKt|aKUt+Cshtft8RJO#$)?T>60#qVTw5Xs)Ir-SG5ve@%
zVcmS4l3EfpYVopXiKH3Xv!bT^?5s4;^lgR(s)o9FY~+0U?x5|{^pa}p<g$YPVyre4
zn^@GVra-16+z+#x=0YF+Bv{Q9-jpuc<f-f~zp`Y{^*KE?d`&@YP3d5X#7eTl#p+w9
z|5{o>2PGHQH7p-Vat6$7p0=G#-r(rNrW}J1r>Y0NDCWlEnE{3=ow%mJT+0B(z{6kz
zz=W{cQ&~9Co<+%e2^v_-WC29r0|piZnJ13vB#b#Sc<i50<EfcYvnLP@)v|!uDF1j?
zSUpHW8cX*)wPk6h%{6WNoZXs1#_Na0>v}B6rm@mpbBB~{pXRb<O0k-PxZJ>-+2X_a
z*^AtJrM021S(Gcy%OZDr(#SbwRpQx>4E${cuk@=Fw@<UEw#}i&oUU~K(Akkfp6fk&
z?yfBI#I)^VC4+z>z9=qTgfbxTXezf6iA<}iWL~E-1ZOLu+?bbGW5fC)fg>p1DM=+T
zfm89;N0=W*!5g(?6x)-kh~Q7a(CLyKaLX|)i!cu*;^6#{`xH|I{E|=@mDMhAQ!0)L
zwImiFJ5=qe8X(cuxx04FU7R;?{I0nLaz4KdY+={@(e#lCx9&aU&aNpy4DaybY7%94
z^ow+BSF^dg#BL?^?(Fa5E0Ud|+I&B6j4PTb@A{!&(fr{9$cV0CSO?zSlFdM0QP!s*
zK;MpSFAhoW<$VG=xB)Hc8|&uoviyD5-1zjdTOFfZ{2ToS8s&($phmYxS66b8!_6jx
zCe`70mPEA&jS<0eUQ-*&sWHA8#jY-MU$5>uvyHQj()Y>Z?+Ml3;4P+~6jb#sc>n#r
zd75FN-2N8O&UOS;)WB?jo@v)?HnvNImBimcP`qp$f(iPM4He3OUqCZpC)^2`anKMI
zR7F^|7gLitg%v!+Bvxj&3x1*Y+ps8CF3je8tZ1mCvAPEOb^MFEh9fJ<eYx@B(;GEC
z8|qX|6XSmfM%#L(1_ZN3SDGnA+nR8%=@0nF#^;nvQC&$U?Nc)ebGq1UAeG73!hm3Q
ztGM#wwtpUYlkS6Cq3+nN4RxNCM`AZk8#>EV*KnbUOxq_5hO$7a$5&v_40r;mdB(hM
z<vAu(Q-*(1jVCpr-ft*KdrdK5DN|DkD(uNEQ;3(tF1u_#@VCUYbf%(9?f7+Rj>0>G
zd8*JawczV?i_Zww87MdnEXF2LY>_T==P-Jf2H~1rmF1$0sIhr06ctqqyHb~FD}#km
zQRp9~@_Sib%WBI>YgR7*w6{z%T_dWO2{na*D($q?O+vINP^rCLzE4}pPmT{9)tgEs
z6}#r76lWDVBf7QfRTGSxuN$$!K5K-1!-z2(Efd$Nmq~^hw$)OscahN;zm0qyDC%9P
zw;Jdt^cV5JzD*ra)~hSsoZ7`hZg($BCtt`(#)6tsKb_6{jK;#6qCot9{-Hq8g;*(B
z7ig%ObBA8<Hg{F?oG*FeExIvFXAPqx$%J9E=8w{CndnZVK4(5?;iB5fiFwZ{QNg9$
zcto~NgH4ukh-=Y3#t`tv7m_<Mh6IPe3=T3@pb$Am=sFm~Z^@vISu)xWX2RRurKW6P
zf)t)aK>vhfgmNTU#=tO`$H4HsJDs{|0}IO*_e;x|v>|<hdA3{=FG<kFJLmN4zU!|Z
z;$eRh7zE{L?CtQNGKC}}zQ3V<>gg^$%5y3iUx<#246O~-^W7ptV|(X)&i8SQQQtJ_
z^s)u?w&<_~QJk~e$NT2)LTDZ&{f<MSjtP;>&y{flWURj3z-Fl{!Tl1Q3}Ka5B6cYg
zG!oWlhlPOwPCye|x#&``(3J&qJi{!fvhac7C^)ap!Ghi+9c(3m+eBeD*n$AXW6~!y
zY_=DUSI)xPJ(M76dK7MVjdE-q8=pRR*WWF>=GJXYw}5P=Ir=Pr&Koff>=!Ai1EH#U
z4BK+0Y7ConH3djMsExMv)SRE$wfc3CsM_e8#+n?MaMSbp=ttSMTl(jQhH3KpzW;tf
z->L%oNwN2a+K{l?Rek8#qzUwq(ero75Xkvu`2}-#jUSk|m=R{$Dh-HayASQHE+)h6
zsRcDRnay3T>GTVBpY0~~Ry(#LndMB5ujsR=;0NBtETu3S8U6XSEq@DlB_jq5A5Y&7
z6!a;pV0<up3w<}Fn2Is~;X8N=p8piKlb7PJ-t9{#Hbgs0HkbifOnOjH*cBIL>lc^;
zZOTF;mre0S+W=fFR=o~kJ0DvOHz922&jy>-D5Mx{qH!?M>I^p~SxLbQ8pkTT_C!9h
zCf#JvX@}st!>;{YrxOg~8LfT0!74N_H(1*~Qa+aRtcK-At4-HdZP4p1N&Fx>2J0Y?
z#-B*C=yXQm<s^$Oem*%(?bBjOmW6c#ooIJ~XtB_?TVh24+jj-ZR~T(oI)lw}K=(UE
z+AGuuzGL_~I{Qhma^mW3p{zZ;BiG(r)4%LJjaFm3%dUB4FV+h%@sR{#Rimbk8lcLj
zAJMa~Enof`F_S!ER_;E%h95%cIo4~X-wixXw_1#53t2$#W#tG>Mr(5BJu@dXW+&@}
z@bcH_*{ceqwTa!IF84Jbgk>JqsAIlF!Z7*-1K>&!EiO$KXM|a>f(0;-u!-UQ&$3+w
zjsV<9i2ypqZ6sU6{KUIw8}<2c*6BsjWKVPZZG)!P5A^pjoAoBMCS))P=Dg7G{5xKK
zMMy$cUB1ThzhrHE?UmqF{RJqo-h^$Ob%oDJCWW)D*5L+`Hwa>q(Uhc~K6ucybfZyE
z_@p6rn`q9&?jg7Be2L|P*ZhCUB^F-;)WmU(fn%~n^kTEDZjwAo3<;+dUFx8gM6?3-
z)6ybFR89D1M%v=_{J{t7`%@2TewlvBALI|l>+wvQspn<lt*0@*nVCe{3nd#%&SaU|
zv$4;<swXjq+KSSu7>iikN)YBxKdN#e{KgdtYNbdpq9s8rFu!smGyXkdqCbpns>jY&
zuADJ4?Iz@r*J(HU58^^9_P+WdXN)lD8r^)FtvDI`60)!lWB8<oypB)*f#P05aVmT{
zmRw-CXp@;e`g7PVvjGqr+y{P`*ekd`SO`6yL+hC#r~?~2wwaWa04s>2Fx~+zA(*o5
zmJ&M!B9C&1RoQIC2HXD-QUeKiJ!%91JFwKMBTU!kg$9nebY(L-7PJASoKf>^SOHnw
zhnMY5A@W-hEfYaxdPLk184`&MX$vksxEO!p`o(oamn=Tm*5}aDWryzj_K>*Y(6Xh6
z@X+=p{l`n!f3$AhN7uh39HsO_`Z8Vq(cR<6+<B58M$gd=fS`%oAQCyRN-HniL(lKs
z{C!>FaQ!Gx-4C1h((`*3YOC_df;-7QUpJFm__Rd*5uQ~ap2R9$yqGABXi{oEM7}+A
z=-WdyhulC+>rS<tS|{okEgZk+qvcCKxN8yun~@CQqh3)gl}mR&cMm;(cf+*uwa(Rk
zdD`N;iRPZ?cH_nL#SOrfnTWRA18qx-;XpJn=Rx>1PFPE&Pyn{C8{&S9JRH{$>6A!*
zM833#k4IQ=QGt*MH*#Z>JWvl7CM5KrTj;MuM^<5fnO)Cp-1y8!l4lSNIdXn*>6-(H
z-tA7x9G%(gP5Q6Q(YVbd`u^`M3FhY@k1o3?>Xqy@{TnLA-|r82qea>La-w_w1d96g
z#Peh?wr||Hal*v-18Mo$UA!p+9Q~D23~qOCL>If=2KQ)Io?}3Yw@Y?@n%!-*riw;i
zs<SjDMNYLE-3sxKDINhe7lv_|1){dE<AgK{OBzCG*h(vy$Pr-VLf2J@({zGu;t}U?
zSs~BlRNfr$V1caXDtob0I52V3#EF|osV=*FrY^8<!-}-D%<kDbXO7%!#I2<}ik(ia
zv(ov}lEFA@oz9oawvX(U)9*$4%Zo3PBz{fj?bi^ehoUCNf3+t|DVpS*Y^yazO19^B
z&kGsLb`-T2uyjzO$QR3up}g)0P)mA|l}5gA>%4;~$0N8AzL00&Hn1uYdy3wuL^@+j
zL&a>&_6kdg>mV3xzA5UqDx>GPEq|deKlV6%`P(fMqWsH+K5~b@PcgLq7w8MVg5o~e
z<W8>?8{ad20lU<Fd(%zdVwXBz9i7nniI;5hl@#~!(zl5m_Vy_*&7$j=Nr#{@cYzkn
zVu&YU)et-qp#X<f7C!7c<#iZ&tkQC^ICLz#2!<p_B326lSb<=;EK~vo0ZG`y%IYGp
z4~8T*Qk+`)n4V6d|LRFX!|CDCj`7R#2;VO_tjwHBu9x#OKXuwZ&IlahNsnF*?|jd~
z>g3*&N%T~st!jz)l;JOG@~p96_f+yOAzQ2B=e)D{<Hhldn+YK=3--55mX4MJni4*}
zo3DG@ZPP2s-rOMhCe(*7!RCJj1%3bC`{O$!#k@LOMMyDURYLoE<J2Nt2oxI;z{%&y
z;`Y{PZ9<4uNVE>#n<bE7cXpzEOyk6wV^Ssh?P>rc3qyc@D#i~ME}Ru)8?!KK$B0;j
zjh2ZSHzIBbw|FST9E`BQcCdJez1Ty}j-4-|mI6Fr>eZN_yYoj8kNkUYN@^gh1Yb|m
zF28Z>WPu)1uiCV25`W8VAw5MjbRT$TqZtB%ikSNkeB%+4Y%^d&@Qe3n_R;C3-o^#I
zH%&C8*zJRxH<@??@|pTozx!A)N$+2DcV@XxFIE^w$sa>^dX9ebu`GW~a!6m2^YNDn
zE+SvC*(JX*HNe{A9l`g}ELgW;yefV|y>RWu@jc#ph_{*yx~ztMo?a-kw`mUVcZ-IM
z9HI8BO(v}2N4@=foqU8i%}FX-Qc}YnH}Xj}h6UwXL$vmb4M{xfgQ5R-O6_PzqD3m!
zB!2y6A&IneO(!-F&BcH)@0dS;kqBpNiBpUS0dNbm-)Y5)LzSO|`CvBN@EEK}xc=;)
zzF!qjJxG5kr9Z~V!uT07tUqz?`Sv4v{~M}Ty9v`z-uf;5h1@w-KZBOH96Q!>OvUkQ
zZu~i@ePAbf@PPaXogbfb>m3=i(tCl(pA&s#7k!DIiI3Q9<QHuu)hkr^<X8)vHCO}*
z^Uzz0!@$D@1AHopU=t`<9U^RoAhwf{FtsbFf=924c?YnB9n3E1CRK3p0cU^<XuQbT
zu#GMeg`4PKWZGwbH*4R!X6f}y47ooo3vX1X)RvCYnDi-<Yh1Z$tJP6j*QIpQ0DonL
z7J87gOKOiJ*AF~)@XmQ@T{XS($4pN%-F`Cx$q@Nb_kKcuxX6+G^Bc)X(uZ`NNWU`*
zmSIcy{6F^4KmsJvFrV60q<f)P*TLn8Vk`~vve+$~S6dAlVe&A2W!KCBGehIwc{C6h
z(eEKLZqZ;mkG>{f<UW6R8t6vC4gn<)PS*$k0xBi4=u3DuT~08eh_Z4cz$hA)Ze(NM
zNfDcGDti}%tq4*IvPt2zN~aFLvX}liv-UbsyiTs2N$h)HIlP*_cO=937=87d8`(Cj
zPYVx{VshV}EwfkLykgHAukTrT)5>`_?UvFP?vy9CY|q`^GEv^SaQ-Tyx#MTj``FV=
z_9QFY&NtDcH&l--CsV)qFEX`aM9=H#!)Q1Y#LXDGv+%-);0x)?CcWCr6i^v^E?_7y
zw=ut2@I=JwR|!@Q+kde=v*4RV#43}2V2)#vw)jMeRwdp7W_$tJYhC}@9n&5uArF-Q
zg`Rxy`6J)l|5LtY!W+c?%s;Eivn0iB;x0ZBojt0kc1GX1Bj@j2{Z60K3$ITZy>$1Q
z;{{X4kn{W}(kHjx_Gf-fdC|_-CXPJt%jOZwh<fS49!JRRUx(74z*Q!b<*AXWHOn4)
znmj&YYTv>mi*9ONH+tfT{$Jeq9zSr$i!Y*+%J9UnC3Fm4@zTcq$CG78hsWxY?JR`5
z4lkvevl%WZUP@KMOBwf&dZyvDLBoN*R3G=Spd}TYj>ID<8QYN2CcM{%B!u-uSvH*D
znG~87&m?Pv6O8V!XoQQC;r_LiG6xw$5aqYM`YzB#nQ5;p2@4Xe0V=k_uK+t1Vk(6(
zk^F&MUh7+)jab@bt4-uf-4&DR*`nUP#qUWOE=5m#WTsttd+y-K+CiS&$}FElXSI*&
zkw3Vi)Mp_d!TA&&RlY*rJa6CR>ulPe#~+>DyGTlAU$%T-)cZp+ZASjUzQswYHEF$H
zJap*IA%QMYLz3QASnQep7z3rq8L?5`YGAq_$a0i>4SbSGBg`0__(cphV#5=?0!lFL
zjXgl#XJI*sMJV#+RVWdlK3jr<uw=IVs*x$|_zn43G&v&1E$yqMm=6JUM8a%AIT#5x
z_hq;TyD$)sai7E^v_}T7_K~!+1#1j)%*29U0kn}dLS|L4uUUcYEoxt_TD)`5p~H9G
zv1oBsZjxA5DiLdX$;_#-O}E{;IW|S5GbK5)siUUak!~^Rv{f~d&Sd7TnwlE3+iFm$
zd-k-t)5seI`NQfyKKF6m@UAAJEi2Ladk|sToI4ud|6pggaJtD1Ezh4M&%UjHzuEKp
zMHg<Wf8xdg+qb>(=C)8WufbNYj!cI|Sm1WIogz8w3Kpzc{c+u}{DMraUY}~vs^`v#
z-LZLnniT}ku;IvkcipU4Evbw~s~Z}2&KjMr(WDb$T%UC_r-sYRBWSWH*!=u(rOCR=
z8p+I?jA~ua8nc{Xm1=rg+-U<>ESxi}Zo-7R;j=xOG>bWXT5mFf-%>y8<j%(T&H9p3
zjUcFQoi(Fxzq<Zo>9k%0ZhU<5>)W?&3uW<otxhAkO#Fi;*Fu_+JJMD#p>Eim2J*hf
zZZ@Q<$LE$8>k3m0X0amLjp0oOoG4!bZ_*&%%FCFE%pZ1QIUFcVfq)@Xw%|o<d)N<V
zfnT;A3?zAM*JTuPd9Vm&?E>2n4!bZZ0U`*ZS9V2_;4WapiRt23mJYfF2kd6B97N!!
zG72h_$!RiFt-t%r6)S&!>hSa|jV!8k2B~R2*-ZAlNbb^G>{+E2tJYCyfeRuv&(@Ww
zj2bO`7Xo%9nOjn@j&4fx2aJaQ${Av_>5YMvTW;GpyQ+Nb^{ci`D{*9vQ8{{)^{~=U
z^Tyq9Z07WPr}RvT*Y~X%Fw$-8K6^pW9x7Fa%^VrltGH_X@`+uvCasL<<>keXkIwnf
zJg;~}7o*OWf45Vu6|f1A2)Pac!@RjjrA{J8GHXh5_4;Q2V7p!K>^>$(RW#z(@guiQ
z9MC0Q%ga4IA>Qd99!cx5V*c>rk^vKkX2ti9F3fYLOwBL9m$w(fh?@}Y6e}*<oSj8k
z&BHJ-I@9>xpFFvK7z<fcET#;MO<5}Gs%JzeS(x2h*~TP8!Zy)mgBndAIl%lb6S{b(
zdok7$6S!tZ0-Kc_oo*#=P}${3l6po(>)X$X4J;A?qMhzrtZcy_AHBMy<|0<X72RWN
z4Otgi5Lvs+5mxCii%uYjf7-n;MzR`D{wd2W#t?kb#J=Z2q}#a0fBY$IAO~@u=u!N`
z#+;AJu&WGn{6Q^4sqFtO0B}Is#_xLi#4F14iDTG`@DnEzE1q9?A+ZL!<N3r1ZJUQx
zk+mDkzOV6CSx?S#(`Ht$?Q*?#$l^KJT4F-u<29};D}@k5IbEubHYaNPoFuAmt!Gsw
z^F1hsjafa3CgG)$E8Yzilp^}G!_=6OKm-eu%E5QqFCeuY+>pSj!zWu@9p^ym1^93R
zsVXduYuij7F(R5cacNDY<D9VfD4UljVQ;r=R!8KL+0x0&?JLmzEWRdT)?@TM%yTtW
z$}+sl+sT6@54N<i^dp{Qqq6g)HQjoIG@0UyS?&C-CNY|L4@2dHgYfd?PL>b<B}3r+
z7`4w7O5;~HFjZ^>mwM!dhe9#=Vy8m3=}kw&+8HnM!3@c^0Vrj`m8uVPy6x#XElo<b
z(Zni2E+@V11OWulSs}{av^3?UZ&z~i5QoJ-V_>$Y!{5az`zT>grS#U%DIO5;-4u|O
z{gsfPWol|tgfN78O0A%ciI7NyuqxhDq6+#Y@GB*JH4HV_CHcdWMY8zuOK??xlkT*}
zW68<!yW)50j5Z4%c|7v7`PrV<WIozj4^wD!yjl8}-P;ngd(>DvChLFwRnps`8{?U9
zdORBTwCcVUe>Jq~PK&>`#Km7vx56%V*=}dS6bQBB3R|krOk$7;2{waeExj_O!#fF2
znj%v1oWW+H9<>G+(v0;y-(T_E`k+R|b5@%{qryHWHWh@gmZ)6=E07H|+O7dSf14s)
z<aD+c2weifjRYACq(FhB2jVPSP+)?bRgScFTb;6DB`kHg%8JPj=0-)hl^Cyq98jf(
z_?n2n<74c9Zp<a`TzNT5r~k5W#v`<)EGx+_h{=-Q=ryGpP14Q>&XRku((WE!`GEcZ
zj!S=}fZj(>AGJPGuEWkDdXrP~_B8rai;8*$$Hi}blmw3+Wi40ce5aNdFe=tz0utLz
zK^<4Vv3Q@8C-%kx`_eM-A0RxUn_RQaKQzwW7YSeb?+rWn-*;+RqKPE7^~akV-Wga@
zKYm#C{D4Zc^+#g;k#2po@#TFP@`j%to-yO$pA^7qMNax};DibxyapCihaF@sB!wtf
z9`Y^RYs#73V-Ln){22X2SQ$S?a>V`Yo*zn2vs849aKkS)sUDG{3UyEsSW1O}0K<YB
z|Ivc+ZKul$dw~r3F%m|qRdT8x(a{&_lYiMUHE(SHQPu^6lOHU&XVm0nt~_U?XX&gN
z8pE23=qfUzRcQH<PNBny`XH$xszFm7yK`>QXxDG0UyZ)-yWfr4no4fgYZ%O#)|N23
z2`nm^#mExD<^@V&msU=!Jaa~l-+1N>sgz<Z968LdBwgsA<2Tdy*~d(C>iF2oMG@?p
zC;(<{R|ID5NYIBZYY`Hpj<9IX_Pr9=Y86D_A{-fVJqvEYb_!W6m<A!9NCLMC;U7If
zfKFt?e-3Hkgl$Q+nJM$;rDWD7O%8cNbeAWEJnF0IU%Yu!{UE!}Fn~1Osgkgy=%v7S
zDvgko#;*vgC7%A|8sSPZ_GPUXo4g~Iq*PR-EE(aguRr7|bVO?X#--Qyk7?)zV-iu1
z9c{!qGEpayjj<%5E-fuX-}Z;mGUQAlNyTesIMsH#!>Hx8qm`adSL_nZP(BQ1a%LoF
zTdDADosD9=R$QH~upgc_7gk7uxiAzC`30<q!~?X&cG?fiC3YBX7yBWQW4$5|Gg^Q#
zgn*CDR5jPVB<a-u*VwgyHFaeF%$*P*JPZLth=}3+5CVkclAy+vs(=qrM2HB8R4Fe3
z6|MC_s9Llxr51r8rIxbRs%x$5x@xOcYW;lGwXRy*wbWv3)mrLWi!UUX|2a27ZFj%@
z{(;QQotfX<xpPnEapuf9+y-tc_vV)_afYhtGe%z~;Z;=bP8LX$M;c6~6<OS#A`<yc
z!i?!veH~dVOeVt^6NPz`*v}=ry}do$#ZT<wGSZS~%CpE;WSPboOw68y**+>YFuOMa
z`}wWtXrDO=>5Ip<h#6-$37r-k1*K#e%oDjVXUmwy+ztLNCNAH_&qXYb2n&l4i^U^c
zMyj2i)erG*S!m;n2*wXEqJuE>#NhhQK#_ru+ra*QzzvD_5V^uE7C47e;EFi<vnpXU
z%udG>$&5D-6ViBtlvflzev1@uyYSVilpO9CuEYHLC-)e7?Ly3G3A5ZuX-G>SCzGvx
zbi9@MvHHg6O_>*t9~?MT@#l1<;`umkZTv)rO(FTm?vjjx(W~>OR8P?<K&75T+A7N+
z!SeFiHcisQ1OlKnpfem9ks?7pL<@r;)E3{KvjEQUm|;1KGVUnHFM@g61Bg^I`PO!r
zxRC%9Z5P54x4Szr4{pGZ7NTA7^v*C^jN?ZOT*$&93D|BB3H+a!hEfYh0GG#61lr=&
zg7{!$j^Oz$=*M7v8w3-1p_iXf<Q6~1JWjvPhfESWEa0Ya1N#QKbNhP9doM9geqZWE
zTqtZ-E$AcL%ekw`T<>NJ$2B*Dig?g=G>OQoxWd~n{cxnCa_rd3jw3(Nnfh|}ucY3(
z$3=XdyYsYPe0WJH8B#ieau4=fGl=umSL(L#g_sG`ym9p#=kD_G+k8oUQz~JK(G5?E
zDlY7Yy5s#xs0RqLdw>R8;;_-$nnSbt{(eCCj@L$O56R(N`?r(1pg(k#rT<D5&9?gF
z&+gw!(in696$a!uZLJ4A3coK06HOS4Mw&?gNaVomJeaqgVGBFJTeFFnfe&fJ2^=}G
z`PyfE58Oh9(b>xpm>qx&go7cN_t`wq9oep#8cDtc{$X><?ptd>34qy(@lU@JB`CI3
z5{X2@-H|*K4?sz`<mtavLX0Tg!*w!{uac<*$Mz+!c?RJ$D9F<pveyhoORO6zCD5`k
zGez<NCP@ig$jqRUf}j43A^sqE<1h+kCvZNG{Ug%t7+^K29AKFk2)ru$z8f$NfFTfX
z5RHO0CExQvLMT!dEGv<=y`7*^T&I(hv!kScYp_b<F~WO<(jy-@JNy!W>vWgqD-$AB
zzUEM=r?+opl$>jktv8`8gK532NFEjG>+LBG^;JbCC`*SH81PXI1w%_clu(d|L=`N|
zR!W#}oI;#B9fV?OO+smKkU<$F$;T-wmJZU-Uc=as$)Vv|eM&$^8AxT6Wdx+?wc(+Y
zL)c+n`Xp%lB)!BOq%;HtmnPJ}VQOrdrxP+q&;{=gG57-m0RaK%Lj_g`ANu_+s<1ju
zXSM1Gvwt<0w%59fS^Hl$OsSzVmAG*ai0}ZY(sCokcC$~Gb(zG~j6>bO;H8AZDkuSX
zymR2yfJhHAYhY@MNB>bNJM#R1#RC02uElvVK9EtdFC|c?0Ca`|;QV?6o5v25gof~|
z{vgSdC|t?&!@p?$IIW|^F<kCyb{*j>_Fi^=dF}UX*;HAi(R)%cz6zl%tzy%u`p37n
z-#OW2AcoI=CbPV&HucT%4wu7;E@@Jd)KxQ9I)?~qy~Djd6>ie9GO3$FVUUu2qh=3{
zikACQvEDB!8BESKyzHCmZH$ynYP#4|ky?N9-`h7`lO4FmeRjj=p!wwwH~71Gj8zm7
zrbuB3a#Pfg<K!m-+@uD@mZP6_D8_n7U5CMJA_zERU3~Xf4ih?lz{6i)D6cvNo>}F9
zM+iWFFfYP50@vIc&~$+Nm6!lbRY*aVM}ZMUCFBpmz>W%-+X23xpOZsZ^<J}iZ}m@$
z-tuqwY5sxb1)zx4**9u>NqXckCvV@f(6B|#(kM1BH^p~IRsD<M;j?N_EL(c=mFy6|
zk!+*~Bl1*ef>gd<LrlTJ<6ejmhm5Pvn!GYMB__aA%(%@on`dU5%}0iOxMZR+HRAcq
zjPy8n&*<mkg3N)@qe9&SqKEl0q%d6(6&a$A3UG6b&tCXiUh0O`bM%_@lHxd3%E;kj
zu{4CuVkMr07*d1fA#BX3;XZoS7(anciL+6!ZOUXj<SY2&ncHCK*Wg$E<ZvKP(Un1F
z+t9#tN`du=za0WD`TbSRACAA0d|cT-yUMqR$$;%puI-fU*|X2g<7~1Cz`h4zktb({
z1xkaNNL0X<AQBl`CK%KvWAA`|cg;lq{^T#&Ov3sa8v3}e!6mn`Li~^4#(Us{4u7oq
z<6RAXPf)4Iq1f2#=>=vio|&!=fra9KG@h-oY;7epKKtmT^MADt8Q56=y$^3wD)c{|
z{mG-pKjn_|eeeH#)N*`M+Y9)AJRkp_%+MNe_h))I7vM01^l>msJ^@j{3Jt6r`NM<~
z1X*pOz)yTIcLlG5uOTmbZ4ZMQC(*Zo)YEhLqnhEsoevb{W<JWuq(MG#M7d-V!Brj+
z_ylpQL%=cs^uaK=p$?`R?u4&w=unw2(bJ^<N7Pa7&r1f^*j)d2Q9Uv)?y(md48L>r
zssMib_Vb!UVFnZp%!d>_eFT##?4}2$zEP(cjAAf2g;EuP{V}jx6lX@-w^2S=?R+-u
z3EN{LM=;n0!x~FKUKNGc?4uxzZZ>Jxktn8uJR9tV`DzYX<dm#>EKnsoEgFLIbYz|)
zkWn(>8gzqwNIN_%{DYJ^@6RClO4#HMhr~dIgHQ0|>fAN+JnORGw+ZdOpIzrUZ%wYt
z_$Y`#h0gCsji=a%))Lj|(JH1Hg8ki0xPr7R0)^qA3D_sVNZL1&?L*B&Aue1P2yu#V
zCO~+Zn@c`2RbUHNn7Aa;7OBIq4(Qt-R#e}?*iS+4HQ1dA1T&TJR20}WGE`vYPoWig
zLI`{kLc-vAHJ(pH$lZa>1{%kU_L(t=MbPhzoRM-mN6-ssB=JMUVxi7K!F@E%QQj>P
zJJVDSLRW#c51~`&K~9on#4w+eBu#Vl>9(am31K<T$n$~S#fRPU0fDQ#d$*iBAa@0Q
zy*l*G7=Wv8Ik6>@WK85v4*IU3o(I>Hr7(On0SV#BH4h+u0c?+Zc!L^t>OoOd3XIS)
zAP1rX-mnzxw)rtMrLn20aWy%|oh526W+0asxz1d{0P}^hV#lZVKiyGbgn*e3kslhH
zXkAld{~U4-^aQENIqTbkfn3<oJpu?)3BBTpQ!8R)SDYex=*0B4u<aKa2B)4uH<i6&
zg5da2u!!Y}i+_|H1CPo006t1G*ZL#(RT-(`>dHtsGi<@mouquHd8hSPuFZOlIl+Bh
zMi!IBWxxqIVZ8=VIk<whF>Au%e1%|;O*6>05lBS5LN-t2G4XPb$aR7jEEC#OfTfJq
zc&#>zyu!(7t`>g9ued$#_EfejLd<SLB_FWn+mp`l)_bYVh%Yx{P<dOY7bvJ!gebhE
z4&WWMM?(`3d_6?8p=8a}*+WL(6M*qJ{P1Ry?f$^P05C+LjX()LcGUa_a3TR`8QVZW
zZwp_FJpnzYdVfv>$)`fpmuKm0B3}!kSmXY-X0)OOCAnB0TF4<0mgy+4eB44x9AF|Q
zaJG0fk`T+-jl{{4wFv|@m6oDSq!JO%maa{t3ayPoCHTXT*dy`b!E5ySa1Erx*M1F5
zH=K6cF!*%vZWxRMAIo4c4!(?I4R8ILuNCG2yb$x?*PbVVzo{L_M-JYUzp<@AJ`V!;
z3O*EM;LRN^S3!kfFhcQ3G5cVh2J6RX!+30kVV0e+cF!3sey}*lzdxx9mSMzr#6h`*
zSdQp`?b=>n+jBuYUSnC{%OIaS_`@xg4PdMkYXeuo_EbJ6=C;SD^QGGIVA}Y>T0&Tf
z`3A4ihrB_9`3HT>V=vnu;!2_1FigXE_-wqvc<rCn3Y>0pSA;QQTclHDb(B}suBeNu
zNY#4P<>-Lun&>Mr6Jq7DE7T(OGWAY%Ph4T#-ng$dnVJon^IBHhs=dQbWsk>a#`o&h
z=#~0%{l^KSgp4r-WA+#%h6KYJ!~L-<j1r^4xb(Tq=ME+MCe|iyNxb=d`t#hlhVcm#
zWD}N7xS5n`PCA+_P0mR^kbEh*H$|EflTwh<oU%9N{KSZf3nw0%lt1apWaH$EQ{1Oi
zr!uKIsaMieX*FpVr)Ez*IZZe%bz1GTYw7vZ`)05+Iy1vEmt}6vyqjgnTAy{v6ksYh
zwU~~YdS=RI=FQwW^H#Pxdv12;EZ<pmvv$n7ol};xD_5RtmV;B9+nbl3w|91PzE}Q%
z{D*V$=Nv7N6eJYX7xceyW^T~j!nv*Ug!9VgwH1aGE-AeEqVmNxFWxOmEUGNpU38~d
zUA(ZkqxfV=V#%_Su2N-bLFu_NQCUt|ec7e?PV;s1m&`v?E-5c4-%@_NLRYb>Qe0V3
zd2PYy1)CT2EZksT<hn?=sH4iSs%5c!amy0flE#-5FKu4B>*cL4_bi*Rta(}2a>eo`
z%XcjAT2ZqyY-Qfctt-#1?5hr{POaWreb$_@Dqz*o)#Fz0Ufs85>YBzi7hj$DYU`_4
zYLnNxukBu^ShsuK_18wf*6`Yu^}g$utUvjuh(FcUiR#wX^}fFM^;`9tdUHelnKzu?
zXxk96p?1UBHwAA_esgyNxAAaeWm8piWs9&SvE@KZ_a^10wpONfVe93$Qs3%no7&d-
zw&d;gZ|~jQ`%Y$iSo^kj!`^Lp_hv^?NB^ITwg|RlY}xmo`n{I-E^aM)zi69$+ktJj
zwwt!!-m!GYo*lh^Dfmmv&WStgcJ_Us`=HjmOS7xx!-fxgb_eY~y!-B7+x7_dEc=`0
zZ|!^4dpq}K@7I0g^s(~e{)71kyAI_YI`c{1CtE+cb@=Gv?jw>T6OWwj%<0_KdHvI+
zpY|Lr{4Dje%g17l?LKzxxZ!x&@uMe{Cpu1cp9(nDdRlh6@$}8lFP&NO59L4F&I-?F
zp55|=>le$;`JFTG`DeyI@0>TCKYStNLjHw%{_ohu$cx)9a$lBz*>frEQqHB;OFdud
zzRI~=b@|LUwcniUl6U2IZR@)Et>WACZx3A=eWmEi*6$L&>-g?rcgt0$tA$rPzmNF7
z?g!r=+OB0^yZ&S2^^oh|-$=c2`eyCT&Y!$~x_m3+*14Z$KR5K0_Z&6<lK9K!+mhQk
zw-5jO>pP9V2K~DEE_?UT-Jahfep~h1+1`-eRrkdA)c30HHQaZ<-+KS%1Nnox2m2oC
z9v*)reAL_*(pTAc=CR;$^5d=jllxCwW!6M%^MCup(Slja_`r%AKRBY`2m(qTjCjp|
zJOt-0t2UGEfmA?X6ge$$V%Edd3B#WY#7u)N{4Xj{Fm0BIcR*@LYsq<sd^AJ@`UheK
zN`V^Klwd(_e^5KDhH@u>)L${grh?tLCH7P$q_eQ*kA<C-1lU<c(-3wP?1j#Qze>oB
zxC$^uJArqrAkTEc0x<kp3@HmCPnm$(c$M*En6>*ay-PSSgY$3Z4)ZH>m-&t9W$rQe
znFq{6<`L7!JZAbCE5k7ZQ~+jh8A_>;I#3ZDigAKzkQgkJxl%XkPC+;yCPh-}NxkS$
zDx=<1PJO6?4x_$wI9Oa8L6y{>2GBqnM1x^tA(V#Ea2i2J(nuOb%_<sAV`wZ@(>SW3
zTFTORs-t?EKu6KhbPNThgVac$qlxr+I*yK~6KE1mrYUqHokS<oDKwR)(W!JAO{ddo
z289FCG>e+(Oqxw+(Hxpf^XP1vPv_7A`U0Ix=g~s?A}ylDw1k$@GCE&E%V`CzqzmXm
zx`<ZM#rrS5M?fe;Sg4MT5zf}=Sq!N$q(et9oUM(41Z_+#I*_1^i9<(&jussjop^Kr
zp^ecyESXonco76+5rSoDV-XUIkXVGoA|w_eu?UIP3(d2&YP^dYA!>xE5u!$j8X=$*
z3mk-~5u(O=#UUaN5y0vO2N7|Ih(kmiB0#AgIEaWtga#2BL}(BJYP-Negjs_S4MH>s
z(I7;F5G_Kq2+<-$ix4eBw206mLW>A3BD9EL5y2vYMFfio77;8WSVXXhU=hLUp}pA{
zY=0gSuf`BU;t>*$5HQ;U4npD)5|200;Z1aS6CK_}hX@@abcoO)LWc+)B6Nt*BSMb|
zJtFjo&?7<*2(uPmJOmK}FTPM6KhJS-dGQ3bF2?Qykj2-};_GK)H1=q%-3K&_M8F~u
zurY8$7U_va8eowISfl|KX@Er<V37t`qyZLbU<?aHFq=ghV37t`qyZLbfJGW$kp@_#
V0TyY1MH*n$dI8Bys}C0l{tx-ZYaRdq

delta 5319
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

diff --git a/view/theme/vier/font/fontawesome-webfont.woff b/view/theme/vier/font/fontawesome-webfont.woff
old mode 100755
new mode 100644
index 628b6a52a87e62c6f22426e17c01f6a303aa194e..dc35ce3c2cf688c89b0bd0d4a82bc4be82b14c40
GIT binary patch
literal 83588
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
L4D;{PWMBXQ&i-xA

literal 65452
zcmY(Kb8seKu=lgEZQI5M8{4*R+qO3w+qP|QoF}&JWb?#te)qlq+*9?P?*2@l(`V+)
zRLxA)cqoXAgZu#bZeP_Ph~MT%EAju2|6~8RiHobseJ6;1Q~dvA(L|FYAu1;R%?!U|
zqHhs{GJt?9s4%g9v%v3||67JJpx&}3c1Dihtp8gQARwTPfIro`7Dg`L3=H}^=YRC|
z1p;Pa>t+7UkU>CBe}epo>y}d{j<z&2G6ey-ko?YL`PNTpbCh+<Z}`o8zvKVvk|Tk_
zY*^a4dVaI)@A1EDK)vIWqkG#rn0)759e$7b2m%5Q`XeCc)y~NCyYAiU|Mn#YRR_hl
zH?lMPX29?Hxqaty$&$JWIy$(xf`B}H=fZy<54y1v!nTu#neq4hzKXy5LjI?wT9x;2
z`#)!Jim!0?+XwlpLYn`dog+16@LV@BG&MBb1v7?$L^d@3_D$cB$hG=;AwiI2ez1Z3
zx8MAad3JyQWdGp8knvQ1{~TmNMl?=gzi)Paeq(w1K#<TL9T?tF0C8SikP?n03n`6~
zp&>X(XA|`IYIv?s|Nbj2?1Vge;#o!iuHeDYP&C(C2!&kG({8y)`YUF6A1zXWm_MkU
z9{RT>3d5k9j1x`}mgT(saZ_{5ai2-B;v6OPYj}pyu8BXhh^RcSMIwAxl9Rc@=*cDP
zy?YzAxIOC?^#V=GX|Vn2@?+-4u@V<5j9B$_5RjZ)DN06JIq7#cdNKKla!Po!88ngb
zsxZ0}`EOxJZgj;#j!Mh?IHR!@iW<9xNJmzZIV?~Z8BOCPWSNDely3AAdW;Gw8F29M
zD1za{z%cg4@uEmp+VTR3v$@Fpo2LeT0F<}E&Dqwn?L&dr+Ue5UQ&krN;yn-4>TFf_
z;NR}ynC||EOJk~EtA@(j2uoeK<-Oi2b?0JyRk`PtR8QqRu+qnmK<@y$ArZ9Lz51Ag
zE~EF!uY8(>fc2iA2MF({jvv-HP?NKnU;i!FkMHXb)N{SN2gX-*X^q)`mfIu4?|3GM
z;m?FAWfNr(`4ny=q7l`PHE{6Z$U<nwa^gt1B1Md01oR4Z1Z}0)R=+FbKJ^ig&b7K2
zKr6uB|HD{kqgPF5r&U0Q#N|ccWHV!eoV?KQ>jo;rXSSFBB>Ti`=7BeDXcIG@>?aCg
z_OR1hK0dj#BB3}0M;io^9SUe!Yvd+P{HKWSQlAwdU=K&$S9;vVZP!Us5|L6Dkp<m0
zvXpfqKeq5p6-gQr&7YiqNw*vBsC&NLgIpnxTBEy)8{Y%Y%Y&DG3P#BFcT8#Ftprzh
z5%*#3(wVhZjv^G48+(X^yQZTEocz<S=^z7~Nl%3=rdbk9+W7Rk=gawD&Y9p90G&GK
zn0JwX65HDTmGJJPqOnrb;#&8qvge57bl1qtImms^Yw-^!-(L}0c=vOVQE<X5cDjL|
z$gV9U;kzjD##wx5h_{SgXyF4RCrd~GpCzQk&|0zuL0UBR1i!PmH^AapUB@vOY9bNL
zw}Vp?YbY5=&d`vlfFL>_oh6~7>!Qo&w}WS(oFI03>1c6}O68cHc5#g9tSgF1q2IV`
zj{O5YM!b+^Z7;ZCW?Zj5tRFv8K4RnO-$M@9yhvk)Ez;!V`eCsd4<EDQi=gPo+rh-9
znjLhDUWyEV?I$0q;*{_}HL(!;nf%ez<Um~?r8~Q+4n8!ub|V78zKy}GZo0vW2klCm
zy<VQ;sSXyg?rMOsg3Cs;mEE+DJa9;CrkdIpf8(ifhM4-;qK(jBJN-Cr^$O*NeeY~&
z8VNp^ac+~BK_ts$y^Z(efQvA^IZQzW4$c4anuNK)Rd#}m#^=so#4^81jo`ZDDsyD-
zcHhSS0!Mv^mOruWV5##~EN%POLtMbm+1aq6j+f~#--EAiHD7hQHy37)A>9zjB3N{Z
z69&?LG!XVGMdoSoWZA(QXl6?Nrvi-eGsSG{x^+0T^I<vwl+F75n**)hWY+12yK~Xs
zD*oC`@}{Pl$C+QHJY|+b0TLHBIVc~#k2#~_Zm+(4dZg{jZMnjAgkrJGE##!h8!TRI
zKpQ1tJ-_$%PF#xPqMTFlM}p<r(TS`ug7OBat;+4~qEA`9hnyQ^k&cWgBr6I#GQpp*
zetcM9<+MVQl@j>}dHHmInH+zzAh(!-3V-&;kww_^5_5xPaN~78`Tga08ly^mI_u(`
zngGvE()LvO7|n7h%-#BR-RmRaJ=7}0l!@aY&pBk^dn}e_zajXUKhihhB;Hv{u3d*=
zZGYt5@z5UAZqu%}>9>it+2@j-C@+?!6rve{Un>u8=!Ynfq@o1*RALr5Iu<bXcv9)`
zZY=y#o_1yXhu4$woWU6&vdcXfHwvxBz2xgw>5>BT_ZF-*QB+g1LmJ)Nl+<EAMr(l9
z@4jfSOd_Y4C+c;a8`gIZy-LS0CcO-VNqv@Tt7a@#5doLe_#~2QQ&9Ry84QeOD!0f!
zDUTk~#TAc0lH_$*p!`1e-LMfmo<Y6!D;psO-`Tq6TwJ^A(8>Q%;F8FI=y?6Wnq+&M
zP=fmv-|fJ+r7k^>_qwR8+Pw(GWdZ8dYeWm*EeS?sHY2~18KeN_WdG|~3wT;YD>wxW
zM~3X4nZ;YX{=pQ#lwJ_nbRj-Nx;+u_+a(BT242e6Qj9wDT+C7WbWbT^_?O=ZjmHb-
z+qE*%i!UIk5a@qS6`(g&=<87+2e^5t=<7!c#G34Royvpw6%YvLq`PV)W-KC`V7WH0
zsxHv#n<lbAHZUWt9#HYAOa~)2pjL?>CR6f-DlEXhtU)6-WYPRV3T|;gZx^1`0+o}R
z_>(iIo?(b=uTsPjxd8QeL@wOxF58$;eJZdO9t@WC96u!Csf=o9?DkfRyW-(lO>+Gq
z>y=7qq4Lf2Xj6AXOYv=f-GF{h+v)nCC9~z3tgYGgI>xnw!`Uht$LKebpv?k}&(8zr
zF3}0l8VhU?eBTC4aA47fS(#63tB4A(&k4+v$N86ffQRwPZ?I_%093Wy1t-&*$9v1c
zTdJ-8jwu4b!J5ahIGt#f3nYN+izd_g1m^G!prN><_Cv;H5hDnqZl@h3Nu)N8v$vPn
zQB0+Y!ZGEQRbSB*kKG)P{T+>#YyY&jUyOFQ@Q0M>@_Vx%+RJ>$d-j%c{puRnkwC6b
z{bjvD87tM~z(bwb@hBj!7O#K_u0ZItt}I<5KX?AckbQJ%S3wL<G=ffu1bVp)oNYf4
z2W9{lg950agYcJwQb{m+l=>VR$Oqm+%!6GY*mN{UUcC>$`&AuLpTDIgSQEsWZ`lGN
zg?tFr{>$}#uHX+aar%*C1SQjAZe{z1RqLOeRZB)mr-4rPIA_frVaSqkHwWce^}}UL
z>X%vTS}c>M^*$Sd_YD|hlb7wj&y#x7Su3;5Ws9)!Wg!Q?u*S#w;b5;UdBfx(hv@Z^
z!CC8e%I(B)-FkM`)93{&WYff{uF9Wu^_U#<)YcNSSJXcfhKM^BtGYR>^?VggmQfqN
zs}nQvsEkzul2n|3x^#y`DlN3QA`E`KuI!b$+8_xFVQ=MA!@w`lLd%qQmo~-rhOwAh
zL~acpqZ3-9diaw&G@vGtsmnMaW2}>hyvl`$);8!st~|wo@N<j{Qt^#-M&>fdRJ$my
z8&d_*GB?WZGrmrwNkD=eA3^sSW)Yfvh#>Q_)?bd={T<iPx|$VLt{7)?xBKuh>SsiQ
zE~|f<?Sv#?+B2}?b2j@iCwyrdsiav1;0RQ<5^$fiUsVMWP<yZdIRVwhc;4544DfL^
zH(thoiUy<nqqR~r1o=MHU)jI2wg61|aS(``AITu*I?ue1@>+sB!iIU;5Nd(`B@$8Z
zA5@?oq2b*l0HnOi>b#>%M#{gcagD~X<j&RsX_;|?F4jp3na9rN)@BNByiH=-CKMQ%
zQB6ufdi|GA0Qu*Y0IgG$0DL&&;28*cQ1-yCAKLWmI;&(`%|duluI!RG`^qwsg<sOl
zj>qsOmo<9L`b{3jmP-c?Rx@!r0TgE@+=w%*hQQq&G%K`~4Blp!*>yMh^+5#+F<baf
z<+Ky+9POOvDGH5hZsb(Tl?6wg&QZjupj@~TtOOrecwS5;U+*Og(%TH(DuI)qBVx4>
zOr1fBQdU0C9gnQY$pT#ph!+*jcgHm}5kz;!J3Ssun$IB<9YgK_rVt)7_ZhkqBQ<7y
z+BY6N>qK)m5pWZ0`XLPxjN3CFYj>YUGF}S)B_4()ksyh}NXj>huSX=fGbTz{ohZii
z{4)*tSZXYu%wfn6Hv5u6xLp85Z)$bO9PoP0$z>%VQ6`_86l=HdSCsZKdZ~%caBriV
zm(d_{mO@Vunx{A8vjW*m4uKImpe>;GA%Ji+l*E0V&mqV=Z-?u_bkHzJzF5lUGtqE)
zYTOJBWEV*W?q|lAHtRkjL5Sb=cCGIr{f%?8mRC|NsAUO<jkTXt8;Fj8W5e%PveJN1
z&2~m@jX|w{B-Tl;3&!%F%lF?pWvPUyl0TuX4+9GjDDR&N0<#c8AY{(~)LlGLTd3f}
z+tZ&X5>QnVUjeo9*@Sdj_~bX>Ia<L-z~>L`^fZ=)!Op|Xi?W}_h}Hp61n0;bhmcp8
ze_)=@pR5PM`GJY0#*k>}5X?;}M7BaKsN{~G5L*M|)a<4hcAV~XjLwj5B*F5SUGjr)
zZhE24p3LWb5O`|Sc?eca6JCqq0xP@tEXa?!)<cxKp2|;bGlve|olf1Q1qG$RhwDm~
zM(37f5#c*W_tOPfHs+sy=zaXD74cgqf9en;SC0iD={*9^AlzH>S7=bO6R6$A7<|8m
z)cGo#X|&d2jOX>y5jZrNcWo!Y`EJl24bwz>gH0*Xc(XqO*PYOnvrIeucS3d;$P6|V
zX3}gi5A^vK^h*41nu^NTg^F!^35a!f0ok0m2`|rA3<aKeOss|<{CaUlvtaBL))KvF
zzv|W;@#qV!eJQ7=&8k3L2Ev(%>5JYt6bT)tC~3!~yo|~;HE2EMIU8Msmfg9kz5<=k
z#h+%O0DZQ-a#HhW!6{{zId4ZXH^2jY6STl0t%`z=5XDn{n%iIIW{}?CG*F2q4_Ao@
z2ymJoU9TloOkHyG(UGOeJ$?`Nee%748ssqZh(tf17LcY;SxXXExhQ2tfZQb0?i^Pv
zyC340XXp2}k2T(=Bzq)m0Xk@ckaswN8Og|Wbl6_fHQI}s$`ig03qd{lZ3Db^e}|u!
zM=ISXba{-a+8nfrW5$N}pLgfzqHCLn`a>i&1M~?~3AkQ;HqE58vsvM<Kvzq+1&IBt
zP&!*4SIa*<x~6X&;irQdzvVwpG~lk#8C@uNgpV8H8R_r{Z9Q-h@QO9v;1D@1yR|xJ
zXlCH4U6NQt3;y9>DAoq3^eL8Ce5{dewN>}{_zU?dw0adi&BS~3w!Vbv6h%$d!lh;O
zC<SF<@!1s+oP6Qtq+Q?asH0n3Gw75Rm*US!^Z=iKw3XOPNR%xkTSuqfXkinqDd<>^
z1Ok7J?U%dVhCuw5H(Ir>UsO^^c!0H54`<0oVScO>HH>~?99z-#(TFoHa&fRsS9{KW
zWqXP_pUthxT5=rPoNrh2(KB#y-C~JVwgf2&zv+LA=jUQ*w{<Z@e}SL6V%2N@6e9OO
zS2?eMS}`y^&&0zPlLpI5gDB(kd^9@rayyyPSQ4=QfJKfcg2a!%(s86$H^f53#R_WD
zR_ZIxHGZp)#2i#UijZH#h{qI$7GuM*wn-e637l<eES1;AEt4ZRGykIsXQTmp4Ray*
z@^FG(y<J{bFd!13RJX)z5ge`dwztJkqI^;9vfMmnT@mDACt7Zn5BIjUVmNc$_;2du
zXF&GPf#2G&X3y+`4s82&zW9osAd&8P@k+tnN&95a&^ccjALc4{?911h^|ouE5<c|j
z99hprv*iLTVCkd9-W3$Si@koFVLJU2qyhKy5+qf*iZMCD06Z6f7Mp_KQ$=jc3<}uk
z&3kmFvPVr&dVLn>1IISUcsS~K>!=Qxz6W+v^`30(cp0<84M|*m6Kyu0{H8b8oz7l%
zk<Aj0G~F%SAQFqV7~%qF{u?W87}!-R;sgozsch-*R8es+pv1kPw^C!sC$vPKMZ0nC
z?1@!#ro|2EJJzm52(&~~9C0&T%Kf}%wuTnh5t|6HIgAzahts8fz3<QLtpw~9-E$eL
zqXa4uXXO`%ckev|;`-X&PZr?CSw~B6Z`udn@&;T$TVtPFPtVv&P0@t6PuP3KMyTG`
zLc&apd#M0<_w>KhPFg}S7&1`ULg6S9EZY9#)xM}cl0qJn3fJQF_);ikOX{42{Tm5S
zvbakPm$S(8NYPs)(ie7IX@ugU5!ve4EPir3#-$W~4ZC1WSOC#w6gy+`J9Lep7bd>_
zUC{~|J7XT<C-jv}gP;MQY4GIjbD>quS|}UHj0;(_7q<sZ8wN3^B`RD=mm#->O1*p0
z8sSu`Q!@Y9FJfs|nQEC5-=tIXG2Z+=mNa5k52i^`38@a+K2NXBlHMv^0Ta`q!8c#R
zw8&lAVal@8+(I%?O8$M@{olh6M*3DqzY$GhWB?Q9BPg*iihx)F&HB}nPj24l!QT=#
zapEBsP+rZ9MItKX_<SFX4vo7)E(kZ^5>C+gc(bs3c%`#=9VBhe4}}?ezA<7Nbhrd9
z;it#tB(-cmBlj2(UNHyoQM)$^I}`O!ZqH?Z8&;2oi5BiO8XksUHPy7Pb3f_d(`k&K
z*X1)<7wiMBU5GHHJw~YamfJyM5lSr_3xXiBSKj^G*sx<DQZic;c{FnH?3do<+Y(o@
zHt^&>iVC)>;qon()P&Bl9(PyLp6|QMuf!<xU%I$zl{RFtcc?TWN2+y=wQR7p%YAv%
z`Wtf_sHr<ax@Mu@!%y|#@>ZagMtH0D7>CS{)*nC;21M?Jc8m;oJ+@mSi+tpLe9Oz{
zbGhB-s^OJv&7mbv3m$4meoR(#UE;;&?bR|&Kw7f9B-(@$Dzd=$7s-tGQ-i7*X`}$>
zezJbej>UhxVB?fhFIMpSAyTCvSWT61Qcvt36}_9Xdd5<YJRsTO8l6G&-emstxNh!}
zKT#5kH%e}+-gAyIN|gjfF0)0qK52qI7flvy8k$nN0~dWsENuFL?5__xEHF=2tm4=%
zCfaZPPA=7v%&rU{1uV;h`E=|=)#JYByS%oM5tq9mRS3|Q&_^J&Y_2VL(M<7EM|rC3
z`0=E`;?L=Pk?q|y*Mwfdw~f#{a|$BVejxD66{Ru#UGi$r$>}isfxJj4YUv;jSS+Rt
z76VYw2iykmlx9}D8LRGHbx#LpitzuKF$|Hi_;rsE{0rb=qx<BZzijN?C1OD{KYw}Y
zJct;;GA5=w5ttp_0&+zmbb?<<gcANsc!e3k#LvAxY-h-$pc!GIl~lS=h*iLehh7wP
zH%KEg4&GjWF2bFCdFHyy(tpgCXi$>s=d^C8i(lixLXBV42#@MJLF+Y=jJT2@BY(EN
z6zseAW7pO-M=f_=yO*7h<N1B=BU#<d+P~o@n=)Qbvp?P~9Dy@kwGPr6ipL0Ne`vP;
zL168#P&nKyAGy??K4zfp$Sm96x5nCPjrmkl1`My9%R(PMndfLR-CE+PC$^cqFnm;`
zEdBz`oufn2dmT1w@+*`nlJn~1FLTLm3T^aMqTdQO(UQ&-hVIcx%#R=qr#h01Q3l)U
z7IDoryW6Xujdiyd&b=0kMty&0Ah5%`zJtO1@<Yjy0vxR4nO!#OASdNfn42^;*jG91
zR3B<M@DYt&7VyKA)w8IY{DeJpuEqlAi>H7`san9jWERl$b?NZ`Sa_&$?{$|><*M(2
zuPV#$Y1w38c7aJ#>w+n|z+MMbZ3QchLKgxBO2AH0&j&!N7$I{D!B4T{TaeeGI+3~v
z+|zeh9Yws1VEgJt`VsSftE8j4ppWAGwi!s&!!&?fCurm0*|k7o)YrXw*_FUq^e~(m
zd=66*eZ<Sb)I+=3Z9uN7sv!HxhAJ1W8gV3p`u%l%7%rIP(^iuh0qp$7yq_NRC76yc
zI+9r-775CO3q4?N!*oKTTfuveY0$-N1$r#6BCJD9k{J(Wowd7tW>7(^)_@)F>=B%7
z_(7)eBHDo8xXWCBZp}6Zk6t~L;2-(I3S@UGrRyi;<8HWJ`|_2`EoH(;_lNUkOOf6>
zHrgm$d%92LLGl7uxL2FaCUI$ztKus0a#3>#W02Hn15_Evml>$Ji3F-r1Btg5s7x6I
zBoBdWJO1M_cquh37kj~TWc_P!1@)m`VcZqIE6aW>)YcN14a>N2+t>1l#?Lbp`gWKx
zwFNZtIh2DqB+k#R(zu#kPB$}`?v=kMje3+#YQ$vtDAmVz1-u9t?gQy2!$pEiiA>oc
zQ>3Ha_2fQWDSk&2UT8=ib{Bm+FIuEaXT=Z?sixp6HS^7WWOxrM7RD;9!)w>%88j>w
z?fjum<@}e~%!!MhwI)EEOY^Hfmp(=(r5h+&Wl?&mmTdDR3Q&`3@t(4Dg+pm4dJ3f3
z!SehGvlGWp0qZu(TFLtoceXsmRDcoxyTF|Ni^=O)YnOL()!3^6;n^3J9e>-KN$ZOU
z(DlF}{>TML6`X|>BcQQ^QkIUR{cA!b6sR&q2D0xHokefX`s`T3?)o7*^Se(i`#rP(
z&BEmQ)*`NAG^Er6pGFQ8>w}Xd#F>S`+fB1h;z!R&HT3RR;FF@M9QSmtuYI=<I|5Fr
zF*<u!0{_fb)49C->KN*d!NHN@S^Aef5tJ1aj>a6Q9D2OpCgVODzjiPsEhwYf7fWaP
z9d-t<6JM5qxKPTQDrNNrvN1koR7{3ki~Cch$wo}a)mXgUSlHFroRCk=1bz{GA*Gh$
z+(6M$y2(bKI25{2?VNIwIGiSzz>2U$(gI}$c%rHmIGEPROn7wBwG+Kv_6}>a*<a+o
zBUQqqaArd^qI&;GS8_yk8NvIXnT|3I`Ny#IG_d`<4L=S@WOmt2Odi6Lx=D909pJLK
zQK-9d83&yPY-OD(bEqM(c|afWEis9^3jA0>55bf$nGJ(2A2Qok4(|{cLsZ}6z!fgj
zSS>A!^ATYkB;qSWB!)6vAFrT`*R!ca7&9k#3oCld5aZG3kO}1_;tLDPisl7Iq=8g*
z6MpSu&fN5o_iTl+XL9U65L~It`7JMUR&3OeAm`B^=`)3;oiR4mT*T!eisp$?PITQ+
z<&+fSf72+H4|{@jmEpQ@PxDFMWQ>O#*cU^-WV^qGeqCJph{S2k!a(GEP~Tus6QIWY
zWKQ0OiJKKY<>NNfL?s464eUp0gL6StJ-L_So%7-kq?h<A^`EMsT2ecopxAH0(!E-w
zQkKfOIftvoNXz%-ip&hrYMVZufy`23&c410_$-F~;Cbo4dM&&D90~gjhx`ibYk#Bp
zV6^Lr{tESv1~FOeAhaiJmd=u6gmpQaBsHVARC&Ro!>}#yl?^I^Iqi+9r%5v$%y`FJ
zYk0a{7Mg-EeUjoPE^?EJw<9uAly~mIp(81^!tC1M80=33i9B;z1`@-fLoFHkUunB}
z);O>vo?9YETM-S1Npp`7^;V}eerU#-{wcs#0)z@KKW$luE87Cq+}feVjCQoqH7`Px
zF*Qc>wtjQERE_;zlb5kPW#`MS^btQ}Zj+h6X6#a;CXR}Zsqv<@+aa6Zz@Wqd*TcL&
zVsy5ciuN$-653S0&e=L?p_%bm;??;OIlsGTQ=qUXaA3pMUCa_rVgq!XX8O%K;07}c
zRrSlqi&!^oDvapTdEx<`nG7`G%@gFxBpk}UR+%zkyPhj&JK|Ptt=fGZ72cYULSoXU
zPa`{4A;F}Sk9u!{JM7JrL+(WvrMo=;4KL)#&R_43Npr=!x3LyMvZ0L4R1DBZ#|y;1
zuP&Y_rFrve4B<%u<vsPT1}*>&u{qLUwX!9!DptfiuBi9kb0=Dm39mm)OTv;Lt!MgC
z!(Otrcr389q8j5T2f<=%&|P_k?`dQ>Ek+Y)4d&Tiiivv$oyjz>Ex0HkxM=f*r=*Ai
zv41Q~X2b5UQv8T3m46Mi6fHuDAbRmUOKE6Py8|iLR}8<)&tGeBa#ok;{zD<4)U98#
zT5wWDe)Kf>6g}ZXd%{5j#ONt#?~HW;8|_&yuUf#eA~g6UU#b_)sMf5wy5zZ|i+--o
z{6%R6O8(O;hM=0^mrQqUCd_(LC7@fjN{ec)tZ;4}d@HnN;4~g{_SL(oUS?H<gYr?*
zbj#Sr^`K&9b0A;G(&Zo~#=mKZ4!s+Zt$lD4+e_HyER@Kl9QHshs67cFun2-Zq45^F
zNxh^Z_e1P&y-w{(we~Oz`eM4X_(SyiY6qR3OPV)z!*=w7Dvv7=gU6Mb*%fGbdO9u?
zA?GR^2gEoI{2dZ85o5q|N_UjDcUXPDb-#L{ti2@4aUM#mhOl+m5^`{Q3bI!O>E~uL
zS{>D3hqDtYeYNxyU*n`JX4_i;i2_5~FU2rMvtHV74yHB@T{FfCYl8kSRHL#KLV*FP
zp$+IGhe&(Q2c}@hOT_&E9iR&2GnCCH>|&p|Tksd<RQ@!))2pVQRN_I?54_(AIVd0e
zDhAr$=^X=tcZC)$&1%D0ndnlyQjvKWTyfA#j@0te)w$3Ekrr^%p+0S3EC*TY6>bo@
zE7#CqCo^B;RS>Otcqj6!Y3_^7xJX7NuhA{j*4p!oJ|r?DV8V_@W3CUSSu9S3rY-)m
zs7;`ztgG2iui2F^fMwP%qfT$|2FV(B<eIxXWLk@<s^+IiFKOa5O-bKvc#}7j(Pf;P
zb<1JjvDmeXd3}0`Y1II{D~5F7W|~CiuAS^e5&|^um7#f9&Q{wqVzKNP^7jJO8(TZA
z=qjd+)!x9jdm)eYwt#q^wGA8dl-dxrZ3(ey6}Go)1?ErDJAzB@M98cW=$ZBd?LSrj
zdb>HgfS3^0v87rI3F1fEPDu-sI8w@Bs>=U3acGS|N<jOn9*=QZ!Pk3f>t5=SU|oAW
zGZd+;5!hb#frzn1gv8}Jw^8)hy@;R<J_0^eA$~s-j`>$uW**%Y2hU@sIc!WZ$EkN>
zbh&6>1Yh6vGp|!g`?w{)ktYNb9=K=(CdOXeV_ON#*yGT{H6dCjP43p76Z2Qyi6D>9
zYdV%g{A>K<6Cq9VuP(vih8n+_wI?r{P!cX$&65$6oPq{a^uzzKwmkBYIF1SIE~PoK
zPFWmjQhh;~pE~4gQ_Yn`4};5@LPuVM5GEE$a7Ci$S!|nsuv=m~epBLL48qX9aWe&k
z-R%CdB(Q-sgM@Nm#!6Zssg>p5V6dc>1}eq*Ff855?+jT;r_UcDEA<{syolJR8_Y9b
z=MhpAg*Woq75jBBj`N32N2O0{s~&u`1h{`-6$w=}7LPt;#5&-&p-{FCnN-~U%ZZN^
zh!cVf=_&pSKjgkfUcG~tom|Q)aAAmC_R1Twrhur<G0O>*7T1u0t79_wMAW`q2VszL
z03AH|5lowrS6?b$b)EvM`bt0*>M5FwIyLUD$vn_&u&Q})KhkauR`9XCZlwTKy@j9Q
zQW~#HP?bfD-iXID#RUi-%*qr!BtN@w4H#-zmeYAKjU$(0RaqiP=Pd;=gsAOfL~pkq
z`HKZ`)dIrcDsZ^+6rQX4;0<sH1KU4j6^#toJBd4CP#<l8lG@bC=Zl^?m#1PFgegCj
zVoA|qfA6<y(&B{ND;1~9OsD@Igm}_W3}8=*-|r&hN{gB^e-weBUdRhyS3<XrfFH4Q
z6**a89{muGx1K9<9;4MvaKBCKltM}Kr;f7b{Yb(X;Q<xf>k?U$4OLJ3Ol+NNwQd)C
zoqABT=&gR!Bb-uhqixr)vMo?v|I5y6R9p@w2BrK00Eu3>yGYmt9kweukn-aF_#OEw
zgMAV7g9l6L)W;V6gkI5;Y2H~ib)B@I<e2&_w`~_YymviBszbJ}A~_gW|Lc^hPHzVd
z6@1N_O^T9kEyW)-zyrISehMXjQdQcWWJWcQJ78lj{F0ufxQ)lO2TOjkvuLLSjG#Cj
zx_EyyyR1fAX0ul5vb*~|Jyx5J_CU|oXFlCNfUVr1*I*vps^Il)9)$k&A~LIUiAkkx
zAQ1AJNouyxqley4j5w_{;_x8@pK%)GtcPBNRy%2jEw4iYnB~~B+&i((qSci#wE>Qh
zQM|>)X(Vzx0F$NH;6`Hk8ddV7`D1w!wgLpXq`Z9ll6Y~exRXNFE7WUFu{#Hx64vZY
z#?7ca#*!Vt#m~a<%#P-C1Xq$Y30sJJC3RNDz8KLkIDmz><b@_GXJ<j19n|CauOm#_
zhYY6@hEh8CwkK8FVaCTR=9NFh_30z^?|{KZF#Il{Fi}VcJX|^XmH(9w+yG%dPu0N8
z8Ze<C3|vC~8Yer#PBzV4t5Y|woCT9Ek~Krk{&ycQp#POiU4e}Ng0D6&>{!)mme%I`
zF4omy=+3okH0B;Ma34Nmm`IRXr-g3BOX&Q{#H52B@nY5_B9yjQC0i&@l^G3%pl<VG
z54WCjFqI8geguIole8#Qc1geIC*?kL=@_O0?<G&kp3`9M#~e3koT{*TmJN_CAlEgO
zWC-<xFwnI7I<DC^Pv?Gr_~+U5oa!(<?-D36@Hpsdy$aA^+U$87oZfozeKtQAHfUMx
z+l-gTggsCGm$|OpxF_lNw(kzC5?~dbuV<CDS`Y6sSnatzE5jQ6TYEQweRW~lhSj{+
zJq~ON>{M=ubxd;35R*UnL0b7s&|%6%l~zsVwYcpf9ro(+7JwZJA~|ER#OdFKmYO!E
z)iu+AC1r58UtT2U_oh*YB+x$V-EU`OcU|$o$!%IqR%{`ZfOMh3|9-Ew#uRWCgERuq
zA|Wz`c7d=e$&S%;xSAu6RLwohb95Xh*=_kz{~A|SYm0$-2<gn|K;VEft!!yjDzayR
zlXP|w@IL&neoOkXA(Di$>&fQXcImPaIvL5jBolcMh=&Qa;c8+(x{GcI<uUfo+arV9
zL-lJ&?w5n(ZMPMhSF`um_LA20iUj+PqL_1z2If_V<65_uO;U(gC~lfV&sEdKUy=)Z
zrm$p37@lk16ec8AGVXco%U4_h-DF*mOIt>Eaqd66N2m1QT(mifL2WuyME+GeXr1T&
z7q?V%V5j8X`M~a3r@v{wPCGLgh|VP@eYkX=YH?Q{T>pv;4B=i!{Ih*5Hb(LK#FxVQ
z+z&?WZn|IF`u5J8cGB#ffWGk<zm|w*VL$Z!@H)0(r(t`-bkFm)jd@x`P*cX1T{v_(
zIsg13A{N*P)>OGV*uW{cqIc3Dfxzg>XF#M(7pFP8qZ5Q9!J1v2<;@1{*|MiXh~jZF
zX?GC5-otPIT8DF`>J--NvdSE=U$@F~-U+C2=Hidi7dnPpHidT|!21Uk#c&V28ZQ!o
zkg%O0aoecF$`;kw^!#A!!TNZ6yxCsVS(SaOs05zR+kc7;GGWM#G1X588NXS)`#O9G
zer$|W8rZVYxI^FpTDx|n^PkJEGZqtd?$^?uSHIpD(rR~--uA`TH`fdUyb}gg5`|R{
zvwcv77%NEkqE5}A4BRx}x{}s_;q$udDN~_vVuv%~D!L+N_%JB)*O`lM;6Euxgo!MX
zUVEijaVcUlInt*OJ5*k_w>!hbd1yOzh!E3eis{1WDrSgmchrlMJGNN(jI(ddMa4cV
zSdllvA0=J7AT;j>cat~!f0GE!$WZ2LiaiM|8EZ2moinUf3h)~bkAv8w1c0HWv?1G0
z>DU7Qh=4&DF{@#7DQA~yLW+q_S&B0Fi?qU@H#i-(o3dpwE*G(rj@LA;#d<Z}4$le3
z=bBnH|B7xp%KwWxcjC0-lHEl<LV)uuzVr$EP})qSQSvuFCMI?fo94IA0PQc(T3*=l
zAxq>VKrj#cc3ecpFNM6&B9crU0$jDCAodi;VQIKn@xph(bM!_1*}99rPc<UzaKg>r
zVBDz;X(B-=)I=D~oT2+5u*^{!)}DrkF7z<disi8So|!nmP<FW`>#!hOP6VUkgP!Q&
z!7%<D)t0>aD#IC2lq&WPU5g6>nj;%zmuIO$GI4)2YLJFFqW7b=s>*OF&bQbmXiCKq
zooS!mQ~mi+3D2;;pb-L8L3rm8tO9y@I1*1~+yL&WNs0)kjg>@l&fzvXfTcs2W&p>`
zrM}l*yp}f30qEZj;A_jQ!t{(ywF!MVN=!m3=mi`Jsn#X}!&U=a-_(8uV&SV>V^4Pf
z&eFz$i`vdPL5v1@2>nAkGQ-R12b^sLItN53xOy^mKOtsZNl^whA6OVYN8DUUIcm;u
zPnrJfGxtYbd0FXnqKy|RG1yO|is`k}J3Jzv&+X^AevQv~elcx;LRBA-bE|K*`LzCT
zyeFOm1!lEO*M`pV2$SG`!N$(VWq1Id%mY;hX5HdIec`<n<Xb`>xwqtz=`SkIuZ?pQ
zw_NYTjm%|no0Wys($o^Yn#?p@B4rLbTZ$pkB7WWR01dyFmlLHO4-QNdYvS{LFD!~s
z>HuKleDTtn^!wgYwhHeg6g3kkshSQ3&5ja*Y4u)H`#>GP-tjemO)<uMY9YE!ife`d
zFFhfJL)y!b#nyHd6ixt;-k$lBJ6Y(jv`9hpXu5wUM&+Kk7grIP>X3Ak*OG9jA}4Oq
zQ{~w^)LKoz3n^pG*02?TmhD`~SMYqXizldv$CamO*d(8#n!3!DhT0;|8;;9j5lM>6
zK@Bb*F+w}vXap3Y=+*rQzkbv!ggOS1Jv1C-BuQ!eNco{L0yYZ=PTX~ztjenmuYow3
z6XS7op8nhr<BOWf@^vu>&>KT(H;}fiYNCkxzIv8OyZlORYEe<%uuQf+J<OPX4F1CJ
z<0qi#@=8DsL+G5ob_>S3h%sOQ3>rOeUDAx}4h1rK7Fm^Y7JU2;p7bI$EmJ*VSzRxu
z?pjI89{EGhHT}<9Lo{0btdo1DSD@0QJN`YlrOd_V`BE!pH!5QJnnXnGm<r+*{<2~-
zN`|fgKg?#K-0w=4v8q$0g1nL<s2H$%Uy|~4?lPV5FNcx6_+sAJ@vbAh+1s|b{#vx{
z^#+ty4L@+F`!%tXgL~zo4yoYdR-8ZtYg(l(x_e54BmCZ(OBXrA7GW&V@?GuvbcBJi
zpA^qSPRDI}@{3h$#b$|tepZc9ucZg>h&&#>xpUHE?7$&<Y#UBNbN967rd?-yp~ij!
zGN!hA!xR#JMe2l}+6Grsh?^$Oj|+(mL?Gym3aY={tNb24We4X+^o1*-d$)?<115K6
zoLgq?s8X&NUYbdn2IQ?G0*o72r<B1wHgU0i^aF^#ltHor6uJz(%W~;>%WS$Dn~D4L
zdI~2@+sAQtCr8bh%*jf}l>W)FmJZRaH{ttxs>9U|GlJzosmX>!x-J@xt$;XT-TWAq
z__QBqO|?pK4HngU-Gw+udq9@h*fXP8)kJ5<1`%KDW^G>dt!1r=$+hs1twzB^F2cMW
zX;wTdq0e|ma+Sk@==JKq!RL>!HGZ4f-TN+nK3-jXMl7!84{SpGUZ%w$|8jx*{`tLq
z#fri!fV{;BCgMm%xw#hHib~;qCG$U7tp(b2MCVpZ!R8K7fLt&LsdCGCx49$2sU+>L
zkwb#c=j36WIHJ-<o^P+|io>B?B@C1v{)>98XH)u(Lf-zu$A=Y4E-;4wt&`t7er&@{
zmfY$P&r3DId%HNpEB$Q{;qCrqkv>E)&$jpE`-Y0+X(N9VEldBs-VEpJoRKn(iT`Jl
z;y8mcEUhs@CY7Ygj6+&L!C5D~l{!u?rY(8<Fzdq1ueu-uzIRUtfc}iZ<bMrRsq2kJ
z6;bHv#M5Jy)W!w9Fl!Rh?S2nFJM1W6(81*7pw*FfNcpn@wQCqSbyq6J|2}-Jk%ucB
zm1f{~4s<y;2`R=w<nrnf(rtHj%NrHmozX1mz9pPWgnwv^`8AVMn{>AD3dQ$_u9o(V
ze+G%=_Tg^&O%>-^NR}{C3PK5idllP~kKQLa8dPbXSRGT%&V7jg$B_+%VAbK5ym^v^
zq9`JQEq>sGpiiY&%%@UOQ-NO6<_1R5-mB!MWzr@S_SN{-oM(vXPu%M?c)p))XY~Wh
zQs?VJe}1xSP%ULxDyyU|*@YH!eI-uh9(ovW1&-`FYC^htQsp&g5qgi)Q+f54^`QT@
zMSmgiRsJdP=(Lz7i=ATx%>}}o$H)zM>oZqOqynt|Tr^~s`n+1O9&t6R8nXr#4|oL?
zzlqjt8)_Y9qCOF?X-ZiGvRps$ikIB~rZAW!twZYCA=uMnMLcg*w{Wa1-<n?YP>s&G
zxxgT8YgZwVo^P^)Mu1@n12)BZBSt$est<btC^W>(L-z(yM%fyp;L*&@0}UHh0wJDn
zWBCMc1PzU(18IR`uvV%@+?3&<t|Q?;XpOFv9|V~ym_Em%mpBDb<&leme;AE{qWnf~
zUE)UI+<8OIjI$SOa$4!(#LISTtq&BfEQ6lFFBJv;&eEt;{JQ8O_#~t5eM<ec*+xL>
zQ5E2AQD>*7i=;~RTl9AtG{%~v_<pXJz_$PMFP~@3=WF0RuLAFWY&0~fmr`=%NI1El
zZ;BmKpZCl9^R?!x!1ELA%(UxqXM2@+%@naWTju0k*9$BL_!#G7a#Gq{9U*uGf?2{q
zv}=9JfWI+YX$X5~-h!A^1!biJC``F#vw3v5KqqwpBEm6bPp)JU-Cqft(oj5;R>6M!
z3LCdJ7=blE6QSFPORETux$L~s1W@zWHJ?E&#9q%u^)w#YX9ZIvhtu?9Cy6YRi6f6G
zD<As<qiJ=787eGy-#(WQo*RTbOZQn+)F4-CTc%^NiON5B?-t$u8}AT7!<U)%I5h|c
z^~BivT#IMx^|#k#Dp>~~R@n;AKJL$DHujr~=ot+T8)0eq$F!|!>G)QhEm(RjMI)=a
z7X82H(<zd~<{)MB&;3^Ap6@I(&+8Y!8oK|oL@8NoS2@3e%*_$VI;)E}v+7R&s3NmN
zdI@`?d*})vZSK&yAUziB$FzZ0sEE4P(l8l52)h#vi4uDm!ppOP3%l0LjpZ1QBP^+L
z5z+i$!)pq(vH3irYrXu!KPOfCVAo%)QSF%1CihsGk_X3}YJ2H9VaiD`%TYs(@$%tH
zMkEi_x;|Fe+|_IAeRv~)LrWv-JsiX{pUy>rsWoUF%+PG#D2mheolG8khK1v7&t}64
z4}oLv8X_OFbn5>-(|9lAd{6^~9V+YfYt7g`caw6{FI(K0z#OD@<%veX1eKti6JA60
z=bmwIOn1oTZg)S3M|j}<N7!Yt9ZrC^f;eOAk1{*jq(9lG=G)I7rDt}(M!`Aj&_IDT
z^Vp%=n*sNyHT8v)$?M<9zD@g6iA9Bz*_)_&n#7R`Sbf4U4I!3OJAFIutYa#u^nC`w
zssb&iS&HfUH1>=Mx#l#jh;KPZMN-;5FLFyiLkwgtJk5v^ZQ%H2Oc7`gBOLtwkFu3&
zm|{BfW33g9si&HuZqwl?^l8v2Fp4h7AA-&?LuOkB2xBGx$^!MLD36dYy)TEC?ZL_)
zMMIKhBXq$xFOl8jB?NXphKRN$Tv})Hei69M3_W}~8jk5b+z~;)gqU7sHe%#di*tMI
z*LCM+a?qt@^Z6X&xZaQ@IBd*mY$p5@y(+Lu*t@7|kR5$6cUO*8O(nD{51n#^SqCvL
zIPNnJRpQSm)-61vE}$AhWQSiRcsI&tS~8QO&r+;m&euPS<9C-D*)%>+8oNa{CMB4{
z%y{)87QB#kX7Hvv?>XB@U%ce5+-#$B#oCfEL0fyTS+spshXZQRGs(N|aMDJ{Xn{p{
zL~pXNMTtYm=h4|O)qdQ5o}kN#q99d<HG(k8Xkzx7iDOSF(@u@wH*5%GCg_XAuctVx
zaOHqQKBe%N6b2q8H=_#=P|BhxFpQ5VfCrzxnru|u^Mq&(dlw?68MdNBN`8`|g^)^P
zx~L__z~LUAv)9+oy{H~<O-+|Q!&~LQ>i%|}BN>=DbhRwQGRERR@|wFAUrm*@i%iCr
zKBKk9_H!7(x#s$sX4?$*i9bo(dN^;9JG0b#p8B+N{|hZU(fXOO<u>oS*iyIMRLvI;
zI>$P>4?nzd$EWaV={VnXgY<bi(P^P@c(UF1#7nZcTF;!JRd3#Eu4eu(6C&eqFnl!D
zaeMjg<oMtU_oh*AajEi@R+9_sB%*~gMaKEL|C402P}QC9I7#&T1x4RuDXSNsge6B>
z`Ar>JH;LY|fWBE1Ng<(J6P@|WG6Vp6u#Z{c+>sTp0M=5n09&<@K-~y0un==9#-}4$
z6rS?$OxC<-##H+BiKk0H57QM=7#=dua!%%UV?t*SQ17;8nzb1O);%q*&)w>`O4$Wp
zac0AqJMXD)TIrxd@4ZKdwZ5>jBo~#vlHTPx{n);}w#+$H<I00CpJfTk+qP!N{5+K<
z6{pdzi(!3R<^4wqs;^lJwI>)r3lmI^T%g2?4WZ<)X^!fJ#k3l`YCAlf|9~vpE7*om
z?J^nA;aPb)k=^$8jyG%IQp10J=h-vbulmtqL%jQM1SbI-vbv>%1^Fau+ZY90q-%q~
zj)N>WVOw6;UYW%4uR98CY}@eiTg1k(i8wo(7LV`xM+c@@O-hQU?H{d^H_j7^t;mbs
z;i%6zoKu^^!4%cTdw2<iw1Qwh6N#|bQ*y}H^^<8Ehp~{md*@iNpW2G(94B?zWrH|@
zEmoT)kGy7;W9TO)E8Vh3gppL0N|&ajc=3(<oFmGYT2RZeKuaqv@vBPJKhS^$R)l~+
z7Qqk?tys#C8N=PDNm7XwqF-4|d278Mqr0_M9E=HnU7V&LIm-kBUhD+6a(4voPp5aX
zKC|4Rv-$?q&~oz(8cu&ZTwcD4M6m8^HueX4=_lB^zfUH2*?ja?=s)9X497p(*(cDk
z*?k6l9<>4$i+qlfc{Kby&u0@4uFICN6fDXBOL}ZOO_Kxy3!c*o3chCI7SDx0hr*Ap
zm+V96@pO&f8yfBrRr6*CEEV&+a8gI-dxDv8sEk`pestyIi}LUTqBi{tGe!&LWm}j-
zyN6CU>+S9AST*`I`}~dcKmK~zk?eD>mzeq#nw!;#HAckF2c`hDN@ug}6SFOMb$pyc
zO4J=36kNIK-Q;|yAGs&-f9HE%O=gPvC^zDLkOSNalOEt!F0fWkl3Hw5>>P0kL_=K{
zZGfdbF-3Iq_A4vexVPI52*hQkfsG7q!?=;SBJLHw`f9er&L_(J2T&4jg3BM?s&b}p
zEJ1X6EbR7{?83i_IPfS6&Fd7!wK$de0h&_&p(3-ojz7Fd*(;V%uU*jzc)ony{?xw?
zU8Tj|&zmpe=~aIJ2Z7(htF#bO*LhSX|05B{{0hesf947+U8=Wf%_@CLt_&jYui=el
zn^g3K7-I)h%yc1ut7d+ec=({k4KLR2ELAJmF!iz>PVTFD)!d;PW}}qI6_m#y?mj<7
zTxjL8iVSfmmS2kf;L<M*IZf*KRNS6<)xZ(ja0SC6X!l<)$4&;_MN0=Xfg1lZxDARX
z;wfvXKW7JC4l29!28@<OrAGL0wnE+FzZbf!ua@F;?cMvX_O~eBw35ftQPO6+p%Hjr
zJ6{iGE5Dx1%U`BXYPqzD9yvJexVdbUb_!`Y3pwge<98YYZYu}IF|h9OR%Tm)_8Kt(
zp9UIy{Wn8xy7bsv2CJhI6UjblHRl1RGU1lM_=7a=GJ_o(L%Xh1+1z)iUCG$7X|5n4
z)WUzJrdRxN?_(x(or>h8l~gm17W!|SLVGvo0w>eIYCpTn$G!yb40>;^qxyjGSt}*3
zan6qTpBH0z*_rr9g%F-y;}w0cCU(<(-tt~HU*(^b^omgrWlJ`gu!L_4pHC_$tj5pK
zaPweg0mV^ojwZJIVxyX_@e2d8@hvVQEVzsy6-D~1Ur0H;>|EB_M9ezoRpIE9&aZ$}
zxdJ|YGlp9mK(gG(aeJ!<Ao<e6>A?1!JjeDYO_!i~C%7xyL}|rGL%s@r>03x?zP0*r
zxA9LpqJ9@-Cok}$+6z22sj%HWqbBD}l_}49E>rdLjD~JX1=8d`K7d{c-^D_DsH=~;
zuF&KU@N)OHFlqSX!6GM0^FBS5(h;3{<GQXU%2>Vg7>6bBoJI|7;XRwWF0`zMq3f<$
zJfTvi%04xR7cIGQqi0m|!mqc%m^w1KA@z^e***B>?lAK%$M)kHo-W(ohfbR%&fID@
zE@2J<kuIeztZ8ax7b0Z5;}rv6A%s*{_Kt-fRlXI;1}OW@tz@5fPOV_GrV&eFy1MR~
zmb#V}q?X1Nw57@3GPL(H!UMk4-+kJ=yk8J@#dbTXE9OxYUFx5$2zr}kW<>!v1xhk1
zr+SZgP4rnYZK>l^x^kd(GS5#XF$$Ec+nrhS`wY6#LSQA;yJKSX^=+ES_yL%rvwvk<
zjVX8qgTlwNi64w}?@1w*&&AGL<N5i|k*^lDi`*0fTE#Le0jMF}f0npodqef*5Du5{
z0Dh<9Nfy3~01$07)n&VQ2n+IGcpn5&>y*!SdYtrqKbvY3){m!<ip2*HA)dzK&JD7#
zcPKr=(a!jiQFc8bi5+Re>(~`DK_Ixfmq4Ky-Pf_5`r+ReNlM?M_^PyqihZ$vZOM**
zw9Y($rOh&J6LSHcH`D{}!xU=m58&p0<I^*9q~S`^>n#zyE&lENH*(dP_Jw|--}2be
z|B~}_<NdD^US=@C1l`K>zuG=lEnf+~4BY%Gd*Y?$f4df+-p@wlKy)ZQf5efpTz=nY
z0|6ID2Av1&TXwbfuz5~<5F0ulWhc+52|Af6c5c6ateE6}=4|Utxfz6o3T-kz3!8}s
z*qbMu>HAD2a!+n?OwBmBa>_jiGr#=g;=)_8a4*i~&eHZNLjrc%RpZ<|wzXEcej>~y
z{0-M*&uVaD*ZJdMJ0AzB^0DRd78lN9MZ5D{c)>euhd-NO3hJf$Bucx5sECMn>9h1c
z&YB=c&q6MvU4MkuEs+nztJ}&1r`wd=J1rD#*hP9{O20UJNI!TuezllI06*?|zoHnE
z(Uk-sB?50T#(=~JqW=59vR^W`<ADQLPRrW7p5o*94whGO+xN+ETZ+@MuCfYDHo0ql
z&*&ER6G@q8Bfg9p)1mm122Sl3oufh7TNMopkI|P+uj9ehE>;SRu46M=dJ!F!cN2p%
zPJD`CQd&c1%qHZ@Iy#SlA^CqtY^(g#;s=;#W+Y@mK66~SVFkB6l3f#Xw?I?HA((Rd
ztPLjCW(#Iy=;_nw6(iDJFQ*tN8uv66&Sy~U24j*2OX9Fsj%)IOyUC-v?%1E!$+7|3
z1lRA6f4i>z5DV;44-@q6ZujC&Ay-t|M16Gd_K)Y_FB<?neD+|l#cvN>H&W~nFerCP
z*>LsOhJY=;CNC}TP7@<m4n-pcZ_pE_>7&Aud4@qlw;6xeK4!;^zuY}1w-{+e*O@I3
z@rtz;6>MFB{lt^ey?yKM{xGe;dr3tVD2DQ&tp@2vcOPoD#kTd8gVg}{ZWi-4O}G0N
zXo^bWB0rx5793ssaHW)q&LWdi9yd&O!@zLfoPYbni~cXvj@8Tj2&-xcfByWqj!pn6
zz;HaS9HSa>Q~Lb5^kAHJ8XF<}rQ?YZ>8NZzY^YrdEQV9Zf7**)f?UlKb+;J2rmf(y
zm{_IzlUunkSd6aBsA0NTi$$6Fn0i*^lFOttQPMFpmG6?H<#>>DaGY6_H?zhCmB>{G
z-p=EXT906*DATz%hiPGzf1bvVuPPJBmpW5!k&d!xF=Z}Y>63I?E)l7HQbuy{h*v@1
zV9ixaZBxGWA!2j+kHZp;YrqM=M}dQuYQdAYmgfHfLO{L0`qA`|R6PW_z;XP;bs$;W
zxD@?x64fPyMpbk!Src7}EXr1E><I!ZTWgGJU|8b&rKX}yYmj+-(>7#S>r0LCjy4oh
ztCQ+Emf985bR3b^lwMTPN@X852#?iwJgeuG%8+Gzt1e@$wNKKQ;<?(@%7&{VT&XEy
zI^2jgYm5yMs)sp2&+Tkf&TiMGqq95#3~*;YOpnZnevUok^ad<QN@!*V;f#+`7DX=-
zqcMk+ii)u^u}dl6D6D2k43v_TiN=yFN&>pb>7pkDjS^wEvtTRD4*w<kqp5pPnqK9F
zTug2rj$KzK=3*&CchrJt4Gpx&3@wmhfG%o`PIO6>?xe(5l(8zQ2#cf@;?BC<QF^fs
z^jeG_>y)RGbx9e9q0n}@vaqE{Zg`6&h6@4@HI&GBEZK}^1Ulh|idbwY;nFxU%w8TP
z;i0Ik7DtI(S2mLtV}SBe1~AJ@M@e)x(2L9-5@q}@D)UI`;~vC9k&6i$gj~?BY$}>{
zWm)C0>(O@hAV9uSX~>}6bjA|d2Ef-dG%M7`UYQh|kW7dM&@rO#D9JGK@mQv0H&L<>
zH)X;x%aBn>VBx6?TH<FIAGN6nf8#Yk$SiCXu^=GPW{Eb)*iDFsV3QGvdJ8rfM1-vv
z5h92>2@w$vS7Ibqn?ckQNkCQy(WT%mA+wJsULr^mMxwwIqryviw<v^bf}$vy2qt=D
zl1RuZn0dWH5iCS+(hJ07)ftd%(;>Z}(-EIRsg-I)0T~TuY!R{905uANjz|Fm?~w(b
zM})VKmNrooY`8%uSVRdrBw^la(b>cU7f1q+i9s)-W(5;7vLPZ#&^k<HvpEPYx0`t0
zq{D862qHBEVP3>uE5%B%4ssEL#eqeePVW*05o5E-L4;bJ!6XY-pA=TGV3e@n6(FHQ
zXQ{Uf1Y=&0MT8t!a0$c=<Ajl3#72`MA$o1zAej|<A#dU_Z9EJklA1-UBw)cqY6Jp3
z6Aaj>lXQswvq}a7vdFwslz0Tgt(OEr(3>Pts3#I8ybH^O*v$qTG3kkntuFcai3f;6
z>>`r%Hi8YjQIzOZVdS(5CcRM<Ff1m4SoId(jA8Duf_Wk-wV1cr&{+yT>bH@M3??M$
zL{X<;7Xq+wA)6UM3d7LrJwz~4E3SgUfDwXm#Yhl&#M?w(ufu|#7xfAeErKMQbv9n-
z6fsZ7NN`ze1fAY&)(gmDC8C>7tkuL@1rLm+fhs51p#nXOkQ?Bx23d6$WU|7TNqPwa
z4LpK*<sH0G!|Ms+v800mh2ge(p$U3qkp!EbC!%N)i3LV-@x2m4Ht2#8`D7mE%mUMh
z0x=$$rV<j@A#Bu(LP!*Sdf3cp9_(nU;RPp8pf<^Ab78U8VbFy|$t)T$3_1^eZQvCh
zGTV(rw2Qo;^I%eE4I(|jjb!I_9-_wp#Q*_-E7;5?Xn{hkIzlk7YqA-FvJG1aqV_)l
z8i`&snvpEj+6hkpe2HK&#K9#SC7oWcBX&iP1Rbx~^iY$L*s#f<(@BzuVN?YjGV<6A
zJ%E*lut5|?ZV!JF>H%cIL|dzaX{L}ypaNJ{SQG$?YeZPNMyw~i4LU;%33I(%V|DRT
zt&V9IIL|o6TN&Ntq?&|fEMH&JXr=O>egJbOcEH&<_8kX@BsksLryMlY3V)`!g6eo~
zibnCV*u(e@ckA2tXv#DlyQbJ|>aV^oJb07dDwpmWeh0}TS5hrdd~E&0Xn$<x9nWZt
zrJ&!~U_3UwnXH-X;Htl8sp&z~!s*%x)JrfOMCIQ(zJog6&vO*@SMxkK0xl|%hd+`f
zMP}k2{zh_T))zG&@%za<l>Qcg{=P}zn4G6es+ftR3cKt(O9|m7xn5P6b+|K}qAK(Q
zN&?r!|Dv%@Rf=9_7>-lC==bQ|y2jY39Z5EGRCckIee0uY41&(G&8Cnu$ZYtJzoNv{
z`aZ{(zDq){vgwD#2hTv+A8_mX(4fY~LxX+m1TJ6X)PTlP8KPYqf+3)a8~MI<nnCS#
z)pDD2sa+GwDsYZ|RY%WGpfd9*LzQZz@&|x4n^RT@ifQ9PGqPBLsE?sb?uSm7Keltf
z`k4CI{d9mzAJVxWT>=4$*JO&*J1Uk2T>_cdSEvf!D6^nNemikKe{5VXYCwzTqA6J2
zECsDwP&C;@j@by8xoO;VZU(oETf;czlt8g*+=MJON<Hxxpi3OO@|U2Q=>;b9!vt_4
zFD|9POP;*^j-^{}7W;Q}&g>KTv7d}K^ew*Qt~(a@8A_jw9?|UDkrgEgQxe>=^p4A)
zTq5+%?A*~W-mD1_Vt~RWi_pbQ&F)Cu-9^hJpO+RAOg>MoFMVaY_{5?mHwoMBu8X*v
zo6sf}S=RHqU)&<R#|62W+!ZBjBR~rKc}BJYDK=^tC4<U_Q_5l4vWN|FXE;rhUE613
zB^~;b@)hN?xS30M&i9%x-sC3%qawA(tu<a#Jqh|w)HcR_2YtmEz7xK9tnQ%C_gZb^
z_*7)q`3INnxN+HuWvf=L*tui*Ys<&^Q7#Up2S~liTVsv4ONtTPO>y53YrO}2_>bW5
z)gJK0AW?1o*hIxQ-&=NI+4(<Qw&SK1t5!kDW4$FCk$Gkto73QeqXtf>NkaNDDean5
z@*^q#<`bt2uwCA}6{9I9A4jNj&fum)jki6E@=v@8d+45DWqj6?Xv%Z<_8i*O-|PPo
z&>Pponlm%~^dPmE&Y&)<Nye8XR+{NC5Ja)G9Fm>FKiX$+I-TD%yB+-_S2j%*_2$%f
z)c5fJR^M~vS6#4c*9D{o-B%Lqx^|Yj41KOXg6>nVjcD5rD#<rW+#+r*w~5=q-NEf2
zwU;j-#$#lA97E16rKQer_9PQ-Wpa)U?E5S1x|d<wRM56G>6F2kVP>ouIgw0|9%ga}
z%A!7Mtpo~T7SNFdxnjsEF+=#^&eB?m#ymq;qSHPi`159)Y$-0fTE_!Uynfl92ku(2
z+9<7Gy63>MS$gx%oo4;4We4^wT`viZ&FAlZV9&Dk5~S2!jlXD-ZRWgRAimRUTM|pw
zUb-Nry;_zeT4D<>U8}v2WiV(t&r2)<;7LCl#KW*-4(S2sv+!Orm@oeG3)qOYL(;2W
z=Lm;vIY9Y#_wi_2+roR&%NH%bY2e=U@_Ms={(QZ;etG)dfzB&q=Pgg&yRdB<;``8U
zos_eM!j64Sdy<`D`Y3iL_cVps0}pi=!wy}mm)HO;LjM`SxtzM>+Cd%Wc^mIl3psRn
zAK|sT813As=Nh;Om!w~17;_g>Iw8y29!@!vlu%HQf(kuEN}sn(Whx$VsC+9_9Hw7W
zK=gA8R4;#4S6=-oYA&+pw@{bLH2X0ZCqLJmd_^T61xnv-fXq;a`qlVP)t};jQ-7*{
z8g)^f9Qwrv#Ki|k{>kSxALDEDXZ8p;3pX<>%8s&C3eECGNyxpV^?(?&DOKfnj!Q4x
z{P?yzFCF>EwQoG}`1SZgL$}RrC_Z`KWt$ER5MA%m-16Syi{6I1XbpPA&|@<h)XRFW
zTe_+n&%X5GZI53{bk~3CiC<q^e9~aDbsO+S3lD9&VqoMSy~}e;d+}^fv@TGqUIuYJ
z2J}exs-@RKVe7}p$Wa~V+1mFpm|PtD_R6SUyqqkvyvFNrj@MapQ!I^sOot=+yu+aW
z!O&*aZsqbY+ysVO%~xsG<}2UzWW(?A#o32_@|I}^RAX?I72{8HnxzHIRo(C?BP>>6
zU;I@6=o>t@9lPqQYkqL-)w6a-$L_W?d%+*uGWJ+Id6T)TtY80rA}2fJ3lg<spxv>>
zxGcqJ${Jwy^3CD6+PO)>&$i0U?hds-;l1kHwo~~D0;}Dxv25sm%|P!^#Sk(1?f4M%
zw<;^ebXcuSH}fByA6EPT?AljyH^X+oRzX%<9a5|ZXVVR0h<yYK&LhPcWK37>&Lq~u
zE{G{JH<>=$kasYhOi^r8lw#SWe9l3*<*Fr{`le5tUe|nuS2r!J*k;%^p@kPEyRdpl
zZ0+l7t*dDXo$tA*WB#SHmd-}Igg<HHV7F)krG8;E!n&rpcWn~hsg9{0t>uf?_N|&)
z=gaBZ4Ko|<2&WIPy56(^=bi}Llgm@hQ`|MR9i7SP%jPDQwPb6$)URt}X0a>ehD$DK
zd@^p5BLlnCE7e;n5#z>{ROt|<xeaVD9U~+d(G*NFno(8l0}NClg&k~_%K;KBS(`22
z$Z1L;6mL#vHAx_M$yOSbt`eD|?*~j85Pj3<ZoA_Xh)-<myT)L&2&UzhM0(ZE>t@aD
z>-*{KjUAD9(4$hLyDc(r@%+U%UAJWabgPcijh9*dRv|RCxu<h}u7Baw)+G%%Kl<Ie
zTxjaWYo5>VQcU6K;+wkcwLnuo)V`*(W7YhbGkY8@KF=90mcC{~c3P;V&F*x^Z6=+?
zd}W(I8kvF{7DRQ^BVnhj*4x!RYx(@TD!%9?^wvp<wrYlCS)USF$?X)i0dYCqN>y*Q
z9=B*iW<>y6ZdcY_87!LKrMN~%E~b6+O@=`lZx^sFq9f+ouGF4}6-&4J+x-Z4<+>Cz
zLKbmqsC(4~8&|eBx5;7IDOrK$RvMZwwczEi4(tG0e`;*LXeBy}=(KvH3;H)-b>Nw8
z+q=45Hn~PvVYiHaf?Nn<ybAFW0UF<u)9Y(2H<)AMTk0QgUep<E_1S}AUwg;=Po1~^
z;EK+f&Je<6g@KrH)GT>S$S7L9QrxJhcYgD#ftDE^(*wbl*8YL*iyuP^U#bb8y1hI%
zc8)Vt<T%FL<iC%5LbJF~-FJDMAN>#e$JaOh`<nC{-&LP?uX2x#QMt+EK6=V(HzjwO
zJc2;Q%_=ql(Y+O?I_e~ri9*krpsFymsQT-ibRVug^JvMQgTizUo2i8iAbe4n$xXLb
z?0`nxbf@S=Xp%R76h$_xzrs!SQ>W}1`zv<4Akz1#@2_9)_rnj}{H<?wb-|DPx)f4;
zyyPG+vb;ad(7cc}L-X2Sd4NUw*Q+BeU)Q&a>q;TmUve<sL#~4V+c*!mu<Dkb+ES(@
zUPZM<c3AjmNE3=+Pe8yl!VeIc9zqQ&G4m3diFzgyul@k#A2;j2sTVX6c{HF?EJ0I@
zP@<GlvN;kn1ucpW2zSKm74s`fZ|zXj%L65&$<$*&79qd6_<82#3nQG>ZP62isJsOI
zAw={Rx0Tui)n#0*wGB{+x1cHDkK!;3Ds~L$Mnp+_s;0w?{1B=?t6f5rz96Zgl=S;^
z>5~4an}}{|?||O!i1a4zN7robRP<9Fo4Rj&dE@rq+<V1WcCBe%ywI=1CM?RyA02!6
z*xt?E3oN>bJCo>HQFDpRpHR!zH<vIzZQ#PW4gVi=?*Si2arcey%<kS^FT2-Ix?WUI
zmQHu4uCpW;xyo{HvT&7UgXM;4HivDBO)~~e$AUnp4uno(l1l;!p+g`*0zo_>yg+D4
z9s=09^?zpenu=}m{NMNeydPV)eRpPdcIH>V-=Bu+_kDe6%k#S$dUsyZ-gmoO?dB%P
zEXL*~H@th-p8LOC*zDWB*j3ZEWqxP1*fV*<QgFeiuS;H_eBEXg$o<*c@e;9CrgCKP
zJ!R#xcufomuuhlHw<s!1>zf|`+vM|~=<j=c=aTZ-Gc_hg$;u2huikV0J(u=3;mVn#
z)y?y*E3Jkn@ns}e0ZD@AE%H7Tsso|_ns?i|o%OxvU);9#RyV8ERv0Wo%c4VX-FeZy
zpD%3kZeQrCp167L)M|0%>YF9$F&kr+!D$OnbIDjpWpZ9|geF!nIht$($?AZ<Adfc_
z*N+W07AeYKioiwfKudy82t=a3C=!WG5mRKeKub4opHn(}YDLYQx#dO`EK~Y5HicqZ
zTVu4#muQO4@%1kfzny>Mx{G?uCQZph-BtC0rdczCP3QKvl{7SzxGE}Kl{Mh(WHN#N
zgXD<7&XyUSLa?JE+~Lzf;NpsPPO}Rdnr6@6Slhf{$-pa##NLI=&!>xR6*cNe@uEoi
zqzb3n)!a9+dQNS5WkqQ)+!=0~9T5}w-h*(Iu+30z)LygDI5Yw29lb~zq%b%Jo>v)?
zrHBm_v4DhOBt>-)(mT#4@u`Jsq=^|4f@$1rg4Ar73xISWCj=1_7A1YrNHhXJNGx5F
zm@rlR?C{>d)dv<&+XD=4mnm$%?!~FCGygCE?%cm;+KlQ+ldBH~yX;YKYk#6_j;+dA
z-n=;0uwiLjs|y+H_3gCY9qrpRH#T|mPI|*zZ>@jx&Gqmj|D^V=<g6ug&)Yh;w`t0p
z{o!uDEK%yOW`1>D_sy}k#G=+KmQ39`r7_Xsan!GExMXK{$kVtcyl!20?eGou+MX8M
z1b>w!teya&)?c^0aq@=7VtV7oKmU2-yBRwx#(_{%MN|dRmI*Z~XNlp2CO;B~Q5Qo!
z4D~2rkVZM2B4qN^j+ymvhJJF(bu-H}*!EgBbJw9=Gs~m}EbBjXJc-99CVA+yp#6Jd
zmEkaGak3Yr_H_k};?T!e9JpZCtP2iE3$YAR_yUpq(uq7LQ80sNz#tuv(quDo2xbB*
z215yA0waPZ1VYF}FCps!NC~xBJaMF2Q*=VQR^k$u5)ClO$uPk+NMT%q6d>^=f|L{>
zU7Mhi5Tg)ia?HIM_ylbI$Ulfl6y8V3@--)6f+;Ao1XgGPFhR;JJqxG$WD6h6Ja=Rs
zPccPBJS2uRfcYlJ${*-^NGApM%ybg=O4QsrnSe<iAJhnLruTSKU|ufdI>9n*ijnZ`
z9HU#6AJtAH+c-F?+5S|}663TXc@BEqY2V$58)dGgsZ1G9^X}-;&&}s8+cCm%ey}rJ
z7>g4&LJ}Vkh+%j#iqkUXkR&$vL*eWM&QX#xp`sr2Us^xq><9pnv!~SG52n_auj~{r
zTc(^?-W;<a5hm7LK2f<;yx-e$*4&wFYT^pIVfbT`1z@iZ{(DtfRdsb$+4+A7fd#V<
zM8x9>uBzD2^Zw#0F7bu6?Aq2@eLduzKa9rwjU>mgJcFTOmO`3w)FttH1f>zm;NkUE
zz+>`}bWX5bd;+Wh>*m4k)$4w|nz>qha?XO*`6iY4BvOq)Cp4B#S=ai&YxLE_9{K}N
z)46hG=d?4<7=AzfJmlB!m=tkF(r<&S!PgTe9B@ylbNzKBhJP)Q8}LZ#4+SyIKm=PR
z@x+oDF-N&VFo+;ymQm-uB7Su1gW?NkazMUMsnc_vZ|>-OX8)Wy`=9As`Pk%r1>TF@
z8-Q@_t)S=?x=4Ip{OFbQuGy=!$@eRuaz!6H{WWyel(zi^-i?daY&!21RK}7MCfVQF
zcQCG%X9O@VPK0&JaAGl=+1J95v}@Lq=|W){Mkru2_BAa-Qd`&%#@Ef_&Hg>Gf$;iX
zA1psX?b4QLp^4Ema=M6isO-F5Q&J@M6)6;Em6LV`m3o8HATvU(7Aza@RB+=sr|tq&
zIkx0&2t)%L0|9`&hvfi0OAC!Mbdp{fL>H*c3I(wyYS67z4s=sFy15CW$Dn78Jr$K|
zoKtt5pvqBQLR1bbM2fq{?6BDTGd-WfofCM4SQy}Jc@h(Yxr+Ux&d5d$0zD`B#td0z
zc_3j00hP4)c8$zY6Xw=5_2`XVH}5y<E8t3UBrSmn!OVG=Un%&GUE&k2#E4m7Bbf2^
zRX{=xf*Jbd!(f-aQtPmbyV;pdGxwKt&1~ADmCksPEVfJMrNrZZDK35=$ezGAx$0~2
zvFx}Y;d+_z{6`^S7D-JQ_MVGLi1+@OKFH(&zpwx?67h=wQO^+j#M@rKdiO$yHGJdw
z<@J-AUjnOMe;v#zzyV`*)-ga}UxQo0C*W2ldHLu2240+2)4Oy|>&Bo=e);Es|NM7(
za4?f$9Bi<kfY1XE<n1&#cccMltL1Bvt3z!NzlBqvHGos&G$0X~UM#*M{`<E6-ZOmO
zqKfFO={Eu8ZMUUw$M_6KPlMvXHvAy;hO3xl-y>_gZ>+1EXB1pYZQmm=J@U!E&rbvC
zaQwT|qdA;^&g*D=04FH=0yKtsBww}Uq=^fx<iN=!4WLni4&a2F?Yt`ek*1hY8Vt;H
zVm~A2H9Y%!#;ONX1v~oyxI)ed^b1Do@$+qvEz;8^Yk*2;rR%l4%^+8b)hl5kzsUTN
zHe;k1dQ6eg<jdpkBhGE#NP>=XVDe;;3OTB-L`rMy6)9r19(QX-EtIxN@?%La#OQz}
zb%iOBsZ{ptakgq_q_WrIy{Q?ssk*#ul0q8)Y-({vF3KhbV1yn+tVXiLV%1WXb(i6Y
zJ1}aKOlA@WLX5(*26mePQ_#zi+tJAzU%N3_8=SRzmZydG2pW~TdQn5iIpv&*Q5kp@
zW8%tpT(*O3@&>YbPDjI{YPCuufJ*8FnE#6_fM)1!4@gsG6=gU)`q}i+z8i1s!y-)0
ztXVa%Llx8r%5ZpElhQ9U7-W8B)3n0%a9Am5SokC`T-J5%U-v`!#!3iRVxg4D`JUvI
z6-iKWq_%k^f0Jj7LCKTL7jGU(yh1!2G?HwwZ$eCB2FNtA_`(#b0|m;(w;+{wNY#}v
zXw9U<b3qcjJHQ}t=kRFLXQK1xr^!1Xlw29u{iM;M`Jgu^R}#J%Jyk+2BRVBXVVC@?
zI8if`{b7`txFa!%tl5a80CN}|SbHW(WaQ0d|8UHGl&B664heQ)V=XRM&8q2xlQvzt
z|I$s9I+Uf#q~;?{5-mHD>na<Ym@1pCQqvkXcJ*`_!>yW1o2`mzYOGwh_?jnw@#Hm&
zX=0rY*Py$(XVgx;V0LBY><gx@nXRf&-E_@0H=)JsHMeZ8p0Ty2C>C%y0=2~!Yq+MO
zwzi@sY_$~E;(f8AnyoXcH{Y`Afz1;qZhnA_{}R5fo#g5eQ-0omCUI4gkP>|X_GK`i
z6fZ%hX^ssF8ns&dl|lg$gpRTo6D|@Y%VUECNw`-+ssz2L7U;hcorhT+6Bvb3fSxQM
zB{9F}U?;OUgoOVnO7f7)^Io#7zYmiTvZwI9vlOo#A~znwgqOXT@N$I`W<By(oQ*y5
zw*tCx%8LF&rMvHey;>gh5?|OLVc8r+)mou`llbX(zZZ9E-UJmtInZ*be@2Vz^|56P
zk>G9#3nLe+9Lb<hoV1MiF{l;pP!<&S6lEOL;+mlI)oLv-k~Rjtg80Qr3P}}muyfQR
zsyFZTVsr5<bR2!9#Bd@3AmA)ecN}#9{Pkv0(?Vo88nGP=)#5l+CzA_)k=)@-Pzr5P
z1seJ~%ng$V1_!3p+xCLVdu{!P+;v@b?iqbE$Z}F60E|-J(bo`AiK$Ge%b$pwf9JXT
z_n+Ib>(JJvy4sExjjNlx1_rvCR~uh!arO1NS`vr)7Z;b|kGrgRF~;V|Z*}bODkr*X
z%LLuht%r8e?_`2ra{292Tg=Q$dU2%w7>tbDk4aH7G^WHgM!pF2F5NLHUxC=oq_>CD
zl}*wSB1zQbQah&9OAys}y%)60l!hiBP7Uz5jsp2nmj|!=nhZ*rJ^0>Tcvt-t)H<{j
zn2~5%X%e>|{_w-YdyVfLAn+YdKa%2j@hoEDJjkOBzY}5(vIFlJ_mZ8Ln^v}<rpfS$
zO1@{T%?70SF*Xmuj&!F;E?g{w(;mr2jfsN<Ig%M1rjk;a7^L<tOQ4-h5`)w2T}Gqz
z<4E3;qQi!UQ_J?U)Lzu4`CPils7$&ao;^n=eqh4f4@!`eWWz*8w)c`ZO)3jKQm029
zwtN()t1LOtl}L1b|20P)>OW5PAL0@p9!~6Ch7mQf5#}&GVQ@f9rc>zoi~{v3H*POD
zgc-o{c<Yr^n<NczxlCNCOOY;PmT+E1uCuu_eTCevQ|bx1K>d_LC<mPBLy`Sxm^iu@
zha<A7bP|0Q!{6YKfL5Uo1xgUKy(D09aP<23gqH)N(VKSfJu3Oer5qmt%?1+A?p(r}
zU>Y5Wz!^N4cNJu2cmo&#WfP3DqdcXfJ*VtZ91D_(PDqyY7VQP+DAnTc)L<0}0iiIk
zaTeZ2%fq4UTH#(^%j_-cEjgaVcaf1ug%0tuVl}8&ALAJciv!0fx;N`s(+=i6peLyO
zI?g!HVdRhXw>?Dtl6sZ;fcgqaP&(iOm7sYnH+FQ?HaluNFb)^?sg4K!AG`i^=Z~&0
zMjba~BT~oUK4I?aoS2r!1gG-rCkoc-lk7k7fAM^HlKmsgj4@hq-3SO5Rmd<ul&k5#
z##X#wU;1C;?EKgN!4t)Qow8)duEpS{Ly`bj5HgJ|kf-=&o}~Uvee-|+EBT-F(p>CH
zL4UP@ET@4lIx-@w8AMEDG4vyzoCfoMq<8<&-gg3P!e|`C>ryWyhYHG*%-k>AH$ei8
zl9+2J@xQH)o~B0)U&|!jc))faPm+E`r=)`R_U3}mr1i@D=L5(U;!qF?9f=%QI`&UD
zQL9FJs0mbTR-6;a>&r1z__8z=rrg`C$-rQZaAF6E2RkPDuXEEdF}sN`g5>R5`ENML
zQWEMnlGaH$fP~MVUB!HusjN?%d^dLCw?e``D0y)*COo9!Lhd(eW%`H&2JRknAG`{~
z*!`3BZsWMuL3;w-jl}c^vltu_HhzezM&Dwmlxcd}s{bIVkZ4ciR52|{i%BB=Fsb9I
z!MwESMmxda__g`+ltN?{$An<dV^4)l12~@~f|t|Lh{4DCLfGpV4MpSFdmD{MENE}E
z5lZpUAYx$|i<wIT@k4QNC?WoN5^nz9!9-#()$4XAQ>moe-J8POL>QU`0tw7+!P)^#
zxY0kPhiMgVFgWB+x#iZRRgRWJV9>3=nqb1+;G?mem&nBE$WSjN-U%$`nmo}sY0psH
z6Zar731fOsk1}XtNG1<|m~ew3H=S}Pa8AkzDmq<Eq*AF54+HGTO}U4MM)0y?c9lFO
z>!{dJ2}XrrEsjAUBC(DlmFLEVS$5V!FLX-sU16GytPcwh2qKP@pno<hesfg0eh6Re
zc;ymPQrS|{v!qfbMwd(?j7><T8+ie27+Elg<m{RBznBP;;!3ebJDP8oQvhbXop7tN
zMrl`yVWkqhfmUjiN^u9+2lkJ<`v_Shd(e+`$_{ada{S#AcN;3#AF}15^6@`;-d<+B
zop3IGxOCrr=n3Se;0;u+@pi+RQd!B?KCmxS;;?f3-MCycsVkWXGj~LLjpU%<$J@z7
zPFL#@yT2GyRQ!B!_PDz#sa!`;xwaOz*C-wfe!QKiTqmvWIJ@DIu`d^$feSXyZafyD
z{sp&^_lQfS0HZ0LQAf(0J)+;xUyR>aWPC$?1J2Fe^9Of=lf7+n&zV5OMCiHFJ^zCj
z2+lm&JHhv?MEBg9FXs<ze7f=^&6)8-OLAkCgw0xrW+eIYjn14#UfTkq1!D*{HGWS-
z1X+Uk_R~Xdw?xG5cBcuHlnf`lxoIL(43qfjnK(=@FsE6A#}I8(S1=#4R}cfDBU$};
zY#Zrm@PPvCJ6u*Q0%l~!2wPK&MnGc(4CVp>+l~(k8iqXncnTXr2PJr`L3%*1AJpps
zB_WkcNV{}z-oPyk&n3p{UNlSPV&)l1*0G?OJtyY`#%;AilYxYV@#9PjXlSXi@>qOp
zi2-3qvM3MZ63{P?2xerY0uZ~2MT*!z+0!9uf<`c!DgnGkfTO4rNUEbq9no(JH^Cs7
zFr!waB<n-%j1>~T6lns<-cQeTyWPX&1P1>W&Oa(t9*WAa;kE$DIhkXUzAi_6d+^{G
z>RV>8fEf3g@$fJ*bGnBx4CU+70vkb=OgTq&R!Au{{s}ZS&?P3j2C$2t%w~!HLv<xX
zT?2ITBnMyu?;hxaDI6L=roKb{NcfdbA7?)`Zn?FvK+Qq29+{^LsgO>60!@u6*gzLZ
z;&Pwl0Fz25Mwb|n5}#y0Re)!kq7;;YvgJJQ6NzOyV`R-`Ri0$&AGMv$u>@bwZ)}=3
zuc;BTl3)GrJ$rk4_A+O+Eo*CAmWJyNu3L8y#wDn?1B5a1M$%u0&zU#xoO$BkBniC@
zU(}O+1z*%gFUA+G>m~UZ!=DhANpKPAy(42pR8nkdwpYqVBei7WJqtSD2u@sJq%q7y
z1~?Um;<4o;<E>1Fh+9CT;f1tL&8hV|1IzkaR&KuOmX(+YSEK~2GolY1{{GG=82qvL
zSI%o!7>qiFPu3A%Gq`<z%%#S8%;YrugOOv!GcU>E*HYv=tELv=kzWhEVNgq$`wG@A
z655tGB*lz6X-t7e3r0@M_`G2zl=Xy3c5-Y+C&pfwv^CFbw&5RmQ*QO?{b!fnJmtYD
zH<q8hKe6)QCEfRSUvh9|VyHQI>9xN)v}{)Lp8c2gds;4YL^j^F;o3W|+q?d*4H3s>
zps#CQN5{O8KNp;HuSumc-FwcWJ<}_-+REvBfc(`9W)3v@6f&W-W%b1KU;E;4_o8iU
zXV3GwyJxN4ws6ki$nVI4-$G`b!(YiMM_Y-338~)cMBd$uiD<`=G7Uj;ERlm+grAIN
zX_B}xx3icVGla9oK&=Gshgz5b1%p_?6CGVJq^PoaHmAaJ5f8b=Ec+&UJXNyPF8+y+
zGKrF9HW1{GUrtk5Oh;U3Kvf)I>%-!^<p<l3r*h>+np`Tj#H@qMedR9kdaK@7;Q|}X
zj}7Ll@&IUzPWn+xgLr*(Qob_F2CKtvYDE05kt(A6R4rjHA}-S)fnaf>F(}>woM1HA
zA*ByPw-)N15RLSFA@TWHffvLV0&=U}RwcJxdhew+`Ggv)sFY%7ByKG*eeDBZh{Inz
zuof)=^Th)nk0x(_`P}QSI~Uym-KJ~RsxG@#Uj<$*Am>Vp__DS6+o0ij)OS06-OL2u
zQ1b8N2n+nV{0DWDTWcm{YE@;kTjjW}V*Ed=Tf|nS&sIy0ZiA`{75~$^sYpIUIri#j
z;|_5b`{7ke2JLC0U&5qa4E|>|k(_|w@&Bms8MzKEq%4f~A7&9@M#Xda^_0&W^2sDv
z3{MT6;I%1Uo7D1B7D#p#CNh=DEW|h8OdWjhVCqfrO;GVBoqQ9d#$1C}*OBUEBD&rb
z7m05slb{0J3otXfE@ub9W3dm(V2#ui692w|+Cl9hmewCpj}osvsuLOxP(9)W>!E^m
zbPjrNXdTreaPo6byZ>bCY~i{gw;sjY0%1HG?E}#F>e2tCen^l0XSNthKa2!Kx>ujh
z9VZJg{$_S5Qkm`i65VzHU+_JeR;Ne5CzzrbSriPAGrlhPO@BRRmpINwW&xx{=D#>d
z&eP+Z+~Fkt!w;hIFO|U;m27ins*GBIrL$}-5N9A9Bm^%3jB*oZyn)$_K^$1h<PbID
zB+NCNMTZ9W<bC_PTUX!PbL8W1j>gYe6^|EH)Sq+wOkXkaZx#Dc-(pifCHJQr7ELZn
zOde=hD}J*=$LsZOmv7;fcXbZ@dLS4%@2FYfa=F0YVc$}Bb^OBgeVcUwn?q}+H~Sh4
z$F;=Y_D@3tc4BW&vmu^kw)wOkXVIbtg<J^0k9|f{d2_HOE)1wyJ#WPMP}#b(s0Wu(
zHPmEk3;qseoGB)dU$h>IqM=fOn!`jYWig?8p@XQdCiDNVW}y?0zxeW_55D;}{psJY
zHwtW>rbY<cD|{7Zi(Odz_y)mPR(;Nq`}S3Ot~>tV|ER5?HKkwkbT4@LIr-VoY!d69
z+EzIvQ_w{+D<{ZQ3`75=A*zraH9+o}rSfOXz?c8ChQzicB$p6-fnQ?y9Az&s8%O8l
z!p`vw2uh}s*A5fMCyhs~(($b(Vr4-#BJRVLC$8n@GGCDA*JpT3N1D^jMg^MDG5Hz>
z7r-#u;}#RHAJ4j`gp<U}8H>6_qhY{yX$4+6ZUy#@Z+T)o$G$-q8yJg*RY@!9zVR!U
zkA?p^Wx_Z^z?6mT!4<+-o&?0tsHHQ&7Ca8m8+DQiJpqZb1l30pw~I?d;#NVBX}smp
zBAMJMqiwMK`ovpzj64V2a`Zm%+sPPlCL?>}!0$=o799CMv*CuFJL}X2Ah&}9cTbtE
zIX>z<@mSHXj!3d9JaI&}iyfkrR0*m>C2D)xU}5Qy0tf`xHbD54Fq={glPMtyTwtAm
zxf1~K);8ziM$pov2H%L+FJR3UgGFo=ThYSIE)cJC^OfM=9~z5`Odo=OSMsp^Sgo=N
zv<)}A?ggvbKvcY4RC@yI&p%fOJeY^c9p^9&Q>j?r$;ES+#7PoUOyxoRJzflg2P8ZY
z_S|&RP{JzBj&#cGQ}RZZ(&!z$j$?jwobo}|XNCz!MTrt7IYC>R#UI78IYgsL9bpVm
z0FUJH%enPDnb-+QvCR`($5HRYb~_T}QVHj#lj!dVlgzp%h6hJ@D(JcYM*T&h_?9?w
z(5Zhyf4v3X47#_#qw%dmfzJN-@DZNM@P9B8MloidoSwIv@S|eHajcQVKT`~d!Ar`-
z%8qj;JoX{6n2lz305{Q6rT_3LNoB3AfI}UZCg)bvB9*kZBD09Cj!&FX7BY}cE4hSu
ziY%s*-`?8AHu1v?gXJYHlkB#|wOCO{yXe~dx~Q|e47Na7)9lR7tiFzIcUsC$1(BY<
zoLWz9N0Lb9EoV%PW}`(4f+ayM!2*Gi%_Sv-Fya^*6>zkF922<!E{7mw0bGzoAGT&P
z514{mfP!1I*dm#GD0uP&rPQcZ3I(9>>l>7KoQ4WAgjpy71Bs8AOkV+mquX(9QIYs1
z?=yj}dFdOz62HoT3;`bP6Ccjt2!UB9cvZn|(*Klh4Q@C=sjRsN0>uf6^aVf`k%A=U
zA#(oUIT$<$%r^OW@k<AgAcuhPl?gp+0qo%cpMfC~zx>*SinQQta)J0$(|U=LiYmC}
z-6I|*jS0QzLm4Kv%qA(8bA-1Wk7(M$y(G9j1DQ?cQxNApIAAqpMG}pb{D3A`Xi7z>
zG>*1(rrom|YnC@pEcZ>-@M_In8dg3CCUo7oyBk=u7g*ucSWjb<!)%#nGq?gm<=kt1
zj)tnTM6qp&UcOW5)Bt5m-wj!P8{%);iFvvT5kVyS-|S>&!rv`DdWK6%cHf{qk;qbP
zqm`t@fg=I5<={X-GUE(Or-IB{;!Khff+4jM{Wx=6C!-!B(2`CaqJx>-_QKmci$Dl(
zhCmSrU~g;yxQFmT{KLr7<V2bP#o<wlVnucX<;8d-0h14-9{4bnk|!DwXkXMrfFL5V
zR_HPLXaSf!B!HO7zM+uBoI`SRB2oIH?+#n#G_6qTZV|=gb5HLB#>=4z?V;tiD*)K}
z)JyQQv`90xvzE-NZ7hw1wdVEqz})p`T~<AP(Tq6#$vyWBmnqaHqxIN5zz6jAe#8V7
zYK6M&qkF|~#CPC5uQ-bMM1Om0xWyB!4yhc=0>u+|tg7p2Y$$K?bV>b<#qnbFZd9kq
zKcr6V$?HV_z&d@N78!bEow_!jb=jm<tEVxisnWZzI4Z%|8nvx&Z|Dehk@^6nZ(Ybr
zxO-Fp$ElmK>4o%wAep<cbu<aO(v<kH>>HiRHk=GLq^V%59<9@8okr^fZ;*+4rxy)V
z6{TLZWYAKw@x4dJ&%Rv#vJZzxawadQg%S#OE(e>?k4tlB74U|<Q3J*b!NM(0&CMom
z6Z$1gMq|PjLyS2hkqjZFVDaqI&dQF!S#Drfc`xh>H_!8x`Zms)ceXR&3<tVa98v@n
z8UP`51?WR7x&mRe|Lpl)8_`+wniHQ?0hR?;Uqz+4zPhWtdntHg4nA~2=*AF>L=9!M
zKG0FwSvq_1((dxE>Uwi!h0h8Z2mxTIQI}>)QXh4WdRj&nW0Hg$FG9XQiZkU%*GZ6h
zkiuUhv943@%sQS0++-GTo0+8e?z;qzF=Jx@)Vt!l*knM!Ceg|X>ZthLQ5<7SCz9`r
zPh0m&0hD{KV9NW_5Fz1M611STBDMGE(Y+A=;s{zK%WNevt?hU=M>otBM**Zrc@8yt
zK_SOfAjB17KbVaHAc4UH-5Q*R!K@c=IJ!3;>pf%R)1<s(>a+7K5smcSN+t6KS&HYS
zuRXeV?cH$pnsu9`3Phn(ydk;wsL&h9RKz}_s+tZ_iLSKcTi_+S1FqrOxmak4i^(g+
zGNA8LFc`HgA<)cWvNH)Wv7_hjsrFU-w(W}Q)kSK3bl0|htJ<ZY7MOs^<5#y%dy0NI
zO)a=@&jsC`c1|Ya?48{g?744&G!SNFBr1oK;ltyh#bfXUMnyP`-5!+{lo9T7Yp6xh
zWO59Be)-@|x**UKlYbl|?2XBuHq6K;Ezlk$v88~UfQb;9u3&xEapHzzakda);*)-7
zkanYqoI8YMy&3r!@<0aO5+~SuOe2G5<58SIpZTnD?pZDf+Jg=T2y70NqQ~hUtL18j
z785G%32M_d(qy-DmAi3ZO0$tMl;|}UgPIlUCa$lu_3Z7@g0NNvQZ$3EVx@Q9E2i`c
z4)j7^wbt_R)?qR=(eD2HoSUi|r+MT)PF-VFx~ET^#FtgzT6tV59`*uGf$Qc!;g(6h
z$I1dWTO*cOX&J{#NJdD#$gSb>$76o%U>YRCDX`w~$eb-ks1=i(Laj<@*!klB5<jP9
zT1CR39#ZPT`Mq67!92ifjf^Cvg5>w&^^bP-iWlpZLyQ8yG$XLh2a1GX1W7G4ZkhA*
ztArfa(d&|q0cej93!%<}mLBv+dkD_A?Df0EM;_4>IqL3vNqpob@xSozP0a9`pEfp?
z!Q*L`PSm+Q!&B&|@gJBnr?c~yBV%3gfI|i1v09{6Wik6@B;%yey+dEQRuIIOK|~PN
zVlA#g5WsJRT6oDQOXijMD2Sl*Y6W~ngLE={`=mJY((}=yLm6Oxiy{MpU-*3ZGJ2eJ
zJ9JwR5nm<+p(l@iJ}wn5npDh}(Ruia(>))=W7&)ri3&h5>iNu-1+@|Kl?0<307xw`
zy0GBwv3U05v;k>;MYbVEzk|v#^^#t~Xmj!xq!C8HFt}r!Hb{{C5CiF9an!RgG>=bU
zBhi512>}ny2AF>R@D){XwfVVcH4m9VKLgg)q%Y8kb!;-3{zdxN^aBs2Kl>;ey+ZtK
zHCP4RkAt_4t-SM2(tp(_60-l!VCi`jQ1Eapy074gdw{@xDE@o+z4YWMptKnL7<}Au
zd};&pbny68G`zhiegjls^|g200p^0zUuN1$&q>@R^9#OJX&kBoGSo_;F?hUAU@1_Q
z3zSY%B<smGw19XPw3kjvqtaTVoY5$k?+`bOwc_R-%N1HiZbTzyuURhFt#1G3dP%r$
zn0)BXLz5e%jqAT@U#*kN&7fDyGar+&X?Rc^G|Qo4`PKK_bM<lslnxpN{pzJVjqp+;
zt^dfoeKL-CoV?xpBeElXu5stm)q26mOW!|{8+>E<#&FCg>NFWeCn~Z3GVVOVnL8sH
zWT?;bZZLw0oFLq0Pver~r;DkPJ}gPEC(=qD@i*v}>CJ9RPi6j2<_D3We1SQW-vrJO
ziP4{!{2x4xBLsdXLHC{kT0X?r!+E(&E7H48>&+oH6eO}I=`60;7!8p<UA%O%u7tEx
z3P*X4zfQZeYvcap;#xo+-)u}d45!&HEXR01AYTUX&UmYZ9M&A=prY8*nu~A2WS+z~
zM7SaVkv)Pi4E&hQg6ualymVkJ2PBljg2DY7@u^R=MuX<&_f&w_BsE5GA-ndcpNb#e
ztW_v^%}Zd}>l`_tQ~_6E^rMuu@BIW!)c_+p&I8qZH){+=&CS5|=}*_PK&d2qx!1+J
zUefSN1^x2qn8>`}&M}G!gbd|`q=@JeW7r}d!C_P`kK3)+8+2nB1kyL~(|C{&cp;EZ
z1_ZeRz025%sO&}d1tQC#cd20WvjrZcB{OggwJjIQO2EYWWicC(qR^CnR(uw$hy7?k
z#vCl^LulOY=VSEc!`lNJ0=w!42J3bP0`%o*V<+C&6=0ggXVVyS7GG71&&F5P;_Knn
z!`lMrqQL=l-i83ZKY%Vm8#@CVMzo8h>yJ)L9w%N^3W}wZ<3^}TCWVm^sq_f$)T(hT
z3a5$P!bZtqV&$PFM7w;@R<e*=6%OTW^kNO6UX{+IcNfyEqHz+Hh(5+%NEP8&>T-|=
zZO0MczC6t^eT*+j;lwJFT&^Be=s_Y?!W--$!MC7S?x61uU@Iwa)TLA~83?#Q(rgx!
zZZel4IT$^I!o5w%+G{f5f|yp(;2{!X%#B05QYC(em_j!dQ+5M-q?ppG1~m!=O9|TH
zJEplsbYGBk1p_dtN@<P4NLj#NAPay{UKSYh86JUaGqZc;A2Q+qmWkFDzQr%#+KeoK
z&XG>OS)eZ|e4qJoUxr3@Q|6soI2?FRAQVXZDQE-8kUHtc#=%{8V{Kh8ctdLt-#2Kq
z2H-P@$DvysN)OS=Wkp3d7IhUZgM%Xg!XCV_wzm%aOoK1cYValL1at%RZHhy%cNx0k
z#-gHSy(jzbZ8(ND6I;p2Tv_I%IFJko<3?t?2~2+aGpQk<`2g=wYeJ*CeJ?;tM5weF
zpGR5_ohPscSXNk)d^rL*A6k(ebc%sj%StAScq{}l=9siK272ua(2HKmpfgmm<JWu6
zsPicAQR+CEnXc#$-+M)gT5X5H5zX}|Iv<S$z1T%E7;0V7d)}I+$3IZh3M*K-qqb_W
z%)r9bh{no~{}8=do^lc&3NQczn!G_Kx^M&?7f#l|i8Ufcy9>ey#{?OIR5A%>r~m5&
zg*5W_Ng$$hHe4}kO3rgOVN|Qi3?_&4(V%7+JyMKrCFWe-BBq2kK}=bALkUcl+?a{w
z)X)Sjp|FYQ<vy2~a5zB9<@2T8BLY81jbEe6Bn=mtLE`jfGL)o~B?jJtW{EZdBrMxc
zUMBD(pU>w4DThN$xWqsG@G_BDWXb0nvw+i<DS_|rlb-eGLjUKe&V5HgQyOsFra!02
zNKCGvUnwjTkw58wp)&QN5y@hf>428=d8trNqz=Y&t1*f&f+L}uxJX$H^dSl1sGu^7
zw2BSQ1V@T##STXLH6N{3v5ZErI?xLcJ`?Y3U4a{@4bttnP%GQP8AEHAsT4B0oHlD1
zMrX7+T-sgF*MK+m3MFl29io+{!HYU1Ay^@=5_e8`@j~A3Dl+LAR-;k>?XcQ}>1t#w
z%Q6tK?+cpE8lipyuic{M-vE>aJzsMeyJP{)&@@aAsMXpn_CSYPts7A3w(p}EbRmE&
z$7S?!dKk4wYd&&zq$OWMa>33&oT7z!$0U~LY-+F}YssO9QImIQc|mi=3S83_-~RIH
zLr6tfr_gAWY*}yR{60`klEq#HxAWRN(TluVyau0n2z9Xw1<f8U|G@))*(tXvFH`}j
zV2k`cGv4O4do+T0@#7M>GoWfuQ1lx}e^@DTx#vVo9J$zv!JRA<B&cF+Z>2+FId;zF
zY)zO4JX4Jft0smIqTl%4VP1QwMrb>~tHZ_`bn7_1P60RX4g}_$?+kR+#zK{|s@h7!
zHp8>G37Si_eEo*@CSGPx&ynl28rl+XSy;B>979=PdblcD*BhS{u!9vhy>EXAx5h(?
zipq!;J?l~>gethoE?+RasK#4rG3j}qqoTCFaa!sA*PM@Gxa@~zUQd}`#v2dn0Ij5X
zU$JFDhrJ@?@Cm%pQWb2OxG3|^cB6OJl9j==fHP-UlS5P}7a$zZ2{6H|9G*@0E(c}{
z_Rj3)wf9=yy#F5H*DB?v-{=+MD;UpXVDBAfaXzuB-B$mHYjDwM^8I~UWq1H-gJo;A
z{DH@ekBB$xd0q`Ry`<1ws1X))^ICLZv!J;cpNm$T=kf%&5Q!Ruvz_wzGK2;hD3V-v
zlSGahj5LkZSAndfaW#_dW~O|HGs@u72T`XWd5FL*E&nL~QZ85WzZR5l3jt**_e;6y
zmj<OmF8=Oq(&zpHywVa?1x(|$>omfAUfZV;V4GgA=f#D=h1Nv|aF?Lh8q&`Qnm#Q*
zU(l@6^5PR3LGpRAlHO5AbamYEF=tF+$#R`B|LNq`q*09#cK74Vt$wg6{k-@f_?{Rn
zIYDzz)-9d&RYS+~^t$IS5EI}Iao2yJJvw*|?YJJ5eY=(~;9-(eY9#I0&}e%W>KTGh
zFdHqkF(K};cp@Pm-hq@LX@{gE(xk`GK3ZbcrgNpukB4;jy?BHXOEX933=SOj&%-%~
zrvm`C`Na3!;Ev0ElfmIxcg{h3HhILi36A+&cX8IkR_@2I--DJa0~~w}*XJS6Rd{jc
zVpgft@3XT@z`8Ry>n<y|5}di5weQm_mF&_@_>^nBkD@VSJ}5`(GlQAV9!w^aX{1Vv
zZ=nse>qs)`M!htBqty!g(63er`-rS9S(d>fokndHZv=f-=~u1MiT7qs!1`_735xjy
zwPS>uN^phDm;gr0a3){W8#4I}Ui2BokrZTz1bqe^lxV4mM<b?K1pPQ^x;D&s3D9Uw
ziwtj|sR3=Y$e647>$h*yaFJQtF6_R!tL$ces_?vPQ;l3NQ)*^xdNbj<xx3`%+2{2&
zzwWG<(zK{%wp`v2?5Lg?u67DjZ2qR2&hm*I+vshpXbk#!I{CzmqC=NY**Lk%%$zt5
zhN%<a$p|<IfUDy!0EWMX-wboE#xv5l`Rn{PwG4_s0W_=D+r44%ohRb4C}jYMFQe%}
zuC=(r67~hbkI3XiV!ytHmGS}$reuaPYr&0LZTjB266nssK)8`Q_>NX9_G!)TlDgwV
zSyTs!*Ccn}67=0n#cgWw7%;g0$UJPLSvU<``RHx-D0*gzS=&)ql)C4~gPRz=&iJ)v
zT;%k#`O;!ss<b<&n*r^3t62W@qB`xAVYGKY)kbxr8bvTgl8-}^5s<K!vg(sG=@6}o
z#e`q6R)DD-aO4YSa{x&AFyRxU0%mFm`M3yP3K4<1=ciNEm=cglf2|aMg`*?H6t={r
zNc;*8b?Hby1vaY{m^@C+e{v3ti&x8ZDy_ow-5cW2^s0YVO&33${PCS1Gkt%m(lbWj
zRUda|fu8h&ktOgN#|HU}KV1S1yh1?(dh6d7r@xf*DhS~Y`l9~+0|)y1;h}WD<ohYC
zcP*}WAYX6xr1b`)YDS;39ezN)ZyQlN;iRpQtM-45S8H)NUp?l+F-@RE^4AX3f4v!O
zG_04^Q=J$mE^vxhJknx7|A*UfX#6TO?n27~R`rvlBPYp*C=pJi$i@kZY@pxX@oHTF
zf&b6btV+{ew*I<&{YTd_aEezy%7Sv5ZDvFTMECfu0S8Cbc|>dE+sU1)%9in(0&F>b
z1CTz?zLM$l?KlcJK%D%<bAR$aA24cZ!g>*x<j}Ye^D|~J+wlj0K?;zJfCDZtFALkY
zsIj)Cv!iBm`u3Al`b&FV*Y-&*VJjcf=>x%eYxK}Gr=tIo181Ipms2di2S85Fw{)k@
z|Dd&h+Ljry1>@B@-m>G&?rOc9+srYV?F%hMSFc%r@EKUOWea$iv$A@%hHqH#bb1Rl
zrtWbP0iCb=smHld)e}zD96zA$uNBtsH>YR_CR6$2_m5Zm;nCG(BjdJ578^2=vBNIQ
zzI7>JW3=6m#Ylo?&P+JfWE{p{286ztxQz+yAckCp5^Ar>h{@3)hs{e=(C!EX9QNQ~
z&@K`mFL2v~%wSwchYbc@NYRkE*gwP2cI(2K=lkqIzs=fL-QnTw3I(SsG79!^XO%~%
z0D{2NS~&wuv$hbg4Z0_E<dQbf?}F9}_l)Mc=K8?Eq#4lVu$Kc6u)~XN0SLDw7JB%m
zKv}4w$tajyH6=|>Yj8$|S7tS8w@^9$_yox-b7Zg<b1!eS1|Kk+h&Bu@I0%M77Gn}*
zDA52xK)$~@XPN}JM<b27<j5aqJXu4mkAuy##J@9gEzR>rpwM}$I>UCsSft_<3On!V
zsP41c{6V|#{Fw`HZ8Oa9Uz})AgmeZ&n5MHWk^Y<12BbY6YF;#Ji`HnB1xjWHt<I*B
z8kb2hHdTbm0!_SUVPXq}0UNx?9sr=+?r^~wlLi9ysNrU~G17e2mZ2biq;jemwZ>}d
zLh1_YcIpx8*M#2%N5f+)Sp>tU1(3jq{zX~zmvQ1nGUj^&n~4!Zr(p3BTNzBoEL#p5
z5J})`G4Pp;=<M29E#`K@i5WGZmeBKg+ysF%190gk{S1lsT*yZNFHI3l_)226khmln
z?l9PfAyW=trW|7ocsCRq^m;?_Q*CYO=enlN0zYjJ1w0B_8vt6P8MJchQlF>2-R&<`
zbH^dAc0_B7O~&H24%5Y6s|<)2B@)miDBH>}6F(QfxU6EL(r8ppEZ+x%`^wRJTC-$&
zBsxp(=6tGYz+)<|jyOyvN2I#g^muzafvj$qsnFfQw}l3tPj9Qy59uH9Mk1d~78iqi
zChrojDXA>d2Z2}orxog4z`E&Rt*NZk55Bmgq|Ee$qF8I@OM;HZiy9rlU{S-2i4i+c
zn^bh&t&zyBwQ2gNb1NEIosMm+Sa{^&dF4%by{UX2-3Us4^Bc=D%ewgQ&)MBj91IpW
zkcFcOY!UzF(nBlIi+>LAj!GaOX~RWd2O2N`hQ`Z$|5!?`qIOdIs9UIqh@Os-2+_M{
zk<e3H6Nq5UTtmb&&TGlOyeR4&QS$NvQ6K3r%^))7#l|tyj~8v$5GG(w<|bVP!-At;
z;U+x<L}+w(43HcVvVBkLXSnYL#_6H-iy@2IYzcwxB};}IHi*x!Uk%)g7dst14HnDQ
z;R!KtL}7^4lrLUfIU#0HfbOMeSPMVu2(@>Fii$&%rXocJrUw@+fUnxMiyEFv+n;J!
ztg)l@#wX#&WPRAa_T1Ilsz6cy6!1h*U{ZUqs3_PzDNqDvFOAlOHS(o^<{eJp|3kYO
zRGK@&;f_N+J?Y<pFU3pBOtc$p6wj@;2AX@G>$KO!-c7Hc5RW_NY9dPiq=oBd2O^Qc
z>?3FqbvP9Cuiuz7>5a+hg`aI}?2?&GvaZH~FY!8OG;(O2(TbbJe*oRI{p;q5-%oyM
z4!Szn^-veSNw=tpw*;&auwT5!1I^`NrxZhp`GfyW2{^+a$RrIqF4Tmw3Ny9}o3ch3
z5CeE8oUi=W5&X(zRHgyAL#<L+zACZPFQ`=MuR)hesWg98W)+X{5ZFThFw<*zaa!1m
zxe3rK)afe0YQ1TA2}s{$H0UbfS#J8O$~?~k9-9Qhi-(a+vAqX-5KOepf}^nFfb0Qg
zK(=BbfW&ai80X6_lj|v7&dGN^t5C@GPrC#<&KZ906vQ=1-8Q<P;yJlO90oVZ|2)D-
zO@sHnDz)JqApTgZ)%fW-YF|18MUM|D*x)??|DeBYEG`Wt;g=IU32LN!6Znl1iKx_<
zF_#C(_ht;b>J%xL*W=Oaj9N%RC)DZm{Zsxjyz4JhHt4lFnAxUxXSSD4Gk}DV=Y#2F
zke4e#;!tYi-4i=k%WXFK>duLGZydQvNqAMV6uY1JM=_hT3w_#*37A4$6zTowf83-{
zBc=OG@qW?FR)}V#Q(LYD3jhEM({sQAkr#i$hC#Pz5$^*F!KdO+M4oOIUlsofTE&kx
zihm~D@_~)Lpa?U+i61fVh<_Dd16uK);y=V+fns`>_$%?BU;@Fpr`TO2?oO90jSole
zvQc2*Or8)Xqx2XwfC~sL`U9K-av&gZG(DJZrXK^xuk(R(>A~T5U`ms2?S>D8((_+{
zXUt3=29JZQE)X}vwsWsP_tG1{4Pa@y-G|CEls*Le7fn1g5xnu_!6(62;*GmOA9y+a
z<a{{w)ASTOe7e9FW6EI3QD`K=!L68%9F0G|j9ftFB*%OjrxY6)A1zIFUusOgxBEHq
z6XTUWJ5y=%iyu9nyzueIFHC~hONxI|Tta?+vTe@s{d2Z$o5P$vXWLouveu4WZ(RU%
zsgBn4Id-29Jo?>34}JF#y!P&*($b>4(M4b6Pv2JXz32!=#^^YdNG^*soB2Vgl%yUE
zZoc5*3odvVK1>$u2!5d9d-1-^|HAJQqFDj+j0+w%q5zS&XG91T^?UIw80!(EVzj3Z
zD#7v5r~?PZSBBuD>6wF|dc0iUF7_h!M@UY`nTqYyI&5Q+g>cSJ41FwN{2ifB27NvP
zlEnNhl0I=jGLpgsl2?FaGaAhctpJG;P9PIx1j8VJb~E@0=9`H7SsYVASIM_WL&Zfw
ze`kD?_O~lrr_;=}%a)$^k#TB8wfMgHMR_>EJD0_qK6<Y;x@>`5r>XESc=fq;;VIn-
zqs=YjKY;NelT81(eLh=J?im(u{_dd8q+vOz@R{riy4YLickVn2&IhHpH0c4nyLE=!
z(A{m|)s2P?TPljqowPJ5m){7_bNCeUs%lQ@wHNsmTyc?H?i=RqYuY=F6RK!~+~|$^
zdY{!RuDed=t)rj1N3=R?iwwJhjsbOXsiRg=^ZfY_PPJD$ojO&R4=fDNFt!j3Rq0*H
z$tc=@bX~%p9VAr8u{cQ$Cu#2jZXYbwVxb;Mx<YL%7(xS;4iJt++^{jsMZn59sjZzf
z+RtDefFC1pb#?p8L3wE2H2I>v{WOeMPQLmHV|%FLmisD#?Iumw>-_B-9)C@piq+jA
z_T8yw?YgSlzJJu~)Lp7Dln=Zk{$p=Xusp)Z&3+k>%XrQDM*;n~)#YL)fRYhjvYX4p
zX5)I^5^HWdOTDbUdXdr94H`^#8EZ7kIGa(ha!6ojIa`|MLN=zqU#7mfZjK|oN|@LW
ze-|~!J*^J4S7)5y?6~3uKU-_`s=ACtOEt!z38+BLsPP?89XOu~HLDl<+3-*vrjdjb
zMg57O^Lb1jgVBjvkbbz!^6=umBLlNM_fFl?F~P_Jj`?peQ+!0@Zl5sg)h~Q40M;!#
z=bQ%Ue%roq`KE=HEGI4+P9JmDMx6i_`p+eX+K|jA3&W_v6UBiN9O~sr(8AAZ0b_iO
z11%Me{#u(7fD_bFIbdzkH66Rl7v8dJ(xu?e!uFf~q#0OBN-f~3UxUfYiUoZOY<G)2
z_1pR<LNI};8tG%CPb6R()g2?=n8#O@;Wv7Xc&AdMRf@N1<O*X3YY!<ydNHX~f}~y$
z7~%^!o{iO@V46+gduHN6a*)IEOuiLN=k8<DYd{aaJ6NS*1mQRdjAn*{dVp>&CiNL!
zC_r-*ohJ9pBFJa)<1G>p1xMi$j4Biy8u^TsT2g}yPZcdoW$r2Ydq*PAV@8@3F2bl%
z!9A!cZr92StAH9P7w5hiwP%oI5N6aQECl<!G>m4XSS$+@O-kY*1zGM^iAc|4G_#vS
z^DatOFI_OPdCr{3jn`khdEmjR>-)TwE7wlh(NkMH+c$B)_+hcLH5LoB)6=It3}`e%
zPu#ilS-0EcMH}otKRS58>GXOh`V;Mup3N8hmN~C^`t;TquaaHAaYHGsrx|rFPM+X+
zb4W8FtjhrdVM59*;r;0a_)nG`-i|}2AfMje11sVGN}ma%=^evg?u6IVXAOT0ZzKGa
z1hbXhMPe9>kc2lA=@t}K6C?8zlUcITEGBhs2?mlRCpKd>k|^yV;(NnMi#Tc>M~J#`
zcmPhi=E#?k`7mnC;C;8n;x>b$ZnN2K89rXt)VQFjiJ6_KoZhscX@66BSreERPQagR
zNDi+`Zk)oYHQdw{Z?2fiY1AAzgpW6sl{YcP7JMJ+|Eo=9Vt08{Q#traS(A`n8&3Qc
zZ~ayJO@!gi;QIJ;+qXX#-=pDV>b+%Ud(|>dlfFKCRe570nnzWrExspw6*|fbIA8>R
zPz|PluLw4Y57QylSY$yCRSE?0xWmct_}xM`fglo$Tj*ddHcEgHHb0<)SiU4PT`-n0
zQ{X`!jrwt<cB9=gi_sTG-53+!%P@Zs*0?y5SY)X&%Sa+9nPO=?_S1Mu01`h4nk9nL
zjDV(3oRp!(mJlrFBB7NGiDrBXeh)ezlO$Vmu@jnNXo5lG6}p(@#N(S0zi13kL6H_D
z$K&#t%$6EXhEz&iBSxC3LbYhhmyrZ6V=Jh|s-RDc)DZMYGrmDh3^*Y!3?LvUG=Tv^
zgJei*2z-Cs1VrGDk^-W;Icd&_?}-bDty#pz6~qULbqm!xF3pY+0t>@s&NbtQ(B!tL
zg>a*0Zk%anCkt;-DHv8@moYk}RZfeyFbqr694BK841f?odVZWiVk{D86+k)7XZ0-f
zs6s9sP$^8jMgz27o0(yZs*tWxCYPCQfg+`fM>2)MX4Y@ufuht#18<R|7y^ZXQ_2_>
zX8^!xH5dUfE94=dVU=35(qXQO!!n1PRj626p*D6ZD(toxniTZ5GDFboahNp_%48}|
zLl@1CnN4M88aRtJyk)i=0-4<8W}u8=8Go29VT|`G^t8(<FVluYj7A1%qcVKX#T6En
z8lp$aOtb|;12pUWpnX>Q4q7EsKw3%DDjNI<Dhx7K!O9@5E#noc$CPSX%R#7R<aMlu
z)+rP$4S^Cej9e=RdM%6_&5*NN0`{OhxT46gHpp9)UT4JuVTQ3{ia%0Rd{;t9_{*)V
z(hC3@zLnYq2B*~&bw|7k4G+~U1H3ftHD2ViuAXQqFQ<8<^4tj>l_~}ee7uvB2h2g^
zSz0v%Yr8@dqy7H+Ni32PR>c?Vkf@<jIvg=C@8A_$Xb$pvqoAx?QqtJm8J(aCxji0Q
z3$!}B-odN^0+6Aq03EH;$i!|SH?XW+34vZo%kk@m;?2BOXLIO_m0qr#op6@X*m~!-
z63A4Z7Y;SKcr|G0cKXexiC#JF1fZrC&}}wB$1w@kSz=Pq@?AOw&2aT?0Mxs56)s4t
z6rflzJ3*PB(P`BdptZAdi%tcg0jL!Qg;s`2Ld#r?z#!?9VRRM%)OtauU=)yL85zw1
zZIfNCYH=xO&el4iqgZxtJ-=3NHMv@giUhz;T%&d~mP-}7a0#tztPWc{<a#+|6<n=e
zH#I1ig>CJYVjygDo7OM3^8vStE;HC6RIos2{I#5;8Cogh0My4Bzz?YmasXriFb<mi
z9LnTS2Q(TPqhVz<YBs<edtPm`n9T;GhG&Fn4n4;!ip{7SqnA|VwgJ$jLETzyP+1nL
z^b-Ppg_=?FUT>$z$kG~Jnarv-t8^V&gF<GL%iLO8R#7`KWcWqxG_S&{Hy2~3@U^iH
z<JGkTzg=>Exd{|I$_{s|*s*zi<7*46r<6eG4WLGs3+iGvpq&?=ymR6d)>G}Xp=#Mw
zs%cZyu87m2(&cgCl9ZNmBN;kO)le<e0vxFm2+}_6NXOh<bTGtt@C<E{sD{x<f`$n<
z8|3f^2fSR2#dAB_V1!@@Uq!}}7Et44EU^($`DH61)W@#db(v51)MtB}O>Xh`;vul8
ztLEDM=LZ7}zwVq1_NUw+OuzTW?-rJBx^DO%XhMgxpZ;#f>^)m2oj0XP_Yr*%D2(mX
zcTTbiP(k}=PVQ)mmOGW_jncvV_)3{+=EAFHst&<xt6P?H+6z8hy!e)$4y^{Te|+oi
ziT}Let0vc1A5Z@qeI@|c+$G%qrhQVZ$s~F|c?76!iTci>Xqn7{x)+T!0~S6%9*$wA
z{aUCVtb2s%Du8*JBQ=--H<n>JhB(L61qg3F&PAoOzKIqn5muo;KPGsKOJ;hE;>KXE
z4$jP6A8J@Mv%1e&RL1KLly{W)E9_PE0}u9gBsaAOr!8nYxWw%4ni!c=T~<?E6Z!A^
zIxpGO1~z<ncz55-&a1`a&ur3nWi|kdH^93!b7K`&m6hZ4db?q!)#J4$D&vd8uGUSR
z%}bjCTEAIqED1&2m6h(M%4K^3leZr@{9%`V(=&j*x^rgVZfQe2jyH%cs{-i_FOvL_
zR;q(!F=c%Waf0hzLnx4g1)jrLT&Bcf8YE~IU?R92>?j?x1NxHyTVzVtSzI#Uvp79p
znVqy%!?;Z1pRk1&EaAN$>t?nvGMU*?;}QR%QOLy}bEi5!qnkcwMZ$bL(=wBp^=pgQ
zYdroadO)vTSFGFJY(m$T6$cz&c8WX2-x<uN3bRqE5FIv7VV=S6j<4wNAO6e$>cO6o
zHo8oFd0<TR<7u!#v9FiN%U~$u1<h>@2JOd)n}bEaDTeq^hbcmO4vBY^_(*AO{-j`z
zLy)D|A%fm0d3Hjy&m@>hY|sc&liIit_0buYGm=k@<oIkJ4NKLPM2i1f`K=;oPql>y
z!)+;hQ1NZ$UyCCpb$UQ`t^>(+oq*Ddy?cJPXV1^TP)S`mn7>zCqvP#C@#}C~TNvnr
zc3uZ=*(*L!URP3V1<4H?#H5w(#TV?6%F5uf21s;kM$q-0WGS^-4(E)j>#9q%Eo&ox
zXnmjyCc6g2AyOJTAxivmy~6{fB(I4R@RB|t60AHh*flT!Ue1>zYxDBpnD!QI7Ra)}
zK_pU{E&f8|4hwqphT^J{1<h7}Q={M7yr48(Y|t}{Mh!5Zfp^W*dR=xTt(24$d4b*4
zJI#F6IAcTw(k<R(PoRF(iS4F@=nM@AH7y{3h83JU77CEOWtN2627)*&63dwJ0ExS0
z<AlhbVBxSNxYc52Q%i4o>$A6RSt>2SCPpv5r_pJ}_a0Nam5+(<X>}U$Jw3xJ9(zo|
zGJ4=g2Z8@Fg;((y@S}skpE(Fs`P-mHRLAy;ujrLZS<iPG&38RArBV-SdRd)8{oQvO
zJvs_%q@!xJbX0r=9o1{T`%azF`+mV*Nb#tLQUN@!;bBciM!-moKS0=A372KePsC)x
z77mEJ%L$k-V|7o6FFe-w`x9#)_+s|~G+_pN#EXY+#nh}@p9B0&6$ak3VClhQ*PVS<
zsY}a!ifR*kB6W9@_>;GHfAPTD^MCW=zs`FF6y16gu)MTW21`p_vtHeL-LZoa-lZ*(
zFv4W1jGwqX6BS4dot`nV@niBu5(S79aBblijE)>5M`V~k>c<j{9yLtRGKgmr{5X$g
zL9j5~CkAD`Y>H~b5mpr8Mc^!EBk2ZcTtuIRHw>$?l!dJzLzd783?ck|xCqit251L(
zaB{w^H)tPfe@zhh82?+=m}px$AsJcI*{Ib$X)Lk|0&RGqL4wRUA_QxNBlL_TLTyku
zGGrGgr;|Si%Adm}wZR8=ye`xVg76%xFLm27$eJS*(r8~b>G`PfuUiIj#e&j>(rv^)
zLF(e4{~UebCr(g++sRC!E+KJvGD(lKL|hO_0}v^CtSpFTM;eX$79$~#z(yau2Ps(u
zfd)w}c$UP!PP!)E!Vp9TqHf{7f^-@qK~=#PI)H6?NH0P12($!{4#VxV9I=+pQX5=`
z1eO`DtU*eNyexQvvL=j1XIK41E3LE&I>0du@7p@%(B|b<o6@(j@5&|_&FIPiuQs!+
zUT&<_>5F6KB}E!2;}uF4YB`y$Ny8gV(VulkjSeK=Bbi=i(8_slSxca)ia}C2lo^%4
z9jcMh-z7eFM_0Q_OH9qE5PO!ex}ej>utv4ov|v(|9I#g3q;j22#tJl3I<ehqRhC>e
z2xM34&8$p7@+L#8Of?&diklWy7qLL@Z|LhRY162^3TPHob_mq0!R2YFT^v-kc&l6r
z$k@x5w)CB=)X_9R{~@bWNIbju%f4l&Q%W-GRZ;V)_0)yvi_Gc7ct$3xNCCBEu`^M#
z2ExFPbUFMn#$)~f(tFX!h;vqXw22i$Ck_U~&TjPS66F#)K?Zy?hV)BGsSJ>PWLF3)
zw~~que}rACvrJ~bW6n0YLZdC_3{I`{@yh?&v|&zF)$9G6Rv;~LP&{$)1M$yV#UKC&
zKL7y`oOa+>Vp{xI{O`ARU!J@VES@&8l96e3GTG&S3|Ce{R;yIkFYDMg&nC#rEvR6|
zMXlB{hP7Lp!2E@gkfJ7Lmlye4S{__jG(qhuI{%-;-pM+x-Q%6)cHE+Iu&hes(z2?a
zwY`4t(<_!Qa}+<`)O+1zt>ue@(&DO)tM~M^wC{Lw<5s{V@4IAL;u@_QbpzPg+`3hx
zRiPf$upX}HIlm4)9hITASA(8zEoC*cd(&GTcD}~Z{aDAOC@*u>Rmtqr3+0O~l!6j4
z*E->bMY^^V+dLtM361?g&!NH6U}kvc%m<!(_JRGs@%nxv-jaUl@q2)ui9Y^P`cdG&
z$J^7h@Vf&CzGIt3$FO+Ds<(ml=U~zw(`Di(Z?6J}hr!>Re-wY7!A+*v^N_5z0oz_^
zEUwBZj-Y3t@mLG7`v9QND~8uuyw18nEE;B!=Fe!6nuCTYY#Y(yPg#an+4J0sdiqxN
z%x=;fHj9T}6YO^32q<6cpW3r%<$}4MEze)NrPUU-bLJ@>E4mjXDrJ)|T)Ch*;xV&~
zTJD%qSE~(1I?rtKvoa$u=a7!1t%@yLaZv{hHP4zqZ$_iRV5yN=r+4kxb`|((*S2Oi
zt##Uz%8$hFfjwvgZynY0a!tjwU3069zF9LW_6!0V(uU%?X<H{38HCct*4ApB{=80^
zaniJb%~y8VI=hxEnmakB)3HnKoTW9|;DVM}7j`#0dG!6z*Ive18pA<YjYJm{l3)JL
zQY1p#Nb;75lm(<%cwq7v@L#}`Wiw*_zI9H$IGp}!&Q|7+$IG&RTj$WT=4=Iyw)s26
ze*w*o`E6kG3F-uxihizWZ=bhgM}e$qL()=pChulk3Q+S&lBSqsh6FTAP$`js-gl}5
zDtOg6T%Zq}Dv@f0T%0NENG8)lB2)gPWyO4-xPW;YQ_KQ7c*?>KWr_$|F{`M=W-6XI
zWogIA@RH3mUrcbij3z2*HyWgLE`t&0rk*14D}`g0)R}ZFb#VB%KOoPFL*KqDpWn`(
z1Z_W)&R%vZ%>7K(I&hy7dOs68z8uNrCMt$AEQv^lC9=2$&#qJi3#Jw_8qpFUSDX-Y
zVo!tMF?nznl|Y|Z+aSL7^IOGlZ+ZQG!+8e*_w=r}wnIn52}+|cF?=PKSOat~lxr8n
z+Ispr0^lBTy&n9o#PAVV{?em=xdkY0eH@gv?1_DF@zdh>yWh8ONpe2$zQ;<d^!7+=
zPurw3IPrsI(kIrB(6bu}GEgiO#8!q_M#_-<q1eKSZKNh_#>7TVNKC547l{6i@#HZd
z>jSly8YZ;2)a$$2Iku|2sG{6btWePwmAcANKRI@HiC$2f+N%vJG+G$^ep6X<`8@BQ
z9ew*odg|ys^Q$HrX`w7WznTlrs9ieC<PKZsOk8KY$QMY+ktB6p5hwRU+5(ID(zqsk
z<-y1*yV_)$Ie0mUfZzyE9LRA|U|re>8A+wf1pu{zXyJM`O$v!X#Yl!^P1zMgjLIBj
zlFx`oe>te--=<|sg~sw}cFAkePOw8~w}?A3i=%)cdtvIA;?ZY#EnL+GWJ-O~BA>E6
zw{{F`sE==Bjd<(a<=GX{rUAxZ;7HtjZniIj2yM!w0ZEm~4Qe^>+7Hav7A0m$agZp|
zy;6=y?`gBQ$DB{@bgFFbOx~&-V{3*;q(qnG#fwS`br?w0!Z-#V4a*)P31vcH;%Jhz
z;7nYPjPoKv7id8_pd&T3Pr$Ibz{x~dPY`ZA>-HoX8n}j;GaEQTlStlv7PGkQBK_j?
zDl5-htiPyC7LCs7=r}%~{`TFk>IWP};*foDW$*Ih+iojf-Wy(I2X01NRnzGQ&krlM
zfx$$g%44-bgVg|SR!>zT!I^1Yq{3ej(a~mZ*gxQRPPlG@_{U(`1gjNCZGzXp5O@to
za55T?&D531d}kQzqnpGJ<BuL|o02yQDX96?ENMb3p!2JtOqeOsR`aVF;5pO~LOccn
zG|PU~GI#ldb=<ths+qdD_(EJhuc>N=E`C$7sd-Mk;@0)I+RaVf@rv7`(t#L=#pLtx
z$<aGa=BD{g6}PRw%Q`#^V(Y~h;CFMH&+s(fW3o3ch*jR*f0xyQSAO*W(e@sIaTM1d
z@XqY+?e*U8bf@d5E?rgEsaVbGa+RChd++_+00RbW+yH|GnBI*s7z`0L2|Y0+fj<E!
zfg}(Jz1Y^RznR&SEF1ENeE;uL*`2mKv%6E?oA=)DMI{{-=-MbKiHSS$U80B0rt;CT
zyuP`8xJW$r*0`v>EU!rw<6kHi^JnLRviX<p`(zRSZkOnq08QGNd<jUqlMkeO>|h5@
z<5`G8m2BKs35F}9(5Ia)_lwbKH8s=ne^nsQmKF!;M6fuXHP9a{uJ9E+7NG4)yUuLT
z8_YTsqJhj)b+OLMxzpg7M{nHZ9Wf$vZKl{S=3B6XgPB>S#X(=YC3Be->LeP(xv)}n
z(!mE!?bM)5lGp~Ys5duIozzrnDMjhfO6Z3Kv63c2B)>}7AHiIhZYas^_r$!|jkaKd
ziMR$<XEc$u6n$IB>0;3cmC2wbA7T(3KU%h8RHiqE;(qLx1I3M-Yr*0d{>_S6mDt9#
z@So&o>y$d(Ya=(yH6mIi?^ts;|Ic(9mnoeKx?j2;$mUAp%?u+KX;E*k;zgeUX494>
zbLsU{-hAj^WdpZ?1)$}NYp(f%KgRFnkKqs)4SGPuM^{|&5&t}YC;vPS!Q}1x2Xs@w
z3Lw@6%I!Uh^Auf5v(S|Rq(B1XTAdPz`6qZWofu5*dum>9XIyU9*;Ed>mz{qqwN}LD
zW-?t5KL0!Z@GN-eJ@d0+<f4jONMp`Ce#J+i;*vHD`D4QGUyIQjfQI#Z@fh*O4I;*%
zXG|KP^TqvvC}UzO`7b`?ul~bt!K8QI;Xek^Pv{4HsjshJeJe1$irs`J^+!^BuKxar
z^?v{9YY+b2!FKRf{JLe`^%?iOHVo>36W>pA%1;$yWB`LF-Gx0-;3B$bL;n}B-Pplk
znC_?hlUeq&QhQbspfxEu_*Z7nI)gIGL@4kB3Wz8^DIj#5r&6fm3;zOKDE2Cs9Q4<m
zlnA!vnC{RSNk@t6SYs%j_Ic&QR<Q;>r%UT#qFg-L#^Sy~-&&%7Ynl7`Kk!HRKitn~
zVWlx*WIBxJ`WQKrT9H#MswypoQi-ZxC6U6?(rVdQ{!ycm=|$O0FFeV=Fk;mR^asix
z<2b0!7xRe6eBFK1OmEW&Ki{sDp&uo9#6P0R|Hk?`;(Rga1%U5E&%f||lD%HgjR86=
z?9llsh-D*)UDKK>={OD+VZb?hf}%1fE1?MT=O3O_8p^4w+VyO<Z+Fj{f>^Y;)SmFP
zN%z3oRE10ipC18U1i`CRs>Pq7mQ{Rw{cB^D%E0u}%QQdWZ@Bn;lG!c7SRaLGtWv&6
zz6gtcl{9t%gM|llgjjZSA|U}0Ikb!OV1#3#3|1RP#GRka#fT}#Y<xUDS)*Z1zpYdS
z^d;(ATJ4I?Ufdlk7&(1rxOD!6_)2%>yhL`VHD8}oF+Sq!v_zMHTX$|B*-}(LqA1Zb
zAyL%8|Eq8NN2T8J&D($`(`m>z?tP`Ps^zU0Ers3!Q@*?qLZ!EOQd#lDvMh}?GMPSD
zwqs*gz*ROgfA;LIh|5+C8^={$-P5?dp)BF{j;QTOwoT|-x4gTztg-XT{4Q-)byhHs
zd3JBtjj@`<kPjoSpV+q;5Ea->O{A7kYpGqsEF3~cZz#P&MI%1Fh$Aptguo4uhtE%2
z#>afRN?>A#9M1a#KAIs;<|(2-7>fWsVuG=t9aMq{dV^>ZL$f|XB+B$+G-V?3!XAS3
z>Ao7ln<9vsp{qKJOS-z3bb@_LI&qM$s*JEZw`}Bp_0YrouQqJi$rhGwpWI#j0~mK1
zV^e_%#!1Dk3m3MwECl?ED?r1?iLsNn^Plx35<Q7Cz2Ty5-u%k3?C+PXUcF=m|2CSY
z-d;h%h^lBr|JRm`tt|3wOMM{AG|HyG2j816GiJ(KPr{S1yttzSH30pTkkF*cIS!Y7
z?f;DG8auXY)Vu34e9oC=lefoj5rMmuD!MCFx$wqC3tF4`J<5Zn+u^nZZbNEHZSJ-?
zma(bvO;5gjqG@Dj=g6iLFF%O`uqwZya;$wWFOwNvvgy-hE~Bh9z19e8s1fna*;FaD
zfLej+cHwP7f+bB}7rfv`YS2aneKPveC3g@$*&ooE@NRL8=%;dc1B(`MX<Hu?J}}{s
z7kwQs{;uf0^l{Fh<f^X);M#;(%o(_%^#H8<Fwz`}G{f$U?CcCjcD5a(kPamAk^b0|
z+ZZnQA2{9pI%p^gH8zI4<*L6)H1w3yH+xIMjR6<8mpXr7KXraDzZ%~q0(NprBZtW?
zj^n~0(j1GS#0liij*M(D`{a&+tvgPh+(B>JadO}-WmO>DR5)J@Bt@b6h8c}nt{9X^
z`QI}ObDF}w3Y8^e+Fetp-Zjm(gWPEtJ>o#~07jdRr-9anRD}q1f}jSJ0oZ6-d8h(#
z0R!&K7pbmJ>sisa!tS>nSl-pS+@{yrz|Q^n)Kk9Vw&kGnQl9dJt+IW|;&%Qcz0Iay
zv#x8|(hh(K6T2?<!MaU)n_aiwYG2>6Y#DgqQce@k_qTINb`ohf!GIDPEx-wAaLa}o
z&9Sb*98+A#V*KT!$_E}fdJZ(AK<c4~2c8Glg2r=49~s#8JW8R9S7DW<)S-udICm6C
z`Lj7?WjS!ceP4ZZ{}rXT^4}djcjjRruPEie$}TI*9?nBzY!k|d-KGofUVnnuVEa=E
zK6BDG*bh!m+Ljnje)WOVuz%YmJ~Nfr#$;TqM2Y4o$||Oqzatt;g6h!_%YGlh2*OLP
z%K|(afL2}F5RU3F4hQ=6X;9kmaO10~PeJ2)aKme_z19T{sege+{t29LBh;gu2L1$S
zSkL@@APb&Ac}w|gQJDsK0ytiMmH+EN*X><Lgv6oXFl;3W!GSHrzLO}j6`~P5zYT`e
zX^?VG6UTNeki<Pg<VOs&u_c;gvu8*7Z_@#|>EVrfohd$c!>Mr1#=9Qb*j)SMsd&Xk
z+H{d(YhAKO1q>R{nVf*nsUjeMhHfjJB1&z~dR+(SqNsP^2^0iBT>O5eRMvS3_ZpgB
zwo)glm#NpO_o%;7|DZmmKBKTUS<FFWwqFUkeAa`tdmWq;7*W(O7|TTBm5^)_cm$h2
zCcPFS@&Ya4WHm4iaw|}jMkK)ktN@13C-#7*xRN%-^SMAi%*L)|5Q*=ARltB&i%M~o
zpht$4h|wZU;~SzD5h^)u;(!3Z9jJt1G&FIhE{sy61{J7+%u6G8PM=+!<C;)DqHygY
zZ*I9QkUzaiDq<v}T+YdAX%PT`6KiPC_RN3_(y%O!MxysXg=OXvyU4&hoNBX13H~mY
z8FV(5F^N=G?skdBqEQ_O;0|NKbp`PPX<ZK6Rhb*l)*GZ|d58|?c|ZlL;gljNCt*01
zRa>CkG(jD#tIB8)%QG{La^v?K?73MMx6&ia5pyuBec+g~I9EgGd>=Rwlh`s$7PxkO
zMS?$5xUdP_N_$Ge#SCX?ueS3edPUMax$cxxnnkY#5dTi03+h)-Z7iM_uW-bx)V@Ox
zoZL4RGOUF4aT#)l#b<O`tFl^9pOC7Z%|=B@g#lWllQ!L;XRJ$%YL$ter!*?03=4rG
zQ{yvgR7N_ewm#lh<aN_}vs$amZL(&nX{EyJOxP{KAe5>8z#7CV5n_fQ&43(-%bIWN
zmPqpK0FmocrWm{dQ=X<o*P@a{$K3H!4lR*NbTLjgFv^<ajO7=zc{187f25FqQw2Dc
zOw55CsNmoVy#~lr8@lD9A^^yph5Z688e{*aOo+angnc!zLRTY-uSBJvSe6o1b77Pb
zHAfD05~A-P1B9N#Dv?-9hIR4?Op&0EPW15fY3?c-LH&+&*?5}QWUgg(j%CeT60BIJ
z;(*vae_AMOYz`;S)#**q0&_-@RVmS!Xq8AQQ7d&an@1*=vQiW1k(%-xuH;s)t*L$7
zlKAo?5VmC0)|c#GwJy`zR^6cY6lB^nq8r}i|HZ$_|NZS`psZ_TSAkC1?5S{gbH!Uq
za_`SEct_WE#{(gq(&#Qi+?rmRX{Tw%W#i=A3zRCUJlCujb9$&?q>PA$Dy2#zV&tH}
zn3reo9tDD>r9l90nz<yR*HpJA0H|m}<f%J9Yt8FN_<#Ir!SY`Nd*ArGHY^>P$dHPC
z`k>i9zVjx3Mw?Ax9?`gJ(|y!%oG}MlC3~nfXg*LuB?t`KF30_`Dq!M7dXq6!Mbjok
zJs?`oNpl4-9}H54X#5)max#EL9B~t-1q<l76HB=qfW|Z>v699byec|S1uL<l6S|Pe
z?>peAeqgkENz>>x<3||ttK|n|KA&%n&vD?^XXFRvzB$dljDvj#Zav_r%eB?_tQp<1
zTt4bPdiI*p&C8Tyo~n}_AY~i}`_OMjqQKBH6V7U}=GV$mM)Mq!aqGd1+9$@ymbZ;w
z1K#L6=t$%n>U-9XZd{@s^I*07pv*VN@52S57T4H37uSe>9knOMs!+q$PHWZ|oZB~g
z?c@e~ZXGEyCtaZ<@xW-=a>mrULN@yG+H`x<S+#lAk+aqcG`N5dGJ+aMO`xVwv#EL1
zPU?2NH|8%OuJ{6if^8tJHyZcj=}@E>lxxv1F|fu8v1lw{Ssl^474&FnvY+e0rQ$?F
z84t0h0Pty8V4?$P+BE@IgFYdyf}r0B6eGD7vp;BX0S!?x2t)!Jvg;eyu%TR(Y0$uH
zfJv{<&Ee{p+S*Pt<D^9`hAm1>9Td+J2OJOr)@m|qr3?`HWTgc&ptMFNu`mpzEq2-x
zNys;{jN%QNllvVGt4YZK+NCe_>NN0~s;kcZ0FS4dnRjMAHsepT@=o#ju!28(ODwo`
zPpNBE`<GQ>shF|5n5G9Brd&5#<@8CxzJasKR6eI*v68xKUJlHMpaPUJdhjyMi6#0B
zHVS9AO;JGxGULq0ZH}E1;D$0W)`yg`9LH!x8YrUGY7g`<v=jij0ftK0P^VoKfuIPS
zRw+y>Ic-u|(J*9`a=7Pj*{K`;$%sEr#hh@rGxbmBqH4PA39#X;M$uQ(ZIQR-a}qRl
zXrZqt!^>$5A|`q6x8I4rRshJvBtV20)Z|Nx<{S9Q#I|}6X9C+VHc(?xPgqS|P931`
zq8_LEhjz_|oZYe)!?R=h0sF2pTxwsY`I-3t-{o}zh?+|SGV$JU5+B&prS<#g4fNGa
zE)K%JV6Xk4J($WQpicks0I2_4es5o}IF)3QlWQ(`i@x2xYD9{fw|{bthzb@5Q8Rjj
z=aNI00p(8xdFB7L0JsKF#lb$F!rsZTU4w{9%hRf;b~FbprZy7~i4Re~qTZlBK$O^d
zpaM=%0IGgs_jJe!r10J~|7D#1FTdw6=^vMZ7X4rE_y1-4SfWI9PS76ezu;owe?KID
zX~7EzNDcG5^oy?o)PG--i1J&{kUc{YI`YHdb-((#;L)Ffd;00%Ipq*Y4E!%H8&Lkg
zs*UXRCeEvwezuozf0X1><wr1FhilNUHgkl3FRk&&zh^J*uzv`ad}!||=KBPt$M^X6
z27W`-9g}>Ls5=$|FUq%n_#rC&k)Z83h@URtB4-fkTPNNj6L=m(H)5Uy2tIK@dii8S
zj22tCpqbC(Mj6;Sj&E3LY#;0krOkw~>l{GK{o^WHHk6}d>-uv3-chYB+v>>yT)7Hp
zpKw>z<kWp$Rg-Fde92vJg2sw*{_^#$__zVgXdP9*tpy*LVEO#E<%gQ^@ut+Nj#Y~f
zHFvCDd~?C`{Kw1lD>7s~<M)g?_28;gZS%{UZ(5FyO^24xS>4fmXz{9!=9?E|d${uy
z#Cw7U0b5dMOdItJjYn;V{mZ80L9eyn>V<hzmW|$j@BY#B7rS5d4ZK3M^P;{NcPGET
z`R1=LV5bb)fjQC31R6Gw2Nd`N3W%|3Ocb&ijVP8ROs0|v_++X+RnMOFI#UUIjXjlc
zdh`9T-<WHJ{r>z(U=rN$@lu}WVT$sUYxtyE4U(F24^0JYlz<Y8&r`}8!Mq;TFBbf@
z2zF@Lb{u7~KGF^rq|brDIBpk<cg_*LDg@FE^pOK<C0TgU0TO3P39y%6z%O9m8WzbF
z!YB9!zJWdCcku~J!onw52-$Sd<<Ieeqv*fi6f=Q-PYyWh&F<|7rAL-L@W2D9U4x-D
zcL3>;B~L&7bgF{y^;W7+E0w1q`oU*)r5E)16Y3|yb?DeHmG-L>etyZ5>V&Xg$crf!
zqUV;N_wJ|iv2S|dGPr1r;OeIlbr*&%H)4D!p+|Bqz0v0iMI#<p)P?zUkIRQWs-YZV
z1Ki`{ig^Ie5A-Y%frHvRt5#|LJcB>+hZJC6zw))2Ftup;xflq(_G|w4z|uD18GeBO
z7wj5)#mcJtm#rx3UY4v+-ON0&f&cy7p664KC*u5TK>Wuyf$oa;cWNAq*M{yo_Doaj
zb$_(iZkq5|SLU5-N3I`LYE6H`LHVHrjs9HpBn?Ds;gXe5M|Pg@z5?E4pgmDUrRvis
z7L{?uq8Ct%Fa#4FGI`L@Loa2xMDY~A3v621ckTQ@^QhK`Z(lw2#M2v~w5}1{1omx7
z9=YYR*D9}+H5DzD@l5?ZP{lucu{4q2J@DD`rMF~9mXx$-Yxw7$=$Xtv^3KvZnJpuv
z`t6V0zxDDXzj6n`qIJbJK-xOUXK{mg{sD|3Fyx(q?9rMA^#KEzDhI=mnBscM1IQdw
zfW{S3XTpHJlqmn&m#@9{<<zb{b8NObt<_HF!4^Z8K66#W9Qw^iH*J3O(aoD4-Oqn}
zk{>C5Zu{CNEq@0)+9xZF7>7aj)JY&?ocQ`{&pq?z9#OXQKuc@FDRzm=o9GWVJ&LYB
zdUW&C{CE7bTaF%FF%dj)b0Gu=o&sY2Tk0adQH-9amTFD=^}t)Fl)woJDkP}Uu?w4E
z6@yHNFO>dH9F3peH)tm=yc5hAzPqe%>C!%4y`rmlvL%vVzQ$q>S9BTmUG#wPCGOW>
zKV{C1QZRo1sZ;y+{vQ5Cq8nMs|55lr-(T~aUAtz?+(l>gEnU{$v6TPKoy$uL^?G!V
z@-=1`3l|C>^M(-<*IYe&;MBhTr+&AWe+KwggSSvR-#25|uHRg<3!|!^A0zslJx?i6
zzsy5C@<@UXMRPtP#74}M(T2EXS_NpVaU6>W0JZ=Fh&!Wo_zeIN?F(SJiG#(`J5I@R
zev}fYeQ~Tv$i@&wZ=~x~ke`UgzKl~z+^{Y8*!5LY3!OCcj0SRIPy5xP<VksvPTR0o
z{P$Dby?-r91q$BfpV$3G-w`wyc?!*i@W5MInNbn+R=DbA?tg%i4cENKPdec48d0v%
zfPK!GTowR}`Rj}sbcxSa-0Ypm$zdtKV`Ag(xuXmQFw<JD(N=97llp|eA;Uv69D4*T
z2J;?J8;$hQD*o!H<Y0!=&Op5}*AnAj<oEg7JbJg$DAm%9V8QdBb@Ny0$Be&mQmsM(
zXq!q^A@q@iSm^V3Pq+4h?-!j5y)8^YaziP@4S8LI2EBt0Q_%av-NS@cLBQ$B+b2)n
zzLoxAJTyyEl*9~Knk4aBW$%){B?A;X^eVO6CfVnjZkt9^({3}(wNKgxHsL~(!D%p4
ztka2879mRUh+I!%x1vemh-kSaDt-Ip&6_9lleP(V&SE^>hN&{d!?zCO)BcwR3wYA5
zwC69AZqSYyTzK|$3YR%)+fOz<DWLx)@dKPWD>Qe;u;*r6Bn>9FO~Mb6z|Btx#|sZ3
z0PW&O;WNo=0$YU_Fz^(KB6=Vb@h7Lr^HE+rP#uGqhIj)AyNQeACmT8nzLK$0r*LFX
z`>lKkNWB)m-{O@5K4kUlz@CrD@kM-0V)*-{&ToAY>_Nwmz@DCnU$e_^@pvr$T^c{i
zy?*GB)aiJ1fuCPU4j19C<WO})rzi~$CCu_^v-nsXrMiZtW|CALO7)Vx#G%p*aYG1(
zs|wC`Jj?I6G23QjGq*4P>wP+<&fe?!jQ{No`wKl5&arL_F#XP~w0IT-H}OXwezni!
z%yP;yc070(<jpqdGICzK6lT9ZQ@7kL$<b$sZL?*zPlJYC*^02mBX(_2cz~wB)HJey
z^EsT^VqaZ_JZr)wf*|%H9n4ay4SP=du};k;dYC%j&^+tI`{*%7F#Zns$))~)mqihe
zNyL$*6sw)bb?nO0&d$<vMto%RgZ6VqY?;G+Vh;|aPC|o>J7?r%@YioKYUW-bd#KnJ
zN%T)$3@bU==-K?c{H-E+^~a;PPm^)iE6vdS%oa8|csJ&g($2G2;X9@83VD9xZeGpF
zWZbUj!Q+6=G&GdimFoPLI7rJlew4$QhyZxmGvP6?kdqB;pjFCOX7OK9X#Sw6t0fe(
zf>I*tpa6}-a;lLUMNOloQ%eyiy$kWuH&gc^UiuXFh=xa)8`~h`)dodT7r_03qxGgi
z2M<xatLZMlmf~>}R>q13;t{k`(I!ssA?abnY+T52rj@r)1m#G8j?)wGRoHd4F@9-G
zhzJ-1MKsRE%eM{-+f73;L~0v#ToH*uT{M=)bs!MigdoKU6p^jaYDE1iq!Oi42^10|
z$d<_!VzpQSq%x62DU(RfeX7?(CDdr3a-7u)#S)WAA_mrz7K=;@4F)KcO*WaJTwyRM
z<h>}a6iM`YiAV{y@E;fqQcevKo2TZalXW_o7==(=ESrYX^g0w#h$V8c^Cgu^g}51|
zQl(c-S1Q#;HIU1J+NgS4skLf>NF;|+iA>BXAv5dFl>`4)XzinWp9c<2v}EO-N4|tI
zsZuFTefy<U5jh2$)nb+vt3|1&!M}i%lSw!QSdiQ#k!(sz>fd-pB7OM{37S;?_3dXe
z*=OI%*@15qif;xK&QHEmOStbo5lMI>T*z<#j+1G>0~@rmc0TtTu}t?3cuObC<V9Z@
z3}1n>5``kAfuHd3bE!%x`yB8xrP9IcKb5J~vQNRMa<!Tl|3jhGDweH;sIy5pR;*3!
zU3mx8D(Gz{shdC3Z@lw@Pe{B5C=k7aQDP}7(;G+AB$g~x0OS82V+eq_5RJs34!jEv
zt$v-qh41BWd3`lF^fU1jpbt!YeK7tyO^q3Kub`82@2G)$hebg4un3clPDvq#PQ&)0
zb(EFzP?OQvSxF_SE6~jH<9$XGr*UC7*F<q2i=F|I^5M;A5oZwg`Z-8^D`Ip6fNhNo
zc<&h7uav<MnRw7+i?F^&TnT{4geK@X(f{;E{Q*5k<FWyK8xiaG;6WK-Puhb+DA&ng
zuYEgMBbD>NmV@cocrism-W4t@z22c#LLjOxysYZa_uVjFr7#0l%19=UR!U$bUgtF{
z6f&m)nB-as##WHWd0S+3xCv}gDNuU|+=(1)xO^WpvMpg-u>-C)uV^V$GR$_eH#mru
z9kkc+S7gXRiTtdVp|FMISqgSq9bAzSafSf+gD!I!f0mO2MrsYt&XcGh9KGa<O<gyI
zf+|CS2-2)${fHyH&3svK9K9~Phx5@vh9Q7xM)XEfb7M9{($_8=v$$AhwgWJ{p9$Zn
z^Ot=aodJVRqqiRoW1#>F6WB#sqyiqyQ_vnllzPzHro+*neamy}j~q^NG-PPN(#gX|
z>iM^NrX$W4#YOPCW!FI#FbraJr}zAVH%2Gtr{;r?^j5XlOuHq#4epyipKsP%4F)z-
z0$r&OBu<gRVAX@;^MCaG-M{Slu{ntc1FmA}HFN?Gj?=<R;K-AsPFes+Tu1-x^MgEK
z89AGkvgj)_kmcz4Ex=RP|9ma~ar10OPNPo6h-C9x`1k9ce(o2%f=}knyOq<484<%t
zm|N$~0~%nRKmRbNV`y|A`C;@vzTiI^^y4@D`HP7j_%D3}hzk~crX%VIqizC^29H>*
z(f0GtoCz8x?QF@eZEvnB?BcJR2-wwYBF^GU=P!G}yHuuRSLYg=Zhq=*U<Punt82Vd
z^;6H3O@)5pjH7Wy<0ilmHrc5E*+*cK15`iWu<7Vqg6Qa9&~DJr_xIyVl1uO<7}a#J
zt%G|>xV>?znIPatJq9-F$w;3KKmQCK4E(ME#L}E-z{hmaFm_-G)1*I4Vg*tBPnZ9%
zPnS&c6x=mmy!-v#V#D-gyU~4;_~B!c!+yZeJ#jLLX0YG!x7#e;3m0}<Y*nB&nY8j&
z;yZIl-+9=#Dxq2kM#C>!9}I&YJ%^lX#A6tQQymb{`HX4;-4h65kFEItr|3z_&v#Bl
z-G~{v?9OeNnb~%y8XR-#wro+y^afTlV}^z`XrH#}$Bxy;{7@H(=%7yjOJ=5gu`zWT
zyZO9}>~r6xN;Q}dgM)_+B8?_$SkFJV-Vjx*_Ub1MOwvJbR9~{UL?6{^exgr@f9W{A
zl!j*q-x@(G4TpYy1tcD#d2*x|;Mby*@ZST8<QFYpbaL=ofQ}G7e?NYHAngHC$xnR$
zI5iSuaQ&hutHc(_09!s_J7r=5<uY<K@hJtcnFBU~MdU3a5OhLWoEiA}kKZe{%EB^Q
zeEhhWMggn%uS)c=O66ZKP3KoBRPah@R8*zUzvzviJNVI^zWy5B!H@0)@^t8jKXqw(
zN`&r6<6BEnVBlF4K)iF{`~mhI^uDlmHX@5eP;j~=1p$}QifN`eRy+~(qtGD0DpbR_
zDA{*rPObj!Z3P`&_UgGamiLae0h@K)+I8*sth(m5H;)~Crj)bPmQ`z=rJ-oz_qSET
z7hf`6!GCqDHLp+;U3TqX00$Pm@h*RW|NN!idp>If!4v)8p6Wlm88Grd=IqX~J<}&V
z`Ny;l0w>ICB1($5C@tcqEf`}$2Q)r59*_Xv;3l~Qm^7>pQ6?IF+Tk1KMFh70PjCW%
zlz;5mXX!8sea#<j1!}Z-eQ_0NOWnb|_ALJxP^9jl!|s9C47rAZ*W7M8i~=YDEan%1
z*&lefY#DeD>^b(qWyg;npY#Ek%`f6V-vXfb7}&$#kdt~p%anRwp@42v7IbHspc|3!
z@0*6Obj1|A2KCDxp-+;XMvp585~<7(5Dd1t(4tI07=El>F^J{vV8iL1M~qmR)>`wp
z1)pc)#XCQ}i&4?%8USSP{dCbp`H_`VT1SGwqjv)H?cnUIcW>A^TU{luZH>3KMsqu>
ztD8EPR<FJ5?)BGBQ#$?9nwCgMb4gBnbxl*(;;MD`!h!r>uRHQFkpAP2MNh^8Im>S=
zz47F&{HM2z%={PYu9>cHQdZZ-qIKDIU0rqA*REcB%~Z8FSDvT|my8h7c3o_PBH*}U
z%c?l>n|hJqh&PinVU#-%_ebIZk($axM|XhJX2yvBU)F>sV$P_CFaOy51NQUV?|ZK6
z-md4)efgZ-{#*~N0ULybm(%Wi=^4-U^gL%5Q9oh5q3ppIp-b@v_wn0P&yWP*|BG<3
z___Op+X=SR9L0W*QANN7#VoBit`Sif?;^7jiz@=ydYc<o*UMnaAOFn%IqiFR7XRlz
z{}D`i877YpHstvGV9OaNKaj`w{e7$8Yk2G5L2n*loM-sW0uH1O&29fi?{PZn^)YQc
zRD?z(Llj{MBm%&|33yXBj?H*tM3V^<k2sSAlmur%fKSM05a$y%7CFQwEfnxMbmBj~
z$O3UNQS4%y8bfnhE7j_NU1d`!rCE8|O2wQ&n_dS32K}vlt^my#+wJz*xm`M))2%OX
zjqhwQ8p@l@OlEdbmQtbQq`|!QqPm<yyAIIr^NY@(;E(-l2i*S-ScgW7I6Q0h!F_i&
zgaT@(MjhU^Y=$GlQslCVM9VexR$JlX0h>N#!A$4lkL53QyL=5A&2nX9Mn>^XClYy1
zy-TBxZdkox$?Wb5jYdIdxNAZk&9mlgZQxV<jKA;w0dxs85b1An#OnsB4r&s$fLcrK
zq;9}|QT$%);R5|3#*RZrzdCLbaafHUTg7tGSUeDmn_@JF4f;e_?Z||>VcZ|!`~lK6
zaV|QB&<)US(4?6z7KnK%H987<qv(P-zJy#Ah#DDcm{AlX7)cH5`;3vE_a=YKywZ%^
z>b>u2s#AaMHrh(2O)GKex;(77bRK`po5j_d_x4ujuKQT2{HL?_L`hF!WMZVSr{qMf
z^PfuP$F7<aW#bBS7vvU>D?3rcXIB^F;(kxbJkZOir<K@@-Cj?Z&QW44@%V8i#nrz9
zy+CpKhx`lto%{<QUViz9pd9po@(&;Vi9s@}M)b!0?xIl1-MM4rP-8ETxQ>AvkGYDA
z?K74v<p1fu{|!+MkdMi|yCeiBbYzdo?wHtmTdnp>sq{;2?QN|SNz$a2+v>DmNTpwB
z>uzg-{u(G7lYLKdcCqXJH&XZUvyQnU<@VVNm&~vi7rXo}lyOh?7#T!WqjeOw?DFBQ
zg@-R`BMJ?d#c`AxQGg?;xzuv3nd#GGDR($Tr_aWCROA^nBQRhu4fuc|YcLB!Oh+&`
z5{T)-WCihHT8E7a`2HbdIO@S^*!=^Zh{FbtV37j`1xc|>UDd++N%N=8@;0}&di{5{
zm4wR2tSZa(XDtoZwd9=cZL<{>wf0DT4Lc#+NrSTvH04V?lDYKNOt}}(YQ)KDoyGnH
z|C_?bqELMioH1Oa_hC&{0_+<-sweE*n31t;OlXdZ*3?DKv~N~ktw(*bHlbvl=3KFA
zQM=hL;iuZ-U|YV)RLHLhN!A*={sLEa>CMi9l{A3w_+n*#Gkn(@kNLdOSobBE!6K>-
z%|j<e6nVdRA9De<8e1xP+}IBWjaMfez$1g0;t;eS)}VH|iCT3OGZN83qnr@%V2gl2
z7;gjn3<N1HstHHk#Ipi+qkwY42JF&JqfcwC3u__lzT=kr50sUcZP>6HD7-o9JsX07
zyoNDj8uIvkBi1ddK3-eZIOUnEd%LEA<L@)f`wX1aFuSrRlp%(kS!D3{ivA|LPgSBE
zJ+>nCMO#T}M|)YRamJjP^u&s;-Is&cUY1L9vNk_z68i(rER(^J*ImNDX(^fCd`CHx
zHF}|)G2hd9)ro?EXY$6wsgvEV38|aLKk`B#Sl&CX3`}95=$V$7Cu_qq41fJLM!90_
z*wV6b7umIIv1OSAc$75f$!7u{pb7s7dAbCQ-ESBjuCvmHf)a0|Vn3+84F38e&3X@P
z2^^kwRaxP*r43hFQ;+hk^p`)v@h>?~F~3INEQ8=t2>^5)#1cJXD<)urVrwdlKtS+^
z2(BsCL>9oS@WwL%*T#w>h(Mv6m$jFNE2H1%0h@tE!$xWF*VhFr8q`bsz`qaiU*D3b
zHJDh|YY3N2J(_H3NgjO;ogz|&KTDdJbm&j3ZUG8L-?!9L+s^Oe%|;ir={J4-tH-vM
z_l)#pcP!0E1O1yrO4f&JW)$hm(P`?kIr^Ypsat=|>OUQtcnGbF+Vr}Jk-*bRzi|v*
zgT0}OoLB=Nk85B^Q(PG5)Wc!?R+E4TmUab1l!j676C48JJ$3>`ghemHONy$2QfyQJ
zjq=3Ct4{3LQPfo)ay#{M5ZBU7>)3!-V$c|5YJkYEvL=0ZTnrgD@$cyJ&V)*=Oo+1{
z=<?L98da@#%F6VN6vDza3YHOTo3a4I&?fk<&ZRF^8!P2kft>Q1xFJ^BRzJO?l<lrn
zM&y8H!Lr{j$XTY+XBwOkFgK3S`|`6HvuLW;sAC}mKwgkmS!2FnAOji!gpig!T}kV+
zY8eTL<pbRyEmnzW(B}vay$jLLO$4L(0zp4qbPs<z8K5A8`vV!Q0WR*vs5Kb95NqR@
z1Ykoop<<1&E|is1Q<IZLTf#wGUY;!&{<KI)f%iuOI3*C_zjFre;Xl0H<Z)RGD{Wnp
zR3rcX^Pu&`he63HxOnHv_^<cZ;R3e<`#rY;`+bbGD-;d}!u%9_Zl2AamkU0>G~r(6
zM*hs9wq}}^G8(w~-B*C~9$>$H`^TxOm2Z!IY@u)0SHSVru3cXXG@a-?dNq!;k7&Zr
z`e*@$D~k9DjLt@|Lqs3CMCU2irqsw3eA!o8r$VAL(Y@zR@hg2abc>QIv_gDq4xXhl
z)MEAo|Bi{_TzW8x@eEAAO_>$c(fyJOcpT>u9ciU9FRB#`)|##p=m0AL!|P3b$^Su{
zp_J&1e9%YJ9#PW6zw+m^vp@$ug?C@5{g3<!1F8LmXO&q2J>73Ot7LNqUfc;c5B%+-
zc_>2W1Wb=$n@PgwhK*@6gtWCO-VRUCO9YOZd|dWoN5lfGgNR!9I{)FJ`}vm_azMOO
zs#0@JZ>^s5^p%~RS3W&w+Ohhb*o`=!u=;}m$JY5kcl{w?e?4_}P!aJoQK+Ns{BJP+
z+wSdBi}*?jlunt0E`Jl<rJ?3ZM<9sxBC$vHEi)Idd;K6kq?y<|sEc<&{%FIzh7zg?
zZLZD-7g@$_<p%^}n~>$R?gP6o5rnc7${b#ZfBX_zC!i`(UC*Jqb|CsPtxZQ}Ni>6C
z(H#N2G|+mJgHCgN!%GCvd&9`qL#B{ugb}_DYtS2XSls8rbCE6*$cH~&g4|cMC-;%O
z+=p|`R(Ecx+692Zmzv~P0N_(6LP3kU;6#4Tz1b#<Gb^TYVXQP(tdywA^Sx$s{)znT
zd$KJScTTa&gD$kfr!43~kG3;xv7lS#+@E8yc=Ae7rdwTJ;58>XF3aL{FjA>uHMra$
zWf-Y}-*t^qDgqf!Yc9uSn;i~TDmASsq4Vf`TgV+Si=>R5<mFl&HYk!BuHyR*GMbhd
zK;kMCF!|G&cECzaR}OTpHb^;`;jrcs-p71C$?)hM=caK*h$+nlWpmF^2pbXz_T#ZE
zjDy1a%pt}qqP>;{7Votl>jJCi`e~bL6640LT?|6t1B;ifZOTXhkwq3gm$Z1j7UsEg
zmG}(4kQbD$U3tx&YgT3Xyo9g7eTo|9YX)mW*HR7G$BQfK`;peOE2=YiqWJtH<JL>}
z(NH<;UKI55eUP|COJfK24fLHpEuvDHr!OSZ$qQkaIDLAc5AU8111j_b6o*tYIe`9|
zi*k5scr0Cv%z?sq@ew(_T9k?3A;xk<GdWsEeYkUGqI5Jnv4}HbV@&^!r=H@!dkXRg
zCvHN)9h)YCIS@k%;vjzzLNI3{q;Qd^cF2v##^9_m$Bc5}G88hS#EZtNkBU;1m+Wo?
zVu*z@hJ|frwA65eu4&@L;P*#ni7d5o+^C8#A^fsp)VPfsAKnDNtn5aCaov?)!c7l@
zjl(IX)We%f*Qk~1HKm&#MnyRFnv#tVZ!B4(=EiNLPY)-ZxFKFrgT8eo)k2M<W*}~Y
zqVfgDN5og6;MdKBu^d$d8RG(D7sj~#At%t0jb&m0jR+F7bPkWjguYAW&p=ughltt*
z%%6w=y{CsG^o5oMcjij<7KJQZ>)tZTLO+rJO`T4c7>}`e`M+Z5Ujo^C{MLjns;fIE
zl`EtZBoe7r+9Q2WW|s9xr4pNDf+SO`B!D=*$_KS}E&4k!0T-2`VpgeyzA>bi=H9u$
zQYdAEqqewZ;DP+F>(C7ow;sQCunyqB*uvuzI$a&eO<#!aZ2O!XB_!o3a__!$Ra)(c
z!TM2)(s&j4-7=IOe|g|zX&1a?TL{FkNwd!6513eAT*Sq7*udEoXLX!06c6Zpa4K*D
z=R*Ew_Q(4|%)))MzNorv|L0NuFZ^GkpYOlC@{3vf9H9QH6)V46x#B8N58r(AP5xmf
z`4bH9xyDz{(c@2pTKVfO8x9}d(DJ&RfBN)z`rIqqgZv*x1Og*Kc90@I2h)DN2kj%8
zh*uiC<8T{wlsbuLhe40y!Wv0m5(ht%?;BLo@__&2o$y=~VHpDWQOTec(7|XfDWVy2
z_zDE?o`Q?d3qhFp$>h{?c0YuE8$AEtTm_OTp5MxEP4Sv=$F4_#0#pL|v0WWu&4n_4
z8=tiKPhar=dci9!zwD<{_xNpFw%Gis|KbvGr9wIff|*i<CekvpwbbV;Z5`PX;m2Mm
zF$&!h-FQeQNct{D3B(#bC25?wp?OJ%k*=^1a4><08A2v71Rcl@g<!wm>bLS}LO#Qp
z;Xg5ivJgcx`Q2u2;2jKs1u`+9^k9hTPoex2St=k!&o!kIuzw)QrxyjZNKhsaKYhVj
z{ovjuYO@{tyU}x4gNO+Lv_Sc_Rlp<wHQ=-8c(adRyua^uzU&0Q|1mIcL&5ER`@wbo
zc_@9!Ct$aq>203p=a--&1sh0-6W~Q$WVf$*KDzW1aGei5gXO$j^bg`|(Lj|Fk5_^i
zF^2uI{*-@G2a7117{PCgnL-X&$)XXj6|4y3bQEg>q<wMdh+_{2Fs0{zgC-s`(sMT-
z-HiUgcbj^~Z{9q<XVYI2?dR_9F3XwFFd;nNJ{s29M2ywLEoQ4sb^eBMQ$_PjYtN0E
zU$b&f+ZYCjT^wM>w$E8vJ-7SZT1$3-R@0MfnU8BH8v@z1y?gcQ?oq2&jY^;SAK*=6
zo9ZT}rkLDD6}l4GMYP2_0efYjMKZO?Y2G)R|J$*pp3H*qQcw?|81N4+3l(H~mmLGP
z+53DE8<f)Uc;l>Djj3jpErMsl8E7p$l$PJBC=2dY9@LFI8eJS?2^iu)16&*y%j)Rl
zZs^>-J9TahsDB3$%x(OW@4Uk=TgbHWZQv;WPl<WjcJ3eVyu;i(AmiK6`7+=V`tSJj
zfW4PZAuccn%~);JOgu|L{Hh57C2+t595x_Q0fyLT`cWJ$L|F6%@ZuNn(**c6?L`FR
z{}KmEUi<~MEQ+#d!WIcwzC^_a6{A_e$^)_U9t8tfru+aXQx#dvw*7R`8vZklM<-{+
z+H8;F>H54;CJSA{-4pg%mG>4XS&gR<ta_zQY)|#DWu?XZWnx<vXe|v&Xg|D(&QS3$
z)tZ4RU+Hjw=8YkV-B-9@^v-7fJw>KiGC5mikSnFlkJjsC5~=^gxGFFXx-FrW$Le5f
zhSn{~;ZMf?pjR5Cz|d+48FDlrP-EkauydAPGY*dN*m5SRq#kYR+1~{8(iW8%B4VT<
z2xi__BhqP1e=Z?71%iAhd66B5jq)Ix75hU%Uyo3D8Ui62z33m)uVll}rO|U2K~uP*
z48>y!e~MV0uoRC7rVIaw!1G7^qU2dh#=e5+xg{NEk{wF`g)cgfC_9=W*HJ@qdh$Pz
zp!)@&Y9?{6-{tf(@17%iw@f05F3qMC+#d*TgcHqcoroq&k6MF1?naDC+9D{96#xl1
z9Kl4xAVoqt-p?lKI=6tKBf2D=(FgZz?Aka7wrt+Ic_ghpAZ`2f@1M3w4^Zc2@+<y%
zaP)nfXOu$Ce(83w1|-3n?b7|cO!g?hnJ?xyKPr=H4oIJZ475V#Dd_>l_4>@*+)Vw3
z5c=7#RY+UMjcb)EwEKZtJa>9-Wo7Putz5c&&z|j4IZ9MXZa#eYW(h9%<g2efi3?(_
zIAQ}t_B4k}sj3L(&~$1(wH^)5OZ*K||K%C$y9(N_#Mk0b+Hf6M^)P+%;q)y?j>P&B
z;1zP>g%dq;c<d(=>5(mSTF@Uqc>SPRA&ZVA>6MnqSt3zq(J?wtxElX~SICKfWq9l-
z6H`fWL8=eW3t9aH_FUjK_&Z1%O`WB1IT1dhQPP6ux?_a44io*92)2RbXpvz3SqWJ+
zCvp)Z3k;@6x)4^ACd%oVlqM1|az8Esh_1bZWyXD0pBd+>pxYcBv3gzwocP}V@T)5_
zV_cKC+V{3IS8>2yE^ZQ+xhueB;Ar^q$N&5;zp5Nv(j-p!{@~1kAQu$`C+n7No-wJ?
z$J89oaq^$CGPBcKJind){`Ol@`~`0~=#<6_T%g=l2oiwZ(l)V_|KZ53xlaB?Z#a-C
zma_(LSZwrHjb4Z6_tof`cadk#r^<;fh69Q?vH^hiTYU~@&`SYvzyt+%O{fEiIDY`6
zNDy#SorBh5XBt2#7}Lh`>A{k)M`xD$a|{!wPcLOE19g{GUJ34z>0(a3eq>#EY%I6L
z94yaP7dkj+UX?qmpc{<U#5MUAhpl$mG>OQXl4O+TSXAvz#&O|*r#9>;O~|yKY!l<o
ztM=s<jiw)~*mz4{b?3oZ?Ox#Cz9Hc5e%6wG_?mZ~`%7=5Gk9g`==UBy-mI$H;naju
z@xBAwmOuE^(IY);eL0W9XEoLLKFNQLejmG~Fs^o9S-S~ve>$~)b5vBl%dHO&+QSK$
zaoBg58Br^hgrcT^Cx)e*aT80UF~c!F;tWd{26R~GVTm;k2G1}Es?3}*Y{V+{f}kPh
z1U|%8(&2d6XbN9Cy12)$R7Pk<PRq}3EtMtsZy<;R)omK<s>aJ70<7=OId{T?BRbX}
z0$@*}zdSIe-e_uGy!B>yby03netk>@`jgeh?;iBL#j0*hwnTm)-CT^0(CxcMBF&V>
z*MLAw(LRxH9$&vYgNJZSY7^Y5wyl~xtI^~&I5J(b>)c??jCpkyx54NF7V%B7)UjS;
zGyU8-ax<2U8THV+;V3O-rMy%T)lMy-wo?13+o==O+ti2D*B}F6-y4DyCguxAWBH87
z%?`#RWFwd4(4IKw32+`=*yO`t4W9TARc4A{*%x|cg4;fh2zAJ8A8-dEm^CMQdRUHT
z3UeMTA3%&S>A86CC2Z1j9t@^Kk_0*r(Q<xV2g>EpXXGx}xp5b&y|fvzVU4(Oy&m5H
zH~&IGjFC<J5qYpmu7}{b5nN?-e}5p1HCe(Uj_hAwDwaE}D9~$+;Oa_%DK`mchkAJ-
zPDwa)X1m^UcEZ@);>?Bs<BsNbLJ(oppaAIori@5|QUZWC!@>D8nh%MMI-5ij9P2i7
z8OBVBCTEmmft|~M5>_V`iw(LQD5j0^7rDi>)#9*A9JVR(Y){rz3JGF(ixFWPrj@2w
zC3d4TXtNk>QoAuP+E8qLkx?-DKp!yK!v%=$K$VI88BM#CoJpf8rghQ?qcYuGoD-!@
z8BSl^=QOV0eQxh#*Kf`Z<t|%>4x6ukZ11_<ByCMzD1Y9({7~K+oCdaE)KMp78Xe^{
z!%7fS(2T;Nte`VH_yB+Qx4-?(Z-D6bVv%>I+-S|T266z+GC(h7a%D^rtr3ekT~;Fy
z!2+?4lZf?!Mkb;uaL{U4z!k`I^_%9JGK@xLOgtstkR31uU}TnZ>j;-Y<110da~y6(
znYbcSKYpp!-0n`_pA(V0(`G*m%~8&oB180jE`L^MDhx*3GG4||*o#)&y?^%X{dcce
zBp_ceT71KmQ>I*b!{SAI80GLGLvSmEF(XB@F5b1Pp~h0vsCm><Y9n<ebtCbBiBW!u
zlXX1_u-G79Lp+p(H6AuC561m0J}5CB^z0NMor=hX(_Jw-<VRVf1aio_F0A)Horeo}
zbn!6Ob`}0Xm}pet>Y_iA|A7*3M!7~)VfTu@Na*xcXS!#!Pnpu3SMI2;28pbAhQVgY
zFuSu#a?8E>KC#YjEHq{3HiQ$v=*udqs>;vt2ZPPCXEkRt-&Y^zU*PZI^*k?fS^WbK
z%-cV2-hKeDYv>u@aLt=ftX{r+^%LOoj=3$B#Z#*#z||W6K^$*wjdMT5TjBR%m-RiH
zQxTcDta%dus6RX&wEi=gtCwn(YJ)A;7Y}-})C!T@sJG<?6BSvlzUok6t-n=2bI;7w
z<4_eGw`a@Mg?{(~u5_Llj5&RpzgJS+Q`}s_KYF#gtsufbx&wO8$&1_CikWZF5w8W>
zp>GEfMXf}9q#e=Ie#A|-QxmAyslQTZ01G6*3#!00iqeGxARh1-uq@tZikc8XVF-tO
z!U+f`HXQJ2JW(|789V_Gp8Ir~uqh7oO2+N?pfnB<>Lx^J_zWHmz7hT(GAPra1;iAN
zn!<5Jw#P$wAH@M<gNYiCA%OqfT-0O0YZQrbLp&<UK>scS`rP=R3!uv4=vvg%4ERVe
z^y9eEdJ*S9Gr5O!4cwFv5wDT72wLt*q6zQl3~MGvk`p>GM&8R8kirdQ>W(=;+#njv
z6A@WLI?n-U&EV@mb2UnJ`;`o#!s6uZL|2c`gVoLTw_kG&sF?nAa8!2|aAkLO=J223
zBY0(e?trmoa>?ZFmdh>mD|#2r8{G;I$~1O!z?>!7)X{yO0!&BO8w>eAzw^$)y?fcW
zgub=d61TjoTdIc{QYkQ*5?P}qmSW4_+{ceuPMFS&2;OflN?o0k^OEtNHlZ7?2|FH%
zoA?);#lJJveG&`tw}Y|q$SFga^FgtgftnKM-Q}q~v(cihHoHeu-&k16|I1>qYN`QZ
zI!)U8#0^D=ulUoS4(#2_e^vv(pS5X|+g%iLM}k{ddp$)(p3lvRjT>DSUyjcb4Q^TG
zEp6XBaou+7WtNd!c2sfMDyLi{vUxKmPF*;C89in}>azCsqIj%r(L3d?5y6ZK@Kr{+
ze?bBN<y+{dyd0?b^8h^YMCvWQL$BZ<n9$P$RO81F6a!TWx-Rv*kK*m^ad>A%MSgxk
z!E~S;W0K1Otf(k01?zIrj}iS$otm5bD7YM#O!XMkKc%JoWo2dK6|<%@;<0A)Ia5#~
zac9KxT!!gD<p6h^QQYN-N<1o~l$!=rAS1N`)mn^dh4=7Z0#$0om{N;c%K5#4>=KJw
z0z^LLOi!srAqT9?=fH`2Mg(j4uU>hjynM%%Wf0I(O@_`Nd>egD>f}j0K4nAWQ;xV@
z>`kzmT1VYRJx6^7M8HU>5W*;8`*snF)ox58-%q4r?h#G<FirXs(Id8yXWg7z$)WXt
zAl>3CFtQXzx+Nx%ae-H;WU4SaD~rt}As0YIp9tgh8OXK-k^ZCch0&_xSZ;(#l~NjC
zb5T9Ss{kn})PudPUZ}-Ehfu>vHF08%$r<z};^t20iAVfD;@4_aIvuOmwpM`bg7q{D
zPvW>vHyA$~Pl^=`OOKL?D=jLOrJ%E;AR`(BalaQTSSc%JSq4fZtc!Noo26pCN#u`~
zJ0pH`j>$&LxMCp3(A{|q*xYQ?utm8HYXdANl8F?o3itsVWMM_HLiMfmlPy}A2n|sM
zt3bIN0}N0j8>-D(=$CSgSPX)=8YY^qB-?7C840%a7H5m{=ttrfu{5eygA%C*b^{>0
z>LSYF5v{#MB`M1C-I`HJk2|bGF)@nuIV$P#V6m8!aQq$#CmS(B<!&hQhD_pK5d;u2
zj7ZF8=%qmHm0^<<z{qW3pFc;T&~Re046u+DvCk<qoveu)Hxe+d<Iw{$sGNa~zL2LD
z>qe^;7I0WEl1w)#_?zT<bW4_FCrFh_Pd%w;vPdKq%gidNT<n!YAi@<i=g5^B6?#_;
z4J^;8)SVN8x!={YYN(KcRV*h1mk%c%q{C<j6&0cy5#=y};M!hA-6YTrhyaLU#dlAP
zPz{7mNRtU%8WkQpK=KnZA&%a;C#s^uX){hinT(AJz_w^2$9SANLU9la;XoRNGk#&i
zfMkf$*9VAzC=mV;mZ_-1pmUkD8TJxze32*=KJ#f!oj228TBEJ)YRxaKt_?T~GrFAG
z#@^1tFk+&5w`lV<mAU?=%z{jLHrT0BWEM!J+xA<F)dl<a!$o<)hD21neZM!eJ6yr%
z=GWxs*U%3ah9>teu8Pl_S*9*&$kChFAK=B@&)N|_kL0vt%(Rcosx1nm(&}20=?~PG
zR-2V3wbP<qn&ry^p2e3NmWgNo&nT}$wu%eAXt|2cbQJShAmrp90)KpeT}h<4Ahq6d
zKvrB0UcfaM@c&v`mDs*4SsoA0cItEmO8Ce{G#^bV&r{r2B0NKxFj@uBn(zz4`_BP3
z6d|M<UKN26L%d)VyBPMjR>@$OD1)0_Xt6b6m4A`3;<J_rpV<G_J^(1Sx@>gjY$hxQ
z(jOj{+Qg$!;7MJmYg|R(lV`-m9mV1e&qTp(C<orpANozCW#0aM^B&3^U8Yty%@!r3
zHp!WL#ZcOd3f!9M&YpPvy<c5*5U_Tg9_#t*b=obHz<g9du-m-w97aU<wBcQ-p~i<L
zAnj^Y4ThdB?()-dEw*C#*#~2UM`=oZPcO`VY{#S<dJ38T!3W(3zrC|!aRsOy^|KH9
zaQflEzu*t!R#r`05ayG7LU`~kPXYB*{t$C_?=OAuLHSCOO%BP_;#f-w`{KkqM0l?Z
z&%8eu2QD-;Tq2Gg^phzJ5YM0=lDL4%;KW{wAobJmR>Q-o)1beQlk(3?IeM{H*(*2^
zA;L`%tyi@LK_b|uss~Y}wht1qQHospAHwv%S4tq1>_g#!mhQDHyXhxLHFx<U5#L?f
zVHnW4M9UKEJz%&dN`S+mGccv+t{ASFH7LS^|4HA4+0?XrZOLo=XF&amyL)z5v3iwy
zTjSM_Jbq2x)e_Nak#yka^kKm33qx%=XxzN<3Q$XIS&exM)$013qR00fc(E|Mo|8!E
zoS)N}87}izV!y-W8SoYYS#DXZ*y0vuw)9rBmY{T237%z5Mq!UIj5@WNa=FQ~;yDsS
zkq{h8qRvjl@0k?+>io%7>!wxApW53u8b+GeUp-Q!<E9kY*~sC^w?4A{uRF$G;fFFH
zVOOD57p`F~nfB6gHHG{U{=Gp({0|?IS;bjm0Hw3e?I3<BiN8rO4%`jTELc~u;LfQ_
z*6sMUX7T;g!VpAVp_*~Odhli-y{RFgD;CLRtSoh-*&MI}NuXj?8{$?b4!)x6Bv4i)
zmn$UQJ@}TO7}#H5$B!G*5hL<C4~6B-Mm4rg(yIX09l%~`*nkf2ccv8tu+J3<2mphq
z?&RdZ%#lieFSSbNrta`XUpY@Dl0G<Lu8=n8gGmD~!bE?nUqqeczn}EM9F+KbDJh#w
z0P2+}DNEAk{AKdl1S#8})>-3;%rh(PCx)ZAA!oD1d5DqnU@c#)2OY0uMD6u+^Y~*s
zrmo%e*hILgY~abj<=ueczy0I-XO@?8b;XscETyHodDa{eHL1R8T<WUz6HaVSj)JwZ
zbKkWrFgCo+e>3T}S68v2fZJCysm!aoNcNh8R^koR)zl#Y**iqAM?=_zmQZb2O%+Fk
zbRn!mtW7`w+~o-N*-u9>+l5uyTtmMC`z5GtG0_VG%pXTM>I{|F;kP?->a#L4ydC*@
z9bSjQ6fk>o9Cm+456SYlNhHrhisa>Ycr%Q~ATILbD@ZQ7WJyN?d*u**6CF#=QH{mX
zkvhBEuJiZ6{}@SP@sZtTwi%5!i`AZCvFOxFBZ}M8i6{gT{Up<F6*4a=XSLXj{T)j{
zKc5)<UqY)}yGKSda?P2}QvcqT{}>U*I+2U9m|t)ium=(eaG`%O^#g^b0YIHef_|7l
z!Lvz*8c0Ia=TiMcetG)I`lm)KAcfcz;<*gXW?`KR`=CMJozc=1bkE~Iy7_m)JoCG!
zXm-tlBPr^4Xug4$rQTn#W^ndNQ8)7+&4ahm6q?vBYMXPgZFs4`BMc9-02x`>_zy1?
zq`e#!P_Ip0jt0obd~ZK&!U6E+TD8Ui9#v|EXE@Eb8Z@NTU?HJQK%4gU#Zk;ysuxp`
z80VQ0^pdepGu;2uKrez_3R<(EpmL2J@CfMSA_9Voxf_oInmB)e5Rj}~Ds@D>J}~0c
zzOuP(Euj)eku0-p+?uZ52WP!~^CO+bwo$4Ku#G=|{kK<)-TmviW3QV%wzMp})Y`kV
zbGg5&YwWn@Vj2C=;<nL+KyGv}Tda0db5T8=5P34PYzpawFZVp_i%sd++<uw8bMCm{
z;-kHNpHHcZ9&~%b!CL^>Gxy~K6aAIbW?Z&>PwY2SJF?3&ou<69x%Fzzq9Y7#%9h#k
z*y%+EV5qrh4H!#w1F(K$ATqek<}o4?Iw0Vn=m}CVTJVfSFv8+@WHJbIetZb(nGA3)
z{1dqT2S4$6gAxW7d1D%&*G&pYT_eIB8=!jXjErE&2D;0p)|*NKBifVQGmp=snMn^W
zd~%XrR-V0V{PKfG<}6u}FZLL-yz%0e?D+@h4A&$BA3jhcRru^sA%ormmCD-?lV<3b
zcW~<7aT#KjJ<H0L)?Zh!Z`SI@q9sqv01J*UU1T#a>}Y&&<=ngHuQp66olsI2uw4Z|
zx>#YKPRo)7%+>HE9;CfkDc6P7q&OFfYSn1+!p0S9)Jt3;2VjzEU0LBo6U|$G)9S0P
zS`D_&dHTxV;WaHq4X$o94ngyU3kFX;{5Slo{5L(FSAx4Pp$mrDGg8F60A&V3?J(UM
zzzmrV=pA6Fo>@b6Ge<9~5%B3-57G|1FKP^#_pvGoI$`TiGop&H^bCFHDy)z$Qsc1^
z2qW?yxHzMUAx;dieFO1ni0Oq)G=*eh|9J5LUOsWZK`EG5BW{+%X!HltAq-L%4#Bhh
zOF@tMWOXC<60-c^+n>~yfTbXl&zwHjz_KT|msdQfk{VS8kM_YyCxIB0^Jn;L_%rSG
z)%;<t>qXPR-6!}nfIG2l=1!u%36kK^(eDe&mo7b!O_+HCB<nNJIZyIGoZS8S=&HRS
zxqbG&7l8PrnIAAkl(G!KOxe2qBp~-icbfV@)igfGdgML8fn|V;KkkqClUN17&M(Ow
zZr9C`o|A(y2&qft*1ACeFIq%o&hR3C*q%!<!88#pam6NTCf%SMnh|8g8I7#RG%(NP
zVH;V$gYi53|FG**Nxj{!he<uS9~Vwh=#aF`mOKJ%U<|N5BAIIfvSD&&C<jSXMuv$`
zI`Z@3qM+R#w5KMd?np*Qj*KRSBb=~gF?gwMReAZUHokNgSr@KAeeVafF63j`F(nLn
z^6e1sEMR|yT^Kowm@2pgOIa6o6;lZTW(WjDP1FYh!u(MN2%+i4m_=wVVIL29Q#IaD
z$P1tG0<mcz8;9wu$MNqz@CbkEArt)voG`Fr90)wH{i_G(faM|YHqEy8_&4tQj-NmM
zX`H(q#X-^C--3P9PyRnsF=Be`W^C+c92OR0q^x4pzheErD;r_#^z|PZTa=ALLzn+M
zf47;D>!y(kn8#>%xB1_<n?|6$8{GdHSiVBzRvMW8OTlNbGm8s>=E%T%we^5r1D)X{
z4my^QjTwB&I%qc{s9s?Mtw0A~x-Mt}+VP?S8K973F*gFA+XOkn9hgr<fx>F)Y|8LU
zmCVJU6%Tlr0<lpUvK(DlOx%tYydIqyv=E&Ma{B=j^Uk8urD~S{dgPc@m3Xw2|DByL
zB+qYC>1`k^;-B84#3!!6t7hpWD`GrP()#Dz$FpYu<H_RR$zoL=9&MNKh#*-3b_oG~
z78w^?1&2sgW|mG)4n?Lwv!IoVCLF#NJhJO$watn`<7BFAWi=NE`86M6V`9_Obhh(X
zbq|_v>#xQax9ZP~{DP^sSla&W5M?~<Z1JZcfI~}?iJhIfHR)d@7b|1@9pyh?RhIQg
z@k#h81SC0_{hO<4KXJ*bm5fZ<20lWDrrfM@N+vSGEG$gI!YVRSViI~CuJXllJUmQX
z=a|^}Og-lWDk(bfWC-#o-HS9&t&#GQv#a7~JeL`e`ggY=n?QZu#8i(Y&zyg5{C07%
z4%7bq*_Wqf$;gYiYZ6rdNimp#&(&vOG)At>l%cgBsG?KFDPyJz8gyb(S5s5~4~;T{
z$DEkN#aI*-K!@YoF$x2lugrqy`BpY9+PSM|$_n1othUCM_FPhC>hVn1&hf2)iJxJy
zGXja5svDX!=F01`@yjrU{hj-_Ka^EckWE)kPM1wcoK1(Zol%%6DV$Y8kX29azz+r{
zfq7eBoH+D)-2w-<%2ERlXO(Vr0iSK>PuOzs2r=2)v+(nB*c`uj;kYdaA0Mltf+Gtb
zAE(VR=F`7G#TKkyVNC#ri!6gRWK|{fKzTK!+eE=R9eisxA0w=?hutb_2IDY40N-o6
zpy1yJFay|8ztH}qm9e4qN&7zo5Fd0GszAX4FoSu*KLN0s4+RT;gAYPy1$M_<pD=p<
znE=!!#K#QjyfZ8)U@m~{Ghsp6XJQ9lDa3%j0+$tXwl_QMfN!7}ObQ!M)fB!U2rLIZ
zpB}A6BQGs+N<u~kNJ#$^b2M#rk&$s}GIbO+2R7Z~BxFR*#AGBAfsK1}Q6^s}(|<oq
zoq$Yv`~9X)bsY)6FC=tyB(NAHbTDlz0+|9L{{1p_G%;~B{Us*$3?%jpPM6Ixb#yfS
zmnJH@Maz+CE<$$)0{|VS=V<@{c-muNWME)mVQAj1azrGa-{va=H#-9eTu@5Uh0*{2
z|7YN2U;}YE7??m504Wy=4FCWDc-muNWME)p_;;6qfs^4s5O6Xu07Z}i<39kDDF*QX
zc-oCr%Wf4h4D~#c+)KIi3RDT`<_aP4Q16D9V1s7SB`mw35&|K%JR}x~t|C5zujxmj
zZp-n+o;c}LWuzl#96LF-V|S6h6TbF{s5wmtG>;DOO_nWW69Gyf_J0a_lqBz2|K{%~
z-+T5qd%R{i*2QuU_yzq}wejjh$sW49UjE_xL~Z84etkN7V7pHKr@Qkxth?rvr?KhH
z{oyJIm!7h;@rF`&;w*Qw?^|lX<qvRtS!^>H<ecY>ko7AUr`(;`+_*CDYgg4m?2bo7
z6GzJBz&492-<k(=KXuXMA=hMz+e+o?^8NvG^1++hxLDlBakrN9rHHgAal5MaYmq;o
zZ^Wke7h~Hkct_d~n)j^V1bH`%Hqy{a-c;9DT(N#w^j%CG>NgWi{HAt;&56r>HG~}B
z#1Ut0ffZ`-mH}>CVEWfPdg&JvEBTG-NAniuav$>EApN((|5kikaBMXvB0qATfKTvu
z4A?hbxWIm;{fTu4d4I0nl9%h+`>JbVk?$9($Gsins{S&yd)EDi?5KCzM?^18{qHfL
zAK?{do&o#(2JIVm@nRfu@1ak#xMN5@wV%~)XYwOD5IN1EAUdf7-skzbovE<ho9UIQ
zSJ`G!&13ETWwQT*Gron>vi{!8hj2!Z>V6WQI-AG1mewcB^&;yxddBkqXCvc*ayGqo
z%iM7&d|qLF)7lx%ud#pI&&|9NcYx2>e<!>ji~bGpb1B?w!0raa#rg9WmDK#2I*e;@
z+^Od>fByjD18-~qc-o!9?N8DP003Y#H6=vz=qDi}zJ$mW4VBapN5m1R5i(AZj6?cK
zz9K0Rhlq}l6p4tlGBYzWA|q7toX3igIM@8(oO7+Y=G@J(#+Y->4>!l$?RNjc?Rg*&
z2=KpPAY6zQvJpj(l1I6sA<>j0IY)FcteDl9gIG$eJvI`@j|&`?9*xBF<E`=A39JN1
z!XcCgwLmwI<sTb^F<>g#N+LP2A#n=MfIE_ar0OJlvLM-*{MT{9aa#&LrT+&KA{rq=
zcupWr$N(f@1R|+LshU(@>Mjz6lpr@x3Qqb_1e6dpiCRO2)39mOG+Ekw+722()6lKx
z1#~E#k#0!e!>}-)GKd+vj6g;NTY{Bg9oTRtCDWAY&)mu)XX&!S*`jPm_F;}8=kuxj
zQ$d^#=g-CEa&y(W-|#d%h@Zx9=K*=lJbT_Ifl9FF$K`7ZQVN^}>qG)^koct#Tc|Dk
zTEsXFoK}-!NGj4aDO3y=yNf@U@Jq}kYo#TnqouoK4mog!f989ct{hX|UcOinQ^7kc
zK08Z=Q_HA2>i&;v8k|O<DbMlGdFUv*o^GQD&vVa57?z*Pm<Xnl8N9&1;A06`VK$2`
zW$W2CwvYY25?9HnlvH}EqO15-d)2b)wTs}z2@afN<%BQEE_u1hT#y^85!8&-Z1Dh|
zg15&v{=8hvtzE2x){*OUb*loDKq_zx4(svtyn0Q&y?$3n5vqlL;r?arWoHATfz+UE
z*uO%)GWjnNT%-|g{z4IB#N&;$#{R}{l1j;_#D5jIst5U?6WndeYBDwLOLL?y>ESi`
zHAge7S>3$S{C7)Pi>k%ba?na><+iT0MYn-%j<!&{pxxZQ(*bmdIxHQ&jzbw=HYy8s
z=65PPeR8PWDi2+6zaHqqbt$@$-6P#T1wmoIfxR)Q#40ClqHo$%xL?U?qFSL|?ZNbb
zJ+m5^hNkK21$w=``&x=ts<mi6+MPa1AJ`YtE#4B`+SD`k7JYDlFwi=%Z74D*3|qIS
z29<-eL(Cz~(7F+CR2bdEuwmWsj)`gV-J#!cnPuiF^X}d1y9Nu~vUAUPFK8uN#a8EU
z$s?lsnEPuFHXg1$0w3ANkYlv5{;|ko$>a6$igDMI>L;@k*a`VW=xNua`x)X{&?dD7
zpL3tvr*KoA7q}N*dx~9Q-+Nj6a>Rjug@5&BS~cx{jeWh~q&d~jcW(%9#I6(<-{qfy
z%y4ERv*J17-27bFZE$<uf^R>~)8`|<D;MGy9xN990rzaZ<Gd%lH+!L8llS0*>BEK(
z>Dya^FHx6NOA)`(|Mer{qdkBMjQputj$alnZ~f;V`Oc%<c-muNWME)oV3K4IVE_Rp
zAZ7$Y1_lQ(p8)^{;sAF5c-oCpO-sW-5PeCjwg|<86pwol4<7mvzp!{I7QKpyf(IdO
zlUB58N!p56e~Ldq#9yKQ0FV9<PrjXO+f-7JWq020%)EIs34j7#kb#xW1GwRiv4tXU
zF}4{qG&qA2o(#@n3$F$*VG~~lFEjVY;1xVuYX;}AVZ9lg$GY`t@G7>gZ-WasvU3K%
zqi8n_{y@dP#xeRB;1MBi(LtB06dG_bhDUTt6rfGNf`baG*ri&9I_|ktA}f-cN9)n*
z>^37$$R5yJ$AkF#=+T~YcQ7J@%h<Sjgc=#r<7?CE&VmT_hx1ZYL{z7vm8f>OD^sSO
z1x#mT@W>GftM14bF2%^coL%vx%}wXDh$dBi+Axvhn~M4+WQ{god!qM_Z!TYl!q;RU
zGnRl>-&&$Fo@pp7^UBk{T30v+oM4%2Qs14+D@mpQN0vFESWO@umvP0jndq)6lfGaV
zo~RsgLVE7|;&WJ|ibI}zIGFucznf-%r2qf`c-n1O1(f8*5uK`G+Pght9LLPK!#jr9
zXP?iEF~y`vnx2tvG?GrRaB&<nGc!ZX6f-3;GlUaUVn|{PGgY-Td%G{$ch_Cr>fcpe
z{i~`cfeHEdpJj<d694B<eg^82fQd5`rzK8JoRK&?aSkLQ1!>4Y7IKh>0u-SHWf*~Z
ziPID3CeDKSFbWG`1y~VQf|X$vSQWkitHBpxb@&pj0c*lqur{m%>%w}lK5PIR!bY$$
zYyz9YX0SPI0b9ZtRG<nqs6zvq(1LMj!&b00Yy;cEmti~D9u~q5up=yjonSHS47<Rt
zup8_Sd%&Ks7wirDz`n2_d<FK01K>b72o8p?!Xa=d90rHO5um`=Km`qS=zxGO^uPcU
zmOvjY7=R59xUe)alK4DP1`m7)AcP5+gejPYW$<-4621XP!8hS(I0lY|<KTEW0ZxRI
z;AA)jPKDFpbT|XfgtOpmI0w#!^Wc2A04{`!;9|H0E``hBa<~Gngsb3cxCX9;>)?90
z0d9nw;9GDr+yb}4ZE!o>0e8Y(a5vlo_rkZ~KDZwqfCu3rco-gmN8vGe9G-yhz<1$$
z@FYA1Ps20tEIbF#!wc{tyaX@9EAT432Cu^#@O}6J{1AQwKZc*cPvK|qb9fWpg16xv
zco%*Fzl8VTefR)AgkQn0;WzLRd<>t!r|=nk4!?!p!SCS@@JIL){2BfNe}%un-{Bwd
zPxu%78~%d{1Vl_?3e%XuEaote1uS9-%Q%Aba6XRW0$c%C#FcPmTqUs%u8Lp4)$ohB
zI(`Y)z%_9#TpQQHb#XmhA2+}aaU<LqH^EJDGu#}vz%6kMD_F%E*0F(2Y~eVzaVy*!
zx4~`k%eWnGj|*`J+z}VyPPiC%#$9k%+zoffJ#bIl3-`u-a9`XHzk>VY0eB!Dga_kS
z@en)|55vRp2vqQEsG^p519j}6z%KUCKogf>A1xf9jSjlF6g~7Yzz`>J5~pw)m*Lm(
zNc;vKh2O-Z@fbW7kHh2f1UwN>!jth7JQYvF)A0;E6VJl4@f<uC&%^Wa0=y6}!i(_|
zyc93P%kc`l60gFm@fy4qufyx{2D}k(!f)ZtcnjW&x8d!02i}Qy;oW!--izPH`|y5z
z03XDM@L_xeAH~P;aeM;5gWtvP;gk3jK8?@dv-li7k1ybh_!7R1ui&fr8orKi;P>$d
z_(S{={uqCPKgFNn&+$!s3*W|f@Ll``{u1BA_wfV#5PyZg#^2ya_%VKhpW<hU^RuCC
zj*TrG<GwmJHtZ{LUyb`(+}Gp25%<lwZ^iw1+_&R?VboU_M|~se8;f^L_bk=-(}U1A
z^^7l6Pd9SHo)DJfinKxFAms<DSKvkw12>pXg}(4oUDF!m0z<J>uO~1tvMif^fKET-
ziGedAvdbK2pqO?}_D&cioo+Ydn>|~#lDgAN2cGI1DZ?3v9PK6))e2I9IS?t&Q9GrM
zGih5S@N{lC$b>F;Y17u6siJGC(~53-x+O@bE7TzCiLNJnBgdx54J}9Sr@EHfE6`y&
zuHo3iFHAUAI1mciQ;bDckdNii%`EkFrz5hOD*I%h_EPlUPic<R&v7$Qy?)yDOgqTv
z>OgpEs_WPReYZLpGf*v4F9u>NPz+)AjG!RpNwX6e1^U*r6-#u3QY7la4un^X1|Baj
zNAi-;56td#iqBFs?GCMraIq}cj&xOBu-B9cvm>0WYwAJhiHs|3-Lwh=)m7M5;bqhg
zZ%7^{J4MF~(!Qa3BCQ*OJj54P_5<N6nyU9FRj*U-s^r4qC^r;R?DVv&5($VHj+^Z|
z9?zHL^5H=46c5s3iO_=*>6!4H=;Y<$Kpr9QTA{BnF$x3Ij>Td`A}ME`zU<3OLqRSf
z9FOv*-E|_EuX{q+zTpJr7#6W2PryhjXsSIFRnK!Kr5(jclvd;-IdtRik`dBH%p)?#
zH<t;e8(LN=mi>WhS@Xq|Zm9!x#;jD&>=NyS+NBurL{3Z-(dahvEa;ZwixPRoHtn8V
zo+f|VBB!gCusf=k@l?Cx46?d27|<PO25Qe1L1E~x(4Fxk+edT{CWQ#fbadC{Ep-am
zQkPgLyhvFw9<T}XV#6nd7nr1RG#(p{XD%c9s#cyDujmGE5=@!_@iKBelZ<IEN2Q4I
z3Mu!TWM53DD4P9TY_eYtjBud&WGg#vUOZxRd7PJt#89nnQD&DYr(}6wN)cttwEINP
z$dy?)^bI;znW9H{lr|LpEK`VSXGpngOc#45Y0x4bMA?DWq%GnBIhW(TC@CH(8W{#}
zG%Uykk+S%}x#3we(axFB<{VNaic!$8gF8vj_mf74f`ZsU&a+dRu&koaZtap|15q&O
z8e?`#k=d4&Qs_oA?2yrjk;-yLE|@bTH<&kPDs<<9cpJ*$jwUjb9>u(o4phJIXDFl6
zVe*=1imtBuqQK0J;w0VkoX}0NFVn=4u#?e*N*N-lhXGxsOI}f3$sf~A`RaryuzwVd
zh}tK{IUex|Lkk^?GKOdNMPSf|JtH4dUh-&LK{jZXNE3NYozi@$_w#g(WDkY!$c!Z2
zKELNUJvz-y4k*r=NYfpP=>qv&1oEW0NTeW*1R2DUD1Ak7Ln++$Q@-O7)u@T$L`oDq
z!^$R$%8+X*vfClT^oai*DoL6{cU+9=%qvSnYRig3IX)o127+>Hj=1g7-K&%lDd!a|
zHbNm<XgSIYbk998B3-NuD_AKSMoi6eDOCoYB4Go=@yYoj=Z9v%H<n{kvBr!}g-Qsj
zFb-v9u9UKz@Da4owCDuA9D!Y~J9%|L+ErT@nSto^&7jz2lSs=FL8c3;14fjlx?^22
z+HpdSsbsUqCI9BkMEsjGMf{sH=5rO6<BPL^xgnykd}+2L{63Y9jHSBVNumU$fur%c
zWHgpyeoMX;mWECcZykxzJ=1Azn+_ALO;h!^rVDW@Ajiy~odRVVnw185To6+(M`3ik
zbb)TPF6|G<kaU+q%T5l2k?m2gbJb3c(wyW)j^7fzazqL;wGf*-Ir1@8FV#x%iy<!!
zqGi^+nS2)~AW9}tv5@hb(kYAO8N%hV&&h^ZnNq5)c5zl^Df%HrB!#c(60Jiml4#j@
zt>lKwma*?lp$jUYydk@BWVxuwhnHart1~hzG?6u<T%r_W6LBaseS<veQL+<Uc&79Y
zC8)UC_`^rbf;lsBf|@<W32OFOCMY8qSdEnK`?U;llTv0O%BnGmDKk-ZT!Hv*y1wbp
zDoCR<bHk#QQfgzhynOoc{u!Didq<YP9AvqUQofwbS%QL|X&4ETvC((=jF4$vhJ;e9
zR0~nbmlc7+p2C_dTSSoMOd;y>>Q+*OUb3gT$<Xg4P1{Q@ai^1Bs3rT}WKs)sekP0j
zOw7)gc}QboxQ41xL@Kpvd%?_XK<QKq1L3dyzf*jy@^D(_;L$lFnVXbat<FuOG)>hs
z)Z&B0gVYpVbAD?0^q5)0&dhd*EcB?Rluj?bVe+Ck7L9wJI>>bCP22a9YKKxsrBxZx
z%s>m-_3<@OCbYa_)XAxNmP3k`SE=%>ap=ze%DkFCYaE66Bt3JTNk2<r>N#d7O@R?k
zk(s8(wZ-pGyHwPi(DRpubYt`!AgVZ-E~RBlq`2V%9++;@5BX}F%`E@8F(*V)3wt=x
zPfrR{bLfYIP5)>?t2!djt_%;)bM=)XlZG|difRsjYL0ZAVAcno8!t`JQ=DF<(k7Z2
zA1g<dO-?8dPgS|8al>~t-r%OmO^cgxZsgCl#g&C)<ZHD;Gi?U7YdmC7n?Y>`wHefA
zP`jN{>SGe2u~g-z#!WriZHEdEn%uOw8Rv#Ul`(GkYlT4-236|ZG`L|zg%K4-RASq9
z9E*F#RT)=hT$OQE##I?tWn7hURn}BvO*KZ;7*S(HEjDjayy2os+{+aVt;H%AHR8S*
z_q=(X_o%bhI%}=7*1G(_(0UBri4`|kaf7#QFsQ+x27?+5YA~q5paz@TWJHq@O-3{s
z(Tq)9EWa_R*&=^;<u?Yk_(O|9Ee5stLyOh4SWT<Ri*=S*O^XrZj2LGG^P<kYs539>
r%!@knqRzaiGcW4njA%2W%?Kt%z0HVr{l7^Jpz#0z00C3{v#kICSvE1`

diff --git a/view/theme/vier/font/fontawesome-webfont.woff2 b/view/theme/vier/font/fontawesome-webfont.woff2
new file mode 100644
index 0000000000000000000000000000000000000000..500e5172534171f678e01f7569d66f9257036a09
GIT binary patch
literal 66624
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
Ugj70-0RR91;1A}g`?1ym0Nn2un*aa+

literal 0
HcmV?d00001

diff --git a/view/theme/vier/templates/wall_thread.tpl b/view/theme/vier/templates/wall_thread.tpl
index 267b35df77..c9ee770819 100644
--- a/view/theme/vier/templates/wall_thread.tpl
+++ b/view/theme/vier/templates/wall_thread.tpl
@@ -91,7 +91,7 @@
 			{{if $item.threaded}}
 			{{/if}}
 			{{if $item.comment}}
-				<a role="button" id="comment-{{$item.id}}" class="fakelink togglecomment" onclick="openClose('item-comments-{{$item.id}}'); commentExpand({{$item.id}});" title="{{$item.switchcomment}}"><i class="icon-reply"><span class="sr-only">{{$item.switchcomment}}</span></i></a>
+				<a role="button" id="comment-{{$item.id}}" class="fakelink togglecomment" onclick="openClose('item-comments-{{$item.id}}'); commentExpand({{$item.id}});" title="{{$item.switchcomment}}"><i class="icon-commenting"><span class="sr-only">{{$item.switchcomment}}</span></i></a>
 			{{/if}}
 
 			{{if $item.isevent}}

From 71227b5d0d5a0110354ec9d5e928cdeb0a832026 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 00:53:30 +0100
Subject: [PATCH 157/273] Receiving should be complete, sending partially works

---
 include/diaspora2.php | 539 ++++++++++++++++++++++++++++++++++++++----
 include/xml.php       |  39 +++
 2 files changed, 538 insertions(+), 40 deletions(-)
 create mode 100644 include/xml.php

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 939a816f40..197cb1da11 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -11,44 +11,8 @@ require_once("include/Contact.php");
 require_once("include/Photo.php");
 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) {
-
-		if (!is_object($xml)) {
-			foreach($array as $key => $value) {
-				$root = new SimpleXMLElement("<".$key."/>");
-				array_to_xml($value, $root);
-
-				$dom = dom_import_simplexml($root)->ownerDocument;
-				$dom->formatOutput = true;
-				return $dom->saveXML();
-			}
-		}
-
-		foreach($array as $key => $value) {
-			if (!is_array($value) AND !is_numeric($key))
-				$xml->addChild($key, $value);
-			elseif (is_array($value))
-				array_to_xml($value, $xml->addChild($key));
-		}
-	}
-
-	function copy(&$source, &$target, $elementname) {
-		if (count($source->children()) == 0)
-			$target->addChild($elementname, $source);
-		else {
-			$child = $target->addChild($elementname);
-			foreach ($source->children() AS $childfield => $childentry)
-				self::copy($childentry, $child, $childfield);
-		}
-	}
-}
+require_once("include/xml.php");
+require_once("include/datetime.php");
 
 /**
  * @brief This class contain functions to create and send Diaspora XML files
@@ -56,6 +20,50 @@ class xml {
  */
 class diaspora {
 
+	public static function fetch_relay() {
+
+		$serverdata = get_config("system", "relay_server");
+		if ($serverdata == "")
+			return array();
+
+		$relay = array();
+
+		$servers = explode(",", $serverdata);
+
+		foreach($servers AS $server) {
+			$server = trim($server);
+			$batch = $server."/receive/public";
+
+			$relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
+
+			if (!$relais) {
+				$addr = "relay@".str_replace("http://", "", normalise_link($server));
+
+				$r = q("INSERT INTO `contact` (`uid`, `created`, `name`, `nick`, `addr`, `url`, `nurl`, `batch`, `network`, `rel`, `blocked`, `pending`, `writable`, `name-date`, `uri-date`, `avatar-date`)
+					VALUES (0, '%s', '%s', 'relay', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, '%s', '%s', '%s')",
+					datetime_convert(),
+					dbesc($addr),
+					dbesc($addr),
+					dbesc($server),
+					dbesc(normalise_link($server)),
+					dbesc($batch),
+					dbesc(NETWORK_DIASPORA),
+					intval(CONTACT_IS_FOLLOWER),
+					dbesc(datetime_convert()),
+					dbesc(datetime_convert()),
+					dbesc(datetime_convert())
+				);
+
+				$relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
+				if ($relais)
+					$relay[] = $relais[0];
+			} else
+				$relay[] = $relais[0];
+		}
+
+		return $relay;
+	}
+
 	/**
 	 * @brief Dispatches public messages and find the fitting receivers
 	 *
@@ -1180,6 +1188,9 @@ EOT;
 	}
 
 	private function receive_request_make_friend($importer, $contact) {
+
+		$a = get_app();
+
 		if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
 			q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
 				intval(CONTACT_IS_FRIEND),
@@ -1204,7 +1215,7 @@ EOT;
 			if($self && $contact["rel"] == CONTACT_IS_FOLLOWER) {
 
 				$arr = array();
-				$arr["uri"] = $arr["parent-uri"] = item_new_uri(App::get_hostname(), $importer["uid"]);
+				$arr["uri"] = $arr["parent-uri"] = item_new_uri($a->get_hostname(), $importer["uid"]);
 				$arr["uid"] = $importer["uid"];
 				$arr["contact-id"] = $self[0]["id"];
 				$arr["wall"] = 1;
@@ -1369,7 +1380,7 @@ EOT;
 
 			// Maybe it is already a reshared item?
 			// Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
-			if (api_share_as_retweet($r[0]))
+			if (self::is_reshare($r[0]["body"]))
 				$r = array();
 			else
 				return $r[0];
@@ -1639,5 +1650,453 @@ EOT;
 
 		return $message_id;
 	}
+
+	/*******************************************************************************************
+	 * Here come all the functions that are needed to transmit data with the Diaspora protocol *
+	 *******************************************************************************************/
+
+	private function get_my_handle($me) {
+		if ($contact["addr"] != "")
+			return $contact["addr"];
+
+		// Normally we should have a filled "addr" field - but in the past this wasn't the case
+		// So - just in case - we build the the address here.
+		return $me["nickname"]."@".substr(App::get_baseurl(), strpos(App::get_baseurl(),"://") + 3);
+	}
+
+	function build_public_message($msg, $user, $contact, $prvkey, $pubkey) {
+
+		logger("Message: ".$msg, LOGGER_DATA);
+
+		$handle = self::get_my_handle($user);
+
+		$b64url_data = base64url_encode($msg);
+
+		$data = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data);
+
+		$type = "application/xml";
+		$encoding = "base64url";
+		$alg = "RSA-SHA256";
+
+		$signable_data = $data.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg);
+
+		$signature = rsa_sign($signable_data,$prvkey);
+		$sig = base64url_encode($signature);
+
+$magic_env = <<< EOT
+<?xml version='1.0' encoding='UTF-8'?>
+<diaspora xmlns="https://joindiaspora.com/protocol" xmlns:me="http://salmon-protocol.org/ns/magic-env" >
+  <header>
+    <author_id>$handle</author_id>
+  </header>
+  <me:env>
+    <me:encoding>base64url</me:encoding>
+    <me:alg>RSA-SHA256</me:alg>
+    <me:data type="application/xml">$data</me:data>
+    <me:sig>$sig</me:sig>
+  </me:env>
+</diaspora>
+EOT;
+
+		logger("magic_env: ".$magic_env, LOGGER_DATA);
+		return $magic_env;
+	}
+
+	private function build_private_message($msg, $user, $contact, $prvkey, $pubkey) {
+
+		logger("Message: ".$msg, LOGGER_DATA);
+
+		// without a public key nothing will work
+
+		if (!$pubkey) {
+			logger("pubkey missing: contact id: ".$contact["id"]);
+			return false;
+		}
+
+		$inner_aes_key = random_string(32);
+		$b_inner_aes_key = base64_encode($inner_aes_key);
+		$inner_iv = random_string(16);
+		$b_inner_iv = base64_encode($inner_iv);
+
+		$outer_aes_key = random_string(32);
+		$b_outer_aes_key = base64_encode($outer_aes_key);
+		$outer_iv = random_string(16);
+		$b_outer_iv = base64_encode($outer_iv);
+
+		$handle = self::get_my_handle($user);
+
+		$padded_data = pkcs5_pad($msg,16);
+		$inner_encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $padded_data, MCRYPT_MODE_CBC, $inner_iv);
+
+		$b64_data = base64_encode($inner_encrypted);
+
+
+		$b64url_data = base64url_encode($b64_data);
+		$data = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data);
+
+		$type = "application/xml";
+		$encoding = "base64url";
+		$alg = "RSA-SHA256";
+
+		$signable_data = $data.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg);
+
+		$signature = rsa_sign($signable_data,$prvkey);
+		$sig = base64url_encode($signature);
+
+$decrypted_header = <<< EOT
+<decrypted_header>
+  <iv>$b_inner_iv</iv>
+  <aes_key>$b_inner_aes_key</aes_key>
+  <author_id>$handle</author_id>
+</decrypted_header>
+EOT;
+
+		$decrypted_header = pkcs5_pad($decrypted_header,16);
+
+		$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $outer_aes_key, $decrypted_header, MCRYPT_MODE_CBC, $outer_iv);
+
+		$outer_json = json_encode(array("iv" => $b_outer_iv, "key" => $b_outer_aes_key));
+
+		$encrypted_outer_key_bundle = "";
+		openssl_public_encrypt($outer_json, $encrypted_outer_key_bundle, $pubkey);
+
+		$b64_encrypted_outer_key_bundle = base64_encode($encrypted_outer_key_bundle);
+
+		logger("outer_bundle: ".$b64_encrypted_outer_key_bundle." key: ".$pubkey, LOGGER_DATA);
+
+		$encrypted_header_json_object = json_encode(array("aes_key" => base64_encode($encrypted_outer_key_bundle),
+								"ciphertext" => base64_encode($ciphertext)));
+		$cipher_json = base64_encode($encrypted_header_json_object);
+
+		$encrypted_header = "<encrypted_header>".$cipher_json."</encrypted_header>";
+
+$magic_env = <<< EOT
+<?xml version='1.0' encoding='UTF-8'?>
+<diaspora xmlns="https://joindiaspora.com/protocol" xmlns:me="http://salmon-protocol.org/ns/magic-env" >
+  $encrypted_header
+  <me:env>
+    <me:encoding>base64url</me:encoding>
+    <me:alg>RSA-SHA256</me:alg>
+    <me:data type="application/xml">$data</me:data>
+    <me:sig>$sig</me:sig>
+  </me:env>
+</diaspora>
+EOT;
+
+		logger("magic_env: ".$magic_env, LOGGER_DATA);
+		return $magic_env;
+	}
+
+	private function build_message($msg, $user, $contact, $prvkey, $pubkey, $public = false) {
+
+		if ($public)
+			$magic_env =  self::build_public_message($msg,$user,$contact,$prvkey,$pubkey);
+		else
+			$magic_env =  self::build_private_message($msg,$user,$contact,$prvkey,$pubkey);
+
+		// The data that will be transmitted is double encoded via "urlencode", strange ...
+		$slap = "xml=".urlencode(urlencode($magic_env));
+		return $slap;
+	}
+
+	private function transmit($owner, $contact, $slap, $public_batch, $queue_run=false, $guid = "") {
+
+		$a = get_app();
+
+		$enabled = intval(get_config("system", "diaspora_enabled"));
+		if(!$enabled)
+			return 200;
+
+		$logid = random_string(4);
+		$dest_url = (($public_batch) ? $contact["batch"] : $contact["notify"]);
+		if (!$dest_url) {
+			logger("no url for contact: ".$contact["id"]." batch mode =".$public_batch);
+			return 0;
+		}
+
+		logger("transmit: ".$logid."-".$guid." ".$dest_url);
+
+		if (!$queue_run && was_recently_delayed($contact["id"])) {
+			$return_code = 0;
+		} else {
+			if (!intval(get_config("system", "diaspora_test"))) {
+				post_url($dest_url."/", $slap);
+				$return_code = $a->get_curl_code();
+			} else {
+				logger("test_mode");
+				return 200;
+			}
+		}
+
+		logger("transmit: ".$logid."-".$guid." returns: ".$return_code);
+
+		if(!$return_code || (($return_code == 503) && (stristr($a->get_curl_headers(), "retry-after")))) {
+			logger("queue message");
+
+			$r = q("SELECT `id` FROM `queue` WHERE `cid` = %d AND `network` = '%s' AND `content` = '%s' AND `batch` = %d LIMIT 1",
+				intval($contact["id"]),
+				dbesc(NETWORK_DIASPORA),
+				dbesc($slap),
+				intval($public_batch)
+			);
+			if(count($r)) {
+				logger("add_to_queue ignored - identical item already in queue");
+			} else {
+				// queue message for redelivery
+				add_to_queue($contact["id"], NETWORK_DIASPORA, $slap, $public_batch);
+			}
+		}
+
+
+		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(
+										"sender_handle" => $myaddr,
+										"recipient_handle" => $theiraddr
+									))));
+
+		$msg = xml::from_array($data, $xml);
+
+		$slap = self::build_message($msg, $me, $contact, $me["prvkey"], $contact["pubkey"]);
+
+		return(self::transmit($owner,$contact,$slap, false));
+
+	}
+
+	public static function send_unshare($me,$contact) {
+		$myaddr = self::get_my_handle($me);
+
+		$data = array("XML" => array("post" => array("retraction" => array(
+										"post_guid" => $me["guid"],
+										"diaspora_handle" => $myaddr,
+										"type" => "Person"
+									))));
+
+		$msg = xml::from_array($data, $xml);
+
+		$slap = self::build_message($msg, $me, $contact, $me["prvkey"], $contact["pubkey"]);
+
+		return(self::transmit($owner,$contact,$slap, false));
+	}
+
+	function is_reshare($body) {
+		$body = trim($body);
+
+		// Skip if it isn't a pure repeated messages
+		// Does it start with a share?
+		if (strpos($body, "[share") > 0)
+			return(false);
+
+		// Does it end with a share?
+		if (strlen($body) > (strrpos($body, "[/share]") + 8))
+			return(false);
+
+		$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
+		// Skip if there is no shared message in there
+		if ($body == $attributes)
+			return(false);
+
+		$guid = "";
+		preg_match("/guid='(.*?)'/ism", $attributes, $matches);
+		if ($matches[1] != "")
+			$guid = $matches[1];
+
+		preg_match('/guid="(.*?)"/ism', $attributes, $matches);
+		if ($matches[1] != "")
+			$guid = $matches[1];
+
+		if ($guid != "") {
+			$r = q("SELECT `contact-id` FROM `item` WHERE `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1",
+				dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA);
+			if ($r) {
+				$ret= array();
+				$ret["root_handle"] = diaspora_handle_from_contact($r[0]["contact-id"]);
+				$ret["root_guid"] = $guid;
+				return($ret);
+			}
+		}
+
+		$profile = "";
+		preg_match("/profile='(.*?)'/ism", $attributes, $matches);
+		if ($matches[1] != "")
+			$profile = $matches[1];
+
+		preg_match('/profile="(.*?)"/ism', $attributes, $matches);
+		if ($matches[1] != "")
+			$profile = $matches[1];
+
+		$ret= array();
+
+		$ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile);
+		if (($ret["root_handle"] == $profile) OR ($ret["root_handle"] == ""))
+			return(false);
+
+		$link = "";
+		preg_match("/link='(.*?)'/ism", $attributes, $matches);
+		if ($matches[1] != "")
+			$link = $matches[1];
+
+		preg_match('/link="(.*?)"/ism', $attributes, $matches);
+		if ($matches[1] != "")
+			$link = $matches[1];
+
+		$ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link);
+		if (($ret["root_guid"] == $link) OR ($ret["root_guid"] == ""))
+			return(false);
+		return($ret);
+	}
+
+	function send_status($item, $owner, $contact, $public_batch = false) {
+
+		$myaddr = self::get_my_handle($owner);
+		$theiraddr = $contact["addr"];
+
+		$title = $item["title"];
+		$body = $item["body"];
+
+		// convert to markdown
+		$body = html_entity_decode(bb2diaspora($body));
+
+		// Adding the title
+		if(strlen($title))
+			$body = "## ".html_entity_decode($title)."\n\n".$body;
+
+		if ($item["attach"]) {
+			$cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism', $item["attach"], $matches, PREG_SET_ORDER);
+			if(cnt) {
+				$body .= "\n".t("Attachments:")."\n";
+				foreach($matches as $mtch)
+					$body .= "[".$mtch[3]."](".$mtch[1].")\n";
+			}
+		}
+
+
+		$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();
+
+			if ($item["location"] != "")
+				$location["address"] = $item["location"];
+
+			if ($item["coord"] != "") {
+				$coord = explode(" ", $item["coord"]);
+				$location["lat"] = $coord[0];
+				$location["lng"] = $coord[1];
+			}
+
+			$message = array("raw_message" => $body,
+					"location" => $location,
+					"guid" => $item["guid"],
+					"diaspora_handle" => $myaddr,
+					"public" => $public,
+					"created_at" => $created,
+					"provider_display_name" => $item["app"]);
+
+			if (count($location) == 0)
+				unset($message["location"]);
+
+			$data = array("XML" => array("post" => array("status_message" => $message)));
+		}
+
+		$msg = xml::from_array($data, $xml);
+
+		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;
+	}
+
+	function send_mail($item,$owner,$contact) {
+
+		$myaddr = self::get_my_handle($owner);
+
+		$r = q("SELECT * FROM `conv` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+			intval($item["convid"]),
+			intval($item["uid"])
+		);
+
+		if (!count($r)) {
+			logger("conversation not found.");
+			return;
+		}
+		$cnv = $r[0];
+
+		$conv = array(
+			"guid" => $cnv["guid"],
+			"subject" => $cnv["subject"],
+			"created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d H:i:s \U\T\C'),
+			"diaspora_handle" => $cnv["creator"],
+			"participant_handles" => $cnv["recips"]
+		);
+
+		$body = bb2diaspora($item["body"]);
+		$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'];
+
+		$sig = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
+
+		$msg = array(
+			"guid" => $item["guid"],
+			"parent_guid" => $cnv["guid"],
+			"parent_author_signature" => $sig,
+			"author_signature" => $sig,
+			"text" => $body,
+			"created_at" => $created,
+			"diaspora_handle" => $myaddr,
+			"conversation_guid" => $cnv["guid"]
+		);
+
+		if ($item["reply"])
+			$data = array("XML" => array("post" => array("message" => $msg)));
+		else {
+			$message = array("guid" => $cnv["guid"],
+					"subject" => $cnv["subject"],
+					"created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d H:i:s \U\T\C'),
+					"message" => $msg,
+					"diaspora_handle" => $cnv["creator"],
+					"participant_handles" => $cnv["recips"]);
+
+			$data = array("XML" => array("post" => array("conversation" => $message)));
+		}
+
+		$xmsg = xml::from_array($data, $xml);
+
+		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;
+	}
 }
 ?>
diff --git a/include/xml.php b/include/xml.php
new file mode 100644
index 0000000000..e46f53acc0
--- /dev/null
+++ b/include/xml.php
@@ -0,0 +1,39 @@
+<?php
+/**
+ * @brief This class contain functions to work with XML data
+ *
+ */
+class xml {
+	function from_array($array, &$xml) {
+
+		if (!is_object($xml)) {
+			foreach($array as $key => $value) {
+				$root = new SimpleXMLElement("<".$key."/>");
+				self::from_array($value, $root);
+
+				$dom = dom_import_simplexml($root)->ownerDocument;
+				$dom->formatOutput = true;
+				$xml = $dom;
+				return $dom->saveXML();
+			}
+		}
+
+		foreach($array as $key => $value) {
+			if (!is_array($value) AND !is_numeric($key))
+				$xml->addChild($key, $value);
+			elseif (is_array($value))
+				self::from_array($value, $xml->addChild($key));
+		}
+	}
+
+	function copy(&$source, &$target, $elementname) {
+		if (count($source->children()) == 0)
+			$target->addChild($elementname, $source);
+		else {
+			$child = $target->addChild($elementname);
+			foreach ($source->children() AS $childfield => $childentry)
+				self::copy($childentry, $child, $childfield);
+		}
+	}
+}
+?>

From 6468fbb9051ab6fe09bfcaaf0f46ce03491ace4f Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 01:37:47 +0100
Subject: [PATCH 158/273] Retraction could work now as well.

---
 include/diaspora2.php                        | 34 ++++++++++++++++++++
 include/xml.php                              |  2 +-
 view/templates/diaspora_relay_retraction.tpl |  5 ++-
 3 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 197cb1da11..c745ab8366 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -2031,6 +2031,40 @@ EOT;
 		return $return_code;
 	}
 
+	function send_retraction($item, $owner, $contact, $public_batch = false) {
+
+		$myaddr = self::get_my_handle($owner);
+
+		// Check whether the retraction is for a top-level post or whether it's a relayable
+		if ($item["uri"] !== $item["parent-uri"]) {
+			$msg_type = "relayable_retraction";
+			$target_type = (($item["verb"] === ACTIVITY_LIKE) ? "Like" : "Comment");
+		} else {
+			$msg_type = "signed_retraction";
+			$target_type = "StatusMessage";
+		}
+
+		$signed_text = $item["guid"].";".$target_type;
+
+		$message = array("target_guid" => $item['guid'],
+				"target_type" => $target_type,
+				"sender_handle" => $myaddr,
+				"target_author_signature" => base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')));
+
+		$data = array("XML" => array("post" => array($msg_type => $message)));
+		$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;
+	}
+
 	function send_mail($item,$owner,$contact) {
 
 		$myaddr = self::get_my_handle($owner);
diff --git a/include/xml.php b/include/xml.php
index e46f53acc0..9c458dab12 100644
--- a/include/xml.php
+++ b/include/xml.php
@@ -20,7 +20,7 @@ class xml {
 
 		foreach($array as $key => $value) {
 			if (!is_array($value) AND !is_numeric($key))
-				$xml->addChild($key, $value);
+				$xml->addChild($key, xmlify($value));
 			elseif (is_array($value))
 				self::from_array($value, $xml->addChild($key));
 		}
diff --git a/view/templates/diaspora_relay_retraction.tpl b/view/templates/diaspora_relay_retraction.tpl
index b3f97a2e13..c4b44cd05f 100644
--- a/view/templates/diaspora_relay_retraction.tpl
+++ b/view/templates/diaspora_relay_retraction.tpl
@@ -1,11 +1,10 @@
-
 <XML>
   <post>
     <relayable_retraction>
-      <target_type>{{$type}}</target_type>
       <target_guid>{{$guid}}</target_guid>
-      <target_author_signature>{{$signature}}</target_author_signature>
+      <target_type>{{$type}}</target_type>
       <sender_handle>{{$handle}}</sender_handle>
+      <target_author_signature>{{$signature}}</target_author_signature>
     </relayable_retraction>
   </post>
 </XML>

From af7b028b13b411bb241dacf488b1085dbaf26780 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 11:41:51 +0100
Subject: [PATCH 159/273] Preparation for followups

---
 include/diaspora2.php | 77 ++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 72 insertions(+), 5 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index c745ab8366..ef1b1c3801 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -1664,7 +1664,7 @@ EOT;
 		return $me["nickname"]."@".substr(App::get_baseurl(), strpos(App::get_baseurl(),"://") + 3);
 	}
 
-	function build_public_message($msg, $user, $contact, $prvkey, $pubkey) {
+	private function build_public_message($msg, $user, $contact, $prvkey, $pubkey) {
 
 		logger("Message: ".$msg, LOGGER_DATA);
 
@@ -1884,7 +1884,7 @@ EOT;
 		return(self::transmit($owner,$contact,$slap, false));
 	}
 
-	function is_reshare($body) {
+	private function is_reshare($body) {
 		$body = trim($body);
 
 		// Skip if it isn't a pure repeated messages
@@ -1951,7 +1951,7 @@ EOT;
 		return($ret);
 	}
 
-	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);
 		$theiraddr = $contact["addr"];
@@ -2030,8 +2030,75 @@ EOT;
 
 		return $return_code;
 	}
+/*
+	public static function diaspora_send_followup($item,$owner,$contact,$public_batch = false) {
 
-	function send_retraction($item, $owner, $contact, $public_batch = false) {
+		$myaddr = self::get_my_handle($owner);
+
+		// 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;
+
+		if($item['verb'] === ACTIVITY_LIKE) {
+			$tpl = get_markup_template('diaspora_like.tpl');
+			$like = true;
+			$target_type = ( $parent['uri'] === $parent['parent-uri']  ? 'Post' : 'Comment');
+			$positive = 'true';
+
+			if(($item['deleted']))
+				logger('diaspora_send_followup: received deleted "like". Those should go to diaspora_send_retraction');
+		} else {
+			$tpl = get_markup_template('diaspora_comment.tpl');
+			$like = false;
+		}
+
+		$text = html_entity_decode(bb2diaspora($item['body']));
+
+		// sign it
+
+		if($like)
+			$signed_text =  $positive . ';' . $item['guid'] . ';' . $target_type . ';' . $parent['guid'] . ';' . $myaddr;
+		else
+			$signed_text = $item['guid'] . ';' . $parent['guid'] . ';' . $text . ';' . $myaddr;
+
+		$authorsig = 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),
+			'$body' => xmlify($text),
+			'$positive' => xmlify($positive),
+				'$handle' => xmlify($myaddr)
+			));
+
+		logger('diaspora_followup: 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)));
+
+		return(diaspora_transmit($owner,$contact,$slap,$public_batch,false,$item['guid']));
+	}
+*/
+	public static function send_retraction($item, $owner, $contact, $public_batch = false) {
 
 		$myaddr = self::get_my_handle($owner);
 
@@ -2065,7 +2132,7 @@ EOT;
 		return $return_code;
 	}
 
-	function send_mail($item,$owner,$contact) {
+	public static function send_mail($item,$owner,$contact) {
 
 		$myaddr = self::get_my_handle($owner);
 

From 8752ec11b244e975bbf2c7589e859bfba38977d3 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 13:15:27 +0100
Subject: [PATCH 160/273] Central function for default group, special setting
 for OStatus

---
 include/diaspora.php |  8 +++-----
 include/follow.php   |  8 +++-----
 include/group.php    | 32 ++++++++++++++++++++++++++++++--
 mod/dfrn_confirm.php |  9 +++------
 mod/dfrn_request.php | 20 ++++++++------------
 mod/settings.php     |  4 ++++
 6 files changed, 51 insertions(+), 30 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 93fe2a472f..635c1aabc3 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -700,12 +700,10 @@ function diaspora_request($importer,$xml) {
 		return;
 	}
 
-	$g = q("select def_gid from user where uid = %d limit 1",
-		intval($importer['uid'])
-	);
-	if($g && intval($g[0]['def_gid'])) {
+	$def_gid = get_default_group($importer['uid'], $ret["network"]);
+	if (intval($def_gid)) {
 		require_once('include/group.php');
-		group_add_member($importer['uid'],'',$contact_record['id'],$g[0]['def_gid']);
+		group_add_member($importer['uid'], '', $contact_record['id'], $def_gid);
 	}
 
 	if($importer['page-flags'] == PAGE_NORMAL) {
diff --git a/include/follow.php b/include/follow.php
index 410e0e58aa..3af629536d 100644
--- a/include/follow.php
+++ b/include/follow.php
@@ -258,12 +258,10 @@ function new_contact($uid,$url,$interactive = false) {
 	$contact_id  = $r[0]['id'];
 	$result['cid'] = $contact_id;
 
-	$g = q("select def_gid from user where uid = %d limit 1",
-		intval($uid)
-	);
-	if($g && intval($g[0]['def_gid'])) {
+	$def_gid = get_default_group($uid, $contact["network"]);
+	if (intval($def_gid)) {
 		require_once('include/group.php');
-		group_add_member($uid,'',$contact_id,$g[0]['def_gid']);
+		group_add_member($uid, '', $contact_id, $def_gid);
 	}
 
 	require_once("include/Photo.php");
diff --git a/include/group.php b/include/group.php
index 2b872f16a7..00b66ad586 100644
--- a/include/group.php
+++ b/include/group.php
@@ -188,7 +188,7 @@ function group_public_members($gid) {
 }
 
 
-function mini_group_select($uid,$gid = 0) {
+function mini_group_select($uid,$gid = 0, $label = "") {
 
 	$grps = array();
 	$o = '';
@@ -205,8 +205,11 @@ function mini_group_select($uid,$gid = 0) {
 	}
 	logger('groups: ' . print_r($grps,true));
 
+	if ($label == "")
+		$label = t('Default privacy group for new contacts');
+
 	$o = replace_macros(get_markup_template('group_selection.tpl'), array(
-		'$label' => t('Default privacy group for new contacts'),
+		'$label' => $label,
 		'$groups' => $grps
 	));
 	return $o;
@@ -375,3 +378,28 @@ function groups_count_unseen() {
 
 	return $r;
 }
+
+/**
+ * @brief Returns the default group for a given user and network
+ *
+ * @param int $uid User id
+ * @param string $network network name
+ *
+ * @return int group id
+ */
+function get_default_group($uid, $network = "") {
+
+	$default_group = 0;
+
+	if ($network == NETWORK_OSTATUS)
+		$default_group = get_pconfig($uid, "ostatus", "default_group");
+
+	if ($default_group != 0)
+		return $default_group;
+
+	$g = q("SELECT `def_gid` FROM `user` WHERE `uid` = %d LIMIT 1", intval($uid));
+	if($g && intval($g[0]["def_gid"]))
+		$default_group = $g[0]["def_gid"];
+
+	return $default_group;
+}
diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php
index 27c04a908d..68950ec285 100644
--- a/mod/dfrn_confirm.php
+++ b/mod/dfrn_confirm.php
@@ -489,13 +489,10 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
 			}
 		}
 
-
-		$g = q("select def_gid from user where uid = %d limit 1",
-			intval($uid)
-		);
-		if($contact && $g && intval($g[0]['def_gid'])) {
+		$def_gid = get_default_group($uid, $contact["network"]);
+		if($contact && intval($def_gid)) {
 			require_once('include/group.php');
-			group_add_member($uid,'',$contact['id'],$g[0]['def_gid']);
+			group_add_member($uid, '', $contact['id'], $def_gid);
 		}
 
 		// Let's send our user to the contact editor in case they want to
diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php
index 5455996069..837eec2dd2 100644
--- a/mod/dfrn_request.php
+++ b/mod/dfrn_request.php
@@ -174,18 +174,16 @@ function dfrn_request_post(&$a) {
 					info( t("Introduction complete.") . EOL);
 				}
 
-				$r = q("select id from contact where uid = %d and url = '%s' and `site-pubkey` = '%s' limit 1",
+				$r = q("SELECT `id`, `network` FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `site-pubkey` = '%s' LIMIT 1",
 					intval(local_user()),
 					dbesc($dfrn_url),
 					$parms['key'] // this was already escaped
 				);
 				if(count($r)) {
-					$g = q("select def_gid from user where uid = %d limit 1",
-						intval(local_user())
-					);
-					if($g && intval($g[0]['def_gid'])) {
+					$def_gid = get_default_group(local_user(), $r[0]["network"]);
+					if(intval($def_gid)) {
 						require_once('include/group.php');
-						group_add_member(local_user(),'',$r[0]['id'],$g[0]['def_gid']);
+						group_add_member(local_user(), '', $r[0]['id'], $def_gid);
 					}
 					$forwardurl = $a->get_baseurl()."/contacts/".$r[0]['id'];
 				} else
@@ -388,19 +386,17 @@ function dfrn_request_post(&$a) {
 				intval($rel)
 			);
 
-			$r = q("select id from contact where poll = '%s' and uid = %d limit 1",
+			$r = q("SELECT `id`, `network` FROM `contact` WHERE `poll` = '%s' AND `uid` = %d LIMIT 1",
 				dbesc($poll),
 				intval($uid)
 			);
 			if(count($r)) {
 				$contact_id = $r[0]['id'];
 
-				$g = q("select def_gid from user where uid = %d limit 1",
-					intval($uid)
-				);
-				if($g && intval($g[0]['def_gid'])) {
+				$def_gid = get_default_group($uid, $r[0]["network"]);
+				if (intval($def_gid)) {
 					require_once('include/group.php');
-					group_add_member($uid,'',$contact_id,$g[0]['def_gid']);
+					group_add_member($uid, '', $contact_id, $def_gid);
 				}
 
 				$photo = avatar_img($addr);
diff --git a/mod/settings.php b/mod/settings.php
index 905a5ed08d..67513e533e 100644
--- a/mod/settings.php
+++ b/mod/settings.php
@@ -199,6 +199,7 @@ function settings_post(&$a) {
 		if(x($_POST, 'general-submit')) {
 			set_pconfig(local_user(), 'system', 'no_intelligent_shortening', intval($_POST['no_intelligent_shortening']));
 			set_pconfig(local_user(), 'system', 'ostatus_autofriend', intval($_POST['snautofollow']));
+			set_pconfig(local_user(), 'ostatus', 'default_group', $_POST['group-selection']);
 			set_pconfig(local_user(), 'ostatus', 'legacy_contact', $_POST['legacy_contact']);
 		} elseif(x($_POST, 'imap-submit')) {
 
@@ -797,8 +798,11 @@ function settings_content(&$a) {
 		$settings_connectors .= '<span class="field_help">'.t('If you receive a message from an unknown OStatus user, this option decides what to do. If it is checked, a new contact will be created for every unknown user.').'</span>';
 		$settings_connectors .= '</div>';
 
+		$default_group = get_pconfig(local_user(), 'ostatus', 'default_group');
 		$legacy_contact = get_pconfig(local_user(), 'ostatus', 'legacy_contact');
 
+		$settings_connectors .= mini_group_select(local_user(), $default_group, t("Default group for OStatus followers"));
+
 		if ($legacy_contact != "")
 			$a->page['htmlhead'] = '<meta http-equiv="refresh" content="0; URL='.$a->get_baseurl().'/ostatus_subscribe?url='.urlencode($legacy_contact).'">';
 

From 4ef33b4d5b874931a5b40600ecbf189b9046693d Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 13:26:30 +0100
Subject: [PATCH 161/273] Clarification of description

---
 mod/settings.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mod/settings.php b/mod/settings.php
index 67513e533e..0c3b23a44b 100644
--- a/mod/settings.php
+++ b/mod/settings.php
@@ -801,7 +801,7 @@ function settings_content(&$a) {
 		$default_group = get_pconfig(local_user(), 'ostatus', 'default_group');
 		$legacy_contact = get_pconfig(local_user(), 'ostatus', 'legacy_contact');
 
-		$settings_connectors .= mini_group_select(local_user(), $default_group, t("Default group for OStatus followers"));
+		$settings_connectors .= mini_group_select(local_user(), $default_group, t("Default group for OStatus contacts"));
 
 		if ($legacy_contact != "")
 			$a->page['htmlhead'] = '<meta http-equiv="refresh" content="0; URL='.$a->get_baseurl().'/ostatus_subscribe?url='.urlencode($legacy_contact).'">';

From bb06026147394db074312a8b77981f1df8b85294 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 14:09:04 +0100
Subject: [PATCH 162/273] Settings for only importing threads from our ostatus
 contacts

---
 mod/admin.php                 | 3 +++
 view/templates/admin_site.tpl | 1 +
 2 files changed, 4 insertions(+)

diff --git a/mod/admin.php b/mod/admin.php
index a98f464f81..f6958098b8 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -598,6 +598,7 @@ function admin_page_site_post(&$a) {
 	$dfrn_only		=	((x($_POST,'dfrn_only'))		? True						: False);
 	$ostatus_disabled	=	!((x($_POST,'ostatus_disabled'))	? True  					: False);
 	$ostatus_poll_interval	=	((x($_POST,'ostatus_poll_interval'))	? intval(trim($_POST['ostatus_poll_interval']))	:  0);
+	$ostatus_full_threads	=	((x($_POST,'ostatus_full_threads'))	? True  					: False);
 	$diaspora_enabled	=	((x($_POST,'diaspora_enabled'))		? True   					: False);
 	$ssl_policy		=	((x($_POST,'ssl_policy'))		? intval($_POST['ssl_policy']) 			: 0);
 	$force_ssl		=	((x($_POST,'force_ssl'))		? True   					: False);
@@ -746,6 +747,7 @@ function admin_page_site_post(&$a) {
 	set_config('system','dfrn_only', $dfrn_only);
 	set_config('system','ostatus_disabled', $ostatus_disabled);
 	set_config('system','ostatus_poll_interval', $ostatus_poll_interval);
+	set_config('system','ostatus_full_threads', $ostatus_full_threads);
 	set_config('system','diaspora_enabled', $diaspora_enabled);
 
 	set_config('config','private_addons', $private_addons);
@@ -947,6 +949,7 @@ function admin_page_site(&$a) {
 		'$max_author_posts_community_page' => array('max_author_posts_community_page', t("Posts per user on community page"), get_config('system','max_author_posts_community_page'), t("The maximum number of posts per user on the community page. (Not valid for 'Global Community')")),
 		'$ostatus_disabled' 	=> array('ostatus_disabled', t("Enable OStatus support"), !get_config('system','ostatus_disabled'), t("Provide built-in OStatus \x28StatusNet, GNU Social etc.\x29 compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed.")),
 		'$ostatus_poll_interval' => array('ostatus_poll_interval', t("OStatus conversation completion interval"), (string) intval(get_config('system','ostatus_poll_interval')), t("How often shall the poller check for new entries in OStatus conversations? This can be a very ressource task."), $ostatus_poll_choices),
+		'$ostatus_full_threads'	=> array('ostatus_disabled', t("Only import OStatus threads from our contacts"), get_config('system','ostatus_full_threads'), t("Normally we import every content from our OStatus contacts. With this option we only store threads that are started by a contact that is known on our system.")),
 		'$ostatus_not_able'	=> t("OStatus support can only be enabled if threading is enabled."),
 		'$diaspora_able'	=> $diaspora_able,
 		'$diaspora_not_able'	=> t("Diaspora support can't be enabled because Friendica was installed into a sub directory."),
diff --git a/view/templates/admin_site.tpl b/view/templates/admin_site.tpl
index b08e5f935f..91957d016a 100644
--- a/view/templates/admin_site.tpl
+++ b/view/templates/admin_site.tpl
@@ -87,6 +87,7 @@
 	{{if $thread_allow.2}}
 		{{include file="field_checkbox.tpl" field=$ostatus_disabled}}
 		{{include file="field_select.tpl" field=$ostatus_poll_interval}}
+		{{include file="field_checkbox.tpl" field=$ostatus_full_threads}}
 	{{else}}
 		<div class='field checkbox' id='div_id_{{$ostatus_disabled.0}}'>
 			<label for='id_{{$ostatus_disabled.0}}'>{{$ostatus_disabled.1}}</label>

From 4bd1061a095a0fd80c69e2151b3fcf0a232a0169 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 14:53:30 +0100
Subject: [PATCH 163/273] Only import OStatus threads if we follow the thread
 starter

---
 boot.php            | 3 +++
 include/ostatus.php | 7 +++++++
 mod/admin.php       | 2 +-
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/boot.php b/boot.php
index 0a2f5c50cd..5cc3499311 100644
--- a/boot.php
+++ b/boot.php
@@ -1509,6 +1509,9 @@ function killme() {
  * @brief Redirect to another URL and terminate this process.
  */
 function goaway($s) {
+	if (!strstr(normalise_link($s), normalise_link(App::get_baseurl())))
+		$s = App::get_baseurl()."/".$s;
+
 	header("Location: $s");
 	killme();
 }
diff --git a/include/ostatus.php b/include/ostatus.php
index 5c5016d0fc..40df688ea7 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -809,6 +809,13 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 			// 2. This first post is a post inside our thread
 			// 3. This first post is a post inside another thread
 			if (($first_id != $parent["uri"]) AND ($parent["uri"] != "")) {
+
+				// Do we only want to import threads that were started by our contacts?
+				if (get_config('system','ostatus_full_threads')) {
+					logger("Don't import uri ".$first_id." because we don't follow this person.", LOGGER_DEBUG);
+					continue;
+				}
+
 				$new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
 							(SELECT `parent` FROM `item`
 								WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s')) LIMIT 1",
diff --git a/mod/admin.php b/mod/admin.php
index f6958098b8..e7c4f51b66 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -949,7 +949,7 @@ function admin_page_site(&$a) {
 		'$max_author_posts_community_page' => array('max_author_posts_community_page', t("Posts per user on community page"), get_config('system','max_author_posts_community_page'), t("The maximum number of posts per user on the community page. (Not valid for 'Global Community')")),
 		'$ostatus_disabled' 	=> array('ostatus_disabled', t("Enable OStatus support"), !get_config('system','ostatus_disabled'), t("Provide built-in OStatus \x28StatusNet, GNU Social etc.\x29 compatibility. All communications in OStatus are public, so privacy warnings will be occasionally displayed.")),
 		'$ostatus_poll_interval' => array('ostatus_poll_interval', t("OStatus conversation completion interval"), (string) intval(get_config('system','ostatus_poll_interval')), t("How often shall the poller check for new entries in OStatus conversations? This can be a very ressource task."), $ostatus_poll_choices),
-		'$ostatus_full_threads'	=> array('ostatus_disabled', t("Only import OStatus threads from our contacts"), get_config('system','ostatus_full_threads'), t("Normally we import every content from our OStatus contacts. With this option we only store threads that are started by a contact that is known on our system.")),
+		'$ostatus_full_threads'	=> array('ostatus_full_threads', t("Only import OStatus threads from our contacts"), get_config('system','ostatus_full_threads'), t("Normally we import every content from our OStatus contacts. With this option we only store threads that are started by a contact that is known on our system.")),
 		'$ostatus_not_able'	=> t("OStatus support can only be enabled if threading is enabled."),
 		'$diaspora_able'	=> $diaspora_able,
 		'$diaspora_not_able'	=> t("Diaspora support can't be enabled because Friendica was installed into a sub directory."),

From 7f48df63a3b278e1ff44d71b8cfdd8966fce2341 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 15:11:04 +0100
Subject: [PATCH 164/273] Relocated the check.

---
 include/ostatus.php | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index 40df688ea7..8749d3ab21 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -810,12 +810,6 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 			// 3. This first post is a post inside another thread
 			if (($first_id != $parent["uri"]) AND ($parent["uri"] != "")) {
 
-				// Do we only want to import threads that were started by our contacts?
-				if (get_config('system','ostatus_full_threads')) {
-					logger("Don't import uri ".$first_id." because we don't follow this person.", LOGGER_DEBUG);
-					continue;
-				}
-
 				$new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
 							(SELECT `parent` FROM `item`
 								WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s')) LIMIT 1",
@@ -925,6 +919,12 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 		} else {
 			logger("No contact found for url ".$actor, LOGGER_DEBUG);
 
+			// Do we only want to import threads that were started by our contacts?
+			if (get_config('system','ostatus_full_threads')) {
+				logger("Don't import uri ".$first_id." because we don't follow this person.", LOGGER_DEBUG);
+				continue;
+			}
+
 			// Adding a global contact
 			/// @TODO Use this data for the post
 			$global_contact_id = get_contact($actor, 0);

From 279a0453f9d338bae467db4c0aee938798e7c8f3 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 15:13:19 +0100
Subject: [PATCH 165/273] Or back ...

---
 include/ostatus.php | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index 8749d3ab21..40df688ea7 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -810,6 +810,12 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 			// 3. This first post is a post inside another thread
 			if (($first_id != $parent["uri"]) AND ($parent["uri"] != "")) {
 
+				// Do we only want to import threads that were started by our contacts?
+				if (get_config('system','ostatus_full_threads')) {
+					logger("Don't import uri ".$first_id." because we don't follow this person.", LOGGER_DEBUG);
+					continue;
+				}
+
 				$new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
 							(SELECT `parent` FROM `item`
 								WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s')) LIMIT 1",
@@ -919,12 +925,6 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 		} else {
 			logger("No contact found for url ".$actor, LOGGER_DEBUG);
 
-			// Do we only want to import threads that were started by our contacts?
-			if (get_config('system','ostatus_full_threads')) {
-				logger("Don't import uri ".$first_id." because we don't follow this person.", LOGGER_DEBUG);
-				continue;
-			}
-
 			// Adding a global contact
 			/// @TODO Use this data for the post
 			$global_contact_id = get_contact($actor, 0);

From 9579725d4deafdbf123fd2c882be0cff93af4b5b Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 19:27:34 +0100
Subject: [PATCH 166/273] This should work better ...

---
 include/ostatus.php | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index 40df688ea7..44431967ec 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -686,7 +686,8 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 	$conversation_url = ostatus_convert_href($conversation_url);
 
 	// If the thread shouldn't be completed then store the item and go away
-	if ((intval(get_config('system','ostatus_poll_interval')) == -2) AND (count($item) > 0)) {
+	// Don't do a completion on liked content
+	if (((intval(get_config('system','ostatus_poll_interval')) == -2) AND (count($item) > 0)) OR ($item["verb"] == ACTIVITY_LIKE)) {
 		//$arr["app"] .= " (OStatus-NoCompletion)";
 		$item_stored = item_store($item, true);
 		return($item_stored);
@@ -725,7 +726,7 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 	$pageno = 1;
 	$items = array();
 
-	logger('fetching conversation url '.$conv.' for user '.$uid);
+	logger('fetching conversation url '.$conv.' ('.$conversation_url.') for user '.$uid);
 
 	do {
 		$conv_arr = z_fetch_url($conv."?page=".$pageno);
@@ -778,6 +779,8 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 	$r = q("SELECT `nurl` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid));
 	$importer = $r[0];
 
+	$new_parent = true;
+
 	foreach ($items as $single_conv) {
 
 		// Update the gcontact table
@@ -810,11 +813,7 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 			// 3. This first post is a post inside another thread
 			if (($first_id != $parent["uri"]) AND ($parent["uri"] != "")) {
 
-				// Do we only want to import threads that were started by our contacts?
-				if (get_config('system','ostatus_full_threads')) {
-					logger("Don't import uri ".$first_id." because we don't follow this person.", LOGGER_DEBUG);
-					continue;
-				}
+				$new_parent = true;
 
 				$new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
 							(SELECT `parent` FROM `item`
@@ -916,12 +915,14 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 		if (isset($single_conv->actor->url))
 			$actor = $single_conv->actor->url;
 
-		$contact = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
+		$contact = q("SELECT `id`, `rel` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
 				$uid, normalise_link($actor), NETWORK_STATUSNET);
 
 		if (count($contact)) {
 			logger("Found contact for url ".$actor, LOGGER_DEBUG);
 			$contact_id = $contact[0]["id"];
+
+			$not_following = !in_array($contact[0]["rel"], array(CONTACT_IS_SHARING, CONTACT_IS_FRIEND));
 		} else {
 			logger("No contact found for url ".$actor, LOGGER_DEBUG);
 
@@ -932,6 +933,14 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 			logger("Global contact ".$global_contact_id." found for url ".$actor, LOGGER_DEBUG);
 
 			$contact_id = $parent["contact-id"];
+
+			$not_following = true;
+		}
+
+		// Do we only want to import threads that were started by our contacts?
+		if ($not_following AND $new_parent AND get_config('system','ostatus_full_threads')) {
+			logger("Don't import uri ".$first_id." because we don't follow the person ".$actor, LOGGER_DEBUG);
+			continue;
 		}
 
 		$arr = array();

From ef2bc47cc6d8f6be3fda65aec366ad237396a52c Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 20:36:28 +0100
Subject: [PATCH 167/273] New way of fetching the conversation id for thread
 completion

---
 include/ostatus.php | 41 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index 44431967ec..138f510906 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -537,7 +537,7 @@ function ostatus_import($xml,$importer,&$contact, &$hub) {
 		} else
 			$item["parent-uri"] = $item["uri"];
 
-		$item_id = ostatus_completion($conversation, $importer["uid"], $item);
+		$item_id = ostatus_completion($conversation, $importer["uid"], $item, $self);
 
 		if (!$item_id) {
 			logger("Error storing item", LOGGER_DEBUG);
@@ -676,18 +676,49 @@ function ostatus_conv_fetch_actor($actor) {
 	update_gcontact($contact);
 }
 
+function ostatus_fetch_conversation($self, $conversation_url = "") {
 
-function ostatus_completion($conversation_url, $uid, $item = array()) {
+	if ($conversation_url != "") {
+		$elements = explode(":", $conversation_url);
+
+		if ((count($elements) <= 2) OR ($elements[0] != "tag"))
+			return $conversation_url;
+	}
+
+	if ($self == "")
+		return "";
+
+	$json = str_replace(".atom", ".json", $self);
+
+	$raw = fetch_url($json);
+	if ($raw == "")
+		return "";
+
+	$data = json_decode($raw);
+	if (!is_object($data))
+		return "";
+
+	$conversation_id = $data->statusnet_conversation_id;
+
+	$pos = strpos($self, "/api/statuses/show/");
+	$base_url = substr($self, 0, $pos);
+
+	return $base_url."/conversation/".$conversation_id;
+}
+
+function ostatus_completion($conversation_url, $uid, $item = array(), $self = "") {
 
 	$a = get_app();
 
 	$item_stored = -1;
 
-	$conversation_url = ostatus_convert_href($conversation_url);
+	//$conversation_url = ostatus_convert_href($conversation_url);
+	$conversation_url = ostatus_fetch_conversation($self, $conversation_url);
 
 	// If the thread shouldn't be completed then store the item and go away
 	// Don't do a completion on liked content
-	if (((intval(get_config('system','ostatus_poll_interval')) == -2) AND (count($item) > 0)) OR ($item["verb"] == ACTIVITY_LIKE)) {
+	if (((intval(get_config('system','ostatus_poll_interval')) == -2) AND (count($item) > 0)) OR
+		($item["verb"] == ACTIVITY_LIKE) OR ($conversation_url == "")) {
 		//$arr["app"] .= " (OStatus-NoCompletion)";
 		$item_stored = item_store($item, true);
 		return($item_stored);
@@ -726,7 +757,7 @@ function ostatus_completion($conversation_url, $uid, $item = array()) {
 	$pageno = 1;
 	$items = array();
 
-	logger('fetching conversation url '.$conv.' ('.$conversation_url.') for user '.$uid);
+	logger('fetching conversation url '.$conv.' (Self: '.$self.') for user '.$uid);
 
 	do {
 		$conv_arr = z_fetch_url($conv."?page=".$pageno);

From 4ef44c67b84a9f8d66b91a61123b10fe2be75784 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 21:06:52 +0100
Subject: [PATCH 168/273] Added documentation

---
 include/ostatus.php | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index 138f510906..54b70e6d6c 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -676,13 +676,21 @@ function ostatus_conv_fetch_actor($actor) {
 	update_gcontact($contact);
 }
 
-function ostatus_fetch_conversation($self, $conversation_url = "") {
+/**
+ * @brief Fetches the conversation url for a given item link or conversation id
+ *
+ * @param string $self The link to the posting
+ * @param string $conversation_id The conversation id
+ *
+ * @return string The conversation url
+ */
+function ostatus_fetch_conversation($self, $conversation_id = "") {
 
-	if ($conversation_url != "") {
-		$elements = explode(":", $conversation_url);
+	if ($conversation_id != "") {
+		$elements = explode(":", $conversation_id);
 
 		if ((count($elements) <= 2) OR ($elements[0] != "tag"))
-			return $conversation_url;
+			return $conversation_id;
 	}
 
 	if ($self == "")

From 182bee265e3aa68bb9c85f732e8306ef28ab6b1f Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 6 Mar 2016 22:49:50 +0100
Subject: [PATCH 169/273] Sending like and comment should work now.

---
 include/diaspora2.php | 131 ++++++++++++++++++++++++------------------
 1 file changed, 75 insertions(+), 56 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index ef1b1c3801..0ab28d7b2c 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -2030,74 +2030,93 @@ EOT;
 
 		return $return_code;
 	}
-/*
-	public static function diaspora_send_followup($item,$owner,$contact,$public_batch = false) {
+
+	private function construct_like($item,$owner,$contact,$public_batch = false) {
 
 		$myaddr = self::get_my_handle($owner);
 
-		// 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;
+		$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
+			dbesc($item["thr-parent"])
+		      );
+		if(!$p)
+			return false;
 
-		if($item['verb'] === ACTIVITY_LIKE) {
-			$tpl = get_markup_template('diaspora_like.tpl');
-			$like = true;
-			$target_type = ( $parent['uri'] === $parent['parent-uri']  ? 'Post' : 'Comment');
-			$positive = 'true';
+		$parent = $p[0];
 
-			if(($item['deleted']))
-				logger('diaspora_send_followup: received deleted "like". Those should go to diaspora_send_retraction');
-		} else {
-			$tpl = get_markup_template('diaspora_comment.tpl');
-			$like = false;
-		}
-
-		$text = html_entity_decode(bb2diaspora($item['body']));
+		$target_type = ($parent["uri"] === $parent["parent-uri"] ? "Post" : "Comment");
+		$positive = "true";
 
 		// sign it
+		$signed_text =  $positive.";".$item["guid"].";".$target_type.";".$parent["guid"].";".$myaddr;
 
-		if($like)
-			$signed_text =  $positive . ';' . $item['guid'] . ';' . $target_type . ';' . $parent['guid'] . ';' . $myaddr;
-		else
-			$signed_text = $item['guid'] . ';' . $parent['guid'] . ';' . $text . ';' . $myaddr;
+		$authorsig = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
 
-		$authorsig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256'));
+		$message = array("positive" => $positive,
+				"guid" => $item["guid"],
+				"target_type" => $item["guid"],
+				"parent_guid" => $parent["guid"],
+				"author_signature" => $authorsig,
+				"diaspora_handle" => $myaddr);
 
-		$msg = replace_macros($tpl,array(
-			'$guid' => xmlify($item['guid']),
-			'$parent_guid' => xmlify($parent['guid']),
-			'$target_type' =>xmlify($target_type),
-			'$authorsig' => xmlify($authorsig),
-			'$body' => xmlify($text),
-			'$positive' => xmlify($positive),
-				'$handle' => xmlify($myaddr)
-			));
+		$data = array("XML" => array("post" => array("like" => $message)));
 
-		logger('diaspora_followup: 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)));
-
-		return(diaspora_transmit($owner,$contact,$slap,$public_batch,false,$item['guid']));
+		return xml::from_array($data, $xml);
 	}
-*/
+
+	private function construct_comment($item,$owner,$contact,$public_batch = false) {
+
+		$myaddr = self::get_my_handle($owner);
+
+		$p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1",
+			intval($item["parent"]),
+			intval($item["parent"])
+		);
+
+		if (!$p)
+			return false;
+
+		$parent = $p[0];
+
+		$text = html_entity_decode(bb2diaspora($item["body"]));
+
+		// sign it
+		$signed_text = $item["guid"].";".$parent["guid"].";".$text.";".$myaddr;
+
+		$authorsig = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
+
+		$message = array("guid" => $item["guid"],
+				"parent_guid" => $parent["guid"],
+				"author_signature" => $authorsig,
+				"text" => $text,
+				"diaspora_handle" => $myaddr);
+
+		$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) {
+
+		if($item['verb'] === ACTIVITY_LIKE)
+			$msg = self::construct_like($item, $owner, $contact, $public_batch);
+		else
+			$msg = self::construct_comment($item, $owner, $contact, $public_batch);
+
+		if (!$msg)
+			return $msg;
+
+		logger("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, $public_batch, false, $item["guid"]);
+
+		logger("guid: ".$item["guid"]." result ".$return_code, LOGGER_DEBUG);
+
+		return $return_code;
+	}
+
 	public static function send_retraction($item, $owner, $contact, $public_batch = false) {
 
 		$myaddr = self::get_my_handle($owner);

From db15f76177fedd9620ed62518d4c11c6ac493107 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 7 Mar 2016 01:34:06 +0100
Subject: [PATCH 170/273] Relaying is nearly done

---
 include/diaspora2.php | 219 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 203 insertions(+), 16 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 0ab28d7b2c..1cc6e55e3b 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -2063,32 +2063,45 @@ EOT;
 		return xml::from_array($data, $xml);
 	}
 
-	private function construct_comment($item,$owner,$contact,$public_batch = false) {
+	private function construct_comment($item,$owner,$contact,$public_batch = false, $data = null) {
 
-		$myaddr = self::get_my_handle($owner);
+		if (is_array($data))
+			$message = $data;
+		else {
+			$myaddr = self::get_my_handle($owner);
 
-		$p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1",
-			intval($item["parent"]),
-			intval($item["parent"])
-		);
+			$p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1",
+				intval($item["parent"]),
+				intval($item["parent"])
+			);
 
-		if (!$p)
-			return false;
+			if (!$p)
+				return false;
 
-		$parent = $p[0];
+			$parent = $p[0];
 
-		$text = html_entity_decode(bb2diaspora($item["body"]));
+			$text = html_entity_decode(bb2diaspora($item["body"]));
+
+			$message = array("guid" => $item["guid"],
+					"parent_guid" => $parent["guid"],
+					"author_signature" => "",
+					"text" => $text,
+					"diaspora_handle" => $myaddr);
+		}
 
 		// sign it
-		$signed_text = $item["guid"].";".$parent["guid"].";".$text.";".$myaddr;
+		$sigmsg = $message;
+		unset($sigmsg["author_signature"]);
+		unset($sigmsg["parent_author_signature"]);
+
+		$signed_text = implode(";", $sigmsg);
 
 		$authorsig = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
 
-		$message = array("guid" => $item["guid"],
-				"parent_guid" => $parent["guid"],
-				"author_signature" => $authorsig,
-				"text" => $text,
-				"diaspora_handle" => $myaddr);
+		if ($message["author_signature"] == "")
+			$message["author_signature"] = $authorsig;
+		else
+			$message["parent_author_signature"] = $authorsig;
 
 		$data = array("XML" => array("post" => array("comment" => $message)));
 
@@ -2117,6 +2130,180 @@ EOT;
 		return $return_code;
 	}
 
+	function send_relay($item, $owner, $contact, $public_batch = false) {
+
+		if ($item["deleted"])
+			$sql_sign_id = "retract_iid";
+		else
+			$sql_sign_id = "iid";
+
+		// fetch the original signature if the relayable was created by a Diaspora
+		// or DFRN user.
+
+		$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 comment guid
+			$guid = array_shift($signed_parts);
+
+			// Remove the parent guid
+			$parent_guid = array_shift($signed_parts);
+
+			// Remove the handle
+			$handle = array_pop($signed_parts);
+
+			// Glue the parts together
+			$text = implode(";", $signed_parts);
+
+			$data = array("guid" => $guid,
+					"parent_guid" => $parent_guid,
+					"parent_author_signature" => "",
+					"author_signature" => $orig_sign['signature'],
+					"text" => implode(";", $signed_parts),
+					"diaspora_handle" => $handle);
+		}
+
+
+		$myaddr = self::get_my_handle($owner);
+
+		if ($item['deleted'])
+			; // Retraction
+		elseif($item['verb'] === ACTIVITY_LIKE)
+			$msg = self::construct_like($item, $owner, $contact, $public_batch);
+		else
+			$msg = self::construct_comment($item, $owner, $contact, $public_batch, $data);
+die($msg);
+/*
+	// 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) {
 
 		$myaddr = self::get_my_handle($owner);

From 373beb0343738fb357b5fbddd9ec76783b003ad5 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 7 Mar 2016 08:17:21 +0100
Subject: [PATCH 171/273] Relayed Likes and relayed comments should work, code
 needs beautification

---
 include/diaspora2.php | 122 +++++++++++++++++++++++++-----------------
 1 file changed, 74 insertions(+), 48 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 1cc6e55e3b..48093cc5b9 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -1799,6 +1799,16 @@ EOT;
 		return $slap;
 	}
 
+	private function get_signature($owner, $message) {
+		$sigmsg = $message;
+		unset($sigmsg["author_signature"]);
+		unset($sigmsg["parent_author_signature"]);
+
+		$signed_text = implode(";", $sigmsg);
+
+		return base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
+	}
+
 	private function transmit($owner, $contact, $slap, $public_batch, $queue_run=false, $guid = "") {
 
 		$a = get_app();
@@ -2031,32 +2041,37 @@ EOT;
 		return $return_code;
 	}
 
-	private function construct_like($item,$owner,$contact,$public_batch = false) {
+	private function construct_like($item,$owner,$contact,$public_batch = false, $data = null) {
 
-		$myaddr = self::get_my_handle($owner);
+		if (is_array($data))
+			$message = $data;
+		else {
+			$myaddr = self::get_my_handle($owner);
 
-		$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
-			dbesc($item["thr-parent"])
-		      );
-		if(!$p)
-			return false;
+			$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
+				dbesc($item["thr-parent"]));
+			if(!$p)
+				return false;
 
-		$parent = $p[0];
+			$parent = $p[0];
 
-		$target_type = ($parent["uri"] === $parent["parent-uri"] ? "Post" : "Comment");
-		$positive = "true";
+			$target_type = ($parent["uri"] === $parent["parent-uri"] ? "Post" : "Comment");
+			$positive = "true";
 
-		// sign it
-		$signed_text =  $positive.";".$item["guid"].";".$target_type.";".$parent["guid"].";".$myaddr;
+			$message = array("positive" => $positive,
+					"guid" => $item["guid"],
+					"target_type" => $target_type,
+					"parent_guid" => $parent["guid"],
+					"author_signature" => $authorsig,
+					"diaspora_handle" => $myaddr);
+		}
 
-		$authorsig = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
+		$authorsig = self::get_signature($owner, $message);
 
-		$message = array("positive" => $positive,
-				"guid" => $item["guid"],
-				"target_type" => $item["guid"],
-				"parent_guid" => $parent["guid"],
-				"author_signature" => $authorsig,
-				"diaspora_handle" => $myaddr);
+		if ($message["author_signature"] == "")
+			$message["author_signature"] = $authorsig;
+		else
+			$message["parent_author_signature"] = $authorsig;
 
 		$data = array("XML" => array("post" => array("like" => $message)));
 
@@ -2089,14 +2104,7 @@ EOT;
 					"diaspora_handle" => $myaddr);
 		}
 
-		// sign it
-		$sigmsg = $message;
-		unset($sigmsg["author_signature"]);
-		unset($sigmsg["parent_author_signature"]);
-
-		$signed_text = implode(";", $sigmsg);
-
-		$authorsig = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
+		$authorsig = self::get_signature($owner, $message);
 
 		if ($message["author_signature"] == "")
 			$message["author_signature"] = $authorsig;
@@ -2153,36 +2161,56 @@ EOT;
 			// Split the signed text
 			$signed_parts = explode(";", $signed_text);
 
-			// Remove the comment guid
-			$guid = array_shift($signed_parts);
+			if ($item['verb'] === ACTIVITY_LIKE) {
+				$data = array("positive" => $signed_parts[0],
+						"guid" => $signed_parts[1],
+						"target_type" => $signed_parts[2],
+						"parent_guid" => $signed_parts[3],
+						"parent_author_signature" => "",
+						"author_signature" => $orig_sign['signature'],
+						"diaspora_handle" => $signed_parts[4]);
+			} else {
+				// Remove the comment guid
+				$guid = array_shift($signed_parts);
 
-			// Remove the parent guid
-			$parent_guid = array_shift($signed_parts);
+				// Remove the parent guid
+				$parent_guid = array_shift($signed_parts);
 
-			// Remove the handle
-			$handle = array_pop($signed_parts);
+				// Remove the handle
+				$handle = array_pop($signed_parts);
 
-			// Glue the parts together
-			$text = implode(";", $signed_parts);
+				// Glue the parts together
+				$text = implode(";", $signed_parts);
 
-			$data = array("guid" => $guid,
-					"parent_guid" => $parent_guid,
-					"parent_author_signature" => "",
-					"author_signature" => $orig_sign['signature'],
-					"text" => implode(";", $signed_parts),
-					"diaspora_handle" => $handle);
+				$data = array("guid" => $guid,
+						"parent_guid" => $parent_guid,
+						"parent_author_signature" => "",
+						"author_signature" => $orig_sign['signature'],
+						"text" => implode(";", $signed_parts),
+						"diaspora_handle" => $handle);
+			}
 		}
 
-
-		$myaddr = self::get_my_handle($owner);
-
 		if ($item['deleted'])
-			; // Retraction
+			; // Relayed Retraction
 		elseif($item['verb'] === ACTIVITY_LIKE)
-			$msg = self::construct_like($item, $owner, $contact, $public_batch);
+			$msg = self::construct_like($item, $owner, $contact, $public_batch, $data);
 		else
 			$msg = self::construct_comment($item, $owner, $contact, $public_batch, $data);
 die($msg);
+
+		logger('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, $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
@@ -2301,8 +2329,6 @@ die($msg);
 
 	return(diaspora_transmit($owner,$contact,$slap,$public_batch,false,$item['guid']));
 */
-	}
-
 
 	public static function send_retraction($item, $owner, $contact, $public_batch = false) {
 

From 16eb8fd9bf705ad5d4d9f739b9264d7c8d15dace Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 7 Mar 2016 15:20:48 +0100
Subject: [PATCH 172/273] Small things ...

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

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 48093cc5b9..4c9d79912e 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -1525,7 +1525,7 @@ EOT;
 
 			// 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')",
+			q("INSERT INTO `sign` (`retract_iid`,`signed_text`) VALUES (%d,'%s')",
 				intval($r[0]["id"]),
 				dbesc(json_encode($data))
 			);
@@ -1552,7 +1552,7 @@ EOT;
 			case "StatusMessage":
 				return self::item_retraction($importer, $contact, $data);;
 
-			case "Person":
+			case "Person": /// @todo an "unshare" shouldn't remove the contact
 				contact_remove($contact["id"]);
 				return true;
 

From ec9c9f0be78f9db691ee1c7174f10a7850033717 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 8 Mar 2016 00:20:06 +0100
Subject: [PATCH 173/273] Don't create lock files if the process is called from
 the poller via the worker

---
 include/cron.php            | 51 +++++++++++++++++++------------------
 include/cronhooks.php       | 49 ++++++++++++++++++-----------------
 include/discover_poco.php   | 46 ++++++++++++++++++---------------
 include/onepoll.php         | 21 ++++++++-------
 include/ostatus.php         | 16 ++++++++----
 include/pubsubpublish.php   | 25 ++++++++++--------
 include/queue.php           | 25 ++++++++++--------
 include/update_gcontact.php | 21 ++++++++-------
 8 files changed, 141 insertions(+), 113 deletions(-)

diff --git a/include/cron.php b/include/cron.php
index 3acf711dd1..6143281710 100644
--- a/include/cron.php
+++ b/include/cron.php
@@ -40,15 +40,33 @@ function cron_run(&$argv, &$argc){
 	load_config('config');
 	load_config('system');
 
-	$maxsysload = intval(get_config('system','maxloadavg'));
-	if($maxsysload < 1)
-		$maxsysload = 50;
+	// Don't check this stuff if the function is called by the poller
+	if (App::callstack() != "poller_run") {
+		$maxsysload = intval(get_config('system','maxloadavg'));
+		if($maxsysload < 1)
+			$maxsysload = 50;
 
-	$load = current_load();
-	if($load) {
-		if(intval($load) > $maxsysload) {
-			logger('system: load ' . $load . ' too high. cron deferred to next scheduled run.');
-			return;
+		$load = current_load();
+		if($load) {
+			if(intval($load) > $maxsysload) {
+				logger('system: load '.$load.' too high. cron deferred to next scheduled run.');
+				return;
+			}
+		}
+
+		$lockpath = get_lockpath();
+		if ($lockpath != '') {
+			$pidfile = new pidfile($lockpath, 'cron');
+			if($pidfile->is_already_running()) {
+				logger("cron: Already running");
+				if ($pidfile->running_time() > 9*60) {
+					$pidfile->kill();
+					logger("cron: killed stale process");
+					// Calling a new instance
+					proc_run('php','include/cron.php');
+				}
+				exit;
+			}
 		}
 	}
 
@@ -66,23 +84,6 @@ function cron_run(&$argv, &$argc){
 		}
 	}
 
-	$lockpath = get_lockpath();
-	if ($lockpath != '') {
-		$pidfile = new pidfile($lockpath, 'cron');
-		if($pidfile->is_already_running()) {
-			logger("cron: Already running");
-			if ($pidfile->running_time() > 9*60) {
-				$pidfile->kill();
-				logger("cron: killed stale process");
-				// Calling a new instance
-				proc_run('php','include/cron.php');
-			}
-			exit;
-		}
-	}
-
-
-
 	$a->set_baseurl(get_config('system','url'));
 
 	load_hooks();
diff --git a/include/cronhooks.php b/include/cronhooks.php
index 8c70008e45..71cb0fb7b2 100644
--- a/include/cronhooks.php
+++ b/include/cronhooks.php
@@ -24,15 +24,33 @@ function cronhooks_run(&$argv, &$argc){
 	load_config('config');
 	load_config('system');
 
-	$maxsysload = intval(get_config('system','maxloadavg'));
-	if($maxsysload < 1)
-		$maxsysload = 50;
+	// Don't check this stuff if the function is called by the poller
+	if (App::callstack() != "poller_run") {
+		$maxsysload = intval(get_config('system','maxloadavg'));
+		if($maxsysload < 1)
+			$maxsysload = 50;
 
-	$load = current_load();
-	if($load) {
-		if(intval($load) > $maxsysload) {
-			logger('system: load ' . $load . ' too high. Cronhooks deferred to next scheduled run.');
-			return;
+		$load = current_load();
+		if($load) {
+			if(intval($load) > $maxsysload) {
+				logger('system: load ' . $load . ' too high. Cronhooks deferred to next scheduled run.');
+				return;
+			}
+		}
+
+		$lockpath = get_lockpath();
+		if ($lockpath != '') {
+			$pidfile = new pidfile($lockpath, 'cronhooks');
+			if($pidfile->is_already_running()) {
+				logger("cronhooks: Already running");
+				if ($pidfile->running_time() > 19*60) {
+					$pidfile->kill();
+					logger("cronhooks: killed stale process");
+					// Calling a new instance
+					proc_run('php','include/cronhooks.php');
+				}
+				exit;
+			}
 		}
 	}
 
@@ -50,21 +68,6 @@ function cronhooks_run(&$argv, &$argc){
 		}
 	}
 
-	$lockpath = get_lockpath();
-	if ($lockpath != '') {
-		$pidfile = new pidfile($lockpath, 'cronhooks');
-		if($pidfile->is_already_running()) {
-			logger("cronhooks: Already running");
-			if ($pidfile->running_time() > 19*60) {
-				$pidfile->kill();
-				logger("cronhooks: killed stale process");
-				// Calling a new instance
-				proc_run('php','include/cronhooks.php');
-			}
-			exit;
-		}
-	}
-
 	$a->set_baseurl(get_config('system','url'));
 
 	load_hooks();
diff --git a/include/discover_poco.php b/include/discover_poco.php
index a8f670334b..550c9897be 100644
--- a/include/discover_poco.php
+++ b/include/discover_poco.php
@@ -25,15 +25,18 @@ function discover_poco_run(&$argv, &$argc){
 	load_config('config');
 	load_config('system');
 
-	$maxsysload = intval(get_config('system','maxloadavg'));
-	if($maxsysload < 1)
-		$maxsysload = 50;
+	// Don't check this stuff if the function is called by the poller
+	if (App::callstack() != "poller_run") {
+		$maxsysload = intval(get_config('system','maxloadavg'));
+		if($maxsysload < 1)
+			$maxsysload = 50;
 
-	$load = current_load();
-	if($load) {
-		if(intval($load) > $maxsysload) {
-			logger('system: load ' . $load . ' too high. discover_poco deferred to next scheduled run.');
-			return;
+		$load = current_load();
+		if($load) {
+			if(intval($load) > $maxsysload) {
+				logger('system: load '.$load.' too high. discover_poco deferred to next scheduled run.');
+				return;
+			}
 		}
 	}
 
@@ -50,19 +53,22 @@ function discover_poco_run(&$argv, &$argc){
 	} else
 		die("Unknown or missing parameter ".$argv[1]."\n");
 
-	$lockpath = get_lockpath();
-	if ($lockpath != '') {
-		$pidfile = new pidfile($lockpath, 'discover_poco'.$mode.urlencode($search));
-		if($pidfile->is_already_running()) {
-			logger("discover_poco: Already running");
-			if ($pidfile->running_time() > 19*60) {
-				$pidfile->kill();
-				logger("discover_poco: killed stale process");
-				// Calling a new instance
-				if ($mode == 0)
-					proc_run('php','include/discover_poco.php');
+	// Don't check this stuff if the function is called by the poller
+	if (App::callstack() != "poller_run") {
+		$lockpath = get_lockpath();
+		if ($lockpath != '') {
+			$pidfile = new pidfile($lockpath, 'discover_poco'.$mode.urlencode($search));
+			if($pidfile->is_already_running()) {
+				logger("discover_poco: Already running");
+				if ($pidfile->running_time() > 19*60) {
+					$pidfile->kill();
+					logger("discover_poco: killed stale process");
+					// Calling a new instance
+					if ($mode == 0)
+						proc_run('php','include/discover_poco.php');
+				}
+				exit;
 			}
-			exit;
 		}
 	}
 
diff --git a/include/onepoll.php b/include/onepoll.php
index 6fb191f73d..8b91070dcc 100644
--- a/include/onepoll.php
+++ b/include/onepoll.php
@@ -60,16 +60,19 @@ function onepoll_run(&$argv, &$argc){
 		return;
 	}
 
-	$lockpath = get_lockpath();
-	if ($lockpath != '') {
-		$pidfile = new pidfile($lockpath, 'onepoll'.$contact_id);
-		if ($pidfile->is_already_running()) {
-			logger("onepoll: Already running for contact ".$contact_id);
-			if ($pidfile->running_time() > 9*60) {
-				$pidfile->kill();
-				logger("killed stale process");
+	// Don't check this stuff if the function is called by the poller
+	if (App::callstack() != "poller_run") {
+		$lockpath = get_lockpath();
+		if ($lockpath != '') {
+			$pidfile = new pidfile($lockpath, 'onepoll'.$contact_id);
+			if ($pidfile->is_already_running()) {
+				logger("onepoll: Already running for contact ".$contact_id);
+				if ($pidfile->running_time() > 9*60) {
+					$pidfile->kill();
+					logger("killed stale process");
+				}
+				exit;
 			}
-			exit;
 		}
 	}
 
diff --git a/include/ostatus.php b/include/ostatus.php
index 54b70e6d6c..ac13ce6bc8 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -954,16 +954,21 @@ function ostatus_completion($conversation_url, $uid, $item = array(), $self = ""
 		if (isset($single_conv->actor->url))
 			$actor = $single_conv->actor->url;
 
-		$contact = q("SELECT `id`, `rel` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
+		$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
 				$uid, normalise_link($actor), NETWORK_STATUSNET);
 
-		if (count($contact)) {
+		if (!$contact)
+			$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `alias` IN ('%s', '%s') AND `network` != '%s'",
+					$uid, $actor, normalise_link($actor), NETWORK_STATUSNET);
+
+		if ($contact) {
 			logger("Found contact for url ".$actor, LOGGER_DEBUG);
 			$contact_id = $contact[0]["id"];
+			$network = $contact[0]["network"];
 
 			$not_following = !in_array($contact[0]["rel"], array(CONTACT_IS_SHARING, CONTACT_IS_FRIEND));
 		} else {
-			logger("No contact found for url ".$actor, LOGGER_DEBUG);
+			logger("No contact found for user ".$uid." and url ".$actor, LOGGER_DEBUG);
 
 			// Adding a global contact
 			/// @TODO Use this data for the post
@@ -972,18 +977,19 @@ function ostatus_completion($conversation_url, $uid, $item = array(), $self = ""
 			logger("Global contact ".$global_contact_id." found for url ".$actor, LOGGER_DEBUG);
 
 			$contact_id = $parent["contact-id"];
+			$network = NETWORK_OSTATUS;
 
 			$not_following = true;
 		}
 
 		// Do we only want to import threads that were started by our contacts?
 		if ($not_following AND $new_parent AND get_config('system','ostatus_full_threads')) {
-			logger("Don't import uri ".$first_id." because we don't follow the person ".$actor, LOGGER_DEBUG);
+			logger("Don't import uri ".$first_id." because user ".$uid." doesn't follow the person ".$actor, LOGGER_DEBUG);
 			continue;
 		}
 
 		$arr = array();
-		$arr["network"] = NETWORK_OSTATUS;
+		$arr["network"] = $network;
 		$arr["uri"] = $single_conv->id;
 		$arr["plink"] = $plink;
 		$arr["uid"] = $uid;
diff --git a/include/pubsubpublish.php b/include/pubsubpublish.php
index 0ac50aaaa7..e7a55f5f09 100644
--- a/include/pubsubpublish.php
+++ b/include/pubsubpublish.php
@@ -79,18 +79,21 @@ function pubsubpublish_run(&$argv, &$argc){
 	load_config('config');
 	load_config('system');
 
-	$lockpath = get_lockpath();
-	if ($lockpath != '') {
-		$pidfile = new pidfile($lockpath, 'pubsubpublish');
-		if($pidfile->is_already_running()) {
-			logger("Already running");
-			if ($pidfile->running_time() > 9*60) {
-				$pidfile->kill();
-				logger("killed stale process");
-				// Calling a new instance
-				proc_run('php',"include/pubsubpublish.php");
+	// Don't check this stuff if the function is called by the poller
+	if (App::callstack() != "poller_run") {
+		$lockpath = get_lockpath();
+		if ($lockpath != '') {
+			$pidfile = new pidfile($lockpath, 'pubsubpublish');
+			if($pidfile->is_already_running()) {
+				logger("Already running");
+				if ($pidfile->running_time() > 9*60) {
+					$pidfile->kill();
+					logger("killed stale process");
+					// Calling a new instance
+					proc_run('php',"include/pubsubpublish.php");
+				}
+				return;
 			}
-			return;
 		}
 	}
 
diff --git a/include/queue.php b/include/queue.php
index 1525ca3abf..157fc88d94 100644
--- a/include/queue.php
+++ b/include/queue.php
@@ -28,18 +28,21 @@ function queue_run(&$argv, &$argc){
 	load_config('config');
 	load_config('system');
 
-	$lockpath = get_lockpath();
-	if ($lockpath != '') {
-		$pidfile = new pidfile($lockpath, 'queue');
-		if($pidfile->is_already_running()) {
-			logger("queue: Already running");
-			if ($pidfile->running_time() > 9*60) {
-				$pidfile->kill();
-				logger("queue: killed stale process");
-				// Calling a new instance
-				proc_run('php',"include/queue.php");
+	// Don't check this stuff if the function is called by the poller
+	if (App::callstack() != "poller_run") {
+		$lockpath = get_lockpath();
+		if ($lockpath != '') {
+			$pidfile = new pidfile($lockpath, 'queue');
+			if($pidfile->is_already_running()) {
+				logger("queue: Already running");
+				if ($pidfile->running_time() > 9*60) {
+					$pidfile->kill();
+					logger("queue: killed stale process");
+					// Calling a new instance
+					proc_run('php',"include/queue.php");
+				}
+				return;
 			}
-			return;
 		}
 	}
 
diff --git a/include/update_gcontact.php b/include/update_gcontact.php
index b5ea30a0a4..b7bf25aa24 100644
--- a/include/update_gcontact.php
+++ b/include/update_gcontact.php
@@ -37,16 +37,19 @@ function update_gcontact_run(&$argv, &$argc){
 		return;
 	}
 
-	$lockpath = get_lockpath();
-	if ($lockpath != '') {
-		$pidfile = new pidfile($lockpath, 'update_gcontact'.$contact_id);
-		if ($pidfile->is_already_running()) {
-			logger("update_gcontact: Already running for contact ".$contact_id);
-			if ($pidfile->running_time() > 9*60) {
-				$pidfile->kill();
-				logger("killed stale process");
+	// Don't check this stuff if the function is called by the poller
+	if (App::callstack() != "poller_run") {
+		$lockpath = get_lockpath();
+		if ($lockpath != '') {
+			$pidfile = new pidfile($lockpath, 'update_gcontact'.$contact_id);
+			if ($pidfile->is_already_running()) {
+				logger("update_gcontact: Already running for contact ".$contact_id);
+				if ($pidfile->running_time() > 9*60) {
+					$pidfile->kill();
+					logger("killed stale process");
+				}
+				exit;
 			}
-			exit;
 		}
 	}
 

From beb2346cfc8e3aa57ed0203e35034241e814b61a Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 8 Mar 2016 20:28:09 +0100
Subject: [PATCH 174/273] The function to check for maxload and the lockfile is
 centralized

---
 boot.php                    | 37 ++++++++++++++++++++++++++++++++++++-
 include/cron.php            | 31 ++++---------------------------
 include/cronhooks.php       | 31 ++++---------------------------
 include/delivery.php        | 13 ++-----------
 include/discover_poco.php   | 37 ++++++-------------------------------
 include/onepoll.php         | 18 +++---------------
 include/poller.php          | 13 ++-----------
 include/pubsubpublish.php   | 20 +++-----------------
 include/queue.php           | 20 +++-----------------
 include/update_gcontact.php | 18 +++---------------
 10 files changed, 66 insertions(+), 172 deletions(-)

diff --git a/boot.php b/boot.php
index 5cc3499311..fe4e5a2757 100644
--- a/boot.php
+++ b/boot.php
@@ -30,7 +30,7 @@ require_once('include/cache.php');
 require_once('library/Mobile_Detect/Mobile_Detect.php');
 require_once('include/features.php');
 require_once('include/identity.php');
-
+require_once('include/pidfile.php');
 require_once('update.php');
 require_once('include/dbstructure.php');
 
@@ -1098,6 +1098,41 @@ class App {
 		return($this->is_friendica_app);
 	}
 
+	function maxload_reached() {
+
+		$maxsysload = intval(get_config('system', 'maxloadavg'));
+		if ($maxsysload < 1)
+			$maxsysload = 50;
+
+		$load = current_load();
+		if ($load) {
+			if (intval($load) > $maxsysload) {
+				logger('system: load '.$load.' too high.');
+				return true;
+			}
+		}
+		return false;
+	}
+
+	function is_already_running($task, $taskname, $timeout = 540) {
+
+		$lockpath = get_lockpath();
+		if ($lockpath != '') {
+			$pidfile = new pidfile($lockpath, $taskname);
+			if ($pidfile->is_already_running()) {
+				logger("Already running");
+				if ($pidfile->running_time() > $timeout) {
+					$pidfile->kill();
+					logger("killed stale process");
+					// Calling a new instance
+					if ($task != "")
+						proc_run('php', $task);
+				}
+				return true;
+			}
+		}
+		return false;
+	}
 }
 
 /**
diff --git a/include/cron.php b/include/cron.php
index 6143281710..1c3297c932 100644
--- a/include/cron.php
+++ b/include/cron.php
@@ -34,7 +34,6 @@ function cron_run(&$argv, &$argc){
 	require_once('include/Contact.php');
 	require_once('include/email.php');
 	require_once('include/socgraph.php');
-	require_once('include/pidfile.php');
 	require_once('mod/nodeinfo.php');
 
 	load_config('config');
@@ -42,32 +41,10 @@ function cron_run(&$argv, &$argc){
 
 	// Don't check this stuff if the function is called by the poller
 	if (App::callstack() != "poller_run") {
-		$maxsysload = intval(get_config('system','maxloadavg'));
-		if($maxsysload < 1)
-			$maxsysload = 50;
-
-		$load = current_load();
-		if($load) {
-			if(intval($load) > $maxsysload) {
-				logger('system: load '.$load.' too high. cron deferred to next scheduled run.');
-				return;
-			}
-		}
-
-		$lockpath = get_lockpath();
-		if ($lockpath != '') {
-			$pidfile = new pidfile($lockpath, 'cron');
-			if($pidfile->is_already_running()) {
-				logger("cron: Already running");
-				if ($pidfile->running_time() > 9*60) {
-					$pidfile->kill();
-					logger("cron: killed stale process");
-					// Calling a new instance
-					proc_run('php','include/cron.php');
-				}
-				exit;
-			}
-		}
+		if (App::maxload_reached())
+			return;
+		if (App::is_already_running('include/cron.php', 'cron', 540))
+			return;
 	}
 
 	$last = get_config('system','last_cron');
diff --git a/include/cronhooks.php b/include/cronhooks.php
index 71cb0fb7b2..22812fb864 100644
--- a/include/cronhooks.php
+++ b/include/cronhooks.php
@@ -19,39 +19,16 @@ function cronhooks_run(&$argv, &$argc){
 
 	require_once('include/session.php');
 	require_once('include/datetime.php');
-	require_once('include/pidfile.php');
 
 	load_config('config');
 	load_config('system');
 
 	// Don't check this stuff if the function is called by the poller
 	if (App::callstack() != "poller_run") {
-		$maxsysload = intval(get_config('system','maxloadavg'));
-		if($maxsysload < 1)
-			$maxsysload = 50;
-
-		$load = current_load();
-		if($load) {
-			if(intval($load) > $maxsysload) {
-				logger('system: load ' . $load . ' too high. Cronhooks deferred to next scheduled run.');
-				return;
-			}
-		}
-
-		$lockpath = get_lockpath();
-		if ($lockpath != '') {
-			$pidfile = new pidfile($lockpath, 'cronhooks');
-			if($pidfile->is_already_running()) {
-				logger("cronhooks: Already running");
-				if ($pidfile->running_time() > 19*60) {
-					$pidfile->kill();
-					logger("cronhooks: killed stale process");
-					// Calling a new instance
-					proc_run('php','include/cronhooks.php');
-				}
-				exit;
-			}
-		}
+		if (App::maxload_reached())
+			return;
+		if (App::is_already_running('include/cronhooks.php', 'cronhooks', 1140))
+			return;
 	}
 
 	$last = get_config('system','last_cronhook');
diff --git a/include/delivery.php b/include/delivery.php
index 021ceb9968..e5ca0946b3 100644
--- a/include/delivery.php
+++ b/include/delivery.php
@@ -57,17 +57,8 @@ function delivery_run(&$argv, &$argc){
 			continue;
 		}
 
-		$maxsysload = intval(get_config('system','maxloadavg'));
-		if($maxsysload < 1)
-			$maxsysload = 50;
-
-		$load = current_load();
-		if($load) {
-			if(intval($load) > $maxsysload) {
-				logger('system: load ' . $load . ' too high. Delivery deferred to next queue run.');
-				return;
-			}
-		}
+		if (App::maxload_reached())
+			return;
 
 		// It's ours to deliver. Remove it from the queue.
 
diff --git a/include/discover_poco.php b/include/discover_poco.php
index 550c9897be..8ba2bb2365 100644
--- a/include/discover_poco.php
+++ b/include/discover_poco.php
@@ -20,25 +20,14 @@ function discover_poco_run(&$argv, &$argc){
 
 	require_once('include/session.php');
 	require_once('include/datetime.php');
-	require_once('include/pidfile.php');
 
 	load_config('config');
 	load_config('system');
 
 	// Don't check this stuff if the function is called by the poller
-	if (App::callstack() != "poller_run") {
-		$maxsysload = intval(get_config('system','maxloadavg'));
-		if($maxsysload < 1)
-			$maxsysload = 50;
-
-		$load = current_load();
-		if($load) {
-			if(intval($load) > $maxsysload) {
-				logger('system: load '.$load.' too high. discover_poco deferred to next scheduled run.');
-				return;
-			}
-		}
-	}
+	if (App::callstack() != "poller_run")
+		if (App::maxload_reached())
+			return;
 
 	if(($argc > 2) && ($argv[1] == "dirsearch")) {
 		$search = urldecode($argv[2]);
@@ -54,23 +43,9 @@ function discover_poco_run(&$argv, &$argc){
 		die("Unknown or missing parameter ".$argv[1]."\n");
 
 	// Don't check this stuff if the function is called by the poller
-	if (App::callstack() != "poller_run") {
-		$lockpath = get_lockpath();
-		if ($lockpath != '') {
-			$pidfile = new pidfile($lockpath, 'discover_poco'.$mode.urlencode($search));
-			if($pidfile->is_already_running()) {
-				logger("discover_poco: Already running");
-				if ($pidfile->running_time() > 19*60) {
-					$pidfile->kill();
-					logger("discover_poco: killed stale process");
-					// Calling a new instance
-					if ($mode == 0)
-						proc_run('php','include/discover_poco.php');
-				}
-				exit;
-			}
-		}
-	}
+	if (App::callstack() != "poller_run")
+		if (App::is_already_running('include/discover_poco.php', 'discover_poco'.$mode.urlencode($search), 1140))
+			return;
 
 	$a->set_baseurl(get_config('system','url'));
 
diff --git a/include/onepoll.php b/include/onepoll.php
index 8b91070dcc..4d270f6135 100644
--- a/include/onepoll.php
+++ b/include/onepoll.php
@@ -31,7 +31,6 @@ function onepoll_run(&$argv, &$argc){
 	require_once('include/Contact.php');
 	require_once('include/email.php');
 	require_once('include/socgraph.php');
-	require_once('include/pidfile.php');
 	require_once('include/queue_fn.php');
 
 	load_config('config');
@@ -61,20 +60,9 @@ function onepoll_run(&$argv, &$argc){
 	}
 
 	// Don't check this stuff if the function is called by the poller
-	if (App::callstack() != "poller_run") {
-		$lockpath = get_lockpath();
-		if ($lockpath != '') {
-			$pidfile = new pidfile($lockpath, 'onepoll'.$contact_id);
-			if ($pidfile->is_already_running()) {
-				logger("onepoll: Already running for contact ".$contact_id);
-				if ($pidfile->running_time() > 9*60) {
-					$pidfile->kill();
-					logger("killed stale process");
-				}
-				exit;
-			}
-		}
-	}
+	if (App::callstack() != "poller_run")
+		if (App::is_already_running('', 'onepoll'.$contact_id, 540))
+			return;
 
 	$d = datetime_convert();
 
diff --git a/include/poller.php b/include/poller.php
index 755862eb6b..7ffd47aa68 100644
--- a/include/poller.php
+++ b/include/poller.php
@@ -29,17 +29,8 @@ function poller_run(&$argv, &$argc){
 	if (poller_max_connections_reached())
 		return;
 
-	$load = current_load();
-	if($load) {
-		$maxsysload = intval(get_config('system','maxloadavg'));
-		if($maxsysload < 1)
-			$maxsysload = 50;
-
-		if(intval($load) > $maxsysload) {
-			logger('system: load ' . $load . ' too high. poller deferred to next scheduled run.');
-			return;
-		}
-	}
+	if (App::maxload_reached())
+		return;
 
 	// Checking the number of workers
 	if (poller_too_much_workers(1)) {
diff --git a/include/pubsubpublish.php b/include/pubsubpublish.php
index e7a55f5f09..b438b36e6b 100644
--- a/include/pubsubpublish.php
+++ b/include/pubsubpublish.php
@@ -74,28 +74,14 @@ function pubsubpublish_run(&$argv, &$argc){
 	};
 
 	require_once('include/items.php');
-	require_once('include/pidfile.php');
 
 	load_config('config');
 	load_config('system');
 
 	// Don't check this stuff if the function is called by the poller
-	if (App::callstack() != "poller_run") {
-		$lockpath = get_lockpath();
-		if ($lockpath != '') {
-			$pidfile = new pidfile($lockpath, 'pubsubpublish');
-			if($pidfile->is_already_running()) {
-				logger("Already running");
-				if ($pidfile->running_time() > 9*60) {
-					$pidfile->kill();
-					logger("killed stale process");
-					// Calling a new instance
-					proc_run('php',"include/pubsubpublish.php");
-				}
-				return;
-			}
-		}
-	}
+	if (App::callstack() != "poller_run")
+		if (App::is_already_running("include/pubsubpublish.php", 'pubsubpublish', 540))
+			return;
 
 	$a->set_baseurl(get_config('system','url'));
 
diff --git a/include/queue.php b/include/queue.php
index 157fc88d94..1222199c70 100644
--- a/include/queue.php
+++ b/include/queue.php
@@ -22,29 +22,15 @@ function queue_run(&$argv, &$argc){
 	require_once("include/datetime.php");
 	require_once('include/items.php');
 	require_once('include/bbcode.php');
-	require_once('include/pidfile.php');
 	require_once('include/socgraph.php');
 
 	load_config('config');
 	load_config('system');
 
 	// Don't check this stuff if the function is called by the poller
-	if (App::callstack() != "poller_run") {
-		$lockpath = get_lockpath();
-		if ($lockpath != '') {
-			$pidfile = new pidfile($lockpath, 'queue');
-			if($pidfile->is_already_running()) {
-				logger("queue: Already running");
-				if ($pidfile->running_time() > 9*60) {
-					$pidfile->kill();
-					logger("queue: killed stale process");
-					// Calling a new instance
-					proc_run('php',"include/queue.php");
-				}
-				return;
-			}
-		}
-	}
+	if (App::callstack() != "poller_run")
+		if (App::is_already_running('include/queue.php', 'queue', 540))
+			return;
 
 	$a->set_baseurl(get_config('system','url'));
 
diff --git a/include/update_gcontact.php b/include/update_gcontact.php
index b7bf25aa24..25c11806a2 100644
--- a/include/update_gcontact.php
+++ b/include/update_gcontact.php
@@ -16,7 +16,6 @@ function update_gcontact_run(&$argv, &$argc){
 		unset($db_host, $db_user, $db_pass, $db_data);
 	};
 
-	require_once('include/pidfile.php');
 	require_once('include/Scrape.php');
 	require_once("include/socgraph.php");
 
@@ -38,20 +37,9 @@ function update_gcontact_run(&$argv, &$argc){
 	}
 
 	// Don't check this stuff if the function is called by the poller
-	if (App::callstack() != "poller_run") {
-		$lockpath = get_lockpath();
-		if ($lockpath != '') {
-			$pidfile = new pidfile($lockpath, 'update_gcontact'.$contact_id);
-			if ($pidfile->is_already_running()) {
-				logger("update_gcontact: Already running for contact ".$contact_id);
-				if ($pidfile->running_time() > 9*60) {
-					$pidfile->kill();
-					logger("killed stale process");
-				}
-				exit;
-			}
-		}
-	}
+	if (App::callstack() != "poller_run")
+		if (App::is_already_running('', 'update_gcontact'.$contact_id, 540))
+			return;
 
 	$r = q("SELECT * FROM `gcontact` WHERE `id` = %d", intval($contact_id));
 

From 65d6d45f8cdb2e1f84fc0c345043598a221312de Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 8 Mar 2016 22:28:49 +0100
Subject: [PATCH 175/273] Changed parameter order

---
 boot.php                    | 2 +-
 include/cron.php            | 2 +-
 include/cronhooks.php       | 2 +-
 include/discover_poco.php   | 2 +-
 include/onepoll.php         | 2 +-
 include/pubsubpublish.php   | 2 +-
 include/queue.php           | 2 +-
 include/update_gcontact.php | 2 +-
 8 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/boot.php b/boot.php
index fe4e5a2757..4d57d21e62 100644
--- a/boot.php
+++ b/boot.php
@@ -1114,7 +1114,7 @@ class App {
 		return false;
 	}
 
-	function is_already_running($task, $taskname, $timeout = 540) {
+	function is_already_running($taskname, $task = "", $timeout = 540) {
 
 		$lockpath = get_lockpath();
 		if ($lockpath != '') {
diff --git a/include/cron.php b/include/cron.php
index 1c3297c932..d68bd7f084 100644
--- a/include/cron.php
+++ b/include/cron.php
@@ -43,7 +43,7 @@ function cron_run(&$argv, &$argc){
 	if (App::callstack() != "poller_run") {
 		if (App::maxload_reached())
 			return;
-		if (App::is_already_running('include/cron.php', 'cron', 540))
+		if (App::is_already_running('cron', 'include/cron.php', 540))
 			return;
 	}
 
diff --git a/include/cronhooks.php b/include/cronhooks.php
index 22812fb864..b6cf0e7237 100644
--- a/include/cronhooks.php
+++ b/include/cronhooks.php
@@ -27,7 +27,7 @@ function cronhooks_run(&$argv, &$argc){
 	if (App::callstack() != "poller_run") {
 		if (App::maxload_reached())
 			return;
-		if (App::is_already_running('include/cronhooks.php', 'cronhooks', 1140))
+		if (App::is_already_running('cronhooks', 'include/cronhooks.php', 1140))
 			return;
 	}
 
diff --git a/include/discover_poco.php b/include/discover_poco.php
index 8ba2bb2365..0b468faea1 100644
--- a/include/discover_poco.php
+++ b/include/discover_poco.php
@@ -44,7 +44,7 @@ function discover_poco_run(&$argv, &$argc){
 
 	// Don't check this stuff if the function is called by the poller
 	if (App::callstack() != "poller_run")
-		if (App::is_already_running('include/discover_poco.php', 'discover_poco'.$mode.urlencode($search), 1140))
+		if (App::is_already_running('discover_poco'.$mode.urlencode($search), 'include/discover_poco.php', 1140))
 			return;
 
 	$a->set_baseurl(get_config('system','url'));
diff --git a/include/onepoll.php b/include/onepoll.php
index 4d270f6135..eb1045de14 100644
--- a/include/onepoll.php
+++ b/include/onepoll.php
@@ -61,7 +61,7 @@ function onepoll_run(&$argv, &$argc){
 
 	// Don't check this stuff if the function is called by the poller
 	if (App::callstack() != "poller_run")
-		if (App::is_already_running('', 'onepoll'.$contact_id, 540))
+		if (App::is_already_running('onepoll'.$contact_id, '', 540))
 			return;
 
 	$d = datetime_convert();
diff --git a/include/pubsubpublish.php b/include/pubsubpublish.php
index b438b36e6b..4fbb505146 100644
--- a/include/pubsubpublish.php
+++ b/include/pubsubpublish.php
@@ -80,7 +80,7 @@ function pubsubpublish_run(&$argv, &$argc){
 
 	// Don't check this stuff if the function is called by the poller
 	if (App::callstack() != "poller_run")
-		if (App::is_already_running("include/pubsubpublish.php", 'pubsubpublish', 540))
+		if (App::is_already_running("pubsubpublish", "include/pubsubpublish.php", 540))
 			return;
 
 	$a->set_baseurl(get_config('system','url'));
diff --git a/include/queue.php b/include/queue.php
index 1222199c70..183ce0f9cd 100644
--- a/include/queue.php
+++ b/include/queue.php
@@ -29,7 +29,7 @@ function queue_run(&$argv, &$argc){
 
 	// Don't check this stuff if the function is called by the poller
 	if (App::callstack() != "poller_run")
-		if (App::is_already_running('include/queue.php', 'queue', 540))
+		if (App::is_already_running('queue', 'include/queue.php', 540))
 			return;
 
 	$a->set_baseurl(get_config('system','url'));
diff --git a/include/update_gcontact.php b/include/update_gcontact.php
index 25c11806a2..88e1817f0b 100644
--- a/include/update_gcontact.php
+++ b/include/update_gcontact.php
@@ -38,7 +38,7 @@ function update_gcontact_run(&$argv, &$argc){
 
 	// Don't check this stuff if the function is called by the poller
 	if (App::callstack() != "poller_run")
-		if (App::is_already_running('', 'update_gcontact'.$contact_id, 540))
+		if (App::is_already_running('update_gcontact'.$contact_id, '', 540))
 			return;
 
 	$r = q("SELECT * FROM `gcontact` WHERE `id` = %d", intval($contact_id));

From c30b369a1a60af4635b8f0a6ae823303fa50e3da Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 8 Mar 2016 22:42:37 +0100
Subject: [PATCH 176/273] Added documentation

---
 boot.php | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/boot.php b/boot.php
index 4d57d21e62..43f69fc115 100644
--- a/boot.php
+++ b/boot.php
@@ -1098,6 +1098,11 @@ class App {
 		return($this->is_friendica_app);
 	}
 
+	/**
+	 * @brief Checks if the maximum load is reached
+	 *
+	 * @return bool Is the load reached?
+	 */
 	function maxload_reached() {
 
 		$maxsysload = intval(get_config('system', 'maxloadavg'));
@@ -1114,6 +1119,15 @@ class App {
 		return false;
 	}
 
+	/**
+	 * @brief Checks if the process is already running
+	 *
+	 * @param string $taskname The name of the task that will be used for the name of the lockfile
+	 * @param string $task The path and name of the php script
+	 * @param int $timeout The timeout after which a task should be killed
+	 *
+	 * @return bool Is the process running?
+	 */
 	function is_already_running($taskname, $task = "", $timeout = 540) {
 
 		$lockpath = get_lockpath();

From 32c66246c4fcddcab30e4850d5c6b62bdfac225a Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 9 Mar 2016 19:30:04 +0100
Subject: [PATCH 177/273] Some fixes for the fetching of postings by using /p/

---
 include/diaspora2.php | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 4c9d79912e..7aa0fc6989 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -550,12 +550,15 @@ class diaspora {
 			return self::fetch_message($source_xml->root_guid, $server, ++$level);
 		}
 
+		$author = "";
+
 		// Fetch the author - for the old and the new Diaspora version
 		if ($source_xml->post->status_message->diaspora_handle)
 			$author = (string)$source_xml->post->status_message->diaspora_handle;
-		elseif ($source_xml->author)
+		elseif ($source_xml->author AND ($source_xml->getName() == "status_message"))
 			$author = (string)$source_xml->author;
 
+		// If this isn't a "status_message" then quit
 		if (!$author)
 			return false;
 
@@ -1391,22 +1394,24 @@ EOT;
 			logger("1st try: reshared message ".$guid." will be fetched from original server: ".$server);
 			$item_id = self::store_by_guid($guid, $server);
 
-			if (!$item_id) {
-				$server = "https://".substr($author, strpos($author, "@") + 1);
-				logger("2nd try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
-				$item = self::store_by_guid($guid, $server);
-			}
 			if (!$item_id) {
 				$server = "http://".substr($orig_author, strpos($orig_author, "@") + 1);
-				logger("3rd try: reshared message ".$guid." will be fetched from original server: ".$server);
-				$item = self::store_by_guid($guid, $server);
+				logger("2nd try: reshared message ".$guid." will be fetched from original server: ".$server);
+				$item_id = self::store_by_guid($guid, $server);
+			}
+
+			// Deactivated by now since there is a risk that someone could manipulate postings through this method
+/*			if (!$item_id) {
+				$server = "https://".substr($author, strpos($author, "@") + 1);
+				logger("3rd try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
+				$item_id = self::store_by_guid($guid, $server);
 			}
 			if (!$item_id) {
 				$server = "http://".substr($author, strpos($author, "@") + 1);
 				logger("4th try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
-				$item = self::store_by_guid($guid, $server);
+				$item_id = self::store_by_guid($guid, $server);
 			}
-
+*/
 			if ($item_id) {
 				$r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`,
 						`author-name`, `author-link`, `author-avatar`

From c0bd7a866d7dc0dc0ebc1e82226add912e39cffa Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 9 Mar 2016 21:53:30 +0100
Subject: [PATCH 178/273] Some small addition to the OStatus part. Better check
 if we follow the actor.

---
 include/ostatus.php | 86 +++++++++++++++++++++++++++++----------------
 1 file changed, 56 insertions(+), 30 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index ac13ce6bc8..0e79b32f89 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -714,6 +714,49 @@ function ostatus_fetch_conversation($self, $conversation_id = "") {
 	return $base_url."/conversation/".$conversation_id;
 }
 
+/**
+ * @brief Fetches actor details of a given actor and user id
+ *
+ * @param string $actor The actor url
+ * @param int $uid The user id
+ *
+ * @return array Array with actor details
+ */
+function ostatus_get_actor_details($actor, $uid) {
+
+	$details = array();
+
+	$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
+				$uid, normalise_link($actor), NETWORK_STATUSNET);
+
+	if (!$contact)
+		$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `alias` IN ('%s', '%s') AND `network` != '%s'",
+				$uid, $actor, normalise_link($actor), NETWORK_STATUSNET);
+
+	if ($contact) {
+		logger("Found contact for url ".$actor, LOGGER_DEBUG);
+		$details["contact_id"] = $contact[0]["id"];
+		$details["network"] = $contact[0]["network"];
+
+		$details["not_following"] = !in_array($contact[0]["rel"], array(CONTACT_IS_SHARING, CONTACT_IS_FRIEND));
+	} else {
+		logger("No contact found for user ".$uid." and url ".$actor, LOGGER_DEBUG);
+
+		// Adding a global contact
+		/// @TODO Use this data for the post
+		$details["global_contact_id"] = get_contact($actor, 0);
+
+		logger("Global contact ".$global_contact_id." found for url ".$actor, LOGGER_DEBUG);
+
+		$details["contact_id"] = $parent["contact-id"];
+		$details["network"] = NETWORK_OSTATUS;
+
+		$details["not_following"] = true;
+	}
+
+	return $details;
+}
+
 function ostatus_completion($conversation_url, $uid, $item = array(), $self = "") {
 
 	$a = get_app();
@@ -954,46 +997,20 @@ function ostatus_completion($conversation_url, $uid, $item = array(), $self = ""
 		if (isset($single_conv->actor->url))
 			$actor = $single_conv->actor->url;
 
-		$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
-				$uid, normalise_link($actor), NETWORK_STATUSNET);
-
-		if (!$contact)
-			$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `alias` IN ('%s', '%s') AND `network` != '%s'",
-					$uid, $actor, normalise_link($actor), NETWORK_STATUSNET);
-
-		if ($contact) {
-			logger("Found contact for url ".$actor, LOGGER_DEBUG);
-			$contact_id = $contact[0]["id"];
-			$network = $contact[0]["network"];
-
-			$not_following = !in_array($contact[0]["rel"], array(CONTACT_IS_SHARING, CONTACT_IS_FRIEND));
-		} else {
-			logger("No contact found for user ".$uid." and url ".$actor, LOGGER_DEBUG);
-
-			// Adding a global contact
-			/// @TODO Use this data for the post
-			$global_contact_id = get_contact($actor, 0);
-
-			logger("Global contact ".$global_contact_id." found for url ".$actor, LOGGER_DEBUG);
-
-			$contact_id = $parent["contact-id"];
-			$network = NETWORK_OSTATUS;
-
-			$not_following = true;
-		}
+		$details = ostatus_get_actor_details($actor, $uid);
 
 		// Do we only want to import threads that were started by our contacts?
-		if ($not_following AND $new_parent AND get_config('system','ostatus_full_threads')) {
+		if ($details["not_following"] AND $new_parent AND get_config('system','ostatus_full_threads')) {
 			logger("Don't import uri ".$first_id." because user ".$uid." doesn't follow the person ".$actor, LOGGER_DEBUG);
 			continue;
 		}
 
 		$arr = array();
-		$arr["network"] = $network;
+		$arr["network"] = $details["network"];
 		$arr["uri"] = $single_conv->id;
 		$arr["plink"] = $plink;
 		$arr["uid"] = $uid;
-		$arr["contact-id"] = $contact_id;
+		$arr["contact-id"] = $details["contact_id"];
 		$arr["parent-uri"] = $parent_uri;
 		$arr["created"] = $single_conv->published;
 		$arr["edited"] = $single_conv->published;
@@ -1119,6 +1136,15 @@ function ostatus_completion($conversation_url, $uid, $item = array(), $self = ""
 
 	if (($item_stored < 0) AND (count($item) > 0)) {
 		//$arr["app"] .= " (OStatus-NoConvFound)";
+
+		if (get_config('system','ostatus_full_threads')) {
+			$details = ostatus_get_actor_details($item["owner-link"], $uid);
+			if ($details["not_following"]) {
+				logger("Don't import uri ".$item["uri"]." because user ".$uid." doesn't follow the person ".$item["owner-link"], LOGGER_DEBUG);
+				return false;
+			}
+		}
+
 		$item_stored = item_store($item, true);
 		if ($item_stored) {
 			logger("Uri ".$item["uri"]." wasn't found in conversation ".$conversation_url, LOGGER_DEBUG);

From df312402e46cc3cdc788c73d0c41874b6c71fcb3 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 9 Mar 2016 22:51:17 +0100
Subject: [PATCH 179/273] Bugfix: A parameter was missing for the OStatus
 author check

---
 include/ostatus.php | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index 0e79b32f89..5ba9f0e83c 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -719,10 +719,11 @@ function ostatus_fetch_conversation($self, $conversation_id = "") {
  *
  * @param string $actor The actor url
  * @param int $uid The user id
+ * @param int $contact_id The default contact-id
  *
  * @return array Array with actor details
  */
-function ostatus_get_actor_details($actor, $uid) {
+function ostatus_get_actor_details($actor, $uid, $contact_id) {
 
 	$details = array();
 
@@ -748,7 +749,7 @@ function ostatus_get_actor_details($actor, $uid) {
 
 		logger("Global contact ".$global_contact_id." found for url ".$actor, LOGGER_DEBUG);
 
-		$details["contact_id"] = $parent["contact-id"];
+		$details["contact_id"] = $contact_id;
 		$details["network"] = NETWORK_OSTATUS;
 
 		$details["not_following"] = true;
@@ -997,7 +998,7 @@ function ostatus_completion($conversation_url, $uid, $item = array(), $self = ""
 		if (isset($single_conv->actor->url))
 			$actor = $single_conv->actor->url;
 
-		$details = ostatus_get_actor_details($actor, $uid);
+		$details = ostatus_get_actor_details($actor, $uid, $parent["contact-id"]);
 
 		// Do we only want to import threads that were started by our contacts?
 		if ($details["not_following"] AND $new_parent AND get_config('system','ostatus_full_threads')) {
@@ -1138,7 +1139,7 @@ function ostatus_completion($conversation_url, $uid, $item = array(), $self = ""
 		//$arr["app"] .= " (OStatus-NoConvFound)";
 
 		if (get_config('system','ostatus_full_threads')) {
-			$details = ostatus_get_actor_details($item["owner-link"], $uid);
+			$details = ostatus_get_actor_details($item["owner-link"], $uid, $item["contact-id"]);
 			if ($details["not_following"]) {
 				logger("Don't import uri ".$item["uri"]." because user ".$uid." doesn't follow the person ".$item["owner-link"], LOGGER_DEBUG);
 				return false;

From 2718c8150f614e6d5c76f91d46f4ebb28e440124 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 11 Mar 2016 20:32:22 +0100
Subject: [PATCH 180/273] The table optimisation level calculation is now using
 the index size as well

---
 include/cron.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/cron.php b/include/cron.php
index d68bd7f084..db7d44be0b 100644
--- a/include/cron.php
+++ b/include/cron.php
@@ -357,7 +357,7 @@ function cron_clear_cache(&$a) {
 			continue;
 
 		// Calculate fragmentation
-		$fragmentation = $table["Data_free"] / $table["Data_length"];
+		$fragmentation = $table["Data_free"] / ($table["Data_length"] + $table["Index_length"]);
 
 		logger("Table ".$table["Name"]." - Fragmentation level: ".round($fragmentation * 100, 2), LOGGER_DEBUG);
 

From 3189f0e23c234ca78396bcf5d44ac02775e491fa Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 11 Mar 2016 20:43:31 +0100
Subject: [PATCH 181/273] Another fix for "goaway". Hopefully now finale.

---
 boot.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/boot.php b/boot.php
index 43f69fc115..a70c7bf616 100644
--- a/boot.php
+++ b/boot.php
@@ -1558,7 +1558,7 @@ function killme() {
  * @brief Redirect to another URL and terminate this process.
  */
 function goaway($s) {
-	if (!strstr(normalise_link($s), normalise_link(App::get_baseurl())))
+	if (!strstr(normalise_link($s), "http://"))
 		$s = App::get_baseurl()."/".$s;
 
 	header("Location: $s");

From b12dbe8831953cf244a66074dc3338baaae02b8a Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 11 Mar 2016 23:28:11 +0100
Subject: [PATCH 182/273] The worker settings are now available in the admin
 settings

---
 mod/admin.php                 | 11 ++++++++++-
 view/templates/admin_site.tpl |  5 +++++
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/mod/admin.php b/mod/admin.php
index e7c4f51b66..57a004f51a 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -619,6 +619,9 @@ function admin_page_site_post(&$a) {
 	$only_tag_search	=	((x($_POST,'only_tag_search'))		? True						: False);
 	$rino			=	((x($_POST,'rino'))			? intval($_POST['rino'])			: 0);
 	$embedly		=	((x($_POST,'embedly'))			? notags(trim($_POST['embedly']))		: '');
+	$worker			=	((x($_POST,'worker'))			? True						: False);
+	$worker_queues		=	((x($_POST,'worker_queues'))		? intval($_POST['worker_queues'])		: 4);
+	$worker_dont_fork	=	((x($_POST,'worker_dont_fork'))		? True						: False);
 
 	if($a->get_path() != "")
 		$diaspora_enabled = false;
@@ -765,7 +768,9 @@ function admin_page_site_post(&$a) {
 	set_config('system','proxy_disabled', $proxy_disabled);
 	set_config('system','old_pager', $old_pager);
 	set_config('system','only_tag_search', $only_tag_search);
-
+	set_config('system','worker', $worker);
+	set_config('system','worker_queues', $worker_queues);
+	set_config('system','worker_dont_fork', $worker_dont_fork);
 
 	if($rino==2 and !function_exists('mcrypt_create_iv')) {
 		notice(t("RINO2 needs mcrypt php extension to work."));
@@ -992,6 +997,10 @@ function admin_page_site(&$a) {
 		'$rino' 		=> array('rino', t("RINO Encryption"), intval(get_config('system','rino_encrypt')), t("Encryption layer between nodes."), array("Disabled", "RINO1 (deprecated)", "RINO2")),
 		'$embedly' 		=> array('embedly', t("Embedly API key"), get_config('system','embedly'), t("<a href='http://embed.ly'>Embedly</a> is used to fetch additional data for web pages. This is an optional parameter.")),
 
+		'$worker'		=> array('worker', t("Enable 'worker' background processing"), get_config('system','worker'), t("The worker background processing limits the number of parallel background jobs to a maximum number and respects the system load.")),
+		'$worker_queues' 	=> array('worker_queues', t("Maximum number of parallel workers"), get_config('system','worker_queues'), t("On shared hosters set this to 2. On larger systems, values of 10 are great. Default value is 4.")),
+		'$worker_dont_fork'	=> array('worker_dont_fork', t("Don't use 'proc_open' with the worker"), get_config('system','worker_dont_fork'), t("Enable this if your system doesn't allow the use of 'proc_open'. This can happen on shared hosters. If this is enabled you should increase the frequency of poller calls in your crontab.")),
+
 		'$form_security_token'	=> get_form_security_token("admin_site")
 
 	));
diff --git a/view/templates/admin_site.tpl b/view/templates/admin_site.tpl
index 91957d016a..d43c6a8c4a 100644
--- a/view/templates/admin_site.tpl
+++ b/view/templates/admin_site.tpl
@@ -152,6 +152,11 @@
 	{{include file="field_input.tpl" field=$max_comments}}
 	{{include file="field_checkbox.tpl" field=$proxy_disabled}}
 	{{include file="field_checkbox.tpl" field=$old_pager}}
+
+	{{include file="field_checkbox.tpl" field=$worker}}
+	{{include file="field_input.tpl" field=$worker_queues}}
+	{{include file="field_checkbox.tpl" field=$worker_dont_fork}}
+
 	<div class="submit"><input type="submit" name="page_site" value="{{$submit|escape:'html'}}" /></div>
 
 	</form>

From bc21fca34567ca0fb57eba6b2e2c38fb1b77462c Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 11 Mar 2016 23:44:46 +0100
Subject: [PATCH 183/273] Remove the setting description from the documentation
 since it isn't a hidden one anymore.

---
 doc/htconfig.md               | 3 ---
 mod/admin.php                 | 1 +
 view/templates/admin_site.tpl | 3 ++-
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/doc/htconfig.md b/doc/htconfig.md
index f9c92bfa08..a36e0bef22 100644
--- a/doc/htconfig.md
+++ b/doc/htconfig.md
@@ -64,9 +64,6 @@ line to your .htconfig.php:
 * throttle_limit_week - Maximum number of posts that a user can send per week with the API.
 * throttle_limit_month - Maximum number of posts that a user can send per month with the API.
 * wall-to-wall_share (Boolean) - Displays forwarded posts like "wall-to-wall" posts.
-* worker (Boolean) - (Experimental) Use the worker system instead of calling several background processes. Reduces the overall load and speeds up item delivery.
-* worker_dont_fork (Boolean) - if enabled, the workers are only called from the poller process. Useful on systems that permit the use of "proc_open".
-* worker_queues - Number of parallel workers. Default value is 10 queues.
 * xrd_timeout - Timeout for fetching the XRD links. Default value is 20 seconds.
 
 ## service_class ##
diff --git a/mod/admin.php b/mod/admin.php
index 57a004f51a..28c8ed15c2 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -909,6 +909,7 @@ function admin_page_site(&$a) {
 		'$advanced' => t('Advanced'),
 		'$portable_contacts' => t('Auto Discovered Contact Directory'),
 		'$performance' => t('Performance'),
+		'$worker_title' => t('Worker'),
 		'$relocate'=> t('Relocate - WARNING: advanced function. Could make this server unreachable.'),
 		'$baseurl' => $a->get_baseurl(true),
 		// name, label, value, help string, extra data...
diff --git a/view/templates/admin_site.tpl b/view/templates/admin_site.tpl
index d43c6a8c4a..f22319b695 100644
--- a/view/templates/admin_site.tpl
+++ b/view/templates/admin_site.tpl
@@ -152,11 +152,12 @@
 	{{include file="field_input.tpl" field=$max_comments}}
 	{{include file="field_checkbox.tpl" field=$proxy_disabled}}
 	{{include file="field_checkbox.tpl" field=$old_pager}}
+	<div class="submit"><input type="submit" name="page_site" value="{{$submit|escape:'html'}}" /></div>
 
+	<h3>{{$worker_title}}</h3>
 	{{include file="field_checkbox.tpl" field=$worker}}
 	{{include file="field_input.tpl" field=$worker_queues}}
 	{{include file="field_checkbox.tpl" field=$worker_dont_fork}}
-
 	<div class="submit"><input type="submit" name="page_site" value="{{$submit|escape:'html'}}" /></div>
 
 	</form>

From 9d52a89c513438cf9c780d10f532eab201b1c2c3 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Sat, 12 Mar 2016 07:36:44 +0100
Subject: [PATCH 184/273] regenerated messages.po file for picking up the
 workers

---
 util/messages.po | 2187 ++++++++++++++++++++++++----------------------
 1 file changed, 1124 insertions(+), 1063 deletions(-)

diff --git a/util/messages.po b/util/messages.po
index 46a9913f45..df1dedd68a 100644
--- a/util/messages.po
+++ b/util/messages.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: \n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2016-01-24 06:49+0100\n"
+"POT-Creation-Date: 2016-03-12 07:34+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,15 +18,15 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 
 
-#: mod/contacts.php:50 include/identity.php:395
+#: mod/contacts.php:50 include/identity.php:396
 msgid "Network:"
 msgstr ""
 
-#: mod/contacts.php:51 mod/contacts.php:961 mod/videos.php:37
+#: mod/contacts.php:51 mod/contacts.php:947 mod/videos.php:37
 #: mod/viewcontacts.php:105 mod/dirfind.php:214 mod/network.php:598
 #: mod/allfriends.php:77 mod/match.php:82 mod/directory.php:172
 #: mod/common.php:123 mod/suggest.php:95 mod/photos.php:41
-#: include/identity.php:298
+#: include/identity.php:299
 msgid "Forum"
 msgstr ""
 
@@ -37,7 +37,7 @@ msgid_plural "%d contacts edited."
 msgstr[0] ""
 msgstr[1] ""
 
-#: mod/contacts.php:159 mod/contacts.php:383
+#: mod/contacts.php:159 mod/contacts.php:368
 msgid "Could not access contact record."
 msgstr ""
 
@@ -49,150 +49,150 @@ msgstr ""
 msgid "Contact updated."
 msgstr ""
 
-#: mod/contacts.php:208 mod/dfrn_request.php:575
+#: mod/contacts.php:208 mod/dfrn_request.php:573
 msgid "Failed to update contact record."
 msgstr ""
 
-#: mod/contacts.php:365 mod/manage.php:96 mod/display.php:509
+#: mod/contacts.php:350 mod/manage.php:96 mod/display.php:513
 #: mod/profile_photo.php:19 mod/profile_photo.php:175 mod/profile_photo.php:186
 #: mod/profile_photo.php:199 mod/ostatus_subscribe.php:9 mod/follow.php:11
-#: mod/follow.php:73 mod/follow.php:155 mod/item.php:180 mod/item.php:192
+#: mod/follow.php:73 mod/follow.php:155 mod/item.php:183 mod/item.php:195
 #: mod/group.php:19 mod/dfrn_confirm.php:55 mod/fsuggest.php:78
 #: mod/wall_upload.php:77 mod/wall_upload.php:80 mod/viewcontacts.php:40
 #: mod/notifications.php:69 mod/message.php:45 mod/message.php:181
-#: mod/crepair.php:117 mod/dirfind.php:11 mod/nogroup.php:25 mod/network.php:4
+#: mod/crepair.php:100 mod/dirfind.php:11 mod/nogroup.php:25 mod/network.php:4
 #: mod/allfriends.php:12 mod/events.php:165 mod/wallmessage.php:9
 #: mod/wallmessage.php:33 mod/wallmessage.php:79 mod/wallmessage.php:103
 #: mod/wall_attach.php:67 mod/wall_attach.php:70 mod/settings.php:20
-#: mod/settings.php:126 mod/settings.php:646 mod/register.php:42
+#: mod/settings.php:126 mod/settings.php:647 mod/register.php:42
 #: mod/delegate.php:12 mod/common.php:18 mod/mood.php:114 mod/suggest.php:58
-#: mod/profiles.php:165 mod/profiles.php:615 mod/editpost.php:10 mod/api.php:26
+#: mod/profiles.php:165 mod/profiles.php:593 mod/editpost.php:10 mod/api.php:26
 #: mod/api.php:31 mod/notes.php:22 mod/poke.php:149 mod/repair_ostatus.php:9
-#: mod/invite.php:15 mod/invite.php:101 mod/photos.php:171 mod/photos.php:1105
+#: mod/invite.php:15 mod/invite.php:101 mod/photos.php:171 mod/photos.php:1091
 #: mod/regmod.php:110 mod/uimport.php:23 mod/attach.php:33
-#: include/items.php:5096 index.php:383
+#: include/items.php:2002 index.php:384
 msgid "Permission denied."
 msgstr ""
 
-#: mod/contacts.php:404
+#: mod/contacts.php:389
 msgid "Contact has been blocked"
 msgstr ""
 
-#: mod/contacts.php:404
+#: mod/contacts.php:389
 msgid "Contact has been unblocked"
 msgstr ""
 
-#: mod/contacts.php:415
+#: mod/contacts.php:400
 msgid "Contact has been ignored"
 msgstr ""
 
-#: mod/contacts.php:415
+#: mod/contacts.php:400
 msgid "Contact has been unignored"
 msgstr ""
 
-#: mod/contacts.php:427
+#: mod/contacts.php:412
 msgid "Contact has been archived"
 msgstr ""
 
-#: mod/contacts.php:427
+#: mod/contacts.php:412
 msgid "Contact has been unarchived"
 msgstr ""
 
-#: mod/contacts.php:454 mod/contacts.php:802
+#: mod/contacts.php:439 mod/contacts.php:794
 msgid "Do you really want to delete this contact?"
 msgstr ""
 
-#: mod/contacts.php:456 mod/follow.php:110 mod/message.php:216
-#: mod/settings.php:1103 mod/settings.php:1109 mod/settings.php:1117
-#: mod/settings.php:1121 mod/settings.php:1126 mod/settings.php:1132
-#: mod/settings.php:1138 mod/settings.php:1144 mod/settings.php:1170
-#: mod/settings.php:1171 mod/settings.php:1172 mod/settings.php:1173
-#: mod/settings.php:1174 mod/dfrn_request.php:857 mod/register.php:238
-#: mod/suggest.php:29 mod/profiles.php:658 mod/profiles.php:661
-#: mod/profiles.php:687 mod/api.php:105 include/items.php:4928
+#: mod/contacts.php:441 mod/follow.php:110 mod/message.php:216
+#: mod/settings.php:1107 mod/settings.php:1113 mod/settings.php:1121
+#: mod/settings.php:1125 mod/settings.php:1130 mod/settings.php:1136
+#: mod/settings.php:1142 mod/settings.php:1148 mod/settings.php:1174
+#: mod/settings.php:1175 mod/settings.php:1176 mod/settings.php:1177
+#: mod/settings.php:1178 mod/dfrn_request.php:855 mod/register.php:238
+#: mod/suggest.php:29 mod/profiles.php:636 mod/profiles.php:639
+#: mod/profiles.php:665 mod/api.php:105 include/items.php:1834
 msgid "Yes"
 msgstr ""
 
-#: mod/contacts.php:459 mod/tagrm.php:11 mod/tagrm.php:94 mod/follow.php:121
+#: mod/contacts.php:444 mod/tagrm.php:11 mod/tagrm.php:94 mod/follow.php:121
 #: mod/videos.php:131 mod/message.php:219 mod/fbrowser.php:93
-#: mod/fbrowser.php:128 mod/settings.php:660 mod/settings.php:686
-#: mod/dfrn_request.php:871 mod/suggest.php:32 mod/editpost.php:148
+#: mod/fbrowser.php:128 mod/settings.php:661 mod/settings.php:687
+#: mod/dfrn_request.php:869 mod/suggest.php:32 mod/editpost.php:148
 #: mod/photos.php:247 mod/photos.php:336 include/conversation.php:1220
-#: include/items.php:4931
+#: include/items.php:1837
 msgid "Cancel"
 msgstr ""
 
-#: mod/contacts.php:471
+#: mod/contacts.php:456
 msgid "Contact has been removed."
 msgstr ""
 
-#: mod/contacts.php:512
+#: mod/contacts.php:497
 #, php-format
 msgid "You are mutual friends with %s"
 msgstr ""
 
-#: mod/contacts.php:516
+#: mod/contacts.php:501
 #, php-format
 msgid "You are sharing with %s"
 msgstr ""
 
-#: mod/contacts.php:521
+#: mod/contacts.php:506
 #, php-format
 msgid "%s is sharing with you"
 msgstr ""
 
-#: mod/contacts.php:541
+#: mod/contacts.php:526
 msgid "Private communications are not available for this contact."
 msgstr ""
 
-#: mod/contacts.php:544 mod/admin.php:822
+#: mod/contacts.php:529 mod/admin.php:838
 msgid "Never"
 msgstr ""
 
-#: mod/contacts.php:548
+#: mod/contacts.php:533
 msgid "(Update was successful)"
 msgstr ""
 
-#: mod/contacts.php:548
+#: mod/contacts.php:533
 msgid "(Update was not successful)"
 msgstr ""
 
-#: mod/contacts.php:550
+#: mod/contacts.php:535 mod/contacts.php:972
 msgid "Suggest friends"
 msgstr ""
 
-#: mod/contacts.php:554
+#: mod/contacts.php:539
 #, php-format
 msgid "Network type: %s"
 msgstr ""
 
-#: mod/contacts.php:567
+#: mod/contacts.php:552
 msgid "Communications lost with this contact!"
 msgstr ""
 
-#: mod/contacts.php:570
+#: mod/contacts.php:555
 msgid "Fetch further information for feeds"
 msgstr ""
 
-#: mod/contacts.php:571 mod/admin.php:831
+#: mod/contacts.php:556 mod/admin.php:847
 msgid "Disabled"
 msgstr ""
 
-#: mod/contacts.php:571
+#: mod/contacts.php:556
 msgid "Fetch information"
 msgstr ""
 
-#: mod/contacts.php:571
+#: mod/contacts.php:556
 msgid "Fetch information and keywords"
 msgstr ""
 
-#: mod/contacts.php:587 mod/manage.php:143 mod/fsuggest.php:107
-#: mod/message.php:342 mod/message.php:525 mod/crepair.php:196
+#: mod/contacts.php:575 mod/manage.php:143 mod/fsuggest.php:107
+#: mod/message.php:342 mod/message.php:525 mod/crepair.php:179
 #: mod/events.php:574 mod/content.php:712 mod/install.php:261
-#: mod/install.php:299 mod/mood.php:137 mod/profiles.php:696
-#: mod/localtime.php:45 mod/poke.php:198 mod/invite.php:140 mod/photos.php:1137
-#: mod/photos.php:1261 mod/photos.php:1579 mod/photos.php:1630
-#: mod/photos.php:1678 mod/photos.php:1766 object/Item.php:710
+#: mod/install.php:299 mod/mood.php:137 mod/profiles.php:674
+#: mod/localtime.php:45 mod/poke.php:198 mod/invite.php:140 mod/photos.php:1123
+#: mod/photos.php:1247 mod/photos.php:1565 mod/photos.php:1616
+#: mod/photos.php:1664 mod/photos.php:1752 object/Item.php:710
 #: view/theme/cleanzero/config.php:80 view/theme/dispy/config.php:70
 #: view/theme/quattro/config.php:64 view/theme/diabook/config.php:148
 #: view/theme/diabook/theme.php:633 view/theme/vier/config.php:107
@@ -200,306 +200,316 @@ msgstr ""
 msgid "Submit"
 msgstr ""
 
-#: mod/contacts.php:588
+#: mod/contacts.php:576
 msgid "Profile Visibility"
 msgstr ""
 
-#: mod/contacts.php:589
+#: mod/contacts.php:577
 #, php-format
 msgid ""
 "Please choose the profile you would like to display to %s when viewing your "
 "profile securely."
 msgstr ""
 
-#: mod/contacts.php:590
+#: mod/contacts.php:578
 msgid "Contact Information / Notes"
 msgstr ""
 
-#: mod/contacts.php:591
+#: mod/contacts.php:579
 msgid "Edit contact notes"
 msgstr ""
 
-#: mod/contacts.php:596 mod/contacts.php:952 mod/viewcontacts.php:97
+#: mod/contacts.php:584 mod/contacts.php:938 mod/viewcontacts.php:97
 #: mod/nogroup.php:41
 #, php-format
 msgid "Visit %s's profile [%s]"
 msgstr ""
 
-#: mod/contacts.php:597
+#: mod/contacts.php:585
 msgid "Block/Unblock contact"
 msgstr ""
 
-#: mod/contacts.php:598
+#: mod/contacts.php:586
 msgid "Ignore contact"
 msgstr ""
 
-#: mod/contacts.php:599
+#: mod/contacts.php:587
 msgid "Repair URL settings"
 msgstr ""
 
-#: mod/contacts.php:600
+#: mod/contacts.php:588
 msgid "View conversations"
 msgstr ""
 
-#: mod/contacts.php:602
-msgid "Delete contact"
-msgstr ""
-
-#: mod/contacts.php:606
+#: mod/contacts.php:594
 msgid "Last update:"
 msgstr ""
 
-#: mod/contacts.php:608
+#: mod/contacts.php:596
 msgid "Update public posts"
 msgstr ""
 
-#: mod/contacts.php:610
+#: mod/contacts.php:598 mod/contacts.php:982
 msgid "Update now"
 msgstr ""
 
-#: mod/contacts.php:612 mod/follow.php:103 mod/dirfind.php:196
+#: mod/contacts.php:600 mod/follow.php:103 mod/dirfind.php:196
 #: mod/allfriends.php:65 mod/match.php:71 mod/suggest.php:82
-#: include/contact_widgets.php:32 include/Contact.php:297
+#: include/contact_widgets.php:32 include/Contact.php:299
 #: include/conversation.php:924
 msgid "Connect/Follow"
 msgstr ""
 
-#: mod/contacts.php:615 mod/contacts.php:806 mod/contacts.php:865
-#: mod/admin.php:1312
+#: mod/contacts.php:603 mod/contacts.php:798 mod/contacts.php:991
+#: mod/admin.php:1334
 msgid "Unblock"
 msgstr ""
 
-#: mod/contacts.php:615 mod/contacts.php:806 mod/contacts.php:865
-#: mod/admin.php:1311
+#: mod/contacts.php:603 mod/contacts.php:798 mod/contacts.php:991
+#: mod/admin.php:1333
 msgid "Block"
 msgstr ""
 
-#: mod/contacts.php:616 mod/contacts.php:807 mod/contacts.php:872
+#: mod/contacts.php:604 mod/contacts.php:799 mod/contacts.php:999
 msgid "Unignore"
 msgstr ""
 
-#: mod/contacts.php:616 mod/contacts.php:807 mod/contacts.php:872
+#: mod/contacts.php:604 mod/contacts.php:799 mod/contacts.php:999
 #: mod/notifications.php:54 mod/notifications.php:179 mod/notifications.php:259
 msgid "Ignore"
 msgstr ""
 
-#: mod/contacts.php:619
+#: mod/contacts.php:607
 msgid "Currently blocked"
 msgstr ""
 
-#: mod/contacts.php:620
+#: mod/contacts.php:608
 msgid "Currently ignored"
 msgstr ""
 
-#: mod/contacts.php:621
+#: mod/contacts.php:609
 msgid "Currently archived"
 msgstr ""
 
-#: mod/contacts.php:622 mod/notifications.php:172 mod/notifications.php:251
+#: mod/contacts.php:610 mod/notifications.php:172 mod/notifications.php:251
 msgid "Hide this contact from others"
 msgstr ""
 
-#: mod/contacts.php:622
+#: mod/contacts.php:610
 msgid ""
 "Replies/likes to your public posts <strong>may</strong> still be visible"
 msgstr ""
 
-#: mod/contacts.php:623
+#: mod/contacts.php:611
 msgid "Notification for new posts"
 msgstr ""
 
-#: mod/contacts.php:623
+#: mod/contacts.php:611
 msgid "Send a notification of every new post of this contact"
 msgstr ""
 
-#: mod/contacts.php:626
+#: mod/contacts.php:614
 msgid "Blacklisted keywords"
 msgstr ""
 
-#: mod/contacts.php:626
+#: mod/contacts.php:614
 msgid ""
 "Comma separated list of keywords that should not be converted to hashtags, "
 "when \"Fetch information and keywords\" is selected"
 msgstr ""
 
-#: mod/contacts.php:633 mod/follow.php:126 mod/notifications.php:255
+#: mod/contacts.php:621 mod/follow.php:126 mod/notifications.php:255
 msgid "Profile URL"
 msgstr ""
 
-#: mod/contacts.php:636 mod/notifications.php:244 mod/events.php:566
-#: mod/directory.php:145 include/identity.php:308 include/bb2diaspora.php:170
+#: mod/contacts.php:624 mod/notifications.php:244 mod/events.php:566
+#: mod/directory.php:145 include/identity.php:309 include/bb2diaspora.php:170
 #: include/event.php:36 include/event.php:60
 msgid "Location:"
 msgstr ""
 
-#: mod/contacts.php:638 mod/notifications.php:246 mod/directory.php:153
-#: include/identity.php:317 include/identity.php:631
+#: mod/contacts.php:626 mod/notifications.php:246 mod/directory.php:153
+#: include/identity.php:318 include/identity.php:632
 msgid "About:"
 msgstr ""
 
-#: mod/contacts.php:640 mod/follow.php:134 mod/notifications.php:248
-#: include/identity.php:625
+#: mod/contacts.php:628 mod/follow.php:134 mod/notifications.php:248
+#: include/identity.php:626
 msgid "Tags:"
 msgstr ""
 
-#: mod/contacts.php:685
+#: mod/contacts.php:629
+msgid "Actions"
+msgstr ""
+
+#: mod/contacts.php:631 mod/contacts.php:825 include/identity.php:687
+#: include/nav.php:75
+msgid "Status"
+msgstr ""
+
+#: mod/contacts.php:632
+msgid "Contact Settings"
+msgstr ""
+
+#: mod/contacts.php:677
 msgid "Suggestions"
 msgstr ""
 
-#: mod/contacts.php:688
+#: mod/contacts.php:680
 msgid "Suggest potential friends"
 msgstr ""
 
-#: mod/contacts.php:693 mod/group.php:192
+#: mod/contacts.php:685 mod/group.php:192
 msgid "All Contacts"
 msgstr ""
 
-#: mod/contacts.php:696
+#: mod/contacts.php:688
 msgid "Show all contacts"
 msgstr ""
 
-#: mod/contacts.php:701
+#: mod/contacts.php:693
 msgid "Unblocked"
 msgstr ""
 
-#: mod/contacts.php:704
+#: mod/contacts.php:696
 msgid "Only show unblocked contacts"
 msgstr ""
 
-#: mod/contacts.php:710
+#: mod/contacts.php:702
 msgid "Blocked"
 msgstr ""
 
-#: mod/contacts.php:713
+#: mod/contacts.php:705
 msgid "Only show blocked contacts"
 msgstr ""
 
-#: mod/contacts.php:719
+#: mod/contacts.php:711
 msgid "Ignored"
 msgstr ""
 
-#: mod/contacts.php:722
+#: mod/contacts.php:714
 msgid "Only show ignored contacts"
 msgstr ""
 
-#: mod/contacts.php:728
+#: mod/contacts.php:720
 msgid "Archived"
 msgstr ""
 
-#: mod/contacts.php:731
+#: mod/contacts.php:723
 msgid "Only show archived contacts"
 msgstr ""
 
-#: mod/contacts.php:737
+#: mod/contacts.php:729
 msgid "Hidden"
 msgstr ""
 
-#: mod/contacts.php:740
+#: mod/contacts.php:732
 msgid "Only show hidden contacts"
 msgstr ""
 
-#: mod/contacts.php:793 mod/contacts.php:841 mod/viewcontacts.php:116
-#: include/identity.php:741 include/identity.php:744 include/text.php:1012
+#: mod/contacts.php:785 mod/contacts.php:845 mod/viewcontacts.php:116
+#: include/identity.php:742 include/identity.php:745 include/text.php:983
 #: include/nav.php:123 include/nav.php:187 view/theme/diabook/theme.php:125
 msgid "Contacts"
 msgstr ""
 
-#: mod/contacts.php:797
+#: mod/contacts.php:789
 msgid "Search your contacts"
 msgstr ""
 
-#: mod/contacts.php:798
+#: mod/contacts.php:790
 msgid "Finding: "
 msgstr ""
 
-#: mod/contacts.php:799 mod/directory.php:210 include/contact_widgets.php:34
+#: mod/contacts.php:791 mod/directory.php:210 include/contact_widgets.php:34
 msgid "Find"
 msgstr ""
 
-#: mod/contacts.php:805 mod/settings.php:156 mod/settings.php:685
+#: mod/contacts.php:797 mod/settings.php:156 mod/settings.php:686
 msgid "Update"
 msgstr ""
 
-#: mod/contacts.php:808 mod/contacts.php:879
+#: mod/contacts.php:800 mod/contacts.php:1007
 msgid "Archive"
 msgstr ""
 
-#: mod/contacts.php:808 mod/contacts.php:879
+#: mod/contacts.php:800 mod/contacts.php:1007
 msgid "Unarchive"
 msgstr ""
 
-#: mod/contacts.php:809 mod/group.php:171 mod/admin.php:1310
-#: mod/content.php:440 mod/content.php:743 mod/settings.php:722
-#: mod/photos.php:1723 object/Item.php:134 include/conversation.php:635
+#: mod/contacts.php:801 mod/contacts.php:1015 mod/group.php:171
+#: mod/admin.php:1332 mod/content.php:440 mod/content.php:743
+#: mod/settings.php:723 mod/photos.php:1709 object/Item.php:134
+#: include/conversation.php:635
 msgid "Delete"
 msgstr ""
 
-#: mod/contacts.php:822 include/identity.php:686 include/nav.php:75
-msgid "Status"
-msgstr ""
-
-#: mod/contacts.php:825 mod/follow.php:143 include/identity.php:689
+#: mod/contacts.php:828 mod/follow.php:143 include/identity.php:690
 msgid "Status Messages and Posts"
 msgstr ""
 
-#: mod/contacts.php:830 mod/profperm.php:104 mod/newmember.php:32
-#: include/identity.php:579 include/identity.php:665 include/identity.php:694
+#: mod/contacts.php:833 mod/profperm.php:104 mod/newmember.php:32
+#: include/identity.php:580 include/identity.php:666 include/identity.php:695
 #: include/nav.php:76 view/theme/diabook/theme.php:124
 msgid "Profile"
 msgstr ""
 
-#: mod/contacts.php:833 include/identity.php:697
+#: mod/contacts.php:836 include/identity.php:698
 msgid "Profile Details"
 msgstr ""
 
-#: mod/contacts.php:844
+#: mod/contacts.php:848
 msgid "View all contacts"
 msgstr ""
 
-#: mod/contacts.php:850 mod/common.php:134
+#: mod/contacts.php:855 mod/common.php:134
 msgid "Common Friends"
 msgstr ""
 
-#: mod/contacts.php:853
+#: mod/contacts.php:858
 msgid "View all common friends"
 msgstr ""
 
-#: mod/contacts.php:857
-msgid "Repair"
+#: mod/contacts.php:862 mod/admin.php:909
+msgid "Advanced"
 msgstr ""
 
-#: mod/contacts.php:860
+#: mod/contacts.php:865
 msgid "Advanced Contact Settings"
 msgstr ""
 
-#: mod/contacts.php:868
-msgid "Toggle Blocked status"
-msgstr ""
-
-#: mod/contacts.php:875
-msgid "Toggle Ignored status"
-msgstr ""
-
-#: mod/contacts.php:882
-msgid "Toggle Archive status"
-msgstr ""
-
-#: mod/contacts.php:924
+#: mod/contacts.php:910
 msgid "Mutual Friendship"
 msgstr ""
 
-#: mod/contacts.php:928
+#: mod/contacts.php:914
 msgid "is a fan of yours"
 msgstr ""
 
-#: mod/contacts.php:932
+#: mod/contacts.php:918
 msgid "you are a fan of"
 msgstr ""
 
-#: mod/contacts.php:953 mod/nogroup.php:42
+#: mod/contacts.php:939 mod/nogroup.php:42
 msgid "Edit contact"
 msgstr ""
 
+#: mod/contacts.php:993
+msgid "Toggle Blocked status"
+msgstr ""
+
+#: mod/contacts.php:1001
+msgid "Toggle Ignored status"
+msgstr ""
+
+#: mod/contacts.php:1009
+msgid "Toggle Archive status"
+msgstr ""
+
+#: mod/contacts.php:1017
+msgid "Delete contact"
+msgstr ""
+
 #: mod/hcard.php:10
 msgid "No profile"
 msgstr ""
@@ -522,7 +532,7 @@ msgstr ""
 msgid "Post successful."
 msgstr ""
 
-#: mod/profperm.php:19 mod/group.php:72 index.php:382
+#: mod/profperm.php:19 mod/group.php:72 index.php:383
 msgid "Permission denied"
 msgstr ""
 
@@ -546,23 +556,23 @@ msgstr ""
 msgid "All Contacts (with secure profile access)"
 msgstr ""
 
-#: mod/display.php:82 mod/display.php:291 mod/display.php:513
-#: mod/viewsrc.php:15 mod/admin.php:234 mod/admin.php:1365 mod/admin.php:1599
-#: mod/notice.php:15 include/items.php:4887
+#: mod/display.php:82 mod/display.php:298 mod/display.php:517
+#: mod/viewsrc.php:15 mod/admin.php:234 mod/admin.php:1387 mod/admin.php:1621
+#: mod/notice.php:15 include/items.php:1793
 msgid "Item not found."
 msgstr ""
 
-#: mod/display.php:220 mod/videos.php:197 mod/viewcontacts.php:35
-#: mod/community.php:22 mod/dfrn_request.php:786 mod/search.php:93
-#: mod/search.php:99 mod/directory.php:37 mod/photos.php:976
+#: mod/display.php:227 mod/videos.php:197 mod/viewcontacts.php:35
+#: mod/community.php:22 mod/dfrn_request.php:784 mod/search.php:93
+#: mod/search.php:99 mod/directory.php:37 mod/photos.php:962
 msgid "Public access denied."
 msgstr ""
 
-#: mod/display.php:339 mod/profile.php:155
+#: mod/display.php:346 mod/profile.php:155
 msgid "Access to this profile has been restricted."
 msgstr ""
 
-#: mod/display.php:506
+#: mod/display.php:510
 msgid "Item has been removed."
 msgstr ""
 
@@ -597,7 +607,7 @@ msgid ""
 "join."
 msgstr ""
 
-#: mod/newmember.php:22 mod/admin.php:1418 mod/admin.php:1676
+#: mod/newmember.php:22 mod/admin.php:1440 mod/admin.php:1698
 #: mod/settings.php:109 include/nav.php:182 view/theme/diabook/theme.php:544
 #: view/theme/diabook/theme.php:648
 msgid "Settings"
@@ -622,7 +632,7 @@ msgid ""
 "potential friends know exactly how to find you."
 msgstr ""
 
-#: mod/newmember.php:36 mod/profile_photo.php:250 mod/profiles.php:709
+#: mod/newmember.php:36 mod/profile_photo.php:250 mod/profiles.php:687
 msgid "Upload Profile Photo"
 msgstr ""
 
@@ -705,7 +715,7 @@ msgid ""
 "hours."
 msgstr ""
 
-#: mod/newmember.php:61 include/group.php:283
+#: mod/newmember.php:61 include/group.php:286
 msgid "Groups"
 msgstr ""
 
@@ -765,8 +775,8 @@ msgstr ""
 #: mod/profile_photo.php:74 mod/profile_photo.php:81 mod/profile_photo.php:88
 #: mod/profile_photo.php:210 mod/profile_photo.php:302
 #: mod/profile_photo.php:311 mod/photos.php:78 mod/photos.php:192
-#: mod/photos.php:775 mod/photos.php:1245 mod/photos.php:1268
-#: mod/photos.php:1862 include/user.php:345 include/user.php:352
+#: mod/photos.php:769 mod/photos.php:1231 mod/photos.php:1254
+#: mod/photos.php:1848 include/user.php:345 include/user.php:352
 #: include/user.php:359 view/theme/diabook/theme.php:500
 msgid "Profile Photos"
 msgstr ""
@@ -787,12 +797,12 @@ msgstr ""
 msgid "Unable to process image"
 msgstr ""
 
-#: mod/profile_photo.php:150 mod/wall_upload.php:151 mod/photos.php:811
+#: mod/profile_photo.php:150 mod/wall_upload.php:151 mod/photos.php:805
 #, php-format
 msgid "Image exceeds size limit of %s"
 msgstr ""
 
-#: mod/profile_photo.php:159 mod/wall_upload.php:183 mod/photos.php:851
+#: mod/profile_photo.php:159 mod/wall_upload.php:188 mod/photos.php:845
 msgid "Unable to process image."
 msgstr ""
 
@@ -836,13 +846,13 @@ msgstr ""
 msgid "Image uploaded successfully."
 msgstr ""
 
-#: mod/profile_photo.php:307 mod/wall_upload.php:216 mod/photos.php:878
+#: mod/profile_photo.php:307 mod/wall_upload.php:221 mod/photos.php:872
 msgid "Image upload failed."
 msgstr ""
 
 #: mod/subthread.php:87 mod/tagger.php:62 include/like.php:165
 #: include/conversation.php:130 include/conversation.php:266
-#: include/text.php:2000 include/diaspora.php:2169
+#: include/text.php:1923 include/diaspora.php:2117
 #: view/theme/diabook/theme.php:471
 msgid "photo"
 msgstr ""
@@ -850,7 +860,7 @@ msgstr ""
 #: mod/subthread.php:87 mod/tagger.php:62 include/like.php:165
 #: include/like.php:334 include/conversation.php:125
 #: include/conversation.php:134 include/conversation.php:261
-#: include/conversation.php:270 include/diaspora.php:2169
+#: include/conversation.php:270 include/diaspora.php:2117
 #: view/theme/diabook/theme.php:466 view/theme/diabook/theme.php:475
 msgid "status"
 msgstr ""
@@ -920,11 +930,11 @@ msgstr ""
 msgid "- select -"
 msgstr ""
 
-#: mod/filer.php:31 mod/editpost.php:109 mod/notes.php:61 include/text.php:1004
+#: mod/filer.php:31 mod/editpost.php:109 mod/notes.php:61 include/text.php:975
 msgid "Save"
 msgstr ""
 
-#: mod/follow.php:19 mod/dfrn_request.php:870
+#: mod/follow.php:19 mod/dfrn_request.php:868
 msgid "Submit Request"
 msgstr ""
 
@@ -944,30 +954,30 @@ msgstr ""
 msgid "The network type couldn't be detected. Contact can't be added."
 msgstr ""
 
-#: mod/follow.php:109 mod/dfrn_request.php:856
+#: mod/follow.php:109 mod/dfrn_request.php:854
 msgid "Please answer the following:"
 msgstr ""
 
-#: mod/follow.php:110 mod/dfrn_request.php:857
+#: mod/follow.php:110 mod/dfrn_request.php:855
 #, php-format
 msgid "Does %s know you?"
 msgstr ""
 
-#: mod/follow.php:110 mod/settings.php:1103 mod/settings.php:1109
-#: mod/settings.php:1117 mod/settings.php:1121 mod/settings.php:1126
-#: mod/settings.php:1132 mod/settings.php:1138 mod/settings.php:1144
-#: mod/settings.php:1170 mod/settings.php:1171 mod/settings.php:1172
-#: mod/settings.php:1173 mod/settings.php:1174 mod/dfrn_request.php:857
-#: mod/register.php:239 mod/profiles.php:658 mod/profiles.php:662
-#: mod/profiles.php:687 mod/api.php:106
+#: mod/follow.php:110 mod/settings.php:1107 mod/settings.php:1113
+#: mod/settings.php:1121 mod/settings.php:1125 mod/settings.php:1130
+#: mod/settings.php:1136 mod/settings.php:1142 mod/settings.php:1148
+#: mod/settings.php:1174 mod/settings.php:1175 mod/settings.php:1176
+#: mod/settings.php:1177 mod/settings.php:1178 mod/dfrn_request.php:855
+#: mod/register.php:239 mod/profiles.php:636 mod/profiles.php:640
+#: mod/profiles.php:665 mod/api.php:106
 msgid "No"
 msgstr ""
 
-#: mod/follow.php:111 mod/dfrn_request.php:861
+#: mod/follow.php:111 mod/dfrn_request.php:859
 msgid "Add a personal note:"
 msgstr ""
 
-#: mod/follow.php:117 mod/dfrn_request.php:867
+#: mod/follow.php:117 mod/dfrn_request.php:865
 msgid "Your Identity Address:"
 msgstr ""
 
@@ -979,17 +989,17 @@ msgstr ""
 msgid "Unable to locate original post."
 msgstr ""
 
-#: mod/item.php:329
+#: mod/item.php:332
 msgid "Empty post discarded."
 msgstr ""
 
-#: mod/item.php:467 mod/wall_upload.php:213 mod/wall_upload.php:227
-#: mod/wall_upload.php:234 include/Photo.php:958 include/Photo.php:973
-#: include/Photo.php:980 include/Photo.php:1002 include/message.php:145
+#: mod/item.php:470 mod/wall_upload.php:218 mod/wall_upload.php:232
+#: mod/wall_upload.php:239 include/Photo.php:994 include/Photo.php:1009
+#: include/Photo.php:1016 include/Photo.php:1038 include/message.php:145
 msgid "Wall Photos"
 msgstr ""
 
-#: mod/item.php:842
+#: mod/item.php:845
 msgid "System error. Post not saved."
 msgstr ""
 
@@ -1039,7 +1049,7 @@ msgstr ""
 msgid "Create a group of contacts/friends."
 msgstr ""
 
-#: mod/group.php:94 mod/group.php:178 include/group.php:289
+#: mod/group.php:94 mod/group.php:178 include/group.php:292
 msgid "Group Name: "
 msgstr ""
 
@@ -1063,7 +1073,7 @@ msgstr ""
 msgid "Group is empty"
 msgstr ""
 
-#: mod/apps.php:7 index.php:226
+#: mod/apps.php:7 index.php:227
 msgid "You must be logged in to use addons. "
 msgstr ""
 
@@ -1076,12 +1086,12 @@ msgid "No installed applications."
 msgstr ""
 
 #: mod/dfrn_confirm.php:64 mod/profiles.php:18 mod/profiles.php:133
-#: mod/profiles.php:179 mod/profiles.php:627
+#: mod/profiles.php:179 mod/profiles.php:605
 msgid "Profile not found."
 msgstr ""
 
 #: mod/dfrn_confirm.php:120 mod/fsuggest.php:20 mod/fsuggest.php:92
-#: mod/crepair.php:131
+#: mod/crepair.php:114
 msgid "Contact not found."
 msgstr ""
 
@@ -1115,57 +1125,57 @@ msgstr ""
 msgid "Introduction failed or was revoked."
 msgstr ""
 
-#: mod/dfrn_confirm.php:430
+#: mod/dfrn_confirm.php:413
 msgid "Unable to set contact photo."
 msgstr ""
 
-#: mod/dfrn_confirm.php:487 include/conversation.php:185
-#: include/diaspora.php:637
+#: mod/dfrn_confirm.php:470 include/conversation.php:185
+#: include/diaspora.php:638
 #, php-format
 msgid "%1$s is now friends with %2$s"
 msgstr ""
 
-#: mod/dfrn_confirm.php:572
+#: mod/dfrn_confirm.php:552
 #, php-format
 msgid "No user record found for '%s' "
 msgstr ""
 
-#: mod/dfrn_confirm.php:582
+#: mod/dfrn_confirm.php:562
 msgid "Our site encryption key is apparently messed up."
 msgstr ""
 
-#: mod/dfrn_confirm.php:593
+#: mod/dfrn_confirm.php:573
 msgid "Empty site URL was provided or URL could not be decrypted by us."
 msgstr ""
 
-#: mod/dfrn_confirm.php:614
+#: mod/dfrn_confirm.php:594
 msgid "Contact record was not found for you on our site."
 msgstr ""
 
-#: mod/dfrn_confirm.php:628
+#: mod/dfrn_confirm.php:608
 #, php-format
 msgid "Site public key not available in contact record for URL %s."
 msgstr ""
 
-#: mod/dfrn_confirm.php:648
+#: mod/dfrn_confirm.php:628
 msgid ""
 "The ID provided by your system is a duplicate on our system. It should work "
 "if you try again."
 msgstr ""
 
-#: mod/dfrn_confirm.php:659
+#: mod/dfrn_confirm.php:639
 msgid "Unable to set your contact credentials on our system."
 msgstr ""
 
-#: mod/dfrn_confirm.php:726
+#: mod/dfrn_confirm.php:698
 msgid "Unable to update your contact profile details on our system"
 msgstr ""
 
-#: mod/dfrn_confirm.php:753 mod/dfrn_request.php:741 include/items.php:4299
+#: mod/dfrn_confirm.php:725 mod/dfrn_request.php:739 include/items.php:1434
 msgid "[Name Withheld]"
 msgstr ""
 
-#: mod/dfrn_confirm.php:798
+#: mod/dfrn_confirm.php:770
 #, php-format
 msgid "%1$s has joined %2$s"
 msgstr ""
@@ -1190,15 +1200,15 @@ msgstr ""
 msgid "No videos selected"
 msgstr ""
 
-#: mod/videos.php:308 mod/photos.php:1087
+#: mod/videos.php:308 mod/photos.php:1073
 msgid "Access to this item is restricted."
 msgstr ""
 
-#: mod/videos.php:383 include/text.php:1472
+#: mod/videos.php:383 include/text.php:1443
 msgid "View Video"
 msgstr ""
 
-#: mod/videos.php:390 mod/photos.php:1890
+#: mod/videos.php:390 mod/photos.php:1876
 msgid "View Album"
 msgstr ""
 
@@ -1230,7 +1240,7 @@ msgstr ""
 
 #: mod/wall_upload.php:20 mod/wall_upload.php:33 mod/wall_upload.php:86
 #: mod/wall_upload.php:122 mod/wall_upload.php:125 mod/wall_attach.php:17
-#: mod/wall_attach.php:25 mod/wall_attach.php:76 include/api.php:1781
+#: mod/wall_attach.php:25 mod/wall_attach.php:76
 msgid "Invalid request."
 msgstr ""
 
@@ -1288,7 +1298,7 @@ msgid ""
 "Password reset failed."
 msgstr ""
 
-#: mod/lostpass.php:109 boot.php:1444
+#: mod/lostpass.php:109 boot.php:1534
 msgid "Password Reset"
 msgstr ""
 
@@ -1364,15 +1374,15 @@ msgstr ""
 msgid "Reset"
 msgstr ""
 
-#: mod/ping.php:265
+#: mod/ping.php:267
 msgid "{0} wants to be your friend"
 msgstr ""
 
-#: mod/ping.php:280
+#: mod/ping.php:282
 msgid "{0} sent you a message"
 msgstr ""
 
-#: mod/ping.php:295
+#: mod/ping.php:297
 msgid "{0} requested registration"
 msgstr ""
 
@@ -1392,7 +1402,7 @@ msgstr ""
 msgid "System"
 msgstr ""
 
-#: mod/notifications.php:87 mod/admin.php:390 include/nav.php:154
+#: mod/notifications.php:87 mod/admin.php:399 include/nav.php:154
 msgid "Network"
 msgstr ""
 
@@ -1438,7 +1448,7 @@ msgstr ""
 msgid "if applicable"
 msgstr ""
 
-#: mod/notifications.php:176 mod/notifications.php:257 mod/admin.php:1308
+#: mod/notifications.php:176 mod/notifications.php:257 mod/admin.php:1330
 msgid "Approve"
 msgstr ""
 
@@ -1488,8 +1498,8 @@ msgstr ""
 msgid "New Follower"
 msgstr ""
 
-#: mod/notifications.php:250 mod/directory.php:147 include/identity.php:310
-#: include/identity.php:590
+#: mod/notifications.php:250 mod/directory.php:147 include/identity.php:311
+#: include/identity.php:591
 msgid "Gender:"
 msgstr ""
 
@@ -1538,11 +1548,11 @@ msgstr ""
 msgid "Network Notifications"
 msgstr ""
 
-#: mod/notifications.php:385 mod/notify.php:72
+#: mod/notifications.php:385 mod/notify.php:60
 msgid "No more system notifications."
 msgstr ""
 
-#: mod/notifications.php:389 mod/notify.php:76
+#: mod/notifications.php:389 mod/notify.php:64
 msgid "System Notifications"
 msgstr ""
 
@@ -1693,7 +1703,7 @@ msgstr ""
 
 #: mod/message.php:341 mod/message.php:526 mod/content.php:501
 #: mod/content.php:885 mod/wallmessage.php:156 mod/editpost.php:124
-#: mod/photos.php:1610 object/Item.php:396 include/conversation.php:713
+#: mod/photos.php:1596 object/Item.php:396 include/conversation.php:713
 #: include/conversation.php:1201
 msgid "Please wait"
 msgstr ""
@@ -1755,98 +1765,98 @@ msgstr[1] ""
 msgid "[Embedded content - reload page to view]"
 msgstr ""
 
-#: mod/crepair.php:104
+#: mod/crepair.php:87
 msgid "Contact settings applied."
 msgstr ""
 
-#: mod/crepair.php:106
+#: mod/crepair.php:89
 msgid "Contact update failed."
 msgstr ""
 
-#: mod/crepair.php:137
+#: mod/crepair.php:120
 msgid ""
 "<strong>WARNING: This is highly advanced</strong> and if you enter incorrect "
 "information your communications with this contact may stop working."
 msgstr ""
 
-#: mod/crepair.php:138
+#: mod/crepair.php:121
 msgid ""
 "Please use your browser 'Back' button <strong>now</strong> if you are "
 "uncertain what to do on this page."
 msgstr ""
 
-#: mod/crepair.php:151 mod/crepair.php:153
+#: mod/crepair.php:134 mod/crepair.php:136
 msgid "No mirroring"
 msgstr ""
 
-#: mod/crepair.php:151
+#: mod/crepair.php:134
 msgid "Mirror as forwarded posting"
 msgstr ""
 
-#: mod/crepair.php:151 mod/crepair.php:153
+#: mod/crepair.php:134 mod/crepair.php:136
 msgid "Mirror as my own posting"
 msgstr ""
 
-#: mod/crepair.php:167
+#: mod/crepair.php:150
 msgid "Return to contact editor"
 msgstr ""
 
-#: mod/crepair.php:169
+#: mod/crepair.php:152
 msgid "Refetch contact data"
 msgstr ""
 
-#: mod/crepair.php:170 mod/admin.php:1306 mod/admin.php:1318 mod/admin.php:1319
-#: mod/admin.php:1332 mod/settings.php:661 mod/settings.php:687
+#: mod/crepair.php:153 mod/admin.php:1328 mod/admin.php:1340 mod/admin.php:1341
+#: mod/admin.php:1354 mod/settings.php:662 mod/settings.php:688
 msgid "Name"
 msgstr ""
 
-#: mod/crepair.php:171
+#: mod/crepair.php:154
 msgid "Account Nickname"
 msgstr ""
 
-#: mod/crepair.php:172
+#: mod/crepair.php:155
 msgid "@Tagname - overrides Name/Nickname"
 msgstr ""
 
-#: mod/crepair.php:173
+#: mod/crepair.php:156
 msgid "Account URL"
 msgstr ""
 
-#: mod/crepair.php:174
+#: mod/crepair.php:157
 msgid "Friend Request URL"
 msgstr ""
 
-#: mod/crepair.php:175
+#: mod/crepair.php:158
 msgid "Friend Confirm URL"
 msgstr ""
 
-#: mod/crepair.php:176
+#: mod/crepair.php:159
 msgid "Notification Endpoint URL"
 msgstr ""
 
-#: mod/crepair.php:177
+#: mod/crepair.php:160
 msgid "Poll/Feed URL"
 msgstr ""
 
-#: mod/crepair.php:178
+#: mod/crepair.php:161
 msgid "New photo from this URL"
 msgstr ""
 
-#: mod/crepair.php:179
+#: mod/crepair.php:162
 msgid "Remote Self"
 msgstr ""
 
-#: mod/crepair.php:182
+#: mod/crepair.php:165
 msgid "Mirror postings from this contact"
 msgstr ""
 
-#: mod/crepair.php:184
+#: mod/crepair.php:167
 msgid ""
 "Mark this contact as remote_self, this will cause friendica to repost new "
 "entries from this contact."
 msgstr ""
 
-#: mod/bookmarklet.php:12 boot.php:1430 include/nav.php:91
+#: mod/bookmarklet.php:12 boot.php:1520 include/nav.php:91
 msgid "Login"
 msgstr ""
 
@@ -1864,8 +1874,8 @@ msgid "Connect"
 msgstr ""
 
 #: mod/dirfind.php:195 mod/allfriends.php:64 mod/match.php:70
-#: mod/directory.php:162 mod/suggest.php:81 include/Contact.php:283
-#: include/Contact.php:296 include/Contact.php:338 include/conversation.php:912
+#: mod/directory.php:162 mod/suggest.php:81 include/Contact.php:285
+#: include/Contact.php:298 include/Contact.php:340 include/conversation.php:912
 #: include/conversation.php:926
 msgid "View Profile"
 msgstr ""
@@ -1879,14 +1889,14 @@ msgstr ""
 msgid "No matches"
 msgstr ""
 
-#: mod/fbrowser.php:32 include/identity.php:702 include/nav.php:77
+#: mod/fbrowser.php:32 include/identity.php:703 include/nav.php:77
 #: view/theme/diabook/theme.php:126
 msgid "Photos"
 msgstr ""
 
 #: mod/fbrowser.php:41 mod/fbrowser.php:62 mod/photos.php:62 mod/photos.php:192
-#: mod/photos.php:1119 mod/photos.php:1245 mod/photos.php:1268
-#: mod/photos.php:1838 mod/photos.php:1850 view/theme/diabook/theme.php:499
+#: mod/photos.php:1105 mod/photos.php:1231 mod/photos.php:1254
+#: mod/photos.php:1824 mod/photos.php:1836 view/theme/diabook/theme.php:499
 msgid "Contact Photos"
 msgstr ""
 
@@ -1902,19 +1912,19 @@ msgstr ""
 msgid "Theme settings updated."
 msgstr ""
 
-#: mod/admin.php:156 mod/admin.php:888
+#: mod/admin.php:156 mod/admin.php:904
 msgid "Site"
 msgstr ""
 
-#: mod/admin.php:157 mod/admin.php:832 mod/admin.php:1301 mod/admin.php:1316
+#: mod/admin.php:157 mod/admin.php:848 mod/admin.php:1323 mod/admin.php:1338
 msgid "Users"
 msgstr ""
 
-#: mod/admin.php:158 mod/admin.php:1416 mod/admin.php:1476 mod/settings.php:72
+#: mod/admin.php:158 mod/admin.php:1438 mod/admin.php:1498 mod/settings.php:72
 msgid "Plugins"
 msgstr ""
 
-#: mod/admin.php:159 mod/admin.php:1674 mod/admin.php:1724
+#: mod/admin.php:159 mod/admin.php:1696 mod/admin.php:1746
 msgid "Themes"
 msgstr ""
 
@@ -1926,19 +1936,19 @@ msgstr ""
 msgid "DB updates"
 msgstr ""
 
-#: mod/admin.php:162 mod/admin.php:385
+#: mod/admin.php:162 mod/admin.php:394
 msgid "Inspect Queue"
 msgstr ""
 
-#: mod/admin.php:163 mod/admin.php:354
+#: mod/admin.php:163 mod/admin.php:363
 msgid "Federation Statistics"
 msgstr ""
 
-#: mod/admin.php:177 mod/admin.php:188 mod/admin.php:1792
+#: mod/admin.php:177 mod/admin.php:188 mod/admin.php:1814
 msgid "Logs"
 msgstr ""
 
-#: mod/admin.php:178 mod/admin.php:1859
+#: mod/admin.php:178 mod/admin.php:1881
 msgid "View Logs"
 msgstr ""
 
@@ -1966,739 +1976,750 @@ msgstr ""
 msgid "User registrations waiting for confirmation"
 msgstr ""
 
-#: mod/admin.php:347
+#: mod/admin.php:356
 msgid ""
 "This page offers you some numbers to the known part of the federated social "
 "network your Friendica node is part of. These numbers are not complete but "
 "only reflect the part of the network your node is aware of."
 msgstr ""
 
-#: mod/admin.php:348
+#: mod/admin.php:357
 msgid ""
 "The <em>Auto Discovered Contact Directory</em> feature is not enabled, it "
 "will improve the data displayed here."
 msgstr ""
 
-#: mod/admin.php:353 mod/admin.php:384 mod/admin.php:441 mod/admin.php:887
-#: mod/admin.php:1300 mod/admin.php:1415 mod/admin.php:1475 mod/admin.php:1673
-#: mod/admin.php:1723 mod/admin.php:1791 mod/admin.php:1858
+#: mod/admin.php:362 mod/admin.php:393 mod/admin.php:450 mod/admin.php:903
+#: mod/admin.php:1322 mod/admin.php:1437 mod/admin.php:1497 mod/admin.php:1695
+#: mod/admin.php:1745 mod/admin.php:1813 mod/admin.php:1880
 msgid "Administration"
 msgstr ""
 
-#: mod/admin.php:360
+#: mod/admin.php:369
 #, php-format
 msgid "Currently this node is aware of %d nodes from the following platforms:"
 msgstr ""
 
-#: mod/admin.php:387
+#: mod/admin.php:396
 msgid "ID"
 msgstr ""
 
-#: mod/admin.php:388
+#: mod/admin.php:397
 msgid "Recipient Name"
 msgstr ""
 
-#: mod/admin.php:389
+#: mod/admin.php:398
 msgid "Recipient Profile"
 msgstr ""
 
-#: mod/admin.php:391
+#: mod/admin.php:400
 msgid "Created"
 msgstr ""
 
-#: mod/admin.php:392
+#: mod/admin.php:401
 msgid "Last Tried"
 msgstr ""
 
-#: mod/admin.php:393
+#: mod/admin.php:402
 msgid ""
 "This page lists the content of the queue for outgoing postings. These are "
 "postings the initial delivery failed for. They will be resend later and "
 "eventually deleted if the delivery fails permanently."
 msgstr ""
 
-#: mod/admin.php:412 mod/admin.php:1254
+#: mod/admin.php:421 mod/admin.php:1276
 msgid "Normal Account"
 msgstr ""
 
-#: mod/admin.php:413 mod/admin.php:1255
+#: mod/admin.php:422 mod/admin.php:1277
 msgid "Soapbox Account"
 msgstr ""
 
-#: mod/admin.php:414 mod/admin.php:1256
+#: mod/admin.php:423 mod/admin.php:1278
 msgid "Community/Celebrity Account"
 msgstr ""
 
-#: mod/admin.php:415 mod/admin.php:1257
+#: mod/admin.php:424 mod/admin.php:1279
 msgid "Automatic Friend Account"
 msgstr ""
 
-#: mod/admin.php:416
+#: mod/admin.php:425
 msgid "Blog Account"
 msgstr ""
 
-#: mod/admin.php:417
+#: mod/admin.php:426
 msgid "Private Forum"
 msgstr ""
 
-#: mod/admin.php:436
+#: mod/admin.php:445
 msgid "Message queues"
 msgstr ""
 
-#: mod/admin.php:442
+#: mod/admin.php:451
 msgid "Summary"
 msgstr ""
 
-#: mod/admin.php:444
+#: mod/admin.php:453
 msgid "Registered users"
 msgstr ""
 
-#: mod/admin.php:446
+#: mod/admin.php:455
 msgid "Pending registrations"
 msgstr ""
 
-#: mod/admin.php:447
+#: mod/admin.php:456
 msgid "Version"
 msgstr ""
 
-#: mod/admin.php:452
+#: mod/admin.php:461
 msgid "Active plugins"
 msgstr ""
 
-#: mod/admin.php:475
+#: mod/admin.php:484
 msgid "Can not parse base url. Must have at least <scheme>://<domain>"
 msgstr ""
 
-#: mod/admin.php:760
+#: mod/admin.php:776
 msgid "RINO2 needs mcrypt php extension to work."
 msgstr ""
 
-#: mod/admin.php:768
+#: mod/admin.php:784
 msgid "Site settings updated."
 msgstr ""
 
-#: mod/admin.php:796 mod/settings.php:912
+#: mod/admin.php:812 mod/settings.php:916
 msgid "No special theme for mobile devices"
 msgstr ""
 
-#: mod/admin.php:815
+#: mod/admin.php:831
 msgid "No community page"
 msgstr ""
 
-#: mod/admin.php:816
+#: mod/admin.php:832
 msgid "Public postings from users of this site"
 msgstr ""
 
-#: mod/admin.php:817
+#: mod/admin.php:833
 msgid "Global community page"
 msgstr ""
 
-#: mod/admin.php:823
+#: mod/admin.php:839
 msgid "At post arrival"
 msgstr ""
 
-#: mod/admin.php:824 include/contact_selectors.php:56
+#: mod/admin.php:840 include/contact_selectors.php:56
 msgid "Frequently"
 msgstr ""
 
-#: mod/admin.php:825 include/contact_selectors.php:57
+#: mod/admin.php:841 include/contact_selectors.php:57
 msgid "Hourly"
 msgstr ""
 
-#: mod/admin.php:826 include/contact_selectors.php:58
+#: mod/admin.php:842 include/contact_selectors.php:58
 msgid "Twice daily"
 msgstr ""
 
-#: mod/admin.php:827 include/contact_selectors.php:59
+#: mod/admin.php:843 include/contact_selectors.php:59
 msgid "Daily"
 msgstr ""
 
-#: mod/admin.php:833
+#: mod/admin.php:849
 msgid "Users, Global Contacts"
 msgstr ""
 
-#: mod/admin.php:834
+#: mod/admin.php:850
 msgid "Users, Global Contacts/fallback"
 msgstr ""
 
-#: mod/admin.php:838
+#: mod/admin.php:854
 msgid "One month"
 msgstr ""
 
-#: mod/admin.php:839
+#: mod/admin.php:855
 msgid "Three months"
 msgstr ""
 
-#: mod/admin.php:840
+#: mod/admin.php:856
 msgid "Half a year"
 msgstr ""
 
-#: mod/admin.php:841
+#: mod/admin.php:857
 msgid "One year"
 msgstr ""
 
-#: mod/admin.php:846
+#: mod/admin.php:862
 msgid "Multi user instance"
 msgstr ""
 
-#: mod/admin.php:869
+#: mod/admin.php:885
 msgid "Closed"
 msgstr ""
 
-#: mod/admin.php:870
+#: mod/admin.php:886
 msgid "Requires approval"
 msgstr ""
 
-#: mod/admin.php:871
+#: mod/admin.php:887
 msgid "Open"
 msgstr ""
 
-#: mod/admin.php:875
+#: mod/admin.php:891
 msgid "No SSL policy, links will track page SSL state"
 msgstr ""
 
-#: mod/admin.php:876
+#: mod/admin.php:892
 msgid "Force all links to use SSL"
 msgstr ""
 
-#: mod/admin.php:877
+#: mod/admin.php:893
 msgid "Self-signed certificate, use SSL for local links only (discouraged)"
 msgstr ""
 
-#: mod/admin.php:889 mod/admin.php:1477 mod/admin.php:1725 mod/admin.php:1793
-#: mod/admin.php:1942 mod/settings.php:659 mod/settings.php:769
-#: mod/settings.php:813 mod/settings.php:882 mod/settings.php:969
-#: mod/settings.php:1204
+#: mod/admin.php:905 mod/admin.php:1499 mod/admin.php:1747 mod/admin.php:1815
+#: mod/admin.php:1964 mod/settings.php:660 mod/settings.php:770
+#: mod/settings.php:817 mod/settings.php:886 mod/settings.php:973
+#: mod/settings.php:1208
 msgid "Save Settings"
 msgstr ""
 
-#: mod/admin.php:890 mod/register.php:263
+#: mod/admin.php:906 mod/register.php:263
 msgid "Registration"
 msgstr ""
 
-#: mod/admin.php:891
+#: mod/admin.php:907
 msgid "File upload"
 msgstr ""
 
-#: mod/admin.php:892
+#: mod/admin.php:908
 msgid "Policies"
 msgstr ""
 
-#: mod/admin.php:893
-msgid "Advanced"
-msgstr ""
-
-#: mod/admin.php:894
+#: mod/admin.php:910
 msgid "Auto Discovered Contact Directory"
 msgstr ""
 
-#: mod/admin.php:895
+#: mod/admin.php:911
 msgid "Performance"
 msgstr ""
 
-#: mod/admin.php:896
+#: mod/admin.php:912
+msgid "Worker"
+msgstr ""
+
+#: mod/admin.php:913
 msgid ""
 "Relocate - WARNING: advanced function. Could make this server unreachable."
 msgstr ""
 
-#: mod/admin.php:899
+#: mod/admin.php:916
 msgid "Site name"
 msgstr ""
 
-#: mod/admin.php:900
+#: mod/admin.php:917
 msgid "Host name"
 msgstr ""
 
-#: mod/admin.php:901
+#: mod/admin.php:918
 msgid "Sender Email"
 msgstr ""
 
-#: mod/admin.php:901
+#: mod/admin.php:918
 msgid ""
 "The email address your server shall use to send notification emails from."
 msgstr ""
 
-#: mod/admin.php:902
+#: mod/admin.php:919
 msgid "Banner/Logo"
 msgstr ""
 
-#: mod/admin.php:903
+#: mod/admin.php:920
 msgid "Shortcut icon"
 msgstr ""
 
-#: mod/admin.php:903
+#: mod/admin.php:920
 msgid "Link to an icon that will be used for browsers."
 msgstr ""
 
-#: mod/admin.php:904
+#: mod/admin.php:921
 msgid "Touch icon"
 msgstr ""
 
-#: mod/admin.php:904
+#: mod/admin.php:921
 msgid "Link to an icon that will be used for tablets and mobiles."
 msgstr ""
 
-#: mod/admin.php:905
+#: mod/admin.php:922
 msgid "Additional Info"
 msgstr ""
 
-#: mod/admin.php:905
+#: mod/admin.php:922
 #, php-format
 msgid ""
 "For public servers: you can add additional information here that will be "
 "listed at %s/siteinfo."
 msgstr ""
 
-#: mod/admin.php:906
+#: mod/admin.php:923
 msgid "System language"
 msgstr ""
 
-#: mod/admin.php:907
+#: mod/admin.php:924
 msgid "System theme"
 msgstr ""
 
-#: mod/admin.php:907
+#: mod/admin.php:924
 msgid ""
 "Default system theme - may be over-ridden by user profiles - <a href='#' "
 "id='cnftheme'>change theme settings</a>"
 msgstr ""
 
-#: mod/admin.php:908
+#: mod/admin.php:925
 msgid "Mobile system theme"
 msgstr ""
 
-#: mod/admin.php:908
+#: mod/admin.php:925
 msgid "Theme for mobile devices"
 msgstr ""
 
-#: mod/admin.php:909
+#: mod/admin.php:926
 msgid "SSL link policy"
 msgstr ""
 
-#: mod/admin.php:909
+#: mod/admin.php:926
 msgid "Determines whether generated links should be forced to use SSL"
 msgstr ""
 
-#: mod/admin.php:910
+#: mod/admin.php:927
 msgid "Force SSL"
 msgstr ""
 
-#: mod/admin.php:910
+#: mod/admin.php:927
 msgid ""
 "Force all Non-SSL requests to SSL - Attention: on some systems it could lead "
 "to endless loops."
 msgstr ""
 
-#: mod/admin.php:911
+#: mod/admin.php:928
 msgid "Old style 'Share'"
 msgstr ""
 
-#: mod/admin.php:911
+#: mod/admin.php:928
 msgid "Deactivates the bbcode element 'share' for repeating items."
 msgstr ""
 
-#: mod/admin.php:912
+#: mod/admin.php:929
 msgid "Hide help entry from navigation menu"
 msgstr ""
 
-#: mod/admin.php:912
+#: mod/admin.php:929
 msgid ""
 "Hides the menu entry for the Help pages from the navigation menu. You can "
 "still access it calling /help directly."
 msgstr ""
 
-#: mod/admin.php:913
+#: mod/admin.php:930
 msgid "Single user instance"
 msgstr ""
 
-#: mod/admin.php:913
+#: mod/admin.php:930
 msgid "Make this instance multi-user or single-user for the named user"
 msgstr ""
 
-#: mod/admin.php:914
+#: mod/admin.php:931
 msgid "Maximum image size"
 msgstr ""
 
-#: mod/admin.php:914
+#: mod/admin.php:931
 msgid ""
 "Maximum size in bytes of uploaded images. Default is 0, which means no "
 "limits."
 msgstr ""
 
-#: mod/admin.php:915
+#: mod/admin.php:932
 msgid "Maximum image length"
 msgstr ""
 
-#: mod/admin.php:915
+#: mod/admin.php:932
 msgid ""
 "Maximum length in pixels of the longest side of uploaded images. Default is "
 "-1, which means no limits."
 msgstr ""
 
-#: mod/admin.php:916
+#: mod/admin.php:933
 msgid "JPEG image quality"
 msgstr ""
 
-#: mod/admin.php:916
+#: mod/admin.php:933
 msgid ""
 "Uploaded JPEGS will be saved at this quality setting [0-100]. Default is "
 "100, which is full quality."
 msgstr ""
 
-#: mod/admin.php:918
+#: mod/admin.php:935
 msgid "Register policy"
 msgstr ""
 
-#: mod/admin.php:919
+#: mod/admin.php:936
 msgid "Maximum Daily Registrations"
 msgstr ""
 
-#: mod/admin.php:919
+#: mod/admin.php:936
 msgid ""
 "If registration is permitted above, this sets the maximum number of new user "
 "registrations to accept per day.  If register is set to closed, this setting "
 "has no effect."
 msgstr ""
 
-#: mod/admin.php:920
+#: mod/admin.php:937
 msgid "Register text"
 msgstr ""
 
-#: mod/admin.php:920
+#: mod/admin.php:937
 msgid "Will be displayed prominently on the registration page."
 msgstr ""
 
-#: mod/admin.php:921
+#: mod/admin.php:938
 msgid "Accounts abandoned after x days"
 msgstr ""
 
-#: mod/admin.php:921
+#: mod/admin.php:938
 msgid ""
 "Will not waste system resources polling external sites for abandonded "
 "accounts. Enter 0 for no time limit."
 msgstr ""
 
-#: mod/admin.php:922
+#: mod/admin.php:939
 msgid "Allowed friend domains"
 msgstr ""
 
-#: mod/admin.php:922
+#: mod/admin.php:939
 msgid ""
 "Comma separated list of domains which are allowed to establish friendships "
 "with this site. Wildcards are accepted. Empty to allow any domains"
 msgstr ""
 
-#: mod/admin.php:923
+#: mod/admin.php:940
 msgid "Allowed email domains"
 msgstr ""
 
-#: mod/admin.php:923
+#: mod/admin.php:940
 msgid ""
 "Comma separated list of domains which are allowed in email addresses for "
 "registrations to this site. Wildcards are accepted. Empty to allow any "
 "domains"
 msgstr ""
 
-#: mod/admin.php:924
+#: mod/admin.php:941
 msgid "Block public"
 msgstr ""
 
-#: mod/admin.php:924
+#: mod/admin.php:941
 msgid ""
 "Check to block public access to all otherwise public personal pages on this "
 "site unless you are currently logged in."
 msgstr ""
 
-#: mod/admin.php:925
+#: mod/admin.php:942
 msgid "Force publish"
 msgstr ""
 
-#: mod/admin.php:925
+#: mod/admin.php:942
 msgid ""
 "Check to force all profiles on this site to be listed in the site directory."
 msgstr ""
 
-#: mod/admin.php:926
+#: mod/admin.php:943
 msgid "Global directory URL"
 msgstr ""
 
-#: mod/admin.php:926
+#: mod/admin.php:943
 msgid ""
 "URL to the global directory. If this is not set, the global directory is "
 "completely unavailable to the application."
 msgstr ""
 
-#: mod/admin.php:927
+#: mod/admin.php:944
 msgid "Allow threaded items"
 msgstr ""
 
-#: mod/admin.php:927
+#: mod/admin.php:944
 msgid "Allow infinite level threading for items on this site."
 msgstr ""
 
-#: mod/admin.php:928
+#: mod/admin.php:945
 msgid "Private posts by default for new users"
 msgstr ""
 
-#: mod/admin.php:928
+#: mod/admin.php:945
 msgid ""
 "Set default post permissions for all new members to the default privacy "
 "group rather than public."
 msgstr ""
 
-#: mod/admin.php:929
+#: mod/admin.php:946
 msgid "Don't include post content in email notifications"
 msgstr ""
 
-#: mod/admin.php:929
+#: mod/admin.php:946
 msgid ""
 "Don't include the content of a post/comment/private message/etc. in the "
 "email notifications that are sent out from this site, as a privacy measure."
 msgstr ""
 
-#: mod/admin.php:930
+#: mod/admin.php:947
 msgid "Disallow public access to addons listed in the apps menu."
 msgstr ""
 
-#: mod/admin.php:930
+#: mod/admin.php:947
 msgid ""
 "Checking this box will restrict addons listed in the apps menu to members "
 "only."
 msgstr ""
 
-#: mod/admin.php:931
+#: mod/admin.php:948
 msgid "Don't embed private images in posts"
 msgstr ""
 
-#: mod/admin.php:931
+#: mod/admin.php:948
 msgid ""
 "Don't replace locally-hosted private photos in posts with an embedded copy "
 "of the image. This means that contacts who receive posts containing private "
 "photos will have to authenticate and load each image, which may take a while."
 msgstr ""
 
-#: mod/admin.php:932
+#: mod/admin.php:949
 msgid "Allow Users to set remote_self"
 msgstr ""
 
-#: mod/admin.php:932
+#: mod/admin.php:949
 msgid ""
 "With checking this, every user is allowed to mark every contact as a "
 "remote_self in the repair contact dialog. Setting this flag on a contact "
 "causes mirroring every posting of that contact in the users stream."
 msgstr ""
 
-#: mod/admin.php:933
+#: mod/admin.php:950
 msgid "Block multiple registrations"
 msgstr ""
 
-#: mod/admin.php:933
+#: mod/admin.php:950
 msgid "Disallow users to register additional accounts for use as pages."
 msgstr ""
 
-#: mod/admin.php:934
+#: mod/admin.php:951
 msgid "OpenID support"
 msgstr ""
 
-#: mod/admin.php:934
+#: mod/admin.php:951
 msgid "OpenID support for registration and logins."
 msgstr ""
 
-#: mod/admin.php:935
+#: mod/admin.php:952
 msgid "Fullname check"
 msgstr ""
 
-#: mod/admin.php:935
+#: mod/admin.php:952
 msgid ""
 "Force users to register with a space between firstname and lastname in Full "
 "name, as an antispam measure"
 msgstr ""
 
-#: mod/admin.php:936
+#: mod/admin.php:953
 msgid "UTF-8 Regular expressions"
 msgstr ""
 
-#: mod/admin.php:936
+#: mod/admin.php:953
 msgid "Use PHP UTF8 regular expressions"
 msgstr ""
 
-#: mod/admin.php:937
+#: mod/admin.php:954
 msgid "Community Page Style"
 msgstr ""
 
-#: mod/admin.php:937
+#: mod/admin.php:954
 msgid ""
 "Type of community page to show. 'Global community' shows every public "
 "posting from an open distributed network that arrived on this server."
 msgstr ""
 
-#: mod/admin.php:938
+#: mod/admin.php:955
 msgid "Posts per user on community page"
 msgstr ""
 
-#: mod/admin.php:938
+#: mod/admin.php:955
 msgid ""
 "The maximum number of posts per user on the community page. (Not valid for "
 "'Global Community')"
 msgstr ""
 
-#: mod/admin.php:939
+#: mod/admin.php:956
 msgid "Enable OStatus support"
 msgstr ""
 
-#: mod/admin.php:939
+#: mod/admin.php:956
 msgid ""
 "Provide built-in OStatus (StatusNet, GNU Social etc.) compatibility. All "
 "communications in OStatus are public, so privacy warnings will be "
 "occasionally displayed."
 msgstr ""
 
-#: mod/admin.php:940
+#: mod/admin.php:957
 msgid "OStatus conversation completion interval"
 msgstr ""
 
-#: mod/admin.php:940
+#: mod/admin.php:957
 msgid ""
 "How often shall the poller check for new entries in OStatus conversations? "
 "This can be a very ressource task."
 msgstr ""
 
-#: mod/admin.php:941
+#: mod/admin.php:958
+msgid "Only import OStatus threads from our contacts"
+msgstr ""
+
+#: mod/admin.php:958
+msgid ""
+"Normally we import every content from our OStatus contacts. With this option "
+"we only store threads that are started by a contact that is known on our "
+"system."
+msgstr ""
+
+#: mod/admin.php:959
 msgid "OStatus support can only be enabled if threading is enabled."
 msgstr ""
 
-#: mod/admin.php:943
+#: mod/admin.php:961
 msgid ""
 "Diaspora support can't be enabled because Friendica was installed into a sub "
 "directory."
 msgstr ""
 
-#: mod/admin.php:944
+#: mod/admin.php:962
 msgid "Enable Diaspora support"
 msgstr ""
 
-#: mod/admin.php:944
+#: mod/admin.php:962
 msgid "Provide built-in Diaspora network compatibility."
 msgstr ""
 
-#: mod/admin.php:945
+#: mod/admin.php:963
 msgid "Only allow Friendica contacts"
 msgstr ""
 
-#: mod/admin.php:945
+#: mod/admin.php:963
 msgid ""
 "All contacts must use Friendica protocols. All other built-in communication "
 "protocols disabled."
 msgstr ""
 
-#: mod/admin.php:946
+#: mod/admin.php:964
 msgid "Verify SSL"
 msgstr ""
 
-#: mod/admin.php:946
+#: mod/admin.php:964
 msgid ""
 "If you wish, you can turn on strict certificate checking. This will mean you "
 "cannot connect (at all) to self-signed SSL sites."
 msgstr ""
 
-#: mod/admin.php:947
+#: mod/admin.php:965
 msgid "Proxy user"
 msgstr ""
 
-#: mod/admin.php:948
+#: mod/admin.php:966
 msgid "Proxy URL"
 msgstr ""
 
-#: mod/admin.php:949
+#: mod/admin.php:967
 msgid "Network timeout"
 msgstr ""
 
-#: mod/admin.php:949
+#: mod/admin.php:967
 msgid "Value is in seconds. Set to 0 for unlimited (not recommended)."
 msgstr ""
 
-#: mod/admin.php:950
+#: mod/admin.php:968
 msgid "Delivery interval"
 msgstr ""
 
-#: mod/admin.php:950
+#: mod/admin.php:968
 msgid ""
 "Delay background delivery processes by this many seconds to reduce system "
 "load. Recommend: 4-5 for shared hosts, 2-3 for virtual private servers. 0-1 "
 "for large dedicated servers."
 msgstr ""
 
-#: mod/admin.php:951
+#: mod/admin.php:969
 msgid "Poll interval"
 msgstr ""
 
-#: mod/admin.php:951
+#: mod/admin.php:969
 msgid ""
 "Delay background polling processes by this many seconds to reduce system "
 "load. If 0, use delivery interval."
 msgstr ""
 
-#: mod/admin.php:952
+#: mod/admin.php:970
 msgid "Maximum Load Average"
 msgstr ""
 
-#: mod/admin.php:952
+#: mod/admin.php:970
 msgid ""
 "Maximum system load before delivery and poll processes are deferred - "
 "default 50."
 msgstr ""
 
-#: mod/admin.php:953
+#: mod/admin.php:971
 msgid "Maximum Load Average (Frontend)"
 msgstr ""
 
-#: mod/admin.php:953
+#: mod/admin.php:971
 msgid "Maximum system load before the frontend quits service - default 50."
 msgstr ""
 
-#: mod/admin.php:954
+#: mod/admin.php:972
 msgid "Maximum table size for optimization"
 msgstr ""
 
-#: mod/admin.php:954
+#: mod/admin.php:972
 msgid ""
 "Maximum table size (in MB) for the automatic optimization - default 100 MB. "
 "Enter -1 to disable it."
 msgstr ""
 
-#: mod/admin.php:955
+#: mod/admin.php:973
 msgid "Minimum level of fragmentation"
 msgstr ""
 
-#: mod/admin.php:955
+#: mod/admin.php:973
 msgid ""
 "Minimum fragmenation level to start the automatic optimization - default "
 "value is 30%."
 msgstr ""
 
-#: mod/admin.php:957
+#: mod/admin.php:975
 msgid "Periodical check of global contacts"
 msgstr ""
 
-#: mod/admin.php:957
+#: mod/admin.php:975
 msgid ""
 "If enabled, the global contacts are checked periodically for missing or "
 "outdated data and the vitality of the contacts and servers."
 msgstr ""
 
-#: mod/admin.php:958
+#: mod/admin.php:976
 msgid "Days between requery"
 msgstr ""
 
-#: mod/admin.php:958
+#: mod/admin.php:976
 msgid "Number of days after which a server is requeried for his contacts."
 msgstr ""
 
-#: mod/admin.php:959
+#: mod/admin.php:977
 msgid "Discover contacts from other servers"
 msgstr ""
 
-#: mod/admin.php:959
+#: mod/admin.php:977
 msgid ""
 "Periodically query other servers for contacts. You can choose between "
 "'users': the users on the remote system, 'Global Contacts': active contacts "
@@ -2708,32 +2729,32 @@ msgid ""
 "Global Contacts'."
 msgstr ""
 
-#: mod/admin.php:960
+#: mod/admin.php:978
 msgid "Timeframe for fetching global contacts"
 msgstr ""
 
-#: mod/admin.php:960
+#: mod/admin.php:978
 msgid ""
 "When the discovery is activated, this value defines the timeframe for the "
 "activity of the global contacts that are fetched from other servers."
 msgstr ""
 
-#: mod/admin.php:961
+#: mod/admin.php:979
 msgid "Search the local directory"
 msgstr ""
 
-#: mod/admin.php:961
+#: mod/admin.php:979
 msgid ""
 "Search the local directory instead of the global directory. When searching "
 "locally, every search will be executed on the global directory in the "
 "background. This improves the search results when the search is repeated."
 msgstr ""
 
-#: mod/admin.php:963
+#: mod/admin.php:981
 msgid "Publish server information"
 msgstr ""
 
-#: mod/admin.php:963
+#: mod/admin.php:981
 msgid ""
 "If enabled, general server and usage data will be published. The data "
 "contains the name and version of the server, number of users with public "
@@ -2741,204 +2762,235 @@ msgid ""
 "href='http://the-federation.info/'>the-federation.info</a> for details."
 msgstr ""
 
-#: mod/admin.php:965
+#: mod/admin.php:983
 msgid "Use MySQL full text engine"
 msgstr ""
 
-#: mod/admin.php:965
+#: mod/admin.php:983
 msgid ""
 "Activates the full text engine. Speeds up search - but can only search for "
 "four and more characters."
 msgstr ""
 
-#: mod/admin.php:966
+#: mod/admin.php:984
 msgid "Suppress Language"
 msgstr ""
 
-#: mod/admin.php:966
+#: mod/admin.php:984
 msgid "Suppress language information in meta information about a posting."
 msgstr ""
 
-#: mod/admin.php:967
+#: mod/admin.php:985
 msgid "Suppress Tags"
 msgstr ""
 
-#: mod/admin.php:967
+#: mod/admin.php:985
 msgid "Suppress showing a list of hashtags at the end of the posting."
 msgstr ""
 
-#: mod/admin.php:968
+#: mod/admin.php:986
 msgid "Path to item cache"
 msgstr ""
 
-#: mod/admin.php:968
+#: mod/admin.php:986
 msgid "The item caches buffers generated bbcode and external images."
 msgstr ""
 
-#: mod/admin.php:969
+#: mod/admin.php:987
 msgid "Cache duration in seconds"
 msgstr ""
 
-#: mod/admin.php:969
+#: mod/admin.php:987
 msgid ""
 "How long should the cache files be hold? Default value is 86400 seconds (One "
 "day). To disable the item cache, set the value to -1."
 msgstr ""
 
-#: mod/admin.php:970
+#: mod/admin.php:988
 msgid "Maximum numbers of comments per post"
 msgstr ""
 
-#: mod/admin.php:970
+#: mod/admin.php:988
 msgid "How much comments should be shown for each post? Default value is 100."
 msgstr ""
 
-#: mod/admin.php:971
+#: mod/admin.php:989
 msgid "Path for lock file"
 msgstr ""
 
-#: mod/admin.php:971
+#: mod/admin.php:989
 msgid ""
 "The lock file is used to avoid multiple pollers at one time. Only define a "
 "folder here."
 msgstr ""
 
-#: mod/admin.php:972
+#: mod/admin.php:990
 msgid "Temp path"
 msgstr ""
 
-#: mod/admin.php:972
+#: mod/admin.php:990
 msgid ""
 "If you have a restricted system where the webserver can't access the system "
 "temp path, enter another path here."
 msgstr ""
 
-#: mod/admin.php:973
+#: mod/admin.php:991
 msgid "Base path to installation"
 msgstr ""
 
-#: mod/admin.php:973
+#: mod/admin.php:991
 msgid ""
 "If the system cannot detect the correct path to your installation, enter the "
 "correct path here. This setting should only be set if you are using a "
 "restricted system and symbolic links to your webroot."
 msgstr ""
 
-#: mod/admin.php:974
+#: mod/admin.php:992
 msgid "Disable picture proxy"
 msgstr ""
 
-#: mod/admin.php:974
+#: mod/admin.php:992
 msgid ""
 "The picture proxy increases performance and privacy. It shouldn't be used on "
 "systems with very low bandwith."
 msgstr ""
 
-#: mod/admin.php:975
+#: mod/admin.php:993
 msgid "Enable old style pager"
 msgstr ""
 
-#: mod/admin.php:975
+#: mod/admin.php:993
 msgid ""
 "The old style pager has page numbers but slows down massively the page speed."
 msgstr ""
 
-#: mod/admin.php:976
+#: mod/admin.php:994
 msgid "Only search in tags"
 msgstr ""
 
-#: mod/admin.php:976
+#: mod/admin.php:994
 msgid "On large systems the text search can slow down the system extremely."
 msgstr ""
 
-#: mod/admin.php:978
+#: mod/admin.php:996
 msgid "New base url"
 msgstr ""
 
-#: mod/admin.php:978
+#: mod/admin.php:996
 msgid ""
 "Change base url for this server. Sends relocate message to all DFRN contacts "
 "of all users."
 msgstr ""
 
-#: mod/admin.php:980
+#: mod/admin.php:998
 msgid "RINO Encryption"
 msgstr ""
 
-#: mod/admin.php:980
+#: mod/admin.php:998
 msgid "Encryption layer between nodes."
 msgstr ""
 
-#: mod/admin.php:981
+#: mod/admin.php:999
 msgid "Embedly API key"
 msgstr ""
 
-#: mod/admin.php:981
+#: mod/admin.php:999
 msgid ""
 "<a href='http://embed.ly'>Embedly</a> is used to fetch additional data for "
 "web pages. This is an optional parameter."
 msgstr ""
 
-#: mod/admin.php:1010
+#: mod/admin.php:1001
+msgid "Enable 'worker' background processing"
+msgstr ""
+
+#: mod/admin.php:1001
+msgid ""
+"The worker background processing limits the number of parallel background "
+"jobs to a maximum number and respects the system load."
+msgstr ""
+
+#: mod/admin.php:1002
+msgid "Maximum number of parallel workers"
+msgstr ""
+
+#: mod/admin.php:1002
+msgid ""
+"On shared hosters set this to 2. On larger systems, values of 10 are great. "
+"Default value is 4."
+msgstr ""
+
+#: mod/admin.php:1003
+msgid "Don't use 'proc_open' with the worker"
+msgstr ""
+
+#: mod/admin.php:1003
+msgid ""
+"Enable this if your system doesn't allow the use of 'proc_open'. This can "
+"happen on shared hosters. If this is enabled you should increase the "
+"frequency of poller calls in your crontab."
+msgstr ""
+
+#: mod/admin.php:1032
 msgid "Update has been marked successful"
 msgstr ""
 
-#: mod/admin.php:1018
-#, php-format
-msgid "Database structure update %s was successfully applied."
-msgstr ""
-
-#: mod/admin.php:1021
-#, php-format
-msgid "Executing of database structure update %s failed with error: %s"
-msgstr ""
-
-#: mod/admin.php:1033
-#, php-format
-msgid "Executing %s failed with error: %s"
-msgstr ""
-
-#: mod/admin.php:1036
-#, php-format
-msgid "Update %s was successfully applied."
-msgstr ""
-
 #: mod/admin.php:1040
 #, php-format
+msgid "Database structure update %s was successfully applied."
+msgstr ""
+
+#: mod/admin.php:1043
+#, php-format
+msgid "Executing of database structure update %s failed with error: %s"
+msgstr ""
+
+#: mod/admin.php:1055
+#, php-format
+msgid "Executing %s failed with error: %s"
+msgstr ""
+
+#: mod/admin.php:1058
+#, php-format
+msgid "Update %s was successfully applied."
+msgstr ""
+
+#: mod/admin.php:1062
+#, php-format
 msgid "Update %s did not return a status. Unknown if it succeeded."
 msgstr ""
 
-#: mod/admin.php:1042
+#: mod/admin.php:1064
 #, php-format
 msgid "There was no additional update function %s that needed to be called."
 msgstr ""
 
-#: mod/admin.php:1061
+#: mod/admin.php:1083
 msgid "No failed updates."
 msgstr ""
 
-#: mod/admin.php:1062
+#: mod/admin.php:1084
 msgid "Check database structure"
 msgstr ""
 
-#: mod/admin.php:1067
+#: mod/admin.php:1089
 msgid "Failed Updates"
 msgstr ""
 
-#: mod/admin.php:1068
+#: mod/admin.php:1090
 msgid ""
 "This does not include updates prior to 1139, which did not return a status."
 msgstr ""
 
-#: mod/admin.php:1069
+#: mod/admin.php:1091
 msgid "Mark success (if update was manually applied)"
 msgstr ""
 
-#: mod/admin.php:1070
+#: mod/admin.php:1092
 msgid "Attempt to execute this update step automatically"
 msgstr ""
 
-#: mod/admin.php:1102
+#: mod/admin.php:1124
 #, php-format
 msgid ""
 "\n"
@@ -2946,7 +2998,7 @@ msgid ""
 "\t\t\t\tthe administrator of %2$s has set up an account for you."
 msgstr ""
 
-#: mod/admin.php:1105
+#: mod/admin.php:1127
 #, php-format
 msgid ""
 "\n"
@@ -2982,168 +3034,168 @@ msgid ""
 "\t\t\tThank you and welcome to %4$s."
 msgstr ""
 
-#: mod/admin.php:1137 include/user.php:423
+#: mod/admin.php:1159 include/user.php:423
 #, php-format
 msgid "Registration details for %s"
 msgstr ""
 
-#: mod/admin.php:1149
+#: mod/admin.php:1171
 #, php-format
 msgid "%s user blocked/unblocked"
 msgid_plural "%s users blocked/unblocked"
 msgstr[0] ""
 msgstr[1] ""
 
-#: mod/admin.php:1156
+#: mod/admin.php:1178
 #, php-format
 msgid "%s user deleted"
 msgid_plural "%s users deleted"
 msgstr[0] ""
 msgstr[1] ""
 
-#: mod/admin.php:1203
+#: mod/admin.php:1225
 #, php-format
 msgid "User '%s' deleted"
 msgstr ""
 
-#: mod/admin.php:1211
+#: mod/admin.php:1233
 #, php-format
 msgid "User '%s' unblocked"
 msgstr ""
 
-#: mod/admin.php:1211
+#: mod/admin.php:1233
 #, php-format
 msgid "User '%s' blocked"
 msgstr ""
 
-#: mod/admin.php:1302
+#: mod/admin.php:1324
 msgid "Add User"
 msgstr ""
 
-#: mod/admin.php:1303
+#: mod/admin.php:1325
 msgid "select all"
 msgstr ""
 
-#: mod/admin.php:1304
+#: mod/admin.php:1326
 msgid "User registrations waiting for confirm"
 msgstr ""
 
-#: mod/admin.php:1305
+#: mod/admin.php:1327
 msgid "User waiting for permanent deletion"
 msgstr ""
 
-#: mod/admin.php:1306
+#: mod/admin.php:1328
 msgid "Request date"
 msgstr ""
 
-#: mod/admin.php:1306 mod/admin.php:1318 mod/admin.php:1319 mod/admin.php:1334
+#: mod/admin.php:1328 mod/admin.php:1340 mod/admin.php:1341 mod/admin.php:1356
 #: include/contact_selectors.php:79 include/contact_selectors.php:86
 msgid "Email"
 msgstr ""
 
-#: mod/admin.php:1307
+#: mod/admin.php:1329
 msgid "No registrations."
 msgstr ""
 
-#: mod/admin.php:1309
+#: mod/admin.php:1331
 msgid "Deny"
 msgstr ""
 
-#: mod/admin.php:1313
+#: mod/admin.php:1335
 msgid "Site admin"
 msgstr ""
 
-#: mod/admin.php:1314
+#: mod/admin.php:1336
 msgid "Account expired"
 msgstr ""
 
-#: mod/admin.php:1317
+#: mod/admin.php:1339
 msgid "New User"
 msgstr ""
 
-#: mod/admin.php:1318 mod/admin.php:1319
+#: mod/admin.php:1340 mod/admin.php:1341
 msgid "Register date"
 msgstr ""
 
-#: mod/admin.php:1318 mod/admin.php:1319
+#: mod/admin.php:1340 mod/admin.php:1341
 msgid "Last login"
 msgstr ""
 
-#: mod/admin.php:1318 mod/admin.php:1319
+#: mod/admin.php:1340 mod/admin.php:1341
 msgid "Last item"
 msgstr ""
 
-#: mod/admin.php:1318
+#: mod/admin.php:1340
 msgid "Deleted since"
 msgstr ""
 
-#: mod/admin.php:1319 mod/settings.php:41
+#: mod/admin.php:1341 mod/settings.php:41
 msgid "Account"
 msgstr ""
 
-#: mod/admin.php:1321
+#: mod/admin.php:1343
 msgid ""
 "Selected users will be deleted!\\n\\nEverything these users had posted on "
 "this site will be permanently deleted!\\n\\nAre you sure?"
 msgstr ""
 
-#: mod/admin.php:1322
+#: mod/admin.php:1344
 msgid ""
 "The user {0} will be deleted!\\n\\nEverything this user has posted on this "
 "site will be permanently deleted!\\n\\nAre you sure?"
 msgstr ""
 
-#: mod/admin.php:1332
+#: mod/admin.php:1354
 msgid "Name of the new user."
 msgstr ""
 
-#: mod/admin.php:1333
+#: mod/admin.php:1355
 msgid "Nickname"
 msgstr ""
 
-#: mod/admin.php:1333
+#: mod/admin.php:1355
 msgid "Nickname of the new user."
 msgstr ""
 
-#: mod/admin.php:1334
+#: mod/admin.php:1356
 msgid "Email address of the new user."
 msgstr ""
 
-#: mod/admin.php:1377
+#: mod/admin.php:1399
 #, php-format
 msgid "Plugin %s disabled."
 msgstr ""
 
-#: mod/admin.php:1381
+#: mod/admin.php:1403
 #, php-format
 msgid "Plugin %s enabled."
 msgstr ""
 
-#: mod/admin.php:1392 mod/admin.php:1628
+#: mod/admin.php:1414 mod/admin.php:1650
 msgid "Disable"
 msgstr ""
 
-#: mod/admin.php:1394 mod/admin.php:1630
+#: mod/admin.php:1416 mod/admin.php:1652
 msgid "Enable"
 msgstr ""
 
-#: mod/admin.php:1417 mod/admin.php:1675
+#: mod/admin.php:1439 mod/admin.php:1697
 msgid "Toggle"
 msgstr ""
 
-#: mod/admin.php:1425 mod/admin.php:1684
+#: mod/admin.php:1447 mod/admin.php:1706
 msgid "Author: "
 msgstr ""
 
-#: mod/admin.php:1426 mod/admin.php:1685
+#: mod/admin.php:1448 mod/admin.php:1707
 msgid "Maintainer: "
 msgstr ""
 
-#: mod/admin.php:1478
+#: mod/admin.php:1500
 msgid "Reload active plugins"
 msgstr ""
 
-#: mod/admin.php:1483
+#: mod/admin.php:1505
 #, php-format
 msgid ""
 "There are currently no plugins available on your node. You can find the "
@@ -3151,62 +3203,62 @@ msgid ""
 "in the open plugin registry at %2$s"
 msgstr ""
 
-#: mod/admin.php:1588
+#: mod/admin.php:1610
 msgid "No themes found."
 msgstr ""
 
-#: mod/admin.php:1666
+#: mod/admin.php:1688
 msgid "Screenshot"
 msgstr ""
 
-#: mod/admin.php:1726
+#: mod/admin.php:1748
 msgid "Reload active themes"
 msgstr ""
 
-#: mod/admin.php:1731
+#: mod/admin.php:1753
 #, php-format
 msgid "No themes found on the system. They should be paced in %1$s"
 msgstr ""
 
-#: mod/admin.php:1732
+#: mod/admin.php:1754
 msgid "[Experimental]"
 msgstr ""
 
-#: mod/admin.php:1733
+#: mod/admin.php:1755
 msgid "[Unsupported]"
 msgstr ""
 
-#: mod/admin.php:1757
+#: mod/admin.php:1779
 msgid "Log settings updated."
 msgstr ""
 
-#: mod/admin.php:1794
+#: mod/admin.php:1816
 msgid "Clear"
 msgstr ""
 
-#: mod/admin.php:1799
+#: mod/admin.php:1821
 msgid "Enable Debugging"
 msgstr ""
 
-#: mod/admin.php:1800
+#: mod/admin.php:1822
 msgid "Log file"
 msgstr ""
 
-#: mod/admin.php:1800
+#: mod/admin.php:1822
 msgid ""
 "Must be writable by web server. Relative to your Friendica top-level "
 "directory."
 msgstr ""
 
-#: mod/admin.php:1801
+#: mod/admin.php:1823
 msgid "Log level"
 msgstr ""
 
-#: mod/admin.php:1804
+#: mod/admin.php:1826
 msgid "PHP logging"
 msgstr ""
 
-#: mod/admin.php:1805
+#: mod/admin.php:1827
 msgid ""
 "To enable logging of PHP errors and warnings you can add the following to "
 "the .htconfig.php file of your installation. The filename set in the "
@@ -3215,20 +3267,20 @@ msgid ""
 "'display_errors' is to enable these options, set to '0' to disable them."
 msgstr ""
 
-#: mod/admin.php:1931 mod/admin.php:1932 mod/settings.php:759
+#: mod/admin.php:1953 mod/admin.php:1954 mod/settings.php:760
 msgid "Off"
 msgstr ""
 
-#: mod/admin.php:1931 mod/admin.php:1932 mod/settings.php:759
+#: mod/admin.php:1953 mod/admin.php:1954 mod/settings.php:760
 msgid "On"
 msgstr ""
 
-#: mod/admin.php:1932
+#: mod/admin.php:1954
 #, php-format
 msgid "Lock feature %s"
 msgstr ""
 
-#: mod/admin.php:1940
+#: mod/admin.php:1962
 msgid "Manage Additional Features"
 msgstr ""
 
@@ -3245,7 +3297,7 @@ msgstr ""
 msgid "Saved Searches"
 msgstr ""
 
-#: mod/network.php:201 include/group.php:293
+#: mod/network.php:201 include/group.php:296
 msgid "add"
 msgstr ""
 
@@ -3362,31 +3414,31 @@ msgstr ""
 msgid "Sat"
 msgstr ""
 
-#: mod/events.php:208 mod/settings.php:948 include/text.php:1274
+#: mod/events.php:208 mod/settings.php:952 include/text.php:1245
 msgid "Sunday"
 msgstr ""
 
-#: mod/events.php:209 mod/settings.php:948 include/text.php:1274
+#: mod/events.php:209 mod/settings.php:952 include/text.php:1245
 msgid "Monday"
 msgstr ""
 
-#: mod/events.php:210 include/text.php:1274
+#: mod/events.php:210 include/text.php:1245
 msgid "Tuesday"
 msgstr ""
 
-#: mod/events.php:211 include/text.php:1274
+#: mod/events.php:211 include/text.php:1245
 msgid "Wednesday"
 msgstr ""
 
-#: mod/events.php:212 include/text.php:1274
+#: mod/events.php:212 include/text.php:1245
 msgid "Thursday"
 msgstr ""
 
-#: mod/events.php:213 include/text.php:1274
+#: mod/events.php:213 include/text.php:1245
 msgid "Friday"
 msgstr ""
 
-#: mod/events.php:214 include/text.php:1274
+#: mod/events.php:214 include/text.php:1245
 msgid "Saturday"
 msgstr ""
 
@@ -3406,7 +3458,7 @@ msgstr ""
 msgid "Apr"
 msgstr ""
 
-#: mod/events.php:219 mod/events.php:231 include/text.php:1278
+#: mod/events.php:219 mod/events.php:231 include/text.php:1249
 msgid "May"
 msgstr ""
 
@@ -3438,47 +3490,47 @@ msgstr ""
 msgid "Dec"
 msgstr ""
 
-#: mod/events.php:227 include/text.php:1278
+#: mod/events.php:227 include/text.php:1249
 msgid "January"
 msgstr ""
 
-#: mod/events.php:228 include/text.php:1278
+#: mod/events.php:228 include/text.php:1249
 msgid "February"
 msgstr ""
 
-#: mod/events.php:229 include/text.php:1278
+#: mod/events.php:229 include/text.php:1249
 msgid "March"
 msgstr ""
 
-#: mod/events.php:230 include/text.php:1278
+#: mod/events.php:230 include/text.php:1249
 msgid "April"
 msgstr ""
 
-#: mod/events.php:232 include/text.php:1278
+#: mod/events.php:232 include/text.php:1249
 msgid "June"
 msgstr ""
 
-#: mod/events.php:233 include/text.php:1278
+#: mod/events.php:233 include/text.php:1249
 msgid "July"
 msgstr ""
 
-#: mod/events.php:234 include/text.php:1278
+#: mod/events.php:234 include/text.php:1249
 msgid "August"
 msgstr ""
 
-#: mod/events.php:235 include/text.php:1278
+#: mod/events.php:235 include/text.php:1249
 msgid "September"
 msgstr ""
 
-#: mod/events.php:236 include/text.php:1278
+#: mod/events.php:236 include/text.php:1249
 msgid "October"
 msgstr ""
 
-#: mod/events.php:237 include/text.php:1278
+#: mod/events.php:237 include/text.php:1249
 msgid "November"
 msgstr ""
 
-#: mod/events.php:238 include/text.php:1278
+#: mod/events.php:238 include/text.php:1249
 msgid "December"
 msgstr ""
 
@@ -3486,15 +3538,15 @@ msgstr ""
 msgid "today"
 msgstr ""
 
-#: mod/events.php:240 include/datetime.php:288
+#: mod/events.php:240 include/datetime.php:344
 msgid "month"
 msgstr ""
 
-#: mod/events.php:241 include/datetime.php:289
+#: mod/events.php:241 include/datetime.php:345
 msgid "week"
 msgstr ""
 
-#: mod/events.php:242 include/datetime.php:290
+#: mod/events.php:242 include/datetime.php:346
 msgid "day"
 msgstr ""
 
@@ -3506,11 +3558,11 @@ msgstr ""
 msgid "Edit event"
 msgstr ""
 
-#: mod/events.php:421 include/text.php:1728 include/text.php:1735
+#: mod/events.php:421 include/text.php:1651 include/text.php:1658
 msgid "link to source"
 msgstr ""
 
-#: mod/events.php:456 include/identity.php:722 include/nav.php:79
+#: mod/events.php:456 include/identity.php:723 include/nav.php:79
 #: include/nav.php:140 view/theme/diabook/theme.php:127
 msgid "Events"
 msgstr ""
@@ -3568,7 +3620,7 @@ msgid "Share this event"
 msgstr ""
 
 #: mod/events.php:572 mod/content.php:721 mod/editpost.php:145
-#: mod/photos.php:1631 mod/photos.php:1679 mod/photos.php:1767
+#: mod/photos.php:1617 mod/photos.php:1665 mod/photos.php:1753
 #: object/Item.php:719 include/conversation.php:1216
 msgid "Preview"
 msgstr ""
@@ -3584,7 +3636,7 @@ msgid ""
 "code or the translation of Friendica. Thank you all!"
 msgstr ""
 
-#: mod/content.php:439 mod/content.php:742 mod/photos.php:1722
+#: mod/content.php:439 mod/content.php:742 mod/photos.php:1708
 #: object/Item.php:133 include/conversation.php:634
 msgid "Select"
 msgstr ""
@@ -3613,23 +3665,23 @@ msgstr[0] ""
 msgstr[1] ""
 
 #: mod/content.php:607 object/Item.php:421 object/Item.php:434
-#: include/text.php:2004
+#: include/text.php:1927
 msgid "comment"
 msgid_plural "comments"
 msgstr[0] ""
 msgstr[1] ""
 
-#: mod/content.php:608 boot.php:870 object/Item.php:422
-#: include/contact_widgets.php:242 include/forums.php:110
-#: include/items.php:5207 view/theme/vier/theme.php:264
+#: mod/content.php:608 boot.php:872 object/Item.php:422
+#: include/contact_widgets.php:242 include/ForumManager.php:117
+#: include/items.php:2113 view/theme/vier/theme.php:260
 msgid "show more"
 msgstr ""
 
-#: mod/content.php:622 mod/photos.php:1418 object/Item.php:117
+#: mod/content.php:622 mod/photos.php:1404 object/Item.php:117
 msgid "Private Message"
 msgstr ""
 
-#: mod/content.php:686 mod/photos.php:1607 object/Item.php:253
+#: mod/content.php:686 mod/photos.php:1593 object/Item.php:253
 msgid "I like this (toggle)"
 msgstr ""
 
@@ -3637,7 +3689,7 @@ msgstr ""
 msgid "like"
 msgstr ""
 
-#: mod/content.php:687 mod/photos.php:1608 object/Item.php:254
+#: mod/content.php:687 mod/photos.php:1594 object/Item.php:254
 msgid "I don't like this (toggle)"
 msgstr ""
 
@@ -3653,13 +3705,13 @@ msgstr ""
 msgid "share"
 msgstr ""
 
-#: mod/content.php:709 mod/photos.php:1627 mod/photos.php:1675
-#: mod/photos.php:1763 object/Item.php:707
+#: mod/content.php:709 mod/photos.php:1613 mod/photos.php:1661
+#: mod/photos.php:1749 object/Item.php:707
 msgid "This is you"
 msgstr ""
 
-#: mod/content.php:711 mod/photos.php:1629 mod/photos.php:1677
-#: mod/photos.php:1765 boot.php:869 object/Item.php:393 object/Item.php:709
+#: mod/content.php:711 mod/photos.php:1615 mod/photos.php:1663
+#: mod/photos.php:1751 boot.php:871 object/Item.php:393 object/Item.php:709
 msgid "Comment"
 msgstr ""
 
@@ -3695,7 +3747,7 @@ msgstr ""
 msgid "Video"
 msgstr ""
 
-#: mod/content.php:730 mod/settings.php:721 object/Item.php:122
+#: mod/content.php:730 mod/settings.php:722 object/Item.php:122
 #: object/Item.php:124
 msgid "Edit"
 msgstr ""
@@ -4094,19 +4146,19 @@ msgstr ""
 msgid "Help:"
 msgstr ""
 
-#: mod/help.php:47 include/nav.php:113 view/theme/vier/theme.php:302
+#: mod/help.php:47 include/nav.php:113 view/theme/vier/theme.php:298
 msgid "Help"
 msgstr ""
 
-#: mod/help.php:53 mod/p.php:16 mod/p.php:25 index.php:270
+#: mod/help.php:53 mod/p.php:16 mod/p.php:25 index.php:271
 msgid "Not Found"
 msgstr ""
 
-#: mod/help.php:56 index.php:273
+#: mod/help.php:56 index.php:274
 msgid "Page not found."
 msgstr ""
 
-#: mod/dfrn_poll.php:103 mod/dfrn_poll.php:536
+#: mod/dfrn_poll.php:101 mod/dfrn_poll.php:534
 #, php-format
 msgid "%1$s welcomes %2$s"
 msgstr ""
@@ -4170,7 +4222,7 @@ msgstr ""
 msgid "Display"
 msgstr ""
 
-#: mod/settings.php:65 mod/settings.php:864
+#: mod/settings.php:65 mod/settings.php:868
 msgid "Social Networks"
 msgstr ""
 
@@ -4182,7 +4234,7 @@ msgstr ""
 msgid "Connected apps"
 msgstr ""
 
-#: mod/settings.php:93 mod/uexport.php:85
+#: mod/settings.php:93 mod/uexport.php:37
 msgid "Export personal data"
 msgstr ""
 
@@ -4194,685 +4246,689 @@ msgstr ""
 msgid "Missing some important data!"
 msgstr ""
 
-#: mod/settings.php:266
+#: mod/settings.php:267
 msgid "Failed to connect with email account using the settings provided."
 msgstr ""
 
-#: mod/settings.php:271
+#: mod/settings.php:272
 msgid "Email settings updated."
 msgstr ""
 
-#: mod/settings.php:286
+#: mod/settings.php:287
 msgid "Features updated"
 msgstr ""
 
-#: mod/settings.php:353
+#: mod/settings.php:354
 msgid "Relocate message has been send to your contacts"
 msgstr ""
 
-#: mod/settings.php:367 include/user.php:39
+#: mod/settings.php:368 include/user.php:39
 msgid "Passwords do not match. Password unchanged."
 msgstr ""
 
-#: mod/settings.php:372
+#: mod/settings.php:373
 msgid "Empty passwords are not allowed. Password unchanged."
 msgstr ""
 
-#: mod/settings.php:380
+#: mod/settings.php:381
 msgid "Wrong password."
 msgstr ""
 
-#: mod/settings.php:391
+#: mod/settings.php:392
 msgid "Password changed."
 msgstr ""
 
-#: mod/settings.php:393
+#: mod/settings.php:394
 msgid "Password update failed. Please try again."
 msgstr ""
 
-#: mod/settings.php:462
+#: mod/settings.php:463
 msgid " Please use a shorter name."
 msgstr ""
 
-#: mod/settings.php:464
+#: mod/settings.php:465
 msgid " Name too short."
 msgstr ""
 
-#: mod/settings.php:473
+#: mod/settings.php:474
 msgid "Wrong Password"
 msgstr ""
 
-#: mod/settings.php:478
+#: mod/settings.php:479
 msgid " Not valid email."
 msgstr ""
 
-#: mod/settings.php:484
+#: mod/settings.php:485
 msgid " Cannot change to that email."
 msgstr ""
 
-#: mod/settings.php:540
+#: mod/settings.php:541
 msgid "Private forum has no privacy permissions. Using default privacy group."
 msgstr ""
 
-#: mod/settings.php:544
+#: mod/settings.php:545
 msgid "Private forum has no privacy permissions and no default privacy group."
 msgstr ""
 
-#: mod/settings.php:583
+#: mod/settings.php:584
 msgid "Settings updated."
 msgstr ""
 
-#: mod/settings.php:658 mod/settings.php:684 mod/settings.php:720
+#: mod/settings.php:659 mod/settings.php:685 mod/settings.php:721
 msgid "Add application"
 msgstr ""
 
-#: mod/settings.php:662 mod/settings.php:688
+#: mod/settings.php:663 mod/settings.php:689
 msgid "Consumer Key"
 msgstr ""
 
-#: mod/settings.php:663 mod/settings.php:689
+#: mod/settings.php:664 mod/settings.php:690
 msgid "Consumer Secret"
 msgstr ""
 
-#: mod/settings.php:664 mod/settings.php:690
+#: mod/settings.php:665 mod/settings.php:691
 msgid "Redirect"
 msgstr ""
 
-#: mod/settings.php:665 mod/settings.php:691
+#: mod/settings.php:666 mod/settings.php:692
 msgid "Icon url"
 msgstr ""
 
-#: mod/settings.php:676
+#: mod/settings.php:677
 msgid "You can't edit this application."
 msgstr ""
 
-#: mod/settings.php:719
+#: mod/settings.php:720
 msgid "Connected Apps"
 msgstr ""
 
-#: mod/settings.php:723
+#: mod/settings.php:724
 msgid "Client key starts with"
 msgstr ""
 
-#: mod/settings.php:724
+#: mod/settings.php:725
 msgid "No name"
 msgstr ""
 
-#: mod/settings.php:725
+#: mod/settings.php:726
 msgid "Remove authorization"
 msgstr ""
 
-#: mod/settings.php:737
+#: mod/settings.php:738
 msgid "No Plugin settings configured"
 msgstr ""
 
-#: mod/settings.php:745
+#: mod/settings.php:746
 msgid "Plugin Settings"
 msgstr ""
 
-#: mod/settings.php:767
+#: mod/settings.php:768
 msgid "Additional Features"
 msgstr ""
 
-#: mod/settings.php:777 mod/settings.php:781
+#: mod/settings.php:778 mod/settings.php:782
 msgid "General Social Media Settings"
 msgstr ""
 
-#: mod/settings.php:787
+#: mod/settings.php:788
 msgid "Disable intelligent shortening"
 msgstr ""
 
-#: mod/settings.php:789
+#: mod/settings.php:790
 msgid ""
 "Normally the system tries to find the best link to add to shortened posts. "
 "If this option is enabled then every shortened post will always point to the "
 "original friendica post."
 msgstr ""
 
-#: mod/settings.php:795
+#: mod/settings.php:796
 msgid "Automatically follow any GNU Social (OStatus) followers/mentioners"
 msgstr ""
 
-#: mod/settings.php:797
+#: mod/settings.php:798
 msgid ""
 "If you receive a message from an unknown OStatus user, this option decides "
 "what to do. If it is checked, a new contact will be created for every "
 "unknown user."
 msgstr ""
 
-#: mod/settings.php:806
+#: mod/settings.php:804
+msgid "Default group for OStatus contacts"
+msgstr ""
+
+#: mod/settings.php:810
 msgid "Your legacy GNU Social account"
 msgstr ""
 
-#: mod/settings.php:808
+#: mod/settings.php:812
 msgid ""
 "If you enter your old GNU Social/Statusnet account name here (in the format "
 "user@domain.tld), your contacts will be added automatically. The field will "
 "be emptied when done."
 msgstr ""
 
-#: mod/settings.php:811
+#: mod/settings.php:815
 msgid "Repair OStatus subscriptions"
 msgstr ""
 
-#: mod/settings.php:820 mod/settings.php:821
+#: mod/settings.php:824 mod/settings.php:825
 #, php-format
 msgid "Built-in support for %s connectivity is %s"
 msgstr ""
 
-#: mod/settings.php:820 mod/dfrn_request.php:865
+#: mod/settings.php:824 mod/dfrn_request.php:863
 #: include/contact_selectors.php:80
 msgid "Diaspora"
 msgstr ""
 
-#: mod/settings.php:820 mod/settings.php:821
+#: mod/settings.php:824 mod/settings.php:825
 msgid "enabled"
 msgstr ""
 
-#: mod/settings.php:820 mod/settings.php:821
+#: mod/settings.php:824 mod/settings.php:825
 msgid "disabled"
 msgstr ""
 
-#: mod/settings.php:821
+#: mod/settings.php:825
 msgid "GNU Social (OStatus)"
 msgstr ""
 
-#: mod/settings.php:857
+#: mod/settings.php:861
 msgid "Email access is disabled on this site."
 msgstr ""
 
-#: mod/settings.php:869
+#: mod/settings.php:873
 msgid "Email/Mailbox Setup"
 msgstr ""
 
-#: mod/settings.php:870
+#: mod/settings.php:874
 msgid ""
 "If you wish to communicate with email contacts using this service "
 "(optional), please specify how to connect to your mailbox."
 msgstr ""
 
-#: mod/settings.php:871
+#: mod/settings.php:875
 msgid "Last successful email check:"
 msgstr ""
 
-#: mod/settings.php:873
+#: mod/settings.php:877
 msgid "IMAP server name:"
 msgstr ""
 
-#: mod/settings.php:874
+#: mod/settings.php:878
 msgid "IMAP port:"
 msgstr ""
 
-#: mod/settings.php:875
+#: mod/settings.php:879
 msgid "Security:"
 msgstr ""
 
-#: mod/settings.php:875 mod/settings.php:880
+#: mod/settings.php:879 mod/settings.php:884
 msgid "None"
 msgstr ""
 
-#: mod/settings.php:876
+#: mod/settings.php:880
 msgid "Email login name:"
 msgstr ""
 
-#: mod/settings.php:877
+#: mod/settings.php:881
 msgid "Email password:"
 msgstr ""
 
-#: mod/settings.php:878
+#: mod/settings.php:882
 msgid "Reply-to address:"
 msgstr ""
 
-#: mod/settings.php:879
+#: mod/settings.php:883
 msgid "Send public posts to all email contacts:"
 msgstr ""
 
-#: mod/settings.php:880
+#: mod/settings.php:884
 msgid "Action after import:"
 msgstr ""
 
-#: mod/settings.php:880
+#: mod/settings.php:884
 msgid "Mark as seen"
 msgstr ""
 
-#: mod/settings.php:880
+#: mod/settings.php:884
 msgid "Move to folder"
 msgstr ""
 
-#: mod/settings.php:881
+#: mod/settings.php:885
 msgid "Move to folder:"
 msgstr ""
 
-#: mod/settings.php:967
+#: mod/settings.php:971
 msgid "Display Settings"
 msgstr ""
 
-#: mod/settings.php:973 mod/settings.php:991
+#: mod/settings.php:977 mod/settings.php:995
 msgid "Display Theme:"
 msgstr ""
 
-#: mod/settings.php:974
+#: mod/settings.php:978
 msgid "Mobile Theme:"
 msgstr ""
 
-#: mod/settings.php:975
+#: mod/settings.php:979
 msgid "Update browser every xx seconds"
 msgstr ""
 
-#: mod/settings.php:975
+#: mod/settings.php:979
 msgid "Minimum of 10 seconds. Enter -1 to disable it."
 msgstr ""
 
-#: mod/settings.php:976
+#: mod/settings.php:980
 msgid "Number of items to display per page:"
 msgstr ""
 
-#: mod/settings.php:976 mod/settings.php:977
+#: mod/settings.php:980 mod/settings.php:981
 msgid "Maximum of 100 items"
 msgstr ""
 
-#: mod/settings.php:977
+#: mod/settings.php:981
 msgid "Number of items to display per page when viewed from mobile device:"
 msgstr ""
 
-#: mod/settings.php:978
+#: mod/settings.php:982
 msgid "Don't show emoticons"
 msgstr ""
 
-#: mod/settings.php:979
+#: mod/settings.php:983
 msgid "Calendar"
 msgstr ""
 
-#: mod/settings.php:980
+#: mod/settings.php:984
 msgid "Beginning of week:"
 msgstr ""
 
-#: mod/settings.php:981
+#: mod/settings.php:985
 msgid "Don't show notices"
 msgstr ""
 
-#: mod/settings.php:982
+#: mod/settings.php:986
 msgid "Infinite scroll"
 msgstr ""
 
-#: mod/settings.php:983
+#: mod/settings.php:987
 msgid "Automatic updates only at the top of the network page"
 msgstr ""
 
-#: mod/settings.php:985 view/theme/cleanzero/config.php:82
+#: mod/settings.php:989 view/theme/cleanzero/config.php:82
 #: view/theme/dispy/config.php:72 view/theme/quattro/config.php:66
 #: view/theme/diabook/config.php:150 view/theme/vier/config.php:109
 #: view/theme/duepuntozero/config.php:61
 msgid "Theme settings"
 msgstr ""
 
-#: mod/settings.php:1062
+#: mod/settings.php:1066
 msgid "User Types"
 msgstr ""
 
-#: mod/settings.php:1063
+#: mod/settings.php:1067
 msgid "Community Types"
 msgstr ""
 
-#: mod/settings.php:1064
+#: mod/settings.php:1068
 msgid "Normal Account Page"
 msgstr ""
 
-#: mod/settings.php:1065
+#: mod/settings.php:1069
 msgid "This account is a normal personal profile"
 msgstr ""
 
-#: mod/settings.php:1068
+#: mod/settings.php:1072
 msgid "Soapbox Page"
 msgstr ""
 
-#: mod/settings.php:1069
+#: mod/settings.php:1073
 msgid "Automatically approve all connection/friend requests as read-only fans"
 msgstr ""
 
-#: mod/settings.php:1072
+#: mod/settings.php:1076
 msgid "Community Forum/Celebrity Account"
 msgstr ""
 
-#: mod/settings.php:1073
+#: mod/settings.php:1077
 msgid "Automatically approve all connection/friend requests as read-write fans"
 msgstr ""
 
-#: mod/settings.php:1076
+#: mod/settings.php:1080
 msgid "Automatic Friend Page"
 msgstr ""
 
-#: mod/settings.php:1077
+#: mod/settings.php:1081
 msgid "Automatically approve all connection/friend requests as friends"
 msgstr ""
 
-#: mod/settings.php:1080
+#: mod/settings.php:1084
 msgid "Private Forum [Experimental]"
 msgstr ""
 
-#: mod/settings.php:1081
+#: mod/settings.php:1085
 msgid "Private forum - approved members only"
 msgstr ""
 
-#: mod/settings.php:1093
+#: mod/settings.php:1097
 msgid "OpenID:"
 msgstr ""
 
-#: mod/settings.php:1093
+#: mod/settings.php:1097
 msgid "(Optional) Allow this OpenID to login to this account."
 msgstr ""
 
-#: mod/settings.php:1103
+#: mod/settings.php:1107
 msgid "Publish your default profile in your local site directory?"
 msgstr ""
 
-#: mod/settings.php:1109
+#: mod/settings.php:1113
 msgid "Publish your default profile in the global social directory?"
 msgstr ""
 
-#: mod/settings.php:1117
+#: mod/settings.php:1121
 msgid "Hide your contact/friend list from viewers of your default profile?"
 msgstr ""
 
-#: mod/settings.php:1121 include/acl_selectors.php:331
+#: mod/settings.php:1125 include/acl_selectors.php:331
 msgid "Hide your profile details from unknown viewers?"
 msgstr ""
 
-#: mod/settings.php:1121
+#: mod/settings.php:1125
 msgid ""
 "If enabled, posting public messages to Diaspora and other networks isn't "
 "possible."
 msgstr ""
 
-#: mod/settings.php:1126
+#: mod/settings.php:1130
 msgid "Allow friends to post to your profile page?"
 msgstr ""
 
-#: mod/settings.php:1132
+#: mod/settings.php:1136
 msgid "Allow friends to tag your posts?"
 msgstr ""
 
-#: mod/settings.php:1138
+#: mod/settings.php:1142
 msgid "Allow us to suggest you as a potential friend to new members?"
 msgstr ""
 
-#: mod/settings.php:1144
+#: mod/settings.php:1148
 msgid "Permit unknown people to send you private mail?"
 msgstr ""
 
-#: mod/settings.php:1152
+#: mod/settings.php:1156
 msgid "Profile is <strong>not published</strong>."
 msgstr ""
 
-#: mod/settings.php:1160
+#: mod/settings.php:1164
 #, php-format
 msgid "Your Identity Address is <strong>'%s'</strong> or '%s'."
 msgstr ""
 
-#: mod/settings.php:1167
+#: mod/settings.php:1171
 msgid "Automatically expire posts after this many days:"
 msgstr ""
 
-#: mod/settings.php:1167
+#: mod/settings.php:1171
 msgid "If empty, posts will not expire. Expired posts will be deleted"
 msgstr ""
 
-#: mod/settings.php:1168
+#: mod/settings.php:1172
 msgid "Advanced expiration settings"
 msgstr ""
 
-#: mod/settings.php:1169
+#: mod/settings.php:1173
 msgid "Advanced Expiration"
 msgstr ""
 
-#: mod/settings.php:1170
+#: mod/settings.php:1174
 msgid "Expire posts:"
 msgstr ""
 
-#: mod/settings.php:1171
+#: mod/settings.php:1175
 msgid "Expire personal notes:"
 msgstr ""
 
-#: mod/settings.php:1172
+#: mod/settings.php:1176
 msgid "Expire starred posts:"
 msgstr ""
 
-#: mod/settings.php:1173
+#: mod/settings.php:1177
 msgid "Expire photos:"
 msgstr ""
 
-#: mod/settings.php:1174
+#: mod/settings.php:1178
 msgid "Only expire posts by others:"
 msgstr ""
 
-#: mod/settings.php:1202
+#: mod/settings.php:1206
 msgid "Account Settings"
 msgstr ""
 
-#: mod/settings.php:1210
+#: mod/settings.php:1214
 msgid "Password Settings"
 msgstr ""
 
-#: mod/settings.php:1211 mod/register.php:274
+#: mod/settings.php:1215 mod/register.php:274
 msgid "New Password:"
 msgstr ""
 
-#: mod/settings.php:1212 mod/register.php:275
+#: mod/settings.php:1216 mod/register.php:275
 msgid "Confirm:"
 msgstr ""
 
-#: mod/settings.php:1212
+#: mod/settings.php:1216
 msgid "Leave password fields blank unless changing"
 msgstr ""
 
-#: mod/settings.php:1213
+#: mod/settings.php:1217
 msgid "Current Password:"
 msgstr ""
 
-#: mod/settings.php:1213 mod/settings.php:1214
+#: mod/settings.php:1217 mod/settings.php:1218
 msgid "Your current password to confirm the changes"
 msgstr ""
 
-#: mod/settings.php:1214
+#: mod/settings.php:1218
 msgid "Password:"
 msgstr ""
 
-#: mod/settings.php:1218
+#: mod/settings.php:1222
 msgid "Basic Settings"
 msgstr ""
 
-#: mod/settings.php:1219 include/identity.php:588
+#: mod/settings.php:1223 include/identity.php:589
 msgid "Full Name:"
 msgstr ""
 
-#: mod/settings.php:1220
+#: mod/settings.php:1224
 msgid "Email Address:"
 msgstr ""
 
-#: mod/settings.php:1221
+#: mod/settings.php:1225
 msgid "Your Timezone:"
 msgstr ""
 
-#: mod/settings.php:1222
+#: mod/settings.php:1226
 msgid "Your Language:"
 msgstr ""
 
-#: mod/settings.php:1222
+#: mod/settings.php:1226
 msgid ""
 "Set the language we use to show you friendica interface and to send you "
 "emails"
 msgstr ""
 
-#: mod/settings.php:1223
+#: mod/settings.php:1227
 msgid "Default Post Location:"
 msgstr ""
 
-#: mod/settings.php:1224
+#: mod/settings.php:1228
 msgid "Use Browser Location:"
 msgstr ""
 
-#: mod/settings.php:1227
+#: mod/settings.php:1231
 msgid "Security and Privacy Settings"
 msgstr ""
 
-#: mod/settings.php:1229
+#: mod/settings.php:1233
 msgid "Maximum Friend Requests/Day:"
 msgstr ""
 
-#: mod/settings.php:1229 mod/settings.php:1259
+#: mod/settings.php:1233 mod/settings.php:1263
 msgid "(to prevent spam abuse)"
 msgstr ""
 
-#: mod/settings.php:1230
+#: mod/settings.php:1234
 msgid "Default Post Permissions"
 msgstr ""
 
-#: mod/settings.php:1231
+#: mod/settings.php:1235
 msgid "(click to open/close)"
 msgstr ""
 
-#: mod/settings.php:1240 mod/photos.php:1199 mod/photos.php:1584
+#: mod/settings.php:1244 mod/photos.php:1185 mod/photos.php:1570
 msgid "Show to Groups"
 msgstr ""
 
-#: mod/settings.php:1241 mod/photos.php:1200 mod/photos.php:1585
+#: mod/settings.php:1245 mod/photos.php:1186 mod/photos.php:1571
 msgid "Show to Contacts"
 msgstr ""
 
-#: mod/settings.php:1242
+#: mod/settings.php:1246
 msgid "Default Private Post"
 msgstr ""
 
-#: mod/settings.php:1243
+#: mod/settings.php:1247
 msgid "Default Public Post"
 msgstr ""
 
-#: mod/settings.php:1247
+#: mod/settings.php:1251
 msgid "Default Permissions for New Posts"
 msgstr ""
 
-#: mod/settings.php:1259
+#: mod/settings.php:1263
 msgid "Maximum private messages per day from unknown people:"
 msgstr ""
 
-#: mod/settings.php:1262
+#: mod/settings.php:1266
 msgid "Notification Settings"
 msgstr ""
 
-#: mod/settings.php:1263
+#: mod/settings.php:1267
 msgid "By default post a status message when:"
 msgstr ""
 
-#: mod/settings.php:1264
+#: mod/settings.php:1268
 msgid "accepting a friend request"
 msgstr ""
 
-#: mod/settings.php:1265
+#: mod/settings.php:1269
 msgid "joining a forum/community"
 msgstr ""
 
-#: mod/settings.php:1266
+#: mod/settings.php:1270
 msgid "making an <em>interesting</em> profile change"
 msgstr ""
 
-#: mod/settings.php:1267
+#: mod/settings.php:1271
 msgid "Send a notification email when:"
 msgstr ""
 
-#: mod/settings.php:1268
+#: mod/settings.php:1272
 msgid "You receive an introduction"
 msgstr ""
 
-#: mod/settings.php:1269
+#: mod/settings.php:1273
 msgid "Your introductions are confirmed"
 msgstr ""
 
-#: mod/settings.php:1270
+#: mod/settings.php:1274
 msgid "Someone writes on your profile wall"
 msgstr ""
 
-#: mod/settings.php:1271
+#: mod/settings.php:1275
 msgid "Someone writes a followup comment"
 msgstr ""
 
-#: mod/settings.php:1272
+#: mod/settings.php:1276
 msgid "You receive a private message"
 msgstr ""
 
-#: mod/settings.php:1273
+#: mod/settings.php:1277
 msgid "You receive a friend suggestion"
 msgstr ""
 
-#: mod/settings.php:1274
+#: mod/settings.php:1278
 msgid "You are tagged in a post"
 msgstr ""
 
-#: mod/settings.php:1275
+#: mod/settings.php:1279
 msgid "You are poked/prodded/etc. in a post"
 msgstr ""
 
-#: mod/settings.php:1277
+#: mod/settings.php:1281
 msgid "Activate desktop notifications"
 msgstr ""
 
-#: mod/settings.php:1277
+#: mod/settings.php:1281
 msgid "Show desktop popup on new notifications"
 msgstr ""
 
-#: mod/settings.php:1279
+#: mod/settings.php:1283
 msgid "Text-only notification emails"
 msgstr ""
 
-#: mod/settings.php:1281
+#: mod/settings.php:1285
 msgid "Send text only notification emails, without the html part"
 msgstr ""
 
-#: mod/settings.php:1283
+#: mod/settings.php:1287
 msgid "Advanced Account/Page Type Settings"
 msgstr ""
 
-#: mod/settings.php:1284
+#: mod/settings.php:1288
 msgid "Change the behaviour of this account for special situations"
 msgstr ""
 
-#: mod/settings.php:1287
+#: mod/settings.php:1291
 msgid "Relocate"
 msgstr ""
 
-#: mod/settings.php:1288
+#: mod/settings.php:1292
 msgid ""
 "If you have moved this profile from another server, and some of your "
 "contacts don't receive your updates, try pushing this button."
 msgstr ""
 
-#: mod/settings.php:1289
+#: mod/settings.php:1293
 msgid "Resend relocate message to contacts"
 msgstr ""
 
-#: mod/dfrn_request.php:96
+#: mod/dfrn_request.php:98
 msgid "This introduction has already been accepted."
 msgstr ""
 
-#: mod/dfrn_request.php:119 mod/dfrn_request.php:516
+#: mod/dfrn_request.php:121 mod/dfrn_request.php:514
 msgid "Profile location is not valid or does not contain profile information."
 msgstr ""
 
-#: mod/dfrn_request.php:124 mod/dfrn_request.php:521
+#: mod/dfrn_request.php:126 mod/dfrn_request.php:519
 msgid "Warning: profile location has no identifiable owner name."
 msgstr ""
 
-#: mod/dfrn_request.php:126 mod/dfrn_request.php:523
+#: mod/dfrn_request.php:128 mod/dfrn_request.php:521
 msgid "Warning: profile location has no profile photo."
 msgstr ""
 
-#: mod/dfrn_request.php:129 mod/dfrn_request.php:526
+#: mod/dfrn_request.php:131 mod/dfrn_request.php:524
 #, php-format
 msgid "%d required parameter was not found at the given location"
 msgid_plural "%d required parameters were not found at the given location"
 msgstr[0] ""
 msgstr[1] ""
 
-#: mod/dfrn_request.php:172
+#: mod/dfrn_request.php:174
 msgid "Introduction complete."
 msgstr ""
 
@@ -4909,93 +4965,93 @@ msgstr ""
 msgid "This account has not been configured for email. Request failed."
 msgstr ""
 
-#: mod/dfrn_request.php:474
+#: mod/dfrn_request.php:472
 msgid "You have already introduced yourself here."
 msgstr ""
 
-#: mod/dfrn_request.php:478
+#: mod/dfrn_request.php:476
 #, php-format
 msgid "Apparently you are already friends with %s."
 msgstr ""
 
-#: mod/dfrn_request.php:499
+#: mod/dfrn_request.php:497
 msgid "Invalid profile URL."
 msgstr ""
 
-#: mod/dfrn_request.php:505 include/follow.php:72
+#: mod/dfrn_request.php:503 include/follow.php:76
 msgid "Disallowed profile URL."
 msgstr ""
 
-#: mod/dfrn_request.php:596
+#: mod/dfrn_request.php:594
 msgid "Your introduction has been sent."
 msgstr ""
 
-#: mod/dfrn_request.php:636
+#: mod/dfrn_request.php:634
 msgid ""
 "Remote subscription can't be done for your network. Please subscribe "
 "directly on your system."
 msgstr ""
 
-#: mod/dfrn_request.php:659
+#: mod/dfrn_request.php:657
 msgid "Please login to confirm introduction."
 msgstr ""
 
-#: mod/dfrn_request.php:669
+#: mod/dfrn_request.php:667
 msgid ""
 "Incorrect identity currently logged in. Please login to <strong>this</"
 "strong> profile."
 msgstr ""
 
-#: mod/dfrn_request.php:683 mod/dfrn_request.php:700
+#: mod/dfrn_request.php:681 mod/dfrn_request.php:698
 msgid "Confirm"
 msgstr ""
 
-#: mod/dfrn_request.php:695
+#: mod/dfrn_request.php:693
 msgid "Hide this contact"
 msgstr ""
 
-#: mod/dfrn_request.php:698
+#: mod/dfrn_request.php:696
 #, php-format
 msgid "Welcome home %s."
 msgstr ""
 
-#: mod/dfrn_request.php:699
+#: mod/dfrn_request.php:697
 #, php-format
 msgid "Please confirm your introduction/connection request to %s."
 msgstr ""
 
-#: mod/dfrn_request.php:828
+#: mod/dfrn_request.php:826
 msgid ""
 "Please enter your 'Identity Address' from one of the following supported "
 "communications networks:"
 msgstr ""
 
-#: mod/dfrn_request.php:849
+#: mod/dfrn_request.php:847
 #, php-format
 msgid ""
 "If you are not yet a member of the free social web, <a href=\"%s/siteinfo"
 "\">follow this link to find a public Friendica site and join us today</a>."
 msgstr ""
 
-#: mod/dfrn_request.php:854
+#: mod/dfrn_request.php:852
 msgid "Friend/Connection Request"
 msgstr ""
 
-#: mod/dfrn_request.php:855
+#: mod/dfrn_request.php:853
 msgid ""
 "Examples: jojo@demo.friendica.com, http://demo.friendica.com/profile/jojo, "
 "testuser@identi.ca"
 msgstr ""
 
-#: mod/dfrn_request.php:863 include/contact_selectors.php:76
+#: mod/dfrn_request.php:861 include/contact_selectors.php:76
 msgid "Friendica"
 msgstr ""
 
-#: mod/dfrn_request.php:864
+#: mod/dfrn_request.php:862
 msgid "StatusNet/Federated Social Web"
 msgstr ""
 
-#: mod/dfrn_request.php:866
+#: mod/dfrn_request.php:864
 #, php-format
 msgid ""
 " - please do not use this form.  Instead, enter %s into your Diaspora search "
@@ -5083,7 +5139,7 @@ msgstr ""
 msgid "Choose a nickname: "
 msgstr ""
 
-#: mod/register.php:280 boot.php:1405 include/nav.php:108
+#: mod/register.php:280 boot.php:1495 include/nav.php:108
 msgid "Register"
 msgstr ""
 
@@ -5111,7 +5167,7 @@ msgstr ""
 msgid "Only one search per minute is permitted for not logged in users."
 msgstr ""
 
-#: mod/search.php:136 include/text.php:1003 include/nav.php:118
+#: mod/search.php:136 include/text.php:974 include/nav.php:118
 msgid "Search"
 msgstr ""
 
@@ -5125,16 +5181,16 @@ msgstr ""
 msgid "Search results for: %s"
 msgstr ""
 
-#: mod/directory.php:149 include/identity.php:313 include/identity.php:610
+#: mod/directory.php:149 include/identity.php:314 include/identity.php:611
 msgid "Status:"
 msgstr ""
 
-#: mod/directory.php:151 include/identity.php:315 include/identity.php:621
+#: mod/directory.php:151 include/identity.php:316 include/identity.php:622
 msgid "Homepage:"
 msgstr ""
 
 #: mod/directory.php:203 view/theme/diabook/theme.php:525
-#: view/theme/vier/theme.php:205
+#: view/theme/vier/theme.php:201
 msgid "Global Directory"
 msgstr ""
 
@@ -5193,21 +5249,21 @@ msgstr ""
 msgid "No contacts in common."
 msgstr ""
 
-#: mod/uexport.php:77
+#: mod/uexport.php:29
 msgid "Export account"
 msgstr ""
 
-#: mod/uexport.php:77
+#: mod/uexport.php:29
 msgid ""
 "Export your account info and contacts. Use this to make a backup of your "
 "account and/or to move it to another server."
 msgstr ""
 
-#: mod/uexport.php:78
+#: mod/uexport.php:30
 msgid "Export all"
 msgstr ""
 
-#: mod/uexport.php:78
+#: mod/uexport.php:30
 msgid ""
 "Export your accout info, contacts and all your items as json. Could be a "
 "very big file, and could take a lot of time. Use this to make a full backup "
@@ -5242,7 +5298,7 @@ msgid "Ignore/Hide"
 msgstr ""
 
 #: mod/suggest.php:111 include/contact_widgets.php:35
-#: view/theme/diabook/theme.php:527 view/theme/vier/theme.php:207
+#: view/theme/diabook/theme.php:527 view/theme/vier/theme.php:203
 msgid "Friend Suggestions"
 msgstr ""
 
@@ -5274,11 +5330,11 @@ msgstr ""
 msgid "Romantic Partner"
 msgstr ""
 
-#: mod/profiles.php:344 mod/photos.php:1647 include/conversation.php:508
+#: mod/profiles.php:344 mod/photos.php:1633 include/conversation.php:508
 msgid "Likes"
 msgstr ""
 
-#: mod/profiles.php:348 mod/photos.php:1647 include/conversation.php:508
+#: mod/profiles.php:348 mod/photos.php:1633 include/conversation.php:508
 msgid "Dislikes"
 msgstr ""
 
@@ -5306,7 +5362,7 @@ msgstr ""
 msgid "Homepage"
 msgstr ""
 
-#: mod/profiles.php:375 mod/profiles.php:708
+#: mod/profiles.php:375 mod/profiles.php:686
 msgid "Interests"
 msgstr ""
 
@@ -5314,7 +5370,7 @@ msgstr ""
 msgid "Address"
 msgstr ""
 
-#: mod/profiles.php:386 mod/profiles.php:704
+#: mod/profiles.php:386 mod/profiles.php:682
 msgid "Location"
 msgstr ""
 
@@ -5322,260 +5378,260 @@ msgstr ""
 msgid "Profile updated."
 msgstr ""
 
-#: mod/profiles.php:565
+#: mod/profiles.php:551
 msgid " and "
 msgstr ""
 
-#: mod/profiles.php:573
+#: mod/profiles.php:559
 msgid "public profile"
 msgstr ""
 
-#: mod/profiles.php:576
+#: mod/profiles.php:562
 #, php-format
 msgid "%1$s changed %2$s to &ldquo;%3$s&rdquo;"
 msgstr ""
 
-#: mod/profiles.php:577
+#: mod/profiles.php:563
 #, php-format
 msgid " - Visit %1$s's %2$s"
 msgstr ""
 
-#: mod/profiles.php:580
+#: mod/profiles.php:566
 #, php-format
 msgid "%1$s has an updated %2$s, changing %3$s."
 msgstr ""
 
-#: mod/profiles.php:655
+#: mod/profiles.php:633
 msgid "Hide contacts and friends:"
 msgstr ""
 
-#: mod/profiles.php:660
+#: mod/profiles.php:638
 msgid "Hide your contact/friend list from viewers of this profile?"
 msgstr ""
 
-#: mod/profiles.php:684
+#: mod/profiles.php:662
 msgid "Show more profile fields:"
 msgstr ""
 
-#: mod/profiles.php:695
+#: mod/profiles.php:673
 msgid "Edit Profile Details"
 msgstr ""
 
-#: mod/profiles.php:697
+#: mod/profiles.php:675
 msgid "Change Profile Photo"
 msgstr ""
 
-#: mod/profiles.php:698
+#: mod/profiles.php:676
 msgid "View this profile"
 msgstr ""
 
-#: mod/profiles.php:699
+#: mod/profiles.php:677
 msgid "Create a new profile using these settings"
 msgstr ""
 
-#: mod/profiles.php:700
+#: mod/profiles.php:678
 msgid "Clone this profile"
 msgstr ""
 
-#: mod/profiles.php:701
+#: mod/profiles.php:679
 msgid "Delete this profile"
 msgstr ""
 
-#: mod/profiles.php:702
+#: mod/profiles.php:680
 msgid "Basic information"
 msgstr ""
 
-#: mod/profiles.php:703
+#: mod/profiles.php:681
 msgid "Profile picture"
 msgstr ""
 
-#: mod/profiles.php:705
+#: mod/profiles.php:683
 msgid "Preferences"
 msgstr ""
 
-#: mod/profiles.php:706
+#: mod/profiles.php:684
 msgid "Status information"
 msgstr ""
 
-#: mod/profiles.php:707
+#: mod/profiles.php:685
 msgid "Additional information"
 msgstr ""
 
-#: mod/profiles.php:710
+#: mod/profiles.php:688
 msgid "Profile Name:"
 msgstr ""
 
-#: mod/profiles.php:711
+#: mod/profiles.php:689
 msgid "Your Full Name:"
 msgstr ""
 
-#: mod/profiles.php:712
+#: mod/profiles.php:690
 msgid "Title/Description:"
 msgstr ""
 
-#: mod/profiles.php:713
+#: mod/profiles.php:691
 msgid "Your Gender:"
 msgstr ""
 
-#: mod/profiles.php:714
+#: mod/profiles.php:692
 msgid "Birthday :"
 msgstr ""
 
-#: mod/profiles.php:715
+#: mod/profiles.php:693
 msgid "Street Address:"
 msgstr ""
 
-#: mod/profiles.php:716
+#: mod/profiles.php:694
 msgid "Locality/City:"
 msgstr ""
 
-#: mod/profiles.php:717
+#: mod/profiles.php:695
 msgid "Postal/Zip Code:"
 msgstr ""
 
-#: mod/profiles.php:718
+#: mod/profiles.php:696
 msgid "Country:"
 msgstr ""
 
-#: mod/profiles.php:719
+#: mod/profiles.php:697
 msgid "Region/State:"
 msgstr ""
 
-#: mod/profiles.php:720
+#: mod/profiles.php:698
 msgid "<span class=\"heart\">&hearts;</span> Marital Status:"
 msgstr ""
 
-#: mod/profiles.php:721
+#: mod/profiles.php:699
 msgid "Who: (if applicable)"
 msgstr ""
 
-#: mod/profiles.php:722
+#: mod/profiles.php:700
 msgid "Examples: cathy123, Cathy Williams, cathy@example.com"
 msgstr ""
 
-#: mod/profiles.php:723
+#: mod/profiles.php:701
 msgid "Since [date]:"
 msgstr ""
 
-#: mod/profiles.php:724 include/identity.php:619
+#: mod/profiles.php:702 include/identity.php:620
 msgid "Sexual Preference:"
 msgstr ""
 
-#: mod/profiles.php:725
+#: mod/profiles.php:703
 msgid "Homepage URL:"
 msgstr ""
 
-#: mod/profiles.php:726 include/identity.php:623
+#: mod/profiles.php:704 include/identity.php:624
 msgid "Hometown:"
 msgstr ""
 
-#: mod/profiles.php:727 include/identity.php:627
+#: mod/profiles.php:705 include/identity.php:628
 msgid "Political Views:"
 msgstr ""
 
-#: mod/profiles.php:728
+#: mod/profiles.php:706
 msgid "Religious Views:"
 msgstr ""
 
-#: mod/profiles.php:729
+#: mod/profiles.php:707
 msgid "Public Keywords:"
 msgstr ""
 
-#: mod/profiles.php:730
+#: mod/profiles.php:708
 msgid "Private Keywords:"
 msgstr ""
 
-#: mod/profiles.php:731 include/identity.php:635
+#: mod/profiles.php:709 include/identity.php:636
 msgid "Likes:"
 msgstr ""
 
-#: mod/profiles.php:732 include/identity.php:637
+#: mod/profiles.php:710 include/identity.php:638
 msgid "Dislikes:"
 msgstr ""
 
-#: mod/profiles.php:733
+#: mod/profiles.php:711
 msgid "Example: fishing photography software"
 msgstr ""
 
-#: mod/profiles.php:734
+#: mod/profiles.php:712
 msgid "(Used for suggesting potential friends, can be seen by others)"
 msgstr ""
 
-#: mod/profiles.php:735
+#: mod/profiles.php:713
 msgid "(Used for searching profiles, never shown to others)"
 msgstr ""
 
-#: mod/profiles.php:736
+#: mod/profiles.php:714
 msgid "Tell us about yourself..."
 msgstr ""
 
-#: mod/profiles.php:737
+#: mod/profiles.php:715
 msgid "Hobbies/Interests"
 msgstr ""
 
-#: mod/profiles.php:738
+#: mod/profiles.php:716
 msgid "Contact information and Social Networks"
 msgstr ""
 
-#: mod/profiles.php:739
+#: mod/profiles.php:717
 msgid "Musical interests"
 msgstr ""
 
-#: mod/profiles.php:740
+#: mod/profiles.php:718
 msgid "Books, literature"
 msgstr ""
 
-#: mod/profiles.php:741
+#: mod/profiles.php:719
 msgid "Television"
 msgstr ""
 
-#: mod/profiles.php:742
+#: mod/profiles.php:720
 msgid "Film/dance/culture/entertainment"
 msgstr ""
 
-#: mod/profiles.php:743
+#: mod/profiles.php:721
 msgid "Love/romance"
 msgstr ""
 
-#: mod/profiles.php:744
+#: mod/profiles.php:722
 msgid "Work/employment"
 msgstr ""
 
-#: mod/profiles.php:745
+#: mod/profiles.php:723
 msgid "School/education"
 msgstr ""
 
-#: mod/profiles.php:750
+#: mod/profiles.php:728
 msgid ""
 "This is your <strong>public</strong> profile.<br />It <strong>may</strong> "
 "be visible to anybody using the internet."
 msgstr ""
 
-#: mod/profiles.php:760
+#: mod/profiles.php:738
 msgid "Age: "
 msgstr ""
 
-#: mod/profiles.php:813
+#: mod/profiles.php:791
 msgid "Edit/Manage Profiles"
 msgstr ""
 
-#: mod/profiles.php:814 include/identity.php:260 include/identity.php:286
+#: mod/profiles.php:792 include/identity.php:261 include/identity.php:287
 msgid "Change profile photo"
 msgstr ""
 
-#: mod/profiles.php:815 include/identity.php:261
+#: mod/profiles.php:793 include/identity.php:262
 msgid "Create New Profile"
 msgstr ""
 
-#: mod/profiles.php:826 include/identity.php:271
+#: mod/profiles.php:804 include/identity.php:272
 msgid "Profile Image"
 msgstr ""
 
-#: mod/profiles.php:828 include/identity.php:274
+#: mod/profiles.php:806 include/identity.php:275
 msgid "visible to everybody"
 msgstr ""
 
-#: mod/profiles.php:829 include/identity.php:275
+#: mod/profiles.php:807 include/identity.php:276
 msgid "Edit visibility"
 msgstr ""
 
@@ -5721,7 +5777,7 @@ msgstr ""
 msgid "Visible to:"
 msgstr ""
 
-#: mod/notes.php:46 include/identity.php:730
+#: mod/notes.php:46 include/identity.php:731
 msgid "Personal Notes"
 msgstr ""
 
@@ -5878,15 +5934,15 @@ msgid ""
 "important, please visit http://friendica.com"
 msgstr ""
 
-#: mod/photos.php:99 include/identity.php:705
+#: mod/photos.php:99 include/identity.php:706
 msgid "Photo Albums"
 msgstr ""
 
-#: mod/photos.php:100 mod/photos.php:1899
+#: mod/photos.php:100 mod/photos.php:1885
 msgid "Recent Photos"
 msgstr ""
 
-#: mod/photos.php:103 mod/photos.php:1320 mod/photos.php:1901
+#: mod/photos.php:103 mod/photos.php:1306 mod/photos.php:1887
 msgid "Upload New Photos"
 msgstr ""
 
@@ -5898,7 +5954,7 @@ msgstr ""
 msgid "Album not found."
 msgstr ""
 
-#: mod/photos.php:232 mod/photos.php:244 mod/photos.php:1262
+#: mod/photos.php:232 mod/photos.php:244 mod/photos.php:1248
 msgid "Delete Album"
 msgstr ""
 
@@ -5906,7 +5962,7 @@ msgstr ""
 msgid "Do you really want to delete this photo album and all its photos?"
 msgstr ""
 
-#: mod/photos.php:322 mod/photos.php:333 mod/photos.php:1580
+#: mod/photos.php:322 mod/photos.php:333 mod/photos.php:1566
 msgid "Delete Photo"
 msgstr ""
 
@@ -5923,151 +5979,151 @@ msgstr ""
 msgid "a photo"
 msgstr ""
 
-#: mod/photos.php:819
+#: mod/photos.php:813
 msgid "Image file is empty."
 msgstr ""
 
-#: mod/photos.php:986
+#: mod/photos.php:972
 msgid "No photos selected"
 msgstr ""
 
-#: mod/photos.php:1147
+#: mod/photos.php:1133
 #, php-format
 msgid "You have used %1$.2f Mbytes of %2$.2f Mbytes photo storage."
 msgstr ""
 
-#: mod/photos.php:1182
+#: mod/photos.php:1168
 msgid "Upload Photos"
 msgstr ""
 
-#: mod/photos.php:1186 mod/photos.php:1257
+#: mod/photos.php:1172 mod/photos.php:1243
 msgid "New album name: "
 msgstr ""
 
-#: mod/photos.php:1187
+#: mod/photos.php:1173
 msgid "or existing album name: "
 msgstr ""
 
-#: mod/photos.php:1188
+#: mod/photos.php:1174
 msgid "Do not show a status post for this upload"
 msgstr ""
 
-#: mod/photos.php:1190 mod/photos.php:1575 include/acl_selectors.php:347
+#: mod/photos.php:1176 mod/photos.php:1561 include/acl_selectors.php:347
 msgid "Permissions"
 msgstr ""
 
-#: mod/photos.php:1201
+#: mod/photos.php:1187
 msgid "Private Photo"
 msgstr ""
 
-#: mod/photos.php:1202
+#: mod/photos.php:1188
 msgid "Public Photo"
 msgstr ""
 
-#: mod/photos.php:1270
+#: mod/photos.php:1256
 msgid "Edit Album"
 msgstr ""
 
-#: mod/photos.php:1276
+#: mod/photos.php:1262
 msgid "Show Newest First"
 msgstr ""
 
-#: mod/photos.php:1278
+#: mod/photos.php:1264
 msgid "Show Oldest First"
 msgstr ""
 
-#: mod/photos.php:1306 mod/photos.php:1884
+#: mod/photos.php:1292 mod/photos.php:1870
 msgid "View Photo"
 msgstr ""
 
-#: mod/photos.php:1353
+#: mod/photos.php:1339
 msgid "Permission denied. Access to this item may be restricted."
 msgstr ""
 
-#: mod/photos.php:1355
+#: mod/photos.php:1341
 msgid "Photo not available"
 msgstr ""
 
-#: mod/photos.php:1411
+#: mod/photos.php:1397
 msgid "View photo"
 msgstr ""
 
-#: mod/photos.php:1411
+#: mod/photos.php:1397
 msgid "Edit photo"
 msgstr ""
 
-#: mod/photos.php:1412
+#: mod/photos.php:1398
 msgid "Use as profile photo"
 msgstr ""
 
-#: mod/photos.php:1437
+#: mod/photos.php:1423
 msgid "View Full Size"
 msgstr ""
 
-#: mod/photos.php:1523
+#: mod/photos.php:1509
 msgid "Tags: "
 msgstr ""
 
-#: mod/photos.php:1526
+#: mod/photos.php:1512
 msgid "[Remove any tag]"
 msgstr ""
 
-#: mod/photos.php:1566
+#: mod/photos.php:1552
 msgid "New album name"
 msgstr ""
 
-#: mod/photos.php:1567
+#: mod/photos.php:1553
 msgid "Caption"
 msgstr ""
 
-#: mod/photos.php:1568
+#: mod/photos.php:1554
 msgid "Add a Tag"
 msgstr ""
 
-#: mod/photos.php:1568
+#: mod/photos.php:1554
 msgid "Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"
 msgstr ""
 
-#: mod/photos.php:1569
+#: mod/photos.php:1555
 msgid "Do not rotate"
 msgstr ""
 
-#: mod/photos.php:1570
+#: mod/photos.php:1556
 msgid "Rotate CW (right)"
 msgstr ""
 
-#: mod/photos.php:1571
+#: mod/photos.php:1557
 msgid "Rotate CCW (left)"
 msgstr ""
 
-#: mod/photos.php:1586
+#: mod/photos.php:1572
 msgid "Private photo"
 msgstr ""
 
-#: mod/photos.php:1587
+#: mod/photos.php:1573
 msgid "Public photo"
 msgstr ""
 
-#: mod/photos.php:1609 include/conversation.php:1182
+#: mod/photos.php:1595 include/conversation.php:1182
 msgid "Share"
 msgstr ""
 
-#: mod/photos.php:1648 include/conversation.php:509
+#: mod/photos.php:1634 include/conversation.php:509
 #: include/conversation.php:1413
 msgid "Attending"
 msgid_plural "Attending"
 msgstr[0] ""
 msgstr[1] ""
 
-#: mod/photos.php:1648 include/conversation.php:509
+#: mod/photos.php:1634 include/conversation.php:509
 msgid "Not attending"
 msgstr ""
 
-#: mod/photos.php:1648 include/conversation.php:509
+#: mod/photos.php:1634 include/conversation.php:509
 msgid "Might attend"
 msgstr ""
 
-#: mod/photos.php:1813
+#: mod/photos.php:1799
 msgid "Map"
 msgstr ""
 
@@ -6127,60 +6183,60 @@ msgstr ""
 msgid "Item was not found."
 msgstr ""
 
-#: boot.php:868
+#: boot.php:870
 msgid "Delete this item?"
 msgstr ""
 
-#: boot.php:871
+#: boot.php:873
 msgid "show fewer"
 msgstr ""
 
-#: boot.php:1292
+#: boot.php:1382
 #, php-format
 msgid "Update %s failed. See error logs."
 msgstr ""
 
-#: boot.php:1404
+#: boot.php:1494
 msgid "Create a New Account"
 msgstr ""
 
-#: boot.php:1429 include/nav.php:72
+#: boot.php:1519 include/nav.php:72
 msgid "Logout"
 msgstr ""
 
-#: boot.php:1432
+#: boot.php:1522
 msgid "Nickname or Email address: "
 msgstr ""
 
-#: boot.php:1433
+#: boot.php:1523
 msgid "Password: "
 msgstr ""
 
-#: boot.php:1434
+#: boot.php:1524
 msgid "Remember me"
 msgstr ""
 
-#: boot.php:1437
+#: boot.php:1527
 msgid "Or login using OpenID: "
 msgstr ""
 
-#: boot.php:1443
+#: boot.php:1533
 msgid "Forgot your password?"
 msgstr ""
 
-#: boot.php:1446
+#: boot.php:1536
 msgid "Website Terms of Service"
 msgstr ""
 
-#: boot.php:1447
+#: boot.php:1537
 msgid "terms of service"
 msgstr ""
 
-#: boot.php:1449
+#: boot.php:1539
 msgid "Website Privacy Policy"
 msgstr ""
 
-#: boot.php:1450
+#: boot.php:1540
 msgid "privacy policy"
 msgstr ""
 
@@ -6224,6 +6280,16 @@ msgstr ""
 msgid "via"
 msgstr ""
 
+#: include/dfrn.php:1092
+#, php-format
+msgid "%s\\'s birthday"
+msgstr ""
+
+#: include/dfrn.php:1093 include/datetime.php:565
+#, php-format
+msgid "Happy Birthday %s"
+msgstr ""
+
 #: include/dbstructure.php:26
 #, php-format
 msgid ""
@@ -6296,7 +6362,7 @@ msgid "Examples: Robert Morgenstein, Fishing"
 msgstr ""
 
 #: include/contact_widgets.php:36 view/theme/diabook/theme.php:526
-#: view/theme/vier/theme.php:206
+#: view/theme/vier/theme.php:202
 msgid "Similar Interests"
 msgstr ""
 
@@ -6305,7 +6371,7 @@ msgid "Random Profile"
 msgstr ""
 
 #: include/contact_widgets.php:38 view/theme/diabook/theme.php:528
-#: view/theme/vier/theme.php:208
+#: view/theme/vier/theme.php:204
 msgid "Invite Friends"
 msgstr ""
 
@@ -6527,58 +6593,58 @@ msgstr ""
 msgid "Show visitors public community forums at the Advanced Profile Page"
 msgstr ""
 
-#: include/follow.php:77
+#: include/follow.php:81
 msgid "Connect URL missing."
 msgstr ""
 
-#: include/follow.php:104
+#: include/follow.php:108
 msgid ""
 "This site is not configured to allow communications with other networks."
 msgstr ""
 
-#: include/follow.php:105 include/follow.php:125
+#: include/follow.php:109 include/follow.php:129
 msgid "No compatible communication protocols or feeds were discovered."
 msgstr ""
 
-#: include/follow.php:123
+#: include/follow.php:127
 msgid "The profile address specified does not provide adequate information."
 msgstr ""
 
-#: include/follow.php:127
+#: include/follow.php:131
 msgid "An author or name was not found."
 msgstr ""
 
-#: include/follow.php:129
+#: include/follow.php:133
 msgid "No browser URL could be matched to this address."
 msgstr ""
 
-#: include/follow.php:131
+#: include/follow.php:135
 msgid ""
 "Unable to match @-style Identity Address with a known protocol or email "
 "contact."
 msgstr ""
 
-#: include/follow.php:132
+#: include/follow.php:136
 msgid "Use mailto: in front of address to force email check."
 msgstr ""
 
-#: include/follow.php:138
+#: include/follow.php:142
 msgid ""
 "The profile address specified belongs to a network which has been disabled "
 "on this site."
 msgstr ""
 
-#: include/follow.php:148
+#: include/follow.php:152
 msgid ""
 "Limited profile. This person will be unable to receive direct/personal "
 "notifications from you."
 msgstr ""
 
-#: include/follow.php:249
+#: include/follow.php:253
 msgid "Unable to retrieve contact information."
 msgstr ""
 
-#: include/follow.php:302
+#: include/follow.php:288
 msgid "following"
 msgstr ""
 
@@ -6593,245 +6659,240 @@ msgstr ""
 msgid "Default privacy group for new contacts"
 msgstr ""
 
-#: include/group.php:239
+#: include/group.php:242
 msgid "Everybody"
 msgstr ""
 
-#: include/group.php:262
+#: include/group.php:265
 msgid "edit"
 msgstr ""
 
-#: include/group.php:285
+#: include/group.php:288
 msgid "Edit groups"
 msgstr ""
 
-#: include/group.php:287
+#: include/group.php:290
 msgid "Edit group"
 msgstr ""
 
-#: include/group.php:288
+#: include/group.php:291
 msgid "Create a new group"
 msgstr ""
 
-#: include/group.php:291
+#: include/group.php:294
 msgid "Contacts not in any group"
 msgstr ""
 
-#: include/datetime.php:43 include/datetime.php:45
+#: include/datetime.php:57 include/datetime.php:59
 msgid "Miscellaneous"
 msgstr ""
 
-#: include/datetime.php:141
+#: include/datetime.php:178
 msgid "YYYY-MM-DD or MM-DD"
 msgstr ""
 
-#: include/datetime.php:271
+#: include/datetime.php:327
 msgid "never"
 msgstr ""
 
-#: include/datetime.php:277
+#: include/datetime.php:333
 msgid "less than a second ago"
 msgstr ""
 
-#: include/datetime.php:287
+#: include/datetime.php:343
 msgid "year"
 msgstr ""
 
-#: include/datetime.php:287
+#: include/datetime.php:343
 msgid "years"
 msgstr ""
 
-#: include/datetime.php:288
+#: include/datetime.php:344
 msgid "months"
 msgstr ""
 
-#: include/datetime.php:289
+#: include/datetime.php:345
 msgid "weeks"
 msgstr ""
 
-#: include/datetime.php:290
+#: include/datetime.php:346
 msgid "days"
 msgstr ""
 
-#: include/datetime.php:291
+#: include/datetime.php:347
 msgid "hour"
 msgstr ""
 
-#: include/datetime.php:291
+#: include/datetime.php:347
 msgid "hours"
 msgstr ""
 
-#: include/datetime.php:292
+#: include/datetime.php:348
 msgid "minute"
 msgstr ""
 
-#: include/datetime.php:292
+#: include/datetime.php:348
 msgid "minutes"
 msgstr ""
 
-#: include/datetime.php:293
+#: include/datetime.php:349
 msgid "second"
 msgstr ""
 
-#: include/datetime.php:293
+#: include/datetime.php:349
 msgid "seconds"
 msgstr ""
 
-#: include/datetime.php:302
+#: include/datetime.php:358
 #, php-format
 msgid "%1$d %2$s ago"
 msgstr ""
 
-#: include/datetime.php:474 include/items.php:2500
+#: include/datetime.php:564
 #, php-format
 msgid "%s's birthday"
 msgstr ""
 
-#: include/datetime.php:475 include/items.php:2501
-#, php-format
-msgid "Happy Birthday %s"
-msgstr ""
-
 #: include/identity.php:42
 msgid "Requested account is not available."
 msgstr ""
 
-#: include/identity.php:95 include/identity.php:284 include/identity.php:662
+#: include/identity.php:95 include/identity.php:285 include/identity.php:663
 msgid "Edit profile"
 msgstr ""
 
-#: include/identity.php:244
+#: include/identity.php:245
 msgid "Atom feed"
 msgstr ""
 
-#: include/identity.php:249
+#: include/identity.php:250
 msgid "Message"
 msgstr ""
 
-#: include/identity.php:255 include/nav.php:185
+#: include/identity.php:256 include/nav.php:185
 msgid "Profiles"
 msgstr ""
 
-#: include/identity.php:255
+#: include/identity.php:256
 msgid "Manage/edit profiles"
 msgstr ""
 
-#: include/identity.php:425 include/identity.php:509
+#: include/identity.php:426 include/identity.php:510
 msgid "g A l F d"
 msgstr ""
 
-#: include/identity.php:426 include/identity.php:510
+#: include/identity.php:427 include/identity.php:511
 msgid "F d"
 msgstr ""
 
-#: include/identity.php:471 include/identity.php:556
+#: include/identity.php:472 include/identity.php:557
 msgid "[today]"
 msgstr ""
 
-#: include/identity.php:483
+#: include/identity.php:484
 msgid "Birthday Reminders"
 msgstr ""
 
-#: include/identity.php:484
+#: include/identity.php:485
 msgid "Birthdays this week:"
 msgstr ""
 
-#: include/identity.php:543
+#: include/identity.php:544
 msgid "[No description]"
 msgstr ""
 
-#: include/identity.php:567
+#: include/identity.php:568
 msgid "Event Reminders"
 msgstr ""
 
-#: include/identity.php:568
+#: include/identity.php:569
 msgid "Events this week:"
 msgstr ""
 
-#: include/identity.php:595
+#: include/identity.php:596
 msgid "j F, Y"
 msgstr ""
 
-#: include/identity.php:596
+#: include/identity.php:597
 msgid "j F"
 msgstr ""
 
-#: include/identity.php:603
+#: include/identity.php:604
 msgid "Birthday:"
 msgstr ""
 
-#: include/identity.php:607
+#: include/identity.php:608
 msgid "Age:"
 msgstr ""
 
-#: include/identity.php:616
+#: include/identity.php:617
 #, php-format
 msgid "for %1$d %2$s"
 msgstr ""
 
-#: include/identity.php:629
+#: include/identity.php:630
 msgid "Religion:"
 msgstr ""
 
-#: include/identity.php:633
+#: include/identity.php:634
 msgid "Hobbies/Interests:"
 msgstr ""
 
-#: include/identity.php:640
+#: include/identity.php:641
 msgid "Contact information and Social Networks:"
 msgstr ""
 
-#: include/identity.php:642
+#: include/identity.php:643
 msgid "Musical interests:"
 msgstr ""
 
-#: include/identity.php:644
+#: include/identity.php:645
 msgid "Books, literature:"
 msgstr ""
 
-#: include/identity.php:646
+#: include/identity.php:647
 msgid "Television:"
 msgstr ""
 
-#: include/identity.php:648
+#: include/identity.php:649
 msgid "Film/dance/culture/entertainment:"
 msgstr ""
 
-#: include/identity.php:650
+#: include/identity.php:651
 msgid "Love/Romance:"
 msgstr ""
 
-#: include/identity.php:652
+#: include/identity.php:653
 msgid "Work/employment:"
 msgstr ""
 
-#: include/identity.php:654
+#: include/identity.php:655
 msgid "School/education:"
 msgstr ""
 
-#: include/identity.php:658
+#: include/identity.php:659
 msgid "Forums:"
 msgstr ""
 
-#: include/identity.php:710 include/identity.php:713 include/nav.php:78
+#: include/identity.php:711 include/identity.php:714 include/nav.php:78
 msgid "Videos"
 msgstr ""
 
-#: include/identity.php:725 include/nav.php:140
+#: include/identity.php:726 include/nav.php:140
 msgid "Events and Calendar"
 msgstr ""
 
-#: include/identity.php:733
+#: include/identity.php:734
 msgid "Only You Can See This"
 msgstr ""
 
 #: include/like.php:167 include/conversation.php:122
-#: include/conversation.php:258 include/text.php:1998
+#: include/conversation.php:258 include/text.php:1921
 #: view/theme/diabook/theme.php:463
 msgid "event"
 msgstr ""
 
-#: include/like.php:184 include/conversation.php:141 include/diaspora.php:2185
+#: include/like.php:184 include/conversation.php:141 include/diaspora.php:2133
 #: view/theme/diabook/theme.php:480
 #, php-format
 msgid "%1$s likes %2$s's %3$s"
@@ -6892,31 +6953,31 @@ msgstr ""
 msgid "stopped following"
 msgstr ""
 
-#: include/Contact.php:337 include/conversation.php:911
+#: include/Contact.php:339 include/conversation.php:911
 msgid "View Status"
 msgstr ""
 
-#: include/Contact.php:339 include/conversation.php:913
+#: include/Contact.php:341 include/conversation.php:913
 msgid "View Photos"
 msgstr ""
 
-#: include/Contact.php:340 include/conversation.php:914
+#: include/Contact.php:342 include/conversation.php:914
 msgid "Network Posts"
 msgstr ""
 
-#: include/Contact.php:341 include/conversation.php:915
+#: include/Contact.php:343 include/conversation.php:915
 msgid "Edit Contact"
 msgstr ""
 
-#: include/Contact.php:342
+#: include/Contact.php:344
 msgid "Drop Contact"
 msgstr ""
 
-#: include/Contact.php:343 include/conversation.php:916
+#: include/Contact.php:345 include/conversation.php:916
 msgid "Send PM"
 msgstr ""
 
-#: include/Contact.php:344 include/conversation.php:920
+#: include/Contact.php:346 include/conversation.php:920
 msgid "Poke"
 msgstr ""
 
@@ -7131,16 +7192,7 @@ msgid_plural "Undecided"
 msgstr[0] ""
 msgstr[1] ""
 
-#: include/forums.php:105 include/text.php:1015 include/nav.php:126
-#: view/theme/vier/theme.php:259
-msgid "Forums"
-msgstr ""
-
-#: include/forums.php:107 view/theme/vier/theme.php:261
-msgid "External link to forum"
-msgstr ""
-
-#: include/network.php:967
+#: include/network.php:975
 msgid "view full size"
 msgstr ""
 
@@ -7176,186 +7228,191 @@ msgstr ""
 msgid "The end"
 msgstr ""
 
-#: include/text.php:894
+#: include/text.php:865
 msgid "No contacts"
 msgstr ""
 
-#: include/text.php:909
+#: include/text.php:880
 #, php-format
 msgid "%d Contact"
 msgid_plural "%d Contacts"
 msgstr[0] ""
 msgstr[1] ""
 
-#: include/text.php:921
+#: include/text.php:892
 msgid "View Contacts"
 msgstr ""
 
-#: include/text.php:1010 include/nav.php:121
+#: include/text.php:981 include/nav.php:121
 msgid "Full Text"
 msgstr ""
 
-#: include/text.php:1011 include/nav.php:122
+#: include/text.php:982 include/nav.php:122
 msgid "Tags"
 msgstr ""
 
-#: include/text.php:1066
+#: include/text.php:986 include/ForumManager.php:112 include/nav.php:126
+#: view/theme/vier/theme.php:255
+msgid "Forums"
+msgstr ""
+
+#: include/text.php:1037
 msgid "poke"
 msgstr ""
 
-#: include/text.php:1066
+#: include/text.php:1037
 msgid "poked"
 msgstr ""
 
-#: include/text.php:1067
+#: include/text.php:1038
 msgid "ping"
 msgstr ""
 
-#: include/text.php:1067
+#: include/text.php:1038
 msgid "pinged"
 msgstr ""
 
-#: include/text.php:1068
+#: include/text.php:1039
 msgid "prod"
 msgstr ""
 
-#: include/text.php:1068
+#: include/text.php:1039
 msgid "prodded"
 msgstr ""
 
-#: include/text.php:1069
+#: include/text.php:1040
 msgid "slap"
 msgstr ""
 
-#: include/text.php:1069
+#: include/text.php:1040
 msgid "slapped"
 msgstr ""
 
-#: include/text.php:1070
+#: include/text.php:1041
 msgid "finger"
 msgstr ""
 
-#: include/text.php:1070
+#: include/text.php:1041
 msgid "fingered"
 msgstr ""
 
-#: include/text.php:1071
+#: include/text.php:1042
 msgid "rebuff"
 msgstr ""
 
-#: include/text.php:1071
+#: include/text.php:1042
 msgid "rebuffed"
 msgstr ""
 
-#: include/text.php:1085
+#: include/text.php:1056
 msgid "happy"
 msgstr ""
 
-#: include/text.php:1086
+#: include/text.php:1057
 msgid "sad"
 msgstr ""
 
-#: include/text.php:1087
+#: include/text.php:1058
 msgid "mellow"
 msgstr ""
 
-#: include/text.php:1088
+#: include/text.php:1059
 msgid "tired"
 msgstr ""
 
-#: include/text.php:1089
+#: include/text.php:1060
 msgid "perky"
 msgstr ""
 
-#: include/text.php:1090
+#: include/text.php:1061
 msgid "angry"
 msgstr ""
 
-#: include/text.php:1091
+#: include/text.php:1062
 msgid "stupified"
 msgstr ""
 
-#: include/text.php:1092
+#: include/text.php:1063
 msgid "puzzled"
 msgstr ""
 
-#: include/text.php:1093
+#: include/text.php:1064
 msgid "interested"
 msgstr ""
 
-#: include/text.php:1094
+#: include/text.php:1065
 msgid "bitter"
 msgstr ""
 
-#: include/text.php:1095
+#: include/text.php:1066
 msgid "cheerful"
 msgstr ""
 
-#: include/text.php:1096
+#: include/text.php:1067
 msgid "alive"
 msgstr ""
 
-#: include/text.php:1097
+#: include/text.php:1068
 msgid "annoyed"
 msgstr ""
 
-#: include/text.php:1098
+#: include/text.php:1069
 msgid "anxious"
 msgstr ""
 
-#: include/text.php:1099
+#: include/text.php:1070
 msgid "cranky"
 msgstr ""
 
-#: include/text.php:1100
+#: include/text.php:1071
 msgid "disturbed"
 msgstr ""
 
-#: include/text.php:1101
+#: include/text.php:1072
 msgid "frustrated"
 msgstr ""
 
-#: include/text.php:1102
+#: include/text.php:1073
 msgid "motivated"
 msgstr ""
 
-#: include/text.php:1103
+#: include/text.php:1074
 msgid "relaxed"
 msgstr ""
 
-#: include/text.php:1104
+#: include/text.php:1075
 msgid "surprised"
 msgstr ""
 
-#: include/text.php:1504
+#: include/text.php:1475
 msgid "bytes"
 msgstr ""
 
-#: include/text.php:1536 include/text.php:1548
+#: include/text.php:1507 include/text.php:1519
 msgid "Click to open/close"
 msgstr ""
 
-#: include/text.php:1722
+#: include/text.php:1645
 msgid "View on separate page"
 msgstr ""
 
-#: include/text.php:1723
+#: include/text.php:1646
 msgid "view on separate page"
 msgstr ""
 
-#: include/text.php:2002
+#: include/text.php:1925
 msgid "activity"
 msgstr ""
 
-#: include/text.php:2005
+#: include/text.php:1928
 msgid "post"
 msgstr ""
 
-#: include/text.php:2173
+#: include/text.php:2096
 msgid "Item filed"
 msgstr ""
 
-#: include/bbcode.php:482 include/bbcode.php:1157 include/bbcode.php:1158
+#: include/bbcode.php:482 include/bbcode.php:1159 include/bbcode.php:1160
 msgid "Image/photo"
 msgstr ""
 
@@ -7371,11 +7428,11 @@ msgid ""
 "\"%s\" target=\"_blank\">post</a>"
 msgstr ""
 
-#: include/bbcode.php:1117 include/bbcode.php:1137
+#: include/bbcode.php:1119 include/bbcode.php:1139
 msgid "$1 wrote:"
 msgstr ""
 
-#: include/bbcode.php:1166 include/bbcode.php:1167
+#: include/bbcode.php:1168 include/bbcode.php:1169
 msgid "Encrypted content"
 msgstr ""
 
@@ -7469,10 +7526,10 @@ msgid "App.net"
 msgstr ""
 
 #: include/contact_selectors.php:103
-msgid "Redmatrix"
+msgid "Hubzilla/Redmatrix"
 msgstr ""
 
-#: include/Scrape.php:624
+#: include/Scrape.php:623
 msgid " on Last.fm"
 msgstr ""
 
@@ -7496,6 +7553,10 @@ msgstr ""
 msgid "This action is not available under your subscription plan."
 msgstr ""
 
+#: include/ForumManager.php:114 view/theme/vier/theme.php:257
+msgid "External link to forum"
+msgstr ""
+
 #: include/nav.php:72
 msgid "End this session"
 msgstr ""
@@ -7648,17 +7709,17 @@ msgstr ""
 msgid "Site map"
 msgstr ""
 
-#: include/api.php:878
+#: include/api.php:906
 #, php-format
 msgid "Daily posting limit of %d posts reached. The post was rejected."
 msgstr ""
 
-#: include/api.php:897
+#: include/api.php:926
 #, php-format
 msgid "Weekly posting limit of %d posts reached. The post was rejected."
 msgstr ""
 
-#: include/api.php:916
+#: include/api.php:947
 #, php-format
 msgid "Monthly posting limit of %d posts reached. The post was rejected."
 msgstr ""
@@ -7781,27 +7842,27 @@ msgid ""
 "\t\tThank you and welcome to %2$s."
 msgstr ""
 
-#: include/diaspora.php:720
+#: include/diaspora.php:719
 msgid "Sharing notification from Diaspora network"
 msgstr ""
 
-#: include/diaspora.php:2625
+#: include/diaspora.php:2570
 msgid "Attachments:"
 msgstr ""
 
-#: include/delivery.php:533
+#: include/delivery.php:438
 msgid "(no subject)"
 msgstr ""
 
-#: include/delivery.php:544 include/enotify.php:37
+#: include/delivery.php:449 include/enotify.php:37
 msgid "noreply"
 msgstr ""
 
-#: include/items.php:4926
+#: include/items.php:1832
 msgid "Do you really want to delete this item?"
 msgstr ""
 
-#: include/items.php:5201
+#: include/items.php:2107
 msgid "Archives"
 msgstr ""
 
@@ -8361,7 +8422,7 @@ msgstr[1] ""
 msgid "Done. You can now login with your username and password"
 msgstr ""
 
-#: index.php:442
+#: index.php:434
 msgid "toggle mobile"
 msgstr ""
 
@@ -8443,7 +8504,7 @@ msgstr ""
 
 #: view/theme/diabook/config.php:160 view/theme/diabook/theme.php:391
 #: view/theme/diabook/theme.php:626 view/theme/vier/config.php:112
-#: view/theme/vier/theme.php:156
+#: view/theme/vier/theme.php:152
 msgid "Community Profiles"
 msgstr ""
 
@@ -8454,19 +8515,19 @@ msgstr ""
 
 #: view/theme/diabook/config.php:162 view/theme/diabook/theme.php:606
 #: view/theme/diabook/theme.php:628 view/theme/vier/config.php:114
-#: view/theme/vier/theme.php:377
+#: view/theme/vier/theme.php:373
 msgid "Connect Services"
 msgstr ""
 
 #: view/theme/diabook/config.php:163 view/theme/diabook/theme.php:523
 #: view/theme/diabook/theme.php:629 view/theme/vier/config.php:115
-#: view/theme/vier/theme.php:203
+#: view/theme/vier/theme.php:199
 msgid "Find Friends"
 msgstr ""
 
 #: view/theme/diabook/config.php:164 view/theme/diabook/theme.php:412
 #: view/theme/diabook/theme.php:630 view/theme/vier/config.php:116
-#: view/theme/vier/theme.php:185
+#: view/theme/vier/theme.php:181
 msgid "Last users"
 msgstr ""
 
@@ -8488,7 +8549,7 @@ msgstr ""
 msgid "Your personal photos"
 msgstr ""
 
-#: view/theme/diabook/theme.php:524 view/theme/vier/theme.php:204
+#: view/theme/diabook/theme.php:524 view/theme/vier/theme.php:200
 msgid "Local Directory"
 msgstr ""
 
@@ -8508,7 +8569,7 @@ msgstr ""
 msgid "Set style"
 msgstr ""
 
-#: view/theme/vier/theme.php:295
+#: view/theme/vier/theme.php:291
 msgid "Quick Start"
 msgstr ""
 

From b5851931d135d8466f3cc6835e43b7f36e130c20 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Sat, 12 Mar 2016 08:57:07 +0100
Subject: [PATCH 185/273] Hotkey documentation

---
 doc/Settings.md    | 2 --
 doc/de/Settings.md | 3 ---
 2 files changed, 5 deletions(-)

diff --git a/doc/Settings.md b/doc/Settings.md
index 86254cb29e..7d909afa09 100644
--- a/doc/Settings.md
+++ b/doc/Settings.md
@@ -11,8 +11,6 @@ Hot Keys
 Friendica traps the following keyboard events:
 
 * [Pause] - Pauses "Ajax" update activity. This is the process that provides updates without reloading the page. You may wish to pause it to reduce network usage and/or as a debugging aid for javascript developers. A pause indicator will appear at the lower right hand corner of the page. Hit the [pause] key once again to resume.
-* [F8] - Displays a language selector
-
 
 Birthday Notifications
 ---
diff --git a/doc/de/Settings.md b/doc/de/Settings.md
index 988b3657c0..4ad9f39ba5 100644
--- a/doc/de/Settings.md
+++ b/doc/de/Settings.md
@@ -14,9 +14,6 @@ Friendica erfasst die folgenden Tastaturbefehle:
 
 * [Pause] - Pausiert die Update-Aktivität via "Ajax". Das ist ein Prozess, der Updates durchführt, ohne die Seite neu zu laden. Du kannst diesen Prozess pausieren, um deine Netzwerkauslastung zu reduzieren und/oder um es in der Javascript-Programmierung zum Debuggen zu nutzen. Ein Pausenzeichen erscheint unten links im Fenster. Klicke die [Pause]-Taste ein weiteres Mal, um die Pause zu beenden.
 
-* [F8] - Zeigt eine Sprachauswahl an
-
-
 **Geburtstagsbenachrichtigung**
 
 Geburtstage erscheinen auf deiner Startseite für alle Freunde, die in den nächsten 6 Tagen Geburtstag haben. 

From 14a2aa552a55c238d4a20d8034bee7604fe2b0e4 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 12 Mar 2016 09:21:13 +0100
Subject: [PATCH 186/273] The name in the notifications has to be double
 encoded

---
 mod/ping.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mod/ping.php b/mod/ping.php
index 2eb94576b3..544aa446bb 100644
--- a/mod/ping.php
+++ b/mod/ping.php
@@ -207,7 +207,7 @@ function ping_init(&$a) {
 			call_hooks('ping_xmlize', $n);
 			$notsxml = '<note id="%d" href="%s" name="%s" url="%s" photo="%s" date="%s" seen="%s" timestamp="%s" >%s</note>'."\n";
 			return sprintf ( $notsxml, intval($n['id']),
-				xmlify($n['href']), xmlify($n['name']), xmlify($n['url']), xmlify($n['photo']),
+				xmlify($n['href']), xmlify(xmlify($n['name'])), xmlify($n['url']), xmlify($n['photo']),
 				xmlify(relative_date($n['date'])), xmlify($n['seen']), xmlify(strtotime($local_time)),
 				xmlify($n['message'])
 			);

From 2a864d889e3e567a8286320966adcc32f9a42bb7 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Sat, 12 Mar 2016 16:25:17 +0100
Subject: [PATCH 187/273] missing include file for the SocNet settings

---
 mod/settings.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/mod/settings.php b/mod/settings.php
index 0c3b23a44b..c7659212bf 100644
--- a/mod/settings.php
+++ b/mod/settings.php
@@ -1,5 +1,6 @@
 <?php
 
+require_once('include/group.php');
 
 function get_theme_config_file($theme){
 	$a = get_app();

From 0f65eee69567483d5b55023e53014655c38a5237 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 12 Mar 2016 19:19:20 +0100
Subject: [PATCH 188/273] Everything could work - needs some beautification and
 documentation

---
 include/diaspora2.php | 473 +++++++++++++-----------------------------
 1 file changed, 142 insertions(+), 331 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 7aa0fc6989..3d12ef5bbf 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -123,53 +123,43 @@ class diaspora {
 		$type = $fields->getName();
 
 		switch ($type) {
-			case "account_deletion": // Done
-				//return true;
+			case "account_deletion":
 				return self::receive_account_deletion($importer, $fields);
 
-			case "comment": // Done
-				//return true;
+			case "comment":
 				return self::receive_comment($importer, $sender, $fields);
 
-			case "conversation": // Done
-				//return true;
+			case "conversation":
 				return self::receive_conversation($importer, $msg, $fields);
 
-			case "like": // Done
-				//return true;
+			case "like":
 				return self::receive_like($importer, $sender, $fields);
 
-			case "message": // Done
-				//return true;
+			case "message":
 				return self::receive_message($importer, $fields);
 
 			case "participation": // Not implemented
 				return self::receive_participation($importer, $fields);
 
-			case "photo": // Not needed
+			case "photo": // Not implemented
 				return self::receive_photo($importer, $fields);
 
 			case "poll_participation": // Not implemented
 				return self::receive_poll_participation($importer, $fields);
 
-			case "profile": // Done
-				//return true;
+			case "profile":
 				return self::receive_profile($importer, $fields);
 
 			case "request":
-				//return true;
 				return self::receive_request($importer, $fields);
 
-			case "reshare": // Done
-				//return true;
+			case "reshare":
 				return self::receive_reshare($importer, $fields);
 
-			case "retraction": // Done
-				//return true;
+			case "retraction":
 				return self::receive_retraction($importer, $sender, $fields);
 
-			case "status_message": // Done
-				//return true;
+			case "status_message":
 				return self::receive_status_message($importer, $fields);
 
 			default:
@@ -1364,7 +1354,7 @@ EOT;
 
 			$u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"]));
 			if($u)
-				$ret = diaspora_share($u[0], $contact_record);
+				$ret = self::send_share($u[0], $contact_record);
 		}
 
 		return true;
@@ -1557,8 +1547,10 @@ EOT;
 			case "StatusMessage":
 				return self::item_retraction($importer, $contact, $data);;
 
-			case "Person": /// @todo an "unshare" shouldn't remove the contact
-				contact_remove($contact["id"]);
+			case "Person":
+				/// @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;
 
 			default:
@@ -1862,41 +1854,43 @@ EOT;
 			}
 		}
 
-
 		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(
-										"sender_handle" => $myaddr,
-										"recipient_handle" => $theiraddr
-									))));
+	private function build_and_transmit($owner, $contact, $type, $message, $public_batch = false, $guid = "") {
+
+		$data = array("XML" => array("post" => array($type => $message)));
 
 		$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) {
-		$myaddr = self::get_my_handle($me);
+	public static function send_share($owner,$contact) {
 
-		$data = array("XML" => array("post" => array("retraction" => array(
-										"post_guid" => $me["guid"],
-										"diaspora_handle" => $myaddr,
-										"type" => "Person"
-									))));
+		$message = array("sender_handle" => self::get_my_handle($owner),
+				"recipient_handle" => $contact["addr"]);
 
-		$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) {
@@ -1969,27 +1963,6 @@ EOT;
 	public static function send_status($item, $owner, $contact, $public_batch = false) {
 
 		$myaddr = self::get_my_handle($owner);
-		$theiraddr = $contact["addr"];
-
-		$title = $item["title"];
-		$body = $item["body"];
-
-		// convert to markdown
-		$body = html_entity_decode(bb2diaspora($body));
-
-		// Adding the title
-		if(strlen($title))
-			$body = "## ".html_entity_decode($title)."\n\n".$body;
-
-		if ($item["attach"]) {
-			$cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism', $item["attach"], $matches, PREG_SET_ORDER);
-			if(cnt) {
-				$body .= "\n".t("Attachments:")."\n";
-				foreach($matches as $mtch)
-					$body .= "[".$mtch[3]."](".$mtch[1].")\n";
-			}
-		}
-
 
 		$public = (($item["private"]) ? "false" : "true");
 
@@ -2005,8 +1978,27 @@ EOT;
 					"created_at" => $created,
 					"provider_display_name" => $item["app"]);
 
-			$data = array("XML" => array("post" => array("reshare" => $message)));
+			$type = "reshare";
 		} else {
+			$title = $item["title"];
+			$body = $item["body"];
+
+			// convert to markdown
+			$body = html_entity_decode(bb2diaspora($body));
+
+			// Adding the title
+			if(strlen($title))
+				$body = "## ".html_entity_decode($title)."\n\n".$body;
+
+			if ($item["attach"]) {
+				$cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism', $item["attach"], $matches, PREG_SET_ORDER);
+				if(cnt) {
+					$body .= "\n".t("Attachments:")."\n";
+					foreach($matches as $mtch)
+						$body .= "[".$mtch[3]."](".$mtch[1].")\n";
+				}
+			}
+
 			$location = array();
 
 			if ($item["location"] != "")
@@ -2029,126 +2021,87 @@ EOT;
 			if (count($location) == 0)
 				unset($message["location"]);
 
-			$data = array("XML" => array("post" => array("status_message" => $message)));
+			$type = "status_message";
 		}
 
-		$msg = xml::from_array($data, $xml);
-
-		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;
+		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
 	}
 
-	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",
-				dbesc($item["thr-parent"]));
-			if(!$p)
-				return false;
+		$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
+			dbesc($item["thr-parent"]));
+		if(!$p)
+			return false;
 
-			$parent = $p[0];
+		$parent = $p[0];
 
-			$target_type = ($parent["uri"] === $parent["parent-uri"] ? "Post" : "Comment");
-			$positive = "true";
+		$target_type = ($parent["uri"] === $parent["parent-uri"] ? "Post" : "Comment");
+		$positive = "true";
 
-			$message = array("positive" => $positive,
-					"guid" => $item["guid"],
-					"target_type" => $target_type,
-					"parent_guid" => $parent["guid"],
-					"author_signature" => $authorsig,
-					"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("like" => $message)));
-
-		return xml::from_array($data, $xml);
+		return(array("positive" => $positive,
+				"guid" => $item["guid"],
+				"target_type" => $target_type,
+				"parent_guid" => $parent["guid"],
+				"author_signature" => $authorsig,
+				"diaspora_handle" => $myaddr));
 	}
 
-	private function construct_comment($item,$owner,$contact,$public_batch = false, $data = null) {
+	private function construct_comment($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` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1",
-				intval($item["parent"]),
-				intval($item["parent"])
-			);
+		$p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1",
+			intval($item["parent"]),
+			intval($item["parent"])
+		);
 
-			if (!$p)
-				return false;
+		if (!$p)
+			return false;
 
-			$parent = $p[0];
+		$parent = $p[0];
 
-			$text = html_entity_decode(bb2diaspora($item["body"]));
+		$text = html_entity_decode(bb2diaspora($item["body"]));
 
-			$message = array("guid" => $item["guid"],
-					"parent_guid" => $parent["guid"],
-					"author_signature" => "",
-					"text" => $text,
-					"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);
+		return(array("guid" => $item["guid"],
+				"parent_guid" => $parent["guid"],
+				"author_signature" => "",
+				"text" => $text,
+				"diaspora_handle" => $myaddr));
 	}
 
 	public static function send_followup($item,$owner,$contact,$public_batch = false) {
 
-		if($item['verb'] === ACTIVITY_LIKE)
-			$msg = self::construct_like($item, $owner, $contact, $public_batch);
-		else
-			$msg = self::construct_comment($item, $owner, $contact, $public_batch);
+		if($item['verb'] === ACTIVITY_LIKE) {
+			$message = self::construct_like($item, $owner);
+			$type = "like";
+		} else {
+			$message = self::construct_comment($item, $owner);
+			$type = "comment";
+		}
 
-		if (!$msg)
-			return $msg;
+		if (!$message)
+			return false;
 
-		logger("base message: ".$msg, LOGGER_DATA);
-		logger("send guid ".$item["guid"], LOGGER_DEBUG);
+		$message["author_signature"] = self::get_signature($owner, $message);
 
-		$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;
+		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
 	}
 
 	function send_relay($item, $owner, $contact, $public_batch = false) {
 
-		if ($item["deleted"])
+		if ($item["deleted"]) {
 			$sql_sign_id = "retract_iid";
-		else
+			$type = "relayable_retraction";
+		} elseif ($item['verb'] === ACTIVITY_LIKE) {
 			$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
 		// or DFRN user.
@@ -2157,24 +2110,32 @@ EOT;
 			intval($item["id"])
 		);
 
-		if(count($r)) {
-			$orig_sign = $r[0];
-			$signed_text = $orig_sign['signed_text'];
-			$authorsig = $orig_sign['signature'];
-			$handle = $orig_sign['signer'];
+		if (!$r)
+			return self::send_followup($item, $owner, $contact, $public_batch);
+
+		$orig_sign = $r[0];
+
+		// Old way - can be removed for the master branch
+		if ($orig_sign['signed_text'] AND $orig_sign['signature'] AND $orig_sign['signer']) {
 
 			// Split the signed text
-			$signed_parts = explode(";", $signed_text);
+			$signed_parts = explode(";", $orig_sign['signed_text']);
 
-			if ($item['verb'] === ACTIVITY_LIKE) {
-				$data = array("positive" => $signed_parts[0],
+			if ($item["deleted"])
+				$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],
 						"target_type" => $signed_parts[2],
 						"parent_guid" => $signed_parts[3],
 						"parent_author_signature" => "",
 						"author_signature" => $orig_sign['signature'],
 						"diaspora_handle" => $signed_parts[4]);
-			} else {
+			else {
 				// Remove the comment guid
 				$guid = array_shift($signed_parts);
 
@@ -2187,154 +2148,26 @@ EOT;
 				// Glue the parts together
 				$text = implode(";", $signed_parts);
 
-				$data = array("guid" => $guid,
+				$message = array("guid" => $guid,
 						"parent_guid" => $parent_guid,
 						"parent_author_signature" => "",
 						"author_signature" => $orig_sign['signature'],
 						"text" => implode(";", $signed_parts),
 						"diaspora_handle" => $handle);
 			}
+		} else { // New way
+			$message = json_decode($orig_sign['signed_text']);
 		}
 
-		if ($item['deleted'])
-			; // Relayed Retraction
-		elseif($item['verb'] === ACTIVITY_LIKE)
-			$msg = self::construct_like($item, $owner, $contact, $public_batch, $data);
-		else
-			$msg = self::construct_comment($item, $owner, $contact, $public_batch, $data);
-die($msg);
+		if ($item["deleted"]) {
+			$signed_text = $message["target_guid"].';'.$message["target_type"];
+			$message["parent_author_signature"] = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
+		} else
+			$message["parent_author_signature"] = self::get_signature($owner, $message);
 
-		logger('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, $public_batch, false, $item['guid']);
-
-		logger("guid: ".$item["guid"]." result ".$return_code, LOGGER_DEBUG);
-
-		return $return_code;
+		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
 	}
 
-/*
-	// 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) {
 
 		$myaddr = self::get_my_handle($owner);
@@ -2355,21 +2188,10 @@ die($msg);
 				"sender_handle" => $myaddr,
 				"target_author_signature" => base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')));
 
-		$data = array("XML" => array("post" => array($msg_type => $message)));
-		$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;
+		return self::build_and_transmit($owner, $contact, $msg_type, $message, $public_batch, $item["guid"]);
 	}
 
-	public static function send_mail($item,$owner,$contact) {
+	public static function send_mail($item, $owner, $contact) {
 
 		$myaddr = self::get_my_handle($owner);
 
@@ -2396,7 +2218,6 @@ die($msg);
 		$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'];
-
 		$sig = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
 
 		$msg = array(
@@ -2410,9 +2231,10 @@ die($msg);
 			"conversation_guid" => $cnv["guid"]
 		);
 
-		if ($item["reply"])
-			$data = array("XML" => array("post" => array("message" => $msg)));
-		else {
+		if ($item["reply"]) {
+			$message = $msg;
+			$type = "message";
+		} else {
 			$message = array("guid" => $cnv["guid"],
 					"subject" => $cnv["subject"],
 					"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"],
 					"participant_handles" => $cnv["recips"]);
 
-			$data = array("XML" => array("post" => array("conversation" => $message)));
+			$type = "conversation";
 		}
 
-		$xmsg = xml::from_array($data, $xml);
-
-		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;
+		return self::build_and_transmit($owner, $contact, $type, $message, false, $item["guid"]);
 	}
 }
 ?>

From f978bc9cc8011ab31e9abd90519008c6248cdebb Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 13 Mar 2016 07:10:24 +0100
Subject: [PATCH 189/273] Some code cleaning, changes to the xml generation

---
 include/diaspora2.php | 183 ++++++++++++++++++++++++------------------
 include/xml.php       |  10 ++-
 2 files changed, 114 insertions(+), 79 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 3d12ef5bbf..97d5ecee9f 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -20,7 +20,7 @@ require_once("include/datetime.php");
  */
 class diaspora {
 
-	public static function fetch_relay() {
+	public static function relay_list() {
 
 		$serverdata = get_config("system", "relay_server");
 		if ($serverdata == "")
@@ -277,13 +277,13 @@ class diaspora {
 			return false;
 
 		if (isset($parent_author_signature)) {
-			$key = self::get_key($msg["author"]);
+			$key = self::key($msg["author"]);
 
 			if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256"))
 				return false;
 		}
 
-		$key = self::get_key($fields->author);
+		$key = self::key($fields->author);
 
 		return rsa_verify($signed_data, $author_signature, $key, "sha256");
 	}
@@ -295,10 +295,10 @@ class diaspora {
 	 *
 	 * @return string The public key
 	 */
-	private function get_key($handle) {
+	private function key($handle) {
 		logger("Fetching diaspora key for: ".$handle);
 
-		$r = self::get_person_by_handle($handle);
+		$r = self::person_by_handle($handle);
 		if($r)
 			return $r["pubkey"];
 
@@ -312,7 +312,7 @@ class diaspora {
 	 *
 	 * @return array the queried data
 	 */
-	private function get_person_by_handle($handle) {
+	private function person_by_handle($handle) {
 
 		$r = q("SELECT * FROM `fcontact` WHERE `network` = '%s' AND `addr` = '%s' LIMIT 1",
 			dbesc(NETWORK_DIASPORA),
@@ -407,7 +407,33 @@ class diaspora {
 		return $r;
 	}
 
-	private function get_contact_by_handle($uid, $handle) {
+	public static function handle_from_contact($contact_id) {
+		$handle = False;
+
+		logger("contact id is ".$contact_id, LOGGER_DEBUG);
+
+		$r = q("SELECT `network`, `addr`, `self`, `url`, `nick` FROM `contact` WHERE `id` = %d",
+		       intval($contact_id)
+		);
+		if($r) {
+			$contact = $r[0];
+
+			logger("contact 'self' = ".$contact['self']." 'url' = ".$contact['url'], LOGGER_DEBUG);
+
+			if($contact['addr'] != "")
+				$handle = $contact['addr'];
+			elseif(($contact['network'] === NETWORK_DFRN) || ($contact['self'] == 1)) {
+				$baseurl_start = strpos($contact['url'],'://') + 3;
+				$baseurl_length = strpos($contact['url'],'/profile') - $baseurl_start; // allows installations in a subdirectory--not sure how Diaspora will handle
+				$baseurl = substr($contact['url'], $baseurl_start, $baseurl_length);
+				$handle = $contact['nick'].'@'.$baseurl;
+			}
+		}
+
+		return $handle;
+	}
+
+	private function contact_by_handle($uid, $handle) {
 		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `addr` = '%s' LIMIT 1",
 			intval($uid),
 			dbesc($handle)
@@ -459,8 +485,8 @@ class diaspora {
 		return false;
 	}
 
-	private function get_allowed_contact_by_handle($importer, $handle, $is_comment = false) {
-		$contact = self::get_contact_by_handle($importer["uid"], $handle);
+	private function allowed_contact_by_handle($importer, $handle, $is_comment = false) {
+		$contact = self::contact_by_handle($importer["uid"], $handle);
 		if (!$contact) {
 			logger("A Contact for handle ".$handle." and user ".$importer["uid"]." was not found");
 			return false;
@@ -505,7 +531,7 @@ class diaspora {
 
 		logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG);
 
-		$msg = self::fetch_message($guid, $server);
+		$msg = self::message($guid, $server);
 
 		if (!$msg)
 			return false;
@@ -516,7 +542,7 @@ class diaspora {
 		return self::dispatch_public($msg);
 	}
 
-	private function fetch_message($guid, $server, $level = 0) {
+	private function message($guid, $server, $level = 0) {
 
 		if ($level > 5)
 			return false;
@@ -534,10 +560,10 @@ class diaspora {
 
 		if ($source_xml->post->reshare) {
 			// Reshare of a reshare - old Diaspora version
-			return self::fetch_message($source_xml->post->reshare->root_guid, $server, ++$level);
+			return self::message($source_xml->post->reshare->root_guid, $server, ++$level);
 		} elseif ($source_xml->getName() == "reshare") {
 			// Reshare of a reshare - new Diaspora version
-			return self::fetch_message($source_xml->root_guid, $server, ++$level);
+			return self::message($source_xml->root_guid, $server, ++$level);
 		}
 
 		$author = "";
@@ -554,12 +580,12 @@ class diaspora {
 
 		$msg = array("message" => $x, "author" => $author);
 
-		$msg["key"] = self::get_key($msg["author"]);
+		$msg["key"] = self::key($msg["author"]);
 
 		return $msg;
 	}
 
-	private function fetch_parent_item($uid, $guid, $author, $contact) {
+	private function parent_item($uid, $guid, $author, $contact) {
 		$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
 				`author-name`, `author-link`, `author-avatar`,
 				`owner-name`, `owner-link`, `owner-avatar`
@@ -570,7 +596,7 @@ class diaspora {
 			$result = self::store_by_guid($guid, $contact["url"], $uid);
 
 			if (!$result) {
-				$person = self::get_person_by_handle($author);
+				$person = self::person_by_handle($author);
 				$result = self::store_by_guid($guid, $person["url"], $uid);
 			}
 
@@ -592,7 +618,7 @@ class diaspora {
 			return $r[0];
 	}
 
-	private function get_author_contact_by_url($contact, $person, $uid) {
+	private function author_contact_by_url($contact, $person, $uid) {
 
 		$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
 			dbesc(normalise_link($person["url"])), intval($uid));
@@ -636,7 +662,7 @@ class diaspora {
 	private function receive_account_deletion($importer, $data) {
 		$author = notags(unxmlify($data->author));
 
-		$contact = self::get_contact_by_handle($importer["uid"], $author);
+		$contact = self::contact_by_handle($importer["uid"], $author);
 		if (!$contact) {
 			logger("cannot find contact for author: ".$author);
 			return false;
@@ -653,25 +679,25 @@ class diaspora {
 		$text = unxmlify($data->text);
 		$author = notags(unxmlify($data->author));
 
-		$contact = self::get_allowed_contact_by_handle($importer, $sender, true);
+		$contact = self::allowed_contact_by_handle($importer, $sender, true);
 		if (!$contact)
 			return false;
 
 		if (self::message_exists($importer["uid"], $guid))
 			return false;
 
-		$parent_item = self::fetch_parent_item($importer["uid"], $parent_guid, $author, $contact);
+		$parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact);
 		if (!$parent_item)
 			return false;
 
-		$person = self::get_person_by_handle($author);
+		$person = self::person_by_handle($author);
 		if (!is_array($person)) {
 			logger("unable to find author details");
 			return false;
 		}
 
 		// Fetch the contact id - if we know this contact
-		$author_contact = self::get_author_contact_by_url($contact, $person, $importer["uid"]);
+		$author_contact = self::author_contact_by_url($contact, $person, $importer["uid"]);
 
 		$datarray = array();
 
@@ -763,7 +789,7 @@ class diaspora {
 			$person = $contact;
 			$key = $msg["key"];
 		} else {
-			$person = self::get_person_by_handle($msg_author);
+			$person = self::person_by_handle($msg_author);
 
 			if (is_array($person) && x($person, "pubkey"))
 				$key = $person["pubkey"];
@@ -852,7 +878,7 @@ class diaspora {
 			return false;
 		}
 
-		$contact = self::get_allowed_contact_by_handle($importer, $msg["author"], true);
+		$contact = self::allowed_contact_by_handle($importer, $msg["author"], true);
 		if (!$contact)
 			return false;
 
@@ -907,22 +933,17 @@ class diaspora {
 
 	private function construct_like_object($importer, $parent_item) {
 		$objtype = ACTIVITY_OBJ_NOTE;
-		$link = xmlify('<link rel="alternate" type="text/html" href="'.App::get_baseurl()."/display/".$importer["nickname"]."/".$parent_item["id"].'" />'."\n") ;
+		$link = '<link rel="alternate" type="text/html" href="'.App::get_baseurl()."/display/".$importer["nickname"]."/".$parent_item["id"].'" />';
 		$parent_body = $parent_item["body"];
 
-		$obj = <<< EOT
+		$xmldata = array("object" => array("type" => $objtype,
+						"local" => "1",
+						"id" => $parent_item["uri"],
+						"link" => $link,
+						"title" => "",
+						"content" => $parent_body));
 
-		<object>
-			<type>$objtype</type>
-			<local>1</local>
-			<id>{$parent_item["uri"]}</id>
-			<link>$link</link>
-			<title></title>
-			<content>$parent_body</content>
-		</object>
-EOT;
-
-		return $obj;
+		return xml::from_array($xmldata, $xml, true);
 	}
 
 	private function receive_like($importer, $sender, $data) {
@@ -937,25 +958,25 @@ EOT;
 		if (!in_array($parent_type, array("Post", "Comment")))
 			return false;
 
-		$contact = self::get_allowed_contact_by_handle($importer, $sender, true);
+		$contact = self::allowed_contact_by_handle($importer, $sender, true);
 		if (!$contact)
 			return false;
 
 		if (self::message_exists($importer["uid"], $guid))
 			return false;
 
-		$parent_item = self::fetch_parent_item($importer["uid"], $parent_guid, $author, $contact);
+		$parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact);
 		if (!$parent_item)
 			return false;
 
-		$person = self::get_person_by_handle($author);
+		$person = self::person_by_handle($author);
 		if (!is_array($person)) {
 			logger("unable to find author details");
 			return false;
 		}
 
 		// Fetch the contact id - if we know this contact
-		$author_contact = self::get_author_contact_by_url($contact, $person, $importer["uid"]);
+		$author_contact = self::author_contact_by_url($contact, $person, $importer["uid"]);
 
 		// "positive" = "false" would be a Dislike - wich isn't currently supported by Diaspora
 		// We would accept this anyhow.
@@ -1019,7 +1040,7 @@ EOT;
 		$author = notags(unxmlify($data->author));
 		$conversation_guid = notags(unxmlify($data->conversation_guid));
 
-		$contact = self::get_allowed_contact_by_handle($importer, $author, true);
+		$contact = self::allowed_contact_by_handle($importer, $author, true);
 		if (!$contact)
 			return false;
 
@@ -1041,7 +1062,7 @@ EOT;
 		$body = diaspora2bb($text);
 		$message_uri = $author.":".$guid;
 
-		$person = self::get_person_by_handle($author);
+		$person = self::person_by_handle($author);
 		if (!$person) {
 			logger("unable to find author details");
 			return false;
@@ -1100,7 +1121,7 @@ EOT;
 	private function receive_profile($importer, $data) {
 		$author = notags(unxmlify($data->author));
 
-		$contact = self::get_contact_by_handle($importer["uid"], $author);
+		$contact = self::contact_by_handle($importer["uid"], $author);
 		if (!$contact)
 			return;
 
@@ -1254,7 +1275,7 @@ EOT;
 		if (!$author || !$recipient)
 			return;
 
-		$contact = self::get_contact_by_handle($importer["uid"],$author);
+		$contact = self::contact_by_handle($importer["uid"],$author);
 
 		if($contact) {
 
@@ -1265,7 +1286,7 @@ EOT;
 			return true;
 		}
 
-		$ret = self::get_person_by_handle($author);
+		$ret = self::person_by_handle($author);
 
 		if (!$ret || ($ret["network"] != NETWORK_DIASPORA)) {
 			logger("Cannot resolve diaspora handle ".$author ." for ".$recipient);
@@ -1295,7 +1316,7 @@ EOT;
 
 		// find the contact record we just created
 
-		$contact_record = self::get_contact_by_handle($importer["uid"],$author);
+		$contact_record = self::contact_by_handle($importer["uid"],$author);
 
 		if (!$contact_record) {
 			logger("unable to locate newly created contact record.");
@@ -1360,7 +1381,7 @@ EOT;
 		return true;
 	}
 
-	private function get_original_item($guid, $orig_author, $author) {
+	private function original_item($guid, $orig_author, $author) {
 
 		// Do we already have this item?
 		$r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`,
@@ -1424,14 +1445,14 @@ EOT;
 		$public = notags(unxmlify($data->public));
 		$created_at = notags(unxmlify($data->created_at));
 
-		$contact = self::get_allowed_contact_by_handle($importer, $author, false);
+		$contact = self::allowed_contact_by_handle($importer, $author, false);
 		if (!$contact)
 			return false;
 
 		if (self::message_exists($importer["uid"], $guid))
 			return false;
 
-		$original_item = self::get_original_item($root_guid, $root_author, $author);
+		$original_item = self::original_item($root_guid, $root_author, $author);
 		if (!$original_item)
 			return false;
 
@@ -1482,7 +1503,7 @@ EOT;
 		$target_guid = notags(unxmlify($data->target_guid));
 		$author = notags(unxmlify($data->author));
 
-		$person = self::get_person_by_handle($author);
+		$person = self::person_by_handle($author);
 		if (!is_array($person)) {
 			logger("unable to find author detail for ".$author);
 			return false;
@@ -1533,7 +1554,7 @@ EOT;
 	private function receive_retraction($importer, $sender, $data) {
 		$target_type = notags(unxmlify($data->target_type));
 
-		$contact = self::get_contact_by_handle($importer["uid"], $sender);
+		$contact = self::contact_by_handle($importer["uid"], $sender);
 		if (!$contact) {
 			logger("cannot find contact for sender: ".$sender." and user ".$importer["uid"]);
 			return false;
@@ -1575,7 +1596,7 @@ EOT;
 		//		print_r($poll);
 		//	die("poll!\n");
 		//}
-		$contact = self::get_allowed_contact_by_handle($importer, $author, false);
+		$contact = self::allowed_contact_by_handle($importer, $author, false);
 		if (!$contact)
 			return false;
 
@@ -1652,7 +1673,7 @@ EOT;
 	 * Here come all the functions that are needed to transmit data with the Diaspora protocol *
 	 *******************************************************************************************/
 
-	private function get_my_handle($me) {
+	private function my_handle($me) {
 		if ($contact["addr"] != "")
 			return $contact["addr"];
 
@@ -1665,7 +1686,7 @@ EOT;
 
 		logger("Message: ".$msg, LOGGER_DATA);
 
-		$handle = self::get_my_handle($user);
+		$handle = self::my_handle($user);
 
 		$b64url_data = base64url_encode($msg);
 
@@ -1694,7 +1715,7 @@ $magic_env = <<< EOT
   </me:env>
 </diaspora>
 EOT;
-
+die($magic_env."\n");
 		logger("magic_env: ".$magic_env, LOGGER_DATA);
 		return $magic_env;
 	}
@@ -1720,7 +1741,7 @@ EOT;
 		$outer_iv = random_string(16);
 		$b_outer_iv = base64_encode($outer_iv);
 
-		$handle = self::get_my_handle($user);
+		$handle = self::my_handle($user);
 
 		$padded_data = pkcs5_pad($msg,16);
 		$inner_encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $padded_data, MCRYPT_MODE_CBC, $inner_iv);
@@ -1740,14 +1761,11 @@ EOT;
 		$signature = rsa_sign($signable_data,$prvkey);
 		$sig = base64url_encode($signature);
 
-$decrypted_header = <<< EOT
-<decrypted_header>
-  <iv>$b_inner_iv</iv>
-  <aes_key>$b_inner_aes_key</aes_key>
-  <author_id>$handle</author_id>
-</decrypted_header>
-EOT;
+		$xmldata = array("decrypted_header" => array("iv" => $b_inner_iv,
+							"aes_key" => $b_inner_aes_key,
+							"author_id" => $handle));
 
+		$decrypted_header = xml::from_array($xmldata, $xml, true);
 		$decrypted_header = pkcs5_pad($decrypted_header,16);
 
 		$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $outer_aes_key, $decrypted_header, MCRYPT_MODE_CBC, $outer_iv);
@@ -1765,6 +1783,15 @@ EOT;
 								"ciphertext" => base64_encode($ciphertext)));
 		$cipher_json = base64_encode($encrypted_header_json_object);
 
+		$xml = nul;
+		$xmldata = array("diaspora" => array("encrypted_header" => $cipher_json,
+						"me:env" => array("me:encoding" => "base64url",
+								"me:alg" => "RSA-SHA256",
+								"me:data" => $data,
+								"me:sig" => $sig)));
+		$encrypted_header = xml::from_array($xmldata, $xml, true);
+echo $encrypted_header."\n";
+
 		$encrypted_header = "<encrypted_header>".$cipher_json."</encrypted_header>";
 
 $magic_env = <<< EOT
@@ -1779,6 +1806,7 @@ $magic_env = <<< EOT
   </me:env>
 </diaspora>
 EOT;
+die($magic_env."\n");
 
 		logger("magic_env: ".$magic_env, LOGGER_DATA);
 		return $magic_env;
@@ -1796,7 +1824,7 @@ EOT;
 		return $slap;
 	}
 
-	private function get_signature($owner, $message) {
+	private function signature($owner, $message) {
 		$sigmsg = $message;
 		unset($sigmsg["author_signature"]);
 		unset($sigmsg["parent_author_signature"]);
@@ -1806,7 +1834,7 @@ EOT;
 		return base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
 	}
 
-	private function transmit($owner, $contact, $slap, $public_batch, $queue_run=false, $guid = "") {
+	public static function transmit($owner, $contact, $slap, $public_batch, $queue_run=false, $guid = "") {
 
 		$a = get_app();
 
@@ -1878,7 +1906,7 @@ die($slap);
 
 	public static function send_share($owner,$contact) {
 
-		$message = array("sender_handle" => self::get_my_handle($owner),
+		$message = array("sender_handle" => self::my_handle($owner),
 				"recipient_handle" => $contact["addr"]);
 
 		return self::build_and_transmit($owner, $contact, "request", $message);
@@ -1887,7 +1915,7 @@ die($slap);
 	public static function send_unshare($owner,$contact) {
 
 		$message = array("post_guid" => $owner["guid"],
-				"diaspora_handle" => self::get_my_handle($owner),
+				"diaspora_handle" => self::my_handle($owner),
 				"type" => "Person");
 
 		return self::build_and_transmit($owner, $contact, "retraction", $message);
@@ -1924,7 +1952,7 @@ die($slap);
 				dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA);
 			if ($r) {
 				$ret= array();
-				$ret["root_handle"] = diaspora_handle_from_contact($r[0]["contact-id"]);
+				$ret["root_handle"] = self::handle_from_contact($r[0]["contact-id"]);
 				$ret["root_guid"] = $guid;
 				return($ret);
 			}
@@ -1962,7 +1990,7 @@ die($slap);
 
 	public static function send_status($item, $owner, $contact, $public_batch = false) {
 
-		$myaddr = self::get_my_handle($owner);
+		$myaddr = self::my_handle($owner);
 
 		$public = (($item["private"]) ? "false" : "true");
 
@@ -2029,7 +2057,7 @@ die($slap);
 
 	private function construct_like($item, $owner) {
 
-		$myaddr = self::get_my_handle($owner);
+		$myaddr = self::my_handle($owner);
 
 		$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
 			dbesc($item["thr-parent"]));
@@ -2051,7 +2079,7 @@ die($slap);
 
 	private function construct_comment($item, $owner) {
 
-		$myaddr = self::get_my_handle($owner);
+		$myaddr = self::my_handle($owner);
 
 		$p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1",
 			intval($item["parent"]),
@@ -2085,7 +2113,7 @@ die($slap);
 		if (!$message)
 			return false;
 
-		$message["author_signature"] = self::get_signature($owner, $message);
+		$message["author_signature"] = self::signature($owner, $message);
 
 		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
 	}
@@ -2115,7 +2143,8 @@ die($slap);
 
 		$orig_sign = $r[0];
 
-		// Old way - can be removed for the master branch
+		// Old way - is used by the internal Friendica functions
+		/// @todo Change all signatur storing functions to the new format
 		if ($orig_sign['signed_text'] AND $orig_sign['signature'] AND $orig_sign['signer']) {
 
 			// Split the signed text
@@ -2163,14 +2192,14 @@ die($slap);
 			$signed_text = $message["target_guid"].';'.$message["target_type"];
 			$message["parent_author_signature"] = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
 		} else
-			$message["parent_author_signature"] = self::get_signature($owner, $message);
+			$message["parent_author_signature"] = self::signature($owner, $message);
 
 		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
 	}
 
 	public static function send_retraction($item, $owner, $contact, $public_batch = false) {
 
-		$myaddr = self::get_my_handle($owner);
+		$myaddr = self::my_handle($owner);
 
 		// Check whether the retraction is for a top-level post or whether it's a relayable
 		if ($item["uri"] !== $item["parent-uri"]) {
@@ -2193,7 +2222,7 @@ die($slap);
 
 	public static function send_mail($item, $owner, $contact) {
 
-		$myaddr = self::get_my_handle($owner);
+		$myaddr = self::my_handle($owner);
 
 		$r = q("SELECT * FROM `conv` WHERE `id` = %d AND `uid` = %d LIMIT 1",
 			intval($item["convid"]),
diff --git a/include/xml.php b/include/xml.php
index 9c458dab12..91480dc03b 100644
--- a/include/xml.php
+++ b/include/xml.php
@@ -4,7 +4,7 @@
  *
  */
 class xml {
-	function from_array($array, &$xml) {
+	function from_array($array, &$xml, $remove_header = false) {
 
 		if (!is_object($xml)) {
 			foreach($array as $key => $value) {
@@ -14,7 +14,13 @@ class xml {
 				$dom = dom_import_simplexml($root)->ownerDocument;
 				$dom->formatOutput = true;
 				$xml = $dom;
-				return $dom->saveXML();
+
+				$xml_text = $dom->saveXML();
+
+				if ($remove_header)
+					$xml_text = trim(substr($xml_text, 21));
+
+				return $xml_text;
 			}
 		}
 

From f8f19038bf43aef56aae3898324a3658e2f04c14 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 13 Mar 2016 09:57:44 +0100
Subject: [PATCH 190/273] XML generation is now improved

---
 include/diaspora2.php | 158 +++++++++++++++++++-----------------------
 include/xml.php       |  42 +++++++++--
 2 files changed, 105 insertions(+), 95 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 97d5ecee9f..da772d68bd 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -729,7 +729,6 @@ class diaspora {
 		self::fetch_guid($datarray);
 
 		$message_id = item_store($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"]) {
@@ -1013,7 +1012,6 @@ class diaspora {
 		$datarray["body"] = self::construct_like_body($contact, $parent_item, $guid);
 
 		$message_id = item_store($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"]) {
@@ -1493,7 +1491,6 @@ class diaspora {
 
 		self::fetch_guid($datarray);
 		$message_id = item_store($datarray);
-		// print_r($datarray);
 
 		return $message_id;
 	}
@@ -1662,16 +1659,15 @@ class diaspora {
 
 		self::fetch_guid($datarray);
 		$message_id = item_store($datarray);
-		// print_r($datarray);
 
 		logger("Stored item with message id ".$message_id, LOGGER_DEBUG);
 
 		return $message_id;
 	}
 
-	/*******************************************************************************************
-	 * Here come all the functions that are needed to transmit data with the Diaspora protocol *
-	 *******************************************************************************************/
+	/******************************************************************************************
+	 * Here are all the functions that are needed to transmit data with the Diaspora protocol *
+	 ******************************************************************************************/
 
 	private function my_handle($me) {
 		if ($contact["addr"] != "")
@@ -1701,21 +1697,18 @@ class diaspora {
 		$signature = rsa_sign($signable_data,$prvkey);
 		$sig = base64url_encode($signature);
 
-$magic_env = <<< EOT
-<?xml version='1.0' encoding='UTF-8'?>
-<diaspora xmlns="https://joindiaspora.com/protocol" xmlns:me="http://salmon-protocol.org/ns/magic-env" >
-  <header>
-    <author_id>$handle</author_id>
-  </header>
-  <me:env>
-    <me:encoding>base64url</me:encoding>
-    <me:alg>RSA-SHA256</me:alg>
-    <me:data type="application/xml">$data</me:data>
-    <me:sig>$sig</me:sig>
-  </me:env>
-</diaspora>
-EOT;
-die($magic_env."\n");
+		$xmldata = array("diaspora" => array("header" => array("author_id" => $handle),
+						"me:env" => array("me:encoding" => "base64url",
+								"me:alg" => "RSA-SHA256",
+								"me:data" => $data,
+								"@attributes" => array("type" => "application/xml"),
+								"me:sig" => $sig)));
+
+		$namespaces = array("" => "https://joindiaspora.com/protocol",
+				"me" => "http://salmon-protocol.org/ns/magic-env");
+
+		$magic_env = xml::from_array($xmldata, $xml, false, $namespaces);
+
 		logger("magic_env: ".$magic_env, LOGGER_DATA);
 		return $magic_env;
 	}
@@ -1783,30 +1776,17 @@ die($magic_env."\n");
 								"ciphertext" => base64_encode($ciphertext)));
 		$cipher_json = base64_encode($encrypted_header_json_object);
 
-		$xml = nul;
 		$xmldata = array("diaspora" => array("encrypted_header" => $cipher_json,
 						"me:env" => array("me:encoding" => "base64url",
 								"me:alg" => "RSA-SHA256",
 								"me:data" => $data,
+								"@attributes" => array("type" => "application/xml"),
 								"me:sig" => $sig)));
-		$encrypted_header = xml::from_array($xmldata, $xml, true);
-echo $encrypted_header."\n";
 
-		$encrypted_header = "<encrypted_header>".$cipher_json."</encrypted_header>";
+		$namespaces = array("" => "https://joindiaspora.com/protocol",
+				"me" => "http://salmon-protocol.org/ns/magic-env");
 
-$magic_env = <<< EOT
-<?xml version='1.0' encoding='UTF-8'?>
-<diaspora xmlns="https://joindiaspora.com/protocol" xmlns:me="http://salmon-protocol.org/ns/magic-env" >
-  $encrypted_header
-  <me:env>
-    <me:encoding>base64url</me:encoding>
-    <me:alg>RSA-SHA256</me:alg>
-    <me:data type="application/xml">$data</me:data>
-    <me:sig>$sig</me:sig>
-  </me:env>
-</diaspora>
-EOT;
-die($magic_env."\n");
+		$magic_env = xml::from_array($xmldata, $xml, false, $namespaces);
 
 		logger("magic_env: ".$magic_env, LOGGER_DATA);
 		return $magic_env;
@@ -1896,7 +1876,7 @@ die($magic_env."\n");
 		logger('send guid '.$guid, LOGGER_DEBUG);
 
 		$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);
@@ -2118,7 +2098,49 @@ die($slap);
 		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
 	}
 
-	function send_relay($item, $owner, $contact, $public_batch = false) {
+	private function message_from_signatur($item, $signature) {
+
+		// Split the signed text
+		$signed_parts = explode(";", $signature['signed_text']);
+
+		if ($item["deleted"])
+			$message = array("parent_author_signature" => "",
+					"target_guid" => $signed_parts[0],
+					"target_type" => $signed_parts[1],
+					"sender_handle" => $signature['signer'],
+					"target_author_signature" => $signature['signature']);
+		elseif ($item['verb'] === ACTIVITY_LIKE)
+			$message = array("positive" => $signed_parts[0],
+					"guid" => $signed_parts[1],
+					"target_type" => $signed_parts[2],
+					"parent_guid" => $signed_parts[3],
+					"parent_author_signature" => "",
+					"author_signature" => $signature['signature'],
+					"diaspora_handle" => $signed_parts[4]);
+		else {
+			// Remove the comment guid
+			$guid = array_shift($signed_parts);
+
+			// Remove the parent guid
+			$parent_guid = array_shift($signed_parts);
+
+			// Remove the handle
+			$handle = array_pop($signed_parts);
+
+			// Glue the parts together
+			$text = implode(";", $signed_parts);
+
+			$message = array("guid" => $guid,
+					"parent_guid" => $parent_guid,
+					"parent_author_signature" => "",
+					"author_signature" => $signature['signature'],
+					"text" => implode(";", $signed_parts),
+					"diaspora_handle" => $handle);
+		}
+		return $message;
+	}
+
+	public static function send_relay($item, $owner, $contact, $public_batch = false) {
 
 		if ($item["deleted"]) {
 			$sql_sign_id = "retract_iid";
@@ -2131,62 +2153,22 @@ die($slap);
 			$type = "comment";
 		}
 
-		// fetch the original signature if the relayable was created by a Diaspora
-		// or DFRN user.
+		// fetch the original signature
 
 		$r = q("SELECT `signed_text`, `signature`, `signer` FROM `sign` WHERE `".$sql_sign_id."` = %d LIMIT 1",
-			intval($item["id"])
-		);
+			intval($item["id"]));
 
 		if (!$r)
 			return self::send_followup($item, $owner, $contact, $public_batch);
 
-		$orig_sign = $r[0];
+		$signature = $r[0];
 
 		// Old way - is used by the internal Friendica functions
 		/// @todo Change all signatur storing functions to the new format
-		if ($orig_sign['signed_text'] AND $orig_sign['signature'] AND $orig_sign['signer']) {
-
-			// Split the signed text
-			$signed_parts = explode(";", $orig_sign['signed_text']);
-
-			if ($item["deleted"])
-				$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],
-						"target_type" => $signed_parts[2],
-						"parent_guid" => $signed_parts[3],
-						"parent_author_signature" => "",
-						"author_signature" => $orig_sign['signature'],
-						"diaspora_handle" => $signed_parts[4]);
-			else {
-				// Remove the comment guid
-				$guid = array_shift($signed_parts);
-
-				// Remove the parent guid
-				$parent_guid = array_shift($signed_parts);
-
-				// Remove the handle
-				$handle = array_pop($signed_parts);
-
-				// Glue the parts together
-				$text = implode(";", $signed_parts);
-
-				$message = array("guid" => $guid,
-						"parent_guid" => $parent_guid,
-						"parent_author_signature" => "",
-						"author_signature" => $orig_sign['signature'],
-						"text" => implode(";", $signed_parts),
-						"diaspora_handle" => $handle);
-			}
-		} else { // New way
-			$message = json_decode($orig_sign['signed_text']);
-		}
+		if ($signature['signed_text'] AND $signature['signature'] AND $signature['signer'])
+			$message = self::message_from_signatur($item, $signature);
+		else // New way
+			$message = json_decode($signature['signed_text']);
 
 		if ($item["deleted"]) {
 			$signed_text = $message["target_guid"].';'.$message["target_type"];
diff --git a/include/xml.php b/include/xml.php
index 91480dc03b..c2313648ce 100644
--- a/include/xml.php
+++ b/include/xml.php
@@ -4,12 +4,15 @@
  *
  */
 class xml {
-	function from_array($array, &$xml, $remove_header = false) {
+	function from_array($array, &$xml, $remove_header = false, $namespaces = array(), $root = true) {
 
-		if (!is_object($xml)) {
+		if ($root) {
 			foreach($array as $key => $value) {
+				foreach ($namespaces AS $nskey => $nsvalue)
+					$key .= " xmlns".($nskey == "" ? "":":").$nskey.'="'.$nsvalue.'"';
+
 				$root = new SimpleXMLElement("<".$key."/>");
-				self::from_array($value, $root);
+				self::from_array($value, $root, $remove_header, $namespaces, false);
 
 				$dom = dom_import_simplexml($root)->ownerDocument;
 				$dom->formatOutput = true;
@@ -25,10 +28,35 @@ class xml {
 		}
 
 		foreach($array as $key => $value) {
-			if (!is_array($value) AND !is_numeric($key))
-				$xml->addChild($key, xmlify($value));
-			elseif (is_array($value))
-				self::from_array($value, $xml->addChild($key));
+			if ($key == "@attributes") {
+				if (!isset($element) OR !is_array($value))
+					continue;
+
+				foreach ($value as $attr_key => $attr_value) {
+					$element_parts = explode(":", $attr_key);
+					if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]]))
+						$namespace = $namespaces[$element_parts[0]];
+					else
+						$namespace = NULL;
+
+					$element->addAttribute ($attr_key, $attr_value, $namespace);
+				}
+
+				continue;
+			}
+
+			$element_parts = explode(":", $key);
+			if ((count($element_parts) > 1) AND isset($namespaces[$element_parts[0]]))
+				$namespace = $namespaces[$element_parts[0]];
+			else
+				$namespace = NULL;
+
+			if (!is_array($value))
+				$element = $xml->addChild($key, xmlify($value), $namespace);
+			elseif (is_array($value)) {
+				$element = $xml->addChild($key, NULL, $namespace);
+				self::from_array($value, $element, $remove_header, $namespaces, false);
+			}
 		}
 	}
 

From 99d5f8afc6df764679312a97fb2426b40ea20566 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 13 Mar 2016 13:04:12 +0100
Subject: [PATCH 191/273] The display contained bad sql queries

---
 mod/display.php | 115 ++++++++++++++++++++++++------------------------
 1 file changed, 58 insertions(+), 57 deletions(-)

diff --git a/mod/display.php b/mod/display.php
index 97261e267d..e53f9e2066 100644
--- a/mod/display.php
+++ b/mod/display.php
@@ -17,7 +17,7 @@ function display_init(&$a) {
 		// Does the local user have this item?
 		if (local_user()) {
 			$r = q("SELECT `id`, `parent`, `author-name`, `author-link`, `author-avatar`, `network`, `body`, `uid` FROM `item`
-				WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 and `item`.`moderated` = 0
+				WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
 					AND `guid` = '%s' AND `uid` = %d", dbesc($a->argv[1]), local_user());
 			if (count($r)) {
 				$nick = $a->user["nickname"];
@@ -30,12 +30,12 @@ function display_init(&$a) {
 			$r = q("SELECT `user`.`nickname`, `item`.`id`, `item`.`parent`, `item`.`author-name`,
 				`item`.`author-link`, `item`.`author-avatar`, `item`.`network`, `item`.`uid`, `item`.`body`
 				FROM `item` INNER JOIN `user` ON `user`.`uid` = `item`.`uid`
-				WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 and `item`.`moderated` = 0
+				WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
 					AND `item`.`allow_cid` = ''  AND `item`.`allow_gid` = ''
 					AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
-					AND `item`.`private` = 0 AND NOT `user`.`hidewall`
+					AND NOT `item`.`private` AND NOT `user`.`hidewall`
 					AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
-				//	AND `item`.`private` = 0 AND `item`.`wall` = 1
+				//	AND NOT `item`.`private` AND `item`.`wall`
 			if (count($r)) {
 				$nick = $r[0]["nickname"];
 				$itemuid = $r[0]["uid"];
@@ -46,17 +46,17 @@ function display_init(&$a) {
 		if ($nick == "") {
 			$r = q("SELECT `item`.`id`, `item`.`parent`, `item`.`author-name`,
 				`item`.`author-link`, `item`.`author-avatar`, `item`.`network`, `item`.`uid`, `item`.`body`
-				FROM `item` WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 and `item`.`moderated` = 0
+				FROM `item` WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
 					AND `item`.`allow_cid` = ''  AND `item`.`allow_gid` = ''
 					AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
-					AND `item`.`private` = 0 AND `item`.`uid` = 0
+					AND NOT `item`.`private` AND `item`.`uid` = 0
 					AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
-				//	AND `item`.`private` = 0 AND `item`.`wall` = 1
+				//	AND NOT `item`.`private` AND `item`.`wall`
 		}
 		if (count($r)) {
 			if ($r[0]["id"] != $r[0]["parent"])
 				$r = q("SELECT `id`, `author-name`, `author-link`, `author-avatar`, `network`, `body`, `uid` FROM `item`
-					WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 and `item`.`moderated` = 0
+					WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
 						AND `id` = %d", $r[0]["parent"]);
 
 			$profiledata = display_fetchauthor($a, $r[0]);
@@ -67,7 +67,7 @@ function display_init(&$a) {
 				if (($nickname != $a->user["nickname"])) {
 					$r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `contact`.`avatar-date` AS picdate, `user`.* FROM `profile`
 						INNER JOIN `contact` on `contact`.`uid` = `profile`.`uid` INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
-						WHERE `user`.`nickname` = '%s' AND `profile`.`is-default` = 1 and `contact`.`self` = 1 LIMIT 1",
+						WHERE `user`.`nickname` = '%s' AND `profile`.`is-default` AND `contact`.`self` LIMIT 1",
 						dbesc($nickname)
 					);
 					if (count($r))
@@ -120,27 +120,27 @@ function display_fetchauthor($a, $item) {
 	}
 
 	if (!$skip) {
-	        $author = "";
-	        preg_match("/author='(.*?)'/ism", $attributes, $matches);
-	        if ($matches[1] != "")
+		$author = "";
+		preg_match("/author='(.*?)'/ism", $attributes, $matches);
+		if ($matches[1] != "")
 			$profiledata["name"] = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
 
-	        preg_match('/author="(.*?)"/ism', $attributes, $matches);
-	        if ($matches[1] != "")
+		preg_match('/author="(.*?)"/ism', $attributes, $matches);
+		if ($matches[1] != "")
 			$profiledata["name"] = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
 
-	        $profile = "";
-	        preg_match("/profile='(.*?)'/ism", $attributes, $matches);
-	        if ($matches[1] != "")
+		$profile = "";
+		preg_match("/profile='(.*?)'/ism", $attributes, $matches);
+		if ($matches[1] != "")
 			$profiledata["url"] = $matches[1];
 
-	        preg_match('/profile="(.*?)"/ism', $attributes, $matches);
-	        if ($matches[1] != "")
+		preg_match('/profile="(.*?)"/ism', $attributes, $matches);
+		if ($matches[1] != "")
 			$profiledata["url"] = $matches[1];
 
-	        $avatar = "";
-	        preg_match("/avatar='(.*?)'/ism", $attributes, $matches);
-	        if ($matches[1] != "")
+		$avatar = "";
+		preg_match("/avatar='(.*?)'/ism", $attributes, $matches);
+		if ($matches[1] != "")
 			$profiledata["photo"] = $matches[1];
 
 		preg_match('/avatar="(.*?)"/ism', $attributes, $matches);
@@ -257,7 +257,7 @@ function display_content(&$a, $update = 0) {
 
 			if (local_user()) {
 				$r = q("SELECT `id` FROM `item`
-					WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 and `item`.`moderated` = 0
+					WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
 						AND `guid` = '%s' AND `uid` = %d", dbesc($a->argv[1]), local_user());
 				if (count($r)) {
 					$item_id = $r[0]["id"];
@@ -267,12 +267,12 @@ function display_content(&$a, $update = 0) {
 
 			if ($nick == "") {
 				$r = q("SELECT `user`.`nickname`, `item`.`id` FROM `item` INNER JOIN `user` ON `user`.`uid` = `item`.`uid`
-					WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 and `item`.`moderated` = 0
+					WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
 						AND `item`.`allow_cid` = ''  AND `item`.`allow_gid` = ''
 						AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
-						AND `item`.`private` = 0  AND NOT `user`.`hidewall`
+						AND NOT `item`.`private` AND NOT `user`.`hidewall`
 						AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
-					//	AND `item`.`private` = 0 AND `item`.`wall` = 1
+					//	AND NOT `item`.`private` AND `item`.`wall`
 				if (count($r)) {
 					$item_id = $r[0]["id"];
 					$nick = $r[0]["nickname"];
@@ -280,12 +280,12 @@ function display_content(&$a, $update = 0) {
 			}
 			if ($nick == "") {
 				$r = q("SELECT `item`.`id` FROM `item`
-					WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 and `item`.`moderated` = 0
+					WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
 						AND `item`.`allow_cid` = ''  AND `item`.`allow_gid` = ''
 						AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
-						AND `item`.`private` = 0  AND `item`.`uid` = 0
+						AND NOT `item`.`private` AND `item`.`uid` = 0
 						AND `item`.`guid` = '%s'", dbesc($a->argv[1]));
-					//	AND `item`.`private` = 0 AND `item`.`wall` = 1
+					//	AND NOT `item`.`private` AND `item`.`wall`
 				if (count($r)) {
 					$item_id = $r[0]["id"];
 				}
@@ -293,12 +293,22 @@ function display_content(&$a, $update = 0) {
 		}
 	}
 
-	if(! $item_id) {
+	if ($item_id AND !is_numeric($item_id)) {
+		$r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc($item_id), intval($a->profile['uid']));
+		if ($r)
+			$item_id = $r[0]["id"];
+		else
+			$item_id = false;
+	}
+
+	if (!$item_id) {
 		$a->error = 404;
-		notice( t('Item not found.') . EOL);
+		notice(t('Item not found.').EOL);
 		return;
 	}
 
+
 	$groups = array();
 
 	$contact = null;
@@ -334,7 +344,7 @@ function display_content(&$a, $update = 0) {
 		}
 	}
 
-	$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1",
+	$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1",
 		intval($a->profile['uid'])
 	);
 	if(count($r))
@@ -367,62 +377,53 @@ function display_content(&$a, $update = 0) {
 
 	$sql_extra = item_permissions_sql($a->profile['uid'],$remote_contact,$groups);
 
-	//	        AND `item`.`parent` = ( SELECT `parent` FROM `item` FORCE INDEX (PRIMARY, `uri`) WHERE ( `id` = '%s' OR `uri` = '%s' ))
-
 	if($update) {
 
-		$r = q("SELECT id FROM item WHERE item.uid = %d
-		        AND `item`.`parent` = (SELECT `parent` FROM `item` WHERE (`id` = '%s' OR `uri` = '%s'))
-		        $sql_extra AND unseen = 1",
-		        intval($a->profile['uid']),
-		        dbesc($item_id),
-		        dbesc($item_id)
+		$r = q("SELECT `id` FROM `item` WHERE `item`.`uid` = %d
+			AND `item`.`parent` = (SELECT `parent` FROM `item` WHERE `id` = %d)
+			$sql_extra AND `unseen`",
+			intval($a->profile['uid']),
+			intval($item_id)
 		);
 
 		if(!$r)
 			return '';
 	}
 
-	//	AND `item`.`parent` = ( SELECT `parent` FROM `item` FORCE INDEX (PRIMARY, `uri`) WHERE ( `id` = '%s' OR `uri` = '%s' )
-
 	$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,  `item`.`network` AS `item_network`,
 		`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
 		`contact`.`network`, `contact`.`thumb`, `contact`.`self`, `contact`.`writable`,
 		`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
 		FROM `item` INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
-		AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
-		WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
-		and `item`.`moderated` = 0
-		AND `item`.`parent` = (SELECT `parent` FROM `item` WHERE (`id` = '%s' OR `uri` = '%s')
-		AND uid = %d)
+		AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
+		WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted`
+		AND NOT `item`.`moderated`
+		AND `item`.`parent` = (SELECT `parent` FROM `item` WHERE `id` = %d)
 		$sql_extra
 		ORDER BY `parent` DESC, `gravity` ASC, `id` ASC",
 		intval($a->profile['uid']),
-		dbesc($item_id),
-		dbesc($item_id),
-		intval($a->profile['uid'])
+		intval($item_id)
 	);
 
 	if(!$r && local_user()) {
 		// Check if this is another person's link to a post that we have
 		$r = q("SELECT `item`.uri FROM `item`
-			WHERE (`item`.`id` = '%s' OR `item`.`uri` = '%s' )
+			WHERE (`item`.`id` = %d OR `item`.`uri` = '%s')
 			LIMIT 1",
-			dbesc($item_id),
+			intval($item_id),
 			dbesc($item_id)
 		);
 		if($r) {
 			$item_uri = $r[0]['uri'];
-			//	AND `item`.`parent` = ( SELECT `parent` FROM `item` FORCE INDEX (PRIMARY, `uri`) WHERE `uri` = '%s' AND uid = %d )
 
 			$r = q("SELECT `item`.*, `item`.`id` AS `item_id`,  `item`.`network` AS `item_network`,
 				`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
 				`contact`.`network`, `contact`.`thumb`, `contact`.`self`, `contact`.`writable`,
 				`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
 				FROM `item` INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
-				AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
-				WHERE `item`.`uid` = %d AND `item`.`visible` = 1 AND `item`.`deleted` = 0
-				and `item`.`moderated` = 0
+				AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
+				WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted`
+				AND NOT `item`.`moderated`
 				AND `item`.`parent` = (SELECT `parent` FROM `item` WHERE `uri` = '%s' AND uid = %d)
 				ORDER BY `parent` DESC, `gravity` ASC, `id` ASC ",
 				intval(local_user()),
@@ -437,7 +438,7 @@ function display_content(&$a, $update = 0) {
 
 		if((local_user()) && (local_user() == $a->profile['uid'])) {
 			q("UPDATE `item` SET `unseen` = 0
-				WHERE `parent` = %d AND `unseen` = 1",
+				WHERE `parent` = %d AND `unseen`",
 				intval($r[0]['parent'])
 			);
 		}

From 07818a65536c1cb6373f4494245c583853e0fa95 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 13 Mar 2016 16:14:51 +0100
Subject: [PATCH 192/273] Decode function is now there as well.

---
 include/diaspora.php  |  15 ++--
 include/diaspora2.php | 168 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 174 insertions(+), 9 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 78ba520790..2b85befa8c 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -111,18 +111,18 @@ function diaspora_dispatch($importer,$msg,$attempt=1) {
 		$ret = diaspora_reshare($importer,$xmlbase->reshare,$msg);
 	}
 	elseif($xmlbase->retraction) {
-		$tempfile = tempnam(get_temppath(), "diaspora-retraction");
-		file_put_contents($tempfile, json_encode($data));
+		//$tempfile = tempnam(get_temppath(), "diaspora-retraction");
+		//file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_retraction($importer,$xmlbase->retraction,$msg);
 	}
 	elseif($xmlbase->signed_retraction) {
-		$tempfile = tempnam(get_temppath(), "diaspora-signed_retraction");
-		file_put_contents($tempfile, json_encode($data));
+		//$tempfile = tempnam(get_temppath(), "diaspora-signed_retraction");
+		//file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_signed_retraction($importer,$xmlbase->signed_retraction,$msg);
 	}
 	elseif($xmlbase->relayable_retraction) {
-		$tempfile = tempnam(get_temppath(), "diaspora-relayable_retraction");
-		file_put_contents($tempfile, json_encode($data));
+		//$tempfile = tempnam(get_temppath(), "diaspora-relayable_retraction");
+		//file_put_contents($tempfile, json_encode($data));
 		$ret = diaspora_signed_retraction($importer,$xmlbase->relayable_retraction,$msg);
 	}
 	elseif($xmlbase->photo) {
@@ -468,6 +468,9 @@ EOT;
 
 function diaspora_decode($importer,$xml) {
 
+	$tempfile = tempnam(get_temppath(), "diaspora-decode");
+	file_put_contents($tempfile, json_encode(array("importer" => $importer, "xml" => $xml)));
+
 	$public = false;
 	$basedom = parse_xml_string($xml);
 
diff --git a/include/diaspora2.php b/include/diaspora2.php
index da772d68bd..081eaf153a 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -64,6 +64,168 @@ class diaspora {
 		return $relay;
 	}
 
+	function repair_signature($signature, $handle = "", $level = 1) {
+
+		if ($signature == "")
+			return ($signature);
+
+		if (base64_encode(base64_decode(base64_decode($signature))) == base64_decode($signature)) {
+			$signature = base64_decode($signature);
+			logger("Repaired double encoded signature from Diaspora/Hubzilla handle ".$handle." - level ".$level, LOGGER_DEBUG);
+
+			// Do a recursive call to be able to fix even multiple levels
+			if ($level < 10)
+				$signature = self::repair_signature($signature, $handle, ++$level);
+		}
+
+		return($signature);
+	}
+
+	/**
+	 * @brief: Decodes incoming Diaspora message
+	 *
+	 * @param array $importer from user table
+	 * @param string $xml urldecoded Diaspora salmon
+	 *
+	 * @return array
+	 * 'message' -> decoded Diaspora XML message
+	 * 'author' -> author diaspora handle
+	 * 'key' -> author public key (converted to pkcs#8)
+	 */
+	function decode($importer, $xml) {
+
+		$public = false;
+		$basedom = parse_xml_string($xml);
+
+		if (!is_object($basedom))
+			return false;
+
+		$children = $basedom->children('https://joindiaspora.com/protocol');
+
+		if($children->header) {
+			$public = true;
+			$author_link = str_replace('acct:','',$children->header->author_id);
+		} else {
+
+			$encrypted_header = json_decode(base64_decode($children->encrypted_header));
+
+			$encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key);
+			$ciphertext = base64_decode($encrypted_header->ciphertext);
+
+			$outer_key_bundle = '';
+			openssl_private_decrypt($encrypted_aes_key_bundle,$outer_key_bundle,$importer['prvkey']);
+
+			$j_outer_key_bundle = json_decode($outer_key_bundle);
+
+			$outer_iv = base64_decode($j_outer_key_bundle->iv);
+			$outer_key = base64_decode($j_outer_key_bundle->key);
+
+			$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $outer_key, $ciphertext, MCRYPT_MODE_CBC, $outer_iv);
+
+
+			$decrypted = pkcs5_unpad($decrypted);
+
+			/**
+			 * $decrypted now contains something like
+			 *
+			 *  <decrypted_header>
+			 *     <iv>8e+G2+ET8l5BPuW0sVTnQw==</iv>
+			 *     <aes_key>UvSMb4puPeB14STkcDWq+4QE302Edu15oaprAQSkLKU=</aes_key>
+			 *     <author_id>galaxor@diaspora.priateship.org</author_id>
+			 *  </decrypted_header>
+			 */
+
+			logger('decrypted: '.$decrypted, LOGGER_DEBUG);
+			$idom = parse_xml_string($decrypted,false);
+
+			$inner_iv = base64_decode($idom->iv);
+			$inner_aes_key = base64_decode($idom->aes_key);
+
+			$author_link = str_replace('acct:','',$idom->author_id);
+		}
+
+		$dom = $basedom->children(NAMESPACE_SALMON_ME);
+
+		// figure out where in the DOM tree our data is hiding
+
+		if($dom->provenance->data)
+			$base = $dom->provenance;
+		elseif($dom->env->data)
+			$base = $dom->env;
+		elseif($dom->data)
+			$base = $dom;
+
+		if (!$base) {
+			logger('unable to locate salmon data in xml');
+			http_status_exit(400);
+		}
+
+
+		// Stash the signature away for now. We have to find their key or it won't be good for anything.
+		$signature = base64url_decode($base->sig);
+
+		// unpack the  data
+
+		// strip whitespace so our data element will return to one big base64 blob
+		$data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$base->data);
+
+
+		// stash away some other stuff for later
+
+		$type = $base->data[0]->attributes()->type[0];
+		$keyhash = $base->sig[0]->attributes()->keyhash[0];
+		$encoding = $base->encoding;
+		$alg = $base->alg;
+
+
+		$signed_data = $data.'.'.base64url_encode($type).'.'.base64url_encode($encoding).'.'.base64url_encode($alg);
+
+
+		// decode the data
+		$data = base64url_decode($data);
+
+
+		if($public)
+			$inner_decrypted = $data;
+		else {
+
+			// Decode the encrypted blob
+
+			$inner_encrypted = base64_decode($data);
+			$inner_decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $inner_encrypted, MCRYPT_MODE_CBC, $inner_iv);
+			$inner_decrypted = pkcs5_unpad($inner_decrypted);
+		}
+
+		if (!$author_link) {
+			logger('Could not retrieve author URI.');
+			http_status_exit(400);
+		}
+		// Once we have the author URI, go to the web and try to find their public key
+		// (first this will look it up locally if it is in the fcontact cache)
+		// This will also convert diaspora public key from pkcs#1 to pkcs#8
+
+		logger('Fetching key for '.$author_link);
+		$key = self::key($author_link);
+
+		if (!$key) {
+			logger('Could not retrieve author key.');
+			http_status_exit(400);
+		}
+
+		$verify = rsa_verify($signed_data,$signature,$key);
+
+		if (!$verify) {
+			logger('Message did not verify. Discarding.');
+			http_status_exit(400);
+		}
+
+		logger('Message verified.');
+
+		return array('message' => $inner_decrypted, 'author' => $author_link, 'key' => $key);
+
+	}
+
+
 	/**
 	 * @brief Dispatches public messages and find the fitting receivers
 	 *
@@ -1287,7 +1449,7 @@ class diaspora {
 		$ret = self::person_by_handle($author);
 
 		if (!$ret || ($ret["network"] != NETWORK_DIASPORA)) {
-			logger("Cannot resolve diaspora handle ".$author ." for ".$recipient);
+			logger("Cannot resolve diaspora handle ".$author." for ".$recipient);
 			return false;
 		}
 
@@ -1854,7 +2016,7 @@ class diaspora {
 				dbesc($slap),
 				intval($public_batch)
 			);
-			if(count($r)) {
+			if($r) {
 				logger("add_to_queue ignored - identical item already in queue");
 			} else {
 				// queue message for redelivery
@@ -2211,7 +2373,7 @@ class diaspora {
 			intval($item["uid"])
 		);
 
-		if (!count($r)) {
+		if (!$r) {
 			logger("conversation not found.");
 			return;
 		}

From 2841aa0281442e7a5570c122d5f3d9ab3a6504a7 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 13 Mar 2016 19:47:02 +0100
Subject: [PATCH 193/273] New implementation is now live.

---
 include/delivery.php  | 182 +++++++++++++++++++++---------------------
 include/diaspora.php  |   1 +
 include/diaspora2.php |  49 ++++++++++--
 mod/receive.php       |  14 ++--
 4 files changed, 144 insertions(+), 102 deletions(-)

diff --git a/include/delivery.php b/include/delivery.php
index e5ca0946b3..d184fe12e1 100644
--- a/include/delivery.php
+++ b/include/delivery.php
@@ -10,11 +10,11 @@ require_once("include/dfrn.php");
 function delivery_run(&$argv, &$argc){
 	global $a, $db;
 
-	if(is_null($a)){
+	if (is_null($a)){
 		$a = new App;
 	}
 
-	if(is_null($db)) {
+	if (is_null($db)) {
 		@include(".htconfig.php");
 		require_once("include/dba.php");
 		$db = new dba($db_host, $db_user, $db_pass, $db_data);
@@ -32,12 +32,12 @@ function delivery_run(&$argv, &$argc){
 
 	load_hooks();
 
-	if($argc < 3)
+	if ($argc < 3)
 		return;
 
 	$a->set_baseurl(get_config('system','url'));
 
-	logger('delivery: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
+	logger('delivery: invoked: '. print_r($argv,true), LOGGER_DEBUG);
 
 	$cmd        = $argv[1];
 	$item_id    = intval($argv[2]);
@@ -53,7 +53,7 @@ function delivery_run(&$argv, &$argc){
 			dbesc($item_id),
 			dbesc($contact_id)
 		);
-		if(! count($r)) {
+		if (!count($r)) {
 			continue;
 		}
 
@@ -68,7 +68,7 @@ function delivery_run(&$argv, &$argc){
 			dbesc($contact_id)
 		);
 
-		if((! $item_id) || (! $contact_id))
+		if (!$item_id || !$contact_id)
 			continue;
 
 		$expire = false;
@@ -84,20 +84,20 @@ function delivery_run(&$argv, &$argc){
 
 		$recipients[] = $contact_id;
 
-		if($cmd === 'mail') {
+		if ($cmd === 'mail') {
 			$normal_mode = false;
 			$mail = true;
 			$message = q("SELECT * FROM `mail` WHERE `id` = %d LIMIT 1",
 					intval($item_id)
 			);
-			if(! count($message)){
+			if (!count($message)){
 				return;
 			}
 			$uid = $message[0]['uid'];
 			$recipients[] = $message[0]['contact-id'];
 			$item = $message[0];
 		}
-		elseif($cmd === 'expire') {
+		elseif ($cmd === 'expire') {
 			$normal_mode = false;
 			$expire = true;
 			$items = q("SELECT * FROM `item` WHERE `uid` = %d AND `wall` = 1
@@ -106,22 +106,22 @@ function delivery_run(&$argv, &$argc){
 			);
 			$uid = $item_id;
 			$item_id = 0;
-			if(! count($items))
+			if (!count($items))
 				continue;
 		}
-		elseif($cmd === 'suggest') {
+		elseif ($cmd === 'suggest') {
 			$normal_mode = false;
 			$fsuggest = true;
 
 			$suggest = q("SELECT * FROM `fsuggest` WHERE `id` = %d LIMIT 1",
 				intval($item_id)
 			);
-			if(! count($suggest))
+			if (!count($suggest))
 				return;
 			$uid = $suggest[0]['uid'];
 			$recipients[] = $suggest[0]['cid'];
 			$item = $suggest[0];
-		} elseif($cmd === 'relocate') {
+		} elseif ($cmd === 'relocate') {
 			$normal_mode = false;
 			$relocate = true;
 			$uid = $item_id;
@@ -131,7 +131,7 @@ function delivery_run(&$argv, &$argc){
 				intval($item_id)
 			);
 
-			if((! count($r)) || (! intval($r[0]['parent']))) {
+			if ((!count($r)) || (!intval($r[0]['parent']))) {
 				continue;
 			}
 
@@ -145,32 +145,32 @@ function delivery_run(&$argv, &$argc){
 				intval($parent_id)
 			);
 
-			if(! count($items)) {
+			if (!count($items)) {
 				continue;
 			}
 
 			$icontacts = null;
 			$contacts_arr = array();
 			foreach($items as $item)
-				if(! in_array($item['contact-id'],$contacts_arr))
+				if (!in_array($item['contact-id'],$contacts_arr))
 					$contacts_arr[] = intval($item['contact-id']);
-			if(count($contacts_arr)) {
+			if (count($contacts_arr)) {
 				$str_contacts = implode(',',$contacts_arr);
 				$icontacts = q("SELECT * FROM `contact`
 					WHERE `id` IN ( $str_contacts ) "
 				);
 			}
-			if( ! ($icontacts && count($icontacts)))
+			if ( !($icontacts && count($icontacts)))
 				continue;
 
 			// avoid race condition with deleting entries
 
-			if($items[0]['deleted']) {
+			if ($items[0]['deleted']) {
 				foreach($items as $item)
 					$item['deleted'] = 1;
 			}
 
-			if((count($items) == 1) && ($items[0]['uri'] === $items[0]['parent-uri'])) {
+			if ((count($items) == 1) && ($items[0]['uri'] === $items[0]['parent-uri'])) {
 				logger('delivery: top level post');
 				$top_level = true;
 			}
@@ -184,7 +184,7 @@ function delivery_run(&$argv, &$argc){
 			intval($uid)
 		);
 
-		if(! count($r))
+		if (!count($r))
 			continue;
 
 		$owner = $r[0];
@@ -193,7 +193,7 @@ function delivery_run(&$argv, &$argc){
 
 		$public_message = true;
 
-		if(! ($mail || $fsuggest || $relocate)) {
+		if (!($mail || $fsuggest || $relocate)) {
 			require_once('include/group.php');
 
 			$parent = $items[0];
@@ -217,7 +217,7 @@ function delivery_run(&$argv, &$argc){
 
 
 			$localhost = $a->get_hostname();
-			if(strpos($localhost,':'))
+			if (strpos($localhost,':'))
 				$localhost = substr($localhost,0,strpos($localhost,':'));
 
 			/**
@@ -230,17 +230,17 @@ function delivery_run(&$argv, &$argc){
 
 			$relay_to_owner = false;
 
-			if((! $top_level) && ($parent['wall'] == 0) && (! $expire) && (stristr($target_item['uri'],$localhost))) {
+			if (!$top_level && ($parent['wall'] == 0) && !$expire && stristr($target_item['uri'],$localhost)) {
 				$relay_to_owner = true;
 			}
 
-			if($relay_to_owner) {
+			if ($relay_to_owner) {
 				logger('followup '.$target_item["guid"], LOGGER_DEBUG);
 				// local followup to remote post
 				$followup = true;
 			}
 
-			if((strlen($parent['allow_cid']))
+			if ((strlen($parent['allow_cid']))
 				|| (strlen($parent['allow_gid']))
 				|| (strlen($parent['deny_cid']))
 				|| (strlen($parent['deny_gid']))) {
@@ -253,10 +253,10 @@ function delivery_run(&$argv, &$argc){
 			intval($contact_id)
 		);
 
-		if(count($r))
+		if (count($r))
 			$contact = $r[0];
 
-		if($contact['self'])
+		if ($contact['self'])
 			continue;
 
 		$deliver_status = 0;
@@ -266,7 +266,7 @@ function delivery_run(&$argv, &$argc){
 		switch($contact['network']) {
 
 			case NETWORK_DFRN:
-				logger('notifier: '.$target_item["guid"].' dfrndelivery: ' . $contact['name']);
+				logger('notifier: '.$target_item["guid"].' dfrndelivery: '.$contact['name']);
 
 				if ($mail) {
 					$item['body'] = fix_private_photos($item['body'],$owner['uid'],null,$message[0]['contact-id']);
@@ -276,13 +276,13 @@ function delivery_run(&$argv, &$argc){
 					q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item['id']));
 				} elseif ($relocate)
 					$atom = dfrn::relocate($owner, $uid);
-				elseif($followup) {
+				elseif ($followup) {
 					$msgitems = array();
 					foreach($items as $item) {  // there is only one item
-						if(!$item['parent'])
+						if (!$item['parent'])
 							continue;
-						if($item['id'] == $item_id) {
-							logger('followup: item: ' . print_r($item,true), LOGGER_DATA);
+						if ($item['id'] == $item_id) {
+							logger('followup: item: '. print_r($item,true), LOGGER_DATA);
 							$msgitems[] = $item;
 						}
 					}
@@ -290,19 +290,19 @@ function delivery_run(&$argv, &$argc){
 				} else {
 					$msgitems = array();
 					foreach($items as $item) {
-						if(!$item['parent'])
+						if (!$item['parent'])
 							continue;
 
 						// private emails may be in included in public conversations. Filter them.
-						if(($public_message) && $item['private'])
+						if ($public_message && $item['private'])
 							continue;
 
 						$item_contact = get_item_contact($item,$icontacts);
-						if(!$item_contact)
+						if (!$item_contact)
 							continue;
 
-						if($normal_mode) {
-							if($item_id == $item['id'] || $item['id'] == $item['parent']) {
+						if ($normal_mode) {
+							if ($item_id == $item['id'] || $item['id'] == $item['parent']) {
 								$item["entry:comment-allow"] = true;
 								$item["entry:cid"] = (($top_level) ? $contact['id'] : 0);
 								$msgitems[] = $item;
@@ -317,15 +317,15 @@ function delivery_run(&$argv, &$argc){
 
 				logger('notifier entry: '.$contact["url"].' '.$target_item["guid"].' entry: '.$atom, LOGGER_DEBUG);
 
-				logger('notifier: ' . $atom, LOGGER_DATA);
+				logger('notifier: '.$atom, LOGGER_DATA);
 				$basepath =  implode('/', array_slice(explode('/',$contact['url']),0,3));
 
 				// perform local delivery if we are on the same site
 
-				if(link_compare($basepath,$a->get_baseurl())) {
+				if (link_compare($basepath,$a->get_baseurl())) {
 
 					$nickname = basename($contact['url']);
-					if($contact['issued-id'])
+					if ($contact['issued-id'])
 						$sql_extra = sprintf(" AND `dfrn-id` = '%s' ", dbesc($contact['issued-id']));
 					else
 						$sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($contact['dfrn-id']));
@@ -347,10 +347,10 @@ function delivery_run(&$argv, &$argc){
 						dbesc($nickname)
 					);
 
-					if($x && count($x)) {
+					if ($x && count($x)) {
 						$write_flag = ((($x[0]['rel']) && ($x[0]['rel'] != CONTACT_IS_SHARING)) ? true : false);
-						if((($owner['page-flags'] == PAGE_COMMUNITY) || ($write_flag)) && (! $x[0]['writable'])) {
-							q("update contact set writable = 1 where id = %d",
+						if ((($owner['page-flags'] == PAGE_COMMUNITY) || $write_flag) && !$x[0]['writable']) {
+							q("UPDATE `contact` SET `writable` = 1 WHERE `id` = %d",
 								intval($x[0]['id'])
 							);
 							$x[0]['writable'] = 1;
@@ -370,14 +370,14 @@ function delivery_run(&$argv, &$argc){
 					}
 				}
 
-				if(! was_recently_delayed($contact['id']))
+				if (!was_recently_delayed($contact['id']))
 					$deliver_status = dfrn::deliver($owner,$contact,$atom);
 				else
 					$deliver_status = (-1);
 
 				logger('notifier: dfrn_delivery to '.$contact["url"].' with guid '.$target_item["guid"].' returns '.$deliver_status);
 
-				if($deliver_status == (-1)) {
+				if ($deliver_status == (-1)) {
 					logger('notifier: delivery failed: queuing message');
 					add_to_queue($contact['id'],NETWORK_DFRN,$atom);
 				}
@@ -385,9 +385,9 @@ function delivery_run(&$argv, &$argc){
 
 			case NETWORK_OSTATUS:
 				// Do not send to otatus if we are not configured to send to public networks
-				if($owner['prvnets'])
+				if ($owner['prvnets'])
 					break;
-				if(get_config('system','ostatus_disabled') || get_config('system','dfrn_only'))
+				if (get_config('system','ostatus_disabled') || get_config('system','dfrn_only'))
 					break;
 
 				// There is currently no code here to distribute anything to OStatus.
@@ -397,67 +397,67 @@ function delivery_run(&$argv, &$argc){
 			case NETWORK_MAIL:
 			case NETWORK_MAIL2:
 
-				if(get_config('system','dfrn_only'))
+				if (get_config('system','dfrn_only'))
 					break;
 				// WARNING: does not currently convert to RFC2047 header encodings, etc.
 
 				$addr = $contact['addr'];
-				if(! strlen($addr))
+				if (!strlen($addr))
 					break;
 
-				if($cmd === 'wall-new' || $cmd === 'comment-new') {
+				if ($cmd === 'wall-new' || $cmd === 'comment-new') {
 
 					$it = null;
-					if($cmd === 'wall-new')
+					if ($cmd === 'wall-new')
 						$it = $items[0];
 					else {
 						$r = q("SELECT * FROM `item` WHERE `id` = %d AND `uid` = %d LIMIT 1",
 							intval($argv[2]),
 							intval($uid)
 						);
-						if(count($r))
+						if (count($r))
 							$it = $r[0];
 					}
-					if(! $it)
+					if (!$it)
 						break;
 
 
 					$local_user = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1",
 						intval($uid)
 					);
-					if(! count($local_user))
+					if (!count($local_user))
 						break;
 
 					$reply_to = '';
 					$r1 = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1",
 						intval($uid)
 					);
-					if($r1 && $r1[0]['reply_to'])
+					if ($r1 && $r1[0]['reply_to'])
 						$reply_to = $r1[0]['reply_to'];
 
 					$subject  = (($it['title']) ? email_header_encode($it['title'],'UTF-8') : t("\x28no subject\x29")) ;
 
 					// only expose our real email address to true friends
 
-					if(($contact['rel'] == CONTACT_IS_FRIEND) && (! $contact['blocked'])) {
-						if($reply_to) {
+					if (($contact['rel'] == CONTACT_IS_FRIEND) && !$contact['blocked']) {
+						if ($reply_to) {
 							$headers  = 'From: '.email_header_encode($local_user[0]['username'],'UTF-8').' <'.$reply_to.'>'."\n";
 							$headers .= 'Sender: '.$local_user[0]['email']."\n";
 						} else
 							$headers  = 'From: '.email_header_encode($local_user[0]['username'],'UTF-8').' <'.$local_user[0]['email'].'>'."\n";
 					} else
-						$headers  = 'From: ' . email_header_encode($local_user[0]['username'],'UTF-8') . ' <' . t('noreply') . '@' . $a->get_hostname() . '>' . "\n";
+						$headers  = 'From: '. email_header_encode($local_user[0]['username'],'UTF-8') .' <'. t('noreply') .'@'.$a->get_hostname() .'>'. "\n";
 
-					//if($reply_to)
-					//	$headers .= 'Reply-to: ' . $reply_to . "\n";
+					//if ($reply_to)
+					//	$headers .= 'Reply-to: '.$reply_to . "\n";
 
-					$headers .= 'Message-Id: <' . iri2msgid($it['uri']). '>' . "\n";
+					$headers .= 'Message-Id: <'. iri2msgid($it['uri']).'>'. "\n";
 
 					//logger("Mail: uri: ".$it['uri']." parent-uri ".$it['parent-uri'], LOGGER_DEBUG);
 					//logger("Mail: Data: ".print_r($it, true), LOGGER_DEBUG);
 					//logger("Mail: Data: ".print_r($it, true), LOGGER_DATA);
 
-					if($it['uri'] !== $it['parent-uri']) {
+					if ($it['uri'] !== $it['parent-uri']) {
 						$headers .= "References: <".iri2msgid($it["parent-uri"]).">";
 
 						// If Threading is enabled, write down the correct parent
@@ -465,23 +465,23 @@ function delivery_run(&$argv, &$argc){
 							$headers .= " <".iri2msgid($it["thr-parent"]).">";
 						$headers .= "\n";
 
-						if(!$it['title']) {
+						if (!$it['title']) {
 							$r = q("SELECT `title` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
 								dbesc($it['parent-uri']),
 								intval($uid));
 
-							if(count($r) AND ($r[0]['title'] != ''))
+							if (count($r) AND ($r[0]['title'] != ''))
 								$subject = $r[0]['title'];
 							else {
 								$r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d LIMIT 1",
 									dbesc($it['parent-uri']),
 									intval($uid));
 
-								if(count($r) AND ($r[0]['title'] != ''))
+								if (count($r) AND ($r[0]['title'] != ''))
 									$subject = $r[0]['title'];
 							}
 						}
-						if(strncasecmp($subject,'RE:',3))
+						if (strncasecmp($subject,'RE:',3))
 							$subject = 'Re: '.$subject;
 					}
 					email_send($addr, $subject, $headers, $it);
@@ -489,60 +489,64 @@ function delivery_run(&$argv, &$argc){
 				break;
 
 			case NETWORK_DIASPORA:
-				if($public_message)
-					$loc = 'public batch ' . $contact['batch'];
+				if ($public_message)
+					$loc = 'public batch '.$contact['batch'];
 				else
 					$loc = $contact['name'];
 
-				logger('delivery: diaspora batch deliver: ' . $loc);
+				logger('delivery: diaspora batch deliver: '.$loc);
 
-				if(get_config('system','dfrn_only') || (!get_config('system','diaspora_enabled')))
+				if (get_config('system','dfrn_only') || (!get_config('system','diaspora_enabled')))
 					break;
 
-				if($mail) {
-					diaspora_send_mail($item,$owner,$contact);
+				if ($mail) {
+					diaspora::send_mail($item,$owner,$contact);
+					//diaspora_send_mail($item,$owner,$contact);
 					break;
 				}
 
-				if(!$normal_mode)
+				if (!$normal_mode)
 					break;
 
-				if((! $contact['pubkey']) && (! $public_message))
+				if (!$contact['pubkey'] && !$public_message)
 					break;
 
 				$unsupported_activities = array(ACTIVITY_DISLIKE, ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE);
 
 				//don't transmit activities which are not supported by diaspora
 				foreach($unsupported_activities as $act) {
-					if(activity_match($target_item['verb'],$act)) {
+					if (activity_match($target_item['verb'],$act)) {
 						break 2;
 					}
 				}
 
-				if(($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
+				if (($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
 					// top-level retraction
-					logger('delivery: diaspora retract: ' . $loc);
+					logger('delivery: diaspora retract: '.$loc);
 
-					diaspora_send_retraction($target_item,$owner,$contact,$public_message);
+					diaspora::send_retraction($target_item,$owner,$contact,$public_message);
+					//diaspora_send_retraction($target_item,$owner,$contact,$public_message);
 					break;
-				} elseif($followup) {
+				} elseif ($followup) {
 					// send comments and likes to owner to relay
-					diaspora_send_followup($target_item,$owner,$contact,$public_message);
+					diaspora::send_followup($target_item,$owner,$contact,$public_message);
+					//diaspora_send_followup($target_item,$owner,$contact,$public_message);
 					break;
-				} elseif($target_item['uri'] !== $target_item['parent-uri']) {
+				} elseif ($target_item['uri'] !== $target_item['parent-uri']) {
 					// we are the relay - send comments, likes and relayable_retractions to our conversants
-					logger('delivery: diaspora relay: ' . $loc);
-
-					diaspora_send_relay($target_item,$owner,$contact,$public_message);
+					logger('delivery: diaspora relay: '.$loc);
+					diaspora::send_relay($target_item,$owner,$contact,$public_message);
+					//diaspora_send_relay($target_item,$owner,$contact,$public_message);
 					break;
-				} elseif(($top_level) && (! $walltowall)) {
+				} elseif ($top_level && !$walltowall) {
 					// currently no workable solution for sending walltowall
-					logger('delivery: diaspora status: ' . $loc);
-					diaspora_send_status($target_item,$owner,$contact,$public_message);
+					logger('delivery: diaspora status: '.$loc);
+					diaspora::send_status($target_item,$owner,$contact,$public_message);
+					//diaspora_send_status($target_item,$owner,$contact,$public_message);
 					break;
 				}
 
-				logger('delivery: diaspora unknown mode: ' . $contact['name']);
+				logger('delivery: diaspora unknown mode: '.$contact['name']);
 
 				break;
 
diff --git a/include/diaspora.php b/include/diaspora.php
index 2b85befa8c..11fe2c9b57 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -15,6 +15,7 @@ require_once('include/lock.php');
 require_once('include/threads.php');
 require_once('mod/share.php');
 require_once('include/enotify.php');
+require_once('include/diaspora2.php');
 
 function diaspora_dispatch_public($msg) {
 
diff --git a/include/diaspora2.php b/include/diaspora2.php
index 081eaf153a..b031651675 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -284,6 +284,8 @@ class diaspora {
 
 		$type = $fields->getName();
 
+		logger("Received message type ".$type." from ".$sender." for user ".$importer["uid"], LOGGER_DEBUG);
+
 		switch ($type) {
 			case "account_deletion":
 				return self::receive_account_deletion($importer, $fields);
@@ -654,7 +656,7 @@ class diaspora {
 			return false;
 		}
 
-		if (!self::post_allow($importer, $contact, false)) {
+		if (!self::post_allow($importer, $contact, $is_comment)) {
 			logger("The handle: ".$handle." is not allowed to post to user ".$importer["uid"]);
 			return false;
 		}
@@ -669,10 +671,10 @@ class diaspora {
 
 		if($r) {
 			logger("message ".$guid." already exists for user ".$uid);
-			return false;
+			return true;
 		}
 
-		return true;
+		return false;
 	}
 
 	private function fetch_guid($item) {
@@ -774,10 +776,12 @@ class diaspora {
 		}
 
 		if (!$r) {
-			logger("parent item not found: parent: ".$guid." item: ".$guid);
+			logger("parent item not found: parent: ".$guid." - user: ".$uid);
 			return false;
-		} else
+		} else {
+			logger("parent item found: parent: ".$guid." - user: ".$uid);
 			return $r[0];
+		}
 	}
 
 	private function author_contact_by_url($contact, $person, $uid) {
@@ -892,6 +896,9 @@ class diaspora {
 
 		$message_id = item_store($datarray);
 
+		if ($message_id)
+			logger("Stored comment ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
+
 		// If we are the origin of the parent we store the original data and notify our followers
 		if($message_id AND $parent_item["origin"]) {
 
@@ -1175,6 +1182,9 @@ class diaspora {
 
 		$message_id = item_store($datarray);
 
+		if ($message_id)
+			logger("Stored like ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
+
 		// If we are the origin of the parent we store the original data and notify our followers
 		if($message_id AND $parent_item["origin"]) {
 
@@ -1358,6 +1368,8 @@ class diaspora {
 
 		update_gcontact($gcontact);
 
+		logger("Profile of contact ".$contact["id"]." stored for user ".$importer["uid"], LOGGER_DEBUG);
+
 		return true;
 	}
 
@@ -1654,6 +1666,9 @@ class diaspora {
 		self::fetch_guid($datarray);
 		$message_id = item_store($datarray);
 
+		if ($message_id)
+			logger("Stored reshare ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
+
 		return $message_id;
 	}
 
@@ -1695,6 +1710,8 @@ class diaspora {
 		);
 		delete_thread($r[0]["id"], $r[0]["parent-uri"]);
 
+		logger("Deleted target ".$target_guid." from user ".$importer["uid"], LOGGER_DEBUG);
+
 		// Now check if the retraction needs to be relayed by us
 		if($p[0]["origin"]) {
 
@@ -1822,7 +1839,8 @@ class diaspora {
 		self::fetch_guid($datarray);
 		$message_id = item_store($datarray);
 
-		logger("Stored item with message id ".$message_id, LOGGER_DEBUG);
+		if ($message_id)
+			logger("Stored item ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
 
 		return $message_id;
 	}
@@ -2329,8 +2347,21 @@ class diaspora {
 		/// @todo Change all signatur storing functions to the new format
 		if ($signature['signed_text'] AND $signature['signature'] AND $signature['signer'])
 			$message = self::message_from_signatur($item, $signature);
-		else // New way
-			$message = json_decode($signature['signed_text']);
+		else {// New way
+			$msg = json_decode($signature['signed_text'], true);
+
+			$message = array();
+			foreach ($msg AS $field => $data) {
+				if (!$item["deleted"]) {
+					if ($field == "author")
+						$field = "diaspora_handle";
+					if ($field == "parent_type")
+						$field = "target_type";
+				}
+
+				$message[$field] = $data;
+			}
+		}
 
 		if ($item["deleted"]) {
 			$signed_text = $message["target_guid"].';'.$message["target_type"];
@@ -2338,6 +2369,8 @@ class diaspora {
 		} else
 			$message["parent_author_signature"] = self::signature($owner, $message);
 
+		logger("Relayed data ".print_r($message, true), LOGGER_DEBUG);
+
 		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
 	}
 
diff --git a/mod/receive.php b/mod/receive.php
index 95a5101675..051ea8c25c 100644
--- a/mod/receive.php
+++ b/mod/receive.php
@@ -53,7 +53,8 @@ function receive_post(&$a) {
 
 	logger('mod-diaspora: message is okay', LOGGER_DEBUG);
 
-	$msg = diaspora_decode($importer,$xml);
+	$msg = diaspora::decode($importer,$xml);
+	//$msg = diaspora_decode($importer,$xml);
 
 	logger('mod-diaspora: decoded', LOGGER_DEBUG);
 
@@ -65,10 +66,13 @@ function receive_post(&$a) {
 	logger('mod-diaspora: dispatching', LOGGER_DEBUG);
 
 	$ret = 0;
-	if($public)
-		diaspora_dispatch_public($msg);
-	else
-		$ret = diaspora_dispatch($importer,$msg);
+	if($public) {
+		diaspora::dispatch_public($msg);
+		//diaspora_dispatch_public($msg);
+	} else {
+		$ret = diaspora::dispatch($importer,$msg);
+		//$ret = diaspora_dispatch($importer,$msg);
+	}
 
 	http_status_exit(($ret) ? $ret : 200);
 	// NOTREACHED

From 75f5cfe63e2d84fbe55384a7b2769c55bbf423b6 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 13 Mar 2016 21:11:48 +0100
Subject: [PATCH 194/273] Retraction and reshares work

---
 include/diaspora2.php | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index b031651675..f6b8b9a704 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -1628,6 +1628,8 @@ class diaspora {
 		if (!$original_item)
 			return false;
 
+		$orig_url = App::get_baseurl()."/display/".$original_item["guid"];
+
 		$datarray = array();
 
 		$datarray["uid"] = $importer["uid"];
@@ -1651,7 +1653,7 @@ class diaspora {
 		$datarray["object"] = json_encode($data);
 
 		$prefix = share_header($original_item["author-name"], $original_item["author-link"], $original_item["author-avatar"],
-					$original_item["guid"], $original_item["created"], $original_item["uri"]);
+					$original_item["guid"], $original_item["created"], $orig_url);
 		$datarray["body"] = $prefix.$original_item["body"]."[/share]";
 
 		$datarray["tag"] = $original_item["tag"];
@@ -1691,16 +1693,20 @@ class diaspora {
 			return false;
 
 		// Only delete it if the author really fits
-		if (!link_compare($r[0]["author-link"],$person["url"]))
+		if (!link_compare($r[0]["author-link"], $person["url"])) {
+			logger("Item author ".$r[0]["author-link"]." doesn't fit to expected contact ".$person["url"], LOGGER_DEBUG);
 			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"]))
+		if (!link_compare($p[0]["author-link"], $contact["url"]) AND !link_compare($r[0]["author-link"], $contact["url"])) {
+			logger("Thread author ".$p[0]["author-link"]." and item author ".$r[0]["author-link"]." don't fit to expected contact ".$contact["url"], LOGGER_DEBUG);
 			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
 		q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', `body` = '' , `title` = '' WHERE `id` = %d",
@@ -1736,6 +1742,8 @@ class diaspora {
 			return false;
 		}
 
+		logger("Got retraction for ".$target_type.", sender ".$sender." and user ".$importer["uid"], LOGGER_DEBUG);
+
 		switch ($target_type) {
 			case "Comment":
 			case "Like":

From 9ae2b2292fd07a53f46689f778cd4630031912a7 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 14 Mar 2016 08:11:14 +0100
Subject: [PATCH 195/273] Some more function calls changed to the new class

---
 include/Contact.php           |  2 +-
 include/contact_selectors.php |  2 +-
 include/delivery.php          |  8 ++++----
 include/diaspora2.php         | 10 ++++++++--
 include/follow.php            |  2 +-
 include/notifier.php          |  6 +++---
 include/queue.php             |  2 +-
 7 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/include/Contact.php b/include/Contact.php
index 3799e0b189..d76c8f826c 100644
--- a/include/Contact.php
+++ b/include/Contact.php
@@ -129,7 +129,7 @@ function terminate_friendship($user,$self,$contact) {
 	}
 	elseif($contact['network'] === NETWORK_DIASPORA) {
 		require_once('include/diaspora.php');
-		diaspora_unshare($user,$contact);
+		diaspora::send_unshare($user,$contact);
 	}
 	elseif($contact['network'] === NETWORK_DFRN) {
 		require_once('include/dfrn.php');
diff --git a/include/contact_selectors.php b/include/contact_selectors.php
index a884a6b52b..3bf68f764e 100644
--- a/include/contact_selectors.php
+++ b/include/contact_selectors.php
@@ -99,7 +99,7 @@ function network_to_name($s, $profile = "") {
 
 	$networkname = str_replace($search,$replace,$s);
 
-	if (($s == NETWORK_DIASPORA) AND ($profile != "") AND diaspora_is_redmatrix($profile)) {
+	if (($s == NETWORK_DIASPORA) AND ($profile != "") AND diaspora::is_redmatrix($profile)) {
 		$networkname = t("Hubzilla/Redmatrix");
 
 		$r = q("SELECT `gserver`.`platform` FROM `gcontact`
diff --git a/include/delivery.php b/include/delivery.php
index d184fe12e1..1e1dadcd93 100644
--- a/include/delivery.php
+++ b/include/delivery.php
@@ -522,25 +522,25 @@ function delivery_run(&$argv, &$argc){
 
 				if (($target_item['deleted']) && (($target_item['uri'] === $target_item['parent-uri']) || $followup)) {
 					// top-level retraction
-					logger('delivery: diaspora retract: '.$loc);
-
+					logger('diaspora retract: '.$loc);
 					diaspora::send_retraction($target_item,$owner,$contact,$public_message);
 					//diaspora_send_retraction($target_item,$owner,$contact,$public_message);
 					break;
 				} elseif ($followup) {
 					// send comments and likes to owner to relay
+					logger('diaspora followup: '.$loc);
 					diaspora::send_followup($target_item,$owner,$contact,$public_message);
 					//diaspora_send_followup($target_item,$owner,$contact,$public_message);
 					break;
 				} elseif ($target_item['uri'] !== $target_item['parent-uri']) {
 					// we are the relay - send comments, likes and relayable_retractions to our conversants
-					logger('delivery: diaspora relay: '.$loc);
+					logger('diaspora relay: '.$loc);
 					diaspora::send_relay($target_item,$owner,$contact,$public_message);
 					//diaspora_send_relay($target_item,$owner,$contact,$public_message);
 					break;
 				} elseif ($top_level && !$walltowall) {
 					// currently no workable solution for sending walltowall
-					logger('delivery: diaspora status: '.$loc);
+					logger('diaspora status: '.$loc);
 					diaspora::send_status($target_item,$owner,$contact,$public_message);
 					//diaspora_send_status($target_item,$owner,$contact,$public_message);
 					break;
diff --git a/include/diaspora2.php b/include/diaspora2.php
index f6b8b9a704..5c17754e80 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -460,6 +460,8 @@ class diaspora {
 	 * @return string The public key
 	 */
 	private function key($handle) {
+		$handle = strval($handle);
+
 		logger("Fetching diaspora key for: ".$handle);
 
 		$r = self::person_by_handle($handle);
@@ -1699,7 +1701,7 @@ class diaspora {
 		}
 
 		// Check if the sender is the thread owner
-		$p = q("SELECT `author-link`, `origin` FROM `item` WHERE `id` = %d",
+		$p = q("SELECT `id`, `author-link`, `origin` FROM `item` WHERE `id` = %d",
 			intval($r[0]["parent"]));
 
 		// Only delete it if the parent author really fits
@@ -1716,7 +1718,7 @@ class diaspora {
 		);
 		delete_thread($r[0]["id"], $r[0]["parent-uri"]);
 
-		logger("Deleted target ".$target_guid." from user ".$importer["uid"], LOGGER_DEBUG);
+		logger("Deleted target ".$target_guid." (".$r[0]["id"].") from user ".$importer["uid"]." parent: ".$p[0]["id"], LOGGER_DEBUG);
 
 		// Now check if the retraction needs to be relayed by us
 		if($p[0]["origin"]) {
@@ -1727,6 +1729,8 @@ class diaspora {
 				intval($r[0]["id"]),
 				dbesc(json_encode($data))
 			);
+			$s = q("select * from sign where retract_iid = %d", intval($r[0]["id"]));
+			logger("Stored signatur for item ".$r[0]["id"]." - ".print_r($s, true), LOGGER_DEBUG);
 
 			// notify others
 			proc_run("php", "include/notifier.php", "drop", $r[0]["id"]);
@@ -2341,6 +2345,8 @@ class diaspora {
 			$type = "comment";
 		}
 
+		logger("Got relayable data ".$type." for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG);
+
 		// fetch the original signature
 
 		$r = q("SELECT `signed_text`, `signature`, `signer` FROM `sign` WHERE `".$sql_sign_id."` = %d LIMIT 1",
diff --git a/include/follow.php b/include/follow.php
index 3af629536d..6eab7e12fa 100644
--- a/include/follow.php
+++ b/include/follow.php
@@ -303,7 +303,7 @@ function new_contact($uid,$url,$interactive = false) {
 		}
 		if($contact['network'] == NETWORK_DIASPORA) {
 			require_once('include/diaspora.php');
-			$ret = diaspora_share($a->user,$contact);
+			$ret = diaspora::send_share($a->user,$contact);
 			logger('mod_follow: diaspora_share returns: ' . $ret);
 		}
 	}
diff --git a/include/notifier.php b/include/notifier.php
index 6c42f19c6a..e65da3adf2 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -536,7 +536,7 @@ function notifier_run(&$argv, &$argc){
 	if($public_message) {
 
 		if (!$followup AND $top_level)
-			$r0 = diaspora_fetch_relay();
+			$r0 = diaspora::relay_list();
 		else
 			$r0 = array();
 
@@ -629,11 +629,11 @@ function notifier_run(&$argv, &$argc){
 	}
 
 	// If the item was deleted, clean up the `sign` table
-	if($target_item['deleted']) {
+	/* if($target_item['deleted']) {
 		$r = q("DELETE FROM sign where `retract_iid` = %d",
 			intval($target_item['id'])
 		);
-	}
+	} */
 
 	logger('notifier: calling hooks', LOGGER_DEBUG);
 
diff --git a/include/queue.php b/include/queue.php
index 183ce0f9cd..878c149731 100644
--- a/include/queue.php
+++ b/include/queue.php
@@ -193,7 +193,7 @@ function queue_run(&$argv, &$argc){
 			case NETWORK_DIASPORA:
 				if($contact['notify']) {
 					logger('queue: diaspora_delivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>');
-					$deliver_status = diaspora_transmit($owner,$contact,$data,$public,true);
+					$deliver_status = diaspora::transmit($owner,$contact,$data,$public,true);
 
 					if($deliver_status == (-1)) {
 						update_queue_time($q_item['id']);

From 3734555715ab780c1d951c7c9d59c91b76b17b39 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 14 Mar 2016 20:04:17 +0100
Subject: [PATCH 196/273] Conversations are working now too

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

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 5c17754e80..c0e054c384 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -918,7 +918,7 @@ class diaspora {
 		return $message_id;
 	}
 
-	private function receive_conversation_message($importer, $contact, $data, $msg, $mesg) {
+	private function receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation) {
 		$guid = notags(unxmlify($data->guid));
 		$subject = notags(unxmlify($data->subject));
 		$author = notags(unxmlify($data->author));
@@ -1086,7 +1086,7 @@ class diaspora {
 		}
 
 		foreach($messages as $mesg)
-			self::receive_conversation_message($importer, $contact, $data, $msg, $mesg);
+			self::receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation);
 
 		return true;
 	}

From 56cb6cc8972f55d82030c8c2b908b05e656640f6 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 14 Mar 2016 20:53:44 +0100
Subject: [PATCH 197/273] Removed just more old diaspora function calls.

---
 database.sql                  | 11 -------
 doc/database.md               |  1 -
 doc/database/db_dsprphotoq.md | 11 -------
 include/cron.php              |  4 ---
 include/dbstructure.php       | 11 -------
 include/delivery.php          |  5 ----
 include/diaspora2.php         |  2 +-
 include/dsprphotoq.php        | 55 -----------------------------------
 include/follow.php            |  2 +-
 mod/dfrn_confirm.php          |  4 +--
 mod/p.php                     |  6 ++--
 mod/receive.php               |  3 --
 object/Item.php               |  2 +-
 13 files changed, 8 insertions(+), 109 deletions(-)
 delete mode 100644 doc/database/db_dsprphotoq.md
 delete mode 100644 include/dsprphotoq.php

diff --git a/database.sql b/database.sql
index 25faf0f4c0..02e5c9b378 100644
--- a/database.sql
+++ b/database.sql
@@ -201,17 +201,6 @@ CREATE TABLE IF NOT EXISTS `deliverq` (
 	 PRIMARY KEY(`id`)
 ) DEFAULT CHARSET=utf8;
 
---
--- TABLE dsprphotoq
---
-CREATE TABLE IF NOT EXISTS `dsprphotoq` (
-	`id` int(10) unsigned NOT NULL auto_increment,
-	`uid` int(11) NOT NULL DEFAULT 0,
-	`msg` mediumtext NOT NULL,
-	`attempt` tinyint(4) NOT NULL DEFAULT 0,
-	 PRIMARY KEY(`id`)
-) DEFAULT CHARSET=utf8;
-
 --
 -- TABLE event
 --
diff --git a/doc/database.md b/doc/database.md
index e37df05e09..f48404c17d 100644
--- a/doc/database.md
+++ b/doc/database.md
@@ -15,7 +15,6 @@ Database Tables
 | [contact](help/database/db_contact)                  | contact table                                    |
 | [conv](help/database/db_conv)                        | private messages                                 |
 | [deliverq](help/database/db_deliverq)                |                                                  |
-| [dsprphotoq](help/database/db_dsprphotoq)            |                                                  |
 | [event](help/database/db_event)                      | Events                                           |
 | [fcontact](help/database/db_fcontact)                | friend suggestion stuff                          |
 | [ffinder](help/database/db_ffinder)                  | friend suggestion stuff                          |
diff --git a/doc/database/db_dsprphotoq.md b/doc/database/db_dsprphotoq.md
deleted file mode 100644
index 6af4d030e0..0000000000
--- a/doc/database/db_dsprphotoq.md
+++ /dev/null
@@ -1,11 +0,0 @@
-Table dsprphotoq
-================
-
-| Field   | Description      | Type             | Null | Key | Default | Extra          |
-|---------|------------------|------------------|------|-----|---------|----------------|
-| id      | sequential ID    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
-| uid     |                  | int(11)          | NO   |     | 0       |                |
-| msg     |                  | mediumtext       | NO   |     | NULL    |                |
-| attempt |                  | tinyint(4)       | NO   |     | 0       |                |
-
-Return to [database documentation](help/database)
diff --git a/include/cron.php b/include/cron.php
index db7d44be0b..60c62786e6 100644
--- a/include/cron.php
+++ b/include/cron.php
@@ -71,10 +71,6 @@ function cron_run(&$argv, &$argc){
 
 	proc_run('php',"include/queue.php");
 
-	// run diaspora photo queue process in the background
-
-	proc_run('php',"include/dsprphotoq.php");
-
 	// run the process to discover global contacts in the background
 
 	proc_run('php',"include/discover_poco.php");
diff --git a/include/dbstructure.php b/include/dbstructure.php
index ddf036f2c1..e5e748bb24 100644
--- a/include/dbstructure.php
+++ b/include/dbstructure.php
@@ -537,17 +537,6 @@ function db_definition() {
 					"PRIMARY" => array("id"),
 					)
 			);
-	$database["dsprphotoq"] = array(
-			"fields" => array(
-					"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
-					"uid" => array("type" => "int(11)", "not null" => "1", "default" => "0"),
-					"msg" => array("type" => "mediumtext", "not null" => "1"),
-					"attempt" => array("type" => "tinyint(4)", "not null" => "1", "default" => "0"),
-					),
-			"indexes" => array(
-					"PRIMARY" => array("id"),
-					)
-			);
 	$database["event"] = array(
 			"fields" => array(
 					"id" => array("type" => "int(11)", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
diff --git a/include/delivery.php b/include/delivery.php
index 1e1dadcd93..9ac9f2391b 100644
--- a/include/delivery.php
+++ b/include/delivery.php
@@ -501,7 +501,6 @@ function delivery_run(&$argv, &$argc){
 
 				if ($mail) {
 					diaspora::send_mail($item,$owner,$contact);
-					//diaspora_send_mail($item,$owner,$contact);
 					break;
 				}
 
@@ -524,25 +523,21 @@ function delivery_run(&$argv, &$argc){
 					// top-level retraction
 					logger('diaspora retract: '.$loc);
 					diaspora::send_retraction($target_item,$owner,$contact,$public_message);
-					//diaspora_send_retraction($target_item,$owner,$contact,$public_message);
 					break;
 				} elseif ($followup) {
 					// send comments and likes to owner to relay
 					logger('diaspora followup: '.$loc);
 					diaspora::send_followup($target_item,$owner,$contact,$public_message);
-					//diaspora_send_followup($target_item,$owner,$contact,$public_message);
 					break;
 				} elseif ($target_item['uri'] !== $target_item['parent-uri']) {
 					// we are the relay - send comments, likes and relayable_retractions to our conversants
 					logger('diaspora relay: '.$loc);
 					diaspora::send_relay($target_item,$owner,$contact,$public_message);
-					//diaspora_send_relay($target_item,$owner,$contact,$public_message);
 					break;
 				} elseif ($top_level && !$walltowall) {
 					// currently no workable solution for sending walltowall
 					logger('diaspora status: '.$loc);
 					diaspora::send_status($target_item,$owner,$contact,$public_message);
-					//diaspora_send_status($target_item,$owner,$contact,$public_message);
 					break;
 				}
 
diff --git a/include/diaspora2.php b/include/diaspora2.php
index c0e054c384..1a354e9cf2 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -2093,7 +2093,7 @@ class diaspora {
 		return self::build_and_transmit($owner, $contact, "retraction", $message);
 	}
 
-	private function is_reshare($body) {
+	public static function is_reshare($body) {
 		$body = trim($body);
 
 		// Skip if it isn't a pure repeated messages
diff --git a/include/dsprphotoq.php b/include/dsprphotoq.php
deleted file mode 100644
index 0d8088d4bd..0000000000
--- a/include/dsprphotoq.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php
-require_once("boot.php");
-require_once('include/diaspora.php');
-
-function dsprphotoq_run($argv, $argc){
-	global $a, $db;
-
-	if(is_null($a)){
-		$a = new App;
-	}
-
-	if(is_null($db)){
-		@include(".htconfig.php");
-		require_once("include/dba.php");
-		$db = new dba($db_host, $db_user, $db_pass, $db_data);
-		unset($db_host, $db_user, $db_pass, $db_data);
-	};
-
-	logger("diaspora photo queue: running", LOGGER_DEBUG);
-
-	$r = q("SELECT * FROM dsprphotoq");
-	if(!$r)
-		return;
-
-	$dphotos = $r;
-
-	logger("diaspora photo queue: processing " . count($dphotos) . " photos");
-
-	foreach($dphotos as $dphoto) {
-
-		$r = array();
-
-		if ($dphoto['uid'] == 0)
-			$r[0] = array("uid" => 0, "page-flags" => PAGE_FREELOVE);
-		else
-			$r = q("SELECT * FROM user WHERE uid = %d",
-				intval($dphoto['uid']));
-
-		if(!$r) {
-			logger("diaspora photo queue: user " . $dphoto['uid'] . " not found");
-			return;
-		}
-
-		$ret = diaspora_dispatch($r[0],unserialize($dphoto['msg']),$dphoto['attempt']);
-		q("DELETE FROM dsprphotoq WHERE id = %d",
-		   intval($dphoto['id'])
-		);
-	}
-}
-
-
-if (array_search(__file__,get_included_files())===0){
-  dsprphotoq_run($_SERVER["argv"],$_SERVER["argc"]);
-  killme();
-}
diff --git a/include/follow.php b/include/follow.php
index 6eab7e12fa..d0411a466a 100644
--- a/include/follow.php
+++ b/include/follow.php
@@ -304,7 +304,7 @@ function new_contact($uid,$url,$interactive = false) {
 		if($contact['network'] == NETWORK_DIASPORA) {
 			require_once('include/diaspora.php');
 			$ret = diaspora::send_share($a->user,$contact);
-			logger('mod_follow: diaspora_share returns: ' . $ret);
+			logger('share returns: '.$ret);
 		}
 	}
 
diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php
index 68950ec285..cc09021dca 100644
--- a/mod/dfrn_confirm.php
+++ b/mod/dfrn_confirm.php
@@ -427,8 +427,8 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
 
 			if(($contact) && ($contact['network'] === NETWORK_DIASPORA)) {
 				require_once('include/diaspora.php');
-				$ret = diaspora_share($user[0],$r[0]);
-				logger('mod_follow: diaspora_share returns: ' . $ret);
+				$ret = diaspora::send_share($user[0],$r[0]);
+				logger('share returns: ' . $ret);
 			}
 
 			// Send a new friend post if we are allowed to...
diff --git a/mod/p.php b/mod/p.php
index 92b72dc1ce..20d6cfdbaf 100644
--- a/mod/p.php
+++ b/mod/p.php
@@ -28,14 +28,14 @@ function p_init($a){
 
 	$post = array();
 
-	$reshared = diaspora_is_reshare($item[0]["body"]);
+	$reshared = diaspora::is_reshare($item[0]["body"]);
 
 	if ($reshared) {
 		$nodename = "reshare";
 		$post["root_diaspora_id"] = $reshared["root_handle"];
 		$post["root_guid"] = $reshared["root_guid"];
 		$post["guid"] = $item[0]["guid"];
-		$post["diaspora_handle"] = diaspora_handle_from_contact($item[0]["contact-id"]);
+		$post["diaspora_handle"] = diaspora::handle_from_contact($item[0]["contact-id"]);
 		$post["public"] = (!$item[0]["private"] ? 'true':'false');
 		$post["created_at"] = datetime_convert('UTC','UTC',$item[0]["created"]);
 	} else {
@@ -48,7 +48,7 @@ function p_init($a){
 		$nodename = "status_message";
 		$post["raw_message"] = str_replace("&", "&amp;", $body);
 		$post["guid"] = $item[0]["guid"];
-		$post["diaspora_handle"] = diaspora_handle_from_contact($item[0]["contact-id"]);
+		$post["diaspora_handle"] = diaspora::handle_from_contact($item[0]["contact-id"]);
 		$post["public"] = (!$item[0]["private"] ? 'true':'false');
 		$post["created_at"] = datetime_convert('UTC','UTC',$item[0]["created"]);
 		$post["provider_display_name"] = $item[0]["app"];
diff --git a/mod/receive.php b/mod/receive.php
index 051ea8c25c..4991ac47e8 100644
--- a/mod/receive.php
+++ b/mod/receive.php
@@ -54,7 +54,6 @@ function receive_post(&$a) {
 	logger('mod-diaspora: message is okay', LOGGER_DEBUG);
 
 	$msg = diaspora::decode($importer,$xml);
-	//$msg = diaspora_decode($importer,$xml);
 
 	logger('mod-diaspora: decoded', LOGGER_DEBUG);
 
@@ -68,10 +67,8 @@ function receive_post(&$a) {
 	$ret = 0;
 	if($public) {
 		diaspora::dispatch_public($msg);
-		//diaspora_dispatch_public($msg);
 	} else {
 		$ret = diaspora::dispatch($importer,$msg);
-		//$ret = diaspora_dispatch($importer,$msg);
 	}
 
 	http_status_exit(($ret) ? $ret : 200);
diff --git a/object/Item.php b/object/Item.php
index e9c96cf159..59659cdaff 100644
--- a/object/Item.php
+++ b/object/Item.php
@@ -324,7 +324,7 @@ class Item extends BaseObject {
 
 		// Diaspora isn't able to do likes on comments - but red does
 		if (($item["item_network"] == NETWORK_DIASPORA) AND ($indent == 'comment') AND
-			!diaspora_is_redmatrix($item["owner-link"]) AND isset($buttons["like"]))
+			!diaspora::is_redmatrix($item["owner-link"]) AND isset($buttons["like"]))
 			unset($buttons["like"]);
 
 		// Diaspora doesn't has multithreaded comments

From 6f43d3a4c4f87dd282691d3e65c75b0ed99a1b3b Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 14 Mar 2016 22:10:26 +0100
Subject: [PATCH 198/273] Profile update is now working with the new function
 as well

---
 include/diaspora2.php      | 86 ++++++++++++++++++++++++++++++++++-
 include/profile_update.php | 92 +-------------------------------------
 2 files changed, 85 insertions(+), 93 deletions(-)

diff --git a/include/diaspora2.php b/include/diaspora2.php
index 1a354e9cf2..75cedeccd1 100644
--- a/include/diaspora2.php
+++ b/include/diaspora2.php
@@ -2058,7 +2058,7 @@ class diaspora {
 	}
 
 
-	private function build_and_transmit($owner, $contact, $type, $message, $public_batch = false, $guid = "") {
+	private function build_and_transmit($owner, $contact, $type, $message, $public_batch = false, $guid = "", $spool = false) {
 
 		$data = array("XML" => array("post" => array($type => $message)));
 
@@ -2069,7 +2069,11 @@ class diaspora {
 
 		$slap = self::build_message($msg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch);
 
-		$return_code = self::transmit($owner, $contact, $slap, $public_batch, false, $guid);
+		if ($spool) {
+			add_to_queue($contact['id'], NETWORK_DIASPORA, $slap, $public_batch);
+			return true;
+		} else
+			$return_code = self::transmit($owner, $contact, $slap, $public_batch, false, $guid);
 
 		logger("guid: ".$item["guid"]." result ".$return_code, LOGGER_DEBUG);
 
@@ -2467,5 +2471,83 @@ class diaspora {
 
 		return self::build_and_transmit($owner, $contact, $type, $message, false, $item["guid"]);
 	}
+
+	public static function send_profile($uid) {
+
+		if (!$uid)
+			return;
+
+		$recips = q("SELECT `id`,`name`,`network`,`pubkey`,`notify` FROM `contact` WHERE `network` = '%s'
+			AND `uid` = %d AND `rel` != %d",
+			dbesc(NETWORK_DIASPORA),
+			intval($uid),
+			intval(CONTACT_IS_SHARING)
+		);
+		if (!$recips)
+			return;
+
+		$r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `user`.*, `user`.`prvkey` AS `uprvkey`, `contact`.`addr`
+			FROM `profile`
+			INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
+			INNER JOIN `contact` ON `profile`.`uid` = `contact`.`uid`
+			WHERE `user`.`uid` = %d AND `profile`.`is-default` AND `contact`.`self` LIMIT 1",
+			intval($uid)
+		);
+
+		if (!$r)
+			return;
+
+		$profile = $r[0];
+
+		$handle = $profile["addr"];
+		$first = ((strpos($profile['name'],' ')
+			? trim(substr($profile['name'],0,strpos($profile['name'],' '))) : $profile['name']));
+		$last = (($first === $profile['name']) ? '' : trim(substr($profile['name'], strlen($first))));
+		$large = App::get_baseurl().'/photo/custom/300/'.$profile['uid'].'.jpg';
+		$medium = App::get_baseurl().'/photo/custom/100/'.$profile['uid'].'.jpg';
+		$small = App::get_baseurl().'/photo/custom/50/'  .$profile['uid'].'.jpg';
+		$searchable = (($profile['publish'] && $profile['net-publish']) ? 'true' : 'false');
+
+		if ($searchable === 'true') {
+			$dob = '1000-00-00';
+
+			if (($profile['dob']) && ($profile['dob'] != '0000-00-00'))
+				$dob = ((intval($profile['dob'])) ? intval($profile['dob']) : '1000') .'-'. datetime_convert('UTC','UTC',$profile['dob'],'m-d');
+
+			$about = $profile['about'];
+			$about = strip_tags(bbcode($about));
+
+			$location = formatted_location($profile);
+			$tags = '';
+			if ($profile['pub_keywords']) {
+				$kw = str_replace(',',' ',$profile['pub_keywords']);
+				$kw = str_replace('  ',' ',$kw);
+				$arr = explode(' ',$profile['pub_keywords']);
+				if (count($arr)) {
+					for($x = 0; $x < 5; $x ++) {
+						if (trim($arr[$x]))
+							$tags .= '#'. trim($arr[$x]) .' ';
+					}
+				}
+			}
+			$tags = trim($tags);
+		}
+
+		$message = array("diaspora_handle" => $handle,
+				"first_name" => $first,
+				"last_name" => $last,
+				"image_url" => $large,
+				"image_url_medium" => $medium,
+				"image_url_small" => $small,
+				"birthday" => $dob,
+				"gender" => $profile['gender'],
+				"bio" => $about,
+				"location" => $location,
+				"searchable" => $searchable,
+				"tag_string" => $tags);
+
+		foreach($recips as $recip)
+			self::build_and_transmit($profile, $recip, "profile", $message, false, "", true);
+	}
 }
 ?>
diff --git a/include/profile_update.php b/include/profile_update.php
index 7cc72cc866..399150f21c 100644
--- a/include/profile_update.php
+++ b/include/profile_update.php
@@ -1,96 +1,6 @@
 <?php
-
-require_once('include/datetime.php');
 require_once('include/diaspora.php');
-require_once('include/queue_fn.php');
-require_once('include/Contact.php');
 
 function profile_change() {
-
-	$a = get_app();
-
-	if(! local_user())
-		return;
-
-//   $url = $a->get_baseurl() . '/profile/' . $a->user['nickname'];
-//   if($url && strlen(get_config('system','directory')))
-//      proc_run('php',"include/directory.php","$url");
-
-	$recips = q("SELECT `id`,`name`,`network`,`pubkey`,`notify` FROM `contact` WHERE `network` = '%s'
-		AND `uid` = %d AND `rel` != %d ",
-		dbesc(NETWORK_DIASPORA),
-		intval(local_user()),
-		intval(CONTACT_IS_SHARING)
-	);
-	if(! count($recips))
-		return;
-
-	$r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `user`.* FROM `profile`
-		INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
-		WHERE `user`.`uid` = %d AND `profile`.`is-default` = 1 LIMIT 1",
-		intval(local_user())
-	);
-
-	if(! count($r))
-		return;
-	$profile = $r[0];
-
-	$handle = xmlify($a->user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3));
-	$first = xmlify(((strpos($profile['name'],' '))
-		? trim(substr($profile['name'],0,strpos($profile['name'],' '))) : $profile['name']));
-	$last = xmlify((($first === $profile['name']) ? '' : trim(substr($profile['name'],strlen($first)))));
-	$large = xmlify($a->get_baseurl() . '/photo/custom/300/' . $profile['uid'] . '.jpg');
-	$medium = xmlify($a->get_baseurl() . '/photo/custom/100/' . $profile['uid'] . '.jpg');
-	$small = xmlify($a->get_baseurl() . '/photo/custom/50/'  . $profile['uid'] . '.jpg');
-	$searchable = xmlify((($profile['publish'] && $profile['net-publish']) ? 'true' : 'false' ));
-//	$searchable = 'true';
-
-	if($searchable === 'true') {
-		$dob = '1000-00-00';
-
-		if(($profile['dob']) && ($profile['dob'] != '0000-00-00'))
-			$dob = ((intval($profile['dob'])) ? intval($profile['dob']) : '1000') . '-' . datetime_convert('UTC','UTC',$profile['dob'],'m-d');
-		$gender = xmlify($profile['gender']);
-		$about = xmlify($profile['about']);
-		require_once('include/bbcode.php');
-		$about = xmlify(strip_tags(bbcode($about)));
-		$location = formatted_location($profile);
-		$location = xmlify($location);
-		$tags = '';
-		if($profile['pub_keywords']) {
-			$kw = str_replace(',',' ',$profile['pub_keywords']);
-			$kw = str_replace('  ',' ',$kw);
-			$arr = explode(' ',$profile['pub_keywords']);
-			if(count($arr)) {
-				for($x = 0; $x < 5; $x ++) {
-					if(trim($arr[$x]))
-						$tags .= '#' . trim($arr[$x]) . ' ';
-				}
-			}
-		}
-		$tags = xmlify(trim($tags));
-	}
-
-	$tpl = get_markup_template('diaspora_profile.tpl');
-
-	$msg = replace_macros($tpl,array(
-		'$handle' => $handle,
-		'$first' => $first,
-		'$last' => $last,
-		'$large' => $large,
-		'$medium' => $medium,
-		'$small' => $small,
-		'$dob' => $dob,
-		'$gender' => $gender,
-		'$about' => $about,
-		'$location' => $location,
-		'$searchable' => $searchable,
-		'$tags' => $tags
-	));
-	logger('profile_change: ' . $msg, LOGGER_ALL);
-
-	foreach($recips as $recip) {
-		$msgtosend = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$a->user,$recip,$a->user['prvkey'],$recip['pubkey'],false)));
-		add_to_queue($recip['id'],NETWORK_DIASPORA,$msgtosend,false);
-	}
+	diaspora::send_profile(local_user());
 }

From dc2e7a66b3cf9401afbc4cf425fc5a37c66d2d74 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 14 Mar 2016 23:11:43 +0100
Subject: [PATCH 199/273] The Diaspora class is now productive

---
 include/diaspora.php  | 5338 ++++++++++++++++++-----------------------
 include/diaspora2.php | 2553 --------------------
 2 files changed, 2359 insertions(+), 5532 deletions(-)
 delete mode 100644 include/diaspora2.php

diff --git a/include/diaspora.php b/include/diaspora.php
index 11fe2c9b57..75cedeccd1 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -1,1702 +1,927 @@
 <?php
-
 /**
  * @file include/diaspora.php
- * 
- * @todo GET /people/9aed8882b9f64896/stream
+ * @brief The implementation of the diaspora protocol
  */
 
-require_once('include/crypto.php');
-require_once('include/items.php');
-require_once('include/bb2diaspora.php');
-require_once('include/contact_selectors.php');
-require_once('include/queue_fn.php');
-require_once('include/lock.php');
-require_once('include/threads.php');
-require_once('mod/share.php');
-require_once('include/enotify.php');
-require_once('include/diaspora2.php');
+require_once("include/items.php");
+require_once("include/bb2diaspora.php");
+require_once("include/Scrape.php");
+require_once("include/Contact.php");
+require_once("include/Photo.php");
+require_once("include/socgraph.php");
+require_once("include/group.php");
+require_once("include/xml.php");
+require_once("include/datetime.php");
 
-function diaspora_dispatch_public($msg) {
+/**
+ * @brief This class contain functions to create and send Diaspora XML files
+ *
+ */
+class diaspora {
 
-	$enabled = intval(get_config('system','diaspora_enabled'));
-	if(! $enabled) {
-		logger('mod-diaspora: disabled');
-		return;
-	}
+	public static function relay_list() {
 
-	// Use a dummy importer to import the data for the public copy
-	$importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE);
-	$result = diaspora_dispatch($importer,$msg);
-	logger("Dispatcher reported ".$result, LOGGER_DEBUG);
+		$serverdata = get_config("system", "relay_server");
+		if ($serverdata == "")
+			return array();
 
-	// Now distribute it to the followers
-	$r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN
-		( SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s' )
-		AND `account_expired` = 0 AND `account_removed` = 0 ",
-		dbesc(NETWORK_DIASPORA),
-		dbesc($msg['author'])
-	);
-	if(count($r)) {
-		foreach($r as $rr) {
-			logger('diaspora_public: delivering to: ' . $rr['username']);
-			diaspora_dispatch($rr,$msg);
+		$relay = array();
+
+		$servers = explode(",", $serverdata);
+
+		foreach($servers AS $server) {
+			$server = trim($server);
+			$batch = $server."/receive/public";
+
+			$relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
+
+			if (!$relais) {
+				$addr = "relay@".str_replace("http://", "", normalise_link($server));
+
+				$r = q("INSERT INTO `contact` (`uid`, `created`, `name`, `nick`, `addr`, `url`, `nurl`, `batch`, `network`, `rel`, `blocked`, `pending`, `writable`, `name-date`, `uri-date`, `avatar-date`)
+					VALUES (0, '%s', '%s', 'relay', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, '%s', '%s', '%s')",
+					datetime_convert(),
+					dbesc($addr),
+					dbesc($addr),
+					dbesc($server),
+					dbesc(normalise_link($server)),
+					dbesc($batch),
+					dbesc(NETWORK_DIASPORA),
+					intval(CONTACT_IS_FOLLOWER),
+					dbesc(datetime_convert()),
+					dbesc(datetime_convert()),
+					dbesc(datetime_convert())
+				);
+
+				$relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
+				if ($relais)
+					$relay[] = $relais[0];
+			} else
+				$relay[] = $relais[0];
 		}
-	}
-	else
-		logger('diaspora_public: no subscribers for '.$msg["author"].' '.print_r($msg, true));
-}
 
-
-
-function diaspora_dispatch($importer,$msg,$attempt=1) {
-
-	$ret = 0;
-
-	$enabled = intval(get_config('system','diaspora_enabled'));
-	if(! $enabled) {
-		logger('mod-diaspora: disabled');
-		return;
+		return $relay;
 	}
 
-	$data = $msg;
+	function repair_signature($signature, $handle = "", $level = 1) {
 
-	// php doesn't like dashes in variable names
+		if ($signature == "")
+			return ($signature);
 
-	$msg['message'] = str_replace(
-			array('<activity_streams-photo>','</activity_streams-photo>'),
-			array('<asphoto>','</asphoto>'),
-			$msg['message']);
+		if (base64_encode(base64_decode(base64_decode($signature))) == base64_decode($signature)) {
+			$signature = base64_decode($signature);
+			logger("Repaired double encoded signature from Diaspora/Hubzilla handle ".$handle." - level ".$level, LOGGER_DEBUG);
 
-
-	$parsed_xml = parse_xml_string($msg['message'],false);
-
-	$xmlbase = $parsed_xml->post;
-
-	logger('diaspora_dispatch: ' . print_r($xmlbase,true), LOGGER_DEBUG);
-
-
-	if($xmlbase->request) {
-		$tempfile = tempnam(get_temppath(), "diaspora-request");
-		file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_request($importer,$xmlbase->request);
-	}
-	elseif($xmlbase->status_message) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-status_message");
-		//file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_post($importer,$xmlbase->status_message,$msg);
-	}
-	elseif($xmlbase->profile) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-profile");
-		//file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_profile($importer,$xmlbase->profile,$msg);
-	}
-	elseif($xmlbase->comment) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-comment");
-		//file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_comment($importer,$xmlbase->comment,$msg);
-	}
-	elseif($xmlbase->like) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-like");
-		//file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_like($importer,$xmlbase->like,$msg);
-	}
-	elseif($xmlbase->asphoto) {
-		$tempfile = tempnam(get_temppath(), "diaspora-asphoto");
-		file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_asphoto($importer,$xmlbase->asphoto,$msg);
-	}
-	elseif($xmlbase->reshare) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-reshare");
-		//file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_reshare($importer,$xmlbase->reshare,$msg);
-	}
-	elseif($xmlbase->retraction) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-retraction");
-		//file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_retraction($importer,$xmlbase->retraction,$msg);
-	}
-	elseif($xmlbase->signed_retraction) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-signed_retraction");
-		//file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_signed_retraction($importer,$xmlbase->signed_retraction,$msg);
-	}
-	elseif($xmlbase->relayable_retraction) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-relayable_retraction");
-		//file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_signed_retraction($importer,$xmlbase->relayable_retraction,$msg);
-	}
-	elseif($xmlbase->photo) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-photo");
-		//file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_photo($importer,$xmlbase->photo,$msg,$attempt);
-	}
-	elseif($xmlbase->conversation) {
-		$tempfile = tempnam(get_temppath(), "diaspora-conversation");
-		file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_conversation($importer,$xmlbase->conversation,$msg);
-	}
-	elseif($xmlbase->message) {
-		$tempfile = tempnam(get_temppath(), "diaspora-message");
-		file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_message($importer,$xmlbase->message,$msg);
-	}
-	elseif($xmlbase->participation) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-participation");
-		//file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_participation($importer,$xmlbase->participation);
-	}
-	elseif($xmlbase->poll_participation) {
-		//$tempfile = tempnam(get_temppath(), "diaspora-poll_participation");
-		//file_put_contents($tempfile, json_encode($data));
-		$ret = diaspora_participation($importer,$xmlbase->poll_participation);
-	}
-	else {
-		$tempfile = tempnam(get_temppath(), "diaspora-unknown");
-		file_put_contents($tempfile, json_encode($data));
-		logger('diaspora_dispatch: unknown message type: ' . print_r($xmlbase,true));
-	}
-	return $ret;
-}
-
-function diaspora_handle_from_contact($contact_id) {
-	$handle = False;
-
-	logger("diaspora_handle_from_contact: contact id is " . $contact_id, LOGGER_DEBUG);
-
-	$r = q("SELECT network, addr, self, url, nick FROM contact WHERE id = %d",
-	       intval($contact_id)
-	);
-	if($r) {
-		$contact = $r[0];
-
-		logger("diaspora_handle_from_contact: contact 'self' = " . $contact['self'] . " 'url' = " . $contact['url'], LOGGER_DEBUG);
-
-		if($contact['network'] === NETWORK_DIASPORA) {
-			$handle = $contact['addr'];
-
-//			logger("diaspora_handle_from_contact: contact id is a Diaspora person, handle = " . $handle, LOGGER_DEBUG);
+			// Do a recursive call to be able to fix even multiple levels
+			if ($level < 10)
+				$signature = self::repair_signature($signature, $handle, ++$level);
 		}
-		elseif(($contact['network'] === NETWORK_DFRN) || ($contact['self'] == 1)) {
-			$baseurl_start = strpos($contact['url'],'://') + 3;
-			$baseurl_length = strpos($contact['url'],'/profile') - $baseurl_start; // allows installations in a subdirectory--not sure how Diaspora will handle
-			$baseurl = substr($contact['url'], $baseurl_start, $baseurl_length);
-			$handle = $contact['nick'] . '@' . $baseurl;
 
-//			logger("diaspora_handle_from_contact: contact id is a DFRN person, handle = " . $handle, LOGGER_DEBUG);
-		}
+		return($signature);
 	}
 
-	return $handle;
-}
+	/**
+	 * @brief: Decodes incoming Diaspora message
+	 *
+	 * @param array $importer from user table
+	 * @param string $xml urldecoded Diaspora salmon
+	 *
+	 * @return array
+	 * 'message' -> decoded Diaspora XML message
+	 * 'author' -> author diaspora handle
+	 * 'key' -> author public key (converted to pkcs#8)
+	 */
+	function decode($importer, $xml) {
 
-function diaspora_get_contact_by_handle($uid,$handle) {
-	$r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `addr` = '%s' LIMIT 1",
-		dbesc(NETWORK_DIASPORA),
-		intval($uid),
-		dbesc($handle)
-	);
-	if($r && count($r))
-		return $r[0];
+		$public = false;
+		$basedom = parse_xml_string($xml);
 
-	$handle_parts = explode("@", $handle);
-	$nurl_sql = '%%://' . $handle_parts[1] . '%%/profile/' . $handle_parts[0];
-	$r = q("SELECT * FROM contact WHERE network = '%s' AND uid = %d AND nurl LIKE '%s' LIMIT 1",
-	       dbesc(NETWORK_DFRN),
-	       intval($uid),
-	       dbesc($nurl_sql)
-	);
-	if($r && count($r))
-		return $r[0];
+		if (!is_object($basedom))
+			return false;
 
-	return false;
-}
+		$children = $basedom->children('https://joindiaspora.com/protocol');
 
-function find_diaspora_person_by_handle($handle) {
+		if($children->header) {
+			$public = true;
+			$author_link = str_replace('acct:','',$children->header->author_id);
+		} else {
 
-	$person = false;
-	$update = false;
-	$got_lock = false;
+			$encrypted_header = json_decode(base64_decode($children->encrypted_header));
 
-	$endlessloop = 0;
-	$maxloops = 10;
+			$encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key);
+			$ciphertext = base64_decode($encrypted_header->ciphertext);
 
-	do {
-		$r = q("select * from fcontact where network = '%s' and addr = '%s' limit 1",
+			$outer_key_bundle = '';
+			openssl_private_decrypt($encrypted_aes_key_bundle,$outer_key_bundle,$importer['prvkey']);
+
+			$j_outer_key_bundle = json_decode($outer_key_bundle);
+
+			$outer_iv = base64_decode($j_outer_key_bundle->iv);
+			$outer_key = base64_decode($j_outer_key_bundle->key);
+
+			$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $outer_key, $ciphertext, MCRYPT_MODE_CBC, $outer_iv);
+
+
+			$decrypted = pkcs5_unpad($decrypted);
+
+			/**
+			 * $decrypted now contains something like
+			 *
+			 *  <decrypted_header>
+			 *     <iv>8e+G2+ET8l5BPuW0sVTnQw==</iv>
+			 *     <aes_key>UvSMb4puPeB14STkcDWq+4QE302Edu15oaprAQSkLKU=</aes_key>
+			 *     <author_id>galaxor@diaspora.priateship.org</author_id>
+			 *  </decrypted_header>
+			 */
+
+			logger('decrypted: '.$decrypted, LOGGER_DEBUG);
+			$idom = parse_xml_string($decrypted,false);
+
+			$inner_iv = base64_decode($idom->iv);
+			$inner_aes_key = base64_decode($idom->aes_key);
+
+			$author_link = str_replace('acct:','',$idom->author_id);
+		}
+
+		$dom = $basedom->children(NAMESPACE_SALMON_ME);
+
+		// figure out where in the DOM tree our data is hiding
+
+		if($dom->provenance->data)
+			$base = $dom->provenance;
+		elseif($dom->env->data)
+			$base = $dom->env;
+		elseif($dom->data)
+			$base = $dom;
+
+		if (!$base) {
+			logger('unable to locate salmon data in xml');
+			http_status_exit(400);
+		}
+
+
+		// Stash the signature away for now. We have to find their key or it won't be good for anything.
+		$signature = base64url_decode($base->sig);
+
+		// unpack the  data
+
+		// strip whitespace so our data element will return to one big base64 blob
+		$data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$base->data);
+
+
+		// stash away some other stuff for later
+
+		$type = $base->data[0]->attributes()->type[0];
+		$keyhash = $base->sig[0]->attributes()->keyhash[0];
+		$encoding = $base->encoding;
+		$alg = $base->alg;
+
+
+		$signed_data = $data.'.'.base64url_encode($type).'.'.base64url_encode($encoding).'.'.base64url_encode($alg);
+
+
+		// decode the data
+		$data = base64url_decode($data);
+
+
+		if($public)
+			$inner_decrypted = $data;
+		else {
+
+			// Decode the encrypted blob
+
+			$inner_encrypted = base64_decode($data);
+			$inner_decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $inner_encrypted, MCRYPT_MODE_CBC, $inner_iv);
+			$inner_decrypted = pkcs5_unpad($inner_decrypted);
+		}
+
+		if (!$author_link) {
+			logger('Could not retrieve author URI.');
+			http_status_exit(400);
+		}
+		// Once we have the author URI, go to the web and try to find their public key
+		// (first this will look it up locally if it is in the fcontact cache)
+		// This will also convert diaspora public key from pkcs#1 to pkcs#8
+
+		logger('Fetching key for '.$author_link);
+		$key = self::key($author_link);
+
+		if (!$key) {
+			logger('Could not retrieve author key.');
+			http_status_exit(400);
+		}
+
+		$verify = rsa_verify($signed_data,$signature,$key);
+
+		if (!$verify) {
+			logger('Message did not verify. Discarding.');
+			http_status_exit(400);
+		}
+
+		logger('Message verified.');
+
+		return array('message' => $inner_decrypted, 'author' => $author_link, 'key' => $key);
+
+	}
+
+
+	/**
+	 * @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"));
+		if (!$enabled) {
+			logger("diaspora is disabled");
+			return false;
+		}
+
+		// Use a dummy importer to import the data for the public copy
+		$importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE);
+		$item_id = self::dispatch($importer,$msg);
+
+		// Now distribute it to the followers
+		$r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN
+			(SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s')
+			AND NOT `account_expired` AND NOT `account_removed`",
+			dbesc(NETWORK_DIASPORA),
+			dbesc($msg["author"])
+		);
+		if($r) {
+			foreach($r as $rr) {
+				logger("delivering to: ".$rr["username"]);
+				self::dispatch($rr,$msg);
+			}
+		} else
+			logger("No subscribers for ".$msg["author"]." ".print_r($msg, true));
+
+		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.
+		// This will often be different with relayed messages (for example "like" and "comment")
+		$sender = $msg["author"];
+
+		if (!diaspora::valid_posting($msg, $fields)) {
+			logger("Invalid posting");
+			return false;
+		}
+
+		$type = $fields->getName();
+
+		logger("Received message type ".$type." from ".$sender." for user ".$importer["uid"], LOGGER_DEBUG);
+
+		switch ($type) {
+			case "account_deletion":
+				return self::receive_account_deletion($importer, $fields);
+
+			case "comment":
+				return self::receive_comment($importer, $sender, $fields);
+
+			case "conversation":
+				return self::receive_conversation($importer, $msg, $fields);
+
+			case "like":
+				return self::receive_like($importer, $sender, $fields);
+
+			case "message":
+				return self::receive_message($importer, $fields);
+
+			case "participation": // Not implemented
+				return self::receive_participation($importer, $fields);
+
+			case "photo": // Not implemented
+				return self::receive_photo($importer, $fields);
+
+			case "poll_participation": // Not implemented
+				return self::receive_poll_participation($importer, $fields);
+
+			case "profile":
+				return self::receive_profile($importer, $fields);
+
+			case "request":
+				return self::receive_request($importer, $fields);
+
+			case "reshare":
+				return self::receive_reshare($importer, $fields);
+
+			case "retraction":
+				return self::receive_retraction($importer, $sender, $fields);
+
+			case "status_message":
+				return self::receive_status_message($importer, $fields);
+
+			default:
+				logger("Unknown message type ".$type);
+				return false;
+		}
+
+		return true;
+	}
+
+	/**
+	 * @brief Checks if a posting is valid and fetches the data fields.
+	 *
+	 * This function does not only check the signature.
+	 * It also does the conversion between the old and the new diaspora format.
+	 *
+	 * @param array $msg Array with the XML, the sender handle and the sender signature
+	 * @param object $fields SimpleXML object that contains the posting when it is valid
+	 *
+	 * @return bool Is the posting valid?
+	 */
+	private function valid_posting($msg, &$fields) {
+
+		$data = parse_xml_string($msg["message"], false);
+
+		if (!is_object($data))
+			return false;
+
+		$first_child = $data->getName();
+
+		// Is this the new or the old version?
+		if ($data->getName() == "XML") {
+			$oldXML = true;
+			foreach ($data->post->children() as $child)
+				$element = $child;
+		} else {
+			$oldXML = false;
+			$element = $data;
+		}
+
+		$type = $element->getName();
+		$orig_type = $type;
+
+		// All retractions are handled identically from now on.
+		// In the new version there will only be "retraction".
+		if (in_array($type, array("signed_retraction", "relayable_retraction")))
+			$type = "retraction";
+
+		$fields = new SimpleXMLElement("<".$type."/>");
+
+		$signed_data = "";
+
+		foreach ($element->children() AS $fieldname => $entry) {
+			if ($oldXML) {
+				// Translation for the old XML structure
+				if ($fieldname == "diaspora_handle")
+					$fieldname = "author";
+
+				if ($fieldname == "participant_handles")
+					$fieldname = "participants";
+
+				if (in_array($type, array("like", "participation"))) {
+					if ($fieldname == "target_type")
+						$fieldname = "parent_type";
+				}
+
+				if ($fieldname == "sender_handle")
+					$fieldname = "author";
+
+				if ($fieldname == "recipient_handle")
+					$fieldname = "recipient";
+
+				if ($fieldname == "root_diaspora_id")
+					$fieldname = "root_author";
+
+				if ($type == "retraction") {
+					if ($fieldname == "post_guid")
+						$fieldname = "target_guid";
+
+					if ($fieldname == "type")
+						$fieldname = "target_type";
+				}
+			}
+
+			if ($fieldname == "author_signature")
+				$author_signature = base64_decode($entry);
+			elseif ($fieldname == "parent_author_signature")
+				$parent_author_signature = base64_decode($entry);
+			elseif ($fieldname != "target_author_signature") {
+				if ($signed_data != "") {
+					$signed_data .= ";";
+					$signed_data_parent .= ";";
+				}
+
+				$signed_data .= $entry;
+			}
+			if (!in_array($fieldname, array("parent_author_signature", "target_author_signature")) OR
+				($orig_type == "relayable_retraction"))
+				xml::copy($entry, $fields, $fieldname);
+		}
+
+		// This is something that shouldn't happen at all.
+		if (in_array($type, array("status_message", "reshare", "profile")))
+			if ($msg["author"] != $fields->author) {
+				logger("Message handle is not the same as envelope sender. Quitting this message.");
+				return false;
+			}
+
+		// Only some message types have signatures. So we quit here for the other types.
+		if (!in_array($type, array("comment", "message", "like")))
+			return true;
+
+		// No author_signature? This is a must, so we quit.
+		if (!isset($author_signature))
+			return false;
+
+		if (isset($parent_author_signature)) {
+			$key = self::key($msg["author"]);
+
+			if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256"))
+				return false;
+		}
+
+		$key = self::key($fields->author);
+
+		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 key($handle) {
+		$handle = strval($handle);
+
+		logger("Fetching diaspora key for: ".$handle);
+
+		$r = self::person_by_handle($handle);
+		if($r)
+			return $r["pubkey"];
+
+		return "";
+	}
+
+	/**
+	 * @brief Fetches data for a given handle
+	 *
+	 * @param string $handle The handle
+	 *
+	 * @return array the queried data
+	 */
+	private function person_by_handle($handle) {
+
+		$r = q("SELECT * FROM `fcontact` WHERE `network` = '%s' AND `addr` = '%s' LIMIT 1",
 			dbesc(NETWORK_DIASPORA),
 			dbesc($handle)
 		);
-		if(count($r)) {
+		if ($r) {
 			$person = $r[0];
-			logger('find_diaspora_person_by handle: in cache ' . print_r($r,true), LOGGER_DEBUG);
+			logger("In cache ".print_r($r,true), LOGGER_DEBUG);
 
 			// update record occasionally so it doesn't get stale
-			$d = strtotime($person['updated'] . ' +00:00');
-			if($d < strtotime('now - 14 days'))
+			$d = strtotime($person["updated"]." +00:00");
+			if ($d < strtotime("now - 14 days"))
 				$update = true;
 		}
 
+		if (!$person OR $update) {
+			logger("create or refresh", LOGGER_DEBUG);
+			$r = probe_url($handle, PROBE_DIASPORA);
 
-		// FETCHING PERSON INFORMATION FROM REMOTE SERVER
-		//
-		// If the person isn't in our 'fcontact' table, or if he/she is but
-		// his/her information hasn't been updated for more than 14 days, then
-		// we want to fetch the person's information from the remote server.
-		//
-		// Note that $person isn't changed by this block of code unless the
-		// person's information has been successfully fetched from the remote
-		// server. So if $person was 'false' to begin with (because he/she wasn't
-		// in the local cache), it'll stay false, and if $person held the local
-		// cache information to begin with, it'll keep that information. That way
-		// if there's a problem with the remote fetch, we can at least use our
-		// cached information--it's better than nothing.
-
-		if((! $person) || ($update))  {
-			// Lock the function to prevent race conditions if multiple items
-			// come in at the same time from a person who doesn't exist in
-			// fcontact
-			//
-			// Don't loop forever. On the last loop, try to create the contact
-			// whether the function is locked or not. Maybe the locking thread
-			// has died or something. At any rate, a duplicate in 'fcontact'
-			// is a much smaller problem than a deadlocked thread
-			$got_lock = lock_function('find_diaspora_person_by_handle', false);
-			if(($endlessloop + 1) >= $maxloops)
-				$got_lock = true;
-
-			if($got_lock) {
-				logger('find_diaspora_person_by_handle: create or refresh', LOGGER_DEBUG);
-				require_once('include/Scrape.php');
-				$r = probe_url($handle, PROBE_DIASPORA);
-
-				// Note that Friendica contacts can return a "Diaspora person"
-				// if Diaspora connectivity is enabled on their server
-				if((count($r)) && ($r['network'] === NETWORK_DIASPORA)) {
-					add_fcontact($r,$update);
-					$person = ($r);
-				}
-
-				unlock_function('find_diaspora_person_by_handle');
-			}
-			else {
-				logger('find_diaspora_person_by_handle: couldn\'t lock function', LOGGER_DEBUG);
-				if(! $person)
-					block_on_function_lock('find_diaspora_person_by_handle');
+			// Note that Friendica contacts will return a "Diaspora person"
+			// if Diaspora connectivity is enabled on their server
+			if ($r AND ($r["network"] === NETWORK_DIASPORA)) {
+				self::add_fcontact($r, $update);
+				$person = $r;
 			}
 		}
-	} while((! $person) && (! $got_lock) && (++$endlessloop < $maxloops));
-	// We need to try again if the person wasn't in 'fcontact' but the function was locked.
-	// The fact that the function was locked may mean that another process was creating the
-	// person's record. It could also mean another process was creating or updating an unrelated
-	// person.
-	//
-	// At any rate, we need to keep trying until we've either got the person or had a chance to
-	// try to fetch his/her remote information. But we don't want to block on locking the
-	// function, because if the other process is creating the record, then when we acquire the lock
-	// we'll dive right into creating another, duplicate record. We DO want to at least wait
-	// until the lock is released, so we don't flood the database with requests.
-	//
-	// If the person was in the 'fcontact' table, don't try again. It's not worth the time, since
-	// we do have some information for the person
-
-	return $person;
-}
-
-
-function get_diaspora_key($uri) {
-	logger('Fetching diaspora key for: ' . $uri);
-
-	$r = find_diaspora_person_by_handle($uri);
-	if($r)
-		return $r['pubkey'];
-	return '';
-}
-
-
-function diaspora_pubmsg_build($msg,$user,$contact,$prvkey,$pubkey) {
-	$a = get_app();
-
-	logger('diaspora_pubmsg_build: ' . $msg, LOGGER_DATA);
-
-
-	$handle = $user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
-
-//	$b64_data = base64_encode($msg);
-//	$b64url_data = base64url_encode($b64_data);
-
-	$b64url_data = base64url_encode($msg);
-
-	$data = str_replace(array("\n","\r"," ","\t"),array('','','',''),$b64url_data);
-
-	$type = 'application/xml';
-	$encoding = 'base64url';
-	$alg = 'RSA-SHA256';
-
-	$signable_data = $data  . '.' . base64url_encode($type) . '.'
-		. base64url_encode($encoding) . '.' . base64url_encode($alg) ;
-
-	$signature = rsa_sign($signable_data,$prvkey);
-	$sig = base64url_encode($signature);
-
-$magic_env = <<< EOT
-<?xml version='1.0' encoding='UTF-8'?>
-<diaspora xmlns="https://joindiaspora.com/protocol" xmlns:me="http://salmon-protocol.org/ns/magic-env" >
-  <header>
-    <author_id>$handle</author_id>
-  </header>
-  <me:env>
-    <me:encoding>base64url</me:encoding>
-    <me:alg>RSA-SHA256</me:alg>
-    <me:data type="application/xml">$data</me:data>
-    <me:sig>$sig</me:sig>
-  </me:env>
-</diaspora>
-EOT;
-
-	logger('diaspora_pubmsg_build: magic_env: ' . $magic_env, LOGGER_DATA);
-	return $magic_env;
-
-}
-
-
-
-
-function diaspora_msg_build($msg,$user,$contact,$prvkey,$pubkey,$public = false) {
-	$a = get_app();
-
-	if($public)
-		return diaspora_pubmsg_build($msg,$user,$contact,$prvkey,$pubkey);
-
-	logger('diaspora_msg_build: ' . $msg, LOGGER_DATA);
-
-	// without a public key nothing will work
-
-	if(! $pubkey) {
-		logger('diaspora_msg_build: pubkey missing: contact id: ' . $contact['id']);
-		return '';
+		return $person;
 	}
 
-	$inner_aes_key = random_string(32);
-	$b_inner_aes_key = base64_encode($inner_aes_key);
-	$inner_iv = random_string(16);
-	$b_inner_iv = base64_encode($inner_iv);
+	/**
+	 * @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
 
-	$outer_aes_key = random_string(32);
-	$b_outer_aes_key = base64_encode($outer_aes_key);
-	$outer_iv = random_string(16);
-	$b_outer_iv = base64_encode($outer_iv);
-
-	$handle = $user['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
-
-	$padded_data = pkcs5_pad($msg,16);
-	$inner_encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $padded_data, MCRYPT_MODE_CBC, $inner_iv);
-
-	$b64_data = base64_encode($inner_encrypted);
-
-
-	$b64url_data = base64url_encode($b64_data);
-	$data = str_replace(array("\n","\r"," ","\t"),array('','','',''),$b64url_data);
-
-	$type = 'application/xml';
-	$encoding = 'base64url';
-	$alg = 'RSA-SHA256';
-
-	$signable_data = $data  . '.' . base64url_encode($type) . '.'
-		. base64url_encode($encoding) . '.' . base64url_encode($alg) ;
-
-	$signature = rsa_sign($signable_data,$prvkey);
-	$sig = base64url_encode($signature);
-
-$decrypted_header = <<< EOT
-<decrypted_header>
-  <iv>$b_inner_iv</iv>
-  <aes_key>$b_inner_aes_key</aes_key>
-  <author_id>$handle</author_id>
-</decrypted_header>
-EOT;
-
-	$decrypted_header = pkcs5_pad($decrypted_header,16);
-
-	$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $outer_aes_key, $decrypted_header, MCRYPT_MODE_CBC, $outer_iv);
-
-	$outer_json = json_encode(array('iv' => $b_outer_iv,'key' => $b_outer_aes_key));
-
-	$encrypted_outer_key_bundle = '';
-	openssl_public_encrypt($outer_json,$encrypted_outer_key_bundle,$pubkey);
-
-	$b64_encrypted_outer_key_bundle = base64_encode($encrypted_outer_key_bundle);
-
-	logger('outer_bundle: ' . $b64_encrypted_outer_key_bundle . ' key: ' . $pubkey, LOGGER_DATA);
-
-	$encrypted_header_json_object = json_encode(array('aes_key' => base64_encode($encrypted_outer_key_bundle), 
-		'ciphertext' => base64_encode($ciphertext)));
-	$cipher_json = base64_encode($encrypted_header_json_object);
-
-	$encrypted_header = '<encrypted_header>' . $cipher_json . '</encrypted_header>';
-
-$magic_env = <<< EOT
-<?xml version='1.0' encoding='UTF-8'?>
-<diaspora xmlns="https://joindiaspora.com/protocol" xmlns:me="http://salmon-protocol.org/ns/magic-env" >
-  $encrypted_header
-  <me:env>
-    <me:encoding>base64url</me:encoding>
-    <me:alg>RSA-SHA256</me:alg>
-    <me:data type="application/xml">$data</me:data>
-    <me:sig>$sig</me:sig>
-  </me:env>
-</diaspora>
-EOT;
-
-	logger('diaspora_msg_build: magic_env: ' . $magic_env, LOGGER_DATA);
-	return $magic_env;
-
-}
-
-/**
- *
- * diaspora_decode($importer,$xml)
- *   array $importer -> from user table
- *   string $xml -> urldecoded Diaspora salmon 
- *
- * Returns array
- * 'message' -> decoded Diaspora XML message
- * 'author' -> author diaspora handle
- * 'key' -> author public key (converted to pkcs#8)
- *
- * Author and key are used elsewhere to save a lookup for verifying replies and likes
- */
-
-
-function diaspora_decode($importer,$xml) {
-
-	$tempfile = tempnam(get_temppath(), "diaspora-decode");
-	file_put_contents($tempfile, json_encode(array("importer" => $importer, "xml" => $xml)));
-
-	$public = false;
-	$basedom = parse_xml_string($xml);
-
-	$children = $basedom->children('https://joindiaspora.com/protocol');
-
-	if($children->header) {
-		$public = true;
-		$author_link = str_replace('acct:','',$children->header->author_id);
-	}
-	else {
-
-		$encrypted_header = json_decode(base64_decode($children->encrypted_header));
-
-		$encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key);
-		$ciphertext = base64_decode($encrypted_header->ciphertext);
-
-		$outer_key_bundle = '';
-		openssl_private_decrypt($encrypted_aes_key_bundle,$outer_key_bundle,$importer['prvkey']);
-
-		$j_outer_key_bundle = json_decode($outer_key_bundle);
-
-		$outer_iv = base64_decode($j_outer_key_bundle->iv);
-		$outer_key = base64_decode($j_outer_key_bundle->key);
-
-		$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $outer_key, $ciphertext, MCRYPT_MODE_CBC, $outer_iv);
-
-
-		$decrypted = pkcs5_unpad($decrypted);
-
-		/**
-		 * $decrypted now contains something like
-		 *
-		 *  <decrypted_header>
-		 *     <iv>8e+G2+ET8l5BPuW0sVTnQw==</iv>
-		 *     <aes_key>UvSMb4puPeB14STkcDWq+4QE302Edu15oaprAQSkLKU=</aes_key>
-
-***** OBSOLETE
-
-		 *     <author>
-		 *       <name>Ryan Hughes</name>
-		 *       <uri>acct:galaxor@diaspora.pirateship.org</uri>
-		 *     </author>
-
-***** CURRENT
-
-		 *     <author_id>galaxor@diaspora.priateship.org</author_id>
-
-***** END DIFFS
-
-		 *  </decrypted_header>
-		 */
-
-		logger('decrypted: ' . $decrypted, LOGGER_DEBUG);
-		$idom = parse_xml_string($decrypted,false);
-
-		$inner_iv = base64_decode($idom->iv);
-		$inner_aes_key = base64_decode($idom->aes_key);
-
-		$author_link = str_replace('acct:','',$idom->author_id);
+		if($update) {
+			$r = q("UPDATE `fcontact` SET
+					`name` = '%s',
+					`photo` = '%s',
+					`request` = '%s',
+					`nick` = '%s',
+					`addr` = '%s',
+					`batch` = '%s',
+					`notify` = '%s',
+					`poll` = '%s',
+					`confirm` = '%s',
+					`alias` = '%s',
+					`pubkey` = '%s',
+					`updated` = '%s'
+				WHERE `url` = '%s' AND `network` = '%s'",
+					dbesc($arr["name"]),
+					dbesc($arr["photo"]),
+					dbesc($arr["request"]),
+					dbesc($arr["nick"]),
+					dbesc($arr["addr"]),
+					dbesc($arr["batch"]),
+					dbesc($arr["notify"]),
+					dbesc($arr["poll"]),
+					dbesc($arr["confirm"]),
+					dbesc($arr["alias"]),
+					dbesc($arr["pubkey"]),
+					dbesc(datetime_convert()),
+					dbesc($arr["url"]),
+					dbesc($arr["network"])
+				);
+		} else {
+			$r = q("INSERT INTO `fcontact` (`url`,`name`,`photo`,`request`,`nick`,`addr`,
+					`batch`, `notify`,`poll`,`confirm`,`network`,`alias`,`pubkey`,`updated`)
+				VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')",
+					dbesc($arr["url"]),
+					dbesc($arr["name"]),
+					dbesc($arr["photo"]),
+					dbesc($arr["request"]),
+					dbesc($arr["nick"]),
+					dbesc($arr["addr"]),
+					dbesc($arr["batch"]),
+					dbesc($arr["notify"]),
+					dbesc($arr["poll"]),
+					dbesc($arr["confirm"]),
+					dbesc($arr["network"]),
+					dbesc($arr["alias"]),
+					dbesc($arr["pubkey"]),
+					dbesc(datetime_convert())
+				);
+		}
 
+		return $r;
 	}
 
-	$dom = $basedom->children(NAMESPACE_SALMON_ME);
+	public static function handle_from_contact($contact_id) {
+		$handle = False;
 
-	// figure out where in the DOM tree our data is hiding
+		logger("contact id is ".$contact_id, LOGGER_DEBUG);
 
-	if($dom->provenance->data)
-		$base = $dom->provenance;
-	elseif($dom->env->data)
-		$base = $dom->env;
-	elseif($dom->data)
-		$base = $dom;
+		$r = q("SELECT `network`, `addr`, `self`, `url`, `nick` FROM `contact` WHERE `id` = %d",
+		       intval($contact_id)
+		);
+		if($r) {
+			$contact = $r[0];
 
-	if(! $base) {
-		logger('mod-diaspora: unable to locate salmon data in xml ');
-		http_status_exit(400);
+			logger("contact 'self' = ".$contact['self']." 'url' = ".$contact['url'], LOGGER_DEBUG);
+
+			if($contact['addr'] != "")
+				$handle = $contact['addr'];
+			elseif(($contact['network'] === NETWORK_DFRN) || ($contact['self'] == 1)) {
+				$baseurl_start = strpos($contact['url'],'://') + 3;
+				$baseurl_length = strpos($contact['url'],'/profile') - $baseurl_start; // allows installations in a subdirectory--not sure how Diaspora will handle
+				$baseurl = substr($contact['url'], $baseurl_start, $baseurl_length);
+				$handle = $contact['nick'].'@'.$baseurl;
+			}
+		}
+
+		return $handle;
 	}
 
+	private function contact_by_handle($uid, $handle) {
+		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `addr` = '%s' LIMIT 1",
+			intval($uid),
+			dbesc($handle)
+		);
 
-	// Stash the signature away for now. We have to find their key or it won't be good for anything.
-	$signature = base64url_decode($base->sig);
+		if ($r)
+			return $r[0];
 
-	// unpack the  data
+		$handle_parts = explode("@", $handle);
+		$nurl_sql = "%%://".$handle_parts[1]."%%/profile/".$handle_parts[0];
+		$r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` LIKE '%s' LIMIT 1",
+			dbesc(NETWORK_DFRN),
+			intval($uid),
+			dbesc($nurl_sql)
+		);
+		if($r)
+			return $r[0];
 
-	// strip whitespace so our data element will return to one big base64 blob
-	$data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$base->data);
-
-
-	// stash away some other stuff for later
-
-	$type = $base->data[0]->attributes()->type[0];
-	$keyhash = $base->sig[0]->attributes()->keyhash[0];
-	$encoding = $base->encoding;
-	$alg = $base->alg;
-
-
-	$signed_data = $data  . '.' . base64url_encode($type) . '.' . base64url_encode($encoding) . '.' . base64url_encode($alg);
-
-
-	// decode the data
-	$data = base64url_decode($data);
-
-
-	if($public) {
-		$inner_decrypted = $data;
-	}
-	else {
-
-		// Decode the encrypted blob
-
-		$inner_encrypted = base64_decode($data);
-		$inner_decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $inner_encrypted, MCRYPT_MODE_CBC, $inner_iv);
-		$inner_decrypted = pkcs5_unpad($inner_decrypted);
+		return false;
 	}
 
-	if(! $author_link) {
-		logger('mod-diaspora: Could not retrieve author URI.');
-		http_status_exit(400);
-	}
-
-	// Once we have the author URI, go to the web and try to find their public key
-	// (first this will look it up locally if it is in the fcontact cache)
-	// This will also convert diaspora public key from pkcs#1 to pkcs#8
-
-	logger('mod-diaspora: Fetching key for ' . $author_link );
-	$key = get_diaspora_key($author_link);
-
-	if(! $key) {
-		logger('mod-diaspora: Could not retrieve author key.');
-		http_status_exit(400);
-	}
-
-	$verify = rsa_verify($signed_data,$signature,$key);
-
-	if(! $verify) {
-		logger('mod-diaspora: Message did not verify. Discarding.');
-		http_status_exit(400);
-	}
-
-	logger('mod-diaspora: Message verified.');
-
-	return array('message' => $inner_decrypted, 'author' => $author_link, 'key' => $key);
-
-}
-
-
-function diaspora_request($importer,$xml) {
-
-	$a = get_app();
-
-	$sender_handle = unxmlify($xml->sender_handle);
-	$recipient_handle = unxmlify($xml->recipient_handle);
-
-	if(! $sender_handle || ! $recipient_handle)
-		return;
-
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$sender_handle);
-
-	if($contact) {
+	private function post_allow($importer, $contact, $is_comment = false) {
 
 		// perhaps we were already sharing with this person. Now they're sharing with us.
 		// That makes us friends.
-
-		if($contact['rel'] == CONTACT_IS_FOLLOWER && in_array($importer['page-flags'], array(PAGE_FREELOVE))) {
+		// Normally this should have handled by getting a request - but this could get lost
+		if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
 			q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
 				intval(CONTACT_IS_FRIEND),
-				intval($contact['id']),
-				intval($importer['uid'])
+				intval($contact["id"]),
+				intval($importer["uid"])
 			);
-		}
-		// send notification
-
-		$r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1",
-			intval($importer['uid'])
-		);
-
-		if((count($r)) && (!$r[0]['hide-friends']) && (!$contact['hidden']) && intval(get_pconfig($importer['uid'],'system','post_newfriend'))) {
-			require_once('include/items.php');
-
-			$self = q("SELECT * FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1",
-				intval($importer['uid'])
-			);
-
-			// they are not CONTACT_IS_FOLLOWER anymore but that's what we have in the array
-
-			if(count($self) && $contact['rel'] == CONTACT_IS_FOLLOWER) {
-
-				$arr = array();
-				$arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $importer['uid']);
-				$arr['uid'] = $importer['uid'];
-				$arr['contact-id'] = $self[0]['id'];
-				$arr['wall'] = 1;
-				$arr['type'] = 'wall';
-				$arr['gravity'] = 0;
-				$arr['origin'] = 1;
-				$arr['author-name'] = $arr['owner-name'] = $self[0]['name'];
-				$arr['author-link'] = $arr['owner-link'] = $self[0]['url'];
-				$arr['author-avatar'] = $arr['owner-avatar'] = $self[0]['thumb'];
-				$arr['verb'] = ACTIVITY_FRIEND;
-				$arr['object-type'] = ACTIVITY_OBJ_PERSON;
-
-				$A = '[url=' . $self[0]['url'] . ']' . $self[0]['name'] . '[/url]';
-				$B = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
-				$BPhoto = '[url=' . $contact['url'] . ']' . '[img]' . $contact['thumb'] . '[/img][/url]';
-				$arr['body'] =  sprintf( t('%1$s is now friends with %2$s'), $A, $B)."\n\n\n".$Bphoto;
-
-				$arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $contact['name'] . '</title>'
-					. '<id>' . $contact['url'] . '/' . $contact['name'] . '</id>';
-				$arr['object'] .= '<link>' . xmlify('<link rel="alternate" type="text/html" href="' . $contact['url'] . '" />' . "\n");
-				$arr['object'] .= xmlify('<link rel="photo" type="image/jpeg" href="' . $contact['thumb'] . '" />' . "\n");
-				$arr['object'] .= '</link></object>' . "\n";
-				$arr['last-child'] = 1;
-
-				$arr['allow_cid'] = $user[0]['allow_cid'];
-				$arr['allow_gid'] = $user[0]['allow_gid'];
-				$arr['deny_cid']  = $user[0]['deny_cid'];
-				$arr['deny_gid']  = $user[0]['deny_gid'];
-
-				$i = item_store($arr);
-				if($i)
-				proc_run('php',"include/notifier.php","activity","$i");
-
-			}
-
+			$contact["rel"] = CONTACT_IS_FRIEND;
+			logger("defining user ".$contact["nick"]." as friend");
 		}
 
-		return;
-	}
+		if(($contact["blocked"]) || ($contact["readonly"]) || ($contact["archive"]))
+			return false;
+		if($contact["rel"] == CONTACT_IS_SHARING || $contact["rel"] == CONTACT_IS_FRIEND)
+			return true;
+		if($contact["rel"] == CONTACT_IS_FOLLOWER)
+			if(($importer["page-flags"] == PAGE_COMMUNITY) OR $is_comment)
+				return true;
 
-	$ret = find_diaspora_person_by_handle($sender_handle);
-
-
-	if((! count($ret)) || ($ret['network'] != NETWORK_DIASPORA)) {
-		logger('diaspora_request: Cannot resolve diaspora handle ' . $sender_handle . ' for ' . $recipient_handle);
-		return;
-	}
-
-	$batch = (($ret['batch']) ? $ret['batch'] : implode('/', array_slice(explode('/',$ret['url']),0,3)) . '/receive/public');
-
-
-
-	$r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`nurl`,`batch`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`)
-		VALUES ( %d, '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s',%d,%d) ",
-		intval($importer['uid']),
-		dbesc($ret['network']),
-		dbesc($ret['addr']),
-		datetime_convert(),
-		dbesc($ret['url']),
-		dbesc(normalise_link($ret['url'])),
-		dbesc($batch),
-		dbesc($ret['name']),
-		dbesc($ret['nick']),
-		dbesc($ret['photo']),
-		dbesc($ret['pubkey']),
-		dbesc($ret['notify']),
-		dbesc($ret['poll']),
-		1,
-		2
-	);
-
-	// find the contact record we just created
-
-	$contact_record = diaspora_get_contact_by_handle($importer['uid'],$sender_handle);
-
-	if(! $contact_record) {
-		logger('diaspora_request: unable to locate newly created contact record.');
-		return;
-	}
-
-	$def_gid = get_default_group($importer['uid'], $ret["network"]);
-	if (intval($def_gid)) {
-		require_once('include/group.php');
-		group_add_member($importer['uid'], '', $contact_record['id'], $def_gid);
-	}
-
-	if($importer['page-flags'] == PAGE_NORMAL) {
-
-		$hash = random_string() . (string) time();   // Generate a confirm_key
-
-		$ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime` )
-			VALUES ( %d, %d, %d, %d, '%s', '%s', '%s' )",
-			intval($importer['uid']),
-			intval($contact_record['id']),
-			0,
-			0,
-			dbesc( t('Sharing notification from Diaspora network')),
-			dbesc($hash),
-			dbesc(datetime_convert())
-		);
-	}
-	else {
-
-		// automatic friend approval
-
-		require_once('include/Photo.php');
-
-		update_contact_avatar($contact_record['photo'],$importer['uid'],$contact_record['id']);
-
-		// technically they are sharing with us (CONTACT_IS_SHARING),
-		// but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX
-		// we are going to change the relationship and make them a follower.
-
-		if($importer['page-flags'] == PAGE_FREELOVE)
-			$new_relation = CONTACT_IS_FRIEND;
-		else
-			$new_relation = CONTACT_IS_FOLLOWER;
-
-		$r = q("UPDATE `contact` SET `rel` = %d,
-			`name-date` = '%s',
-			`uri-date` = '%s',
-			`blocked` = 0,
-			`pending` = 0,
-			`writable` = 1
-			WHERE `id` = %d
-			",
-			intval($new_relation),
-			dbesc(datetime_convert()),
-			dbesc(datetime_convert()),
-			intval($contact_record['id'])
-		);
-
-		$u = q("select * from user where uid = %d limit 1",intval($importer['uid']));
-		if($u)
-			$ret = diaspora_share($u[0],$contact_record);
-	}
-
-	return;
-}
-
-function diaspora_post_allow($importer,$contact, $is_comment = false) {
-
-	// perhaps we were already sharing with this person. Now they're sharing with us.
-	// That makes us friends.
-	// Normally this should have handled by getting a request - but this could get lost
-	if($contact['rel'] == CONTACT_IS_FOLLOWER && in_array($importer['page-flags'], array(PAGE_FREELOVE))) {
-		q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
-			intval(CONTACT_IS_FRIEND),
-			intval($contact['id']),
-			intval($importer['uid'])
-		);
-		$contact['rel'] = CONTACT_IS_FRIEND;
-		logger('diaspora_post_allow: defining user '.$contact["nick"].' as friend');
-	}
-
-	if(($contact['blocked']) || ($contact['readonly']) || ($contact['archive']))
-		return false;
-	if($contact['rel'] == CONTACT_IS_SHARING || $contact['rel'] == CONTACT_IS_FRIEND)
-		return true;
-	if($contact['rel'] == CONTACT_IS_FOLLOWER)
-		if(($importer['page-flags'] == PAGE_COMMUNITY) OR $is_comment)
+		// Messages for the global users are always accepted
+		if ($importer["uid"] == 0)
 			return true;
 
-	// Messages for the global users are always accepted
-	if ($importer['uid'] == 0)
-		return true;
-
-	return false;
-}
-
-function diaspora_is_redmatrix($url) {
-	return(strstr($url, "/channel/"));
-}
-
-function diaspora_plink($addr, $guid) {
-	$r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr));
-
-	// Fallback
-	if (!$r)
-		return 'https://'.substr($addr,strpos($addr,'@')+1).'/posts/'.$guid;
-
-	// Friendica contacts are often detected as Diaspora contacts in the "fcontact" table
-	// So we try another way as well.
-	$s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"])));
-	if ($s)
-		$r[0]["network"] = $s[0]["network"];
-
-	if ($r[0]["network"] == NETWORK_DFRN)
-		return(str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/"));
-
-	if (diaspora_is_redmatrix($r[0]["url"]))
-		return $r[0]["url"]."/?f=&mid=".$guid;
-
-	return 'https://'.substr($addr,strpos($addr,'@')+1).'/posts/'.$guid;
-}
-
-function diaspora_repair_signature($signature, $handle = "", $level = 1) {
-
-	if ($signature == "")
-		return($signature);
-
-	if (base64_encode(base64_decode(base64_decode($signature))) == base64_decode($signature)) {
-		$signature = base64_decode($signature);
-		logger("Repaired double encoded signature from Diaspora/Hubzilla handle ".$handle." - level ".$level, LOGGER_DEBUG);
-
-		// Do a recursive call to be able to fix even multiple levels
-		if ($level < 10)
-			$signature = diaspora_repair_signature($signature, $handle, ++$level);
-	}
-
-	return($signature);
-}
-
-function diaspora_post($importer,$xml,$msg) {
-
-	$a = get_app();
-	$guid = notags(unxmlify($xml->guid));
-	$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-
-	if($diaspora_handle != $msg['author']) {
-		logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
-		return 202;
-	}
-
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
-	if(! $contact) {
-		logger('diaspora_post: A Contact for handle '.$diaspora_handle.' and user '.$importer['uid'].' was not found');
-		return 203;
-	}
-
-	if(! diaspora_post_allow($importer,$contact, false)) {
-		logger('diaspora_post: Ignoring this author.');
-		return 202;
-	}
-
-	$message_id = $diaspora_handle . ':' . $guid;
-	$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-		intval($importer['uid']),
-		dbesc($guid)
-	);
-	if(count($r)) {
-		logger('diaspora_post: message exists: ' . $guid);
-		return 208;
-	}
-
-	$created = unxmlify($xml->created_at);
-	$private = ((unxmlify($xml->public) == 'false') ? 1 : 0);
-
-	$body = diaspora2bb($xml->raw_message);
-
-	$datarray = array();
-
-	$datarray["object"] = json_encode($xml);
-
-	if($xml->photo->remote_photo_path AND $xml->photo->remote_photo_name)
-		$datarray["object-type"] = ACTIVITY_OBJ_PHOTO;
-	else {
-		$datarray['object-type'] = ACTIVITY_OBJ_NOTE;
-		// Add OEmbed and other information to the body
-		if (!diaspora_is_redmatrix($contact['url']))
-			$body = add_page_info_to_body($body, false, true);
-	}
-
-	$str_tags = '';
-
-	$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]';
-		}
-	}
-
-	$plink = diaspora_plink($diaspora_handle, $guid);
-
-	$datarray['uid'] = $importer['uid'];
-	$datarray['contact-id'] = $contact['id'];
-	$datarray['wall'] = 0;
-	$datarray['network'] = NETWORK_DIASPORA;
-	$datarray['verb'] = ACTIVITY_POST;
-	$datarray['guid'] = $guid;
-	$datarray['uri'] = $datarray['parent-uri'] = $message_id;
-	$datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created);
-	$datarray['private'] = $private;
-	$datarray['parent'] = 0;
-	$datarray['plink'] = $plink;
-	$datarray['owner-name'] = $contact['name'];
-	$datarray['owner-link'] = $contact['url'];
-	//$datarray['owner-avatar'] = $contact['thumb'];
-	$datarray['owner-avatar'] = ((x($contact,'thumb')) ? $contact['thumb'] : $contact['photo']);
-	$datarray['author-name'] = $contact['name'];
-	$datarray['author-link'] = $contact['url'];
-	$datarray['author-avatar'] = $contact['thumb'];
-	$datarray['body'] = $body;
-	$datarray['tag'] = $str_tags;
-	if ($xml->provider_display_name)
-		$datarray["app"] = unxmlify($xml->provider_display_name);
-	else
-		$datarray['app']  = 'Diaspora';
-
-	// if empty content it might be a photo that hasn't arrived yet. If a photo arrives, we'll make it visible.
-
-	$datarray['visible'] = ((strlen($body)) ? 1 : 0);
-
-	DiasporaFetchGuid($datarray);
-	$message_id = item_store($datarray);
-
-	logger("Stored item with message id ".$message_id, LOGGER_DEBUG);
-
-	return 201;
-
-}
-
-function DiasporaFetchGuid($item) {
-	preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi",
-		function ($match) use ($item){
-			return(DiasporaFetchGuidSub($match, $item));
-		},$item["body"]);
-}
-
-function DiasporaFetchGuidSub($match, $item) {
-	$a = get_app();
-
-	if (!diaspora_store_by_guid($match[1], $item["author-link"]))
-		diaspora_store_by_guid($match[1], $item["owner-link"]);
-}
-
-function diaspora_store_by_guid($guid, $server, $uid = 0) {
-	require_once("include/Contact.php");
-
-	$serverparts = parse_url($server);
-	$server = $serverparts["scheme"]."://".$serverparts["host"];
-
-	logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG);
-
-	$item = diaspora_fetch_message($guid, $server);
-
-	if (!$item)
 		return false;
+	}
 
-	logger("Successfully fetched item ".$guid." from ".$server, LOGGER_DEBUG);
-
-	$body = $item["body"];
-	$str_tags = $item["tag"];
-	$app = $item["app"];
-	$created = $item["created"];
-	$author = $item["author"];
-	$guid = $item["guid"];
-	$private = $item["private"];
-	$object = $item["object"];
-	$objecttype = $item["object-type"];
-
-	$message_id = $author.':'.$guid;
-	$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-		intval($uid),
-		dbesc($guid)
-	);
-	if(count($r))
-		return $r[0]["id"];
-
-	$person = find_diaspora_person_by_handle($author);
-
-	$contact_id = get_contact($person['url'], $uid);
-
-	$contacts = q("SELECT * FROM `contact` WHERE `id` = %d", intval($contact_id));
-	$importers = q("SELECT * FROM `user` WHERE `uid` = %d", intval($uid));
-
-	if ($contacts AND $importers)
-		if(!diaspora_post_allow($importers[0],$contacts[0], false)) {
-			logger('Ignoring author '.$person['url'].' for uid '.$uid);
+	private function allowed_contact_by_handle($importer, $handle, $is_comment = false) {
+		$contact = self::contact_by_handle($importer["uid"], $handle);
+		if (!$contact) {
+			logger("A Contact for handle ".$handle." and user ".$importer["uid"]." was not found");
 			return false;
-		} else
-			logger('Author '.$person['url'].' is allowed for uid '.$uid);
+		}
 
-	$datarray = array();
-	$datarray['uid'] = $uid;
-	$datarray['contact-id'] = $contact_id;
-	$datarray['wall'] = 0;
-	$datarray['network']  = NETWORK_DIASPORA;
-	$datarray['guid'] = $guid;
-	$datarray['uri'] = $datarray['parent-uri'] = $message_id;
-	$datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created);
-	$datarray['private'] = $private;
-	$datarray['parent'] = 0;
-	$datarray['plink'] = diaspora_plink($author, $guid);
-	$datarray['author-name'] = $person['name'];
-	$datarray['author-link'] = $person['url'];
-	$datarray['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']);
-	$datarray['owner-name'] = $datarray['author-name'];
-	$datarray['owner-link'] = $datarray['author-link'];
-	$datarray['owner-avatar'] = $datarray['author-avatar'];
-	$datarray['body'] = $body;
-	$datarray['tag'] = $str_tags;
-	$datarray['app']  = $app;
-	$datarray['visible'] = ((strlen($body)) ? 1 : 0);
-	$datarray['object'] = $object;
-	$datarray['object-type'] = $objecttype;
+		if (!self::post_allow($importer, $contact, $is_comment)) {
+			logger("The handle: ".$handle." is not allowed to post to user ".$importer["uid"]);
+			return false;
+		}
+		return $contact;
+	}
 
-	if ($datarray['contact-id'] == 0)
-		return false;
+	private function message_exists($uid, $guid) {
+		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($uid),
+			dbesc($guid)
+		);
 
-	DiasporaFetchGuid($datarray);
-	$message_id = item_store($datarray);
+		if($r) {
+			logger("message ".$guid." already exists for user ".$uid);
+			return true;
+		}
 
-	/// @TODO
-	/// Looking if there is some subscribe mechanism in Diaspora to get all comments for this post
-
-	return $message_id;
-}
-
-function diaspora_fetch_message($guid, $server, $level = 0) {
-
-	if ($level > 5)
-		return false;
-
-	$a = get_app();
-
-	// This will not work if the server is not a Diaspora server
-	$source_url = $server.'/p/'.$guid.'.xml';
-	$x = fetch_url($source_url);
-	if(!$x)
-		return false;
-
-	$x = str_replace(array('<activity_streams-photo>','</activity_streams-photo>'),array('<asphoto>','</asphoto>'),$x);
-	$source_xml = parse_xml_string($x,false);
-
-	$item = array();
-	$item["app"] = 'Diaspora';
-	$item["guid"] = $guid;
-	$body = "";
-
-	if ($source_xml->post->status_message->created_at)
-		$item["created"] = unxmlify($source_xml->post->status_message->created_at);
-
-	if ($source_xml->post->status_message->provider_display_name)
-		$item["app"] = unxmlify($source_xml->post->status_message->provider_display_name);
-
-	if ($source_xml->post->status_message->diaspora_handle)
-		$item["author"] = unxmlify($source_xml->post->status_message->diaspora_handle);
-
-	if ($source_xml->post->status_message->guid)
-		$item["guid"] = unxmlify($source_xml->post->status_message->guid);
-
-	$item["private"] = (unxmlify($source_xml->post->status_message->public) == 'false');
-	$item["object"] = json_encode($source_xml->post);
-
-	if(strlen($source_xml->post->asphoto->objectId) && ($source_xml->post->asphoto->objectId != 0) && ($source_xml->post->asphoto->image_url)) {
-		$item["object-type"] = ACTIVITY_OBJ_PHOTO;
-		$body = '[url=' . notags(unxmlify($source_xml->post->asphoto->image_url)) . '][img]' . notags(unxmlify($source_xml->post->asphoto->objectId)) . '[/img][/url]' . "\n";
-		$body = scale_external_images($body,false);
-	} elseif($source_xml->post->asphoto->image_url) {
-		$item["object-type"] = ACTIVITY_OBJ_PHOTO;
-		$body = '[img]' . notags(unxmlify($source_xml->post->asphoto->image_url)) . '[/img]' . "\n";
-		$body = scale_external_images($body);
-	} elseif($source_xml->post->status_message) {
-		$body = diaspora2bb($source_xml->post->status_message->raw_message);
-
-		// Checking for embedded pictures
-		if($source_xml->post->status_message->photo->remote_photo_path AND
-			$source_xml->post->status_message->photo->remote_photo_name) {
-
-			$item["object-type"] = ACTIVITY_OBJ_PHOTO;
-
-			$remote_photo_path = notags(unxmlify($source_xml->post->status_message->photo->remote_photo_path));
-			$remote_photo_name = notags(unxmlify($source_xml->post->status_message->photo->remote_photo_name));
-
-			$body = '[img]'.$remote_photo_path.$remote_photo_name.'[/img]'."\n".$body;
-
-			logger('embedded picture link found: '.$body, LOGGER_DEBUG);
-		} else
-			$item["object-type"] = ACTIVITY_OBJ_NOTE;
-
-		$body = scale_external_images($body);
-
-		// Add OEmbed and other information to the body
-		/// @TODO It could be a repeated redmatrix item
-		/// Then we shouldn't add further data to it
-		if ($item["object-type"] == ACTIVITY_OBJ_NOTE)
-			$body = add_page_info_to_body($body, false, true);
-
-	} elseif($source_xml->post->reshare) {
-		// Reshare of a reshare
-		return diaspora_fetch_message($source_xml->post->reshare->root_guid, $server, ++$level);
-	} else {
-		// Maybe it is a reshare of a photo that will be delivered at a later time (testing)
-		logger('no content found: '.print_r($source_xml,true));
 		return false;
 	}
 
-	if (trim($body) == "")
-		return false;
-
-	$item["tag"] = '';
-	$item["body"] = $body;
-
-	return $item;
-}
-
-function diaspora_reshare($importer,$xml,$msg) {
-
-	logger('diaspora_reshare: init: ' . print_r($xml,true));
-
-	$a = get_app();
-	$guid = notags(unxmlify($xml->guid));
-	$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-
-
-	if($diaspora_handle != $msg['author']) {
-		logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
-		return 202;
+	private function fetch_guid($item) {
+		preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi",
+			function ($match) use ($item){
+				return(self::fetch_guid_sub($match, $item));
+			},$item["body"]);
 	}
 
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
-	if(! $contact)
-		return;
-
-	if(! diaspora_post_allow($importer,$contact, false)) {
-		logger('diaspora_reshare: Ignoring this author: ' . $diaspora_handle . ' ' . print_r($xml,true));
-		return 202;
+	private function fetch_guid_sub($match, $item) {
+		if (!self::store_by_guid($match[1], $item["author-link"]))
+			self::store_by_guid($match[1], $item["owner-link"]);
 	}
 
-	$message_id = $diaspora_handle . ':' . $guid;
-	$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-		intval($importer['uid']),
-		dbesc($guid)
-	);
-	if(count($r)) {
-		logger('diaspora_reshare: message exists: ' . $guid);
-		return;
+	private function store_by_guid($guid, $server, $uid = 0) {
+		$serverparts = parse_url($server);
+		$server = $serverparts["scheme"]."://".$serverparts["host"];
+
+		logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG);
+
+		$msg = self::message($guid, $server);
+
+		if (!$msg)
+			return false;
+
+		logger("Successfully fetched item ".$guid." from ".$server, LOGGER_DEBUG);
+
+		// Now call the dispatcher
+		return self::dispatch_public($msg);
 	}
 
-	$orig_author = notags(unxmlify($xml->root_diaspora_id));
-	$orig_guid = notags(unxmlify($xml->root_guid));
-	$orig_url = $a->get_baseurl()."/display/".$orig_guid;
+	private function message($guid, $server, $level = 0) {
 
-	$create_original_post = false;
+		if ($level > 5)
+			return false;
 
-	// Do we already have this item?
-	$r = q("SELECT `body`, `tag`, `app`, `created`, `plink`, `object`, `object-type`, `uri` FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
-		dbesc($orig_guid),
-		dbesc(NETWORK_DIASPORA)
-	);
-	if(count($r)) {
-		logger('reshared message '.$orig_guid." reshared by ".$guid.' already exists on system.');
+		// This will work for Diaspora and newer Friendica servers
+		$source_url = $server."/p/".$guid.".xml";
+		$x = fetch_url($source_url);
+		if(!$x)
+			return false;
 
-		// Maybe it is already a reshared item?
-		// Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
-		require_once('include/api.php');
-		if (api_share_as_retweet($r[0]))
-			$r = array();
-		else {
-			$body = $r[0]["body"];
-			$str_tags = $r[0]["tag"];
-			$app = $r[0]["app"];
-			$orig_created = $r[0]["created"];
-			$orig_plink = $r[0]["plink"];
-			$orig_uri = $r[0]["uri"];
-			$object = $r[0]["object"];
-			$objecttype = $r[0]["object-type"];
+		$source_xml = parse_xml_string($x, false);
+
+		if (!is_object($source_xml))
+			return false;
+
+		if ($source_xml->post->reshare) {
+			// Reshare of a reshare - old Diaspora version
+			return self::message($source_xml->post->reshare->root_guid, $server, ++$level);
+		} elseif ($source_xml->getName() == "reshare") {
+			// Reshare of a reshare - new Diaspora version
+			return self::message($source_xml->root_guid, $server, ++$level);
+		}
+
+		$author = "";
+
+		// Fetch the author - for the old and the new Diaspora version
+		if ($source_xml->post->status_message->diaspora_handle)
+			$author = (string)$source_xml->post->status_message->diaspora_handle;
+		elseif ($source_xml->author AND ($source_xml->getName() == "status_message"))
+			$author = (string)$source_xml->author;
+
+		// If this isn't a "status_message" then quit
+		if (!$author)
+			return false;
+
+		$msg = array("message" => $x, "author" => $author);
+
+		$msg["key"] = self::key($msg["author"]);
+
+		return $msg;
+	}
+
+	private function parent_item($uid, $guid, $author, $contact) {
+		$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
+				`author-name`, `author-link`, `author-avatar`,
+				`owner-name`, `owner-link`, `owner-avatar`
+			FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($uid), dbesc($guid));
+
+		if(!$r) {
+			$result = self::store_by_guid($guid, $contact["url"], $uid);
+
+			if (!$result) {
+				$person = self::person_by_handle($author);
+				$result = self::store_by_guid($guid, $person["url"], $uid);
+			}
+
+			if ($result) {
+				logger("Fetched missing item ".$guid." - result: ".$result, LOGGER_DEBUG);
+
+				$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
+						`author-name`, `author-link`, `author-avatar`,
+						`owner-name`, `owner-link`, `owner-avatar`
+					FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+					intval($uid), dbesc($guid));
+			}
+		}
+
+		if (!$r) {
+			logger("parent item not found: parent: ".$guid." - user: ".$uid);
+			return false;
+		} else {
+			logger("parent item found: parent: ".$guid." - user: ".$uid);
+			return $r[0];
 		}
 	}
 
-	if (!count($r)) {
-		$body = "";
-		$str_tags = "";
-		$app = "";
+	private function author_contact_by_url($contact, $person, $uid) {
 
-		$server = 'https://'.substr($orig_author,strpos($orig_author,'@')+1);
-		logger('1st try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
-		$item = diaspora_fetch_message($orig_guid, $server);
-
-		if (!$item) {
-			$server = 'https://'.substr($diaspora_handle,strpos($diaspora_handle,'@')+1);
-			logger('2nd try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
-			$item = diaspora_fetch_message($orig_guid, $server);
-		}
-		if (!$item) {
-			$server = 'http://'.substr($orig_author,strpos($orig_author,'@')+1);
-			logger('3rd try: reshared message '.$orig_guid." reshared by ".$guid.' will be fetched from original server: '.$server);
-			$item = diaspora_fetch_message($orig_guid, $server);
-		}
-		if (!$item) {
-			$server = 'http://'.substr($diaspora_handle,strpos($diaspora_handle,'@')+1);
-			logger('4th try: reshared message '.$orig_guid." reshared by ".$guid." will be fetched from sharer's server: ".$server);
-			$item = diaspora_fetch_message($orig_guid, $server);
+		$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc(normalise_link($person["url"])), intval($uid));
+		if ($r) {
+			$cid = $r[0]["id"];
+			$network = $r[0]["network"];
+		} else {
+			$cid = $contact["id"];
+			$network = NETWORK_DIASPORA;
 		}
 
-		if ($item) {
-			$body = $item["body"];
-			$str_tags = $item["tag"];
-			$app = $item["app"];
-			$orig_created = $item["created"];
-			$orig_author = $item["author"];
-			$orig_guid = $item["guid"];
-			$orig_plink = diaspora_plink($orig_author, $orig_guid);
-			$orig_uri = $orig_author.':'.$orig_guid;
-			$create_original_post = ($body != "");
-			$object = $item["object"];
-			$objecttype = $item["object-type"];
-		}
+		return (array("cid" => $cid, "network" => $network));
 	}
 
-	$plink = diaspora_plink($diaspora_handle, $guid);
-
-	$person = find_diaspora_person_by_handle($orig_author);
-
-	$created = unxmlify($xml->created_at);
-	$private = ((unxmlify($xml->public) == 'false') ? 1 : 0);
-
-	$datarray = array();
-
-	$datarray['uid'] = $importer['uid'];
-	$datarray['contact-id'] = $contact['id'];
-	$datarray['wall'] = 0;
-	$datarray['network']  = NETWORK_DIASPORA;
-	$datarray['guid'] = $guid;
-	$datarray['uri'] = $datarray['parent-uri'] = $message_id;
-	$datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created);
-	$datarray['private'] = $private;
-	$datarray['parent'] = 0;
-	$datarray['plink'] = $plink;
-	$datarray['owner-name'] = $contact['name'];
-	$datarray['owner-link'] = $contact['url'];
-	$datarray['owner-avatar'] = ((x($contact,'thumb')) ? $contact['thumb'] : $contact['photo']);
-	if (!intval(get_config('system','wall-to-wall_share'))) {
-		$prefix = share_header($person['name'], $person['url'], ((x($person,'thumb')) ? $person['thumb'] : $person['photo']), $orig_guid, $orig_created, $orig_url);
-
-		$datarray['author-name'] = $contact['name'];
-		$datarray['author-link'] = $contact['url'];
-		$datarray['author-avatar'] = $contact['thumb'];
-		$datarray['body'] = $prefix.$body."[/share]";
-	} else {
-		// Let reshared messages look like wall-to-wall posts
-		$datarray['author-name'] = $person['name'];
-		$datarray['author-link'] = $person['url'];
-		$datarray['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']);
-		$datarray['body'] = $body;
+	public static function is_redmatrix($url) {
+		return(strstr($url, "/channel/"));
 	}
 
-	$datarray["object"] = json_encode($xml);
-	$datarray['object-type'] = $objecttype;
+	private function plink($addr, $guid) {
+		$r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr));
 
-	$datarray['tag'] = $str_tags;
-	$datarray['app']  = $app;
+		// Fallback
+		if (!$r)
+			return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
 
-	// if empty content it might be a photo that hasn't arrived yet. If a photo arrives, we'll make it visible. (testing)
-	$datarray['visible'] = ((strlen($body)) ? 1 : 0);
+		// Friendica contacts are often detected as Diaspora contacts in the "fcontact" table
+		// So we try another way as well.
+		$s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"])));
+		if ($s)
+			$r[0]["network"] = $s[0]["network"];
 
-	// Store the original item of a reshare
-	if ($create_original_post) {
-		require_once("include/Contact.php");
+		if ($r[0]["network"] == NETWORK_DFRN)
+			return(str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/"));
 
-		$datarray2 = $datarray;
+		if (self::is_redmatrix($r[0]["url"]))
+			return $r[0]["url"]."/?f=&mid=".$guid;
 
-		$datarray2['uid'] = 0;
-		$datarray2['contact-id'] = get_contact($person['url'], 0);
-		$datarray2['guid'] = $orig_guid;
-		$datarray2['uri'] = $datarray2['parent-uri'] = $orig_uri;
-		$datarray2['changed'] = $datarray2['created'] = $datarray2['edited'] = $datarray2['commented'] = $datarray2['received'] = datetime_convert('UTC','UTC',$orig_created);
-		$datarray2['parent'] = 0;
-		$datarray2['plink'] = $orig_plink;
-
-		$datarray2['author-name'] = $person['name'];
-		$datarray2['author-link'] = $person['url'];
-		$datarray2['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']);
-		$datarray2['owner-name'] = $datarray2['author-name'];
-		$datarray2['owner-link'] = $datarray2['author-link'];
-		$datarray2['owner-avatar'] = $datarray2['author-avatar'];
-		$datarray2['body'] = $body;
-		$datarray2["object"] = $object;
-
-		DiasporaFetchGuid($datarray2);
-		$message_id = item_store($datarray2);
-
-		logger("Store original item ".$orig_guid." under message id ".$message_id);
+		return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
 	}
 
-	DiasporaFetchGuid($datarray);
-	$message_id = item_store($datarray);
+	private function receive_account_deletion($importer, $data) {
+		$author = notags(unxmlify($data->author));
 
-	return;
-
-}
-
-
-function diaspora_asphoto($importer,$xml,$msg) {
-	logger('diaspora_asphoto called');
-
-	$a = get_app();
-	$guid = notags(unxmlify($xml->guid));
-	$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-
-	if($diaspora_handle != $msg['author']) {
-		logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
-		return 202;
-	}
-
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
-	if(! $contact)
-		return;
-
-	if(! diaspora_post_allow($importer,$contact, false)) {
-		logger('diaspora_asphoto: Ignoring this author.');
-		return 202;
-	}
-
-	$message_id = $diaspora_handle . ':' . $guid;
-	$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-		intval($importer['uid']),
-		dbesc($guid)
-	);
-	if(count($r)) {
-		logger('diaspora_asphoto: message exists: ' . $guid);
-		return;
-	}
-
-	$created = unxmlify($xml->created_at);
-	$private = ((unxmlify($xml->public) == 'false') ? 1 : 0);
-
-	if(strlen($xml->objectId) && ($xml->objectId != 0) && ($xml->image_url)) {
-		$body = '[url=' . notags(unxmlify($xml->image_url)) . '][img]' . notags(unxmlify($xml->objectId)) . '[/img][/url]' . "\n";
-		$body = scale_external_images($body,false);
-	}
-	elseif($xml->image_url) {
-		$body = '[img]' . notags(unxmlify($xml->image_url)) . '[/img]' . "\n";
-		$body = scale_external_images($body);
-	}
-	else {
-		logger('diaspora_asphoto: no photo url found.');
-		return;
-	}
-
-	$plink = diaspora_plink($diaspora_handle, $guid);
-
-	$datarray = array();
-
-	$datarray['uid'] = $importer['uid'];
-	$datarray['contact-id'] = $contact['id'];
-	$datarray['wall'] = 0;
-	$datarray['network']  = NETWORK_DIASPORA;
-	$datarray['guid'] = $guid;
-	$datarray['uri'] = $datarray['parent-uri'] = $message_id;
-	$datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert('UTC','UTC',$created);
-	$datarray['private'] = $private;
-	$datarray['parent'] = 0;
-	$datarray['plink'] = $plink;
-	$datarray['owner-name'] = $contact['name'];
-	$datarray['owner-link'] = $contact['url'];
-	//$datarray['owner-avatar'] = $contact['thumb'];
-	$datarray['owner-avatar'] = ((x($contact,'thumb')) ? $contact['thumb'] : $contact['photo']);
-	$datarray['author-name'] = $contact['name'];
-	$datarray['author-link'] = $contact['url'];
-	$datarray['author-avatar'] = $contact['thumb'];
-	$datarray['body'] = $body;
-	$datarray["object"] = json_encode($xml);
-	$datarray['object-type'] = ACTIVITY_OBJ_PHOTO;
-
-	$datarray['app']  = 'Diaspora/Cubbi.es';
-
-	DiasporaFetchGuid($datarray);
-	$message_id = item_store($datarray);
-
-	//if($message_id) {
-	//	q("update item set plink = '%s' where id = %d",
-	//		dbesc($a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id),
-	//		intval($message_id)
-	//	);
-	//}
-
-	return;
-
-}
-
-function diaspora_comment($importer,$xml,$msg) {
-
-	$a = get_app();
-	$guid = notags(unxmlify($xml->guid));
-	$parent_guid = notags(unxmlify($xml->parent_guid));
-	$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-	$target_type = notags(unxmlify($xml->target_type));
-	$text = unxmlify($xml->text);
-	$author_signature = notags(unxmlify($xml->author_signature));
-
-	$parent_author_signature = (($xml->parent_author_signature) ? notags(unxmlify($xml->parent_author_signature)) : '');
-
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$msg['author']);
-	if(! $contact) {
-		logger('diaspora_comment: cannot find contact: ' . $msg['author']);
-		return;
-	}
-
-	if(! diaspora_post_allow($importer,$contact, true)) {
-		logger('diaspora_comment: Ignoring this author.');
-		return 202;
-	}
-
-	$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-		intval($importer['uid']),
-		dbesc($guid)
-	);
-	if(count($r)) {
-		logger('diaspora_comment: our comment just got relayed back to us (or there was a guid collision) : ' . $guid);
-		return;
-	}
-
-	$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-		intval($importer['uid']),
-		dbesc($parent_guid)
-	);
-
-	if(!count($r)) {
-		$result = diaspora_store_by_guid($parent_guid, $contact['url'], $importer['uid']);
-
-		if (!$result) {
-			$person = find_diaspora_person_by_handle($diaspora_handle);
-			$result = diaspora_store_by_guid($parent_guid, $person['url'], $importer['uid']);
+		$contact = self::contact_by_handle($importer["uid"], $author);
+		if (!$contact) {
+			logger("cannot find contact for author: ".$author);
+			return false;
 		}
 
-		if ($result) {
-			logger("Fetched missing item ".$parent_guid." - result: ".$result, LOGGER_DEBUG);
+		// We now remove the contact
+		contact_remove($contact["id"]);
+		return true;
+	}
 
-			$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-				intval($importer['uid']),
-				dbesc($parent_guid)
+	private function receive_comment($importer, $sender, $data) {
+		$guid = notags(unxmlify($data->guid));
+		$parent_guid = notags(unxmlify($data->parent_guid));
+		$text = unxmlify($data->text);
+		$author = notags(unxmlify($data->author));
+
+		$contact = self::allowed_contact_by_handle($importer, $sender, true);
+		if (!$contact)
+			return false;
+
+		if (self::message_exists($importer["uid"], $guid))
+			return false;
+
+		$parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact);
+		if (!$parent_item)
+			return false;
+
+		$person = self::person_by_handle($author);
+		if (!is_array($person)) {
+			logger("unable to find author details");
+			return false;
+		}
+
+		// Fetch the contact id - if we know this contact
+		$author_contact = self::author_contact_by_url($contact, $person, $importer["uid"]);
+
+		$datarray = array();
+
+		$datarray["uid"] = $importer["uid"];
+		$datarray["contact-id"] = $author_contact["cid"];
+		$datarray["network"]  = $author_contact["network"];
+
+		$datarray["author-name"] = $person["name"];
+		$datarray["author-link"] = $person["url"];
+		$datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]);
+
+		$datarray["owner-name"] = $contact["name"];
+		$datarray["owner-link"] = $contact["url"];
+		$datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
+
+		$datarray["guid"] = $guid;
+		$datarray["uri"] = $author.":".$guid;
+
+		$datarray["type"] = "remote-comment";
+		$datarray["verb"] = ACTIVITY_POST;
+		$datarray["gravity"] = GRAVITY_COMMENT;
+		$datarray["parent-uri"] = $parent_item["uri"];
+
+		$datarray["object-type"] = ACTIVITY_OBJ_COMMENT;
+		$datarray["object"] = json_encode($data);
+
+		$datarray["body"] = diaspora2bb($text);
+
+		self::fetch_guid($datarray);
+
+		$message_id = item_store($datarray);
+
+		if ($message_id)
+			logger("Stored comment ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
+
+		// 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.
+			// 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))
 			);
+
+			// notify others
+			proc_run("php", "include/notifier.php", "comment-import", $message_id);
 		}
+
+		return $message_id;
 	}
 
-	if(! count($r)) {
-		logger('diaspora_comment: parent item not found: parent: ' . $parent_guid . ' item: ' . $guid);
-		return;
-	}
-	$parent_item = $r[0];
-
-
-	/* How Diaspora performs comment signature checking:
-
-	   - If an item has been sent by the comment author to the top-level post owner to relay on
-	     to the rest of the contacts on the top-level post, the top-level post owner should check
-	     the author_signature, then create a parent_author_signature before relaying the comment on
-	   - If an item has been relayed on by the top-level post owner, the contacts who receive it
-	     check only the parent_author_signature. Basically, they trust that the top-level post
-	     owner has already verified the authenticity of anything he/she sends out
-	   - In either case, the signature that get checked is the signature created by the person
-	     who sent the salmon
-	*/
-
-	$signed_data = $guid . ';' . $parent_guid . ';' . $text . ';' . $diaspora_handle;
-	$key = $msg['key'];
-
-	if($parent_author_signature) {
-		// If a parent_author_signature exists, then we've received the comment
-		// relayed from the top-level post owner. There's no need to check the
-		// author_signature if the parent_author_signature is valid
-
-		$parent_author_signature = base64_decode($parent_author_signature);
-
-		if(! rsa_verify($signed_data,$parent_author_signature,$key,'sha256')) {
-			logger('diaspora_comment: top-level owner verification failed.');
-			return;
-		}
-	}
-	else {
-		// If there's no parent_author_signature, then we've received the comment
-		// from the comment creator. In that case, the person is commenting on
-		// our post, so he/she must be a contact of ours and his/her public key
-		// should be in $msg['key']
-
-		$author_signature = base64_decode($author_signature);
-
-		if(! rsa_verify($signed_data,$author_signature,$key,'sha256')) {
-			logger('diaspora_comment: comment author verification failed.');
-			return;
-		}
-	}
-
-	// Phew! Everything checks out. Now create an item.
-
-	// Find the original comment author information.
-	// We need this to make sure we display the comment author
-	// information (name and avatar) correctly.
-	if(strcasecmp($diaspora_handle,$msg['author']) == 0)
-		$person = $contact;
-	else {
-		$person = find_diaspora_person_by_handle($diaspora_handle);
-
-		if(! is_array($person)) {
-			logger('diaspora_comment: unable to find author details');
-			return;
-		}
-	}
-
-	// Fetch the contact id - if we know this contact
-	$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
-		dbesc(normalise_link($person['url'])), intval($importer['uid']));
-	if ($r) {
-		$cid = $r[0]['id'];
-		$network = $r[0]['network'];
-	} else {
-		$cid = $contact['id'];
-		$network = NETWORK_DIASPORA;
-	}
-
-	$body = diaspora2bb($text);
-	$message_id = $diaspora_handle . ':' . $guid;
-
-	$datarray = array();
-
-	$datarray['uid'] = $importer['uid'];
-	$datarray['contact-id'] = $cid;
-	$datarray['type'] = 'remote-comment';
-	$datarray['wall'] = $parent_item['wall'];
-	$datarray['network']  = $network;
-	$datarray['verb'] = ACTIVITY_POST;
-	$datarray['gravity'] = GRAVITY_COMMENT;
-	$datarray['guid'] = $guid;
-	$datarray['uri'] = $message_id;
-	$datarray['parent-uri'] = $parent_item['uri'];
-
-	// No timestamps for comments? OK, we'll the use current time.
-	$datarray['changed'] = $datarray['created'] = $datarray['edited'] = datetime_convert();
-	$datarray['private'] = $parent_item['private'];
-
-	$datarray['owner-name'] = $parent_item['owner-name'];
-	$datarray['owner-link'] = $parent_item['owner-link'];
-	$datarray['owner-avatar'] = $parent_item['owner-avatar'];
-
-	$datarray['author-name'] = $person['name'];
-	$datarray['author-link'] = $person['url'];
-	$datarray['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']);
-	$datarray['body'] = $body;
-	$datarray["object"] = json_encode($xml);
-	$datarray["object-type"] = ACTIVITY_OBJ_COMMENT;
-
-	// We can't be certain what the original app is if the message is relayed.
-	if(($parent_item['origin']) && (! $parent_author_signature))
-		$datarray['app']  = 'Diaspora';
-
-	DiasporaFetchGuid($datarray);
-	$message_id = item_store($datarray);
-
-	$datarray['id'] = $message_id;
-
-	//if($message_id) {
-		//q("update item set plink = '%s' where id = %d",
-		//	//dbesc($a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id),
-		//	dbesc($a->get_baseurl().'/display/'.$datarray['guid']),
-		//	intval($message_id)
-		//);
-	//}
-
-	// If we are the origin of the parent we store the original signature and notify our followers
-	if($parent_item['origin']) {
-		$author_signature_base64 = base64_encode($author_signature);
-		$author_signature_base64 = diaspora_repair_signature($author_signature_base64, $diaspora_handle);
-
-		q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
-			intval($message_id),
-			dbesc($signed_data),
-			dbesc($author_signature_base64),
-			dbesc($diaspora_handle)
-		);
-
-		// notify others
-		proc_run('php','include/notifier.php','comment-import',$message_id);
-	}
-
-	return;
-}
-
-
-
-
-function diaspora_conversation($importer,$xml,$msg) {
-
-	$a = get_app();
-
-	$guid = notags(unxmlify($xml->guid));
-	$subject = notags(unxmlify($xml->subject));
-	$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-	$participant_handles = notags(unxmlify($xml->participant_handles));
-	$created_at = datetime_convert('UTC','UTC',notags(unxmlify($xml->created_at)));
-
-	$parent_uri = $diaspora_handle . ':' . $guid;
-
-	$messages = $xml->message;
-
-	if(! count($messages)) {
-		logger('diaspora_conversation: empty conversation');
-		return;
-	}
-
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$msg['author']);
-	if(! $contact) {
-		logger('diaspora_conversation: cannot find contact: ' . $msg['author']);
-		return;
-	}
-
-	if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) {
-		logger('diaspora_conversation: Ignoring this author.');
-		return 202;
-	}
-
-	$conversation = null;
-
-	$c = q("select * from conv where uid = %d and guid = '%s' limit 1",
-		intval($importer['uid']),
-		dbesc($guid)
-	);
-	if(count($c))
-		$conversation = $c[0];
-	else {
-		$r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ",
-			intval($importer['uid']),
-			dbesc($guid),
-			dbesc($diaspora_handle),
-			dbesc(datetime_convert('UTC','UTC',$created_at)),
-			dbesc(datetime_convert()),
-			dbesc($subject),
-			dbesc($participant_handles)
-		);
-		if($r)
-			$c = q("select * from conv where uid = %d and guid = '%s' limit 1",
-		intval($importer['uid']),
-	    dbesc($guid)
-	);
-	    if(count($c))
-	    $conversation = $c[0];
-	}
-	if(! $conversation) {
-		logger('diaspora_conversation: unable to create conversation.');
-		return;
-	}
-
-	foreach($messages as $mesg) {
+	private function receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation) {
+		$guid = notags(unxmlify($data->guid));
+		$subject = notags(unxmlify($data->subject));
+		$author = notags(unxmlify($data->author));
 
 		$reply = 0;
 
@@ -1705,1469 +930,1624 @@ function diaspora_conversation($importer,$xml,$msg) {
 		$msg_parent_author_signature = notags(unxmlify($mesg->parent_author_signature));
 		$msg_author_signature = notags(unxmlify($mesg->author_signature));
 		$msg_text = unxmlify($mesg->text);
-		$msg_created_at = datetime_convert('UTC','UTC',notags(unxmlify($mesg->created_at)));
-		$msg_diaspora_handle = notags(unxmlify($mesg->diaspora_handle));
+		$msg_created_at = datetime_convert("UTC", "UTC", notags(unxmlify($mesg->created_at)));
+
+		// "diaspora_handle" is the element name from the old version
+		// "author" is the element name from the new version
+		if ($mesg->author)
+			$msg_author = notags(unxmlify($mesg->author));
+		elseif ($mesg->diaspora_handle)
+			$msg_author = notags(unxmlify($mesg->diaspora_handle));
+		else
+			return false;
+
 		$msg_conversation_guid = notags(unxmlify($mesg->conversation_guid));
+
 		if($msg_conversation_guid != $guid) {
-			logger('diaspora_conversation: message conversation guid does not belong to the current conversation. ' . $xml);
-			continue;
+			logger("message conversation guid does not belong to the current conversation.");
+			return false;
 		}
 
 		$body = diaspora2bb($msg_text);
-		$message_id = $msg_diaspora_handle . ':' . $msg_guid;
+		$message_uri = $msg_author.":".$msg_guid;
 
-		$author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
+		$author_signed_data = $msg_guid.";".$msg_parent_guid.";".$msg_text.";".unxmlify($mesg->created_at).";".$msg_author.";".$msg_conversation_guid;
 
 		$author_signature = base64_decode($msg_author_signature);
 
-		if(strcasecmp($msg_diaspora_handle,$msg['author']) == 0) {
+		if(strcasecmp($msg_author,$msg["author"]) == 0) {
 			$person = $contact;
-			$key = $msg['key'];
-		}
-		else {
-			$person = find_diaspora_person_by_handle($msg_diaspora_handle);	
+			$key = $msg["key"];
+		} else {
+			$person = self::person_by_handle($msg_author);
 
-			if(is_array($person) && x($person,'pubkey'))
-				$key = $person['pubkey'];
+			if (is_array($person) && x($person, "pubkey"))
+				$key = $person["pubkey"];
 			else {
-				logger('diaspora_conversation: unable to find author details');
-				continue;
+				logger("unable to find author details");
+					return false;
 			}
 		}
 
-		if(! rsa_verify($author_signed_data,$author_signature,$key,'sha256')) {
-			logger('diaspora_conversation: verification failed.');
-			continue;
+		if (!rsa_verify($author_signed_data, $author_signature, $key, "sha256")) {
+			logger("verification failed.");
+			return false;
 		}
 
 		if($msg_parent_author_signature) {
-			$owner_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($mesg->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
+			$owner_signed_data = $msg_guid.";".$msg_parent_guid.";".$msg_text.";".unxmlify($mesg->created_at).";".$msg_author.";".$msg_conversation_guid;
 
 			$parent_author_signature = base64_decode($msg_parent_author_signature);
 
-			$key = $msg['key'];
+			$key = $msg["key"];
 
-			if(! rsa_verify($owner_signed_data,$parent_author_signature,$key,'sha256')) {
-				logger('diaspora_conversation: owner verification failed.');
-				continue;
+			if (!rsa_verify($owner_signed_data, $parent_author_signature, $key, "sha256")) {
+				logger("owner verification failed.");
+				return false;
 			}
 		}
 
-		$r = q("select id from mail where `uri` = '%s' limit 1",
-			dbesc($message_id)
+		$r = q("SELECT `id` FROM `mail` WHERE `uri` = '%s' LIMIT 1",
+			dbesc($message_uri)
 		);
-		if(count($r)) {
-			logger('diaspora_conversation: duplicate message already delivered.', LOGGER_DEBUG);
-			continue;
+		if($r) {
+			logger("duplicate message already delivered.", LOGGER_DEBUG);
+			return false;
 		}
 
-		q("insert into mail ( `uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`) values ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
-			intval($importer['uid']),
+		q("INSERT INTO `mail` (`uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`)
+			VALUES (%d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
+			intval($importer["uid"]),
 			dbesc($msg_guid),
-			intval($conversation['id']),
-			dbesc($person['name']),
-			dbesc($person['photo']),
-			dbesc($person['url']),
-			intval($contact['id']),
+			intval($conversation["id"]),
+			dbesc($person["name"]),
+			dbesc($person["photo"]),
+			dbesc($person["url"]),
+			intval($contact["id"]),
 			dbesc($subject),
 			dbesc($body),
 			0,
 			0,
-			dbesc($message_id),
-			dbesc($parent_uri),
+			dbesc($message_uri),
+			dbesc($author.":".$guid),
 			dbesc($msg_created_at)
 		);
 
-		q("update conv set updated = '%s' where id = %d",
+		q("UPDATE `conv` SET `updated` = '%s' WHERE `id` = %d",
 			dbesc(datetime_convert()),
-			intval($conversation['id'])
+			intval($conversation["id"])
 		);
 
 		notification(array(
-			'type' => NOTIFY_MAIL,
-			'notify_flags' => $importer['notify-flags'],
-			'language' => $importer['language'],
-			'to_name' => $importer['username'],
-			'to_email' => $importer['email'],
-			'uid' =>$importer['uid'],
-			'item' => array('subject' => $subject, 'body' => $body),
-			'source_name' => $person['name'],
-			'source_link' => $person['url'],
-			'source_photo' => $person['thumb'],
-			'verb' => ACTIVITY_POST,
-			'otype' => 'mail'
+			"type" => NOTIFY_MAIL,
+			"notify_flags" => $importer["notify-flags"],
+			"language" => $importer["language"],
+			"to_name" => $importer["username"],
+			"to_email" => $importer["email"],
+			"uid" =>$importer["uid"],
+			"item" => array("subject" => $subject, "body" => $body),
+			"source_name" => $person["name"],
+			"source_link" => $person["url"],
+			"source_photo" => $person["thumb"],
+			"verb" => ACTIVITY_POST,
+			"otype" => "mail"
 		));
 	}
 
-	return;
-}
+	private function receive_conversation($importer, $msg, $data) {
+		$guid = notags(unxmlify($data->guid));
+		$subject = notags(unxmlify($data->subject));
+		$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
+		$author = notags(unxmlify($data->author));
+		$participants = notags(unxmlify($data->participants));
 
-function diaspora_message($importer,$xml,$msg) {
+		$messages = $data->message;
 
-	$a = get_app();
-
-	$msg_guid = notags(unxmlify($xml->guid));
-	$msg_parent_guid = notags(unxmlify($xml->parent_guid));
-	$msg_parent_author_signature = notags(unxmlify($xml->parent_author_signature));
-	$msg_author_signature = notags(unxmlify($xml->author_signature));
-	$msg_text = unxmlify($xml->text);
-	$msg_created_at = datetime_convert('UTC','UTC',notags(unxmlify($xml->created_at)));
-	$msg_diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-	$msg_conversation_guid = notags(unxmlify($xml->conversation_guid));
-
-	$parent_uri = $msg_diaspora_handle . ':' . $msg_parent_guid;
-
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$msg_diaspora_handle);
-	if(! $contact) {
-		logger('diaspora_message: cannot find contact: ' . $msg_diaspora_handle);
-		return;
-	}
-
-	if(($contact['rel'] == CONTACT_IS_FOLLOWER) || ($contact['blocked']) || ($contact['readonly'])) {
-		logger('diaspora_message: Ignoring this author.');
-		return 202;
-	}
-
-	$conversation = null;
-
-	$c = q("select * from conv where uid = %d and guid = '%s' limit 1",
-		intval($importer['uid']),
-		dbesc($msg_conversation_guid)
-	);
-	if(count($c))
-		$conversation = $c[0];
-	else {
-		logger('diaspora_message: conversation not available.');
-		return;
-	}
-
-	$reply = 0;
-
-	$body = diaspora2bb($msg_text);
-	$message_id = $msg_diaspora_handle . ':' . $msg_guid;
-
-	$author_signed_data = $msg_guid . ';' . $msg_parent_guid . ';' . $msg_text . ';' . unxmlify($xml->created_at) . ';' . $msg_diaspora_handle . ';' . $msg_conversation_guid;
-
-
-	$author_signature = base64_decode($msg_author_signature);
-
-	$person = find_diaspora_person_by_handle($msg_diaspora_handle);
-	if(is_array($person) && x($person,'pubkey'))
-		$key = $person['pubkey'];
-	else {
-		logger('diaspora_message: unable to find author details');
-		return;
-	}
-
-	if(! rsa_verify($author_signed_data,$author_signature,$key,'sha256')) {
-		logger('diaspora_message: verification failed.');
-		return;
-	}
-
-	$r = q("select id from mail where `uri` = '%s' and uid = %d limit 1",
-		dbesc($message_id),
-		intval($importer['uid'])
-	);
-	if(count($r)) {
-		logger('diaspora_message: duplicate message already delivered.', LOGGER_DEBUG);
-		return;
-	}
-
-	q("insert into mail ( `uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`) values ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
-		intval($importer['uid']),
-		dbesc($msg_guid),
-		intval($conversation['id']),
-		dbesc($person['name']),
-		dbesc($person['photo']),
-		dbesc($person['url']),
-		intval($contact['id']),
-		dbesc($conversation['subject']),
-		dbesc($body),
-		0,
-		1,
-		dbesc($message_id),
-		dbesc($parent_uri),
-		dbesc($msg_created_at)
-	);
-
-	q("update conv set updated = '%s' where id = %d",
-		dbesc(datetime_convert()),
-		intval($conversation['id'])
-	);
-
-	return;
-}
-
-function diaspora_participation($importer,$xml) {
-	logger("Unsupported message type 'participation' ".print_r($xml, true));
-}
-
-function diaspora_photo($importer,$xml,$msg,$attempt=1) {
-
-	$a = get_app();
-
-	logger('diaspora_photo: init',LOGGER_DEBUG);
-
-	$remote_photo_path = notags(unxmlify($xml->remote_photo_path));
-
-	$remote_photo_name = notags(unxmlify($xml->remote_photo_name));
-
-	$status_message_guid = notags(unxmlify($xml->status_message_guid));
-
-	$guid = notags(unxmlify($xml->guid));
-
-	$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-
-	$public = notags(unxmlify($xml->public));
-
-	$created_at = notags(unxmlify($xml_created_at));
-
-	logger('diaspora_photo: status_message_guid: ' . $status_message_guid, LOGGER_DEBUG);
-
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$msg['author']);
-	if(! $contact) {
-		logger('diaspora_photo: contact record not found: ' . $msg['author'] . ' handle: ' . $diaspora_handle);
-		return;
-	}
-
-	if(! diaspora_post_allow($importer,$contact, false)) {
-		logger('diaspora_photo: Ignoring this author.');
-		return 202;
-	}
-
-	$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-		intval($importer['uid']),
-		dbesc($status_message_guid)
-	);
-
-/*	deactivated by now since it can lead to multiplicated pictures in posts.
-	if(!count($r)) {
-		$result = diaspora_store_by_guid($status_message_guid, $contact['url'], $importer['uid']);
-
-		if (!$result) {
-			$person = find_diaspora_person_by_handle($diaspora_handle);
-			$result = diaspora_store_by_guid($status_message_guid, $person['url'], $importer['uid']);
+		if (!count($messages)) {
+			logger("empty conversation");
+			return false;
 		}
 
-		if ($result) {
-			logger("Fetched missing item ".$status_message_guid." - result: ".$result, LOGGER_DEBUG);
+		$contact = self::allowed_contact_by_handle($importer, $msg["author"], true);
+		if (!$contact)
+			return false;
 
-			$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-				intval($importer['uid']),
-				dbesc($status_message_guid)
+		$conversation = null;
+
+		$c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($importer["uid"]),
+			dbesc($guid)
+		);
+		if($c)
+			$conversation = $c[0];
+		else {
+			$r = q("INSERT INTO `conv` (`uid`, `guid`, `creator`, `created`, `updated`, `subject`, `recips`)
+				VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s')",
+				intval($importer["uid"]),
+				dbesc($guid),
+				dbesc($author),
+				dbesc(datetime_convert("UTC", "UTC", $created_at)),
+				dbesc(datetime_convert()),
+				dbesc($subject),
+				dbesc($participants)
+			);
+			if($r)
+				$c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+					intval($importer["uid"]),
+					dbesc($guid)
+				);
+
+			if($c)
+				$conversation = $c[0];
+		}
+		if (!$conversation) {
+			logger("unable to create conversation.");
+			return;
+		}
+
+		foreach($messages as $mesg)
+			self::receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation);
+
+		return true;
+	}
+
+	private function construct_like_body($contact, $parent_item, $guid) {
+		$bodyverb = t('%1$s likes %2$s\'s %3$s');
+
+		$ulink = "[url=".$contact["url"]."]".$contact["name"]."[/url]";
+		$alink = "[url=".$parent_item["author-link"]."]".$parent_item["author-name"]."[/url]";
+		$plink = "[url=".App::get_baseurl()."/display/".urlencode($guid)."]".t("status")."[/url]";
+
+		return sprintf($bodyverb, $ulink, $alink, $plink);
+	}
+
+	private function construct_like_object($importer, $parent_item) {
+		$objtype = ACTIVITY_OBJ_NOTE;
+		$link = '<link rel="alternate" type="text/html" href="'.App::get_baseurl()."/display/".$importer["nickname"]."/".$parent_item["id"].'" />';
+		$parent_body = $parent_item["body"];
+
+		$xmldata = array("object" => array("type" => $objtype,
+						"local" => "1",
+						"id" => $parent_item["uri"],
+						"link" => $link,
+						"title" => "",
+						"content" => $parent_body));
+
+		return xml::from_array($xmldata, $xml, true);
+	}
+
+	private function receive_like($importer, $sender, $data) {
+		$positive = notags(unxmlify($data->positive));
+		$guid = notags(unxmlify($data->guid));
+		$parent_type = notags(unxmlify($data->parent_type));
+		$parent_guid = notags(unxmlify($data->parent_guid));
+		$author = notags(unxmlify($data->author));
+
+		// likes on comments aren't supported by Diaspora - only on posts
+		// But maybe this will be supported in the future, so we will accept it.
+		if (!in_array($parent_type, array("Post", "Comment")))
+			return false;
+
+		$contact = self::allowed_contact_by_handle($importer, $sender, true);
+		if (!$contact)
+			return false;
+
+		if (self::message_exists($importer["uid"], $guid))
+			return false;
+
+		$parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact);
+		if (!$parent_item)
+			return false;
+
+		$person = self::person_by_handle($author);
+		if (!is_array($person)) {
+			logger("unable to find author details");
+			return false;
+		}
+
+		// Fetch the contact id - if we know this contact
+		$author_contact = self::author_contact_by_url($contact, $person, $importer["uid"]);
+
+		// "positive" = "false" would be a Dislike - wich isn't currently supported by Diaspora
+		// We would accept this anyhow.
+		if ($positive === "true")
+			$verb = ACTIVITY_LIKE;
+		else
+			$verb = ACTIVITY_DISLIKE;
+
+		$datarray = array();
+
+		$datarray["uid"] = $importer["uid"];
+		$datarray["contact-id"] = $author_contact["cid"];
+		$datarray["network"]  = $author_contact["network"];
+
+		$datarray["author-name"] = $person["name"];
+		$datarray["author-link"] = $person["url"];
+		$datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]);
+
+		$datarray["owner-name"] = $contact["name"];
+		$datarray["owner-link"] = $contact["url"];
+		$datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
+
+		$datarray["guid"] = $guid;
+		$datarray["uri"] = $author.":".$guid;
+
+		$datarray["type"] = "activity";
+		$datarray["verb"] = $verb;
+		$datarray["gravity"] = GRAVITY_LIKE;
+		$datarray["parent-uri"] = $parent_item["uri"];
+
+		$datarray["object-type"] = ACTIVITY_OBJ_NOTE;
+		$datarray["object"] = self::construct_like_object($importer, $parent_item);
+
+		$datarray["body"] = self::construct_like_body($contact, $parent_item, $guid);
+
+		$message_id = item_store($datarray);
+
+		if ($message_id)
+			logger("Stored like ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
+
+		// 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.
+			// 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))
+			);
+
+			// notify others
+			proc_run("php", "include/notifier.php", "comment-import", $message_id);
+		}
+
+		return $message_id;
+	}
+
+	private function receive_message($importer, $data) {
+		$guid = notags(unxmlify($data->guid));
+		$parent_guid = notags(unxmlify($data->parent_guid));
+		$text = unxmlify($data->text);
+		$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
+		$author = notags(unxmlify($data->author));
+		$conversation_guid = notags(unxmlify($data->conversation_guid));
+
+		$contact = self::allowed_contact_by_handle($importer, $author, true);
+		if (!$contact)
+			return false;
+
+		$conversation = null;
+
+		$c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
+			intval($importer["uid"]),
+			dbesc($conversation_guid)
+		);
+		if($c)
+			$conversation = $c[0];
+		else {
+			logger("conversation not available.");
+			return false;
+		}
+
+		$reply = 0;
+
+		$body = diaspora2bb($text);
+		$message_uri = $author.":".$guid;
+
+		$person = self::person_by_handle($author);
+		if (!$person) {
+			logger("unable to find author details");
+			return false;
+		}
+
+		$r = q("SELECT `id` FROM `mail` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
+			dbesc($message_uri),
+			intval($importer["uid"])
+		);
+		if($r) {
+			logger("duplicate message already delivered.", LOGGER_DEBUG);
+			return false;
+		}
+
+		q("INSERT INTO `mail` (`uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`)
+				VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
+			intval($importer["uid"]),
+			dbesc($guid),
+			intval($conversation["id"]),
+			dbesc($person["name"]),
+			dbesc($person["photo"]),
+			dbesc($person["url"]),
+			intval($contact["id"]),
+			dbesc($conversation["subject"]),
+			dbesc($body),
+			0,
+			1,
+			dbesc($message_uri),
+			dbesc($author.":".$parent_guid),
+			dbesc($created_at)
+		);
+
+		q("UPDATE `conv` SET `updated` = '%s' WHERE `id` = %d",
+			dbesc(datetime_convert()),
+			intval($conversation["id"])
+		);
+
+		return true;
+	}
+
+	private function receive_participation($importer, $data) {
+		// I'm not sure if we can fully support this message type
+		return true;
+	}
+
+	private function receive_photo($importer, $data) {
+		// There doesn't seem to be a reason for this function, since the photo data is transmitted in the status message as well
+		return true;
+	}
+
+	private function receive_poll_participation($importer, $data) {
+		// We don't support polls by now
+		return true;
+	}
+
+	private function receive_profile($importer, $data) {
+		$author = notags(unxmlify($data->author));
+
+		$contact = self::contact_by_handle($importer["uid"], $author);
+		if (!$contact)
+			return;
+
+		$name = unxmlify($data->first_name).((strlen($data->last_name)) ? " ".unxmlify($data->last_name) : "");
+		$image_url = unxmlify($data->image_url);
+		$birthday = unxmlify($data->birthday);
+		$location = diaspora2bb(unxmlify($data->location));
+		$about = diaspora2bb(unxmlify($data->bio));
+		$gender = unxmlify($data->gender);
+		$searchable = (unxmlify($data->searchable) == "true");
+		$nsfw = (unxmlify($data->nsfw) == "true");
+		$tags = unxmlify($data->tag_string);
+
+		$tags = explode("#", $tags);
+
+		$keywords = array();
+		foreach ($tags as $tag) {
+			$tag = trim(strtolower($tag));
+			if ($tag != "")
+				$keywords[] = $tag;
+		}
+
+		$keywords = implode(", ", $keywords);
+
+		$handle_parts = explode("@", $author);
+		$nick = $handle_parts[0];
+
+		if($name === "")
+			$name = $handle_parts[0];
+
+		if( preg_match("|^https?://|", $image_url) === 0)
+			$image_url = "http://".$handle_parts[1].$image_url;
+
+		update_contact_avatar($image_url, $importer["uid"], $contact["id"]);
+
+		// Generic birthday. We don't know the timezone. The year is irrelevant.
+
+		$birthday = str_replace("1000", "1901", $birthday);
+
+		if ($birthday != "")
+			$birthday = datetime_convert("UTC", "UTC", $birthday, "Y-m-d");
+
+		// this is to prevent multiple birthday notifications in a single year
+		// if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year
+
+		if(substr($birthday,5) === substr($contact["bd"],5))
+			$birthday = $contact["bd"];
+
+		$r = q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `name-date` = '%s', `bd` = '%s',
+				`location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d AND `uid` = %d",
+			dbesc($name),
+			dbesc($nick),
+			dbesc($author),
+			dbesc(datetime_convert()),
+			dbesc($birthday),
+			dbesc($location),
+			dbesc($about),
+			dbesc($keywords),
+			dbesc($gender),
+			intval($contact["id"]),
+			intval($importer["uid"])
+		);
+
+		if ($searchable) {
+			poco_check($contact["url"], $name, NETWORK_DIASPORA, $image_url, $about, $location, $gender, $keywords, "",
+				datetime_convert(), 2, $contact["id"], $importer["uid"]);
+		}
+
+		$gcontact = array("url" => $contact["url"], "network" => NETWORK_DIASPORA, "generation" => 2,
+					"photo" => $image_url, "name" => $name, "location" => $location,
+					"about" => $about, "birthday" => $birthday, "gender" => $gender,
+					"addr" => $author, "nick" => $nick, "keywords" => $keywords,
+					"hide" => !$searchable, "nsfw" => $nsfw);
+
+		update_gcontact($gcontact);
+
+		logger("Profile of contact ".$contact["id"]." stored for user ".$importer["uid"], LOGGER_DEBUG);
+
+		return true;
+	}
+
+	private function receive_request_make_friend($importer, $contact) {
+
+		$a = get_app();
+
+		if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
+			q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
+				intval(CONTACT_IS_FRIEND),
+				intval($contact["id"]),
+				intval($importer["uid"])
 			);
 		}
+		// send notification
+
+		$r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1",
+			intval($importer["uid"])
+		);
+
+		if($r && !$r[0]["hide-friends"] && !$contact["hidden"] && intval(get_pconfig($importer["uid"], "system", "post_newfriend"))) {
+
+			$self = q("SELECT * FROM `contact` WHERE `self` AND `uid` = %d LIMIT 1",
+				intval($importer["uid"])
+			);
+
+			// they are not CONTACT_IS_FOLLOWER anymore but that's what we have in the array
+
+			if($self && $contact["rel"] == CONTACT_IS_FOLLOWER) {
+
+				$arr = array();
+				$arr["uri"] = $arr["parent-uri"] = item_new_uri($a->get_hostname(), $importer["uid"]);
+				$arr["uid"] = $importer["uid"];
+				$arr["contact-id"] = $self[0]["id"];
+				$arr["wall"] = 1;
+				$arr["type"] = 'wall';
+				$arr["gravity"] = 0;
+				$arr["origin"] = 1;
+				$arr["author-name"] = $arr["owner-name"] = $self[0]["name"];
+				$arr["author-link"] = $arr["owner-link"] = $self[0]["url"];
+				$arr["author-avatar"] = $arr["owner-avatar"] = $self[0]["thumb"];
+				$arr["verb"] = ACTIVITY_FRIEND;
+				$arr["object-type"] = ACTIVITY_OBJ_PERSON;
+
+				$A = "[url=".$self[0]["url"]."]".$self[0]["name"]."[/url]";
+				$B = "[url=".$contact["url"]."]".$contact["name"]."[/url]";
+				$BPhoto = "[url=".$contact["url"]."][img]".$contact["thumb"]."[/img][/url]";
+				$arr["body"] = sprintf(t("%1$s is now friends with %2$s"), $A, $B)."\n\n\n".$Bphoto;
+
+				$arr["object"] = "<object><type>".ACTIVITY_OBJ_PERSON."</type><title>".$contact["name"]."</title>"
+					."<id>".$contact["url"]."/".$contact["name"]."</id>";
+				$arr["object"] .= "<link>".xmlify('<link rel="alternate" type="text/html" href="'.$contact["url"].'" />'."\n");
+				$arr["object"] .= xmlify('<link rel="photo" type="image/jpeg" href="'.$contact["thumb"].'" />'."\n");
+				$arr["object"] .= "</link></object>\n";
+				$arr["last-child"] = 1;
+
+				$arr["allow_cid"] = $user[0]["allow_cid"];
+				$arr["allow_gid"] = $user[0]["allow_gid"];
+				$arr["deny_cid"]  = $user[0]["deny_cid"];
+				$arr["deny_gid"]  = $user[0]["deny_gid"];
+
+				$i = item_store($arr);
+				if($i)
+					proc_run("php", "include/notifier.php", "activity", $i);
+
+			}
+
+		}
 	}
+
+	private function receive_request($importer, $data) {
+		$author = unxmlify($data->author);
+		$recipient = unxmlify($data->recipient);
+
+		if (!$author || !$recipient)
+			return;
+
+		$contact = self::contact_by_handle($importer["uid"],$author);
+
+		if($contact) {
+
+			// perhaps we were already sharing with this person. Now they're sharing with us.
+			// That makes us friends.
+
+			self::receive_request_make_friend($importer, $contact);
+			return true;
+		}
+
+		$ret = self::person_by_handle($author);
+
+		if (!$ret || ($ret["network"] != NETWORK_DIASPORA)) {
+			logger("Cannot resolve diaspora handle ".$author." for ".$recipient);
+			return false;
+		}
+
+		$batch = (($ret["batch"]) ? $ret["batch"] : implode("/", array_slice(explode("/", $ret["url"]), 0, 3))."/receive/public");
+
+		$r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`nurl`,`batch`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`)
+			VALUES (%d, '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s',%d,%d)",
+			intval($importer["uid"]),
+			dbesc($ret["network"]),
+			dbesc($ret["addr"]),
+			datetime_convert(),
+			dbesc($ret["url"]),
+			dbesc(normalise_link($ret["url"])),
+			dbesc($batch),
+			dbesc($ret["name"]),
+			dbesc($ret["nick"]),
+			dbesc($ret["photo"]),
+			dbesc($ret["pubkey"]),
+			dbesc($ret["notify"]),
+			dbesc($ret["poll"]),
+			1,
+			2
+		);
+
+		// find the contact record we just created
+
+		$contact_record = self::contact_by_handle($importer["uid"],$author);
+
+		if (!$contact_record) {
+			logger("unable to locate newly created contact record.");
+			return;
+		}
+
+		$g = q("SELECT `def_gid` FROM `user` WHERE `uid` = %d LIMIT 1",
+			intval($importer["uid"])
+		);
+
+		if($g && intval($g[0]["def_gid"]))
+			group_add_member($importer["uid"], "", $contact_record["id"], $g[0]["def_gid"]);
+
+		if($importer["page-flags"] == PAGE_NORMAL) {
+
+			$hash = random_string().(string)time();   // Generate a confirm_key
+
+			$ret = q("INSERT INTO `intro` (`uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime`)
+				VALUES (%d, %d, %d, %d, '%s', '%s', '%s')",
+				intval($importer["uid"]),
+				intval($contact_record["id"]),
+				0,
+				0,
+				dbesc(t("Sharing notification from Diaspora network")),
+				dbesc($hash),
+				dbesc(datetime_convert())
+			);
+		} else {
+
+			// automatic friend approval
+
+			update_contact_avatar($contact_record["photo"],$importer["uid"],$contact_record["id"]);
+
+			// technically they are sharing with us (CONTACT_IS_SHARING),
+			// but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX
+			// we are going to change the relationship and make them a follower.
+
+			if($importer["page-flags"] == PAGE_FREELOVE)
+				$new_relation = CONTACT_IS_FRIEND;
+			else
+				$new_relation = CONTACT_IS_FOLLOWER;
+
+			$r = q("UPDATE `contact` SET `rel` = %d,
+				`name-date` = '%s',
+				`uri-date` = '%s',
+				`blocked` = 0,
+				`pending` = 0,
+				`writable` = 1
+				WHERE `id` = %d
+				",
+				intval($new_relation),
+				dbesc(datetime_convert()),
+				dbesc(datetime_convert()),
+				intval($contact_record["id"])
+			);
+
+			$u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"]));
+			if($u)
+				$ret = self::send_share($u[0], $contact_record);
+		}
+
+		return true;
+	}
+
+	private function original_item($guid, $orig_author, $author) {
+
+		// Do we already have this item?
+		$r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`,
+				`author-name`, `author-link`, `author-avatar`
+				FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
+			dbesc($guid));
+
+		if($r) {
+			logger("reshared message ".$guid." already exists on system.");
+
+			// Maybe it is already a reshared item?
+			// Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
+			if (self::is_reshare($r[0]["body"]))
+				$r = array();
+			else
+				return $r[0];
+		}
+
+		if (!$r) {
+			$server = "https://".substr($orig_author, strpos($orig_author, "@") + 1);
+			logger("1st try: reshared message ".$guid." will be fetched from original server: ".$server);
+			$item_id = self::store_by_guid($guid, $server);
+
+			if (!$item_id) {
+				$server = "http://".substr($orig_author, strpos($orig_author, "@") + 1);
+				logger("2nd try: reshared message ".$guid." will be fetched from original server: ".$server);
+				$item_id = self::store_by_guid($guid, $server);
+			}
+
+			// Deactivated by now since there is a risk that someone could manipulate postings through this method
+/*			if (!$item_id) {
+				$server = "https://".substr($author, strpos($author, "@") + 1);
+				logger("3rd try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
+				$item_id = self::store_by_guid($guid, $server);
+			}
+			if (!$item_id) {
+				$server = "http://".substr($author, strpos($author, "@") + 1);
+				logger("4th try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
+				$item_id = self::store_by_guid($guid, $server);
+			}
 */
-	if(!count($r)) {
-		if($attempt <= 3) {
-			q("INSERT INTO dsprphotoq (uid, msg, attempt) VALUES (%d, '%s', %d)",
-			   intval($importer['uid']),
-			   dbesc(serialize($msg)),
-			   intval($attempt + 1)
-			);
-		}
+			if ($item_id) {
+				$r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`,
+						`author-name`, `author-link`, `author-avatar`
+					FROM `item` WHERE `id` = %d AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
+					intval($item_id));
 
-		logger('diaspora_photo: attempt = ' . $attempt . '; status message not found: ' . $status_message_guid . ' for photo: ' . $guid);
-		return;
-	}
+				if ($r)
+					return $r[0];
 
-	$parent_item = $r[0];
-
-	$link_text = '[img]' . $remote_photo_path . $remote_photo_name . '[/img]' . "\n";
-
-	$link_text = scale_external_images($link_text, true,
-					   array($remote_photo_name, 'scaled_full_' . $remote_photo_name));
-
-	if(strpos($parent_item['body'],$link_text) === false) {
-
-		$parent_item['body'] = $link_text . $parent_item['body'];
-
-		$r = q("UPDATE `item` SET `body` = '%s', `visible` = 1 WHERE `id` = %d AND `uid` = %d",
-			dbesc($parent_item['body']),
-			intval($parent_item['id']),
-			intval($parent_item['uid'])
-		);
-		put_item_in_cache($parent_item, true);
-		update_thread($parent_item['id']);
-	}
-
-	return;
-}
-
-
-
-
-function diaspora_like($importer,$xml,$msg) {
-
-	$a = get_app();
-	$guid = notags(unxmlify($xml->guid));
-	$parent_guid = notags(unxmlify($xml->parent_guid));
-	$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-	$target_type = notags(unxmlify($xml->target_type));
-	$positive = notags(unxmlify($xml->positive));
-	$author_signature = notags(unxmlify($xml->author_signature));
-
-	$parent_author_signature = (($xml->parent_author_signature) ? notags(unxmlify($xml->parent_author_signature)) : '');
-
-	// likes on comments not supported here and likes on photos not supported by Diaspora
-
-//	if($target_type !== 'Post')
-//		return;
-
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$msg['author']);
-	if(! $contact) {
-		logger('diaspora_like: cannot find contact: ' . $msg['author']);
-		return;
-	}
-
-	if(! diaspora_post_allow($importer,$contact, false)) {
-		logger('diaspora_like: Ignoring this author.');
-		return 202;
-	}
-
-	$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-		intval($importer['uid']),
-		dbesc($parent_guid)
-	);
-
-	if(!count($r)) {
-		$result = diaspora_store_by_guid($parent_guid, $contact['url'], $importer['uid']);
-
-		if (!$result) {
-			$person = find_diaspora_person_by_handle($diaspora_handle);
-			$result = diaspora_store_by_guid($parent_guid, $person['url'], $importer['uid']);
-		}
-
-		if ($result) {
-			logger("Fetched missing item ".$parent_guid." - result: ".$result, LOGGER_DEBUG);
-
-			$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-				intval($importer['uid']),
-				dbesc($parent_guid)
-			);
-		}
-	}
-
-	if(! count($r)) {
-		logger('diaspora_like: parent item not found: ' . $guid);
-		return;
-	}
-
-	$parent_item = $r[0];
-
-	$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-		intval($importer['uid']),
-		dbesc($guid)
-	);
-	if(count($r)) {
-		if($positive === 'true') {
-			logger('diaspora_like: duplicate like: ' . $guid);
-			return;
-		}
-		// Note: I don't think "Like" objects with positive = "false" are ever actually used
-		// It looks like "RelayableRetractions" are used for "unlike" instead
-		if($positive === 'false') {
-			logger('diaspora_like: received a like with positive set to "false"...ignoring');
-/*			q("UPDATE `item` SET `deleted` = 1 WHERE `id` = %d AND `uid` = %d",
-				intval($r[0]['id']),
-				intval($importer['uid'])
-			);*/
-			// FIXME--actually don't unless it turns out that Diaspora does indeed send out "false" likes
-			//  send notification via proc_run()
-			return;
-		}
-	}
-	// Note: I don't think "Like" objects with positive = "false" are ever actually used
-	// It looks like "RelayableRetractions" are used for "unlike" instead
-	if($positive === 'false') {
-		logger('diaspora_like: received a like with positive set to "false"');
-		logger('diaspora_like: unlike received with no corresponding like...ignoring');
-		return;
-	}
-
-
-	/* How Diaspora performs "like" signature checking:
-
-	   - If an item has been sent by the like author to the top-level post owner to relay on
-	     to the rest of the contacts on the top-level post, the top-level post owner should check
-	     the author_signature, then create a parent_author_signature before relaying the like on
-	   - If an item has been relayed on by the top-level post owner, the contacts who receive it
-	     check only the parent_author_signature. Basically, they trust that the top-level post
-	     owner has already verified the authenticity of anything he/she sends out
-	   - In either case, the signature that get checked is the signature created by the person
-	     who sent the salmon
-	*/
-
-	// Diaspora has changed the way they are signing the likes.
-	// Just to make sure that we don't miss any likes we will check the old and the current way.
-	$old_signed_data = $guid . ';' . $target_type . ';' . $parent_guid . ';' . $positive . ';' . $diaspora_handle;
-
-	$signed_data = $positive . ';' . $guid . ';' . $target_type . ';' . $parent_guid . ';' . $diaspora_handle;
-
-	$key = $msg['key'];
-
-	if ($parent_author_signature) {
-		// If a parent_author_signature exists, then we've received the like
-		// relayed from the top-level post owner. There's no need to check the
-		// author_signature if the parent_author_signature is valid
-
-		$parent_author_signature = base64_decode($parent_author_signature);
-
-		if (!rsa_verify($signed_data,$parent_author_signature,$key,'sha256') AND
-			!rsa_verify($old_signed_data,$parent_author_signature,$key,'sha256')) {
-
-			logger('diaspora_like: top-level owner verification failed.');
-			return;
-		}
-	} else {
-		// If there's no parent_author_signature, then we've received the like
-		// from the like creator. In that case, the person is "like"ing
-		// our post, so he/she must be a contact of ours and his/her public key
-		// should be in $msg['key']
-
-		$author_signature = base64_decode($author_signature);
-
-		if (!rsa_verify($signed_data,$author_signature,$key,'sha256') AND
-			!rsa_verify($old_signed_data,$author_signature,$key,'sha256')) {
-
-			logger('diaspora_like: like creator verification failed.');
-			return;
-		}
-	}
-
-	// Phew! Everything checks out. Now create an item.
-
-	// Find the original comment author information.
-	// We need this to make sure we display the comment author
-	// information (name and avatar) correctly.
-	if(strcasecmp($diaspora_handle,$msg['author']) == 0)
-		$person = $contact;
-	else {
-		$person = find_diaspora_person_by_handle($diaspora_handle);
-
-		if(! is_array($person)) {
-			logger('diaspora_like: unable to find author details');
-			return;
-		}
-	}
-
-	$uri = $diaspora_handle . ':' . $guid;
-
-	$activity = ACTIVITY_LIKE;
-	$post_type = (($parent_item['resource-id']) ? t('photo') : t('status'));
-	$objtype = (($parent_item['resource-id']) ? ACTIVITY_OBJ_PHOTO : ACTIVITY_OBJ_NOTE );
-	$link = xmlify('<link rel="alternate" type="text/html" href="' . $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $parent_item['id'] . '" />' . "\n") ;
-	$body = $parent_item['body'];
-
-	$obj = <<< EOT
-
-	<object>
-		<type>$objtype</type>
-		<local>1</local>
-		<id>{$parent_item['uri']}</id>
-		<link>$link</link>
-		<title></title>
-		<content>$body</content>
-	</object>
-EOT;
-	$bodyverb = t('%1$s likes %2$s\'s %3$s');
-
-	// Fetch the contact id - if we know this contact
-	$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
-		dbesc(normalise_link($person['url'])), intval($importer['uid']));
-	if ($r) {
-		$cid = $r[0]['id'];
-		$network = $r[0]['network'];
-	} else {
-		$cid = $contact['id'];
-		$network = NETWORK_DIASPORA;
-	}
-
-	$arr = array();
-
-	$arr['uri'] = $uri;
-	$arr['uid'] = $importer['uid'];
-	$arr['guid'] = $guid;
-	$arr['network']  = $network;
-	$arr['contact-id'] = $cid;
-	$arr['type'] = 'activity';
-	$arr['wall'] = $parent_item['wall'];
-	$arr['gravity'] = GRAVITY_LIKE;
-	$arr['parent'] = $parent_item['id'];
-	$arr['parent-uri'] = $parent_item['uri'];
-
-	$arr['owner-name'] = $parent_item['name'];
-	$arr['owner-link'] = $parent_item['url'];
-	//$arr['owner-avatar'] = $parent_item['thumb'];
-	$arr['owner-avatar'] = ((x($parent_item,'thumb')) ? $parent_item['thumb'] : $parent_item['photo']);
-
-	$arr['author-name'] = $person['name'];
-	$arr['author-link'] = $person['url'];
-	$arr['author-avatar'] = ((x($person,'thumb')) ? $person['thumb'] : $person['photo']);
-
-	$ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
-	$alink = '[url=' . $parent_item['author-link'] . ']' . $parent_item['author-name'] . '[/url]';
-	//$plink = '[url=' . $a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $parent_item['id'] . ']' . $post_type . '[/url]';
-	$plink = '[url='.$a->get_baseurl().'/display/'.urlencode($guid).']'.$post_type.'[/url]';
-	$arr['body'] =  sprintf( $bodyverb, $ulink, $alink, $plink );
-
-	$arr['app']  = 'Diaspora';
-
-	$arr['private'] = $parent_item['private'];
-	$arr['verb'] = $activity;
-	$arr['object-type'] = $objtype;
-	$arr['object'] = $obj;
-	$arr['visible'] = 1;
-	$arr['unseen'] = 1;
-	$arr['last-child'] = 0;
-
-	$message_id = item_store($arr);
-
-
-	//if($message_id) {
-	//	q("update item set plink = '%s' where id = %d",
-	//		//dbesc($a->get_baseurl() . '/display/' . $importer['nickname'] . '/' . $message_id),
-	//		dbesc($a->get_baseurl().'/display/'.$guid),
-	//		intval($message_id)
-	//	);
-	//}
-
-	// If we are the origin of the parent we store the original signature and notify our followers
-	if($parent_item['origin']) {
-		$author_signature_base64 = base64_encode($author_signature);
-		$author_signature_base64 = diaspora_repair_signature($author_signature_base64, $diaspora_handle);
-
-		q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
-			intval($message_id),
-			dbesc($signed_data),
-			dbesc($author_signature_base64),
-			dbesc($diaspora_handle)
-		);
-
-		// notify others
-		proc_run('php','include/notifier.php','comment-import',$message_id);
-	}
-
-	return;
-}
-
-function diaspora_retraction($importer,$xml) {
-
-
-	$guid = notags(unxmlify($xml->guid));
-	$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-	$type = notags(unxmlify($xml->type));
-
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
-	if(! $contact)
-		return;
-
-	if($type === 'Person') {
-		require_once('include/Contact.php');
-		contact_remove($contact['id']);
-	} elseif($type === 'StatusMessage') {
-		$guid = notags(unxmlify($xml->post_guid));
-
-		$r = q("SELECT * FROM `item` WHERE `guid` = '%s' AND `uid` = %d AND NOT `file` LIKE '%%[%%' LIMIT 1",
-			dbesc($guid),
-			intval($importer['uid'])
-		);
-		if(count($r)) {
-			if(link_compare($r[0]['author-link'],$contact['url'])) {
-				q("UPDATE `item` SET `deleted` = 1, `changed` = '%s' WHERE `id` = %d",
-					dbesc(datetime_convert()),
-					intval($r[0]['id'])
-				);
-				delete_thread($r[0]['id'], $r[0]['parent-uri']);
 			}
 		}
-	} elseif($type === 'Post') {
-		$r = q("select * from item where guid = '%s' and uid = %d and not file like '%%[%%' limit 1",
-			dbesc('guid'),
-			intval($importer['uid'])
+		return false;
+	}
+
+	private function receive_reshare($importer, $data) {
+		$root_author = notags(unxmlify($data->root_author));
+		$root_guid = notags(unxmlify($data->root_guid));
+		$guid = notags(unxmlify($data->guid));
+		$author = notags(unxmlify($data->author));
+		$public = notags(unxmlify($data->public));
+		$created_at = notags(unxmlify($data->created_at));
+
+		$contact = self::allowed_contact_by_handle($importer, $author, false);
+		if (!$contact)
+			return false;
+
+		if (self::message_exists($importer["uid"], $guid))
+			return false;
+
+		$original_item = self::original_item($root_guid, $root_author, $author);
+		if (!$original_item)
+			return false;
+
+		$orig_url = App::get_baseurl()."/display/".$original_item["guid"];
+
+		$datarray = array();
+
+		$datarray["uid"] = $importer["uid"];
+		$datarray["contact-id"] = $contact["id"];
+		$datarray["network"]  = NETWORK_DIASPORA;
+
+		$datarray["author-name"] = $contact["name"];
+		$datarray["author-link"] = $contact["url"];
+		$datarray["author-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
+
+		$datarray["owner-name"] = $datarray["author-name"];
+		$datarray["owner-link"] = $datarray["author-link"];
+		$datarray["owner-avatar"] = $datarray["author-avatar"];
+
+		$datarray["guid"] = $guid;
+		$datarray["uri"] = $datarray["parent-uri"] = $author.":".$guid;
+
+		$datarray["verb"] = ACTIVITY_POST;
+		$datarray["gravity"] = GRAVITY_PARENT;
+
+		$datarray["object"] = json_encode($data);
+
+		$prefix = share_header($original_item["author-name"], $original_item["author-link"], $original_item["author-avatar"],
+					$original_item["guid"], $original_item["created"], $orig_url);
+		$datarray["body"] = $prefix.$original_item["body"]."[/share]";
+
+		$datarray["tag"] = $original_item["tag"];
+		$datarray["app"]  = $original_item["app"];
+
+		$datarray["plink"] = self::plink($author, $guid);
+		$datarray["private"] = (($public == "false") ? 1 : 0);
+		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
+
+		$datarray["object-type"] = $original_item["object-type"];
+
+		self::fetch_guid($datarray);
+		$message_id = item_store($datarray);
+
+		if ($message_id)
+			logger("Stored reshare ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
+
+		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::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),
+			intval($importer["uid"])
 		);
-		if(count($r)) {
-			if(link_compare($r[0]['author-link'],$contact['url'])) {
-				q("update item set `deleted` = 1, `changed` = '%s' where `id` = %d",
-					dbesc(datetime_convert()),
-					intval($r[0]['id'])
-				);
-				delete_thread($r[0]['id'], $r[0]['parent-uri']);
+		if (!$r)
+			return false;
+
+		// Only delete it if the author really fits
+		if (!link_compare($r[0]["author-link"], $person["url"])) {
+			logger("Item author ".$r[0]["author-link"]." doesn't fit to expected contact ".$person["url"], LOGGER_DEBUG);
+			return false;
+		}
+
+		// Check if the sender is the thread owner
+		$p = q("SELECT `id`, `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"]) AND !link_compare($r[0]["author-link"], $contact["url"])) {
+			logger("Thread author ".$p[0]["author-link"]." and item author ".$r[0]["author-link"]." don't fit to expected contact ".$contact["url"], LOGGER_DEBUG);
+			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
+		q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', `body` = '' , `title` = '' WHERE `id` = %d",
+			dbesc(datetime_convert()),
+			dbesc(datetime_convert()),
+			intval($r[0]["id"])
+		);
+		delete_thread($r[0]["id"], $r[0]["parent-uri"]);
+
+		logger("Deleted target ".$target_guid." (".$r[0]["id"].") from user ".$importer["uid"]." parent: ".$p[0]["id"], LOGGER_DEBUG);
+
+		// Now check if the retraction needs to be relayed by us
+		if($p[0]["origin"]) {
+
+			// 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` (`retract_iid`,`signed_text`) VALUES (%d,'%s')",
+				intval($r[0]["id"]),
+				dbesc(json_encode($data))
+			);
+			$s = q("select * from sign where retract_iid = %d", intval($r[0]["id"]));
+			logger("Stored signatur for item ".$r[0]["id"]." - ".print_r($s, true), LOGGER_DEBUG);
+
+			// notify others
+			proc_run("php", "include/notifier.php", "drop", $r[0]["id"]);
+		}
+	}
+
+	private function receive_retraction($importer, $sender, $data) {
+		$target_type = notags(unxmlify($data->target_type));
+
+		$contact = self::contact_by_handle($importer["uid"], $sender);
+		if (!$contact) {
+			logger("cannot find contact for sender: ".$sender." and user ".$importer["uid"]);
+			return false;
+		}
+
+		logger("Got retraction for ".$target_type.", sender ".$sender." and user ".$importer["uid"], LOGGER_DEBUG);
+
+		switch ($target_type) {
+			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":
+				/// @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;
+
+			default:
+				logger("Unknown target type ".$target_type);
+				return false;
+		}
+		return true;
+	}
+
+	private function receive_status_message($importer, $data) {
+
+		$raw_message = unxmlify($data->raw_message);
+		$guid = notags(unxmlify($data->guid));
+		$author = notags(unxmlify($data->author));
+		$public = notags(unxmlify($data->public));
+		$created_at = notags(unxmlify($data->created_at));
+		$provider_display_name = notags(unxmlify($data->provider_display_name));
+
+		/// @todo enable support for polls
+		//if ($data->poll) {
+		//	foreach ($data->poll AS $poll)
+		//		print_r($poll);
+		//	die("poll!\n");
+		//}
+		$contact = self::allowed_contact_by_handle($importer, $author, false);
+		if (!$contact)
+			return false;
+
+		if (self::message_exists($importer["uid"], $guid))
+			return false;
+
+		$address = array();
+		if ($data->location)
+			foreach ($data->location->children() AS $fieldname => $data)
+				$address[$fieldname] = notags(unxmlify($data));
+
+		$body = diaspora2bb($raw_message);
+
+		$datarray = array();
+
+		if ($data->photo) {
+			foreach ($data->photo AS $photo)
+				$body = "[img]".$photo->remote_photo_path.$photo->remote_photo_name."[/img]\n".$body;
+
+			$datarray["object-type"] = ACTIVITY_OBJ_PHOTO;
+		} else {
+			$datarray["object-type"] = ACTIVITY_OBJ_NOTE;
+
+			// Add OEmbed and other information to the body
+			if (!self::is_redmatrix($contact["url"]))
+				$body = add_page_info_to_body($body, false, true);
+		}
+
+		$datarray["uid"] = $importer["uid"];
+		$datarray["contact-id"] = $contact["id"];
+		$datarray["network"] = NETWORK_DIASPORA;
+
+		$datarray["author-name"] = $contact["name"];
+		$datarray["author-link"] = $contact["url"];
+		$datarray["author-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
+
+		$datarray["owner-name"] = $datarray["author-name"];
+		$datarray["owner-link"] = $datarray["author-link"];
+		$datarray["owner-avatar"] = $datarray["author-avatar"];
+
+		$datarray["guid"] = $guid;
+		$datarray["uri"] = $datarray["parent-uri"] = $author.":".$guid;
+
+		$datarray["verb"] = ACTIVITY_POST;
+		$datarray["gravity"] = GRAVITY_PARENT;
+
+		$datarray["object"] = json_encode($data);
+
+		$datarray["body"] = $body;
+
+		if ($provider_display_name != "")
+			$datarray["app"] = $provider_display_name;
+
+		$datarray["plink"] = self::plink($author, $guid);
+		$datarray["private"] = (($public == "false") ? 1 : 0);
+		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
+
+		if (isset($address["address"]))
+			$datarray["location"] = $address["address"];
+
+		if (isset($address["lat"]) AND isset($address["lng"]))
+			$datarray["coord"] = $address["lat"]." ".$address["lng"];
+
+		self::fetch_guid($datarray);
+		$message_id = item_store($datarray);
+
+		if ($message_id)
+			logger("Stored item ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
+
+		return $message_id;
+	}
+
+	/******************************************************************************************
+	 * Here are all the functions that are needed to transmit data with the Diaspora protocol *
+	 ******************************************************************************************/
+
+	private function my_handle($me) {
+		if ($contact["addr"] != "")
+			return $contact["addr"];
+
+		// Normally we should have a filled "addr" field - but in the past this wasn't the case
+		// So - just in case - we build the the address here.
+		return $me["nickname"]."@".substr(App::get_baseurl(), strpos(App::get_baseurl(),"://") + 3);
+	}
+
+	private function build_public_message($msg, $user, $contact, $prvkey, $pubkey) {
+
+		logger("Message: ".$msg, LOGGER_DATA);
+
+		$handle = self::my_handle($user);
+
+		$b64url_data = base64url_encode($msg);
+
+		$data = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data);
+
+		$type = "application/xml";
+		$encoding = "base64url";
+		$alg = "RSA-SHA256";
+
+		$signable_data = $data.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg);
+
+		$signature = rsa_sign($signable_data,$prvkey);
+		$sig = base64url_encode($signature);
+
+		$xmldata = array("diaspora" => array("header" => array("author_id" => $handle),
+						"me:env" => array("me:encoding" => "base64url",
+								"me:alg" => "RSA-SHA256",
+								"me:data" => $data,
+								"@attributes" => array("type" => "application/xml"),
+								"me:sig" => $sig)));
+
+		$namespaces = array("" => "https://joindiaspora.com/protocol",
+				"me" => "http://salmon-protocol.org/ns/magic-env");
+
+		$magic_env = xml::from_array($xmldata, $xml, false, $namespaces);
+
+		logger("magic_env: ".$magic_env, LOGGER_DATA);
+		return $magic_env;
+	}
+
+	private function build_private_message($msg, $user, $contact, $prvkey, $pubkey) {
+
+		logger("Message: ".$msg, LOGGER_DATA);
+
+		// without a public key nothing will work
+
+		if (!$pubkey) {
+			logger("pubkey missing: contact id: ".$contact["id"]);
+			return false;
+		}
+
+		$inner_aes_key = random_string(32);
+		$b_inner_aes_key = base64_encode($inner_aes_key);
+		$inner_iv = random_string(16);
+		$b_inner_iv = base64_encode($inner_iv);
+
+		$outer_aes_key = random_string(32);
+		$b_outer_aes_key = base64_encode($outer_aes_key);
+		$outer_iv = random_string(16);
+		$b_outer_iv = base64_encode($outer_iv);
+
+		$handle = self::my_handle($user);
+
+		$padded_data = pkcs5_pad($msg,16);
+		$inner_encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $padded_data, MCRYPT_MODE_CBC, $inner_iv);
+
+		$b64_data = base64_encode($inner_encrypted);
+
+
+		$b64url_data = base64url_encode($b64_data);
+		$data = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data);
+
+		$type = "application/xml";
+		$encoding = "base64url";
+		$alg = "RSA-SHA256";
+
+		$signable_data = $data.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg);
+
+		$signature = rsa_sign($signable_data,$prvkey);
+		$sig = base64url_encode($signature);
+
+		$xmldata = array("decrypted_header" => array("iv" => $b_inner_iv,
+							"aes_key" => $b_inner_aes_key,
+							"author_id" => $handle));
+
+		$decrypted_header = xml::from_array($xmldata, $xml, true);
+		$decrypted_header = pkcs5_pad($decrypted_header,16);
+
+		$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $outer_aes_key, $decrypted_header, MCRYPT_MODE_CBC, $outer_iv);
+
+		$outer_json = json_encode(array("iv" => $b_outer_iv, "key" => $b_outer_aes_key));
+
+		$encrypted_outer_key_bundle = "";
+		openssl_public_encrypt($outer_json, $encrypted_outer_key_bundle, $pubkey);
+
+		$b64_encrypted_outer_key_bundle = base64_encode($encrypted_outer_key_bundle);
+
+		logger("outer_bundle: ".$b64_encrypted_outer_key_bundle." key: ".$pubkey, LOGGER_DATA);
+
+		$encrypted_header_json_object = json_encode(array("aes_key" => base64_encode($encrypted_outer_key_bundle),
+								"ciphertext" => base64_encode($ciphertext)));
+		$cipher_json = base64_encode($encrypted_header_json_object);
+
+		$xmldata = array("diaspora" => array("encrypted_header" => $cipher_json,
+						"me:env" => array("me:encoding" => "base64url",
+								"me:alg" => "RSA-SHA256",
+								"me:data" => $data,
+								"@attributes" => array("type" => "application/xml"),
+								"me:sig" => $sig)));
+
+		$namespaces = array("" => "https://joindiaspora.com/protocol",
+				"me" => "http://salmon-protocol.org/ns/magic-env");
+
+		$magic_env = xml::from_array($xmldata, $xml, false, $namespaces);
+
+		logger("magic_env: ".$magic_env, LOGGER_DATA);
+		return $magic_env;
+	}
+
+	private function build_message($msg, $user, $contact, $prvkey, $pubkey, $public = false) {
+
+		if ($public)
+			$magic_env =  self::build_public_message($msg,$user,$contact,$prvkey,$pubkey);
+		else
+			$magic_env =  self::build_private_message($msg,$user,$contact,$prvkey,$pubkey);
+
+		// The data that will be transmitted is double encoded via "urlencode", strange ...
+		$slap = "xml=".urlencode(urlencode($magic_env));
+		return $slap;
+	}
+
+	private function signature($owner, $message) {
+		$sigmsg = $message;
+		unset($sigmsg["author_signature"]);
+		unset($sigmsg["parent_author_signature"]);
+
+		$signed_text = implode(";", $sigmsg);
+
+		return base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
+	}
+
+	public static function transmit($owner, $contact, $slap, $public_batch, $queue_run=false, $guid = "") {
+
+		$a = get_app();
+
+		$enabled = intval(get_config("system", "diaspora_enabled"));
+		if(!$enabled)
+			return 200;
+
+		$logid = random_string(4);
+		$dest_url = (($public_batch) ? $contact["batch"] : $contact["notify"]);
+		if (!$dest_url) {
+			logger("no url for contact: ".$contact["id"]." batch mode =".$public_batch);
+			return 0;
+		}
+
+		logger("transmit: ".$logid."-".$guid." ".$dest_url);
+
+		if (!$queue_run && was_recently_delayed($contact["id"])) {
+			$return_code = 0;
+		} else {
+			if (!intval(get_config("system", "diaspora_test"))) {
+				post_url($dest_url."/", $slap);
+				$return_code = $a->get_curl_code();
+			} else {
+				logger("test_mode");
+				return 200;
 			}
 		}
-	}
 
-	return 202;
-	// NOTREACHED
-}
+		logger("transmit: ".$logid."-".$guid." returns: ".$return_code);
 
-function diaspora_signed_retraction($importer,$xml,$msg) {
+		if(!$return_code || (($return_code == 503) && (stristr($a->get_curl_headers(), "retry-after")))) {
+			logger("queue message");
 
-
-	$guid = notags(unxmlify($xml->target_guid));
-	$diaspora_handle = notags(unxmlify($xml->sender_handle));
-	$type = notags(unxmlify($xml->target_type));
-	$sig = notags(unxmlify($xml->target_author_signature));
-
-	$parent_author_signature = (($xml->parent_author_signature) ? notags(unxmlify($xml->parent_author_signature)) : '');
-
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
-	if(! $contact) {
-		logger('diaspora_signed_retraction: no contact ' . $diaspora_handle . ' for ' . $importer['uid']);
-		return;
-	}
-
-
-	$signed_data = $guid . ';' . $type ;
-	$key = $msg['key'];
-
-	/* How Diaspora performs relayable_retraction signature checking:
-
-	   - If an item has been sent by the item author to the top-level post owner to relay on
-	     to the rest of the contacts on the top-level post, the top-level post owner checks
-	     the author_signature, then creates a parent_author_signature before relaying the item on
-	   - If an item has been relayed on by the top-level post owner, the contacts who receive it
-	     check only the parent_author_signature. Basically, they trust that the top-level post
-	     owner has already verified the authenticity of anything he/she sends out
-	   - In either case, the signature that get checked is the signature created by the person
-	     who sent the salmon
-	*/
-
-	if($parent_author_signature) {
-
-		$parent_author_signature = base64_decode($parent_author_signature);
-
-		if(! rsa_verify($signed_data,$parent_author_signature,$key,'sha256')) {
-			logger('diaspora_signed_retraction: top-level post owner verification failed');
-			return;
+			$r = q("SELECT `id` FROM `queue` WHERE `cid` = %d AND `network` = '%s' AND `content` = '%s' AND `batch` = %d LIMIT 1",
+				intval($contact["id"]),
+				dbesc(NETWORK_DIASPORA),
+				dbesc($slap),
+				intval($public_batch)
+			);
+			if($r) {
+				logger("add_to_queue ignored - identical item already in queue");
+			} else {
+				// queue message for redelivery
+				add_to_queue($contact["id"], NETWORK_DIASPORA, $slap, $public_batch);
+			}
 		}
 
-	} else {
-
-		$sig_decode = base64_decode($sig);
-
-		if(! rsa_verify($signed_data,$sig_decode,$key,'sha256')) {
-			logger('diaspora_signed_retraction: retraction owner verification failed.' . print_r($msg,true));
-			return;
-		}
+		return(($return_code) ? $return_code : (-1));
 	}
 
-	if($type === 'StatusMessage' || $type === 'Comment' || $type === 'Like') {
-		$r = q("select * from item where guid = '%s' and uid = %d and not file like '%%[%%' limit 1",
-			dbesc($guid),
-			intval($importer['uid'])
+
+	private function build_and_transmit($owner, $contact, $type, $message, $public_batch = false, $guid = "", $spool = false) {
+
+		$data = array("XML" => array("post" => array($type => $message)));
+
+		$msg = xml::from_array($data, $xml);
+
+		logger('message: '.$msg, LOGGER_DATA);
+		logger('send guid '.$guid, LOGGER_DEBUG);
+
+		$slap = self::build_message($msg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch);
+
+		if ($spool) {
+			add_to_queue($contact['id'], NETWORK_DIASPORA, $slap, $public_batch);
+			return true;
+		} else
+			$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_share($owner,$contact) {
+
+		$message = array("sender_handle" => self::my_handle($owner),
+				"recipient_handle" => $contact["addr"]);
+
+		return self::build_and_transmit($owner, $contact, "request", $message);
+	}
+
+	public static function send_unshare($owner,$contact) {
+
+		$message = array("post_guid" => $owner["guid"],
+				"diaspora_handle" => self::my_handle($owner),
+				"type" => "Person");
+
+		return self::build_and_transmit($owner, $contact, "retraction", $message);
+	}
+
+	public static function is_reshare($body) {
+		$body = trim($body);
+
+		// Skip if it isn't a pure repeated messages
+		// Does it start with a share?
+		if (strpos($body, "[share") > 0)
+			return(false);
+
+		// Does it end with a share?
+		if (strlen($body) > (strrpos($body, "[/share]") + 8))
+			return(false);
+
+		$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
+		// Skip if there is no shared message in there
+		if ($body == $attributes)
+			return(false);
+
+		$guid = "";
+		preg_match("/guid='(.*?)'/ism", $attributes, $matches);
+		if ($matches[1] != "")
+			$guid = $matches[1];
+
+		preg_match('/guid="(.*?)"/ism', $attributes, $matches);
+		if ($matches[1] != "")
+			$guid = $matches[1];
+
+		if ($guid != "") {
+			$r = q("SELECT `contact-id` FROM `item` WHERE `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1",
+				dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA);
+			if ($r) {
+				$ret= array();
+				$ret["root_handle"] = self::handle_from_contact($r[0]["contact-id"]);
+				$ret["root_guid"] = $guid;
+				return($ret);
+			}
+		}
+
+		$profile = "";
+		preg_match("/profile='(.*?)'/ism", $attributes, $matches);
+		if ($matches[1] != "")
+			$profile = $matches[1];
+
+		preg_match('/profile="(.*?)"/ism', $attributes, $matches);
+		if ($matches[1] != "")
+			$profile = $matches[1];
+
+		$ret= array();
+
+		$ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile);
+		if (($ret["root_handle"] == $profile) OR ($ret["root_handle"] == ""))
+			return(false);
+
+		$link = "";
+		preg_match("/link='(.*?)'/ism", $attributes, $matches);
+		if ($matches[1] != "")
+			$link = $matches[1];
+
+		preg_match('/link="(.*?)"/ism', $attributes, $matches);
+		if ($matches[1] != "")
+			$link = $matches[1];
+
+		$ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link);
+		if (($ret["root_guid"] == $link) OR ($ret["root_guid"] == ""))
+			return(false);
+		return($ret);
+	}
+
+	public static function send_status($item, $owner, $contact, $public_batch = false) {
+
+		$myaddr = self::my_handle($owner);
+
+		$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"];
+			$body = $item["body"];
+
+			// convert to markdown
+			$body = html_entity_decode(bb2diaspora($body));
+
+			// Adding the title
+			if(strlen($title))
+				$body = "## ".html_entity_decode($title)."\n\n".$body;
+
+			if ($item["attach"]) {
+				$cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism', $item["attach"], $matches, PREG_SET_ORDER);
+				if(cnt) {
+					$body .= "\n".t("Attachments:")."\n";
+					foreach($matches as $mtch)
+						$body .= "[".$mtch[3]."](".$mtch[1].")\n";
+				}
+			}
+
+			$location = array();
+
+			if ($item["location"] != "")
+				$location["address"] = $item["location"];
+
+			if ($item["coord"] != "") {
+				$coord = explode(" ", $item["coord"]);
+				$location["lat"] = $coord[0];
+				$location["lng"] = $coord[1];
+			}
+
+			$message = array("raw_message" => $body,
+					"location" => $location,
+					"guid" => $item["guid"],
+					"diaspora_handle" => $myaddr,
+					"public" => $public,
+					"created_at" => $created,
+					"provider_display_name" => $item["app"]);
+
+			if (count($location) == 0)
+				unset($message["location"]);
+
+			$type = "status_message";
+		}
+
+		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
+	}
+
+	private function construct_like($item, $owner) {
+
+		$myaddr = self::my_handle($owner);
+
+		$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
+			dbesc($item["thr-parent"]));
+		if(!$p)
+			return false;
+
+		$parent = $p[0];
+
+		$target_type = ($parent["uri"] === $parent["parent-uri"] ? "Post" : "Comment");
+		$positive = "true";
+
+		return(array("positive" => $positive,
+				"guid" => $item["guid"],
+				"target_type" => $target_type,
+				"parent_guid" => $parent["guid"],
+				"author_signature" => $authorsig,
+				"diaspora_handle" => $myaddr));
+	}
+
+	private function construct_comment($item, $owner) {
+
+		$myaddr = self::my_handle($owner);
+
+		$p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1",
+			intval($item["parent"]),
+			intval($item["parent"])
 		);
-		if(count($r)) {
-			if(link_compare($r[0]['author-link'],$contact['url'])) {
-				q("update item set `deleted` = 1, `edited` = '%s', `changed` = '%s', `body` = '' , `title` = '' where `id` = %d",
-					dbesc(datetime_convert()),
-					dbesc(datetime_convert()),
-					intval($r[0]['id'])
-				);
-				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']) {
-						q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
-							$r[0]['id'],
-							dbesc($signed_data),
-							dbesc($sig),
-							dbesc($diaspora_handle)
-						);
+		if (!$p)
+			return false;
 
-						// the existence of parent_author_signature would have meant the parent_author or owner
-						// is already relaying.
-						logger('diaspora_signed_retraction: relaying relayable_retraction');
+		$parent = $p[0];
 
-						proc_run('php','include/notifier.php','drop',$r[0]['id']);
+		$text = html_entity_decode(bb2diaspora($item["body"]));
+
+		return(array("guid" => $item["guid"],
+				"parent_guid" => $parent["guid"],
+				"author_signature" => "",
+				"text" => $text,
+				"diaspora_handle" => $myaddr));
+	}
+
+	public static function send_followup($item,$owner,$contact,$public_batch = false) {
+
+		if($item['verb'] === ACTIVITY_LIKE) {
+			$message = self::construct_like($item, $owner);
+			$type = "like";
+		} else {
+			$message = self::construct_comment($item, $owner);
+			$type = "comment";
+		}
+
+		if (!$message)
+			return false;
+
+		$message["author_signature"] = self::signature($owner, $message);
+
+		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
+	}
+
+	private function message_from_signatur($item, $signature) {
+
+		// Split the signed text
+		$signed_parts = explode(";", $signature['signed_text']);
+
+		if ($item["deleted"])
+			$message = array("parent_author_signature" => "",
+					"target_guid" => $signed_parts[0],
+					"target_type" => $signed_parts[1],
+					"sender_handle" => $signature['signer'],
+					"target_author_signature" => $signature['signature']);
+		elseif ($item['verb'] === ACTIVITY_LIKE)
+			$message = array("positive" => $signed_parts[0],
+					"guid" => $signed_parts[1],
+					"target_type" => $signed_parts[2],
+					"parent_guid" => $signed_parts[3],
+					"parent_author_signature" => "",
+					"author_signature" => $signature['signature'],
+					"diaspora_handle" => $signed_parts[4]);
+		else {
+			// Remove the comment guid
+			$guid = array_shift($signed_parts);
+
+			// Remove the parent guid
+			$parent_guid = array_shift($signed_parts);
+
+			// Remove the handle
+			$handle = array_pop($signed_parts);
+
+			// Glue the parts together
+			$text = implode(";", $signed_parts);
+
+			$message = array("guid" => $guid,
+					"parent_guid" => $parent_guid,
+					"parent_author_signature" => "",
+					"author_signature" => $signature['signature'],
+					"text" => implode(";", $signed_parts),
+					"diaspora_handle" => $handle);
+		}
+		return $message;
+	}
+
+	public static function send_relay($item, $owner, $contact, $public_batch = false) {
+
+		if ($item["deleted"]) {
+			$sql_sign_id = "retract_iid";
+			$type = "relayable_retraction";
+		} elseif ($item['verb'] === ACTIVITY_LIKE) {
+			$sql_sign_id = "iid";
+			$type = "like";
+		} else {
+			$sql_sign_id = "iid";
+			$type = "comment";
+		}
+
+		logger("Got relayable data ".$type." for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG);
+
+		// fetch the original signature
+
+		$r = q("SELECT `signed_text`, `signature`, `signer` FROM `sign` WHERE `".$sql_sign_id."` = %d LIMIT 1",
+			intval($item["id"]));
+
+		if (!$r)
+			return self::send_followup($item, $owner, $contact, $public_batch);
+
+		$signature = $r[0];
+
+		// Old way - is used by the internal Friendica functions
+		/// @todo Change all signatur storing functions to the new format
+		if ($signature['signed_text'] AND $signature['signature'] AND $signature['signer'])
+			$message = self::message_from_signatur($item, $signature);
+		else {// New way
+			$msg = json_decode($signature['signed_text'], true);
+
+			$message = array();
+			foreach ($msg AS $field => $data) {
+				if (!$item["deleted"]) {
+					if ($field == "author")
+						$field = "diaspora_handle";
+					if ($field == "parent_type")
+						$field = "target_type";
+				}
+
+				$message[$field] = $data;
+			}
+		}
+
+		if ($item["deleted"]) {
+			$signed_text = $message["target_guid"].';'.$message["target_type"];
+			$message["parent_author_signature"] = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
+		} else
+			$message["parent_author_signature"] = self::signature($owner, $message);
+
+		logger("Relayed data ".print_r($message, true), LOGGER_DEBUG);
+
+		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
+	}
+
+	public static function send_retraction($item, $owner, $contact, $public_batch = false) {
+
+		$myaddr = self::my_handle($owner);
+
+		// Check whether the retraction is for a top-level post or whether it's a relayable
+		if ($item["uri"] !== $item["parent-uri"]) {
+			$msg_type = "relayable_retraction";
+			$target_type = (($item["verb"] === ACTIVITY_LIKE) ? "Like" : "Comment");
+		} else {
+			$msg_type = "signed_retraction";
+			$target_type = "StatusMessage";
+		}
+
+		$signed_text = $item["guid"].";".$target_type;
+
+		$message = array("target_guid" => $item['guid'],
+				"target_type" => $target_type,
+				"sender_handle" => $myaddr,
+				"target_author_signature" => base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')));
+
+		return self::build_and_transmit($owner, $contact, $msg_type, $message, $public_batch, $item["guid"]);
+	}
+
+	public static function send_mail($item, $owner, $contact) {
+
+		$myaddr = self::my_handle($owner);
+
+		$r = q("SELECT * FROM `conv` WHERE `id` = %d AND `uid` = %d LIMIT 1",
+			intval($item["convid"]),
+			intval($item["uid"])
+		);
+
+		if (!$r) {
+			logger("conversation not found.");
+			return;
+		}
+		$cnv = $r[0];
+
+		$conv = array(
+			"guid" => $cnv["guid"],
+			"subject" => $cnv["subject"],
+			"created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d H:i:s \U\T\C'),
+			"diaspora_handle" => $cnv["creator"],
+			"participant_handles" => $cnv["recips"]
+		);
+
+		$body = bb2diaspora($item["body"]);
+		$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'];
+		$sig = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
+
+		$msg = array(
+			"guid" => $item["guid"],
+			"parent_guid" => $cnv["guid"],
+			"parent_author_signature" => $sig,
+			"author_signature" => $sig,
+			"text" => $body,
+			"created_at" => $created,
+			"diaspora_handle" => $myaddr,
+			"conversation_guid" => $cnv["guid"]
+		);
+
+		if ($item["reply"]) {
+			$message = $msg;
+			$type = "message";
+		} else {
+			$message = array("guid" => $cnv["guid"],
+					"subject" => $cnv["subject"],
+					"created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d H:i:s \U\T\C'),
+					"message" => $msg,
+					"diaspora_handle" => $cnv["creator"],
+					"participant_handles" => $cnv["recips"]);
+
+			$type = "conversation";
+		}
+
+		return self::build_and_transmit($owner, $contact, $type, $message, false, $item["guid"]);
+	}
+
+	public static function send_profile($uid) {
+
+		if (!$uid)
+			return;
+
+		$recips = q("SELECT `id`,`name`,`network`,`pubkey`,`notify` FROM `contact` WHERE `network` = '%s'
+			AND `uid` = %d AND `rel` != %d",
+			dbesc(NETWORK_DIASPORA),
+			intval($uid),
+			intval(CONTACT_IS_SHARING)
+		);
+		if (!$recips)
+			return;
+
+		$r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `user`.*, `user`.`prvkey` AS `uprvkey`, `contact`.`addr`
+			FROM `profile`
+			INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
+			INNER JOIN `contact` ON `profile`.`uid` = `contact`.`uid`
+			WHERE `user`.`uid` = %d AND `profile`.`is-default` AND `contact`.`self` LIMIT 1",
+			intval($uid)
+		);
+
+		if (!$r)
+			return;
+
+		$profile = $r[0];
+
+		$handle = $profile["addr"];
+		$first = ((strpos($profile['name'],' ')
+			? trim(substr($profile['name'],0,strpos($profile['name'],' '))) : $profile['name']));
+		$last = (($first === $profile['name']) ? '' : trim(substr($profile['name'], strlen($first))));
+		$large = App::get_baseurl().'/photo/custom/300/'.$profile['uid'].'.jpg';
+		$medium = App::get_baseurl().'/photo/custom/100/'.$profile['uid'].'.jpg';
+		$small = App::get_baseurl().'/photo/custom/50/'  .$profile['uid'].'.jpg';
+		$searchable = (($profile['publish'] && $profile['net-publish']) ? 'true' : 'false');
+
+		if ($searchable === 'true') {
+			$dob = '1000-00-00';
+
+			if (($profile['dob']) && ($profile['dob'] != '0000-00-00'))
+				$dob = ((intval($profile['dob'])) ? intval($profile['dob']) : '1000') .'-'. datetime_convert('UTC','UTC',$profile['dob'],'m-d');
+
+			$about = $profile['about'];
+			$about = strip_tags(bbcode($about));
+
+			$location = formatted_location($profile);
+			$tags = '';
+			if ($profile['pub_keywords']) {
+				$kw = str_replace(',',' ',$profile['pub_keywords']);
+				$kw = str_replace('  ',' ',$kw);
+				$arr = explode(' ',$profile['pub_keywords']);
+				if (count($arr)) {
+					for($x = 0; $x < 5; $x ++) {
+						if (trim($arr[$x]))
+							$tags .= '#'. trim($arr[$x]) .' ';
 					}
 				}
 			}
+			$tags = trim($tags);
 		}
-	}
-	else
-		logger('diaspora_signed_retraction: unknown type: ' . $type);
 
-	return 202;
-	// NOTREACHED
-}
-
-function diaspora_profile($importer,$xml,$msg) {
-
-	$a = get_app();
-	$diaspora_handle = notags(unxmlify($xml->diaspora_handle));
-
-
-	if($diaspora_handle != $msg['author']) {
-		logger('diaspora_post: Potential forgery. Message handle is not the same as envelope sender.');
-		return 202;
-	}
-
-	$contact = diaspora_get_contact_by_handle($importer['uid'],$diaspora_handle);
-	if(! $contact)
-		return;
-
-	//if($contact['blocked']) {
-	//	logger('diaspora_post: Ignoring this author.');
-	//	return 202;
-	//}
-
-	$name = unxmlify($xml->first_name) . ((strlen($xml->last_name)) ? ' ' . unxmlify($xml->last_name) : '');
-	$image_url = unxmlify($xml->image_url);
-	$birthday = unxmlify($xml->birthday);
-	$location = diaspora2bb(unxmlify($xml->location));
-	$about = diaspora2bb(unxmlify($xml->bio));
-	$gender = unxmlify($xml->gender);
-	$searchable = (unxmlify($xml->searchable) == "true");
-	$nsfw = (unxmlify($xml->nsfw) == "true");
-	$tags = unxmlify($xml->tag_string);
-
-	$tags = explode("#", $tags);
-
-	$keywords = array();
-	foreach ($tags as $tag) {
-		$tag = trim(strtolower($tag));
-		if ($tag != "")
-			$keywords[] = $tag;
-	}
-
-	$keywords = implode(", ", $keywords);
-
-	$handle_parts = explode("@", $diaspora_handle);
-	$nick = $handle_parts[0];
-
-	if($name === '') {
-		$name = $handle_parts[0];
-	}
-
-	if( preg_match("|^https?://|", $image_url) === 0) {
-		$image_url = "http://" . $handle_parts[1] . $image_url;
-	}
-
-/*	$r = q("SELECT DISTINCT ( `resource-id` ) FROM `photo` WHERE  `uid` = %d AND `contact-id` = %d AND `album` = 'Contact Photos' ",
-		intval($importer['uid']),
-		intval($contact['id'])
-	);
-	$oldphotos = ((count($r)) ? $r : null);*/
-
-	require_once('include/Photo.php');
-
-	update_contact_avatar($image_url,$importer['uid'],$contact['id']);
-
-	// Generic birthday. We don't know the timezone. The year is irrelevant.
-
-	$birthday = str_replace('1000','1901',$birthday);
-
-	if ($birthday != "")
-		$birthday = datetime_convert('UTC','UTC',$birthday,'Y-m-d');
-
-	// this is to prevent multiple birthday notifications in a single year
-	// if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year
-
-	if(substr($birthday,5) === substr($contact['bd'],5))
-		$birthday = $contact['bd'];
-
-	/// @TODO Update name on item['author-name'] if the name changed. See consume_feed()
-	/// (Not doing this currently because D* protocol is scheduled for revision soon).
-
-	$r = q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `name-date` = '%s', `bd` = '%s',
-			`location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d AND `uid` = %d",
-		dbesc($name),
-		dbesc($nick),
-		dbesc($diaspora_handle),
-		dbesc(datetime_convert()),
-		dbesc($birthday),
-		dbesc($location),
-		dbesc($about),
-		dbesc($keywords),
-		dbesc($gender),
-		intval($contact['id']),
-		intval($importer['uid'])
-	);
-
-	if ($searchable) {
-		require_once('include/socgraph.php');
-		poco_check($contact['url'], $name, NETWORK_DIASPORA, $image_url, $about, $location, $gender, $keywords, "",
-			datetime_convert(), 2, $contact['id'], $importer['uid']);
-	}
-
-	update_gcontact(array("url" => $contact['url'], "network" => NETWORK_DIASPORA, "generation" => 2,
-				"photo" => $image_url, "name" => $name, "location" => $location,
-				"about" => $about, "birthday" => $birthday, "gender" => $gender,
-				"addr" => $diaspora_handle, "nick" => $nick, "keywords" => $keywords,
-				"hide" => !$searchable, "nsfw" => $nsfw));
-
-/*	if($r) {
-		if($oldphotos) {
-			foreach($oldphotos as $ph) {
-				q("DELETE FROM `photo` WHERE `uid` = %d AND `contact-id` = %d AND `album` = 'Contact Photos' AND `resource-id` = '%s' ",
-					intval($importer['uid']),
-					intval($contact['id']),
-					dbesc($ph['resource-id'])
-				);
-			}
-		}
-	}	*/
-
-	return;
-
-}
-
-function diaspora_share($me,$contact) {
-	$a = get_app();
-	$myaddr = $me['nickname'] . '@' .  substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
-	$theiraddr = $contact['addr'];
-
-	$tpl = get_markup_template('diaspora_share.tpl');
-	$msg = replace_macros($tpl, array(
-		'$sender' => $myaddr,
-		'$recipient' => $theiraddr
-	));
-
-	$slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$me,$contact,$me['prvkey'],$contact['pubkey'])));
-	//$slap = 'xml=' . urlencode(diaspora_msg_build($msg,$me,$contact,$me['prvkey'],$contact['pubkey']));
-
-	return(diaspora_transmit($owner,$contact,$slap, false));
-}
-
-function diaspora_unshare($me,$contact) {
-
-	$a = get_app();
-	$myaddr = $me['nickname'] . '@' .  substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
-
-	$tpl = get_markup_template('diaspora_retract.tpl');
-	$msg = replace_macros($tpl, array(
-		'$guid'   => $me['guid'],
-		'$type'   => 'Person',
-		'$handle' => $myaddr
-	));
-
-	$slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($msg,$me,$contact,$me['prvkey'],$contact['pubkey'])));
-	//$slap = 'xml=' . urlencode(diaspora_msg_build($msg,$me,$contact,$me['prvkey'],$contact['pubkey']));
-
-	return(diaspora_transmit($owner,$contact,$slap, false));
-
-}
-
-
-function diaspora_send_status($item,$owner,$contact,$public_batch = false) {
-
-	$a = get_app();
-	$myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
-	$theiraddr = $contact['addr'];
-
-	$images = array();
-
-	$title = $item['title'];
-	$body = $item['body'];
-
-/*
-	// We're trying to match Diaspora's split message/photo protocol but
-	// all the photos are displayed on D* as links and not img's - even
-	// though we're sending pretty much precisely what they send us when
-	// doing the same operation.  
-	// Commented out for now, we'll use bb2diaspora to convert photos to markdown
-	// which seems to get through intact.
-
-	$cnt = preg_match_all('|\[img\](.*?)\[\/img\]|',$body,$matches,PREG_SET_ORDER);
-	if($cnt) {
-		foreach($matches as $mtch) {
-			$detail = array();
-			$detail['str'] = $mtch[0];
-			$detail['path'] = dirname($mtch[1]) . '/';
-			$detail['file'] = basename($mtch[1]);
-			$detail['guid'] = $item['guid'];
-			$detail['handle'] = $myaddr;
-			$images[] = $detail;
-			$body = str_replace($detail['str'],$mtch[1],$body);
-		}
-	}
-*/
-
-	//if(strlen($title))
-	//	$body = "[b]".html_entity_decode($title)."[/b]\n\n".$body;
-
-	// convert to markdown
-	$body = xmlify(html_entity_decode(bb2diaspora($body)));
-	//$body = bb2diaspora($body);
-
-	// Adding the title
-	if(strlen($title))
-		$body = "## ".html_entity_decode($title)."\n\n".$body;
-
-	if($item['attach']) {
-		$cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism',$item['attach'],$matches,PREG_SET_ORDER);
-		if(cnt) {
-			$body .= "\n" . t('Attachments:') . "\n";
-			foreach($matches as $mtch) {
-				$body .= '[' . $mtch[3] . '](' . $mtch[1] . ')' . "\n";
-			}
-		}
-	}
-
-
-	$public = (($item['private']) ? 'false' : 'true');
-
-	require_once('include/datetime.php');
-	$created = datetime_convert('UTC','UTC',$item['created'],'Y-m-d H:i:s \U\T\C');
-
-	// Detect a share element and do a reshare
-	// see: https://github.com/Raven24/diaspora-federation/blob/master/lib/diaspora-federation/entities/reshare.rb
-	if (!$item['private'] AND ($ret = diaspora_is_reshare($item["body"]))) {
-		$tpl = get_markup_template('diaspora_reshare.tpl');
-		$msg = replace_macros($tpl, array(
-			'$root_handle' => xmlify($ret['root_handle']),
-			'$root_guid' => $ret['root_guid'],
-			'$guid' => $item['guid'],
-			'$handle' => xmlify($myaddr),
-			'$public' => $public,
-			'$created' => $created,
-			'$provider' => $item["app"]
-		));
-	} else {
-		$tpl = get_markup_template('diaspora_post.tpl');
-		$msg = replace_macros($tpl, array(
-			'$body' => $body,
-			'$guid' => $item['guid'],
-			'$handle' => xmlify($myaddr),
-			'$public' => $public,
-			'$created' => $created,
-			'$provider' => $item["app"]
-		));
-	}
-
-	logger('diaspora_send_status: '.$owner['username'].' -> '.$contact['name'].' 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_code = diaspora_transmit($owner,$contact,$slap,$public_batch,false,$item['guid']);
-
-	logger('diaspora_send_status: guid: '.$item['guid'].' result '.$return_code, LOGGER_DEBUG);
-
-	if(count($images)) {
-		diaspora_send_images($item,$owner,$contact,$images,$public_batch);
-	}
-
-	return $return_code;
-}
-
-function diaspora_is_reshare($body) {
-	$body = trim($body);
-
-	// Skip if it isn't a pure repeated messages
-	// Does it start with a share?
-	if (strpos($body, "[share") > 0)
-		return(false);
-
-	// Does it end with a share?
-	if (strlen($body) > (strrpos($body, "[/share]") + 8))
-		return(false);
-
-	$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
-	// Skip if there is no shared message in there
-	if ($body == $attributes)
-		return(false);
-
-	$guid = "";
-	preg_match("/guid='(.*?)'/ism", $attributes, $matches);
-	if ($matches[1] != "")
-		$guid = $matches[1];
-
-	preg_match('/guid="(.*?)"/ism', $attributes, $matches);
-	if ($matches[1] != "")
-		$guid = $matches[1];
-
-	if ($guid != "") {
-		$r = q("SELECT `contact-id` FROM `item` WHERE `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1",
-			dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA);
-		if ($r) {
-			$ret= array();
-			$ret["root_handle"] = diaspora_handle_from_contact($r[0]["contact-id"]);
-			$ret["root_guid"] = $guid;
-			return($ret);
-		}
-	}
-
-	$profile = "";
-	preg_match("/profile='(.*?)'/ism", $attributes, $matches);
-	if ($matches[1] != "")
-		$profile = $matches[1];
-
-	preg_match('/profile="(.*?)"/ism', $attributes, $matches);
-	if ($matches[1] != "")
-		$profile = $matches[1];
-
-	$ret= array();
-
-	$ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile);
-	if (($ret["root_handle"] == $profile) OR ($ret["root_handle"] == ""))
-		return(false);
-
-	$link = "";
-	preg_match("/link='(.*?)'/ism", $attributes, $matches);
-	if ($matches[1] != "")
-		$link = $matches[1];
-
-	preg_match('/link="(.*?)"/ism', $attributes, $matches);
-	if ($matches[1] != "")
-		$link = $matches[1];
-
-	$ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link);
-	if (($ret["root_guid"] == $link) OR ($ret["root_guid"] == ""))
-		return(false);
-
-	return($ret);
-}
-
-function diaspora_send_images($item,$owner,$contact,$images,$public_batch = false) {
-	$a = get_app();
-	if(! count($images))
-		return;
-	$mysite = substr($a->get_baseurl(),strpos($a->get_baseurl(),'://') + 3) . '/photo';
-
-	$tpl = get_markup_template('diaspora_photo.tpl');
-	foreach($images as $image) {
-		if(! stristr($image['path'],$mysite))
-			continue;
-		$resource = str_replace('.jpg','',$image['file']);
-		$resource = substr($resource,0,strpos($resource,'-'));
-
-		$r = q("select * from photo where `resource-id` = '%s' and `uid` = %d limit 1",
-			dbesc($resource),
-			intval($owner['uid'])
-		);
-		if(! count($r))
-			continue;
-		$public = (($r[0]['allow_cid'] || $r[0]['allow_gid'] || $r[0]['deny_cid'] || $r[0]['deny_gid']) ? 'false' : 'true' );
-		$msg = replace_macros($tpl,array(
-			'$path' => xmlify($image['path']),
-			'$filename' => xmlify($image['file']),
-			'$msg_guid' => xmlify($image['guid']),
-			'$guid' => xmlify($r[0]['guid']),
-			'$handle' => xmlify($image['handle']),
-			'$public' => xmlify($public),
-			'$created_at' => xmlify(datetime_convert('UTC','UTC',$r[0]['created'],'Y-m-d H:i:s \U\T\C'))
-		));
-
-
-		logger('diaspora_send_photo: base message: ' . $msg, LOGGER_DATA);
-		logger('send guid '.$r[0]['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));
-
-		diaspora_transmit($owner,$contact,$slap,$public_batch,false,$r[0]['guid']);
-	}
-
-}
-
-function diaspora_send_followup($item,$owner,$contact,$public_batch = false) {
-
-	$a = get_app();
-	$myaddr = $owner['nickname'] . '@' .  substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
-//	$theiraddr = $contact['addr'];
-
-	// 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;
-
-	if($item['verb'] === ACTIVITY_LIKE) {
-		$tpl = get_markup_template('diaspora_like.tpl');
-		$like = true;
-		$target_type = ( $parent['uri'] === $parent['parent-uri']  ? 'Post' : 'Comment');
-//		$target_type = (strpos($parent['type'], 'comment') ? 'Comment' : 'Post');
-//		$positive = (($item['deleted']) ? 'false' : 'true');
-		$positive = 'true';
-
-		if(($item['deleted']))
-			logger('diaspora_send_followup: received deleted "like". Those should go to diaspora_send_retraction');
-	}
-	else {
-		$tpl = get_markup_template('diaspora_comment.tpl');
-		$like = false;
-	}
-
-	$text = html_entity_decode(bb2diaspora($item['body']));
-
-	// sign it
-
-	if($like)
-		$signed_text =  $positive . ';' . $item['guid'] . ';' . $target_type . ';' . $parent['guid'] . ';' . $myaddr;
-	else
-		$signed_text = $item['guid'] . ';' . $parent['guid'] . ';' . $text . ';' . $myaddr;
-
-	$authorsig = 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),
-		'$body' => xmlify($text),
-		'$positive' => xmlify($positive),
-		'$handle' => xmlify($myaddr)
-	));
-
-	logger('diaspora_followup: 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']));
-}
-
-
-function diaspora_send_relay($item,$owner,$contact,$public_batch = false) {
-
-
-	$a = get_app();
-	$myaddr = $owner['nickname'] . '@' . substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
-//	$theiraddr = $contact['addr'];
-
-	// 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']));
-
-}
-
-
-
-function diaspora_send_retraction($item,$owner,$contact,$public_batch = false) {
-
-	$a = get_app();
-	$myaddr = $owner['nickname'] . '@' .  substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
-
-	// Check whether the retraction is for a top-level post or whether it's a relayable
-	if( $item['uri'] !== $item['parent-uri'] ) {
-
-		$tpl = get_markup_template('diaspora_relay_retraction.tpl');
-		$target_type = (($item['verb'] === ACTIVITY_LIKE) ? 'Like' : 'Comment');
-	}
-	else {
-
-		$tpl = get_markup_template('diaspora_signed_retract.tpl');
-		$target_type = 'StatusMessage';
-	}
-
-	$signed_text = $item['guid'] . ';' . $target_type;
-
-	$msg = replace_macros($tpl, array(
-		'$guid'   => xmlify($item['guid']),
-		'$type'   => xmlify($target_type),
-		'$handle' => xmlify($myaddr),
-		'$signature' => xmlify(base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')))
-	));
-
-	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']));
-}
-
-function diaspora_send_mail($item,$owner,$contact) {
-
-	$a = get_app();
-	$myaddr = $owner['nickname'] . '@' .  substr($a->get_baseurl(), strpos($a->get_baseurl(),'://') + 3);
-
-	$r = q("select * from conv where id = %d and uid = %d limit 1",
-		intval($item['convid']),
-		intval($item['uid'])
-	);
-
-	if(! count($r)) {
-		logger('diaspora_send_mail: conversation not found.');
-		return;
-	}
-	$cnv = $r[0];
-
-	$conv = array(
-		'guid' => xmlify($cnv['guid']),
-		'subject' => xmlify($cnv['subject']),
-		'created_at' => xmlify(datetime_convert('UTC','UTC',$cnv['created'],'Y-m-d H:i:s \U\T\C')),
-		'diaspora_handle' => xmlify($cnv['creator']),
-		'participant_handles' => xmlify($cnv['recips'])
-	);
-
-	$body = bb2diaspora($item['body']);
-	$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'];
-
-	$sig = base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256'));
-
-	$msg = array(
-		'guid' => xmlify($item['guid']),
-		'parent_guid' => xmlify($cnv['guid']),
-		'parent_author_signature' => xmlify($sig),
-		'author_signature' => xmlify($sig),
-		'text' => xmlify($body),
-		'created_at' => xmlify($created),
-		'diaspora_handle' => xmlify($myaddr),
-		'conversation_guid' => xmlify($cnv['guid'])
-	);
-
-	if($item['reply']) {
-		$tpl = get_markup_template('diaspora_message.tpl');
-		$xmsg = replace_macros($tpl, array('$msg' => $msg));
-	}
-	else {
-		$conv['messages'] = array($msg);
-		$tpl = get_markup_template('diaspora_conversation.tpl');
-		$xmsg = replace_macros($tpl, array('$conv' => $conv));
-	}
-
-	logger('diaspora_conversation: ' . print_r($xmsg,true), LOGGER_DATA);
-	logger('send guid '.$item['guid'], LOGGER_DEBUG);
-
-	$slap = 'xml=' . urlencode(urlencode(diaspora_msg_build($xmsg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],false)));
-	//$slap = 'xml=' . urlencode(diaspora_msg_build($xmsg,$owner,$contact,$owner['uprvkey'],$contact['pubkey'],false));
-
-	return(diaspora_transmit($owner,$contact,$slap,false,false,$item['guid']));
-
-
-}
-
-function diaspora_transmit($owner,$contact,$slap,$public_batch,$queue_run=false,$guid = "") {
-
-	$enabled = intval(get_config('system','diaspora_enabled'));
-	if(! $enabled) {
-		return 200;
-	}
-
-	$a = get_app();
-	$logid = random_string(4);
-	$dest_url = (($public_batch) ? $contact['batch'] : $contact['notify']);
-	if(! $dest_url) {
-		logger('diaspora_transmit: no url for contact: ' . $contact['id'] . ' batch mode =' . $public_batch);
-		return 0;
-	}
-
-	logger('diaspora_transmit: '.$logid.'-'.$guid.' '.$dest_url);
-
-	if( (! $queue_run) && (was_recently_delayed($contact['id'])) ) {
-		$return_code = 0;
-	}
-	else {
-		if (!intval(get_config('system','diaspora_test'))) {
-			post_url($dest_url . '/', $slap);
-			$return_code = $a->get_curl_code();
-		} else {
-			logger('diaspora_transmit: test_mode');
-			return 200;
-		}
-	}
-
-	logger('diaspora_transmit: '.$logid.'-'.$guid.' returns: '.$return_code);
-
-	if((! $return_code) || (($return_code == 503) && (stristr($a->get_curl_headers(),'retry-after')))) {
-		logger('diaspora_transmit: queue message');
-
-		$r = q("SELECT id from queue where cid = %d and network = '%s' and content = '%s' and batch = %d limit 1",
-			intval($contact['id']),
-			dbesc(NETWORK_DIASPORA),
-			dbesc($slap),
-			intval($public_batch)
-		);
-		if(count($r)) {
-			logger('diaspora_transmit: add_to_queue ignored - identical item already in queue');
-		}
-		else {
-			// queue message for redelivery
-			add_to_queue($contact['id'],NETWORK_DIASPORA,$slap,$public_batch);
-		}
-	}
-
-
-	return(($return_code) ? $return_code : (-1));
-}
-
-function diaspora_fetch_relay() {
-
-	$serverdata = get_config("system", "relay_server");
-	if ($serverdata == "")
-		return array();
-
-	$relay = array();
-
-	$servers = explode(",", $serverdata);
-
-	foreach($servers AS $server) {
-		$server = trim($server);
-		$batch = $server."/receive/public";
-
-		$relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
-
-		if (!$relais) {
-			$addr = "relay@".str_replace("http://", "", normalise_link($server));
-
-			$r = q("INSERT INTO `contact` (`uid`, `created`, `name`, `nick`, `addr`, `url`, `nurl`, `batch`, `network`, `rel`, `blocked`, `pending`, `writable`, `name-date`, `uri-date`, `avatar-date`)
-				VALUES (0, '%s', '%s', 'relay', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, '%s', '%s', '%s')",
-				datetime_convert(),
-				dbesc($addr),
-				dbesc($addr),
-				dbesc($server),
-				dbesc(normalise_link($server)),
-				dbesc($batch),
-				dbesc(NETWORK_DIASPORA),
-				intval(CONTACT_IS_FOLLOWER),
-				dbesc(datetime_convert()),
-				dbesc(datetime_convert()),
-				dbesc(datetime_convert())
-			);
-
-			$relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
-			if ($relais)
-				$relay[] = $relais[0];
-		} else
-			$relay[] = $relais[0];
-	}
-
-	return $relay;
+		$message = array("diaspora_handle" => $handle,
+				"first_name" => $first,
+				"last_name" => $last,
+				"image_url" => $large,
+				"image_url_medium" => $medium,
+				"image_url_small" => $small,
+				"birthday" => $dob,
+				"gender" => $profile['gender'],
+				"bio" => $about,
+				"location" => $location,
+				"searchable" => $searchable,
+				"tag_string" => $tags);
+
+		foreach($recips as $recip)
+			self::build_and_transmit($profile, $recip, "profile", $message, false, "", true);
+	}
 }
+?>
diff --git a/include/diaspora2.php b/include/diaspora2.php
deleted file mode 100644
index 75cedeccd1..0000000000
--- a/include/diaspora2.php
+++ /dev/null
@@ -1,2553 +0,0 @@
-<?php
-/**
- * @file include/diaspora.php
- * @brief The implementation of the diaspora protocol
- */
-
-require_once("include/items.php");
-require_once("include/bb2diaspora.php");
-require_once("include/Scrape.php");
-require_once("include/Contact.php");
-require_once("include/Photo.php");
-require_once("include/socgraph.php");
-require_once("include/group.php");
-require_once("include/xml.php");
-require_once("include/datetime.php");
-
-/**
- * @brief This class contain functions to create and send Diaspora XML files
- *
- */
-class diaspora {
-
-	public static function relay_list() {
-
-		$serverdata = get_config("system", "relay_server");
-		if ($serverdata == "")
-			return array();
-
-		$relay = array();
-
-		$servers = explode(",", $serverdata);
-
-		foreach($servers AS $server) {
-			$server = trim($server);
-			$batch = $server."/receive/public";
-
-			$relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
-
-			if (!$relais) {
-				$addr = "relay@".str_replace("http://", "", normalise_link($server));
-
-				$r = q("INSERT INTO `contact` (`uid`, `created`, `name`, `nick`, `addr`, `url`, `nurl`, `batch`, `network`, `rel`, `blocked`, `pending`, `writable`, `name-date`, `uri-date`, `avatar-date`)
-					VALUES (0, '%s', '%s', 'relay', '%s', '%s', '%s', '%s', '%s', %d, 0, 0, 1, '%s', '%s', '%s')",
-					datetime_convert(),
-					dbesc($addr),
-					dbesc($addr),
-					dbesc($server),
-					dbesc(normalise_link($server)),
-					dbesc($batch),
-					dbesc(NETWORK_DIASPORA),
-					intval(CONTACT_IS_FOLLOWER),
-					dbesc(datetime_convert()),
-					dbesc(datetime_convert()),
-					dbesc(datetime_convert())
-				);
-
-				$relais = q("SELECT `batch`, `id`, `name`,`network` FROM `contact` WHERE `uid` = 0 AND `batch` = '%s' LIMIT 1", dbesc($batch));
-				if ($relais)
-					$relay[] = $relais[0];
-			} else
-				$relay[] = $relais[0];
-		}
-
-		return $relay;
-	}
-
-	function repair_signature($signature, $handle = "", $level = 1) {
-
-		if ($signature == "")
-			return ($signature);
-
-		if (base64_encode(base64_decode(base64_decode($signature))) == base64_decode($signature)) {
-			$signature = base64_decode($signature);
-			logger("Repaired double encoded signature from Diaspora/Hubzilla handle ".$handle." - level ".$level, LOGGER_DEBUG);
-
-			// Do a recursive call to be able to fix even multiple levels
-			if ($level < 10)
-				$signature = self::repair_signature($signature, $handle, ++$level);
-		}
-
-		return($signature);
-	}
-
-	/**
-	 * @brief: Decodes incoming Diaspora message
-	 *
-	 * @param array $importer from user table
-	 * @param string $xml urldecoded Diaspora salmon
-	 *
-	 * @return array
-	 * 'message' -> decoded Diaspora XML message
-	 * 'author' -> author diaspora handle
-	 * 'key' -> author public key (converted to pkcs#8)
-	 */
-	function decode($importer, $xml) {
-
-		$public = false;
-		$basedom = parse_xml_string($xml);
-
-		if (!is_object($basedom))
-			return false;
-
-		$children = $basedom->children('https://joindiaspora.com/protocol');
-
-		if($children->header) {
-			$public = true;
-			$author_link = str_replace('acct:','',$children->header->author_id);
-		} else {
-
-			$encrypted_header = json_decode(base64_decode($children->encrypted_header));
-
-			$encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key);
-			$ciphertext = base64_decode($encrypted_header->ciphertext);
-
-			$outer_key_bundle = '';
-			openssl_private_decrypt($encrypted_aes_key_bundle,$outer_key_bundle,$importer['prvkey']);
-
-			$j_outer_key_bundle = json_decode($outer_key_bundle);
-
-			$outer_iv = base64_decode($j_outer_key_bundle->iv);
-			$outer_key = base64_decode($j_outer_key_bundle->key);
-
-			$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $outer_key, $ciphertext, MCRYPT_MODE_CBC, $outer_iv);
-
-
-			$decrypted = pkcs5_unpad($decrypted);
-
-			/**
-			 * $decrypted now contains something like
-			 *
-			 *  <decrypted_header>
-			 *     <iv>8e+G2+ET8l5BPuW0sVTnQw==</iv>
-			 *     <aes_key>UvSMb4puPeB14STkcDWq+4QE302Edu15oaprAQSkLKU=</aes_key>
-			 *     <author_id>galaxor@diaspora.priateship.org</author_id>
-			 *  </decrypted_header>
-			 */
-
-			logger('decrypted: '.$decrypted, LOGGER_DEBUG);
-			$idom = parse_xml_string($decrypted,false);
-
-			$inner_iv = base64_decode($idom->iv);
-			$inner_aes_key = base64_decode($idom->aes_key);
-
-			$author_link = str_replace('acct:','',$idom->author_id);
-		}
-
-		$dom = $basedom->children(NAMESPACE_SALMON_ME);
-
-		// figure out where in the DOM tree our data is hiding
-
-		if($dom->provenance->data)
-			$base = $dom->provenance;
-		elseif($dom->env->data)
-			$base = $dom->env;
-		elseif($dom->data)
-			$base = $dom;
-
-		if (!$base) {
-			logger('unable to locate salmon data in xml');
-			http_status_exit(400);
-		}
-
-
-		// Stash the signature away for now. We have to find their key or it won't be good for anything.
-		$signature = base64url_decode($base->sig);
-
-		// unpack the  data
-
-		// strip whitespace so our data element will return to one big base64 blob
-		$data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$base->data);
-
-
-		// stash away some other stuff for later
-
-		$type = $base->data[0]->attributes()->type[0];
-		$keyhash = $base->sig[0]->attributes()->keyhash[0];
-		$encoding = $base->encoding;
-		$alg = $base->alg;
-
-
-		$signed_data = $data.'.'.base64url_encode($type).'.'.base64url_encode($encoding).'.'.base64url_encode($alg);
-
-
-		// decode the data
-		$data = base64url_decode($data);
-
-
-		if($public)
-			$inner_decrypted = $data;
-		else {
-
-			// Decode the encrypted blob
-
-			$inner_encrypted = base64_decode($data);
-			$inner_decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $inner_encrypted, MCRYPT_MODE_CBC, $inner_iv);
-			$inner_decrypted = pkcs5_unpad($inner_decrypted);
-		}
-
-		if (!$author_link) {
-			logger('Could not retrieve author URI.');
-			http_status_exit(400);
-		}
-		// Once we have the author URI, go to the web and try to find their public key
-		// (first this will look it up locally if it is in the fcontact cache)
-		// This will also convert diaspora public key from pkcs#1 to pkcs#8
-
-		logger('Fetching key for '.$author_link);
-		$key = self::key($author_link);
-
-		if (!$key) {
-			logger('Could not retrieve author key.');
-			http_status_exit(400);
-		}
-
-		$verify = rsa_verify($signed_data,$signature,$key);
-
-		if (!$verify) {
-			logger('Message did not verify. Discarding.');
-			http_status_exit(400);
-		}
-
-		logger('Message verified.');
-
-		return array('message' => $inner_decrypted, 'author' => $author_link, 'key' => $key);
-
-	}
-
-
-	/**
-	 * @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"));
-		if (!$enabled) {
-			logger("diaspora is disabled");
-			return false;
-		}
-
-		// Use a dummy importer to import the data for the public copy
-		$importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE);
-		$item_id = self::dispatch($importer,$msg);
-
-		// Now distribute it to the followers
-		$r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN
-			(SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s')
-			AND NOT `account_expired` AND NOT `account_removed`",
-			dbesc(NETWORK_DIASPORA),
-			dbesc($msg["author"])
-		);
-		if($r) {
-			foreach($r as $rr) {
-				logger("delivering to: ".$rr["username"]);
-				self::dispatch($rr,$msg);
-			}
-		} else
-			logger("No subscribers for ".$msg["author"]." ".print_r($msg, true));
-
-		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.
-		// This will often be different with relayed messages (for example "like" and "comment")
-		$sender = $msg["author"];
-
-		if (!diaspora::valid_posting($msg, $fields)) {
-			logger("Invalid posting");
-			return false;
-		}
-
-		$type = $fields->getName();
-
-		logger("Received message type ".$type." from ".$sender." for user ".$importer["uid"], LOGGER_DEBUG);
-
-		switch ($type) {
-			case "account_deletion":
-				return self::receive_account_deletion($importer, $fields);
-
-			case "comment":
-				return self::receive_comment($importer, $sender, $fields);
-
-			case "conversation":
-				return self::receive_conversation($importer, $msg, $fields);
-
-			case "like":
-				return self::receive_like($importer, $sender, $fields);
-
-			case "message":
-				return self::receive_message($importer, $fields);
-
-			case "participation": // Not implemented
-				return self::receive_participation($importer, $fields);
-
-			case "photo": // Not implemented
-				return self::receive_photo($importer, $fields);
-
-			case "poll_participation": // Not implemented
-				return self::receive_poll_participation($importer, $fields);
-
-			case "profile":
-				return self::receive_profile($importer, $fields);
-
-			case "request":
-				return self::receive_request($importer, $fields);
-
-			case "reshare":
-				return self::receive_reshare($importer, $fields);
-
-			case "retraction":
-				return self::receive_retraction($importer, $sender, $fields);
-
-			case "status_message":
-				return self::receive_status_message($importer, $fields);
-
-			default:
-				logger("Unknown message type ".$type);
-				return false;
-		}
-
-		return true;
-	}
-
-	/**
-	 * @brief Checks if a posting is valid and fetches the data fields.
-	 *
-	 * This function does not only check the signature.
-	 * It also does the conversion between the old and the new diaspora format.
-	 *
-	 * @param array $msg Array with the XML, the sender handle and the sender signature
-	 * @param object $fields SimpleXML object that contains the posting when it is valid
-	 *
-	 * @return bool Is the posting valid?
-	 */
-	private function valid_posting($msg, &$fields) {
-
-		$data = parse_xml_string($msg["message"], false);
-
-		if (!is_object($data))
-			return false;
-
-		$first_child = $data->getName();
-
-		// Is this the new or the old version?
-		if ($data->getName() == "XML") {
-			$oldXML = true;
-			foreach ($data->post->children() as $child)
-				$element = $child;
-		} else {
-			$oldXML = false;
-			$element = $data;
-		}
-
-		$type = $element->getName();
-		$orig_type = $type;
-
-		// All retractions are handled identically from now on.
-		// In the new version there will only be "retraction".
-		if (in_array($type, array("signed_retraction", "relayable_retraction")))
-			$type = "retraction";
-
-		$fields = new SimpleXMLElement("<".$type."/>");
-
-		$signed_data = "";
-
-		foreach ($element->children() AS $fieldname => $entry) {
-			if ($oldXML) {
-				// Translation for the old XML structure
-				if ($fieldname == "diaspora_handle")
-					$fieldname = "author";
-
-				if ($fieldname == "participant_handles")
-					$fieldname = "participants";
-
-				if (in_array($type, array("like", "participation"))) {
-					if ($fieldname == "target_type")
-						$fieldname = "parent_type";
-				}
-
-				if ($fieldname == "sender_handle")
-					$fieldname = "author";
-
-				if ($fieldname == "recipient_handle")
-					$fieldname = "recipient";
-
-				if ($fieldname == "root_diaspora_id")
-					$fieldname = "root_author";
-
-				if ($type == "retraction") {
-					if ($fieldname == "post_guid")
-						$fieldname = "target_guid";
-
-					if ($fieldname == "type")
-						$fieldname = "target_type";
-				}
-			}
-
-			if ($fieldname == "author_signature")
-				$author_signature = base64_decode($entry);
-			elseif ($fieldname == "parent_author_signature")
-				$parent_author_signature = base64_decode($entry);
-			elseif ($fieldname != "target_author_signature") {
-				if ($signed_data != "") {
-					$signed_data .= ";";
-					$signed_data_parent .= ";";
-				}
-
-				$signed_data .= $entry;
-			}
-			if (!in_array($fieldname, array("parent_author_signature", "target_author_signature")) OR
-				($orig_type == "relayable_retraction"))
-				xml::copy($entry, $fields, $fieldname);
-		}
-
-		// This is something that shouldn't happen at all.
-		if (in_array($type, array("status_message", "reshare", "profile")))
-			if ($msg["author"] != $fields->author) {
-				logger("Message handle is not the same as envelope sender. Quitting this message.");
-				return false;
-			}
-
-		// Only some message types have signatures. So we quit here for the other types.
-		if (!in_array($type, array("comment", "message", "like")))
-			return true;
-
-		// No author_signature? This is a must, so we quit.
-		if (!isset($author_signature))
-			return false;
-
-		if (isset($parent_author_signature)) {
-			$key = self::key($msg["author"]);
-
-			if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256"))
-				return false;
-		}
-
-		$key = self::key($fields->author);
-
-		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 key($handle) {
-		$handle = strval($handle);
-
-		logger("Fetching diaspora key for: ".$handle);
-
-		$r = self::person_by_handle($handle);
-		if($r)
-			return $r["pubkey"];
-
-		return "";
-	}
-
-	/**
-	 * @brief Fetches data for a given handle
-	 *
-	 * @param string $handle The handle
-	 *
-	 * @return array the queried data
-	 */
-	private function person_by_handle($handle) {
-
-		$r = q("SELECT * FROM `fcontact` WHERE `network` = '%s' AND `addr` = '%s' LIMIT 1",
-			dbesc(NETWORK_DIASPORA),
-			dbesc($handle)
-		);
-		if ($r) {
-			$person = $r[0];
-			logger("In cache ".print_r($r,true), LOGGER_DEBUG);
-
-			// update record occasionally so it doesn't get stale
-			$d = strtotime($person["updated"]." +00:00");
-			if ($d < strtotime("now - 14 days"))
-				$update = true;
-		}
-
-		if (!$person OR $update) {
-			logger("create or refresh", LOGGER_DEBUG);
-			$r = probe_url($handle, PROBE_DIASPORA);
-
-			// Note that Friendica contacts will return a "Diaspora person"
-			// if Diaspora connectivity is enabled on their server
-			if ($r AND ($r["network"] === NETWORK_DIASPORA)) {
-				self::add_fcontact($r, $update);
-				$person = $r;
-			}
-		}
-		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
-
-		if($update) {
-			$r = q("UPDATE `fcontact` SET
-					`name` = '%s',
-					`photo` = '%s',
-					`request` = '%s',
-					`nick` = '%s',
-					`addr` = '%s',
-					`batch` = '%s',
-					`notify` = '%s',
-					`poll` = '%s',
-					`confirm` = '%s',
-					`alias` = '%s',
-					`pubkey` = '%s',
-					`updated` = '%s'
-				WHERE `url` = '%s' AND `network` = '%s'",
-					dbesc($arr["name"]),
-					dbesc($arr["photo"]),
-					dbesc($arr["request"]),
-					dbesc($arr["nick"]),
-					dbesc($arr["addr"]),
-					dbesc($arr["batch"]),
-					dbesc($arr["notify"]),
-					dbesc($arr["poll"]),
-					dbesc($arr["confirm"]),
-					dbesc($arr["alias"]),
-					dbesc($arr["pubkey"]),
-					dbesc(datetime_convert()),
-					dbesc($arr["url"]),
-					dbesc($arr["network"])
-				);
-		} else {
-			$r = q("INSERT INTO `fcontact` (`url`,`name`,`photo`,`request`,`nick`,`addr`,
-					`batch`, `notify`,`poll`,`confirm`,`network`,`alias`,`pubkey`,`updated`)
-				VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')",
-					dbesc($arr["url"]),
-					dbesc($arr["name"]),
-					dbesc($arr["photo"]),
-					dbesc($arr["request"]),
-					dbesc($arr["nick"]),
-					dbesc($arr["addr"]),
-					dbesc($arr["batch"]),
-					dbesc($arr["notify"]),
-					dbesc($arr["poll"]),
-					dbesc($arr["confirm"]),
-					dbesc($arr["network"]),
-					dbesc($arr["alias"]),
-					dbesc($arr["pubkey"]),
-					dbesc(datetime_convert())
-				);
-		}
-
-		return $r;
-	}
-
-	public static function handle_from_contact($contact_id) {
-		$handle = False;
-
-		logger("contact id is ".$contact_id, LOGGER_DEBUG);
-
-		$r = q("SELECT `network`, `addr`, `self`, `url`, `nick` FROM `contact` WHERE `id` = %d",
-		       intval($contact_id)
-		);
-		if($r) {
-			$contact = $r[0];
-
-			logger("contact 'self' = ".$contact['self']." 'url' = ".$contact['url'], LOGGER_DEBUG);
-
-			if($contact['addr'] != "")
-				$handle = $contact['addr'];
-			elseif(($contact['network'] === NETWORK_DFRN) || ($contact['self'] == 1)) {
-				$baseurl_start = strpos($contact['url'],'://') + 3;
-				$baseurl_length = strpos($contact['url'],'/profile') - $baseurl_start; // allows installations in a subdirectory--not sure how Diaspora will handle
-				$baseurl = substr($contact['url'], $baseurl_start, $baseurl_length);
-				$handle = $contact['nick'].'@'.$baseurl;
-			}
-		}
-
-		return $handle;
-	}
-
-	private function contact_by_handle($uid, $handle) {
-		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `addr` = '%s' LIMIT 1",
-			intval($uid),
-			dbesc($handle)
-		);
-
-		if ($r)
-			return $r[0];
-
-		$handle_parts = explode("@", $handle);
-		$nurl_sql = "%%://".$handle_parts[1]."%%/profile/".$handle_parts[0];
-		$r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` LIKE '%s' LIMIT 1",
-			dbesc(NETWORK_DFRN),
-			intval($uid),
-			dbesc($nurl_sql)
-		);
-		if($r)
-			return $r[0];
-
-		return false;
-	}
-
-	private function post_allow($importer, $contact, $is_comment = false) {
-
-		// perhaps we were already sharing with this person. Now they're sharing with us.
-		// That makes us friends.
-		// Normally this should have handled by getting a request - but this could get lost
-		if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
-			q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
-				intval(CONTACT_IS_FRIEND),
-				intval($contact["id"]),
-				intval($importer["uid"])
-			);
-			$contact["rel"] = CONTACT_IS_FRIEND;
-			logger("defining user ".$contact["nick"]." as friend");
-		}
-
-		if(($contact["blocked"]) || ($contact["readonly"]) || ($contact["archive"]))
-			return false;
-		if($contact["rel"] == CONTACT_IS_SHARING || $contact["rel"] == CONTACT_IS_FRIEND)
-			return true;
-		if($contact["rel"] == CONTACT_IS_FOLLOWER)
-			if(($importer["page-flags"] == PAGE_COMMUNITY) OR $is_comment)
-				return true;
-
-		// Messages for the global users are always accepted
-		if ($importer["uid"] == 0)
-			return true;
-
-		return false;
-	}
-
-	private function allowed_contact_by_handle($importer, $handle, $is_comment = false) {
-		$contact = self::contact_by_handle($importer["uid"], $handle);
-		if (!$contact) {
-			logger("A Contact for handle ".$handle." and user ".$importer["uid"]." was not found");
-			return false;
-		}
-
-		if (!self::post_allow($importer, $contact, $is_comment)) {
-			logger("The handle: ".$handle." is not allowed to post to user ".$importer["uid"]);
-			return false;
-		}
-		return $contact;
-	}
-
-	private function message_exists($uid, $guid) {
-		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-			intval($uid),
-			dbesc($guid)
-		);
-
-		if($r) {
-			logger("message ".$guid." already exists for user ".$uid);
-			return true;
-		}
-
-		return false;
-	}
-
-	private function fetch_guid($item) {
-		preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi",
-			function ($match) use ($item){
-				return(self::fetch_guid_sub($match, $item));
-			},$item["body"]);
-	}
-
-	private function fetch_guid_sub($match, $item) {
-		if (!self::store_by_guid($match[1], $item["author-link"]))
-			self::store_by_guid($match[1], $item["owner-link"]);
-	}
-
-	private function store_by_guid($guid, $server, $uid = 0) {
-		$serverparts = parse_url($server);
-		$server = $serverparts["scheme"]."://".$serverparts["host"];
-
-		logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG);
-
-		$msg = self::message($guid, $server);
-
-		if (!$msg)
-			return false;
-
-		logger("Successfully fetched item ".$guid." from ".$server, LOGGER_DEBUG);
-
-		// Now call the dispatcher
-		return self::dispatch_public($msg);
-	}
-
-	private function message($guid, $server, $level = 0) {
-
-		if ($level > 5)
-			return false;
-
-		// This will work for Diaspora and newer Friendica servers
-		$source_url = $server."/p/".$guid.".xml";
-		$x = fetch_url($source_url);
-		if(!$x)
-			return false;
-
-		$source_xml = parse_xml_string($x, false);
-
-		if (!is_object($source_xml))
-			return false;
-
-		if ($source_xml->post->reshare) {
-			// Reshare of a reshare - old Diaspora version
-			return self::message($source_xml->post->reshare->root_guid, $server, ++$level);
-		} elseif ($source_xml->getName() == "reshare") {
-			// Reshare of a reshare - new Diaspora version
-			return self::message($source_xml->root_guid, $server, ++$level);
-		}
-
-		$author = "";
-
-		// Fetch the author - for the old and the new Diaspora version
-		if ($source_xml->post->status_message->diaspora_handle)
-			$author = (string)$source_xml->post->status_message->diaspora_handle;
-		elseif ($source_xml->author AND ($source_xml->getName() == "status_message"))
-			$author = (string)$source_xml->author;
-
-		// If this isn't a "status_message" then quit
-		if (!$author)
-			return false;
-
-		$msg = array("message" => $x, "author" => $author);
-
-		$msg["key"] = self::key($msg["author"]);
-
-		return $msg;
-	}
-
-	private function parent_item($uid, $guid, $author, $contact) {
-		$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
-				`author-name`, `author-link`, `author-avatar`,
-				`owner-name`, `owner-link`, `owner-avatar`
-			FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-			intval($uid), dbesc($guid));
-
-		if(!$r) {
-			$result = self::store_by_guid($guid, $contact["url"], $uid);
-
-			if (!$result) {
-				$person = self::person_by_handle($author);
-				$result = self::store_by_guid($guid, $person["url"], $uid);
-			}
-
-			if ($result) {
-				logger("Fetched missing item ".$guid." - result: ".$result, LOGGER_DEBUG);
-
-				$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
-						`author-name`, `author-link`, `author-avatar`,
-						`owner-name`, `owner-link`, `owner-avatar`
-					FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-					intval($uid), dbesc($guid));
-			}
-		}
-
-		if (!$r) {
-			logger("parent item not found: parent: ".$guid." - user: ".$uid);
-			return false;
-		} else {
-			logger("parent item found: parent: ".$guid." - user: ".$uid);
-			return $r[0];
-		}
-	}
-
-	private function author_contact_by_url($contact, $person, $uid) {
-
-		$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
-			dbesc(normalise_link($person["url"])), intval($uid));
-		if ($r) {
-			$cid = $r[0]["id"];
-			$network = $r[0]["network"];
-		} else {
-			$cid = $contact["id"];
-			$network = NETWORK_DIASPORA;
-		}
-
-		return (array("cid" => $cid, "network" => $network));
-	}
-
-	public static function is_redmatrix($url) {
-		return(strstr($url, "/channel/"));
-	}
-
-	private function plink($addr, $guid) {
-		$r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr));
-
-		// Fallback
-		if (!$r)
-			return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
-
-		// Friendica contacts are often detected as Diaspora contacts in the "fcontact" table
-		// So we try another way as well.
-		$s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"])));
-		if ($s)
-			$r[0]["network"] = $s[0]["network"];
-
-		if ($r[0]["network"] == NETWORK_DFRN)
-			return(str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/"));
-
-		if (self::is_redmatrix($r[0]["url"]))
-			return $r[0]["url"]."/?f=&mid=".$guid;
-
-		return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
-	}
-
-	private function receive_account_deletion($importer, $data) {
-		$author = notags(unxmlify($data->author));
-
-		$contact = self::contact_by_handle($importer["uid"], $author);
-		if (!$contact) {
-			logger("cannot find contact for author: ".$author);
-			return false;
-		}
-
-		// We now remove the contact
-		contact_remove($contact["id"]);
-		return true;
-	}
-
-	private function receive_comment($importer, $sender, $data) {
-		$guid = notags(unxmlify($data->guid));
-		$parent_guid = notags(unxmlify($data->parent_guid));
-		$text = unxmlify($data->text);
-		$author = notags(unxmlify($data->author));
-
-		$contact = self::allowed_contact_by_handle($importer, $sender, true);
-		if (!$contact)
-			return false;
-
-		if (self::message_exists($importer["uid"], $guid))
-			return false;
-
-		$parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact);
-		if (!$parent_item)
-			return false;
-
-		$person = self::person_by_handle($author);
-		if (!is_array($person)) {
-			logger("unable to find author details");
-			return false;
-		}
-
-		// Fetch the contact id - if we know this contact
-		$author_contact = self::author_contact_by_url($contact, $person, $importer["uid"]);
-
-		$datarray = array();
-
-		$datarray["uid"] = $importer["uid"];
-		$datarray["contact-id"] = $author_contact["cid"];
-		$datarray["network"]  = $author_contact["network"];
-
-		$datarray["author-name"] = $person["name"];
-		$datarray["author-link"] = $person["url"];
-		$datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]);
-
-		$datarray["owner-name"] = $contact["name"];
-		$datarray["owner-link"] = $contact["url"];
-		$datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
-
-		$datarray["guid"] = $guid;
-		$datarray["uri"] = $author.":".$guid;
-
-		$datarray["type"] = "remote-comment";
-		$datarray["verb"] = ACTIVITY_POST;
-		$datarray["gravity"] = GRAVITY_COMMENT;
-		$datarray["parent-uri"] = $parent_item["uri"];
-
-		$datarray["object-type"] = ACTIVITY_OBJ_COMMENT;
-		$datarray["object"] = json_encode($data);
-
-		$datarray["body"] = diaspora2bb($text);
-
-		self::fetch_guid($datarray);
-
-		$message_id = item_store($datarray);
-
-		if ($message_id)
-			logger("Stored comment ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
-
-		// 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.
-			// 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))
-			);
-
-			// notify others
-			proc_run("php", "include/notifier.php", "comment-import", $message_id);
-		}
-
-		return $message_id;
-	}
-
-	private function receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation) {
-		$guid = notags(unxmlify($data->guid));
-		$subject = notags(unxmlify($data->subject));
-		$author = notags(unxmlify($data->author));
-
-		$reply = 0;
-
-		$msg_guid = notags(unxmlify($mesg->guid));
-		$msg_parent_guid = notags(unxmlify($mesg->parent_guid));
-		$msg_parent_author_signature = notags(unxmlify($mesg->parent_author_signature));
-		$msg_author_signature = notags(unxmlify($mesg->author_signature));
-		$msg_text = unxmlify($mesg->text);
-		$msg_created_at = datetime_convert("UTC", "UTC", notags(unxmlify($mesg->created_at)));
-
-		// "diaspora_handle" is the element name from the old version
-		// "author" is the element name from the new version
-		if ($mesg->author)
-			$msg_author = notags(unxmlify($mesg->author));
-		elseif ($mesg->diaspora_handle)
-			$msg_author = notags(unxmlify($mesg->diaspora_handle));
-		else
-			return false;
-
-		$msg_conversation_guid = notags(unxmlify($mesg->conversation_guid));
-
-		if($msg_conversation_guid != $guid) {
-			logger("message conversation guid does not belong to the current conversation.");
-			return false;
-		}
-
-		$body = diaspora2bb($msg_text);
-		$message_uri = $msg_author.":".$msg_guid;
-
-		$author_signed_data = $msg_guid.";".$msg_parent_guid.";".$msg_text.";".unxmlify($mesg->created_at).";".$msg_author.";".$msg_conversation_guid;
-
-		$author_signature = base64_decode($msg_author_signature);
-
-		if(strcasecmp($msg_author,$msg["author"]) == 0) {
-			$person = $contact;
-			$key = $msg["key"];
-		} else {
-			$person = self::person_by_handle($msg_author);
-
-			if (is_array($person) && x($person, "pubkey"))
-				$key = $person["pubkey"];
-			else {
-				logger("unable to find author details");
-					return false;
-			}
-		}
-
-		if (!rsa_verify($author_signed_data, $author_signature, $key, "sha256")) {
-			logger("verification failed.");
-			return false;
-		}
-
-		if($msg_parent_author_signature) {
-			$owner_signed_data = $msg_guid.";".$msg_parent_guid.";".$msg_text.";".unxmlify($mesg->created_at).";".$msg_author.";".$msg_conversation_guid;
-
-			$parent_author_signature = base64_decode($msg_parent_author_signature);
-
-			$key = $msg["key"];
-
-			if (!rsa_verify($owner_signed_data, $parent_author_signature, $key, "sha256")) {
-				logger("owner verification failed.");
-				return false;
-			}
-		}
-
-		$r = q("SELECT `id` FROM `mail` WHERE `uri` = '%s' LIMIT 1",
-			dbesc($message_uri)
-		);
-		if($r) {
-			logger("duplicate message already delivered.", LOGGER_DEBUG);
-			return false;
-		}
-
-		q("INSERT INTO `mail` (`uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`)
-			VALUES (%d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
-			intval($importer["uid"]),
-			dbesc($msg_guid),
-			intval($conversation["id"]),
-			dbesc($person["name"]),
-			dbesc($person["photo"]),
-			dbesc($person["url"]),
-			intval($contact["id"]),
-			dbesc($subject),
-			dbesc($body),
-			0,
-			0,
-			dbesc($message_uri),
-			dbesc($author.":".$guid),
-			dbesc($msg_created_at)
-		);
-
-		q("UPDATE `conv` SET `updated` = '%s' WHERE `id` = %d",
-			dbesc(datetime_convert()),
-			intval($conversation["id"])
-		);
-
-		notification(array(
-			"type" => NOTIFY_MAIL,
-			"notify_flags" => $importer["notify-flags"],
-			"language" => $importer["language"],
-			"to_name" => $importer["username"],
-			"to_email" => $importer["email"],
-			"uid" =>$importer["uid"],
-			"item" => array("subject" => $subject, "body" => $body),
-			"source_name" => $person["name"],
-			"source_link" => $person["url"],
-			"source_photo" => $person["thumb"],
-			"verb" => ACTIVITY_POST,
-			"otype" => "mail"
-		));
-	}
-
-	private function receive_conversation($importer, $msg, $data) {
-		$guid = notags(unxmlify($data->guid));
-		$subject = notags(unxmlify($data->subject));
-		$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
-		$author = notags(unxmlify($data->author));
-		$participants = notags(unxmlify($data->participants));
-
-		$messages = $data->message;
-
-		if (!count($messages)) {
-			logger("empty conversation");
-			return false;
-		}
-
-		$contact = self::allowed_contact_by_handle($importer, $msg["author"], true);
-		if (!$contact)
-			return false;
-
-		$conversation = null;
-
-		$c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-			intval($importer["uid"]),
-			dbesc($guid)
-		);
-		if($c)
-			$conversation = $c[0];
-		else {
-			$r = q("INSERT INTO `conv` (`uid`, `guid`, `creator`, `created`, `updated`, `subject`, `recips`)
-				VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s')",
-				intval($importer["uid"]),
-				dbesc($guid),
-				dbesc($author),
-				dbesc(datetime_convert("UTC", "UTC", $created_at)),
-				dbesc(datetime_convert()),
-				dbesc($subject),
-				dbesc($participants)
-			);
-			if($r)
-				$c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-					intval($importer["uid"]),
-					dbesc($guid)
-				);
-
-			if($c)
-				$conversation = $c[0];
-		}
-		if (!$conversation) {
-			logger("unable to create conversation.");
-			return;
-		}
-
-		foreach($messages as $mesg)
-			self::receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation);
-
-		return true;
-	}
-
-	private function construct_like_body($contact, $parent_item, $guid) {
-		$bodyverb = t('%1$s likes %2$s\'s %3$s');
-
-		$ulink = "[url=".$contact["url"]."]".$contact["name"]."[/url]";
-		$alink = "[url=".$parent_item["author-link"]."]".$parent_item["author-name"]."[/url]";
-		$plink = "[url=".App::get_baseurl()."/display/".urlencode($guid)."]".t("status")."[/url]";
-
-		return sprintf($bodyverb, $ulink, $alink, $plink);
-	}
-
-	private function construct_like_object($importer, $parent_item) {
-		$objtype = ACTIVITY_OBJ_NOTE;
-		$link = '<link rel="alternate" type="text/html" href="'.App::get_baseurl()."/display/".$importer["nickname"]."/".$parent_item["id"].'" />';
-		$parent_body = $parent_item["body"];
-
-		$xmldata = array("object" => array("type" => $objtype,
-						"local" => "1",
-						"id" => $parent_item["uri"],
-						"link" => $link,
-						"title" => "",
-						"content" => $parent_body));
-
-		return xml::from_array($xmldata, $xml, true);
-	}
-
-	private function receive_like($importer, $sender, $data) {
-		$positive = notags(unxmlify($data->positive));
-		$guid = notags(unxmlify($data->guid));
-		$parent_type = notags(unxmlify($data->parent_type));
-		$parent_guid = notags(unxmlify($data->parent_guid));
-		$author = notags(unxmlify($data->author));
-
-		// likes on comments aren't supported by Diaspora - only on posts
-		// But maybe this will be supported in the future, so we will accept it.
-		if (!in_array($parent_type, array("Post", "Comment")))
-			return false;
-
-		$contact = self::allowed_contact_by_handle($importer, $sender, true);
-		if (!$contact)
-			return false;
-
-		if (self::message_exists($importer["uid"], $guid))
-			return false;
-
-		$parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact);
-		if (!$parent_item)
-			return false;
-
-		$person = self::person_by_handle($author);
-		if (!is_array($person)) {
-			logger("unable to find author details");
-			return false;
-		}
-
-		// Fetch the contact id - if we know this contact
-		$author_contact = self::author_contact_by_url($contact, $person, $importer["uid"]);
-
-		// "positive" = "false" would be a Dislike - wich isn't currently supported by Diaspora
-		// We would accept this anyhow.
-		if ($positive === "true")
-			$verb = ACTIVITY_LIKE;
-		else
-			$verb = ACTIVITY_DISLIKE;
-
-		$datarray = array();
-
-		$datarray["uid"] = $importer["uid"];
-		$datarray["contact-id"] = $author_contact["cid"];
-		$datarray["network"]  = $author_contact["network"];
-
-		$datarray["author-name"] = $person["name"];
-		$datarray["author-link"] = $person["url"];
-		$datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]);
-
-		$datarray["owner-name"] = $contact["name"];
-		$datarray["owner-link"] = $contact["url"];
-		$datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
-
-		$datarray["guid"] = $guid;
-		$datarray["uri"] = $author.":".$guid;
-
-		$datarray["type"] = "activity";
-		$datarray["verb"] = $verb;
-		$datarray["gravity"] = GRAVITY_LIKE;
-		$datarray["parent-uri"] = $parent_item["uri"];
-
-		$datarray["object-type"] = ACTIVITY_OBJ_NOTE;
-		$datarray["object"] = self::construct_like_object($importer, $parent_item);
-
-		$datarray["body"] = self::construct_like_body($contact, $parent_item, $guid);
-
-		$message_id = item_store($datarray);
-
-		if ($message_id)
-			logger("Stored like ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
-
-		// 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.
-			// 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))
-			);
-
-			// notify others
-			proc_run("php", "include/notifier.php", "comment-import", $message_id);
-		}
-
-		return $message_id;
-	}
-
-	private function receive_message($importer, $data) {
-		$guid = notags(unxmlify($data->guid));
-		$parent_guid = notags(unxmlify($data->parent_guid));
-		$text = unxmlify($data->text);
-		$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
-		$author = notags(unxmlify($data->author));
-		$conversation_guid = notags(unxmlify($data->conversation_guid));
-
-		$contact = self::allowed_contact_by_handle($importer, $author, true);
-		if (!$contact)
-			return false;
-
-		$conversation = null;
-
-		$c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-			intval($importer["uid"]),
-			dbesc($conversation_guid)
-		);
-		if($c)
-			$conversation = $c[0];
-		else {
-			logger("conversation not available.");
-			return false;
-		}
-
-		$reply = 0;
-
-		$body = diaspora2bb($text);
-		$message_uri = $author.":".$guid;
-
-		$person = self::person_by_handle($author);
-		if (!$person) {
-			logger("unable to find author details");
-			return false;
-		}
-
-		$r = q("SELECT `id` FROM `mail` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
-			dbesc($message_uri),
-			intval($importer["uid"])
-		);
-		if($r) {
-			logger("duplicate message already delivered.", LOGGER_DEBUG);
-			return false;
-		}
-
-		q("INSERT INTO `mail` (`uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`)
-				VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')",
-			intval($importer["uid"]),
-			dbesc($guid),
-			intval($conversation["id"]),
-			dbesc($person["name"]),
-			dbesc($person["photo"]),
-			dbesc($person["url"]),
-			intval($contact["id"]),
-			dbesc($conversation["subject"]),
-			dbesc($body),
-			0,
-			1,
-			dbesc($message_uri),
-			dbesc($author.":".$parent_guid),
-			dbesc($created_at)
-		);
-
-		q("UPDATE `conv` SET `updated` = '%s' WHERE `id` = %d",
-			dbesc(datetime_convert()),
-			intval($conversation["id"])
-		);
-
-		return true;
-	}
-
-	private function receive_participation($importer, $data) {
-		// I'm not sure if we can fully support this message type
-		return true;
-	}
-
-	private function receive_photo($importer, $data) {
-		// There doesn't seem to be a reason for this function, since the photo data is transmitted in the status message as well
-		return true;
-	}
-
-	private function receive_poll_participation($importer, $data) {
-		// We don't support polls by now
-		return true;
-	}
-
-	private function receive_profile($importer, $data) {
-		$author = notags(unxmlify($data->author));
-
-		$contact = self::contact_by_handle($importer["uid"], $author);
-		if (!$contact)
-			return;
-
-		$name = unxmlify($data->first_name).((strlen($data->last_name)) ? " ".unxmlify($data->last_name) : "");
-		$image_url = unxmlify($data->image_url);
-		$birthday = unxmlify($data->birthday);
-		$location = diaspora2bb(unxmlify($data->location));
-		$about = diaspora2bb(unxmlify($data->bio));
-		$gender = unxmlify($data->gender);
-		$searchable = (unxmlify($data->searchable) == "true");
-		$nsfw = (unxmlify($data->nsfw) == "true");
-		$tags = unxmlify($data->tag_string);
-
-		$tags = explode("#", $tags);
-
-		$keywords = array();
-		foreach ($tags as $tag) {
-			$tag = trim(strtolower($tag));
-			if ($tag != "")
-				$keywords[] = $tag;
-		}
-
-		$keywords = implode(", ", $keywords);
-
-		$handle_parts = explode("@", $author);
-		$nick = $handle_parts[0];
-
-		if($name === "")
-			$name = $handle_parts[0];
-
-		if( preg_match("|^https?://|", $image_url) === 0)
-			$image_url = "http://".$handle_parts[1].$image_url;
-
-		update_contact_avatar($image_url, $importer["uid"], $contact["id"]);
-
-		// Generic birthday. We don't know the timezone. The year is irrelevant.
-
-		$birthday = str_replace("1000", "1901", $birthday);
-
-		if ($birthday != "")
-			$birthday = datetime_convert("UTC", "UTC", $birthday, "Y-m-d");
-
-		// this is to prevent multiple birthday notifications in a single year
-		// if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year
-
-		if(substr($birthday,5) === substr($contact["bd"],5))
-			$birthday = $contact["bd"];
-
-		$r = q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `name-date` = '%s', `bd` = '%s',
-				`location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d AND `uid` = %d",
-			dbesc($name),
-			dbesc($nick),
-			dbesc($author),
-			dbesc(datetime_convert()),
-			dbesc($birthday),
-			dbesc($location),
-			dbesc($about),
-			dbesc($keywords),
-			dbesc($gender),
-			intval($contact["id"]),
-			intval($importer["uid"])
-		);
-
-		if ($searchable) {
-			poco_check($contact["url"], $name, NETWORK_DIASPORA, $image_url, $about, $location, $gender, $keywords, "",
-				datetime_convert(), 2, $contact["id"], $importer["uid"]);
-		}
-
-		$gcontact = array("url" => $contact["url"], "network" => NETWORK_DIASPORA, "generation" => 2,
-					"photo" => $image_url, "name" => $name, "location" => $location,
-					"about" => $about, "birthday" => $birthday, "gender" => $gender,
-					"addr" => $author, "nick" => $nick, "keywords" => $keywords,
-					"hide" => !$searchable, "nsfw" => $nsfw);
-
-		update_gcontact($gcontact);
-
-		logger("Profile of contact ".$contact["id"]." stored for user ".$importer["uid"], LOGGER_DEBUG);
-
-		return true;
-	}
-
-	private function receive_request_make_friend($importer, $contact) {
-
-		$a = get_app();
-
-		if($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) {
-			q("UPDATE `contact` SET `rel` = %d, `writable` = 1 WHERE `id` = %d AND `uid` = %d",
-				intval(CONTACT_IS_FRIEND),
-				intval($contact["id"]),
-				intval($importer["uid"])
-			);
-		}
-		// send notification
-
-		$r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1",
-			intval($importer["uid"])
-		);
-
-		if($r && !$r[0]["hide-friends"] && !$contact["hidden"] && intval(get_pconfig($importer["uid"], "system", "post_newfriend"))) {
-
-			$self = q("SELECT * FROM `contact` WHERE `self` AND `uid` = %d LIMIT 1",
-				intval($importer["uid"])
-			);
-
-			// they are not CONTACT_IS_FOLLOWER anymore but that's what we have in the array
-
-			if($self && $contact["rel"] == CONTACT_IS_FOLLOWER) {
-
-				$arr = array();
-				$arr["uri"] = $arr["parent-uri"] = item_new_uri($a->get_hostname(), $importer["uid"]);
-				$arr["uid"] = $importer["uid"];
-				$arr["contact-id"] = $self[0]["id"];
-				$arr["wall"] = 1;
-				$arr["type"] = 'wall';
-				$arr["gravity"] = 0;
-				$arr["origin"] = 1;
-				$arr["author-name"] = $arr["owner-name"] = $self[0]["name"];
-				$arr["author-link"] = $arr["owner-link"] = $self[0]["url"];
-				$arr["author-avatar"] = $arr["owner-avatar"] = $self[0]["thumb"];
-				$arr["verb"] = ACTIVITY_FRIEND;
-				$arr["object-type"] = ACTIVITY_OBJ_PERSON;
-
-				$A = "[url=".$self[0]["url"]."]".$self[0]["name"]."[/url]";
-				$B = "[url=".$contact["url"]."]".$contact["name"]."[/url]";
-				$BPhoto = "[url=".$contact["url"]."][img]".$contact["thumb"]."[/img][/url]";
-				$arr["body"] = sprintf(t("%1$s is now friends with %2$s"), $A, $B)."\n\n\n".$Bphoto;
-
-				$arr["object"] = "<object><type>".ACTIVITY_OBJ_PERSON."</type><title>".$contact["name"]."</title>"
-					."<id>".$contact["url"]."/".$contact["name"]."</id>";
-				$arr["object"] .= "<link>".xmlify('<link rel="alternate" type="text/html" href="'.$contact["url"].'" />'."\n");
-				$arr["object"] .= xmlify('<link rel="photo" type="image/jpeg" href="'.$contact["thumb"].'" />'."\n");
-				$arr["object"] .= "</link></object>\n";
-				$arr["last-child"] = 1;
-
-				$arr["allow_cid"] = $user[0]["allow_cid"];
-				$arr["allow_gid"] = $user[0]["allow_gid"];
-				$arr["deny_cid"]  = $user[0]["deny_cid"];
-				$arr["deny_gid"]  = $user[0]["deny_gid"];
-
-				$i = item_store($arr);
-				if($i)
-					proc_run("php", "include/notifier.php", "activity", $i);
-
-			}
-
-		}
-	}
-
-	private function receive_request($importer, $data) {
-		$author = unxmlify($data->author);
-		$recipient = unxmlify($data->recipient);
-
-		if (!$author || !$recipient)
-			return;
-
-		$contact = self::contact_by_handle($importer["uid"],$author);
-
-		if($contact) {
-
-			// perhaps we were already sharing with this person. Now they're sharing with us.
-			// That makes us friends.
-
-			self::receive_request_make_friend($importer, $contact);
-			return true;
-		}
-
-		$ret = self::person_by_handle($author);
-
-		if (!$ret || ($ret["network"] != NETWORK_DIASPORA)) {
-			logger("Cannot resolve diaspora handle ".$author." for ".$recipient);
-			return false;
-		}
-
-		$batch = (($ret["batch"]) ? $ret["batch"] : implode("/", array_slice(explode("/", $ret["url"]), 0, 3))."/receive/public");
-
-		$r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`nurl`,`batch`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`)
-			VALUES (%d, '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s',%d,%d)",
-			intval($importer["uid"]),
-			dbesc($ret["network"]),
-			dbesc($ret["addr"]),
-			datetime_convert(),
-			dbesc($ret["url"]),
-			dbesc(normalise_link($ret["url"])),
-			dbesc($batch),
-			dbesc($ret["name"]),
-			dbesc($ret["nick"]),
-			dbesc($ret["photo"]),
-			dbesc($ret["pubkey"]),
-			dbesc($ret["notify"]),
-			dbesc($ret["poll"]),
-			1,
-			2
-		);
-
-		// find the contact record we just created
-
-		$contact_record = self::contact_by_handle($importer["uid"],$author);
-
-		if (!$contact_record) {
-			logger("unable to locate newly created contact record.");
-			return;
-		}
-
-		$g = q("SELECT `def_gid` FROM `user` WHERE `uid` = %d LIMIT 1",
-			intval($importer["uid"])
-		);
-
-		if($g && intval($g[0]["def_gid"]))
-			group_add_member($importer["uid"], "", $contact_record["id"], $g[0]["def_gid"]);
-
-		if($importer["page-flags"] == PAGE_NORMAL) {
-
-			$hash = random_string().(string)time();   // Generate a confirm_key
-
-			$ret = q("INSERT INTO `intro` (`uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime`)
-				VALUES (%d, %d, %d, %d, '%s', '%s', '%s')",
-				intval($importer["uid"]),
-				intval($contact_record["id"]),
-				0,
-				0,
-				dbesc(t("Sharing notification from Diaspora network")),
-				dbesc($hash),
-				dbesc(datetime_convert())
-			);
-		} else {
-
-			// automatic friend approval
-
-			update_contact_avatar($contact_record["photo"],$importer["uid"],$contact_record["id"]);
-
-			// technically they are sharing with us (CONTACT_IS_SHARING),
-			// but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX
-			// we are going to change the relationship and make them a follower.
-
-			if($importer["page-flags"] == PAGE_FREELOVE)
-				$new_relation = CONTACT_IS_FRIEND;
-			else
-				$new_relation = CONTACT_IS_FOLLOWER;
-
-			$r = q("UPDATE `contact` SET `rel` = %d,
-				`name-date` = '%s',
-				`uri-date` = '%s',
-				`blocked` = 0,
-				`pending` = 0,
-				`writable` = 1
-				WHERE `id` = %d
-				",
-				intval($new_relation),
-				dbesc(datetime_convert()),
-				dbesc(datetime_convert()),
-				intval($contact_record["id"])
-			);
-
-			$u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"]));
-			if($u)
-				$ret = self::send_share($u[0], $contact_record);
-		}
-
-		return true;
-	}
-
-	private function original_item($guid, $orig_author, $author) {
-
-		// Do we already have this item?
-		$r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`,
-				`author-name`, `author-link`, `author-avatar`
-				FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
-			dbesc($guid));
-
-		if($r) {
-			logger("reshared message ".$guid." already exists on system.");
-
-			// Maybe it is already a reshared item?
-			// Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
-			if (self::is_reshare($r[0]["body"]))
-				$r = array();
-			else
-				return $r[0];
-		}
-
-		if (!$r) {
-			$server = "https://".substr($orig_author, strpos($orig_author, "@") + 1);
-			logger("1st try: reshared message ".$guid." will be fetched from original server: ".$server);
-			$item_id = self::store_by_guid($guid, $server);
-
-			if (!$item_id) {
-				$server = "http://".substr($orig_author, strpos($orig_author, "@") + 1);
-				logger("2nd try: reshared message ".$guid." will be fetched from original server: ".$server);
-				$item_id = self::store_by_guid($guid, $server);
-			}
-
-			// Deactivated by now since there is a risk that someone could manipulate postings through this method
-/*			if (!$item_id) {
-				$server = "https://".substr($author, strpos($author, "@") + 1);
-				logger("3rd try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
-				$item_id = self::store_by_guid($guid, $server);
-			}
-			if (!$item_id) {
-				$server = "http://".substr($author, strpos($author, "@") + 1);
-				logger("4th try: reshared message ".$guid." will be fetched from sharer's server: ".$server);
-				$item_id = self::store_by_guid($guid, $server);
-			}
-*/
-			if ($item_id) {
-				$r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`,
-						`author-name`, `author-link`, `author-avatar`
-					FROM `item` WHERE `id` = %d AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
-					intval($item_id));
-
-				if ($r)
-					return $r[0];
-
-			}
-		}
-		return false;
-	}
-
-	private function receive_reshare($importer, $data) {
-		$root_author = notags(unxmlify($data->root_author));
-		$root_guid = notags(unxmlify($data->root_guid));
-		$guid = notags(unxmlify($data->guid));
-		$author = notags(unxmlify($data->author));
-		$public = notags(unxmlify($data->public));
-		$created_at = notags(unxmlify($data->created_at));
-
-		$contact = self::allowed_contact_by_handle($importer, $author, false);
-		if (!$contact)
-			return false;
-
-		if (self::message_exists($importer["uid"], $guid))
-			return false;
-
-		$original_item = self::original_item($root_guid, $root_author, $author);
-		if (!$original_item)
-			return false;
-
-		$orig_url = App::get_baseurl()."/display/".$original_item["guid"];
-
-		$datarray = array();
-
-		$datarray["uid"] = $importer["uid"];
-		$datarray["contact-id"] = $contact["id"];
-		$datarray["network"]  = NETWORK_DIASPORA;
-
-		$datarray["author-name"] = $contact["name"];
-		$datarray["author-link"] = $contact["url"];
-		$datarray["author-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
-
-		$datarray["owner-name"] = $datarray["author-name"];
-		$datarray["owner-link"] = $datarray["author-link"];
-		$datarray["owner-avatar"] = $datarray["author-avatar"];
-
-		$datarray["guid"] = $guid;
-		$datarray["uri"] = $datarray["parent-uri"] = $author.":".$guid;
-
-		$datarray["verb"] = ACTIVITY_POST;
-		$datarray["gravity"] = GRAVITY_PARENT;
-
-		$datarray["object"] = json_encode($data);
-
-		$prefix = share_header($original_item["author-name"], $original_item["author-link"], $original_item["author-avatar"],
-					$original_item["guid"], $original_item["created"], $orig_url);
-		$datarray["body"] = $prefix.$original_item["body"]."[/share]";
-
-		$datarray["tag"] = $original_item["tag"];
-		$datarray["app"]  = $original_item["app"];
-
-		$datarray["plink"] = self::plink($author, $guid);
-		$datarray["private"] = (($public == "false") ? 1 : 0);
-		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
-
-		$datarray["object-type"] = $original_item["object-type"];
-
-		self::fetch_guid($datarray);
-		$message_id = item_store($datarray);
-
-		if ($message_id)
-			logger("Stored reshare ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
-
-		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::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),
-			intval($importer["uid"])
-		);
-		if (!$r)
-			return false;
-
-		// Only delete it if the author really fits
-		if (!link_compare($r[0]["author-link"], $person["url"])) {
-			logger("Item author ".$r[0]["author-link"]." doesn't fit to expected contact ".$person["url"], LOGGER_DEBUG);
-			return false;
-		}
-
-		// Check if the sender is the thread owner
-		$p = q("SELECT `id`, `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"]) AND !link_compare($r[0]["author-link"], $contact["url"])) {
-			logger("Thread author ".$p[0]["author-link"]." and item author ".$r[0]["author-link"]." don't fit to expected contact ".$contact["url"], LOGGER_DEBUG);
-			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
-		q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s', `body` = '' , `title` = '' WHERE `id` = %d",
-			dbesc(datetime_convert()),
-			dbesc(datetime_convert()),
-			intval($r[0]["id"])
-		);
-		delete_thread($r[0]["id"], $r[0]["parent-uri"]);
-
-		logger("Deleted target ".$target_guid." (".$r[0]["id"].") from user ".$importer["uid"]." parent: ".$p[0]["id"], LOGGER_DEBUG);
-
-		// Now check if the retraction needs to be relayed by us
-		if($p[0]["origin"]) {
-
-			// 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` (`retract_iid`,`signed_text`) VALUES (%d,'%s')",
-				intval($r[0]["id"]),
-				dbesc(json_encode($data))
-			);
-			$s = q("select * from sign where retract_iid = %d", intval($r[0]["id"]));
-			logger("Stored signatur for item ".$r[0]["id"]." - ".print_r($s, true), LOGGER_DEBUG);
-
-			// notify others
-			proc_run("php", "include/notifier.php", "drop", $r[0]["id"]);
-		}
-	}
-
-	private function receive_retraction($importer, $sender, $data) {
-		$target_type = notags(unxmlify($data->target_type));
-
-		$contact = self::contact_by_handle($importer["uid"], $sender);
-		if (!$contact) {
-			logger("cannot find contact for sender: ".$sender." and user ".$importer["uid"]);
-			return false;
-		}
-
-		logger("Got retraction for ".$target_type.", sender ".$sender." and user ".$importer["uid"], LOGGER_DEBUG);
-
-		switch ($target_type) {
-			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":
-				/// @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;
-
-			default:
-				logger("Unknown target type ".$target_type);
-				return false;
-		}
-		return true;
-	}
-
-	private function receive_status_message($importer, $data) {
-
-		$raw_message = unxmlify($data->raw_message);
-		$guid = notags(unxmlify($data->guid));
-		$author = notags(unxmlify($data->author));
-		$public = notags(unxmlify($data->public));
-		$created_at = notags(unxmlify($data->created_at));
-		$provider_display_name = notags(unxmlify($data->provider_display_name));
-
-		/// @todo enable support for polls
-		//if ($data->poll) {
-		//	foreach ($data->poll AS $poll)
-		//		print_r($poll);
-		//	die("poll!\n");
-		//}
-		$contact = self::allowed_contact_by_handle($importer, $author, false);
-		if (!$contact)
-			return false;
-
-		if (self::message_exists($importer["uid"], $guid))
-			return false;
-
-		$address = array();
-		if ($data->location)
-			foreach ($data->location->children() AS $fieldname => $data)
-				$address[$fieldname] = notags(unxmlify($data));
-
-		$body = diaspora2bb($raw_message);
-
-		$datarray = array();
-
-		if ($data->photo) {
-			foreach ($data->photo AS $photo)
-				$body = "[img]".$photo->remote_photo_path.$photo->remote_photo_name."[/img]\n".$body;
-
-			$datarray["object-type"] = ACTIVITY_OBJ_PHOTO;
-		} else {
-			$datarray["object-type"] = ACTIVITY_OBJ_NOTE;
-
-			// Add OEmbed and other information to the body
-			if (!self::is_redmatrix($contact["url"]))
-				$body = add_page_info_to_body($body, false, true);
-		}
-
-		$datarray["uid"] = $importer["uid"];
-		$datarray["contact-id"] = $contact["id"];
-		$datarray["network"] = NETWORK_DIASPORA;
-
-		$datarray["author-name"] = $contact["name"];
-		$datarray["author-link"] = $contact["url"];
-		$datarray["author-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]);
-
-		$datarray["owner-name"] = $datarray["author-name"];
-		$datarray["owner-link"] = $datarray["author-link"];
-		$datarray["owner-avatar"] = $datarray["author-avatar"];
-
-		$datarray["guid"] = $guid;
-		$datarray["uri"] = $datarray["parent-uri"] = $author.":".$guid;
-
-		$datarray["verb"] = ACTIVITY_POST;
-		$datarray["gravity"] = GRAVITY_PARENT;
-
-		$datarray["object"] = json_encode($data);
-
-		$datarray["body"] = $body;
-
-		if ($provider_display_name != "")
-			$datarray["app"] = $provider_display_name;
-
-		$datarray["plink"] = self::plink($author, $guid);
-		$datarray["private"] = (($public == "false") ? 1 : 0);
-		$datarray["changed"] = $datarray["created"] = $datarray["edited"] = datetime_convert("UTC", "UTC", $created_at);
-
-		if (isset($address["address"]))
-			$datarray["location"] = $address["address"];
-
-		if (isset($address["lat"]) AND isset($address["lng"]))
-			$datarray["coord"] = $address["lat"]." ".$address["lng"];
-
-		self::fetch_guid($datarray);
-		$message_id = item_store($datarray);
-
-		if ($message_id)
-			logger("Stored item ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
-
-		return $message_id;
-	}
-
-	/******************************************************************************************
-	 * Here are all the functions that are needed to transmit data with the Diaspora protocol *
-	 ******************************************************************************************/
-
-	private function my_handle($me) {
-		if ($contact["addr"] != "")
-			return $contact["addr"];
-
-		// Normally we should have a filled "addr" field - but in the past this wasn't the case
-		// So - just in case - we build the the address here.
-		return $me["nickname"]."@".substr(App::get_baseurl(), strpos(App::get_baseurl(),"://") + 3);
-	}
-
-	private function build_public_message($msg, $user, $contact, $prvkey, $pubkey) {
-
-		logger("Message: ".$msg, LOGGER_DATA);
-
-		$handle = self::my_handle($user);
-
-		$b64url_data = base64url_encode($msg);
-
-		$data = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data);
-
-		$type = "application/xml";
-		$encoding = "base64url";
-		$alg = "RSA-SHA256";
-
-		$signable_data = $data.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg);
-
-		$signature = rsa_sign($signable_data,$prvkey);
-		$sig = base64url_encode($signature);
-
-		$xmldata = array("diaspora" => array("header" => array("author_id" => $handle),
-						"me:env" => array("me:encoding" => "base64url",
-								"me:alg" => "RSA-SHA256",
-								"me:data" => $data,
-								"@attributes" => array("type" => "application/xml"),
-								"me:sig" => $sig)));
-
-		$namespaces = array("" => "https://joindiaspora.com/protocol",
-				"me" => "http://salmon-protocol.org/ns/magic-env");
-
-		$magic_env = xml::from_array($xmldata, $xml, false, $namespaces);
-
-		logger("magic_env: ".$magic_env, LOGGER_DATA);
-		return $magic_env;
-	}
-
-	private function build_private_message($msg, $user, $contact, $prvkey, $pubkey) {
-
-		logger("Message: ".$msg, LOGGER_DATA);
-
-		// without a public key nothing will work
-
-		if (!$pubkey) {
-			logger("pubkey missing: contact id: ".$contact["id"]);
-			return false;
-		}
-
-		$inner_aes_key = random_string(32);
-		$b_inner_aes_key = base64_encode($inner_aes_key);
-		$inner_iv = random_string(16);
-		$b_inner_iv = base64_encode($inner_iv);
-
-		$outer_aes_key = random_string(32);
-		$b_outer_aes_key = base64_encode($outer_aes_key);
-		$outer_iv = random_string(16);
-		$b_outer_iv = base64_encode($outer_iv);
-
-		$handle = self::my_handle($user);
-
-		$padded_data = pkcs5_pad($msg,16);
-		$inner_encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $inner_aes_key, $padded_data, MCRYPT_MODE_CBC, $inner_iv);
-
-		$b64_data = base64_encode($inner_encrypted);
-
-
-		$b64url_data = base64url_encode($b64_data);
-		$data = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data);
-
-		$type = "application/xml";
-		$encoding = "base64url";
-		$alg = "RSA-SHA256";
-
-		$signable_data = $data.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg);
-
-		$signature = rsa_sign($signable_data,$prvkey);
-		$sig = base64url_encode($signature);
-
-		$xmldata = array("decrypted_header" => array("iv" => $b_inner_iv,
-							"aes_key" => $b_inner_aes_key,
-							"author_id" => $handle));
-
-		$decrypted_header = xml::from_array($xmldata, $xml, true);
-		$decrypted_header = pkcs5_pad($decrypted_header,16);
-
-		$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $outer_aes_key, $decrypted_header, MCRYPT_MODE_CBC, $outer_iv);
-
-		$outer_json = json_encode(array("iv" => $b_outer_iv, "key" => $b_outer_aes_key));
-
-		$encrypted_outer_key_bundle = "";
-		openssl_public_encrypt($outer_json, $encrypted_outer_key_bundle, $pubkey);
-
-		$b64_encrypted_outer_key_bundle = base64_encode($encrypted_outer_key_bundle);
-
-		logger("outer_bundle: ".$b64_encrypted_outer_key_bundle." key: ".$pubkey, LOGGER_DATA);
-
-		$encrypted_header_json_object = json_encode(array("aes_key" => base64_encode($encrypted_outer_key_bundle),
-								"ciphertext" => base64_encode($ciphertext)));
-		$cipher_json = base64_encode($encrypted_header_json_object);
-
-		$xmldata = array("diaspora" => array("encrypted_header" => $cipher_json,
-						"me:env" => array("me:encoding" => "base64url",
-								"me:alg" => "RSA-SHA256",
-								"me:data" => $data,
-								"@attributes" => array("type" => "application/xml"),
-								"me:sig" => $sig)));
-
-		$namespaces = array("" => "https://joindiaspora.com/protocol",
-				"me" => "http://salmon-protocol.org/ns/magic-env");
-
-		$magic_env = xml::from_array($xmldata, $xml, false, $namespaces);
-
-		logger("magic_env: ".$magic_env, LOGGER_DATA);
-		return $magic_env;
-	}
-
-	private function build_message($msg, $user, $contact, $prvkey, $pubkey, $public = false) {
-
-		if ($public)
-			$magic_env =  self::build_public_message($msg,$user,$contact,$prvkey,$pubkey);
-		else
-			$magic_env =  self::build_private_message($msg,$user,$contact,$prvkey,$pubkey);
-
-		// The data that will be transmitted is double encoded via "urlencode", strange ...
-		$slap = "xml=".urlencode(urlencode($magic_env));
-		return $slap;
-	}
-
-	private function signature($owner, $message) {
-		$sigmsg = $message;
-		unset($sigmsg["author_signature"]);
-		unset($sigmsg["parent_author_signature"]);
-
-		$signed_text = implode(";", $sigmsg);
-
-		return base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
-	}
-
-	public static function transmit($owner, $contact, $slap, $public_batch, $queue_run=false, $guid = "") {
-
-		$a = get_app();
-
-		$enabled = intval(get_config("system", "diaspora_enabled"));
-		if(!$enabled)
-			return 200;
-
-		$logid = random_string(4);
-		$dest_url = (($public_batch) ? $contact["batch"] : $contact["notify"]);
-		if (!$dest_url) {
-			logger("no url for contact: ".$contact["id"]." batch mode =".$public_batch);
-			return 0;
-		}
-
-		logger("transmit: ".$logid."-".$guid." ".$dest_url);
-
-		if (!$queue_run && was_recently_delayed($contact["id"])) {
-			$return_code = 0;
-		} else {
-			if (!intval(get_config("system", "diaspora_test"))) {
-				post_url($dest_url."/", $slap);
-				$return_code = $a->get_curl_code();
-			} else {
-				logger("test_mode");
-				return 200;
-			}
-		}
-
-		logger("transmit: ".$logid."-".$guid." returns: ".$return_code);
-
-		if(!$return_code || (($return_code == 503) && (stristr($a->get_curl_headers(), "retry-after")))) {
-			logger("queue message");
-
-			$r = q("SELECT `id` FROM `queue` WHERE `cid` = %d AND `network` = '%s' AND `content` = '%s' AND `batch` = %d LIMIT 1",
-				intval($contact["id"]),
-				dbesc(NETWORK_DIASPORA),
-				dbesc($slap),
-				intval($public_batch)
-			);
-			if($r) {
-				logger("add_to_queue ignored - identical item already in queue");
-			} else {
-				// queue message for redelivery
-				add_to_queue($contact["id"], NETWORK_DIASPORA, $slap, $public_batch);
-			}
-		}
-
-		return(($return_code) ? $return_code : (-1));
-	}
-
-
-	private function build_and_transmit($owner, $contact, $type, $message, $public_batch = false, $guid = "", $spool = false) {
-
-		$data = array("XML" => array("post" => array($type => $message)));
-
-		$msg = xml::from_array($data, $xml);
-
-		logger('message: '.$msg, LOGGER_DATA);
-		logger('send guid '.$guid, LOGGER_DEBUG);
-
-		$slap = self::build_message($msg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch);
-
-		if ($spool) {
-			add_to_queue($contact['id'], NETWORK_DIASPORA, $slap, $public_batch);
-			return true;
-		} else
-			$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_share($owner,$contact) {
-
-		$message = array("sender_handle" => self::my_handle($owner),
-				"recipient_handle" => $contact["addr"]);
-
-		return self::build_and_transmit($owner, $contact, "request", $message);
-	}
-
-	public static function send_unshare($owner,$contact) {
-
-		$message = array("post_guid" => $owner["guid"],
-				"diaspora_handle" => self::my_handle($owner),
-				"type" => "Person");
-
-		return self::build_and_transmit($owner, $contact, "retraction", $message);
-	}
-
-	public static function is_reshare($body) {
-		$body = trim($body);
-
-		// Skip if it isn't a pure repeated messages
-		// Does it start with a share?
-		if (strpos($body, "[share") > 0)
-			return(false);
-
-		// Does it end with a share?
-		if (strlen($body) > (strrpos($body, "[/share]") + 8))
-			return(false);
-
-		$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
-		// Skip if there is no shared message in there
-		if ($body == $attributes)
-			return(false);
-
-		$guid = "";
-		preg_match("/guid='(.*?)'/ism", $attributes, $matches);
-		if ($matches[1] != "")
-			$guid = $matches[1];
-
-		preg_match('/guid="(.*?)"/ism', $attributes, $matches);
-		if ($matches[1] != "")
-			$guid = $matches[1];
-
-		if ($guid != "") {
-			$r = q("SELECT `contact-id` FROM `item` WHERE `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1",
-				dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA);
-			if ($r) {
-				$ret= array();
-				$ret["root_handle"] = self::handle_from_contact($r[0]["contact-id"]);
-				$ret["root_guid"] = $guid;
-				return($ret);
-			}
-		}
-
-		$profile = "";
-		preg_match("/profile='(.*?)'/ism", $attributes, $matches);
-		if ($matches[1] != "")
-			$profile = $matches[1];
-
-		preg_match('/profile="(.*?)"/ism', $attributes, $matches);
-		if ($matches[1] != "")
-			$profile = $matches[1];
-
-		$ret= array();
-
-		$ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile);
-		if (($ret["root_handle"] == $profile) OR ($ret["root_handle"] == ""))
-			return(false);
-
-		$link = "";
-		preg_match("/link='(.*?)'/ism", $attributes, $matches);
-		if ($matches[1] != "")
-			$link = $matches[1];
-
-		preg_match('/link="(.*?)"/ism', $attributes, $matches);
-		if ($matches[1] != "")
-			$link = $matches[1];
-
-		$ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link);
-		if (($ret["root_guid"] == $link) OR ($ret["root_guid"] == ""))
-			return(false);
-		return($ret);
-	}
-
-	public static function send_status($item, $owner, $contact, $public_batch = false) {
-
-		$myaddr = self::my_handle($owner);
-
-		$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"];
-			$body = $item["body"];
-
-			// convert to markdown
-			$body = html_entity_decode(bb2diaspora($body));
-
-			// Adding the title
-			if(strlen($title))
-				$body = "## ".html_entity_decode($title)."\n\n".$body;
-
-			if ($item["attach"]) {
-				$cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism', $item["attach"], $matches, PREG_SET_ORDER);
-				if(cnt) {
-					$body .= "\n".t("Attachments:")."\n";
-					foreach($matches as $mtch)
-						$body .= "[".$mtch[3]."](".$mtch[1].")\n";
-				}
-			}
-
-			$location = array();
-
-			if ($item["location"] != "")
-				$location["address"] = $item["location"];
-
-			if ($item["coord"] != "") {
-				$coord = explode(" ", $item["coord"]);
-				$location["lat"] = $coord[0];
-				$location["lng"] = $coord[1];
-			}
-
-			$message = array("raw_message" => $body,
-					"location" => $location,
-					"guid" => $item["guid"],
-					"diaspora_handle" => $myaddr,
-					"public" => $public,
-					"created_at" => $created,
-					"provider_display_name" => $item["app"]);
-
-			if (count($location) == 0)
-				unset($message["location"]);
-
-			$type = "status_message";
-		}
-
-		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
-	}
-
-	private function construct_like($item, $owner) {
-
-		$myaddr = self::my_handle($owner);
-
-		$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
-			dbesc($item["thr-parent"]));
-		if(!$p)
-			return false;
-
-		$parent = $p[0];
-
-		$target_type = ($parent["uri"] === $parent["parent-uri"] ? "Post" : "Comment");
-		$positive = "true";
-
-		return(array("positive" => $positive,
-				"guid" => $item["guid"],
-				"target_type" => $target_type,
-				"parent_guid" => $parent["guid"],
-				"author_signature" => $authorsig,
-				"diaspora_handle" => $myaddr));
-	}
-
-	private function construct_comment($item, $owner) {
-
-		$myaddr = self::my_handle($owner);
-
-		$p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1",
-			intval($item["parent"]),
-			intval($item["parent"])
-		);
-
-		if (!$p)
-			return false;
-
-		$parent = $p[0];
-
-		$text = html_entity_decode(bb2diaspora($item["body"]));
-
-		return(array("guid" => $item["guid"],
-				"parent_guid" => $parent["guid"],
-				"author_signature" => "",
-				"text" => $text,
-				"diaspora_handle" => $myaddr));
-	}
-
-	public static function send_followup($item,$owner,$contact,$public_batch = false) {
-
-		if($item['verb'] === ACTIVITY_LIKE) {
-			$message = self::construct_like($item, $owner);
-			$type = "like";
-		} else {
-			$message = self::construct_comment($item, $owner);
-			$type = "comment";
-		}
-
-		if (!$message)
-			return false;
-
-		$message["author_signature"] = self::signature($owner, $message);
-
-		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
-	}
-
-	private function message_from_signatur($item, $signature) {
-
-		// Split the signed text
-		$signed_parts = explode(";", $signature['signed_text']);
-
-		if ($item["deleted"])
-			$message = array("parent_author_signature" => "",
-					"target_guid" => $signed_parts[0],
-					"target_type" => $signed_parts[1],
-					"sender_handle" => $signature['signer'],
-					"target_author_signature" => $signature['signature']);
-		elseif ($item['verb'] === ACTIVITY_LIKE)
-			$message = array("positive" => $signed_parts[0],
-					"guid" => $signed_parts[1],
-					"target_type" => $signed_parts[2],
-					"parent_guid" => $signed_parts[3],
-					"parent_author_signature" => "",
-					"author_signature" => $signature['signature'],
-					"diaspora_handle" => $signed_parts[4]);
-		else {
-			// Remove the comment guid
-			$guid = array_shift($signed_parts);
-
-			// Remove the parent guid
-			$parent_guid = array_shift($signed_parts);
-
-			// Remove the handle
-			$handle = array_pop($signed_parts);
-
-			// Glue the parts together
-			$text = implode(";", $signed_parts);
-
-			$message = array("guid" => $guid,
-					"parent_guid" => $parent_guid,
-					"parent_author_signature" => "",
-					"author_signature" => $signature['signature'],
-					"text" => implode(";", $signed_parts),
-					"diaspora_handle" => $handle);
-		}
-		return $message;
-	}
-
-	public static function send_relay($item, $owner, $contact, $public_batch = false) {
-
-		if ($item["deleted"]) {
-			$sql_sign_id = "retract_iid";
-			$type = "relayable_retraction";
-		} elseif ($item['verb'] === ACTIVITY_LIKE) {
-			$sql_sign_id = "iid";
-			$type = "like";
-		} else {
-			$sql_sign_id = "iid";
-			$type = "comment";
-		}
-
-		logger("Got relayable data ".$type." for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG);
-
-		// fetch the original signature
-
-		$r = q("SELECT `signed_text`, `signature`, `signer` FROM `sign` WHERE `".$sql_sign_id."` = %d LIMIT 1",
-			intval($item["id"]));
-
-		if (!$r)
-			return self::send_followup($item, $owner, $contact, $public_batch);
-
-		$signature = $r[0];
-
-		// Old way - is used by the internal Friendica functions
-		/// @todo Change all signatur storing functions to the new format
-		if ($signature['signed_text'] AND $signature['signature'] AND $signature['signer'])
-			$message = self::message_from_signatur($item, $signature);
-		else {// New way
-			$msg = json_decode($signature['signed_text'], true);
-
-			$message = array();
-			foreach ($msg AS $field => $data) {
-				if (!$item["deleted"]) {
-					if ($field == "author")
-						$field = "diaspora_handle";
-					if ($field == "parent_type")
-						$field = "target_type";
-				}
-
-				$message[$field] = $data;
-			}
-		}
-
-		if ($item["deleted"]) {
-			$signed_text = $message["target_guid"].';'.$message["target_type"];
-			$message["parent_author_signature"] = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
-		} else
-			$message["parent_author_signature"] = self::signature($owner, $message);
-
-		logger("Relayed data ".print_r($message, true), LOGGER_DEBUG);
-
-		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
-	}
-
-	public static function send_retraction($item, $owner, $contact, $public_batch = false) {
-
-		$myaddr = self::my_handle($owner);
-
-		// Check whether the retraction is for a top-level post or whether it's a relayable
-		if ($item["uri"] !== $item["parent-uri"]) {
-			$msg_type = "relayable_retraction";
-			$target_type = (($item["verb"] === ACTIVITY_LIKE) ? "Like" : "Comment");
-		} else {
-			$msg_type = "signed_retraction";
-			$target_type = "StatusMessage";
-		}
-
-		$signed_text = $item["guid"].";".$target_type;
-
-		$message = array("target_guid" => $item['guid'],
-				"target_type" => $target_type,
-				"sender_handle" => $myaddr,
-				"target_author_signature" => base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')));
-
-		return self::build_and_transmit($owner, $contact, $msg_type, $message, $public_batch, $item["guid"]);
-	}
-
-	public static function send_mail($item, $owner, $contact) {
-
-		$myaddr = self::my_handle($owner);
-
-		$r = q("SELECT * FROM `conv` WHERE `id` = %d AND `uid` = %d LIMIT 1",
-			intval($item["convid"]),
-			intval($item["uid"])
-		);
-
-		if (!$r) {
-			logger("conversation not found.");
-			return;
-		}
-		$cnv = $r[0];
-
-		$conv = array(
-			"guid" => $cnv["guid"],
-			"subject" => $cnv["subject"],
-			"created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d H:i:s \U\T\C'),
-			"diaspora_handle" => $cnv["creator"],
-			"participant_handles" => $cnv["recips"]
-		);
-
-		$body = bb2diaspora($item["body"]);
-		$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'];
-		$sig = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
-
-		$msg = array(
-			"guid" => $item["guid"],
-			"parent_guid" => $cnv["guid"],
-			"parent_author_signature" => $sig,
-			"author_signature" => $sig,
-			"text" => $body,
-			"created_at" => $created,
-			"diaspora_handle" => $myaddr,
-			"conversation_guid" => $cnv["guid"]
-		);
-
-		if ($item["reply"]) {
-			$message = $msg;
-			$type = "message";
-		} else {
-			$message = array("guid" => $cnv["guid"],
-					"subject" => $cnv["subject"],
-					"created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d H:i:s \U\T\C'),
-					"message" => $msg,
-					"diaspora_handle" => $cnv["creator"],
-					"participant_handles" => $cnv["recips"]);
-
-			$type = "conversation";
-		}
-
-		return self::build_and_transmit($owner, $contact, $type, $message, false, $item["guid"]);
-	}
-
-	public static function send_profile($uid) {
-
-		if (!$uid)
-			return;
-
-		$recips = q("SELECT `id`,`name`,`network`,`pubkey`,`notify` FROM `contact` WHERE `network` = '%s'
-			AND `uid` = %d AND `rel` != %d",
-			dbesc(NETWORK_DIASPORA),
-			intval($uid),
-			intval(CONTACT_IS_SHARING)
-		);
-		if (!$recips)
-			return;
-
-		$r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `user`.*, `user`.`prvkey` AS `uprvkey`, `contact`.`addr`
-			FROM `profile`
-			INNER JOIN `user` ON `profile`.`uid` = `user`.`uid`
-			INNER JOIN `contact` ON `profile`.`uid` = `contact`.`uid`
-			WHERE `user`.`uid` = %d AND `profile`.`is-default` AND `contact`.`self` LIMIT 1",
-			intval($uid)
-		);
-
-		if (!$r)
-			return;
-
-		$profile = $r[0];
-
-		$handle = $profile["addr"];
-		$first = ((strpos($profile['name'],' ')
-			? trim(substr($profile['name'],0,strpos($profile['name'],' '))) : $profile['name']));
-		$last = (($first === $profile['name']) ? '' : trim(substr($profile['name'], strlen($first))));
-		$large = App::get_baseurl().'/photo/custom/300/'.$profile['uid'].'.jpg';
-		$medium = App::get_baseurl().'/photo/custom/100/'.$profile['uid'].'.jpg';
-		$small = App::get_baseurl().'/photo/custom/50/'  .$profile['uid'].'.jpg';
-		$searchable = (($profile['publish'] && $profile['net-publish']) ? 'true' : 'false');
-
-		if ($searchable === 'true') {
-			$dob = '1000-00-00';
-
-			if (($profile['dob']) && ($profile['dob'] != '0000-00-00'))
-				$dob = ((intval($profile['dob'])) ? intval($profile['dob']) : '1000') .'-'. datetime_convert('UTC','UTC',$profile['dob'],'m-d');
-
-			$about = $profile['about'];
-			$about = strip_tags(bbcode($about));
-
-			$location = formatted_location($profile);
-			$tags = '';
-			if ($profile['pub_keywords']) {
-				$kw = str_replace(',',' ',$profile['pub_keywords']);
-				$kw = str_replace('  ',' ',$kw);
-				$arr = explode(' ',$profile['pub_keywords']);
-				if (count($arr)) {
-					for($x = 0; $x < 5; $x ++) {
-						if (trim($arr[$x]))
-							$tags .= '#'. trim($arr[$x]) .' ';
-					}
-				}
-			}
-			$tags = trim($tags);
-		}
-
-		$message = array("diaspora_handle" => $handle,
-				"first_name" => $first,
-				"last_name" => $last,
-				"image_url" => $large,
-				"image_url_medium" => $medium,
-				"image_url_small" => $small,
-				"birthday" => $dob,
-				"gender" => $profile['gender'],
-				"bio" => $about,
-				"location" => $location,
-				"searchable" => $searchable,
-				"tag_string" => $tags);
-
-		foreach($recips as $recip)
-			self::build_and_transmit($profile, $recip, "profile", $message, false, "", true);
-	}
-}
-?>

From 4b5e7007a7148d85858f6851bdb8900dfb05e7cd Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 14 Mar 2016 23:54:01 +0100
Subject: [PATCH 200/273] Bugfix: XML copy had problems with "&"

---
 include/diaspora.php | 12 ++++++------
 include/xml.php      |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 75cedeccd1..4c3cb41726 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -291,7 +291,7 @@ class diaspora {
 				return self::receive_account_deletion($importer, $fields);
 
 			case "comment":
-				return self::receive_comment($importer, $sender, $fields);
+				return self::receive_comment($importer, $sender, $fields, $msg["message"]);
 
 			case "conversation":
 				return self::receive_conversation($importer, $msg, $fields);
@@ -324,7 +324,7 @@ class diaspora {
 				return self::receive_retraction($importer, $sender, $fields);
 
 			case "status_message":
-				return self::receive_status_message($importer, $fields);
+				return self::receive_status_message($importer, $fields, $msg["message"]);
 
 			default:
 				logger("Unknown message type ".$type);
@@ -841,7 +841,7 @@ class diaspora {
 		return true;
 	}
 
-	private function receive_comment($importer, $sender, $data) {
+	private function receive_comment($importer, $sender, $data, $xml) {
 		$guid = notags(unxmlify($data->guid));
 		$parent_guid = notags(unxmlify($data->parent_guid));
 		$text = unxmlify($data->text);
@@ -890,7 +890,7 @@ class diaspora {
 		$datarray["parent-uri"] = $parent_item["uri"];
 
 		$datarray["object-type"] = ACTIVITY_OBJ_COMMENT;
-		$datarray["object"] = json_encode($data);
+		$datarray["object"] = $xml;
 
 		$datarray["body"] = diaspora2bb($text);
 
@@ -1769,7 +1769,7 @@ class diaspora {
 		return true;
 	}
 
-	private function receive_status_message($importer, $data) {
+	private function receive_status_message($importer, $data, $xml) {
 
 		$raw_message = unxmlify($data->raw_message);
 		$guid = notags(unxmlify($data->guid));
@@ -1831,7 +1831,7 @@ class diaspora {
 		$datarray["verb"] = ACTIVITY_POST;
 		$datarray["gravity"] = GRAVITY_PARENT;
 
-		$datarray["object"] = json_encode($data);
+		$datarray["object"] = $xml;
 
 		$datarray["body"] = $body;
 
diff --git a/include/xml.php b/include/xml.php
index c2313648ce..c74c23c473 100644
--- a/include/xml.php
+++ b/include/xml.php
@@ -62,7 +62,7 @@ class xml {
 
 	function copy(&$source, &$target, $elementname) {
 		if (count($source->children()) == 0)
-			$target->addChild($elementname, $source);
+			$target->addChild($elementname, xmlify($source));
 		else {
 			$child = $target->addChild($elementname);
 			foreach ($source->children() AS $childfield => $childentry)

From eed55664fc61a0e285dcf5c814b39496537c7039 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 15 Mar 2016 00:26:28 +0100
Subject: [PATCH 201/273] Reshares now store the original XML as well.

---
 include/diaspora.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 4c3cb41726..3c3f5cb25a 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -318,7 +318,7 @@ class diaspora {
 				return self::receive_request($importer, $fields);
 
 			case "reshare":
-				return self::receive_reshare($importer, $fields);
+				return self::receive_reshare($importer, $fields, $msg["message"]);
 
 			case "retraction":
 				return self::receive_retraction($importer, $sender, $fields);
@@ -1611,7 +1611,7 @@ class diaspora {
 		return false;
 	}
 
-	private function receive_reshare($importer, $data) {
+	private function receive_reshare($importer, $data, $xml) {
 		$root_author = notags(unxmlify($data->root_author));
 		$root_guid = notags(unxmlify($data->root_guid));
 		$guid = notags(unxmlify($data->guid));
@@ -1652,7 +1652,7 @@ class diaspora {
 		$datarray["verb"] = ACTIVITY_POST;
 		$datarray["gravity"] = GRAVITY_PARENT;
 
-		$datarray["object"] = json_encode($data);
+		$datarray["object"] = $xml;
 
 		$prefix = share_header($original_item["author-name"], $original_item["author-link"], $original_item["author-avatar"],
 					$original_item["guid"], $original_item["created"], $orig_url);

From 3f2a23d48c0b588f0a31bb7cdb8b6490f307029f Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 15 Mar 2016 07:05:10 +0100
Subject: [PATCH 202/273] Unused files are removed

---
 view/templates/diasp_dec_hdr.tpl              |  9 ------
 view/templates/diaspora_comment.tpl           | 12 --------
 view/templates/diaspora_comment_relay.tpl     | 13 --------
 view/templates/diaspora_conversation.tpl      | 30 -------------------
 view/templates/diaspora_like.tpl              | 13 --------
 view/templates/diaspora_like_relay.tpl        | 14 ---------
 view/templates/diaspora_message.tpl           | 17 -----------
 view/templates/diaspora_photo.tpl             | 14 ---------
 view/templates/diaspora_post.tpl              | 13 --------
 view/templates/diaspora_profile.tpl           | 17 -----------
 view/templates/diaspora_relay_retraction.tpl  | 10 -------
 .../diaspora_relayable_retraction.tpl         | 12 --------
 view/templates/diaspora_reshare.tpl           | 14 ---------
 view/templates/diaspora_retract.tpl           | 10 -------
 view/templates/diaspora_share.tpl             |  9 ------
 view/templates/diaspora_signed_retract.tpl    | 11 -------
 16 files changed, 218 deletions(-)
 delete mode 100644 view/templates/diasp_dec_hdr.tpl
 delete mode 100644 view/templates/diaspora_comment.tpl
 delete mode 100644 view/templates/diaspora_comment_relay.tpl
 delete mode 100644 view/templates/diaspora_conversation.tpl
 delete mode 100644 view/templates/diaspora_like.tpl
 delete mode 100644 view/templates/diaspora_like_relay.tpl
 delete mode 100644 view/templates/diaspora_message.tpl
 delete mode 100644 view/templates/diaspora_photo.tpl
 delete mode 100644 view/templates/diaspora_post.tpl
 delete mode 100644 view/templates/diaspora_profile.tpl
 delete mode 100644 view/templates/diaspora_relay_retraction.tpl
 delete mode 100644 view/templates/diaspora_relayable_retraction.tpl
 delete mode 100644 view/templates/diaspora_reshare.tpl
 delete mode 100644 view/templates/diaspora_retract.tpl
 delete mode 100644 view/templates/diaspora_share.tpl
 delete mode 100644 view/templates/diaspora_signed_retract.tpl

diff --git a/view/templates/diasp_dec_hdr.tpl b/view/templates/diasp_dec_hdr.tpl
deleted file mode 100644
index 136d1ca302..0000000000
--- a/view/templates/diasp_dec_hdr.tpl
+++ /dev/null
@@ -1,9 +0,0 @@
-
-<decrypted_hdeader>
-  <iv>{{$inner_iv}}</iv>
-  <aes_key>{{$inner_key}}</aes_key>
-  <author>
-    <name>{{$author_name}}</name>
-    <uri>{{$author_uri}}</uri>
-  </author>
-</decrypted_header>
diff --git a/view/templates/diaspora_comment.tpl b/view/templates/diaspora_comment.tpl
deleted file mode 100644
index 107cc73022..0000000000
--- a/view/templates/diaspora_comment.tpl
+++ /dev/null
@@ -1,12 +0,0 @@
-
-<XML>
-  <post>
-    <comment>
-      <guid>{{$guid}}</guid>
-      <parent_guid>{{$parent_guid}}</parent_guid>
-      <author_signature>{{$authorsig}}</author_signature>
-      <text>{{$body}}</text>
-      <diaspora_handle>{{$handle}}</diaspora_handle>
-    </comment>
-  </post>
-</XML>
\ No newline at end of file
diff --git a/view/templates/diaspora_comment_relay.tpl b/view/templates/diaspora_comment_relay.tpl
deleted file mode 100644
index b4f84dc84e..0000000000
--- a/view/templates/diaspora_comment_relay.tpl
+++ /dev/null
@@ -1,13 +0,0 @@
-
-<XML>
-  <post>
-    <comment>
-      <guid>{{$guid}}</guid>
-      <parent_guid>{{$parent_guid}}</parent_guid>
-      <parent_author_signature>{{$parentsig}}</parent_author_signature>
-      <author_signature>{{$authorsig}}</author_signature>
-      <text>{{$body}}</text>
-      <diaspora_handle>{{$handle}}</diaspora_handle>
-    </comment>
-  </post>
-</XML>
\ No newline at end of file
diff --git a/view/templates/diaspora_conversation.tpl b/view/templates/diaspora_conversation.tpl
deleted file mode 100644
index 28e4cdb98f..0000000000
--- a/view/templates/diaspora_conversation.tpl
+++ /dev/null
@@ -1,30 +0,0 @@
-
-<XML>
-  <post>
-    <conversation>
-      <guid>{{$conv.guid}}</guid>
-      <subject>{{$conv.subject}}</subject>
-      <created_at>{{$conv.created_at}}</created_at>
-
-      {{foreach $conv.messages as $msg}}
-
-      <message>
-        <guid>{{$msg.guid}}</guid>
-        <parent_guid>{{$msg.parent_guid}}</parent_guid>
-        {{if $msg.parent_author_signature}}
-        <parent_author_signature>{{$msg.parent_author_signature}}</parent_author_signature>
-        {{/if}}
-        <author_signature>{{$msg.author_signature}}</author_signature>
-        <text>{{$msg.text}}</text>
-        <created_at>{{$msg.created_at}}</created_at>
-        <diaspora_handle>{{$msg.diaspora_handle}}</diaspora_handle>
-        <conversation_guid>{{$msg.conversation_guid}}</conversation_guid>
-      </message>
-
-      {{/foreach}}
-
-      <diaspora_handle>{{$conv.diaspora_handle}}</diaspora_handle>
-      <participant_handles>{{$conv.participant_handles}}</participant_handles>
-    </conversation>
-  </post>
-</XML>
diff --git a/view/templates/diaspora_like.tpl b/view/templates/diaspora_like.tpl
deleted file mode 100644
index 165b0f5f7b..0000000000
--- a/view/templates/diaspora_like.tpl
+++ /dev/null
@@ -1,13 +0,0 @@
-
-<XML>
-  <post>
-    <like>
-      <positive>{{$positive}}</positive>
-      <guid>{{$guid}}</guid>
-      <target_type>{{$target_type}}</target_type>
-      <parent_guid>{{$parent_guid}}</parent_guid>
-      <author_signature>{{$authorsig}}</author_signature>
-      <diaspora_handle>{{$handle}}</diaspora_handle>
-    </like>
-  </post>
-</XML>
diff --git a/view/templates/diaspora_like_relay.tpl b/view/templates/diaspora_like_relay.tpl
deleted file mode 100644
index e1696e722a..0000000000
--- a/view/templates/diaspora_like_relay.tpl
+++ /dev/null
@@ -1,14 +0,0 @@
-
-<XML>
-  <post>
-    <like>
-      <positive>{{$positive}}</positive>
-      <guid>{{$guid}}</guid>
-      <target_type>{{$target_type}}</target_type>
-      <parent_guid>{{$parent_guid}}</parent_guid>
-      <parent_author_signature>{{$parentsig}}</parent_author_signature>
-      <author_signature>{{$authorsig}}</author_signature>
-      <diaspora_handle>{{$handle}}</diaspora_handle>
-    </like>
-  </post>
-</XML>
diff --git a/view/templates/diaspora_message.tpl b/view/templates/diaspora_message.tpl
deleted file mode 100644
index f9adb833b6..0000000000
--- a/view/templates/diaspora_message.tpl
+++ /dev/null
@@ -1,17 +0,0 @@
-
-<XML>
-  <post>
-      <message>
-        <guid>{{$msg.guid}}</guid>
-        <parent_guid>{{$msg.parent_guid}}</parent_guid>
-	{{if $msg.parent_author_signature}}
-        <parent_author_signature>{{$msg.parent_author_signature}}</parent_author_signature>
-        {{/if}}
-        <author_signature>{{$msg.author_signature}}</author_signature>
-        <text>{{$msg.text}}</text>
-        <created_at>{{$msg.created_at}}</created_at>
-        <diaspora_handle>{{$msg.diaspora_handle}}</diaspora_handle>
-        <conversation_guid>{{$msg.conversation_guid}}</conversation_guid>
-      </message>
-  </post>
-</XML>
diff --git a/view/templates/diaspora_photo.tpl b/view/templates/diaspora_photo.tpl
deleted file mode 100644
index 0330499577..0000000000
--- a/view/templates/diaspora_photo.tpl
+++ /dev/null
@@ -1,14 +0,0 @@
-
-<XML>
-  <post>
-    <photo>
-      <guid>{{$guid}}</guid>
-      <diaspora_handle>{{$handle}}</diaspora_handle>
-      <public>{{$public}}</public>
-      <created_at>{{$created_at}}</created_at>
-      <remote_photo_path>{{$path}}</remote_photo_path>
-      <remote_photo_name>{{$filename}}</remote_photo_name>
-      <status_message_guid>{{$msg_guid}}</status_message_guid>
-    </photo>
-  </post>
-</XML>
diff --git a/view/templates/diaspora_post.tpl b/view/templates/diaspora_post.tpl
deleted file mode 100644
index d6ba97327c..0000000000
--- a/view/templates/diaspora_post.tpl
+++ /dev/null
@@ -1,13 +0,0 @@
-
-<XML>
-  <post>
-    <status_message>
-      <raw_message>{{$body}}</raw_message>
-      <guid>{{$guid}}</guid>
-      <diaspora_handle>{{$handle}}</diaspora_handle>
-      <public>{{$public}}</public>
-      <created_at>{{$created}}</created_at>
-      <provider_display_name>{{$provider}}</provider_display_name>
-    </status_message>
-  </post>
-</XML>
diff --git a/view/templates/diaspora_profile.tpl b/view/templates/diaspora_profile.tpl
deleted file mode 100644
index afbbb1e1a2..0000000000
--- a/view/templates/diaspora_profile.tpl
+++ /dev/null
@@ -1,17 +0,0 @@
-
-<XML>
- <post><profile>
-  <diaspora_handle>{{$handle}}</diaspora_handle>
-  <first_name>{{$first}}</first_name>
-  <last_name>{{$last}}</last_name>
-  <image_url>{{$large}}</image_url>
-  <image_url_medium>{{$medium}}</image_url_medium>
-  <image_url_small>{{$small}}</image_url_small>
-  <birthday>{{$dob}}</birthday>
-  <gender>{{$gender}}</gender>
-  <bio>{{$about}}</bio>
-  <location>{{$location}}</location>
-  <searchable>{{$searchable}}</searchable>
-  <tag_string>{{$tags}}</tag_string>
- </profile></post>
-</XML>
diff --git a/view/templates/diaspora_relay_retraction.tpl b/view/templates/diaspora_relay_retraction.tpl
deleted file mode 100644
index c4b44cd05f..0000000000
--- a/view/templates/diaspora_relay_retraction.tpl
+++ /dev/null
@@ -1,10 +0,0 @@
-<XML>
-  <post>
-    <relayable_retraction>
-      <target_guid>{{$guid}}</target_guid>
-      <target_type>{{$type}}</target_type>
-      <sender_handle>{{$handle}}</sender_handle>
-      <target_author_signature>{{$signature}}</target_author_signature>
-    </relayable_retraction>
-  </post>
-</XML>
diff --git a/view/templates/diaspora_relayable_retraction.tpl b/view/templates/diaspora_relayable_retraction.tpl
deleted file mode 100644
index 2ae776d1d0..0000000000
--- a/view/templates/diaspora_relayable_retraction.tpl
+++ /dev/null
@@ -1,12 +0,0 @@
-
-<XML>
-  <post>
-    <relayable_retraction>
-      <parent_author_signature>{{$parentsig}}</parent_author_signature>
-      <target_guid>{{$guid}}</target_guid>
-      <target_type>{{$target_type}}</target_type>
-      <sender_handle>{{$handle}}</sender_handle>
-      <target_author_signature>{{$authorsig}}</target_author_signature>
-    </relayable_retraction>
-  </post>
-</XML>
diff --git a/view/templates/diaspora_reshare.tpl b/view/templates/diaspora_reshare.tpl
deleted file mode 100644
index 6a4776b1bc..0000000000
--- a/view/templates/diaspora_reshare.tpl
+++ /dev/null
@@ -1,14 +0,0 @@
-
-<XML>
-  <post>
-    <reshare>
-      <root_diaspora_id>{{$root_handle}}</root_diaspora_id>
-      <root_guid>{{$root_guid}}</root_guid>
-      <guid>{{$guid}}</guid>
-      <diaspora_handle>{{$handle}}</diaspora_handle>
-      <public>{{$public}}</public>
-      <created_at>{{$created}}</created_at>
-      <provider_display_name>{{$provider}}</provider_display_name>
-    </reshare>
-  </post>
-</XML>
diff --git a/view/templates/diaspora_retract.tpl b/view/templates/diaspora_retract.tpl
deleted file mode 100644
index 3ddfcabfa7..0000000000
--- a/view/templates/diaspora_retract.tpl
+++ /dev/null
@@ -1,10 +0,0 @@
-
-<XML>
-  <post>
-    <retraction>
-      <post_guid>{{$guid}}</post_guid>
-      <diaspora_handle>{{$handle}}</diaspora_handle>
-      <type>{{$type}}</type>
-    </retraction>
-  </post>
-</XML>
diff --git a/view/templates/diaspora_share.tpl b/view/templates/diaspora_share.tpl
deleted file mode 100644
index 0142ab36c5..0000000000
--- a/view/templates/diaspora_share.tpl
+++ /dev/null
@@ -1,9 +0,0 @@
-
-<XML>
-  <post>
-    <request>
-      <sender_handle>{{$sender}}</sender_handle>
-      <recipient_handle>{{$recipient}}</recipient_handle>
-    </request>
-  </post>
-</XML>
\ No newline at end of file
diff --git a/view/templates/diaspora_signed_retract.tpl b/view/templates/diaspora_signed_retract.tpl
deleted file mode 100644
index 83d0def4d2..0000000000
--- a/view/templates/diaspora_signed_retract.tpl
+++ /dev/null
@@ -1,11 +0,0 @@
-
-<XML>
-  <post>
-    <signed_retraction>
-      <target_guid>{{$guid}}</target_guid>
-      <target_type>{{$type}}</target_type>
-      <sender_handle>{{$handle}}</sender_handle>
-      <target_author_signature>{{$signature}}</target_author_signature>
-    </signed_retraction>
-  </post>
-</XML>

From 8027854886a7d8a51fb3b97864e01f877403fc4a Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 15 Mar 2016 07:18:11 +0100
Subject: [PATCH 203/273] Removed moved function

---
 include/diaspora.php |  1 -
 include/network.php  | 58 --------------------------------------------
 2 files changed, 59 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 3c3f5cb25a..d5f2a21d9e 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -517,7 +517,6 @@ class diaspora {
 	 * @return string The id of the fcontact entry
 	 */
 	private function add_fcontact($arr, $update = false) {
-		/// @todo Remove this function from include/network.php
 
 		if($update) {
 			$r = q("UPDATE `fcontact` SET
diff --git a/include/network.php b/include/network.php
index c6379e407b..27459112d6 100644
--- a/include/network.php
+++ b/include/network.php
@@ -862,64 +862,6 @@ function parse_xml_string($s,$strict = true) {
 	return $x;
 }}
 
-function add_fcontact($arr,$update = false) {
-
-	if($update) {
-		$r = q("UPDATE `fcontact` SET
-			`name` = '%s',
-			`photo` = '%s',
-			`request` = '%s',
-			`nick` = '%s',
-			`addr` = '%s',
-			`batch` = '%s',
-			`notify` = '%s',
-			`poll` = '%s',
-			`confirm` = '%s',
-			`alias` = '%s',
-			`pubkey` = '%s',
-			`updated` = '%s'
-			WHERE `url` = '%s' AND `network` = '%s'",
-			dbesc($arr['name']),
-			dbesc($arr['photo']),
-			dbesc($arr['request']),
-			dbesc($arr['nick']),
-			dbesc($arr['addr']),
-			dbesc($arr['batch']),
-			dbesc($arr['notify']),
-			dbesc($arr['poll']),
-			dbesc($arr['confirm']),
-			dbesc($arr['alias']),
-			dbesc($arr['pubkey']),
-			dbesc(datetime_convert()),
-			dbesc($arr['url']),
-			dbesc($arr['network'])
-		);
-	}
-	else {
-		$r = q("insert into fcontact ( `url`,`name`,`photo`,`request`,`nick`,`addr`,
-			`batch`, `notify`,`poll`,`confirm`,`network`,`alias`,`pubkey`,`updated` )
-			values('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')",
-			dbesc($arr['url']),
-			dbesc($arr['name']),
-			dbesc($arr['photo']),
-			dbesc($arr['request']),
-			dbesc($arr['nick']),
-			dbesc($arr['addr']),
-			dbesc($arr['batch']),
-			dbesc($arr['notify']),
-			dbesc($arr['poll']),
-			dbesc($arr['confirm']),
-			dbesc($arr['network']),
-			dbesc($arr['alias']),
-			dbesc($arr['pubkey']),
-			dbesc(datetime_convert())
-		);
-	}
-
-	return $r;
-}
-
-
 function scale_external_images($srctext, $include_link = true, $scale_replace = false) {
 
 	// Suppress "view full size"

From be001d171b385af3650cb8152542f3a60c645f63 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 15 Mar 2016 20:14:08 +0100
Subject: [PATCH 204/273] Values are sanitized, messages are not relayed when
 there is no signature

---
 include/diaspora.php | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index d5f2a21d9e..f4e3132959 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -221,7 +221,9 @@ class diaspora {
 
 		logger('Message verified.');
 
-		return array('message' => $inner_decrypted, 'author' => $author_link, 'key' => $key);
+		return array('message' => (string)$inner_decrypted,
+				'author' => unxmlify($author_link),
+				'key' => (string)$key);
 
 	}
 
@@ -1801,7 +1803,8 @@ class diaspora {
 
 		if ($data->photo) {
 			foreach ($data->photo AS $photo)
-				$body = "[img]".$photo->remote_photo_path.$photo->remote_photo_name."[/img]\n".$body;
+				$body = "[img]".unxmlify($photo->remote_photo_path).
+					unxmlify($photo->remote_photo_name)."[/img]\n".$body;
 
 			$datarray["object-type"] = ACTIVITY_OBJ_PHOTO;
 		} else {
@@ -2355,8 +2358,10 @@ class diaspora {
 		$r = q("SELECT `signed_text`, `signature`, `signer` FROM `sign` WHERE `".$sql_sign_id."` = %d LIMIT 1",
 			intval($item["id"]));
 
-		if (!$r)
-			return self::send_followup($item, $owner, $contact, $public_batch);
+		if (!$r) {
+			logger("Couldn't fetch signatur for contact ".$contact["addr"]." at item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG);
+			return false;
+		}
 
 		$signature = $r[0];
 

From 071ffd43bf66ff6478c09a4afc6ef010e34d8384 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 16 Mar 2016 11:44:45 +0100
Subject: [PATCH 205/273] DFRN: Mentions were imported as hash tags

---
 include/dfrn.php | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index ad04a91295..1c5ac2b012 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -2022,14 +2022,28 @@ class dfrn {
 		$categories = $xpath->query("atom:category", $entry);
 		if ($categories) {
 			foreach ($categories AS $category) {
-				foreach($category->attributes AS $attributes)
-					if ($attributes->name == "term") {
+				$term = "";
+				$scheme = "";
+				foreach($category->attributes AS $attributes) {
+					if ($attributes->name == "term")
 						$term = $attributes->textContent;
+
+					if ($attributes->name == "scheme")
+						$scheme = $attributes->textContent;
+				}
+
+				if (($term != "") AND ($scheme != "")) {
+					$parts = explode(":", $scheme);
+					if ((count($parts) >= 4) AND (array_shift($parts) == "X-DFRN")) {
+						$termhash = array_shift($parts);
+						$termurl = implode(":", $parts);
+
 						if(strlen($item["tag"]))
 							$item["tag"] .= ",";
 
-						$item["tag"] .= "#[url=".App::get_baseurl()."/search?tag=".$term."]".$term."[/url]";
+						$item["tag"] .= $termhash."[url=".$termurl."]".$term."[/url]";
 					}
+				}
 			}
 		}
 

From 84a475e5897d5753c45b6cbb0a982893ee2cda1e Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 16 Mar 2016 16:49:54 +0100
Subject: [PATCH 206/273] Missing include

---
 include/diaspora.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/diaspora.php b/include/diaspora.php
index f4e3132959..da69cdc799 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -13,6 +13,7 @@ require_once("include/socgraph.php");
 require_once("include/group.php");
 require_once("include/xml.php");
 require_once("include/datetime.php");
+require_once("include/queue_fn.php");
 
 /**
  * @brief This class contain functions to create and send Diaspora XML files

From 468734a26ee6f7aeadcaaa5a2ba10c3b613c8dcc Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 16 Mar 2016 19:30:46 +0100
Subject: [PATCH 207/273] Added checklist

---
 include/diaspora.php | 51 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 42 insertions(+), 9 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index da69cdc799..f7c38c2271 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -2,6 +2,36 @@
 /**
  * @file include/diaspora.php
  * @brief The implementation of the diaspora protocol
+ *
+ * Checklist:
+ *
+ * Checked:
+ * - send status
+ * - send comment
+ * - send like
+ * - send mail
+ * - receive status
+ * - receive reshare
+ * - receive comment
+ * - receive like
+ * - receive connect request
+ * - receive profile data
+ * - receive mail
+ * - relay comment
+ * - relay like
+ * -
+ * -
+ *
+ * Unchecked:
+ * - receive account deletion
+ * - send share
+ * - send unshare
+ * - send status retraction
+ * - send comment retraction
+ * - send like retraction
+ * - relay comment retraction
+ * - relay like retraction
+ * -
  */
 
 require_once("include/items.php");
@@ -2374,16 +2404,19 @@ class diaspora {
 			$msg = json_decode($signature['signed_text'], true);
 
 			$message = array();
-			foreach ($msg AS $field => $data) {
-				if (!$item["deleted"]) {
-					if ($field == "author")
-						$field = "diaspora_handle";
-					if ($field == "parent_type")
-						$field = "target_type";
-				}
+			if (is_array($msg)) {
+				foreach ($msg AS $field => $data) {
+					if (!$item["deleted"]) {
+						if ($field == "author")
+							$field = "diaspora_handle";
+						if ($field == "parent_type")
+							$field = "target_type";
+					}
 
-				$message[$field] = $data;
-			}
+					$message[$field] = $data;
+				}
+			} else
+				logger("Signature text for item ".$item["guid"]." (".$item["id"].") couldn't be extracted: ".$signature['signed_text'], LOGGER_DEBUG);
 		}
 
 		if ($item["deleted"]) {

From e058feed289269e9edccd3047318d8b06dce7739 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 16 Mar 2016 21:27:07 +0100
Subject: [PATCH 208/273] Better reshare detection

---
 include/diaspora.php | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index f7c38c2271..4a6cbad131 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -1600,7 +1600,7 @@ class diaspora {
 
 			// Maybe it is already a reshared item?
 			// Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
-			if (self::is_reshare($r[0]["body"]))
+			if (self::is_reshare($r[0]["body"], false))
 				$r = array();
 			else
 				return $r[0];
@@ -2130,7 +2130,7 @@ class diaspora {
 		return self::build_and_transmit($owner, $contact, "retraction", $message);
 	}
 
-	public static function is_reshare($body) {
+	public static function is_reshare($body, $complete = true) {
 		$body = trim($body);
 
 		// Skip if it isn't a pure repeated messages
@@ -2147,6 +2147,10 @@ class diaspora {
 		if ($body == $attributes)
 			return(false);
 
+		// If we don't do the complete check we quit here
+		if (!$complete)
+			return true;
+
 		$guid = "";
 		preg_match("/guid='(.*?)'/ism", $attributes, $matches);
 		if ($matches[1] != "")

From 88fea17cab1fa3e1e8fb7bb0e2c3ea3480dbb8ee Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 17 Mar 2016 00:37:44 +0100
Subject: [PATCH 209/273] Everything tested, one open to-do

---
 include/delivery.php |  3 ++-
 include/diaspora.php | 40 +++++++++++++++++++++++++++++-----------
 2 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/include/delivery.php b/include/delivery.php
index 9ac9f2391b..fe33774382 100644
--- a/include/delivery.php
+++ b/include/delivery.php
@@ -243,7 +243,8 @@ function delivery_run(&$argv, &$argc){
 			if ((strlen($parent['allow_cid']))
 				|| (strlen($parent['allow_gid']))
 				|| (strlen($parent['deny_cid']))
-				|| (strlen($parent['deny_gid']))) {
+				|| (strlen($parent['deny_gid']))
+				|| $parent["private"]) {
 				$public_message = false; // private recipients, not public
 			}
 
diff --git a/include/diaspora.php b/include/diaspora.php
index 4a6cbad131..870466497d 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -10,6 +10,11 @@
  * - send comment
  * - send like
  * - send mail
+ * - send status retraction
+ * - send comment retraction on own post
+ * - send comment retraction on diaspora post
+ * - send like retraction on own post
+ * - send like retraction on diaspora post
  * - receive status
  * - receive reshare
  * - receive comment
@@ -17,21 +22,21 @@
  * - receive connect request
  * - receive profile data
  * - receive mail
+ * - receive comment retraction
+ * - receive like retraction
  * - relay comment
  * - relay like
- * -
- * -
+ * - relay comment retraction from diaspora
+ * - relay comment retraction from friendica
+ * - relay like retraction from diaspora
+ * - relay like retraction from friendica
  *
- * Unchecked:
+ * Should work:
  * - receive account deletion
  * - send share
  * - send unshare
- * - send status retraction
- * - send comment retraction
- * - send like retraction
- * - relay comment retraction
- * - relay like retraction
- * -
+ *
+ * Unchecked:
  */
 
 require_once("include/items.php");
@@ -2394,7 +2399,10 @@ class diaspora {
 			intval($item["id"]));
 
 		if (!$r) {
-			logger("Couldn't fetch signatur for contact ".$contact["addr"]." at item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG);
+			if ($item["deleted"])
+				return self::send_retraction($item, $owner, $contact, $public_batch);
+
+			logger("Couldn't fetch signatur for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG);
 			return false;
 		}
 
@@ -2436,6 +2444,9 @@ class diaspora {
 
 	public static function send_retraction($item, $owner, $contact, $public_batch = false) {
 
+		/// @todo Fetch handle from every contact (via gcontact)
+		$itemaddr = self::handle_from_contact($item["contact-id"]);
+
 		$myaddr = self::my_handle($owner);
 
 		// Check whether the retraction is for a top-level post or whether it's a relayable
@@ -2451,9 +2462,16 @@ class diaspora {
 
 		$message = array("target_guid" => $item['guid'],
 				"target_type" => $target_type,
-				"sender_handle" => $myaddr,
+				"sender_handle" => $itemaddr,
 				"target_author_signature" => base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')));
 
+		if ($itemaddr != $myaddr) {
+			$message["parent_author_signature"] = $message["target_author_signature"];
+			unset($message["target_author_signature"]);
+		}
+
+		logger("Got message ".print_r($message, true), LOGGER_DEBUG);
+
 		return self::build_and_transmit($owner, $contact, $msg_type, $message, $public_batch, $item["guid"]);
 	}
 

From 16b92af71f0d838f7859869461f1acea25329d95 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 17 Mar 2016 12:24:23 +0100
Subject: [PATCH 210/273] Retraction do work as well

---
 database.sql            |  4 +--
 doc/database/db_sign.md |  1 -
 include/dbstructure.php |  2 --
 include/diaspora.php    | 73 ++++++++++++++++-------------------------
 include/items.php       | 51 ----------------------------
 include/like.php        | 69 --------------------------------------
 include/notifier.php    |  7 ----
 7 files changed, 29 insertions(+), 178 deletions(-)

diff --git a/database.sql b/database.sql
index 02e5c9b378..89b821e23a 100644
--- a/database.sql
+++ b/database.sql
@@ -901,13 +901,11 @@ CREATE TABLE IF NOT EXISTS `session` (
 CREATE TABLE IF NOT EXISTS `sign` (
 	`id` int(10) unsigned NOT NULL auto_increment,
 	`iid` int(10) unsigned NOT NULL DEFAULT 0,
-	`retract_iid` int(10) unsigned NOT NULL DEFAULT 0,
 	`signed_text` mediumtext NOT NULL,
 	`signature` text NOT NULL,
 	`signer` varchar(255) NOT NULL DEFAULT '',
 	 PRIMARY KEY(`id`),
-	 INDEX `iid` (`iid`),
-	 INDEX `retract_iid` (`retract_iid`)
+	 INDEX `iid` (`iid`)
 ) DEFAULT CHARSET=utf8;
 
 --
diff --git a/doc/database/db_sign.md b/doc/database/db_sign.md
index 8de59ac675..6986613e59 100644
--- a/doc/database/db_sign.md
+++ b/doc/database/db_sign.md
@@ -5,7 +5,6 @@ Table sign
 | ------------ | ------------- | ---------------- | ---- | --- | ------- | --------------- |
 | id           | sequential ID | int(10) unsigned | NO   | PRI | NULL    | auto_increment  |
 | iid          | item.id       | int(10) unsigned | NO   | MUL | 0       |                 |
-| retract_iid  |               | int(10) unsigned | NO   | MUL | 0       |                 |
 | signed_text  |               | mediumtext       | NO   |     | NULL    |                 |
 | signature    |               | text             | NO   |     | NULL    |                 |
 | signer       |               | varchar(255)     | NO   |     |         |                 |
diff --git a/include/dbstructure.php b/include/dbstructure.php
index e5e748bb24..e34e409023 100644
--- a/include/dbstructure.php
+++ b/include/dbstructure.php
@@ -1235,7 +1235,6 @@ function db_definition() {
 			"fields" => array(
 					"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
 					"iid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
-					"retract_iid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
 					"signed_text" => array("type" => "mediumtext", "not null" => "1"),
 					"signature" => array("type" => "text", "not null" => "1"),
 					"signer" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@@ -1243,7 +1242,6 @@ function db_definition() {
 			"indexes" => array(
 					"PRIMARY" => array("id"),
 					"iid" => array("iid"),
-					"retract_iid" => array("retract_iid"),
 					)
 			);
 	$database["spam"] = array(
diff --git a/include/diaspora.php b/include/diaspora.php
index 870466497d..c888959d71 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -12,8 +12,8 @@
  * - send mail
  * - send status retraction
  * - send comment retraction on own post
- * - send comment retraction on diaspora post
  * - send like retraction on own post
+ * - send comment retraction on diaspora post
  * - send like retraction on diaspora post
  * - receive status
  * - receive reshare
@@ -30,10 +30,10 @@
  * - relay comment retraction from friendica
  * - relay like retraction from diaspora
  * - relay like retraction from friendica
+ * - send share
  *
  * Should work:
  * - receive account deletion
- * - send share
  * - send unshare
  *
  * Unchecked:
@@ -610,15 +610,21 @@ class diaspora {
 		return $r;
 	}
 
-	public static function handle_from_contact($contact_id) {
+	public static function handle_from_contact($contact_id, $gcontact_id = 0) {
 		$handle = False;
 
-		logger("contact id is ".$contact_id, LOGGER_DEBUG);
+		logger("contact id is ".$contact_id." - gcontact id is ".$gcontact_id, LOGGER_DEBUG);
+
+		if ($gcontact_id != 0) {
+			$r = q("SELECT `addr` FROM `gcontact` WHERE `id` = %d AND `addr` != ''",
+				intval($gcontact_id));
+			if ($r)
+				return $r[0]["addr"];
+		}
 
 		$r = q("SELECT `network`, `addr`, `self`, `url`, `nick` FROM `contact` WHERE `id` = %d",
-		       intval($contact_id)
-		);
-		if($r) {
+			intval($contact_id));
+		if ($r) {
 			$contact = $r[0];
 
 			logger("contact 'self' = ".$contact['self']." 'url' = ".$contact['url'], LOGGER_DEBUG);
@@ -1759,16 +1765,6 @@ class diaspora {
 
 		// Now check if the retraction needs to be relayed by us
 		if($p[0]["origin"]) {
-
-			// 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` (`retract_iid`,`signed_text`) VALUES (%d,'%s')",
-				intval($r[0]["id"]),
-				dbesc(json_encode($data))
-			);
-			$s = q("select * from sign where retract_iid = %d", intval($r[0]["id"]));
-			logger("Stored signatur for item ".$r[0]["id"]." - ".print_r($s, true), LOGGER_DEBUG);
-
 			// notify others
 			proc_run("php", "include/notifier.php", "drop", $r[0]["id"]);
 		}
@@ -2380,28 +2376,21 @@ class diaspora {
 
 	public static function send_relay($item, $owner, $contact, $public_batch = false) {
 
-		if ($item["deleted"]) {
-			$sql_sign_id = "retract_iid";
-			$type = "relayable_retraction";
-		} elseif ($item['verb'] === ACTIVITY_LIKE) {
-			$sql_sign_id = "iid";
+		if ($item["deleted"])
+			return self::send_retraction($item, $owner, $contact, $public_batch, true);
+		elseif ($item['verb'] === ACTIVITY_LIKE)
 			$type = "like";
-		} else {
-			$sql_sign_id = "iid";
+		else
 			$type = "comment";
-		}
 
 		logger("Got relayable data ".$type." for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG);
 
 		// fetch the original signature
 
-		$r = q("SELECT `signed_text`, `signature`, `signer` FROM `sign` WHERE `".$sql_sign_id."` = %d LIMIT 1",
+		$r = q("SELECT `signed_text`, `signature`, `signer` FROM `sign` WHERE `iid` = %d LIMIT 1",
 			intval($item["id"]));
 
 		if (!$r) {
-			if ($item["deleted"])
-				return self::send_retraction($item, $owner, $contact, $public_batch);
-
 			logger("Couldn't fetch signatur for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG);
 			return false;
 		}
@@ -2431,23 +2420,17 @@ class diaspora {
 				logger("Signature text for item ".$item["guid"]." (".$item["id"].") couldn't be extracted: ".$signature['signed_text'], LOGGER_DEBUG);
 		}
 
-		if ($item["deleted"]) {
-			$signed_text = $message["target_guid"].';'.$message["target_type"];
-			$message["parent_author_signature"] = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
-		} else
-			$message["parent_author_signature"] = self::signature($owner, $message);
+		$message["parent_author_signature"] = self::signature($owner, $message);
 
 		logger("Relayed data ".print_r($message, true), LOGGER_DEBUG);
 
 		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
 	}
 
-	public static function send_retraction($item, $owner, $contact, $public_batch = false) {
+	public static function send_retraction($item, $owner, $contact, $public_batch = false, $relay = false) {
 
-		/// @todo Fetch handle from every contact (via gcontact)
-		$itemaddr = self::handle_from_contact($item["contact-id"]);
-
-		$myaddr = self::my_handle($owner);
+		$itemaddr = self::handle_from_contact($item["contact-id"], $item["gcontact-id"]);
+		//$myaddr = self::my_handle($owner);
 
 		// Check whether the retraction is for a top-level post or whether it's a relayable
 		if ($item["uri"] !== $item["parent-uri"]) {
@@ -2458,17 +2441,17 @@ class diaspora {
 			$target_type = "StatusMessage";
 		}
 
+		if ($relay AND ($item["uri"] !== $item["parent-uri"]))
+			$signature = "parent_author_signature";
+		else
+			$signature = "target_author_signature";
+
 		$signed_text = $item["guid"].";".$target_type;
 
 		$message = array("target_guid" => $item['guid'],
 				"target_type" => $target_type,
 				"sender_handle" => $itemaddr,
-				"target_author_signature" => base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')));
-
-		if ($itemaddr != $myaddr) {
-			$message["parent_author_signature"] = $message["target_author_signature"];
-			unset($message["target_author_signature"]);
-		}
+				$signature => base64_encode(rsa_sign($signed_text,$owner['uprvkey'],'sha256')));
 
 		logger("Got message ".print_r($message, true), LOGGER_DEBUG);
 
diff --git a/include/items.php b/include/items.php
index 8d6b5b471c..f8c3149d58 100644
--- a/include/items.php
+++ b/include/items.php
@@ -1980,9 +1980,6 @@ function drop_item($id,$interactive = true) {
 					intval($r[0]['id'])
 				);
 			}
-
-			// Add a relayable_retraction signature for Diaspora.
-			store_diaspora_retract_sig($item, $a->user, $a->get_baseurl());
 		}
 
 		$drop_id = intval($item['id']);
@@ -2115,51 +2112,3 @@ function posted_date_widget($url,$uid,$wall) {
 	));
 	return $o;
 }
-
-function store_diaspora_retract_sig($item, $user, $baseurl) {
-	// Note that we can't add a target_author_signature
-	// if the comment was deleted by a remote user. That should be ok, because if a remote user is deleting
-	// the comment, that means we're the home of the post, and Diaspora will only
-	// check the parent_author_signature of retractions that it doesn't have to relay further
-	//
-	// I don't think this function gets called for an "unlike," but I'll check anyway
-
-	$enabled = intval(get_config('system','diaspora_enabled'));
-	if(! $enabled) {
-		logger('drop_item: diaspora support disabled, not storing retraction signature', LOGGER_DEBUG);
-		return;
-	}
-
-	logger('drop_item: storing diaspora retraction signature');
-
-	$signed_text = $item['guid'] . ';' . ( ($item['verb'] === ACTIVITY_LIKE) ? 'Like' : 'Comment');
-
-	if(local_user() == $item['uid']) {
-
-		$handle = $user['nickname'] . '@' . substr($baseurl, strpos($baseurl,'://') + 3);
-		$authorsig = base64_encode(rsa_sign($signed_text,$user['prvkey'],'sha256'));
-	}
-	else {
-		$r = q("SELECT `nick`, `url` FROM `contact` WHERE `id` = '%d' LIMIT 1",
-			$item['contact-id'] // If this function gets called, drop_item() has already checked remote_user() == $item['contact-id']
-		);
-		if(count($r)) {
-			// The below handle only works for NETWORK_DFRN. I think that's ok, because this function
-			// only handles DFRN deletes
-			$handle_baseurl_start = strpos($r['url'],'://') + 3;
-			$handle_baseurl_length = strpos($r['url'],'/profile') - $handle_baseurl_start;
-			$handle = $r['nick'] . '@' . substr($r['url'], $handle_baseurl_start, $handle_baseurl_length);
-			$authorsig = '';
-		}
-	}
-
-	if(isset($handle))
-		q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
-			intval($item['id']),
-			dbesc($signed_text),
-			dbesc($authorsig),
-			dbesc($handle)
-		);
-
-	return;
-}
diff --git a/include/like.php b/include/like.php
index 646e0727be..2e5367e51e 100644
--- a/include/like.php
+++ b/include/like.php
@@ -151,9 +151,6 @@ function do_like($item_id, $verb) {
 			intval($like_item['id'])
 		);
 
-		// Save the author information for the unlike in case we need to relay to Diaspora
-		store_diaspora_like_retract_sig($activity, $item, $like_item, $contact);
-
 		$like_item_id = $like_item['id'];
 		proc_run('php',"include/notifier.php","like","$like_item_id");
 
@@ -251,72 +248,6 @@ EOT;
 	return true;
 }
 
-
-
-function store_diaspora_like_retract_sig($activity, $item, $like_item, $contact) {
-	// Note that we can only create a signature for a user of the local server. We don't have
-	// a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it
-	// means we are the relay, and for relayable_retractions, Diaspora
-	// only checks the parent_author_signature if it doesn't have to relay further
-	//
-	// If $item['resource-id'] exists, it means the item is a photo. Diaspora doesn't support
-	// likes on photos, so don't bother.
-
-	$enabled = intval(get_config('system','diaspora_enabled'));
-	if(! $enabled) {
-		logger('mod_like: diaspora support disabled, not storing like retraction signature', LOGGER_DEBUG);
-		return;
-	}
-
-	logger('mod_like: storing diaspora like retraction signature');
-
-	if(($activity === ACTIVITY_LIKE) && (! $item['resource-id'])) {
-		$signed_text = $like_item['guid'] . ';' . 'Like';
-
-		// Only works for NETWORK_DFRN
-		$contact_baseurl_start = strpos($contact['url'],'://') + 3;
-		$contact_baseurl_length = strpos($contact['url'],'/profile') - $contact_baseurl_start;
-		$contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length);
-		$diaspora_handle = $contact['nick'] . '@' . $contact_baseurl;
-
-		// This code could never had worked (the return values form the queries were used in a wrong way.
-		// Additionally it is needlessly complicated. Either the contact is owner or not. And we have this data already.
-/*
-		// Get contact's private key if he's a user of the local Friendica server
-		$r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1",
-			dbesc($contact['url'])
-		);
-
-		if( $r) {
-			$contact_uid = $r['uid'];
-			$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
-				intval($contact_uid)
-			);
-*/
-		// Is the contact the owner? Then fetch the private key
-		if ($contact['self'] AND ($contact['uid'] > 0)) {
-			$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
-				intval($contact['uid'])
-			);
-
-			if($r)
-				$authorsig = base64_encode(rsa_sign($signed_text,$r[0]['prvkey'],'sha256'));
-		}
-
-		if(! isset($authorsig))
-			$authorsig = '';
-
-		q("insert into sign (`retract_iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
-			intval($like_item['id']),
-			dbesc($signed_text),
-			dbesc($authorsig),
-			dbesc($diaspora_handle)
-		);
-	}
-
-	return;
-}
-
 function store_diaspora_like_sig($activity, $post_type, $contact, $post_id) {
 	// Note that we can only create a signature for a user of the local server. We don't have
 	// a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it
diff --git a/include/notifier.php b/include/notifier.php
index e65da3adf2..a46744f070 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -628,13 +628,6 @@ function notifier_run(&$argv, &$argc){
 		proc_run('php','include/pubsubpublish.php');
 	}
 
-	// If the item was deleted, clean up the `sign` table
-	/* if($target_item['deleted']) {
-		$r = q("DELETE FROM sign where `retract_iid` = %d",
-			intval($target_item['id'])
-		);
-	} */
-
 	logger('notifier: calling hooks', LOGGER_DEBUG);
 
 	if($normal_mode)

From bc579ff799595d7c4271e3562b554d5cecaf5b5b Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Thu, 17 Mar 2016 17:41:06 +0100
Subject: [PATCH 211/273] added title element to emoji images in main
 repository

---
 include/text.php | 70 ++++++++++++++++++++++++------------------------
 1 file changed, 35 insertions(+), 35 deletions(-)

diff --git a/include/text.php b/include/text.php
index 07524e851d..c868499cc6 100644
--- a/include/text.php
+++ b/include/text.php
@@ -1148,41 +1148,41 @@ function smilies($s, $sample = false) {
 	);
 
 	$icons = array(
-		'<img class="smiley" src="' . z_root() . '/images/smiley-heart.gif" alt="&lt;3" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-brokenheart.gif" alt="&lt;/3" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-brokenheart.gif" alt="&lt;\\3" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-smile.gif" alt=":-)" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-wink.gif" alt=";-)" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-frown.gif" alt=":-(" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-tongue-out.gif" alt=":-P" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-tongue-out.gif" alt=":-p" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-\"" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-\"" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-x" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-X" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-laughing.gif" alt=":-D" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt="8-|" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt="8-O" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt=":-O" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-thumbsup.gif" alt="\\o/" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="o.O" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="O.o" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="o_O" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="O_o" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-cry.gif" alt=":\'(" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-foot-in-mouth.gif" alt=":-!" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-undecided.gif" alt=":-/" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-embarassed.gif" alt=":-[" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-cool.gif" alt="8-)" />',
-		'<img class="smiley" src="' . z_root() . '/images/beer_mug.gif" alt=":beer" />',
-		'<img class="smiley" src="' . z_root() . '/images/beer_mug.gif" alt=":homebrew" />',
-		'<img class="smiley" src="' . z_root() . '/images/coffee.gif" alt=":coffee" />',
-		'<img class="smiley" src="' . z_root() . '/images/smiley-facepalm.gif" alt=":facepalm" />',
-		'<img class="smiley" src="' . z_root() . '/images/like.gif" alt=":like" />',
-		'<img class="smiley" src="' . z_root() . '/images/dislike.gif" alt=":dislike" />',
-		'<a href="http://friendica.com">~friendica <img class="smiley" src="' . z_root() . '/images/friendica-16.png" alt="~friendica" /></a>',
-		'<a href="http://redmatrix.me/">red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="red" />matrix</a>',
-		'<a href="http://redmatrix.me/">red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="red" />matrix</a>'
+		'<img class="smiley" src="' . z_root() . '/images/smiley-heart.gif" alt="&lt;3" title="&lt;3" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-brokenheart.gif" alt="&lt;/3" title="&lt;/3" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-brokenheart.gif" alt="&lt;\\3" title="&lt;\\3" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-smile.gif" alt=":-)" title=":-)" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-wink.gif" alt=";-)" title=";-)" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-frown.gif" alt=":-(" title=":-(" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-tongue-out.gif" alt=":-P" title=":-P" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-tongue-out.gif" alt=":-p" title=":-P" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-\" title=":-\" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-x" title=":-x" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-kiss.gif" alt=":-X" title=":-X" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-laughing.gif" alt=":-D" title=":-D"  />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt="8-|" title="8-|" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt="8-O" title="8-O" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-surprised.gif" alt=":-O" title="8-O" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-thumbsup.gif" alt="\\o/" title="\\o/" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="o.O" title="o.O" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="O.o" title="O.o" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="o_O" title="o_O" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-Oo.gif" alt="O_o" title="O_o" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-cry.gif" alt=":\'(" title=":\'("/>',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-foot-in-mouth.gif" alt=":-!" title=":-!" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-undecided.gif" alt=":-/" title=":-/" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-embarassed.gif" alt=":-[" title=":-[" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-cool.gif" alt="8-)" title="8-)" />',
+		'<img class="smiley" src="' . z_root() . '/images/beer_mug.gif" alt=":beer" title=":beer" />',
+		'<img class="smiley" src="' . z_root() . '/images/beer_mug.gif" alt=":homebrew" title=":homebrew" />',
+		'<img class="smiley" src="' . z_root() . '/images/coffee.gif" alt=":coffee" title=":coffee" />',
+		'<img class="smiley" src="' . z_root() . '/images/smiley-facepalm.gif" alt=":facepalm" title=":facepalm" />',
+		'<img class="smiley" src="' . z_root() . '/images/like.gif" alt=":like" title=":like" />',
+		'<img class="smiley" src="' . z_root() . '/images/dislike.gif" alt=":dislike" title=":dislike" />',
+		'<a href="http://friendica.com">~friendica <img class="smiley" src="' . z_root() . '/images/friendica-16.png" alt="~friendica" title="~friendica" /></a>',
+		'<a href="http://redmatrix.me/">red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="red#" title="red#" />matrix</a>',
+		'<a href="http://redmatrix.me/">red<img class="smiley" src="' . z_root() . '/images/rm-16.png" alt="red#matrix" title="red#matrix" />matrix</a>'
 	);
 
 	$params = array('texts' => $texts, 'icons' => $icons, 'string' => $s);

From fab48926d07907568aea5fb9766dad8a132a97c7 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 17 Mar 2016 23:44:18 +0100
Subject: [PATCH 212/273] Added some documentation, script to generate a basic
 doxygen header

---
 include/diaspora.php   | 479 ++++++++++++++++++++++++++++++++++++++++-
 util/createdoxygen.php |  82 +++++++
 2 files changed, 552 insertions(+), 9 deletions(-)
 create mode 100755 util/createdoxygen.php

diff --git a/include/diaspora.php b/include/diaspora.php
index c888959d71..dd0efa1d73 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -56,6 +56,13 @@ require_once("include/queue_fn.php");
  */
 class diaspora {
 
+	/**
+	 * @brief Return a list of relay servers
+	 *
+	 * This is an experimental Diaspora feature.
+	 *
+	 * @return array of relay servers
+	 */
 	public static function relay_list() {
 
 		$serverdata = get_config("system", "relay_server");
@@ -100,6 +107,15 @@ class diaspora {
 		return $relay;
 	}
 
+	/**
+	 * @brief repairs a signature that was double encoded
+	 *
+	 * @param string $signature The signature
+	 * @param string $handle The handle of the signature owner
+	 * @param integer $level This value is only set inside this function to avoid endless loops
+	 *
+	 * @return the repaired signature
+	 */
 	function repair_signature($signature, $handle = "", $level = 1) {
 
 		if ($signature == "")
@@ -120,7 +136,7 @@ class diaspora {
 	/**
 	 * @brief: Decodes incoming Diaspora message
 	 *
-	 * @param array $importer from user table
+	 * @param array $importer Array of the importer user
 	 * @param string $xml urldecoded Diaspora salmon
 	 *
 	 * @return array
@@ -610,6 +626,14 @@ class diaspora {
 		return $r;
 	}
 
+	/**
+	 * @brief get a handle (user@domain.tld) from a given contact id or gcontact id
+	 *
+	 * @param int $contact_id The id in the contact table
+	 * @param int $gcontact_id The id in the gcontact table
+	 *
+	 * @return string the handle
+	 */
 	public static function handle_from_contact($contact_id, $gcontact_id = 0) {
 		$handle = False;
 
@@ -642,6 +666,14 @@ class diaspora {
 		return $handle;
 	}
 
+	/**
+	 * @brief Get a contact id for a given handle
+	 *
+	 * @param int $uid The user id
+	 * @param string $handle The handle in the format user@domain.tld
+	 *
+	 * @return The contact id
+	 */
 	private function contact_by_handle($uid, $handle) {
 		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `addr` = '%s' LIMIT 1",
 			intval($uid),
@@ -664,6 +696,15 @@ class diaspora {
 		return false;
 	}
 
+	/**
+	 * @brief Check if posting is allowed for this contact
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param array $contact The contact that is checked
+	 * @param bool $is_comment Is the check for a comment?
+	 *
+	 * @return bool is the contact allowed to post?
+	 */
 	private function post_allow($importer, $contact, $is_comment = false) {
 
 		// perhaps we were already sharing with this person. Now they're sharing with us.
@@ -694,6 +735,15 @@ class diaspora {
 		return false;
 	}
 
+	/**
+	 * @brief Fetches the contact id for a handle and checks if posting is allowed
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param string $handle The checked handle in the format user@domain.tld
+	 * @param bool $is_comment Is the check for a comment?
+	 *
+	 * @return bool is posting allowed?
+	 */
 	private function allowed_contact_by_handle($importer, $handle, $is_comment = false) {
 		$contact = self::contact_by_handle($importer["uid"], $handle);
 		if (!$contact) {
@@ -708,6 +758,14 @@ class diaspora {
 		return $contact;
 	}
 
+	/**
+	 * @brief Does the message already exists on the system?
+	 *
+	 * @param int $uid The user id
+	 * @param string $guid The guid of the message
+	 *
+	 * @return bool "true" if the message already was stored into the system
+	 */
 	private function message_exists($uid, $guid) {
 		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
 			intval($uid),
@@ -722,6 +780,11 @@ class diaspora {
 		return false;
 	}
 
+	/**
+	 * @brief Checks for links to posts in a message
+	 *
+	 * @param array $item The item array
+	 */
 	private function fetch_guid($item) {
 		preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi",
 			function ($match) use ($item){
@@ -729,11 +792,26 @@ class diaspora {
 			},$item["body"]);
 	}
 
+	/**
+	 * @brief sub function of "fetch_guid"
+	 *
+	 * @param array $match array containing a link that has to be checked for a message link
+	 * @param array $item The item array
+	 */
 	private function fetch_guid_sub($match, $item) {
 		if (!self::store_by_guid($match[1], $item["author-link"]))
 			self::store_by_guid($match[1], $item["owner-link"]);
 	}
 
+	/**
+	 * @brief Fetches an item with a given guid from a given server
+	 *
+	 * @param string $guid the message guid
+	 * @param string $server The server address
+	 * @param int $uid The user id of the user
+	 *
+	 * @return int the message id of the stored message or false
+	 */
 	private function store_by_guid($guid, $server, $uid = 0) {
 		$serverparts = parse_url($server);
 		$server = $serverparts["scheme"]."://".$serverparts["host"];
@@ -751,6 +829,15 @@ class diaspora {
 		return self::dispatch_public($msg);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param string $guid message guid
+	 * @param $server
+	 * @param $level
+	 *
+	 * @return 
+	 */
 	private function message($guid, $server, $level = 0) {
 
 		if ($level > 5)
@@ -794,6 +881,16 @@ class diaspora {
 		return $msg;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param int $uid The user id
+	 * @param string $guid message guid
+	 * @param $author
+	 * @param array $contact The contact that is checked
+	 *
+	 * @return 
+	 */
 	private function parent_item($uid, $guid, $author, $contact) {
 		$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
 				`author-name`, `author-link`, `author-avatar`,
@@ -829,6 +926,15 @@ class diaspora {
 		}
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $contact The contact that is checked
+	 * @param $person
+	 * @param int $uid The user id
+	 *
+	 * @return 
+	 */
 	private function author_contact_by_url($contact, $person, $uid) {
 
 		$r = q("SELECT `id`, `network` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
@@ -844,10 +950,25 @@ class diaspora {
 		return (array("cid" => $cid, "network" => $network));
 	}
 
+	/**
+	 * @brief Is the profile a hubzilla profile?
+	 *
+	 * @param string $url The profile link
+	 *
+	 * @return bool is it a hubzilla server?
+	 */
 	public static function is_redmatrix($url) {
 		return(strstr($url, "/channel/"));
 	}
 
+	/**
+	 * @brief Generate a post link with a given handle and message guid
+	 *
+	 * @param $addr
+	 * @param string $guid message guid
+	 *
+	 * @return string the post link
+	 */
 	private function plink($addr, $guid) {
 		$r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr));
 
@@ -870,6 +991,14 @@ class diaspora {
 		return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param object $data The message object
+	 *
+	 * @return 
+	 */
 	private function receive_account_deletion($importer, $data) {
 		$author = notags(unxmlify($data->author));
 
@@ -884,6 +1013,16 @@ class diaspora {
 		return true;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param string $sender The sender of the message
+	 * @param object $data The message object
+	 * @param string $xml The original XML of the message
+	 *
+	 * @return int The message id of the generated comment or "false" if there was an error
+	 */
 	private function receive_comment($importer, $sender, $data, $xml) {
 		$guid = notags(unxmlify($data->guid));
 		$parent_guid = notags(unxmlify($data->parent_guid));
@@ -961,6 +1100,18 @@ class diaspora {
 		return $message_id;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param array $contact The contact that is checked
+	 * @param object $data The message object
+	 * @param $msg
+	 * @param $mesg
+	 * @param $conversation
+	 *
+	 * @return 
+	 */
 	private function receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation) {
 		$guid = notags(unxmlify($data->guid));
 		$subject = notags(unxmlify($data->subject));
@@ -1077,6 +1228,15 @@ class diaspora {
 		));
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param $msg
+	 * @param object $data The message object
+	 *
+	 * @return 
+	 */
 	private function receive_conversation($importer, $msg, $data) {
 		$guid = notags(unxmlify($data->guid));
 		$subject = notags(unxmlify($data->subject));
@@ -1134,6 +1294,15 @@ class diaspora {
 		return true;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $contact The contact that is checked
+	 * @param $parent_item
+	 * @param string $guid message guid
+	 *
+	 * @return 
+	 */
 	private function construct_like_body($contact, $parent_item, $guid) {
 		$bodyverb = t('%1$s likes %2$s\'s %3$s');
 
@@ -1144,6 +1313,14 @@ class diaspora {
 		return sprintf($bodyverb, $ulink, $alink, $plink);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param $parent_item
+	 *
+	 * @return 
+	 */
 	private function construct_like_object($importer, $parent_item) {
 		$objtype = ACTIVITY_OBJ_NOTE;
 		$link = '<link rel="alternate" type="text/html" href="'.App::get_baseurl()."/display/".$importer["nickname"]."/".$parent_item["id"].'" />';
@@ -1159,6 +1336,15 @@ class diaspora {
 		return xml::from_array($xmldata, $xml, true);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param string $sender The sender of the message
+	 * @param object $data The message object
+	 *
+	 * @return int The message id of the generated like or "false" if there was an error
+	 */
 	private function receive_like($importer, $sender, $data) {
 		$positive = notags(unxmlify($data->positive));
 		$guid = notags(unxmlify($data->guid));
@@ -1247,6 +1433,14 @@ class diaspora {
 		return $message_id;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param object $data The message object
+	 *
+	 * @return 
+	 */
 	private function receive_message($importer, $data) {
 		$guid = notags(unxmlify($data->guid));
 		$parent_guid = notags(unxmlify($data->parent_guid));
@@ -1318,27 +1512,59 @@ class diaspora {
 		return true;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param object $data The message object
+	 *
+	 * @return bool always true
+	 */
 	private function receive_participation($importer, $data) {
 		// I'm not sure if we can fully support this message type
 		return true;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param object $data The message object
+	 *
+	 * @return 
+	 */
 	private function receive_photo($importer, $data) {
 		// There doesn't seem to be a reason for this function, since the photo data is transmitted in the status message as well
 		return true;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param object $data The message object
+	 *
+	 * @return 
+	 */
 	private function receive_poll_participation($importer, $data) {
 		// We don't support polls by now
 		return true;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param object $data The message object
+	 *
+	 * @return 
+	 */
 	private function receive_profile($importer, $data) {
 		$author = notags(unxmlify($data->author));
 
 		$contact = self::contact_by_handle($importer["uid"], $author);
 		if (!$contact)
-			return;
+			return false;
 
 		$name = unxmlify($data->first_name).((strlen($data->last_name)) ? " ".unxmlify($data->last_name) : "");
 		$image_url = unxmlify($data->image_url);
@@ -1418,6 +1644,14 @@ class diaspora {
 		return true;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param array $contact The contact that is checked
+	 *
+	 * @return 
+	 */
 	private function receive_request_make_friend($importer, $contact) {
 
 		$a = get_app();
@@ -1485,6 +1719,14 @@ class diaspora {
 		}
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param object $data The message object
+	 *
+	 * @return 
+	 */
 	private function receive_request($importer, $data) {
 		$author = unxmlify($data->author);
 		$recipient = unxmlify($data->recipient);
@@ -1598,6 +1840,15 @@ class diaspora {
 		return true;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param string $guid message guid
+	 * @param $orig_author
+	 * @param $author
+	 *
+	 * @return 
+	 */
 	private function original_item($guid, $orig_author, $author) {
 
 		// Do we already have this item?
@@ -1654,6 +1905,15 @@ class diaspora {
 		return false;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param object $data The message object
+	 * @param string $xml The original XML of the message
+	 *
+	 * @return 
+	 */
 	private function receive_reshare($importer, $data, $xml) {
 		$root_author = notags(unxmlify($data->root_author));
 		$root_guid = notags(unxmlify($data->root_guid));
@@ -1719,6 +1979,15 @@ class diaspora {
 		return $message_id;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param array $contact The contact that is checked
+	 * @param object $data The message object
+	 *
+	 * @return 
+	 */
 	private function item_retraction($importer, $contact, $data) {
 		$target_type = notags(unxmlify($data->target_type));
 		$target_guid = notags(unxmlify($data->target_guid));
@@ -1770,6 +2039,15 @@ class diaspora {
 		}
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param string $sender The sender of the message
+	 * @param object $data The message object
+	 *
+	 * @return 
+	 */
 	private function receive_retraction($importer, $sender, $data) {
 		$target_type = notags(unxmlify($data->target_type));
 
@@ -1802,6 +2080,15 @@ class diaspora {
 		return true;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $importer Array of the importer user
+	 * @param object $data The message object
+	 * @param string $xml The original XML of the message
+	 *
+	 * @return 
+	 */
 	private function receive_status_message($importer, $data, $xml) {
 
 		$raw_message = unxmlify($data->raw_message);
@@ -1895,6 +2182,13 @@ class diaspora {
 	 * Here are all the functions that are needed to transmit data with the Diaspora protocol *
 	 ******************************************************************************************/
 
+	/**
+	 * @brief 
+	 *
+	 * @param $me
+	 *
+	 * @return 
+	 */
 	private function my_handle($me) {
 		if ($contact["addr"] != "")
 			return $contact["addr"];
@@ -1904,6 +2198,17 @@ class diaspora {
 		return $me["nickname"]."@".substr(App::get_baseurl(), strpos(App::get_baseurl(),"://") + 3);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $msg
+	 * @param $user
+	 * @param array $contact The contact that is checked
+	 * @param $prvkey
+	 * @param $pubkey
+	 *
+	 * @return 
+	 */
 	private function build_public_message($msg, $user, $contact, $prvkey, $pubkey) {
 
 		logger("Message: ".$msg, LOGGER_DATA);
@@ -1939,6 +2244,17 @@ class diaspora {
 		return $magic_env;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $msg
+	 * @param $user
+	 * @param array $contact The contact that is checked
+	 * @param $prvkey
+	 * @param $pubkey
+	 *
+	 * @return 
+	 */
 	private function build_private_message($msg, $user, $contact, $prvkey, $pubkey) {
 
 		logger("Message: ".$msg, LOGGER_DATA);
@@ -2018,6 +2334,18 @@ class diaspora {
 		return $magic_env;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $msg
+	 * @param $user
+	 * @param array $contact The contact that is checked
+	 * @param $prvkey
+	 * @param $pubkey
+	 * @param $public
+	 *
+	 * @return 
+	 */
 	private function build_message($msg, $user, $contact, $prvkey, $pubkey, $public = false) {
 
 		if ($public)
@@ -2030,6 +2358,14 @@ class diaspora {
 		return $slap;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $owner the array of the item owner
+	 * @param $message
+	 *
+	 * @return 
+	 */
 	private function signature($owner, $message) {
 		$sigmsg = $message;
 		unset($sigmsg["author_signature"]);
@@ -2040,6 +2376,18 @@ class diaspora {
 		return base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256"));
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $owner the array of the item owner
+	 * @param array $contact The contact that is checked
+	 * @param $slap
+	 * @param bool $public_batch Is it a public post?
+	 * @param $queue_run
+	 * @param string $guid message guid
+	 *
+	 * @return 
+	 */
 	public static function transmit($owner, $contact, $slap, $public_batch, $queue_run=false, $guid = "") {
 
 		$a = get_app();
@@ -2092,6 +2440,19 @@ class diaspora {
 	}
 
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $owner the array of the item owner
+	 * @param array $contact The contact that is checked
+	 * @param $type
+	 * @param $message
+	 * @param bool $public_batch Is it a public post?
+	 * @param string $guid message guid
+	 * @param $spool
+	 *
+	 * @return 
+	 */
 	private function build_and_transmit($owner, $contact, $type, $message, $public_batch = false, $guid = "", $spool = false) {
 
 		$data = array("XML" => array("post" => array($type => $message)));
@@ -2114,6 +2475,14 @@ class diaspora {
 		return $return_code;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $owner the array of the item owner
+	 * @param array $contact The contact that is checked
+	 *
+	 * @return int The result of the transmission
+	 */
 	public static function send_share($owner,$contact) {
 
 		$message = array("sender_handle" => self::my_handle($owner),
@@ -2122,6 +2491,14 @@ class diaspora {
 		return self::build_and_transmit($owner, $contact, "request", $message);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $owner the array of the item owner
+	 * @param array $contact The contact that is checked
+	 *
+	 * @return int The result of the transmission
+	 */
 	public static function send_unshare($owner,$contact) {
 
 		$message = array("post_guid" => $owner["guid"],
@@ -2131,6 +2508,14 @@ class diaspora {
 		return self::build_and_transmit($owner, $contact, "retraction", $message);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $body
+	 * @param $complete
+	 *
+	 * @return 
+	 */
 	public static function is_reshare($body, $complete = true) {
 		$body = trim($body);
 
@@ -2202,6 +2587,16 @@ class diaspora {
 		return($ret);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $item The item that will be exported
+	 * @param array $owner the array of the item owner
+	 * @param array $contact The contact that is checked
+	 * @param bool $public_batch Is it a public post?
+	 *
+	 * @return int The result of the transmission
+	 */
 	public static function send_status($item, $owner, $contact, $public_batch = false) {
 
 		$myaddr = self::my_handle($owner);
@@ -2269,10 +2664,16 @@ class diaspora {
 		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $item The item that will be exported
+	 * @param array $owner the array of the item owner
+	 *
+	 * @return 
+	 */
 	private function construct_like($item, $owner) {
 
-		$myaddr = self::my_handle($owner);
-
 		$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
 			dbesc($item["thr-parent"]));
 		if(!$p)
@@ -2288,13 +2689,19 @@ class diaspora {
 				"target_type" => $target_type,
 				"parent_guid" => $parent["guid"],
 				"author_signature" => $authorsig,
-				"diaspora_handle" => $myaddr));
+				"diaspora_handle" => self::my_handle($owner)));
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $item The item that will be exported
+	 * @param array $owner the array of the item owner
+	 *
+	 * @return 
+	 */
 	private function construct_comment($item, $owner) {
 
-		$myaddr = self::my_handle($owner);
-
 		$p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1",
 			intval($item["parent"]),
 			intval($item["parent"])
@@ -2311,9 +2718,19 @@ class diaspora {
 				"parent_guid" => $parent["guid"],
 				"author_signature" => "",
 				"text" => $text,
-				"diaspora_handle" => $myaddr));
+				"diaspora_handle" => self::my_handle($owner)));
 	}
 
+	/**
+	 * @brief Send a like or a comment
+	 *
+	 * @param array $item The item that will be exported
+	 * @param array $owner the array of the item owner
+	 * @param array $contact The contact that is checked
+	 * @param bool $public_batch Is it a public post?
+	 *
+	 * @return int The result of the transmission
+	 */
 	public static function send_followup($item,$owner,$contact,$public_batch = false) {
 
 		if($item['verb'] === ACTIVITY_LIKE) {
@@ -2332,6 +2749,14 @@ class diaspora {
 		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $item The item that will be exported
+	 * @param $signature
+	 *
+	 * @return int The result of the transmission
+	 */
 	private function message_from_signatur($item, $signature) {
 
 		// Split the signed text
@@ -2374,6 +2799,16 @@ class diaspora {
 		return $message;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $item The item that will be exported
+	 * @param array $owner the array of the item owner
+	 * @param array $contact The contact that is checked
+	 * @param bool $public_batch Is it a public post?
+	 *
+	 * @return int The result of the transmission
+	 */
 	public static function send_relay($item, $owner, $contact, $public_batch = false) {
 
 		if ($item["deleted"])
@@ -2427,10 +2862,20 @@ class diaspora {
 		return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $item The item that will be exported
+	 * @param array $owner the array of the item owner
+	 * @param array $contact The contact that is checked
+	 * @param bool $public_batch Is it a public post?
+	 * @param $relay
+	 *
+	 * @return int The result of the transmission
+	 */
 	public static function send_retraction($item, $owner, $contact, $public_batch = false, $relay = false) {
 
 		$itemaddr = self::handle_from_contact($item["contact-id"], $item["gcontact-id"]);
-		//$myaddr = self::my_handle($owner);
 
 		// Check whether the retraction is for a top-level post or whether it's a relayable
 		if ($item["uri"] !== $item["parent-uri"]) {
@@ -2458,6 +2903,15 @@ class diaspora {
 		return self::build_and_transmit($owner, $contact, $msg_type, $message, $public_batch, $item["guid"]);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param array $item The item that will be exported
+	 * @param array $owner The owner
+	 * @param array $contact The contact that is checked
+	 *
+	 * @return int The result of the transmission
+	 */
 	public static function send_mail($item, $owner, $contact) {
 
 		$myaddr = self::my_handle($owner);
@@ -2515,6 +2969,13 @@ class diaspora {
 		return self::build_and_transmit($owner, $contact, $type, $message, false, $item["guid"]);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param int $uid The user id
+	 *
+	 * @return int The result of the transmission
+	 */
 	public static function send_profile($uid) {
 
 		if (!$uid)
diff --git a/util/createdoxygen.php b/util/createdoxygen.php
new file mode 100755
index 0000000000..d48114b671
--- /dev/null
+++ b/util/createdoxygen.php
@@ -0,0 +1,82 @@
+#!/usr/bin/php
+<?php
+if (count($_SERVER["argv"]) < 2)
+	die("usage: createdoxygen.php file\n");
+
+$file = $_SERVER["argv"][1];
+$data = file_get_contents($file);
+
+$lines = explode("\n", $data);
+
+$previous = "";
+
+foreach ($lines AS $line) {
+	$line = rtrim(trim($line, "\r"));
+
+	if (strstr(strtolower($line), "function")) {
+		$detect = strtolower(trim($line));
+		$detect = implode(" ", explode(" ", $detect));
+
+		$found = false;
+
+		if (substr($detect, 0, 9) == "function ")
+			$found = true;
+
+		if (substr($detect, 0, 17) == "private function ")
+			$found = true;
+
+		if (substr($detect, 0, 23) == "public static function ")
+			$found = true;
+
+		if (substr($detect, 0, 10) == "function (")
+			$found = false;
+
+		if ($found and (trim($previous) == "*/"))
+			$found = false;
+
+		if ($found and !strstr($detect, "{"))
+			$found = false;
+
+		if ($found) {
+			echo add_documentation($line);
+		}
+	}
+	echo $line."\n";
+	$previous = $line;
+}
+
+function add_documentation($line) {
+
+	$trimmed = ltrim($line);
+	$length = strlen($line) - strlen($trimmed);
+	$space = substr($line, 0, $length);
+
+	$block = $space."/**\n".
+		$space." * @brief \n".
+		$space." *\n"; /**/
+
+
+	$left = strpos($line, "(");
+	$line = substr($line, $left + 1);
+
+	$right = strpos($line, ")");
+	$line = trim(substr($line, 0, $right));
+
+	if ($line != "") {
+		$parameters = explode(",", $line);
+		foreach ($parameters AS $parameter) {
+			$parameter = trim($parameter);
+			$splitted = explode("=", $parameter);
+
+			$block .= $space." * @param ".trim($splitted[0], "& ")."\n";
+		}
+		if (count($parameters) > 0)
+			$block .= $space." *\n";
+	}
+
+	$block .= $space." * @return \n".
+		$space." */\n";
+
+	return $block;
+}
+?>

From e74587b37576df113e05a56bc7a4d29f736a4fb5 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 18 Mar 2016 08:07:23 +0100
Subject: [PATCH 213/273] Just some more documentation

---
 include/diaspora.php | 149 ++++++++++++++++++++++---------------------
 1 file changed, 75 insertions(+), 74 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index dd0efa1d73..14ff6e42f8 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -830,13 +830,13 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Fetches a message from a server
 	 *
 	 * @param string $guid message guid
-	 * @param $server
-	 * @param $level
+	 * @param string $server The url of the server
+	 * @param int $level Endless loop prevention
 	 *
-	 * @return 
+	 * @return array of message, author and public key
 	 */
 	private function message($guid, $server, $level = 0) {
 
@@ -882,14 +882,14 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Fetches the item record of a given guid
 	 *
 	 * @param int $uid The user id
 	 * @param string $guid message guid
-	 * @param $author
+	 * @param string $author The handle of the item
 	 * @param array $contact The contact that is checked
 	 *
-	 * @return 
+	 * @return array the item record
 	 */
 	private function parent_item($uid, $guid, $author, $contact) {
 		$r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`,
@@ -927,13 +927,13 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief returns contact details
 	 *
-	 * @param array $contact The contact that is checked
-	 * @param $person
+	 * @param array $contact The default contact if the person isn't found
+	 * @param array $person The record of the person
 	 * @param int $uid The user id
 	 *
-	 * @return 
+	 * @return array of contact id and network type
 	 */
 	private function author_contact_by_url($contact, $person, $uid) {
 
@@ -964,7 +964,7 @@ class diaspora {
 	/**
 	 * @brief Generate a post link with a given handle and message guid
 	 *
-	 * @param $addr
+	 * @param string $addr The user handle
 	 * @param string $guid message guid
 	 *
 	 * @return string the post link
@@ -1101,16 +1101,16 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief processes and stores private messages
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param array $contact The contact that is checked
 	 * @param object $data The message object
-	 * @param $msg
-	 * @param $mesg
-	 * @param $conversation
+	 * @param array $msg Array of the processed message, author handle and key
+	 * @param object $mesg The private message
+	 * @param array $conversation The conversation record to which this message belongs
 	 *
-	 * @return 
+	 * @return bool "true" if it was successful
 	 */
 	private function receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation) {
 		$guid = notags(unxmlify($data->guid));
@@ -1226,13 +1226,14 @@ class diaspora {
 			"verb" => ACTIVITY_POST,
 			"otype" => "mail"
 		));
+		return true;
 	}
 
 	/**
 	 * @brief 
 	 *
 	 * @param array $importer Array of the importer user
-	 * @param $msg
+	 * @param array $msg Array of the processed message, author handle and key
 	 * @param object $data The message object
 	 *
 	 * @return 
@@ -2183,11 +2184,11 @@ class diaspora {
 	 ******************************************************************************************/
 
 	/**
-	 * @brief 
+	 * @brief returnes the handle of a contact
 	 *
-	 * @param $me
+	 * @param array $me contact array
 	 *
-	 * @return 
+	 * @return string the handle in the format user@domain.tld
 	 */
 	private function my_handle($me) {
 		if ($contact["addr"] != "")
@@ -2199,15 +2200,15 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Creates the envelope for a public message
 	 *
-	 * @param $msg
-	 * @param $user
-	 * @param array $contact The contact that is checked
-	 * @param $prvkey
-	 * @param $pubkey
+	 * @param string $msg The message that is to be transmitted
+	 * @param array $user The record of the sender
+	 * @param array $contact Target of the communication
+	 * @param string $prvkey The private key of the sender
+	 * @param string $pubkey The public key of the receiver
 	 *
-	 * @return 
+	 * @return string The envelope
 	 */
 	private function build_public_message($msg, $user, $contact, $prvkey, $pubkey) {
 
@@ -2245,15 +2246,15 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Creates the envelope for a private message
 	 *
-	 * @param $msg
-	 * @param $user
-	 * @param array $contact The contact that is checked
-	 * @param $prvkey
-	 * @param $pubkey
+	 * @param string $msg The message that is to be transmitted
+	 * @param array $user The record of the sender
+	 * @param array $contact Target of the communication
+	 * @param string $prvkey The private key of the sender
+	 * @param string $pubkey The public key of the receiver
 	 *
-	 * @return 
+	 * @return string The envelope
 	 */
 	private function build_private_message($msg, $user, $contact, $prvkey, $pubkey) {
 
@@ -2335,14 +2336,14 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Create the envelope for a message
 	 *
-	 * @param $msg
-	 * @param $user
-	 * @param array $contact The contact that is checked
-	 * @param $prvkey
-	 * @param $pubkey
-	 * @param $public
+	 * @param string $msg The message that is to be transmitted
+	 * @param array $user The record of the sender
+	 * @param array $contact Target of the communication
+	 * @param string $prvkey The private key of the sender
+	 * @param string $pubkey The public key of the receiver
+	 * @param bool $public Is the message public?
 	 *
 	 * @return 
 	 */
@@ -2359,12 +2360,12 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Creates a signature for a message
 	 *
-	 * @param array $owner the array of the item owner
-	 * @param $message
+	 * @param array $owner the array of the owner of the message
+	 * @param array $message The message that is to be signed
 	 *
-	 * @return 
+	 * @return string The signature
 	 */
 	private function signature($owner, $message) {
 		$sigmsg = $message;
@@ -2377,16 +2378,16 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Transmit a message to a target server
 	 *
 	 * @param array $owner the array of the item owner
-	 * @param array $contact The contact that is checked
-	 * @param $slap
+	 * @param array $contact Target of the communication
+	 * @param string $slap The message that is to be transmitted
 	 * @param bool $public_batch Is it a public post?
-	 * @param $queue_run
+	 * @param bool $queue_run Is the transmission called from the queue?
 	 * @param string $guid message guid
 	 *
-	 * @return 
+	 * @return int Result of the transmission
 	 */
 	public static function transmit($owner, $contact, $slap, $public_batch, $queue_run=false, $guid = "") {
 
@@ -2444,14 +2445,14 @@ class diaspora {
 	 * @brief 
 	 *
 	 * @param array $owner the array of the item owner
-	 * @param array $contact The contact that is checked
-	 * @param $type
-	 * @param $message
+	 * @param array $contact Target of the communication
+	 * @param string $type The message type
+	 * @param array $message The message data
 	 * @param bool $public_batch Is it a public post?
 	 * @param string $guid message guid
-	 * @param $spool
+	 * @param bool $spool Should the transmission be spooled or transmitted?
 	 *
-	 * @return 
+	 * @return int Result of the transmission
 	 */
 	private function build_and_transmit($owner, $contact, $type, $message, $public_batch = false, $guid = "", $spool = false) {
 
@@ -2479,7 +2480,7 @@ class diaspora {
 	 * @brief 
 	 *
 	 * @param array $owner the array of the item owner
-	 * @param array $contact The contact that is checked
+	 * @param array $contact Target of the communication
 	 *
 	 * @return int The result of the transmission
 	 */
@@ -2495,7 +2496,7 @@ class diaspora {
 	 * @brief 
 	 *
 	 * @param array $owner the array of the item owner
-	 * @param array $contact The contact that is checked
+	 * @param array $contact Target of the communication
 	 *
 	 * @return int The result of the transmission
 	 */
@@ -2509,12 +2510,12 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Checks a message body if it is a reshare
 	 *
-	 * @param $body
-	 * @param $complete
+	 * @param string $body The message body that is to be check
+	 * @param bool $complete Should it be a complete check or a simple check?
 	 *
-	 * @return 
+	 * @return array|bool Reshare details or "false" if no reshare
 	 */
 	public static function is_reshare($body, $complete = true) {
 		$body = trim($body);
@@ -2592,7 +2593,7 @@ class diaspora {
 	 *
 	 * @param array $item The item that will be exported
 	 * @param array $owner the array of the item owner
-	 * @param array $contact The contact that is checked
+	 * @param array $contact Target of the communication
 	 * @param bool $public_batch Is it a public post?
 	 *
 	 * @return int The result of the transmission
@@ -2726,7 +2727,7 @@ class diaspora {
 	 *
 	 * @param array $item The item that will be exported
 	 * @param array $owner the array of the item owner
-	 * @param array $contact The contact that is checked
+	 * @param array $contact Target of the communication
 	 * @param bool $public_batch Is it a public post?
 	 *
 	 * @return int The result of the transmission
@@ -2750,14 +2751,14 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Creates a message from a signature record entry
 	 *
 	 * @param array $item The item that will be exported
-	 * @param $signature
+	 * @param array $signature The entry of the "sign" record
 	 *
-	 * @return int The result of the transmission
+	 * @return string The message
 	 */
-	private function message_from_signatur($item, $signature) {
+	private function message_from_signature($item, $signature) {
 
 		// Split the signed text
 		$signed_parts = explode(";", $signature['signed_text']);
@@ -2804,7 +2805,7 @@ class diaspora {
 	 *
 	 * @param array $item The item that will be exported
 	 * @param array $owner the array of the item owner
-	 * @param array $contact The contact that is checked
+	 * @param array $contact Target of the communication
 	 * @param bool $public_batch Is it a public post?
 	 *
 	 * @return int The result of the transmission
@@ -2835,7 +2836,7 @@ class diaspora {
 		// Old way - is used by the internal Friendica functions
 		/// @todo Change all signatur storing functions to the new format
 		if ($signature['signed_text'] AND $signature['signature'] AND $signature['signer'])
-			$message = self::message_from_signatur($item, $signature);
+			$message = self::message_from_signature($item, $signature);
 		else {// New way
 			$msg = json_decode($signature['signed_text'], true);
 
@@ -2863,13 +2864,13 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Sends a retraction (deletion) of a message, like or comment
 	 *
 	 * @param array $item The item that will be exported
 	 * @param array $owner the array of the item owner
-	 * @param array $contact The contact that is checked
+	 * @param array $contact Target of the communication
 	 * @param bool $public_batch Is it a public post?
-	 * @param $relay
+	 * @param bool $relay Is the retraction transmitted from a relay?
 	 *
 	 * @return int The result of the transmission
 	 */
@@ -2908,7 +2909,7 @@ class diaspora {
 	 *
 	 * @param array $item The item that will be exported
 	 * @param array $owner The owner
-	 * @param array $contact The contact that is checked
+	 * @param array $contact Target of the communication
 	 *
 	 * @return int The result of the transmission
 	 */

From a2507804f2eab92df5ff721b3c836da5d1ca7461 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 18 Mar 2016 16:42:10 +0100
Subject: [PATCH 214/273] There is no table "sess_data" - this database call is
 useless

---
 include/session.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/session.php b/include/session.php
index 11641d6cea..12551efc42 100644
--- a/include/session.php
+++ b/include/session.php
@@ -69,7 +69,7 @@ function ref_session_destroy ($id) {
 if(! function_exists('ref_session_gc')) {
 function ref_session_gc($expire) {
 	q("DELETE FROM `session` WHERE `expire` < %d", dbesc(time()));
-	q("OPTIMIZE TABLE `sess_data`");
+	//q("OPTIMIZE TABLE `sess_data`");
 	return true;
 }}
 

From 5c44a787bf0f6c514ee33cb75faee544618eb775 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 18 Mar 2016 22:28:20 +0100
Subject: [PATCH 215/273] The documentation should now be complete

---
 include/diaspora.php | 118 +++++++++++++++++++++----------------------
 1 file changed, 58 insertions(+), 60 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 14ff6e42f8..4e1b300507 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -110,6 +110,8 @@ class diaspora {
 	/**
 	 * @brief repairs a signature that was double encoded
 	 *
+	 * The function is unused at the moment. It was copied from the old implementation.
+	 *
 	 * @param string $signature The signature
 	 * @param string $handle The handle of the signature owner
 	 * @param integer $level This value is only set inside this function to avoid endless loops
@@ -887,7 +889,7 @@ class diaspora {
 	 * @param int $uid The user id
 	 * @param string $guid message guid
 	 * @param string $author The handle of the item
-	 * @param array $contact The contact that is checked
+	 * @param array $contact The contact of the item owner
 	 *
 	 * @return array the item record
 	 */
@@ -992,12 +994,12 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes an account deletion
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param object $data The message object
 	 *
-	 * @return 
+	 * @return bool Success
 	 */
 	private function receive_account_deletion($importer, $data) {
 		$author = notags(unxmlify($data->author));
@@ -1014,7 +1016,7 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes an incoming comment
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param string $sender The sender of the message
@@ -1104,7 +1106,7 @@ class diaspora {
 	 * @brief processes and stores private messages
 	 *
 	 * @param array $importer Array of the importer user
-	 * @param array $contact The contact that is checked
+	 * @param array $contact The contact of the message
 	 * @param object $data The message object
 	 * @param array $msg Array of the processed message, author handle and key
 	 * @param object $mesg The private message
@@ -1230,13 +1232,13 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes new private messages (answers to private messages are processed elsewhere)
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param array $msg Array of the processed message, author handle and key
 	 * @param object $data The message object
 	 *
-	 * @return 
+	 * @return bool Success
 	 */
 	private function receive_conversation($importer, $msg, $data) {
 		$guid = notags(unxmlify($data->guid));
@@ -1296,13 +1298,13 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Creates the body for a "like" message
 	 *
-	 * @param array $contact The contact that is checked
-	 * @param $parent_item
+	 * @param array $contact The contact that send us the "like"
+	 * @param array $parent_item The item array of the parent item
 	 * @param string $guid message guid
 	 *
-	 * @return 
+	 * @return string the body
 	 */
 	private function construct_like_body($contact, $parent_item, $guid) {
 		$bodyverb = t('%1$s likes %2$s\'s %3$s');
@@ -1315,12 +1317,12 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Creates a XML object for a "like"
 	 *
 	 * @param array $importer Array of the importer user
-	 * @param $parent_item
+	 * @param array $parent_item The item array of the parent item
 	 *
-	 * @return 
+	 * @return string The XML
 	 */
 	private function construct_like_object($importer, $parent_item) {
 		$objtype = ACTIVITY_OBJ_NOTE;
@@ -1338,7 +1340,7 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes "like" messages
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param string $sender The sender of the message
@@ -1435,12 +1437,12 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes private messages
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param object $data The message object
 	 *
-	 * @return 
+	 * @return bool Success?
 	 */
 	private function receive_message($importer, $data) {
 		$guid = notags(unxmlify($data->guid));
@@ -1514,7 +1516,7 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes participations - unsupported by now
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param object $data The message object
@@ -1527,12 +1529,12 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes photos - unneeded
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param object $data The message object
 	 *
-	 * @return 
+	 * @return bool always true
 	 */
 	private function receive_photo($importer, $data) {
 		// There doesn't seem to be a reason for this function, since the photo data is transmitted in the status message as well
@@ -1540,12 +1542,12 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes poll participations - unssupported
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param object $data The message object
 	 *
-	 * @return 
+	 * @return bool always true
 	 */
 	private function receive_poll_participation($importer, $data) {
 		// We don't support polls by now
@@ -1553,12 +1555,12 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes incoming profile updates
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param object $data The message object
 	 *
-	 * @return 
+	 * @return bool Success
 	 */
 	private function receive_profile($importer, $data) {
 		$author = notags(unxmlify($data->author));
@@ -1646,12 +1648,10 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes incoming friend requests
 	 *
 	 * @param array $importer Array of the importer user
-	 * @param array $contact The contact that is checked
-	 *
-	 * @return 
+	 * @param array $contact The contact that send the request
 	 */
 	private function receive_request_make_friend($importer, $contact) {
 
@@ -1714,26 +1714,24 @@ class diaspora {
 				$i = item_store($arr);
 				if($i)
 					proc_run("php", "include/notifier.php", "activity", $i);
-
 			}
-
 		}
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes incoming sharing notification
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param object $data The message object
 	 *
-	 * @return 
+	 * @return bool Success
 	 */
 	private function receive_request($importer, $data) {
 		$author = unxmlify($data->author);
 		$recipient = unxmlify($data->recipient);
 
 		if (!$author || !$recipient)
-			return;
+			return false;
 
 		$contact = self::contact_by_handle($importer["uid"],$author);
 
@@ -1842,13 +1840,13 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Fetches a message with a given guid
 	 *
 	 * @param string $guid message guid
-	 * @param $orig_author
-	 * @param $author
+	 * @param string $orig_author handle of the original post
+	 * @param string $author handle of the sharer
 	 *
-	 * @return 
+	 * @return array The fetched item
 	 */
 	private function original_item($guid, $orig_author, $author) {
 
@@ -1907,13 +1905,13 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes a reshare message
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param object $data The message object
 	 * @param string $xml The original XML of the message
 	 *
-	 * @return 
+	 * @return int the message id
 	 */
 	private function receive_reshare($importer, $data, $xml) {
 		$root_author = notags(unxmlify($data->root_author));
@@ -1981,13 +1979,13 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Processes retractions
 	 *
 	 * @param array $importer Array of the importer user
-	 * @param array $contact The contact that is checked
+	 * @param array $contact The contact of the item owner
 	 * @param object $data The message object
 	 *
-	 * @return 
+	 * @return bool success
 	 */
 	private function item_retraction($importer, $contact, $data) {
 		$target_type = notags(unxmlify($data->target_type));
@@ -2038,16 +2036,18 @@ class diaspora {
 			// notify others
 			proc_run("php", "include/notifier.php", "drop", $r[0]["id"]);
 		}
+
+		return true;
 	}
 
 	/**
-	 * @brief 
+	 * @brief Receives retraction messages
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param string $sender The sender of the message
 	 * @param object $data The message object
 	 *
-	 * @return 
+	 * @return bool Success
 	 */
 	private function receive_retraction($importer, $sender, $data) {
 		$target_type = notags(unxmlify($data->target_type));
@@ -2082,13 +2082,13 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Receives status messages
 	 *
 	 * @param array $importer Array of the importer user
 	 * @param object $data The message object
 	 * @param string $xml The original XML of the message
 	 *
-	 * @return 
+	 * @return int The message id of the newly created item
 	 */
 	private function receive_status_message($importer, $data, $xml) {
 
@@ -2345,7 +2345,7 @@ class diaspora {
 	 * @param string $pubkey The public key of the receiver
 	 * @param bool $public Is the message public?
 	 *
-	 * @return 
+	 * @return string The message that will be transmitted to other servers
 	 */
 	private function build_message($msg, $user, $contact, $prvkey, $pubkey, $public = false) {
 
@@ -2442,7 +2442,7 @@ class diaspora {
 
 
 	/**
-	 * @brief 
+	 * @brief Builds and transmit messages
 	 *
 	 * @param array $owner the array of the item owner
 	 * @param array $contact Target of the communication
@@ -2477,7 +2477,7 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Sends a "share" message
 	 *
 	 * @param array $owner the array of the item owner
 	 * @param array $contact Target of the communication
@@ -2493,7 +2493,7 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief sends an "unshare"
 	 *
 	 * @param array $owner the array of the item owner
 	 * @param array $contact Target of the communication
@@ -2589,7 +2589,7 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Sends a post
 	 *
 	 * @param array $item The item that will be exported
 	 * @param array $owner the array of the item owner
@@ -2666,12 +2666,12 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Creates a "like" object
 	 *
 	 * @param array $item The item that will be exported
 	 * @param array $owner the array of the item owner
 	 *
-	 * @return 
+	 * @return array The data for a "like"
 	 */
 	private function construct_like($item, $owner) {
 
@@ -2694,12 +2694,12 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Creates the object for a comment
 	 *
 	 * @param array $item The item that will be exported
 	 * @param array $owner the array of the item owner
 	 *
-	 * @return 
+	 * @return array The data for a comment
 	 */
 	private function construct_comment($item, $owner) {
 
@@ -2801,7 +2801,7 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Relays messages (like, comment, retraction) to other servers if we are the thread owner
 	 *
 	 * @param array $item The item that will be exported
 	 * @param array $owner the array of the item owner
@@ -2905,7 +2905,7 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Sends a mail
 	 *
 	 * @param array $item The item that will be exported
 	 * @param array $owner The owner
@@ -2971,11 +2971,9 @@ class diaspora {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Sends profile data
 	 *
 	 * @param int $uid The user id
-	 *
-	 * @return int The result of the transmission
 	 */
 	public static function send_profile($uid) {
 

From d676ae0f32a33e0f75c28d31f32f3d9476b4efd6 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 19 Mar 2016 15:49:47 +0100
Subject: [PATCH 216/273] The signature creation now moved into the Diaspora
 class. That's much cleaner.

---
 include/diaspora.php | 124 +++++++++++++++++++++++++++++++++++++++++--
 include/like.php     |  83 +----------------------------
 mod/item.php         |  42 +--------------
 3 files changed, 125 insertions(+), 124 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 4e1b300507..59bad946e2 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -2190,13 +2190,18 @@ class diaspora {
 	 *
 	 * @return string the handle in the format user@domain.tld
 	 */
-	private function my_handle($me) {
+	private function my_handle($contact) {
 		if ($contact["addr"] != "")
 			return $contact["addr"];
 
 		// Normally we should have a filled "addr" field - but in the past this wasn't the case
 		// So - just in case - we build the the address here.
-		return $me["nickname"]."@".substr(App::get_baseurl(), strpos(App::get_baseurl(),"://") + 3);
+		if ($contact["nickname"] != "")
+			$nick = $contact["nickname"];
+		else
+			$nick = $contact["nick"];
+
+		return $nick."@".substr(App::get_baseurl(), strpos(App::get_baseurl(),"://") + 3);
 	}
 
 	/**
@@ -2689,7 +2694,7 @@ class diaspora {
 				"guid" => $item["guid"],
 				"target_type" => $target_type,
 				"parent_guid" => $parent["guid"],
-				"author_signature" => $authorsig,
+				"author_signature" => "",
 				"diaspora_handle" => self::my_handle($owner)));
 	}
 
@@ -3052,5 +3057,118 @@ class diaspora {
 		foreach($recips as $recip)
 			self::build_and_transmit($profile, $recip, "profile", $message, false, "", true);
 	}
+
+	/**
+	 * @brief Stores the signature for likes that are created on our system
+	 *
+	 * @param array $contact The contact array of the "like"
+	 * @param int $post_id The post id of the "like"
+	 *
+	 * @return bool Success
+	 */
+	function store_like_signature($contact, $post_id) {
+
+		$enabled = intval(get_config('system','diaspora_enabled'));
+		if (!$enabled) {
+			logger('Diaspora support disabled, not storing like signature', LOGGER_DEBUG);
+			return false;
+		}
+
+		// Is the contact the owner? Then fetch the private key
+		if (!$contact['self'] OR ($contact['uid'] == 0)) {
+			logger("No owner post, so not storing signature", LOGGER_DEBUG);
+			return false;
+		}
+
+		$r = q("SELECT `prvkey` FROM `user` WHERE `uid` = %d LIMIT 1", intval($contact['uid']));
+		if(!$r)
+			return false;
+
+		$contact["uprvkey"] = $r[0]['prvkey'];
+
+		$r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($post_id));
+		if (!$r)
+			return false;
+
+		if (!in_array($r[0]["verb"], array(ACTIVITY_LIKE, ACTIVITY_DISLIKE)))
+			return false;
+
+		$message = self::construct_like($r[0], $contact);
+		$message["author_signature"] = self::signature($contact, $message);
+
+		// In the future we will store the signature more flexible to support new fields.
+		// Right now we cannot change this since old Friendica versions (prior to 3.5) can only handle this format.
+		// (We are transmitting this data here via DFRN)
+
+		$signed_text = $message["positive"].";".$message["guid"].";".$message["target_type"].";".
+				$message["parent_guid"].";".$message["diaspora_handle"];
+
+		q("INSERT INTO `sign` (`iid`,`signed_text`,`signature`,`signer`) VALUES (%d,'%s','%s','%s')",
+			intval($post_id),
+			dbesc($signed_text),
+			dbesc($message["author_signature"]),
+			dbesc($message["diaspora_handle"])
+		);
+
+		// This here will replace the lines above, once Diaspora changed its protocol
+		//q("INSERT INTO `sign` (`iid`,`signed_text`) VALUES (%d,'%s')",
+		//	intval($message_id),
+		//	dbesc(json_encode($message))
+		//);
+
+		logger('Stored diaspora like signature');
+		return true;
+	}
+
+	/**
+	 * @brief Stores the signature for comments that are created on our system
+	 *
+	 * @param array $item The item array of the comment
+	 * @param array $contact The contact array of the item owner
+	 * @param string $uprvkey The private key of the sender
+	 * @param int $message_id The message id of the comment
+	 *
+	 * @return bool Success
+	 */
+	function store_comment_signature($item, $contact, $uprvkey, $message_id) {
+
+		if ($uprvkey == "") {
+			logger('No private key, so not storing comment signature', LOGGER_DEBUG);
+			return false;
+		}
+
+		$enabled = intval(get_config('system','diaspora_enabled'));
+		if (!$enabled) {
+			logger('Diaspora support disabled, not storing comment signature', LOGGER_DEBUG);
+			return false;
+		}
+
+		$contact["uprvkey"] = $uprvkey;
+
+		$message = self::construct_comment($item, $contact);
+		$message["author_signature"] = self::signature($contact, $message);
+
+		// In the future we will store the signature more flexible to support new fields.
+		// Right now we cannot change this since old Friendica versions (prior to 3.5) can only handle this format.
+		// (We are transmitting this data here via DFRN)
+		$signed_text = $message["guid"].";".$message["parent_guid"].";".
+				$message["text"].";".$message["diaspora_handle"];
+
+		q("INSERT INTO `sign` (`iid`,`signed_text`,`signature`,`signer`) VALUES (%d,'%s','%s','%s')",
+			intval($message_id),
+			dbesc($signed_text),
+			dbesc($message["author_signature"]),
+			dbesc($message["diaspora_handle"])
+		);
+
+		// This here will replace the lines above, once Diaspora changed its protocol
+		//q("INSERT INTO `sign` (`iid`,`signed_text`) VALUES (%d,'%s')",
+		//	intval($message_id),
+		//	dbesc(json_encode($message))
+		//);
+
+		logger('Stored diaspora comment signature');
+		return true;
+	}
 }
 ?>
diff --git a/include/like.php b/include/like.php
index 2e5367e51e..49534ea613 100644
--- a/include/like.php
+++ b/include/like.php
@@ -1,4 +1,5 @@
 <?php
+require_once("include/diaspora.php");
 
 /**
  * @brief add/remove activity to an item
@@ -237,7 +238,7 @@ EOT;
 
 
 	// Save the author information for the like in case we need to relay to Diaspora
-	store_diaspora_like_sig($activity, $post_type, $contact, $post_id);
+	diaspora::store_like_signature($contact, $post_id);
 
 	$arr['id'] = $post_id;
 
@@ -247,83 +248,3 @@ EOT;
 
 	return true;
 }
-
-function store_diaspora_like_sig($activity, $post_type, $contact, $post_id) {
-	// Note that we can only create a signature for a user of the local server. We don't have
-	// a key for remote users. That is ok, because if a remote user is "unlike"ing a post, it
-	// means we are the relay, and for relayable_retractions, Diaspora
-	// only checks the parent_author_signature if it doesn't have to relay further
-
-	$enabled = intval(get_config('system','diaspora_enabled'));
-	if(! $enabled) {
-		logger('mod_like: diaspora support disabled, not storing like signature', LOGGER_DEBUG);
-		return;
-	}
-
-	logger('mod_like: storing diaspora like signature');
-
-	if(($activity === ACTIVITY_LIKE) && ($post_type === t('status'))) {
-		// Only works for NETWORK_DFRN
-		$contact_baseurl_start = strpos($contact['url'],'://') + 3;
-		$contact_baseurl_length = strpos($contact['url'],'/profile') - $contact_baseurl_start;
-		$contact_baseurl = substr($contact['url'], $contact_baseurl_start, $contact_baseurl_length);
-		$diaspora_handle = $contact['nick'] . '@' . $contact_baseurl;
-
-
-		// This code could never had worked (the return values form the queries were used in a wrong way.
-		// Additionally it is needlessly complicated. Either the contact is owner or not. And we have this data already.
-/*
-		// Get contact's private key if he's a user of the local Friendica server
-		$r = q("SELECT `contact`.`uid` FROM `contact` WHERE `url` = '%s' AND `self` = 1 LIMIT 1",
-			dbesc($contact['url'])
-		);
-
-		if( $r) {
-			$contact_uid = $r['uid'];
-			$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
-				intval($contact_uid)
-			);
-
-			if( $r)
-				$contact_uprvkey = $r['prvkey'];
-		}
-*/
-
-		// Is the contact the owner? Then fetch the private key
-		if ($contact['self'] AND ($contact['uid'] > 0)) {
-			$r = q("SELECT prvkey FROM user WHERE uid = %d LIMIT 1",
-				intval($contact['uid'])
-			);
-
-			if($r)
-				$contact_uprvkey = $r[0]['prvkey'];
-		}
-
-		$r = q("SELECT guid, parent FROM `item` WHERE id = %d LIMIT 1",
-			intval($post_id)
-		);
-		if( $r) {
-			$p = q("SELECT guid FROM `item` WHERE id = %d AND parent = %d LIMIT 1",
-				intval($r[0]['parent']),
-				intval($r[0]['parent'])
-			);
-			if( $p) {
-				$signed_text = 'true;'.$r[0]['guid'].';Post;'.$p[0]['guid'].';'.$diaspora_handle;
-
-				if(isset($contact_uprvkey))
-					$authorsig = base64_encode(rsa_sign($signed_text,$contact_uprvkey,'sha256'));
-				else
-					$authorsig = '';
-
-				q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
-					intval($post_id),
-					dbesc($signed_text),
-					dbesc($authorsig),
-					dbesc($diaspora_handle)
-				);
-			}
-		}
-	}
-
-	return;
-}
diff --git a/mod/item.php b/mod/item.php
index 2ade524a05..14c8203c98 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -24,6 +24,7 @@ require_once('include/threads.php');
 require_once('include/text.php');
 require_once('include/items.php');
 require_once('include/Scrape.php');
+require_once('include/diaspora.php');
 
 function item_post(&$a) {
 
@@ -900,7 +901,7 @@ function item_post(&$a) {
 
 
 		// Store the comment signature information in case we need to relay to Diaspora
-		store_diaspora_comment_sig($datarray, $author, ($self ? $user['prvkey'] : false), $parent_item, $post_id);
+		diaspora::store_comment_signature($datarray, $author, ($self ? $user['prvkey'] : false), $post_id);
 
 	} else {
 		$parent = $post_id;
@@ -1245,42 +1246,3 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
 
 	return array('replaced' => $replaced, 'contact' => $r[0]);
 }
-
-
-function store_diaspora_comment_sig($datarray, $author, $uprvkey, $parent_item, $post_id) {
-	// We won't be able to sign Diaspora comments for authenticated visitors - we don't have their private key
-
-	$enabled = intval(get_config('system','diaspora_enabled'));
-	if(! $enabled) {
-		logger('mod_item: diaspora support disabled, not storing comment signature', LOGGER_DEBUG);
-		return;
-	}
-
-
-	logger('mod_item: storing diaspora comment signature');
-
-	require_once('include/bb2diaspora.php');
-	$signed_body = html_entity_decode(bb2diaspora($datarray['body']));
-
-	// Only works for NETWORK_DFRN
-	$contact_baseurl_start = strpos($author['url'],'://') + 3;
-	$contact_baseurl_length = strpos($author['url'],'/profile') - $contact_baseurl_start;
-	$contact_baseurl = substr($author['url'], $contact_baseurl_start, $contact_baseurl_length);
-	$diaspora_handle = $author['nick'] . '@' . $contact_baseurl;
-
-	$signed_text = $datarray['guid'] . ';' . $parent_item['guid'] . ';' . $signed_body . ';' . $diaspora_handle;
-
-	if( $uprvkey !== false )
-		$authorsig = rsa_sign($signed_text,$uprvkey,'sha256');
-	else
-		$authorsig = '';
-
-	q("insert into sign (`iid`,`signed_text`,`signature`,`signer`) values (%d,'%s','%s','%s') ",
-		intval($post_id),
-		dbesc($signed_text),
-		dbesc(base64_encode($authorsig)),
-		dbesc($diaspora_handle)
-	);
-
-	return;
-}

From 186eaf1264320de3e5604d09b7ae7818ba5c4465 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 20 Mar 2016 10:30:06 +0100
Subject: [PATCH 217/273] Take the second largest picture as preview - not the
 smallest one

---
 mod/fbrowser.php | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/mod/fbrowser.php b/mod/fbrowser.php
index 0a2a7dead5..5836efbe52 100644
--- a/mod/fbrowser.php
+++ b/mod/fbrowser.php
@@ -74,10 +74,18 @@ function fbrowser_content($a){
 					$filename_e = $rr['filename'];
 				}
 
+				// Take the second largest picture as preview
+				$p = q("SELECT `scale` FROM `photo` WHERE `resource-id` = '%s' AND `scale` > %d ORDER BY `resource-id`, `scale` LIMIT 1",
+					dbesc($rr['resource-id']), intval($rr['hiq']));
+				if ($p)
+					$scale = $p[0]["scale"];
+				else
+					$scale = $rr['loq'];
+
 				return array(
 					$a->get_baseurl() . '/photos/' . $a->user['nickname'] . '/image/' . $rr['resource-id'],
 					$filename_e,
-					$a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $rr['loq'] . '.'. $ext
+					$a->get_baseurl() . '/photo/' . $rr['resource-id'] . '-' . $scale . '.'. $ext
 				);
 			}
 			$files = array_map("_map_files1", $r);

From 8f00836ffb47758fa16101cafeb1a03d13d88de4 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 20 Mar 2016 15:01:50 +0100
Subject: [PATCH 218/273] Add the guid to items that we create locally

---
 include/like.php     | 1 +
 mod/dfrn_confirm.php | 3 ++-
 mod/mood.php         | 2 +-
 mod/photos.php       | 5 +++--
 mod/poke.php         | 1 +
 mod/profiles.php     | 2 ++
 mod/subthread.php    | 5 +++--
 mod/tagger.php       | 5 +++--
 8 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/include/like.php b/include/like.php
index 646e0727be..d852cc3b31 100644
--- a/include/like.php
+++ b/include/like.php
@@ -196,6 +196,7 @@ EOT;
 
 	$arr = array();
 
+	$arr['guid'] = get_guid(32);
 	$arr['uri'] = $uri;
 	$arr['uid'] = $owner_uid;
 	$arr['contact-id'] = $contact['id'];
diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php
index 68950ec285..aed9809ca2 100644
--- a/mod/dfrn_confirm.php
+++ b/mod/dfrn_confirm.php
@@ -448,6 +448,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
 				if(count($self)) {
 
 					$arr = array();
+					$arr['guid'] = get_guid(32);
 					$arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), $uid);
 					$arr['uid'] = $uid;
 					$arr['contact-id'] = $self[0]['id'];
@@ -466,7 +467,7 @@ function dfrn_confirm_post(&$a,$handsfree = null) {
 					$BPhoto = '[url=' . $contact['url'] . ']' . '[img]' . $contact['thumb'] . '[/img][/url]';
 
 					$arr['verb'] = ACTIVITY_FRIEND;
-				    $arr['object-type'] = ACTIVITY_OBJ_PERSON;
+					$arr['object-type'] = ACTIVITY_OBJ_PERSON;
 					$arr['body'] =  sprintf( t('%1$s is now friends with %2$s'), $A, $B)."\n\n\n".$BPhoto;
 
 					$arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $contact['name'] . '</title>'
diff --git a/mod/mood.php b/mod/mood.php
index eee11e20c5..5e6ca0fcfc 100644
--- a/mod/mood.php
+++ b/mod/mood.php
@@ -62,7 +62,7 @@ function mood_init(&$a) {
 	$action = sprintf( t('%1$s is currently %2$s'), '[url=' . $poster['url'] . ']' . $poster['name'] . '[/url]' , $verbs[$verb]); 
 
 	$arr = array();
-
+	$arr['guid']          = get_guid(32);
 	$arr['uid']           = $uid;
 	$arr['uri']           = $uri;
 	$arr['parent-uri']    = (($parent_uri) ? $parent_uri : $uri);
diff --git a/mod/photos.php b/mod/photos.php
index 2257a96653..4761b627d8 100644
--- a/mod/photos.php
+++ b/mod/photos.php
@@ -488,7 +488,7 @@ function photos_post(&$a) {
 			$uri = item_new_uri($a->get_hostname(),$page_owner_uid);
 
 			$arr = array();
-
+			$arr['guid']          = get_guid(32);
 			$arr['uid']           = $page_owner_uid;
 			$arr['uri']           = $uri;
 			$arr['parent-uri']    = $uri;
@@ -677,7 +677,7 @@ function photos_post(&$a) {
 					$uri = item_new_uri($a->get_hostname(),$page_owner_uid);
 
 					$arr = array();
-
+					$arr['guid']          = get_guid(32);
 					$arr['uid']           = $page_owner_uid;
 					$arr['uri']           = $uri;
 					$arr['parent-uri']    = $uri;
@@ -904,6 +904,7 @@ function photos_post(&$a) {
 	if($lat && $lon)
 		$arr['coord'] = $lat . ' ' . $lon;
 
+	$arr['guid']          = get_guid(32);
 	$arr['uid']           = $page_owner_uid;
 	$arr['uri']           = $uri;
 	$arr['parent-uri']    = $uri;
diff --git a/mod/poke.php b/mod/poke.php
index 45a577cda6..4a643435be 100644
--- a/mod/poke.php
+++ b/mod/poke.php
@@ -91,6 +91,7 @@ function poke_init(&$a) {
 
 	$arr = array();
 
+	$arr['guid']          = get_guid(32);
 	$arr['uid']           = $uid;
 	$arr['uri']           = $uri;
 	$arr['parent-uri']    = (($parent_uri) ? $parent_uri : $uri);
diff --git a/mod/profiles.php b/mod/profiles.php
index 0b8261422f..39382fbdd5 100644
--- a/mod/profiles.php
+++ b/mod/profiles.php
@@ -526,6 +526,8 @@ function profile_activity($changed, $value) {
 		return;
 
 	$arr = array();
+
+	$arr['guid'] = get_guid(32);
 	$arr['uri'] = $arr['parent-uri'] = item_new_uri($a->get_hostname(), local_user());
 	$arr['uid'] = local_user();
 	$arr['contact-id'] = $self[0]['id'];
diff --git a/mod/subthread.php b/mod/subthread.php
index 1486a33b42..33cf7489c1 100644
--- a/mod/subthread.php
+++ b/mod/subthread.php
@@ -103,10 +103,11 @@ EOT;
 	$bodyverb = t('%1$s is following %2$s\'s %3$s');
 
 	if(! isset($bodyverb))
-			return; 
+			return;
 
 	$arr = array();
 
+	$arr['guid'] = get_guid(32);
 	$arr['uri'] = $uri;
 	$arr['uid'] = $owner_uid;
 	$arr['contact-id'] = $contact['id'];
@@ -123,7 +124,7 @@ EOT;
 	$arr['author-name'] = $contact['name'];
 	$arr['author-link'] = $contact['url'];
 	$arr['author-avatar'] = $contact['thumb'];
-	
+
 	$ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
 	$alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]';
 	$plink = '[url=' . $a->get_baseurl() . '/display/' . $owner['nickname'] . '/' . $item['id'] . ']' . $post_type . '[/url]';
diff --git a/mod/tagger.php b/mod/tagger.php
index 2c469a58bb..26166a3cc0 100644
--- a/mod/tagger.php
+++ b/mod/tagger.php
@@ -95,12 +95,13 @@ EOT;
 	$bodyverb = t('%1$s tagged %2$s\'s %3$s with %4$s');
 
 	if(! isset($bodyverb))
-			return; 
+			return;
 
 	$termlink = html_entity_decode('&#x2317;') . '[url=' . $a->get_baseurl() . '/search?tag=' . urlencode($term) . ']'. $term . '[/url]';
 
 	$arr = array();
 
+	$arr['guid'] = get_guid(32);
 	$arr['uri'] = $uri;
 	$arr['uid'] = $owner_uid;
 	$arr['contact-id'] = $contact['id'];
@@ -115,7 +116,7 @@ EOT;
 	$arr['author-name'] = $contact['name'];
 	$arr['author-link'] = $contact['url'];
 	$arr['author-avatar'] = $contact['thumb'];
-	
+
 	$ulink = '[url=' . $contact['url'] . ']' . $contact['name'] . '[/url]';
 	$alink = '[url=' . $item['author-link'] . ']' . $item['author-name'] . '[/url]';
 	$plink = '[url=' . $item['plink'] . ']' . $post_type . '[/url]';

From 77ed71e2e07ebbea9295308ba02fbc7e75ff927d Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 20 Mar 2016 15:53:37 +0100
Subject: [PATCH 219/273] DFRN: Remote tagging works now

---
 include/dfrn.php | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/include/dfrn.php b/include/dfrn.php
index 1c5ac2b012..d96805a56b 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -85,7 +85,7 @@ class dfrn {
 					$converse = true;
 				if($a->argv[$x] == 'starred')
 					$starred = true;
-				if($a->argv[$x] === 'category' && $a->argc > ($x + 1) && strlen($a->argv[$x+1]))
+				if($a->argv[$x] == 'category' && $a->argc > ($x + 1) && strlen($a->argv[$x+1]))
 					$category = $a->argv[$x+1];
 			}
 		}
@@ -244,7 +244,7 @@ class dfrn {
 		foreach($items as $item) {
 
 			// prevent private email from leaking.
-			if($item['network'] === NETWORK_MAIL)
+			if($item['network'] == NETWORK_MAIL)
 				continue;
 
 			// public feeds get html, our own nodes use bbcode
@@ -628,7 +628,7 @@ class dfrn {
 			if($r->title)
 				xml_add_element($doc, $entry, "title", $r->title);
 			if($r->link) {
-				if(substr($r->link,0,1) === '<') {
+				if(substr($r->link,0,1) == '<') {
 					if(strstr($r->link,'&') && (! strstr($r->link,'&amp;')))
 						$r->link = str_replace('&','&amp;', $r->link);
 
@@ -759,7 +759,7 @@ class dfrn {
 
 		// The "content" field is not read by the receiver. We could remove it when the type is "text"
 		// We keep it at the moment, maybe there is some old version that doesn't read "dfrn:env"
-		xml_add_element($doc, $entry, "content", (($type === 'html') ? $htmlbody : $body), array("type" => $type));
+		xml_add_element($doc, $entry, "content", (($type == 'html') ? $htmlbody : $body), array("type" => $type));
 
 		// We save this value in "plink". Maybe we should read it from there as well?
 		xml_add_element($doc, $entry, "link", "", array("rel" => "alternate", "type" => "text/html",
@@ -1773,6 +1773,9 @@ class dfrn {
 	 * @return bool Should the processing of the entries be continued?
 	 */
 	private function process_verbs($entrytype, $importer, &$item, &$is_like) {
+
+		logger("Process verb ".$item["verb"]." and object-type ".$item["object-type"]." for entrytype ".$entrytype, LOGGER_DEBUG);
+
 		if (($entrytype == DFRN_TOP_LEVEL)) {
 			// The filling of the the "contact" variable is done for legcy reasons
 			// The functions below are partly used by ostatus.php as well - where we have this variable
@@ -1803,11 +1806,11 @@ class dfrn {
 				return false;
 			}
 		} else {
-			if(($item["verb"] === ACTIVITY_LIKE)
-				|| ($item["verb"] === ACTIVITY_DISLIKE)
-				|| ($item["verb"] === ACTIVITY_ATTEND)
-				|| ($item["verb"] === ACTIVITY_ATTENDNO)
-				|| ($item["verb"] === ACTIVITY_ATTENDMAYBE)) {
+			if(($item["verb"] == ACTIVITY_LIKE)
+				|| ($item["verb"] == ACTIVITY_DISLIKE)
+				|| ($item["verb"] == ACTIVITY_ATTEND)
+				|| ($item["verb"] == ACTIVITY_ATTENDNO)
+				|| ($item["verb"] == ACTIVITY_ATTENDMAYBE)) {
 				$is_like = true;
 				$item["type"] = "activity";
 				$item["gravity"] = GRAVITY_LIKE;
@@ -1833,7 +1836,7 @@ class dfrn {
 			} else
 				$is_like = false;
 
-			if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
+			if(($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) {
 
 				$xo = parse_xml_string($item["object"],false);
 				$xt = parse_xml_string($item["target"],false);
@@ -2261,15 +2264,17 @@ class dfrn {
 			else
 				return;
 
-			if($item["object-type"] === ACTIVITY_OBJ_EVENT) {
+			if($item["object-type"] == ACTIVITY_OBJ_EVENT) {
 				logger("Deleting event ".$item["event-id"], LOGGER_DEBUG);
 				event_delete($item["event-id"]);
 			}
 
-			if(($item["verb"] === ACTIVITY_TAG) && ($item["object-type"] === ACTIVITY_OBJ_TAGTERM)) {
+			if(($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) {
+
 				$xo = parse_xml_string($item["object"],false);
 				$xt = parse_xml_string($item["target"],false);
-				if($xt->type === ACTIVITY_OBJ_NOTE) {
+
+				if($xt->type == ACTIVITY_OBJ_NOTE) {
 					$i = q("SELECT `id`, `contact-id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1",
 						dbesc($xt->id),
 						intval($importer["importer_uid"])

From 5a04ba84164070855c26737640f41ed3cb6dcf11 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 20 Mar 2016 16:16:15 +0100
Subject: [PATCH 220/273] Added documentation

---
 include/xml.php | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/include/xml.php b/include/xml.php
index c74c23c473..2aed3fe8ed 100644
--- a/include/xml.php
+++ b/include/xml.php
@@ -4,6 +4,16 @@
  *
  */
 class xml {
+	/**
+	 * @brief Creates an XML structure out of a given array
+	 *
+	 * @param array $array The array of the XML structure that will be generated
+	 * @param object $xml The createdXML will be returned by reference
+	 * @param bool $remove_header Should the XML header be removed or not?
+	 * @param array $namespaces List of namespaces
+	 *
+	 * @return string The created XML
+	 */
 	function from_array($array, &$xml, $remove_header = false, $namespaces = array(), $root = true) {
 
 		if ($root) {
@@ -60,6 +70,13 @@ class xml {
 		}
 	}
 
+	/**
+	 * @brief Copies an XML object
+	 *
+	 * @param object $source The XML source
+	 * @param object $target The XML target
+	 * @param string $elementname Name of the XML element of the target
+	 */
 	function copy(&$source, &$target, $elementname) {
 		if (count($source->children()) == 0)
 			$target->addChild($elementname, xmlify($source));

From c284ab5eff79fa2a87f7214fe433001712db08c9 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 21 Mar 2016 19:58:45 +0100
Subject: [PATCH 221/273] Some more documentation - to make @rabuzarus happy

---
 include/diaspora.php | 19 ++++++-------------
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 59bad946e2..6f30ab9247 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -116,7 +116,7 @@ class diaspora {
 	 * @param string $handle The handle of the signature owner
 	 * @param integer $level This value is only set inside this function to avoid endless loops
 	 *
-	 * @return the repaired signature
+	 * @return string the repaired signature
 	 */
 	function repair_signature($signature, $handle = "", $level = 1) {
 
@@ -179,16 +179,6 @@ class diaspora {
 
 			$decrypted = pkcs5_unpad($decrypted);
 
-			/**
-			 * $decrypted now contains something like
-			 *
-			 *  <decrypted_header>
-			 *     <iv>8e+G2+ET8l5BPuW0sVTnQw==</iv>
-			 *     <aes_key>UvSMb4puPeB14STkcDWq+4QE302Edu15oaprAQSkLKU=</aes_key>
-			 *     <author_id>galaxor@diaspora.priateship.org</author_id>
-			 *  </decrypted_header>
-			 */
-
 			logger('decrypted: '.$decrypted, LOGGER_DEBUG);
 			$idom = parse_xml_string($decrypted,false);
 
@@ -795,7 +785,7 @@ class diaspora {
 	}
 
 	/**
-	 * @brief sub function of "fetch_guid"
+	 * @brief sub function of "fetch_guid" which checks for links in messages
 	 *
 	 * @param array $match array containing a link that has to be checked for a message link
 	 * @param array $item The item array
@@ -838,7 +828,10 @@ class diaspora {
 	 * @param string $server The url of the server
 	 * @param int $level Endless loop prevention
 	 *
-	 * @return array of message, author and public key
+	 * @return array
+	 *      'message' => The message XML
+	 *      'author' => The author handle
+	 *      'key' => The public key of the author
 	 */
 	private function message($guid, $server, $level = 0) {
 

From 90d4b9342452345671672ed301c66e842a74aa24 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 22 Mar 2016 07:13:56 +0100
Subject: [PATCH 222/273] Avoid an empty handle

---
 include/diaspora.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 6f30ab9247..632e3782c7 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -647,7 +647,7 @@ class diaspora {
 
 			if($contact['addr'] != "")
 				$handle = $contact['addr'];
-			elseif(($contact['network'] === NETWORK_DFRN) || ($contact['self'] == 1)) {
+			else {
 				$baseurl_start = strpos($contact['url'],'://') + 3;
 				$baseurl_length = strpos($contact['url'],'/profile') - $baseurl_start; // allows installations in a subdirectory--not sure how Diaspora will handle
 				$baseurl = substr($contact['url'], $baseurl_start, $baseurl_length);

From 62103fe5f42363d14e33b127c5ccaf2ba176d6ca Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 22 Mar 2016 23:00:42 +0100
Subject: [PATCH 223/273] Reshare of reshares now work.

---
 include/diaspora.php | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 632e3782c7..289f717708 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -1853,10 +1853,14 @@ class diaspora {
 			logger("reshared message ".$guid." already exists on system.");
 
 			// Maybe it is already a reshared item?
-			// Then refetch the content, since there can be many side effects with reshared posts from other networks or reshares from reshares
-			if (self::is_reshare($r[0]["body"], false))
+			// Then refetch the content, if it is a reshare from a reshare.
+			// If it is a reshared post from another network then reformat to avoid display problems with two share elements
+			if (self::is_reshare($r[0]["body"], true))
 				$r = array();
-			else
+			elseif (self::is_reshare($r[0]["body"], false)) {
+				$r[0]["body"] = diaspora2bb(bb2diaspora($r[0]["body"]));
+				return $r[0];
+			} else
 				return $r[0];
 		}
 

From 791ce24cd52d118391fd9c6a1b0a2a10efb6240f Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 22 Mar 2016 23:24:07 +0100
Subject: [PATCH 224/273] Bugfix: Avoid warning with non object OEmbed data

---
 include/bbcode.php | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/bbcode.php b/include/bbcode.php
index c1156e3afe..8545b2ff82 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -311,6 +311,9 @@ function tryoembed($match){
 
 	$o = oembed_fetch_url($url);
 
+	if (!is_object($o))
+		return $match[0];
+
 	if (isset($match[2]))
 		$o->title = $match[2];
 

From 28dfaa694c2203163eee6d61b724dede4590c099 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 23 Mar 2016 07:36:17 +0100
Subject: [PATCH 225/273] Add OEmbed data to the body of reshares

---
 include/diaspora.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/diaspora.php b/include/diaspora.php
index 289f717708..b339e73157 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -1859,6 +1859,10 @@ class diaspora {
 				$r = array();
 			elseif (self::is_reshare($r[0]["body"], false)) {
 				$r[0]["body"] = diaspora2bb(bb2diaspora($r[0]["body"]));
+
+				// Add OEmbed and other information to the body
+				$r[0]["body"] = add_page_info_to_body($r[0]["body"], false, true);
+
 				return $r[0];
 			} else
 				return $r[0];

From ac35f8c756a85cd36c8c2c2df7b7306056443f49 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 23 Mar 2016 09:22:59 +0100
Subject: [PATCH 226/273] If the message already exists then the message id
 should be returned

---
 include/diaspora.php | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index b339e73157..308a799118 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -755,8 +755,8 @@ class diaspora {
 	 *
 	 * @param int $uid The user id
 	 * @param string $guid The guid of the message
-	 *
-	 * @return bool "true" if the message already was stored into the system
+y	 *
+	 * @return int|bool message id if the message already was stored into the system - or false.
 	 */
 	private function message_exists($uid, $guid) {
 		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
@@ -766,7 +766,7 @@ class diaspora {
 
 		if($r) {
 			logger("message ".$guid." already exists for user ".$uid);
-			return true;
+			return $r[0]["id"];
 		}
 
 		return false;
@@ -1028,8 +1028,9 @@ class diaspora {
 		if (!$contact)
 			return false;
 
-		if (self::message_exists($importer["uid"], $guid))
-			return false;
+		$message_id = self::message_exists($importer["uid"], $guid);
+		if ($message_id)
+			return $message_id;
 
 		$parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact);
 		if (!$parent_item)
@@ -1357,8 +1358,9 @@ class diaspora {
 		if (!$contact)
 			return false;
 
-		if (self::message_exists($importer["uid"], $guid))
-			return false;
+		$message_id = self::message_exists($importer["uid"], $guid);
+		if ($message_id)
+			return $message_id;
 
 		$parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact);
 		if (!$parent_item)
@@ -1926,8 +1928,9 @@ class diaspora {
 		if (!$contact)
 			return false;
 
-		if (self::message_exists($importer["uid"], $guid))
-			return false;
+		$message_id = self::message_exists($importer["uid"], $guid);
+		if ($message_id)
+			return $message_id;
 
 		$original_item = self::original_item($root_guid, $root_author, $author);
 		if (!$original_item)
@@ -2110,8 +2113,9 @@ class diaspora {
 		if (!$contact)
 			return false;
 
-		if (self::message_exists($importer["uid"], $guid))
-			return false;
+		$message_id = self::message_exists($importer["uid"], $guid);
+		if ($message_id)
+			return $message_id;
 
 		$address = array();
 		if ($data->location)

From 799ff777977cb46485c46a659848f92772aadf77 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 23 Mar 2016 10:24:01 +0100
Subject: [PATCH 227/273] API: Support for the conversation api call from GNU
 Social

---
 doc/api.md      | 12 ++++++++++++
 include/api.php |  1 +
 2 files changed, 13 insertions(+)

diff --git a/doc/api.md b/doc/api.md
index bf287585d3..7d6f440c58 100644
--- a/doc/api.md
+++ b/doc/api.md
@@ -388,6 +388,18 @@ Friendica doesn't allow showing friends of other users.
 ---
 ### statusnet/config (*)
 
+---
+### statusnet/conversation (*; AUTH)
+It shows all direct answers (excluding the original post) to a given id.
+
+#### Parameter
+* id: id of the post
+* count: Items per page (default: 20)
+* page: page number
+* since_id: minimal id
+* max_id: maximum id
+* include_entities: "true" shows entities for pictures and links (Default: false)
+
 ---
 ### statusnet/version (*)
 
diff --git a/include/api.php b/include/api.php
index 699b066d25..a494e3cdd9 100644
--- a/include/api.php
+++ b/include/api.php
@@ -1550,6 +1550,7 @@
 		return api_apply_template("timeline", $type, $data);
 	}
 	api_register_func('api/conversation/show','api_conversation_show', true);
+	api_register_func('api/statusnet/conversation','api_conversation_show', true);
 
 
 	/**

From 7aae852fe0285ac7dd88685f92715691a099190d Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 23 Mar 2016 22:12:08 +0100
Subject: [PATCH 228/273] Some more code cleaning

---
 include/diaspora.php | 35 ++++++++++++++++++++++++++---------
 include/xml.php      |  1 +
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 308a799118..a608516622 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -1694,11 +1694,8 @@ y	 *
 				$BPhoto = "[url=".$contact["url"]."][img]".$contact["thumb"]."[/img][/url]";
 				$arr["body"] = sprintf(t("%1$s is now friends with %2$s"), $A, $B)."\n\n\n".$Bphoto;
 
-				$arr["object"] = "<object><type>".ACTIVITY_OBJ_PERSON."</type><title>".$contact["name"]."</title>"
-					."<id>".$contact["url"]."/".$contact["name"]."</id>";
-				$arr["object"] .= "<link>".xmlify('<link rel="alternate" type="text/html" href="'.$contact["url"].'" />'."\n");
-				$arr["object"] .= xmlify('<link rel="photo" type="image/jpeg" href="'.$contact["thumb"].'" />'."\n");
-				$arr["object"] .= "</link></object>\n";
+				$arr["object"] = self::construct_new_friend_object($contact);
+
 				$arr["last-child"] = 1;
 
 				$arr["allow_cid"] = $user[0]["allow_cid"];
@@ -1713,6 +1710,26 @@ y	 *
 		}
 	}
 
+	/**
+	 * @brief Creates a XML object for a "new friend" message
+	 *
+	 * @param array $contact Array of the contact
+	 *
+	 * @return string The XML
+	 */
+        private function construct_new_friend_object($contact) {
+                $objtype = ACTIVITY_OBJ_PERSON;
+                $link = '<link rel="alternate" type="text/html" href="'.$contact["url"].'" />'."\n".
+                        '<link rel="photo" type="image/jpeg" href="'.$contact["thumb"].'" />'."\n";
+
+                $xmldata = array("object" => array("type" => $objtype,
+                                                "title" => $contact["name"],
+                                                "id" => $contact["url"]."/".$contact["name"],
+                                                "link" => $link));
+
+                return xml::from_array($xmldata, $xml, true);
+        }
+
 	/**
 	 * @brief Processes incoming sharing notification
 	 *
@@ -2184,9 +2201,9 @@ y	 *
 		return $message_id;
 	}
 
-	/******************************************************************************************
+	/* ************************************************************************************** *
 	 * Here are all the functions that are needed to transmit data with the Diaspora protocol *
-	 ******************************************************************************************/
+	 * ************************************************************************************** */
 
 	/**
 	 * @brief returnes the handle of a contact
@@ -3071,7 +3088,7 @@ y	 *
 	 *
 	 * @return bool Success
 	 */
-	function store_like_signature($contact, $post_id) {
+	public static function store_like_signature($contact, $post_id) {
 
 		$enabled = intval(get_config('system','diaspora_enabled'));
 		if (!$enabled) {
@@ -3135,7 +3152,7 @@ y	 *
 	 *
 	 * @return bool Success
 	 */
-	function store_comment_signature($item, $contact, $uprvkey, $message_id) {
+	public static function store_comment_signature($item, $contact, $uprvkey, $message_id) {
 
 		if ($uprvkey == "") {
 			logger('No private key, so not storing comment signature', LOGGER_DEBUG);
diff --git a/include/xml.php b/include/xml.php
index 2aed3fe8ed..47a2f6f7d5 100644
--- a/include/xml.php
+++ b/include/xml.php
@@ -1,5 +1,6 @@
 <?php
 /**
+ * @file include/xml.php
  * @brief This class contain functions to work with XML data
  *
  */

From 24afcdd5dd6354fb34a37aec82b6144f4a76840c Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 24 Mar 2016 08:35:06 +0100
Subject: [PATCH 229/273] Scrape: Always take the first alias

---
 include/Scrape.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/Scrape.php b/include/Scrape.php
index e8e9a97a16..03d21047e7 100644
--- a/include/Scrape.php
+++ b/include/Scrape.php
@@ -444,7 +444,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 				if($link['@attributes']['rel'] === 'alias') {
 					if(strpos($link['@attributes']['href'],'@') === false) {
 						if(isset($profile)) {
-							if($link['@attributes']['href'] !== $profile)
+							if(($link['@attributes']['href'] !== $profile) AND ($alias == ""))
 								$alias = unamp($link['@attributes']['href']);
 						}
 						else

From 7bf079d858db1604b9c2a34a414756c1b70066de Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 24 Mar 2016 15:59:53 +0100
Subject: [PATCH 230/273] Some more documentation - again.

---
 include/diaspora.php | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index a608516622..c5d6943e59 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -755,7 +755,7 @@ class diaspora {
 	 *
 	 * @param int $uid The user id
 	 * @param string $guid The guid of the message
-y	 *
+	 *
 	 * @return int|bool message id if the message already was stored into the system - or false.
 	 */
 	private function message_exists($uid, $guid) {
@@ -2143,6 +2143,7 @@ y	 *
 
 		$datarray = array();
 
+		// Attach embedded pictures to the body
 		if ($data->photo) {
 			foreach ($data->photo AS $photo)
 				$body = "[img]".unxmlify($photo->remote_photo_path).

From 7e7cac19f62cef5fe52660a9312ac01a7d3f74a2 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 24 Mar 2016 21:32:55 +0100
Subject: [PATCH 231/273] Avoid a guid whith spaces.

---
 include/diaspora.php | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index c5d6943e59..32190bc7d6 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -2611,8 +2611,9 @@ class diaspora {
 			$link = $matches[1];
 
 		$ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link);
-		if (($ret["root_guid"] == $link) OR ($ret["root_guid"] == ""))
+		if (($ret["root_guid"] == $link) OR (trim($ret["root_guid"]) == ""))
 			return(false);
+
 		return($ret);
 	}
 

From 16ef9f49408050aab2b6a180f7df9103145f0c03 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 25 Mar 2016 00:49:18 +0100
Subject: [PATCH 232/273] Support for the new contact request data type

---
 include/diaspora.php | 50 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 38 insertions(+), 12 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 32190bc7d6..277eb6f8e8 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -339,6 +339,9 @@ class diaspora {
 			case "comment":
 				return self::receive_comment($importer, $sender, $fields, $msg["message"]);
 
+			case "contact":
+				return self::receive_contact_request($importer, $fields);
+
 			case "conversation":
 				return self::receive_conversation($importer, $msg, $fields);
 
@@ -360,9 +363,6 @@ class diaspora {
 			case "profile":
 				return self::receive_profile($importer, $fields);
 
-			case "request":
-				return self::receive_request($importer, $fields);
-
 			case "reshare":
 				return self::receive_reshare($importer, $fields, $msg["message"]);
 
@@ -418,6 +418,9 @@ class diaspora {
 		if (in_array($type, array("signed_retraction", "relayable_retraction")))
 			$type = "retraction";
 
+		if ($type == "request")
+			$type = "contact";
+
 		$fields = new SimpleXMLElement("<".$type."/>");
 
 		$signed_data = "";
@@ -1377,7 +1380,7 @@ class diaspora {
 
 		// "positive" = "false" would be a Dislike - wich isn't currently supported by Diaspora
 		// We would accept this anyhow.
-		if ($positive === "true")
+		if ($positive == "true")
 			$verb = ACTIVITY_LIKE;
 		else
 			$verb = ACTIVITY_DISLIKE;
@@ -1738,22 +1741,43 @@ class diaspora {
 	 *
 	 * @return bool Success
 	 */
-	private function receive_request($importer, $data) {
+	private function receive_contact_request($importer, $data) {
 		$author = unxmlify($data->author);
 		$recipient = unxmlify($data->recipient);
 
 		if (!$author || !$recipient)
 			return false;
 
+		// the current protocol version doesn't know these fields
+		// That means that we will assume their existance
+		if (isset($data->following))
+			$following = (unxmlify($data->following) == "true");
+		else
+			$following = true;
+
+		if (isset($data->sharing))
+			$sharing = (unxmlify($data->sharing) == "true");
+		else
+			$sharing = true;
+
 		$contact = self::contact_by_handle($importer["uid"],$author);
 
-		if($contact) {
+		// perhaps we were already sharing with this person. Now they're sharing with us.
+		// That makes us friends.
+		if ($contact) {
+			if ($following AND $sharing) {
+				self::receive_request_make_friend($importer, $contact);
+				return true;
+			} else /// @todo Handle all possible variations of adding and retracting of permissions
+				return false;
+		}
 
-			// perhaps we were already sharing with this person. Now they're sharing with us.
-			// That makes us friends.
-
-			self::receive_request_make_friend($importer, $contact);
-			return true;
+		if (!$following AND $sharing AND in_array($importer["page-flags"], array(PAGE_SOAPBOX, PAGE_NORMAL))) {
+			logger("Author ".$author." wants to share with us - but doesn't want to listen. Request is ignored.", LOGGER_DEBUG);
+			return false;
+		} elseif (!$following AND !$sharing) {
+			logger("Author ".$author." doesn't want anything - and we don't know the author. Request is ignored.", LOGGER_DEBUG);
+			return false;
 		}
 
 		$ret = self::person_by_handle($author);
@@ -1824,8 +1848,10 @@ class diaspora {
 			// but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX
 			// we are going to change the relationship and make them a follower.
 
-			if($importer["page-flags"] == PAGE_FREELOVE)
+			if (($importer["page-flags"] == PAGE_FREELOVE) AND $sharing AND $following)
 				$new_relation = CONTACT_IS_FRIEND;
+			elseif (($importer["page-flags"] == PAGE_FREELOVE) AND $sharing)
+				$new_relation = CONTACT_IS_SHARING;
 			else
 				$new_relation = CONTACT_IS_FOLLOWER;
 

From faa9b77a90be70f76990451aff9c25fa2e05dad4 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 27 Mar 2016 23:25:32 +0200
Subject: [PATCH 233/273] Some more small documentation stuff

---
 include/diaspora.php | 4 ++--
 include/xml.php      | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 277eb6f8e8..d2a90fc983 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -118,7 +118,7 @@ class diaspora {
 	 *
 	 * @return string the repaired signature
 	 */
-	function repair_signature($signature, $handle = "", $level = 1) {
+	private function repair_signature($signature, $handle = "", $level = 1) {
 
 		if ($signature == "")
 			return ($signature);
@@ -146,7 +146,7 @@ class diaspora {
 	 * 'author' -> author diaspora handle
 	 * 'key' -> author public key (converted to pkcs#8)
 	 */
-	function decode($importer, $xml) {
+	public static function decode($importer, $xml) {
 
 		$public = false;
 		$basedom = parse_xml_string($xml);
diff --git a/include/xml.php b/include/xml.php
index 47a2f6f7d5..2bcc73b8f7 100644
--- a/include/xml.php
+++ b/include/xml.php
@@ -15,7 +15,7 @@ class xml {
 	 *
 	 * @return string The created XML
 	 */
-	function from_array($array, &$xml, $remove_header = false, $namespaces = array(), $root = true) {
+	public static function from_array($array, &$xml, $remove_header = false, $namespaces = array(), $root = true) {
 
 		if ($root) {
 			foreach($array as $key => $value) {
@@ -78,7 +78,7 @@ class xml {
 	 * @param object $target The XML target
 	 * @param string $elementname Name of the XML element of the target
 	 */
-	function copy(&$source, &$target, $elementname) {
+	public static function copy(&$source, &$target, $elementname) {
 		if (count($source->children()) == 0)
 			$target->addChild($elementname, xmlify($source));
 		else {

From 7e711d9d62ff9163d7cc83e24bae556e82f7fef8 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 27 Mar 2016 23:38:35 +0200
Subject: [PATCH 234/273] And some more doc stuff

---
 include/diaspora.php | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index d2a90fc983..3795def479 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -737,7 +737,7 @@ class diaspora {
 	 * @param string $handle The checked handle in the format user@domain.tld
 	 * @param bool $is_comment Is the check for a comment?
 	 *
-	 * @return bool is posting allowed?
+	 * @return array The contact data
 	 */
 	private function allowed_contact_by_handle($importer, $handle, $is_comment = false) {
 		$contact = self::contact_by_handle($importer["uid"], $handle);
@@ -931,7 +931,9 @@ class diaspora {
 	 * @param array $person The record of the person
 	 * @param int $uid The user id
 	 *
-	 * @return array of contact id and network type
+	 * @return array
+	 *      'cid' => contact id
+	 *      'network' => network type
 	 */
 	private function author_contact_by_url($contact, $person, $uid) {
 

From b6121a0009340a15e7d0317803707d4c11197a6d Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 28 Mar 2016 00:06:46 +0200
Subject: [PATCH 235/273] And wow ... some more documentation

---
 include/xml.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/xml.php b/include/xml.php
index 2bcc73b8f7..aa74cf65cf 100644
--- a/include/xml.php
+++ b/include/xml.php
@@ -12,6 +12,7 @@ class xml {
 	 * @param object $xml The createdXML will be returned by reference
 	 * @param bool $remove_header Should the XML header be removed or not?
 	 * @param array $namespaces List of namespaces
+	 * @param bool $root - interally used parameter. Mustn't be used from outside.
 	 *
 	 * @return string The created XML
 	 */

From 3c24f43011b3f00bf1ee6e494f2af2d06cd68b51 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 28 Mar 2016 22:21:14 +0200
Subject: [PATCH 236/273] Guesss what? Yeah, some documentation

---
 util/createdoxygen.php | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 mode change 100755 => 100644 util/createdoxygen.php

diff --git a/util/createdoxygen.php b/util/createdoxygen.php
old mode 100755
new mode 100644
index d48114b671..163c94bb97
--- a/util/createdoxygen.php
+++ b/util/createdoxygen.php
@@ -1,5 +1,10 @@
 #!/usr/bin/php
 <?php
+/**
+ * @file util/createdoxygen.php
+ * @brief Adds a doxygen header to functions
+ */
+
 if (count($_SERVER["argv"]) < 2)
 	die("usage: createdoxygen.php file\n");
 
@@ -45,6 +50,13 @@ foreach ($lines AS $line) {
 	$previous = $line;
 }
 
+/**
+ * @brief Adds a doxygen header
+ *
+ * @param string $line The current line of the document
+ *
+ * @return string added doxygen header
+ */
 function add_documentation($line) {
 
 	$trimmed = ltrim($line);

From f80f4f6a97cea623ee53a596069a96fbcf147c8d Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Mon, 28 Mar 2016 22:35:11 +0200
Subject: [PATCH 237/273] Some changed doxygen header stuff

---
 include/diaspora.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/diaspora.php b/include/diaspora.php
index 3795def479..e3a3dcd78c 100644
--- a/include/diaspora.php
+++ b/include/diaspora.php
@@ -277,7 +277,7 @@ class diaspora {
 	 *
 	 * @param array $msg The post that will be dispatched
 	 *
-	 * @return bool Was the message accepted?
+	 * @return int The message id of the generated message, "true" or "false" if there was an error
 	 */
 	public static function dispatch_public($msg) {
 
@@ -289,7 +289,7 @@ class diaspora {
 
 		// Use a dummy importer to import the data for the public copy
 		$importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE);
-		$item_id = self::dispatch($importer,$msg);
+		$message_id = self::dispatch($importer,$msg);
 
 		// Now distribute it to the followers
 		$r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN
@@ -306,7 +306,7 @@ class diaspora {
 		} else
 			logger("No subscribers for ".$msg["author"]." ".print_r($msg, true));
 
-		return $item_id;
+		return $message_id;
 	}
 
 	/**
@@ -315,7 +315,7 @@ class diaspora {
 	 * @param array $importer Array of the importer user
 	 * @param array $msg The post that will be dispatched
 	 *
-	 * @return bool Was the message accepted?
+	 * @return int The message id of the generated message, "true" or "false" if there was an error
 	 */
 	public static function dispatch($importer, $msg) {
 

From 4d668fac8b35459c7d8d3edf717632f807cc24fa Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 29 Mar 2016 17:54:36 +0200
Subject: [PATCH 238/273] Not sure if that is correct ...

---
 include/xml.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/include/xml.php b/include/xml.php
index aa74cf65cf..a454e61566 100644
--- a/include/xml.php
+++ b/include/xml.php
@@ -1,6 +1,10 @@
 <?php
 /**
  * @file include/xml.php
+ */
+
+
+/**
  * @brief This class contain functions to work with XML data
  *
  */

From b93e1d73a1a3823fbb3fd317a85be17e8fad1d3c Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 30 Mar 2016 12:43:15 +0200
Subject: [PATCH 239/273] New OStatus implementation

---
 include/items.php         |    6 +-
 include/notifier.php      |    2 +-
 include/ostatus.php       |    1 +
 include/ostatus2.php      | 1778 +++++++++++++++++++++++++++++++++++++
 include/pubsubpublish.php |    2 +-
 mod/salmon.php            |    4 +-
 6 files changed, 1786 insertions(+), 7 deletions(-)
 create mode 100644 include/ostatus2.php

diff --git a/include/items.php b/include/items.php
index f8c3149d58..233d72d133 100644
--- a/include/items.php
+++ b/include/items.php
@@ -383,9 +383,9 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
 	// Converting the plink
 	if ($arr['network'] == NETWORK_OSTATUS) {
 		if (isset($arr['plink']))
-			$arr['plink'] = ostatus_convert_href($arr['plink']);
+			$arr['plink'] = ostatus::convert_href($arr['plink']);
 		elseif (isset($arr['uri']))
-			$arr['plink'] = ostatus_convert_href($arr['uri']);
+			$arr['plink'] = ostatus::convert_href($arr['uri']);
 	}
 
 	if(x($arr, 'gravity'))
@@ -1243,7 +1243,7 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0)
 			//$tempfile = tempnam(get_temppath(), "ostatus2");
 			//file_put_contents($tempfile, $xml);
 			logger("Consume OStatus messages ", LOGGER_DEBUG);
-			ostatus_import($xml,$importer,$contact, $hub);
+			ostatus::import($xml,$importer,$contact, $hub);
 		}
 		return;
 	}
diff --git a/include/notifier.php b/include/notifier.php
index a46744f070..18a617ac2f 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -223,7 +223,7 @@ function notifier_run(&$argv, &$argc){
 
 	if(! ($mail || $fsuggest || $relocate)) {
 
-		$slap = ostatus_salmon($target_item,$owner);
+		$slap = ostatus::salmon($target_item,$owner);
 
 		require_once('include/group.php');
 
diff --git a/include/ostatus.php b/include/ostatus.php
index 5ba9f0e83c..02447e3ade 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -12,6 +12,7 @@ require_once("include/Scrape.php");
 require_once("include/follow.php");
 require_once("include/api.php");
 require_once("mod/proxy.php");
+require_once("include/ostatus2.php");
 
 define('OSTATUS_DEFAULT_POLL_INTERVAL', 30); // given in minutes
 define('OSTATUS_DEFAULT_POLL_TIMEFRAME', 1440); // given in minutes
diff --git a/include/ostatus2.php b/include/ostatus2.php
new file mode 100644
index 0000000000..53c279f254
--- /dev/null
+++ b/include/ostatus2.php
@@ -0,0 +1,1778 @@
+<?php
+require_once("include/Contact.php");
+require_once("include/threads.php");
+require_once("include/html2bbcode.php");
+require_once("include/bbcode.php");
+require_once("include/items.php");
+require_once("mod/share.php");
+require_once("include/enotify.php");
+require_once("include/socgraph.php");
+require_once("include/Photo.php");
+require_once("include/Scrape.php");
+require_once("include/follow.php");
+require_once("include/api.php");
+require_once("mod/proxy.php");
+
+class xml2 {
+	public static function create_element($doc, $element, $value = "", $attributes = array()) {
+		$element = $doc->createElement($element, xmlify($value));
+
+		foreach ($attributes AS $key => $value) {
+			$attribute = $doc->createAttribute($key);
+			$attribute->value = xmlify($value);
+			$element->appendChild($attribute);
+		}
+		return $element;
+	}
+
+	public static function add_element($doc, $parent, $element, $value = "", $attributes = array()) {
+		$element = self::create_element($doc, $element, $value, $attributes);
+		$parent->appendChild($element);
+	}
+}
+
+class ostatus {
+	const OSTATUS_DEFAULT_POLL_INTERVAL = 30; // given in minutes
+	const OSTATUS_DEFAULT_POLL_TIMEFRAME = 1440; // given in minutes
+	const OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS = 14400; // given in minutes
+
+	private function fetchauthor($xpath, $context, $importer, &$contact, $onlyfetch) {
+
+		$author = array();
+		$author["author-link"] = $xpath->evaluate('atom:author/atom:uri/text()', $context)->item(0)->nodeValue;
+		$author["author-name"] = $xpath->evaluate('atom:author/atom:name/text()', $context)->item(0)->nodeValue;
+
+		// Preserve the value
+		$authorlink = $author["author-link"];
+
+		$alternate = $xpath->query("atom:author/atom:link[@rel='alternate']", $context)->item(0)->attributes;
+		if (is_object($alternate))
+			foreach($alternate AS $attributes)
+				if ($attributes->name == "href")
+					$author["author-link"] = $attributes->textContent;
+
+		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'",
+			intval($importer["uid"]), dbesc(normalise_link($author["author-link"])),
+			dbesc(normalise_link($authorlink)), dbesc(NETWORK_STATUSNET));
+		if ($r) {
+			$contact = $r[0];
+			$author["contact-id"] = $r[0]["id"];
+		} else
+			$author["contact-id"] = $contact["id"];
+
+		$avatarlist = array();
+		$avatars = $xpath->query("atom:author/atom:link[@rel='avatar']", $context);
+		foreach($avatars AS $avatar) {
+			$href = "";
+			$width = 0;
+			foreach($avatar->attributes AS $attributes) {
+				if ($attributes->name == "href")
+					$href = $attributes->textContent;
+				if ($attributes->name == "width")
+					$width = $attributes->textContent;
+			}
+			if (($width > 0) AND ($href != ""))
+				$avatarlist[$width] = $href;
+		}
+		if (count($avatarlist) > 0) {
+			krsort($avatarlist);
+			$author["author-avatar"] = current($avatarlist);
+		}
+
+		$displayname = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue;
+		if ($displayname != "")
+			$author["author-name"] = $displayname;
+
+		$author["owner-name"] = $author["author-name"];
+		$author["owner-link"] = $author["author-link"];
+		$author["owner-avatar"] = $author["author-avatar"];
+
+		// Only update the contacts if it is an OStatus contact
+		if ($r AND !$onlyfetch AND ($contact["network"] == NETWORK_OSTATUS)) {
+			// Update contact data
+
+			$value = $xpath->query("atom:link[@rel='salmon']", $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["notify"] = $value;
+
+			$value = $xpath->evaluate('atom:author/uri/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["alias"] = $value;
+
+			$value = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["name"] = $value;
+
+			$value = $xpath->evaluate('atom:author/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["nick"] = $value;
+
+			$value = $xpath->evaluate('atom:author/poco:note/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["about"] = html2bbcode($value);
+
+			$value = $xpath->evaluate('atom:author/poco:address/poco:formatted/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["location"] = $value;
+
+			if (($contact["name"] != $r[0]["name"]) OR ($contact["nick"] != $r[0]["nick"]) OR ($contact["about"] != $r[0]["about"]) OR ($contact["location"] != $r[0]["location"])) {
+
+				logger("Update contact data for contact ".$contact["id"], LOGGER_DEBUG);
+
+				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', `name-date` = '%s' WHERE `id` = %d",
+					dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
+					dbesc(datetime_convert()), intval($contact["id"]));
+
+				poco_check($contact["url"], $contact["name"], $contact["network"], $author["author-avatar"], $contact["about"], $contact["location"],
+							"", "", "", datetime_convert(), 2, $contact["id"], $contact["uid"]);
+			}
+
+			if (isset($author["author-avatar"]) AND ($author["author-avatar"] != $r[0]['avatar'])) {
+				logger("Update profile picture for contact ".$contact["id"], LOGGER_DEBUG);
+
+				update_contact_avatar($author["author-avatar"], $importer["uid"], $contact["id"]);
+			}
+
+			$contact["generation"] = 2;
+			$contact["photo"] = $author["author-avatar"];
+			update_gcontact($contact);
+		}
+
+		return($author);
+	}
+
+	public static function salmon_author($xml, $importer) {
+
+		if ($xml == "")
+			return;
+
+		$doc = new DOMDocument();
+		@$doc->loadXML($xml);
+
+		$xpath = new DomXPath($doc);
+		$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
+		$xpath->registerNamespace('thr', NAMESPACE_THREAD);
+		$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
+		$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
+		$xpath->registerNamespace('media', NAMESPACE_MEDIA);
+		$xpath->registerNamespace('poco', NAMESPACE_POCO);
+		$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
+		$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
+
+		$entries = $xpath->query('/atom:entry');
+
+		foreach ($entries AS $entry) {
+			// fetch the author
+			$author = self::fetchauthor($xpath, $entry, $importer, $contact, true);
+			return $author;
+		}
+	}
+
+	public static function import($xml,$importer,&$contact, &$hub) {
+
+		logger("Import OStatus message", LOGGER_DEBUG);
+
+		if ($xml == "")
+			return;
+
+		//$tempfile = tempnam(get_temppath(), "import");
+		//file_put_contents($tempfile, $xml);
+
+		$doc = new DOMDocument();
+		@$doc->loadXML($xml);
+
+		$xpath = new DomXPath($doc);
+		$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
+		$xpath->registerNamespace('thr', NAMESPACE_THREAD);
+		$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
+		$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
+		$xpath->registerNamespace('media', NAMESPACE_MEDIA);
+		$xpath->registerNamespace('poco', NAMESPACE_POCO);
+		$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
+		$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
+
+		$gub = "";
+		$hub_attributes = $xpath->query("/atom:feed/atom:link[@rel='hub']")->item(0)->attributes;
+		if (is_object($hub_attributes))
+			foreach($hub_attributes AS $hub_attribute)
+				if ($hub_attribute->name == "href") {
+					$hub = $hub_attribute->textContent;
+					logger("Found hub ".$hub, LOGGER_DEBUG);
+				}
+
+		$header = array();
+		$header["uid"] = $importer["uid"];
+		$header["network"] = NETWORK_OSTATUS;
+		$header["type"] = "remote";
+		$header["wall"] = 0;
+		$header["origin"] = 0;
+		$header["gravity"] = GRAVITY_PARENT;
+
+		// it could either be a received post or a post we fetched by ourselves
+		// depending on that, the first node is different
+		$first_child = $doc->firstChild->tagName;
+
+		if ($first_child == "feed")
+			$entries = $xpath->query('/atom:feed/atom:entry');
+		else
+			$entries = $xpath->query('/atom:entry');
+
+		$conversation = "";
+		$conversationlist = array();
+		$item_id = 0;
+
+		// Reverse the order of the entries
+		$entrylist = array();
+
+		foreach ($entries AS $entry)
+			$entrylist[] = $entry;
+
+		foreach (array_reverse($entrylist) AS $entry) {
+
+			$mention = false;
+
+			// fetch the author
+			if ($first_child == "feed")
+				$author = self::fetchauthor($xpath, $doc->firstChild, $importer, $contact, false);
+			else
+				$author = self::fetchauthor($xpath, $entry, $importer, $contact, false);
+
+			$value = $xpath->evaluate('atom:author/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$nickname = $value;
+			else
+				$nickname = $author["author-name"];
+
+			$item = array_merge($header, $author);
+
+			// Now get the item
+			$item["uri"] = $xpath->query('atom:id/text()', $entry)->item(0)->nodeValue;
+
+			$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
+				intval($importer["uid"]), dbesc($item["uri"]));
+			if ($r) {
+				logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
+				continue;
+			}
+
+			$item["body"] = add_page_info_to_body(html2bbcode($xpath->query('atom:content/text()', $entry)->item(0)->nodeValue));
+			$item["object-type"] = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue;
+
+			if (($item["object-type"] == ACTIVITY_OBJ_BOOKMARK) OR ($item["object-type"] == ACTIVITY_OBJ_EVENT)) {
+				$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
+				$item["body"] = $xpath->query('atom:summary/text()', $entry)->item(0)->nodeValue;
+			} elseif ($item["object-type"] == ACTIVITY_OBJ_QUESTION)
+				$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
+
+			$item["object"] = $xml;
+			$item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue;
+
+			/// @TODO
+			/// Delete a message
+			if ($item["verb"] == "qvitter-delete-notice") {
+				// ignore "Delete" messages (by now)
+				logger("Ignore delete message ".print_r($item, true));
+				continue;
+			}
+
+			if ($item["verb"] == ACTIVITY_JOIN) {
+				// ignore "Join" messages
+				logger("Ignore join message ".print_r($item, true));
+				continue;
+			}
+
+			if ($item["verb"] == ACTIVITY_FOLLOW) {
+				new_follower($importer, $contact, $item, $nickname);
+				continue;
+			}
+
+			if ($item["verb"] == NAMESPACE_OSTATUS."/unfollow") {
+				lose_follower($importer, $contact, $item, $dummy);
+				continue;
+			}
+
+			if ($item["verb"] == ACTIVITY_FAVORITE) {
+				$orig_uri = $xpath->query("activity:object/atom:id", $entry)->item(0)->nodeValue;
+				logger("Favorite ".$orig_uri." ".print_r($item, true));
+
+				$item["verb"] = ACTIVITY_LIKE;
+				$item["parent-uri"] = $orig_uri;
+				$item["gravity"] = GRAVITY_LIKE;
+			}
+
+			if ($item["verb"] == NAMESPACE_OSTATUS."/unfavorite") {
+				// Ignore "Unfavorite" message
+				logger("Ignore unfavorite message ".print_r($item, true));
+				continue;
+			}
+
+			// http://activitystrea.ms/schema/1.0/rsvp-yes
+			if (!in_array($item["verb"], array(ACTIVITY_POST, ACTIVITY_LIKE, ACTIVITY_SHARE)))
+				logger("Unhandled verb ".$item["verb"]." ".print_r($item, true));
+
+			$item["created"] = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
+			$item["edited"] = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue;
+			$conversation = $xpath->query('ostatus:conversation/text()', $entry)->item(0)->nodeValue;
+
+			$related = "";
+
+			$inreplyto = $xpath->query('thr:in-reply-to', $entry);
+			if (is_object($inreplyto->item(0))) {
+				foreach($inreplyto->item(0)->attributes AS $attributes) {
+					if ($attributes->name == "ref")
+						$item["parent-uri"] = $attributes->textContent;
+					if ($attributes->name == "href")
+						$related = $attributes->textContent;
+				}
+			}
+
+			$georsspoint = $xpath->query('georss:point', $entry);
+			if ($georsspoint)
+				$item["coord"] = $georsspoint->item(0)->nodeValue;
+
+			$categories = $xpath->query('atom:category', $entry);
+			if ($categories) {
+				foreach ($categories AS $category) {
+					foreach($category->attributes AS $attributes)
+						if ($attributes->name == "term") {
+							$term = $attributes->textContent;
+							if(strlen($item["tag"]))
+								$item["tag"] .= ',';
+							$item["tag"] .= "#[url=".App::get_baseurl()."/search?tag=".$term."]".$term."[/url]";
+						}
+				}
+			}
+
+			$self = "";
+			$enclosure = "";
+
+			$links = $xpath->query('atom:link', $entry);
+			if ($links) {
+				$rel = "";
+				$href = "";
+				$type = "";
+				$length = "0";
+				$title = "";
+				foreach ($links AS $link) {
+					foreach($link->attributes AS $attributes) {
+						if ($attributes->name == "href")
+							$href = $attributes->textContent;
+						if ($attributes->name == "rel")
+							$rel = $attributes->textContent;
+						if ($attributes->name == "type")
+							$type = $attributes->textContent;
+						if ($attributes->name == "length")
+							$length = $attributes->textContent;
+						if ($attributes->name == "title")
+							$title = $attributes->textContent;
+					}
+					if (($rel != "") AND ($href != ""))
+						switch($rel) {
+							case "alternate":
+								$item["plink"] = $href;
+								if (($item["object-type"] == ACTIVITY_OBJ_QUESTION) OR
+									($item["object-type"] == ACTIVITY_OBJ_EVENT))
+									$item["body"] .= add_page_info($href);
+								break;
+							case "ostatus:conversation":
+								$conversation = $href;
+								break;
+							case "enclosure":
+								$enclosure = $href;
+								if(strlen($item["attach"]))
+									$item["attach"] .= ',';
+
+								$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
+								break;
+							case "related":
+								if ($item["object-type"] != ACTIVITY_OBJ_BOOKMARK) {
+									if (!isset($item["parent-uri"]))
+										$item["parent-uri"] = $href;
+
+									if ($related == "")
+										$related = $href;
+								} else
+									$item["body"] .= add_page_info($href);
+								break;
+							case "self":
+								$self = $href;
+								break;
+							case "mentioned":
+								// Notification check
+								if ($importer["nurl"] == normalise_link($href))
+									$mention = true;
+								break;
+						}
+				}
+			}
+
+			$local_id = "";
+			$repeat_of = "";
+
+			$notice_info = $xpath->query('statusnet:notice_info', $entry);
+			if ($notice_info AND ($notice_info->length > 0)) {
+				foreach($notice_info->item(0)->attributes AS $attributes) {
+					if ($attributes->name == "source")
+						$item["app"] = strip_tags($attributes->textContent);
+					if ($attributes->name == "local_id")
+						$local_id = $attributes->textContent;
+					if ($attributes->name == "repeat_of")
+						$repeat_of = $attributes->textContent;
+				}
+			}
+
+			// Is it a repeated post?
+			if ($repeat_of != "") {
+				$activityobjects = $xpath->query('activity:object', $entry)->item(0);
+
+				if (is_object($activityobjects)) {
+
+					$orig_uri = $xpath->query("activity:object/atom:id", $activityobjects)->item(0)->nodeValue;
+					if (!isset($orig_uri))
+						$orig_uri = $xpath->query('atom:id/text()', $activityobjects)->item(0)->nodeValue;
+
+					$orig_links = $xpath->query("activity:object/atom:link[@rel='alternate']", $activityobjects);
+					if ($orig_links AND ($orig_links->length > 0))
+						foreach($orig_links->item(0)->attributes AS $attributes)
+							if ($attributes->name == "href")
+								$orig_link = $attributes->textContent;
+
+					if (!isset($orig_link))
+						$orig_link = $xpath->query("atom:link[@rel='alternate']", $activityobjects)->item(0)->nodeValue;
+
+					if (!isset($orig_link))
+						$orig_link =  self::convert_href($orig_uri);
+
+					$orig_body = $xpath->query('activity:object/atom:content/text()', $activityobjects)->item(0)->nodeValue;
+					if (!isset($orig_body))
+						$orig_body = $xpath->query('atom:content/text()', $activityobjects)->item(0)->nodeValue;
+
+					$orig_created = $xpath->query('atom:published/text()', $activityobjects)->item(0)->nodeValue;
+
+					$orig_contact = $contact;
+					$orig_author = self::fetchauthor($xpath, $activityobjects, $importer, $orig_contact, false);
+
+					$item["author-name"] = $orig_author["author-name"];
+					$item["author-link"] = $orig_author["author-link"];
+					$item["author-avatar"] = $orig_author["author-avatar"];
+					$item["body"] = add_page_info_to_body(html2bbcode($orig_body));
+					$item["created"] = $orig_created;
+
+					$item["uri"] = $orig_uri;
+					$item["plink"] = $orig_link;
+
+					$item["verb"] = $xpath->query('activity:verb/text()', $activityobjects)->item(0)->nodeValue;
+
+					$item["object-type"] = $xpath->query('activity:object/activity:object-type/text()', $activityobjects)->item(0)->nodeValue;
+					if (!isset($item["object-type"]))
+						$item["object-type"] = $xpath->query('activity:object-type/text()', $activityobjects)->item(0)->nodeValue;
+				}
+			}
+
+			//if ($enclosure != "")
+			//	$item["body"] .= add_page_info($enclosure);
+
+			if (isset($item["parent-uri"])) {
+				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
+					intval($importer["uid"]), dbesc($item["parent-uri"]));
+
+				if (!$r AND ($related != "")) {
+					$reply_path = str_replace("/notice/", "/api/statuses/show/", $related).".atom";
+
+					if ($reply_path != $related) {
+						logger("Fetching related items for user ".$importer["uid"]." from ".$reply_path, LOGGER_DEBUG);
+						$reply_xml = fetch_url($reply_path);
+
+						$reply_contact = $contact;
+						self::import($reply_xml,$importer,$reply_contact, $reply_hub);
+
+						// After the import try to fetch the parent item again
+						$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
+							intval($importer["uid"]), dbesc($item["parent-uri"]));
+					}
+				}
+				if ($r) {
+					$item["type"] = 'remote-comment';
+					$item["gravity"] = GRAVITY_COMMENT;
+				}
+			} else
+				$item["parent-uri"] = $item["uri"];
+
+			$item_id = self::completion($conversation, $importer["uid"], $item, $self);
+
+			if (!$item_id) {
+				logger("Error storing item", LOGGER_DEBUG);
+				continue;
+			}
+
+			logger("Item was stored with id ".$item_id, LOGGER_DEBUG);
+		}
+	}
+
+	public static function convert_href($href) {
+		$elements = explode(":",$href);
+
+		if ((count($elements) <= 2) OR ($elements[0] != "tag"))
+			return $href;
+
+		$server = explode(",", $elements[1]);
+		$conversation = explode("=", $elements[2]);
+
+		if ((count($elements) == 4) AND ($elements[2] == "post"))
+			return "http://".$server[0]."/notice/".$elements[3];
+
+		if ((count($conversation) != 2) OR ($conversation[1] ==""))
+			return $href;
+
+		if ($elements[3] == "objectType=thread")
+			return "http://".$server[0]."/conversation/".$conversation[1];
+		else
+			return "http://".$server[0]."/notice/".$conversation[1];
+
+		return $href;
+	}
+
+	public static function check_conversations($mentions = false, $override = false) {
+		$last = get_config('system','ostatus_last_poll');
+
+		$poll_interval = intval(get_config('system','ostatus_poll_interval'));
+		if(! $poll_interval)
+			$poll_interval = OSTATUS_DEFAULT_POLL_INTERVAL;
+
+		// Don't poll if the interval is set negative
+		if (($poll_interval < 0) AND !$override)
+			return;
+
+		if (!$mentions) {
+			$poll_timeframe = intval(get_config('system','ostatus_poll_timeframe'));
+			if (!$poll_timeframe)
+				$poll_timeframe = OSTATUS_DEFAULT_POLL_TIMEFRAME;
+		} else {
+			$poll_timeframe = intval(get_config('system','ostatus_poll_timeframe'));
+			if (!$poll_timeframe)
+				$poll_timeframe = OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS;
+		}
+
+
+		if ($last AND !$override) {
+			$next = $last + ($poll_interval * 60);
+			if ($next > time()) {
+				logger('poll interval not reached');
+				return;
+			}
+		}
+
+		logger('cron_start');
+
+		$start = date("Y-m-d H:i:s", time() - ($poll_timeframe * 60));
+
+		if ($mentions)
+			$conversations = q("SELECT `term`.`oid`, `term`.`url`, `term`.`uid` FROM `term`
+						STRAIGHT_JOIN `thread` ON `thread`.`iid` = `term`.`oid` AND `thread`.`uid` = `term`.`uid`
+						WHERE `term`.`type` = 7 AND `term`.`term` > '%s' AND `thread`.`mention`
+						GROUP BY `term`.`url`, `term`.`uid` ORDER BY `term`.`term` DESC", dbesc($start));
+		else
+			$conversations = q("SELECT `oid`, `url`, `uid` FROM `term`
+						WHERE `type` = 7 AND `term` > '%s'
+						GROUP BY `url`, `uid` ORDER BY `term` DESC", dbesc($start));
+
+		foreach ($conversations AS $conversation) {
+			self::completion($conversation['url'], $conversation['uid']);
+		}
+
+		logger('cron_end');
+
+		set_config('system','ostatus_last_poll', time());
+	}
+
+	/**
+	 * @brief Updates the gcontact table with actor data from the conversation
+	 *
+	 * @param object $actor The actor object that contains the contact data
+	 */
+	private function conv_fetch_actor($actor) {
+
+		// We set the generation to "3" since the data here is not as reliable as the data we get on other occasions
+		$contact = array("network" => NETWORK_OSTATUS, "generation" => 3);
+
+		if (isset($actor->url))
+			$contact["url"] = $actor->url;
+
+		if (isset($actor->displayName))
+			$contact["name"] = $actor->displayName;
+
+		if (isset($actor->portablecontacts_net->displayName))
+			$contact["name"] = $actor->portablecontacts_net->displayName;
+
+		if (isset($actor->portablecontacts_net->preferredUsername))
+			$contact["nick"] = $actor->portablecontacts_net->preferredUsername;
+
+		if (isset($actor->id))
+			$contact["alias"] = $actor->id;
+
+		if (isset($actor->summary))
+			$contact["about"] = $actor->summary;
+
+		if (isset($actor->portablecontacts_net->note))
+			$contact["about"] = $actor->portablecontacts_net->note;
+
+		if (isset($actor->portablecontacts_net->addresses->formatted))
+			$contact["location"] = $actor->portablecontacts_net->addresses->formatted;
+
+
+		if (isset($actor->image->url))
+			$contact["photo"] = $actor->image->url;
+
+		if (isset($actor->image->width))
+			$avatarwidth = $actor->image->width;
+
+		if (is_array($actor->status_net->avatarLinks))
+			foreach ($actor->status_net->avatarLinks AS $avatar) {
+				if ($avatarsize < $avatar->width) {
+					$contact["photo"] = $avatar->url;
+					$avatarsize = $avatar->width;
+				}
+			}
+
+		update_gcontact($contact);
+	}
+
+	/**
+	 * @brief Fetches the conversation url for a given item link or conversation id
+	 *
+	 * @param string $self The link to the posting
+	 * @param string $conversation_id The conversation id
+	 *
+	 * @return string The conversation url
+	 */
+	private function fetch_conversation($self, $conversation_id = "") {
+
+		if ($conversation_id != "") {
+			$elements = explode(":", $conversation_id);
+
+			if ((count($elements) <= 2) OR ($elements[0] != "tag"))
+				return $conversation_id;
+		}
+
+		if ($self == "")
+			return "";
+
+		$json = str_replace(".atom", ".json", $self);
+
+		$raw = fetch_url($json);
+		if ($raw == "")
+			return "";
+
+		$data = json_decode($raw);
+		if (!is_object($data))
+			return "";
+
+		$conversation_id = $data->statusnet_conversation_id;
+
+		$pos = strpos($self, "/api/statuses/show/");
+		$base_url = substr($self, 0, $pos);
+
+		return $base_url."/conversation/".$conversation_id;
+	}
+
+	/**
+	 * @brief Fetches actor details of a given actor and user id
+	 *
+	 * @param string $actor The actor url
+	 * @param int $uid The user id
+	 * @param int $contact_id The default contact-id
+	 *
+	 * @return array Array with actor details
+	 */
+	private function get_actor_details($actor, $uid, $contact_id) {
+
+		$details = array();
+
+		$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
+					$uid, normalise_link($actor), NETWORK_STATUSNET);
+
+		if (!$contact)
+			$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `alias` IN ('%s', '%s') AND `network` != '%s'",
+					$uid, $actor, normalise_link($actor), NETWORK_STATUSNET);
+
+		if ($contact) {
+			logger("Found contact for url ".$actor, LOGGER_DEBUG);
+			$details["contact_id"] = $contact[0]["id"];
+			$details["network"] = $contact[0]["network"];
+
+			$details["not_following"] = !in_array($contact[0]["rel"], array(CONTACT_IS_SHARING, CONTACT_IS_FRIEND));
+		} else {
+			logger("No contact found for user ".$uid." and url ".$actor, LOGGER_DEBUG);
+
+			// Adding a global contact
+			/// @TODO Use this data for the post
+			$details["global_contact_id"] = get_contact($actor, 0);
+
+			logger("Global contact ".$global_contact_id." found for url ".$actor, LOGGER_DEBUG);
+
+			$details["contact_id"] = $contact_id;
+			$details["network"] = NETWORK_OSTATUS;
+
+			$details["not_following"] = true;
+		}
+
+		return $details;
+	}
+
+	private function completion($conversation_url, $uid, $item = array(), $self = "") {
+
+
+		$item_stored = -1;
+
+		$conversation_url = self::fetch_conversation($self, $conversation_url);
+
+		// If the thread shouldn't be completed then store the item and go away
+		// Don't do a completion on liked content
+		if (((intval(get_config('system','ostatus_poll_interval')) == -2) AND (count($item) > 0)) OR
+			($item["verb"] == ACTIVITY_LIKE) OR ($conversation_url == "")) {
+			$item_stored = item_store($item, true);
+			return($item_stored);
+		}
+
+		// Get the parent
+		$parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
+				(SELECT `parent` FROM `item` WHERE `id` IN
+					(SELECT `oid` FROM `term` WHERE `uid` = %d AND `otype` = %d AND `type` = %d AND `url` = '%s'))",
+				intval($uid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), dbesc($conversation_url));
+
+		if ($parents)
+			$parent = $parents[0];
+		elseif (count($item) > 0) {
+			$parent = $item;
+			$parent["type"] = "remote";
+			$parent["verb"] = ACTIVITY_POST;
+			$parent["visible"] = 1;
+		} else {
+			// Preset the parent
+			$r = q("SELECT `id` FROM `contact` WHERE `self` AND `uid`=%d", $uid);
+			if (!$r)
+				return(-2);
+
+			$parent = array();
+			$parent["id"] = 0;
+			$parent["parent"] = 0;
+			$parent["uri"] = "";
+			$parent["contact-id"] = $r[0]["id"];
+			$parent["type"] = "remote";
+			$parent["verb"] = ACTIVITY_POST;
+			$parent["visible"] = 1;
+		}
+
+		$conv = str_replace("/conversation/", "/api/statusnet/conversation/", $conversation_url).".as";
+		$pageno = 1;
+		$items = array();
+
+		logger('fetching conversation url '.$conv.' (Self: '.$self.') for user '.$uid);
+
+		do {
+			$conv_arr = z_fetch_url($conv."?page=".$pageno);
+
+			// If it is a non-ssl site and there is an error, then try ssl or vice versa
+			if (!$conv_arr["success"] AND (substr($conv, 0, 7) == "http://")) {
+				$conv = str_replace("http://", "https://", $conv);
+				$conv_as = fetch_url($conv."?page=".$pageno);
+			} elseif (!$conv_arr["success"] AND (substr($conv, 0, 8) == "https://")) {
+				$conv = str_replace("https://", "http://", $conv);
+				$conv_as = fetch_url($conv."?page=".$pageno);
+			} else
+				$conv_as = $conv_arr["body"];
+
+			$conv_as = str_replace(',"statusnet:notice_info":', ',"statusnet_notice_info":', $conv_as);
+			$conv_as = json_decode($conv_as);
+
+			$no_of_items = sizeof($items);
+
+			if (@is_array($conv_as->items))
+				foreach ($conv_as->items AS $single_item)
+					$items[$single_item->id] = $single_item;
+
+			if ($no_of_items == sizeof($items))
+				break;
+
+			$pageno++;
+
+		} while (true);
+
+		logger('fetching conversation done. Found '.count($items).' items');
+
+		if (!sizeof($items)) {
+			if (count($item) > 0) {
+				$item_stored = item_store($item, true);
+
+				if ($item_stored) {
+					logger("Conversation ".$conversation_url." couldn't be fetched. Item uri ".$item["uri"]." stored: ".$item_stored, LOGGER_DEBUG);
+					self::store_conversation($item_id, $conversation_url);
+				}
+
+				return($item_stored);
+			} else
+				return(-3);
+		}
+
+		$items = array_reverse($items);
+
+		$r = q("SELECT `nurl` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid));
+		$importer = $r[0];
+
+		$new_parent = true;
+
+		foreach ($items as $single_conv) {
+
+			// Update the gcontact table
+			self::conv_fetch_actor($single_conv->actor);
+
+			// Test - remove before flight
+			//$tempfile = tempnam(get_temppath(), "conversation");
+			//file_put_contents($tempfile, json_encode($single_conv));
+
+			$mention = false;
+
+			if (isset($single_conv->object->id))
+				$single_conv->id = $single_conv->object->id;
+
+			$plink = self::convert_href($single_conv->id);
+			if (isset($single_conv->object->url))
+				$plink = self::convert_href($single_conv->object->url);
+
+			if (@!$single_conv->id)
+				continue;
+
+			logger("Got id ".$single_conv->id, LOGGER_DEBUG);
+
+			if ($first_id == "") {
+				$first_id = $single_conv->id;
+
+				// The first post of the conversation isn't our first post. There are three options:
+				// 1. Our conversation hasn't the "real" thread starter
+				// 2. This first post is a post inside our thread
+				// 3. This first post is a post inside another thread
+				if (($first_id != $parent["uri"]) AND ($parent["uri"] != "")) {
+
+					$new_parent = true;
+
+					$new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
+								(SELECT `parent` FROM `item`
+									WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s')) LIMIT 1",
+						intval($uid), dbesc($first_id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
+					if ($new_parents) {
+						if ($new_parents[0]["parent"] == $parent["parent"]) {
+							// Option 2: This post is already present inside our thread - but not as thread starter
+							logger("Option 2: uri present in our thread: ".$first_id, LOGGER_DEBUG);
+							$first_id = $parent["uri"];
+						} else {
+							// Option 3: Not so good. We have mixed parents. We have to see how to clean this up.
+							// For now just take the new parent.
+							$parent = $new_parents[0];
+							$first_id = $parent["uri"];
+							logger("Option 3: mixed parents for uri ".$first_id, LOGGER_DEBUG);
+						}
+					} else {
+						// Option 1: We hadn't got the real thread starter
+						// We have to clean up our existing messages.
+						$parent["id"] = 0;
+						$parent["uri"] = $first_id;
+						logger("Option 1: we have a new parent: ".$first_id, LOGGER_DEBUG);
+					}
+				} elseif ($parent["uri"] == "") {
+					$parent["id"] = 0;
+					$parent["uri"] = $first_id;
+				}
+			}
+
+			$parent_uri = $parent["uri"];
+
+			// "context" only seems to exist on older servers
+			if (isset($single_conv->context->inReplyTo->id)) {
+				$parent_exists = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
+							intval($uid), dbesc($single_conv->context->inReplyTo->id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
+				if ($parent_exists)
+					$parent_uri = $single_conv->context->inReplyTo->id;
+			}
+
+			// This is the current way
+			if (isset($single_conv->object->inReplyTo->id)) {
+				$parent_exists = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
+							intval($uid), dbesc($single_conv->object->inReplyTo->id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
+				if ($parent_exists)
+					$parent_uri = $single_conv->object->inReplyTo->id;
+			}
+
+			$message_exists = q("SELECT `id`, `parent`, `uri` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
+							intval($uid), dbesc($single_conv->id),
+							dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
+			if ($message_exists) {
+				logger("Message ".$single_conv->id." already existed on the system", LOGGER_DEBUG);
+
+				if ($parent["id"] != 0) {
+					$existing_message = $message_exists[0];
+
+					// We improved the way we fetch OStatus messages, this shouldn't happen very often now
+					/// @TODO We have to change the shadow copies as well. This way here is really ugly.
+					if ($existing_message["parent"] != $parent["id"]) {
+						logger('updating id '.$existing_message["id"].' with parent '.$existing_message["parent"].' to parent '.$parent["id"].' uri '.$parent["uri"].' thread '.$parent_uri, LOGGER_DEBUG);
+
+						// Update the parent id of the selected item
+						$r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `id` = %d",
+							intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["id"]));
+
+						// Update the parent uri in the thread - but only if it points to itself
+						$r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE `id` = %d AND `uri` = `thr-parent`",
+							dbesc($parent_uri), intval($existing_message["id"]));
+
+						// try to change all items of the same parent
+						$r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `parent` = %d",
+							intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["parent"]));
+
+						// Update the parent uri in the thread - but only if it points to itself
+						$r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE (`parent` = %d) AND (`uri` = `thr-parent`)",
+							dbesc($parent["uri"]), intval($existing_message["parent"]));
+
+						// Now delete the thread
+						delete_thread($existing_message["parent"]);
+					}
+				}
+
+				// The item we are having on the system is the one that we wanted to store via the item array
+				if (isset($item["uri"]) AND ($item["uri"] == $existing_message["uri"])) {
+					$item = array();
+					$item_stored = 0;
+				}
+
+				continue;
+			}
+
+			if (is_array($single_conv->to))
+				foreach($single_conv->to AS $to)
+					if ($importer["nurl"] == normalise_link($to->id))
+						$mention = true;
+
+			$actor = $single_conv->actor->id;
+			if (isset($single_conv->actor->url))
+				$actor = $single_conv->actor->url;
+
+			$details = self::get_actor_details($actor, $uid, $parent["contact-id"]);
+
+			// Do we only want to import threads that were started by our contacts?
+			if ($details["not_following"] AND $new_parent AND get_config('system','ostatus_full_threads')) {
+				logger("Don't import uri ".$first_id." because user ".$uid." doesn't follow the person ".$actor, LOGGER_DEBUG);
+				continue;
+			}
+
+			$arr = array();
+			$arr["network"] = $details["network"];
+			$arr["uri"] = $single_conv->id;
+			$arr["plink"] = $plink;
+			$arr["uid"] = $uid;
+			$arr["contact-id"] = $details["contact_id"];
+			$arr["parent-uri"] = $parent_uri;
+			$arr["created"] = $single_conv->published;
+			$arr["edited"] = $single_conv->published;
+			$arr["owner-name"] = $single_conv->actor->displayName;
+			if ($arr["owner-name"] == '')
+				$arr["owner-name"] = $single_conv->actor->contact->displayName;
+			if ($arr["owner-name"] == '')
+				$arr["owner-name"] = $single_conv->actor->portablecontacts_net->displayName;
+
+			$arr["owner-link"] = $actor;
+			$arr["owner-avatar"] = $single_conv->actor->image->url;
+			$arr["author-name"] = $arr["owner-name"];
+			$arr["author-link"] = $actor;
+			$arr["author-avatar"] = $single_conv->actor->image->url;
+			$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->content));
+
+			if (isset($single_conv->status_net->notice_info->source))
+				$arr["app"] = strip_tags($single_conv->status_net->notice_info->source);
+			elseif (isset($single_conv->statusnet->notice_info->source))
+				$arr["app"] = strip_tags($single_conv->statusnet->notice_info->source);
+			elseif (isset($single_conv->statusnet_notice_info->source))
+				$arr["app"] = strip_tags($single_conv->statusnet_notice_info->source);
+			elseif (isset($single_conv->provider->displayName))
+				$arr["app"] = $single_conv->provider->displayName;
+			else
+				$arr["app"] = "OStatus";
+
+
+			$arr["object"] = json_encode($single_conv);
+			$arr["verb"] = $parent["verb"];
+			$arr["visible"] = $parent["visible"];
+			$arr["location"] = $single_conv->location->displayName;
+			$arr["coord"] = trim($single_conv->location->lat." ".$single_conv->location->lon);
+
+			// Is it a reshared item?
+			if (isset($single_conv->verb) AND ($single_conv->verb == "share") AND isset($single_conv->object)) {
+				if (is_array($single_conv->object))
+					$single_conv->object = $single_conv->object[0];
+
+				logger("Found reshared item ".$single_conv->object->id);
+
+				// $single_conv->object->context->conversation;
+
+				if (isset($single_conv->object->object->id))
+					$arr["uri"] = $single_conv->object->object->id;
+				else
+					$arr["uri"] = $single_conv->object->id;
+
+				if (isset($single_conv->object->object->url))
+					$plink = self::convert_href($single_conv->object->object->url);
+				else
+					$plink = self::convert_href($single_conv->object->url);
+
+				if (isset($single_conv->object->object->content))
+					$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->object->content));
+				else
+					$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->content));
+
+				$arr["plink"] = $plink;
+
+				$arr["created"] = $single_conv->object->published;
+				$arr["edited"] = $single_conv->object->published;
+
+				$arr["author-name"] = $single_conv->object->actor->displayName;
+				if ($arr["owner-name"] == '')
+					$arr["author-name"] = $single_conv->object->actor->contact->displayName;
+
+				$arr["author-link"] = $single_conv->object->actor->url;
+				$arr["author-avatar"] = $single_conv->object->actor->image->url;
+
+				$arr["app"] = $single_conv->object->provider->displayName."#";
+				//$arr["verb"] = $single_conv->object->verb;
+
+				$arr["location"] = $single_conv->object->location->displayName;
+				$arr["coord"] = trim($single_conv->object->location->lat." ".$single_conv->object->location->lon);
+			}
+
+			if ($arr["location"] == "")
+				unset($arr["location"]);
+
+			if ($arr["coord"] == "")
+				unset($arr["coord"]);
+
+			// Copy fields from given item array
+			if (isset($item["uri"]) AND (($item["uri"] == $arr["uri"]) OR ($item["uri"] ==  $single_conv->id))) {
+				$copy_fields = array("owner-name", "owner-link", "owner-avatar", "author-name", "author-link", "author-avatar",
+							"gravity", "body", "object-type", "object", "verb", "created", "edited", "coord", "tag",
+							"title", "attach", "app", "type", "location", "contact-id", "uri");
+				foreach ($copy_fields AS $field)
+					if (isset($item[$field]))
+						$arr[$field] = $item[$field];
+
+			}
+
+			$newitem = item_store($arr);
+			if (!$newitem) {
+				logger("Item wasn't stored ".print_r($arr, true), LOGGER_DEBUG);
+				continue;
+			}
+
+			if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) {
+				$item = array();
+				$item_stored = $newitem;
+			}
+
+			logger('Stored new item '.$plink.' for parent '.$arr["parent-uri"].' under id '.$newitem, LOGGER_DEBUG);
+
+			// Add the conversation entry (but don't fetch the whole conversation)
+			self::store_conversation($newitem, $conversation_url);
+
+			// If the newly created item is the top item then change the parent settings of the thread
+			// This shouldn't happen anymore. This is supposed to be absolote.
+			if ($arr["uri"] == $first_id) {
+				logger('setting new parent to id '.$newitem);
+				$new_parents = q("SELECT `id`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1",
+					intval($uid), intval($newitem));
+				if ($new_parents)
+					$parent = $new_parents[0];
+			}
+		}
+
+		if (($item_stored < 0) AND (count($item) > 0)) {
+
+			if (get_config('system','ostatus_full_threads')) {
+				$details = self::get_actor_details($item["owner-link"], $uid, $item["contact-id"]);
+				if ($details["not_following"]) {
+					logger("Don't import uri ".$item["uri"]." because user ".$uid." doesn't follow the person ".$item["owner-link"], LOGGER_DEBUG);
+					return false;
+				}
+			}
+
+			$item_stored = item_store($item, true);
+			if ($item_stored) {
+				logger("Uri ".$item["uri"]." wasn't found in conversation ".$conversation_url, LOGGER_DEBUG);
+				self::store_conversation($item_stored, $conversation_url);
+			}
+		}
+
+		return($item_stored);
+	}
+
+	private function store_conversation($itemid, $conversation_url) {
+
+		$conversation_url = self::convert_href($conversation_url);
+
+		$messages = q("SELECT `uid`, `parent`, `created`, `received`, `guid` FROM `item` WHERE `id` = %d LIMIT 1", intval($itemid));
+		if (!$messages)
+			return;
+		$message = $messages[0];
+
+		// Store conversation url if not done before
+		$conversation = q("SELECT `url` FROM `term` WHERE `uid` = %d AND `oid` = %d AND `otype` = %d AND `type` = %d",
+			intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION));
+
+		if (!$conversation) {
+			$r = q("INSERT INTO `term` (`uid`, `oid`, `otype`, `type`, `term`, `url`, `created`, `received`, `guid`) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s')",
+				intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION),
+				dbesc($message["created"]), dbesc($conversation_url), dbesc($message["created"]), dbesc($message["received"]), dbesc($message["guid"]));
+			logger('Storing conversation url '.$conversation_url.' for id '.$itemid);
+		}
+	}
+
+	private function get_reshared_guid($item) {
+		$body = trim($item["body"]);
+
+		// Skip if it isn't a pure repeated messages
+		// Does it start with a share?
+		if (strpos($body, "[share") > 0)
+			return("");
+
+		// Does it end with a share?
+		if (strlen($body) > (strrpos($body, "[/share]") + 8))
+			return("");
+
+		$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
+		// Skip if there is no shared message in there
+		if ($body == $attributes)
+			return(false);
+
+		$guid = "";
+		preg_match("/guid='(.*?)'/ism", $attributes, $matches);
+		if ($matches[1] != "")
+			$guid = $matches[1];
+
+		preg_match('/guid="(.*?)"/ism', $attributes, $matches);
+		if ($matches[1] != "")
+			$guid = $matches[1];
+
+		return $guid;
+	}
+
+	private function format_picture_post($body) {
+		$siteinfo = get_attached_data($body);
+
+		if (($siteinfo["type"] == "photo")) {
+			if (isset($siteinfo["preview"]))
+				$preview = $siteinfo["preview"];
+			else
+				$preview = $siteinfo["image"];
+
+			// Is it a remote picture? Then make a smaller preview here
+			$preview = proxy_url($preview, false, PROXY_SIZE_SMALL);
+
+			// Is it a local picture? Then make it smaller here
+			$preview = str_replace(array("-0.jpg", "-0.png"), array("-2.jpg", "-2.png"), $preview);
+			$preview = str_replace(array("-1.jpg", "-1.png"), array("-2.jpg", "-2.png"), $preview);
+
+			if (isset($siteinfo["url"]))
+				$url = $siteinfo["url"];
+			else
+				$url = $siteinfo["image"];
+
+			$body = trim($siteinfo["text"])." [url]".$url."[/url]\n[img]".$preview."[/img]";
+		}
+
+		return $body;
+	}
+
+	private function add_header($doc, $owner) {
+
+		$a = get_app();
+
+		$root = $doc->createElementNS(NAMESPACE_ATOM1, 'feed');
+		$doc->appendChild($root);
+
+		$root->setAttribute("xmlns:thr", NAMESPACE_THREAD);
+		$root->setAttribute("xmlns:georss", NAMESPACE_GEORSS);
+		$root->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY);
+		$root->setAttribute("xmlns:media", NAMESPACE_MEDIA);
+		$root->setAttribute("xmlns:poco", NAMESPACE_POCO);
+		$root->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
+		$root->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
+
+		$attributes = array("uri" => "https://friendi.ca", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION);
+		xml2::add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes);
+		xml2::add_element($doc, $root, "id", App::get_baseurl()."/profile/".$owner["nick"]);
+		xml2::add_element($doc, $root, "title", sprintf("%s timeline", $owner["name"]));
+		xml2::add_element($doc, $root, "subtitle", sprintf("Updates from %s on %s", $owner["name"], $a->config["sitename"]));
+		xml2::add_element($doc, $root, "logo", $owner["photo"]);
+		xml2::add_element($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME));
+
+		$author = self::add_author($doc, $owner);
+		$root->appendChild($author);
+
+		$attributes = array("href" => $owner["url"], "rel" => "alternate", "type" => "text/html");
+		xml2::add_element($doc, $root, "link", "", $attributes);
+
+		/// @TODO We have to find out what this is
+		/// $attributes = array("href" => App::get_baseurl()."/sup",
+		///		"rel" => "http://api.friendfeed.com/2008/03#sup",
+		///		"type" => "application/json");
+		/// xml2::add_element($doc, $root, "link", "", $attributes);
+
+		self::hublinks($doc, $root);
+
+		$attributes = array("href" => App::get_baseurl()."/salmon/".$owner["nick"], "rel" => "salmon");
+		xml2::add_element($doc, $root, "link", "", $attributes);
+
+		$attributes = array("href" => App::get_baseurl()."/salmon/".$owner["nick"], "rel" => "http://salmon-protocol.org/ns/salmon-replies");
+		xml2::add_element($doc, $root, "link", "", $attributes);
+
+		$attributes = array("href" => App::get_baseurl()."/salmon/".$owner["nick"], "rel" => "http://salmon-protocol.org/ns/salmon-mention");
+		xml2::add_element($doc, $root, "link", "", $attributes);
+
+		$attributes = array("href" => App::get_baseurl()."/api/statuses/user_timeline/".$owner["nick"].".atom",
+				"rel" => "self", "type" => "application/atom+xml");
+		xml2::add_element($doc, $root, "link", "", $attributes);
+
+		return $root;
+	}
+
+	public static function hublinks($doc, $root) {
+		$hub = get_config('system','huburl');
+
+		$hubxml = '';
+		if(strlen($hub)) {
+			$hubs = explode(',', $hub);
+			if(count($hubs)) {
+				foreach($hubs as $h) {
+					$h = trim($h);
+					if(! strlen($h))
+						continue;
+					if ($h === '[internal]')
+						$h = App::get_baseurl() . '/pubsubhubbub';
+					xml2::add_element($doc, $root, "link", "", array("href" => $h, "rel" => "hub"));
+				}
+			}
+		}
+	}
+
+	private function get_attachment($doc, $root, $item) {
+		$o = "";
+		$siteinfo = get_attached_data($item["body"]);
+
+		switch($siteinfo["type"]) {
+			case 'link':
+				$attributes = array("rel" => "enclosure",
+						"href" => $siteinfo["url"],
+						"type" => "text/html; charset=UTF-8",
+						"length" => "",
+						"title" => $siteinfo["title"]);
+				xml2::add_element($doc, $root, "link", "", $attributes);
+				break;
+			case 'photo':
+				$imgdata = get_photo_info($siteinfo["image"]);
+				$attributes = array("rel" => "enclosure",
+						"href" => $siteinfo["image"],
+						"type" => $imgdata["mime"],
+						"length" => intval($imgdata["size"]));
+				xml2::add_element($doc, $root, "link", "", $attributes);
+				break;
+			case 'video':
+				$attributes = array("rel" => "enclosure",
+						"href" => $siteinfo["url"],
+						"type" => "text/html; charset=UTF-8",
+						"length" => "",
+						"title" => $siteinfo["title"]);
+				xml2::add_element($doc, $root, "link", "", $attributes);
+				break;
+			default:
+				break;
+		}
+
+		if (($siteinfo["type"] != "photo") AND isset($siteinfo["image"])) {
+			$photodata = get_photo_info($siteinfo["image"]);
+
+			$attributes = array("rel" => "preview", "href" => $siteinfo["image"], "media:width" => $photodata[0], "media:height" => $photodata[1]);
+			xml2::add_element($doc, $root, "link", "", $attributes);
+		}
+
+
+		$arr = explode('[/attach],',$item['attach']);
+		if(count($arr)) {
+			foreach($arr as $r) {
+				$matches = false;
+				$cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|',$r,$matches);
+				if($cnt) {
+					$attributes = array("rel" => "enclosure",
+							"href" => $matches[1],
+							"type" => $matches[3]);
+
+					if(intval($matches[2]))
+						$attributes["length"] = intval($matches[2]);
+
+					if(trim($matches[4]) != "")
+						$attributes["title"] = trim($matches[4]);
+
+					xml2::add_element($doc, $root, "link", "", $attributes);
+				}
+			}
+		}
+	}
+
+	private function add_author($doc, $owner) {
+
+		$r = q("SELECT `homepage` FROM `profile` WHERE `uid` = %d AND `is-default` LIMIT 1", intval($owner["uid"]));
+		if ($r)
+			$profile = $r[0];
+
+		$author = $doc->createElement("author");
+		xml2::add_element($doc, $author, "activity:object-type", ACTIVITY_OBJ_PERSON);
+		xml2::add_element($doc, $author, "uri", $owner["url"]);
+		xml2::add_element($doc, $author, "name", $owner["name"]);
+		xml2::add_element($doc, $author, "summary", bbcode($owner["about"], false, false, 7));
+
+		$attributes = array("rel" => "alternate", "type" => "text/html", "href" => $owner["url"]);
+		xml2::add_element($doc, $author, "link", "", $attributes);
+
+		$attributes = array(
+				"rel" => "avatar",
+				"type" => "image/jpeg", // To-Do?
+				"media:width" => 175,
+				"media:height" => 175,
+				"href" => $owner["photo"]);
+		xml2::add_element($doc, $author, "link", "", $attributes);
+
+		if (isset($owner["thumb"])) {
+			$attributes = array(
+					"rel" => "avatar",
+					"type" => "image/jpeg", // To-Do?
+					"media:width" => 80,
+					"media:height" => 80,
+					"href" => $owner["thumb"]);
+			xml2::add_element($doc, $author, "link", "", $attributes);
+		}
+
+		xml2::add_element($doc, $author, "poco:preferredUsername", $owner["nick"]);
+		xml2::add_element($doc, $author, "poco:displayName", $owner["name"]);
+		xml2::add_element($doc, $author, "poco:note", bbcode($owner["about"], false, false, 7));
+
+		if (trim($owner["location"]) != "") {
+			$element = $doc->createElement("poco:address");
+			xml2::add_element($doc, $element, "poco:formatted", $owner["location"]);
+			$author->appendChild($element);
+		}
+
+		if (trim($profile["homepage"]) != "") {
+			$urls = $doc->createElement("poco:urls");
+			xml2::add_element($doc, $urls, "poco:type", "homepage");
+			xml2::add_element($doc, $urls, "poco:value", $profile["homepage"]);
+			xml2::add_element($doc, $urls, "poco:primary", "true");
+			$author->appendChild($urls);
+		}
+
+		if (count($profile)) {
+			xml2::add_element($doc, $author, "followers", "", array("url" => App::get_baseurl()."/viewcontacts/".$owner["nick"]));
+			xml2::add_element($doc, $author, "statusnet:profile_info", "", array("local_id" => $owner["uid"]));
+		}
+
+		return $author;
+	}
+
+	/**
+	 * @TODO Picture attachments should look like this:
+	 *	<a href="https://status.pirati.ca/attachment/572819" title="https://status.pirati.ca/file/heluecht-20151202T222602-rd3u49p.gif"
+	 *	class="attachment thumbnail" id="attachment-572819" rel="nofollow external">https://status.pirati.ca/attachment/572819</a>
+	 *
+	*/
+
+	function construct_verb($item) {
+		if ($item['verb'])
+			return $item['verb'];
+		return ACTIVITY_POST;
+	}
+
+	function construct_objecttype($item) {
+		if (in_array($item['object-type'], array(ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_COMMENT)))
+			return $item['object-type'];
+		return ACTIVITY_OBJ_NOTE;
+	}
+
+	private function entry($doc, $item, $owner, $toplevel = false) {
+		$repeated_guid = self::get_reshared_guid($item);
+		if ($repeated_guid != "")
+			$xml = self::reshare_entry($doc, $item, $owner, $repeated_guid, $toplevel);
+
+		if ($xml)
+			return $xml;
+
+		if ($item["verb"] == ACTIVITY_LIKE)
+			return self::like_entry($doc, $item, $owner, $toplevel);
+		else
+			return self::note_entry($doc, $item, $owner, $toplevel);
+	}
+
+	private function source_entry($doc, $contact) {
+		$source = $doc->createElement("source");
+		xml2::add_element($doc, $source, "id", $contact["poll"]);
+		xml2::add_element($doc, $source, "title", $contact["name"]);
+		xml2::add_element($doc, $source, "link", "", array("rel" => "alternate",
+								"type" => "text/html",
+								"href" => $contact["alias"]));
+		xml2::add_element($doc, $source, "link", "", array("rel" => "self",
+								"type" => "application/atom+xml",
+								"href" => $contact["poll"]));
+		xml2::add_element($doc, $source, "icon", $contact["photo"]);
+		xml2::add_element($doc, $source, "updated", datetime_convert("UTC","UTC",$contact["success_update"]."+00:00",ATOM_TIME));
+
+		return $source;
+	}
+
+	private function contact_entry($url, $owner) {
+
+		$r = q("SELECT * FROM `contact` WHERE `nurl` = '%s' AND `uid` IN (0, %d) ORDER BY `uid` DESC LIMIT 1",
+			dbesc(normalise_link($url)), intval($owner["uid"]));
+		if ($r) {
+			$contact = $r[0];
+			$contact["uid"] = -1;
+		}
+
+		if (!$r) {
+			$r = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1",
+				dbesc(normalise_link($url)));
+			if ($r) {
+				$contact = $r[0];
+				$contact["uid"] = -1;
+				$contact["success_update"] = $contact["updated"];
+			}
+		}
+
+		if (!$r)
+			$contact = owner;
+
+		if (!isset($contact["poll"])) {
+			$data = probe_url($url);
+			$contact["alias"] = $data["alias"];
+			$contact["poll"] = $data["poll"];
+		}
+
+		if (!isset($contact["alias"]))
+			$contact["alias"] = $contact["url"];
+
+		return $contact;
+	}
+
+	private function reshare_entry($doc, $item, $owner, $repeated_guid, $toplevel) {
+
+		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
+			logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
+		}
+
+		$title = self::entry_header($doc, $entry, $owner, $toplevel);
+
+		$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' AND NOT `private` AND `network` IN ('%s', '%s', '%s') LIMIT 1",
+			intval($owner["uid"]), dbesc($repeated_guid),
+			dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
+		if ($r)
+			$repeated_item = $r[0];
+		else
+			return false;
+
+		$contact = self::contact_entry($repeated_item['author-link'], $owner);
+
+		$parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']);
+
+		$title = $owner["nick"]." repeated a notice by ".$contact["nick"];
+
+		self::entry_content($doc, $entry, $item, $owner, $title, ACTIVITY_SHARE, false);
+
+		$as_object = $doc->createElement("activity:object");
+
+// ostatusWaEeYs
+// ostatusogu9zg - besser
+		xml2::add_element($doc, $as_object, "activity:object-type", NAMESPACE_ACTIVITY_SCHEMA."activity");
+
+		self::entry_content($doc, $as_object, $repeated_item, $owner, "", "", false);
+
+		$author = self::add_author($doc, $contact);
+                $as_object->appendChild($author);
+
+		$as_object2 = $doc->createElement("activity:object");
+
+		xml2::add_element($doc, $as_object2, "activity:object-type", self::construct_objecttype($repeated_item));
+
+		$title = sprintf("New comment by %s", $contact["nick"]);
+
+		self::entry_content($doc, $as_object2, $repeated_item, $owner, $title);
+
+		$as_object->appendChild($as_object2);
+
+		self::entry_footer($doc, $as_object, $item, $owner, false);
+
+		$source = self::source_entry($doc, $contact);
+
+		$as_object->appendChild($source);
+
+		$entry->appendChild($as_object);
+
+		self::entry_footer($doc, $entry, $item, $owner);
+
+		return $entry;
+	}
+
+	private function like_entry($doc, $item, $owner, $toplevel) {
+
+		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
+			logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
+		}
+
+		$title = self::entry_header($doc, $entry, $owner, $toplevel);
+
+		$verb = NAMESPACE_ACTIVITY_SCHEMA."favorite";
+		self::entry_content($doc, $entry, $item, $owner, "Favorite", $verb, false);
+
+		$as_object = $doc->createElement("activity:object");
+
+		$parent = q("SELECT * FROM `item` WHERE `id` = %d", intval($item["parent"]));
+		$parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']);
+
+		xml2::add_element($doc, $as_object, "activity:object-type", self::construct_objecttype($parent[0]));
+
+		self::entry_content($doc, $as_object, $parent[0], $owner, "New entry");
+
+		$entry->appendChild($as_object);
+
+		self::entry_footer($doc, $entry, $item, $owner);
+
+		return $entry;
+	}
+
+	private function note_entry($doc, $item, $owner, $toplevel) {
+
+		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
+			logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
+		}
+
+		$title = self::entry_header($doc, $entry, $owner, $toplevel);
+
+		xml2::add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE);
+
+		self::entry_content($doc, $entry, $item, $owner, $title);
+
+		self::entry_footer($doc, $entry, $item, $owner);
+
+		return $entry;
+	}
+
+	private function entry_header($doc, &$entry, $owner, $toplevel) {
+		if (!$toplevel) {
+			$entry = $doc->createElement("entry");
+			$title = sprintf("New note by %s", $owner["nick"]);
+		} else {
+			$entry = $doc->createElementNS(NAMESPACE_ATOM1, "entry");
+
+			$entry->setAttribute("xmlns:thr", NAMESPACE_THREAD);
+			$entry->setAttribute("xmlns:georss", NAMESPACE_GEORSS);
+			$entry->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY);
+			$entry->setAttribute("xmlns:media", NAMESPACE_MEDIA);
+			$entry->setAttribute("xmlns:poco", NAMESPACE_POCO);
+			$entry->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
+			$entry->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
+
+			$author = self::add_author($doc, $owner);
+			$entry->appendChild($author);
+
+			$title = sprintf("New comment by %s", $owner["nick"]);
+		}
+		return $title;
+	}
+
+	private function entry_content($doc, $entry, $item, $owner, $title, $verb = "", $complete = true) {
+
+		if ($verb == "")
+			$verb = self::construct_verb($item);
+
+		xml2::add_element($doc, $entry, "id", $item["uri"]);
+		xml2::add_element($doc, $entry, "title", $title);
+
+		$body = self::format_picture_post($item['body']);
+
+		if ($item['title'] != "")
+			$body = "[b]".$item['title']."[/b]\n\n".$body;
+
+		$body = bbcode($body, false, false, 7);
+
+		xml2::add_element($doc, $entry, "content", $body, array("type" => "html"));
+
+		xml2::add_element($doc, $entry, "link", "", array("rel" => "alternate", "type" => "text/html",
+								"href" => App::get_baseurl()."/display/".$item["guid"]));
+
+		if ($complete)
+			xml2::add_element($doc, $entry, "status_net", "", array("notice_id" => $item["id"]));
+
+		xml2::add_element($doc, $entry, "activity:verb", $verb);
+
+		xml2::add_element($doc, $entry, "published", datetime_convert("UTC","UTC",$item["created"]."+00:00",ATOM_TIME));
+		xml2::add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME));
+	}
+
+	private function entry_footer($doc, $entry, $item, $owner, $complete = true) {
+
+		$mentioned = array();
+
+		if (($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || (($item['thr-parent'] !== '') && ($item['thr-parent'] !== $item['uri']))) {
+			$parent = q("SELECT `guid`, `author-link`, `owner-link` FROM `item` WHERE `id` = %d", intval($item["parent"]));
+			$parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']);
+
+			$attributes = array(
+					"ref" => $parent_item,
+					"type" => "text/html",
+					"href" => App::get_baseurl()."/display/".$parent[0]["guid"]);
+			xml2::add_element($doc, $entry, "thr:in-reply-to", "", $attributes);
+
+			$attributes = array(
+					"rel" => "related",
+					"href" => App::get_baseurl()."/display/".$parent[0]["guid"]);
+			xml2::add_element($doc, $entry, "link", "", $attributes);
+
+			$mentioned[$parent[0]["author-link"]] = $parent[0]["author-link"];
+			$mentioned[$parent[0]["owner-link"]] = $parent[0]["owner-link"];
+
+			$thrparent = q("SELECT `guid`, `author-link`, `owner-link` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
+					intval($owner["uid"]),
+					dbesc($parent_item));
+			if ($thrparent) {
+				$mentioned[$thrparent[0]["author-link"]] = $thrparent[0]["author-link"];
+				$mentioned[$thrparent[0]["owner-link"]] = $thrparent[0]["owner-link"];
+			}
+		}
+
+		xml2::add_element($doc, $entry, "link", "", array("rel" => "ostatus:conversation",
+							"href" => App::get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]));
+		xml2::add_element($doc, $entry, "ostatus:conversation", App::get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]);
+
+		$tags = item_getfeedtags($item);
+
+		if(count($tags))
+			foreach($tags as $t)
+				if ($t[0] == "@")
+					$mentioned[$t[1]] = $t[1];
+
+		// Make sure that mentions are accepted (GNU Social has problems with mixing HTTP and HTTPS)
+		$newmentions = array();
+		foreach ($mentioned AS $mention) {
+			$newmentions[str_replace("http://", "https://", $mention)] = str_replace("http://", "https://", $mention);
+			$newmentions[str_replace("https://", "http://", $mention)] = str_replace("https://", "http://", $mention);
+		}
+		$mentioned = $newmentions;
+
+		foreach ($mentioned AS $mention) {
+			$r = q("SELECT `forum`, `prv` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s'",
+				intval($owner["uid"]),
+				dbesc(normalise_link($mention)));
+			if ($r[0]["forum"] OR $r[0]["prv"])
+				xml2::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
+											"ostatus:object-type" => ACTIVITY_OBJ_GROUP,
+											"href" => $mention));
+			else
+				xml2::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
+											"ostatus:object-type" => ACTIVITY_OBJ_PERSON,
+											"href" => $mention));
+		}
+
+		if (!$item["private"]) {
+			xml2::add_element($doc, $entry, "link", "", array("rel" => "ostatus:attention",
+									"href" => "http://activityschema.org/collection/public"));
+			xml2::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
+									"ostatus:object-type" => "http://activitystrea.ms/schema/1.0/collection",
+									"href" => "http://activityschema.org/collection/public"));
+		}
+
+		if(count($tags))
+			foreach($tags as $t)
+				if ($t[0] != "@")
+					xml2::add_element($doc, $entry, "category", "", array("term" => $t[2]));
+
+		self::get_attachment($doc, $entry, $item);
+
+		if ($complete) {
+			$app = $item["app"];
+			if ($app == "")
+				$app = "web";
+
+			$attributes = array("local_id" => $item["id"], "source" => $app);
+
+			if (isset($parent["id"]))
+				$attributes["repeat_of"] = $parent["id"];
+
+			if ($item["coord"] != "")
+				xml2::add_element($doc, $entry, "georss:point", $item["coord"]);
+
+			xml2::add_element($doc, $entry, "statusnet:notice_info", "", $attributes);
+		}
+	}
+
+	public static function feed(&$a, $owner_nick, $last_update) {
+
+		$r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`
+				FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
+				WHERE `contact`.`self` AND `user`.`nickname` = '%s' LIMIT 1",
+				dbesc($owner_nick));
+		if (!$r)
+			return;
+
+		$owner = $r[0];
+
+		if(!strlen($last_update))
+			$last_update = 'now -30 days';
+
+		$check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s');
+
+		$items = q("SELECT STRAIGHT_JOIN `item`.*, `item`.`id` AS `item_id` FROM `item`
+				INNER JOIN `thread` ON `thread`.`iid` = `item`.`parent`
+				LEFT JOIN `item` AS `thritem` ON `thritem`.`uri`=`item`.`thr-parent` AND `thritem`.`uid`=`item`.`uid`
+				WHERE `item`.`uid` = %d AND `item`.`received` > '%s' AND NOT `item`.`private` AND NOT `item`.`deleted`
+					AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
+					AND ((`item`.`wall` AND (`item`.`parent` = `item`.`id`))
+						OR (`item`.`network` = '%s' AND ((`thread`.`network` IN ('%s', '%s')) OR (`thritem`.`network` IN ('%s', '%s')))) AND `thread`.`mention`)
+					AND ((`item`.`owner-link` IN ('%s', '%s') AND (`item`.`parent` = `item`.`id`))
+						OR (`item`.`author-link` IN ('%s', '%s')))
+				ORDER BY `item`.`received` DESC
+				LIMIT 0, 300",
+				intval($owner["uid"]), dbesc($check_date), dbesc(NETWORK_DFRN),
+				//dbesc(NETWORK_OSTATUS), dbesc(NETWORK_OSTATUS),
+				//dbesc(NETWORK_OSTATUS), dbesc(NETWORK_OSTATUS),
+				dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN),
+				dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN),
+				dbesc($owner["nurl"]), dbesc(str_replace("http://", "https://", $owner["nurl"])),
+				dbesc($owner["nurl"]), dbesc(str_replace("http://", "https://", $owner["nurl"]))
+			);
+
+		$doc = new DOMDocument('1.0', 'utf-8');
+		$doc->formatOutput = true;
+
+		$root = self::add_header($doc, $owner);
+
+		foreach ($items AS $item) {
+			$entry = self::entry($doc, $item, $owner);
+			$root->appendChild($entry);
+		}
+
+		return(trim($doc->saveXML()));
+	}
+
+	public static function salmon($item,$owner) {
+
+		$doc = new DOMDocument('1.0', 'utf-8');
+		$doc->formatOutput = true;
+
+		$entry = self::entry($doc, $item, $owner, true);
+
+		$doc->appendChild($entry);
+
+		return(trim($doc->saveXML()));
+	}
+}
+?>
diff --git a/include/pubsubpublish.php b/include/pubsubpublish.php
index 4fbb505146..625eefc261 100644
--- a/include/pubsubpublish.php
+++ b/include/pubsubpublish.php
@@ -16,7 +16,7 @@ function handle_pubsubhubbub() {
 
 		logger("Generate feed for user ".$rr['nickname']." - last updated ".$rr['last_update'], LOGGER_DEBUG);
 
-		$params = ostatus_feed($a, $rr['nickname'], $rr['last_update']);
+		$params = ostatus::feed($a, $rr['nickname'], $rr['last_update']);
 		$hmac_sig = hash_hmac("sha1", $params, $rr['secret']);
 
 		$headers = array("Content-type: application/atom+xml",
diff --git a/mod/salmon.php b/mod/salmon.php
index 9c22e42d11..37230a5573 100644
--- a/mod/salmon.php
+++ b/mod/salmon.php
@@ -84,7 +84,7 @@ function salmon_post(&$a) {
 	// decode the data
 	$data = base64url_decode($data);
 
-	$author = ostatus_salmon_author($data,$importer);
+	$author = ostatus::salmon_author($data,$importer);
 	$author_link = $author["author-link"];
 
 	if(! $author_link) {
@@ -181,7 +181,7 @@ function salmon_post(&$a) {
 
 	$contact_rec = ((count($r)) ? $r[0] : null);
 
-	ostatus_import($data,$importer,$contact_rec, $hub);
+	ostatus::import($data,$importer,$contact_rec, $hub);
 
 	http_status_exit(200);
 }

From 4a5a964d8959883b73c541af1fe6474fd835e1b9 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 30 Mar 2016 12:46:10 +0200
Subject: [PATCH 240/273] "Scrape" now respects the new url formats with
 "index.php"

---
 include/Scrape.php | 49 ++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 43 insertions(+), 6 deletions(-)

diff --git a/include/Scrape.php b/include/Scrape.php
index 03d21047e7..deff0b080f 100644
--- a/include/Scrape.php
+++ b/include/Scrape.php
@@ -356,7 +356,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 
 	$result = array();
 
-	if(! $url)
+	if (!$url)
 		return $result;
 
 	$result = Cache::get("probe_url:".$mode.":".$url);
@@ -365,6 +365,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 		return $result;
 	}
 
+	$original_url = $url;
 	$network = null;
 	$diaspora = false;
 	$diaspora_base = '';
@@ -393,7 +394,12 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 		else
 			$links = lrdd($url);
 
-		if(count($links)) {
+		if ((count($links) == 0) AND strstr($url, "/index.php")) {
+			$url = str_replace("/index.php", "", $url);
+			$links = lrdd($url);
+		}
+
+		if (count($links)) {
 			$has_lrdd = true;
 
 			logger('probe_url: found lrdd links: ' . print_r($links,true), LOGGER_DATA);
@@ -440,12 +446,21 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 			// aliases, let's hope we're lucky and get one that matches the feed author-uri because
 			// otherwise we're screwed.
 
+			$backup_alias = "";
+
 			foreach($links as $link) {
 				if($link['@attributes']['rel'] === 'alias') {
 					if(strpos($link['@attributes']['href'],'@') === false) {
 						if(isset($profile)) {
-							if(($link['@attributes']['href'] !== $profile) AND ($alias == ""))
-								$alias = unamp($link['@attributes']['href']);
+							$alias_url = $link['@attributes']['href'];
+
+							if(($alias_url !== $profile) AND ($backup_alias == "") AND
+								($alias_url !== str_replace("/index.php", "", $profile)))
+								$backup_alias = $alias_url;
+
+							if(($alias_url !== $profile) AND !strstr($alias_url, "index.php") AND
+								($alias_url !== str_replace("/index.php", "", $profile)))
+								$alias = $alias_url;
 						}
 						else
 							$profile = unamp($link['@attributes']['href']);
@@ -453,6 +468,9 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 				}
 			}
 
+			if ($alias == "")
+				$alias = $backup_alias;
+
 			// If the profile is different from the url then the url is abviously an alias
 			if (($alias == "") AND ($profile != "") AND !$at_addr AND (normalise_link($profile) != normalise_link($url)))
 				$alias = $url;
@@ -769,6 +787,9 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 	if (($baseurl == "") AND ($poll != ""))
 		$baseurl = matching_url(normalise_link($profile), normalise_link($poll));
 
+	if (substr($baseurl, -10) == "/index.php")
+		$baseurl = str_replace("/index.php", "", $baseurl);
+
 	$baseurl = rtrim($baseurl, "/");
 
 	if(strpos($url,'@') AND ($addr == "") AND ($network == NETWORK_DFRN))
@@ -816,8 +837,24 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 	}
 
 	// Only store into the cache if the value seems to be valid
-	if ($result['network'] != NETWORK_PHANTOM)
-		Cache::set("probe_url:".$mode.":".$url,serialize($result), CACHE_DAY);
+	if ($result['network'] != NETWORK_PHANTOM) {
+		Cache::set("probe_url:".$mode.":".$original_url,serialize($result), CACHE_DAY);
+
+		/// @todo temporary fix - we need a real contact update function that updates only changing fields
+		/// The biggest problem is the avatar picture that could have a reduced image size.
+		/// It should only be updated if the existing picture isn't existing anymore.
+		if (($result['network'] != NETWORK_FEED) AND $result["addr"] AND $result["name"] AND $result["nick"])
+			q("UPDATE `contact` SET `addr` = '%s', `alias` = '%s', `name` = '%s', `nick` = '%s',
+				`name-date` = '%s', `uri-date` = '%s' WHERE `nurl` = '%s' AND NOT `self`",
+				dbesc($result["addr"]),
+				dbesc($result["alias"]),
+				dbesc($result["name"]),
+				dbesc($result["nick"]),
+				dbesc(datetime_convert()),
+				dbesc(datetime_convert()),
+				dbesc(normalise_link($result['url']))
+		);
+	}
 
 	return $result;
 }

From 2c5b5c1cd471c890b7e06e28dc979c2a0e8736b0 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 30 Mar 2016 23:25:20 +0200
Subject: [PATCH 241/273] OStatus class is now moved into the right place

---
 include/cron.php    |    4 +-
 include/dfrn.php    |  191 +--
 include/ostatus.php | 3081 ++++++++++++++++++++++---------------------
 include/xml.php     |   35 +
 4 files changed, 1688 insertions(+), 1623 deletions(-)

diff --git a/include/cron.php b/include/cron.php
index 60c62786e6..c60284b738 100644
--- a/include/cron.php
+++ b/include/cron.php
@@ -101,10 +101,10 @@ function cron_run(&$argv, &$argc){
 
 	// Check OStatus conversations
 	// Check only conversations with mentions (for a longer time)
-	check_conversations(true);
+	ostatus::check_conversations(true);
 
 	// Check every conversation
-	check_conversations(false);
+	ostatus::check_conversations(false);
 
 	// Set the gcontact-id in the item table if missing
 	item_set_gcontact();
diff --git a/include/dfrn.php b/include/dfrn.php
index d96805a56b..14be747305 100644
--- a/include/dfrn.php
+++ b/include/dfrn.php
@@ -19,6 +19,7 @@ require_once("include/text.php");
 require_once("include/oembed.php");
 require_once("include/html2bbcode.php");
 require_once("include/bbcode.php");
+require_once("include/xml.php");
 
 /**
  * @brief This class contain functions to create and send DFRN XML files
@@ -286,17 +287,17 @@ class dfrn {
 		$mail = $doc->createElement("dfrn:mail");
 		$sender = $doc->createElement("dfrn:sender");
 
-		xml_add_element($doc, $sender, "dfrn:name", $owner['name']);
-		xml_add_element($doc, $sender, "dfrn:uri", $owner['url']);
-		xml_add_element($doc, $sender, "dfrn:avatar", $owner['thumb']);
+		xml::add_element($doc, $sender, "dfrn:name", $owner['name']);
+		xml::add_element($doc, $sender, "dfrn:uri", $owner['url']);
+		xml::add_element($doc, $sender, "dfrn:avatar", $owner['thumb']);
 
 		$mail->appendChild($sender);
 
-		xml_add_element($doc, $mail, "dfrn:id", $item['uri']);
-		xml_add_element($doc, $mail, "dfrn:in-reply-to", $item['parent-uri']);
-		xml_add_element($doc, $mail, "dfrn:sentdate", datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME));
-		xml_add_element($doc, $mail, "dfrn:subject", $item['title']);
-		xml_add_element($doc, $mail, "dfrn:content", $item['body']);
+		xml::add_element($doc, $mail, "dfrn:id", $item['uri']);
+		xml::add_element($doc, $mail, "dfrn:in-reply-to", $item['parent-uri']);
+		xml::add_element($doc, $mail, "dfrn:sentdate", datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME));
+		xml::add_element($doc, $mail, "dfrn:subject", $item['title']);
+		xml::add_element($doc, $mail, "dfrn:content", $item['body']);
 
 		$root->appendChild($mail);
 
@@ -319,11 +320,11 @@ class dfrn {
 
 		$suggest = $doc->createElement("dfrn:suggest");
 
-		xml_add_element($doc, $suggest, "dfrn:url", $item['url']);
-		xml_add_element($doc, $suggest, "dfrn:name", $item['name']);
-		xml_add_element($doc, $suggest, "dfrn:photo", $item['photo']);
-		xml_add_element($doc, $suggest, "dfrn:request", $item['request']);
-		xml_add_element($doc, $suggest, "dfrn:note", $item['note']);
+		xml::add_element($doc, $suggest, "dfrn:url", $item['url']);
+		xml::add_element($doc, $suggest, "dfrn:name", $item['name']);
+		xml::add_element($doc, $suggest, "dfrn:photo", $item['photo']);
+		xml::add_element($doc, $suggest, "dfrn:request", $item['request']);
+		xml::add_element($doc, $suggest, "dfrn:note", $item['note']);
 
 		$root->appendChild($suggest);
 
@@ -365,16 +366,16 @@ class dfrn {
 
 		$relocate = $doc->createElement("dfrn:relocate");
 
-		xml_add_element($doc, $relocate, "dfrn:url", $owner['url']);
-		xml_add_element($doc, $relocate, "dfrn:name", $owner['name']);
-		xml_add_element($doc, $relocate, "dfrn:photo", $photos[4]);
-		xml_add_element($doc, $relocate, "dfrn:thumb", $photos[5]);
-		xml_add_element($doc, $relocate, "dfrn:micro", $photos[6]);
-		xml_add_element($doc, $relocate, "dfrn:request", $owner['request']);
-		xml_add_element($doc, $relocate, "dfrn:confirm", $owner['confirm']);
-		xml_add_element($doc, $relocate, "dfrn:notify", $owner['notify']);
-		xml_add_element($doc, $relocate, "dfrn:poll", $owner['poll']);
-		xml_add_element($doc, $relocate, "dfrn:sitepubkey", get_config('system','site_pubkey'));
+		xml::add_element($doc, $relocate, "dfrn:url", $owner['url']);
+		xml::add_element($doc, $relocate, "dfrn:name", $owner['name']);
+		xml::add_element($doc, $relocate, "dfrn:photo", $photos[4]);
+		xml::add_element($doc, $relocate, "dfrn:thumb", $photos[5]);
+		xml::add_element($doc, $relocate, "dfrn:micro", $photos[6]);
+		xml::add_element($doc, $relocate, "dfrn:request", $owner['request']);
+		xml::add_element($doc, $relocate, "dfrn:confirm", $owner['confirm']);
+		xml::add_element($doc, $relocate, "dfrn:notify", $owner['notify']);
+		xml::add_element($doc, $relocate, "dfrn:poll", $owner['poll']);
+		xml::add_element($doc, $relocate, "dfrn:sitepubkey", get_config('system','site_pubkey'));
 
 		$root->appendChild($relocate);
 
@@ -410,39 +411,39 @@ class dfrn {
 		$root->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
 		$root->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
 
-		xml_add_element($doc, $root, "id", app::get_baseurl()."/profile/".$owner["nick"]);
-		xml_add_element($doc, $root, "title", $owner["name"]);
+		xml::add_element($doc, $root, "id", app::get_baseurl()."/profile/".$owner["nick"]);
+		xml::add_element($doc, $root, "title", $owner["name"]);
 
 		$attributes = array("uri" => "https://friendi.ca", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION);
-		xml_add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes);
+		xml::add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes);
 
 		$attributes = array("rel" => "license", "href" => "http://creativecommons.org/licenses/by/3.0/");
-		xml_add_element($doc, $root, "link", "", $attributes);
+		xml::add_element($doc, $root, "link", "", $attributes);
 
 		$attributes = array("rel" => "alternate", "type" => "text/html", "href" => $alternatelink);
-		xml_add_element($doc, $root, "link", "", $attributes);
+		xml::add_element($doc, $root, "link", "", $attributes);
 
 
 		if ($public) {
 			// DFRN itself doesn't uses this. But maybe someone else wants to subscribe to the public feed.
-			ostatus_hublinks($doc, $root);
+			ostatus::hublinks($doc, $root);
 
 			$attributes = array("rel" => "salmon", "href" => app::get_baseurl()."/salmon/".$owner["nick"]);
-			xml_add_element($doc, $root, "link", "", $attributes);
+			xml::add_element($doc, $root, "link", "", $attributes);
 
 			$attributes = array("rel" => "http://salmon-protocol.org/ns/salmon-replies", "href" => app::get_baseurl()."/salmon/".$owner["nick"]);
-			xml_add_element($doc, $root, "link", "", $attributes);
+			xml::add_element($doc, $root, "link", "", $attributes);
 
 			$attributes = array("rel" => "http://salmon-protocol.org/ns/salmon-mention", "href" => app::get_baseurl()."/salmon/".$owner["nick"]);
-			xml_add_element($doc, $root, "link", "", $attributes);
+			xml::add_element($doc, $root, "link", "", $attributes);
 		}
 
 		if ($owner['page-flags'] == PAGE_COMMUNITY)
-			xml_add_element($doc, $root, "dfrn:community", 1);
+			xml::add_element($doc, $root, "dfrn:community", 1);
 
 		/// @todo We need a way to transmit the different page flags like "PAGE_PRVGROUP"
 
-		xml_add_element($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME));
+		xml::add_element($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME));
 
 		$author = self::add_author($doc, $owner, $authorelement, $public);
 		$root->appendChild($author);
@@ -468,26 +469,26 @@ class dfrn {
 		$picdate = datetime_convert('UTC', 'UTC', $owner['avatar-date'].'+00:00', ATOM_TIME);
 
 		$attributes = array("dfrn:updated" => $namdate);
-		xml_add_element($doc, $author, "name", $owner["name"], $attributes);
+		xml::add_element($doc, $author, "name", $owner["name"], $attributes);
 
 		$attributes = array("dfrn:updated" => $namdate);
-		xml_add_element($doc, $author, "uri", app::get_baseurl().'/profile/'.$owner["nickname"], $attributes);
+		xml::add_element($doc, $author, "uri", app::get_baseurl().'/profile/'.$owner["nickname"], $attributes);
 
 		$attributes = array("dfrn:updated" => $namdate);
-		xml_add_element($doc, $author, "dfrn:handle", $owner["addr"], $attributes);
+		xml::add_element($doc, $author, "dfrn:handle", $owner["addr"], $attributes);
 
 		$attributes = array("rel" => "photo", "type" => "image/jpeg", "dfrn:updated" => $picdate,
 					"media:width" => 175, "media:height" => 175, "href" => $owner['photo']);
-		xml_add_element($doc, $author, "link", "", $attributes);
+		xml::add_element($doc, $author, "link", "", $attributes);
 
 		$attributes = array("rel" => "avatar", "type" => "image/jpeg", "dfrn:updated" => $picdate,
 					"media:width" => 175, "media:height" => 175, "href" => $owner['photo']);
-		xml_add_element($doc, $author, "link", "", $attributes);
+		xml::add_element($doc, $author, "link", "", $attributes);
 
 		$birthday = feed_birthday($owner['uid'], $owner['timezone']);
 
 		if ($birthday)
-			xml_add_element($doc, $author, "dfrn:birthday", $birthday);
+			xml::add_element($doc, $author, "dfrn:birthday", $birthday);
 
 		// The following fields will only be generated if this isn't for a public feed
 		if ($public)
@@ -502,25 +503,25 @@ class dfrn {
 			intval($owner['uid']));
 		if ($r) {
 			$profile = $r[0];
-			xml_add_element($doc, $author, "poco:displayName", $profile["name"]);
-			xml_add_element($doc, $author, "poco:updated", $namdate);
+			xml::add_element($doc, $author, "poco:displayName", $profile["name"]);
+			xml::add_element($doc, $author, "poco:updated", $namdate);
 
 			if (trim($profile["dob"]) != "0000-00-00")
-				xml_add_element($doc, $author, "poco:birthday", "0000-".date("m-d", strtotime($profile["dob"])));
+				xml::add_element($doc, $author, "poco:birthday", "0000-".date("m-d", strtotime($profile["dob"])));
 
-			xml_add_element($doc, $author, "poco:note", $profile["about"]);
-			xml_add_element($doc, $author, "poco:preferredUsername", $profile["nickname"]);
+			xml::add_element($doc, $author, "poco:note", $profile["about"]);
+			xml::add_element($doc, $author, "poco:preferredUsername", $profile["nickname"]);
 
 			$savetz = date_default_timezone_get();
 			date_default_timezone_set($profile["timezone"]);
-			xml_add_element($doc, $author, "poco:utcOffset", date("P"));
+			xml::add_element($doc, $author, "poco:utcOffset", date("P"));
 			date_default_timezone_set($savetz);
 
 			if (trim($profile["homepage"]) != "") {
 				$urls = $doc->createElement("poco:urls");
-				xml_add_element($doc, $urls, "poco:type", "homepage");
-				xml_add_element($doc, $urls, "poco:value", $profile["homepage"]);
-				xml_add_element($doc, $urls, "poco:primary", "true");
+				xml::add_element($doc, $urls, "poco:type", "homepage");
+				xml::add_element($doc, $urls, "poco:value", $profile["homepage"]);
+				xml::add_element($doc, $urls, "poco:primary", "true");
 				$author->appendChild($urls);
 			}
 
@@ -528,7 +529,7 @@ class dfrn {
 				$keywords = explode(",", $profile["pub_keywords"]);
 
 				foreach ($keywords AS $keyword)
-					xml_add_element($doc, $author, "poco:tags", trim($keyword));
+					xml::add_element($doc, $author, "poco:tags", trim($keyword));
 
 			}
 
@@ -536,25 +537,25 @@ class dfrn {
 			$xmpp = "";
 			if (trim($xmpp) != "") {
 				$ims = $doc->createElement("poco:ims");
-				xml_add_element($doc, $ims, "poco:type", "xmpp");
-				xml_add_element($doc, $ims, "poco:value", $xmpp);
-				xml_add_element($doc, $ims, "poco:primary", "true");
+				xml::add_element($doc, $ims, "poco:type", "xmpp");
+				xml::add_element($doc, $ims, "poco:value", $xmpp);
+				xml::add_element($doc, $ims, "poco:primary", "true");
 				$author->appendChild($ims);
 			}
 
 			if (trim($profile["locality"].$profile["region"].$profile["country-name"]) != "") {
 				$element = $doc->createElement("poco:address");
 
-				xml_add_element($doc, $element, "poco:formatted", formatted_location($profile));
+				xml::add_element($doc, $element, "poco:formatted", formatted_location($profile));
 
 				if (trim($profile["locality"]) != "")
-					xml_add_element($doc, $element, "poco:locality", $profile["locality"]);
+					xml::add_element($doc, $element, "poco:locality", $profile["locality"]);
 
 				if (trim($profile["region"]) != "")
-					xml_add_element($doc, $element, "poco:region", $profile["region"]);
+					xml::add_element($doc, $element, "poco:region", $profile["region"]);
 
 				if (trim($profile["country-name"]) != "")
-					xml_add_element($doc, $element, "poco:country", $profile["country-name"]);
+					xml::add_element($doc, $element, "poco:country", $profile["country-name"]);
 
 				$author->appendChild($element);
 			}
@@ -578,9 +579,9 @@ class dfrn {
 		$contact = get_contact_details_by_url($contact_url, $item["uid"]);
 
 		$author = $doc->createElement($element);
-		xml_add_element($doc, $author, "name", $contact["name"]);
-		xml_add_element($doc, $author, "uri", $contact["url"]);
-		xml_add_element($doc, $author, "dfrn:handle", $contact["addr"]);
+		xml::add_element($doc, $author, "name", $contact["name"]);
+		xml::add_element($doc, $author, "uri", $contact["url"]);
+		xml::add_element($doc, $author, "dfrn:handle", $contact["addr"]);
 
 		/// @Todo
 		/// - Check real image type and image size
@@ -591,7 +592,7 @@ class dfrn {
 				"media:width" => 80,
 				"media:height" => 80,
 				"href" => $contact["photo"]);
-		xml_add_element($doc, $author, "link", "", $attributes);
+		xml::add_element($doc, $author, "link", "", $attributes);
 
 		$attributes = array(
 				"rel" => "avatar",
@@ -599,7 +600,7 @@ class dfrn {
 				"media:width" => 80,
 				"media:height" => 80,
 				"href" => $contact["photo"]);
-		xml_add_element($doc, $author, "link", "", $attributes);
+		xml::add_element($doc, $author, "link", "", $attributes);
 
 		return $author;
 	}
@@ -622,11 +623,11 @@ class dfrn {
 			if(!$r)
 				return false;
 			if($r->type)
-				xml_add_element($doc, $entry, "activity:object-type", $r->type);
+				xml::add_element($doc, $entry, "activity:object-type", $r->type);
 			if($r->id)
-				xml_add_element($doc, $entry, "id", $r->id);
+				xml::add_element($doc, $entry, "id", $r->id);
 			if($r->title)
-				xml_add_element($doc, $entry, "title", $r->title);
+				xml::add_element($doc, $entry, "title", $r->title);
 			if($r->link) {
 				if(substr($r->link,0,1) == '<') {
 					if(strstr($r->link,'&') && (! strstr($r->link,'&amp;')))
@@ -641,16 +642,16 @@ class dfrn {
 							$attributes = array();
 							foreach ($link->attributes() AS $parameter => $value)
 								$attributes[$parameter] = $value;
-							xml_add_element($doc, $entry, "link", "", $attributes);
+							xml::add_element($doc, $entry, "link", "", $attributes);
 						}
 					}
 				} else {
 					$attributes = array("rel" => "alternate", "type" => "text/html", "href" => $r->link);
-					xml_add_element($doc, $entry, "link", "", $attributes);
+					xml::add_element($doc, $entry, "link", "", $attributes);
 				}
 			}
 			if($r->content)
-				xml_add_element($doc, $entry, "content", bbcode($r->content), array("type" => "html"));
+				xml::add_element($doc, $entry, "content", bbcode($r->content), array("type" => "html"));
 
 			return $entry;
 		}
@@ -684,7 +685,7 @@ class dfrn {
 					if(trim($matches[4]) != "")
 						$attributes["title"] = trim($matches[4]);
 
-					xml_add_element($doc, $root, "link", "", $attributes);
+					xml::add_element($doc, $root, "link", "", $attributes);
 				}
 			}
 		}
@@ -711,7 +712,7 @@ class dfrn {
 
 		if($item['deleted']) {
 			$attributes = array("ref" => $item['uri'], "when" => datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME));
-			return xml_create_element($doc, "at:deleted-entry", "", $attributes);
+			return xml::create_element($doc, "at:deleted-entry", "", $attributes);
 		}
 
 		$entry = $doc->createElement("entry");
@@ -745,66 +746,66 @@ class dfrn {
 			$attributes = array("ref" => $parent_item, "type" => "text/html",
 						"href" => app::get_baseurl().'/display/'.$parent[0]['guid'],
 						"dfrn:diaspora_guid" => $parent[0]['guid']);
-			xml_add_element($doc, $entry, "thr:in-reply-to", "", $attributes);
+			xml::add_element($doc, $entry, "thr:in-reply-to", "", $attributes);
 		}
 
-		xml_add_element($doc, $entry, "id", $item["uri"]);
-		xml_add_element($doc, $entry, "title", $item["title"]);
+		xml::add_element($doc, $entry, "id", $item["uri"]);
+		xml::add_element($doc, $entry, "title", $item["title"]);
 
-		xml_add_element($doc, $entry, "published", datetime_convert("UTC","UTC",$item["created"]."+00:00",ATOM_TIME));
-		xml_add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME));
+		xml::add_element($doc, $entry, "published", datetime_convert("UTC","UTC",$item["created"]."+00:00",ATOM_TIME));
+		xml::add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME));
 
 		// "dfrn:env" is used to read the content
-		xml_add_element($doc, $entry, "dfrn:env", base64url_encode($body, true));
+		xml::add_element($doc, $entry, "dfrn:env", base64url_encode($body, true));
 
 		// The "content" field is not read by the receiver. We could remove it when the type is "text"
 		// We keep it at the moment, maybe there is some old version that doesn't read "dfrn:env"
-		xml_add_element($doc, $entry, "content", (($type == 'html') ? $htmlbody : $body), array("type" => $type));
+		xml::add_element($doc, $entry, "content", (($type == 'html') ? $htmlbody : $body), array("type" => $type));
 
 		// We save this value in "plink". Maybe we should read it from there as well?
-		xml_add_element($doc, $entry, "link", "", array("rel" => "alternate", "type" => "text/html",
+		xml::add_element($doc, $entry, "link", "", array("rel" => "alternate", "type" => "text/html",
 								"href" => app::get_baseurl()."/display/".$item["guid"]));
 
 		// "comment-allow" is some old fashioned stuff for old Friendica versions.
 		// It is included in the rewritten code for completeness
 		if ($comment)
-			xml_add_element($doc, $entry, "dfrn:comment-allow", intval($item['last-child']));
+			xml::add_element($doc, $entry, "dfrn:comment-allow", intval($item['last-child']));
 
 		if($item['location'])
-			xml_add_element($doc, $entry, "dfrn:location", $item['location']);
+			xml::add_element($doc, $entry, "dfrn:location", $item['location']);
 
 		if($item['coord'])
-			xml_add_element($doc, $entry, "georss:point", $item['coord']);
+			xml::add_element($doc, $entry, "georss:point", $item['coord']);
 
 		if(($item['private']) || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid']))
-			xml_add_element($doc, $entry, "dfrn:private", (($item['private']) ? $item['private'] : 1));
+			xml::add_element($doc, $entry, "dfrn:private", (($item['private']) ? $item['private'] : 1));
 
 		if($item['extid'])
-			xml_add_element($doc, $entry, "dfrn:extid", $item['extid']);
+			xml::add_element($doc, $entry, "dfrn:extid", $item['extid']);
 
 		if($item['bookmark'])
-			xml_add_element($doc, $entry, "dfrn:bookmark", "true");
+			xml::add_element($doc, $entry, "dfrn:bookmark", "true");
 
 		if($item['app'])
-			xml_add_element($doc, $entry, "statusnet:notice_info", "", array("local_id" => $item['id'], "source" => $item['app']));
+			xml::add_element($doc, $entry, "statusnet:notice_info", "", array("local_id" => $item['id'], "source" => $item['app']));
 
-		xml_add_element($doc, $entry, "dfrn:diaspora_guid", $item["guid"]);
+		xml::add_element($doc, $entry, "dfrn:diaspora_guid", $item["guid"]);
 
 		// The signed text contains the content in Markdown, the sender handle and the signatur for the content
 		// It is needed for relayed comments to Diaspora.
 		if($item['signed_text']) {
 			$sign = base64_encode(json_encode(array('signed_text' => $item['signed_text'],'signature' => $item['signature'],'signer' => $item['signer'])));
-			xml_add_element($doc, $entry, "dfrn:diaspora_signature", $sign);
+			xml::add_element($doc, $entry, "dfrn:diaspora_signature", $sign);
 		}
 
-		xml_add_element($doc, $entry, "activity:verb", construct_verb($item));
+		xml::add_element($doc, $entry, "activity:verb", construct_verb($item));
 
 		if ($item['object-type'] != "")
-			xml_add_element($doc, $entry, "activity:object-type", $item['object-type']);
+			xml::add_element($doc, $entry, "activity:object-type", $item['object-type']);
 		elseif ($item['id'] == $item['parent'])
-			xml_add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE);
+			xml::add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE);
 		else
-			xml_add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_COMMENT);
+			xml::add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_COMMENT);
 
 		$actobj = self::create_activity($doc, "activity:object", $item['object']);
 		if ($actobj)
@@ -819,7 +820,7 @@ class dfrn {
 		if(count($tags)) {
 			foreach($tags as $t)
 				if (($type != 'html') OR ($t[0] != "@"))
-					xml_add_element($doc, $entry, "category", "", array("scheme" => "X-DFRN:".$t[0].":".$t[1], "term" => $t[2]));
+					xml::add_element($doc, $entry, "category", "", array("scheme" => "X-DFRN:".$t[0].":".$t[1], "term" => $t[2]));
 		}
 
 		if(count($tags))
@@ -832,11 +833,11 @@ class dfrn {
 				intval($owner["uid"]),
 				dbesc(normalise_link($mention)));
 			if ($r[0]["forum"] OR $r[0]["prv"])
-				xml_add_element($doc, $entry, "link", "", array("rel" => "mentioned",
+				xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
 											"ostatus:object-type" => ACTIVITY_OBJ_GROUP,
 											"href" => $mention));
 			else
-				xml_add_element($doc, $entry, "link", "", array("rel" => "mentioned",
+				xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
 											"ostatus:object-type" => ACTIVITY_OBJ_PERSON,
 											"href" => $mention));
 		}
@@ -1323,7 +1324,7 @@ class dfrn {
 		$obj_element = $obj_doc->createElementNS(NAMESPACE_ATOM1, $element);
 
 		$activity_type = $xpath->query("activity:object-type/text()", $activity)->item(0)->nodeValue;
-		xml_add_element($obj_doc, $obj_element, "type", $activity_type);
+		xml::add_element($obj_doc, $obj_element, "type", $activity_type);
 
 		$id = $xpath->query("atom:id", $activity)->item(0);
 		if (is_object($id))
diff --git a/include/ostatus.php b/include/ostatus.php
index 02447e3ade..ba5b80cd5d 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -12,485 +12,429 @@ require_once("include/Scrape.php");
 require_once("include/follow.php");
 require_once("include/api.php");
 require_once("mod/proxy.php");
-require_once("include/ostatus2.php");
+require_once("include/xml.php");
 
-define('OSTATUS_DEFAULT_POLL_INTERVAL', 30); // given in minutes
-define('OSTATUS_DEFAULT_POLL_TIMEFRAME', 1440); // given in minutes
-define('OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS', 14400); // given in minutes
+class ostatus {
+	const OSTATUS_DEFAULT_POLL_INTERVAL = 30; // given in minutes
+	const OSTATUS_DEFAULT_POLL_TIMEFRAME = 1440; // given in minutes
+	const OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS = 14400; // given in minutes
 
-function ostatus_check_follow_friends() {
-	$r = q("SELECT `uid`,`v` FROM `pconfig` WHERE `cat`='system' AND `k`='ostatus_legacy_contact' AND `v` != ''");
+	private function fetchauthor($xpath, $context, $importer, &$contact, $onlyfetch) {
 
-	if (!$r)
-		return;
+		$author = array();
+		$author["author-link"] = $xpath->evaluate('atom:author/atom:uri/text()', $context)->item(0)->nodeValue;
+		$author["author-name"] = $xpath->evaluate('atom:author/atom:name/text()', $context)->item(0)->nodeValue;
 
-	foreach ($r AS $contact) {
-		ostatus_follow_friends($contact["uid"], $contact["v"]);
-		set_pconfig($contact["uid"], "system", "ostatus_legacy_contact", "");
-	}
-}
+		// Preserve the value
+		$authorlink = $author["author-link"];
 
-// This function doesn't work reliable by now.
-function ostatus_follow_friends($uid, $url) {
-	$contact = probe_url($url);
+		$alternate = $xpath->query("atom:author/atom:link[@rel='alternate']", $context)->item(0)->attributes;
+		if (is_object($alternate))
+			foreach($alternate AS $attributes)
+				if ($attributes->name == "href")
+					$author["author-link"] = $attributes->textContent;
 
-	if (!$contact)
-		return;
+		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'",
+			intval($importer["uid"]), dbesc(normalise_link($author["author-link"])),
+			dbesc(normalise_link($authorlink)), dbesc(NETWORK_STATUSNET));
+		if ($r) {
+			$contact = $r[0];
+			$author["contact-id"] = $r[0]["id"];
+		} else
+			$author["contact-id"] = $contact["id"];
 
-	$api = $contact["baseurl"]."/api/";
-
-	// Fetching friends
-	$data = z_fetch_url($api."statuses/friends.json?screen_name=".$contact["nick"]);
-
-	if (!$data["success"])
-		return;
-
-	$friends = json_decode($data["body"]);
-
-	foreach ($friends AS $friend) {
-		$url = $friend->statusnet_profile_url;
-		$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND
-			(`nurl` = '%s' OR `alias` = '%s' OR `alias` = '%s') AND
-			`network` != '%s' LIMIT 1",
-			intval($uid), dbesc(normalise_link($url)),
-			dbesc(normalise_link($url)), dbesc($url), dbesc(NETWORK_STATUSNET));
-		if (!$r) {
-			$data = probe_url($friend->statusnet_profile_url);
-			if ($data["network"] == NETWORK_OSTATUS) {
-				$result = new_contact($uid,$friend->statusnet_profile_url);
-				if ($result["success"])
-					logger($friend->name." ".$url." - success", LOGGER_DEBUG);
-				else
-					logger($friend->name." ".$url." - failed", LOGGER_DEBUG);
-			} else
-				logger($friend->name." ".$url." - not OStatus", LOGGER_DEBUG);
+		$avatarlist = array();
+		$avatars = $xpath->query("atom:author/atom:link[@rel='avatar']", $context);
+		foreach($avatars AS $avatar) {
+			$href = "";
+			$width = 0;
+			foreach($avatar->attributes AS $attributes) {
+				if ($attributes->name == "href")
+					$href = $attributes->textContent;
+				if ($attributes->name == "width")
+					$width = $attributes->textContent;
+			}
+			if (($width > 0) AND ($href != ""))
+				$avatarlist[$width] = $href;
 		}
-	}
-}
-
-function ostatus_fetchauthor($xpath, $context, $importer, &$contact, $onlyfetch) {
-
-	$author = array();
-	$author["author-link"] = $xpath->evaluate('atom:author/atom:uri/text()', $context)->item(0)->nodeValue;
-	$author["author-name"] = $xpath->evaluate('atom:author/atom:name/text()', $context)->item(0)->nodeValue;
-
-	// Preserve the value
-	$authorlink = $author["author-link"];
-
-	$alternate = $xpath->query("atom:author/atom:link[@rel='alternate']", $context)->item(0)->attributes;
-	if (is_object($alternate))
-		foreach($alternate AS $attributes)
-			if ($attributes->name == "href")
-				$author["author-link"] = $attributes->textContent;
-
-	$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'",
-		intval($importer["uid"]), dbesc(normalise_link($author["author-link"])),
-		dbesc(normalise_link($authorlink)), dbesc(NETWORK_STATUSNET));
-	if ($r) {
-		$contact = $r[0];
-		$author["contact-id"] = $r[0]["id"];
-	} else
-		$author["contact-id"] = $contact["id"];
-
-	$avatarlist = array();
-	$avatars = $xpath->query("atom:author/atom:link[@rel='avatar']", $context);
-	foreach($avatars AS $avatar) {
-		$href = "";
-		$width = 0;
-		foreach($avatar->attributes AS $attributes) {
-			if ($attributes->name == "href")
-				$href = $attributes->textContent;
-			if ($attributes->name == "width")
-				$width = $attributes->textContent;
-		}
-		if (($width > 0) AND ($href != ""))
-			$avatarlist[$width] = $href;
-	}
-	if (count($avatarlist) > 0) {
-		krsort($avatarlist);
-		$author["author-avatar"] = current($avatarlist);
-	}
-
-	$displayname = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue;
-	if ($displayname != "")
-		$author["author-name"] = $displayname;
-
-	$author["owner-name"] = $author["author-name"];
-	$author["owner-link"] = $author["author-link"];
-	$author["owner-avatar"] = $author["author-avatar"];
-
-	// Only update the contacts if it is an OStatus contact
-	if ($r AND !$onlyfetch AND ($contact["network"] == NETWORK_OSTATUS)) {
-		// Update contact data
-
-		$value = $xpath->query("atom:link[@rel='salmon']", $context)->item(0)->nodeValue;
-		if ($value != "")
-			$contact["notify"] = $value;
-
-		$value = $xpath->evaluate('atom:author/uri/text()', $context)->item(0)->nodeValue;
-		if ($value != "")
-			$contact["alias"] = $value;
-
-		$value = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue;
-		if ($value != "")
-			$contact["name"] = $value;
-
-		$value = $xpath->evaluate('atom:author/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
-		if ($value != "")
-			$contact["nick"] = $value;
-
-		$value = $xpath->evaluate('atom:author/poco:note/text()', $context)->item(0)->nodeValue;
-		if ($value != "")
-			$contact["about"] = html2bbcode($value);
-
-		$value = $xpath->evaluate('atom:author/poco:address/poco:formatted/text()', $context)->item(0)->nodeValue;
-		if ($value != "")
-			$contact["location"] = $value;
-
-		if (($contact["name"] != $r[0]["name"]) OR ($contact["nick"] != $r[0]["nick"]) OR ($contact["about"] != $r[0]["about"]) OR ($contact["location"] != $r[0]["location"])) {
-
-			logger("Update contact data for contact ".$contact["id"], LOGGER_DEBUG);
-
-			q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', `name-date` = '%s' WHERE `id` = %d",
-				dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
-				dbesc(datetime_convert()), intval($contact["id"]));
-
-			poco_check($contact["url"], $contact["name"], $contact["network"], $author["author-avatar"], $contact["about"], $contact["location"],
-						"", "", "", datetime_convert(), 2, $contact["id"], $contact["uid"]);
+		if (count($avatarlist) > 0) {
+			krsort($avatarlist);
+			$author["author-avatar"] = current($avatarlist);
 		}
 
-		if (isset($author["author-avatar"]) AND ($author["author-avatar"] != $r[0]['avatar'])) {
-			logger("Update profile picture for contact ".$contact["id"], LOGGER_DEBUG);
+		$displayname = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue;
+		if ($displayname != "")
+			$author["author-name"] = $displayname;
 
-			update_contact_avatar($author["author-avatar"], $importer["uid"], $contact["id"]);
-		}
+		$author["owner-name"] = $author["author-name"];
+		$author["owner-link"] = $author["author-link"];
+		$author["owner-avatar"] = $author["author-avatar"];
 
-		$contact["generation"] = 2;
-		$contact["photo"] = $author["author-avatar"];
-		update_gcontact($contact);
-	}
+		// Only update the contacts if it is an OStatus contact
+		if ($r AND !$onlyfetch AND ($contact["network"] == NETWORK_OSTATUS)) {
+			// Update contact data
 
-	return($author);
-}
+			$value = $xpath->query("atom:link[@rel='salmon']", $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["notify"] = $value;
 
-function ostatus_salmon_author($xml, $importer) {
-	$a = get_app();
+			$value = $xpath->evaluate('atom:author/uri/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["alias"] = $value;
 
-	if ($xml == "")
-		return;
+			$value = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["name"] = $value;
 
-	$doc = new DOMDocument();
-	@$doc->loadXML($xml);
+			$value = $xpath->evaluate('atom:author/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["nick"] = $value;
 
-	$xpath = new DomXPath($doc);
-	$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
-	$xpath->registerNamespace('thr', NAMESPACE_THREAD);
-	$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
-	$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
-	$xpath->registerNamespace('media', NAMESPACE_MEDIA);
-	$xpath->registerNamespace('poco', NAMESPACE_POCO);
-	$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
-	$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
+			$value = $xpath->evaluate('atom:author/poco:note/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["about"] = html2bbcode($value);
 
-	$entries = $xpath->query('/atom:entry');
+			$value = $xpath->evaluate('atom:author/poco:address/poco:formatted/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$contact["location"] = $value;
 
-	foreach ($entries AS $entry) {
-		// fetch the author
-		$author = ostatus_fetchauthor($xpath, $entry, $importer, $contact, true);
-		return $author;
-	}
-}
+			if (($contact["name"] != $r[0]["name"]) OR ($contact["nick"] != $r[0]["nick"]) OR ($contact["about"] != $r[0]["about"]) OR ($contact["location"] != $r[0]["location"])) {
 
-function ostatus_import($xml,$importer,&$contact, &$hub) {
+				logger("Update contact data for contact ".$contact["id"], LOGGER_DEBUG);
 
-	$a = get_app();
+				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', `name-date` = '%s' WHERE `id` = %d",
+					dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
+					dbesc(datetime_convert()), intval($contact["id"]));
 
-	logger("Import OStatus message", LOGGER_DEBUG);
-
-	if ($xml == "")
-		return;
-
-	$doc = new DOMDocument();
-	@$doc->loadXML($xml);
-
-	$xpath = new DomXPath($doc);
-	$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
-	$xpath->registerNamespace('thr', NAMESPACE_THREAD);
-	$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
-	$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
-	$xpath->registerNamespace('media', NAMESPACE_MEDIA);
-	$xpath->registerNamespace('poco', NAMESPACE_POCO);
-	$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
-	$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
-
-	$gub = "";
-	$hub_attributes = $xpath->query("/atom:feed/atom:link[@rel='hub']")->item(0)->attributes;
-	if (is_object($hub_attributes))
-		foreach($hub_attributes AS $hub_attribute)
-			if ($hub_attribute->name == "href") {
-				$hub = $hub_attribute->textContent;
-				logger("Found hub ".$hub, LOGGER_DEBUG);
+				poco_check($contact["url"], $contact["name"], $contact["network"], $author["author-avatar"], $contact["about"], $contact["location"],
+							"", "", "", datetime_convert(), 2, $contact["id"], $contact["uid"]);
 			}
 
-	$header = array();
-	$header["uid"] = $importer["uid"];
-	$header["network"] = NETWORK_OSTATUS;
-	$header["type"] = "remote";
-	$header["wall"] = 0;
-	$header["origin"] = 0;
-	$header["gravity"] = GRAVITY_PARENT;
+			if (isset($author["author-avatar"]) AND ($author["author-avatar"] != $r[0]['avatar'])) {
+				logger("Update profile picture for contact ".$contact["id"], LOGGER_DEBUG);
 
-	// it could either be a received post or a post we fetched by ourselves
-	// depending on that, the first node is different
-	$first_child = $doc->firstChild->tagName;
+				update_contact_avatar($author["author-avatar"], $importer["uid"], $contact["id"]);
+			}
+
+			$contact["generation"] = 2;
+			$contact["photo"] = $author["author-avatar"];
+			update_gcontact($contact);
+		}
+
+		return($author);
+	}
+
+	public static function salmon_author($xml, $importer) {
+
+		if ($xml == "")
+			return;
+
+		$doc = new DOMDocument();
+		@$doc->loadXML($xml);
+
+		$xpath = new DomXPath($doc);
+		$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
+		$xpath->registerNamespace('thr', NAMESPACE_THREAD);
+		$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
+		$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
+		$xpath->registerNamespace('media', NAMESPACE_MEDIA);
+		$xpath->registerNamespace('poco', NAMESPACE_POCO);
+		$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
+		$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
 
-	if ($first_child == "feed")
-		$entries = $xpath->query('/atom:feed/atom:entry');
-	else
 		$entries = $xpath->query('/atom:entry');
 
-	$conversation = "";
-	$conversationlist = array();
-	$item_id = 0;
-
-	// Reverse the order of the entries
-	$entrylist = array();
-
-	foreach ($entries AS $entry)
-		$entrylist[] = $entry;
-
-	foreach (array_reverse($entrylist) AS $entry) {
-
-		$mention = false;
-
-		// fetch the author
-		if ($first_child == "feed")
-			$author = ostatus_fetchauthor($xpath, $doc->firstChild, $importer, $contact, false);
-		else
-			$author = ostatus_fetchauthor($xpath, $entry, $importer, $contact, false);
-
-		$value = $xpath->evaluate('atom:author/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
-		if ($value != "")
-			$nickname = $value;
-		else
-			$nickname = $author["author-name"];
-
-		$item = array_merge($header, $author);
-
-		// Now get the item
-		$item["uri"] = $xpath->query('atom:id/text()', $entry)->item(0)->nodeValue;
-
-		$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
-			intval($importer["uid"]), dbesc($item["uri"]));
-		if ($r) {
-			logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
-			continue;
+		foreach ($entries AS $entry) {
+			// fetch the author
+			$author = self::fetchauthor($xpath, $entry, $importer, $contact, true);
+			return $author;
 		}
+	}
 
-		$item["body"] = add_page_info_to_body(html2bbcode($xpath->query('atom:content/text()', $entry)->item(0)->nodeValue));
-		$item["object-type"] = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue;
+	public static function import($xml,$importer,&$contact, &$hub) {
 
-		if (($item["object-type"] == ACTIVITY_OBJ_BOOKMARK) OR ($item["object-type"] == ACTIVITY_OBJ_EVENT)) {
-			$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
-			$item["body"] = $xpath->query('atom:summary/text()', $entry)->item(0)->nodeValue;
-		} elseif ($item["object-type"] == ACTIVITY_OBJ_QUESTION)
-			$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
+		logger("Import OStatus message", LOGGER_DEBUG);
 
-		$item["object"] = $xml;
-		$item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue;
+		if ($xml == "")
+			return;
 
-		/// @TODO
-		/// Delete a message
-		if ($item["verb"] == "qvitter-delete-notice") {
-			// ignore "Delete" messages (by now)
-			logger("Ignore delete message ".print_r($item, true));
-			continue;
-		}
+		//$tempfile = tempnam(get_temppath(), "import");
+		//file_put_contents($tempfile, $xml);
 
-		if ($item["verb"] == ACTIVITY_JOIN) {
-			// ignore "Join" messages
-			logger("Ignore join message ".print_r($item, true));
-			continue;
-		}
+		$doc = new DOMDocument();
+		@$doc->loadXML($xml);
 
-		if ($item["verb"] == ACTIVITY_FOLLOW) {
-			new_follower($importer, $contact, $item, $nickname);
-			continue;
-		}
+		$xpath = new DomXPath($doc);
+		$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
+		$xpath->registerNamespace('thr', NAMESPACE_THREAD);
+		$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
+		$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
+		$xpath->registerNamespace('media', NAMESPACE_MEDIA);
+		$xpath->registerNamespace('poco', NAMESPACE_POCO);
+		$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
+		$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
 
-		if ($item["verb"] == NAMESPACE_OSTATUS."/unfollow") {
-			lose_follower($importer, $contact, $item, $dummy);
-			continue;
-		}
-
-		if ($item["verb"] == ACTIVITY_FAVORITE) {
-			$orig_uri = $xpath->query("activity:object/atom:id", $entry)->item(0)->nodeValue;
-			logger("Favorite ".$orig_uri." ".print_r($item, true));
-
-			$item["verb"] = ACTIVITY_LIKE;
-			$item["parent-uri"] = $orig_uri;
-			$item["gravity"] = GRAVITY_LIKE;
-		}
-
-		if ($item["verb"] == NAMESPACE_OSTATUS."/unfavorite") {
-			// Ignore "Unfavorite" message
-			logger("Ignore unfavorite message ".print_r($item, true));
-			continue;
-		}
-
-		// http://activitystrea.ms/schema/1.0/rsvp-yes
-		if (!in_array($item["verb"], array(ACTIVITY_POST, ACTIVITY_LIKE, ACTIVITY_SHARE)))
-			logger("Unhandled verb ".$item["verb"]." ".print_r($item, true));
-
-		$item["created"] = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
-		$item["edited"] = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue;
-		$conversation = $xpath->query('ostatus:conversation/text()', $entry)->item(0)->nodeValue;
-
-		$related = "";
-
-		$inreplyto = $xpath->query('thr:in-reply-to', $entry);
-		if (is_object($inreplyto->item(0))) {
-			foreach($inreplyto->item(0)->attributes AS $attributes) {
-				if ($attributes->name == "ref")
-					$item["parent-uri"] = $attributes->textContent;
-				if ($attributes->name == "href")
-					$related = $attributes->textContent;
-			}
-		}
-
-		$georsspoint = $xpath->query('georss:point', $entry);
-		if ($georsspoint)
-			$item["coord"] = $georsspoint->item(0)->nodeValue;
-
-		/// @TODO
-		/// $item["location"] =
-
-		$categories = $xpath->query('atom:category', $entry);
-		if ($categories) {
-			foreach ($categories AS $category) {
-				foreach($category->attributes AS $attributes)
-					if ($attributes->name == "term") {
-						$term = $attributes->textContent;
-						if(strlen($item["tag"]))
-							$item["tag"] .= ',';
-						$item["tag"] .= "#[url=".$a->get_baseurl()."/search?tag=".$term."]".$term."[/url]";
-					}
-			}
-		}
-
-		$self = "";
-		$enclosure = "";
-
-		$links = $xpath->query('atom:link', $entry);
-		if ($links) {
-			$rel = "";
-			$href = "";
-			$type = "";
-			$length = "0";
-			$title = "";
-			foreach ($links AS $link) {
-				foreach($link->attributes AS $attributes) {
-					if ($attributes->name == "href")
-						$href = $attributes->textContent;
-					if ($attributes->name == "rel")
-						$rel = $attributes->textContent;
-					if ($attributes->name == "type")
-						$type = $attributes->textContent;
-					if ($attributes->name == "length")
-						$length = $attributes->textContent;
-					if ($attributes->name == "title")
-						$title = $attributes->textContent;
+		$gub = "";
+		$hub_attributes = $xpath->query("/atom:feed/atom:link[@rel='hub']")->item(0)->attributes;
+		if (is_object($hub_attributes))
+			foreach($hub_attributes AS $hub_attribute)
+				if ($hub_attribute->name == "href") {
+					$hub = $hub_attribute->textContent;
+					logger("Found hub ".$hub, LOGGER_DEBUG);
 				}
-				if (($rel != "") AND ($href != ""))
-					switch($rel) {
-						case "alternate":
-							$item["plink"] = $href;
-							if (($item["object-type"] == ACTIVITY_OBJ_QUESTION) OR
-								($item["object-type"] == ACTIVITY_OBJ_EVENT))
-								$item["body"] .= add_page_info($href);
-							break;
-						case "ostatus:conversation":
-							$conversation = $href;
-							break;
-						case "enclosure":
-							$enclosure = $href;
-							if(strlen($item["attach"]))
-								$item["attach"] .= ',';
 
-							$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
-							break;
-						case "related":
-							if ($item["object-type"] != ACTIVITY_OBJ_BOOKMARK) {
-								if (!isset($item["parent-uri"]))
-									$item["parent-uri"] = $href;
+		$header = array();
+		$header["uid"] = $importer["uid"];
+		$header["network"] = NETWORK_OSTATUS;
+		$header["type"] = "remote";
+		$header["wall"] = 0;
+		$header["origin"] = 0;
+		$header["gravity"] = GRAVITY_PARENT;
 
-								if ($related == "")
-									$related = $href;
-							} else
-								$item["body"] .= add_page_info($href);
-							break;
-						case "self":
-							$self = $href;
-							break;
-						case "mentioned":
-							// Notification check
-							if ($importer["nurl"] == normalise_link($href))
-								$mention = true;
-							break;
-					}
+		// it could either be a received post or a post we fetched by ourselves
+		// depending on that, the first node is different
+		$first_child = $doc->firstChild->tagName;
+
+		if ($first_child == "feed")
+			$entries = $xpath->query('/atom:feed/atom:entry');
+		else
+			$entries = $xpath->query('/atom:entry');
+
+		$conversation = "";
+		$conversationlist = array();
+		$item_id = 0;
+
+		// Reverse the order of the entries
+		$entrylist = array();
+
+		foreach ($entries AS $entry)
+			$entrylist[] = $entry;
+
+		foreach (array_reverse($entrylist) AS $entry) {
+
+			$mention = false;
+
+			// fetch the author
+			if ($first_child == "feed")
+				$author = self::fetchauthor($xpath, $doc->firstChild, $importer, $contact, false);
+			else
+				$author = self::fetchauthor($xpath, $entry, $importer, $contact, false);
+
+			$value = $xpath->evaluate('atom:author/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
+			if ($value != "")
+				$nickname = $value;
+			else
+				$nickname = $author["author-name"];
+
+			$item = array_merge($header, $author);
+
+			// Now get the item
+			$item["uri"] = $xpath->query('atom:id/text()', $entry)->item(0)->nodeValue;
+
+			$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
+				intval($importer["uid"]), dbesc($item["uri"]));
+			if ($r) {
+				logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
+				continue;
 			}
-		}
 
-		$local_id = "";
-		$repeat_of = "";
+			$item["body"] = add_page_info_to_body(html2bbcode($xpath->query('atom:content/text()', $entry)->item(0)->nodeValue));
+			$item["object-type"] = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue;
 
-		$notice_info = $xpath->query('statusnet:notice_info', $entry);
-		if ($notice_info AND ($notice_info->length > 0)) {
-			foreach($notice_info->item(0)->attributes AS $attributes) {
-				if ($attributes->name == "source")
-					$item["app"] = strip_tags($attributes->textContent);
-				if ($attributes->name == "local_id")
-					$local_id = $attributes->textContent;
-				if ($attributes->name == "repeat_of")
-					$repeat_of = $attributes->textContent;
+			if (($item["object-type"] == ACTIVITY_OBJ_BOOKMARK) OR ($item["object-type"] == ACTIVITY_OBJ_EVENT)) {
+				$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
+				$item["body"] = $xpath->query('atom:summary/text()', $entry)->item(0)->nodeValue;
+			} elseif ($item["object-type"] == ACTIVITY_OBJ_QUESTION)
+				$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
+
+			$item["object"] = $xml;
+			$item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue;
+
+			/// @TODO
+			/// Delete a message
+			if ($item["verb"] == "qvitter-delete-notice") {
+				// ignore "Delete" messages (by now)
+				logger("Ignore delete message ".print_r($item, true));
+				continue;
 			}
-		}
 
-		// Is it a repeated post?
-		if ($repeat_of != "") {
-			$activityobjects = $xpath->query('activity:object', $entry)->item(0);
+			if ($item["verb"] == ACTIVITY_JOIN) {
+				// ignore "Join" messages
+				logger("Ignore join message ".print_r($item, true));
+				continue;
+			}
 
-			if (is_object($activityobjects)) {
+			if ($item["verb"] == ACTIVITY_FOLLOW) {
+				new_follower($importer, $contact, $item, $nickname);
+				continue;
+			}
 
-				$orig_uri = $xpath->query("activity:object/atom:id", $activityobjects)->item(0)->nodeValue;
-				if (!isset($orig_uri))
-					$orig_uri = $xpath->query('atom:id/text()', $activityobjects)->item(0)->nodeValue;
+			if ($item["verb"] == NAMESPACE_OSTATUS."/unfollow") {
+				lose_follower($importer, $contact, $item, $dummy);
+				continue;
+			}
 
-				$orig_links = $xpath->query("activity:object/atom:link[@rel='alternate']", $activityobjects);
-				if ($orig_links AND ($orig_links->length > 0))
-					foreach($orig_links->item(0)->attributes AS $attributes)
+			if ($item["verb"] == ACTIVITY_FAVORITE) {
+				$orig_uri = $xpath->query("activity:object/atom:id", $entry)->item(0)->nodeValue;
+				logger("Favorite ".$orig_uri." ".print_r($item, true));
+
+				$item["verb"] = ACTIVITY_LIKE;
+				$item["parent-uri"] = $orig_uri;
+				$item["gravity"] = GRAVITY_LIKE;
+			}
+
+			if ($item["verb"] == NAMESPACE_OSTATUS."/unfavorite") {
+				// Ignore "Unfavorite" message
+				logger("Ignore unfavorite message ".print_r($item, true));
+				continue;
+			}
+
+			// http://activitystrea.ms/schema/1.0/rsvp-yes
+			if (!in_array($item["verb"], array(ACTIVITY_POST, ACTIVITY_LIKE, ACTIVITY_SHARE)))
+				logger("Unhandled verb ".$item["verb"]." ".print_r($item, true));
+
+			$item["created"] = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
+			$item["edited"] = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue;
+			$conversation = $xpath->query('ostatus:conversation/text()', $entry)->item(0)->nodeValue;
+
+			$related = "";
+
+			$inreplyto = $xpath->query('thr:in-reply-to', $entry);
+			if (is_object($inreplyto->item(0))) {
+				foreach($inreplyto->item(0)->attributes AS $attributes) {
+					if ($attributes->name == "ref")
+						$item["parent-uri"] = $attributes->textContent;
+					if ($attributes->name == "href")
+						$related = $attributes->textContent;
+				}
+			}
+
+			$georsspoint = $xpath->query('georss:point', $entry);
+			if ($georsspoint)
+				$item["coord"] = $georsspoint->item(0)->nodeValue;
+
+			$categories = $xpath->query('atom:category', $entry);
+			if ($categories) {
+				foreach ($categories AS $category) {
+					foreach($category->attributes AS $attributes)
+						if ($attributes->name == "term") {
+							$term = $attributes->textContent;
+							if(strlen($item["tag"]))
+								$item["tag"] .= ',';
+							$item["tag"] .= "#[url=".App::get_baseurl()."/search?tag=".$term."]".$term."[/url]";
+						}
+				}
+			}
+
+			$self = "";
+			$enclosure = "";
+
+			$links = $xpath->query('atom:link', $entry);
+			if ($links) {
+				$rel = "";
+				$href = "";
+				$type = "";
+				$length = "0";
+				$title = "";
+				foreach ($links AS $link) {
+					foreach($link->attributes AS $attributes) {
 						if ($attributes->name == "href")
-							$orig_link = $attributes->textContent;
+							$href = $attributes->textContent;
+						if ($attributes->name == "rel")
+							$rel = $attributes->textContent;
+						if ($attributes->name == "type")
+							$type = $attributes->textContent;
+						if ($attributes->name == "length")
+							$length = $attributes->textContent;
+						if ($attributes->name == "title")
+							$title = $attributes->textContent;
+					}
+					if (($rel != "") AND ($href != ""))
+						switch($rel) {
+							case "alternate":
+								$item["plink"] = $href;
+								if (($item["object-type"] == ACTIVITY_OBJ_QUESTION) OR
+									($item["object-type"] == ACTIVITY_OBJ_EVENT))
+									$item["body"] .= add_page_info($href);
+								break;
+							case "ostatus:conversation":
+								$conversation = $href;
+								break;
+							case "enclosure":
+								$enclosure = $href;
+								if(strlen($item["attach"]))
+									$item["attach"] .= ',';
 
-				if (!isset($orig_link))
-					$orig_link = $xpath->query("atom:link[@rel='alternate']", $activityobjects)->item(0)->nodeValue;
+								$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
+								break;
+							case "related":
+								if ($item["object-type"] != ACTIVITY_OBJ_BOOKMARK) {
+									if (!isset($item["parent-uri"]))
+										$item["parent-uri"] = $href;
 
-				if (!isset($orig_link))
-					$orig_link =  ostatus_convert_href($orig_uri);
+									if ($related == "")
+										$related = $href;
+								} else
+									$item["body"] .= add_page_info($href);
+								break;
+							case "self":
+								$self = $href;
+								break;
+							case "mentioned":
+								// Notification check
+								if ($importer["nurl"] == normalise_link($href))
+									$mention = true;
+								break;
+						}
+				}
+			}
 
-				$orig_body = $xpath->query('activity:object/atom:content/text()', $activityobjects)->item(0)->nodeValue;
-				if (!isset($orig_body))
-					$orig_body = $xpath->query('atom:content/text()', $activityobjects)->item(0)->nodeValue;
+			$local_id = "";
+			$repeat_of = "";
 
-				$orig_created = $xpath->query('atom:published/text()', $activityobjects)->item(0)->nodeValue;
+			$notice_info = $xpath->query('statusnet:notice_info', $entry);
+			if ($notice_info AND ($notice_info->length > 0)) {
+				foreach($notice_info->item(0)->attributes AS $attributes) {
+					if ($attributes->name == "source")
+						$item["app"] = strip_tags($attributes->textContent);
+					if ($attributes->name == "local_id")
+						$local_id = $attributes->textContent;
+					if ($attributes->name == "repeat_of")
+						$repeat_of = $attributes->textContent;
+				}
+			}
 
-				$orig_contact = $contact;
-				$orig_author = ostatus_fetchauthor($xpath, $activityobjects, $importer, $orig_contact, false);
+			// Is it a repeated post?
+			if ($repeat_of != "") {
+				$activityobjects = $xpath->query('activity:object', $entry)->item(0);
+
+				if (is_object($activityobjects)) {
+
+					$orig_uri = $xpath->query("activity:object/atom:id", $activityobjects)->item(0)->nodeValue;
+					if (!isset($orig_uri))
+						$orig_uri = $xpath->query('atom:id/text()', $activityobjects)->item(0)->nodeValue;
+
+					$orig_links = $xpath->query("activity:object/atom:link[@rel='alternate']", $activityobjects);
+					if ($orig_links AND ($orig_links->length > 0))
+						foreach($orig_links->item(0)->attributes AS $attributes)
+							if ($attributes->name == "href")
+								$orig_link = $attributes->textContent;
+
+					if (!isset($orig_link))
+						$orig_link = $xpath->query("atom:link[@rel='alternate']", $activityobjects)->item(0)->nodeValue;
+
+					if (!isset($orig_link))
+						$orig_link =  self::convert_href($orig_uri);
+
+					$orig_body = $xpath->query('activity:object/atom:content/text()', $activityobjects)->item(0)->nodeValue;
+					if (!isset($orig_body))
+						$orig_body = $xpath->query('atom:content/text()', $activityobjects)->item(0)->nodeValue;
+
+					$orig_created = $xpath->query('atom:published/text()', $activityobjects)->item(0)->nodeValue;
+
+					$orig_contact = $contact;
+					$orig_author = self::fetchauthor($xpath, $activityobjects, $importer, $orig_contact, false);
 
-				//if (!intval(get_config('system','wall-to-wall_share'))) {
-				//	$prefix = share_header($orig_author['author-name'], $orig_author['author-link'], $orig_author['author-avatar'], "", $orig_created, $orig_link);
-				//	$item["body"] = $prefix.add_page_info_to_body(html2bbcode($orig_body))."[/share]";
-				//} else {
 					$item["author-name"] = $orig_author["author-name"];
 					$item["author-link"] = $orig_author["author-link"];
 					$item["author-avatar"] = $orig_author["author-avatar"];
@@ -499,1234 +443,1319 @@ function ostatus_import($xml,$importer,&$contact, &$hub) {
 
 					$item["uri"] = $orig_uri;
 					$item["plink"] = $orig_link;
-				//}
 
-				$item["verb"] = $xpath->query('activity:verb/text()', $activityobjects)->item(0)->nodeValue;
+					$item["verb"] = $xpath->query('activity:verb/text()', $activityobjects)->item(0)->nodeValue;
 
-				$item["object-type"] = $xpath->query('activity:object/activity:object-type/text()', $activityobjects)->item(0)->nodeValue;
-				if (!isset($item["object-type"]))
-					$item["object-type"] = $xpath->query('activity:object-type/text()', $activityobjects)->item(0)->nodeValue;
-			}
-		}
-
-		//if ($enclosure != "")
-		//	$item["body"] .= add_page_info($enclosure);
-
-		if (isset($item["parent-uri"])) {
-			$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
-				intval($importer["uid"]), dbesc($item["parent-uri"]));
-
-			if (!$r AND ($related != "")) {
-				$reply_path = str_replace("/notice/", "/api/statuses/show/", $related).".atom";
-
-				if ($reply_path != $related) {
-					logger("Fetching related items for user ".$importer["uid"]." from ".$reply_path, LOGGER_DEBUG);
-					$reply_xml = fetch_url($reply_path);
-
-					$reply_contact = $contact;
-					ostatus_import($reply_xml,$importer,$reply_contact, $reply_hub);
-
-					// After the import try to fetch the parent item again
-					$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
-						intval($importer["uid"]), dbesc($item["parent-uri"]));
+					$item["object-type"] = $xpath->query('activity:object/activity:object-type/text()', $activityobjects)->item(0)->nodeValue;
+					if (!isset($item["object-type"]))
+						$item["object-type"] = $xpath->query('activity:object-type/text()', $activityobjects)->item(0)->nodeValue;
 				}
 			}
-			if ($r) {
-				$item["type"] = 'remote-comment';
-				$item["gravity"] = GRAVITY_COMMENT;
+
+			//if ($enclosure != "")
+			//	$item["body"] .= add_page_info($enclosure);
+
+			if (isset($item["parent-uri"])) {
+				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
+					intval($importer["uid"]), dbesc($item["parent-uri"]));
+
+				if (!$r AND ($related != "")) {
+					$reply_path = str_replace("/notice/", "/api/statuses/show/", $related).".atom";
+
+					if ($reply_path != $related) {
+						logger("Fetching related items for user ".$importer["uid"]." from ".$reply_path, LOGGER_DEBUG);
+						$reply_xml = fetch_url($reply_path);
+
+						$reply_contact = $contact;
+						self::import($reply_xml,$importer,$reply_contact, $reply_hub);
+
+						// After the import try to fetch the parent item again
+						$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
+							intval($importer["uid"]), dbesc($item["parent-uri"]));
+					}
+				}
+				if ($r) {
+					$item["type"] = 'remote-comment';
+					$item["gravity"] = GRAVITY_COMMENT;
+				}
+			} else
+				$item["parent-uri"] = $item["uri"];
+
+			$item_id = self::completion($conversation, $importer["uid"], $item, $self);
+
+			if (!$item_id) {
+				logger("Error storing item", LOGGER_DEBUG);
+				continue;
 			}
-		} else
-			$item["parent-uri"] = $item["uri"];
 
-		$item_id = ostatus_completion($conversation, $importer["uid"], $item, $self);
-
-		if (!$item_id) {
-			logger("Error storing item", LOGGER_DEBUG);
-			continue;
-		}
-
-		logger("Item was stored with id ".$item_id, LOGGER_DEBUG);
-	}
-}
-
-function ostatus_convert_href($href) {
-	$elements = explode(":",$href);
-
-	if ((count($elements) <= 2) OR ($elements[0] != "tag"))
-		return $href;
-
-	$server = explode(",", $elements[1]);
-	$conversation = explode("=", $elements[2]);
-
-	if ((count($elements) == 4) AND ($elements[2] == "post"))
-		return "http://".$server[0]."/notice/".$elements[3];
-
-	if ((count($conversation) != 2) OR ($conversation[1] ==""))
-		return $href;
-
-	if ($elements[3] == "objectType=thread")
-		return "http://".$server[0]."/conversation/".$conversation[1];
-	else
-		return "http://".$server[0]."/notice/".$conversation[1];
-
-	return $href;
-}
-
-function check_conversations($mentions = false, $override = false) {
-	$last = get_config('system','ostatus_last_poll');
-
-	$poll_interval = intval(get_config('system','ostatus_poll_interval'));
-	if(! $poll_interval)
-		$poll_interval = OSTATUS_DEFAULT_POLL_INTERVAL;
-
-	// Don't poll if the interval is set negative
-	if (($poll_interval < 0) AND !$override)
-		return;
-
-	if (!$mentions) {
-		$poll_timeframe = intval(get_config('system','ostatus_poll_timeframe'));
-		if (!$poll_timeframe)
-			$poll_timeframe = OSTATUS_DEFAULT_POLL_TIMEFRAME;
-	} else {
-		$poll_timeframe = intval(get_config('system','ostatus_poll_timeframe'));
-		if (!$poll_timeframe)
-			$poll_timeframe = OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS;
-	}
-
-
-	if ($last AND !$override) {
-		$next = $last + ($poll_interval * 60);
-		if ($next > time()) {
-			logger('poll interval not reached');
-			return;
+			logger("Item was stored with id ".$item_id, LOGGER_DEBUG);
 		}
 	}
 
-	logger('cron_start');
-
-	$start = date("Y-m-d H:i:s", time() - ($poll_timeframe * 60));
-
-	if ($mentions)
-		$conversations = q("SELECT `term`.`oid`, `term`.`url`, `term`.`uid` FROM `term`
-					STRAIGHT_JOIN `thread` ON `thread`.`iid` = `term`.`oid` AND `thread`.`uid` = `term`.`uid`
-					WHERE `term`.`type` = 7 AND `term`.`term` > '%s' AND `thread`.`mention`
-					GROUP BY `term`.`url`, `term`.`uid` ORDER BY `term`.`term` DESC", dbesc($start));
-	else
-		$conversations = q("SELECT `oid`, `url`, `uid` FROM `term`
-					WHERE `type` = 7 AND `term` > '%s'
-					GROUP BY `url`, `uid` ORDER BY `term` DESC", dbesc($start));
-
-	foreach ($conversations AS $conversation) {
-		ostatus_completion($conversation['url'], $conversation['uid']);
-	}
-
-	logger('cron_end');
-
-	set_config('system','ostatus_last_poll', time());
-}
-
-/**
- * @brief Updates the gcontact table with actor data from the conversation
- *
- * @param object $actor The actor object that contains the contact data
- */
-function ostatus_conv_fetch_actor($actor) {
-
-	// We set the generation to "3" since the data here is not as reliable as the data we get on other occasions
-	$contact = array("network" => NETWORK_OSTATUS, "generation" => 3);
-
-	if (isset($actor->url))
-		$contact["url"] = $actor->url;
-
-	if (isset($actor->displayName))
-		$contact["name"] = $actor->displayName;
-
-	if (isset($actor->portablecontacts_net->displayName))
-		$contact["name"] = $actor->portablecontacts_net->displayName;
-
-	if (isset($actor->portablecontacts_net->preferredUsername))
-		$contact["nick"] = $actor->portablecontacts_net->preferredUsername;
-
-	if (isset($actor->id))
-		$contact["alias"] = $actor->id;
-
-	if (isset($actor->summary))
-		$contact["about"] = $actor->summary;
-
-	if (isset($actor->portablecontacts_net->note))
-		$contact["about"] = $actor->portablecontacts_net->note;
-
-	if (isset($actor->portablecontacts_net->addresses->formatted))
-		$contact["location"] = $actor->portablecontacts_net->addresses->formatted;
-
-
-	if (isset($actor->image->url))
-		$contact["photo"] = $actor->image->url;
-
-	if (isset($actor->image->width))
-		$avatarwidth = $actor->image->width;
-
-	if (is_array($actor->status_net->avatarLinks))
-		foreach ($actor->status_net->avatarLinks AS $avatar) {
-			if ($avatarsize < $avatar->width) {
-				$contact["photo"] = $avatar->url;
-				$avatarsize = $avatar->width;
-			}
-		}
-
-	update_gcontact($contact);
-}
-
-/**
- * @brief Fetches the conversation url for a given item link or conversation id
- *
- * @param string $self The link to the posting
- * @param string $conversation_id The conversation id
- *
- * @return string The conversation url
- */
-function ostatus_fetch_conversation($self, $conversation_id = "") {
-
-	if ($conversation_id != "") {
-		$elements = explode(":", $conversation_id);
+	public static function convert_href($href) {
+		$elements = explode(":",$href);
 
 		if ((count($elements) <= 2) OR ($elements[0] != "tag"))
-			return $conversation_id;
+			return $href;
+
+		$server = explode(",", $elements[1]);
+		$conversation = explode("=", $elements[2]);
+
+		if ((count($elements) == 4) AND ($elements[2] == "post"))
+			return "http://".$server[0]."/notice/".$elements[3];
+
+		if ((count($conversation) != 2) OR ($conversation[1] ==""))
+			return $href;
+
+		if ($elements[3] == "objectType=thread")
+			return "http://".$server[0]."/conversation/".$conversation[1];
+		else
+			return "http://".$server[0]."/notice/".$conversation[1];
+
+		return $href;
 	}
 
-	if ($self == "")
-		return "";
+	public static function check_conversations($mentions = false, $override = false) {
+		$last = get_config('system','ostatus_last_poll');
 
-	$json = str_replace(".atom", ".json", $self);
+		$poll_interval = intval(get_config('system','ostatus_poll_interval'));
+		if(! $poll_interval)
+			$poll_interval = OSTATUS_DEFAULT_POLL_INTERVAL;
 
-	$raw = fetch_url($json);
-	if ($raw == "")
-		return "";
+		// Don't poll if the interval is set negative
+		if (($poll_interval < 0) AND !$override)
+			return;
 
-	$data = json_decode($raw);
-	if (!is_object($data))
-		return "";
+		if (!$mentions) {
+			$poll_timeframe = intval(get_config('system','ostatus_poll_timeframe'));
+			if (!$poll_timeframe)
+				$poll_timeframe = OSTATUS_DEFAULT_POLL_TIMEFRAME;
+		} else {
+			$poll_timeframe = intval(get_config('system','ostatus_poll_timeframe'));
+			if (!$poll_timeframe)
+				$poll_timeframe = OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS;
+		}
 
-	$conversation_id = $data->statusnet_conversation_id;
 
-	$pos = strpos($self, "/api/statuses/show/");
-	$base_url = substr($self, 0, $pos);
+		if ($last AND !$override) {
+			$next = $last + ($poll_interval * 60);
+			if ($next > time()) {
+				logger('poll interval not reached');
+				return;
+			}
+		}
 
-	return $base_url."/conversation/".$conversation_id;
-}
+		logger('cron_start');
 
-/**
- * @brief Fetches actor details of a given actor and user id
- *
- * @param string $actor The actor url
- * @param int $uid The user id
- * @param int $contact_id The default contact-id
- *
- * @return array Array with actor details
- */
-function ostatus_get_actor_details($actor, $uid, $contact_id) {
+		$start = date("Y-m-d H:i:s", time() - ($poll_timeframe * 60));
 
-	$details = array();
+		if ($mentions)
+			$conversations = q("SELECT `term`.`oid`, `term`.`url`, `term`.`uid` FROM `term`
+						STRAIGHT_JOIN `thread` ON `thread`.`iid` = `term`.`oid` AND `thread`.`uid` = `term`.`uid`
+						WHERE `term`.`type` = 7 AND `term`.`term` > '%s' AND `thread`.`mention`
+						GROUP BY `term`.`url`, `term`.`uid` ORDER BY `term`.`term` DESC", dbesc($start));
+		else
+			$conversations = q("SELECT `oid`, `url`, `uid` FROM `term`
+						WHERE `type` = 7 AND `term` > '%s'
+						GROUP BY `url`, `uid` ORDER BY `term` DESC", dbesc($start));
 
-	$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
-				$uid, normalise_link($actor), NETWORK_STATUSNET);
+		foreach ($conversations AS $conversation) {
+			self::completion($conversation['url'], $conversation['uid']);
+		}
 
-	if (!$contact)
-		$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `alias` IN ('%s', '%s') AND `network` != '%s'",
-				$uid, $actor, normalise_link($actor), NETWORK_STATUSNET);
+		logger('cron_end');
 
-	if ($contact) {
-		logger("Found contact for url ".$actor, LOGGER_DEBUG);
-		$details["contact_id"] = $contact[0]["id"];
-		$details["network"] = $contact[0]["network"];
-
-		$details["not_following"] = !in_array($contact[0]["rel"], array(CONTACT_IS_SHARING, CONTACT_IS_FRIEND));
-	} else {
-		logger("No contact found for user ".$uid." and url ".$actor, LOGGER_DEBUG);
-
-		// Adding a global contact
-		/// @TODO Use this data for the post
-		$details["global_contact_id"] = get_contact($actor, 0);
-
-		logger("Global contact ".$global_contact_id." found for url ".$actor, LOGGER_DEBUG);
-
-		$details["contact_id"] = $contact_id;
-		$details["network"] = NETWORK_OSTATUS;
-
-		$details["not_following"] = true;
+		set_config('system','ostatus_last_poll', time());
 	}
 
-	return $details;
-}
+	/**
+	 * @brief Updates the gcontact table with actor data from the conversation
+	 *
+	 * @param object $actor The actor object that contains the contact data
+	 */
+	private function conv_fetch_actor($actor) {
 
-function ostatus_completion($conversation_url, $uid, $item = array(), $self = "") {
+		// We set the generation to "3" since the data here is not as reliable as the data we get on other occasions
+		$contact = array("network" => NETWORK_OSTATUS, "generation" => 3);
 
-	$a = get_app();
+		if (isset($actor->url))
+			$contact["url"] = $actor->url;
 
-	$item_stored = -1;
+		if (isset($actor->displayName))
+			$contact["name"] = $actor->displayName;
 
-	//$conversation_url = ostatus_convert_href($conversation_url);
-	$conversation_url = ostatus_fetch_conversation($self, $conversation_url);
+		if (isset($actor->portablecontacts_net->displayName))
+			$contact["name"] = $actor->portablecontacts_net->displayName;
+
+		if (isset($actor->portablecontacts_net->preferredUsername))
+			$contact["nick"] = $actor->portablecontacts_net->preferredUsername;
+
+		if (isset($actor->id))
+			$contact["alias"] = $actor->id;
+
+		if (isset($actor->summary))
+			$contact["about"] = $actor->summary;
+
+		if (isset($actor->portablecontacts_net->note))
+			$contact["about"] = $actor->portablecontacts_net->note;
+
+		if (isset($actor->portablecontacts_net->addresses->formatted))
+			$contact["location"] = $actor->portablecontacts_net->addresses->formatted;
+
+
+		if (isset($actor->image->url))
+			$contact["photo"] = $actor->image->url;
+
+		if (isset($actor->image->width))
+			$avatarwidth = $actor->image->width;
+
+		if (is_array($actor->status_net->avatarLinks))
+			foreach ($actor->status_net->avatarLinks AS $avatar) {
+				if ($avatarsize < $avatar->width) {
+					$contact["photo"] = $avatar->url;
+					$avatarsize = $avatar->width;
+				}
+			}
+
+		update_gcontact($contact);
+	}
+
+	/**
+	 * @brief Fetches the conversation url for a given item link or conversation id
+	 *
+	 * @param string $self The link to the posting
+	 * @param string $conversation_id The conversation id
+	 *
+	 * @return string The conversation url
+	 */
+	private function fetch_conversation($self, $conversation_id = "") {
+
+		if ($conversation_id != "") {
+			$elements = explode(":", $conversation_id);
+
+			if ((count($elements) <= 2) OR ($elements[0] != "tag"))
+				return $conversation_id;
+		}
+
+		if ($self == "")
+			return "";
+
+		$json = str_replace(".atom", ".json", $self);
+
+		$raw = fetch_url($json);
+		if ($raw == "")
+			return "";
+
+		$data = json_decode($raw);
+		if (!is_object($data))
+			return "";
+
+		$conversation_id = $data->statusnet_conversation_id;
+
+		$pos = strpos($self, "/api/statuses/show/");
+		$base_url = substr($self, 0, $pos);
+
+		return $base_url."/conversation/".$conversation_id;
+	}
+
+	/**
+	 * @brief Fetches actor details of a given actor and user id
+	 *
+	 * @param string $actor The actor url
+	 * @param int $uid The user id
+	 * @param int $contact_id The default contact-id
+	 *
+	 * @return array Array with actor details
+	 */
+	private function get_actor_details($actor, $uid, $contact_id) {
+
+		$details = array();
+
+		$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
+					$uid, normalise_link($actor), NETWORK_STATUSNET);
+
+		if (!$contact)
+			$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `alias` IN ('%s', '%s') AND `network` != '%s'",
+					$uid, $actor, normalise_link($actor), NETWORK_STATUSNET);
+
+		if ($contact) {
+			logger("Found contact for url ".$actor, LOGGER_DEBUG);
+			$details["contact_id"] = $contact[0]["id"];
+			$details["network"] = $contact[0]["network"];
+
+			$details["not_following"] = !in_array($contact[0]["rel"], array(CONTACT_IS_SHARING, CONTACT_IS_FRIEND));
+		} else {
+			logger("No contact found for user ".$uid." and url ".$actor, LOGGER_DEBUG);
+
+			// Adding a global contact
+			/// @TODO Use this data for the post
+			$details["global_contact_id"] = get_contact($actor, 0);
+
+			logger("Global contact ".$global_contact_id." found for url ".$actor, LOGGER_DEBUG);
+
+			$details["contact_id"] = $contact_id;
+			$details["network"] = NETWORK_OSTATUS;
+
+			$details["not_following"] = true;
+		}
+
+		return $details;
+	}
+
+	private function completion($conversation_url, $uid, $item = array(), $self = "") {
+
+
+		$item_stored = -1;
+
+		$conversation_url = self::fetch_conversation($self, $conversation_url);
+
+		// If the thread shouldn't be completed then store the item and go away
+		// Don't do a completion on liked content
+		if (((intval(get_config('system','ostatus_poll_interval')) == -2) AND (count($item) > 0)) OR
+			($item["verb"] == ACTIVITY_LIKE) OR ($conversation_url == "")) {
+			$item_stored = item_store($item, true);
+			return($item_stored);
+		}
+
+		// Get the parent
+		$parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
+				(SELECT `parent` FROM `item` WHERE `id` IN
+					(SELECT `oid` FROM `term` WHERE `uid` = %d AND `otype` = %d AND `type` = %d AND `url` = '%s'))",
+				intval($uid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), dbesc($conversation_url));
+
+		if ($parents)
+			$parent = $parents[0];
+		elseif (count($item) > 0) {
+			$parent = $item;
+			$parent["type"] = "remote";
+			$parent["verb"] = ACTIVITY_POST;
+			$parent["visible"] = 1;
+		} else {
+			// Preset the parent
+			$r = q("SELECT `id` FROM `contact` WHERE `self` AND `uid`=%d", $uid);
+			if (!$r)
+				return(-2);
+
+			$parent = array();
+			$parent["id"] = 0;
+			$parent["parent"] = 0;
+			$parent["uri"] = "";
+			$parent["contact-id"] = $r[0]["id"];
+			$parent["type"] = "remote";
+			$parent["verb"] = ACTIVITY_POST;
+			$parent["visible"] = 1;
+		}
+
+		$conv = str_replace("/conversation/", "/api/statusnet/conversation/", $conversation_url).".as";
+		$pageno = 1;
+		$items = array();
+
+		logger('fetching conversation url '.$conv.' (Self: '.$self.') for user '.$uid);
+
+		do {
+			$conv_arr = z_fetch_url($conv."?page=".$pageno);
+
+			// If it is a non-ssl site and there is an error, then try ssl or vice versa
+			if (!$conv_arr["success"] AND (substr($conv, 0, 7) == "http://")) {
+				$conv = str_replace("http://", "https://", $conv);
+				$conv_as = fetch_url($conv."?page=".$pageno);
+			} elseif (!$conv_arr["success"] AND (substr($conv, 0, 8) == "https://")) {
+				$conv = str_replace("https://", "http://", $conv);
+				$conv_as = fetch_url($conv."?page=".$pageno);
+			} else
+				$conv_as = $conv_arr["body"];
+
+			$conv_as = str_replace(',"statusnet:notice_info":', ',"statusnet_notice_info":', $conv_as);
+			$conv_as = json_decode($conv_as);
+
+			$no_of_items = sizeof($items);
+
+			if (@is_array($conv_as->items))
+				foreach ($conv_as->items AS $single_item)
+					$items[$single_item->id] = $single_item;
+
+			if ($no_of_items == sizeof($items))
+				break;
+
+			$pageno++;
+
+		} while (true);
+
+		logger('fetching conversation done. Found '.count($items).' items');
+
+		if (!sizeof($items)) {
+			if (count($item) > 0) {
+				$item_stored = item_store($item, true);
+
+				if ($item_stored) {
+					logger("Conversation ".$conversation_url." couldn't be fetched. Item uri ".$item["uri"]." stored: ".$item_stored, LOGGER_DEBUG);
+					self::store_conversation($item_id, $conversation_url);
+				}
+
+				return($item_stored);
+			} else
+				return(-3);
+		}
+
+		$items = array_reverse($items);
+
+		$r = q("SELECT `nurl` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid));
+		$importer = $r[0];
+
+		$new_parent = true;
+
+		foreach ($items as $single_conv) {
+
+			// Update the gcontact table
+			self::conv_fetch_actor($single_conv->actor);
+
+			// Test - remove before flight
+			//$tempfile = tempnam(get_temppath(), "conversation");
+			//file_put_contents($tempfile, json_encode($single_conv));
+
+			$mention = false;
+
+			if (isset($single_conv->object->id))
+				$single_conv->id = $single_conv->object->id;
+
+			$plink = self::convert_href($single_conv->id);
+			if (isset($single_conv->object->url))
+				$plink = self::convert_href($single_conv->object->url);
+
+			if (@!$single_conv->id)
+				continue;
+
+			logger("Got id ".$single_conv->id, LOGGER_DEBUG);
+
+			if ($first_id == "") {
+				$first_id = $single_conv->id;
+
+				// The first post of the conversation isn't our first post. There are three options:
+				// 1. Our conversation hasn't the "real" thread starter
+				// 2. This first post is a post inside our thread
+				// 3. This first post is a post inside another thread
+				if (($first_id != $parent["uri"]) AND ($parent["uri"] != "")) {
+
+					$new_parent = true;
+
+					$new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
+								(SELECT `parent` FROM `item`
+									WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s')) LIMIT 1",
+						intval($uid), dbesc($first_id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
+					if ($new_parents) {
+						if ($new_parents[0]["parent"] == $parent["parent"]) {
+							// Option 2: This post is already present inside our thread - but not as thread starter
+							logger("Option 2: uri present in our thread: ".$first_id, LOGGER_DEBUG);
+							$first_id = $parent["uri"];
+						} else {
+							// Option 3: Not so good. We have mixed parents. We have to see how to clean this up.
+							// For now just take the new parent.
+							$parent = $new_parents[0];
+							$first_id = $parent["uri"];
+							logger("Option 3: mixed parents for uri ".$first_id, LOGGER_DEBUG);
+						}
+					} else {
+						// Option 1: We hadn't got the real thread starter
+						// We have to clean up our existing messages.
+						$parent["id"] = 0;
+						$parent["uri"] = $first_id;
+						logger("Option 1: we have a new parent: ".$first_id, LOGGER_DEBUG);
+					}
+				} elseif ($parent["uri"] == "") {
+					$parent["id"] = 0;
+					$parent["uri"] = $first_id;
+				}
+			}
+
+			$parent_uri = $parent["uri"];
+
+			// "context" only seems to exist on older servers
+			if (isset($single_conv->context->inReplyTo->id)) {
+				$parent_exists = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
+							intval($uid), dbesc($single_conv->context->inReplyTo->id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
+				if ($parent_exists)
+					$parent_uri = $single_conv->context->inReplyTo->id;
+			}
+
+			// This is the current way
+			if (isset($single_conv->object->inReplyTo->id)) {
+				$parent_exists = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
+							intval($uid), dbesc($single_conv->object->inReplyTo->id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
+				if ($parent_exists)
+					$parent_uri = $single_conv->object->inReplyTo->id;
+			}
+
+			$message_exists = q("SELECT `id`, `parent`, `uri` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
+							intval($uid), dbesc($single_conv->id),
+							dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
+			if ($message_exists) {
+				logger("Message ".$single_conv->id." already existed on the system", LOGGER_DEBUG);
+
+				if ($parent["id"] != 0) {
+					$existing_message = $message_exists[0];
+
+					// We improved the way we fetch OStatus messages, this shouldn't happen very often now
+					/// @TODO We have to change the shadow copies as well. This way here is really ugly.
+					if ($existing_message["parent"] != $parent["id"]) {
+						logger('updating id '.$existing_message["id"].' with parent '.$existing_message["parent"].' to parent '.$parent["id"].' uri '.$parent["uri"].' thread '.$parent_uri, LOGGER_DEBUG);
+
+						// Update the parent id of the selected item
+						$r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `id` = %d",
+							intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["id"]));
+
+						// Update the parent uri in the thread - but only if it points to itself
+						$r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE `id` = %d AND `uri` = `thr-parent`",
+							dbesc($parent_uri), intval($existing_message["id"]));
+
+						// try to change all items of the same parent
+						$r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `parent` = %d",
+							intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["parent"]));
+
+						// Update the parent uri in the thread - but only if it points to itself
+						$r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE (`parent` = %d) AND (`uri` = `thr-parent`)",
+							dbesc($parent["uri"]), intval($existing_message["parent"]));
+
+						// Now delete the thread
+						delete_thread($existing_message["parent"]);
+					}
+				}
+
+				// The item we are having on the system is the one that we wanted to store via the item array
+				if (isset($item["uri"]) AND ($item["uri"] == $existing_message["uri"])) {
+					$item = array();
+					$item_stored = 0;
+				}
+
+				continue;
+			}
+
+			if (is_array($single_conv->to))
+				foreach($single_conv->to AS $to)
+					if ($importer["nurl"] == normalise_link($to->id))
+						$mention = true;
+
+			$actor = $single_conv->actor->id;
+			if (isset($single_conv->actor->url))
+				$actor = $single_conv->actor->url;
+
+			$details = self::get_actor_details($actor, $uid, $parent["contact-id"]);
+
+			// Do we only want to import threads that were started by our contacts?
+			if ($details["not_following"] AND $new_parent AND get_config('system','ostatus_full_threads')) {
+				logger("Don't import uri ".$first_id." because user ".$uid." doesn't follow the person ".$actor, LOGGER_DEBUG);
+				continue;
+			}
+
+			$arr = array();
+			$arr["network"] = $details["network"];
+			$arr["uri"] = $single_conv->id;
+			$arr["plink"] = $plink;
+			$arr["uid"] = $uid;
+			$arr["contact-id"] = $details["contact_id"];
+			$arr["parent-uri"] = $parent_uri;
+			$arr["created"] = $single_conv->published;
+			$arr["edited"] = $single_conv->published;
+			$arr["owner-name"] = $single_conv->actor->displayName;
+			if ($arr["owner-name"] == '')
+				$arr["owner-name"] = $single_conv->actor->contact->displayName;
+			if ($arr["owner-name"] == '')
+				$arr["owner-name"] = $single_conv->actor->portablecontacts_net->displayName;
+
+			$arr["owner-link"] = $actor;
+			$arr["owner-avatar"] = $single_conv->actor->image->url;
+			$arr["author-name"] = $arr["owner-name"];
+			$arr["author-link"] = $actor;
+			$arr["author-avatar"] = $single_conv->actor->image->url;
+			$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->content));
+
+			if (isset($single_conv->status_net->notice_info->source))
+				$arr["app"] = strip_tags($single_conv->status_net->notice_info->source);
+			elseif (isset($single_conv->statusnet->notice_info->source))
+				$arr["app"] = strip_tags($single_conv->statusnet->notice_info->source);
+			elseif (isset($single_conv->statusnet_notice_info->source))
+				$arr["app"] = strip_tags($single_conv->statusnet_notice_info->source);
+			elseif (isset($single_conv->provider->displayName))
+				$arr["app"] = $single_conv->provider->displayName;
+			else
+				$arr["app"] = "OStatus";
+
+
+			$arr["object"] = json_encode($single_conv);
+			$arr["verb"] = $parent["verb"];
+			$arr["visible"] = $parent["visible"];
+			$arr["location"] = $single_conv->location->displayName;
+			$arr["coord"] = trim($single_conv->location->lat." ".$single_conv->location->lon);
+
+			// Is it a reshared item?
+			if (isset($single_conv->verb) AND ($single_conv->verb == "share") AND isset($single_conv->object)) {
+				if (is_array($single_conv->object))
+					$single_conv->object = $single_conv->object[0];
+
+				logger("Found reshared item ".$single_conv->object->id);
+
+				// $single_conv->object->context->conversation;
+
+				if (isset($single_conv->object->object->id))
+					$arr["uri"] = $single_conv->object->object->id;
+				else
+					$arr["uri"] = $single_conv->object->id;
+
+				if (isset($single_conv->object->object->url))
+					$plink = self::convert_href($single_conv->object->object->url);
+				else
+					$plink = self::convert_href($single_conv->object->url);
+
+				if (isset($single_conv->object->object->content))
+					$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->object->content));
+				else
+					$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->content));
+
+				$arr["plink"] = $plink;
+
+				$arr["created"] = $single_conv->object->published;
+				$arr["edited"] = $single_conv->object->published;
+
+				$arr["author-name"] = $single_conv->object->actor->displayName;
+				if ($arr["owner-name"] == '')
+					$arr["author-name"] = $single_conv->object->actor->contact->displayName;
+
+				$arr["author-link"] = $single_conv->object->actor->url;
+				$arr["author-avatar"] = $single_conv->object->actor->image->url;
+
+				$arr["app"] = $single_conv->object->provider->displayName."#";
+				//$arr["verb"] = $single_conv->object->verb;
+
+				$arr["location"] = $single_conv->object->location->displayName;
+				$arr["coord"] = trim($single_conv->object->location->lat." ".$single_conv->object->location->lon);
+			}
+
+			if ($arr["location"] == "")
+				unset($arr["location"]);
+
+			if ($arr["coord"] == "")
+				unset($arr["coord"]);
+
+			// Copy fields from given item array
+			if (isset($item["uri"]) AND (($item["uri"] == $arr["uri"]) OR ($item["uri"] ==  $single_conv->id))) {
+				$copy_fields = array("owner-name", "owner-link", "owner-avatar", "author-name", "author-link", "author-avatar",
+							"gravity", "body", "object-type", "object", "verb", "created", "edited", "coord", "tag",
+							"title", "attach", "app", "type", "location", "contact-id", "uri");
+				foreach ($copy_fields AS $field)
+					if (isset($item[$field]))
+						$arr[$field] = $item[$field];
+
+			}
+
+			$newitem = item_store($arr);
+			if (!$newitem) {
+				logger("Item wasn't stored ".print_r($arr, true), LOGGER_DEBUG);
+				continue;
+			}
+
+			if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) {
+				$item = array();
+				$item_stored = $newitem;
+			}
+
+			logger('Stored new item '.$plink.' for parent '.$arr["parent-uri"].' under id '.$newitem, LOGGER_DEBUG);
+
+			// Add the conversation entry (but don't fetch the whole conversation)
+			self::store_conversation($newitem, $conversation_url);
+
+			// If the newly created item is the top item then change the parent settings of the thread
+			// This shouldn't happen anymore. This is supposed to be absolote.
+			if ($arr["uri"] == $first_id) {
+				logger('setting new parent to id '.$newitem);
+				$new_parents = q("SELECT `id`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1",
+					intval($uid), intval($newitem));
+				if ($new_parents)
+					$parent = $new_parents[0];
+			}
+		}
+
+		if (($item_stored < 0) AND (count($item) > 0)) {
+
+			if (get_config('system','ostatus_full_threads')) {
+				$details = self::get_actor_details($item["owner-link"], $uid, $item["contact-id"]);
+				if ($details["not_following"]) {
+					logger("Don't import uri ".$item["uri"]." because user ".$uid." doesn't follow the person ".$item["owner-link"], LOGGER_DEBUG);
+					return false;
+				}
+			}
+
+			$item_stored = item_store($item, true);
+			if ($item_stored) {
+				logger("Uri ".$item["uri"]." wasn't found in conversation ".$conversation_url, LOGGER_DEBUG);
+				self::store_conversation($item_stored, $conversation_url);
+			}
+		}
 
-	// If the thread shouldn't be completed then store the item and go away
-	// Don't do a completion on liked content
-	if (((intval(get_config('system','ostatus_poll_interval')) == -2) AND (count($item) > 0)) OR
-		($item["verb"] == ACTIVITY_LIKE) OR ($conversation_url == "")) {
-		//$arr["app"] .= " (OStatus-NoCompletion)";
-		$item_stored = item_store($item, true);
 		return($item_stored);
 	}
 
-	// Get the parent
-	$parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
-			(SELECT `parent` FROM `item` WHERE `id` IN
-				(SELECT `oid` FROM `term` WHERE `uid` = %d AND `otype` = %d AND `type` = %d AND `url` = '%s'))",
-			intval($uid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), dbesc($conversation_url));
+	private function store_conversation($itemid, $conversation_url) {
 
-	if ($parents)
-		$parent = $parents[0];
-	elseif (count($item) > 0) {
-		$parent = $item;
-		$parent["type"] = "remote";
-		$parent["verb"] = ACTIVITY_POST;
-		$parent["visible"] = 1;
-	} else {
-		// Preset the parent
-		$r = q("SELECT `id` FROM `contact` WHERE `self` AND `uid`=%d", $uid);
-		if (!$r)
-			return(-2);
+		$conversation_url = self::convert_href($conversation_url);
 
-		$parent = array();
-		$parent["id"] = 0;
-		$parent["parent"] = 0;
-		$parent["uri"] = "";
-		$parent["contact-id"] = $r[0]["id"];
-		$parent["type"] = "remote";
-		$parent["verb"] = ACTIVITY_POST;
-		$parent["visible"] = 1;
+		$messages = q("SELECT `uid`, `parent`, `created`, `received`, `guid` FROM `item` WHERE `id` = %d LIMIT 1", intval($itemid));
+		if (!$messages)
+			return;
+		$message = $messages[0];
+
+		// Store conversation url if not done before
+		$conversation = q("SELECT `url` FROM `term` WHERE `uid` = %d AND `oid` = %d AND `otype` = %d AND `type` = %d",
+			intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION));
+
+		if (!$conversation) {
+			$r = q("INSERT INTO `term` (`uid`, `oid`, `otype`, `type`, `term`, `url`, `created`, `received`, `guid`) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s')",
+				intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION),
+				dbesc($message["created"]), dbesc($conversation_url), dbesc($message["created"]), dbesc($message["received"]), dbesc($message["guid"]));
+			logger('Storing conversation url '.$conversation_url.' for id '.$itemid);
+		}
 	}
 
-	$conv = str_replace("/conversation/", "/api/statusnet/conversation/", $conversation_url).".as";
-	$pageno = 1;
-	$items = array();
+	private function get_reshared_guid($item) {
+		$body = trim($item["body"]);
 
-	logger('fetching conversation url '.$conv.' (Self: '.$self.') for user '.$uid);
+		// Skip if it isn't a pure repeated messages
+		// Does it start with a share?
+		if (strpos($body, "[share") > 0)
+			return("");
 
-	do {
-		$conv_arr = z_fetch_url($conv."?page=".$pageno);
+		// Does it end with a share?
+		if (strlen($body) > (strrpos($body, "[/share]") + 8))
+			return("");
 
-		// If it is a non-ssl site and there is an error, then try ssl or vice versa
-		if (!$conv_arr["success"] AND (substr($conv, 0, 7) == "http://")) {
-			$conv = str_replace("http://", "https://", $conv);
-			$conv_as = fetch_url($conv."?page=".$pageno);
-		} elseif (!$conv_arr["success"] AND (substr($conv, 0, 8) == "https://")) {
-			$conv = str_replace("https://", "http://", $conv);
-			$conv_as = fetch_url($conv."?page=".$pageno);
-		} else
-			$conv_as = $conv_arr["body"];
+		$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
+		// Skip if there is no shared message in there
+		if ($body == $attributes)
+			return(false);
 
-		$conv_as = str_replace(',"statusnet:notice_info":', ',"statusnet_notice_info":', $conv_as);
-		$conv_as = json_decode($conv_as);
+		$guid = "";
+		preg_match("/guid='(.*?)'/ism", $attributes, $matches);
+		if ($matches[1] != "")
+			$guid = $matches[1];
 
-		$no_of_items = sizeof($items);
+		preg_match('/guid="(.*?)"/ism', $attributes, $matches);
+		if ($matches[1] != "")
+			$guid = $matches[1];
 
-		if (@is_array($conv_as->items))
-			foreach ($conv_as->items AS $single_item)
-				$items[$single_item->id] = $single_item;
-
-		if ($no_of_items == sizeof($items))
-			break;
-
-		$pageno++;
-
-	} while (true);
-
-	logger('fetching conversation done. Found '.count($items).' items');
-
-	if (!sizeof($items)) {
-		if (count($item) > 0) {
-			//$arr["app"] .= " (OStatus-NoConvFetched)";
-			$item_stored = item_store($item, true);
-
-			if ($item_stored) {
-				logger("Conversation ".$conversation_url." couldn't be fetched. Item uri ".$item["uri"]." stored: ".$item_stored, LOGGER_DEBUG);
-				ostatus_store_conversation($item_id, $conversation_url);
-			}
-
-			return($item_stored);
-		} else
-			return(-3);
+		return $guid;
 	}
 
-	$items = array_reverse($items);
+	private function format_picture_post($body) {
+		$siteinfo = get_attached_data($body);
 
-	$r = q("SELECT `nurl` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid));
-	$importer = $r[0];
+		if (($siteinfo["type"] == "photo")) {
+			if (isset($siteinfo["preview"]))
+				$preview = $siteinfo["preview"];
+			else
+				$preview = $siteinfo["image"];
 
-	$new_parent = true;
+			// Is it a remote picture? Then make a smaller preview here
+			$preview = proxy_url($preview, false, PROXY_SIZE_SMALL);
 
-	foreach ($items as $single_conv) {
+			// Is it a local picture? Then make it smaller here
+			$preview = str_replace(array("-0.jpg", "-0.png"), array("-2.jpg", "-2.png"), $preview);
+			$preview = str_replace(array("-1.jpg", "-1.png"), array("-2.jpg", "-2.png"), $preview);
 
-		// Update the gcontact table
-		ostatus_conv_fetch_actor($single_conv->actor);
+			if (isset($siteinfo["url"]))
+				$url = $siteinfo["url"];
+			else
+				$url = $siteinfo["image"];
 
-		// Test - remove before flight
-		//$tempfile = tempnam(get_temppath(), "conversation");
-		//file_put_contents($tempfile, json_encode($single_conv));
-
-		$mention = false;
-
-		if (isset($single_conv->object->id))
-			$single_conv->id = $single_conv->object->id;
-
-		$plink = ostatus_convert_href($single_conv->id);
-		if (isset($single_conv->object->url))
-			$plink = ostatus_convert_href($single_conv->object->url);
-
-		if (@!$single_conv->id)
-			continue;
-
-		logger("Got id ".$single_conv->id, LOGGER_DEBUG);
-
-		if ($first_id == "") {
-			$first_id = $single_conv->id;
-
-			// The first post of the conversation isn't our first post. There are three options:
-			// 1. Our conversation hasn't the "real" thread starter
-			// 2. This first post is a post inside our thread
-			// 3. This first post is a post inside another thread
-			if (($first_id != $parent["uri"]) AND ($parent["uri"] != "")) {
-
-				$new_parent = true;
-
-				$new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
-							(SELECT `parent` FROM `item`
-								WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s')) LIMIT 1",
-					intval($uid), dbesc($first_id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
-				if ($new_parents) {
-					if ($new_parents[0]["parent"] == $parent["parent"]) {
-						// Option 2: This post is already present inside our thread - but not as thread starter
-						logger("Option 2: uri present in our thread: ".$first_id, LOGGER_DEBUG);
-						$first_id = $parent["uri"];
-					} else {
-						// Option 3: Not so good. We have mixed parents. We have to see how to clean this up.
-						// For now just take the new parent.
-						$parent = $new_parents[0];
-						$first_id = $parent["uri"];
-						logger("Option 3: mixed parents for uri ".$first_id, LOGGER_DEBUG);
-					}
-				} else {
-					// Option 1: We hadn't got the real thread starter
-					// We have to clean up our existing messages.
-					$parent["id"] = 0;
-					$parent["uri"] = $first_id;
-					logger("Option 1: we have a new parent: ".$first_id, LOGGER_DEBUG);
-				}
-			} elseif ($parent["uri"] == "") {
-				$parent["id"] = 0;
-				$parent["uri"] = $first_id;
-			}
+			$body = trim($siteinfo["text"])." [url]".$url."[/url]\n[img]".$preview."[/img]";
 		}
 
-		$parent_uri = $parent["uri"];
+		return $body;
+	}
 
-		// "context" only seems to exist on older servers
-		if (isset($single_conv->context->inReplyTo->id)) {
-			$parent_exists = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
-						intval($uid), dbesc($single_conv->context->inReplyTo->id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
-			if ($parent_exists)
-				$parent_uri = $single_conv->context->inReplyTo->id;
-		}
+	private function add_header($doc, $owner) {
 
-		// This is the current way
-		if (isset($single_conv->object->inReplyTo->id)) {
-			$parent_exists = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
-						intval($uid), dbesc($single_conv->object->inReplyTo->id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
-			if ($parent_exists)
-				$parent_uri = $single_conv->object->inReplyTo->id;
-		}
+		$a = get_app();
 
-		$message_exists = q("SELECT `id`, `parent`, `uri` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
-						intval($uid), dbesc($single_conv->id),
-						dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
-		if ($message_exists) {
-			logger("Message ".$single_conv->id." already existed on the system", LOGGER_DEBUG);
+		$root = $doc->createElementNS(NAMESPACE_ATOM1, 'feed');
+		$doc->appendChild($root);
 
-			if ($parent["id"] != 0) {
-				$existing_message = $message_exists[0];
+		$root->setAttribute("xmlns:thr", NAMESPACE_THREAD);
+		$root->setAttribute("xmlns:georss", NAMESPACE_GEORSS);
+		$root->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY);
+		$root->setAttribute("xmlns:media", NAMESPACE_MEDIA);
+		$root->setAttribute("xmlns:poco", NAMESPACE_POCO);
+		$root->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
+		$root->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
 
-				// We improved the way we fetch OStatus messages, this shouldn't happen very often now
-				/// @TODO We have to change the shadow copies as well. This way here is really ugly.
-				if ($existing_message["parent"] != $parent["id"]) {
-					logger('updating id '.$existing_message["id"].' with parent '.$existing_message["parent"].' to parent '.$parent["id"].' uri '.$parent["uri"].' thread '.$parent_uri, LOGGER_DEBUG);
+		$attributes = array("uri" => "https://friendi.ca", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION);
+		xml::add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes);
+		xml::add_element($doc, $root, "id", App::get_baseurl()."/profile/".$owner["nick"]);
+		xml::add_element($doc, $root, "title", sprintf("%s timeline", $owner["name"]));
+		xml::add_element($doc, $root, "subtitle", sprintf("Updates from %s on %s", $owner["name"], $a->config["sitename"]));
+		xml::add_element($doc, $root, "logo", $owner["photo"]);
+		xml::add_element($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME));
 
-					// Update the parent id of the selected item
-					$r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `id` = %d",
-						intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["id"]));
+		$author = self::add_author($doc, $owner);
+		$root->appendChild($author);
 
-					// Update the parent uri in the thread - but only if it points to itself
-					$r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE `id` = %d AND `uri` = `thr-parent`",
-						dbesc($parent_uri), intval($existing_message["id"]));
+		$attributes = array("href" => $owner["url"], "rel" => "alternate", "type" => "text/html");
+		xml::add_element($doc, $root, "link", "", $attributes);
 
-					// try to change all items of the same parent
-					$r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `parent` = %d",
-						intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["parent"]));
+		/// @TODO We have to find out what this is
+		/// $attributes = array("href" => App::get_baseurl()."/sup",
+		///		"rel" => "http://api.friendfeed.com/2008/03#sup",
+		///		"type" => "application/json");
+		/// xml::add_element($doc, $root, "link", "", $attributes);
 
-					// Update the parent uri in the thread - but only if it points to itself
-					$r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE (`parent` = %d) AND (`uri` = `thr-parent`)",
-						dbesc($parent["uri"]), intval($existing_message["parent"]));
+		self::hublinks($doc, $root);
 
-					// Now delete the thread
-					delete_thread($existing_message["parent"]);
+		$attributes = array("href" => App::get_baseurl()."/salmon/".$owner["nick"], "rel" => "salmon");
+		xml::add_element($doc, $root, "link", "", $attributes);
+
+		$attributes = array("href" => App::get_baseurl()."/salmon/".$owner["nick"], "rel" => "http://salmon-protocol.org/ns/salmon-replies");
+		xml::add_element($doc, $root, "link", "", $attributes);
+
+		$attributes = array("href" => App::get_baseurl()."/salmon/".$owner["nick"], "rel" => "http://salmon-protocol.org/ns/salmon-mention");
+		xml::add_element($doc, $root, "link", "", $attributes);
+
+		$attributes = array("href" => App::get_baseurl()."/api/statuses/user_timeline/".$owner["nick"].".atom",
+				"rel" => "self", "type" => "application/atom+xml");
+		xml::add_element($doc, $root, "link", "", $attributes);
+
+		return $root;
+	}
+
+	public static function hublinks($doc, $root) {
+		$hub = get_config('system','huburl');
+
+		$hubxml = '';
+		if(strlen($hub)) {
+			$hubs = explode(',', $hub);
+			if(count($hubs)) {
+				foreach($hubs as $h) {
+					$h = trim($h);
+					if(! strlen($h))
+						continue;
+					if ($h === '[internal]')
+						$h = App::get_baseurl() . '/pubsubhubbub';
+					xml::add_element($doc, $root, "link", "", array("href" => $h, "rel" => "hub"));
 				}
 			}
-
-			// The item we are having on the system is the one that we wanted to store via the item array
-			if (isset($item["uri"]) AND ($item["uri"] == $existing_message["uri"])) {
-				$item = array();
-				$item_stored = 0;
-			}
-
-			continue;
-		}
-
-		if (is_array($single_conv->to))
-			foreach($single_conv->to AS $to)
-				if ($importer["nurl"] == normalise_link($to->id))
-					$mention = true;
-
-		$actor = $single_conv->actor->id;
-		if (isset($single_conv->actor->url))
-			$actor = $single_conv->actor->url;
-
-		$details = ostatus_get_actor_details($actor, $uid, $parent["contact-id"]);
-
-		// Do we only want to import threads that were started by our contacts?
-		if ($details["not_following"] AND $new_parent AND get_config('system','ostatus_full_threads')) {
-			logger("Don't import uri ".$first_id." because user ".$uid." doesn't follow the person ".$actor, LOGGER_DEBUG);
-			continue;
-		}
-
-		$arr = array();
-		$arr["network"] = $details["network"];
-		$arr["uri"] = $single_conv->id;
-		$arr["plink"] = $plink;
-		$arr["uid"] = $uid;
-		$arr["contact-id"] = $details["contact_id"];
-		$arr["parent-uri"] = $parent_uri;
-		$arr["created"] = $single_conv->published;
-		$arr["edited"] = $single_conv->published;
-		$arr["owner-name"] = $single_conv->actor->displayName;
-		if ($arr["owner-name"] == '')
-			$arr["owner-name"] = $single_conv->actor->contact->displayName;
-		if ($arr["owner-name"] == '')
-			$arr["owner-name"] = $single_conv->actor->portablecontacts_net->displayName;
-
-		$arr["owner-link"] = $actor;
-		$arr["owner-avatar"] = $single_conv->actor->image->url;
-		$arr["author-name"] = $arr["owner-name"];
-		$arr["author-link"] = $actor;
-		$arr["author-avatar"] = $single_conv->actor->image->url;
-		$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->content));
-
-		if (isset($single_conv->status_net->notice_info->source))
-			$arr["app"] = strip_tags($single_conv->status_net->notice_info->source);
-		elseif (isset($single_conv->statusnet->notice_info->source))
-			$arr["app"] = strip_tags($single_conv->statusnet->notice_info->source);
-		elseif (isset($single_conv->statusnet_notice_info->source))
-			$arr["app"] = strip_tags($single_conv->statusnet_notice_info->source);
-		elseif (isset($single_conv->provider->displayName))
-			$arr["app"] = $single_conv->provider->displayName;
-		else
-			$arr["app"] = "OStatus";
-
-		//$arr["app"] .= " (Conversation)";
-
-		$arr["object"] = json_encode($single_conv);
-		$arr["verb"] = $parent["verb"];
-		$arr["visible"] = $parent["visible"];
-		$arr["location"] = $single_conv->location->displayName;
-		$arr["coord"] = trim($single_conv->location->lat." ".$single_conv->location->lon);
-
-		// Is it a reshared item?
-		if (isset($single_conv->verb) AND ($single_conv->verb == "share") AND isset($single_conv->object)) {
-			if (is_array($single_conv->object))
-				$single_conv->object = $single_conv->object[0];
-
-			logger("Found reshared item ".$single_conv->object->id);
-
-			// $single_conv->object->context->conversation;
-
-			if (isset($single_conv->object->object->id))
-				$arr["uri"] = $single_conv->object->object->id;
-			else
-				$arr["uri"] = $single_conv->object->id;
-
-			if (isset($single_conv->object->object->url))
-				$plink = ostatus_convert_href($single_conv->object->object->url);
-			else
-				$plink = ostatus_convert_href($single_conv->object->url);
-
-			if (isset($single_conv->object->object->content))
-				$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->object->content));
-			else
-				$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->content));
-
-			$arr["plink"] = $plink;
-
-			$arr["created"] = $single_conv->object->published;
-			$arr["edited"] = $single_conv->object->published;
-
-			$arr["author-name"] = $single_conv->object->actor->displayName;
-			if ($arr["owner-name"] == '')
-				$arr["author-name"] = $single_conv->object->actor->contact->displayName;
-
-			$arr["author-link"] = $single_conv->object->actor->url;
-			$arr["author-avatar"] = $single_conv->object->actor->image->url;
-
-			$arr["app"] = $single_conv->object->provider->displayName."#";
-			//$arr["verb"] = $single_conv->object->verb;
-
-			$arr["location"] = $single_conv->object->location->displayName;
-			$arr["coord"] = trim($single_conv->object->location->lat." ".$single_conv->object->location->lon);
-		}
-
-		if ($arr["location"] == "")
-			unset($arr["location"]);
-
-		if ($arr["coord"] == "")
-			unset($arr["coord"]);
-
-		// Copy fields from given item array
-		if (isset($item["uri"]) AND (($item["uri"] == $arr["uri"]) OR ($item["uri"] ==  $single_conv->id))) {
-			$copy_fields = array("owner-name", "owner-link", "owner-avatar", "author-name", "author-link", "author-avatar",
-						"gravity", "body", "object-type", "object", "verb", "created", "edited", "coord", "tag",
-						"title", "attach", "app", "type", "location", "contact-id", "uri");
-			foreach ($copy_fields AS $field)
-				if (isset($item[$field]))
-					$arr[$field] = $item[$field];
-
-			//$arr["app"] .= " (OStatus)";
-		}
-
-		$newitem = item_store($arr);
-		if (!$newitem) {
-			logger("Item wasn't stored ".print_r($arr, true), LOGGER_DEBUG);
-			continue;
-		}
-
-		if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) {
-			$item = array();
-			$item_stored = $newitem;
-		}
-
-		logger('Stored new item '.$plink.' for parent '.$arr["parent-uri"].' under id '.$newitem, LOGGER_DEBUG);
-
-		// Add the conversation entry (but don't fetch the whole conversation)
-		ostatus_store_conversation($newitem, $conversation_url);
-
-		// If the newly created item is the top item then change the parent settings of the thread
-		// This shouldn't happen anymore. This is supposed to be absolote.
-		if ($arr["uri"] == $first_id) {
-			logger('setting new parent to id '.$newitem);
-			$new_parents = q("SELECT `id`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1",
-				intval($uid), intval($newitem));
-			if ($new_parents)
-				$parent = $new_parents[0];
 		}
 	}
 
-	if (($item_stored < 0) AND (count($item) > 0)) {
-		//$arr["app"] .= " (OStatus-NoConvFound)";
+	private function get_attachment($doc, $root, $item) {
+		$o = "";
+		$siteinfo = get_attached_data($item["body"]);
 
-		if (get_config('system','ostatus_full_threads')) {
-			$details = ostatus_get_actor_details($item["owner-link"], $uid, $item["contact-id"]);
-			if ($details["not_following"]) {
-				logger("Don't import uri ".$item["uri"]." because user ".$uid." doesn't follow the person ".$item["owner-link"], LOGGER_DEBUG);
-				return false;
-			}
-		}
-
-		$item_stored = item_store($item, true);
-		if ($item_stored) {
-			logger("Uri ".$item["uri"]." wasn't found in conversation ".$conversation_url, LOGGER_DEBUG);
-			ostatus_store_conversation($item_stored, $conversation_url);
-		}
-	}
-
-	return($item_stored);
-}
-
-function ostatus_store_conversation($itemid, $conversation_url) {
-	global $a;
-
-	$conversation_url = ostatus_convert_href($conversation_url);
-
-	$messages = q("SELECT `uid`, `parent`, `created`, `received`, `guid` FROM `item` WHERE `id` = %d LIMIT 1", intval($itemid));
-	if (!$messages)
-		return;
-	$message = $messages[0];
-
-	// Store conversation url if not done before
-	$conversation = q("SELECT `url` FROM `term` WHERE `uid` = %d AND `oid` = %d AND `otype` = %d AND `type` = %d",
-		intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION));
-
-	if (!$conversation) {
-		$r = q("INSERT INTO `term` (`uid`, `oid`, `otype`, `type`, `term`, `url`, `created`, `received`, `guid`) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s')",
-			intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION),
-			dbesc($message["created"]), dbesc($conversation_url), dbesc($message["created"]), dbesc($message["received"]), dbesc($message["guid"]));
-		logger('Storing conversation url '.$conversation_url.' for id '.$itemid);
-	}
-}
-
-function get_reshared_guid($item) {
-	$body = trim($item["body"]);
-
-	// Skip if it isn't a pure repeated messages
-	// Does it start with a share?
-	if (strpos($body, "[share") > 0)
-		return("");
-
-	// Does it end with a share?
-	if (strlen($body) > (strrpos($body, "[/share]") + 8))
-		return("");
-
-	$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
-	// Skip if there is no shared message in there
-	if ($body == $attributes)
-		return(false);
-
-	$guid = "";
-	preg_match("/guid='(.*?)'/ism", $attributes, $matches);
-	if ($matches[1] != "")
-		$guid = $matches[1];
-
-	preg_match('/guid="(.*?)"/ism', $attributes, $matches);
-	if ($matches[1] != "")
-		$guid = $matches[1];
-
-	return $guid;
-}
-
-function xml_create_element($doc, $element, $value = "", $attributes = array()) {
-	$element = $doc->createElement($element, xmlify($value));
-
-	foreach ($attributes AS $key => $value) {
-		$attribute = $doc->createAttribute($key);
-		$attribute->value = xmlify($value);
-		$element->appendChild($attribute);
-	}
-	return $element;
-}
-
-function xml_add_element($doc, $parent, $element, $value = "", $attributes = array()) {
-	$element = xml_create_element($doc, $element, $value, $attributes);
-	$parent->appendChild($element);
-}
-
-function ostatus_format_picture_post($body) {
-	$siteinfo = get_attached_data($body);
-
-	if (($siteinfo["type"] == "photo")) {
-		if (isset($siteinfo["preview"]))
-			$preview = $siteinfo["preview"];
-		else
-			$preview = $siteinfo["image"];
-
-		// Is it a remote picture? Then make a smaller preview here
-		$preview = proxy_url($preview, false, PROXY_SIZE_SMALL);
-
-		// Is it a local picture? Then make it smaller here
-		$preview = str_replace(array("-0.jpg", "-0.png"), array("-2.jpg", "-2.png"), $preview);
-		$preview = str_replace(array("-1.jpg", "-1.png"), array("-2.jpg", "-2.png"), $preview);
-
-		if (isset($siteinfo["url"]))
-			$url = $siteinfo["url"];
-		else
-			$url = $siteinfo["image"];
-
-		$body = trim($siteinfo["text"])." [url]".$url."[/url]\n[img]".$preview."[/img]";
-	}
-
-	return $body;
-}
-
-function ostatus_add_header($doc, $owner) {
-	$a = get_app();
-
-	$root = $doc->createElementNS(NAMESPACE_ATOM1, 'feed');
-	$doc->appendChild($root);
-
-	$root->setAttribute("xmlns:thr", NAMESPACE_THREAD);
-	$root->setAttribute("xmlns:georss", NAMESPACE_GEORSS);
-	$root->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY);
-	$root->setAttribute("xmlns:media", NAMESPACE_MEDIA);
-	$root->setAttribute("xmlns:poco", NAMESPACE_POCO);
-	$root->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
-	$root->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
-
-	$attributes = array("uri" => "https://friendi.ca", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION);
-	xml_add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes);
-	xml_add_element($doc, $root, "id", $a->get_baseurl()."/profile/".$owner["nick"]);
-	xml_add_element($doc, $root, "title", sprintf("%s timeline", $owner["name"]));
-	xml_add_element($doc, $root, "subtitle", sprintf("Updates from %s on %s", $owner["name"], $a->config["sitename"]));
-	xml_add_element($doc, $root, "logo", $owner["photo"]);
-	xml_add_element($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME));
-
-	$author = ostatus_add_author($doc, $owner);
-	$root->appendChild($author);
-
-	$attributes = array("href" => $owner["url"], "rel" => "alternate", "type" => "text/html");
-	xml_add_element($doc, $root, "link", "", $attributes);
-
-	/// @TODO We have to find out what this is
-	/// $attributes = array("href" => $a->get_baseurl()."/sup",
-	///		"rel" => "http://api.friendfeed.com/2008/03#sup",
-	///		"type" => "application/json");
-	/// xml_add_element($doc, $root, "link", "", $attributes);
-
-	ostatus_hublinks($doc, $root);
-
-	$attributes = array("href" => $a->get_baseurl()."/salmon/".$owner["nick"], "rel" => "salmon");
-	xml_add_element($doc, $root, "link", "", $attributes);
-
-	$attributes = array("href" => $a->get_baseurl()."/salmon/".$owner["nick"], "rel" => "http://salmon-protocol.org/ns/salmon-replies");
-	xml_add_element($doc, $root, "link", "", $attributes);
-
-	$attributes = array("href" => $a->get_baseurl()."/salmon/".$owner["nick"], "rel" => "http://salmon-protocol.org/ns/salmon-mention");
-	xml_add_element($doc, $root, "link", "", $attributes);
-
-	$attributes = array("href" => $a->get_baseurl()."/api/statuses/user_timeline/".$owner["nick"].".atom",
-			"rel" => "self", "type" => "application/atom+xml");
-	xml_add_element($doc, $root, "link", "", $attributes);
-
-	return $root;
-}
-
-function ostatus_hublinks($doc, $root) {
-	$a = get_app();
-	$hub = get_config('system','huburl');
-
-	$hubxml = '';
-	if(strlen($hub)) {
-		$hubs = explode(',', $hub);
-		if(count($hubs)) {
-			foreach($hubs as $h) {
-				$h = trim($h);
-				if(! strlen($h))
-					continue;
-				if ($h === '[internal]')
-					$h = $a->get_baseurl() . '/pubsubhubbub';
-				xml_add_element($doc, $root, "link", "", array("href" => $h, "rel" => "hub"));
-			}
-		}
-	}
-}
-
-function ostatus_get_attachment($doc, $root, $item) {
-	$o = "";
-	$siteinfo = get_attached_data($item["body"]);
-
-	switch($siteinfo["type"]) {
-		case 'link':
-			$attributes = array("rel" => "enclosure",
-					"href" => $siteinfo["url"],
-					"type" => "text/html; charset=UTF-8",
-					"length" => "",
-					"title" => $siteinfo["title"]);
-			xml_add_element($doc, $root, "link", "", $attributes);
-			break;
-		case 'photo':
-			$imgdata = get_photo_info($siteinfo["image"]);
-			$attributes = array("rel" => "enclosure",
-					"href" => $siteinfo["image"],
-					"type" => $imgdata["mime"],
-					"length" => intval($imgdata["size"]));
-			xml_add_element($doc, $root, "link", "", $attributes);
-			break;
-		case 'video':
-			$attributes = array("rel" => "enclosure",
-					"href" => $siteinfo["url"],
-					"type" => "text/html; charset=UTF-8",
-					"length" => "",
-					"title" => $siteinfo["title"]);
-			xml_add_element($doc, $root, "link", "", $attributes);
-			break;
-		default:
-			break;
-	}
-
-	if (($siteinfo["type"] != "photo") AND isset($siteinfo["image"])) {
-		$photodata = get_photo_info($siteinfo["image"]);
-
-		$attributes = array("rel" => "preview", "href" => $siteinfo["image"], "media:width" => $photodata[0], "media:height" => $photodata[1]);
-		xml_add_element($doc, $root, "link", "", $attributes);
-	}
-
-
-	$arr = explode('[/attach],',$item['attach']);
-	if(count($arr)) {
-		foreach($arr as $r) {
-			$matches = false;
-			$cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|',$r,$matches);
-			if($cnt) {
+		switch($siteinfo["type"]) {
+			case 'link':
 				$attributes = array("rel" => "enclosure",
-						"href" => $matches[1],
-						"type" => $matches[3]);
+						"href" => $siteinfo["url"],
+						"type" => "text/html; charset=UTF-8",
+						"length" => "",
+						"title" => $siteinfo["title"]);
+				xml::add_element($doc, $root, "link", "", $attributes);
+				break;
+			case 'photo':
+				$imgdata = get_photo_info($siteinfo["image"]);
+				$attributes = array("rel" => "enclosure",
+						"href" => $siteinfo["image"],
+						"type" => $imgdata["mime"],
+						"length" => intval($imgdata["size"]));
+				xml::add_element($doc, $root, "link", "", $attributes);
+				break;
+			case 'video':
+				$attributes = array("rel" => "enclosure",
+						"href" => $siteinfo["url"],
+						"type" => "text/html; charset=UTF-8",
+						"length" => "",
+						"title" => $siteinfo["title"]);
+				xml::add_element($doc, $root, "link", "", $attributes);
+				break;
+			default:
+				break;
+		}
 
-				if(intval($matches[2]))
-					$attributes["length"] = intval($matches[2]);
+		if (($siteinfo["type"] != "photo") AND isset($siteinfo["image"])) {
+			$photodata = get_photo_info($siteinfo["image"]);
 
-				if(trim($matches[4]) != "")
-					$attributes["title"] = trim($matches[4]);
+			$attributes = array("rel" => "preview", "href" => $siteinfo["image"], "media:width" => $photodata[0], "media:height" => $photodata[1]);
+			xml::add_element($doc, $root, "link", "", $attributes);
+		}
 
-				xml_add_element($doc, $root, "link", "", $attributes);
+
+		$arr = explode('[/attach],',$item['attach']);
+		if(count($arr)) {
+			foreach($arr as $r) {
+				$matches = false;
+				$cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|',$r,$matches);
+				if($cnt) {
+					$attributes = array("rel" => "enclosure",
+							"href" => $matches[1],
+							"type" => $matches[3]);
+
+					if(intval($matches[2]))
+						$attributes["length"] = intval($matches[2]);
+
+					if(trim($matches[4]) != "")
+						$attributes["title"] = trim($matches[4]);
+
+					xml::add_element($doc, $root, "link", "", $attributes);
+				}
 			}
 		}
 	}
-}
 
-function ostatus_add_author($doc, $owner) {
-	$a = get_app();
+	private function add_author($doc, $owner) {
 
-	$r = q("SELECT `homepage` FROM `profile` WHERE `uid` = %d AND `is-default` LIMIT 1", intval($owner["uid"]));
-	if ($r)
-		$profile = $r[0];
+		$r = q("SELECT `homepage` FROM `profile` WHERE `uid` = %d AND `is-default` LIMIT 1", intval($owner["uid"]));
+		if ($r)
+			$profile = $r[0];
 
-	$author = $doc->createElement("author");
-	xml_add_element($doc, $author, "activity:object-type", ACTIVITY_OBJ_PERSON);
-	xml_add_element($doc, $author, "uri", $owner["url"]);
-	xml_add_element($doc, $author, "name", $owner["name"]);
+		$author = $doc->createElement("author");
+		xml::add_element($doc, $author, "activity:object-type", ACTIVITY_OBJ_PERSON);
+		xml::add_element($doc, $author, "uri", $owner["url"]);
+		xml::add_element($doc, $author, "name", $owner["name"]);
+		xml::add_element($doc, $author, "summary", bbcode($owner["about"], false, false, 7));
 
-	$attributes = array("rel" => "alternate", "type" => "text/html", "href" => $owner["url"]);
-	xml_add_element($doc, $author, "link", "", $attributes);
+		$attributes = array("rel" => "alternate", "type" => "text/html", "href" => $owner["url"]);
+		xml::add_element($doc, $author, "link", "", $attributes);
 
-	$attributes = array(
-			"rel" => "avatar",
-			"type" => "image/jpeg", // To-Do?
-			"media:width" => 175,
-			"media:height" => 175,
-			"href" => $owner["photo"]);
-	xml_add_element($doc, $author, "link", "", $attributes);
-
-	if (isset($owner["thumb"])) {
 		$attributes = array(
 				"rel" => "avatar",
 				"type" => "image/jpeg", // To-Do?
-				"media:width" => 80,
-				"media:height" => 80,
-				"href" => $owner["thumb"]);
-		xml_add_element($doc, $author, "link", "", $attributes);
+				"media:width" => 175,
+				"media:height" => 175,
+				"href" => $owner["photo"]);
+		xml::add_element($doc, $author, "link", "", $attributes);
+
+		if (isset($owner["thumb"])) {
+			$attributes = array(
+					"rel" => "avatar",
+					"type" => "image/jpeg", // To-Do?
+					"media:width" => 80,
+					"media:height" => 80,
+					"href" => $owner["thumb"]);
+			xml::add_element($doc, $author, "link", "", $attributes);
+		}
+
+		xml::add_element($doc, $author, "poco:preferredUsername", $owner["nick"]);
+		xml::add_element($doc, $author, "poco:displayName", $owner["name"]);
+		xml::add_element($doc, $author, "poco:note", bbcode($owner["about"], false, false, 7));
+
+		if (trim($owner["location"]) != "") {
+			$element = $doc->createElement("poco:address");
+			xml::add_element($doc, $element, "poco:formatted", $owner["location"]);
+			$author->appendChild($element);
+		}
+
+		if (trim($profile["homepage"]) != "") {
+			$urls = $doc->createElement("poco:urls");
+			xml::add_element($doc, $urls, "poco:type", "homepage");
+			xml::add_element($doc, $urls, "poco:value", $profile["homepage"]);
+			xml::add_element($doc, $urls, "poco:primary", "true");
+			$author->appendChild($urls);
+		}
+
+		if (count($profile)) {
+			xml::add_element($doc, $author, "followers", "", array("url" => App::get_baseurl()."/viewcontacts/".$owner["nick"]));
+			xml::add_element($doc, $author, "statusnet:profile_info", "", array("local_id" => $owner["uid"]));
+		}
+
+		return $author;
 	}
 
-	xml_add_element($doc, $author, "poco:preferredUsername", $owner["nick"]);
-	xml_add_element($doc, $author, "poco:displayName", $owner["name"]);
-	xml_add_element($doc, $author, "poco:note", $owner["about"]);
+	/**
+	 * @TODO Picture attachments should look like this:
+	 *	<a href="https://status.pirati.ca/attachment/572819" title="https://status.pirati.ca/file/heluecht-20151202T222602-rd3u49p.gif"
+	 *	class="attachment thumbnail" id="attachment-572819" rel="nofollow external">https://status.pirati.ca/attachment/572819</a>
+	 *
+	*/
 
-	if (trim($owner["location"]) != "") {
-		$element = $doc->createElement("poco:address");
-		xml_add_element($doc, $element, "poco:formatted", $owner["location"]);
-		$author->appendChild($element);
+	function construct_verb($item) {
+		if ($item['verb'])
+			return $item['verb'];
+		return ACTIVITY_POST;
 	}
 
-	if (trim($profile["homepage"]) != "") {
-		$urls = $doc->createElement("poco:urls");
-		xml_add_element($doc, $urls, "poco:type", "homepage");
-		xml_add_element($doc, $urls, "poco:value", $profile["homepage"]);
-		xml_add_element($doc, $urls, "poco:primary", "true");
-		$author->appendChild($urls);
+	function construct_objecttype($item) {
+		if (in_array($item['object-type'], array(ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_COMMENT)))
+			return $item['object-type'];
+		return ACTIVITY_OBJ_NOTE;
 	}
 
-	if (count($profile)) {
-		xml_add_element($doc, $author, "followers", "", array("url" => $a->get_baseurl()."/viewcontacts/".$owner["nick"]));
-		xml_add_element($doc, $author, "statusnet:profile_info", "", array("local_id" => $owner["uid"]));
+	private function entry($doc, $item, $owner, $toplevel = false) {
+		$repeated_guid = self::get_reshared_guid($item);
+		if ($repeated_guid != "")
+			$xml = self::reshare_entry($doc, $item, $owner, $repeated_guid, $toplevel);
+
+		if ($xml)
+			return $xml;
+
+		if ($item["verb"] == ACTIVITY_LIKE)
+			return self::like_entry($doc, $item, $owner, $toplevel);
+		else
+			return self::note_entry($doc, $item, $owner, $toplevel);
 	}
 
-	return $author;
-}
+	private function source_entry($doc, $contact) {
+		$source = $doc->createElement("source");
+		xml::add_element($doc, $source, "id", $contact["poll"]);
+		xml::add_element($doc, $source, "title", $contact["name"]);
+		xml::add_element($doc, $source, "link", "", array("rel" => "alternate",
+								"type" => "text/html",
+								"href" => $contact["alias"]));
+		xml::add_element($doc, $source, "link", "", array("rel" => "self",
+								"type" => "application/atom+xml",
+								"href" => $contact["poll"]));
+		xml::add_element($doc, $source, "icon", $contact["photo"]);
+		xml::add_element($doc, $source, "updated", datetime_convert("UTC","UTC",$contact["success_update"]."+00:00",ATOM_TIME));
 
-/** 
- * @TODO Picture attachments should look like this:
- *	<a href="https://status.pirati.ca/attachment/572819" title="https://status.pirati.ca/file/heluecht-20151202T222602-rd3u49p.gif"
- *	class="attachment thumbnail" id="attachment-572819" rel="nofollow external">https://status.pirati.ca/attachment/572819</a>
- * 
-*/
-
-function ostatus_entry($doc, $item, $owner, $toplevel = false, $repeat = false) {
-	$a = get_app();
-
-	if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
-		logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
+		return $source;
 	}
 
-	$is_repeat = false;
+	private function contact_entry($url, $owner) {
 
-/*	if (!$repeat) {
-		$repeated_guid = get_reshared_guid($item);
+		$r = q("SELECT * FROM `contact` WHERE `nurl` = '%s' AND `uid` IN (0, %d) ORDER BY `uid` DESC LIMIT 1",
+			dbesc(normalise_link($url)), intval($owner["uid"]));
+		if ($r) {
+			$contact = $r[0];
+			$contact["uid"] = -1;
+		}
 
-		if ($repeated_guid != "") {
-			$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1",
-				intval($owner["uid"]), dbesc($repeated_guid));
+		if (!$r) {
+			$r = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1",
+				dbesc(normalise_link($url)));
 			if ($r) {
-				$repeated_item = $r[0];
-				$is_repeat = true;
+				$contact = $r[0];
+				$contact["uid"] = -1;
+				$contact["success_update"] = $contact["updated"];
 			}
 		}
-	}
-*/
-	if (!$toplevel AND !$repeat) {
-		$entry = $doc->createElement("entry");
-		$title = sprintf("New note by %s", $owner["nick"]);
-	} elseif (!$toplevel AND $repeat) {
-		$entry = $doc->createElement("activity:object");
-		$title = sprintf("New note by %s", $owner["nick"]);
-	} else {
-		$entry = $doc->createElementNS(NAMESPACE_ATOM1, "entry");
 
-		$entry->setAttribute("xmlns:thr", NAMESPACE_THREAD);
-		$entry->setAttribute("xmlns:georss", NAMESPACE_GEORSS);
-		$entry->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY);
-		$entry->setAttribute("xmlns:media", NAMESPACE_MEDIA);
-		$entry->setAttribute("xmlns:poco", NAMESPACE_POCO);
-		$entry->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
-		$entry->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
+		if (!$r)
+			$contact = owner;
 
-		$author = ostatus_add_author($doc, $owner);
-		$entry->appendChild($author);
-
-		$title = sprintf("New comment by %s", $owner["nick"]);
-	}
-
-	// To use the object-type "bookmark" we have to implement these elements:
-	//
-	// <activity:object-type>http://activitystrea.ms/schema/1.0/bookmark</activity:object-type>
-	// <title>Historic Rocket Landing</title>
-	// <summary>Nur ein Testbeitrag.</summary>
-	// <link rel="related" href="https://www.youtube.com/watch?v=9pillaOxGCo"/>
-	// <link rel="preview" href="https://pirati.cc/file/thumb-4526-450x338-b48c8055f0c2fed0c3f67adc234c4b99484a90c42ed3cac73dc1081a4d0a7bc1.jpg.jpg" media:width="450" media:height="338"/>
-	//
-	// But: it seems as if it doesn't federate well between the GS servers
-	// So we just set it to "note" to be sure that it reaches their target systems
-
-	if (!$repeat)
-		xml_add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE);
-	else
-		xml_add_element($doc, $entry, "activity:object-type", NAMESPACE_ACTIVITY_SCHEMA.'activity');
-
-	xml_add_element($doc, $entry, "id", $item["uri"]);
-	xml_add_element($doc, $entry, "title", $title);
-
-	if($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid'])
-		$body = fix_private_photos($item['body'],$owner['uid'],$item, 0);
-	else
-		$body = $item['body'];
-
-	$body = ostatus_format_picture_post($body);
-
-	if ($item['title'] != "")
-		$body = "[b]".$item['title']."[/b]\n\n".$body;
-
-	//$body = bb_remove_share_information($body);
-	$body = bbcode($body, false, false, 7);
-
-	xml_add_element($doc, $entry, "content", $body, array("type" => "html"));
-
-	xml_add_element($doc, $entry, "link", "", array("rel" => "alternate", "type" => "text/html",
-							"href" => $a->get_baseurl()."/display/".$item["guid"]));
-
-	xml_add_element($doc, $entry, "status_net", "", array("notice_id" => $item["id"]));
-
-	if (!$is_repeat)
-		xml_add_element($doc, $entry, "activity:verb", construct_verb($item));
-	else
-		xml_add_element($doc, $entry, "activity:verb", ACTIVITY_SHARE);
-
-	xml_add_element($doc, $entry, "published", datetime_convert("UTC","UTC",$item["created"]."+00:00",ATOM_TIME));
-	xml_add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME));
-
-	if ($is_repeat) {
-		$repeated_owner = array();
-		$repeated_owner["name"] = $repeated_item["author-name"];
-		$repeated_owner["url"] = $repeated_item["author-link"];
-		$repeated_owner["photo"] = $repeated_item["author-avatar"];
-		$repeated_owner["nick"] = $repeated_owner["name"];
-		$repeated_owner["location"] = "";
-		$repeated_owner["about"] = "";
-		$repeated_owner["uid"] = 0;
-
-		// Fetch the missing data from the global contacts
-		$r =q("SELECT * FROM `gcontact` WHERE `nurl` = '%s'", normalise_link($repeated_item["author-link"]));
-		if ($r) {
-			if ($r[0]["nick"] != "")
-				$repeated_owner["nick"] = $r[0]["nick"];
-
-			$repeated_owner["location"] = $r[0]["location"];
-			$repeated_owner["about"] = $r[0]["about"];
+		if (!isset($contact["poll"])) {
+			$data = probe_url($url);
+			$contact["alias"] = $data["alias"];
+			$contact["poll"] = $data["poll"];
 		}
 
-		$entry_repeat = ostatus_entry($doc, $repeated_item, $repeated_owner, false, true);
-		$entry->appendChild($entry_repeat);
-	} elseif ($repeat) {
-		$author = ostatus_add_author($doc, $owner);
-		$entry->appendChild($author);
+		if (!isset($contact["alias"]))
+			$contact["alias"] = $contact["url"];
+
+		return $contact;
 	}
 
-	$mentioned = array();
+	private function reshare_entry($doc, $item, $owner, $repeated_guid, $toplevel) {
+
+		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
+			logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
+		}
+
+		$title = self::entry_header($doc, $entry, $owner, $toplevel);
+
+		$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' AND NOT `private` AND `network` IN ('%s', '%s', '%s') LIMIT 1",
+			intval($owner["uid"]), dbesc($repeated_guid),
+			dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
+		if ($r)
+			$repeated_item = $r[0];
+		else
+			return false;
+
+		$contact = self::contact_entry($repeated_item['author-link'], $owner);
 
-	if (($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || (($item['thr-parent'] !== '') && ($item['thr-parent'] !== $item['uri']))) {
-		$parent = q("SELECT `guid`, `author-link`, `owner-link` FROM `item` WHERE `id` = %d", intval($item["parent"]));
 		$parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']);
 
-		$attributes = array(
-				"ref" => $parent_item,
-				"type" => "text/html",
-				"href" => $a->get_baseurl()."/display/".$parent[0]["guid"]);
-		xml_add_element($doc, $entry, "thr:in-reply-to", "", $attributes);
+		$title = $owner["nick"]." repeated a notice by ".$contact["nick"];
 
-		$attributes = array(
-				"rel" => "related",
-				"href" => $a->get_baseurl()."/display/".$parent[0]["guid"]);
-		xml_add_element($doc, $entry, "link", "", $attributes);
+		self::entry_content($doc, $entry, $item, $owner, $title, ACTIVITY_SHARE, false);
 
-		$mentioned[$parent[0]["author-link"]] = $parent[0]["author-link"];
-		$mentioned[$parent[0]["owner-link"]] = $parent[0]["owner-link"];
+		$as_object = $doc->createElement("activity:object");
 
-		$thrparent = q("SELECT `guid`, `author-link`, `owner-link` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
+// ostatusWaEeYs
+// ostatusogu9zg - besser
+		xml::add_element($doc, $as_object, "activity:object-type", NAMESPACE_ACTIVITY_SCHEMA."activity");
+
+		self::entry_content($doc, $as_object, $repeated_item, $owner, "", "", false);
+
+		$author = self::add_author($doc, $contact);
+                $as_object->appendChild($author);
+
+		$as_object2 = $doc->createElement("activity:object");
+
+		xml::add_element($doc, $as_object2, "activity:object-type", self::construct_objecttype($repeated_item));
+
+		$title = sprintf("New comment by %s", $contact["nick"]);
+
+		self::entry_content($doc, $as_object2, $repeated_item, $owner, $title);
+
+		$as_object->appendChild($as_object2);
+
+		self::entry_footer($doc, $as_object, $item, $owner, false);
+
+		$source = self::source_entry($doc, $contact);
+
+		$as_object->appendChild($source);
+
+		$entry->appendChild($as_object);
+
+		self::entry_footer($doc, $entry, $item, $owner);
+
+		return $entry;
+	}
+
+	private function like_entry($doc, $item, $owner, $toplevel) {
+
+		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
+			logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
+		}
+
+		$title = self::entry_header($doc, $entry, $owner, $toplevel);
+
+		$verb = NAMESPACE_ACTIVITY_SCHEMA."favorite";
+		self::entry_content($doc, $entry, $item, $owner, "Favorite", $verb, false);
+
+		$as_object = $doc->createElement("activity:object");
+
+		$parent = q("SELECT * FROM `item` WHERE `id` = %d", intval($item["parent"]));
+		$parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']);
+
+		xml::add_element($doc, $as_object, "activity:object-type", self::construct_objecttype($parent[0]));
+
+		self::entry_content($doc, $as_object, $parent[0], $owner, "New entry");
+
+		$entry->appendChild($as_object);
+
+		self::entry_footer($doc, $entry, $item, $owner);
+
+		return $entry;
+	}
+
+	private function note_entry($doc, $item, $owner, $toplevel) {
+
+		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
+			logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
+		}
+
+		$title = self::entry_header($doc, $entry, $owner, $toplevel);
+
+		xml::add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE);
+
+		self::entry_content($doc, $entry, $item, $owner, $title);
+
+		self::entry_footer($doc, $entry, $item, $owner);
+
+		return $entry;
+	}
+
+	private function entry_header($doc, &$entry, $owner, $toplevel) {
+		if (!$toplevel) {
+			$entry = $doc->createElement("entry");
+			$title = sprintf("New note by %s", $owner["nick"]);
+		} else {
+			$entry = $doc->createElementNS(NAMESPACE_ATOM1, "entry");
+
+			$entry->setAttribute("xmlns:thr", NAMESPACE_THREAD);
+			$entry->setAttribute("xmlns:georss", NAMESPACE_GEORSS);
+			$entry->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY);
+			$entry->setAttribute("xmlns:media", NAMESPACE_MEDIA);
+			$entry->setAttribute("xmlns:poco", NAMESPACE_POCO);
+			$entry->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
+			$entry->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
+
+			$author = self::add_author($doc, $owner);
+			$entry->appendChild($author);
+
+			$title = sprintf("New comment by %s", $owner["nick"]);
+		}
+		return $title;
+	}
+
+	private function entry_content($doc, $entry, $item, $owner, $title, $verb = "", $complete = true) {
+
+		if ($verb == "")
+			$verb = self::construct_verb($item);
+
+		xml::add_element($doc, $entry, "id", $item["uri"]);
+		xml::add_element($doc, $entry, "title", $title);
+
+		$body = self::format_picture_post($item['body']);
+
+		if ($item['title'] != "")
+			$body = "[b]".$item['title']."[/b]\n\n".$body;
+
+		$body = bbcode($body, false, false, 7);
+
+		xml::add_element($doc, $entry, "content", $body, array("type" => "html"));
+
+		xml::add_element($doc, $entry, "link", "", array("rel" => "alternate", "type" => "text/html",
+								"href" => App::get_baseurl()."/display/".$item["guid"]));
+
+		if ($complete)
+			xml::add_element($doc, $entry, "status_net", "", array("notice_id" => $item["id"]));
+
+		xml::add_element($doc, $entry, "activity:verb", $verb);
+
+		xml::add_element($doc, $entry, "published", datetime_convert("UTC","UTC",$item["created"]."+00:00",ATOM_TIME));
+		xml::add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME));
+	}
+
+	private function entry_footer($doc, $entry, $item, $owner, $complete = true) {
+
+		$mentioned = array();
+
+		if (($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || (($item['thr-parent'] !== '') && ($item['thr-parent'] !== $item['uri']))) {
+			$parent = q("SELECT `guid`, `author-link`, `owner-link` FROM `item` WHERE `id` = %d", intval($item["parent"]));
+			$parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']);
+
+			$attributes = array(
+					"ref" => $parent_item,
+					"type" => "text/html",
+					"href" => App::get_baseurl()."/display/".$parent[0]["guid"]);
+			xml::add_element($doc, $entry, "thr:in-reply-to", "", $attributes);
+
+			$attributes = array(
+					"rel" => "related",
+					"href" => App::get_baseurl()."/display/".$parent[0]["guid"]);
+			xml::add_element($doc, $entry, "link", "", $attributes);
+
+			$mentioned[$parent[0]["author-link"]] = $parent[0]["author-link"];
+			$mentioned[$parent[0]["owner-link"]] = $parent[0]["owner-link"];
+
+			$thrparent = q("SELECT `guid`, `author-link`, `owner-link` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
+					intval($owner["uid"]),
+					dbesc($parent_item));
+			if ($thrparent) {
+				$mentioned[$thrparent[0]["author-link"]] = $thrparent[0]["author-link"];
+				$mentioned[$thrparent[0]["owner-link"]] = $thrparent[0]["owner-link"];
+			}
+		}
+
+		xml::add_element($doc, $entry, "link", "", array("rel" => "ostatus:conversation",
+							"href" => App::get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]));
+		xml::add_element($doc, $entry, "ostatus:conversation", App::get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]);
+
+		$tags = item_getfeedtags($item);
+
+		if(count($tags))
+			foreach($tags as $t)
+				if ($t[0] == "@")
+					$mentioned[$t[1]] = $t[1];
+
+		// Make sure that mentions are accepted (GNU Social has problems with mixing HTTP and HTTPS)
+		$newmentions = array();
+		foreach ($mentioned AS $mention) {
+			$newmentions[str_replace("http://", "https://", $mention)] = str_replace("http://", "https://", $mention);
+			$newmentions[str_replace("https://", "http://", $mention)] = str_replace("https://", "http://", $mention);
+		}
+		$mentioned = $newmentions;
+
+		foreach ($mentioned AS $mention) {
+			$r = q("SELECT `forum`, `prv` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s'",
 				intval($owner["uid"]),
-				dbesc($parent_item));
-		if ($thrparent) {
-			$mentioned[$thrparent[0]["author-link"]] = $thrparent[0]["author-link"];
-			$mentioned[$thrparent[0]["owner-link"]] = $thrparent[0]["owner-link"];
+				dbesc(normalise_link($mention)));
+			if ($r[0]["forum"] OR $r[0]["prv"])
+				xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
+											"ostatus:object-type" => ACTIVITY_OBJ_GROUP,
+											"href" => $mention));
+			else
+				xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
+											"ostatus:object-type" => ACTIVITY_OBJ_PERSON,
+											"href" => $mention));
+		}
+
+		if (!$item["private"]) {
+			xml::add_element($doc, $entry, "link", "", array("rel" => "ostatus:attention",
+									"href" => "http://activityschema.org/collection/public"));
+			xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
+									"ostatus:object-type" => "http://activitystrea.ms/schema/1.0/collection",
+									"href" => "http://activityschema.org/collection/public"));
+		}
+
+		if(count($tags))
+			foreach($tags as $t)
+				if ($t[0] != "@")
+					xml::add_element($doc, $entry, "category", "", array("term" => $t[2]));
+
+		self::get_attachment($doc, $entry, $item);
+
+		if ($complete) {
+			$app = $item["app"];
+			if ($app == "")
+				$app = "web";
+
+			$attributes = array("local_id" => $item["id"], "source" => $app);
+
+			if (isset($parent["id"]))
+				$attributes["repeat_of"] = $parent["id"];
+
+			if ($item["coord"] != "")
+				xml::add_element($doc, $entry, "georss:point", $item["coord"]);
+
+			xml::add_element($doc, $entry, "statusnet:notice_info", "", $attributes);
 		}
 	}
 
-	xml_add_element($doc, $entry, "link", "", array("rel" => "ostatus:conversation",
-							"href" => $a->get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]));
-	xml_add_element($doc, $entry, "ostatus:conversation", $a->get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]);
+	public static function feed(&$a, $owner_nick, $last_update) {
 
-	$tags = item_getfeedtags($item);
+		$r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`
+				FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
+				WHERE `contact`.`self` AND `user`.`nickname` = '%s' LIMIT 1",
+				dbesc($owner_nick));
+		if (!$r)
+			return;
 
-	if(count($tags))
-		foreach($tags as $t)
-			if ($t[0] == "@")
-				$mentioned[$t[1]] = $t[1];
+		$owner = $r[0];
 
-	// Make sure that mentions are accepted (GNU Social has problems with mixing HTTP and HTTPS)
-	$newmentions = array();
-	foreach ($mentioned AS $mention) {
-		$newmentions[str_replace("http://", "https://", $mention)] = str_replace("http://", "https://", $mention);
-		$newmentions[str_replace("https://", "http://", $mention)] = str_replace("https://", "http://", $mention);
-	}
-	$mentioned = $newmentions;
+		if(!strlen($last_update))
+			$last_update = 'now -30 days';
 
-	foreach ($mentioned AS $mention) {
-		$r = q("SELECT `forum`, `prv` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s'",
-			intval($owner["uid"]),
-			dbesc(normalise_link($mention)));
-		if ($r[0]["forum"] OR $r[0]["prv"])
-			xml_add_element($doc, $entry, "link", "", array("rel" => "mentioned",
-										"ostatus:object-type" => ACTIVITY_OBJ_GROUP,
-										"href" => $mention));
-		else
-			xml_add_element($doc, $entry, "link", "", array("rel" => "mentioned",
-										"ostatus:object-type" => ACTIVITY_OBJ_PERSON,
-										"href" => $mention));
+		$check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s');
+
+		$items = q("SELECT STRAIGHT_JOIN `item`.*, `item`.`id` AS `item_id` FROM `item`
+				INNER JOIN `thread` ON `thread`.`iid` = `item`.`parent`
+				LEFT JOIN `item` AS `thritem` ON `thritem`.`uri`=`item`.`thr-parent` AND `thritem`.`uid`=`item`.`uid`
+				WHERE `item`.`uid` = %d AND `item`.`received` > '%s' AND NOT `item`.`private` AND NOT `item`.`deleted`
+					AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
+					AND ((`item`.`wall` AND (`item`.`parent` = `item`.`id`))
+						OR (`item`.`network` = '%s' AND ((`thread`.`network` IN ('%s', '%s')) OR (`thritem`.`network` IN ('%s', '%s')))) AND `thread`.`mention`)
+					AND ((`item`.`owner-link` IN ('%s', '%s') AND (`item`.`parent` = `item`.`id`))
+						OR (`item`.`author-link` IN ('%s', '%s')))
+				ORDER BY `item`.`received` DESC
+				LIMIT 0, 300",
+				intval($owner["uid"]), dbesc($check_date), dbesc(NETWORK_DFRN),
+				//dbesc(NETWORK_OSTATUS), dbesc(NETWORK_OSTATUS),
+				//dbesc(NETWORK_OSTATUS), dbesc(NETWORK_OSTATUS),
+				dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN),
+				dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN),
+				dbesc($owner["nurl"]), dbesc(str_replace("http://", "https://", $owner["nurl"])),
+				dbesc($owner["nurl"]), dbesc(str_replace("http://", "https://", $owner["nurl"]))
+			);
+
+		$doc = new DOMDocument('1.0', 'utf-8');
+		$doc->formatOutput = true;
+
+		$root = self::add_header($doc, $owner);
+
+		foreach ($items AS $item) {
+			$entry = self::entry($doc, $item, $owner);
+			$root->appendChild($entry);
+		}
+
+		return(trim($doc->saveXML()));
 	}
 
-	if (!$item["private"])
-		xml_add_element($doc, $entry, "link", "", array("rel" => "mentioned",
-								"ostatus:object-type" => "http://activitystrea.ms/schema/1.0/collection",
-								"href" => "http://activityschema.org/collection/public"));
+	public static function salmon($item,$owner) {
 
-	if(count($tags))
-		foreach($tags as $t)
-			if ($t[0] != "@")
-				xml_add_element($doc, $entry, "category", "", array("term" => $t[2]));
+		$doc = new DOMDocument('1.0', 'utf-8');
+		$doc->formatOutput = true;
 
-	ostatus_get_attachment($doc, $entry, $item);
+		$entry = self::entry($doc, $item, $owner, true);
 
-	/// @TODO
-	/// The API call has yet to be implemented
-	//$attributes = array("href" => $a->get_baseurl()."/api/statuses/show/".$item["id"].".atom",
-	//		"rel" => "self", "type" => "application/atom+xml");
-	//xml_add_element($doc, $entry, "link", "", $attributes);
+		$doc->appendChild($entry);
 
-	//$attributes = array("href" => $a->get_baseurl()."/api/statuses/show/".$item["id"].".atom",
-	//		"rel" => "edit", "type" => "application/atom+xml");
-	//xml_add_element($doc, $entry, "link", "", $attributes);
-
-	$app = $item["app"];
-	if ($app == "")
-		$app = "web";
-
-
-	$attributes = array("local_id" => $item["id"], "source" => $app);
-	if ($is_repeat)
-		$attributes["repeat_of"] = $repeated_item["id"];
-
-	xml_add_element($doc, $entry, "statusnet:notice_info", "", $attributes);
-
-	return $entry;
-}
-
-function ostatus_feed(&$a, $owner_nick, $last_update) {
-
-	$r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`
-			FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
-			WHERE `contact`.`self` AND `user`.`nickname` = '%s' LIMIT 1",
-			dbesc($owner_nick));
-	if (!$r)
-		return;
-
-	$owner = $r[0];
-
-	if(!strlen($last_update))
-		$last_update = 'now -30 days';
-
-	$check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s');
-
-	$items = q("SELECT STRAIGHT_JOIN `item`.*, `item`.`id` AS `item_id` FROM `item`
-			INNER JOIN `thread` ON `thread`.`iid` = `item`.`parent`
-			LEFT JOIN `item` AS `thritem` ON `thritem`.`uri`=`item`.`thr-parent` AND `thritem`.`uid`=`item`.`uid`
-			WHERE `item`.`uid` = %d AND `item`.`received` > '%s' AND NOT `item`.`private` AND NOT `item`.`deleted`
-				AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
-				AND ((`item`.`wall` AND (`item`.`parent` = `item`.`id`))
-					OR (`item`.`network` = '%s' AND ((`thread`.`network` IN ('%s', '%s')) OR (`thritem`.`network` IN ('%s', '%s')))) AND `thread`.`mention`)
-				AND ((`item`.`owner-link` IN ('%s', '%s') AND (`item`.`parent` = `item`.`id`))
-					OR (`item`.`author-link` IN ('%s', '%s')))
-			ORDER BY `item`.`received` DESC
-			LIMIT 0, 300",
-			intval($owner["uid"]), dbesc($check_date), dbesc(NETWORK_DFRN),
-			//dbesc(NETWORK_OSTATUS), dbesc(NETWORK_OSTATUS),
-			//dbesc(NETWORK_OSTATUS), dbesc(NETWORK_OSTATUS),
-			dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN),
-			dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN),
-			dbesc($owner["nurl"]), dbesc(str_replace("http://", "https://", $owner["nurl"])),
-			dbesc($owner["nurl"]), dbesc(str_replace("http://", "https://", $owner["nurl"]))
-		);
-
-	$doc = new DOMDocument('1.0', 'utf-8');
-	$doc->formatOutput = true;
-
-	$root = ostatus_add_header($doc, $owner);
-
-	foreach ($items AS $item) {
-		$entry = ostatus_entry($doc, $item, $owner);
-		$root->appendChild($entry);
+		return(trim($doc->saveXML()));
 	}
-
-	return(trim($doc->saveXML()));
-}
-
-function ostatus_salmon($item,$owner) {
-
-	$doc = new DOMDocument('1.0', 'utf-8');
-	$doc->formatOutput = true;
-
-	$entry = ostatus_entry($doc, $item, $owner, true);
-
-	$doc->appendChild($entry);
-
-	return(trim($doc->saveXML()));
 }
 ?>
diff --git a/include/xml.php b/include/xml.php
index a454e61566..76ad88cf48 100644
--- a/include/xml.php
+++ b/include/xml.php
@@ -92,5 +92,40 @@ class xml {
 				self::copy($childentry, $child, $childfield);
 		}
 	}
+
+	/**
+	 * @brief Create an XML element
+	 *
+	 * @param object $doc XML root
+	 * @param string $element XML element name
+	 * @param string $value XML value
+	 * @param array $attributes array containing the attributes
+	 *
+	 * @return object XML element object
+	 */
+	public static function create_element($doc, $element, $value = "", $attributes = array()) {
+		$element = $doc->createElement($element, xmlify($value));
+
+		foreach ($attributes AS $key => $value) {
+			$attribute = $doc->createAttribute($key);
+			$attribute->value = xmlify($value);
+			$element->appendChild($attribute);
+		}
+		return $element;
+	}
+
+	/**
+	 * @brief Create an XML and append it to the parent object
+	 *
+	 * @param object $doc XML root
+	 * @param object $parent parent object
+	 * @param string $element XML element name
+	 * @param string $value XML value
+	 * @param array $attributes array containing the attributes
+	 */
+	public static function add_element($doc, $parent, $element, $value = "", $attributes = array()) {
+		$element = self::create_element($doc, $element, $value, $attributes);
+		$parent->appendChild($element);
+	}
 }
 ?>

From 1f2c495cd8f68a9539dea7307fcbb1de3e84934b Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 30 Mar 2016 23:26:37 +0200
Subject: [PATCH 242/273] Tempory file is deleted

---
 include/ostatus2.php | 1778 ------------------------------------------
 1 file changed, 1778 deletions(-)
 delete mode 100644 include/ostatus2.php

diff --git a/include/ostatus2.php b/include/ostatus2.php
deleted file mode 100644
index 53c279f254..0000000000
--- a/include/ostatus2.php
+++ /dev/null
@@ -1,1778 +0,0 @@
-<?php
-require_once("include/Contact.php");
-require_once("include/threads.php");
-require_once("include/html2bbcode.php");
-require_once("include/bbcode.php");
-require_once("include/items.php");
-require_once("mod/share.php");
-require_once("include/enotify.php");
-require_once("include/socgraph.php");
-require_once("include/Photo.php");
-require_once("include/Scrape.php");
-require_once("include/follow.php");
-require_once("include/api.php");
-require_once("mod/proxy.php");
-
-class xml2 {
-	public static function create_element($doc, $element, $value = "", $attributes = array()) {
-		$element = $doc->createElement($element, xmlify($value));
-
-		foreach ($attributes AS $key => $value) {
-			$attribute = $doc->createAttribute($key);
-			$attribute->value = xmlify($value);
-			$element->appendChild($attribute);
-		}
-		return $element;
-	}
-
-	public static function add_element($doc, $parent, $element, $value = "", $attributes = array()) {
-		$element = self::create_element($doc, $element, $value, $attributes);
-		$parent->appendChild($element);
-	}
-}
-
-class ostatus {
-	const OSTATUS_DEFAULT_POLL_INTERVAL = 30; // given in minutes
-	const OSTATUS_DEFAULT_POLL_TIMEFRAME = 1440; // given in minutes
-	const OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS = 14400; // given in minutes
-
-	private function fetchauthor($xpath, $context, $importer, &$contact, $onlyfetch) {
-
-		$author = array();
-		$author["author-link"] = $xpath->evaluate('atom:author/atom:uri/text()', $context)->item(0)->nodeValue;
-		$author["author-name"] = $xpath->evaluate('atom:author/atom:name/text()', $context)->item(0)->nodeValue;
-
-		// Preserve the value
-		$authorlink = $author["author-link"];
-
-		$alternate = $xpath->query("atom:author/atom:link[@rel='alternate']", $context)->item(0)->attributes;
-		if (is_object($alternate))
-			foreach($alternate AS $attributes)
-				if ($attributes->name == "href")
-					$author["author-link"] = $attributes->textContent;
-
-		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'",
-			intval($importer["uid"]), dbesc(normalise_link($author["author-link"])),
-			dbesc(normalise_link($authorlink)), dbesc(NETWORK_STATUSNET));
-		if ($r) {
-			$contact = $r[0];
-			$author["contact-id"] = $r[0]["id"];
-		} else
-			$author["contact-id"] = $contact["id"];
-
-		$avatarlist = array();
-		$avatars = $xpath->query("atom:author/atom:link[@rel='avatar']", $context);
-		foreach($avatars AS $avatar) {
-			$href = "";
-			$width = 0;
-			foreach($avatar->attributes AS $attributes) {
-				if ($attributes->name == "href")
-					$href = $attributes->textContent;
-				if ($attributes->name == "width")
-					$width = $attributes->textContent;
-			}
-			if (($width > 0) AND ($href != ""))
-				$avatarlist[$width] = $href;
-		}
-		if (count($avatarlist) > 0) {
-			krsort($avatarlist);
-			$author["author-avatar"] = current($avatarlist);
-		}
-
-		$displayname = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue;
-		if ($displayname != "")
-			$author["author-name"] = $displayname;
-
-		$author["owner-name"] = $author["author-name"];
-		$author["owner-link"] = $author["author-link"];
-		$author["owner-avatar"] = $author["author-avatar"];
-
-		// Only update the contacts if it is an OStatus contact
-		if ($r AND !$onlyfetch AND ($contact["network"] == NETWORK_OSTATUS)) {
-			// Update contact data
-
-			$value = $xpath->query("atom:link[@rel='salmon']", $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["notify"] = $value;
-
-			$value = $xpath->evaluate('atom:author/uri/text()', $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["alias"] = $value;
-
-			$value = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["name"] = $value;
-
-			$value = $xpath->evaluate('atom:author/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["nick"] = $value;
-
-			$value = $xpath->evaluate('atom:author/poco:note/text()', $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["about"] = html2bbcode($value);
-
-			$value = $xpath->evaluate('atom:author/poco:address/poco:formatted/text()', $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["location"] = $value;
-
-			if (($contact["name"] != $r[0]["name"]) OR ($contact["nick"] != $r[0]["nick"]) OR ($contact["about"] != $r[0]["about"]) OR ($contact["location"] != $r[0]["location"])) {
-
-				logger("Update contact data for contact ".$contact["id"], LOGGER_DEBUG);
-
-				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', `name-date` = '%s' WHERE `id` = %d",
-					dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
-					dbesc(datetime_convert()), intval($contact["id"]));
-
-				poco_check($contact["url"], $contact["name"], $contact["network"], $author["author-avatar"], $contact["about"], $contact["location"],
-							"", "", "", datetime_convert(), 2, $contact["id"], $contact["uid"]);
-			}
-
-			if (isset($author["author-avatar"]) AND ($author["author-avatar"] != $r[0]['avatar'])) {
-				logger("Update profile picture for contact ".$contact["id"], LOGGER_DEBUG);
-
-				update_contact_avatar($author["author-avatar"], $importer["uid"], $contact["id"]);
-			}
-
-			$contact["generation"] = 2;
-			$contact["photo"] = $author["author-avatar"];
-			update_gcontact($contact);
-		}
-
-		return($author);
-	}
-
-	public static function salmon_author($xml, $importer) {
-
-		if ($xml == "")
-			return;
-
-		$doc = new DOMDocument();
-		@$doc->loadXML($xml);
-
-		$xpath = new DomXPath($doc);
-		$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
-		$xpath->registerNamespace('thr', NAMESPACE_THREAD);
-		$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
-		$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
-		$xpath->registerNamespace('media', NAMESPACE_MEDIA);
-		$xpath->registerNamespace('poco', NAMESPACE_POCO);
-		$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
-		$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
-
-		$entries = $xpath->query('/atom:entry');
-
-		foreach ($entries AS $entry) {
-			// fetch the author
-			$author = self::fetchauthor($xpath, $entry, $importer, $contact, true);
-			return $author;
-		}
-	}
-
-	public static function import($xml,$importer,&$contact, &$hub) {
-
-		logger("Import OStatus message", LOGGER_DEBUG);
-
-		if ($xml == "")
-			return;
-
-		//$tempfile = tempnam(get_temppath(), "import");
-		//file_put_contents($tempfile, $xml);
-
-		$doc = new DOMDocument();
-		@$doc->loadXML($xml);
-
-		$xpath = new DomXPath($doc);
-		$xpath->registerNamespace('atom', NAMESPACE_ATOM1);
-		$xpath->registerNamespace('thr', NAMESPACE_THREAD);
-		$xpath->registerNamespace('georss', NAMESPACE_GEORSS);
-		$xpath->registerNamespace('activity', NAMESPACE_ACTIVITY);
-		$xpath->registerNamespace('media', NAMESPACE_MEDIA);
-		$xpath->registerNamespace('poco', NAMESPACE_POCO);
-		$xpath->registerNamespace('ostatus', NAMESPACE_OSTATUS);
-		$xpath->registerNamespace('statusnet', NAMESPACE_STATUSNET);
-
-		$gub = "";
-		$hub_attributes = $xpath->query("/atom:feed/atom:link[@rel='hub']")->item(0)->attributes;
-		if (is_object($hub_attributes))
-			foreach($hub_attributes AS $hub_attribute)
-				if ($hub_attribute->name == "href") {
-					$hub = $hub_attribute->textContent;
-					logger("Found hub ".$hub, LOGGER_DEBUG);
-				}
-
-		$header = array();
-		$header["uid"] = $importer["uid"];
-		$header["network"] = NETWORK_OSTATUS;
-		$header["type"] = "remote";
-		$header["wall"] = 0;
-		$header["origin"] = 0;
-		$header["gravity"] = GRAVITY_PARENT;
-
-		// it could either be a received post or a post we fetched by ourselves
-		// depending on that, the first node is different
-		$first_child = $doc->firstChild->tagName;
-
-		if ($first_child == "feed")
-			$entries = $xpath->query('/atom:feed/atom:entry');
-		else
-			$entries = $xpath->query('/atom:entry');
-
-		$conversation = "";
-		$conversationlist = array();
-		$item_id = 0;
-
-		// Reverse the order of the entries
-		$entrylist = array();
-
-		foreach ($entries AS $entry)
-			$entrylist[] = $entry;
-
-		foreach (array_reverse($entrylist) AS $entry) {
-
-			$mention = false;
-
-			// fetch the author
-			if ($first_child == "feed")
-				$author = self::fetchauthor($xpath, $doc->firstChild, $importer, $contact, false);
-			else
-				$author = self::fetchauthor($xpath, $entry, $importer, $contact, false);
-
-			$value = $xpath->evaluate('atom:author/poco:preferredUsername/text()', $context)->item(0)->nodeValue;
-			if ($value != "")
-				$nickname = $value;
-			else
-				$nickname = $author["author-name"];
-
-			$item = array_merge($header, $author);
-
-			// Now get the item
-			$item["uri"] = $xpath->query('atom:id/text()', $entry)->item(0)->nodeValue;
-
-			$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
-				intval($importer["uid"]), dbesc($item["uri"]));
-			if ($r) {
-				logger("Item with uri ".$item["uri"]." for user ".$importer["uid"]." already existed under id ".$r[0]["id"], LOGGER_DEBUG);
-				continue;
-			}
-
-			$item["body"] = add_page_info_to_body(html2bbcode($xpath->query('atom:content/text()', $entry)->item(0)->nodeValue));
-			$item["object-type"] = $xpath->query('activity:object-type/text()', $entry)->item(0)->nodeValue;
-
-			if (($item["object-type"] == ACTIVITY_OBJ_BOOKMARK) OR ($item["object-type"] == ACTIVITY_OBJ_EVENT)) {
-				$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
-				$item["body"] = $xpath->query('atom:summary/text()', $entry)->item(0)->nodeValue;
-			} elseif ($item["object-type"] == ACTIVITY_OBJ_QUESTION)
-				$item["title"] = $xpath->query('atom:title/text()', $entry)->item(0)->nodeValue;
-
-			$item["object"] = $xml;
-			$item["verb"] = $xpath->query('activity:verb/text()', $entry)->item(0)->nodeValue;
-
-			/// @TODO
-			/// Delete a message
-			if ($item["verb"] == "qvitter-delete-notice") {
-				// ignore "Delete" messages (by now)
-				logger("Ignore delete message ".print_r($item, true));
-				continue;
-			}
-
-			if ($item["verb"] == ACTIVITY_JOIN) {
-				// ignore "Join" messages
-				logger("Ignore join message ".print_r($item, true));
-				continue;
-			}
-
-			if ($item["verb"] == ACTIVITY_FOLLOW) {
-				new_follower($importer, $contact, $item, $nickname);
-				continue;
-			}
-
-			if ($item["verb"] == NAMESPACE_OSTATUS."/unfollow") {
-				lose_follower($importer, $contact, $item, $dummy);
-				continue;
-			}
-
-			if ($item["verb"] == ACTIVITY_FAVORITE) {
-				$orig_uri = $xpath->query("activity:object/atom:id", $entry)->item(0)->nodeValue;
-				logger("Favorite ".$orig_uri." ".print_r($item, true));
-
-				$item["verb"] = ACTIVITY_LIKE;
-				$item["parent-uri"] = $orig_uri;
-				$item["gravity"] = GRAVITY_LIKE;
-			}
-
-			if ($item["verb"] == NAMESPACE_OSTATUS."/unfavorite") {
-				// Ignore "Unfavorite" message
-				logger("Ignore unfavorite message ".print_r($item, true));
-				continue;
-			}
-
-			// http://activitystrea.ms/schema/1.0/rsvp-yes
-			if (!in_array($item["verb"], array(ACTIVITY_POST, ACTIVITY_LIKE, ACTIVITY_SHARE)))
-				logger("Unhandled verb ".$item["verb"]." ".print_r($item, true));
-
-			$item["created"] = $xpath->query('atom:published/text()', $entry)->item(0)->nodeValue;
-			$item["edited"] = $xpath->query('atom:updated/text()', $entry)->item(0)->nodeValue;
-			$conversation = $xpath->query('ostatus:conversation/text()', $entry)->item(0)->nodeValue;
-
-			$related = "";
-
-			$inreplyto = $xpath->query('thr:in-reply-to', $entry);
-			if (is_object($inreplyto->item(0))) {
-				foreach($inreplyto->item(0)->attributes AS $attributes) {
-					if ($attributes->name == "ref")
-						$item["parent-uri"] = $attributes->textContent;
-					if ($attributes->name == "href")
-						$related = $attributes->textContent;
-				}
-			}
-
-			$georsspoint = $xpath->query('georss:point', $entry);
-			if ($georsspoint)
-				$item["coord"] = $georsspoint->item(0)->nodeValue;
-
-			$categories = $xpath->query('atom:category', $entry);
-			if ($categories) {
-				foreach ($categories AS $category) {
-					foreach($category->attributes AS $attributes)
-						if ($attributes->name == "term") {
-							$term = $attributes->textContent;
-							if(strlen($item["tag"]))
-								$item["tag"] .= ',';
-							$item["tag"] .= "#[url=".App::get_baseurl()."/search?tag=".$term."]".$term."[/url]";
-						}
-				}
-			}
-
-			$self = "";
-			$enclosure = "";
-
-			$links = $xpath->query('atom:link', $entry);
-			if ($links) {
-				$rel = "";
-				$href = "";
-				$type = "";
-				$length = "0";
-				$title = "";
-				foreach ($links AS $link) {
-					foreach($link->attributes AS $attributes) {
-						if ($attributes->name == "href")
-							$href = $attributes->textContent;
-						if ($attributes->name == "rel")
-							$rel = $attributes->textContent;
-						if ($attributes->name == "type")
-							$type = $attributes->textContent;
-						if ($attributes->name == "length")
-							$length = $attributes->textContent;
-						if ($attributes->name == "title")
-							$title = $attributes->textContent;
-					}
-					if (($rel != "") AND ($href != ""))
-						switch($rel) {
-							case "alternate":
-								$item["plink"] = $href;
-								if (($item["object-type"] == ACTIVITY_OBJ_QUESTION) OR
-									($item["object-type"] == ACTIVITY_OBJ_EVENT))
-									$item["body"] .= add_page_info($href);
-								break;
-							case "ostatus:conversation":
-								$conversation = $href;
-								break;
-							case "enclosure":
-								$enclosure = $href;
-								if(strlen($item["attach"]))
-									$item["attach"] .= ',';
-
-								$item["attach"] .= '[attach]href="'.$href.'" length="'.$length.'" type="'.$type.'" title="'.$title.'"[/attach]';
-								break;
-							case "related":
-								if ($item["object-type"] != ACTIVITY_OBJ_BOOKMARK) {
-									if (!isset($item["parent-uri"]))
-										$item["parent-uri"] = $href;
-
-									if ($related == "")
-										$related = $href;
-								} else
-									$item["body"] .= add_page_info($href);
-								break;
-							case "self":
-								$self = $href;
-								break;
-							case "mentioned":
-								// Notification check
-								if ($importer["nurl"] == normalise_link($href))
-									$mention = true;
-								break;
-						}
-				}
-			}
-
-			$local_id = "";
-			$repeat_of = "";
-
-			$notice_info = $xpath->query('statusnet:notice_info', $entry);
-			if ($notice_info AND ($notice_info->length > 0)) {
-				foreach($notice_info->item(0)->attributes AS $attributes) {
-					if ($attributes->name == "source")
-						$item["app"] = strip_tags($attributes->textContent);
-					if ($attributes->name == "local_id")
-						$local_id = $attributes->textContent;
-					if ($attributes->name == "repeat_of")
-						$repeat_of = $attributes->textContent;
-				}
-			}
-
-			// Is it a repeated post?
-			if ($repeat_of != "") {
-				$activityobjects = $xpath->query('activity:object', $entry)->item(0);
-
-				if (is_object($activityobjects)) {
-
-					$orig_uri = $xpath->query("activity:object/atom:id", $activityobjects)->item(0)->nodeValue;
-					if (!isset($orig_uri))
-						$orig_uri = $xpath->query('atom:id/text()', $activityobjects)->item(0)->nodeValue;
-
-					$orig_links = $xpath->query("activity:object/atom:link[@rel='alternate']", $activityobjects);
-					if ($orig_links AND ($orig_links->length > 0))
-						foreach($orig_links->item(0)->attributes AS $attributes)
-							if ($attributes->name == "href")
-								$orig_link = $attributes->textContent;
-
-					if (!isset($orig_link))
-						$orig_link = $xpath->query("atom:link[@rel='alternate']", $activityobjects)->item(0)->nodeValue;
-
-					if (!isset($orig_link))
-						$orig_link =  self::convert_href($orig_uri);
-
-					$orig_body = $xpath->query('activity:object/atom:content/text()', $activityobjects)->item(0)->nodeValue;
-					if (!isset($orig_body))
-						$orig_body = $xpath->query('atom:content/text()', $activityobjects)->item(0)->nodeValue;
-
-					$orig_created = $xpath->query('atom:published/text()', $activityobjects)->item(0)->nodeValue;
-
-					$orig_contact = $contact;
-					$orig_author = self::fetchauthor($xpath, $activityobjects, $importer, $orig_contact, false);
-
-					$item["author-name"] = $orig_author["author-name"];
-					$item["author-link"] = $orig_author["author-link"];
-					$item["author-avatar"] = $orig_author["author-avatar"];
-					$item["body"] = add_page_info_to_body(html2bbcode($orig_body));
-					$item["created"] = $orig_created;
-
-					$item["uri"] = $orig_uri;
-					$item["plink"] = $orig_link;
-
-					$item["verb"] = $xpath->query('activity:verb/text()', $activityobjects)->item(0)->nodeValue;
-
-					$item["object-type"] = $xpath->query('activity:object/activity:object-type/text()', $activityobjects)->item(0)->nodeValue;
-					if (!isset($item["object-type"]))
-						$item["object-type"] = $xpath->query('activity:object-type/text()', $activityobjects)->item(0)->nodeValue;
-				}
-			}
-
-			//if ($enclosure != "")
-			//	$item["body"] .= add_page_info($enclosure);
-
-			if (isset($item["parent-uri"])) {
-				$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
-					intval($importer["uid"]), dbesc($item["parent-uri"]));
-
-				if (!$r AND ($related != "")) {
-					$reply_path = str_replace("/notice/", "/api/statuses/show/", $related).".atom";
-
-					if ($reply_path != $related) {
-						logger("Fetching related items for user ".$importer["uid"]." from ".$reply_path, LOGGER_DEBUG);
-						$reply_xml = fetch_url($reply_path);
-
-						$reply_contact = $contact;
-						self::import($reply_xml,$importer,$reply_contact, $reply_hub);
-
-						// After the import try to fetch the parent item again
-						$r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
-							intval($importer["uid"]), dbesc($item["parent-uri"]));
-					}
-				}
-				if ($r) {
-					$item["type"] = 'remote-comment';
-					$item["gravity"] = GRAVITY_COMMENT;
-				}
-			} else
-				$item["parent-uri"] = $item["uri"];
-
-			$item_id = self::completion($conversation, $importer["uid"], $item, $self);
-
-			if (!$item_id) {
-				logger("Error storing item", LOGGER_DEBUG);
-				continue;
-			}
-
-			logger("Item was stored with id ".$item_id, LOGGER_DEBUG);
-		}
-	}
-
-	public static function convert_href($href) {
-		$elements = explode(":",$href);
-
-		if ((count($elements) <= 2) OR ($elements[0] != "tag"))
-			return $href;
-
-		$server = explode(",", $elements[1]);
-		$conversation = explode("=", $elements[2]);
-
-		if ((count($elements) == 4) AND ($elements[2] == "post"))
-			return "http://".$server[0]."/notice/".$elements[3];
-
-		if ((count($conversation) != 2) OR ($conversation[1] ==""))
-			return $href;
-
-		if ($elements[3] == "objectType=thread")
-			return "http://".$server[0]."/conversation/".$conversation[1];
-		else
-			return "http://".$server[0]."/notice/".$conversation[1];
-
-		return $href;
-	}
-
-	public static function check_conversations($mentions = false, $override = false) {
-		$last = get_config('system','ostatus_last_poll');
-
-		$poll_interval = intval(get_config('system','ostatus_poll_interval'));
-		if(! $poll_interval)
-			$poll_interval = OSTATUS_DEFAULT_POLL_INTERVAL;
-
-		// Don't poll if the interval is set negative
-		if (($poll_interval < 0) AND !$override)
-			return;
-
-		if (!$mentions) {
-			$poll_timeframe = intval(get_config('system','ostatus_poll_timeframe'));
-			if (!$poll_timeframe)
-				$poll_timeframe = OSTATUS_DEFAULT_POLL_TIMEFRAME;
-		} else {
-			$poll_timeframe = intval(get_config('system','ostatus_poll_timeframe'));
-			if (!$poll_timeframe)
-				$poll_timeframe = OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS;
-		}
-
-
-		if ($last AND !$override) {
-			$next = $last + ($poll_interval * 60);
-			if ($next > time()) {
-				logger('poll interval not reached');
-				return;
-			}
-		}
-
-		logger('cron_start');
-
-		$start = date("Y-m-d H:i:s", time() - ($poll_timeframe * 60));
-
-		if ($mentions)
-			$conversations = q("SELECT `term`.`oid`, `term`.`url`, `term`.`uid` FROM `term`
-						STRAIGHT_JOIN `thread` ON `thread`.`iid` = `term`.`oid` AND `thread`.`uid` = `term`.`uid`
-						WHERE `term`.`type` = 7 AND `term`.`term` > '%s' AND `thread`.`mention`
-						GROUP BY `term`.`url`, `term`.`uid` ORDER BY `term`.`term` DESC", dbesc($start));
-		else
-			$conversations = q("SELECT `oid`, `url`, `uid` FROM `term`
-						WHERE `type` = 7 AND `term` > '%s'
-						GROUP BY `url`, `uid` ORDER BY `term` DESC", dbesc($start));
-
-		foreach ($conversations AS $conversation) {
-			self::completion($conversation['url'], $conversation['uid']);
-		}
-
-		logger('cron_end');
-
-		set_config('system','ostatus_last_poll', time());
-	}
-
-	/**
-	 * @brief Updates the gcontact table with actor data from the conversation
-	 *
-	 * @param object $actor The actor object that contains the contact data
-	 */
-	private function conv_fetch_actor($actor) {
-
-		// We set the generation to "3" since the data here is not as reliable as the data we get on other occasions
-		$contact = array("network" => NETWORK_OSTATUS, "generation" => 3);
-
-		if (isset($actor->url))
-			$contact["url"] = $actor->url;
-
-		if (isset($actor->displayName))
-			$contact["name"] = $actor->displayName;
-
-		if (isset($actor->portablecontacts_net->displayName))
-			$contact["name"] = $actor->portablecontacts_net->displayName;
-
-		if (isset($actor->portablecontacts_net->preferredUsername))
-			$contact["nick"] = $actor->portablecontacts_net->preferredUsername;
-
-		if (isset($actor->id))
-			$contact["alias"] = $actor->id;
-
-		if (isset($actor->summary))
-			$contact["about"] = $actor->summary;
-
-		if (isset($actor->portablecontacts_net->note))
-			$contact["about"] = $actor->portablecontacts_net->note;
-
-		if (isset($actor->portablecontacts_net->addresses->formatted))
-			$contact["location"] = $actor->portablecontacts_net->addresses->formatted;
-
-
-		if (isset($actor->image->url))
-			$contact["photo"] = $actor->image->url;
-
-		if (isset($actor->image->width))
-			$avatarwidth = $actor->image->width;
-
-		if (is_array($actor->status_net->avatarLinks))
-			foreach ($actor->status_net->avatarLinks AS $avatar) {
-				if ($avatarsize < $avatar->width) {
-					$contact["photo"] = $avatar->url;
-					$avatarsize = $avatar->width;
-				}
-			}
-
-		update_gcontact($contact);
-	}
-
-	/**
-	 * @brief Fetches the conversation url for a given item link or conversation id
-	 *
-	 * @param string $self The link to the posting
-	 * @param string $conversation_id The conversation id
-	 *
-	 * @return string The conversation url
-	 */
-	private function fetch_conversation($self, $conversation_id = "") {
-
-		if ($conversation_id != "") {
-			$elements = explode(":", $conversation_id);
-
-			if ((count($elements) <= 2) OR ($elements[0] != "tag"))
-				return $conversation_id;
-		}
-
-		if ($self == "")
-			return "";
-
-		$json = str_replace(".atom", ".json", $self);
-
-		$raw = fetch_url($json);
-		if ($raw == "")
-			return "";
-
-		$data = json_decode($raw);
-		if (!is_object($data))
-			return "";
-
-		$conversation_id = $data->statusnet_conversation_id;
-
-		$pos = strpos($self, "/api/statuses/show/");
-		$base_url = substr($self, 0, $pos);
-
-		return $base_url."/conversation/".$conversation_id;
-	}
-
-	/**
-	 * @brief Fetches actor details of a given actor and user id
-	 *
-	 * @param string $actor The actor url
-	 * @param int $uid The user id
-	 * @param int $contact_id The default contact-id
-	 *
-	 * @return array Array with actor details
-	 */
-	private function get_actor_details($actor, $uid, $contact_id) {
-
-		$details = array();
-
-		$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
-					$uid, normalise_link($actor), NETWORK_STATUSNET);
-
-		if (!$contact)
-			$contact = q("SELECT `id`, `rel`, `network` FROM `contact` WHERE `uid` = %d AND `alias` IN ('%s', '%s') AND `network` != '%s'",
-					$uid, $actor, normalise_link($actor), NETWORK_STATUSNET);
-
-		if ($contact) {
-			logger("Found contact for url ".$actor, LOGGER_DEBUG);
-			$details["contact_id"] = $contact[0]["id"];
-			$details["network"] = $contact[0]["network"];
-
-			$details["not_following"] = !in_array($contact[0]["rel"], array(CONTACT_IS_SHARING, CONTACT_IS_FRIEND));
-		} else {
-			logger("No contact found for user ".$uid." and url ".$actor, LOGGER_DEBUG);
-
-			// Adding a global contact
-			/// @TODO Use this data for the post
-			$details["global_contact_id"] = get_contact($actor, 0);
-
-			logger("Global contact ".$global_contact_id." found for url ".$actor, LOGGER_DEBUG);
-
-			$details["contact_id"] = $contact_id;
-			$details["network"] = NETWORK_OSTATUS;
-
-			$details["not_following"] = true;
-		}
-
-		return $details;
-	}
-
-	private function completion($conversation_url, $uid, $item = array(), $self = "") {
-
-
-		$item_stored = -1;
-
-		$conversation_url = self::fetch_conversation($self, $conversation_url);
-
-		// If the thread shouldn't be completed then store the item and go away
-		// Don't do a completion on liked content
-		if (((intval(get_config('system','ostatus_poll_interval')) == -2) AND (count($item) > 0)) OR
-			($item["verb"] == ACTIVITY_LIKE) OR ($conversation_url == "")) {
-			$item_stored = item_store($item, true);
-			return($item_stored);
-		}
-
-		// Get the parent
-		$parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
-				(SELECT `parent` FROM `item` WHERE `id` IN
-					(SELECT `oid` FROM `term` WHERE `uid` = %d AND `otype` = %d AND `type` = %d AND `url` = '%s'))",
-				intval($uid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), dbesc($conversation_url));
-
-		if ($parents)
-			$parent = $parents[0];
-		elseif (count($item) > 0) {
-			$parent = $item;
-			$parent["type"] = "remote";
-			$parent["verb"] = ACTIVITY_POST;
-			$parent["visible"] = 1;
-		} else {
-			// Preset the parent
-			$r = q("SELECT `id` FROM `contact` WHERE `self` AND `uid`=%d", $uid);
-			if (!$r)
-				return(-2);
-
-			$parent = array();
-			$parent["id"] = 0;
-			$parent["parent"] = 0;
-			$parent["uri"] = "";
-			$parent["contact-id"] = $r[0]["id"];
-			$parent["type"] = "remote";
-			$parent["verb"] = ACTIVITY_POST;
-			$parent["visible"] = 1;
-		}
-
-		$conv = str_replace("/conversation/", "/api/statusnet/conversation/", $conversation_url).".as";
-		$pageno = 1;
-		$items = array();
-
-		logger('fetching conversation url '.$conv.' (Self: '.$self.') for user '.$uid);
-
-		do {
-			$conv_arr = z_fetch_url($conv."?page=".$pageno);
-
-			// If it is a non-ssl site and there is an error, then try ssl or vice versa
-			if (!$conv_arr["success"] AND (substr($conv, 0, 7) == "http://")) {
-				$conv = str_replace("http://", "https://", $conv);
-				$conv_as = fetch_url($conv."?page=".$pageno);
-			} elseif (!$conv_arr["success"] AND (substr($conv, 0, 8) == "https://")) {
-				$conv = str_replace("https://", "http://", $conv);
-				$conv_as = fetch_url($conv."?page=".$pageno);
-			} else
-				$conv_as = $conv_arr["body"];
-
-			$conv_as = str_replace(',"statusnet:notice_info":', ',"statusnet_notice_info":', $conv_as);
-			$conv_as = json_decode($conv_as);
-
-			$no_of_items = sizeof($items);
-
-			if (@is_array($conv_as->items))
-				foreach ($conv_as->items AS $single_item)
-					$items[$single_item->id] = $single_item;
-
-			if ($no_of_items == sizeof($items))
-				break;
-
-			$pageno++;
-
-		} while (true);
-
-		logger('fetching conversation done. Found '.count($items).' items');
-
-		if (!sizeof($items)) {
-			if (count($item) > 0) {
-				$item_stored = item_store($item, true);
-
-				if ($item_stored) {
-					logger("Conversation ".$conversation_url." couldn't be fetched. Item uri ".$item["uri"]." stored: ".$item_stored, LOGGER_DEBUG);
-					self::store_conversation($item_id, $conversation_url);
-				}
-
-				return($item_stored);
-			} else
-				return(-3);
-		}
-
-		$items = array_reverse($items);
-
-		$r = q("SELECT `nurl` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid));
-		$importer = $r[0];
-
-		$new_parent = true;
-
-		foreach ($items as $single_conv) {
-
-			// Update the gcontact table
-			self::conv_fetch_actor($single_conv->actor);
-
-			// Test - remove before flight
-			//$tempfile = tempnam(get_temppath(), "conversation");
-			//file_put_contents($tempfile, json_encode($single_conv));
-
-			$mention = false;
-
-			if (isset($single_conv->object->id))
-				$single_conv->id = $single_conv->object->id;
-
-			$plink = self::convert_href($single_conv->id);
-			if (isset($single_conv->object->url))
-				$plink = self::convert_href($single_conv->object->url);
-
-			if (@!$single_conv->id)
-				continue;
-
-			logger("Got id ".$single_conv->id, LOGGER_DEBUG);
-
-			if ($first_id == "") {
-				$first_id = $single_conv->id;
-
-				// The first post of the conversation isn't our first post. There are three options:
-				// 1. Our conversation hasn't the "real" thread starter
-				// 2. This first post is a post inside our thread
-				// 3. This first post is a post inside another thread
-				if (($first_id != $parent["uri"]) AND ($parent["uri"] != "")) {
-
-					$new_parent = true;
-
-					$new_parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
-								(SELECT `parent` FROM `item`
-									WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s')) LIMIT 1",
-						intval($uid), dbesc($first_id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
-					if ($new_parents) {
-						if ($new_parents[0]["parent"] == $parent["parent"]) {
-							// Option 2: This post is already present inside our thread - but not as thread starter
-							logger("Option 2: uri present in our thread: ".$first_id, LOGGER_DEBUG);
-							$first_id = $parent["uri"];
-						} else {
-							// Option 3: Not so good. We have mixed parents. We have to see how to clean this up.
-							// For now just take the new parent.
-							$parent = $new_parents[0];
-							$first_id = $parent["uri"];
-							logger("Option 3: mixed parents for uri ".$first_id, LOGGER_DEBUG);
-						}
-					} else {
-						// Option 1: We hadn't got the real thread starter
-						// We have to clean up our existing messages.
-						$parent["id"] = 0;
-						$parent["uri"] = $first_id;
-						logger("Option 1: we have a new parent: ".$first_id, LOGGER_DEBUG);
-					}
-				} elseif ($parent["uri"] == "") {
-					$parent["id"] = 0;
-					$parent["uri"] = $first_id;
-				}
-			}
-
-			$parent_uri = $parent["uri"];
-
-			// "context" only seems to exist on older servers
-			if (isset($single_conv->context->inReplyTo->id)) {
-				$parent_exists = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
-							intval($uid), dbesc($single_conv->context->inReplyTo->id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
-				if ($parent_exists)
-					$parent_uri = $single_conv->context->inReplyTo->id;
-			}
-
-			// This is the current way
-			if (isset($single_conv->object->inReplyTo->id)) {
-				$parent_exists = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
-							intval($uid), dbesc($single_conv->object->inReplyTo->id), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
-				if ($parent_exists)
-					$parent_uri = $single_conv->object->inReplyTo->id;
-			}
-
-			$message_exists = q("SELECT `id`, `parent`, `uri` FROM `item` WHERE `uid` = %d AND `uri` = '%s' AND `network` IN ('%s','%s') LIMIT 1",
-							intval($uid), dbesc($single_conv->id),
-							dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN));
-			if ($message_exists) {
-				logger("Message ".$single_conv->id." already existed on the system", LOGGER_DEBUG);
-
-				if ($parent["id"] != 0) {
-					$existing_message = $message_exists[0];
-
-					// We improved the way we fetch OStatus messages, this shouldn't happen very often now
-					/// @TODO We have to change the shadow copies as well. This way here is really ugly.
-					if ($existing_message["parent"] != $parent["id"]) {
-						logger('updating id '.$existing_message["id"].' with parent '.$existing_message["parent"].' to parent '.$parent["id"].' uri '.$parent["uri"].' thread '.$parent_uri, LOGGER_DEBUG);
-
-						// Update the parent id of the selected item
-						$r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `id` = %d",
-							intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["id"]));
-
-						// Update the parent uri in the thread - but only if it points to itself
-						$r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE `id` = %d AND `uri` = `thr-parent`",
-							dbesc($parent_uri), intval($existing_message["id"]));
-
-						// try to change all items of the same parent
-						$r = q("UPDATE `item` SET `parent` = %d, `parent-uri` = '%s' WHERE `parent` = %d",
-							intval($parent["id"]), dbesc($parent["uri"]), intval($existing_message["parent"]));
-
-						// Update the parent uri in the thread - but only if it points to itself
-						$r = q("UPDATE `item` SET `thr-parent` = '%s' WHERE (`parent` = %d) AND (`uri` = `thr-parent`)",
-							dbesc($parent["uri"]), intval($existing_message["parent"]));
-
-						// Now delete the thread
-						delete_thread($existing_message["parent"]);
-					}
-				}
-
-				// The item we are having on the system is the one that we wanted to store via the item array
-				if (isset($item["uri"]) AND ($item["uri"] == $existing_message["uri"])) {
-					$item = array();
-					$item_stored = 0;
-				}
-
-				continue;
-			}
-
-			if (is_array($single_conv->to))
-				foreach($single_conv->to AS $to)
-					if ($importer["nurl"] == normalise_link($to->id))
-						$mention = true;
-
-			$actor = $single_conv->actor->id;
-			if (isset($single_conv->actor->url))
-				$actor = $single_conv->actor->url;
-
-			$details = self::get_actor_details($actor, $uid, $parent["contact-id"]);
-
-			// Do we only want to import threads that were started by our contacts?
-			if ($details["not_following"] AND $new_parent AND get_config('system','ostatus_full_threads')) {
-				logger("Don't import uri ".$first_id." because user ".$uid." doesn't follow the person ".$actor, LOGGER_DEBUG);
-				continue;
-			}
-
-			$arr = array();
-			$arr["network"] = $details["network"];
-			$arr["uri"] = $single_conv->id;
-			$arr["plink"] = $plink;
-			$arr["uid"] = $uid;
-			$arr["contact-id"] = $details["contact_id"];
-			$arr["parent-uri"] = $parent_uri;
-			$arr["created"] = $single_conv->published;
-			$arr["edited"] = $single_conv->published;
-			$arr["owner-name"] = $single_conv->actor->displayName;
-			if ($arr["owner-name"] == '')
-				$arr["owner-name"] = $single_conv->actor->contact->displayName;
-			if ($arr["owner-name"] == '')
-				$arr["owner-name"] = $single_conv->actor->portablecontacts_net->displayName;
-
-			$arr["owner-link"] = $actor;
-			$arr["owner-avatar"] = $single_conv->actor->image->url;
-			$arr["author-name"] = $arr["owner-name"];
-			$arr["author-link"] = $actor;
-			$arr["author-avatar"] = $single_conv->actor->image->url;
-			$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->content));
-
-			if (isset($single_conv->status_net->notice_info->source))
-				$arr["app"] = strip_tags($single_conv->status_net->notice_info->source);
-			elseif (isset($single_conv->statusnet->notice_info->source))
-				$arr["app"] = strip_tags($single_conv->statusnet->notice_info->source);
-			elseif (isset($single_conv->statusnet_notice_info->source))
-				$arr["app"] = strip_tags($single_conv->statusnet_notice_info->source);
-			elseif (isset($single_conv->provider->displayName))
-				$arr["app"] = $single_conv->provider->displayName;
-			else
-				$arr["app"] = "OStatus";
-
-
-			$arr["object"] = json_encode($single_conv);
-			$arr["verb"] = $parent["verb"];
-			$arr["visible"] = $parent["visible"];
-			$arr["location"] = $single_conv->location->displayName;
-			$arr["coord"] = trim($single_conv->location->lat." ".$single_conv->location->lon);
-
-			// Is it a reshared item?
-			if (isset($single_conv->verb) AND ($single_conv->verb == "share") AND isset($single_conv->object)) {
-				if (is_array($single_conv->object))
-					$single_conv->object = $single_conv->object[0];
-
-				logger("Found reshared item ".$single_conv->object->id);
-
-				// $single_conv->object->context->conversation;
-
-				if (isset($single_conv->object->object->id))
-					$arr["uri"] = $single_conv->object->object->id;
-				else
-					$arr["uri"] = $single_conv->object->id;
-
-				if (isset($single_conv->object->object->url))
-					$plink = self::convert_href($single_conv->object->object->url);
-				else
-					$plink = self::convert_href($single_conv->object->url);
-
-				if (isset($single_conv->object->object->content))
-					$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->object->content));
-				else
-					$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->content));
-
-				$arr["plink"] = $plink;
-
-				$arr["created"] = $single_conv->object->published;
-				$arr["edited"] = $single_conv->object->published;
-
-				$arr["author-name"] = $single_conv->object->actor->displayName;
-				if ($arr["owner-name"] == '')
-					$arr["author-name"] = $single_conv->object->actor->contact->displayName;
-
-				$arr["author-link"] = $single_conv->object->actor->url;
-				$arr["author-avatar"] = $single_conv->object->actor->image->url;
-
-				$arr["app"] = $single_conv->object->provider->displayName."#";
-				//$arr["verb"] = $single_conv->object->verb;
-
-				$arr["location"] = $single_conv->object->location->displayName;
-				$arr["coord"] = trim($single_conv->object->location->lat." ".$single_conv->object->location->lon);
-			}
-
-			if ($arr["location"] == "")
-				unset($arr["location"]);
-
-			if ($arr["coord"] == "")
-				unset($arr["coord"]);
-
-			// Copy fields from given item array
-			if (isset($item["uri"]) AND (($item["uri"] == $arr["uri"]) OR ($item["uri"] ==  $single_conv->id))) {
-				$copy_fields = array("owner-name", "owner-link", "owner-avatar", "author-name", "author-link", "author-avatar",
-							"gravity", "body", "object-type", "object", "verb", "created", "edited", "coord", "tag",
-							"title", "attach", "app", "type", "location", "contact-id", "uri");
-				foreach ($copy_fields AS $field)
-					if (isset($item[$field]))
-						$arr[$field] = $item[$field];
-
-			}
-
-			$newitem = item_store($arr);
-			if (!$newitem) {
-				logger("Item wasn't stored ".print_r($arr, true), LOGGER_DEBUG);
-				continue;
-			}
-
-			if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) {
-				$item = array();
-				$item_stored = $newitem;
-			}
-
-			logger('Stored new item '.$plink.' for parent '.$arr["parent-uri"].' under id '.$newitem, LOGGER_DEBUG);
-
-			// Add the conversation entry (but don't fetch the whole conversation)
-			self::store_conversation($newitem, $conversation_url);
-
-			// If the newly created item is the top item then change the parent settings of the thread
-			// This shouldn't happen anymore. This is supposed to be absolote.
-			if ($arr["uri"] == $first_id) {
-				logger('setting new parent to id '.$newitem);
-				$new_parents = q("SELECT `id`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `uid` = %d AND `id` = %d LIMIT 1",
-					intval($uid), intval($newitem));
-				if ($new_parents)
-					$parent = $new_parents[0];
-			}
-		}
-
-		if (($item_stored < 0) AND (count($item) > 0)) {
-
-			if (get_config('system','ostatus_full_threads')) {
-				$details = self::get_actor_details($item["owner-link"], $uid, $item["contact-id"]);
-				if ($details["not_following"]) {
-					logger("Don't import uri ".$item["uri"]." because user ".$uid." doesn't follow the person ".$item["owner-link"], LOGGER_DEBUG);
-					return false;
-				}
-			}
-
-			$item_stored = item_store($item, true);
-			if ($item_stored) {
-				logger("Uri ".$item["uri"]." wasn't found in conversation ".$conversation_url, LOGGER_DEBUG);
-				self::store_conversation($item_stored, $conversation_url);
-			}
-		}
-
-		return($item_stored);
-	}
-
-	private function store_conversation($itemid, $conversation_url) {
-
-		$conversation_url = self::convert_href($conversation_url);
-
-		$messages = q("SELECT `uid`, `parent`, `created`, `received`, `guid` FROM `item` WHERE `id` = %d LIMIT 1", intval($itemid));
-		if (!$messages)
-			return;
-		$message = $messages[0];
-
-		// Store conversation url if not done before
-		$conversation = q("SELECT `url` FROM `term` WHERE `uid` = %d AND `oid` = %d AND `otype` = %d AND `type` = %d",
-			intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION));
-
-		if (!$conversation) {
-			$r = q("INSERT INTO `term` (`uid`, `oid`, `otype`, `type`, `term`, `url`, `created`, `received`, `guid`) VALUES (%d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s')",
-				intval($message["uid"]), intval($itemid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION),
-				dbesc($message["created"]), dbesc($conversation_url), dbesc($message["created"]), dbesc($message["received"]), dbesc($message["guid"]));
-			logger('Storing conversation url '.$conversation_url.' for id '.$itemid);
-		}
-	}
-
-	private function get_reshared_guid($item) {
-		$body = trim($item["body"]);
-
-		// Skip if it isn't a pure repeated messages
-		// Does it start with a share?
-		if (strpos($body, "[share") > 0)
-			return("");
-
-		// Does it end with a share?
-		if (strlen($body) > (strrpos($body, "[/share]") + 8))
-			return("");
-
-		$attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body);
-		// Skip if there is no shared message in there
-		if ($body == $attributes)
-			return(false);
-
-		$guid = "";
-		preg_match("/guid='(.*?)'/ism", $attributes, $matches);
-		if ($matches[1] != "")
-			$guid = $matches[1];
-
-		preg_match('/guid="(.*?)"/ism', $attributes, $matches);
-		if ($matches[1] != "")
-			$guid = $matches[1];
-
-		return $guid;
-	}
-
-	private function format_picture_post($body) {
-		$siteinfo = get_attached_data($body);
-
-		if (($siteinfo["type"] == "photo")) {
-			if (isset($siteinfo["preview"]))
-				$preview = $siteinfo["preview"];
-			else
-				$preview = $siteinfo["image"];
-
-			// Is it a remote picture? Then make a smaller preview here
-			$preview = proxy_url($preview, false, PROXY_SIZE_SMALL);
-
-			// Is it a local picture? Then make it smaller here
-			$preview = str_replace(array("-0.jpg", "-0.png"), array("-2.jpg", "-2.png"), $preview);
-			$preview = str_replace(array("-1.jpg", "-1.png"), array("-2.jpg", "-2.png"), $preview);
-
-			if (isset($siteinfo["url"]))
-				$url = $siteinfo["url"];
-			else
-				$url = $siteinfo["image"];
-
-			$body = trim($siteinfo["text"])." [url]".$url."[/url]\n[img]".$preview."[/img]";
-		}
-
-		return $body;
-	}
-
-	private function add_header($doc, $owner) {
-
-		$a = get_app();
-
-		$root = $doc->createElementNS(NAMESPACE_ATOM1, 'feed');
-		$doc->appendChild($root);
-
-		$root->setAttribute("xmlns:thr", NAMESPACE_THREAD);
-		$root->setAttribute("xmlns:georss", NAMESPACE_GEORSS);
-		$root->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY);
-		$root->setAttribute("xmlns:media", NAMESPACE_MEDIA);
-		$root->setAttribute("xmlns:poco", NAMESPACE_POCO);
-		$root->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
-		$root->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
-
-		$attributes = array("uri" => "https://friendi.ca", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION);
-		xml2::add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes);
-		xml2::add_element($doc, $root, "id", App::get_baseurl()."/profile/".$owner["nick"]);
-		xml2::add_element($doc, $root, "title", sprintf("%s timeline", $owner["name"]));
-		xml2::add_element($doc, $root, "subtitle", sprintf("Updates from %s on %s", $owner["name"], $a->config["sitename"]));
-		xml2::add_element($doc, $root, "logo", $owner["photo"]);
-		xml2::add_element($doc, $root, "updated", datetime_convert("UTC", "UTC", "now", ATOM_TIME));
-
-		$author = self::add_author($doc, $owner);
-		$root->appendChild($author);
-
-		$attributes = array("href" => $owner["url"], "rel" => "alternate", "type" => "text/html");
-		xml2::add_element($doc, $root, "link", "", $attributes);
-
-		/// @TODO We have to find out what this is
-		/// $attributes = array("href" => App::get_baseurl()."/sup",
-		///		"rel" => "http://api.friendfeed.com/2008/03#sup",
-		///		"type" => "application/json");
-		/// xml2::add_element($doc, $root, "link", "", $attributes);
-
-		self::hublinks($doc, $root);
-
-		$attributes = array("href" => App::get_baseurl()."/salmon/".$owner["nick"], "rel" => "salmon");
-		xml2::add_element($doc, $root, "link", "", $attributes);
-
-		$attributes = array("href" => App::get_baseurl()."/salmon/".$owner["nick"], "rel" => "http://salmon-protocol.org/ns/salmon-replies");
-		xml2::add_element($doc, $root, "link", "", $attributes);
-
-		$attributes = array("href" => App::get_baseurl()."/salmon/".$owner["nick"], "rel" => "http://salmon-protocol.org/ns/salmon-mention");
-		xml2::add_element($doc, $root, "link", "", $attributes);
-
-		$attributes = array("href" => App::get_baseurl()."/api/statuses/user_timeline/".$owner["nick"].".atom",
-				"rel" => "self", "type" => "application/atom+xml");
-		xml2::add_element($doc, $root, "link", "", $attributes);
-
-		return $root;
-	}
-
-	public static function hublinks($doc, $root) {
-		$hub = get_config('system','huburl');
-
-		$hubxml = '';
-		if(strlen($hub)) {
-			$hubs = explode(',', $hub);
-			if(count($hubs)) {
-				foreach($hubs as $h) {
-					$h = trim($h);
-					if(! strlen($h))
-						continue;
-					if ($h === '[internal]')
-						$h = App::get_baseurl() . '/pubsubhubbub';
-					xml2::add_element($doc, $root, "link", "", array("href" => $h, "rel" => "hub"));
-				}
-			}
-		}
-	}
-
-	private function get_attachment($doc, $root, $item) {
-		$o = "";
-		$siteinfo = get_attached_data($item["body"]);
-
-		switch($siteinfo["type"]) {
-			case 'link':
-				$attributes = array("rel" => "enclosure",
-						"href" => $siteinfo["url"],
-						"type" => "text/html; charset=UTF-8",
-						"length" => "",
-						"title" => $siteinfo["title"]);
-				xml2::add_element($doc, $root, "link", "", $attributes);
-				break;
-			case 'photo':
-				$imgdata = get_photo_info($siteinfo["image"]);
-				$attributes = array("rel" => "enclosure",
-						"href" => $siteinfo["image"],
-						"type" => $imgdata["mime"],
-						"length" => intval($imgdata["size"]));
-				xml2::add_element($doc, $root, "link", "", $attributes);
-				break;
-			case 'video':
-				$attributes = array("rel" => "enclosure",
-						"href" => $siteinfo["url"],
-						"type" => "text/html; charset=UTF-8",
-						"length" => "",
-						"title" => $siteinfo["title"]);
-				xml2::add_element($doc, $root, "link", "", $attributes);
-				break;
-			default:
-				break;
-		}
-
-		if (($siteinfo["type"] != "photo") AND isset($siteinfo["image"])) {
-			$photodata = get_photo_info($siteinfo["image"]);
-
-			$attributes = array("rel" => "preview", "href" => $siteinfo["image"], "media:width" => $photodata[0], "media:height" => $photodata[1]);
-			xml2::add_element($doc, $root, "link", "", $attributes);
-		}
-
-
-		$arr = explode('[/attach],',$item['attach']);
-		if(count($arr)) {
-			foreach($arr as $r) {
-				$matches = false;
-				$cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|',$r,$matches);
-				if($cnt) {
-					$attributes = array("rel" => "enclosure",
-							"href" => $matches[1],
-							"type" => $matches[3]);
-
-					if(intval($matches[2]))
-						$attributes["length"] = intval($matches[2]);
-
-					if(trim($matches[4]) != "")
-						$attributes["title"] = trim($matches[4]);
-
-					xml2::add_element($doc, $root, "link", "", $attributes);
-				}
-			}
-		}
-	}
-
-	private function add_author($doc, $owner) {
-
-		$r = q("SELECT `homepage` FROM `profile` WHERE `uid` = %d AND `is-default` LIMIT 1", intval($owner["uid"]));
-		if ($r)
-			$profile = $r[0];
-
-		$author = $doc->createElement("author");
-		xml2::add_element($doc, $author, "activity:object-type", ACTIVITY_OBJ_PERSON);
-		xml2::add_element($doc, $author, "uri", $owner["url"]);
-		xml2::add_element($doc, $author, "name", $owner["name"]);
-		xml2::add_element($doc, $author, "summary", bbcode($owner["about"], false, false, 7));
-
-		$attributes = array("rel" => "alternate", "type" => "text/html", "href" => $owner["url"]);
-		xml2::add_element($doc, $author, "link", "", $attributes);
-
-		$attributes = array(
-				"rel" => "avatar",
-				"type" => "image/jpeg", // To-Do?
-				"media:width" => 175,
-				"media:height" => 175,
-				"href" => $owner["photo"]);
-		xml2::add_element($doc, $author, "link", "", $attributes);
-
-		if (isset($owner["thumb"])) {
-			$attributes = array(
-					"rel" => "avatar",
-					"type" => "image/jpeg", // To-Do?
-					"media:width" => 80,
-					"media:height" => 80,
-					"href" => $owner["thumb"]);
-			xml2::add_element($doc, $author, "link", "", $attributes);
-		}
-
-		xml2::add_element($doc, $author, "poco:preferredUsername", $owner["nick"]);
-		xml2::add_element($doc, $author, "poco:displayName", $owner["name"]);
-		xml2::add_element($doc, $author, "poco:note", bbcode($owner["about"], false, false, 7));
-
-		if (trim($owner["location"]) != "") {
-			$element = $doc->createElement("poco:address");
-			xml2::add_element($doc, $element, "poco:formatted", $owner["location"]);
-			$author->appendChild($element);
-		}
-
-		if (trim($profile["homepage"]) != "") {
-			$urls = $doc->createElement("poco:urls");
-			xml2::add_element($doc, $urls, "poco:type", "homepage");
-			xml2::add_element($doc, $urls, "poco:value", $profile["homepage"]);
-			xml2::add_element($doc, $urls, "poco:primary", "true");
-			$author->appendChild($urls);
-		}
-
-		if (count($profile)) {
-			xml2::add_element($doc, $author, "followers", "", array("url" => App::get_baseurl()."/viewcontacts/".$owner["nick"]));
-			xml2::add_element($doc, $author, "statusnet:profile_info", "", array("local_id" => $owner["uid"]));
-		}
-
-		return $author;
-	}
-
-	/**
-	 * @TODO Picture attachments should look like this:
-	 *	<a href="https://status.pirati.ca/attachment/572819" title="https://status.pirati.ca/file/heluecht-20151202T222602-rd3u49p.gif"
-	 *	class="attachment thumbnail" id="attachment-572819" rel="nofollow external">https://status.pirati.ca/attachment/572819</a>
-	 *
-	*/
-
-	function construct_verb($item) {
-		if ($item['verb'])
-			return $item['verb'];
-		return ACTIVITY_POST;
-	}
-
-	function construct_objecttype($item) {
-		if (in_array($item['object-type'], array(ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_COMMENT)))
-			return $item['object-type'];
-		return ACTIVITY_OBJ_NOTE;
-	}
-
-	private function entry($doc, $item, $owner, $toplevel = false) {
-		$repeated_guid = self::get_reshared_guid($item);
-		if ($repeated_guid != "")
-			$xml = self::reshare_entry($doc, $item, $owner, $repeated_guid, $toplevel);
-
-		if ($xml)
-			return $xml;
-
-		if ($item["verb"] == ACTIVITY_LIKE)
-			return self::like_entry($doc, $item, $owner, $toplevel);
-		else
-			return self::note_entry($doc, $item, $owner, $toplevel);
-	}
-
-	private function source_entry($doc, $contact) {
-		$source = $doc->createElement("source");
-		xml2::add_element($doc, $source, "id", $contact["poll"]);
-		xml2::add_element($doc, $source, "title", $contact["name"]);
-		xml2::add_element($doc, $source, "link", "", array("rel" => "alternate",
-								"type" => "text/html",
-								"href" => $contact["alias"]));
-		xml2::add_element($doc, $source, "link", "", array("rel" => "self",
-								"type" => "application/atom+xml",
-								"href" => $contact["poll"]));
-		xml2::add_element($doc, $source, "icon", $contact["photo"]);
-		xml2::add_element($doc, $source, "updated", datetime_convert("UTC","UTC",$contact["success_update"]."+00:00",ATOM_TIME));
-
-		return $source;
-	}
-
-	private function contact_entry($url, $owner) {
-
-		$r = q("SELECT * FROM `contact` WHERE `nurl` = '%s' AND `uid` IN (0, %d) ORDER BY `uid` DESC LIMIT 1",
-			dbesc(normalise_link($url)), intval($owner["uid"]));
-		if ($r) {
-			$contact = $r[0];
-			$contact["uid"] = -1;
-		}
-
-		if (!$r) {
-			$r = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1",
-				dbesc(normalise_link($url)));
-			if ($r) {
-				$contact = $r[0];
-				$contact["uid"] = -1;
-				$contact["success_update"] = $contact["updated"];
-			}
-		}
-
-		if (!$r)
-			$contact = owner;
-
-		if (!isset($contact["poll"])) {
-			$data = probe_url($url);
-			$contact["alias"] = $data["alias"];
-			$contact["poll"] = $data["poll"];
-		}
-
-		if (!isset($contact["alias"]))
-			$contact["alias"] = $contact["url"];
-
-		return $contact;
-	}
-
-	private function reshare_entry($doc, $item, $owner, $repeated_guid, $toplevel) {
-
-		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
-			logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
-		}
-
-		$title = self::entry_header($doc, $entry, $owner, $toplevel);
-
-		$r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' AND NOT `private` AND `network` IN ('%s', '%s', '%s') LIMIT 1",
-			intval($owner["uid"]), dbesc($repeated_guid),
-			dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
-		if ($r)
-			$repeated_item = $r[0];
-		else
-			return false;
-
-		$contact = self::contact_entry($repeated_item['author-link'], $owner);
-
-		$parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']);
-
-		$title = $owner["nick"]." repeated a notice by ".$contact["nick"];
-
-		self::entry_content($doc, $entry, $item, $owner, $title, ACTIVITY_SHARE, false);
-
-		$as_object = $doc->createElement("activity:object");
-
-// ostatusWaEeYs
-// ostatusogu9zg - besser
-		xml2::add_element($doc, $as_object, "activity:object-type", NAMESPACE_ACTIVITY_SCHEMA."activity");
-
-		self::entry_content($doc, $as_object, $repeated_item, $owner, "", "", false);
-
-		$author = self::add_author($doc, $contact);
-                $as_object->appendChild($author);
-
-		$as_object2 = $doc->createElement("activity:object");
-
-		xml2::add_element($doc, $as_object2, "activity:object-type", self::construct_objecttype($repeated_item));
-
-		$title = sprintf("New comment by %s", $contact["nick"]);
-
-		self::entry_content($doc, $as_object2, $repeated_item, $owner, $title);
-
-		$as_object->appendChild($as_object2);
-
-		self::entry_footer($doc, $as_object, $item, $owner, false);
-
-		$source = self::source_entry($doc, $contact);
-
-		$as_object->appendChild($source);
-
-		$entry->appendChild($as_object);
-
-		self::entry_footer($doc, $entry, $item, $owner);
-
-		return $entry;
-	}
-
-	private function like_entry($doc, $item, $owner, $toplevel) {
-
-		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
-			logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
-		}
-
-		$title = self::entry_header($doc, $entry, $owner, $toplevel);
-
-		$verb = NAMESPACE_ACTIVITY_SCHEMA."favorite";
-		self::entry_content($doc, $entry, $item, $owner, "Favorite", $verb, false);
-
-		$as_object = $doc->createElement("activity:object");
-
-		$parent = q("SELECT * FROM `item` WHERE `id` = %d", intval($item["parent"]));
-		$parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']);
-
-		xml2::add_element($doc, $as_object, "activity:object-type", self::construct_objecttype($parent[0]));
-
-		self::entry_content($doc, $as_object, $parent[0], $owner, "New entry");
-
-		$entry->appendChild($as_object);
-
-		self::entry_footer($doc, $entry, $item, $owner);
-
-		return $entry;
-	}
-
-	private function note_entry($doc, $item, $owner, $toplevel) {
-
-		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
-			logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG);
-		}
-
-		$title = self::entry_header($doc, $entry, $owner, $toplevel);
-
-		xml2::add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE);
-
-		self::entry_content($doc, $entry, $item, $owner, $title);
-
-		self::entry_footer($doc, $entry, $item, $owner);
-
-		return $entry;
-	}
-
-	private function entry_header($doc, &$entry, $owner, $toplevel) {
-		if (!$toplevel) {
-			$entry = $doc->createElement("entry");
-			$title = sprintf("New note by %s", $owner["nick"]);
-		} else {
-			$entry = $doc->createElementNS(NAMESPACE_ATOM1, "entry");
-
-			$entry->setAttribute("xmlns:thr", NAMESPACE_THREAD);
-			$entry->setAttribute("xmlns:georss", NAMESPACE_GEORSS);
-			$entry->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY);
-			$entry->setAttribute("xmlns:media", NAMESPACE_MEDIA);
-			$entry->setAttribute("xmlns:poco", NAMESPACE_POCO);
-			$entry->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS);
-			$entry->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET);
-
-			$author = self::add_author($doc, $owner);
-			$entry->appendChild($author);
-
-			$title = sprintf("New comment by %s", $owner["nick"]);
-		}
-		return $title;
-	}
-
-	private function entry_content($doc, $entry, $item, $owner, $title, $verb = "", $complete = true) {
-
-		if ($verb == "")
-			$verb = self::construct_verb($item);
-
-		xml2::add_element($doc, $entry, "id", $item["uri"]);
-		xml2::add_element($doc, $entry, "title", $title);
-
-		$body = self::format_picture_post($item['body']);
-
-		if ($item['title'] != "")
-			$body = "[b]".$item['title']."[/b]\n\n".$body;
-
-		$body = bbcode($body, false, false, 7);
-
-		xml2::add_element($doc, $entry, "content", $body, array("type" => "html"));
-
-		xml2::add_element($doc, $entry, "link", "", array("rel" => "alternate", "type" => "text/html",
-								"href" => App::get_baseurl()."/display/".$item["guid"]));
-
-		if ($complete)
-			xml2::add_element($doc, $entry, "status_net", "", array("notice_id" => $item["id"]));
-
-		xml2::add_element($doc, $entry, "activity:verb", $verb);
-
-		xml2::add_element($doc, $entry, "published", datetime_convert("UTC","UTC",$item["created"]."+00:00",ATOM_TIME));
-		xml2::add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME));
-	}
-
-	private function entry_footer($doc, $entry, $item, $owner, $complete = true) {
-
-		$mentioned = array();
-
-		if (($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || (($item['thr-parent'] !== '') && ($item['thr-parent'] !== $item['uri']))) {
-			$parent = q("SELECT `guid`, `author-link`, `owner-link` FROM `item` WHERE `id` = %d", intval($item["parent"]));
-			$parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']);
-
-			$attributes = array(
-					"ref" => $parent_item,
-					"type" => "text/html",
-					"href" => App::get_baseurl()."/display/".$parent[0]["guid"]);
-			xml2::add_element($doc, $entry, "thr:in-reply-to", "", $attributes);
-
-			$attributes = array(
-					"rel" => "related",
-					"href" => App::get_baseurl()."/display/".$parent[0]["guid"]);
-			xml2::add_element($doc, $entry, "link", "", $attributes);
-
-			$mentioned[$parent[0]["author-link"]] = $parent[0]["author-link"];
-			$mentioned[$parent[0]["owner-link"]] = $parent[0]["owner-link"];
-
-			$thrparent = q("SELECT `guid`, `author-link`, `owner-link` FROM `item` WHERE `uid` = %d AND `uri` = '%s'",
-					intval($owner["uid"]),
-					dbesc($parent_item));
-			if ($thrparent) {
-				$mentioned[$thrparent[0]["author-link"]] = $thrparent[0]["author-link"];
-				$mentioned[$thrparent[0]["owner-link"]] = $thrparent[0]["owner-link"];
-			}
-		}
-
-		xml2::add_element($doc, $entry, "link", "", array("rel" => "ostatus:conversation",
-							"href" => App::get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]));
-		xml2::add_element($doc, $entry, "ostatus:conversation", App::get_baseurl()."/display/".$owner["nick"]."/".$item["parent"]);
-
-		$tags = item_getfeedtags($item);
-
-		if(count($tags))
-			foreach($tags as $t)
-				if ($t[0] == "@")
-					$mentioned[$t[1]] = $t[1];
-
-		// Make sure that mentions are accepted (GNU Social has problems with mixing HTTP and HTTPS)
-		$newmentions = array();
-		foreach ($mentioned AS $mention) {
-			$newmentions[str_replace("http://", "https://", $mention)] = str_replace("http://", "https://", $mention);
-			$newmentions[str_replace("https://", "http://", $mention)] = str_replace("https://", "http://", $mention);
-		}
-		$mentioned = $newmentions;
-
-		foreach ($mentioned AS $mention) {
-			$r = q("SELECT `forum`, `prv` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s'",
-				intval($owner["uid"]),
-				dbesc(normalise_link($mention)));
-			if ($r[0]["forum"] OR $r[0]["prv"])
-				xml2::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
-											"ostatus:object-type" => ACTIVITY_OBJ_GROUP,
-											"href" => $mention));
-			else
-				xml2::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
-											"ostatus:object-type" => ACTIVITY_OBJ_PERSON,
-											"href" => $mention));
-		}
-
-		if (!$item["private"]) {
-			xml2::add_element($doc, $entry, "link", "", array("rel" => "ostatus:attention",
-									"href" => "http://activityschema.org/collection/public"));
-			xml2::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
-									"ostatus:object-type" => "http://activitystrea.ms/schema/1.0/collection",
-									"href" => "http://activityschema.org/collection/public"));
-		}
-
-		if(count($tags))
-			foreach($tags as $t)
-				if ($t[0] != "@")
-					xml2::add_element($doc, $entry, "category", "", array("term" => $t[2]));
-
-		self::get_attachment($doc, $entry, $item);
-
-		if ($complete) {
-			$app = $item["app"];
-			if ($app == "")
-				$app = "web";
-
-			$attributes = array("local_id" => $item["id"], "source" => $app);
-
-			if (isset($parent["id"]))
-				$attributes["repeat_of"] = $parent["id"];
-
-			if ($item["coord"] != "")
-				xml2::add_element($doc, $entry, "georss:point", $item["coord"]);
-
-			xml2::add_element($doc, $entry, "statusnet:notice_info", "", $attributes);
-		}
-	}
-
-	public static function feed(&$a, $owner_nick, $last_update) {
-
-		$r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`
-				FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid`
-				WHERE `contact`.`self` AND `user`.`nickname` = '%s' LIMIT 1",
-				dbesc($owner_nick));
-		if (!$r)
-			return;
-
-		$owner = $r[0];
-
-		if(!strlen($last_update))
-			$last_update = 'now -30 days';
-
-		$check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s');
-
-		$items = q("SELECT STRAIGHT_JOIN `item`.*, `item`.`id` AS `item_id` FROM `item`
-				INNER JOIN `thread` ON `thread`.`iid` = `item`.`parent`
-				LEFT JOIN `item` AS `thritem` ON `thritem`.`uri`=`item`.`thr-parent` AND `thritem`.`uid`=`item`.`uid`
-				WHERE `item`.`uid` = %d AND `item`.`received` > '%s' AND NOT `item`.`private` AND NOT `item`.`deleted`
-					AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid`  = '' AND `item`.`deny_gid`  = ''
-					AND ((`item`.`wall` AND (`item`.`parent` = `item`.`id`))
-						OR (`item`.`network` = '%s' AND ((`thread`.`network` IN ('%s', '%s')) OR (`thritem`.`network` IN ('%s', '%s')))) AND `thread`.`mention`)
-					AND ((`item`.`owner-link` IN ('%s', '%s') AND (`item`.`parent` = `item`.`id`))
-						OR (`item`.`author-link` IN ('%s', '%s')))
-				ORDER BY `item`.`received` DESC
-				LIMIT 0, 300",
-				intval($owner["uid"]), dbesc($check_date), dbesc(NETWORK_DFRN),
-				//dbesc(NETWORK_OSTATUS), dbesc(NETWORK_OSTATUS),
-				//dbesc(NETWORK_OSTATUS), dbesc(NETWORK_OSTATUS),
-				dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN),
-				dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DFRN),
-				dbesc($owner["nurl"]), dbesc(str_replace("http://", "https://", $owner["nurl"])),
-				dbesc($owner["nurl"]), dbesc(str_replace("http://", "https://", $owner["nurl"]))
-			);
-
-		$doc = new DOMDocument('1.0', 'utf-8');
-		$doc->formatOutput = true;
-
-		$root = self::add_header($doc, $owner);
-
-		foreach ($items AS $item) {
-			$entry = self::entry($doc, $item, $owner);
-			$root->appendChild($entry);
-		}
-
-		return(trim($doc->saveXML()));
-	}
-
-	public static function salmon($item,$owner) {
-
-		$doc = new DOMDocument('1.0', 'utf-8');
-		$doc->formatOutput = true;
-
-		$entry = self::entry($doc, $item, $owner, true);
-
-		$doc->appendChild($entry);
-
-		return(trim($doc->saveXML()));
-	}
-}
-?>

From 6ff5c23d50095e5407bf69f8a4ec2220c5d2d408 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 31 Mar 2016 00:14:51 +0200
Subject: [PATCH 243/273] Doxygen structure added

---
 include/ostatus.php | 240 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 238 insertions(+), 2 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index ba5b80cd5d..dcbd91f415 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -1,4 +1,8 @@
 <?php
+/**
+ * @file include/ostatus.php
+ */
+
 require_once("include/Contact.php");
 require_once("include/threads.php");
 require_once("include/html2bbcode.php");
@@ -14,11 +18,26 @@ require_once("include/api.php");
 require_once("mod/proxy.php");
 require_once("include/xml.php");
 
+/**
+ * @brief This class contain functions for the OStatus protocol
+ *
+ */
 class ostatus {
 	const OSTATUS_DEFAULT_POLL_INTERVAL = 30; // given in minutes
 	const OSTATUS_DEFAULT_POLL_TIMEFRAME = 1440; // given in minutes
 	const OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS = 14400; // given in minutes
 
+	/**
+	 * @brief 
+	 *
+	 * @param $xpath
+	 * @param $context
+	 * @param $importer
+	 * @param $contact
+	 * @param $onlyfetch
+	 *
+	 * @return 
+	 */
 	private function fetchauthor($xpath, $context, $importer, &$contact, $onlyfetch) {
 
 		$author = array();
@@ -124,6 +143,14 @@ class ostatus {
 		return($author);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $xml
+	 * @param $importer
+	 *
+	 * @return 
+	 */
 	public static function salmon_author($xml, $importer) {
 
 		if ($xml == "")
@@ -151,6 +178,16 @@ class ostatus {
 		}
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $xml
+	 * @param $importer
+	 * @param $contact
+	 * @param $hub
+	 *
+	 * @return 
+	 */
 	public static function import($xml,$importer,&$contact, &$hub) {
 
 		logger("Import OStatus message", LOGGER_DEBUG);
@@ -492,6 +529,13 @@ class ostatus {
 		}
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $href
+	 *
+	 * @return 
+	 */
 	public static function convert_href($href) {
 		$elements = explode(":",$href);
 
@@ -515,6 +559,14 @@ class ostatus {
 		return $href;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $mentions
+	 * @param $override
+	 *
+	 * @return 
+	 */
 	public static function check_conversations($mentions = false, $override = false) {
 		$last = get_config('system','ostatus_last_poll');
 
@@ -702,6 +754,15 @@ class ostatus {
 		return $details;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $conversation_url
+	 * @param $uid
+	 * @param $item
+	 *
+	 * @return 
+	 */
 	private function completion($conversation_url, $uid, $item = array(), $self = "") {
 
 
@@ -1093,6 +1154,14 @@ class ostatus {
 		return($item_stored);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $itemid
+	 * @param $conversation_url
+	 *
+	 * @return 
+	 */
 	private function store_conversation($itemid, $conversation_url) {
 
 		$conversation_url = self::convert_href($conversation_url);
@@ -1114,6 +1183,13 @@ class ostatus {
 		}
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $item
+	 *
+	 * @return 
+	 */
 	private function get_reshared_guid($item) {
 		$body = trim($item["body"]);
 
@@ -1143,6 +1219,13 @@ class ostatus {
 		return $guid;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $body
+	 *
+	 * @return 
+	 */
 	private function format_picture_post($body) {
 		$siteinfo = get_attached_data($body);
 
@@ -1170,6 +1253,14 @@ class ostatus {
 		return $body;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $owner
+	 *
+	 * @return 
+	 */
 	private function add_header($doc, $owner) {
 
 		$a = get_app();
@@ -1223,6 +1314,14 @@ class ostatus {
 		return $root;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $root
+	 *
+	 * @return 
+	 */
 	public static function hublinks($doc, $root) {
 		$hub = get_config('system','huburl');
 
@@ -1242,6 +1341,15 @@ class ostatus {
 		}
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $root
+	 * @param $item
+	 *
+	 * @return 
+	 */
 	private function get_attachment($doc, $root, $item) {
 		$o = "";
 		$siteinfo = get_attached_data($item["body"]);
@@ -1305,6 +1413,14 @@ class ostatus {
 		}
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $owner
+	 *
+	 * @return 
+	 */
 	private function add_author($doc, $owner) {
 
 		$r = q("SELECT `homepage` FROM `profile` WHERE `uid` = %d AND `is-default` LIMIT 1", intval($owner["uid"]));
@@ -1371,18 +1487,42 @@ class ostatus {
 	 *
 	*/
 
+	/**
+	 * @brief 
+	 *
+	 * @param $item
+	 *
+	 * @return 
+	 */
 	function construct_verb($item) {
 		if ($item['verb'])
 			return $item['verb'];
 		return ACTIVITY_POST;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $item
+	 *
+	 * @return 
+	 */
 	function construct_objecttype($item) {
 		if (in_array($item['object-type'], array(ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_COMMENT)))
 			return $item['object-type'];
 		return ACTIVITY_OBJ_NOTE;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $item
+	 * @param $owner
+	 * @param $toplevel
+	 *
+	 * @return 
+	 */
 	private function entry($doc, $item, $owner, $toplevel = false) {
 		$repeated_guid = self::get_reshared_guid($item);
 		if ($repeated_guid != "")
@@ -1397,6 +1537,14 @@ class ostatus {
 			return self::note_entry($doc, $item, $owner, $toplevel);
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $contact
+	 *
+	 * @return 
+	 */
 	private function source_entry($doc, $contact) {
 		$source = $doc->createElement("source");
 		xml::add_element($doc, $source, "id", $contact["poll"]);
@@ -1413,6 +1561,14 @@ class ostatus {
 		return $source;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $url
+	 * @param $owner
+	 *
+	 * @return 
+	 */
 	private function contact_entry($url, $owner) {
 
 		$r = q("SELECT * FROM `contact` WHERE `nurl` = '%s' AND `uid` IN (0, %d) ORDER BY `uid` DESC LIMIT 1",
@@ -1447,6 +1603,17 @@ class ostatus {
 		return $contact;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $item
+	 * @param $owner
+	 * @param $repeated_guid
+	 * @param $toplevel
+	 *
+	 * @return 
+	 */
 	private function reshare_entry($doc, $item, $owner, $repeated_guid, $toplevel) {
 
 		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
@@ -1473,8 +1640,6 @@ class ostatus {
 
 		$as_object = $doc->createElement("activity:object");
 
-// ostatusWaEeYs
-// ostatusogu9zg - besser
 		xml::add_element($doc, $as_object, "activity:object-type", NAMESPACE_ACTIVITY_SCHEMA."activity");
 
 		self::entry_content($doc, $as_object, $repeated_item, $owner, "", "", false);
@@ -1505,6 +1670,16 @@ class ostatus {
 		return $entry;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $item
+	 * @param $owner
+	 * @param $toplevel
+	 *
+	 * @return 
+	 */
 	private function like_entry($doc, $item, $owner, $toplevel) {
 
 		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
@@ -1532,6 +1707,16 @@ class ostatus {
 		return $entry;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $item
+	 * @param $owner
+	 * @param $toplevel
+	 *
+	 * @return 
+	 */
 	private function note_entry($doc, $item, $owner, $toplevel) {
 
 		if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) {
@@ -1549,6 +1734,16 @@ class ostatus {
 		return $entry;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $entry
+	 * @param $owner
+	 * @param $toplevel
+	 *
+	 * @return 
+	 */
 	private function entry_header($doc, &$entry, $owner, $toplevel) {
 		if (!$toplevel) {
 			$entry = $doc->createElement("entry");
@@ -1572,6 +1767,19 @@ class ostatus {
 		return $title;
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $entry
+	 * @param $item
+	 * @param $owner
+	 * @param $title
+	 * @param $verb
+	 * @param $complete
+	 *
+	 * @return 
+	 */
 	private function entry_content($doc, $entry, $item, $owner, $title, $verb = "", $complete = true) {
 
 		if ($verb == "")
@@ -1601,6 +1809,17 @@ class ostatus {
 		xml::add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME));
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $doc
+	 * @param $entry
+	 * @param $item
+	 * @param $owner
+	 * @param $complete
+	 *
+	 * @return 
+	 */
 	private function entry_footer($doc, $entry, $item, $owner, $complete = true) {
 
 		$mentioned = array();
@@ -1697,6 +1916,15 @@ class ostatus {
 		}
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $a
+	 * @param $owner_nick
+	 * @param $last_update
+	 *
+	 * @return 
+	 */
 	public static function feed(&$a, $owner_nick, $last_update) {
 
 		$r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`
@@ -1746,6 +1974,14 @@ class ostatus {
 		return(trim($doc->saveXML()));
 	}
 
+	/**
+	 * @brief 
+	 *
+	 * @param $item
+	 * @param $owner
+	 *
+	 * @return 
+	 */
 	public static function salmon($item,$owner) {
 
 		$doc = new DOMDocument('1.0', 'utf-8');

From ffd73d137bee6d17f44adc8bb37bfd15c23ec67e Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 31 Mar 2016 07:34:13 +0200
Subject: [PATCH 244/273] Added some documentation

---
 include/ostatus.php | 126 +++++++++++++++++++++-----------------------
 1 file changed, 61 insertions(+), 65 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index dcbd91f415..0796fcc3b7 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -28,15 +28,15 @@ class ostatus {
 	const OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS = 14400; // given in minutes
 
 	/**
-	 * @brief 
+	 * @brief Fetches author data
 	 *
-	 * @param $xpath
-	 * @param $context
-	 * @param $importer
-	 * @param $contact
-	 * @param $onlyfetch
+	 * @param object $xpath The xpath object
+	 * @param object $context The xml context of the author detals
+	 * @param array $importer user record of the importing user
+	 * @param array $contact Called by reference, will contain the fetched contact
+	 * @param bool $onlyfetch Only fetch the header without updating the contact entries
 	 *
-	 * @return 
+	 * @return array Array of author related entries for the item
 	 */
 	private function fetchauthor($xpath, $context, $importer, &$contact, $onlyfetch) {
 
@@ -147,7 +147,7 @@ class ostatus {
 	 * @brief 
 	 *
 	 * @param $xml
-	 * @param $importer
+	 * @param array $importer user record of the importing user
 	 *
 	 * @return 
 	 */
@@ -179,14 +179,12 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Imports an XML string containing OStatus elements
 	 *
-	 * @param $xml
-	 * @param $importer
+	 * @param string $xml The XML
+	 * @param array $importer user record of the importing user
 	 * @param $contact
-	 * @param $hub
-	 *
-	 * @return 
+	 * @param array $hub Called by reference, returns the fetched hub data
 	 */
 	public static function import($xml,$importer,&$contact, &$hub) {
 
@@ -530,11 +528,11 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Create an url out of an uri
 	 *
-	 * @param $href
+	 * @param string $href URI in the format "parameter1:parameter1:..."
 	 *
-	 * @return 
+	 * @return string URL in the format http(s)://....
 	 */
 	public static function convert_href($href) {
 		$elements = explode(":",$href);
@@ -560,12 +558,10 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Checks if there are entries in conversations that aren't present on our side
 	 *
-	 * @param $mentions
-	 * @param $override
-	 *
-	 * @return 
+	 * @param bool $mentions Fetch conversations where we are mentioned
+	 * @param bool $override Override the interval setting
 	 */
 	public static function check_conversations($mentions = false, $override = false) {
 		$last = get_config('system','ostatus_last_poll');
@@ -759,7 +755,7 @@ class ostatus {
 	 *
 	 * @param $conversation_url
 	 * @param $uid
-	 * @param $item
+	 * @param array $item Data of the item that is to be posted
 	 *
 	 * @return 
 	 */
@@ -1184,11 +1180,11 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Checks if the current post is a reshare
 	 *
-	 * @param $item
+	 * @param array $item The item array of thw post
 	 *
-	 * @return 
+	 * @return string The guid if the post is a reshare
 	 */
 	private function get_reshared_guid($item) {
 		$body = trim($item["body"]);
@@ -1220,11 +1216,11 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Cleans the body of a post if it contains picture links
 	 *
-	 * @param $body
+	 * @param string $body The body
 	 *
-	 * @return 
+	 * @return string The cleaned body
 	 */
 	private function format_picture_post($body) {
 		$siteinfo = get_attached_data($body);
@@ -1256,8 +1252,8 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
-	 * @param $owner
+	 * @param object $doc XML document
+	 * @param array $owner Contact data of the poster
 	 *
 	 * @return 
 	 */
@@ -1317,7 +1313,7 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
+	 * @param object $doc XML document
 	 * @param $root
 	 *
 	 * @return 
@@ -1344,9 +1340,9 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
+	 * @param object $doc XML document
 	 * @param $root
-	 * @param $item
+	 * @param array $item Data of the item that is to be posted
 	 *
 	 * @return 
 	 */
@@ -1416,8 +1412,8 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
-	 * @param $owner
+	 * @param object $doc XML document
+	 * @param array $owner Contact data of the poster
 	 *
 	 * @return 
 	 */
@@ -1490,7 +1486,7 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $item
+	 * @param array $item Data of the item that is to be posted
 	 *
 	 * @return 
 	 */
@@ -1503,7 +1499,7 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $item
+	 * @param array $item Data of the item that is to be posted
 	 *
 	 * @return 
 	 */
@@ -1516,9 +1512,9 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
-	 * @param $item
-	 * @param $owner
+	 * @param object $doc XML document
+	 * @param array $item Data of the item that is to be posted
+	 * @param array $owner Contact data of the poster
 	 * @param $toplevel
 	 *
 	 * @return 
@@ -1540,7 +1536,7 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
+	 * @param object $doc XML document
 	 * @param $contact
 	 *
 	 * @return 
@@ -1565,7 +1561,7 @@ class ostatus {
 	 * @brief 
 	 *
 	 * @param $url
-	 * @param $owner
+	 * @param array $owner Contact data of the poster
 	 *
 	 * @return 
 	 */
@@ -1606,9 +1602,9 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
-	 * @param $item
-	 * @param $owner
+	 * @param object $doc XML document
+	 * @param array $item Data of the item that is to be posted
+	 * @param array $owner Contact data of the poster
 	 * @param $repeated_guid
 	 * @param $toplevel
 	 *
@@ -1673,12 +1669,12 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
-	 * @param $item
-	 * @param $owner
+	 * @param object $doc XML document
+	 * @param array $item Data of the item that is to be posted
+	 * @param array $owner Contact data of the poster
 	 * @param $toplevel
 	 *
-	 * @return 
+	 * @return object
 	 */
 	private function like_entry($doc, $item, $owner, $toplevel) {
 
@@ -1710,9 +1706,9 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
-	 * @param $item
-	 * @param $owner
+	 * @param object $doc XML document
+	 * @param array $item Data of the item that is to be posted
+	 * @param array $owner Contact data of the poster
 	 * @param $toplevel
 	 *
 	 * @return 
@@ -1737,9 +1733,9 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
+	 * @param object $doc XML document
 	 * @param $entry
-	 * @param $owner
+	 * @param array $owner Contact data of the poster
 	 * @param $toplevel
 	 *
 	 * @return 
@@ -1770,10 +1766,10 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
+	 * @param object $doc XML document
 	 * @param $entry
-	 * @param $item
-	 * @param $owner
+	 * @param array $item Data of the item that is to be posted
+	 * @param array $owner Contact data of the poster
 	 * @param $title
 	 * @param $verb
 	 * @param $complete
@@ -1812,10 +1808,10 @@ class ostatus {
 	/**
 	 * @brief 
 	 *
-	 * @param $doc
+	 * @param object $doc XML document
 	 * @param $entry
-	 * @param $item
-	 * @param $owner
+	 * @param array $item Data of the item that is to be posted
+	 * @param array $owner Contact data of the poster
 	 * @param $complete
 	 *
 	 * @return 
@@ -1975,12 +1971,12 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Creates the XML for a salmon message
 	 *
-	 * @param $item
-	 * @param $owner
+	 * @param array $item Data of the item that is to be posted
+	 * @param array $owner Contact data of the poster
 	 *
-	 * @return 
+	 * @return string XML for the salmon
 	 */
 	public static function salmon($item,$owner) {
 

From d0b8f2092de0b839e956043de4442a46044fb59e Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 31 Mar 2016 22:01:56 +0200
Subject: [PATCH 245/273] Some more documentation

---
 include/ostatus.php | 119 ++++++++++++++++++++------------------------
 1 file changed, 55 insertions(+), 64 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index 0796fcc3b7..60db968f1d 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -144,12 +144,12 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Fetches author data from a given XML string
 	 *
-	 * @param $xml
+	 * @param string $xml The XML
 	 * @param array $importer user record of the importing user
 	 *
-	 * @return 
+	 * @return array Array of author related entries for the item
 	 */
 	public static function salmon_author($xml, $importer) {
 
@@ -751,13 +751,13 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Stores an item and completes the thread
 	 *
-	 * @param $conversation_url
-	 * @param $uid
+	 * @param string $conversation_url The URI of the conversation
+	 * @param integer $uid The user id
 	 * @param array $item Data of the item that is to be posted
 	 *
-	 * @return 
+	 * @return integer The item id of the posted item array
 	 */
 	private function completion($conversation_url, $uid, $item = array(), $self = "") {
 
@@ -1151,12 +1151,10 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Stores conversation data into the database
 	 *
-	 * @param $itemid
-	 * @param $conversation_url
-	 *
-	 * @return 
+	 * @param integer $itemid The id of the item
+	 * @param string $conversation_url The uri of the conversation
 	 */
 	private function store_conversation($itemid, $conversation_url) {
 
@@ -1250,12 +1248,12 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Adds the header elements to the XML document
 	 *
 	 * @param object $doc XML document
 	 * @param array $owner Contact data of the poster
 	 *
-	 * @return 
+	 * @return object header root element
 	 */
 	private function add_header($doc, $owner) {
 
@@ -1311,12 +1309,10 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Add the link to the push hubs to the XML document
 	 *
 	 * @param object $doc XML document
-	 * @param $root
-	 *
-	 * @return 
+	 * @param object $root XML root element where the hub links are added
 	 */
 	public static function hublinks($doc, $root) {
 		$hub = get_config('system','huburl');
@@ -1338,13 +1334,11 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Adds attachement data to the XML document
 	 *
 	 * @param object $doc XML document
-	 * @param $root
+	 * @param object $root XML root element where the hub links are added
 	 * @param array $item Data of the item that is to be posted
-	 *
-	 * @return 
 	 */
 	private function get_attachment($doc, $root, $item) {
 		$o = "";
@@ -1410,12 +1404,12 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Adds the author element to the XML document
 	 *
 	 * @param object $doc XML document
 	 * @param array $owner Contact data of the poster
 	 *
-	 * @return 
+	 * @return object author element
 	 */
 	private function add_author($doc, $owner) {
 
@@ -1484,11 +1478,11 @@ class ostatus {
 	*/
 
 	/**
-	 * @brief 
+	 * @brief Returns the given activity if present - otherwise returns the "post" activity
 	 *
 	 * @param array $item Data of the item that is to be posted
 	 *
-	 * @return 
+	 * @return string activity
 	 */
 	function construct_verb($item) {
 		if ($item['verb'])
@@ -1497,11 +1491,11 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Returns the given object type if present - otherwise returns the "note" object type
 	 *
 	 * @param array $item Data of the item that is to be posted
 	 *
-	 * @return 
+	 * @return string Object type
 	 */
 	function construct_objecttype($item) {
 		if (in_array($item['object-type'], array(ACTIVITY_OBJ_NOTE, ACTIVITY_OBJ_COMMENT)))
@@ -1510,14 +1504,14 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Adds an entry element to the XML document
 	 *
 	 * @param object $doc XML document
 	 * @param array $item Data of the item that is to be posted
 	 * @param array $owner Contact data of the poster
-	 * @param $toplevel
+	 * @param bool $toplevel
 	 *
-	 * @return 
+	 * @return object Entry element
 	 */
 	private function entry($doc, $item, $owner, $toplevel = false) {
 		$repeated_guid = self::get_reshared_guid($item);
@@ -1534,12 +1528,12 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Adds a source entry to the XML document
 	 *
 	 * @param object $doc XML document
-	 * @param $contact
+	 * @param array $contact Array of the contact that is added
 	 *
-	 * @return 
+	 * @return object Source element
 	 */
 	private function source_entry($doc, $contact) {
 		$source = $doc->createElement("source");
@@ -1558,12 +1552,12 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Fetches contact data from the contact or the gcontact table
 	 *
-	 * @param $url
+	 * @param string $url URL of the contact
 	 * @param array $owner Contact data of the poster
 	 *
-	 * @return 
+	 * @return array Contact array
 	 */
 	private function contact_entry($url, $owner) {
 
@@ -1600,15 +1594,15 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Adds an entry element with reshared content
 	 *
 	 * @param object $doc XML document
 	 * @param array $item Data of the item that is to be posted
 	 * @param array $owner Contact data of the poster
 	 * @param $repeated_guid
-	 * @param $toplevel
+	 * @param bool $toplevel Is it for en entry element (false) or a feed entry (true)?
 	 *
-	 * @return 
+	 * @return object Entry element
 	 */
 	private function reshare_entry($doc, $item, $owner, $repeated_guid, $toplevel) {
 
@@ -1667,14 +1661,14 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Adds an entry element with a "like"
 	 *
 	 * @param object $doc XML document
 	 * @param array $item Data of the item that is to be posted
 	 * @param array $owner Contact data of the poster
-	 * @param $toplevel
+	 * @param bool $toplevel Is it for en entry element (false) or a feed entry (true)?
 	 *
-	 * @return object
+	 * @return object Entry element with "like"
 	 */
 	private function like_entry($doc, $item, $owner, $toplevel) {
 
@@ -1704,14 +1698,14 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Adds a regular entry element
 	 *
 	 * @param object $doc XML document
 	 * @param array $item Data of the item that is to be posted
 	 * @param array $owner Contact data of the poster
-	 * @param $toplevel
+	 * @param bool $toplevel Is it for en entry element (false) or a feed entry (true)?
 	 *
-	 * @return 
+	 * @return object Entry element
 	 */
 	private function note_entry($doc, $item, $owner, $toplevel) {
 
@@ -1731,16 +1725,17 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Adds a header element to the XML document
 	 *
 	 * @param object $doc XML document
-	 * @param $entry
+	 * @param object $entry Entry element
 	 * @param array $owner Contact data of the poster
-	 * @param $toplevel
+	 * @param bool $toplevel Is it for en entry element (false) or a feed entry (true)?
 	 *
-	 * @return 
+	 * @return string The title for the element
 	 */
 	private function entry_header($doc, &$entry, $owner, $toplevel) {
+		/// @todo Check if this title stuff is really needed (I guess not)
 		if (!$toplevel) {
 			$entry = $doc->createElement("entry");
 			$title = sprintf("New note by %s", $owner["nick"]);
@@ -1764,17 +1759,15 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Adds elements to the XML document
 	 *
 	 * @param object $doc XML document
-	 * @param $entry
+	 * @param object $entry Entry element where the content is added
 	 * @param array $item Data of the item that is to be posted
 	 * @param array $owner Contact data of the poster
-	 * @param $title
-	 * @param $verb
-	 * @param $complete
-	 *
-	 * @return 
+	 * @param string $title Title for the post
+	 * @param string $verb The activity verb
+	 * @param bool $complete Add the "status_net" element?
 	 */
 	private function entry_content($doc, $entry, $item, $owner, $title, $verb = "", $complete = true) {
 
@@ -1813,8 +1806,6 @@ class ostatus {
 	 * @param array $item Data of the item that is to be posted
 	 * @param array $owner Contact data of the poster
 	 * @param $complete
-	 *
-	 * @return 
 	 */
 	private function entry_footer($doc, $entry, $item, $owner, $complete = true) {
 
@@ -1913,13 +1904,13 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Creates the XML feed for a given nickname
 	 *
-	 * @param $a
-	 * @param $owner_nick
-	 * @param $last_update
+	 * @param app $a The application class
+	 * @param string $owner_nick Nickname of the feed owner
+	 * @param string $last_update Date of the last update
 	 *
-	 * @return 
+	 * @return string XML feed
 	 */
 	public static function feed(&$a, $owner_nick, $last_update) {
 

From ffcc5f372f5626c592ada8de2b7eacfbc61f6622 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Thu, 31 Mar 2016 22:24:54 +0200
Subject: [PATCH 246/273] Some more documentation

---
 include/ostatus.php | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index 60db968f1d..e31b4474da 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -187,6 +187,7 @@ class ostatus {
 	 * @param array $hub Called by reference, returns the fetched hub data
 	 */
 	public static function import($xml,$importer,&$contact, &$hub) {
+		/// @todo this function is too long. It has to be split in many parts
 
 		logger("Import OStatus message", LOGGER_DEBUG);
 
@@ -761,6 +762,7 @@ class ostatus {
 	 */
 	private function completion($conversation_url, $uid, $item = array(), $self = "") {
 
+		/// @todo This function is totally ugly and has to be rewritten totally
 
 		$item_stored = -1;
 
@@ -1728,7 +1730,7 @@ class ostatus {
 	 * @brief Adds a header element to the XML document
 	 *
 	 * @param object $doc XML document
-	 * @param object $entry Entry element
+	 * @param object $entry The entry element where the elements are added
 	 * @param array $owner Contact data of the poster
 	 * @param bool $toplevel Is it for en entry element (false) or a feed entry (true)?
 	 *
@@ -1799,10 +1801,10 @@ class ostatus {
 	}
 
 	/**
-	 * @brief 
+	 * @brief Adds the elements at the foot of an entry to the XML document
 	 *
 	 * @param object $doc XML document
-	 * @param $entry
+	 * @param object $entry The entry element where the elements are added
 	 * @param array $item Data of the item that is to be posted
 	 * @param array $owner Contact data of the poster
 	 * @param $complete

From 416a0e5ec2684f1bfe029da9438b2782127d9355 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 1 Apr 2016 21:09:52 +0200
Subject: [PATCH 247/273] Don't optimize the tables when the maximum size is
 lower than zero

---
 include/cron.php | 46 ++++++++++++++++++++++++----------------------
 1 file changed, 24 insertions(+), 22 deletions(-)

diff --git a/include/cron.php b/include/cron.php
index c60284b738..a2482ff300 100644
--- a/include/cron.php
+++ b/include/cron.php
@@ -335,35 +335,37 @@ function cron_clear_cache(&$a) {
 	if ($max_tablesize == 0)
 		$max_tablesize = 100 * 1000000; // Default are 100 MB
 
-	// Minimum fragmentation level in percent
-	$fragmentation_level = intval(get_config('system','optimize_fragmentation')) / 100;
-	if ($fragmentation_level == 0)
-		$fragmentation_level = 0.3; // Default value is 30%
+	if ($max_tablesize > 0) {
+		// Minimum fragmentation level in percent
+		$fragmentation_level = intval(get_config('system','optimize_fragmentation')) / 100;
+		if ($fragmentation_level == 0)
+			$fragmentation_level = 0.3; // Default value is 30%
 
-	// Optimize some tables that need to be optimized
-	$r = q("SHOW TABLE STATUS");
-	foreach($r as $table) {
+		// Optimize some tables that need to be optimized
+		$r = q("SHOW TABLE STATUS");
+		foreach($r as $table) {
 
-		// Don't optimize tables that are too large
-		if ($table["Data_length"] > $max_tablesize)
-			continue;
+			// Don't optimize tables that are too large
+			if ($table["Data_length"] > $max_tablesize)
+				continue;
 
-		// Don't optimize empty tables
-		if ($table["Data_length"] == 0)
-			continue;
+			// Don't optimize empty tables
+			if ($table["Data_length"] == 0)
+				continue;
 
-		// Calculate fragmentation
-		$fragmentation = $table["Data_free"] / ($table["Data_length"] + $table["Index_length"]);
+			// Calculate fragmentation
+			$fragmentation = $table["Data_free"] / ($table["Data_length"] + $table["Index_length"]);
 
-		logger("Table ".$table["Name"]." - Fragmentation level: ".round($fragmentation * 100, 2), LOGGER_DEBUG);
+			logger("Table ".$table["Name"]." - Fragmentation level: ".round($fragmentation * 100, 2), LOGGER_DEBUG);
 
-		// Don't optimize tables that needn't to be optimized
-		if ($fragmentation < $fragmentation_level)
-			continue;
+			// Don't optimize tables that needn't to be optimized
+			if ($fragmentation < $fragmentation_level)
+				continue;
 
-		// So optimize it
-		logger("Optimize Table ".$table["Name"], LOGGER_DEBUG);
-		q("OPTIMIZE TABLE `%s`", dbesc($table["Name"]));
+			// So optimize it
+			logger("Optimize Table ".$table["Name"], LOGGER_DEBUG);
+			q("OPTIMIZE TABLE `%s`", dbesc($table["Name"]));
+		}
 	}
 
 	set_config('system','cache_last_cleared', time());

From eeb462cd0460d029a8b9e29f3dd122eb16befec1 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Fri, 1 Apr 2016 21:41:37 +0200
Subject: [PATCH 248/273] Only update the contact entry with uid=0

---
 include/Scrape.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/Scrape.php b/include/Scrape.php
index deff0b080f..3fead0c415 100644
--- a/include/Scrape.php
+++ b/include/Scrape.php
@@ -845,7 +845,7 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 		/// It should only be updated if the existing picture isn't existing anymore.
 		if (($result['network'] != NETWORK_FEED) AND $result["addr"] AND $result["name"] AND $result["nick"])
 			q("UPDATE `contact` SET `addr` = '%s', `alias` = '%s', `name` = '%s', `nick` = '%s',
-				`name-date` = '%s', `uri-date` = '%s' WHERE `nurl` = '%s' AND NOT `self`",
+				`name-date` = '%s', `uri-date` = '%s' WHERE `nurl` = '%s' AND NOT `self` AND `uid` = 0",
 				dbesc($result["addr"]),
 				dbesc($result["alias"]),
 				dbesc($result["name"]),

From 08fb662b4a7b9c94a5882b0c6f47ed463dfb0ba2 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 2 Apr 2016 00:24:56 +0200
Subject: [PATCH 249/273] OStatus: Salmon now works with "likes"/The alias is
 stored now as well

---
 include/notifier.php | 16 +++++++++++++++-
 include/ostatus.php  | 13 +++++++------
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/include/notifier.php b/include/notifier.php
index 18a617ac2f..ffbb22e7bf 100644
--- a/include/notifier.php
+++ b/include/notifier.php
@@ -229,7 +229,7 @@ function notifier_run(&$argv, &$argc){
 
 		$parent = $items[0];
 
-		$thr_parent = q("SELECT `network` FROM `item` WHERE `uri` = '%s' AND `uid` = %d",
+		$thr_parent = q("SELECT `network`, `author-link`, `owner-link` FROM `item` WHERE `uri` = '%s' AND `uid` = %d",
 			dbesc($target_item["thr-parent"]), intval($target_item["uid"]));
 
 		logger('Parent is '.$parent['network'].'. Thread parent is '.$thr_parent[0]['network'], LOGGER_DEBUG);
@@ -390,6 +390,20 @@ function notifier_run(&$argv, &$argc){
 
 			logger('Some parent is OStatus for '.$target_item["guid"], LOGGER_DEBUG);
 
+			// Send a salmon to the parent author
+			$probed_contact = probe_url($thr_parent[0]['author-link']);
+			if ($probed_contact["notify"] != "") {
+				logger('Notify parent author '.$probed_contact["url"].': '.$probed_contact["notify"]);
+				$url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
+			}
+
+			// Send a salmon to the parent owner
+			$probed_contact = probe_url($thr_parent[0]['owner-link']);
+			if ($probed_contact["notify"] != "") {
+				logger('Notify parent owner '.$probed_contact["url"].': '.$probed_contact["notify"]);
+				$url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
+			}
+
 			// Send a salmon notification to every person we mentioned in the post
 			$arr = explode(',',$target_item['tag']);
 			foreach($arr as $x) {
diff --git a/include/ostatus.php b/include/ostatus.php
index e31b4474da..4775e2ccb9 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -44,8 +44,7 @@ class ostatus {
 		$author["author-link"] = $xpath->evaluate('atom:author/atom:uri/text()', $context)->item(0)->nodeValue;
 		$author["author-name"] = $xpath->evaluate('atom:author/atom:name/text()', $context)->item(0)->nodeValue;
 
-		// Preserve the value
-		$authorlink = $author["author-link"];
+		$aliaslink = $author["author-link"];
 
 		$alternate = $xpath->query("atom:author/atom:link[@rel='alternate']", $context)->item(0)->attributes;
 		if (is_object($alternate))
@@ -55,7 +54,7 @@ class ostatus {
 
 		$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'",
 			intval($importer["uid"]), dbesc(normalise_link($author["author-link"])),
-			dbesc(normalise_link($authorlink)), dbesc(NETWORK_STATUSNET));
+			dbesc(normalise_link($aliaslink)), dbesc(NETWORK_STATUSNET));
 		if ($r) {
 			$contact = $r[0];
 			$author["contact-id"] = $r[0]["id"];
@@ -117,12 +116,14 @@ class ostatus {
 			if ($value != "")
 				$contact["location"] = $value;
 
-			if (($contact["name"] != $r[0]["name"]) OR ($contact["nick"] != $r[0]["nick"]) OR ($contact["about"] != $r[0]["about"]) OR ($contact["location"] != $r[0]["location"])) {
+			if (($contact["name"] != $r[0]["name"]) OR ($contact["nick"] != $r[0]["nick"]) OR ($contact["about"] != $r[0]["about"]) OR
+				($contact["alias"] != $r[0]["alias"]) OR ($contact["location"] != $r[0]["location"])) {
 
 				logger("Update contact data for contact ".$contact["id"], LOGGER_DEBUG);
 
-				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', `name-date` = '%s' WHERE `id` = %d",
-					dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
+				q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `alias` = '%s', `about` = '%s', `location` = '%s', `name-date` = '%s' WHERE `id` = %d",
+					dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["alias"]),
+					dbesc($contact["about"]), dbesc($contact["location"]),
 					dbesc(datetime_convert()), intval($contact["id"]));
 
 				poco_check($contact["url"], $contact["name"], $contact["network"], $author["author-avatar"], $contact["about"], $contact["location"],

From bc05984786547a1440261be932d8d7f5498d74ae Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 2 Apr 2016 09:06:10 +0200
Subject: [PATCH 250/273] Only update contact when scrape runs with
 "probe_normal"

---
 include/Scrape.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/Scrape.php b/include/Scrape.php
index 3fead0c415..9913f360d6 100644
--- a/include/Scrape.php
+++ b/include/Scrape.php
@@ -843,15 +843,15 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 		/// @todo temporary fix - we need a real contact update function that updates only changing fields
 		/// The biggest problem is the avatar picture that could have a reduced image size.
 		/// It should only be updated if the existing picture isn't existing anymore.
-		if (($result['network'] != NETWORK_FEED) AND $result["addr"] AND $result["name"] AND $result["nick"])
+		if (($result['network'] != NETWORK_FEED) AND ($mode == PROBE_NORMAL) AND
+			$result["addr"] AND $result["name"] AND $result["nick"])
 			q("UPDATE `contact` SET `addr` = '%s', `alias` = '%s', `name` = '%s', `nick` = '%s',
-				`name-date` = '%s', `uri-date` = '%s' WHERE `nurl` = '%s' AND NOT `self` AND `uid` = 0",
+				`success_update` = '%s' WHERE `nurl` = '%s' AND NOT `self` AND `uid` = 0",
 				dbesc($result["addr"]),
 				dbesc($result["alias"]),
 				dbesc($result["name"]),
 				dbesc($result["nick"]),
 				dbesc(datetime_convert()),
-				dbesc(datetime_convert()),
 				dbesc(normalise_link($result['url']))
 		);
 	}

From fd965b046aa12bad60330c4c5655dd21a325f998 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 2 Apr 2016 14:10:40 +0200
Subject: [PATCH 251/273] Update contact data for uid=0 at feed import

---
 include/ostatus.php | 37 ++++++++++++++++++++++++++++++++-----
 1 file changed, 32 insertions(+), 5 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index 4775e2ccb9..d6e2e17735 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -90,13 +90,20 @@ class ostatus {
 
 		// Only update the contacts if it is an OStatus contact
 		if ($r AND !$onlyfetch AND ($contact["network"] == NETWORK_OSTATUS)) {
+
 			// Update contact data
 
-			$value = $xpath->query("atom:link[@rel='salmon']", $context)->item(0)->nodeValue;
-			if ($value != "")
-				$contact["notify"] = $value;
+			// This query doesn't seem to work
+			// $value = $xpath->query("atom:link[@rel='salmon']", $context)->item(0)->nodeValue;
+			// if ($value != "")
+			//	$contact["notify"] = $value;
 
-			$value = $xpath->evaluate('atom:author/uri/text()', $context)->item(0)->nodeValue;
+			// This query doesn't seem to work as well - I hate these queries
+			// $value = $xpath->query("atom:link[@rel='self' and @type='application/atom+xml']", $context)->item(0)->nodeValue;
+			// if ($value != "")
+			//	$contact["poll"] = $value;
+
+			$value = $xpath->evaluate('atom:author/atom:uri/text()', $context)->item(0)->nodeValue;
 			if ($value != "")
 				$contact["alias"] = $value;
 
@@ -136,6 +143,24 @@ class ostatus {
 				update_contact_avatar($author["author-avatar"], $importer["uid"], $contact["id"]);
 			}
 
+			// Ensure that we are having this contact (with uid=0)
+			$cid = get_contact($author["author-link"], 0);
+
+			if ($cid) {
+				// Update it with the current values
+				q("UPDATE `contact` SET `url` = '%s', `name` = '%s', `nick` = '%s', `alias` = '%s',
+						`about` = '%s', `location` = '%s', `notify` = '%s', `poll` = '%s',
+						`success_update` = '%s', `last-update` = '%s'
+					WHERE `id` = %d",
+					dbesc($author["author-link"]), dbesc($contact["name"]), dbesc($contact["nick"]),
+					dbesc($contact["alias"]), dbesc($contact["about"]), dbesc($contact["location"]),
+					dbesc($contact["notify"]), dbesc($contact["poll"]),
+					dbesc(datetime_convert()), dbesc(datetime_convert()), intval($cid));
+
+				// Update the avatar
+				update_contact_avatar($author["author-avatar"], 0, $cid);
+			}
+
 			$contact["generation"] = 2;
 			$contact["photo"] = $author["author-avatar"];
 			update_gcontact($contact);
@@ -1586,8 +1611,10 @@ class ostatus {
 
 		if (!isset($contact["poll"])) {
 			$data = probe_url($url);
-			$contact["alias"] = $data["alias"];
 			$contact["poll"] = $data["poll"];
+
+			if (!$contact["alias"])
+				$contact["alias"] = $data["alias"];
 		}
 
 		if (!isset($contact["alias"]))

From b4b62493e6f43ed85d9c9cecabf118814db8d454 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 2 Apr 2016 15:41:55 +0200
Subject: [PATCH 252/273] Bugfix: The nickname vanished/better way to fetch the
 alias

---
 include/Scrape.php | 21 +++++++++++++++------
 include/cron.php   |  3 +++
 include/feed.php   |  5 ++++-
 mod/noscrape.php   |  2 +-
 4 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/include/Scrape.php b/include/Scrape.php
index 9913f360d6..ac95c0d5d3 100644
--- a/include/Scrape.php
+++ b/include/Scrape.php
@@ -23,13 +23,15 @@ function scrape_dfrn($url, $dont_probe = false) {
 		if (is_array($noscrapedata)) {
 			if ($noscrapedata["nick"] != "")
 				return($noscrapedata);
+			else
+				unset($noscrapedata["nick"]);
 		} else
 			$noscrapedata = array();
 	}
 
 	$s = fetch_url($url);
 
-	if(! $s)
+	if (!$s)
 		return $ret;
 
 	if (!$dont_probe) {
@@ -703,6 +705,9 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 					if (($vcard["nick"] == "") AND ($data["header"]["author-nick"] != ""))
 						$vcard["nick"] = $data["header"]["author-nick"];
 
+					if (($network == NETWORK_OSTATUS) AND ($data["header"]["author-id"] != ""))
+						$alias = $data["header"]["author-id"];
+
 					if(!$profile AND ($data["header"]["author-link"] != "") AND !in_array($network, array("", NETWORK_FEED)))
 						$profile = $data["header"]["author-link"];
 				}
@@ -844,13 +849,17 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 		/// The biggest problem is the avatar picture that could have a reduced image size.
 		/// It should only be updated if the existing picture isn't existing anymore.
 		if (($result['network'] != NETWORK_FEED) AND ($mode == PROBE_NORMAL) AND
-			$result["addr"] AND $result["name"] AND $result["nick"])
-			q("UPDATE `contact` SET `addr` = '%s', `alias` = '%s', `name` = '%s', `nick` = '%s',
-				`success_update` = '%s' WHERE `nurl` = '%s' AND NOT `self` AND `uid` = 0",
-				dbesc($result["addr"]),
-				dbesc($result["alias"]),
+			$result["name"] AND $result["nick"] AND $result["url"] AND $result["addr"] AND $result["poll"])
+			q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `url` = '%s', `addr` = '%s',
+					`notify` = '%s', `poll` = '%s', `alias` = '%s', `success_update` = '%s'
+				WHERE `nurl` = '%s' AND NOT `self` AND `uid` = 0",
 				dbesc($result["name"]),
 				dbesc($result["nick"]),
+				dbesc($result["url"]),
+				dbesc($result["addr"]),
+				dbesc($result["notify"]),
+				dbesc($result["poll"]),
+				dbesc($result["alias"]),
 				dbesc(datetime_convert()),
 				dbesc(normalise_link($result['url']))
 		);
diff --git a/include/cron.php b/include/cron.php
index a2482ff300..e2f4102804 100644
--- a/include/cron.php
+++ b/include/cron.php
@@ -405,6 +405,9 @@ function cron_repair_database() {
 	// This call is very "cheap" so we can do it at any time without a problem
 	q("UPDATE `item` INNER JOIN `item` AS `parent` ON `parent`.`uri` = `item`.`parent-uri` AND `parent`.`uid` = `item`.`uid` SET `item`.`parent` = `parent`.`id` WHERE `item`.`parent` = 0");
 
+	// There was an issue where the nick vanishes from the contact table
+	q("UPDATE `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid` SET `nick` = `nickname` WHERE `self` AND `nick`=''");
+
 	/// @todo
 	/// - remove thread entries without item
 	/// - remove sign entries without item
diff --git a/include/feed.php b/include/feed.php
index 04cfba75a6..293de3cc96 100644
--- a/include/feed.php
+++ b/include/feed.php
@@ -54,8 +54,10 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
 				if ($attributes->name == "href")
 					$author["author-link"] = $attributes->textContent;
 
+		$author["author-id"] = $xpath->evaluate('/atom:feed/atom:author/atom:uri/text()')->item(0)->nodeValue;
+
 		if ($author["author-link"] == "")
-			$author["author-link"] = $xpath->evaluate('/atom:feed/atom:author/atom:uri/text()')->item(0)->nodeValue;
+			$author["author-link"] = $author["author-id"];
 
 		if ($author["author-link"] == "") {
 			$self = $xpath->query("atom:link[@rel='self']")->item(0)->attributes;
@@ -127,6 +129,7 @@ function feed_import($xml,$importer,&$contact, &$hub, $simulate = false) {
 
 		// This is no field in the item table. So we have to unset it.
 		unset($author["author-nick"]);
+		unset($author["author-id"]);
 	}
 
 	$header = array();
diff --git a/mod/noscrape.php b/mod/noscrape.php
index 1f7105b769..4be1a740cd 100644
--- a/mod/noscrape.php
+++ b/mod/noscrape.php
@@ -28,7 +28,7 @@ function noscrape_init(&$a) {
 	$json_info = array(
 		'fn' => $a->profile['name'],
 		'addr' => $a->profile['addr'],
-		'nick' => $a->user['nickname'],
+		'nick' => $which,
 		'key' => $a->profile['pubkey'],
 		'homepage' => $a->get_baseurl()."/profile/{$which}",
 		'comm' => (x($a->profile,'page-flags')) && ($a->profile['page-flags'] == PAGE_COMMUNITY),

From 68b88c038426bfbe97010f2b85a4675fd49d299f Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 2 Apr 2016 15:49:57 +0200
Subject: [PATCH 253/273] Notify and poll aren't fetched at the moment

---
 include/ostatus.php | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index d6e2e17735..bf14536f9e 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -149,12 +149,11 @@ class ostatus {
 			if ($cid) {
 				// Update it with the current values
 				q("UPDATE `contact` SET `url` = '%s', `name` = '%s', `nick` = '%s', `alias` = '%s',
-						`about` = '%s', `location` = '%s', `notify` = '%s', `poll` = '%s',
+						`about` = '%s', `location` = '%s',
 						`success_update` = '%s', `last-update` = '%s'
 					WHERE `id` = %d",
 					dbesc($author["author-link"]), dbesc($contact["name"]), dbesc($contact["nick"]),
 					dbesc($contact["alias"]), dbesc($contact["about"]), dbesc($contact["location"]),
-					dbesc($contact["notify"]), dbesc($contact["poll"]),
 					dbesc(datetime_convert()), dbesc(datetime_convert()), intval($cid));
 
 				// Update the avatar

From ce2c1b4fc1b9328e8f968083062b921e02b4fa59 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 2 Apr 2016 17:43:53 +0200
Subject: [PATCH 254/273] Small bugfix: We always liked the parent

---
 include/ostatus.php | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/ostatus.php b/include/ostatus.php
index bf14536f9e..b798a605f9 100644
--- a/include/ostatus.php
+++ b/include/ostatus.php
@@ -1712,7 +1712,8 @@ class ostatus {
 
 		$as_object = $doc->createElement("activity:object");
 
-		$parent = q("SELECT * FROM `item` WHERE `id` = %d", intval($item["parent"]));
+		$parent = q("SELECT * FROM `item` WHERE `uri` = '%s' AND `uid` = %d",
+			dbesc($item["thr-parent"]), intval($item["uid"]));
 		$parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']);
 
 		xml::add_element($doc, $as_object, "activity:object-type", self::construct_objecttype($parent[0]));

From beb1e040696ae53b58aebdd2f639b0eb90c639fd Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 3 Apr 2016 13:48:31 +0200
Subject: [PATCH 255/273] New field in item table ("shadow") that indicates if
 there is a shadow entry

---
 boot.php                |   8 +--
 include/Contact.php     |  54 -----------------
 include/cron.php        |   5 +-
 include/dbstructure.php |   1 +
 include/post_update.php | 129 ++++++++++++++++++++++++++++++++++++++++
 include/threads.php     |   8 ++-
 update.php              |   2 +-
 7 files changed, 145 insertions(+), 62 deletions(-)
 create mode 100644 include/post_update.php

diff --git a/boot.php b/boot.php
index a70c7bf616..13cc2aaf5b 100644
--- a/boot.php
+++ b/boot.php
@@ -6,11 +6,11 @@
 
 /**
  * Friendica
- * 
+ *
  * Friendica is a communications platform for integrated social communications
  * utilising decentralised communications and linkage to several indie social
  * projects - as well as popular mainstream providers.
- * 
+ *
  * Our mission is to free our friends and families from the clutches of
  * data-harvesting corporations, and pave the way to a future where social
  * communications are free and open and flow between alternate providers as
@@ -18,7 +18,7 @@
  */
 
 require_once('include/autoloader.php');
- 
+
 require_once('include/config.php');
 require_once('include/network.php');
 require_once('include/plugin.php');
@@ -38,7 +38,7 @@ define ( 'FRIENDICA_PLATFORM',     'Friendica');
 define ( 'FRIENDICA_CODENAME',     'Asparagus');
 define ( 'FRIENDICA_VERSION',      '3.5-dev' );
 define ( 'DFRN_PROTOCOL_VERSION',  '2.23'    );
-define ( 'DB_UPDATE_VERSION',      1194      );
+define ( 'DB_UPDATE_VERSION',      1195      );
 
 /**
  * @brief Constant with a HTML line break.
diff --git a/include/Contact.php b/include/Contact.php
index d76c8f826c..79a14ab581 100644
--- a/include/Contact.php
+++ b/include/Contact.php
@@ -555,60 +555,6 @@ function posts_from_gcontact($a, $gcontact_id) {
 	return $o;
 }
 
-/**
- * @brief set the gcontact-id in all item entries
- *
- * This job has to be started multiple times until all entries are set.
- * It isn't started in the update function since it would consume too much time and can be done in the background.
- */
-function item_set_gcontact() {
-	define ('POST_UPDATE_VERSION', 1192);
-
-	// Was the script completed?
-	if (get_config("system", "post_update_version") >= POST_UPDATE_VERSION)
-		return;
-
-	// Check if the first step is done (Setting "gcontact-id" in the item table)
-	$r = q("SELECT `author-link`, `author-name`, `author-avatar`, `uid`, `network` FROM `item` WHERE `gcontact-id` = 0 LIMIT 1000");
-	if (!$r) {
-		// Are there unfinished entries in the thread table?
-		$r = q("SELECT COUNT(*) AS `total` FROM `thread`
-			INNER JOIN `item` ON `item`.`id` =`thread`.`iid`
-			WHERE `thread`.`gcontact-id` = 0 AND
-				(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)");
-
-		if ($r AND ($r[0]["total"] == 0)) {
-			set_config("system", "post_update_version", POST_UPDATE_VERSION);
-			return false;
-		}
-
-		// Update the thread table from the item table
-		q("UPDATE `thread` INNER JOIN `item` ON `item`.`id`=`thread`.`iid`
-				SET `thread`.`gcontact-id` = `item`.`gcontact-id`
-			WHERE `thread`.`gcontact-id` = 0 AND
-				(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)");
-
-		return false;
-	}
-
-	$item_arr = array();
-	foreach ($r AS $item) {
-		$index = $item["author-link"]."-".$item["uid"];
-		$item_arr[$index] = array("author-link" => $item["author-link"],
-						"uid" => $item["uid"],
-						"network" => $item["network"]);
-	}
-
-	// Set the "gcontact-id" in the item table and add a new gcontact entry if needed
-	foreach($item_arr AS $item) {
-		$gcontact_id = get_gcontact_id(array("url" => $item['author-link'], "network" => $item['network'],
-						"photo" => $item['author-avatar'], "name" => $item['author-name']));
-		q("UPDATE `item` SET `gcontact-id` = %d WHERE `uid` = %d AND `author-link` = '%s' AND `gcontact-id` = 0",
-			intval($gcontact_id), intval($item["uid"]), dbesc($item["author-link"]));
-	}
-	return true;
-}
-
 /**
  * @brief Returns posts from a given contact
  *
diff --git a/include/cron.php b/include/cron.php
index e2f4102804..4eb76f1ce2 100644
--- a/include/cron.php
+++ b/include/cron.php
@@ -35,6 +35,7 @@ function cron_run(&$argv, &$argc){
 	require_once('include/email.php');
 	require_once('include/socgraph.php');
 	require_once('mod/nodeinfo.php');
+	require_once('include/post_update.php');
 
 	load_config('config');
 	load_config('system');
@@ -106,8 +107,8 @@ function cron_run(&$argv, &$argc){
 	// Check every conversation
 	ostatus::check_conversations(false);
 
-	// Set the gcontact-id in the item table if missing
-	item_set_gcontact();
+	// Do post update functions
+	post_update();
 
 	// update nodeinfo data
 	nodeinfo_cron();
diff --git a/include/dbstructure.php b/include/dbstructure.php
index e34e409023..33e0c7dc8c 100644
--- a/include/dbstructure.php
+++ b/include/dbstructure.php
@@ -783,6 +783,7 @@ function db_definition() {
 					"parent-uri" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
 					"extid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
 					"thr-parent" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
+					"shadow" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
 					"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
 					"edited" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
 					"commented" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
diff --git a/include/post_update.php b/include/post_update.php
new file mode 100644
index 0000000000..2143ac3d6f
--- /dev/null
+++ b/include/post_update.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * @brief Calls the post update functions
+ */
+function post_update() {
+
+	if (!post_update_1192())
+		return;
+
+	if (!post_update_1195())
+		return;
+}
+
+/**
+ * @brief set the gcontact-id in all item entries
+ *
+ * This job has to be started multiple times until all entries are set.
+ * It isn't started in the update function since it would consume too much time and can be done in the background.
+ *
+ * @return bool "true" when the job is done
+ */
+function post_update_1192() {
+
+	// Was the script completed?
+	if (get_config("system", "post_update_version") >= 1192)
+		return true;
+
+	// Check if the first step is done (Setting "gcontact-id" in the item table)
+	$r = q("SELECT `author-link`, `author-name`, `author-avatar`, `uid`, `network` FROM `item` WHERE `gcontact-id` = 0 LIMIT 1000");
+	if (!$r) {
+		// Are there unfinished entries in the thread table?
+		$r = q("SELECT COUNT(*) AS `total` FROM `thread`
+			INNER JOIN `item` ON `item`.`id` =`thread`.`iid`
+			WHERE `thread`.`gcontact-id` = 0 AND
+				(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)");
+
+		if ($r AND ($r[0]["total"] == 0)) {
+			set_config("system", "post_update_version", 1192);
+			return true;
+		}
+
+		// Update the thread table from the item table
+		q("UPDATE `thread` INNER JOIN `item` ON `item`.`id`=`thread`.`iid`
+				SET `thread`.`gcontact-id` = `item`.`gcontact-id`
+			WHERE `thread`.`gcontact-id` = 0 AND
+				(`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)");
+
+		return false;
+	}
+
+	$item_arr = array();
+	foreach ($r AS $item) {
+		$index = $item["author-link"]."-".$item["uid"];
+		$item_arr[$index] = array("author-link" => $item["author-link"],
+						"uid" => $item["uid"],
+						"network" => $item["network"]);
+	}
+
+	// Set the "gcontact-id" in the item table and add a new gcontact entry if needed
+	foreach($item_arr AS $item) {
+		$gcontact_id = get_gcontact_id(array("url" => $item['author-link'], "network" => $item['network'],
+						"photo" => $item['author-avatar'], "name" => $item['author-name']));
+		q("UPDATE `item` SET `gcontact-id` = %d WHERE `uid` = %d AND `author-link` = '%s' AND `gcontact-id` = 0",
+			intval($gcontact_id), intval($item["uid"]), dbesc($item["author-link"]));
+	}
+	return false;
+}
+
+/**
+ * @brief Updates the "shadow" field in the item table
+ *
+ * @return bool "true" when the job is done
+ */
+function post_update_1195() {
+
+	// Was the script completed?
+	if (get_config("system", "post_update_version") >= 1195)
+		return true;
+
+	$end_id = get_config("system", "post_update_1195_end");
+	if (!$end_id) {
+		$r = q("SELECT `id` FROM `item` WHERE `uid` != 0 ORDER BY `id` DESC LIMIT 1");
+		if ($r) {
+			set_config("system", "post_update_1195_end", $r[0]["id"]);
+			$end_id = get_config("system", "post_update_1195_end");
+		}
+	}
+
+	$start_id = get_config("system", "post_update_1195_start");
+
+	$query1 = "SELECT `item`.`id` FROM `item` ";
+
+	$query2 = "INNER JOIN `item` AS `shadow` ON `item`.`uri` = `shadow`.`uri` AND `shadow`.`uid` = 0 ";
+
+	$query3 = "WHERE `item`.`uid` != 0 AND `item`.`id` >= %d AND `item`.`id` <= %d
+			AND `item`.`visible` AND NOT `item`.`private`
+			AND NOT `item`.`deleted` AND NOT `item`.`moderated`
+			AND `item`.`network` IN ('%s', '%s', '%s', '')
+			AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = ''
+			AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
+			AND `item`.`shadow` = 0";
+
+	$r = q($query1.$query2.$query3."  ORDER BY `item`.`id` LIMIT 1",
+		intval($start_id), intval($end_id),
+		dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
+	if (!$r) {
+		set_config("system", "post_update_version", 1195);
+		return true;
+	} else {
+		set_config("system", "post_update_1195_start", $r[0]["id"]);
+		$start_id = get_config("system", "post_update_1195_start");
+	}
+
+
+	$r = q($query1.$query2.$query3."  ORDER BY `item`.`id` LIMIT 10000,1",
+		intval($start_id), intval($end_id),
+		dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
+	if ($r)
+		$pos_id = $r[0]["id"];
+	else
+		$pos_id = $end_id;
+
+	logger("Progress: Start: ".$start_id." position: ".$pos_id." end: ".$end_id, LOGGER_DEBUG);
+
+	$r = q("UPDATE `item` ".$query2." SET `item`.`shadow` = `shadow`.`id` ".$query3,
+		intval($start_id), intval($pos_id),
+		dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
+}
+?>
diff --git a/include/threads.php b/include/threads.php
index 0320eaa018..21fdb0df34 100644
--- a/include/threads.php
+++ b/include/threads.php
@@ -65,13 +65,19 @@ function add_thread($itemid, $onlyshadow = false) {
 			require_once("include/Contact.php");
 
 			unset($item[0]['id']);
+			unset($item[0]['shadow']);
 			$item[0]['uid'] = 0;
 			$item[0]['origin'] = 0;
 			$item[0]['contact-id'] = get_contact($item[0]['author-link'], 0);
 			$public_shadow = item_store($item[0], false, false, true);
 
 			logger("add_thread: Stored public shadow for post ".$itemid." under id ".$public_shadow, LOGGER_DEBUG);
-		}
+		} else
+			$public_shadow = $r[0]["id"];
+
+		if ($public_shadow > 0)
+			q("UPDATE `item` SET `shadow` = %d WHERE `id` = %d", intval($public_shadow), intval($itemid));
+
 	}
 }
 
diff --git a/update.php b/update.php
index 0689aa19b3..dad94f271b 100644
--- a/update.php
+++ b/update.php
@@ -1,6 +1,6 @@
 <?php
 
-define( 'UPDATE_VERSION' , 1194 );
+define( 'UPDATE_VERSION' , 1195 );
 
 /**
  *

From 9f57425d0880cc49a09562b1b63d502463440c0a Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 3 Apr 2016 16:36:05 +0200
Subject: [PATCH 256/273] Post update ist now done.

---
 boot.php                |  2 +-
 include/dbstructure.php |  1 -
 include/items.php       |  4 ++--
 include/post_update.php | 40 ++++++++++++++++++++++++++--------------
 mod/search.php          |  5 ++---
 update.php              |  2 +-
 6 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/boot.php b/boot.php
index 13cc2aaf5b..58b4bc0983 100644
--- a/boot.php
+++ b/boot.php
@@ -38,7 +38,7 @@ define ( 'FRIENDICA_PLATFORM',     'Friendica');
 define ( 'FRIENDICA_CODENAME',     'Asparagus');
 define ( 'FRIENDICA_VERSION',      '3.5-dev' );
 define ( 'DFRN_PROTOCOL_VERSION',  '2.23'    );
-define ( 'DB_UPDATE_VERSION',      1195      );
+define ( 'DB_UPDATE_VERSION',      1194      );
 
 /**
  * @brief Constant with a HTML line break.
diff --git a/include/dbstructure.php b/include/dbstructure.php
index 33e0c7dc8c..e34e409023 100644
--- a/include/dbstructure.php
+++ b/include/dbstructure.php
@@ -783,7 +783,6 @@ function db_definition() {
 					"parent-uri" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
 					"extid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
 					"thr-parent" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
-					"shadow" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0"),
 					"created" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
 					"edited" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
 					"commented" => array("type" => "datetime", "not null" => "1", "default" => "0000-00-00 00:00:00"),
diff --git a/include/items.php b/include/items.php
index 233d72d133..4627b10ca2 100644
--- a/include/items.php
+++ b/include/items.php
@@ -707,9 +707,9 @@ function item_store($arr,$force_parent = false, $notify = false, $dontcache = fa
 	if ($arr["uid"] == 0) {
 		$arr["global"] = true;
 
-		q("UPDATE `item` SET `global` = 1 WHERE `guid` = '%s'", dbesc($arr["guid"]));
+		q("UPDATE `item` SET `global` = 1 WHERE `uri` = '%s'", dbesc($arr["uri"]));
 	}  else {
-		$isglobal = q("SELECT `global` FROM `item` WHERE `uid` = 0 AND `guid` = '%s'", dbesc($arr["guid"]));
+		$isglobal = q("SELECT `global` FROM `item` WHERE `uid` = 0 AND `uri` = '%s'", dbesc($arr["uri"]));
 
 		$arr["global"] = (count($isglobal) > 0);
 	}
diff --git a/include/post_update.php b/include/post_update.php
index 2143ac3d6f..2bdfe1f6fd 100644
--- a/include/post_update.php
+++ b/include/post_update.php
@@ -1,4 +1,8 @@
 <?php
+/**
+ * @file include/post_update.php
+ */
+
 /**
  * @brief Calls the post update functions
  */
@@ -7,7 +11,7 @@ function post_update() {
 	if (!post_update_1192())
 		return;
 
-	if (!post_update_1195())
+	if (!post_update_1194())
 		return;
 }
 
@@ -67,26 +71,30 @@ function post_update_1192() {
 }
 
 /**
- * @brief Updates the "shadow" field in the item table
+ * @brief Updates the "global" field in the item table
  *
  * @return bool "true" when the job is done
  */
-function post_update_1195() {
+function post_update_1194() {
 
 	// Was the script completed?
-	if (get_config("system", "post_update_version") >= 1195)
+	if (get_config("system", "post_update_version") >= 1194)
 		return true;
 
-	$end_id = get_config("system", "post_update_1195_end");
+	logger("Start", LOGGER_DEBUG);
+
+	$end_id = get_config("system", "post_update_1194_end");
 	if (!$end_id) {
 		$r = q("SELECT `id` FROM `item` WHERE `uid` != 0 ORDER BY `id` DESC LIMIT 1");
 		if ($r) {
-			set_config("system", "post_update_1195_end", $r[0]["id"]);
-			$end_id = get_config("system", "post_update_1195_end");
+			set_config("system", "post_update_1194_end", $r[0]["id"]);
+			$end_id = get_config("system", "post_update_1194_end");
 		}
 	}
 
-	$start_id = get_config("system", "post_update_1195_start");
+	logger("End ID: ".$end_id, LOGGER_DEBUG);
+
+	$start_id = get_config("system", "post_update_1194_start");
 
 	$query1 = "SELECT `item`.`id` FROM `item` ";
 
@@ -98,21 +106,23 @@ function post_update_1195() {
 			AND `item`.`network` IN ('%s', '%s', '%s', '')
 			AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = ''
 			AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = ''
-			AND `item`.`shadow` = 0";
+			AND NOT `item`.`global`";
 
 	$r = q($query1.$query2.$query3."  ORDER BY `item`.`id` LIMIT 1",
 		intval($start_id), intval($end_id),
 		dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
 	if (!$r) {
-		set_config("system", "post_update_version", 1195);
+		set_config("system", "post_update_version", 1194);
+		logger("Update is done", LOGGER_DEBUG);
 		return true;
 	} else {
-		set_config("system", "post_update_1195_start", $r[0]["id"]);
-		$start_id = get_config("system", "post_update_1195_start");
+		set_config("system", "post_update_1194_start", $r[0]["id"]);
+		$start_id = get_config("system", "post_update_1194_start");
 	}
 
+	logger("Start ID: ".$start_id, LOGGER_DEBUG);
 
-	$r = q($query1.$query2.$query3."  ORDER BY `item`.`id` LIMIT 10000,1",
+	$r = q($query1.$query2.$query3."  ORDER BY `item`.`id` LIMIT 1000,1",
 		intval($start_id), intval($end_id),
 		dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
 	if ($r)
@@ -122,8 +132,10 @@ function post_update_1195() {
 
 	logger("Progress: Start: ".$start_id." position: ".$pos_id." end: ".$end_id, LOGGER_DEBUG);
 
-	$r = q("UPDATE `item` ".$query2." SET `item`.`shadow` = `shadow`.`id` ".$query3,
+	$r = q("UPDATE `item` ".$query2." SET `item`.`global` = 1 ".$query3,
 		intval($start_id), intval($pos_id),
 		dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS));
+
+	logger("Done", LOGGER_DEBUG);
 }
 ?>
diff --git a/mod/search.php b/mod/search.php
index 1776a92552..790f577ba6 100644
--- a/mod/search.php
+++ b/mod/search.php
@@ -217,11 +217,10 @@ function search_content(&$a) {
 			FROM `item`
 				INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
 			WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
-				AND (`item`.`uid` = 0 OR (`item`.`uid` = %s AND (`item`.`private` OR NOT `item`.`network` IN ('%s', '%s', '%s'))))
+				AND (`item`.`uid` = 0 OR (`item`.`uid` = %s AND NOT `item`.`global`))
 				$sql_extra
 			GROUP BY `item`.`uri` ORDER BY `item`.`id` DESC LIMIT %d , %d ",
-				intval(local_user()), dbesc(NETWORK_DFRN), dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DIASPORA),
-				intval($a->pager['start']), intval($a->pager['itemspage']));
+				intval(local_user()), intval($a->pager['start']), intval($a->pager['itemspage']));
 	}
 
 	if(! count($r)) {
diff --git a/update.php b/update.php
index dad94f271b..0689aa19b3 100644
--- a/update.php
+++ b/update.php
@@ -1,6 +1,6 @@
 <?php
 
-define( 'UPDATE_VERSION' , 1195 );
+define( 'UPDATE_VERSION' , 1194 );
 
 /**
  *

From f192767d7ad1eace0a9f5e33ba8d2625782ad562 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 3 Apr 2016 16:38:32 +0200
Subject: [PATCH 257/273] Some reverted stuff

---
 include/threads.php | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/include/threads.php b/include/threads.php
index 21fdb0df34..0320eaa018 100644
--- a/include/threads.php
+++ b/include/threads.php
@@ -65,19 +65,13 @@ function add_thread($itemid, $onlyshadow = false) {
 			require_once("include/Contact.php");
 
 			unset($item[0]['id']);
-			unset($item[0]['shadow']);
 			$item[0]['uid'] = 0;
 			$item[0]['origin'] = 0;
 			$item[0]['contact-id'] = get_contact($item[0]['author-link'], 0);
 			$public_shadow = item_store($item[0], false, false, true);
 
 			logger("add_thread: Stored public shadow for post ".$itemid." under id ".$public_shadow, LOGGER_DEBUG);
-		} else
-			$public_shadow = $r[0]["id"];
-
-		if ($public_shadow > 0)
-			q("UPDATE `item` SET `shadow` = %d WHERE `id` = %d", intval($public_shadow), intval($itemid));
-
+		}
 	}
 }
 

From 94e8139c7e5bd90d814e18c6a7ce2b4d44008100 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 3 Apr 2016 18:18:36 +0200
Subject: [PATCH 258/273] issue 2247: Update more fields when relocation the
 server

---
 mod/admin.php | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/mod/admin.php b/mod/admin.php
index 28c8ed15c2..2fc9c48a78 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -492,6 +492,10 @@ function admin_page_site_post(&$a) {
 
 		$old_url = $a->get_baseurl(true);
 
+		// Generate host names for relocation the addresses in the format user@address.tld
+		$new_host = str_replace("http://", "@", normalise_link($new_url));
+		$old_host = str_replace("http://", "@", normalise_link($old_url));
+
 		function update_table($table_name, $fields, $old_url, $new_url) {
 			global $db, $a;
 
@@ -516,11 +520,16 @@ function admin_page_site_post(&$a) {
 		}
 
 		// update tables
+		// update profile links in the format "http://server.tld"
 		update_table("profile", array('photo', 'thumb'), $old_url, $new_url);
 		update_table("term", array('url'), $old_url, $new_url);
-		update_table("contact", array('photo','thumb','micro','url','nurl','request','notify','poll','confirm','poco'), $old_url, $new_url);
-		update_table("gcontact", array('photo','url','nurl','server_url'), $old_url, $new_url);
-		update_table("item", array('owner-link','owner-avatar','author-name','author-link','author-avatar','body','plink','tag'), $old_url, $new_url);
+		update_table("contact", array('photo','thumb','micro','url','nurl','alias','request','notify','poll','confirm','poco', 'avatar'), $old_url, $new_url);
+		update_table("gcontact", array('url','nurl','photo','server_url','notify','alias'), $old_url, $new_url);
+		update_table("item", array('owner-link','owner-avatar','author-link','author-avatar','body','plink','tag'), $old_url, $new_url);
+
+		// update profile addresses in the format "user@server.tld"
+		update_table("contact", array('addr'), $old_host, $new_host);
+		update_table("gcontact", array('connect','addr'), $old_host, $new_host);
 
 		// update config
 		$a->set_baseurl($new_url);

From 3fdaafd54a8a24c5f265eb0dcdc218a51901a4eb Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 3 Apr 2016 18:49:41 +0200
Subject: [PATCH 259/273] Some more documentation

---
 include/cron.php | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/cron.php b/include/cron.php
index 4eb76f1ce2..00dd500704 100644
--- a/include/cron.php
+++ b/include/cron.php
@@ -107,7 +107,8 @@ function cron_run(&$argv, &$argc){
 	// Check every conversation
 	ostatus::check_conversations(false);
 
-	// Do post update functions
+	// Call possible post update functions
+	// see include/post_update.php for more details
 	post_update();
 
 	// update nodeinfo data

From 1f61efc7fef9196aaba9082d6b0e92e371da088c Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 3 Apr 2016 19:29:35 +0200
Subject: [PATCH 260/273] Scrape: Changed detection for the profile link

---
 include/Scrape.php | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/Scrape.php b/include/Scrape.php
index ac95c0d5d3..68926a997e 100644
--- a/include/Scrape.php
+++ b/include/Scrape.php
@@ -705,10 +705,14 @@ function probe_url($url, $mode = PROBE_NORMAL, $level = 1) {
 					if (($vcard["nick"] == "") AND ($data["header"]["author-nick"] != ""))
 						$vcard["nick"] = $data["header"]["author-nick"];
 
-					if (($network == NETWORK_OSTATUS) AND ($data["header"]["author-id"] != ""))
-						$alias = $data["header"]["author-id"];
+					if ($network == NETWORK_OSTATUS) {
+						if ($data["header"]["author-id"] != "")
+							$alias = $data["header"]["author-id"];
 
-					if(!$profile AND ($data["header"]["author-link"] != "") AND !in_array($network, array("", NETWORK_FEED)))
+						if ($data["header"]["author-link"] != "")
+							$profile = $data["header"]["author-link"];
+
+					} elseif(!$profile AND ($data["header"]["author-link"] != "") AND !in_array($network, array("", NETWORK_FEED)))
 						$profile = $data["header"]["author-link"];
 				}
 			}

From a88d950c33ce27f5fe7e5c1183e2daa4a21c6453 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Sun, 3 Apr 2016 20:55:39 +0200
Subject: [PATCH 261/273] set language in HTML header to selected UI language

---
 view/default.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/view/default.php b/view/default.php
index 121d5212c6..df9adbc392 100644
--- a/view/default.php
+++ b/view/default.php
@@ -1,5 +1,5 @@
 <!DOCTYPE html >
-<html itemscope itemtype="http://schema.org/Blog" />
+<html itemscope itemtype="http://schema.org/Blog" lang="<?php echo $lang; ?>">
 <head>
   <title><?php if(x($page,'title')) echo $page['title'] ?></title>
   <script>var baseurl="<?php echo $a->get_baseurl() ?>";</script>

From d9b6355bb8d67bd22bf9dbf3cfb6036b8d8f5af9 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Sun, 3 Apr 2016 21:00:18 +0200
Subject: [PATCH 262/273] added lang info to frost themes

---
 view/theme/frost-mobile/default.php | 2 +-
 view/theme/frost/default.php        | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/view/theme/frost-mobile/default.php b/view/theme/frost-mobile/default.php
index 3a424ad5f4..332291ca92 100644
--- a/view/theme/frost-mobile/default.php
+++ b/view/theme/frost-mobile/default.php
@@ -1,5 +1,5 @@
 <!DOCTYPE html >
-<html>
+<html lang="<?php echo $lang; ?>">
 <head>
   <title><?php if(x($page,'title')) echo $page['title'] ?></title>
   <script>var baseurl="<?php echo $a->get_baseurl() ?>";</script>
diff --git a/view/theme/frost/default.php b/view/theme/frost/default.php
index c379955f79..c67bdcf20e 100644
--- a/view/theme/frost/default.php
+++ b/view/theme/frost/default.php
@@ -1,5 +1,5 @@
 <!DOCTYPE html >
-<html>
+<html lang="<?php echo $lang; ?>">
 <head>
   <title><?php if(x($page,'title')) echo $page['title'] ?></title>
   <script>var baseurl="<?php echo $a->get_baseurl() ?>";</script>

From 1ee405c9c3d9e6ae805df34a2b57b80d0428e8cb Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Mon, 4 Apr 2016 08:10:27 +0200
Subject: [PATCH 263/273] added aria describedby elements refering to field
 help to the input templates

---
 view/templates/field_checkbox.tpl    | 4 ++--
 view/templates/field_combobox.tpl    | 4 ++--
 view/templates/field_input.tpl       | 4 ++--
 view/templates/field_intcheckbox.tpl | 4 ++--
 view/templates/field_openid.tpl      | 4 ++--
 view/templates/field_password.tpl    | 4 ++--
 view/templates/field_radio.tpl       | 4 ++--
 view/templates/field_richtext.tpl    | 4 ++--
 view/templates/field_select.tpl      | 4 ++--
 view/templates/field_select_raw.tpl  | 4 ++--
 view/templates/field_textarea.tpl    | 4 ++--
 view/templates/field_themeselect.tpl | 4 ++--
 view/templates/field_yesno.tpl       | 4 ++--
 view/templates/login.tpl             | 3 ++-
 14 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/view/templates/field_checkbox.tpl b/view/templates/field_checkbox.tpl
index e476c07d72..06796376b6 100644
--- a/view/templates/field_checkbox.tpl
+++ b/view/templates/field_checkbox.tpl
@@ -1,5 +1,5 @@
 	<div class='field checkbox' id='div_id_{{$field.0}}'>
 		<label for='id_{{$field.0}}'>{{$field.1}}</label>
-		<input type="checkbox" name='{{$field.0}}' id='id_{{$field.0}}' value="1" {{if $field.2}}checked="checked"{{/if}}>
-		<span class='field_help'>{{$field.3}}</span>
+		<input type="checkbox" name='{{$field.0}}' id='id_{{$field.0}}' aria-describedby='{{$field.0}}_tip' value="1" {{if $field.2}}checked="checked"{{/if}}>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 	</div>
diff --git a/view/templates/field_combobox.tpl b/view/templates/field_combobox.tpl
index a2f7c3f27e..4586550166 100644
--- a/view/templates/field_combobox.tpl
+++ b/view/templates/field_combobox.tpl
@@ -7,12 +7,12 @@
 		   {{foreach $field.4 as $opt=>$val}}<option value="{{$val|escape:'html'}}">{{/foreach}}
 		</datalist> *}}
 		
-		<input id="id_{{$field.0}}" type="text" value="{{$field.2}}">
+		<input id="id_{{$field.0}}" type="text" value="{{$field.2}}" aria-describedby='{{$field.0}}_tip'>
 		<select id="select_{{$field.0}}" onChange="$('#id_{{$field.0}}').val($(this).val())">
 			<option value="">{{$field.5}}</option>
 			{{foreach $field.4 as $opt=>$val}}<option value="{{$val|escape:'html'}}">{{$val}}</option>{{/foreach}}
 		</select>
 		
-		<span class='field_help'>{{$field.3}}</span>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 	</div>
 
diff --git a/view/templates/field_input.tpl b/view/templates/field_input.tpl
index 6a3328c5cc..8db8e545f3 100644
--- a/view/templates/field_input.tpl
+++ b/view/templates/field_input.tpl
@@ -1,6 +1,6 @@
 	
 	<div class='field input' id='wrapper_{{$field.0}}'>
 		<label for='id_{{$field.0}}'>{{$field.1}}</label>
-		<input{{if $field.6 eq 'email'}} type='email'{{elseif $field.6 eq 'url'}} type='url'{{/if}} name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.2|escape:'html'}}"{{if $field.4 eq 'required'}} required{{/if}}{{if $field.5 eq 'autofocus'}} autofocus{{/if}}>
-		<span class='field_help'>{{$field.3}}</span>
+		<input{{if $field.6 eq 'email'}} type='email'{{elseif $field.6 eq 'url'}} type='url'{{/if}} name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.2|escape:'html'}}"{{if $field.4 eq 'required'}} required{{/if}}{{if $field.5 eq 'autofocus'}} autofocus{{/if}} aria-describedby='{{$field.0}}_tip'>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 	</div>
diff --git a/view/templates/field_intcheckbox.tpl b/view/templates/field_intcheckbox.tpl
index 2f3c27d920..73bdf60417 100644
--- a/view/templates/field_intcheckbox.tpl
+++ b/view/templates/field_intcheckbox.tpl
@@ -2,6 +2,6 @@
 	
 	<div class='field checkbox'>
 		<label for='id_{{$field.0}}'>{{$field.1}}</label>
-		<input type="checkbox" name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.3|escape:'html'}}" {{if $field.2}}checked="true"{{/if}}>
-		<span class='field_help'>{{$field.4}}</span>
+		<input type="checkbox" name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.3|escape:'html'}}" {{if $field.2}}checked="true"{{/if}} aria-describedby='{{$field.0}}_tip'>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.4}}</span>
 	</div>
diff --git a/view/templates/field_openid.tpl b/view/templates/field_openid.tpl
index e5f236c679..25773189f8 100644
--- a/view/templates/field_openid.tpl
+++ b/view/templates/field_openid.tpl
@@ -1,6 +1,6 @@
 	
 	<div class='field input openid' id='wrapper_{{$field.0}}'>
 		<label for='id_{{$field.0}}'>{{$field.1}}</label>
-		<input name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.2|escape:'html'}}">
-		<span class='field_help'>{{$field.3}}</span>
+		<input name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.2|escape:'html'}}" aria-describedby='{{$field.0}}_tip'>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 	</div>
diff --git a/view/templates/field_password.tpl b/view/templates/field_password.tpl
index 8a9f0dc330..333ce67c38 100644
--- a/view/templates/field_password.tpl
+++ b/view/templates/field_password.tpl
@@ -1,6 +1,6 @@
 	
 	<div class='field password' id='wrapper_{{$field.0}}'>
 		<label for='id_{{$field.0}}'>{{$field.1}}</label>
-		<input type='password' name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.2|escape:'html'}}"{{if $field.4 eq 'required'}} required{{/if}}{{if $field.5 eq 'autofocus'}} autofocus{{/if}}>
-		<span class='field_help'>{{$field.3}}</span>
+		<input type='password' name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.2|escape:'html'}}"{{if $field.4 eq 'required'}} required{{/if}}{{if $field.5 eq 'autofocus'}} autofocus{{/if}} aria-describedby='{{$field.0}}_tip'>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 	</div>
diff --git a/view/templates/field_radio.tpl b/view/templates/field_radio.tpl
index 86cc8fc47e..ef8ec4f9a6 100644
--- a/view/templates/field_radio.tpl
+++ b/view/templates/field_radio.tpl
@@ -2,6 +2,6 @@
 	
 	<div class='field radio'>
 		<label for='id_{{$field.0}}_{{$field.2}}'>{{$field.1}}</label>
-		<input type="radio" name='{{$field.0}}' id='id_{{$field.0}}_{{$field.2}}' value="{{$field.2|escape:'html'}}" {{if $field.4}}checked="true"{{/if}}>
-		<span class='field_help'>{{$field.3}}</span>
+		<input type="radio" name='{{$field.0}}' id='id_{{$field.0}}_{{$field.2}}' value="{{$field.2|escape:'html'}}" {{if $field.4}}checked="true"{{/if}} aria-describedby={{$field.0}}_tip'>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 	</div>
diff --git a/view/templates/field_richtext.tpl b/view/templates/field_richtext.tpl
index f0ea50b58b..67553bb95a 100644
--- a/view/templates/field_richtext.tpl
+++ b/view/templates/field_richtext.tpl
@@ -2,6 +2,6 @@
 	
 	<div class='field richtext'>
 		<label for='id_{{$field.0}}'>{{$field.1}}</label>
-		<textarea name='{{$field.0}}' id='id_{{$field.0}}' class="fieldRichtext">{{$field.2}}</textarea>
-		<span class='field_help'>{{$field.3}}</span>
+		<textarea name='{{$field.0}}' id='id_{{$field.0}}' class="fieldRichtext" aria-describedby='{{$field.0}}_tip'>{{$field.2}}</textarea>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 	</div>
diff --git a/view/templates/field_select.tpl b/view/templates/field_select.tpl
index 4fbbd4beb0..2d037439df 100644
--- a/view/templates/field_select.tpl
+++ b/view/templates/field_select.tpl
@@ -2,8 +2,8 @@
 	
 	<div class='field select'>
 		<label for='id_{{$field.0}}'>{{$field.1}}</label>
-		<select name='{{$field.0}}' id='id_{{$field.0}}'>
+		<select name='{{$field.0}}' id='id_{{$field.0}}' aria-describedby='{{$field.0}}_tip'>
 			{{foreach $field.4 as $opt=>$val}}<option value="{{$opt|escape:'html'}}" {{if $opt==$field.2}}selected="selected"{{/if}}>{{$val}}</option>{{/foreach}}
 		</select>
-		<span class='field_help'>{{$field.3}}</span>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 	</div>
diff --git a/view/templates/field_select_raw.tpl b/view/templates/field_select_raw.tpl
index 02308e2f4b..4c826a0427 100644
--- a/view/templates/field_select_raw.tpl
+++ b/view/templates/field_select_raw.tpl
@@ -2,8 +2,8 @@
 	
 	<div class='field select'>
 		<label for='id_{{$field.0}}'>{{$field.1}}</label>
-		<select name='{{$field.0}}' id='id_{{$field.0}}'>
+		<select name='{{$field.0}}' id='id_{{$field.0}}' aria-describedby='{{$field.0}}_tip'>
 			{{$field.4}}
 		</select>
-		<span class='field_help'>{{$field.3}}</span>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 	</div>
diff --git a/view/templates/field_textarea.tpl b/view/templates/field_textarea.tpl
index 29d3b7a7c6..c37537d6ec 100644
--- a/view/templates/field_textarea.tpl
+++ b/view/templates/field_textarea.tpl
@@ -2,6 +2,6 @@
 	
 	<div class='field textarea'>
 		<label for='id_{{$field.0}}'>{{$field.1}}</label>
-		<textarea name='{{$field.0}}' id='id_{{$field.0}}'>{{$field.2}}</textarea>
-		<span class='field_help'>{{$field.3}}</span>
+		<textarea name='{{$field.0}}' id='id_{{$field.0}}' aria-describedby='{{$field.0}}_tip'>{{$field.2}}</textarea>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 	</div>
diff --git a/view/templates/field_themeselect.tpl b/view/templates/field_themeselect.tpl
index edd25dbe0f..51f6057ae3 100644
--- a/view/templates/field_themeselect.tpl
+++ b/view/templates/field_themeselect.tpl
@@ -2,9 +2,9 @@
 	{{if $field.5}}<script>$(function(){ previewTheme($("#id_{{$field.0}}")[0]); });</script>{{/if}}
 	<div class='field select'>
 		<label for='id_{{$field.0}}'>{{$field.1}}</label>
-		<select name='{{$field.0}}' id='id_{{$field.0}}' {{if $field.5}}onchange="previewTheme(this);"{{/if}} >
+		<select name='{{$field.0}}' id='id_{{$field.0}}' {{if $field.5}}onchange="previewTheme(this);"{{/if}} aria-describedby='{{$field.0}}_tip'>
 			{{foreach $field.4 as $opt=>$val}}<option value="{{$opt|escape:'html'}}" {{if $opt==$field.2}}selected="selected"{{/if}}>{{$val}}</option>{{/foreach}}
 		</select>
-		<span class='field_help'>{{$field.3}}</span>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 		{{if $field.5}}<div id="theme-preview"></div>{{/if}}
 	</div>
diff --git a/view/templates/field_yesno.tpl b/view/templates/field_yesno.tpl
index de70c5ae6d..155d0488b3 100644
--- a/view/templates/field_yesno.tpl
+++ b/view/templates/field_yesno.tpl
@@ -2,7 +2,7 @@
 	<div class='field yesno'>
 		<label for='id_{{$field.0}}'>{{$field.1}}</label>
 		<div class='onoff' id="id_{{$field.0}}_onoff">
-			<input  type="hidden" name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.2|escape:'html'}}">
+			<input  type="hidden" name='{{$field.0}}' id='id_{{$field.0}}' value="{{$field.2|escape:'html'}}" aria-describedby='{{$field.0}}_tip'>
 			<a href="#" class='off'>
 				{{if $field.4}}{{$field.4.0}}{{else}}OFF{{/if}}
 			</a>
@@ -10,5 +10,5 @@
 				{{if $field.4}}{{$field.4.1}}{{else}}ON{{/if}}
 			</a>
 		</div>
-		<span class='field_help'>{{$field.3}}</span>
+		<span class='field_help' role='tooltip' id='{{$field.0}}_tip'>{{$field.3}}</span>
 	</div>
diff --git a/view/templates/login.tpl b/view/templates/login.tpl
index 37d105c087..caa2e74a4b 100644
--- a/view/templates/login.tpl
+++ b/view/templates/login.tpl
@@ -1,6 +1,7 @@
 
 
 <form action="{{$dest_url}}" method="post" >
+<fieldset>
 	<input type="hidden" name="auth-params" value="login" />
 
 	<div id="login_standard">
@@ -29,7 +30,7 @@
 		<input type="hidden" name="{{$k}}" value="{{$v|escape:'html'}}" />
 	{{/foreach}}
 	
-	
+</fieldset>
 </form>
 
 

From 952f8514a5f410755a8df1b83655e0d9b6b1cf87 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 5 Apr 2016 23:28:33 +0200
Subject: [PATCH 264/273] "remember me" in session does work now

---
 include/auth.php    | 39 ++++++++-------------------------------
 include/session.php |  1 -
 2 files changed, 8 insertions(+), 32 deletions(-)

diff --git a/include/auth.php b/include/auth.php
index a5b6432fff..4abff19710 100644
--- a/include/auth.php
+++ b/include/auth.php
@@ -5,35 +5,14 @@ require_once('include/security.php');
 require_once('include/datetime.php');
 
 function nuke_session() {
-	if (get_config('system', 'disable_database_session')) {
-		session_unset();
-		return;
-	}
 
 	new_cookie(0); // make sure cookie is deleted on browser close, as a security measure
-
-	unset($_SESSION['authenticated']);
-	unset($_SESSION['uid']);
-	unset($_SESSION['visitor_id']);
-	unset($_SESSION['administrator']);
-	unset($_SESSION['cid']);
-	unset($_SESSION['theme']);
-	unset($_SESSION['mobile-theme']);
-	unset($_SESSION['page_flags']);
-	unset($_SESSION['submanage']);
-	unset($_SESSION['my_url']);
-	unset($_SESSION['my_address']);
-	unset($_SESSION['addr']);
-	unset($_SESSION['return_url']);
-
+	session_unset();
 }
 
 
 // login/logout
 
-
-
-
 if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-params'))) || ($_POST['auth-params'] !== 'login'))) {
 
 	if(((x($_POST,'auth-params')) && ($_POST['auth-params'] === 'logout')) || ($a->module === 'logout')) {
@@ -41,6 +20,7 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p
 		// process logout request
 		call_hooks("logging_out");
 		nuke_session();
+		new_cookie(-1);
 		info( t('Logged out.') . EOL);
 		goaway(z_root());
 	}
@@ -90,8 +70,7 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p
 		}
 		authenticate_success($r[0], false, false, $login_refresh);
 	}
-}
-else {
+} else {
 
 	if(isset($_SESSION)) {
 		nuke_session();
@@ -209,13 +188,11 @@ else {
 }
 
 function new_cookie($time) {
-	if (!get_config('system', 'disable_database_session'))
-		$old_sid = session_id();
 
-	session_set_cookie_params($time);
+	if ($time != 0)
+		$time = $time + time();
 
-	if (!get_config('system', 'disable_database_session')) {
-		session_regenerate_id(false);
-		q("UPDATE session SET sid = '%s' WHERE sid = '%s'", dbesc(session_id()), dbesc($old_sid));
-	}
+	$params = session_get_cookie_params();
+	setcookie(session_name(), session_id(), $time, $params['path'], $params['domain'], $params['secure'], isset($params['httponly']));
+	return;
 }
diff --git a/include/session.php b/include/session.php
index 12551efc42..8f9d64606c 100644
--- a/include/session.php
+++ b/include/session.php
@@ -69,7 +69,6 @@ function ref_session_destroy ($id) {
 if(! function_exists('ref_session_gc')) {
 function ref_session_gc($expire) {
 	q("DELETE FROM `session` WHERE `expire` < %d", dbesc(time()));
-	//q("OPTIMIZE TABLE `sess_data`");
 	return true;
 }}
 

From 5df20fda119b8f178fd41002074fbb7bef87df7d Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Wed, 6 Apr 2016 20:13:34 +0200
Subject: [PATCH 265/273] Issue 2241: added language selector to the admin
 wizard

---
 mod/install.php                     | 5 +++++
 view/templates/htconfig.tpl         | 4 ++++
 view/templates/install_settings.tpl | 1 +
 3 files changed, 10 insertions(+)

diff --git a/mod/install.php b/mod/install.php
index 8434b38e38..7013070764 100755
--- a/mod/install.php
+++ b/mod/install.php
@@ -77,6 +77,7 @@ function install_post(&$a) {
 			$dbdata = notags(trim($_POST['dbdata']));
 			$phpath = notags(trim($_POST['phpath']));
 			$timezone = notags(trim($_POST['timezone']));
+            $language = notags(trim($_POST['language']));
 			$adminmail = notags(trim($_POST['adminmail']));
 
 			// connect to db
@@ -89,6 +90,7 @@ function install_post(&$a) {
 				'$dbpass' => $dbpass,
 				'$dbdata' => $dbdata,
 				'$timezone' => $timezone,
+                '$language' => $language,
 				'$urlpath' => $urlpath,
 				'$phpath' => $phpath,
 				'$adminmail' => $adminmail
@@ -273,6 +275,8 @@ function install_content(&$a) {
 
 			$adminmail = notags(trim($_POST['adminmail']));
 			$timezone = ((x($_POST,'timezone')) ? ($_POST['timezone']) : 'America/Los_Angeles');
+            /* Installed langs */
+            $lang_choices = get_avaiable_languages();
 
 			$tpl = get_markup_template('install_settings.tpl');
 			$o .= replace_macros($tpl, array(
@@ -292,6 +296,7 @@ function install_content(&$a) {
 
 				'$timezone' => field_timezone('timezone', t('Please select a default timezone for your website'), $timezone, ''),
 
+                '$language' => array('language', t('System Language:'), $language, t('Set the default language for your Friendica installation interface and to send emails.'), $lang_choices),
 				'$baseurl' => $a->get_baseurl(),
 
 
diff --git a/view/templates/htconfig.tpl b/view/templates/htconfig.tpl
index 6b3bda6173..971bb50482 100644
--- a/view/templates/htconfig.tpl
+++ b/view/templates/htconfig.tpl
@@ -20,6 +20,10 @@ $a->path = '{{$urlpath}}';
 
 $default_timezone = '{{$timezone}}';
 
+// Default system language
+
+$a->config['system']['language'] = '{{$language}}';
+
 // What is your site name?
 
 $a->config['sitename'] = "My Friend Network";
diff --git a/view/templates/install_settings.tpl b/view/templates/install_settings.tpl
index 8d6823f114..5584e14365 100644
--- a/view/templates/install_settings.tpl
+++ b/view/templates/install_settings.tpl
@@ -19,6 +19,7 @@
 
 {{include file="field_input.tpl" field=$adminmail}}
 {{$timezone}}
+{{include file="field_select.tpl" field=$language}}
 
 <input id="install-submit" type="submit" name="submit" value="{{$submit|escape:'html'}}" /> 
 

From a28372c03232ac2d5b9f2f37e39ec865143ca785 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Wed, 6 Apr 2016 20:18:33 +0200
Subject: [PATCH 266/273] intendation...

---
 mod/install.php | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/mod/install.php b/mod/install.php
index 7013070764..4ad851564c 100755
--- a/mod/install.php
+++ b/mod/install.php
@@ -77,7 +77,7 @@ function install_post(&$a) {
 			$dbdata = notags(trim($_POST['dbdata']));
 			$phpath = notags(trim($_POST['phpath']));
 			$timezone = notags(trim($_POST['timezone']));
-            $language = notags(trim($_POST['language']));
+			$language = notags(trim($_POST['language']));
 			$adminmail = notags(trim($_POST['adminmail']));
 
 			// connect to db
@@ -90,7 +90,7 @@ function install_post(&$a) {
 				'$dbpass' => $dbpass,
 				'$dbdata' => $dbdata,
 				'$timezone' => $timezone,
-                '$language' => $language,
+				'$language' => $language,
 				'$urlpath' => $urlpath,
 				'$phpath' => $phpath,
 				'$adminmail' => $adminmail
@@ -275,8 +275,8 @@ function install_content(&$a) {
 
 			$adminmail = notags(trim($_POST['adminmail']));
 			$timezone = ((x($_POST,'timezone')) ? ($_POST['timezone']) : 'America/Los_Angeles');
-            /* Installed langs */
-            $lang_choices = get_avaiable_languages();
+			/* Installed langs */
+			$lang_choices = get_avaiable_languages();
 
 			$tpl = get_markup_template('install_settings.tpl');
 			$o .= replace_macros($tpl, array(
@@ -295,8 +295,7 @@ function install_content(&$a) {
 
 
 				'$timezone' => field_timezone('timezone', t('Please select a default timezone for your website'), $timezone, ''),
-
-                '$language' => array('language', t('System Language:'), $language, t('Set the default language for your Friendica installation interface and to send emails.'), $lang_choices),
+				'$language' => array('language', t('System Language:'), $language, t('Set the default language for your Friendica installation interface and to send emails.'), $lang_choices),
 				'$baseurl' => $a->get_baseurl(),
 
 

From ac9d3922640d3193e42837e3f2d3e5bfd4e87a23 Mon Sep 17 00:00:00 2001
From: Tobias Diekershoff <tobias.diekershoff@gmx.net>
Date: Wed, 6 Apr 2016 20:21:41 +0200
Subject: [PATCH 267/273] make en the default language

---
 mod/install.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mod/install.php b/mod/install.php
index 4ad851564c..b1c2010eef 100755
--- a/mod/install.php
+++ b/mod/install.php
@@ -295,7 +295,7 @@ function install_content(&$a) {
 
 
 				'$timezone' => field_timezone('timezone', t('Please select a default timezone for your website'), $timezone, ''),
-				'$language' => array('language', t('System Language:'), $language, t('Set the default language for your Friendica installation interface and to send emails.'), $lang_choices),
+				'$language' => array('language', t('System Language:'), 'en', t('Set the default language for your Friendica installation interface and to send emails.'), $lang_choices),
 				'$baseurl' => $a->get_baseurl(),
 
 

From a3c79d2007884b2057db6279be011e2db6b6cdbe Mon Sep 17 00:00:00 2001
From: rabuzarus <rabuzarus@t-online.de>
Date: Thu, 7 Apr 2016 14:43:56 +0200
Subject: [PATCH 268/273] Update ForumManager.php

fix some doxygen description
---
 include/ForumManager.php | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/ForumManager.php b/include/ForumManager.php
index 49417d1831..fe12b45525 100644
--- a/include/ForumManager.php
+++ b/include/ForumManager.php
@@ -1,12 +1,12 @@
 <?php
 
 /**
- * @file include/forum.php
- * @brief Functions related to forum functionality *
+ * @file include/ForumManager.php
+ * @brief ForumManager class with it's methods related to forum functionality *
  */
 
 /**
- * @brief This class handles functions related to the forum functionality
+ * @brief This class handles metheods related to the forum functionality
  */
 class ForumManager {
 
@@ -187,4 +187,4 @@ class ForumManager {
 		return $r;
 	}
 
-}
\ No newline at end of file
+}

From d5bf386cf74fdb928ffe022344d2544363a04bf3 Mon Sep 17 00:00:00 2001
From: rabuzarus <rabuzarus@t-online.de>
Date: Thu, 7 Apr 2016 16:58:26 +0200
Subject: [PATCH 269/273] Update ForumManager.php - small correction

---
 include/ForumManager.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/ForumManager.php b/include/ForumManager.php
index fe12b45525..7b5fb1c2f6 100644
--- a/include/ForumManager.php
+++ b/include/ForumManager.php
@@ -2,7 +2,7 @@
 
 /**
  * @file include/ForumManager.php
- * @brief ForumManager class with it's methods related to forum functionality *
+ * @brief ForumManager class with its methods related to forum functionality *
  */
 
 /**

From 34dc23b87115b34f1322a8f9c59dddc719bff121 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sat, 9 Apr 2016 22:44:32 +0200
Subject: [PATCH 270/273] API: Improvement for Twidere/Conversation call
 improved

---
 include/api.php | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/include/api.php b/include/api.php
index a494e3cdd9..8d74a4612d 100644
--- a/include/api.php
+++ b/include/api.php
@@ -1524,15 +1524,21 @@
 		if ($max_id > 0)
 			$sql_extra = ' AND `item`.`id` <= '.intval($max_id);
 
+		// Not sure why this query was so complicated. We should keep it here for a while,
+		// just to make sure that we really don't need it.
+		//	FROM `item` INNER JOIN (SELECT `uri`,`parent` FROM `item` WHERE `id` = %d) AS `temp1`
+		//	ON (`item`.`thr-parent` = `temp1`.`uri` AND `item`.`parent` = `temp1`.`parent`)
+
 		$r = q("SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
 			`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
 			`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
 			`contact`.`id` AS `cid`, `contact`.`uid` AS `contact-uid`
-			FROM `item` INNER JOIN (SELECT `uri`,`parent` FROM `item` WHERE `id` = %d) AS `temp1`
-			ON (`item`.`thr-parent` = `temp1`.`uri` AND `item`.`parent` = `temp1`.`parent`), `contact`
-			WHERE `item`.`visible` = 1 and `item`.`moderated` = 0 AND `item`.`deleted` = 0
-			AND `item`.`uid` = %d AND `item`.`verb` = '%s' AND `contact`.`id` = `item`.`contact-id`
-			AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
+			FROM `item`
+			INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
+			WHERE `item`.`parent` = %d AND `item`.`visible`
+			AND NOT `item`.`moderated` AND NOT `item`.`deleted`
+			AND `item`.`uid` = %d AND `item`.`verb` = '%s'
+			AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
 			AND `item`.`id`>%d $sql_extra
 			ORDER BY `item`.`id` DESC LIMIT %d ,%d",
 			intval($id), intval(api_user()),
@@ -2059,6 +2065,10 @@
 
 		$statushtml = trim(bbcode($body, false, false));
 
+		$search = array("<br>", "<blockquote>", "</blockquote>");
+		$replace = array("<br>\n", "\n<blockquote>", "</blockquote>\n");
+		$statushtml = str_replace($search, $replace, $statushtml);
+
 		if ($item['title'] != "")
 			$statushtml = "<h4>".bbcode($item['title'])."</h4>\n".$statushtml;
 

From 90f5cb23f211c951b49914a0d4d0a7c1090d16f6 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Sun, 10 Apr 2016 13:36:26 +0200
Subject: [PATCH 271/273] fbrowser: Take the picture as that mostly fits

---
 mod/fbrowser.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mod/fbrowser.php b/mod/fbrowser.php
index 5836efbe52..110ca9585c 100644
--- a/mod/fbrowser.php
+++ b/mod/fbrowser.php
@@ -74,9 +74,9 @@ function fbrowser_content($a){
 					$filename_e = $rr['filename'];
 				}
 
-				// Take the second largest picture as preview
-				$p = q("SELECT `scale` FROM `photo` WHERE `resource-id` = '%s' AND `scale` > %d ORDER BY `resource-id`, `scale` LIMIT 1",
-					dbesc($rr['resource-id']), intval($rr['hiq']));
+				// Take the largest picture that is smaller or equal 640 pixels
+				$p = q("SELECT `scale` FROM `photo` WHERE `resource-id` = '%s' AND `height` <= 640 AND `width` <= 640 ORDER BY `resource-id`, `scale` LIMIT 1",
+					dbesc($rr['resource-id']));
 				if ($p)
 					$scale = $p[0]["scale"];
 				else

From 018b3ed25f8d8c1f0c9e54261777070a4ff23198 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Tue, 12 Apr 2016 22:53:54 +0200
Subject: [PATCH 272/273] API: Just some more elements where Twidere has
 problems ...

---
 include/api.php | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/include/api.php b/include/api.php
index 8d74a4612d..305a86ca13 100644
--- a/include/api.php
+++ b/include/api.php
@@ -2065,8 +2065,14 @@
 
 		$statushtml = trim(bbcode($body, false, false));
 
-		$search = array("<br>", "<blockquote>", "</blockquote>");
-		$replace = array("<br>\n", "\n<blockquote>", "</blockquote>\n");
+		$search = array("<br>", "<blockquote>", "</blockquote>",
+				"<h1>", "</h1>", "<h2>", "</h2>",
+				"<h3>", "</h3>", "<h4>", "</h4>",
+				"<h5>", "</h5>", "<h6>", "</h6>");
+		$replace = array("<br>\n", "\n<blockquote>", "</blockquote>\n",
+				"\n<h1>", "</h1>\n", "\n<h2>", "</h2>\n",
+				"\n<h3>", "</h3>\n", "\n<h4>", "</h4>\n",
+				"\n<h5>", "</h5>\n", "\n<h6>", "</h6>\n");
 		$statushtml = str_replace($search, $replace, $statushtml);
 
 		if ($item['title'] != "")

From 71caebdae09f74fd6f702887aba712e220820ef7 Mon Sep 17 00:00:00 2001
From: Michael Vogel <icarus@dabo.de>
Date: Wed, 13 Apr 2016 07:00:36 +0200
Subject: [PATCH 273/273] Bugfix: Sometimes mentions vanished - now they
 shouldn't do this anymore

---
 mod/item.php | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/mod/item.php b/mod/item.php
index 14c8203c98..ffb486a7db 100644
--- a/mod/item.php
+++ b/mod/item.php
@@ -1065,10 +1065,11 @@ function item_content(&$a) {
  * the appropiate link.
  *
  * @param unknown_type $body the text to replace the tag in
- * @param unknown_type $inform a comma-seperated string containing everybody to inform
- * @param unknown_type $str_tags string to add the tag to
- * @param unknown_type $profile_uid
- * @param unknown_type $tag the tag to replace
+ * @param string $inform a comma-seperated string containing everybody to inform
+ * @param string $str_tags string to add the tag to
+ * @param integer $profile_uid
+ * @param string $tag the tag to replace
+ * @param string $network The network of the post
  *
  * @return boolean true if replaced, false if not replaced
  */
@@ -1176,7 +1177,7 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
 			//select someone from this user's contacts by name in the current network
 			if (!$r AND ($network != ""))
 				$r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network` FROM `contact` WHERE `name` = '%s' AND `network` = '%s' AND `uid` = %d LIMIT 1",
-						dbesc($newname),
+						dbesc($name),
 						dbesc($network),
 						intval($profile_uid)
 				);
@@ -1193,7 +1194,7 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
 			//select someone from this user's contacts by name
 			if(!$r)
 				$r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network` FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1",
-						dbesc($newname),
+						dbesc($name),
 						intval($profile_uid)
 				);
 		}
@@ -1216,13 +1217,13 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
 		}
 
 		//if there is an url for this persons profile
-		if(isset($profile)) {
+		if (isset($profile) AND ($newname != "")) {
 
 			$replaced = true;
 			//create profile link
 			$profile = str_replace(',','%2c',$profile);
-			$newtag = '@[url=' . $profile . ']' . $newname	. '[/url]';
-			$body = str_replace('@' . $name, $newtag, $body);
+			$newtag = '@[url='.$profile.']'.$newname.'[/url]';
+			$body = str_replace('@'.$name, $newtag, $body);
 			//append tag to str_tags
 			if(! stristr($str_tags,$newtag)) {
 				if(strlen($str_tags))
@@ -1234,7 +1235,7 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo
 			// subscribed to you. But the nickname URL is OK if they are. Grrr. We'll tag both.
 
 			if(strlen($alias)) {
-				$newtag = '@[url=' . $alias . ']' . $newname	. '[/url]';
+				$newtag = '@[url='.$alias.']'.$newname.'[/url]';
 				if(! stristr($str_tags,$newtag)) {
 					if(strlen($str_tags))
 						$str_tags .= ',';