From afed5f3afc62431735b48a0ca6b5fb16ec598cf3 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Wed, 27 Jan 2016 11:30:12 +0100 Subject: [PATCH 01/35] 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 @@ +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 Date: Wed, 27 Jan 2016 15:57:11 +0100 Subject: [PATCH 02/35] 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 Date: Wed, 27 Jan 2016 20:06:23 +0100 Subject: [PATCH 03/35] 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 Date: Fri, 29 Jan 2016 17:42:38 +0100 Subject: [PATCH 04/35] 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 Date: Fri, 29 Jan 2016 23:14:01 +0100 Subject: [PATCH 05/35] 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 Date: Sat, 30 Jan 2016 01:20:43 +0100 Subject: [PATCH 06/35] 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 @@ 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 Date: Sat, 30 Jan 2016 02:57:40 +0100 Subject: [PATCH 07/35] 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 Date: Sat, 30 Jan 2016 03:17:46 +0100 Subject: [PATCH 08/35] 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 Date: Sat, 30 Jan 2016 14:13:58 +0100 Subject: [PATCH 09/35] 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 Date: Sat, 30 Jan 2016 16:37:18 +0100 Subject: [PATCH 10/35] 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 8a9862c9cedcf0f05aea3ad892d4a7cb774beb1b Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Mon, 1 Feb 2016 00:09:03 +0100 Subject: [PATCH 11/35] 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("".unxmlify($xo->link)."",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 Date: Mon, 1 Feb 2016 23:52:37 +0100 Subject: [PATCH 12/35] 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("".unxmlify($xo->link)."",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("".unxmlify($xo->link)."",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 811ed4e1c0bad71c29af927267dbc85b57dc6027 Mon Sep 17 00:00:00 2001 From: rabuzarus <> Date: Wed, 3 Feb 2016 19:48:09 +0100 Subject: [PATCH 13/35] 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 @@ '; 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(''; + // 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 .= "
"; $o .= '
'; $o .= ""; + 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() + * %1$d %2$s ago, 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 = ''; - $o .= ""; - for($a = 0; $a < 7; $a ++) - $o .= ''; - $o .= ''; + $o = '
$str_month $y
' . mb_substr(day_translate($dn[$a]),0,3,'UTF-8') . '
'; + $o .= ""; + for($a = 0; $a < 7; $a ++) + $o .= ''; - while($d <= $l) { - if(($dow == $f) && (! $started)) - $started = true; - $today = (((isset($tddate)) && ($tddate == $d)) ? "class=\"today\" " : ''); - $o .= "'; - $dow ++; - if(($dow == 7) && ($d <= $l)) { - $dow = 0; - $o .= ''; - } - } - if($dow) - for($a = $dow; $a < 7; $a ++) - $o .= ''; - $o .= '
$str_month $y
' . mb_substr(day_translate($dn[$a]),0,3,'UTF-8') . '"; - $day = str_replace(' ',' ',sprintf('%2.2d', $d)); - if($started) { - if(is_array($links) && isset($links[$d])) - $o .= "$day"; - else - $o .= $day; - $d ++; - } - else - $o .= ' '; - $o .= '
 
'."\r\n"; + $o .= ''; - return $o; -}} + while($d <= $l) { + if(($dow == $f) && (! $started)) + $started = true; + $today = (((isset($tddate)) && ($tddate == $d)) ? "class=\"today\" " : ''); + $o .= ""; + $day = str_replace(' ',' ',sprintf('%2.2d', $d)); + if($started) { + if(is_array($links) && isset($links[$d])) + $o .= "$day"; + else + $o .= $day; + $d ++; + } else { + $o .= ' '; + } + + $o .= ''; + $dow ++; + if(($dow == 7) && ($d <= $l)) { + $dow = 0; + $o .= ''; + } + } + if($dow) + for($a = $dow; $a < 7; $a ++) + $o .= ' '; + + $o .= ''."\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 2d0c2990ea13a756578b3117efeee788413648b6 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Wed, 3 Feb 2016 23:04:52 +0100 Subject: [PATCH 14/35] 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 5f6ba00408ca0f28b2d36d799fa62d37c72333a8 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Thu, 4 Feb 2016 10:19:13 +0100 Subject: [PATCH 15/35] 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 Date: Thu, 4 Feb 2016 12:51:34 +0100 Subject: [PATCH 16/35] 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 @@ 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 0390001d4e9244f114e3021c6ae243cdd77d99c9 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Thu, 4 Feb 2016 15:53:22 +0100 Subject: [PATCH 17/35] 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 92a31344b5e8e0c01aec325874a86808f7bba8e5 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Thu, 4 Feb 2016 20:34:18 +0100 Subject: [PATCH 18/35] 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 2bd36e562889803841588a276232ef5fa819730a Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Thu, 4 Feb 2016 23:52:06 +0100 Subject: [PATCH 19/35] 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 Date: Fri, 5 Feb 2016 09:03:17 +0100 Subject: [PATCH 20/35] 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 d408cea871e00a7f3c5e58b466395802eba523f7 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Fri, 5 Feb 2016 21:25:20 +0100 Subject: [PATCH 21/35] 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'] = '' . "\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'] .= '' . $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'] . '' . "\n"; - } - if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data']) - $res['object'] .= '' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'] . '' . "\n"; - if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']) - $res['object'] .= '' . encode_rel_links($child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']) . '' . "\n"; - if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'title') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data']) - $res['object'] .= '' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'] . '' . "\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'] .= '' . xmlify($body) . '' . "\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'] .= '' . $body . '' . "\n"; - } - - $res['object'] .= '' . "\n"; - } - - $rawobj = $item->get_item_tags(NAMESPACE_ACTIVITY, 'target'); - - if($rawobj) { - $res['target'] = '' . "\n"; - $child = $rawobj[0]['child']; - if($child[NAMESPACE_ACTIVITY]['object-type'][0]['data']) { - $res['target'] .= '' . $child[NAMESPACE_ACTIVITY]['object-type'][0]['data'] . '' . "\n"; - } - if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'id') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data']) - $res['target'] .= '' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['id'][0]['data'] . '' . "\n"; - if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'link') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']) - $res['target'] .= '' . encode_rel_links($child[SIMPLEPIE_NAMESPACE_ATOM_10]['link']) . '' . "\n"; - if(x($child[SIMPLEPIE_NAMESPACE_ATOM_10], 'data') && $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data']) - $res['target'] .= '' . $child[SIMPLEPIE_NAMESPACE_ATOM_10]['title'][0]['data'] . '' . "\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'] .= '' . xmlify($body) . '' . "\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'] .= '' . $body . '' . "\n"; - } - - $res['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 .= '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("".unxmlify($xo->link)."",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 @@ Date: Fri, 5 Feb 2016 21:31:11 +0100 Subject: [PATCH 22/35] 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("".unxmlify($xo->link)."",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 @@ -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("".unxmlify($xo->link)."",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 9e3f849e89ce1fdbd195660878f1b10cdeea8248 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Fri, 5 Feb 2016 22:12:54 +0100 Subject: [PATCH 23/35] 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 4896517385f3b4484564bf675a5342f74d70f48a Mon Sep 17 00:00:00 2001 From: rabuzarus <> Date: Sat, 6 Feb 2016 01:08:10 +0100 Subject: [PATCH 24/35] 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 Date: Sat, 6 Feb 2016 10:16:16 +0100 Subject: [PATCH 25/35] 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 Date: Sat, 6 Feb 2016 11:16:00 +0100 Subject: [PATCH 26/35] 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("".unxmlify($xo->link)."",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 Date: Sat, 6 Feb 2016 17:48:03 +0100 Subject: [PATCH 27/35] 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 Date: Sat, 6 Feb 2016 21:44:10 +0100 Subject: [PATCH 28/35] 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 b202e02fbf09859c06ed21cc3b6bec1530ccf1f1 Mon Sep 17 00:00:00 2001 From: fabrixxm Date: Sun, 7 Feb 2016 15:11:34 +0100 Subject: [PATCH 29/35] 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 @@ 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 @@ 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 @@ 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",'
', $s); } -if(! function_exists('babel_content')) { function babel_content(&$a) { $o .= '

