From afed5f3afc62431735b48a0ca6b5fb16ec598cf3 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Wed, 27 Jan 2016 11:30:12 +0100 Subject: [PATCH 001/126] 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 000000000..7336946a7 --- /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 cf044d883..f52d46b7e 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 002/126] 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 2c8e8ce38..883afe15f 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 7336946a7..5a3582926 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 003/126] 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 5a3582926..b3a8dbaf8 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 004/126] 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 3f1608d3e..91fce55a8 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 b3a8dbaf8..c93438035 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 005/126] 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 883afe15f..50d78de3c 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 c93438035..3265eb6ff 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 37b308db7..caaeec84f 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 006/126] 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 3265eb6ff..fd5b71cad 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 007/126] 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 fd5b71cad..20735bd50 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 65b274019..7df4e0c78 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 57728d329..e517f785e 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 008/126] 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 20735bd50..b1a1c80e0 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 009/126] 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 b1a1c80e0..9660d9209 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 7df4e0c78..6ed53ffcd 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 010/126] 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 50d78de3c..4c1f21dd0 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 9660d9209..8a72e4006 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 011/126] 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 8a72e4006..0e185d3f4 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 012/126] 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 0e185d3f4..bfcb002bb 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 c1070e4655996e047951dada992b65abebf74834 Mon Sep 17 00:00:00 2001 From: rabuzarus <> Date: Wed, 3 Feb 2016 18:05:26 +0100 Subject: [PATCH 013/126] forums.php is now forum.php and providing class forum --- include/forum.php | 190 ++++++++++++++++++++++++++++++++++++++ include/forums.php | 185 ------------------------------------- include/identity.php | 4 +- mod/network.php | 4 +- mod/ping.php | 4 +- view/theme/vier/theme.php | 4 +- 6 files changed, 198 insertions(+), 193 deletions(-) create mode 100644 include/forum.php delete mode 100644 include/forums.php diff --git a/include/forum.php b/include/forum.php new file mode 100644 index 000000000..290f0134a --- /dev/null +++ b/include/forum.php @@ -0,0 +1,190 @@ + forum url + * 'name' => forum name + * 'id' => number of the key from the array + * 'micro' => contact photo in format micro + */ + public static function get_forumlist($uid, $showhidden = true, $lastitem, $showprivate = false) { + + $forumlist = array(); + + $order = (($showhidden) ? '' : ' AND NOT `hidden` '); + $order .= (($lastitem) ? ' ORDER BY `last-item` DESC ' : ' ORDER BY `name` ASC '); + $select = '`forum` '; + if ($showprivate) { + $select = '(`forum` OR `prv`)'; + } + + $contacts = q("SELECT `contact`.`id`, `contact`.`url`, `contact`.`name`, `contact`.`micro` FROM `contact` + WHERE `network`= 'dfrn' AND $select AND `uid` = %d + AND NOT `blocked` AND NOT `hidden` AND NOT `pending` AND NOT `archive` + AND `success_update` > `failure_update` + $order ", + intval($uid) + ); + + if (!$contacts) + return($forumlist); + + foreach($contacts as $contact) { + $forumlist[] = array( + 'url' => $contact['url'], + 'name' => $contact['name'], + 'id' => $contact['id'], + 'micro' => $contact['micro'], + ); + } + return($forumlist); + } + + + /** + * @brief Forumlist widget + * + * Sidebar widget to show subcribed friendica forums. If activated + * in the settings, it appears at the notwork page sidebar + * + * @param int $uid The ID of the User + * @param int $cid + * The contact id which is used to mark a forum as "selected" + * @return string + */ + public static function widget_forumlist($uid,$cid = 0) { + + if(! intval(feature_enabled(local_user(),'forumlist_widget'))) + return; + + $o = ''; + + //sort by last updated item + $lastitem = true; + + $contacts = self::get_forumlist($uid,true,$lastitem, true); + $total = count($contacts); + $visible_forums = 10; + + if(count($contacts)) { + + $id = 0; + + foreach($contacts as $contact) { + + $selected = (($cid == $contact['id']) ? ' forum-selected' : ''); + + $entry = array( + 'url' => z_root() . '/network?f=&cid=' . $contact['id'], + 'external_url' => z_root() . '/redir/' . $contact['id'], + 'name' => $contact['name'], + 'cid' => $contact['id'], + 'selected' => $selected, + 'micro' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO), + 'id' => ++$id, + ); + $entries[] = $entry; + } + + $tpl = get_markup_template('widget_forumlist.tpl'); + + $o .= replace_macros($tpl,array( + '$title' => t('Forums'), + '$forums' => $entries, + '$link_desc' => t('External link to forum'), + '$total' => $total, + '$visible_forums' => $visible_forums, + '$showmore' => t('show more'), + )); + } + + return $o; + } + + /** + * @brief Format forumlist as contact block + * + * This function is used to show the forumlist in + * the advanced profile. + * + * @param int $uid The ID of the User + * @return string + * + */ + public static function forumlist_profile_advanced($uid) { + + $profile = intval(feature_enabled($uid,'forumlist_profile')); + if(! $profile) + return; + + $o = ''; + + // place holder in case somebody wants configurability + $show_total = 9999; + + //don't sort by last updated item + $lastitem = false; + + $contacts = self::get_forumlist($uid,false,$lastitem,false); + + $total_shown = 0; + + foreach($contacts as $contact) { + $forumlist .= micropro($contact,false,'forumlist-profile-advanced'); + $total_shown ++; + if($total_shown == $show_total) + break; + } + + if(count($contacts) > 0) + $o .= $forumlist; + return $o; + } + + /** + * @brief count unread forum items + * + * Count unread items of connected forums and private groups + * + * @return array + * 'id' => contact id + * 'name' => contact/forum name + * 'count' => counted unseen forum items + * + */ + public static function count_unseen_items() { + $r = q("SELECT `contact`.`id`, `contact`.`name`, COUNT(*) AS `count` FROM `item` + INNER JOIN `contact` ON `item`.`contact-id` = `contact`.`id` + WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted` AND `item`.`unseen` + AND `contact`.`network`= 'dfrn' AND (`contact`.`forum` OR `contact`.`prv`) + AND NOT `contact`.`blocked` AND NOT `contact`.`hidden` + AND NOT `contact`.`pending` AND NOT `contact`.`archive` + AND `contact`.`success_update` > `failure_update` + GROUP BY `contact`.`id` ", + intval(local_user()) + ); + + return $r; + } + +} \ No newline at end of file diff --git a/include/forums.php b/include/forums.php deleted file mode 100644 index 952d09a49..000000000 --- a/include/forums.php +++ /dev/null @@ -1,185 +0,0 @@ - forum url - * 'name' => forum name - * 'id' => number of the key from the array - * 'micro' => contact photo in format micro - */ -function get_forumlist($uid, $showhidden = true, $lastitem, $showprivate = false) { - - $forumlist = array(); - - $order = (($showhidden) ? '' : ' AND NOT `hidden` '); - $order .= (($lastitem) ? ' ORDER BY `last-item` DESC ' : ' ORDER BY `name` ASC '); - $select = '`forum` '; - if ($showprivate) { - $select = '(`forum` OR `prv`)'; - } - - $contacts = q("SELECT `contact`.`id`, `contact`.`url`, `contact`.`name`, `contact`.`micro` FROM `contact` - WHERE `network`= 'dfrn' AND $select AND `uid` = %d - AND NOT `blocked` AND NOT `hidden` AND NOT `pending` AND NOT `archive` - AND `success_update` > `failure_update` - $order ", - intval($uid) - ); - - if (!$contacts) - return($forumlist); - - foreach($contacts as $contact) { - $forumlist[] = array( - 'url' => $contact['url'], - 'name' => $contact['name'], - 'id' => $contact['id'], - 'micro' => $contact['micro'], - ); - } - return($forumlist); -} - - -/** - * @brief Forumlist widget - * - * Sidebar widget to show subcribed friendica forums. If activated - * in the settings, it appears at the notwork page sidebar - * - * @param int $uid - * @param int $cid - * The contact id which is used to mark a forum as "selected" - * @return string - */ -function widget_forumlist($uid,$cid = 0) { - - if(! intval(feature_enabled(local_user(),'forumlist_widget'))) - return; - - $o = ''; - - //sort by last updated item - $lastitem = true; - - $contacts = get_forumlist($uid,true,$lastitem, true); - $total = count($contacts); - $visible_forums = 10; - - if(count($contacts)) { - - $id = 0; - - foreach($contacts as $contact) { - - $selected = (($cid == $contact['id']) ? ' forum-selected' : ''); - - $entry = array( - 'url' => z_root() . '/network?f=&cid=' . $contact['id'], - 'external_url' => z_root() . '/redir/' . $contact['id'], - 'name' => $contact['name'], - 'cid' => $contact['id'], - 'selected' => $selected, - 'micro' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO), - 'id' => ++$id, - ); - $entries[] = $entry; - } - - $tpl = get_markup_template('widget_forumlist.tpl'); - - $o .= replace_macros($tpl,array( - '$title' => t('Forums'), - '$forums' => $entries, - '$link_desc' => t('External link to forum'), - '$total' => $total, - '$visible_forums' => $visible_forums, - '$showmore' => t('show more'), - )); - } - - return $o; -} - -/** - * @brief Format forumlist as contact block - * - * This function is used to show the forumlist in - * the advanced profile. - * - * @param int $uid - * @return string - * - */ -function forumlist_profile_advanced($uid) { - - $profile = intval(feature_enabled($uid,'forumlist_profile')); - if(! $profile) - return; - - $o = ''; - - // place holder in case somebody wants configurability - $show_total = 9999; - - //don't sort by last updated item - $lastitem = false; - - $contacts = get_forumlist($uid,false,$lastitem,false); - - $total_shown = 0; - - foreach($contacts as $contact) { - $forumlist .= micropro($contact,false,'forumlist-profile-advanced'); - $total_shown ++; - if($total_shown == $show_total) - break; - } - - if(count($contacts) > 0) - $o .= $forumlist; - return $o; -} - -/** - * @brief count unread forum items - * - * Count unread items of connected forums and private groups - * - * @return array - * 'id' => contact id - * 'name' => contact/forum name - * 'count' => counted unseen forum items - * - */ - -function forums_count_unseen() { - $r = q("SELECT `contact`.`id`, `contact`.`name`, COUNT(*) AS `count` FROM `item` - INNER JOIN `contact` ON `item`.`contact-id` = `contact`.`id` - WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted` AND `item`.`unseen` - AND `contact`.`network`= 'dfrn' AND (`contact`.`forum` OR `contact`.`prv`) - AND NOT `contact`.`blocked` AND NOT `contact`.`hidden` - AND NOT `contact`.`pending` AND NOT `contact`.`archive` - AND `contact`.`success_update` > `failure_update` - GROUP BY `contact`.`id` ", - intval(local_user()) - ); - - return $r; -} diff --git a/include/identity.php b/include/identity.php index fdd28f81c..87c91e6dc 100644 --- a/include/identity.php +++ b/include/identity.php @@ -3,7 +3,7 @@ * @file include/identity.php */ -require_once('include/forums.php'); +require_once('include/forum.php'); require_once('include/bbcode.php'); require_once("mod/proxy.php"); @@ -655,7 +655,7 @@ function advanced_profile(&$a) { //show subcribed forum if it is enabled in the usersettings if (feature_enabled($uid,'forumlist_profile')) { - $profile['forumlist'] = array( t('Forums:'), forumlist_profile_advanced($uid)); + $profile['forumlist'] = array( t('Forums:'), forum::forumlist_profile_advanced($uid)); } if ($a->profile['uid'] == local_user()) diff --git a/mod/network.php b/mod/network.php index a07c5868e..151384cd6 100644 --- a/mod/network.php +++ b/mod/network.php @@ -114,7 +114,7 @@ function network_init(&$a) { require_once('include/group.php'); require_once('include/contact_widgets.php'); require_once('include/items.php'); - require_once('include/forums.php'); + require_once('include/forum.php'); if(! x($a->page,'aside')) $a->page['aside'] = ''; @@ -148,7 +148,7 @@ function network_init(&$a) { } $a->page['aside'] .= (feature_enabled(local_user(),'groups') ? group_side('network/0','network','standard',$group_id) : ''); - $a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? widget_forumlist(local_user(),$cid) : ''); + $a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? forum::widget_forumlist(local_user(),$cid) : ''); $a->page['aside'] .= posted_date_widget($a->get_baseurl() . '/network',local_user(),false); $a->page['aside'] .= networks_widget($a->get_baseurl(true) . '/network',(x($_GET, 'nets') ? $_GET['nets'] : '')); $a->page['aside'] .= saved_searches($search); diff --git a/mod/ping.php b/mod/ping.php index 57728d329..3d34e2fe6 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -1,7 +1,7 @@ user['uid'],true,$lastitem, true); + $contacts = forum::get_forumlist($a->user['uid'],true,$lastitem, true); $total = count($contacts); $visible_forums = 10; From 811ed4e1c0bad71c29af927267dbc85b57dc6027 Mon Sep 17 00:00:00 2001 From: rabuzarus <> Date: Wed, 3 Feb 2016 19:48:09 +0100 Subject: [PATCH 014/126] 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 a05af5e38..3a75690d2 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 c7158772619f2b38a55b22c7639ee3fd58bc0db0 Mon Sep 17 00:00:00 2001 From: Silke Meyer Date: Wed, 3 Feb 2016 20:47:41 +0100 Subject: [PATCH 015/126] Slightly updated docs about Let's Encrypt --- doc/SSL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/SSL.md b/doc/SSL.md index a72eec2a1..bcff929fe 100644 --- a/doc/SSL.md +++ b/doc/SSL.md @@ -90,8 +90,8 @@ If you run your own server, upload the files and check out the Mozilla wiki link Let's encrypt --- -If you run your own server and you control your name server, the "Let's encrypt" initiative might become an interesting alternative. -Their offer is not ready, yet. +If you run your own server, the "Let's encrypt" initiative might become an interesting alternative. +Their offer is in public beta right now. Check out [their website](https://letsencrypt.org/) for status updates. Web server settings From 2d0c2990ea13a756578b3117efeee788413648b6 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Wed, 3 Feb 2016 23:04:52 +0100 Subject: [PATCH 016/126] 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 bfcb002bb..981e59643 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 0e98e8f19..f1291d649 100644 --- a/include/items.php +++ b/include/items.php @@ -1696,13 +1696,29 @@ function consume_feed($xml,$importer,&$contact, &$hub, $datedir = 0, $pass = 0) return; } // dfrn-test -// if ($contact['network'] === NETWORK_DFRN) { -// logger("Consume DFRN messages", LOGGER_DEBUG); -// logger("dfrn-test"); -// dfrn2::import($xml,$importer, $contact); -// return; -// } +/* + if ($contact['network'] === NETWORK_DFRN) { + logger("Consume DFRN messages", LOGGER_DEBUG); + logger("dfrn-test"); + $r = q("SELECT `contact`.*, `contact`.`uid` AS `importer_uid`, + `contact`.`pubkey` AS `cpubkey`, + `contact`.`prvkey` AS `cprvkey`, + `contact`.`thumb` AS `thumb`, + `contact`.`url` as `url`, + `contact`.`name` as `senderName`, + `user`.* + FROM `contact` + LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid` + WHERE `contact`.`id` = %d AND `user`.`uid` = %d", + dbesc($contact["id"], $importer["uid"]); + ); + if ($r) { + dfrn2::import($xml,$r[0], true); + return; + } + } +*/ // Test - remove before flight //if ($pass < 2) { // $tempfile = tempnam(get_temppath(), "dfrn-consume-"); @@ -2408,7 +2424,7 @@ function item_is_remote_self($contact, &$datarray) { function local_delivery($importer,$data) { // dfrn-Test - //return dfrn2::import($data, $importer, $contact); + //return dfrn2::import($data, $importer); require_once('library/simplepie/simplepie.inc'); From e11ff25de2122fd619a68152af8f7a66cfb11ca1 Mon Sep 17 00:00:00 2001 From: fabrixxm Date: Wed, 3 Feb 2016 23:22:45 +0100 Subject: [PATCH 017/126] fix empty ACL window on desktop --- view/templates/acl_selector.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/templates/acl_selector.tpl b/view/templates/acl_selector.tpl index bb7613506..7c68a7306 100644 --- a/view/templates/acl_selector.tpl +++ b/view/templates/acl_selector.tpl @@ -30,7 +30,7 @@ $(document).ready(function() { baseurl+"/acl", [ {{$allowcid}},{{$allowgid}},{{$denycid}},{{$denygid}} ], {{$features.aclautomention}}, - {{$APP->is_mobile}} + {{if $APP->is_mobile}}true{{else}}false{{/if}} ); } }); From 5f6ba00408ca0f28b2d36d799fa62d37c72333a8 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Thu, 4 Feb 2016 10:19:13 +0100 Subject: [PATCH 018/126] 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 981e59643..0abf92feb 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 019/126] 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 0abf92feb..87b2273ef 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 f1291d649..0ec645cc7 100644 --- a/include/items.php +++ b/include/items.php @@ -17,7 +17,7 @@ require_once('include/feed.php'); require_once('include/Contact.php'); require_once('mod/share.php'); require_once('include/enotify.php'); -//require_once('include/import-dfrn.php'); +require_once('include/import-dfrn.php'); require_once('library/defuse/php-encryption-1.2.1/Crypto.php'); @@ -2424,7 +2424,7 @@ function item_is_remote_self($contact, &$datarray) { function local_delivery($importer,$data) { // dfrn-Test - //return dfrn2::import($data, $importer); + return dfrn2::import($data, $importer); require_once('library/simplepie/simplepie.inc'); From 9a54afa629acc58a8e1df9dd48a2dd1f718b8a77 Mon Sep 17 00:00:00 2001 From: rabuzarus <> Date: Thu, 4 Feb 2016 14:47:20 +0100 Subject: [PATCH 020/126] Forum class - rename Class CamelCase and rename some methods --- include/{forum.php => Forum.php} | 12 ++++++------ include/identity.php | 4 ++-- mod/network.php | 4 ++-- mod/ping.php | 4 ++-- view/theme/vier/theme.php | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) rename include/{forum.php => Forum.php} (92%) diff --git a/include/forum.php b/include/Forum.php similarity index 92% rename from include/forum.php rename to include/Forum.php index 290f0134a..847affa87 100644 --- a/include/forum.php +++ b/include/Forum.php @@ -8,7 +8,7 @@ /** * @brief This class handles functions related to the forum functionality */ -class forum { +class Forum { /** * @brief Function to list all forums a user is connected with @@ -27,7 +27,7 @@ class forum { * 'id' => number of the key from the array * 'micro' => contact photo in format micro */ - public static function get_forumlist($uid, $showhidden = true, $lastitem, $showprivate = false) { + public static function get_list($uid, $showhidden = true, $lastitem, $showprivate = false) { $forumlist = array(); @@ -72,7 +72,7 @@ class forum { * The contact id which is used to mark a forum as "selected" * @return string */ - public static function widget_forumlist($uid,$cid = 0) { + public static function widget($uid,$cid = 0) { if(! intval(feature_enabled(local_user(),'forumlist_widget'))) return; @@ -82,7 +82,7 @@ class forum { //sort by last updated item $lastitem = true; - $contacts = self::get_forumlist($uid,true,$lastitem, true); + $contacts = self::get_list($uid,true,$lastitem, true); $total = count($contacts); $visible_forums = 10; @@ -131,7 +131,7 @@ class forum { * @return string * */ - public static function forumlist_profile_advanced($uid) { + public static function profile_advanced($uid) { $profile = intval(feature_enabled($uid,'forumlist_profile')); if(! $profile) @@ -145,7 +145,7 @@ class forum { //don't sort by last updated item $lastitem = false; - $contacts = self::get_forumlist($uid,false,$lastitem,false); + $contacts = self::get_list($uid,false,$lastitem,false); $total_shown = 0; diff --git a/include/identity.php b/include/identity.php index 87c91e6dc..a6932f091 100644 --- a/include/identity.php +++ b/include/identity.php @@ -3,7 +3,7 @@ * @file include/identity.php */ -require_once('include/forum.php'); +require_once('include/Forum.php'); require_once('include/bbcode.php'); require_once("mod/proxy.php"); @@ -655,7 +655,7 @@ function advanced_profile(&$a) { //show subcribed forum if it is enabled in the usersettings if (feature_enabled($uid,'forumlist_profile')) { - $profile['forumlist'] = array( t('Forums:'), forum::forumlist_profile_advanced($uid)); + $profile['forumlist'] = array( t('Forums:'), Forum::profile_advanced($uid)); } if ($a->profile['uid'] == local_user()) diff --git a/mod/network.php b/mod/network.php index 151384cd6..b72d72d78 100644 --- a/mod/network.php +++ b/mod/network.php @@ -114,7 +114,7 @@ function network_init(&$a) { require_once('include/group.php'); require_once('include/contact_widgets.php'); require_once('include/items.php'); - require_once('include/forum.php'); + require_once('include/Forum.php'); if(! x($a->page,'aside')) $a->page['aside'] = ''; @@ -148,7 +148,7 @@ function network_init(&$a) { } $a->page['aside'] .= (feature_enabled(local_user(),'groups') ? group_side('network/0','network','standard',$group_id) : ''); - $a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? forum::widget_forumlist(local_user(),$cid) : ''); + $a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? Forum::widget(local_user(),$cid) : ''); $a->page['aside'] .= posted_date_widget($a->get_baseurl() . '/network',local_user(),false); $a->page['aside'] .= networks_widget($a->get_baseurl(true) . '/network',(x($_GET, 'nets') ? $_GET['nets'] : '')); $a->page['aside'] .= saved_searches($search); diff --git a/mod/ping.php b/mod/ping.php index 3d34e2fe6..2abad13b0 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -1,7 +1,7 @@ user['uid'],true,$lastitem, true); + $contacts = Forum::get_list($a->user['uid'],true,$lastitem, true); $total = count($contacts); $visible_forums = 10; From 52dbb0b4a2fd4aa4d747605e329002334a26dd72 Mon Sep 17 00:00:00 2001 From: rabuzarus <> Date: Thu, 4 Feb 2016 14:51:54 +0100 Subject: [PATCH 021/126] Forum class - rename Class CamelCase and rename some methods --- include/{Forum.php => ForumManager.php} | 2 +- include/identity.php | 4 ++-- mod/network.php | 4 ++-- mod/ping.php | 4 ++-- view/theme/vier/theme.php | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) rename include/{Forum.php => ForumManager.php} (99%) diff --git a/include/Forum.php b/include/ForumManager.php similarity index 99% rename from include/Forum.php rename to include/ForumManager.php index 847affa87..49417d183 100644 --- a/include/Forum.php +++ b/include/ForumManager.php @@ -8,7 +8,7 @@ /** * @brief This class handles functions related to the forum functionality */ -class Forum { +class ForumManager { /** * @brief Function to list all forums a user is connected with diff --git a/include/identity.php b/include/identity.php index a6932f091..ec66225d0 100644 --- a/include/identity.php +++ b/include/identity.php @@ -3,7 +3,7 @@ * @file include/identity.php */ -require_once('include/Forum.php'); +require_once('include/ForumManager.php'); require_once('include/bbcode.php'); require_once("mod/proxy.php"); @@ -655,7 +655,7 @@ function advanced_profile(&$a) { //show subcribed forum if it is enabled in the usersettings if (feature_enabled($uid,'forumlist_profile')) { - $profile['forumlist'] = array( t('Forums:'), Forum::profile_advanced($uid)); + $profile['forumlist'] = array( t('Forums:'), ForumManager::profile_advanced($uid)); } if ($a->profile['uid'] == local_user()) diff --git a/mod/network.php b/mod/network.php index b72d72d78..0010a3d82 100644 --- a/mod/network.php +++ b/mod/network.php @@ -114,7 +114,7 @@ function network_init(&$a) { require_once('include/group.php'); require_once('include/contact_widgets.php'); require_once('include/items.php'); - require_once('include/Forum.php'); + require_once('include/ForumManager.php'); if(! x($a->page,'aside')) $a->page['aside'] = ''; @@ -148,7 +148,7 @@ function network_init(&$a) { } $a->page['aside'] .= (feature_enabled(local_user(),'groups') ? group_side('network/0','network','standard',$group_id) : ''); - $a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? Forum::widget(local_user(),$cid) : ''); + $a->page['aside'] .= (feature_enabled(local_user(),'forumlist_widget') ? ForumManager::widget(local_user(),$cid) : ''); $a->page['aside'] .= posted_date_widget($a->get_baseurl() . '/network',local_user(),false); $a->page['aside'] .= networks_widget($a->get_baseurl(true) . '/network',(x($_GET, 'nets') ? $_GET['nets'] : '')); $a->page['aside'] .= saved_searches($search); diff --git a/mod/ping.php b/mod/ping.php index 2abad13b0..577a2c6c8 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -1,7 +1,7 @@ user['uid'],true,$lastitem, true); + $contacts = ForumManager::get_list($a->user['uid'],true,$lastitem, true); $total = count($contacts); $visible_forums = 10; From 0390001d4e9244f114e3021c6ae243cdd77d99c9 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Thu, 4 Feb 2016 15:53:22 +0100 Subject: [PATCH 022/126] 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 87b2273ef..c4b3fed36 100644 --- a/include/import-dfrn.php +++ b/include/import-dfrn.php @@ -95,8 +95,6 @@ class dfrn2 { $author["avatar"] = current($avatarlist); } - //$onlyfetch = true; // Test - if ($r AND !$onlyfetch) { // When was the last change to name or uri? @@ -481,11 +479,13 @@ class dfrn2 { } private function update_content($current, $item, $importer, $entrytype) { + $changed = false; + if (edited_timestamp_is_newer($current, $item)) { // do not accept (ignore) an earlier edit than one we currently have. if(datetime_convert("UTC","UTC",$item["edited"]) < $current["edited"]) - return; + return(false); $r = q("UPDATE `item` SET `title` = '%s', `body` = '%s', `tag` = '%s', `edited` = '%s', `changed` = '%s' WHERE `uri` = '%s' AND `uid` = %d", dbesc($item["title"]), @@ -499,6 +499,8 @@ class dfrn2 { create_tags_from_itemuri($item["uri"], $importer["importer_uid"]); update_thread_uri($item["uri"], $importer["importer_uid"]); + $changed = true; + if ($entrytype == DFRN_REPLY_RC) proc_run("php", "include/notifier.php","comment-import", $current["id"]); } @@ -517,6 +519,7 @@ class dfrn2 { intval($importer["importer_uid"]) ); } + return $changed; } private function get_entry_type($importer, $item) { @@ -812,7 +815,8 @@ class dfrn2 { if(count($r)) $ev["id"] = $r[0]["id"]; $xyz = event_store($ev); - return; + logger("Event ".$ev["id"]." was stored", LOGGER_DEBUG); + return; } } } @@ -824,13 +828,18 @@ class dfrn2 { // Update content if 'updated' changes if(count($r)) { - self::update_content($r[0], $item, $importer, $entrytype); + if (self::update_content($r[0], $item, $importer, $entrytype)) + logger("Item ".$item["uri"]." was updated.", LOGGER_DEBUG); + else + logger("Item ".$item["uri"]." already existed.", LOGGER_DEBUG); return; } if (in_array($entrytype, array(DFRN_REPLY, DFRN_REPLY_RC))) { - if($importer["rel"] == CONTACT_IS_FOLLOWER) + if($importer["rel"] == CONTACT_IS_FOLLOWER) { + logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG); return; + } if(($item["verb"] === ACTIVITY_LIKE) || ($item["verb"] === ACTIVITY_DISLIKE) @@ -931,6 +940,7 @@ class dfrn2 { } } else { if(!link_compare($item["owner-link"],$importer["url"])) { + /// @todo Check if this is really used // The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery, // but otherwise there's a possible data mixup on the sender's system. // the tgroup delivery code called from item_store will correct it if it's a forum, From 12c6ba9081e05ecb2b9ebcbb16aeb0b7dfc0eb55 Mon Sep 17 00:00:00 2001 From: rabuzarus <> Date: Thu, 4 Feb 2016 16:21:40 +0100 Subject: [PATCH 023/126] vier: remove some hardcoded css to be more mobile friendly --- view/theme/vier/style.css | 67 +++++++++++---------------------------- 1 file changed, 19 insertions(+), 48 deletions(-) diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css index 7d7e2683a..8c0327797 100644 --- a/view/theme/vier/style.css +++ b/view/theme/vier/style.css @@ -1583,63 +1583,34 @@ section.minimal { width: calc(100% - 165px); } -.wall-item-container.comment .wall-item-content { - max-width: 585px; -} -.wall-item-container.thread_level_3 .wall-item-content { - max-width: 570px; -} -.wall-item-container.thread_level_4 .wall-item-content { - max-width: 555px; -} -.wall-item-container.thread_level_5 .wall-item-content { - max-width: 540px; -} -.wall-item-container.thread_level_6 .wall-item-content { - max-width: 525px; -} +.wall-item-container.comment .wall-item-content, +.wall-item-container.thread_level_3 .wall-item-content, +.wall-item-container.thread_level_4 .wall-item-content, +.wall-item-container.thread_level_5 .wall-item-content, +.wall-item-container.thread_level_6 .wall-item-content, .wall-item-container.thread_level_7 .wall-item-content { - max-width: 510px; + max-width: calc(100% - 1px); } -.children .wall-item-comment-wrapper textarea { - width: 570px; -} -.wall-item-container.thread_level_3 .wall-item-comment-wrapper textarea { - width: 555px; -} -.wall-item-container.thread_level_4 .wall-item-comment-wrapper textarea { - width: 540px; -} -.wall-item-container.thread_level_5 .wall-item-comment-wrapper textarea { - width: 525px; -} -.wall-item-container.thread_level_6 .wall-item-comment-wrapper textarea { - width: 510px; -} +.children .wall-item-comment-wrapper textarea, +.wall-item-container.thread_level_3 .wall-item-comment-wrapper textarea, +.wall-item-container.thread_level_4 .wall-item-comment-wrapper textarea, +.wall-item-container.thread_level_5 .wall-item-comment-wrapper textarea, +.wall-item-container.thread_level_6 .wall-item-comment-wrapper textarea, .wall-item-container.thread_level_7 .wall-item-comment-wrapper textarea { - width: 495px; + width: calc(100% - 11px); } -.children .wall-item-bottom .comment-edit-preview { - width: 575px; -} -.wall-item-container.thread_level_3 .wall-item-bottom .comment-edit-preview { - width: 560px; -} -.wall-item-container.thread_level_4 .wall-item-bottom .comment-edit-preview { - width: 545px; -} -.wall-item-container.thread_level_5 .wall-item-bottom .comment-edit-preview { - width: 530px; -} -.wall-item-container.thread_level_6 .wall-item-bottom .comment-edit-preview { - width: 515px; -} +.children .wall-item-bottom .comment-edit-preview, +.wall-item-container.thread_level_3 .wall-item-bottom .comment-edit-preview, +.wall-item-container.thread_level_4 .wall-item-bottom .comment-edit-preview, +.wall-item-container.thread_level_5 .wall-item-bottom .comment-edit-preview, +.wall-item-container.thread_level_6 .wall-item-bottom .comment-edit-preview, .wall-item-container.thread_level_7 .wall-item-bottom .comment-edit-preview { - width: 500px; + width: calc(100% - 6px); } + .wall-item-container.comment .contact-photo { width: 32px; height: 32px; From a75be65860391ea81e91ba28d2b4047c8b3bcc02 Mon Sep 17 00:00:00 2001 From: rabuzarus <> Date: Thu, 4 Feb 2016 16:45:39 +0100 Subject: [PATCH 024/126] vier: little float fix --- view/theme/vier/style.css | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css index 8c0327797..39d2af680 100644 --- a/view/theme/vier/style.css +++ b/view/theme/vier/style.css @@ -1042,6 +1042,9 @@ aside { box-shadow: 1px 2px 0px 0px #D8D8D8; color: #737373; } +aside .vcard .tool { + clear: both; +} aside .vcard .fn { font-size: 18px; font-weight: bold; @@ -1050,7 +1053,6 @@ aside .vcard .fn { } aside .vcard .title { margin-bottom: 5px; - float: left; } aside .vcard dl { height: auto; From b85369a03bcc10c8f6860be11e129c03dd49c141 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Thu, 4 Feb 2016 18:58:33 +0100 Subject: [PATCH 025/126] Vier: The font "system" can make the system look ugly --- view/theme/vier/style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css index e0abee837..7d56f6c40 100644 --- a/view/theme/vier/style.css +++ b/view/theme/vier/style.css @@ -269,7 +269,7 @@ div.pager { /* global */ body { /* font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; */ - font-family: system,-apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Helvetica,Arial,sans-serif; + font-family: -apple-system,".SFNSText-Regular","San Francisco","Roboto","Segoe UI","Helvetica Neue","Lucida Grande",Helvetica,Arial,sans-serif; font-size: 14px; /* font-size: 13px; line-height: 19.5px; */ From acefb846810434a77335862bfb9bd1294c079a9c Mon Sep 17 00:00:00 2001 From: Andrej Stieben Date: Thu, 4 Feb 2016 19:37:06 +0100 Subject: [PATCH 026/126] Improved documentation formatting (of Plugins.md) --- doc/Plugins.md | 101 +++++++++++++++++++++++----------------------- doc/de/Plugins.md | 75 ++++++++++++++++++---------------- 2 files changed, 92 insertions(+), 84 deletions(-) diff --git a/doc/Plugins.md b/doc/Plugins.md index 24d403e1f..a30a3f4a7 100644 --- a/doc/Plugins.md +++ b/doc/Plugins.md @@ -1,5 +1,7 @@ Friendica Addon/Plugin development -========================== +============== + +* [Home](help) Please see the sample addon 'randplace' for a working example of using some of these features. Addons work by intercepting event hooks - which must be registered. @@ -16,12 +18,12 @@ Future extensions may provide for "setup" amd "remove". Plugins should contain a comment block with the four following parameters: - /* - * Name: My Great Plugin - * Description: This is what my plugin does. It's really cool - * Version: 1.0 - * Author: John Q. Public - */ + /* + * Name: My Great Plugin + * Description: This is what my plugin does. It's really cool. + * Version: 1.0 + * Author: John Q. Public + */ Register your plugin hooks during installation. @@ -45,7 +47,7 @@ Your hook callback functions will be called with at least one and possibly two a If you wish to make changes to the calling data, you must declare them as reference variables (with '&') during function declaration. -###$a +#### $a $a is the Friendica 'App' class. It contains a wealth of information about the current state of Friendica: @@ -56,13 +58,13 @@ It contains a wealth of information about the current state of Friendica: It is recommeded you call this '$a' to match its usage elsewhere. -###$b +#### $b $b can be called anything you like. This is information specific to the hook currently being processed, and generally contains information that is being immediately processed or acted on that you can use, display, or alter. Remember to declare it with '&' if you wish to alter it. Modules --------- +--- Plugins/addons may also act as "modules" and intercept all page requests for a given URL path. In order for a plugin to act as a module it needs to define a function "plugin_name_module()" which takes no arguments and needs not do anything. @@ -72,15 +74,15 @@ These are parsed into an array $a->argv, with a corresponding $a->argc indicatin So http://my.web.site/plugin/arg1/arg2 would look for a module named "plugin" and pass its module functions the $a App structure (which is available to many components). This will include: - $a->argc = 3 - $a->argv = array(0 => 'plugin', 1 => 'arg1', 2 => 'arg2'); + $a->argc = 3 + $a->argv = array(0 => 'plugin', 1 => 'arg1', 2 => 'arg2'); Your module functions will often contain the function plugin_name_content(&$a), which defines and returns the page body content. They may also contain plugin_name_post(&$a) which is called before the _content function and typically handles the results of POST forms. You may also have plugin_name_init(&$a) which is called very early on and often does module initialisation. Templates ----------- +--- If your plugin needs some template, you can use the Friendica template system. Friendica uses [smarty3](http://www.smarty.net/) as a template engine. @@ -104,140 +106,140 @@ See also the wiki page [Quick Template Guide](https://github.com/friendica/frien Current hooks ------------- -###'authenticate' +### 'authenticate' 'authenticate' is called when a user attempts to login. $b is an array containing: - 'username' => the supplied username - 'password' => the supplied password + 'username' => the supplied username + 'password' => the supplied password 'authenticated' => set this to non-zero to authenticate the user. 'user_record' => successful authentication must also return a valid user record from the database -###'logged_in' +### 'logged_in' 'logged_in' is called after a user has successfully logged in. $b contains the $a->user array. -###'display_item' +### 'display_item' 'display_item' is called when formatting a post for display. $b is an array: 'item' => The item (array) details pulled from the database 'output' => the (string) HTML representation of this item prior to adding it to the page -###'post_local' +### 'post_local' * called when a status post or comment is entered on the local system * $b is the item array of the information to be stored in the database * Please note: body contents are bbcode - not HTML -###'post_local_end' +### 'post_local_end' * called when a local status post or comment has been stored on the local system * $b is the item array of the information which has just been stored in the database * Please note: body contents are bbcode - not HTML -###'post_remote' +### 'post_remote' * called when receiving a post from another source. This may also be used to post local activity or system generated messages. * $b is the item array of information to be stored in the database and the item body is bbcode. -###'settings_form' +### 'settings_form' * called when generating the HTML for the user Settings page * $b is the (string) HTML of the settings page before the final '' tag. -###'settings_post' +### 'settings_post' * called when the Settings pages are submitted * $b is the $_POST array -###'plugin_settings' +### 'plugin_settings' * called when generating the HTML for the addon settings page * $b is the (string) HTML of the addon settings page before the final '' tag. -###'plugin_settings_post' +### 'plugin_settings_post' * called when the Addon Settings pages are submitted * $b is the $_POST array -###'profile_post' +### 'profile_post' * called when posting a profile page * $b is the $_POST array -###'profile_edit' +### 'profile_edit' 'profile_edit' is called prior to output of profile edit page. $b is an array containing: 'profile' => profile (array) record from the database 'entry' => the (string) HTML of the generated entry -###'profile_advanced' +### 'profile_advanced' * called when the HTML is generated for the 'Advanced profile', corresponding to the 'Profile' tab within a person's profile page * $b is the (string) HTML representation of the generated profile * The profile array details are in $a->profile. -###'directory_item' +### 'directory_item' 'directory_item' is called from the Directory page when formatting an item for display. $b is an array: 'contact' => contact (array) record for the person from the database 'entry' => the (string) HTML of the generated entry -###'profile_sidebar_enter' +### 'profile_sidebar_enter' * called prior to generating the sidebar "short" profile for a page * $b is the person's profile array -###'profile_sidebar' +### 'profile_sidebar' 'profile_sidebar is called when generating the sidebar "short" profile for a page. $b is an array: 'profile' => profile (array) record for the person from the database 'entry' => the (string) HTML of the generated entry -###'contact_block_end' +### 'contact_block_end' is called when formatting the block of contacts/friends on a profile sidebar has completed. $b is an array: 'contacts' => array of contacts 'output' => the (string) generated HTML of the contact block -###'bbcode' +### 'bbcode' * called during conversion of bbcode to html * $b is a string converted text -###'html2bbcode' +### 'html2bbcode' * called during conversion of html to bbcode (e.g. remote message posting) * $b is a string converted text -###'page_header' +### 'page_header' * called after building the page navigation section * $b is a string HTML of nav region -###'personal_xrd' +### 'personal_xrd' 'personal_xrd' is called prior to output of personal XRD file. $b is an array: 'user' => the user record for the person 'xml' => the complete XML to be output -###'home_content' +### 'home_content' * called prior to output home page content, shown to unlogged users * $b is (string) HTML of section region -###'contact_edit' +### 'contact_edit' is called when editing contact details on an individual from the Contacts page. $b is an array: 'contact' => contact record (array) of target contact 'output' => the (string) generated HTML of the contact edit page -###'contact_edit_post' +### 'contact_edit_post' * called when posting the contact edit page. * $b is the $_POST array -###'init_1' +### 'init_1' * called just after DB has been opened and before session start * $b is not used or passed -###'page_end' +### 'page_end' * called after HTML content functions have completed * $b is (string) HTML of content div -###'avatar_lookup' +### 'avatar_lookup' 'avatar_lookup' is called when looking up the avatar. $b is an array: @@ -245,11 +247,11 @@ $b is an array: 'email' => email to look up the avatar for 'url' => the (string) generated URL of the avatar -###'emailer_send_prepare' +### 'emailer_send_prepare' 'emailer_send_prepare' called from Emailer::send() before building the mime message. $b is an array, params to Emailer::send() - 'fromName' => name of the sender + 'fromName' => name of the sender 'fromEmail' => email fo the sender 'replyTo' => replyTo address to direct responses 'toEmail' => destination email address @@ -258,20 +260,20 @@ $b is an array, params to Emailer::send() 'textVersion' => text only version of the message 'additionalMailHeader' => additions to the smtp mail header -###'emailer_send' +### 'emailer_send' is called before calling PHP's mail(). $b is an array, params to mail() - 'to' - 'subject' + 'to' + 'subject' 'body' 'headers' -###'nav_info' +### 'nav_info' is called after the navigational menu is build in include/nav.php. $b is an array containing $nav from nav.php. -###'template_vars' +### 'template_vars' is called before vars are passed to the template engine to render the page. The registered function can add,change or remove variables passed to template. $b is an array with: @@ -463,4 +465,3 @@ mod/cb.php: call_hooks('cb_afterpost'); mod/cb.php: call_hooks('cb_content', $o); mod/directory.php: call_hooks('directory_item', $arr); - diff --git a/doc/de/Plugins.md b/doc/de/Plugins.md index dcff41a4b..11113843b 100644 --- a/doc/de/Plugins.md +++ b/doc/de/Plugins.md @@ -1,27 +1,27 @@ -**Friendica Addon/Plugin-Entwicklung** +Friendica Addon/Plugin-Entwicklung ============== * [Zur Startseite der Hilfe](help) -Bitte schau dir das Beispiel-Addon "randplace" für ein funktionierendes Beispiel für manche der hier aufgeführten Funktionen an. -Das Facebook-Addon bietet ein Beispiel dafür, die "addon"- und "module"-Funktion gemeinsam zu integrieren. -Addons arbeiten, indem sie Event Hooks abfangen. Module arbeiten, indem bestimmte Seitenanfragen (durch den URL-Pfad) abgefangen werden +Bitte schau dir das Beispiel-Addon "randplace" für ein funktionierendes Beispiel für manche der hier aufgeführten Funktionen an. +Das Facebook-Addon bietet ein Beispiel dafür, die "addon"- und "module"-Funktion gemeinsam zu integrieren. +Addons arbeiten, indem sie Event Hooks abfangen. Module arbeiten, indem bestimmte Seitenanfragen (durch den URL-Pfad) abgefangen werden -Plugin-Namen können keine Leerstellen oder andere Interpunktionen enthalten und werden als Datei- und Funktionsnamen genutzt. -Du kannst einen lesbaren Namen im Kommentarblock eintragen. -Jedes Addon muss beides beinhalten - eine Installations- und eine Deinstallationsfunktion, die auf dem Addon-/Plugin-Namen basieren; z.B. "plugin1name_install()". -Diese beiden Funktionen haben keine Argumente und sind dafür verantwortlich, Event Hooks zu registrieren und abzumelden (unregistering), die dein Plugin benötigt. -Die Installations- und Deinstallationsfunktionfunktionen werden auch ausgeführt (z.B. neu installiert), wenn sich das Plugin nach der Installation ändert - somit sollte deine Deinstallationsfunktion keine Daten zerstört und deine Installationsfunktion sollte bestehende Daten berücksichtigen. +Plugin-Namen können keine Leerstellen oder andere Interpunktionen enthalten und werden als Datei- und Funktionsnamen genutzt. +Du kannst einen lesbaren Namen im Kommentarblock eintragen. +Jedes Addon muss beides beinhalten - eine Installations- und eine Deinstallationsfunktion, die auf dem Addon-/Plugin-Namen basieren; z.B. "plugin1name_install()". +Diese beiden Funktionen haben keine Argumente und sind dafür verantwortlich, Event Hooks zu registrieren und abzumelden (unregistering), die dein Plugin benötigt. +Die Installations- und Deinstallationsfunktionfunktionen werden auch ausgeführt (z.B. neu installiert), wenn sich das Plugin nach der Installation ändert - somit sollte deine Deinstallationsfunktion keine Daten zerstört und deine Installationsfunktion sollte bestehende Daten berücksichtigen. Zukünftige Extensions werden möglicherweise "Setup" und "Entfernen" anbieten. Plugins sollten einen Kommentarblock mit den folgenden vier Parametern enthalten: - /* - * Name: My Great Plugin - * Description: This is what my plugin does. It's really cool - * Version: 1.0 - * Author: John Q. Public - */ + /* + * Name: My Great Plugin + * Description: This is what my plugin does. It's really cool + * Version: 1.0 + * Author: John Q. Public + */ Registriere deine Plugin-Hooks während der Installation. @@ -29,45 +29,50 @@ Registriere deine Plugin-Hooks während der Installation. $hookname ist ein String und entspricht einem bekannten Friendica-Hook. -$file steht für den Pfadnamen, der relativ zum Top-Level-Friendicaverzeichnis liegt. +$file steht für den Pfadnamen, der relativ zum Top-Level-Friendicaverzeichnis liegt. Das *sollte* "addon/plugin_name/plugin_name.php' sein. $function ist ein String und der Name der Funktion, die ausgeführt wird, wenn der Hook aufgerufen wird. +Argumente +--- + Deine Hook-Callback-Funktion wird mit mindestens einem und bis zu zwei Argumenten aufgerufen function myhook_function(&$a, &$b) { } -Wenn du Änderungen an den aufgerufenen Daten vornehmen willst, musst du diese als Referenzvariable (mit "&") während der Funktionsdeklaration deklarieren. +Wenn du Änderungen an den aufgerufenen Daten vornehmen willst, musst du diese als Referenzvariable (mit "&") während der Funktionsdeklaration deklarieren. -$a ist die Friendica "App"-Klasse, die eine Menge an Informationen über den aktuellen Friendica-Status beinhaltet, u.a. welche Module genutzt werden, Konfigurationsinformationen, Inhalte der Seite zum Zeitpunkt des Hook-Aufrufs. -Es ist empfohlen, diese Funktion "$a" zu nennen, um seine Nutzung an den Gebrauch an anderer Stelle anzugleichen. +$a ist die Friendica "App"-Klasse, die eine Menge an Informationen über den aktuellen Friendica-Status beinhaltet, u.a. welche Module genutzt werden, Konfigurationsinformationen, Inhalte der Seite zum Zeitpunkt des Hook-Aufrufs. +Es ist empfohlen, diese Funktion "$a" zu nennen, um seine Nutzung an den Gebrauch an anderer Stelle anzugleichen. -$b kann frei benannt werden. -Diese Information ist speziell auf den Hook bezogen, der aktuell bearbeitet wird, und beinhaltet normalerweise Daten, die du sofort nutzen, anzeigen oder bearbeiten kannst. -Achte darauf, diese mit "&" zu deklarieren, wenn du sie bearbeiten willst. +$b kann frei benannt werden. +Diese Information ist speziell auf den Hook bezogen, der aktuell bearbeitet wird, und beinhaltet normalerweise Daten, die du sofort nutzen, anzeigen oder bearbeiten kannst. +Achte darauf, diese mit "&" zu deklarieren, wenn du sie bearbeiten willst. -**Module** +Module +--- -Plugins/Addons können auch als "Module" agieren und alle Seitenanfragen für eine bestimte URL abfangen. -Um ein Plugin als Modul zu nutzen, ist es nötig, die Funktion "plugin_name_module()" zu definieren, die keine Argumente benötigt und nichts weiter machen muss. +Plugins/Addons können auch als "Module" agieren und alle Seitenanfragen für eine bestimte URL abfangen. +Um ein Plugin als Modul zu nutzen, ist es nötig, die Funktion "plugin_name_module()" zu definieren, die keine Argumente benötigt und nichts weiter machen muss. -Wenn diese Funktion existiert, wirst du nun alle Seitenanfragen für "http://my.web.site/plugin_name" erhalten - mit allen URL-Komponenten als zusätzliche Argumente. -Diese werden in ein Array $a->argv geparst und stimmen mit $a->argc überein, wobei sie die Anzahl der URL-Komponenten abbilden. +Wenn diese Funktion existiert, wirst du nun alle Seitenanfragen für "http://my.web.site/plugin_name" erhalten - mit allen URL-Komponenten als zusätzliche Argumente. +Diese werden in ein Array $a->argv geparst und stimmen mit $a->argc überein, wobei sie die Anzahl der URL-Komponenten abbilden. So würde http://my.web.site/plugin/arg1/arg2 nach einem Modul "plugin" suchen und seiner Modulfunktion die $a-App-Strukur übergeben (dies ist für viele Komponenten verfügbar). Das umfasst: - $a->argc = 3 - $a->argv = array(0 => 'plugin', 1 => 'arg1', 2 => 'arg2'); + $a->argc = 3 + $a->argv = array(0 => 'plugin', 1 => 'arg1', 2 => 'arg2'); -Deine Modulfunktionen umfassen oft die Funktion plugin_name_content(&$a), welche den Seiteninhalt definiert und zurückgibt. -Sie können auch plugin_name_post(&$a) umfassen, welches vor der content-Funktion aufgerufen wird und normalerweise die Resultate der POST-Formulare handhabt. +Deine Modulfunktionen umfassen oft die Funktion plugin_name_content(&$a), welche den Seiteninhalt definiert und zurückgibt. +Sie können auch plugin_name_post(&$a) umfassen, welches vor der content-Funktion aufgerufen wird und normalerweise die Resultate der POST-Formulare handhabt. Du kannst ebenso plugin_name_init(&$a) nutzen, was oft frühzeitig aufgerufen wird und das Modul initialisert. -**Derzeitige Hooks:** +Derzeitige Hooks +--- **'authenticate'** - wird aufgerufen, wenn sich der User einloggt. $b ist ein Array @@ -180,6 +185,9 @@ Du kannst ebenso plugin_name_init(&$a) nutzen, was oft frühzeitig aufgerufen wi - wird aufgerufen nachdem in include/nav,php der Inhalt des Navigations Menüs erzeugt wurde. - $b ist ein Array, das $nav wiederspiegelt. +Komplette Liste der Hook-Callbacks +--- + Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 14-Feb-2012 generiert): Bitte schau in die Quellcodes für Details zu Hooks, die oben nicht dokumentiert sind. boot.php: call_hooks('login_hook',$o); @@ -204,7 +212,7 @@ include/text.php: call_hooks('contact_block_end', $arr); include/text.php: call_hooks('smilie', $s); -include/text.php: call_hooks('prepare_body_init', $item); +include/text.php: call_hooks('prepare_body_init', $item); include/text.php: call_hooks('prepare_body', $prep_arr); @@ -359,4 +367,3 @@ mod/cb.php: call_hooks('cb_afterpost'); mod/cb.php: call_hooks('cb_content', $o); mod/directory.php: call_hooks('directory_item', $arr); - From 92a31344b5e8e0c01aec325874a86808f7bba8e5 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Thu, 4 Feb 2016 20:34:18 +0100 Subject: [PATCH 027/126] 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 c4b3fed36..edbbde98a 100644 --- a/include/import-dfrn.php +++ b/include/import-dfrn.php @@ -5,6 +5,7 @@ require_once("include/socgraph.php"); require_once("include/items.php"); require_once("include/tags.php"); require_once("include/files.php"); +require_once("include/event.php"); class dfrn2 { @@ -702,6 +703,12 @@ class dfrn2 { $object = $xpath->query("activity:object", $entry)->item(0); $item["object"] = self::transform_activity($xpath, $object, "object"); + if (trim($item["object"]) != "") { + $r = parse_xml_string($item["object"], false); + if (isset($r->type)) + $item["object-type"] = $r->type; + } + $target = $xpath->query("activity:target", $entry)->item(0); $item["target"] = self::transform_activity($xpath, $target, "target"); @@ -790,7 +797,7 @@ class dfrn2 { if ($entrytype == DFRN_REPLY_RC) { $item["type"] = "remote-comment"; $item["wall"] = 1; - } else { + } elseif ($entrytype == DFRN_TOP_LEVEL) { // The Diaspora signature is only stored in replies // Since this isn't a field in the item table this would create a bug when inserting this in the item table unset($item["dsprsig"]); @@ -798,9 +805,11 @@ class dfrn2 { if (!isset($item["object-type"])) $item["object-type"] = ACTIVITY_OBJ_NOTE; - if ($item["object-type"] === ACTIVITY_OBJ_EVENT) { + if ($item["object-type"] == ACTIVITY_OBJ_EVENT) { + logger("Item ".$item["uri"]." seems to contain an event.", LOGGER_DEBUG); $ev = bbtoevent($item["body"]); if((x($ev, "desc") || x($ev, "summary")) && x($ev, "start")) { + logger("Event in item ".$item["uri"]." was found.", LOGGER_DEBUG); $ev["cid"] = $importer["id"]; $ev["uid"] = $importer["uid"]; $ev["uri"] = $item["uri"]; @@ -814,9 +823,10 @@ class dfrn2 { ); if(count($r)) $ev["id"] = $r[0]["id"]; - $xyz = event_store($ev); - logger("Event ".$ev["id"]." was stored", LOGGER_DEBUG); - return; + + $event_id = event_store($ev); + logger("Event ".$event_id." was stored", LOGGER_DEBUG); + return; } } } From 48e6ff21aa50b428a970c53f1f6618c4794fa043 Mon Sep 17 00:00:00 2001 From: Andrej Stieben Date: Thu, 4 Feb 2016 21:45:21 +0100 Subject: [PATCH 028/126] Added the possibility for themes to override core module functions --- doc/themes.md | 16 ++++++++++++++-- index.php | 11 ++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/doc/themes.md b/doc/themes.md index add44c776..ec3a76ac2 100644 --- a/doc/themes.md +++ b/doc/themes.md @@ -59,7 +59,19 @@ The same rule applies to the JavaScript files found in they will be overwritten by files in - /view/theme/**your-theme-name**/js. + /view/theme/**your-theme-name**/js + +### Modules + +You have the freedom to override core modules found in + + /mod + +They will be overwritten by files in + + /view/theme/**your-theme-name**/mod + +Be aware that you can break things easily here if you don't know what you do. Also notice that you can override parts of the module – functions not defined in your theme module will be loaded from the core module. ## Expand an existing Theme @@ -288,4 +300,4 @@ The default file is in /view/default.php if you want to change it, say adding a 4th column for banners of your favourite FLOSS projects, place a new default.php file in your theme directory. -As with the theme.php file, you can use the properties of the $a variable with holds the friendica application to decide what content is displayed. \ No newline at end of file +As with the theme.php file, you can use the properties of the $a variable with holds the friendica application to decide what content is displayed. diff --git a/index.php b/index.php index bf926d1fe..2b1053cc1 100644 --- a/index.php +++ b/index.php @@ -233,7 +233,16 @@ if(strlen($a->module)) { } /** - * If not, next look for a 'standard' program module in the 'mod' directory + * If not, next look for module overrides by the theme + */ + + if((! $a->module_loaded) && (file_exists("view/theme/" . current_theme() . "/mod/{$a->module}.php"))) { + include_once("view/theme/" . current_theme() . "/mod/{$a->module}.php"); + // We will not set module_loaded to true to allow for partial overrides. + } + + /** + * Finally, look for a 'standard' program module in the 'mod' directory */ if((! $a->module_loaded) && (file_exists("mod/{$a->module}.php"))) { From 2bd36e562889803841588a276232ef5fa819730a Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Thu, 4 Feb 2016 23:52:06 +0100 Subject: [PATCH 029/126] 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 edbbde98a..72d507bbf 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 0ec645cc7..52a1071f2 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 030/126] 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 72d507bbf..244018887 100644 --- a/include/import-dfrn.php +++ b/include/import-dfrn.php @@ -829,6 +829,26 @@ class dfrn2 { return; } } +/* + if(activity_match($item['verb'],ACTIVITY_FOLLOW)) { + logger('consume-feed: New follower'); + new_follower($importer,$contact,$item); + return; + } + if(activity_match($item['verb'],ACTIVITY_UNFOLLOW)) { + lose_follower($importer,$contact,$item); + return; + } + if(activity_match($item['verb'],ACTIVITY_REQ_FRIEND)) { + logger('consume-feed: New friend request'); + new_follower($importer,$contact,$item,(?),true); + return; + } + if(activity_match($item['verb'],ACTIVITY_UNFRIEND)) { + lose_sharer($importer,$contact,$item); + return; + } +*/ } $r = q("SELECT `id`, `uid`, `last-child`, `edited`, `body` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", @@ -1125,11 +1145,11 @@ class dfrn2 { return; if($importer["readonly"]) { - // We aren't receiving stuff from this person. But we will quietly ignore them - // rather than a blatant "go away" message. - logger('ignoring contact '.$importer["id"]); - return; - } + // We aren't receiving stuff from this person. But we will quietly ignore them + // rather than a blatant "go away" message. + logger('ignoring contact '.$importer["id"]); + return; + } $doc = new DOMDocument(); @$doc->loadXML($xml); @@ -1163,6 +1183,7 @@ class dfrn2 { // is it a public forum? Private forums aren't supported by now with this method $forum = intval($xpath->evaluate("/atom:feed/dfrn:community/text()", $context)->item(0)->nodeValue); + /// @todo Check the opposite as well (forum changed to non-forum) if ($forum) q("UPDATE `contact` SET `forum` = %d WHERE `forum` != %d AND `id` = %d", intval($forum), intval($forum), From a81d929cdf223ac0ecf5407a3696db788cd705c4 Mon Sep 17 00:00:00 2001 From: Andrej Stieben Date: Fri, 5 Feb 2016 14:11:10 +0100 Subject: [PATCH 031/126] Minor documentation update, as requested by @tobiasd --- doc/de/Plugins.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/de/Plugins.md b/doc/de/Plugins.md index 11113843b..40be4a069 100644 --- a/doc/de/Plugins.md +++ b/doc/de/Plugins.md @@ -5,7 +5,8 @@ Friendica Addon/Plugin-Entwicklung Bitte schau dir das Beispiel-Addon "randplace" für ein funktionierendes Beispiel für manche der hier aufgeführten Funktionen an. Das Facebook-Addon bietet ein Beispiel dafür, die "addon"- und "module"-Funktion gemeinsam zu integrieren. -Addons arbeiten, indem sie Event Hooks abfangen. Module arbeiten, indem bestimmte Seitenanfragen (durch den URL-Pfad) abgefangen werden +Addons arbeiten, indem sie Event Hooks abfangen. +Module arbeiten, indem bestimmte Seitenanfragen (durch den URL-Pfad) abgefangen werden. Plugin-Namen können keine Leerstellen oder andere Interpunktionen enthalten und werden als Datei- und Funktionsnamen genutzt. Du kannst einen lesbaren Namen im Kommentarblock eintragen. @@ -18,7 +19,7 @@ Plugins sollten einen Kommentarblock mit den folgenden vier Parametern enthalten /* * Name: My Great Plugin - * Description: This is what my plugin does. It's really cool + * Description: This is what my plugin does. It's really cool. * Version: 1.0 * Author: John Q. Public */ @@ -59,9 +60,9 @@ Module Plugins/Addons können auch als "Module" agieren und alle Seitenanfragen für eine bestimte URL abfangen. Um ein Plugin als Modul zu nutzen, ist es nötig, die Funktion "plugin_name_module()" zu definieren, die keine Argumente benötigt und nichts weiter machen muss. -Wenn diese Funktion existiert, wirst du nun alle Seitenanfragen für "http://my.web.site/plugin_name" erhalten - mit allen URL-Komponenten als zusätzliche Argumente. +Wenn diese Funktion existiert, wirst du nun alle Seitenanfragen für "http://example.com/plugin_name" erhalten - mit allen URL-Komponenten als zusätzliche Argumente. Diese werden in ein Array $a->argv geparst und stimmen mit $a->argc überein, wobei sie die Anzahl der URL-Komponenten abbilden. -So würde http://my.web.site/plugin/arg1/arg2 nach einem Modul "plugin" suchen und seiner Modulfunktion die $a-App-Strukur übergeben (dies ist für viele Komponenten verfügbar). Das umfasst: +So würde http://example.com/plugin/arg1/arg2 nach einem Modul "plugin" suchen und seiner Modulfunktion die $a-App-Strukur übergeben (dies ist für viele Komponenten verfügbar). Das umfasst: $a->argc = 3 $a->argv = array(0 => 'plugin', 1 => 'arg1', 2 => 'arg2'); From f70f4bb89937d3056f71d8a2d5ba32836946186e Mon Sep 17 00:00:00 2001 From: fabrixxm Date: Fri, 5 Feb 2016 18:43:46 +0100 Subject: [PATCH 032/126] ACL: fix TypeError when selecting permissions --- js/acl.js | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/js/acl.js b/js/acl.js index 8e4e06c83..3c96d1346 100644 --- a/js/acl.js +++ b/js/acl.js @@ -28,7 +28,7 @@ function ACL(backend_url, preset, automention, is_mobile){ if (preset.length==0) this.showall.addClass("selected"); /*events*/ - this.showall.click(this.on_showall); + this.showall.click(this.on_showall.bind(this)); $(document).on("click", ".acl-button-show", this.on_button_show.bind(this)); $(document).on("click", ".acl-button-hide", this.on_button_hide.bind(this)); $("#acl-search").keypress(this.on_search.bind(this)); @@ -123,12 +123,8 @@ ACL.prototype.on_button_show = function(event){ event.preventDefault() event.stopImmediatePropagation() event.stopPropagation(); - - /*this.showall.removeClass("selected"); - $(this).siblings(".acl-button-hide").removeClass("selected"); - $(this).toggleClass("selected");*/ - - this.set_allow($(this).parent().attr('id')); + + this.set_allow($(event.target).parent().attr('id')); return false; } @@ -137,11 +133,7 @@ ACL.prototype.on_button_hide = function(event){ event.stopImmediatePropagation() event.stopPropagation(); - /*this.showall.removeClass("selected"); - $(this).siblings(".acl-button-show").removeClass("selected"); - $(this).toggleClass("selected");*/ - - this.set_deny($(this).parent().attr('id')); + this.set_deny($(event.target).parent().attr('id')); return false; } @@ -303,7 +295,7 @@ ACL.prototype.populate = function(data){ html = "
"+this.item_tpl+"
"; html = html.format(item.photo, item.name, item.type, item.id, (item.forum=='1'?'forum':''), item.network, item.link); if (item.uids!=undefined) this.group_uids[item.id] = item.uids; - //console.log(html); + this.list_content.append(html); this.data[item.id] = item; }.bind(this)); From 41405ed0f2ff24dff89e11e5ecd695fb4cf11066 Mon Sep 17 00:00:00 2001 From: rabuzarus <> Date: Fri, 5 Feb 2016 21:24:01 +0100 Subject: [PATCH 033/126] vier: display smiley-preview as inline-block - needs addons update --- view/theme/vier/dark.css | 5 +++++ view/theme/vier/style.css | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/view/theme/vier/dark.css b/view/theme/vier/dark.css index 8e128ae27..7c671e4b7 100644 --- a/view/theme/vier/dark.css +++ b/view/theme/vier/dark.css @@ -63,3 +63,8 @@ li :hover { #viewcontact_wrapper-network { background-color: #343434; } + +table.smiley-preview{ + background-color: #252C33 !important; + box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.7); +} \ No newline at end of file diff --git a/view/theme/vier/style.css b/view/theme/vier/style.css index 0b52b5096..2b78d25d7 100644 --- a/view/theme/vier/style.css +++ b/view/theme/vier/style.css @@ -2024,6 +2024,15 @@ section.minimal { cursor: pointer; margin-top: 3px; height: 10px; + display: inline-block; +} +#smileybutton { + position: absolute; + z-index: 99; +} +table.smiley-preview{ + background-color: #FFF; + box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.7); } #jot-perms-icon { float: right; From d408cea871e00a7f3c5e58b466395802eba523f7 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Fri, 5 Feb 2016 21:25:20 +0100 Subject: [PATCH 034/126] 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 5ef942dd0..021ceb996 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 52a1071f2..798ee5695 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 4aa777b55..780fb456f 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -1,6 +1,7 @@ Date: Fri, 5 Feb 2016 21:30:31 +0100 Subject: [PATCH 035/126] vier smileybutton: little polish in dark.css --- view/theme/vier/dark.css | 1 - 1 file changed, 1 deletion(-) diff --git a/view/theme/vier/dark.css b/view/theme/vier/dark.css index 7c671e4b7..5ddaf71a2 100644 --- a/view/theme/vier/dark.css +++ b/view/theme/vier/dark.css @@ -66,5 +66,4 @@ li :hover { table.smiley-preview{ background-color: #252C33 !important; - box-shadow: 0px 5px 10px rgba(0, 0, 0, 0.7); } \ No newline at end of file From 1c82e9f209eb72a7ed8d0fc1ee6a66b8d02d4110 Mon Sep 17 00:00:00 2001 From: Michael Vogel Date: Fri, 5 Feb 2016 21:31:11 +0100 Subject: [PATCH 036/126] 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 4c1f21dd0..e286b75cc 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 244018887..000000000 --- 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 caaeec84f..00022f8c6 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -1312,6 +1312,10 @@ function ostatus_add_author($doc, $owner) { function ostatus_entry($doc, $item, $owner, $toplevel = false, $repeat = false) { $a = get_app(); + if (($item["id"] != $item["parent"]) AND (normalise_link($item["author-link"]) != normalise_link($owner["url"]))) { + logger("OStatus entry is from author ".$owner["url"]." - not from ".$item["author-link"].". Quitting.", LOGGER_DEBUG); + } + $is_repeat = false; /* if (!$repeat) { From bcf10206359ee610c3a3f19c53d54563ae7dd8ca Mon Sep 17 00:00:00 2001 From: rabuzarus <> Date: Fri, 5 Feb 2016 21:38:55 +0100 Subject: [PATCH 037/126] vier smileybutton: dark.css insert new line at the end of the file --- view/theme/vier/dark.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/view/theme/vier/dark.css b/view/theme/vier/dark.css index 5ddaf71a2..d9b419e18 100644 --- a/view/theme/vier/dark.css +++ b/view/theme/vier/dark.css @@ -66,4 +66,4 @@ li :hover { table.smiley-preview{ background-color: #252C33 !important; -} \ No newline at end of file +} From db949bb802448184bfe5164d8d3dd86ddf51b187 Mon Sep 17 00:00:00 2001 From: Andrej Stieben Date: Fri, 5 Feb 2016 21:52:39 +0100 Subject: [PATCH 038/126] Updated modules to allow for partial overrides without errors Only define functions if they have not been defined before, e.g. in themes. This makes it possible to override parts of a module and still use the other functions. --- mod/_well_known.php | 4 ++ mod/acctlink.php | 3 +- mod/acl.php | 4 +- mod/admin.php | 78 ++++++++++++++++++++++++++++----------- mod/allfriends.php | 2 + mod/amcd.php | 5 ++- mod/api.php | 11 +++--- mod/apps.php | 40 ++++++++++---------- mod/attach.php | 3 +- mod/babel.php | 46 ++++++++++++----------- mod/bookmarklet.php | 5 ++- mod/cb.php | 11 +++++- mod/common.php | 2 + mod/community.php | 13 ++++--- mod/contactgroup.php | 4 +- mod/contacts.php | 38 +++++++++++++++---- mod/content.php | 48 ++++++++++++------------ mod/credits.php | 2 + mod/crepair.php | 10 +++-- mod/delegate.php | 10 +++-- mod/dfrn_confirm.php | 3 +- mod/dfrn_notify.php | 6 ++- mod/dfrn_poll.php | 13 ++++--- mod/directory.php | 19 +++++----- mod/dirfind.php | 6 ++- mod/display.php | 9 +++-- mod/editpost.php | 5 +-- mod/events.php | 6 ++- mod/fbrowser.php | 3 +- mod/filer.php | 5 ++- mod/filerm.php | 2 + mod/follow.php | 4 ++ mod/friendica.php | 11 +++--- mod/fsuggest.php | 19 +++++----- mod/group.php | 11 ++++-- mod/hcard.php | 10 ++--- mod/help.php | 3 +- mod/hostxrd.php | 3 +- mod/ignored.php | 3 +- mod/install.php | 55 ++++++++++++++++++--------- mod/invite.php | 13 ++++--- mod/item.php | 13 +++++-- mod/like.php | 7 ++-- mod/localtime.php | 11 +++--- mod/lockview.php | 20 +++++----- mod/login.php | 4 +- mod/lostpass.php | 7 ++-- mod/maintenance.php | 3 +- mod/manage.php | 8 ++-- mod/match.php | 2 + mod/message.php | 13 +++++-- mod/modexp.php | 4 +- mod/mood.php | 10 ++--- mod/msearch.php | 9 +++-- mod/navigation.php | 3 +- mod/network.php | 17 +++++++-- mod/newmember.php | 10 +++-- mod/nodeinfo.php | 11 ++++-- mod/nogroup.php | 6 ++- mod/noscrape.php | 3 +- mod/notes.php | 20 +++++----- mod/notice.php | 9 +++-- mod/notifications.php | 6 ++- mod/notify.php | 8 ++-- mod/oembed.php | 4 +- mod/oexchange.php | 17 ++++----- mod/openid.php | 10 ++--- mod/opensearch.php | 16 ++++---- mod/ostatus_subscribe.php | 2 + mod/p.php | 4 +- mod/parse_url.php | 18 +++++++-- mod/photo.php | 2 + mod/photos.php | 15 ++++---- mod/ping.php | 4 ++ mod/poco.php | 3 +- mod/poke.php | 12 +++--- mod/post.php | 7 ++-- mod/pretheme.php | 4 +- mod/probe.php | 4 +- mod/profile.php | 7 ++-- mod/profile_photo.php | 26 ++++++------- mod/profiles.php | 14 +++++-- mod/profperm.php | 12 +++--- mod/proxy.php | 12 ++++++ mod/pubsub.php | 20 +++++----- mod/pubsubhubbub.php | 5 ++- mod/qsearch.php | 3 +- mod/randprof.php | 3 +- mod/receive.php | 4 +- mod/redir.php | 6 ++- mod/regmod.php | 9 +++-- mod/removeme.php | 6 ++- mod/repair_ostatus.php | 2 + mod/rsd_xml.php | 6 +-- mod/salmon.php | 7 +++- mod/search.php | 14 ++++--- mod/session.php | 3 +- mod/settings.php | 16 ++++---- mod/share.php | 9 ++++- mod/smilies.php | 6 ++- mod/starred.php | 3 +- mod/statistics_json.php | 2 + mod/subthread.php | 12 +++--- mod/suggest.php | 9 +++-- mod/tagger.php | 8 ++-- mod/tagrm.php | 9 +++-- mod/toggle_mobile.php | 3 +- mod/uexport.php | 30 +++++++++------ mod/uimport.php | 12 ++++-- mod/update_community.php | 5 ++- mod/update_display.php | 3 +- mod/update_network.php | 3 +- mod/update_notes.php | 9 +++-- mod/update_profile.php | 9 +++-- mod/videos.php | 12 +++--- mod/view.php | 10 +++-- mod/viewcontacts.php | 5 ++- mod/viewsrc.php | 6 +-- mod/wall_attach.php | 2 + mod/wall_upload.php | 2 + mod/wallmessage.php | 12 +++--- mod/webfinger.php | 6 +-- mod/xrd.php | 3 +- 123 files changed, 768 insertions(+), 471 deletions(-) diff --git a/mod/_well_known.php b/mod/_well_known.php index 33070a1ec..6c33136f9 100644 --- a/mod/_well_known.php +++ b/mod/_well_known.php @@ -2,6 +2,7 @@ require_once("mod/hostxrd.php"); require_once("mod/nodeinfo.php"); +if(! function_exists('_well_known_init')) { function _well_known_init(&$a){ if ($a->argc > 1) { switch($a->argv[1]) { @@ -19,7 +20,9 @@ function _well_known_init(&$a){ http_status_exit(404); killme(); } +} +if(! function_exists('wk_social_relay')) { function wk_social_relay(&$a) { define('SR_SCOPE_ALL', 'all'); @@ -64,3 +67,4 @@ function wk_social_relay(&$a) { echo json_encode($relay, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES); exit; } +} diff --git a/mod/acctlink.php b/mod/acctlink.php index a2365803a..a551e3dbd 100644 --- a/mod/acctlink.php +++ b/mod/acctlink.php @@ -2,8 +2,8 @@ require_once('include/Scrape.php'); +if(! function_exists('acctlink_init')) { function acctlink_init(&$a) { - if(x($_GET,'addr')) { $addr = trim($_GET['addr']); $res = probe_url($addr); @@ -14,3 +14,4 @@ function acctlink_init(&$a) { } } } +} diff --git a/mod/acl.php b/mod/acl.php index f5e04b96a..5666ccabb 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 7f9000807..ff17c0b8c 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -2,7 +2,7 @@ /** * @file mod/admin.php - * + * * @brief Friendica admin */ @@ -23,6 +23,7 @@ require_once("include/text.php"); * @param App $a * */ +if(! function_exists('admin_post')) { function admin_post(&$a){ @@ -110,6 +111,7 @@ function admin_post(&$a){ goaway($a->get_baseurl(true) . '/admin' ); return; // NOTREACHED } +} /** * @brief Generates content of the admin panel pages @@ -128,6 +130,7 @@ function admin_post(&$a){ * @param App $a * @return string */ +if(! function_exists('admin_content')) { function admin_content(&$a) { if(!is_site_admin()) { @@ -245,6 +248,7 @@ function admin_content(&$a) { return $o; } } +} /** * @brief Subpage with some stats about "the federation" network @@ -260,6 +264,7 @@ function admin_content(&$a) { * @param App $a * @return string */ +if(! function_exists('admin_page_federation')) { function admin_page_federation(&$a) { // get counts on active friendica, diaspora, redmatrix, hubzilla, gnu // social and statusnet nodes this node is knowing @@ -284,7 +289,7 @@ function admin_page_federation(&$a) { // what versions for that platform do we know at all? // again only the active nodes $v = q('SELECT count(*) AS total, version FROM gserver - WHERE last_contact > last_failure AND platform LIKE "%s" + WHERE last_contact > last_failure AND platform LIKE "%s" GROUP BY version ORDER BY version;', $p); @@ -301,12 +306,12 @@ function admin_page_federation(&$a) { $newVC = $vv['total']; $newVV = $vv['version']; $posDash = strpos($newVV, '-'); - if($posDash) + if($posDash) $newVV = substr($newVV, 0, $posDash); if(isset($newV[$newVV])) - $newV[$newVV] += $newVC; + $newV[$newVV] += $newVC; else - $newV[$newVV] = $newVC; + $newV[$newVV] = $newVC; } foreach ($newV as $key => $value) { array_push($newVv, array('total'=>$value, 'version'=>$key)); @@ -361,6 +366,7 @@ function admin_page_federation(&$a) { '$baseurl' => $a->get_baseurl(), )); } +} /** * @brief Admin Inspect Queue Page @@ -375,6 +381,7 @@ function admin_page_federation(&$a) { * @param App $a * @return string */ +if(! function_exists('admin_page_queue')) { function admin_page_queue(&$a) { // get content from the queue table $r = q("SELECT c.name,c.nurl,q.id,q.network,q.created,q.last from queue as q, contact as c where c.id=q.cid order by q.cid, q.created;"); @@ -394,6 +401,7 @@ function admin_page_queue(&$a) { '$entries' => $r, )); } +} /** * @brief Admin Summary Page @@ -406,6 +414,7 @@ function admin_page_queue(&$a) { * @param App $a * @return string */ +if(! function_exists('admin_page_summary')) { function admin_page_summary(&$a) { $r = q("SELECT `page-flags`, COUNT(uid) as `count` FROM `user` GROUP BY `page-flags`"); $accounts = array( @@ -452,12 +461,14 @@ function admin_page_summary(&$a) { '$plugins' => array( t('Active plugins'), $a->plugins ) )); } +} /** * @brief Process send data from Admin Site Page - * + * * @param App $a */ +if(! function_exists('admin_page_site_post')) { function admin_page_site_post(&$a) { if(!x($_POST,"page_site")) { return; @@ -770,6 +781,7 @@ function admin_page_site_post(&$a) { return; // NOTREACHED } +} /** * @brief Generate Admin Site subpage @@ -779,6 +791,7 @@ function admin_page_site_post(&$a) { * @param App $a * @return string */ +if(! function_exists('admin_page_site')) { function admin_page_site(&$a) { /* Installed langs */ @@ -983,7 +996,7 @@ function admin_page_site(&$a) { '$form_security_token' => get_form_security_token("admin_site") )); - +} } /** @@ -998,6 +1011,7 @@ function admin_page_site(&$a) { * @param App $a * @return string **/ +if(! function_exists('admin_page_dbsync')) { function admin_page_dbsync(&$a) { $o = ''; @@ -1073,14 +1087,15 @@ function admin_page_dbsync(&$a) { } return $o; - +} } /** * @brief Process data send by Users admin page - * + * * @param App $a */ +if(! function_exists('admin_page_users_post')) { function admin_page_users_post(&$a){ $pending = ( x($_POST, 'pending') ? $_POST['pending'] : array() ); $users = ( x($_POST, 'user') ? $_POST['user'] : array() ); @@ -1171,6 +1186,7 @@ function admin_page_users_post(&$a){ goaway($a->get_baseurl(true) . '/admin/users' ); return; // NOTREACHED } +} /** * @brief Admin panel subpage for User management @@ -1184,6 +1200,7 @@ function admin_page_users_post(&$a){ * @param App $a * @return string */ +if(! function_exists('admin_page_users')) { function admin_page_users(&$a){ if($a->argc>2) { $uid = $a->argv[3]; @@ -1336,7 +1353,7 @@ function admin_page_users(&$a){ $o .= paginate($a); return $o; } - +} /** * @brief Plugins admin page @@ -1354,6 +1371,7 @@ function admin_page_users(&$a){ * @param App $a * @return string */ +if(! function_exists('admin_page_plugins')) { function admin_page_plugins(&$a){ /* @@ -1479,17 +1497,19 @@ function admin_page_plugins(&$a){ '$baseurl' => $a->get_baseurl(true), '$function' => 'plugins', '$plugins' => $plugins, - '$pcount' => count($plugins), + '$pcount' => count($plugins), '$noplugshint' => sprintf( t('There are currently no plugins available on your node. You can find the official plugin repository at %1$s and might find other interesting plugins in the open plugin registry at %2$s'), 'https://github.com/friendica/friendica-addons', 'http://addons.friendi.ca'), '$form_security_token' => get_form_security_token("admin_themes"), )); } +} /** * @param array $themes * @param string $th * @param int $result */ +if(! function_exists('toggle_theme')) { function toggle_theme(&$themes,$th,&$result) { for($x = 0; $x < count($themes); $x ++) { if($themes[$x]['name'] === $th) { @@ -1504,12 +1524,14 @@ function toggle_theme(&$themes,$th,&$result) { } } } +} /** * @param array $themes * @param string $th * @return int */ +if(! function_exists('theme_status')) { function theme_status($themes,$th) { for($x = 0; $x < count($themes); $x ++) { if($themes[$x]['name'] === $th) { @@ -1523,12 +1545,13 @@ function theme_status($themes,$th) { } return 0; } - +} /** * @param array $themes * @return string */ +if(! function_exists('rebuild_theme_table')) { function rebuild_theme_table($themes) { $o = ''; if(count($themes)) { @@ -1542,7 +1565,7 @@ function rebuild_theme_table($themes) { } return $o; } - +} /** * @brief Themes admin page @@ -1560,6 +1583,7 @@ function rebuild_theme_table($themes) { * @param App $a * @return string */ +if(! function_exists('admin_page_themes')) { function admin_page_themes(&$a){ $allowed_themes_str = get_config('system','allowed_themes'); @@ -1734,13 +1758,14 @@ function admin_page_themes(&$a){ '$form_security_token' => get_form_security_token("admin_themes"), )); } - +} /** * @brief Prosesses data send by Logs admin page - * + * * @param App $a */ +if(! function_exists('admin_page_logs_post')) { function admin_page_logs_post(&$a) { if(x($_POST,"page_logs")) { check_form_security_token_redirectOnErr('/admin/logs', 'admin_logs'); @@ -1758,6 +1783,7 @@ function admin_page_logs_post(&$a) { goaway($a->get_baseurl(true) . '/admin/logs' ); return; // NOTREACHED } +} /** * @brief Generates admin panel subpage for configuration of the logs @@ -1775,6 +1801,7 @@ function admin_page_logs_post(&$a) { * @param App $a * @return string */ +if(! function_exists('admin_page_logs')) { function admin_page_logs(&$a){ $log_choices = array( @@ -1806,6 +1833,7 @@ function admin_page_logs(&$a){ '$phplogcode' => "error_reporting(E_ERROR | E_WARNING | E_PARSE );\nini_set('error_log','php.out');\nini_set('log_errors','1');\nini_set('display_errors', '1');", )); } +} /** * @brief Generates admin panel subpage to view the Friendica log @@ -1825,6 +1853,7 @@ function admin_page_logs(&$a){ * @param App $a * @return string */ +if(! function_exists('admin_page_viewlogs')) { function admin_page_viewlogs(&$a){ $t = get_markup_template("admin_viewlogs.tpl"); $f = get_config('system','logfile'); @@ -1861,12 +1890,14 @@ function admin_page_viewlogs(&$a){ '$logname' => get_config('system','logfile') )); } +} /** * @brief Prosesses data send by the features admin page - * + * * @param App $a */ +if(! function_exists('admin_page_features_post')) { function admin_page_features_post(&$a) { check_form_security_token_redirectOnErr('/admin/features', 'admin_manage_features'); @@ -1898,23 +1929,25 @@ function admin_page_features_post(&$a) { goaway($a->get_baseurl(true) . '/admin/features' ); return; // NOTREACHED } +} /** * @brief Subpage for global additional feature management - * + * * This functin generates the subpage 'Manage Additional Features' * for the admin panel. At this page the admin can set preferences - * for the user settings of the 'additional features'. If needed this + * for the user settings of the 'additional features'. If needed this * preferences can be locked through the admin. - * + * * The returned string contains the HTML code of the subpage 'Manage * Additional Features' - * + * * @param App $a * @return string */ +if(! function_exists('admin_page_features')) { function admin_page_features(&$a) { - + if((argc() > 1) && (argv(1) === 'features')) { $arr = array(); $features = get_features(false); @@ -1933,7 +1966,7 @@ function admin_page_features(&$a) { ); } } - + $tpl = get_markup_template("admin_settings_features.tpl"); $o .= replace_macros($tpl, array( '$form_security_token' => get_form_security_token("admin_manage_features"), @@ -1945,3 +1978,4 @@ function admin_page_features(&$a) { return $o; } } +} diff --git a/mod/allfriends.php b/mod/allfriends.php index 356a389b8..8843265a9 100644 --- a/mod/allfriends.php +++ b/mod/allfriends.php @@ -5,6 +5,7 @@ require_once('include/Contact.php'); require_once('include/contact_selectors.php'); require_once('mod/contacts.php'); +if(! function_exists('allfriends_content')) { function allfriends_content(&$a) { $o = ''; @@ -97,3 +98,4 @@ function allfriends_content(&$a) { return $o; } +} diff --git a/mod/amcd.php b/mod/amcd.php index a2a1327e6..141a80429 100644 --- a/mod/amcd.php +++ b/mod/amcd.php @@ -1,5 +1,5 @@ get_parameters(); $token = $params['oauth_token']; @@ -19,9 +17,10 @@ function oauth_get_client($request){ return $r[0]; } +} +if(! function_exists('api_post')) { function api_post(&$a) { - if(! local_user()) { notice( t('Permission denied.') . EOL); return; @@ -31,9 +30,10 @@ function api_post(&$a) { notice( t('Permission denied.') . EOL); return; } - +} } +if(! function_exists('api_content')) { function api_content(&$a) { if ($a->cmd=='api/oauth/authorize'){ /* @@ -114,3 +114,4 @@ function api_content(&$a) { echo api_call($a); killme(); } +} diff --git a/mod/apps.php b/mod/apps.php index a821ef5d5..e807feae7 100644 --- a/mod/apps.php +++ b/mod/apps.php @@ -1,25 +1,23 @@ apps)==0) + notice( t('No installed applications.') . EOL); + + $tpl = get_markup_template("apps.tpl"); + return replace_macros($tpl, array( + '$title' => $title, + '$apps' => $a->apps, + )); } - - $title = t('Applications'); - - if(count($a->apps)==0) - notice( t('No installed applications.') . EOL); - - - $tpl = get_markup_template("apps.tpl"); - return replace_macros($tpl, array( - '$title' => $title, - '$apps' => $a->apps, - )); - - - } diff --git a/mod/attach.php b/mod/attach.php index 03f850f0d..849faa26e 100644 --- a/mod/attach.php +++ b/mod/attach.php @@ -1,7 +1,7 @@ argc != 2) { @@ -47,3 +47,4 @@ function attach_init(&$a) { killme(); // NOTREACHED } +} diff --git a/mod/babel.php b/mod/babel.php index d31e090c5..56455bdb2 100644 --- a/mod/babel.php +++ b/mod/babel.php @@ -9,55 +9,56 @@ 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; @@ -66,14 +67,15 @@ 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 be8645c1f..4db6bf401 100644 --- a/mod/bookmarklet.php +++ b/mod/bookmarklet.php @@ -1,12 +1,14 @@ '.t('Login').''; @@ -44,3 +46,4 @@ function bookmarklet_content(&$a) { return $o; } +} diff --git a/mod/cb.php b/mod/cb.php index 6375d2398..04d01302c 100644 --- a/mod/cb.php +++ b/mod/cb.php @@ -4,21 +4,28 @@ * General purpose landing page for plugins/addons */ - +if(! function_exists('cb_init')) { function cb_init(&$a) { call_hooks('cb_init'); } +} +if(! function_exists('cb_post')) { function cb_post(&$a) { call_hooks('cb_post', $_POST); } +} +if(! function_exists('cb_afterpost')) { function cb_afterpost(&$a) { call_hooks('cb_afterpost'); } +} +if(! function_exists('cb_content')) { function cb_content(&$a) { $o = ''; call_hooks('cb_content', $o); return $o; -} \ No newline at end of file +} +} diff --git a/mod/common.php b/mod/common.php index c9409b3ef..4cdbe9641 100644 --- a/mod/common.php +++ b/mod/common.php @@ -5,6 +5,7 @@ require_once('include/Contact.php'); require_once('include/contact_selectors.php'); require_once('mod/contacts.php'); +if(! function_exists('common_content')) { function common_content(&$a) { $o = ''; @@ -144,3 +145,4 @@ function common_content(&$a) { return $o; } +} diff --git a/mod/community.php b/mod/community.php index b6d72a355..c64c6216b 100644 --- a/mod/community.php +++ b/mod/community.php @@ -1,15 +1,14 @@ data['contact']['network'] != "") AND ($a->data['contact']['network'] != NETWORK_DFRN)) { $networkname = format_network_name($a->data['contact']['network'],$a->data['contact']['url']); - } else + } else $networkname = ''; $vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"),array( @@ -88,9 +89,10 @@ function contacts_init(&$a) { '$base' => $base )); - +} } +if(! function_exists('contacts_batch_actions')) { function contacts_batch_actions(&$a){ $contacts_id = $_POST['contact_batch']; if (!is_array($contacts_id)) return; @@ -132,10 +134,10 @@ function contacts_batch_actions(&$a){ goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']); else goaway($a->get_baseurl(true) . '/contacts'); - +} } - +if(! function_exists('contacts_post')) { function contacts_post(&$a) { if(! local_user()) @@ -215,10 +217,11 @@ function contacts_post(&$a) { $a->data['contact'] = $r[0]; return; - +} } /*contact actions*/ +if(! function_exists('_contact_update')) { function _contact_update($contact_id) { $r = q("SELECT `uid`, `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id)); if (!$r) @@ -239,7 +242,9 @@ function _contact_update($contact_id) { // pull feed and consume it, which should subscribe to the hub. proc_run('php',"include/onepoll.php","$contact_id", "force"); } +} +if(! function_exists('_contact_update_profile')) { function _contact_update_profile($contact_id) { $r = q("SELECT `uid`, `url`, `network` FROM `contact` WHERE `id` = %d", intval($contact_id)); if (!$r) @@ -299,7 +304,9 @@ function _contact_update_profile($contact_id) { // Update the entry in the gcontact table update_gcontact_from_probe($data["url"]); } +} +if(! function_exists('_contact_block')) { function _contact_block($contact_id, $orig_record) { $blocked = (($orig_record['blocked']) ? 0 : 1); $r = q("UPDATE `contact` SET `blocked` = %d WHERE `id` = %d AND `uid` = %d", @@ -308,8 +315,10 @@ function _contact_block($contact_id, $orig_record) { intval(local_user()) ); return $r; - } +} + +if(! function_exists('_contact_ignore')) { function _contact_ignore($contact_id, $orig_record) { $readonly = (($orig_record['readonly']) ? 0 : 1); $r = q("UPDATE `contact` SET `readonly` = %d WHERE `id` = %d AND `uid` = %d", @@ -319,6 +328,9 @@ function _contact_ignore($contact_id, $orig_record) { ); return $r; } +} + +if(! function_exists('_contact_archive')) { function _contact_archive($contact_id, $orig_record) { $archived = (($orig_record['archive']) ? 0 : 1); $r = q("UPDATE `contact` SET `archive` = %d WHERE `id` = %d AND `uid` = %d", @@ -331,14 +343,18 @@ function _contact_archive($contact_id, $orig_record) { } return $r; } +} + +if(! function_exists('_contact_drop')) { function _contact_drop($contact_id, $orig_record) { $a = get_app(); terminate_friendship($a->user,$a->contact,$orig_record); contact_remove($orig_record['id']); } +} - +if(! function_exists('contacts_content')) { function contacts_content(&$a) { $sort_type = 0; @@ -799,7 +815,9 @@ function contacts_content(&$a) { return $o; } +} +if(! function_exists('contacts_tab')) { function contacts_tab($a, $contact_id, $active_tab) { // tabs $tabs = array( @@ -873,7 +891,9 @@ function contacts_tab($a, $contact_id, $active_tab) { return $tab_str; } +} +if(! function_exists('contact_posts')) { function contact_posts($a, $contact_id) { $r = q("SELECT `url` FROM `contact` WHERE `id` = %d", intval($contact_id)); @@ -901,7 +921,9 @@ function contact_posts($a, $contact_id) { return $o; } +} +if(! function_exists('_contact_detail_for_template')) { function _contact_detail_for_template($rr){ $community = ''; @@ -952,5 +974,5 @@ function _contact_detail_for_template($rr){ 'url' => $url, 'network' => network_to_name($rr['network'], $rr['url']), ); - +} } diff --git a/mod/content.php b/mod/content.php index c5a555611..ab0fe7e4b 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 f8cfb03f3..8e6321760 100644 --- a/mod/credits.php +++ b/mod/credits.php @@ -5,6 +5,7 @@ * addons repository will be listed though ATM) */ +if(! function_exists('credits_content')) { function credits_content (&$a) { /* fill the page with credits */ $f = fopen('util/credits.txt','r'); @@ -18,3 +19,4 @@ function credits_content (&$a) { '$names' => $arr, )); } +} diff --git a/mod/crepair.php b/mod/crepair.php index 5b4db09da..50502b498 100644 --- a/mod/crepair.php +++ b/mod/crepair.php @@ -2,6 +2,7 @@ require_once("include/contact_selectors.php"); require_once("mod/contacts.php"); +if(! function_exists('crepair_init')) { function crepair_init(&$a) { if(! local_user()) return; @@ -28,8 +29,9 @@ function crepair_init(&$a) { profile_load($a, "", 0, get_contact_details_by_url($contact["url"])); } } +} - +if(! function_exists('crepair_post')) { function crepair_post(&$a) { if(! local_user()) return; @@ -91,9 +93,9 @@ function crepair_post(&$a) { return; } +} - - +if(! function_exists('crepair_content')) { function crepair_content(&$a) { if(! local_user()) { @@ -180,5 +182,5 @@ function crepair_content(&$a) { )); return $o; - +} } diff --git a/mod/delegate.php b/mod/delegate.php index 20d2e605e..d421de376 100644 --- a/mod/delegate.php +++ b/mod/delegate.php @@ -1,11 +1,13 @@ get_baseurl())), intval(local_user()), dbesc(NETWORK_DFRN) - ); + ); if(! count($r)) { notice( t('No potential page delegates located.') . EOL); @@ -144,5 +146,5 @@ function delegate_content(&$a) { return $o; - +} } diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php index 27c04a908..00e215e33 100644 --- a/mod/dfrn_confirm.php +++ b/mod/dfrn_confirm.php @@ -16,6 +16,7 @@ require_once('include/enotify.php'); +if(! function_exists('dfrn_confirm_post')) { function dfrn_confirm_post(&$a,$handsfree = null) { if(is_array($handsfree)) { @@ -801,5 +802,5 @@ function dfrn_confirm_post(&$a,$handsfree = null) { goaway(z_root()); // NOTREACHED - +} } diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index 4aa777b55..04500e89a 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -5,6 +5,7 @@ require_once('include/event.php'); require_once('library/defuse/php-encryption-1.2.1/Crypto.php'); +if(! function_exists('dfrn_notify_post')) { function dfrn_notify_post(&$a) { logger(__function__, LOGGER_TRACE); $dfrn_id = ((x($_POST,'dfrn_id')) ? notags(trim($_POST['dfrn_id'])) : ''); @@ -213,8 +214,9 @@ function dfrn_notify_post(&$a) { // NOTREACHED } +} - +if(! function_exists('dfrn_notify_content')) { function dfrn_notify_content(&$a) { if(x($_GET,'dfrn_id')) { @@ -338,5 +340,5 @@ function dfrn_notify_content(&$a) { killme(); } - +} } diff --git a/mod/dfrn_poll.php b/mod/dfrn_poll.php index ab6637607..82c75d28c 100644 --- a/mod/dfrn_poll.php +++ b/mod/dfrn_poll.php @@ -3,7 +3,7 @@ require_once('include/items.php'); require_once('include/auth.php'); require_once('include/dfrn.php'); - +if(! function_exists('dfrn_poll_init')) { function dfrn_poll_init(&$a) { @@ -160,7 +160,7 @@ function dfrn_poll_init(&$a) { if($final_dfrn_id != $orig_id) { logger('profile_check: ' . $final_dfrn_id . ' != ' . $orig_id, LOGGER_DEBUG); - // did not decode properly - cannot trust this site + // did not decode properly - cannot trust this site xml_status(3, 'Bad decryption'); } @@ -195,11 +195,11 @@ function dfrn_poll_init(&$a) { return; // NOTREACHED } } - +} } - +if(! function_exists('dfrn_poll_post')) { function dfrn_poll_post(&$a) { $dfrn_id = ((x($_POST,'dfrn_id')) ? $_POST['dfrn_id'] : ''); @@ -257,7 +257,7 @@ function dfrn_poll_post(&$a) { if($final_dfrn_id != $orig_id) { logger('profile_check: ' . $final_dfrn_id . ' != ' . $orig_id, LOGGER_DEBUG); - // did not decode properly - cannot trust this site + // did not decode properly - cannot trust this site xml_status(3, 'Bad decryption'); } @@ -377,7 +377,9 @@ function dfrn_poll_post(&$a) { } } +} +if(! function_exists('dfrn_poll_content')) { function dfrn_poll_content(&$a) { $dfrn_id = ((x($_GET,'dfrn_id')) ? $_GET['dfrn_id'] : ''); @@ -562,3 +564,4 @@ function dfrn_poll_content(&$a) { } } } +} diff --git a/mod/directory.php b/mod/directory.php index 294a55585..7ce1530ef 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,3 +217,4 @@ function directory_content(&$a) { return $o; } +} diff --git a/mod/dirfind.php b/mod/dirfind.php index 0dfe4d67a..f5e90705b 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -5,6 +5,7 @@ require_once('include/Contact.php'); require_once('include/contact_selectors.php'); require_once('mod/contacts.php'); +if(! function_exists('dirfind_init')) { function dirfind_init(&$a) { if(! local_user()) { @@ -19,9 +20,9 @@ function dirfind_init(&$a) { $a->page['aside'] .= follow_widget(); } +} - - +if(! function_exists('dirfind_content')) { function dirfind_content(&$a, $prefix = "") { $community = false; @@ -235,3 +236,4 @@ function dirfind_content(&$a, $prefix = "") { return $o; } +} diff --git a/mod/display.php b/mod/display.php index 4e3392707..9995a2b3e 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 c266082c8..be3456b58 100644 --- a/mod/filerm.php +++ b/mod/filerm.php @@ -1,5 +1,6 @@ argv[1]=="json"){ $register_policy = Array('REGISTER_CLOSED', 'REGISTER_APPROVE', 'REGISTER_OPEN'); @@ -56,9 +57,9 @@ function friendica_init(&$a) { killme(); } } +} - - +if(! function_exists('friendica_content')) { function friendica_content(&$a) { $o = ''; @@ -70,7 +71,7 @@ function friendica_content(&$a) { $o .= t('This is Friendica, version') . ' ' . FRIENDICA_VERSION . ' '; $o .= t('running at web location') . ' ' . z_root() . '

'; - $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') . '

'; @@ -102,8 +103,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 6b1cbd753..26a5e9806 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,3 +109,4 @@ function fsuggest_content(&$a) { return $o; } +} diff --git a/mod/group.php b/mod/group.php index 5b28784f5..2f8053eef 100644 --- a/mod/group.php +++ b/mod/group.php @@ -1,18 +1,21 @@ page['aside'] = group_side('contacts','group','extended',(($a->argc > 1) ? intval($a->argv[1]) : 0)); } } +} - - +if(! function_exists('group_post')) { function group_post(&$a) { if(! local_user()) { @@ -64,7 +67,9 @@ function group_post(&$a) { } return; } +} +if(! function_exists('group_content')) { function group_content(&$a) { $change = false; @@ -229,5 +234,5 @@ function group_content(&$a) { } return replace_macros($tpl, $context); - +} } diff --git a/mod/hcard.php b/mod/hcard.php index 6d2d9e2eb..af49423de 100644 --- a/mod/hcard.php +++ b/mod/hcard.php @@ -1,5 +1,6 @@ argc > 2) && ($a->argv[2] === 'view')) { $which = $a->user['nickname']; - $profile = $a->argv[1]; + $profile = $a->argv[1]; } profile_load($a,$which,$profile); @@ -23,7 +24,7 @@ function hcard_init(&$a) { if((x($a->profile,'page-flags')) && ($a->profile['page-flags'] == PAGE_COMMUNITY)) { $a->page['htmlhead'] .= ''; } - 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']); @@ -42,10 +43,9 @@ 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 5465d3e90..320e622fa 100644 --- a/mod/help.php +++ b/mod/help.php @@ -18,6 +18,7 @@ if (!function_exists('load_doc_file')) { } +if(! function_exists('help_content')) { function help_content(&$a) { nav_set_selected('help'); @@ -98,5 +99,5 @@ function help_content(&$a) { } ".$html; return $html; - +} } diff --git a/mod/hostxrd.php b/mod/hostxrd.php index 4121764f1..5b178e9b8 100644 --- a/mod/hostxrd.php +++ b/mod/hostxrd.php @@ -2,6 +2,7 @@ require_once('include/crypto.php'); +if(! function_exists('hostxrd_init')) { function hostxrd_init(&$a) { header('Access-Control-Allow-Origin: *'); header("Content-type: text/xml"); @@ -27,5 +28,5 @@ function hostxrd_init(&$a) { )); session_write_close(); exit(); - +} } diff --git a/mod/ignored.php b/mod/ignored.php index e876b4ef8..8a681a115 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; @@ -112,14 +113,18 @@ function install_post(&$a) { break; } } +} +if(! function_exists('get_db_errno')) { function get_db_errno() { if(class_exists('mysqli')) return mysqli_connect_errno(); else return mysql_errno(); } +} +if(! function_exists('install_content')) { function install_content(&$a) { global $install_wizard_pass, $db; @@ -304,6 +309,7 @@ function install_content(&$a) { } } +} /** * checks : array passed to template @@ -312,7 +318,8 @@ function install_content(&$a) { * required : boolean * help : string optional */ -function check_add(&$checks, $title, $status, $required, $help){ +if(! function_exists('check_add')) { +function check_add(&$checks, $title, $status, $required, $help) { $checks[] = array( 'title' => $title, 'status' => $status, @@ -320,7 +327,9 @@ function check_add(&$checks, $title, $status, $required, $help){ 'help' => $help, ); } +} +if(! function_exists('check_php')) { function check_php(&$phpath, &$checks) { $passed = $passed2 = $passed3 = false; if (strlen($phpath)){ @@ -370,9 +379,10 @@ function check_php(&$phpath, &$checks) { check_add($checks, t('PHP register_argc_argv'), $passed3, true, $help); } - +} } +if(! function_exists('check_keys')) { function check_keys(&$checks) { $help = ''; @@ -392,10 +402,10 @@ function check_keys(&$checks) { $help .= t('If running under Windows, please see "http://www.php.net/manual/en/openssl.installation.php".'); } check_add($checks, t('Generate encryption keys'), $res, true, $help); - +} } - +if(! function_exists('check_funcs')) { function check_funcs(&$checks) { $ck_funcs = array(); check_add($ck_funcs, t('libCurl PHP module'), true, true, ""); @@ -457,8 +467,9 @@ function check_funcs(&$checks) { /*if((x($_SESSION,'sysmsg')) && is_array($_SESSION['sysmsg']) && count($_SESSION['sysmsg'])) notice( t('Please see the file "INSTALL.txt".') . EOL);*/ } +} - +if(! function_exists('check_htconfig')) { function check_htconfig(&$checks) { $status = true; $help = ""; @@ -473,9 +484,10 @@ function check_htconfig(&$checks) { } check_add($checks, t('.htconfig.php is writable'), $status, false, $help); - +} } +if(! function_exists('check_smarty3')) { function check_smarty3(&$checks) { $status = true; $help = ""; @@ -489,9 +501,10 @@ function check_smarty3(&$checks) { } check_add($checks, t('view/smarty3 is writable'), $status, true, $help); - +} } +if(! function_exists('check_htaccess')) { function check_htaccess(&$checks) { $a = get_app(); $status = true; @@ -511,7 +524,9 @@ function check_htaccess(&$checks) { // cannot check modrewrite if libcurl is not installed } } +} +if(! function_exists('check_imagik')) { function check_imagik(&$checks) { $imagick = false; $gif = false; @@ -528,16 +543,18 @@ function check_imagik(&$checks) { check_add($checks, t('ImageMagick supports GIF'), $gif, false, ""); } } +} - - +if(! function_exists('manual_config')) { function manual_config(&$a) { $data = htmlentities($a->data['txt'],ENT_COMPAT,'UTF-8'); $o = t('The database configuration file ".htconfig.php" could not be written. Please use the enclosed text to create a configuration file in your web server root.'); $o .= ""; return $o; } +} +if(! function_exists('load_database_rem')) { function load_database_rem($v, $i){ $l = trim($i); if (strlen($l)>1 && ($l[0]=="-" || ($l[0]=="/" && $l[1]=="*"))){ @@ -546,8 +563,9 @@ function load_database_rem($v, $i){ return $v."\n".$i; } } +} - +if(! function_exists('load_database')) { function load_database($db) { require_once("include/dbstructure.php"); @@ -567,7 +585,9 @@ function load_database($db) { return $errors; } +} +if(! function_exists('what_next')) { function what_next() { $a = get_app(); $baseurl = $a->get_baseurl(); @@ -579,5 +599,4 @@ function what_next() { .t("Go to your new Friendica node 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 ccf876c7c..1f559dabc 100644 --- a/mod/invite.php +++ b/mod/invite.php @@ -9,6 +9,7 @@ require_once('include/email.php'); +if(! function_exists('invite_post')) { function invite_post(&$a) { if(! local_user()) { @@ -49,7 +50,7 @@ function invite_post(&$a) { notice( sprintf( t('%s : Not a valid email address.'), $recip) . EOL); continue; } - + if($invonly && ($x || is_site_admin())) { $code = autoname(8) . srand(1000,9999); $nmessage = str_replace('$invite_code',$code,$message); @@ -70,8 +71,8 @@ function invite_post(&$a) { else $nmessage = $message; - $res = mail($recip, email_header_encode( t('Please join us on Friendica'),'UTF-8'), - $nmessage, + $res = mail($recip, email_header_encode( t('Please join us on Friendica'),'UTF-8'), + $nmessage, "From: " . $a->user['email'] . "\n" . 'Content-type: text/plain; charset=UTF-8' . "\n" . 'Content-transfer-encoding: 8bit' ); @@ -93,8 +94,9 @@ function invite_post(&$a) { notice( sprintf( tt("%d message sent.", "%d messages sent.", $total) , $total) . EOL); return; } +} - +if(! function_exists('invite_content')) { function invite_content(&$a) { if(! local_user()) { @@ -134,7 +136,7 @@ function invite_content(&$a) { '$msg_text' => t('Your message:'), '$default_message' => t('You are cordially invited to join me and other close friends on Friendica - and help us to create a better social web.') . "\r\n" . "\r\n" . $linktxt - . "\r\n" . "\r\n" . (($invonly) ? t('You will need to supply this invitation code: $invite_code') . "\r\n" . "\r\n" : '') .t('Once you have registered, please connect with me via my profile page at:') + . "\r\n" . "\r\n" . (($invonly) ? t('You will need to supply this invitation code: $invite_code') . "\r\n" . "\r\n" : '') .t('Once you have registered, please connect with me via my profile page at:') . "\r\n" . "\r\n" . $a->get_baseurl() . '/profile/' . $a->user['nickname'] . "\r\n" . "\r\n" . t('For more information about the Friendica project and why we feel it is important, please visit http://friendica.com') . "\r\n" . "\r\n" , '$submit' => t('Submit') @@ -142,3 +144,4 @@ function invite_content(&$a) { return $o; } +} diff --git a/mod/item.php b/mod/item.php index 8c5a47964..f8f2e0faf 100644 --- a/mod/item.php +++ b/mod/item.php @@ -25,6 +25,7 @@ require_once('include/text.php'); require_once('include/items.php'); require_once('include/Scrape.php'); +if(! function_exists('item_post')) { function item_post(&$a) { if((! local_user()) && (! remote_user()) && (! x($_REQUEST,'commenter'))) @@ -1017,7 +1018,9 @@ function item_post(&$a) { item_post_return($a->get_baseurl(), $api_source, $return_path); // NOTREACHED } +} +if(! function_exists('item_post_return')) { function item_post_return($baseurl, $api_source, $return_path) { // figure out how to return, depending on from whence we came @@ -1037,9 +1040,9 @@ function item_post_return($baseurl, $api_source, $return_path) { echo json_encode($json); killme(); } +} - - +if(! function_exists('item_content')) { function item_content(&$a) { if((! local_user()) && (! remote_user())) @@ -1058,6 +1061,7 @@ function item_content(&$a) { } return $o; } +} /** * This function removes the tag $tag from the text $body and replaces it with @@ -1071,6 +1075,7 @@ function item_content(&$a) { * * @return boolean true if replaced, false if not replaced */ +if(! function_exists('handle_tag')) { function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $network = "") { require_once("include/Scrape.php"); require_once("include/socgraph.php"); @@ -1245,8 +1250,9 @@ function handle_tag($a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $netwo return array('replaced' => $replaced, 'contact' => $r[0]); } +} - +if(! function_exists('store_diaspora_comment_sig')) { function store_diaspora_comment_sig($datarray, $author, $uprvkey, $parent_item, $post_id) { // We won't be able to sign Diaspora comments for authenticated visitors - we don't have their private key @@ -1284,3 +1290,4 @@ function store_diaspora_comment_sig($datarray, $author, $uprvkey, $parent_item, return; } +} diff --git a/mod/like.php b/mod/like.php index 8d383b9ab..ef483a1f9 100755 --- a/mod/like.php +++ b/mod/like.php @@ -5,6 +5,7 @@ require_once('include/bbcode.php'); require_once('include/items.php'); require_once('include/like.php'); +if(! function_exists('like_content')) { function like_content(&$a) { if(! local_user() && ! remote_user()) { return false; @@ -28,11 +29,11 @@ function like_content(&$a) { killme(); // NOTREACHED // return; // NOTREACHED } - +} // Decide how to return. If we were called with a 'return' argument, // then redirect back to the calling page. If not, just quietly end - +if(! function_exists('like_content_return')) { function like_content_return($baseurl, $return_path) { if($return_path) { @@ -45,4 +46,4 @@ function like_content_return($baseurl, $return_path) { killme(); } - +} diff --git a/mod/localtime.php b/mod/localtime.php index d1453bc52..fc500f4dd 100644 --- a/mod/localtime.php +++ b/mod/localtime.php @@ -2,7 +2,7 @@ require_once('include/datetime.php'); - +if(! function_exists('localtime_post')) { function localtime_post(&$a) { $t = $_REQUEST['time']; @@ -13,9 +13,10 @@ function localtime_post(&$a) { if($_POST['timezone']) $a->data['mod-localtime'] = datetime_convert('UTC',$_POST['timezone'],$t,$bd_format); - +} } +if(! function_exists('localtime_content')) { function localtime_content(&$a) { $t = $_REQUEST['time']; if(! $t) @@ -38,12 +39,12 @@ function localtime_content(&$a) { $o .= '
'; - $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 0ae54c8c1..82f93f498 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 d09fc1868..47c329eb6 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 938d1cbb0..0c4bb1a83 100644 --- a/mod/lostpass.php +++ b/mod/lostpass.php @@ -4,6 +4,7 @@ require_once('include/email.php'); require_once('include/enotify.php'); require_once('include/text.php'); +if(! function_exists('lostpass_post')) { function lostpass_post(&$a) { $loginame = notags(trim($_POST['login-name'])); @@ -74,10 +75,10 @@ function lostpass_post(&$a) { 'body' => $body)); goaway(z_root()); - +} } - +if(! function_exists('lostpass_content')) { function lostpass_content(&$a) { @@ -164,5 +165,5 @@ function lostpass_content(&$a) { return $o; } - +} } diff --git a/mod/maintenance.php b/mod/maintenance.php index b50c94c9b..02de29108 100644 --- a/mod/maintenance.php +++ b/mod/maintenance.php @@ -1,7 +1,8 @@ t('System down for maintenance') )); } +} diff --git a/mod/manage.php b/mod/manage.php index adcc3d787..6af3db997 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 3b0367b42..f4936b28d 100644 --- a/mod/match.php +++ b/mod/match.php @@ -13,6 +13,7 @@ require_once('mod/proxy.php'); * @param App &$a * @return void|string */ +if(! function_exists('match_content')) { function match_content(&$a) { $o = ''; @@ -109,3 +110,4 @@ function match_content(&$a) { return $o; } +} diff --git a/mod/message.php b/mod/message.php index 1724ebc42..1f11797d8 100644 --- a/mod/message.php +++ b/mod/message.php @@ -3,6 +3,7 @@ require_once('include/acl_selectors.php'); require_once('include/message.php'); +if(! function_exists('message_init')) { function message_init(&$a) { $tabs = ''; @@ -36,9 +37,10 @@ function message_init(&$a) { '$baseurl' => $a->get_baseurl(true), '$base' => $base )); - +} } +if(! function_exists('message_post')) { function message_post(&$a) { if(! local_user()) { @@ -91,7 +93,7 @@ function message_post(&$a) { } else goaway($a->get_baseurl(true) . '/' . $_SESSION['return_url']); - +} } // Note: the code in 'item_extract_images' and 'item_redir_and_replace_images' @@ -171,7 +173,7 @@ function item_redir_and_replace_images($body, $images, $cid) { }} - +if(! function_exists('message_content')) { function message_content(&$a) { $o = ''; @@ -530,7 +532,9 @@ function message_content(&$a) { return $o; } } +} +if(! function_exists('get_messages')) { function get_messages($user, $lstart, $lend) { return q("SELECT max(`mail`.`created`) AS `mailcreated`, min(`mail`.`seen`) AS `mailseen`, @@ -541,7 +545,9 @@ function get_messages($user, $lstart, $lend) { intval($user), intval($lstart), intval($lend) ); } +} +if(! function_exists('render_messages')) { function render_messages($msg, $t) { $a = get_app(); @@ -593,3 +599,4 @@ function render_messages($msg, $t) { return $rslt; } +} diff --git a/mod/modexp.php b/mod/modexp.php index bba2c2882..282d55a24 100644 --- a/mod/modexp.php +++ b/mod/modexp.php @@ -2,6 +2,7 @@ require_once('library/asn1.php'); +if(! function_exists('modexp_init')) { function modexp_init(&$a) { if($a->argc != 2) @@ -29,6 +30,5 @@ function modexp_init(&$a) { echo 'RSA' . '.' . $m . '.' . $e ; killme(); - } - +} diff --git a/mod/mood.php b/mod/mood.php index eee11e20c..2476f0656 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 89de5b705..3b1b0b617 100644 --- a/mod/msearch.php +++ b/mod/msearch.php @@ -1,5 +1,6 @@ $rr['name'], - 'url' => $a->get_baseurl() . '/profile/' . $rr['nickname'], + 'name' => $rr['name'], + 'url' => $a->get_baseurl() . '/profile/' . $rr['nickname'], 'photo' => $a->get_baseurl() . '/photo/avatar/' . $rr['uid'] . '.jpg', 'tags' => str_replace(array(',',' '),array(' ',' '),$rr['pub_keywords']) ); @@ -38,5 +39,5 @@ function msearch_post(&$a) { echo json_encode($output); killme(); - -} \ No newline at end of file +} +} diff --git a/mod/navigation.php b/mod/navigation.php index 5db69b171..8fbabfda9 100644 --- a/mod/navigation.php +++ b/mod/navigation.php @@ -2,6 +2,7 @@ require_once("include/nav.php"); +if(! function_exists('navigation_content')) { function navigation_content(&$a) { $nav_info = nav_info($a); @@ -22,5 +23,5 @@ function navigation_content(&$a) { '$apps' => $a->apps, '$clear_notifs' => t('Clear notifications') )); - +} } diff --git a/mod/network.php b/mod/network.php index a07c5868e..9b07384e1 100644 --- a/mod/network.php +++ b/mod/network.php @@ -1,4 +1,6 @@ page['aside'] .= networks_widget($a->get_baseurl(true) . '/network',(x($_GET, 'nets') ? $_GET['nets'] : '')); $a->page['aside'] .= saved_searches($search); $a->page['aside'] .= fileas_widget($a->get_baseurl(true) . '/network',(x($_GET, 'file') ? $_GET['file'] : '')); - +} } +if(! function_exists('saved_searches')) { function saved_searches($search) { if(! feature_enabled(local_user(),'savedsearch')) @@ -204,7 +207,7 @@ function saved_searches($search) { )); return $o; - +} } /** @@ -222,6 +225,7 @@ function saved_searches($search) { * * @return Array ( $no_active, $comment_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active ); */ +if(! function_exists('network_query_get_sel_tab')) { function network_query_get_sel_tab($a) { $no_active=''; $starred_active = ''; @@ -278,10 +282,12 @@ function network_query_get_sel_tab($a) { return array($no_active, $all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active); } +} /** * Return selected network from query */ +if(! function_exists('network_query_get_sel_net')) { function network_query_get_sel_net() { $network = false; @@ -291,7 +297,9 @@ function network_query_get_sel_net() { return $network; } +} +if(! function_exists('network_query_get_sel_group')) { function network_query_get_sel_group($a) { $group = false; @@ -301,8 +309,9 @@ function network_query_get_sel_group($a) { return $group; } +} - +if(! function_exists('network_content')) { function network_content(&$a, $update = 0) { require_once('include/conversation.php'); @@ -886,4 +895,4 @@ function network_content(&$a, $update = 0) { return $o; } - +} diff --git a/mod/newmember.php b/mod/newmember.php index aa55c3a09..ef2533330 100644 --- a/mod/newmember.php +++ b/mod/newmember.php @@ -1,5 +1,6 @@ '; - $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 .= ''; @@ -23,7 +24,7 @@ function newmember_content(&$a) { $o .= '