Babel Diagnostic

'; $o .= '
'; $o .= t('Source (bbcode) text:') . EOL . '' . EOL; - $o .= '
'; + $o .= ''; $o .= '

'; $o .= '
'; $o .= t('Source (Diaspora) text to convert to BBcode:') . EOL . '' . EOL; - $o .= '
'; + $o .= ''; $o .= '

'; if(x($_REQUEST,'text')) { $text = trim($_REQUEST['text']); - $o .= "

" . t("Source input: ") . "

" . EOL. EOL; - $o .= visible_lf($text) . EOL. EOL; + $o .= "

" . t("Source input: ") . "

" . EOL. EOL; + $o .= visible_lf($text) . EOL. EOL; $html = bbcode($text); - $o .= "

" . t("bb2html (raw HTML): ") . "

" . EOL. EOL; - $o .= htmlspecialchars($html). EOL. EOL; + $o .= "

" . t("bb2html (raw HTML): ") . "

" . EOL. EOL; + $o .= htmlspecialchars($html). EOL. EOL; //$html = bbcode($text); - $o .= "

" . t("bb2html: ") . "

" . EOL. EOL; - $o .= $html. EOL. EOL; + $o .= "

" . t("bb2html: ") . "

" . EOL. EOL; + $o .= $html. EOL. EOL; $bbcode = html2bbcode($html); - $o .= "

" . t("bb2html2bb: ") . "

" . EOL. EOL; - $o .= visible_lf($bbcode) . EOL. EOL; + $o .= "

" . t("bb2html2bb: ") . "

" . EOL. EOL; + $o .= visible_lf($bbcode) . EOL. EOL; $diaspora = bb2diaspora($text); - $o .= "

" . t("bb2md: ") . "

" . EOL. EOL; - $o .= visible_lf($diaspora) . EOL. EOL; + $o .= "

" . t("bb2md: ") . "

" . EOL. EOL; + $o .= visible_lf($diaspora) . EOL. EOL; $html = Markdown($diaspora); - $o .= "

" . t("bb2md2html: ") . "

" . EOL. EOL; - $o .= $html. EOL. EOL; + $o .= "

" . t("bb2md2html: ") . "

" . EOL. EOL; + $o .= $html. EOL. EOL; $bbcode = diaspora2bb($diaspora); - $o .= "

" . t("bb2dia2bb: ") . "

" . EOL. EOL; - $o .= visible_lf($bbcode) . EOL. EOL; + $o .= "

" . t("bb2dia2bb: ") . "

" . EOL. EOL; + $o .= visible_lf($bbcode) . EOL. EOL; $bbcode = html2bbcode($html); - $o .= "

" . t("bb2md2html2bb: ") . "

" . EOL. EOL; - $o .= visible_lf($bbcode) . EOL. EOL; + $o .= "

" . t("bb2md2html2bb: ") . "

" . 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 .= "

" . t("Source input (Diaspora format): ") . "

" . EOL. EOL; - $o .= visible_lf($d2bbtext) . EOL. EOL; + $o .= "

" . t("Source input (Diaspora format): ") . "

" . EOL. EOL; + $o .= visible_lf($d2bbtext) . EOL. EOL; $bb = diaspora2bb($d2bbtext); - $o .= "

" . t("diaspora2bb: ") . "

" . EOL. EOL; - $o .= visible_lf($bb) . EOL. EOL; + $o .= "

" . t("diaspora2bb: ") . "

" . 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 @@ '.t('Login').''; @@ -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 @@ 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 @@ 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 @@ 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 .= '
' . t('Age: ') . $years ; +// $details .= '
' . t('Age: ') . $years ; // } // if(strlen($rr['gender'])) // $details .= '
' . 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 @@ 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 @@ 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() . '

'; - $o .= t('Please visit Friendica.com to learn more about the Friendica project.') . '

'; + $o .= t('Please visit Friendica.com to learn more about the Friendica project.') . '

'; $o .= t('Bug reports and issues: please visit') . ' ' . ''.t('the bugtracker at github').'

'; $o .= t('Suggestions, praise, donations, etc. - please email "Info" at Friendica - dot com') . '

'; @@ -103,8 +102,8 @@ function friendica_content(&$a) { else $o .= '

' . t('No installed plugins/addons/apps') . '

'; - 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 @@ '; - $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 @@ 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 @@ 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'] .= ''; } - if(x($a->profile,'openidserver')) + if(x($a->profile,'openidserver')) $a->page['htmlhead'] .= '' . "\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'] .= '' . "\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'] .= "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) { } ".$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 @@ 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 .= ""; 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 registration page 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.") ."

"; } -} + + 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 .= '
'; - $o .= '

' . t('Please select your timezone:') . '

'; + $o .= '

' . t('Please select your timezone:') . '

'; $o .= select_timezone(($_REQUEST['timezone']) ? $_REQUEST['timezone'] : 'America/Los_Angeles'); $o .= '
'; 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 @@ 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.') . '
'; @@ -53,7 +53,7 @@ function lockview_content(&$a) { dbesc(implode(', ', $allowed_groups)) ); if(count($r)) - foreach($r as $rr) + foreach($r as $rr) $l[] = '' . $rr['name'] . ''; } 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[] = '' . $rr['name'] . ''; } 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[] = '' . $rr['name'] . ''; } 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 @@ 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 @@ 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 @@ $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 @@ 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 @@ '; - $o .= '
  • ' . '' . t('Friendica Walk-Through') . '
    ' . t('On your Quick Start page - find a brief introduction to your profile and network tabs, make some new connections, and find some groups to join.') . '
  • ' . EOL; + $o .= '
  • ' . '' . t('Friendica Walk-Through') . '
    ' . t('On your Quick Start page - find a brief introduction to your profile and network tabs, make some new connections, and find some groups to join.') . '
  • ' . EOL; $o .= ''; @@ -24,7 +23,7 @@ function newmember_content(&$a) { $o .= '
      '; - $o .= '
    • ' . '' . t('Go to Your Settings') . '
      ' . t('On your Settings 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.') . '
    • ' . EOL; + $o .= '
    • ' . '' . t('Go to Your Settings') . '
      ' . t('On your Settings 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.') . '
    • ' . EOL; $o .= '
    • ' . 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.') . '
    • ' . EOL; @@ -34,7 +33,7 @@ function newmember_content(&$a) { $o .= '
        '; - $o .= '
      • ' . '' . t('Upload Profile Photo') . '
        ' . 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.') . '
      • ' . EOL; + $o .= '
      • ' . '' . t('Upload Profile Photo') . '
        ' . 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.') . '
      • ' . EOL; $o .= '
      • ' . '' . t('Edit Your Profile') . '
        ' . t('Edit your default profile to your liking. Review the settings for hiding your list of friends and hiding the profile from unknown visitors.') . '
      • ' . EOL; @@ -47,7 +46,7 @@ function newmember_content(&$a) { $o .= '
          '; $mail_disabled = ((function_exists('imap_open') && (! get_config('system','imap_disabled'))) ? 0 : 1); - + if(! $mail_disabled) $o .= '
        • ' . '' . t('Importing Emails') . '
          ' . 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') . '
        • ' . 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ $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 @@ * * - * + * * *

          Shiny Trinket

          * @@ -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 @@ 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 @@ Probe Diagnostic'; $o .= '
          '; $o .= 'Lookup address: '; - $o .= '
          '; + $o .= ''; $o .= '

          '; @@ -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'] .= "get_baseurl()."/dfrn_{$dfrn}/{$which}\" />\r\n"; $a->page['htmlhead'] .= "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 @@ 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 .= '
          '; - if($change) + if($change) $o = ''; - + $o .= '
          '; $o .= '

          ' . t('Visible To') . '

          '; $o .= '
          '; @@ -157,5 +156,6 @@ function profperm_content(&$a) { } $o .= '
          '; 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("/(]*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 @@ 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 @@ 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 @@ 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 @@ 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 @@ @@ -20,5 +21,4 @@ function rsd_xml_content(&$a) { '; 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 @@ 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 .= '' . "\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 @@ 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("'", "[", "]"),$author). "' profile='".str_replace(array("'", "[", "]"), array("'", "[", "]"),$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 @@ 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('⌗') . '[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 .= ''; 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 @@ 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 "
          "; 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 "";
           	echo "\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 "";
           	echo "\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 "";
           	echo "\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 "";
           	echo "\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 "";
           	echo "\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 @@
           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 @@
           Webfinger Diagnostic';
           
           	$o .= '
          '; $o .= 'Lookup address: '; - $o .= '
          '; + $o .= ''; $o .= '

          '; @@ -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 e267630c546190b2a2cf437d98bbd415d48c4de2 Mon Sep 17 00:00:00 2001 From: rabuzarus Date: Mon, 8 Feb 2016 01:59:05 +0100 Subject: [PATCH 30/35] 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 b3f7e8d38808080a181f24720951842c0c76485e Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Mon, 8 Feb 2016 15:26:24 +0100 Subject: [PATCH 31/35] 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 Date: Mon, 8 Feb 2016 22:37:29 +0100 Subject: [PATCH 32/35] 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('/\/','',$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("".$r->link."", 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 7af3dd01d808c99a5d7d02d152fe3399625b41e0 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Tue, 9 Feb 2016 06:42:00 +0100 Subject: [PATCH 33/35] 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 Date: Tue, 9 Feb 2016 09:39:29 +0100 Subject: [PATCH 34/35] 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 Date: Tue, 9 Feb 2016 10:21:10 +0100 Subject: [PATCH 35/35] 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);