From f23469121662325745660b3e39ca31f02365a8b2 Mon Sep 17 00:00:00 2001 From: Adam Magness Date: Tue, 7 Nov 2017 19:37:53 -0500 Subject: [PATCH 1/5] Relocate class files from /include to /src/ dbm, Diaspora, dfrn, and NotificationsManager moved to namespace. Includes and references in files updated. --- include/Contact.php | 6 +- include/api.php | 2 +- include/contact_selectors.php | 3 +- include/delivery.php | 18 +- include/follow.php | 2 +- include/items.php | 4 +- include/like.php | 3 +- include/notifier.php | 2 +- include/profile_update.php | 2 +- include/queue.php | 6 +- mod/dfrn_confirm.php | 2 +- mod/dfrn_notify.php | 6 +- mod/dfrn_poll.php | 6 +- mod/display.php | 5 +- mod/fetch.php | 2 +- mod/item.php | 2 +- mod/notifications.php | 2 +- mod/notify.php | 3 +- mod/p.php | 3 +- mod/receive.php | 2 +- object/Item.php | 2 +- src/App.php | 8 +- src/Core/Config.php | 4 +- src/Core/NotificationsManager.php | 868 +++++++ src/Core/PConfig.php | 6 +- src/Core/Worker.php | 16 +- src/Database/Dbm.php | 115 + src/Network/Probe.php | 8 +- src/Protocol/Dfrn.php | 2970 ++++++++++++++++++++++ src/Protocol/Diaspora.php | 3948 +++++++++++++++++++++++++++++ src/Util/Lock.php | 6 +- 31 files changed, 7965 insertions(+), 67 deletions(-) create mode 100644 src/Core/NotificationsManager.php create mode 100644 src/Database/Dbm.php create mode 100644 src/Protocol/Dfrn.php create mode 100644 src/Protocol/Diaspora.php diff --git a/include/Contact.php b/include/Contact.php index a7a22671fe..c75de6afc8 100644 --- a/include/Contact.php +++ b/include/Contact.php @@ -5,6 +5,8 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Network\Probe; +use Friendica\Protocol\Diaspora; +use Friendica\Protocol\Dfrn; // Included here for completeness, but this is a very dangerous operation. // It is the caller's responsibility to confirm the requestor's intent and @@ -90,11 +92,9 @@ function terminate_friendship($user,$self,$contact) { slapper($user,$contact['notify'],$slap); } } elseif ($contact['network'] === NETWORK_DIASPORA) { - require_once 'include/diaspora.php'; Diaspora::send_unshare($user,$contact); } elseif ($contact['network'] === NETWORK_DFRN) { - require_once 'include/dfrn.php'; - dfrn::deliver($user,$contact,'placeholder', 1); + Dfrn::deliver($user,$contact,'placeholder', 1); } } diff --git a/include/api.php b/include/api.php index d677206b47..09ce9d6b26 100644 --- a/include/api.php +++ b/include/api.php @@ -9,6 +9,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; +use Friendica\Core\NotificationsManager; use Friendica\Core\Worker; require_once 'include/HTTPExceptions.php'; @@ -28,7 +29,6 @@ require_once 'mod/proxy.php'; require_once 'include/message.php'; require_once 'include/group.php'; require_once 'include/like.php'; -require_once 'include/NotificationsManager.php'; require_once 'include/plaintext.php'; require_once 'include/xml.php'; diff --git a/include/contact_selectors.php b/include/contact_selectors.php index 48f2fb005e..4109f38cd1 100644 --- a/include/contact_selectors.php +++ b/include/contact_selectors.php @@ -1,5 +1,6 @@ '); - $deliver_status = dfrn::deliver($owner, $contact, $data); + $deliver_status = Dfrn::deliver($owner, $contact, $data); if ($deliver_status == (-1)) { update_queue_time($q_item['id']); diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php index e53abd2206..f0d5d76305 100644 --- a/mod/dfrn_confirm.php +++ b/mod/dfrn_confirm.php @@ -24,6 +24,7 @@ use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Network\Probe; +use Friendica\Protocol\Diaspora; require_once 'include/enotify.php'; require_once 'include/group.php'; @@ -438,7 +439,6 @@ function dfrn_confirm_post(App $a, $handsfree = null) { if ((isset($new_relation) && $new_relation == CONTACT_IS_FRIEND)) { if (($contact) && ($contact['network'] === NETWORK_DIASPORA)) { - require_once 'include/diaspora.php'; $ret = Diaspora::send_share($user[0],$r[0]); logger('share returns: ' . $ret); } diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index 5ff90d4851..65e9535c6a 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -8,9 +8,9 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Protocol\Dfrn; require_once('include/items.php'); -require_once('include/dfrn.php'); require_once('include/event.php'); require_once('library/defuse/php-encryption-1.2.1/Crypto.php'); @@ -180,7 +180,7 @@ function dfrn_notify_post(App $a) { *we got a key. old code send only the key, without RINO version. * we assume RINO 1 if key and no RINO version */ - $data = dfrn::aes_decrypt(hex2bin($data), $final_key); + $data = Dfrn::aes_decrypt(hex2bin($data), $final_key); break; case 2: try { @@ -212,7 +212,7 @@ function dfrn_notify_post(App $a) { logger('rino: decrypted data: ' . $data, LOGGER_DATA); } - $ret = dfrn::import($data, $importer); + $ret = Dfrn::import($data, $importer); xml_status($ret, 'Processed'); // NOTREACHED diff --git a/mod/dfrn_poll.php b/mod/dfrn_poll.php index 2a5eff5667..6f3d843810 100644 --- a/mod/dfrn_poll.php +++ b/mod/dfrn_poll.php @@ -3,10 +3,10 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; +use Friendica\Protocol\Dfrn; require_once('include/items.php'); require_once('include/auth.php'); -require_once('include/dfrn.php'); require_once('include/ostatus.php'); function dfrn_poll_init(App $a) { @@ -58,7 +58,7 @@ function dfrn_poll_init(App $a) { logger('dfrn_poll: public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $user); header("Content-type: application/atom+xml"); - echo dfrn::feed('', $user,$last_update, 0, $hidewall); + echo Dfrn::feed('', $user,$last_update, 0, $hidewall); killme(); } @@ -387,7 +387,7 @@ function dfrn_poll_post(App $a) { } header("Content-type: application/atom+xml"); - $o = dfrn::feed($dfrn_id, $a->argv[1], $last_update, $direction); + $o = Dfrn::feed($dfrn_id, $a->argv[1], $last_update, $direction); echo $o; killme(); diff --git a/mod/display.php b/mod/display.php index d2ee12c570..62cb0445fe 100644 --- a/mod/display.php +++ b/mod/display.php @@ -3,8 +3,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; - -require_once('include/dfrn.php'); +use Friendica\Protocol\Dfrn; function display_init(App $a) { @@ -492,7 +491,7 @@ function display_content(App $a, $update = 0) { } function displayShowFeed($item_id, $conversation) { - $xml = dfrn::itemFeed($item_id, $conversation); + $xml = Dfrn::itemFeed($item_id, $conversation); if ($xml == '') { http_status_exit(500); } diff --git a/mod/fetch.php b/mod/fetch.php index 30c38bf543..9587afbf0e 100644 --- a/mod/fetch.php +++ b/mod/fetch.php @@ -5,9 +5,9 @@ This file is part of the Diaspora protocol. It is used for fetching single publi use Friendica\App; use Friendica\Core\System; +use Friendica\Protocol\Diaspora; require_once("include/crypto.php"); -require_once("include/diaspora.php"); require_once("include/xml.php"); function fetch_init(App $a) { diff --git a/mod/item.php b/mod/item.php index 51488fa728..61259df74a 100644 --- a/mod/item.php +++ b/mod/item.php @@ -20,6 +20,7 @@ use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Network\Probe; +use Friendica\Protocol\Diaspora; require_once 'include/crypto.php'; require_once 'include/enotify.php'; @@ -29,7 +30,6 @@ require_once 'include/files.php'; require_once 'include/threads.php'; require_once 'include/text.php'; require_once 'include/items.php'; -require_once 'include/diaspora.php'; require_once 'include/Contact.php'; function item_post(App $a) { diff --git a/mod/notifications.php b/mod/notifications.php index 95467a584f..271e400df5 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -6,9 +6,9 @@ */ use Friendica\App; +use Friendica\Core\NotificationsManager; use Friendica\Core\System; -require_once("include/NotificationsManager.php"); require_once("include/contact_selectors.php"); require_once("include/network.php"); diff --git a/mod/notify.php b/mod/notify.php index 867ead9fa7..6f7d222d8b 100644 --- a/mod/notify.php +++ b/mod/notify.php @@ -1,10 +1,9 @@ argc != 2) { diff --git a/mod/receive.php b/mod/receive.php index 68d304ae70..73382794dd 100644 --- a/mod/receive.php +++ b/mod/receive.php @@ -6,10 +6,10 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Protocol\Diaspora; require_once('include/salmon.php'); require_once('include/crypto.php'); -require_once('include/diaspora.php'); function receive_post(App $a) { $enabled = intval(Config::get('system', 'diaspora_enabled')); diff --git a/object/Item.php b/object/Item.php index 6d2d35f345..fa8c893c7f 100644 --- a/object/Item.php +++ b/object/Item.php @@ -4,10 +4,10 @@ if(class_exists('Item')) use Friendica\Core\Config; use Friendica\Core\PConfig; +use Friendica\Protocol\Diaspora; require_once('object/BaseObject.php'); require_once('include/text.php'); -require_once('include/diaspora.php'); require_once('boot.php'); /** diff --git a/src/App.php b/src/App.php index 5c1c2bb9c1..7ff56cee3a 100644 --- a/src/App.php +++ b/src/App.php @@ -5,10 +5,10 @@ namespace Friendica; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\PConfig; +use Friendica\Database\Dbm; use Cache; use dba; -use dbm; use Detection\MobileDetect; @@ -706,7 +706,7 @@ class App { dba::transaction(); $r = q('SELECT `pid` FROM `process` WHERE `pid` = %d', intval(getmypid())); - if (!dbm::is_result($r)) { + if (!Dbm::is_result($r)) { dba::insert('process', array('pid' => getmypid(), 'command' => $command, 'created' => datetime_convert())); } dba::commit(); @@ -719,7 +719,7 @@ class App { dba::transaction(); $r = q('SELECT `pid` FROM `process`'); - if (dbm::is_result($r)) { + if (Dbm::is_result($r)) { foreach ($r AS $process) { if (!posix_kill($process['pid'], 0)) { q('DELETE FROM `process` WHERE `pid` = %d', intval($process['pid'])); @@ -806,7 +806,7 @@ class App { } } - $processlist = dbm::processlist(); + $processlist = Dbm::processlist(); if ($processlist['list'] != '') { logger('Processcheck: Processes: ' . $processlist['amount'] . ' - Processlist: ' . $processlist['list'], LOGGER_DEBUG); diff --git a/src/Core/Config.php b/src/Core/Config.php index be0d0def16..546177ff78 100644 --- a/src/Core/Config.php +++ b/src/Core/Config.php @@ -1,8 +1,8 @@ $family, 'k' => $key), array('limit' => 1)); - if (dbm::is_result($ret)) { + if (Dbm::is_result($ret)) { // manage array value $val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret['v']) ? unserialize($ret['v']) : $ret['v']); diff --git a/src/Core/NotificationsManager.php b/src/Core/NotificationsManager.php new file mode 100644 index 0000000000..113091d7ec --- /dev/null +++ b/src/Core/NotificationsManager.php @@ -0,0 +1,868 @@ +a = get_app(); + } + + /** + * @brief set some extra note properties + * + * @param array $notes array of note arrays from db + * @return array Copy of input array with added properties + * + * Set some extra properties to note array from db: + * - timestamp as int in default TZ + * - date_rel : relative date string + * - msg_html: message as html string + * - msg_plain: message as plain text string + */ + private function _set_extra($notes) { + $rets = array(); + foreach($notes as $n) { + $local_time = datetime_convert('UTC',date_default_timezone_get(),$n['date']); + $n['timestamp'] = strtotime($local_time); + $n['date_rel'] = relative_date($n['date']); + $n['msg_html'] = bbcode($n['msg'], false, false, false, false); + $n['msg_plain'] = explode("\n",trim(html2plain($n['msg_html'], 0)))[0]; + + $rets[] = $n; + } + return $rets; + } + + + /** + * @brief Get all notifications for local_user() + * + * @param array $filter optional Array "column name"=>value: filter query by columns values + * @param string $order optional Space separated list of column to sort by. prepend name with "+" to sort ASC, "-" to sort DESC. Default to "-date" + * @param string $limit optional Query limits + * + * @return array of results or false on errors + */ + public function getAll($filter = array(), $order="-date", $limit="") { + $filter_str = array(); + $filter_sql = ""; + foreach($filter as $column => $value) { + $filter_str[] = sprintf("`%s` = '%s'", $column, dbesc($value)); + } + if (count($filter_str)>0) { + $filter_sql = "AND ".implode(" AND ", $filter_str); + } + + $aOrder = explode(" ", $order); + $asOrder = array(); + foreach($aOrder as $o) { + $dir = "asc"; + if ($o[0]==="-") { + $dir = "desc"; + $o = substr($o,1); + } + if ($o[0]==="+") { + $dir = "asc"; + $o = substr($o,1); + } + $asOrder[] = "$o $dir"; + } + $order_sql = implode(", ", $asOrder); + + if($limit!="") + $limit = " LIMIT ".$limit; + + $r = q("SELECT * FROM `notify` WHERE `uid` = %d $filter_sql ORDER BY $order_sql $limit", + intval(local_user()) + ); + + if (Dbm::is_result($r)) + return $this->_set_extra($r); + + return false; + } + + /** + * @brief Get one note for local_user() by $id value + * + * @param int $id + * @return array note values or null if not found + */ + public function getByID($id) { + $r = q("SELECT * FROM `notify` WHERE `id` = %d AND `uid` = %d LIMIT 1", + intval($id), + intval(local_user()) + ); + if (Dbm::is_result($r)) { + return $this->_set_extra($r)[0]; + } + return null; + } + + /** + * @brief set seen state of $note of local_user() + * + * @param array $note + * @param bool $seen optional true or false, default true + * @return bool true on success, false on errors + */ + public function setSeen($note, $seen = true) { + return q("UPDATE `notify` SET `seen` = %d WHERE ( `link` = '%s' OR ( `parent` != 0 AND `parent` = %d AND `otype` = '%s' )) AND `uid` = %d", + intval($seen), + dbesc($note['link']), + intval($note['parent']), + dbesc($note['otype']), + intval(local_user()) + ); + } + + /** + * @brief set seen state of all notifications of local_user() + * + * @param bool $seen optional true or false. default true + * @return bool true on success, false on error + */ + public function setAllSeen($seen = true) { + return q("UPDATE `notify` SET `seen` = %d WHERE `uid` = %d", + intval($seen), + intval(local_user()) + ); + } + + /** + * @brief List of pages for the Notifications TabBar + * + * @return array with with notifications TabBar data + */ + public function getTabs() { + $tabs = array( + array( + 'label' => t('System'), + 'url'=>'notifications/system', + 'sel'=> (($this->a->argv[1] == 'system') ? 'active' : ''), + 'id' => 'system-tab', + 'accesskey' => 'y', + ), + array( + 'label' => t('Network'), + 'url'=>'notifications/network', + 'sel'=> (($this->a->argv[1] == 'network') ? 'active' : ''), + 'id' => 'network-tab', + 'accesskey' => 'w', + ), + array( + 'label' => t('Personal'), + 'url'=>'notifications/personal', + 'sel'=> (($this->a->argv[1] == 'personal') ? 'active' : ''), + 'id' => 'personal-tab', + 'accesskey' => 'r', + ), + array( + 'label' => t('Home'), + 'url' => 'notifications/home', + 'sel'=> (($this->a->argv[1] == 'home') ? 'active' : ''), + 'id' => 'home-tab', + 'accesskey' => 'h', + ), + array( + 'label' => t('Introductions'), + 'url' => 'notifications/intros', + 'sel'=> (($this->a->argv[1] == 'intros') ? 'active' : ''), + 'id' => 'intro-tab', + 'accesskey' => 'i', + ), + ); + + return $tabs; + } + + /** + * @brief Format the notification query in an usable array + * + * @param array $notifs The array from the db query + * @param string $ident The notifications identifier (e.g. network) + * @return array + * string 'label' => The type of the notification + * string 'link' => URL to the source + * string 'image' => The avatar image + * string 'url' => The profile url of the contact + * string 'text' => The notification text + * string 'when' => The date of the notification + * string 'ago' => T relative date of the notification + * bool 'seen' => Is the notification marked as "seen" + */ + private function formatNotifs($notifs, $ident = "") { + + $notif = array(); + $arr = array(); + + if (Dbm::is_result($notifs)) { + + foreach ($notifs as $it) { + // Because we use different db tables for the notification query + // we have sometimes $it['unseen'] and sometimes $it['seen]. + // So we will have to transform $it['unseen'] + if (array_key_exists('unseen', $it)) { + $it['seen'] = ($it['unseen'] > 0 ? false : true); + } + + // Depending on the identifier of the notification we need to use different defaults + switch ($ident) { + case 'system': + $default_item_label = 'notify'; + $default_item_link = System::baseUrl(true).'/notify/view/'. $it['id']; + $default_item_image = proxy_url($it['photo'], false, PROXY_SIZE_MICRO); + $default_item_url = $it['url']; + $default_item_text = strip_tags(bbcode($it['msg'])); + $default_item_when = datetime_convert('UTC', date_default_timezone_get(), $it['date'], 'r'); + $default_item_ago = relative_date($it['date']); + break; + + case 'home': + $default_item_label = 'comment'; + $default_item_link = System::baseUrl(true).'/display/'.$it['pguid']; + $default_item_image = proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO); + $default_item_url = $it['author-link']; + $default_item_text = sprintf(t("%s commented on %s's post"), $it['author-name'], $it['pname']); + $default_item_when = datetime_convert('UTC', date_default_timezone_get(), $it['created'], 'r'); + $default_item_ago = relative_date($it['created']); + break; + + default: + $default_item_label = (($it['id'] == $it['parent']) ? 'post' : 'comment'); + $default_item_link = System::baseUrl(true).'/display/'.$it['pguid']; + $default_item_image = proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO); + $default_item_url = $it['author-link']; + $default_item_text = (($it['id'] == $it['parent']) + ? sprintf(t("%s created a new post"), $it['author-name']) + : sprintf(t("%s commented on %s's post"), $it['author-name'], $it['pname'])); + $default_item_when = datetime_convert('UTC', date_default_timezone_get(), $it['created'], 'r'); + $default_item_ago = relative_date($it['created']); + + } + + // Transform the different types of notification in an usable array + switch ($it['verb']){ + case ACTIVITY_LIKE: + $notif = array( + 'label' => 'like', + 'link' => System::baseUrl(true).'/display/'.$it['pguid'], + 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), + 'url' => $it['author-link'], + 'text' => sprintf(t("%s liked %s's post"), $it['author-name'], $it['pname']), + 'when' => $default_item_when, + 'ago' => $default_item_ago, + 'seen' => $it['seen'] + ); + break; + + case ACTIVITY_DISLIKE: + $notif = array( + 'label' => 'dislike', + 'link' => System::baseUrl(true).'/display/'.$it['pguid'], + 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), + 'url' => $it['author-link'], + 'text' => sprintf(t("%s disliked %s's post"), $it['author-name'], $it['pname']), + 'when' => $default_item_when, + 'ago' => $default_item_ago, + 'seen' => $it['seen'] + ); + break; + + case ACTIVITY_ATTEND: + $notif = array( + 'label' => 'attend', + 'link' => System::baseUrl(true).'/display/'.$it['pguid'], + 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), + 'url' => $it['author-link'], + 'text' => sprintf(t("%s is attending %s's event"), $it['author-name'], $it['pname']), + 'when' => $default_item_when, + 'ago' => $default_item_ago, + 'seen' => $it['seen'] + ); + break; + + case ACTIVITY_ATTENDNO: + $notif = array( + 'label' => 'attendno', + 'link' => System::baseUrl(true).'/display/'.$it['pguid'], + 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), + 'url' => $it['author-link'], + 'text' => sprintf( t("%s is not attending %s's event"), $it['author-name'], $it['pname']), + 'when' => $default_item_when, + 'ago' => $default_item_ago, + 'seen' => $it['seen'] + ); + break; + + case ACTIVITY_ATTENDMAYBE: + $notif = array( + 'label' => 'attendmaybe', + 'link' => System::baseUrl(true).'/display/'.$it['pguid'], + 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), + 'url' => $it['author-link'], + 'text' => sprintf(t("%s may attend %s's event"), $it['author-name'], $it['pname']), + 'when' => $default_item_when, + 'ago' => $default_item_ago, + 'seen' => $it['seen'] + ); + break; + + case ACTIVITY_FRIEND: + $xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">"; + $obj = parse_xml_string($xmlhead.$it['object']); + $it['fname'] = $obj->title; + + $notif = array( + 'label' => 'friend', + 'link' => System::baseUrl(true).'/display/'.$it['pguid'], + 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), + 'url' => $it['author-link'], + 'text' => sprintf(t("%s is now friends with %s"), $it['author-name'], $it['fname']), + 'when' => $default_item_when, + 'ago' => $default_item_ago, + 'seen' => $it['seen'] + ); + break; + + default: + $notif = array( + 'label' => $default_item_label, + 'link' => $default_item_link, + 'image' => $default_item_image, + 'url' => $default_item_url, + 'text' => $default_item_text, + 'when' => $default_item_when, + 'ago' => $default_item_ago, + 'seen' => $it['seen'] + ); + } + + $arr[] = $notif; + } + } + + return $arr; + + } + + /** + * @brief Total number of network notifications + * @param int|string $seen + * If 0 only include notifications into the query + * which aren't marked as "seen" + * @return int Number of network notifications + */ + private function networkTotal($seen = 0) { + $sql_seen = ""; + + if($seen === 0) + $sql_seen = " AND `item`.`unseen` = 1 "; + + $r = q("SELECT COUNT(*) AS `total` + FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent` + WHERE `item`.`visible` = 1 AND `pitem`.`parent` != 0 AND + `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0 + $sql_seen", + intval(local_user()) + ); + + if (Dbm::is_result($r)) + return $r[0]['total']; + + return 0; + } + + /** + * @brief Get network notifications + * + * @param int|string $seen + * If 0 only include notifications into the query + * which aren't marked as "seen" + * @param int $start Start the query at this point + * @param int $limit Maximum number of query results + * + * @return array with + * string 'ident' => Notification identifier + * int 'total' => Total number of available network notifications + * array 'notifications' => Network notifications + */ + public function networkNotifs($seen = 0, $start = 0, $limit = 80) { + $ident = 'network'; + $total = $this->networkTotal($seen); + $notifs = array(); + $sql_seen = ""; + + if($seen === 0) + $sql_seen = " AND `item`.`unseen` = 1 "; + + + $r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`, + `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` AS `object`, + `pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`, `pitem`.`guid` AS `pguid` + FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent` + WHERE `item`.`visible` = 1 AND `pitem`.`parent` != 0 AND + `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0 + $sql_seen + ORDER BY `item`.`created` DESC LIMIT %d, %d ", + intval(local_user()), + intval($start), + intval($limit) + ); + + if (Dbm::is_result($r)) + $notifs = $this->formatNotifs($r, $ident); + + $arr = array ( + 'notifications' => $notifs, + 'ident' => $ident, + 'total' => $total, + ); + + return $arr; + } + + /** + * @brief Total number of system notifications + * @param int|string $seen + * If 0 only include notifications into the query + * which aren't marked as "seen" + * @return int Number of system notifications + */ + private function systemTotal($seen = 0) { + $sql_seen = ""; + + if($seen === 0) + $sql_seen = " AND `seen` = 0 "; + + $r = q("SELECT COUNT(*) AS `total` FROM `notify` WHERE `uid` = %d $sql_seen", + intval(local_user()) + ); + + if (Dbm::is_result($r)) + return $r[0]['total']; + + return 0; + } + + /** + * @brief Get system notifications + * + * @param int|string $seen + * If 0 only include notifications into the query + * which aren't marked as "seen" + * @param int $start Start the query at this point + * @param int $limit Maximum number of query results + * + * @return array with + * string 'ident' => Notification identifier + * int 'total' => Total number of available system notifications + * array 'notifications' => System notifications + */ + public function systemNotifs($seen = 0, $start = 0, $limit = 80) { + $ident = 'system'; + $total = $this->systemTotal($seen); + $notifs = array(); + $sql_seen = ""; + + if($seen === 0) + $sql_seen = " AND `seen` = 0 "; + + $r = q("SELECT `id`, `url`, `photo`, `msg`, `date`, `seen` FROM `notify` + WHERE `uid` = %d $sql_seen ORDER BY `date` DESC LIMIT %d, %d ", + intval(local_user()), + intval($start), + intval($limit) + ); + + if (Dbm::is_result($r)) + $notifs = $this->formatNotifs($r, $ident); + + $arr = array ( + 'notifications' => $notifs, + 'ident' => $ident, + 'total' => $total, + ); + + return $arr; + } + + /** + * @brief Addional SQL query string for the personal notifications + * + * @return string The additional sql query + */ + private function _personal_sql_extra() { + $myurl = System::baseUrl(true) . '/profile/'. $this->a->user['nickname']; + $myurl = substr($myurl,strpos($myurl,'://')+3); + $myurl = str_replace(array('www.','.'),array('','\\.'),$myurl); + $diasp_url = str_replace('/profile/','/u/',$myurl); + $sql_extra = sprintf(" AND ( `item`.`author-link` regexp '%s' OR `item`.`tag` regexp '%s' OR `item`.`tag` regexp '%s' ) ", + dbesc($myurl . '$'), + dbesc($myurl . '\\]'), + dbesc($diasp_url . '\\]') + ); + + return $sql_extra; + } + + /** + * @brief Total number of personal notifications + * @param int|string $seen + * If 0 only include notifications into the query + * which aren't marked as "seen" + * @return int Number of personal notifications + */ + private function personalTotal($seen = 0) { + $sql_seen = ""; + $sql_extra = $this->_personal_sql_extra(); + + if($seen === 0) + $sql_seen = " AND `item`.`unseen` = 1 "; + + $r = q("SELECT COUNT(*) AS `total` + FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent` + WHERE `item`.`visible` = 1 + $sql_extra + $sql_seen + AND `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0 " , + intval(local_user()) + ); + + if (Dbm::is_result($r)) + return $r[0]['total']; + + return 0; + } + + /** + * @brief Get personal notifications + * + * @param int|string $seen + * If 0 only include notifications into the query + * which aren't marked as "seen" + * @param int $start Start the query at this point + * @param int $limit Maximum number of query results + * + * @return array with + * string 'ident' => Notification identifier + * int 'total' => Total number of available personal notifications + * array 'notifications' => Personal notifications + */ + public function personalNotifs($seen = 0, $start = 0, $limit = 80) { + $ident = 'personal'; + $total = $this->personalTotal($seen); + $sql_extra = $this->_personal_sql_extra(); + $notifs = array(); + $sql_seen = ""; + + if($seen === 0) + $sql_seen = " AND `item`.`unseen` = 1 "; + + $r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`, + `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` AS `object`, + `pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`, `pitem`.`guid` AS `pguid` + FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent` + WHERE `item`.`visible` = 1 + $sql_extra + $sql_seen + AND `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0 + ORDER BY `item`.`created` DESC LIMIT %d, %d " , + intval(local_user()), + intval($start), + intval($limit) + ); + + if (Dbm::is_result($r)) + $notifs = $this->formatNotifs($r, $ident); + + $arr = array ( + 'notifications' => $notifs, + 'ident' => $ident, + 'total' => $total, + ); + + return $arr; + } + + /** + * @brief Total number of home notifications + * @param int|string $seen + * If 0 only include notifications into the query + * which aren't marked as "seen" + * @return int Number of home notifications + */ + private function homeTotal($seen = 0) { + $sql_seen = ""; + + if($seen === 0) + $sql_seen = " AND `item`.`unseen` = 1 "; + + $r = q("SELECT COUNT(*) AS `total` FROM `item` + WHERE `item`.`visible` = 1 AND + `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 1 + $sql_seen", + intval(local_user()) + ); + + if (Dbm::is_result($r)) + return $r[0]['total']; + + return 0; + } + + /** + * @brief Get home notifications + * + * @param int|string $seen + * If 0 only include notifications into the query + * which aren't marked as "seen" + * @param int $start Start the query at this point + * @param int $limit Maximum number of query results + * + * @return array with + * string 'ident' => Notification identifier + * int 'total' => Total number of available home notifications + * array 'notifications' => Home notifications + */ + public function homeNotifs($seen = 0, $start = 0, $limit = 80) { + $ident = 'home'; + $total = $this->homeTotal($seen); + $notifs = array(); + $sql_seen = ""; + + if($seen === 0) + $sql_seen = " AND `item`.`unseen` = 1 "; + + $r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`, + `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` AS `object`, + `pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`, `pitem`.`guid` AS `pguid` + FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent` + WHERE `item`.`visible` = 1 AND + `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 1 + $sql_seen + ORDER BY `item`.`created` DESC LIMIT %d, %d ", + intval(local_user()), + intval($start), + intval($limit) + ); + + if (Dbm::is_result($r)) + $notifs = $this->formatNotifs($r, $ident); + + $arr = array ( + 'notifications' => $notifs, + 'ident' => $ident, + 'total' => $total, + ); + + return $arr; + } + + /** + * @brief Total number of introductions + * @param bool $all + * If false only include introductions into the query + * which aren't marked as ignored + * @return int Number of introductions + */ + private function introTotal($all = false) { + $sql_extra = ""; + + if(!$all) + $sql_extra = " AND `ignore` = 0 "; + + $r = q("SELECT COUNT(*) AS `total` FROM `intro` + WHERE `intro`.`uid` = %d $sql_extra AND `intro`.`blocked` = 0 ", + intval($_SESSION['uid']) + ); + + if (Dbm::is_result($r)) + return $r[0]['total']; + + return 0; + } + + /** + * @brief Get introductions + * + * @param bool $all + * If false only include introductions into the query + * which aren't marked as ignored + * @param int $start Start the query at this point + * @param int $limit Maximum number of query results + * + * @return array with + * string 'ident' => Notification identifier + * int 'total' => Total number of available introductions + * array 'notifications' => Introductions + */ + public function introNotifs($all = false, $start = 0, $limit = 80) { + $ident = 'introductions'; + $total = $this->introTotal($seen); + $notifs = array(); + $sql_extra = ""; + + if(!$all) + $sql_extra = " AND `ignore` = 0 "; + + /// @todo Fetch contact details by "get_contact_details_by_url" instead of queries to contact, fcontact and gcontact + $r = q("SELECT `intro`.`id` AS `intro_id`, `intro`.*, `contact`.*, + `fcontact`.`name` AS `fname`, `fcontact`.`url` AS `furl`, + `fcontact`.`photo` AS `fphoto`, `fcontact`.`request` AS `frequest`, + `gcontact`.`location` AS `glocation`, `gcontact`.`about` AS `gabout`, + `gcontact`.`keywords` AS `gkeywords`, `gcontact`.`gender` AS `ggender`, + `gcontact`.`network` AS `gnetwork`, `gcontact`.`addr` AS `gaddr` + FROM `intro` + LEFT JOIN `contact` ON `contact`.`id` = `intro`.`contact-id` + LEFT JOIN `gcontact` ON `gcontact`.`nurl` = `contact`.`nurl` + LEFT JOIN `fcontact` ON `intro`.`fid` = `fcontact`.`id` + WHERE `intro`.`uid` = %d $sql_extra AND `intro`.`blocked` = 0 + LIMIT %d, %d", + intval($_SESSION['uid']), + intval($start), + intval($limit) + ); + + if (Dbm::is_result($r)) + $notifs = $this->formatIntros($r); + + $arr = array ( + 'ident' => $ident, + 'total' => $total, + 'notifications' => $notifs, + ); + + return $arr; + } + + /** + * @brief Format the notification query in an usable array + * + * @param array $intros The array from the db query + * @return array with the introductions + */ + private function formatIntros($intros) { + $knowyou = ''; + + foreach($intros as $it) { + // There are two kind of introduction. Contacts suggested by other contacts and normal connection requests. + // We have to distinguish between these two because they use different data. + + // Contact suggestions + if($it['fid']) { + + $return_addr = bin2hex($this->a->user['nickname'] . '@' . $this->a->get_hostname() . (($this->a->path) ? '/' . $this->a->path : '')); + + $intro = array( + 'label' => 'friend_suggestion', + 'notify_type' => t('Friend Suggestion'), + 'intro_id' => $it['intro_id'], + 'madeby' => $it['name'], + 'contact_id' => $it['contact-id'], + 'photo' => ((x($it,'fphoto')) ? proxy_url($it['fphoto'], false, PROXY_SIZE_SMALL) : "images/person-175.jpg"), + 'name' => $it['fname'], + 'url' => zrl($it['furl']), + 'hidden' => $it['hidden'] == 1, + 'post_newfriend' => (intval(PConfig::get(local_user(),'system','post_newfriend')) ? '1' : 0), + + 'knowyou' => $knowyou, + 'note' => $it['note'], + 'request' => $it['frequest'] . '?addr=' . $return_addr, + + ); + + // Normal connection requests + } else { + + $it = $this->getMissingIntroData($it); + + // Don't show these data until you are connected. Diaspora is doing the same. + if($it['gnetwork'] === NETWORK_DIASPORA) { + $it['glocation'] = ""; + $it['gabout'] = ""; + $it['ggender'] = ""; + } + $intro = array( + 'label' => (($it['network'] !== NETWORK_OSTATUS) ? 'friend_request' : 'follower'), + 'notify_type' => (($it['network'] !== NETWORK_OSTATUS) ? t('Friend/Connect Request') : t('New Follower')), + 'dfrn_id' => $it['issued-id'], + 'uid' => $_SESSION['uid'], + 'intro_id' => $it['intro_id'], + 'contact_id' => $it['contact-id'], + 'photo' => ((x($it,'photo')) ? proxy_url($it['photo'], false, PROXY_SIZE_SMALL) : "images/person-175.jpg"), + 'name' => $it['name'], + 'location' => bbcode($it['glocation'], false, false), + 'about' => bbcode($it['gabout'], false, false), + 'keywords' => $it['gkeywords'], + 'gender' => $it['ggender'], + 'hidden' => $it['hidden'] == 1, + 'post_newfriend' => (intval(PConfig::get(local_user(),'system','post_newfriend')) ? '1' : 0), + 'url' => $it['url'], + 'zrl' => zrl($it['url']), + 'addr' => $it['gaddr'], + 'network' => $it['gnetwork'], + 'knowyou' => $it['knowyou'], + 'note' => $it['note'], + ); + } + + $arr[] = $intro; + } + + return $arr; + } + + /** + * @brief Check for missing contact data and try to fetch the data from + * from other sources + * + * @param array $arr The input array with the intro data + * + * @return array The array with the intro data + */ + private function getMissingIntroData($arr) { + // If the network and the addr isn't available from the gcontact + // table entry, take the one of the contact table entry + if ($arr['gnetwork'] == "") { + $arr['gnetwork'] = $arr['network']; + } + if ($arr['gaddr'] == "") { + $arr['gaddr'] = $arr['addr']; + } + + // If the network and addr is still not available + // get the missing data data from other sources + if ($arr['gnetwork'] == "" || $arr['gaddr'] == "") { + $ret = get_contact_details_by_url($arr['url']); + + if ($arr['gnetwork'] == "" && $ret['network'] != "") { + $arr['gnetwork'] = $ret['network']; + } + if ($arr['gaddr'] == "" && $ret['addr'] != "") { + $arr['gaddr'] = $ret['addr']; + } + } + + return $arr; + } +} diff --git a/src/Core/PConfig.php b/src/Core/PConfig.php index 1c64888247..9f6c49bb41 100644 --- a/src/Core/PConfig.php +++ b/src/Core/PConfig.php @@ -1,8 +1,8 @@ $family, 'uid' => $uid)); - if (dbm::is_result($r)) { + if (Dbm::is_result($r)) { while ($rr = dba::fetch($r)) { $k = $rr['k']; $a->config[$uid][$family][$k] = $rr['v']; @@ -90,7 +90,7 @@ class PConfig { } $ret = dba::select('pconfig', array('v'), array('uid' => $uid, 'cat' => $family, 'k' => $key), array('limit' => 1)); - if (dbm::is_result($ret)) { + if (Dbm::is_result($ret)) { $val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret['v']) ? unserialize($ret['v']) : $ret['v']); $a->config[$uid][$family][$key] = $val; self::$in_db[$uid][$family][$key] = true; diff --git a/src/Core/Worker.php b/src/Core/Worker.php index e1787071cb..148b707d14 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -5,10 +5,10 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\Worker; +use Friendica\Database\Dbm; use Friendica\Util\Lock; use dba; -use dbm; /** * @file src/Core/Worker.php @@ -142,7 +142,7 @@ class Worker { */ private static function totalEntries() { $s = dba::fetch_first("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE `executed` <= ? AND NOT `done`", NULL_DATE); - if (dbm::is_result($s)) { + if (Dbm::is_result($s)) { return $s["total"]; } else { return 0; @@ -157,7 +157,7 @@ class Worker { private static function highestPriority() { $condition = array("`executed` <= ? AND NOT `done`", NULL_DATE); $s = dba::select('workerqueue', array('priority'), $condition, array('limit' => 1, 'order' => array('priority'))); - if (dbm::is_result($s)) { + if (Dbm::is_result($s)) { return $s["priority"]; } else { return 0; @@ -405,7 +405,7 @@ class Worker { if ($max == 0) { // the maximum number of possible user connections can be a system variable $r = dba::fetch_first("SHOW VARIABLES WHERE `variable_name` = 'max_user_connections'"); - if (dbm::is_result($r)) { + if (Dbm::is_result($r)) { $max = $r["Value"]; } // Or it can be granted. This overrides the system variable @@ -441,7 +441,7 @@ class Worker { // We will now check for the system values. // This limit could be reached although the user limits are fine. $r = dba::fetch_first("SHOW VARIABLES WHERE `variable_name` = 'max_connections'"); - if (!dbm::is_result($r)) { + if (!Dbm::is_result($r)) { return false; } $max = intval($r["Value"]); @@ -449,7 +449,7 @@ class Worker { return false; } $r = dba::fetch_first("SHOW STATUS WHERE `variable_name` = 'Threads_connected'"); - if (!dbm::is_result($r)) { + if (!Dbm::is_result($r)) { return false; } $used = intval($r["Value"]); @@ -631,7 +631,7 @@ class Worker { INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid` AND NOT `done`"); // No active processes at all? Fine - if (!dbm::is_result($r)) { + if (!Dbm::is_result($r)) { return false; } $priorities = array(); @@ -754,7 +754,7 @@ class Worker { // There can already be jobs for us in the queue. $r = dba::select('workerqueue', array(), array('pid' => getmypid(), 'done' => false)); - if (dbm::is_result($r)) { + if (Dbm::is_result($r)) { self::$db_duration += (microtime(true) - $stamp); return dba::inArray($r); } diff --git a/src/Database/Dbm.php b/src/Database/Dbm.php new file mode 100644 index 0000000000..c5db97f0ee --- /dev/null +++ b/src/Database/Dbm.php @@ -0,0 +1,115 @@ + List of processes, separated in their different states + * 'amount' => Number of concurrent database processes + */ + public static function processlist() { + $r = q("SHOW PROCESSLIST"); + $s = array(); + + $processes = 0; + $states = array(); + foreach ($r AS $process) { + $state = trim($process["State"]); + + // Filter out all non blocking processes + if (!in_array($state, array("", "init", "statistics", "updating"))) { + ++$states[$state]; + ++$processes; + } + } + + $statelist = ""; + foreach ($states AS $state => $usage) { + if ($statelist != "") + $statelist .= ", "; + $statelist .= $state.": ".$usage; + } + return(array("list" => $statelist, "amount" => $processes)); + } + + /** + * Checks if $array is a filled array with at least one entry. + * + * @param $array mixed A filled array with at least one entry + * @return Whether $array is a filled array or an object with rows + */ + public static function is_result($array) { + // It could be a return value from an update statement + if (is_bool($array)) { + return $array; + } + + if (is_object($array)) { + return dba::num_rows($array) > 0; + } + + return (is_array($array) && (count($array) > 0)); + } + + /** + * @brief Callback function for "esc_array" + * + * @param mixed $value Array value + * @param string $key Array key + * @param boolean $add_quotation add quotation marks for string values + */ + private static function esc_array_callback(&$value, $key, $add_quotation) { + + if (!$add_quotation) { + if (is_bool($value)) { + $value = ($value ? '1' : '0'); + } else { + $value = dbesc($value); + } + return; + } + + if (is_bool($value)) { + $value = ($value ? 'true' : 'false'); + } elseif (is_float($value) || is_integer($value)) { + $value = (string)$value; + } else { + $value = "'".dbesc($value)."'"; + } + } + + /** + * @brief Escapes a whole array + * + * @param mixed $arr Array with values to be escaped + * @param boolean $add_quotation add quotation marks for string values + */ + public static function esc_array(&$arr, $add_quotation = false) { + array_walk($arr, 'self::esc_array_callback', $add_quotation); + } + + /** + * Checks Converts any date string into a SQL compatible date string + * + * @param string $date a date string in any format + * @return string SQL style date string + */ + public static function date($date = 'now') { + $timestamp = strtotime($date); + + // Don't allow lower date strings as '0001-01-01 00:00:00' + if ($timestamp < -62135596800) { + $timestamp = -62135596800; + } + + return date('Y-m-d H:i:s', (int)$timestamp); + } +} diff --git a/src/Network/Probe.php b/src/Network/Probe.php index 2f79fe80e1..7e1d28ef8a 100644 --- a/src/Network/Probe.php +++ b/src/Network/Probe.php @@ -11,9 +11,9 @@ namespace Friendica\Network; use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; +use Friendica\Database\Dbm; use dba; -use dbm; use Cache; use xml; @@ -397,7 +397,7 @@ class Probe { } } - $fields['updated'] = dbm::date(); + $fields['updated'] = Dbm::date(); $condition = array('nurl' => normalise_link($data["url"])); @@ -420,7 +420,7 @@ class Probe { 'confirm' => $data['confirm'], 'poco' => $data['poco'], 'network' => $data['network'], - 'success_update' => dbm::date()); + 'success_update' => Dbm::date()); $fieldnames = array(); @@ -1501,7 +1501,7 @@ class Probe { $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval($uid)); - if (dbm::is_result($x) && dbm::is_result($r)) { + if (Dbm::is_result($x) && Dbm::is_result($r)) { $mailbox = construct_mailbox_name($r[0]); $password = ''; openssl_private_decrypt(hex2bin($r[0]['pass']), $password, $x[0]['prvkey']); diff --git a/src/Protocol/Dfrn.php b/src/Protocol/Dfrn.php new file mode 100644 index 0000000000..d0597603a2 --- /dev/null +++ b/src/Protocol/Dfrn.php @@ -0,0 +1,2970 @@ +formatOutput = true; + + $root = self::add_header($doc, $owner, "dfrn:owner", "", false); + + if (! count($items)) { + return trim($doc->saveXML()); + } + + foreach ($items as $item) { + $entry = self::entry($doc, "text", $item, $owner, $item["entry:comment-allow"], $item["entry:cid"]); + $root->appendChild($entry); + } + + return(trim($doc->saveXML())); + } + + /** + * @brief Generate an atom feed for the given user + * + * This function is called when another server is pulling data from the user feed. + * + * @param string $dfrn_id DFRN ID from the requesting party + * @param string $owner_nick Owner nick name + * @param string $last_update Date of the last update + * @param int $direction Can be -1, 0 or 1. + * @param boolean $onlyheader Output only the header without content? (Default is "no") + * + * @return string DFRN feed entries + */ + public static function feed($dfrn_id, $owner_nick, $last_update, $direction = 0, $onlyheader = false) { + + $a = get_app(); + + $sitefeed = ((strlen($owner_nick)) ? false : true); // not yet implemented, need to rewrite huge chunks of following logic + $public_feed = (($dfrn_id) ? false : true); + $starred = false; // not yet implemented, possible security issues + $converse = false; + + if ($public_feed && $a->argc > 2) { + for ($x = 2; $x < $a->argc; $x++) { + if ($a->argv[$x] == 'converse') { + $converse = true; + } + if ($a->argv[$x] == 'starred') { + $starred = true; + } + if ($a->argv[$x] == 'category' && $a->argc > ($x + 1) && strlen($a->argv[$x+1])) { + $category = $a->argv[$x+1]; + } + } + } + + + + // default permissions - anonymous user + + $sql_extra = " AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' "; + + $r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`, `user`.`account-type` + FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` + WHERE `contact`.`self` AND `user`.`nickname` = '%s' LIMIT 1", + dbesc($owner_nick) + ); + + if (! Dbm::is_result($r)) { + killme(); + } + + $owner = $r[0]; + $owner_id = $owner['uid']; + $owner_nick = $owner['nickname']; + + $sql_post_table = ""; + + if (! $public_feed) { + + $sql_extra = ''; + switch($direction) { + case (-1): + $sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($dfrn_id)); + $my_id = $dfrn_id; + break; + case 0: + $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id)); + $my_id = '1:' . $dfrn_id; + break; + case 1: + $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id)); + $my_id = '0:' . $dfrn_id; + break; + default: + return false; + break; // NOTREACHED + } + + $r = q("SELECT * FROM `contact` WHERE NOT `blocked` AND `contact`.`uid` = %d $sql_extra LIMIT 1", + intval($owner_id) + ); + + if (! Dbm::is_result($r)) { + killme(); + } + + $contact = $r[0]; + require_once('include/security.php'); + $groups = init_groups_visitor($contact['id']); + + if (count($groups)) { + for ($x = 0; $x < count($groups); $x ++) + $groups[$x] = '<' . intval($groups[$x]) . '>' ; + $gs = implode('|', $groups); + } else { + $gs = '<<>>' ; // Impossible to match + } + + $sql_extra = sprintf(" + AND ( `allow_cid` = '' OR `allow_cid` REGEXP '<%d>' ) + AND ( `deny_cid` = '' OR NOT `deny_cid` REGEXP '<%d>' ) + AND ( `allow_gid` = '' OR `allow_gid` REGEXP '%s' ) + AND ( `deny_gid` = '' OR NOT `deny_gid` REGEXP '%s') + ", + intval($contact['id']), + intval($contact['id']), + dbesc($gs), + dbesc($gs) + ); + } + + if ($public_feed) { + $sort = 'DESC'; + } else { + $sort = 'ASC'; + } + + if (! strlen($last_update)) { + $last_update = 'now -30 days'; + } + + if (isset($category)) { + $sql_post_table = sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ", + dbesc(protect_sprintf($category)), intval(TERM_OBJ_POST), intval(TERM_CATEGORY), intval($owner_id)); + //$sql_extra .= file_tag_file_query('item',$category,'category'); + } + + if ($public_feed) { + if (! $converse) { + $sql_extra .= " AND `contact`.`self` = 1 "; + } + } + + $check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s'); + + $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, + `contact`.`name`, `contact`.`network`, `contact`.`photo`, `contact`.`url`, + `contact`.`name-date`, `contact`.`uri-date`, `contact`.`avatar-date`, + `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`, + `sign`.`signed_text`, `sign`.`signature`, `sign`.`signer` + FROM `item` USE INDEX (`uid_wall_changed`) $sql_post_table + STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` + AND (NOT `contact`.`blocked` OR `contact`.`pending`) + LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` + WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`moderated` AND `item`.`parent` != 0 + AND `item`.`wall` AND `item`.`changed` > '%s' + $sql_extra + ORDER BY `item`.`parent` ".$sort.", `item`.`created` ASC LIMIT 0, 300", + intval($owner_id), + dbesc($check_date), + dbesc($sort) + ); + + /* + * Will check further below if this actually returned results. + * We will provide an empty feed if that is the case. + */ + + $items = $r; + + $doc = new DOMDocument('1.0', 'utf-8'); + $doc->formatOutput = true; + + $alternatelink = $owner['url']; + + if (isset($category)) { + $alternatelink .= "/category/".$category; + } + + if ($public_feed) { + $author = "dfrn:owner"; + } else { + $author = "author"; + } + + $root = self::add_header($doc, $owner, $author, $alternatelink, true); + + /// @TODO This hook can't work anymore + // call_hooks('atom_feed', $atom); + + if (!Dbm::is_result($items) || $onlyheader) { + $atom = trim($doc->saveXML()); + + call_hooks('atom_feed_end', $atom); + + return $atom; + } + + foreach ($items as $item) { + + // prevent private email from leaking. + if ($item['network'] == NETWORK_MAIL) { + continue; + } + + // public feeds get html, our own nodes use bbcode + + if ($public_feed) { + $type = 'html'; + // catch any email that's in a public conversation and make sure it doesn't leak + if ($item['private']) { + continue; + } + } else { + $type = 'text'; + } + + $entry = self::entry($doc, $type, $item, $owner, true); + $root->appendChild($entry); + + } + + $atom = trim($doc->saveXML()); + + call_hooks('atom_feed_end', $atom); + + return $atom; + } + + /** + * @brief Generate an atom entry for a given item id + * + * @param int $item_id The item id + * @param boolean $conversation Show the conversation. If false show the single post. + * + * @return string DFRN feed entry + */ + public static function itemFeed($item_id, $conversation = false) { + if ($conversation) { + $condition = '`item`.`parent`'; + } else { + $condition = '`item`.`id`'; + } + + $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, + `contact`.`name`, `contact`.`network`, `contact`.`photo`, `contact`.`url`, + `contact`.`name-date`, `contact`.`uri-date`, `contact`.`avatar-date`, + `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`, + `sign`.`signed_text`, `sign`.`signature`, `sign`.`signer` + FROM `item` + STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` + AND (NOT `contact`.`blocked` OR `contact`.`pending`) + LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` + WHERE %s = %d AND `item`.`visible` AND NOT `item`.`moderated` AND `item`.`parent` != 0 + AND NOT `item`.`private`", + $condition, + intval($item_id) + ); + + if (!Dbm::is_result($r)) { + killme(); + } + + $items = $r; + $item = $r[0]; + + $r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`, `user`.`account-type` + FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` + WHERE `contact`.`self` AND `user`.`uid` = %d LIMIT 1", + intval($item['uid']) + ); + + if (!Dbm::is_result($r)) { + killme(); + } + + $owner = $r[0]; + + $doc = new DOMDocument('1.0', 'utf-8'); + $doc->formatOutput = true; + $type = 'html'; + + if ($conversation) { + $root = $doc->createElementNS(NAMESPACE_ATOM1, 'feed'); + $doc->appendChild($root); + + $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); + + //$root = self::add_header($doc, $owner, "dfrn:owner", "", false); + + foreach ($items as $item) { + $entry = self::entry($doc, $type, $item, $owner, true, 0); + $root->appendChild($entry); + } + } else { + $root = self::entry($doc, $type, $item, $owner, true, 0, true); + } + + $atom = trim($doc->saveXML()); + return $atom; + } + + /** + * @brief Create XML text for DFRN mails + * + * @param array $item message elements + * @param array $owner Owner record + * + * @return string DFRN mail + * @todo Add type-hints + */ + public static function mail($item, $owner) { + $doc = new DOMDocument('1.0', 'utf-8'); + $doc->formatOutput = true; + + $root = self::add_header($doc, $owner, "dfrn:owner", "", false); + + $mail = $doc->createElement("dfrn:mail"); + $sender = $doc->createElement("dfrn:sender"); + + xml::add_element($doc, $sender, "dfrn:name", $owner['name']); + xml::add_element($doc, $sender, "dfrn:uri", $owner['url']); + xml::add_element($doc, $sender, "dfrn:avatar", $owner['thumb']); + + $mail->appendChild($sender); + + xml::add_element($doc, $mail, "dfrn:id", $item['uri']); + xml::add_element($doc, $mail, "dfrn:in-reply-to", $item['parent-uri']); + xml::add_element($doc, $mail, "dfrn:sentdate", datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)); + xml::add_element($doc, $mail, "dfrn:subject", $item['title']); + xml::add_element($doc, $mail, "dfrn:content", $item['body']); + + $root->appendChild($mail); + + return(trim($doc->saveXML())); + } + + /** + * @brief Create XML text for DFRN friend suggestions + * + * @param array $item suggestion elements + * @param array $owner Owner record + * + * @return string DFRN suggestions + * @todo Add type-hints + */ + public static function fsuggest($item, $owner) { + $doc = new DOMDocument('1.0', 'utf-8'); + $doc->formatOutput = true; + + $root = self::add_header($doc, $owner, "dfrn:owner", "", false); + + $suggest = $doc->createElement("dfrn:suggest"); + + xml::add_element($doc, $suggest, "dfrn:url", $item['url']); + xml::add_element($doc, $suggest, "dfrn:name", $item['name']); + xml::add_element($doc, $suggest, "dfrn:photo", $item['photo']); + xml::add_element($doc, $suggest, "dfrn:request", $item['request']); + xml::add_element($doc, $suggest, "dfrn:note", $item['note']); + + $root->appendChild($suggest); + + return(trim($doc->saveXML())); + } + + /** + * @brief Create XML text for DFRN relocations + * + * @param array $owner Owner record + * @param int $uid User ID + * + * @return string DFRN relocations + * @todo Add type-hints + */ + public static function relocate($owner, $uid) { + + /* get site pubkey. this could be a new installation with no site keys*/ + $pubkey = Config::get('system','site_pubkey'); + if (! $pubkey) { + $res = new_keypair(1024); + Config::set('system','site_prvkey', $res['prvkey']); + Config::set('system','site_pubkey', $res['pubkey']); + } + + $rp = q("SELECT `resource-id` , `scale`, type FROM `photo` + WHERE `profile` = 1 AND `uid` = %d ORDER BY scale;", $uid); + $photos = array(); + $ext = Photo::supportedTypes(); + + foreach ($rp as $p) { + $photos[$p['scale']] = System::baseUrl().'/photo/'.$p['resource-id'].'-'.$p['scale'].'.'.$ext[$p['type']]; + } + + unset($rp, $ext); + + $doc = new DOMDocument('1.0', 'utf-8'); + $doc->formatOutput = true; + + $root = self::add_header($doc, $owner, "dfrn:owner", "", false); + + $relocate = $doc->createElement("dfrn:relocate"); + + xml::add_element($doc, $relocate, "dfrn:url", $owner['url']); + xml::add_element($doc, $relocate, "dfrn:name", $owner['name']); + xml::add_element($doc, $relocate, "dfrn:addr", $owner['addr']); + xml::add_element($doc, $relocate, "dfrn:avatar", $owner['avatar']); + xml::add_element($doc, $relocate, "dfrn:photo", $photos[4]); + xml::add_element($doc, $relocate, "dfrn:thumb", $photos[5]); + xml::add_element($doc, $relocate, "dfrn:micro", $photos[6]); + xml::add_element($doc, $relocate, "dfrn:request", $owner['request']); + xml::add_element($doc, $relocate, "dfrn:confirm", $owner['confirm']); + xml::add_element($doc, $relocate, "dfrn:notify", $owner['notify']); + xml::add_element($doc, $relocate, "dfrn:poll", $owner['poll']); + xml::add_element($doc, $relocate, "dfrn:sitepubkey", Config::get('system','site_pubkey')); + + $root->appendChild($relocate); + + return(trim($doc->saveXML())); + } + + /** + * @brief Adds the header elements for the DFRN protocol + * + * @param object $doc XML document + * @param array $owner Owner record + * @param string $authorelement Element name for the author + * @param string $alternatelink link to profile or category + * @param bool $public Is it a header for public posts? + * + * @return object XML root object + * @todo Add type-hints + */ + private static function add_header($doc, $owner, $authorelement, $alternatelink = "", $public = false) { + + if ($alternatelink == "") { + $alternatelink = $owner['url']; + } + + $root = $doc->createElementNS(NAMESPACE_ATOM1, 'feed'); + $doc->appendChild($root); + + $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", System::baseUrl()."/profile/".$owner["nick"]); + xml::add_element($doc, $root, "title", $owner["name"]); + + $attributes = array("uri" => "https://friendi.ca", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION); + xml::add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes); + + $attributes = array("rel" => "license", "href" => "http://creativecommons.org/licenses/by/3.0/"); + xml::add_element($doc, $root, "link", "", $attributes); + + $attributes = array("rel" => "alternate", "type" => "text/html", "href" => $alternatelink); + xml::add_element($doc, $root, "link", "", $attributes); + + + if ($public) { + // DFRN itself doesn't uses this. But maybe someone else wants to subscribe to the public feed. + ostatus::hublinks($doc, $root, $owner["nick"]); + + $attributes = array("rel" => "salmon", "href" => System::baseUrl()."/salmon/".$owner["nick"]); + xml::add_element($doc, $root, "link", "", $attributes); + + $attributes = array("rel" => "http://salmon-protocol.org/ns/salmon-replies", "href" => System::baseUrl()."/salmon/".$owner["nick"]); + xml::add_element($doc, $root, "link", "", $attributes); + + $attributes = array("rel" => "http://salmon-protocol.org/ns/salmon-mention", "href" => System::baseUrl()."/salmon/".$owner["nick"]); + xml::add_element($doc, $root, "link", "", $attributes); + } + + // For backward compatibility we keep this element + if ($owner['page-flags'] == PAGE_COMMUNITY) { + xml::add_element($doc, $root, "dfrn:community", 1); + } + + // The former element is replaced by this one + xml::add_element($doc, $root, "dfrn:account_type", $owner["account-type"]); + + /// @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); + $root->appendChild($author); + + return $root; + } + + /** + * @brief Adds the author element in the header for the DFRN protocol + * + * @param object $doc XML document + * @param array $owner Owner record + * @param string $authorelement Element name for the author + * + * @return object XML author object + * @todo Add type-hints + */ + private static function add_author($doc, $owner, $authorelement, $public) { + + // Is the profile hidden or shouldn't be published in the net? Then add the "hide" element + $r = q("SELECT `id` FROM `profile` INNER JOIN `user` ON `user`.`uid` = `profile`.`uid` + WHERE (`hidewall` OR NOT `net-publish`) AND `user`.`uid` = %d", + intval($owner['uid'])); + if (Dbm::is_result($r)) { + $hidewall = true; + } else { + $hidewall = false; + } + + $author = $doc->createElement($authorelement); + + $namdate = datetime_convert('UTC', 'UTC', $owner['name-date'].'+00:00', ATOM_TIME); + $uridate = datetime_convert('UTC', 'UTC', $owner['uri-date'].'+00:00', ATOM_TIME); + $picdate = datetime_convert('UTC', 'UTC', $owner['avatar-date'].'+00:00', ATOM_TIME); + + $attributes = array(); + + if (!$public || !$hidewall) { + $attributes = array("dfrn:updated" => $namdate); + } + + xml::add_element($doc, $author, "name", $owner["name"], $attributes); + xml::add_element($doc, $author, "uri", System::baseUrl().'/profile/'.$owner["nickname"], $attributes); + xml::add_element($doc, $author, "dfrn:handle", $owner["addr"], $attributes); + + $attributes = array("rel" => "photo", "type" => "image/jpeg", + "media:width" => 175, "media:height" => 175, "href" => $owner['photo']); + + if (!$public || !$hidewall) { + $attributes["dfrn:updated"] = $picdate; + } + + xml::add_element($doc, $author, "link", "", $attributes); + + $attributes["rel"] = "avatar"; + xml::add_element($doc, $author, "link", "", $attributes); + + if ($hidewall) { + xml::add_element($doc, $author, "dfrn:hide", "true"); + } + + // The following fields will only be generated if the data isn't meant for a public feed + if ($public) { + return $author; + } + + $birthday = feed_birthday($owner['uid'], $owner['timezone']); + + if ($birthday) + xml::add_element($doc, $author, "dfrn:birthday", $birthday); + + // Only show contact details when we are allowed to + $r = q("SELECT `profile`.`about`, `profile`.`name`, `profile`.`homepage`, `user`.`nickname`, + `user`.`timezone`, `profile`.`locality`, `profile`.`region`, `profile`.`country-name`, + `profile`.`pub_keywords`, `profile`.`xmpp`, `profile`.`dob` + FROM `profile` + INNER JOIN `user` ON `user`.`uid` = `profile`.`uid` + WHERE `profile`.`is-default` AND NOT `user`.`hidewall` AND `user`.`uid` = %d", + intval($owner['uid'])); + if (Dbm::is_result($r)) { + $profile = $r[0]; + + xml::add_element($doc, $author, "poco:displayName", $profile["name"]); + xml::add_element($doc, $author, "poco:updated", $namdate); + + if (trim($profile["dob"]) > '0001-01-01') { + xml::add_element($doc, $author, "poco:birthday", "0000-".date("m-d", strtotime($profile["dob"]))); + } + + xml::add_element($doc, $author, "poco:note", $profile["about"]); + xml::add_element($doc, $author, "poco:preferredUsername", $profile["nickname"]); + + $savetz = date_default_timezone_get(); + date_default_timezone_set($profile["timezone"]); + xml::add_element($doc, $author, "poco:utcOffset", date("P")); + date_default_timezone_set($savetz); + + if (trim($profile["homepage"]) != "") { + $urls = $doc->createElement("poco:urls"); + xml::add_element($doc, $urls, "poco:type", "homepage"); + xml::add_element($doc, $urls, "poco:value", $profile["homepage"]); + xml::add_element($doc, $urls, "poco:primary", "true"); + $author->appendChild($urls); + } + + if (trim($profile["pub_keywords"]) != "") { + $keywords = explode(",", $profile["pub_keywords"]); + + foreach ($keywords AS $keyword) { + xml::add_element($doc, $author, "poco:tags", trim($keyword)); + } + + } + + if (trim($profile["xmpp"]) != "") { + $ims = $doc->createElement("poco:ims"); + xml::add_element($doc, $ims, "poco:type", "xmpp"); + xml::add_element($doc, $ims, "poco:value", $profile["xmpp"]); + xml::add_element($doc, $ims, "poco:primary", "true"); + $author->appendChild($ims); + } + + if (trim($profile["locality"].$profile["region"].$profile["country-name"]) != "") { + $element = $doc->createElement("poco:address"); + + xml::add_element($doc, $element, "poco:formatted", formatted_location($profile)); + + if (trim($profile["locality"]) != "") { + xml::add_element($doc, $element, "poco:locality", $profile["locality"]); + } + + if (trim($profile["region"]) != "") { + xml::add_element($doc, $element, "poco:region", $profile["region"]); + } + + if (trim($profile["country-name"]) != "") { + xml::add_element($doc, $element, "poco:country", $profile["country-name"]); + } + + $author->appendChild($element); + } + } + + return $author; + } + + /** + * @brief Adds the author elements in the "entry" elements of the DFRN protocol + * + * @param object $doc XML document + * @param string $element Element name for the author + * @param string $contact_url Link of the contact + * @param array $items Item elements + * + * @return object XML author object + * @todo Add type-hints + */ + private static function add_entry_author($doc, $element, $contact_url, $item) { + + $contact = get_contact_details_by_url($contact_url, $item["uid"]); + + $author = $doc->createElement($element); + xml::add_element($doc, $author, "name", $contact["name"]); + xml::add_element($doc, $author, "uri", $contact["url"]); + xml::add_element($doc, $author, "dfrn:handle", $contact["addr"]); + + /// @Todo + /// - Check real image type and image size + /// - Check which of these boths elements we should use + $attributes = array( + "rel" => "photo", + "type" => "image/jpeg", + "media:width" => 80, + "media:height" => 80, + "href" => $contact["photo"]); + xml::add_element($doc, $author, "link", "", $attributes); + + $attributes = array( + "rel" => "avatar", + "type" => "image/jpeg", + "media:width" => 80, + "media:height" => 80, + "href" => $contact["photo"]); + xml::add_element($doc, $author, "link", "", $attributes); + + return $author; + } + + /** + * @brief Adds the activity elements + * + * @param object $doc XML document + * @param string $element Element name for the activity + * @param string $activity activity value + * + * @return object XML activity object + * @todo Add type-hints + */ + private static function create_activity($doc, $element, $activity) { + + if ($activity) { + $entry = $doc->createElement($element); + + $r = parse_xml_string($activity, false); + if (!$r) { + return false; + } + if ($r->type) { + xml::add_element($doc, $entry, "activity:object-type", $r->type); + } + if ($r->id) { + xml::add_element($doc, $entry, "id", $r->id); + } + if ($r->title) { + xml::add_element($doc, $entry, "title", $r->title); + } + + if ($r->link) { + if (substr($r->link, 0, 1) == '<') { + if (strstr($r->link, '&') && (! strstr($r->link, '&'))) { + $r->link = str_replace('&', '&', $r->link); + } + + $r->link = preg_replace('/\/', '', $r->link); + + // XML does need a single element as root element so we add a dummy element here + $data = parse_xml_string("" . $r->link . "", false); + if (is_object($data)) { + foreach ($data->link AS $link) { + $attributes = array(); + foreach ($link->attributes() AS $parameter => $value) { + $attributes[$parameter] = $value; + } + xml::add_element($doc, $entry, "link", "", $attributes); + } + } + } else { + $attributes = array("rel" => "alternate", "type" => "text/html", "href" => $r->link); + xml::add_element($doc, $entry, "link", "", $attributes); + } + } + if ($r->content) { + xml::add_element($doc, $entry, "content", bbcode($r->content), array("type" => "html")); + } + + return $entry; + } + + return false; + } + + /** + * @brief Adds the elements for attachments + * + * @param object $doc XML document + * @param object $root XML root + * @param array $item Item element + * + * @return object XML attachment object + * @todo Add type-hints + */ + private static function get_attachment($doc, $root, $item) { + $arr = explode('[/attach],',$item['attach']); + if (count($arr)) { + foreach ($arr as $r) { + $matches = false; + $cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|',$r,$matches); + if ($cnt) { + $attributes = array("rel" => "enclosure", + "href" => $matches[1], + "type" => $matches[3]); + + if (intval($matches[2])) { + $attributes["length"] = intval($matches[2]); + } + + if (trim($matches[4]) != "") { + $attributes["title"] = trim($matches[4]); + } + + xml::add_element($doc, $root, "link", "", $attributes); + } + } + } + } + + /** + * @brief Adds the "entry" elements for the DFRN protocol + * + * @param object $doc XML document + * @param string $type "text" or "html" + * @param array $item Item element + * @param array $owner Owner record + * @param bool $comment Trigger the sending of the "comment" element + * @param int $cid Contact ID of the recipient + * @param bool $single If set, the entry is created as an XML document with a single "entry" element + * + * @return object XML entry object + * @todo Add type-hints + */ + private static function entry($doc, $type, $item, $owner, $comment = false, $cid = 0, $single = false) { + + $mentioned = array(); + + if (!$item['parent']) { + return; + } + + if ($item['deleted']) { + $attributes = array("ref" => $item['uri'], "when" => datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)); + return xml::create_element($doc, "at:deleted-entry", "", $attributes); + } + + if (!$single) { + $entry = $doc->createElement("entry"); + } else { + $entry = $doc->createElementNS(NAMESPACE_ATOM1, 'entry'); + $doc->appendChild($entry); + + $entry->setAttribute("xmlns:thr", NAMESPACE_THREAD); + $entry->setAttribute("xmlns:at", NAMESPACE_TOMB); + $entry->setAttribute("xmlns:media", NAMESPACE_MEDIA); + $entry->setAttribute("xmlns:dfrn", NAMESPACE_DFRN); + $entry->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY); + $entry->setAttribute("xmlns:georss", NAMESPACE_GEORSS); + $entry->setAttribute("xmlns:poco", NAMESPACE_POCO); + $entry->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS); + $entry->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET); + } + + if ($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid']) { + $body = fix_private_photos($item['body'],$owner['uid'],$item,$cid); + } else { + $body = $item['body']; + } + + // Remove the abstract element. It is only locally important. + $body = remove_abstract($body); + + if ($type == 'html') { + $htmlbody = $body; + + if ($item['title'] != "") { + $htmlbody = "[b]".$item['title']."[/b]\n\n".$htmlbody; + } + + $htmlbody = bbcode($htmlbody, false, false, 7); + } + + $author = self::add_entry_author($doc, "author", $item["author-link"], $item); + $entry->appendChild($author); + + $dfrnowner = self::add_entry_author($doc, "dfrn:owner", $item["owner-link"], $item); + $entry->appendChild($dfrnowner); + + if (($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || (($item['thr-parent'] !== '') && ($item['thr-parent'] !== $item['uri']))) { + $parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']); + $parent = q("SELECT `guid`,`plink` FROM `item` WHERE `uri` = '%s' AND `uid` = %d", dbesc($parent_item), intval($item['uid'])); + $attributes = array("ref" => $parent_item, "type" => "text/html", + "href" => $parent[0]['plink'], + "dfrn:diaspora_guid" => $parent[0]['guid']); + xml::add_element($doc, $entry, "thr:in-reply-to", "", $attributes); + } + + // Add conversation data. This is used for OStatus + $conversation_href = System::baseUrl()."/display/".$owner["nick"]."/".$item["parent"]; + $conversation_uri = $conversation_href; + + if (isset($parent_item)) { + $r = dba::fetch_first("SELECT `conversation-uri`, `conversation-href` FROM `conversation` WHERE `item-uri` = ?", $item['parent-uri']); + if (Dbm::is_result($r)) { + if ($r['conversation-uri'] != '') { + $conversation_uri = $r['conversation-uri']; + } + if ($r['conversation-href'] != '') { + $conversation_href = $r['conversation-href']; + } + } + } + + $attributes = array( + "href" => $conversation_href, + "ref" => $conversation_uri); + + xml::add_element($doc, $entry, "ostatus:conversation", $conversation_uri, $attributes); + + xml::add_element($doc, $entry, "id", $item["uri"]); + xml::add_element($doc, $entry, "title", $item["title"]); + + xml::add_element($doc, $entry, "published", datetime_convert("UTC","UTC",$item["created"]."+00:00",ATOM_TIME)); + xml::add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME)); + + // "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" => System::baseUrl()."/display/".$item["guid"])); + + // "comment-allow" is some old fashioned stuff for old Friendica versions. + // It is included in the rewritten code for completeness + if ($comment) { + xml::add_element($doc, $entry, "dfrn:comment-allow", intval($item['last-child'])); + } + + if ($item['location']) { + xml::add_element($doc, $entry, "dfrn:location", $item['location']); + } + + if ($item['coord']) { + xml::add_element($doc, $entry, "georss:point", $item['coord']); + } + + if (($item['private']) || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) { + xml::add_element($doc, $entry, "dfrn:private", (($item['private']) ? $item['private'] : 1)); + } + + if ($item['extid']) { + xml::add_element($doc, $entry, "dfrn:extid", $item['extid']); + } + + if ($item['bookmark']) { + xml::add_element($doc, $entry, "dfrn:bookmark", "true"); + } + + if ($item['app']) { + xml::add_element($doc, $entry, "statusnet:notice_info", "", array("local_id" => $item['id'], "source" => $item['app'])); + } + + xml::add_element($doc, $entry, "dfrn:diaspora_guid", $item["guid"]); + + // The signed text contains the content in Markdown, the sender handle and the signatur for the content + // It is needed for relayed comments to Diaspora. + if ($item['signed_text']) { + $sign = base64_encode(json_encode(array('signed_text' => $item['signed_text'],'signature' => $item['signature'],'signer' => $item['signer']))); + xml::add_element($doc, $entry, "dfrn:diaspora_signature", $sign); + } + + xml::add_element($doc, $entry, "activity:verb", construct_verb($item)); + + if ($item['object-type'] != "") { + xml::add_element($doc, $entry, "activity:object-type", $item['object-type']); + } elseif ($item['id'] == $item['parent']) { + xml::add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE); + } else { + xml::add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_COMMENT); + } + + $actobj = self::create_activity($doc, "activity:object", $item['object']); + if ($actobj) { + $entry->appendChild($actobj); + } + + $actarg = self::create_activity($doc, "activity:target", $item['target']); + if ($actarg) { + $entry->appendChild($actarg); + } + + $tags = item_getfeedtags($item); + + if (count($tags)) { + foreach ($tags as $t) { + if (($type != 'html') || ($t[0] != "@")) { + xml::add_element($doc, $entry, "category", "", array("scheme" => "X-DFRN:".$t[0].":".$t[1], "term" => $t[2])); + } + } + } + + if (count($tags)) { + foreach ($tags as $t) { + if ($t[0] == "@") { + $mentioned[$t[1]] = $t[1]; + } + } + } + + foreach ($mentioned AS $mention) { + $r = q("SELECT `forum`, `prv` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s'", + intval($owner["uid"]), + dbesc(normalise_link($mention))); + + if (Dbm::is_result($r) && ($r[0]["forum"] || $r[0]["prv"])) { + xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned", + "ostatus:object-type" => ACTIVITY_OBJ_GROUP, + "href" => $mention)); + } else { + xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned", + "ostatus:object-type" => ACTIVITY_OBJ_PERSON, + "href" => $mention)); + } + } + + self::get_attachment($doc, $entry, $item); + + return $entry; + } + + /** + * @brief encrypts data via AES + * + * @param string $data The data that is to be encrypted + * @param string $key The AES key + * + * @return string encrypted data + */ + private static function aes_encrypt($data, $key) { + return openssl_encrypt($data, 'aes-128-ecb', $key, OPENSSL_RAW_DATA); + } + + /** + * @brief decrypts data via AES + * + * @param string $encrypted The encrypted data + * @param string $key The AES key + * + * @return string decrypted data + */ + public static function aes_decrypt($encrypted, $key) { + return openssl_decrypt($encrypted, 'aes-128-ecb', $key, OPENSSL_RAW_DATA); + } + + /** + * @brief Delivers the atom content to the contacts + * + * @param array $owner Owner record + * @param array $contactr Contact record of the receiver + * @param string $atom Content that will be transmitted + * @param bool $dissolve (to be documented) + * + * @return int Deliver status. -1 means an error. + * @todo Add array type-hint for $owner, $contact + */ + public static function deliver($owner,$contact,$atom, $dissolve = false) { + + $a = get_app(); + + $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']); + + if ($contact['duplex'] && $contact['dfrn-id']) { + $idtosend = '0:' . $orig_id; + } + if ($contact['duplex'] && $contact['issued-id']) { + $idtosend = '1:' . $orig_id; + } + + $rino = Config::get('system', 'rino_encrypt'); + $rino = intval($rino); + + logger("Local rino version: ". $rino, LOGGER_DEBUG); + + $ssl_val = intval(Config::get('system','ssl_policy')); + $ssl_policy = ''; + + switch ($ssl_val) { + case SSL_POLICY_FULL: + $ssl_policy = 'full'; + break; + case SSL_POLICY_SELFSIGN: + $ssl_policy = 'self'; + break; + case SSL_POLICY_NONE: + default: + $ssl_policy = 'none'; + break; + } + + $url = $contact['notify'] . '&dfrn_id=' . $idtosend . '&dfrn_version=' . DFRN_PROTOCOL_VERSION . (($rino) ? '&rino='.$rino : ''); + + logger('dfrn_deliver: ' . $url); + + $ret = z_fetch_url($url); + + if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { + return -2; // timed out + } + + $xml = $ret['body']; + + $curl_stat = $a->get_curl_code(); + if (!$curl_stat) { + return -3; // timed out + } + + logger('dfrn_deliver: ' . $xml, LOGGER_DATA); + + if (! $xml) { + return 3; + } + + if (strpos($xml,'status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id))) { + return (($res->status) ? $res->status : 3); + } + + $postvars = array(); + $sent_dfrn_id = hex2bin((string) $res->dfrn_id); + $challenge = hex2bin((string) $res->challenge); + $perm = (($res->perm) ? $res->perm : null); + $dfrn_version = (float) (($res->dfrn_version) ? $res->dfrn_version : 2.0); + $rino_remote_version = intval($res->rino); + $page = (($owner['page-flags'] == PAGE_COMMUNITY) ? 1 : 0); + + logger("Remote rino version: ".$rino_remote_version." for ".$contact["url"], LOGGER_DEBUG); + + if ($owner['page-flags'] == PAGE_PRVGROUP) { + $page = 2; + } + + $final_dfrn_id = ''; + + if ($perm) { + if ((($perm == 'rw') && (! intval($contact['writable']))) + || (($perm == 'r') && (intval($contact['writable'])))) { + q("update contact set writable = %d where id = %d", + intval(($perm == 'rw') ? 1 : 0), + intval($contact['id']) + ); + $contact['writable'] = (string) 1 - intval($contact['writable']); + } + } + + if (($contact['duplex'] && strlen($contact['pubkey'])) + || ($owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey'])) + || ($contact['rel'] == CONTACT_IS_SHARING && strlen($contact['pubkey']))) { + openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']); + openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']); + } else { + openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']); + openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']); + } + + $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.')); + + if (strpos($final_dfrn_id,':') == 1) { + $final_dfrn_id = substr($final_dfrn_id,2); + } + + if ($final_dfrn_id != $orig_id) { + logger('dfrn_deliver: wrong dfrn_id.'); + // did not decode properly - cannot trust this site + return 3; + } + + $postvars['dfrn_id'] = $idtosend; + $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION; + if ($dissolve) { + $postvars['dissolve'] = '1'; + } + + + if ((($contact['rel']) && ($contact['rel'] != CONTACT_IS_SHARING) && (! $contact['blocked'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) { + $postvars['data'] = $atom; + $postvars['perm'] = 'rw'; + } else { + $postvars['data'] = str_replace('1','0',$atom); + $postvars['perm'] = 'r'; + } + + $postvars['ssl_policy'] = $ssl_policy; + + if ($page) { + $postvars['page'] = $page; + } + + + if ($rino > 0 && $rino_remote_version > 0 && (! $dissolve)) { + logger('rino version: '. $rino_remote_version); + + switch ($rino_remote_version) { + case 1: + // Deprecated rino version! + $key = openssl_random_pseudo_bytes(16); + $data = self::aes_encrypt($postvars['data'], $key); + break; + case 2: + // RINO 2 based on php-encryption + try { + $key = Crypto::createNewRandomKey(); + } catch (CryptoTestFailed $ex) { + logger('Cannot safely create a key'); + return -4; + } catch (CannotPerformOperation $ex) { + logger('Cannot safely create a key'); + return -5; + } + try { + $data = Crypto::encrypt($postvars['data'], $key); + } catch (CryptoTestFailed $ex) { + logger('Cannot safely perform encryption'); + return -6; + } catch (CannotPerformOperation $ex) { + logger('Cannot safely perform encryption'); + return -7; + } + break; + default: + logger("rino: invalid requested verision '$rino_remote_version'"); + return -8; + } + + $postvars['rino'] = $rino_remote_version; + $postvars['data'] = bin2hex($data); + + //logger('rino: sent key = ' . $key, LOGGER_DEBUG); + + + if ($dfrn_version >= 2.1) { + if (($contact['duplex'] && strlen($contact['pubkey'])) + || ($owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey'])) + || ($contact['rel'] == CONTACT_IS_SHARING && strlen($contact['pubkey']))) { + openssl_public_encrypt($key,$postvars['key'],$contact['pubkey']); + } else { + openssl_private_encrypt($key,$postvars['key'],$contact['prvkey']); + } + + } else { + if (($contact['duplex'] && strlen($contact['prvkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) { + openssl_private_encrypt($key,$postvars['key'],$contact['prvkey']); + } else { + openssl_public_encrypt($key,$postvars['key'],$contact['pubkey']); + } + + } + + logger('md5 rawkey ' . md5($postvars['key'])); + + $postvars['key'] = bin2hex($postvars['key']); + } + + + logger('dfrn_deliver: ' . "SENDING: " . print_r($postvars,true), LOGGER_DATA); + + $xml = post_url($contact['notify'], $postvars); + + logger('dfrn_deliver: ' . "RECEIVED: " . $xml, LOGGER_DATA); + + $curl_stat = $a->get_curl_code(); + if ((!$curl_stat) || (!strlen($xml))) { + return -9; // timed out + } + + if (($curl_stat == 503) && (stristr($a->get_curl_headers(),'retry-after'))) { + return -10; + } + + if (strpos($xml,' NULL_DATE) { + logger("dfrn_deliver: $url back from the dead - removing mark for death"); + require_once('include/Contact.php'); + unmark_for_death($contact); + } + + $res = parse_xml_string($xml); + + if (!isset($res->status)) { + return -11; + } + + if (!empty($res->message)) { + logger('Delivery returned status '.$res->status.' - '.$res->message, LOGGER_DEBUG); + } + + return intval($res->status); + } + + /** + * @brief Add new birthday event for this person + * + * @param array $contact Contact record + * @param string $birthday Birthday of the contact + * @todo Add array type-hint for $contact + */ + private static function birthday_event($contact, $birthday) { + + // Check for duplicates + $r = q("SELECT `id` FROM `event` WHERE `uid` = %d AND `cid` = %d AND `start` = '%s' AND `type` = '%s' LIMIT 1", + intval($contact["uid"]), + intval($contact["id"]), + dbesc(datetime_convert("UTC","UTC", $birthday)), + dbesc("birthday")); + + if (Dbm::is_result($r)) { + return; + } + + 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 + * @todo Find good type-hints for all parameter + */ + private static function fetchauthor($xpath, $context, $importer, $element, $onlyfetch, $xml = "") { + + $author = array(); + $author["name"] = $xpath->evaluate($element."/atom:name/text()", $context)->item(0)->nodeValue; + $author["link"] = $xpath->evaluate($element."/atom:uri/text()", $context)->item(0)->nodeValue; + + $r = q("SELECT `id`, `uid`, `url`, `network`, `avatar-date`, `name-date`, `uri-date`, `addr`, + `name`, `nick`, `about`, `location`, `keywords`, `xmpp`, `bdyear`, `bd`, `hidden`, `contact-type` + FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'", + intval($importer["uid"]), dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET)); + + if (Dbm::is_result($r)) { + $contact = $r[0]; + $author["contact-id"] = $r[0]["id"]; + $author["network"] = $r[0]["network"]; + } else { + if (!$onlyfetch) { + logger("Contact ".$author["link"]." wasn't found for user ".$importer["uid"]." XML: ".$xml, LOGGER_DEBUG); + } + + $author["contact-id"] = $importer["id"]; + $author["network"] = $importer["network"]; + $onlyfetch = true; + } + + // 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) { + /// @TODO Rewrite these similar if () to one switch + 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) && ($href != "")) { + $avatarlist[$width] = $href; + } + } + if (count($avatarlist) > 0) { + krsort($avatarlist); + $author["avatar"] = current($avatarlist); + } + + if (Dbm::is_result($r) && !$onlyfetch) { + logger("Check if contact details for contact " . $r[0]["id"] . " (" . $r[0]["nick"] . ") have to be updated.", LOGGER_DEBUG); + + $poco = array("url" => $contact["url"]); + + // When was the last change to name or uri? + $name_element = $xpath->query($element . "/atom:name", $context)->item(0); + foreach ($name_element->attributes AS $attributes) { + if ($attributes->name == "updated") { + $poco["name-date"] = $attributes->textContent; + } + } + + $link_element = $xpath->query($element . "/atom:link", $context)->item(0); + foreach ($link_element->attributes AS $attributes) { + if ($attributes->name == "updated") { + $poco["uri-date"] = $attributes->textContent; + } + } + + // Update contact data + $value = $xpath->evaluate($element . "/dfrn:handle/text()", $context)->item(0)->nodeValue; + if ($value != "") { + $poco["addr"] = $value; + } + + $value = $xpath->evaluate($element . "/poco:displayName/text()", $context)->item(0)->nodeValue; + if ($value != "") { + $poco["name"] = $value; + } + + $value = $xpath->evaluate($element . "/poco:preferredUsername/text()", $context)->item(0)->nodeValue; + if ($value != "") { + $poco["nick"] = $value; + } + + $value = $xpath->evaluate($element . "/poco:note/text()", $context)->item(0)->nodeValue; + if ($value != "") { + $poco["about"] = $value; + } + + $value = $xpath->evaluate($element . "/poco:address/poco:formatted/text()", $context)->item(0)->nodeValue; + if ($value != "") { + $poco["location"] = $value; + } + + /// @todo Only search for elements with "poco:type" = "xmpp" + $value = $xpath->evaluate($element . "/poco:ims/poco:value/text()", $context)->item(0)->nodeValue; + if ($value != "") { + $poco["xmpp"] = $value; + } + + /// @todo Add support for the following fields that we don't support by now in the contact table: + /// - poco:utcOffset + /// - poco:urls + /// - poco:locality + /// - poco:region + /// - poco:country + + // If the "hide" element is present then the profile isn't searchable. + $hide = intval($xpath->evaluate($element . "/dfrn:hide/text()", $context)->item(0)->nodeValue == "true"); + + logger("Hidden status for contact " . $contact["url"] . ": " . $hide, LOGGER_DEBUG); + + // If the contact isn't searchable then set the contact to "hidden". + // Problem: This can be manually overridden by the user. + if ($hide) { + $contact["hidden"] = true; + } + + // 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)) { + $poco["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); + + $poco["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", "0001-01-01"))) { + $bdyear = date("Y"); + $value = str_replace("0000", $bdyear, $value); + + if (strtotime($value) < time()) { + $value = str_replace($bdyear, $bdyear + 1, $value); + $bdyear = $bdyear + 1; + } + + $poco["bd"] = $value; + } + + $contact = array_merge($contact, $poco); + + 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["url"]); + 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])) { + logger("Difference for contact " . $contact["id"] . " in field '" . $field . "'. New value: '" . $contact[$field] . "', old value '" . $r[0][$field] . "'", LOGGER_DEBUG); + $update = true; + } + } + + foreach ($fields AS $field => $data) { + if ($contact[$field] != $r[0][$field]) { + logger("Difference for contact " . $contact["id"] . " in field '" . $field . "'. New value: '" . $contact[$field] . "', old value '" . $r[0][$field] . "'", LOGGER_DEBUG); + $update = true; + } + } + + if ($update) { + logger("Update contact data for contact " . $contact["id"] . " (" . $contact["nick"] . ")", LOGGER_DEBUG); + + q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', + `addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s', `hidden` = %d, + `xmpp` = '%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"]), intval($contact["hidden"]), dbesc($contact["xmpp"]), + dbesc(Dbm::date($contact["name-date"])), dbesc(Dbm::date($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"]))); + + /* + * The generation is a sign for the reliability of the provided data. + * It is used in the socgraph.php to prevent that old contact data + * that was relayed over several servers can overwrite contact + * data that we received directly. + */ + + $poco["generation"] = 2; + $poco["photo"] = $author["avatar"]; + $poco["hide"] = $hide; + $poco["contact-type"] = $contact["contact-type"]; + $gcid = update_gcontact($poco); + + link_gcontact($gcid, $importer["uid"], $contact["id"]); + } + + return($author); + } + + /** + * @brief Transforms activity objects into an XML string + * + * @param object $xpath XPath object + * @param object $activity Activity object + * @param text $element element name + * + * @return string XML string + * @todo Find good type-hints for all parameter + */ + private static 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)); + } + + $links = $xpath->query("atom:link", $activity); + if (is_object($links)) { + foreach ($links AS $link) { + $obj_element->appendChild($obj_doc->importNode($link, true)); + } + } + + $content = $xpath->query("atom:content", $activity)->item(0); + if (is_object($content)) { + $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); + } + + /** + * @brief Processes the mail elements + * + * @param object $xpath XPath object + * @param object $mail mail elements + * @param array $importer Record of the importer user mixed with contact of the content + * @todo Find good type-hints for all parameter + */ + private static function process_mail($xpath, $mail, $importer) { + + logger("Processing mails"); + + /// @TODO Rewrite this to one statement + $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; + + dba::insert('mail', $msg); + + // send notifications. + /// @TODO Arange this mess + $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."); + } + + /** + * @brief Processes the suggestion elements + * + * @param object $xpath XPath object + * @param object $suggestion suggestion elements + * @param array $importer Record of the importer user mixed with contact of the content + * @todo Find good type-hints for all parameter + */ + private static function process_suggestion($xpath, $suggestion, $importer) { + $a = get_app(); + + logger("Processing suggestions"); + + /// @TODO Rewrite this to one statement + $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"]) + ); + + /* + * The valid result means the friend we're about to send a friend + * suggestion already has them in their contact, which means no further + * action is required. + * + * @see https://github.com/friendica/friendica/pull/3254#discussion_r107315246 + */ + if (Dbm::is_result($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 (Dbm::is_result($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) + ); + + /* + * The valid result means the friend we're about to send a friend + * suggestion already has them in their contact, which means no further + * action is required. + * + * @see https://github.com/friendica/friendica/pull/3254#discussion_r107315246 + */ + if (Dbm::is_result($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 no record in fcontact is found, below INSERT statement will not + * link an introduction to it. + */ + if (!Dbm::is_result($r)) { + // database record did not get created. Quietly give up. + killme(); + } + + $fid = $r[0]["id"]; + + $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" => System::baseUrl()."/notifications/intros", + "source_name" => $importer["name"], + "source_link" => $importer["url"], + "source_photo" => $importer["photo"], + "verb" => ACTIVITY_REQ_FRIEND, + "otype" => "intro" + )); + + return true; + + } + + /** + * @brief Processes the relocation elements + * + * @param object $xpath XPath object + * @param object $relocation relocation elements + * @param array $importer Record of the importer user mixed with contact of the content + * @todo Find good type-hints for all parameter + */ + private static function process_relocation($xpath, $relocation, $importer) { + + logger("Processing relocations"); + + /// @TODO Rewrite this to one statement + $relocate = array(); + $relocate["uid"] = $importer["importer_uid"]; + $relocate["cid"] = $importer["id"]; + $relocate["url"] = $xpath->query("dfrn:url/text()", $relocation)->item(0)->nodeValue; + $relocate["addr"] = $xpath->query("dfrn:addr/text()", $relocation)->item(0)->nodeValue; + $relocate["name"] = $xpath->query("dfrn:name/text()", $relocation)->item(0)->nodeValue; + $relocate["avatar"] = $xpath->query("dfrn:avatar/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; + + if (($relocate["avatar"] == "") && ($relocate["photo"] != "")) { + $relocate["avatar"] = $relocate["photo"]; + } + + if ($relocate["addr"] == "") { + $relocate["addr"] = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$3@$2", $relocate["url"]); + } + + // update contact + $r = q("SELECT `photo`, `url` FROM `contact` WHERE `id` = %d AND `uid` = %d;", + intval($importer["id"]), + intval($importer["importer_uid"])); + + if (!Dbm::is_result($r)) { + logger("Query failed to execute, no result returned in " . __FUNCTION__); + return false; + } + + $old = $r[0]; + + // Update the gcontact entry + $relocate["server_url"] = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$1$2", $relocate["url"]); + + $x = q("UPDATE `gcontact` SET + `name` = '%s', + `photo` = '%s', + `url` = '%s', + `nurl` = '%s', + `addr` = '%s', + `connect` = '%s', + `notify` = '%s', + `server_url` = '%s' + WHERE `nurl` = '%s';", + dbesc($relocate["name"]), + dbesc($relocate["avatar"]), + dbesc($relocate["url"]), + dbesc(normalise_link($relocate["url"])), + dbesc($relocate["addr"]), + dbesc($relocate["addr"]), + dbesc($relocate["notify"]), + dbesc($relocate["server_url"]), + dbesc(normalise_link($old["url"]))); + + // Update the contact table. We try to find every entry. + $x = q("UPDATE `contact` SET + `name` = '%s', + `avatar` = '%s', + `url` = '%s', + `nurl` = '%s', + `addr` = '%s', + `request` = '%s', + `confirm` = '%s', + `notify` = '%s', + `poll` = '%s', + `site-pubkey` = '%s' + WHERE (`id` = %d AND `uid` = %d) OR (`nurl` = '%s');", + dbesc($relocate["name"]), + dbesc($relocate["avatar"]), + dbesc($relocate["url"]), + dbesc(normalise_link($relocate["url"])), + dbesc($relocate["addr"]), + dbesc($relocate["request"]), + dbesc($relocate["confirm"]), + dbesc($relocate["notify"]), + dbesc($relocate["poll"]), + dbesc($relocate["sitepubkey"]), + intval($importer["id"]), + intval($importer["importer_uid"]), + dbesc(normalise_link($old["url"]))); + + update_contact_avatar($relocate["avatar"], $importer["importer_uid"], $importer["id"], true); + + if ($x === false) { + return false; + } + + // update items + /// @todo This is an extreme performance killer + $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) { + $r = q("SELECT `id` FROM `item` WHERE `%s` = '%s' AND `uid` = %d LIMIT 1", + $n, dbesc($f[0]), + intval($importer["importer_uid"])); + + if (Dbm::is_result($r)) { + $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; + } + + /** + * @brief Updates an item + * + * @param array $current the current item record + * @param array $item the new item record + * @param array $importer Record of the importer user mixed with contact of the content + * @param int $entrytype Is it a toplevel entry, a comment or a relayed comment? + * @todo set proper type-hints (array?) + */ + private static 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; + } + + $fields = array('title' => $item["title"], 'body' => $item["body"], + 'tag' => $item["tag"], 'changed' => datetime_convert(), + 'edited' => datetime_convert("UTC", "UTC", $item["edited"])); + + $condition = array("`uri` = ? AND `uid` IN (0, ?)", $item["uri"], $importer["importer_uid"]); + dba::update('item', $fields, $condition); + + create_tags_from_itemuri($item["uri"], $importer["importer_uid"]); + update_thread_uri($item["uri"], $importer["importer_uid"]); + + $changed = true; + + if ($entrytype == DFRN_REPLY_RC) { + Worker::add(PRIORITY_HIGH, "notifier","comment-import", $current["id"]); + } + } + + // update last-child if it changes + if ($item["last-child"] && ($item["last-child"] != $current["last-child"])) { + $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` IN (0, %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` IN (0, %d)", + intval($item["last-child"]), + dbesc(datetime_convert()), + dbesc($item["uri"]), + intval($importer["importer_uid"]) + ); + } + return $changed; + } + + /** + * @brief Detects the entry type of the item + * + * @param array $importer Record of the importer user mixed with contact of the content + * @param array $item the new item record + * + * @return int Is it a toplevel entry, a comment or a relayed comment? + * @todo set proper type-hints (array?) + */ + private static 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 (Dbm::is_result($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 (Dbm::is_result($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. + */ + + /// @TODO Maybe merge these if() blocks into one? + if ($is_a_remote_action && $community && (!$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; + } + + } + + /** + * @brief Send a "poke" + * + * @param array $item the new item record + * @param array $importer Record of the importer user mixed with contact of the content + * @param int $posted_id The record number of item record that was just posted + * @todo set proper type-hints (array?) + */ + private static 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? + foreach ($xo->link as $l) { + $atts = $l->attributes(); + switch ($atts["rel"]) { + case "alternate": + $Blink = $atts["href"]; + break; + default: + break; + } + } + + if ($Blink && link_compare($Blink, System::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" => System::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"] + )); + } + } + } + + /** + * @brief Processes several actions, depending on the verb + * + * @param int $entrytype Is it a toplevel entry, a comment or a relayed comment? + * @param array $importer Record of the importer user mixed with contact of the content + * @param array $item the new item record + * @param bool $is_like Is the verb a "like"? + * + * @return bool Should the processing of the entries be continued? + * @todo set proper type-hints (array?) + */ + private static function process_verbs($entrytype, $importer, &$item, &$is_like) { + + logger("Process verb ".$item["verb"]." and object-type ".$item["object-type"]." for entrytype ".$entrytype, LOGGER_DEBUG); + + if (($entrytype == DFRN_TOP_LEVEL)) { + // The filling of the the "contact" variable is done for legcy reasons + // The functions below are partly used by ostatus.php as well - where we have this variable + $r = q("SELECT * FROM `contact` WHERE `id` = %d", intval($importer["id"])); + $contact = $r[0]; + $nickname = $contact["nick"]; + + // Big question: Do we need these functions? They were part of the "consume_feed" function. + // This function once was responsible for DFRN and OStatus. + if (activity_match($item["verb"], ACTIVITY_FOLLOW)) { + logger("New follower"); + new_follower($importer, $contact, $item, $nickname); + return false; + } + if (activity_match($item["verb"], ACTIVITY_UNFOLLOW)) { + logger("Lost follower"); + lose_follower($importer, $contact, $item); + return false; + } + if (activity_match($item["verb"], ACTIVITY_REQ_FRIEND)) { + logger("New friend request"); + new_follower($importer, $contact, $item, $nickname, true); + return false; + } + if (activity_match($item["verb"], ACTIVITY_UNFRIEND)) { + logger("Lost sharer"); + lose_sharer($importer, $contact, $item); + return false; + } + } else { + if (($item["verb"] == ACTIVITY_LIKE) + || ($item["verb"] == ACTIVITY_DISLIKE) + || ($item["verb"] == ACTIVITY_ATTEND) + || ($item["verb"] == ACTIVITY_ATTENDNO) + || ($item["verb"] == ACTIVITY_ATTENDMAYBE)) { + $is_like = true; + $item["type"] = "activity"; + $item["gravity"] = GRAVITY_LIKE; + // only one like or dislike per person + // splitted into two queries for performance issues + $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1", + intval($item["uid"]), + dbesc($item["author-link"]), + dbesc($item["verb"]), + dbesc($item["parent-uri"]) + ); + if (Dbm::is_result($r)) { + return false; + } + + $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1", + intval($item["uid"]), + dbesc($item["author-link"]), + dbesc($item["verb"]), + dbesc($item["parent-uri"]) + ); + if (Dbm::is_result($r)) { + return false; + } + } else { + $is_like = false; + } + + if (($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) { + + $xo = parse_xml_string($item["object"],false); + $xt = parse_xml_string($item["target"],false); + + if ($xt->type == ACTIVITY_OBJ_NOTE) { + $r = q("SELECT `id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", + dbesc($xt->id), + intval($importer["importer_uid"]) + ); + + if (!Dbm::is_result($r)) { + logger("Query failed to execute, no result returned in " . __FUNCTION__); + return false; + } + + // extract tag, if not duplicate, add to parent item + if ($xo->content) { + if (!(stristr($r[0]["tag"],trim($xo->content)))) { + q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d", + dbesc($r[0]["tag"] . (strlen($r[0]["tag"]) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'), + intval($r[0]["id"]) + ); + create_tags_from_item($r[0]["id"]); + } + } + } + } + } + return true; + } + + /** + * @brief Processes the link elements + * + * @param object $links link elements + * @param array $item the item record + * @todo set proper type-hints + */ + private static function parse_links($links, &$item) { + $rel = ""; + $href = ""; + $type = ""; + $length = "0"; + $title = ""; + foreach ($links AS $link) { + foreach ($link->attributes AS $attributes) { + /// @TODO Rewrite these repeated (same) if () statements to a switch() + 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 != "") && ($href != "")) { + switch ($rel) { + case "alternate": + $item["plink"] = $href; + break; + case "enclosure": + $enclosure = $href; + if (strlen($item["attach"])) { + $item["attach"] .= ","; + } + + $item["attach"] .= '[attach]href="' . $href . '" length="' . $length . '" type="' . $type . '" title="' . $title . '"[/attach]'; + break; + } + } + } + } + + /** + * @brief Processes the entry elements which contain the items and comments + * + * @param array $header Array of the header elements that always stay the same + * @param object $xpath XPath object + * @param object $entry entry elements + * @param array $importer Record of the importer user mixed with contact of the content + * @todo Add type-hints + */ + private static function process_entry($header, $xpath, $entry, $importer, $xml) { + + logger("Processing entries"); + + $item = $header; + + $item["protocol"] = PROTOCOL_DFRN; + + $item["source"] = $xml; + + // Get the uri + $item["uri"] = $xpath->query("atom:id/text()", $entry)->item(0)->nodeValue; + + $item["edited"] = $xpath->query("atom:updated/text()", $entry)->item(0)->nodeValue; + + $current = 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"]) + ); + + // Is there an existing item? + if (Dbm::is_result($current) && edited_timestamp_is_newer($current[0], $item) && + (datetime_convert("UTC","UTC",$item["edited"]) < $current[0]["edited"])) { + logger("Item ".$item["uri"]." already existed.", LOGGER_DEBUG); + return; + } + + // 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["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']); + } + + /// @todo We should check for a repeated post and if we know the repeated author. + + // We don't need the content element since "dfrn:env" is always present + //$item["body"] = $xpath->query("atom:content/text()", $entry)->item(0)->nodeValue; + + $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:bookmark/text()", $entry)->item(0)->nodeValue == "true") { + $item["bookmark"] = true; + } + + $notice_info = $xpath->query("statusnet:notice_info", $entry); + if ($notice_info && ($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) { + $term = ""; + $scheme = ""; + foreach ($category->attributes AS $attributes) { + if ($attributes->name == "term") { + $term = $attributes->textContent; + } + + if ($attributes->name == "scheme") { + $scheme = $attributes->textContent; + } + } + + if (($term != "") && ($scheme != "")) { + $parts = explode(":", $scheme); + if ((count($parts) >= 4) && (array_shift($parts) == "X-DFRN")) { + $termhash = array_shift($parts); + $termurl = implode(":", $parts); + + if (strlen($item["tag"])) { + $item["tag"] .= ","; + } + + $item["tag"] .= $termhash . "[url=" . $termurl . "]" . $term . "[/url]"; + } + } + } + } + + $enclosure = ""; + + $links = $xpath->query("atom:link", $entry); + if ($links) { + self::parse_links($links, $item); + } + + $item['conversation-uri'] = $xpath->query('ostatus:conversation/text()', $entry)->item(0)->nodeValue; + + $conv = $xpath->query('ostatus:conversation', $entry); + if (is_object($conv->item(0))) { + foreach ($conv->item(0)->attributes AS $attributes) { + if ($attributes->name == "ref") { + $item['conversation-uri'] = $attributes->textContent; + } + if ($attributes->name == "href") { + $item['conversation-href'] = $attributes->textContent; + } + } + } + + // 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"]) && ($owner["network"] != "")) { + $item["network"] = $owner["network"]; + } + + if ($item["contact-id"] != $author["contact-id"]) { + $item["contact-id"] = $author["contact-id"]; + } + + if (($item["network"] != $author["network"]) && ($author["network"] != "")) { + $item["network"] = $author["network"]; + } + + /// @TODO maybe remove this old-lost code then? + // This code was taken from the old DFRN code + // When activated, forums don't work. + // And: Why should we disallow commenting by followers? + // the behaviour is now similar to the Diaspora part. + //if ($importer["rel"] == CONTACT_IS_FOLLOWER) { + // logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG); + // return; + //} + } + + 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; + } + + // Is it an event? + if ($item["object-type"] == ACTIVITY_OBJ_EVENT) { + logger("Item ".$item["uri"]." seems to contain an event.", LOGGER_DEBUG); + $ev = bbtoevent($item["body"]); + if ((x($ev, "desc") || x($ev, "summary")) && x($ev, "start")) { + logger("Event in item ".$item["uri"]." was found.", LOGGER_DEBUG); + /// @TODO Mixure of "/' ahead ... + $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 (Dbm::is_result($r)) { + $ev["id"] = $r[0]["id"]; + } + + $event_id = event_store($ev); + logger("Event ".$event_id." was stored", LOGGER_DEBUG); + return; + } + } + } + + if (!self::process_verbs($entrytype, $importer, $item, $is_like)) { + logger("Exiting because 'process_verbs' told us so", LOGGER_DEBUG); + return; + } + + // Update content if 'updated' changes + if (Dbm::is_result($current)) { + 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))) { + $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 (Dbm::is_result($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 && ($entrytype == DFRN_REPLY_RC)) { + logger("Notifying followers about comment ".$posted_id, LOGGER_DEBUG); + Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $posted_id); + } + + return true; + } + } else { // $entrytype == DFRN_TOP_LEVEL + if (!link_compare($item["owner-link"],$importer["url"])) { + /* + * The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery, + * but otherwise there's a possible data mixup on the sender's system. + * 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); + } + } + + /** + * @brief Deletes items + * + * @param object $xpath XPath object + * @param object $deletion deletion elements + * @param array $importer Record of the importer user mixed with contact of the content + * @todo set proper type-hints + */ + private static function process_deletion($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 || !$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 (!Dbm::is_result($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 (Dbm::is_result($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` IN (0, %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` IN (0, %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` IN (0, %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 (Dbm::is_result($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); + Worker::add(PRIORITY_HIGH, "notifier","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 + * @return integer Import status + * @todo set proper type-hints + */ + public static function import($xml, $importer, $sort_by_date = false) { + + if ($xml == "") { + return 400; + } + + $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 + + // The "atom:author" is only present in feeds + if ($xpath->query("/atom:feed/atom:author")->length > 0) { + self::fetchauthor($xpath, $doc->firstChild, $importer, "atom:author", false, $xml); + } + + // Only the "dfrn:owner" in the head section contains all data + if ($xpath->query("/atom:feed/dfrn:owner")->length > 0) { + self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", false, $xml); + } + + logger("Import DFRN message for user " . $importer["uid"] . " from contact " . $importer["id"], LOGGER_DEBUG); + + // The account type is new since 3.5.1 + if ($xpath->query("/atom:feed/dfrn:account_type")->length > 0) { + $accounttype = intval($xpath->evaluate("/atom:feed/dfrn:account_type/text()", $context)->item(0)->nodeValue); + + if ($accounttype != $importer["contact-type"]) { + dba::update('contact', array('contact-type' => $accounttype), array('id' => $importer["id"])); + } + } + + // is it a public forum? Private forums aren't supported with this method + // This is deprecated since 3.5.1 + $forum = intval($xpath->evaluate("/atom:feed/dfrn:community/text()", $context)->item(0)->nodeValue); + + if ($forum != $importer["forum"]) { + $condition = array('`forum` != ? AND `id` = ?', $forum, $importer["id"]); + dba::update('contact', array('forum' => $forum), $condition); + } + + // We are processing relocations even if we are ignoring a contact + $relocations = $xpath->query("/atom:feed/dfrn:relocate"); + foreach ($relocations AS $relocation) { + self::process_relocation($xpath, $relocation, $importer); + } + + 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 403; + } + + $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); + } + + $deletions = $xpath->query("/atom:feed/at:deleted-entry"); + foreach ($deletions AS $deletion) { + self::process_deletion($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, $xml); + } + } 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, $xml); + } + } + logger("Import done for user " . $importer["uid"] . " from contact " . $importer["id"], LOGGER_DEBUG); + return 200; + } +} diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php new file mode 100644 index 0000000000..5960d32af8 --- /dev/null +++ b/src/Protocol/Diaspora.php @@ -0,0 +1,3948 @@ +children('http://salmon-protocol.org/ns/magic-env'); + + if (sizeof($children) == 0) { + logger("XML has no children"); + return false; + } + + $handle = ""; + + $data = base64url_decode($children->data); + $type = $children->data->attributes()->type[0]; + + $encoding = $children->encoding; + + $alg = $children->alg; + + $sig = base64url_decode($children->sig); + $key_id = $children->sig->attributes()->key_id[0]; + if ($key_id != "") + $handle = base64url_decode($key_id); + + $b64url_data = base64url_encode($data); + $msg = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data); + + $signable_data = $msg.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg); + + $key = self::key($handle); + + $verify = rsa_verify($signable_data, $sig, $key); + if (!$verify) { + logger('Message did not verify. Discarding.'); + return false; + } + + return $data; + } + + /** + * @brief encrypts data via AES + * + * @param string $key The AES key + * @param string $iv The IV (is used for CBC encoding) + * @param string $data The data that is to be encrypted + * + * @return string encrypted data + */ + private static function aes_encrypt($key, $iv, $data) { + return openssl_encrypt($data, 'aes-256-cbc', str_pad($key, 32, "\0"), OPENSSL_RAW_DATA, str_pad($iv, 16, "\0")); + } + + /** + * @brief decrypts data via AES + * + * @param string $key The AES key + * @param string $iv The IV (is used for CBC encoding) + * @param string $encrypted The encrypted data + * + * @return string decrypted data + */ + private static function aes_decrypt($key, $iv, $encrypted) { + return openssl_decrypt($encrypted,'aes-256-cbc', str_pad($key, 32, "\0"), OPENSSL_RAW_DATA,str_pad($iv, 16, "\0")); + } + + /** + * @brief: Decodes incoming Diaspora message in the new format + * + * @param array $importer Array of the importer user + * @param string $raw raw post message + * + * @return array + * 'message' -> decoded Diaspora XML message + * 'author' -> author diaspora handle + * 'key' -> author public key (converted to pkcs#8) + */ + public static function decode_raw($importer, $raw) { + $data = json_decode($raw); + + // Is it a private post? Then decrypt the outer Salmon + if (is_object($data)) { + $encrypted_aes_key_bundle = base64_decode($data->aes_key); + $ciphertext = base64_decode($data->encrypted_magic_envelope); + + $outer_key_bundle = ''; + @openssl_private_decrypt($encrypted_aes_key_bundle, $outer_key_bundle, $importer['prvkey']); + $j_outer_key_bundle = json_decode($outer_key_bundle); + + if (!is_object($j_outer_key_bundle)) { + logger('Outer Salmon did not verify. Discarding.'); + http_status_exit(400); + } + + $outer_iv = base64_decode($j_outer_key_bundle->iv); + $outer_key = base64_decode($j_outer_key_bundle->key); + + $xml = self::aes_decrypt($outer_key, $outer_iv, $ciphertext); + } else { + $xml = $raw; + } + + $basedom = parse_xml_string($xml); + + if (!is_object($basedom)) { + logger('Received data does not seem to be an XML. Discarding. '.$xml); + http_status_exit(400); + } + + $base = $basedom->children(NAMESPACE_SALMON_ME); + + // Not sure if this cleaning is needed + $data = str_replace(array(" ", "\t", "\r", "\n"), array("", "", "", ""), $base->data); + + // Build the signed data + $type = $base->data[0]->attributes()->type[0]; + $encoding = $base->encoding; + $alg = $base->alg; + $signed_data = $data.'.'.base64url_encode($type).'.'.base64url_encode($encoding).'.'.base64url_encode($alg); + + // This is the signature + $signature = base64url_decode($base->sig); + + // Get the senders' public key + $key_id = $base->sig[0]->attributes()->key_id[0]; + $author_addr = base64_decode($key_id); + $key = self::key($author_addr); + + $verify = rsa_verify($signed_data, $signature, $key); + if (!$verify) { + logger('Message did not verify. Discarding.'); + http_status_exit(400); + } + + return array('message' => (string)base64url_decode($base->data), + 'author' => unxmlify($author_addr), + 'key' => (string)$key); + } + + /** + * @brief: Decodes incoming Diaspora message in the deprecated format + * + * @param array $importer Array of the importer user + * @param string $xml urldecoded Diaspora salmon + * + * @return array + * 'message' -> decoded Diaspora XML message + * 'author' -> author diaspora handle + * 'key' -> author public key (converted to pkcs#8) + */ + public static function decode($importer, $xml) { + + $public = false; + $basedom = parse_xml_string($xml); + + if (!is_object($basedom)) { + logger("XML is not parseable."); + return false; + } + $children = $basedom->children('https://joindiaspora.com/protocol'); + + if ($children->header) { + $public = true; + $author_link = str_replace('acct:','',$children->header->author_id); + } else { + // This happens with posts from a relais + if (!$importer) { + logger("This is no private post in the old format", LOGGER_DEBUG); + return false; + } + + $encrypted_header = json_decode(base64_decode($children->encrypted_header)); + + $encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key); + $ciphertext = base64_decode($encrypted_header->ciphertext); + + $outer_key_bundle = ''; + openssl_private_decrypt($encrypted_aes_key_bundle,$outer_key_bundle,$importer['prvkey']); + + $j_outer_key_bundle = json_decode($outer_key_bundle); + + $outer_iv = base64_decode($j_outer_key_bundle->iv); + $outer_key = base64_decode($j_outer_key_bundle->key); + + $decrypted = self::aes_decrypt($outer_key, $outer_iv, $ciphertext); + + logger('decrypted: '.$decrypted, LOGGER_DEBUG); + $idom = parse_xml_string($decrypted); + + $inner_iv = base64_decode($idom->iv); + $inner_aes_key = base64_decode($idom->aes_key); + + $author_link = str_replace('acct:','',$idom->author_id); + } + + $dom = $basedom->children(NAMESPACE_SALMON_ME); + + // figure out where in the DOM tree our data is hiding + + if ($dom->provenance->data) + $base = $dom->provenance; + elseif ($dom->env->data) + $base = $dom->env; + elseif ($dom->data) + $base = $dom; + + if (!$base) { + logger('unable to locate salmon data in xml'); + http_status_exit(400); + } + + + // Stash the signature away for now. We have to find their key or it won't be good for anything. + $signature = base64url_decode($base->sig); + + // unpack the data + + // strip whitespace so our data element will return to one big base64 blob + $data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$base->data); + + + // stash away some other stuff for later + + $type = $base->data[0]->attributes()->type[0]; + $keyhash = $base->sig[0]->attributes()->keyhash[0]; + $encoding = $base->encoding; + $alg = $base->alg; + + + $signed_data = $data.'.'.base64url_encode($type).'.'.base64url_encode($encoding).'.'.base64url_encode($alg); + + + // decode the data + $data = base64url_decode($data); + + + if ($public) + $inner_decrypted = $data; + else { + + // Decode the encrypted blob + + $inner_encrypted = base64_decode($data); + $inner_decrypted = self::aes_decrypt($inner_aes_key, $inner_iv, $inner_encrypted); + } + + if (!$author_link) { + logger('Could not retrieve author URI.'); + http_status_exit(400); + } + // Once we have the author URI, go to the web and try to find their public key + // (first this will look it up locally if it is in the fcontact cache) + // This will also convert diaspora public key from pkcs#1 to pkcs#8 + + logger('Fetching key for '.$author_link); + $key = self::key($author_link); + + if (!$key) { + logger('Could not retrieve author key.'); + http_status_exit(400); + } + + $verify = rsa_verify($signed_data,$signature,$key); + + if (!$verify) { + logger('Message did not verify. Discarding.'); + http_status_exit(400); + } + + logger('Message verified.'); + + return array('message' => (string)$inner_decrypted, + 'author' => unxmlify($author_link), + 'key' => (string)$key); + } + + + /** + * @brief Dispatches public messages and find the fitting receivers + * + * @param array $msg The post that will be dispatched + * + * @return int The message id of the generated message, "true" or "false" if there was an error + */ + public static function dispatch_public($msg) { + + $enabled = intval(Config::get("system", "diaspora_enabled")); + if (!$enabled) { + logger("diaspora is disabled"); + return false; + } + + if (!($postdata = self::valid_posting($msg))) { + logger("Invalid posting"); + return false; + } + + $fields = $postdata['fields']; + + // Is it a an action (comment, like, ...) for our own post? + if (isset($fields->parent_guid) && !$postdata["relayed"]) { + $guid = notags(unxmlify($fields->parent_guid)); + $importer = self::importer_for_guid($guid); + if (is_array($importer)) { + logger("delivering to origin: ".$importer["name"]); + $message_id = self::dispatch($importer, $msg, $fields); + return $message_id; + } + } + + // Process item retractions. This has to be done separated from the other stuff, + // since retractions for comments could come even from non followers. + if (!empty($fields) && in_array($fields->getName(), array('retraction'))) { + $target = notags(unxmlify($fields->target_type)); + if (in_array($target, array("Comment", "Like", "Post", "Reshare", "StatusMessage"))) { + logger('processing retraction for '.$target, LOGGER_DEBUG); + $importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE); + $message_id = self::dispatch($importer, $msg, $fields); + return $message_id; + } + } + + // Now distribute it to the followers + $r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN + (SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s') + AND NOT `account_expired` AND NOT `account_removed`", + dbesc(NETWORK_DIASPORA), + dbesc($msg["author"]) + ); + + if (Dbm::is_result($r)) { + foreach ($r as $rr) { + logger("delivering to: ".$rr["username"]); + self::dispatch($rr, $msg, $fields); + } + } elseif (!Config::get('system', 'relay_subscribe', false)) { + logger("Unwanted message from ".$msg["author"]." send by ".$_SERVER["REMOTE_ADDR"]." with ".$_SERVER["HTTP_USER_AGENT"].": ".print_r($msg, true), LOGGER_DEBUG); + } else { + // Use a dummy importer to import the data for the public copy + $importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE); + $message_id = self::dispatch($importer, $msg, $fields); + } + + return $message_id; + } + + /** + * @brief Dispatches the different message types to the different functions + * + * @param array $importer Array of the importer user + * @param array $msg The post that will be dispatched + * @param object $fields SimpleXML object that contains the message + * + * @return int The message id of the generated message, "true" or "false" if there was an error + */ + public static function dispatch($importer, $msg, $fields = null) { + + // The sender is the handle of the contact that sent the message. + // This will often be different with relayed messages (for example "like" and "comment") + $sender = $msg["author"]; + + // This is only needed for private postings since this is already done for public ones before + if (is_null($fields)) { + if (!($postdata = self::valid_posting($msg))) { + logger("Invalid posting"); + return false; + } + $fields = $postdata['fields']; + } + + $type = $fields->getName(); + + logger("Received message type ".$type." from ".$sender." for user ".$importer["uid"], LOGGER_DEBUG); + + switch ($type) { + case "account_migration": + return self::receiveAccountMigration($importer, $fields); + + case "account_deletion": + return self::receive_account_deletion($importer, $fields); + + case "comment": + return self::receive_comment($importer, $sender, $fields, $msg["message"]); + + case "contact": + return self::receive_contact_request($importer, $fields); + + case "conversation": + return self::receive_conversation($importer, $msg, $fields); + + case "like": + return self::receive_like($importer, $sender, $fields); + + case "message": + return self::receive_message($importer, $fields); + + case "participation": // Not implemented + return self::receive_participation($importer, $fields); + + case "photo": // Not implemented + return self::receive_photo($importer, $fields); + + case "poll_participation": // Not implemented + return self::receive_poll_participation($importer, $fields); + + case "profile": + return self::receive_profile($importer, $fields); + + case "reshare": + return self::receive_reshare($importer, $fields, $msg["message"]); + + case "retraction": + return self::receive_retraction($importer, $sender, $fields); + + case "status_message": + return self::receive_status_message($importer, $fields, $msg["message"]); + + default: + logger("Unknown message type ".$type); + return false; + } + + return true; + } + + /** + * @brief Checks if a posting is valid and fetches the data fields. + * + * This function does not only check the signature. + * It also does the conversion between the old and the new diaspora format. + * + * @param array $msg Array with the XML, the sender handle and the sender signature + * + * @return bool|array If the posting is valid then an array with an SimpleXML object is returned + */ + private static function valid_posting($msg) { + + $data = parse_xml_string($msg["message"]); + + if (!is_object($data)) { + logger("No valid XML ".$msg["message"], LOGGER_DEBUG); + return false; + } + + $first_child = $data->getName(); + + // Is this the new or the old version? + if ($data->getName() == "XML") { + $oldXML = true; + foreach ($data->post->children() as $child) + $element = $child; + } else { + $oldXML = false; + $element = $data; + } + + $type = $element->getName(); + $orig_type = $type; + + logger("Got message type ".$type.": ".$msg["message"], LOGGER_DATA); + + // All retractions are handled identically from now on. + // In the new version there will only be "retraction". + if (in_array($type, array("signed_retraction", "relayable_retraction"))) + $type = "retraction"; + + if ($type == "request") + $type = "contact"; + + $fields = new SimpleXMLElement("<".$type."/>"); + + $signed_data = ""; + + foreach ($element->children() AS $fieldname => $entry) { + if ($oldXML) { + // Translation for the old XML structure + if ($fieldname == "diaspora_handle") { + $fieldname = "author"; + } + if ($fieldname == "participant_handles") { + $fieldname = "participants"; + } + if (in_array($type, array("like", "participation"))) { + if ($fieldname == "target_type") { + $fieldname = "parent_type"; + } + } + if ($fieldname == "sender_handle") { + $fieldname = "author"; + } + if ($fieldname == "recipient_handle") { + $fieldname = "recipient"; + } + if ($fieldname == "root_diaspora_id") { + $fieldname = "root_author"; + } + if ($type == "status_message") { + if ($fieldname == "raw_message") { + $fieldname = "text"; + } + } + if ($type == "retraction") { + if ($fieldname == "post_guid") { + $fieldname = "target_guid"; + } + if ($fieldname == "type") { + $fieldname = "target_type"; + } + } + } + + if (($fieldname == "author_signature") && ($entry != "")) + $author_signature = base64_decode($entry); + elseif (($fieldname == "parent_author_signature") && ($entry != "")) + $parent_author_signature = base64_decode($entry); + elseif (!in_array($fieldname, array("author_signature", "parent_author_signature", "target_author_signature"))) { + if ($signed_data != "") { + $signed_data .= ";"; + $signed_data_parent .= ";"; + } + + $signed_data .= $entry; + } + if (!in_array($fieldname, array("parent_author_signature", "target_author_signature")) || + ($orig_type == "relayable_retraction")) + xml::copy($entry, $fields, $fieldname); + } + + // This is something that shouldn't happen at all. + if (in_array($type, array("status_message", "reshare", "profile"))) + if ($msg["author"] != $fields->author) { + logger("Message handle is not the same as envelope sender. Quitting this message."); + return false; + } + + // Only some message types have signatures. So we quit here for the other types. + if (!in_array($type, array("comment", "like"))) { + return array("fields" => $fields, "relayed" => false); + } + // No author_signature? This is a must, so we quit. + if (!isset($author_signature)) { + logger("No author signature for type ".$type." - Message: ".$msg["message"], LOGGER_DEBUG); + return false; + } + + if (isset($parent_author_signature)) { + $relayed = true; + + $key = self::key($msg["author"]); + + if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256")) { + logger("No valid parent author signature for parent author ".$msg["author"]. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$parent_author_signature, LOGGER_DEBUG); + return false; + } + } else { + $relayed = false; + } + + $key = self::key($fields->author); + + if (!rsa_verify($signed_data, $author_signature, $key, "sha256")) { + logger("No valid author signature for author ".$fields->author. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$author_signature, LOGGER_DEBUG); + return false; + } else { + return array("fields" => $fields, "relayed" => $relayed); + } + } + + /** + * @brief Fetches the public key for a given handle + * + * @param string $handle The handle + * + * @return string The public key + */ + private static function key($handle) { + $handle = strval($handle); + + logger("Fetching diaspora key for: ".$handle); + + $r = self::person_by_handle($handle); + if ($r) + return $r["pubkey"]; + + return ""; + } + + /** + * @brief Fetches data for a given handle + * + * @param string $handle The handle + * + * @return array the queried data + */ + public static function person_by_handle($handle) { + + $r = q("SELECT * FROM `fcontact` WHERE `network` = '%s' AND `addr` = '%s' LIMIT 1", + dbesc(NETWORK_DIASPORA), + dbesc($handle) + ); + if ($r) { + $person = $r[0]; + logger("In cache ".print_r($r,true), LOGGER_DEBUG); + + // update record occasionally so it doesn't get stale + $d = strtotime($person["updated"]." +00:00"); + if ($d < strtotime("now - 14 days")) + $update = true; + + if ($person["guid"] == "") + $update = true; + } + + if (!$person || $update) { + logger("create or refresh", LOGGER_DEBUG); + $r = Probe::uri($handle, NETWORK_DIASPORA); + + // Note that Friendica contacts will return a "Diaspora person" + // if Diaspora connectivity is enabled on their server + if ($r && ($r["network"] === NETWORK_DIASPORA)) { + self::add_fcontact($r, $update); + $person = $r; + } + } + return $person; + } + + /** + * @brief Updates the fcontact table + * + * @param array $arr The fcontact data + * @param bool $update Update or insert? + * + * @return string The id of the fcontact entry + */ + private static function add_fcontact($arr, $update = false) { + + if ($update) { + $r = q("UPDATE `fcontact` SET + `name` = '%s', + `photo` = '%s', + `request` = '%s', + `nick` = '%s', + `addr` = '%s', + `guid` = '%s', + `batch` = '%s', + `notify` = '%s', + `poll` = '%s', + `confirm` = '%s', + `alias` = '%s', + `pubkey` = '%s', + `updated` = '%s' + WHERE `url` = '%s' AND `network` = '%s'", + dbesc($arr["name"]), + dbesc($arr["photo"]), + dbesc($arr["request"]), + dbesc($arr["nick"]), + dbesc(strtolower($arr["addr"])), + dbesc($arr["guid"]), + dbesc($arr["batch"]), + dbesc($arr["notify"]), + dbesc($arr["poll"]), + dbesc($arr["confirm"]), + dbesc($arr["alias"]), + dbesc($arr["pubkey"]), + dbesc(datetime_convert()), + dbesc($arr["url"]), + dbesc($arr["network"]) + ); + } else { + $r = q("INSERT INTO `fcontact` (`url`,`name`,`photo`,`request`,`nick`,`addr`, `guid`, + `batch`, `notify`,`poll`,`confirm`,`network`,`alias`,`pubkey`,`updated`) + VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')", + dbesc($arr["url"]), + dbesc($arr["name"]), + dbesc($arr["photo"]), + dbesc($arr["request"]), + dbesc($arr["nick"]), + dbesc($arr["addr"]), + dbesc($arr["guid"]), + dbesc($arr["batch"]), + dbesc($arr["notify"]), + dbesc($arr["poll"]), + dbesc($arr["confirm"]), + dbesc($arr["network"]), + dbesc($arr["alias"]), + dbesc($arr["pubkey"]), + dbesc(datetime_convert()) + ); + } + + return $r; + } + + /** + * @brief get a handle (user@domain.tld) from a given contact id or gcontact id + * + * @param int $contact_id The id in the contact table + * @param int $gcontact_id The id in the gcontact table + * + * @return string the handle + */ + public static function handle_from_contact($contact_id, $gcontact_id = 0) { + $handle = false; + + logger("contact id is ".$contact_id." - gcontact id is ".$gcontact_id, LOGGER_DEBUG); + + if ($gcontact_id != 0) { + $r = q("SELECT `addr` FROM `gcontact` WHERE `id` = %d AND `addr` != ''", + intval($gcontact_id)); + + if (Dbm::is_result($r)) { + return strtolower($r[0]["addr"]); + } + } + + $r = q("SELECT `network`, `addr`, `self`, `url`, `nick` FROM `contact` WHERE `id` = %d", + intval($contact_id)); + + if (Dbm::is_result($r)) { + $contact = $r[0]; + + logger("contact 'self' = ".$contact['self']." 'url' = ".$contact['url'], LOGGER_DEBUG); + + if ($contact['addr'] != "") { + $handle = $contact['addr']; + } else { + $baseurl_start = strpos($contact['url'],'://') + 3; + $baseurl_length = strpos($contact['url'],'/profile') - $baseurl_start; // allows installations in a subdirectory--not sure how Diaspora will handle + $baseurl = substr($contact['url'], $baseurl_start, $baseurl_length); + $handle = $contact['nick'].'@'.$baseurl; + } + } + + return strtolower($handle); + } + + /** + * @brief get a url (scheme://domain.tld/u/user) from a given Diaspora* + * fcontact guid + * + * @param mixed $fcontact_guid Hexadecimal string guid + * + * @return string the contact url or null + */ + public static function url_from_contact_guid($fcontact_guid) { + logger("fcontact guid is ".$fcontact_guid, LOGGER_DEBUG); + + $r = q("SELECT `url` FROM `fcontact` WHERE `url` != '' AND `network` = '%s' AND `guid` = '%s'", + dbesc(NETWORK_DIASPORA), + dbesc($fcontact_guid) + ); + + if (Dbm::is_result($r)) { + return $r[0]['url']; + } + + return null; + } + + /** + * @brief Get a contact id for a given handle + * + * @param int $uid The user id + * @param string $handle The handle in the format user@domain.tld + * + * @return The contact id + */ + private static function contact_by_handle($uid, $handle) { + + // First do a direct search on the contact table + $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `addr` = '%s' LIMIT 1", + intval($uid), + dbesc($handle) + ); + + if (Dbm::is_result($r)) { + return $r[0]; + } else { + /* + * We haven't found it? + * We use another function for it that will possibly create a contact entry. + */ + $cid = get_contact($handle, $uid); + + if ($cid > 0) { + /// @TODO Contact retrieval should be encapsulated into an "entity" class like `Contact` + $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($cid)); + + if (Dbm::is_result($r)) { + return $r[0]; + } + } + } + + $handle_parts = explode("@", $handle); + $nurl_sql = "%%://".$handle_parts[1]."%%/profile/".$handle_parts[0]; + $r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` LIKE '%s' LIMIT 1", + dbesc(NETWORK_DFRN), + intval($uid), + dbesc($nurl_sql) + ); + if (Dbm::is_result($r)) { + return $r[0]; + } + + logger("Haven't found contact for user ".$uid." and handle ".$handle, LOGGER_DEBUG); + return false; + } + + /** + * @brief Check if posting is allowed for this contact + * + * @param array $importer Array of the importer user + * @param array $contact The contact that is checked + * @param bool $is_comment Is the check for a comment? + * + * @return bool is the contact allowed to post? + */ + private static function post_allow($importer, $contact, $is_comment = false) { + + /* + * Perhaps we were already sharing with this person. Now they're sharing with us. + * That makes us friends. + * Normally this should have handled by getting a request - but this could get lost + */ + if ($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) { + dba::update('contact', array('rel' => CONTACT_IS_FRIEND, 'writable' => true), + array('id' => $contact["id"], 'uid' => $contact["uid"])); + + $contact["rel"] = CONTACT_IS_FRIEND; + logger("defining user ".$contact["nick"]." as friend"); + } + + // We don't seem to like that person + if ($contact["blocked"] || $contact["readonly"] || $contact["archive"]) { + // Maybe blocked, don't accept. + return false; + // We are following this person? + } elseif (($contact["rel"] == CONTACT_IS_SHARING) || ($contact["rel"] == CONTACT_IS_FRIEND)) { + // Yes, then it is fine. + return true; + // Is it a post to a community? + } elseif (($contact["rel"] == CONTACT_IS_FOLLOWER) && ($importer["page-flags"] == PAGE_COMMUNITY)) { + // That's good + return true; + // Is the message a global user or a comment? + } elseif (($importer["uid"] == 0) || $is_comment) { + // Messages for the global users and comments are always accepted + return true; + } + + return false; + } + + /** + * @brief Fetches the contact id for a handle and checks if posting is allowed + * + * @param array $importer Array of the importer user + * @param string $handle The checked handle in the format user@domain.tld + * @param bool $is_comment Is the check for a comment? + * + * @return array The contact data + */ + private static function allowed_contact_by_handle($importer, $handle, $is_comment = false) { + $contact = self::contact_by_handle($importer["uid"], $handle); + if (!$contact) { + logger("A Contact for handle ".$handle." and user ".$importer["uid"]." was not found"); + // If a contact isn't found, we accept it anyway if it is a comment + if ($is_comment) { + return $importer; + } else { + return false; + } + } + + if (!self::post_allow($importer, $contact, $is_comment)) { + logger("The handle: ".$handle." is not allowed to post to user ".$importer["uid"]); + return false; + } + return $contact; + } + + /** + * @brief Does the message already exists on the system? + * + * @param int $uid The user id + * @param string $guid The guid of the message + * + * @return int|bool message id if the message already was stored into the system - or false. + */ + private static function message_exists($uid, $guid) { + $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($uid), + dbesc($guid) + ); + + if (Dbm::is_result($r)) { + logger("message ".$guid." already exists for user ".$uid); + return $r[0]["id"]; + } + + return false; + } + + /** + * @brief Checks for links to posts in a message + * + * @param array $item The item array + */ + private static function fetch_guid($item) { + $expression = "=diaspora://.*?/post/([0-9A-Za-z\-_@.:]{15,254}[0-9A-Za-z])=ism"; + preg_replace_callback($expression, + function ($match) use ($item) { + return self::fetch_guid_sub($match, $item); + }, $item["body"]); + + preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi", + function ($match) use ($item) { + return self::fetch_guid_sub($match, $item); + }, $item["body"]); + } + + /** + * @brief Checks for relative /people/* links in an item body to match local + * contacts or prepends the remote host taken from the author link. + * + * @param string $body The item body to replace links from + * @param string $author_link The author link for missing local contact fallback + * + * @return the replaced string + */ + public static function replace_people_guid($body, $author_link) { + $return = preg_replace_callback("&\[url=/people/([^\[\]]*)\](.*)\[\/url\]&Usi", + function ($match) use ($author_link) { + // $match + // 0 => '[url=/people/0123456789abcdef]Foo Bar[/url]' + // 1 => '0123456789abcdef' + // 2 => 'Foo Bar' + $handle = self::url_from_contact_guid($match[1]); + + if ($handle) { + $return = '@[url='.$handle.']'.$match[2].'[/url]'; + } else { + // No local match, restoring absolute remote URL from author scheme and host + $author_url = parse_url($author_link); + $return = '[url='.$author_url['scheme'].'://'.$author_url['host'].'/people/'.$match[1].']'.$match[2].'[/url]'; + } + + return $return; + }, $body); + + return $return; + } + + /** + * @brief sub function of "fetch_guid" which checks for links in messages + * + * @param array $match array containing a link that has to be checked for a message link + * @param array $item The item array + */ + private static function fetch_guid_sub($match, $item) { + if (!self::store_by_guid($match[1], $item["author-link"])) + self::store_by_guid($match[1], $item["owner-link"]); + } + + /** + * @brief Fetches an item with a given guid from a given server + * + * @param string $guid the message guid + * @param string $server The server address + * @param int $uid The user id of the user + * + * @return int the message id of the stored message or false + */ + private static function store_by_guid($guid, $server, $uid = 0) { + $serverparts = parse_url($server); + $server = $serverparts["scheme"]."://".$serverparts["host"]; + + logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG); + + $msg = self::message($guid, $server); + + if (!$msg) + return false; + + logger("Successfully fetched item ".$guid." from ".$server, LOGGER_DEBUG); + + // Now call the dispatcher + return self::dispatch_public($msg); + } + + /** + * @brief Fetches a message from a server + * + * @param string $guid message guid + * @param string $server The url of the server + * @param int $level Endless loop prevention + * + * @return array + * 'message' => The message XML + * 'author' => The author handle + * 'key' => The public key of the author + */ + private static function message($guid, $server, $level = 0) { + + if ($level > 5) + return false; + + // This will work for new Diaspora servers and Friendica servers from 3.5 + $source_url = $server."/fetch/post/".urlencode($guid); + + logger("Fetch post from ".$source_url, LOGGER_DEBUG); + + $envelope = fetch_url($source_url); + if ($envelope) { + logger("Envelope was fetched.", LOGGER_DEBUG); + $x = self::verify_magic_envelope($envelope); + if (!$x) + logger("Envelope could not be verified.", LOGGER_DEBUG); + else + logger("Envelope was verified.", LOGGER_DEBUG); + } else + $x = false; + + // This will work for older Diaspora and Friendica servers + if (!$x) { + $source_url = $server."/p/".urlencode($guid).".xml"; + logger("Fetch post from ".$source_url, LOGGER_DEBUG); + + $x = fetch_url($source_url); + if (!$x) + return false; + } + + $source_xml = parse_xml_string($x); + + if (!is_object($source_xml)) + return false; + + if ($source_xml->post->reshare) { + // Reshare of a reshare - old Diaspora version + logger("Message is a reshare", LOGGER_DEBUG); + return self::message($source_xml->post->reshare->root_guid, $server, ++$level); + } elseif ($source_xml->getName() == "reshare") { + // Reshare of a reshare - new Diaspora version + logger("Message is a new reshare", LOGGER_DEBUG); + return self::message($source_xml->root_guid, $server, ++$level); + } + + $author = ""; + + // Fetch the author - for the old and the new Diaspora version + if ($source_xml->post->status_message->diaspora_handle) + $author = (string)$source_xml->post->status_message->diaspora_handle; + elseif ($source_xml->author && ($source_xml->getName() == "status_message")) + $author = (string)$source_xml->author; + + // If this isn't a "status_message" then quit + if (!$author) { + logger("Message doesn't seem to be a status message", LOGGER_DEBUG); + return false; + } + + $msg = array("message" => $x, "author" => $author); + + $msg["key"] = self::key($msg["author"]); + + return $msg; + } + + /** + * @brief Fetches the item record of a given guid + * + * @param int $uid The user id + * @param string $guid message guid + * @param string $author The handle of the item + * @param array $contact The contact of the item owner + * + * @return array the item record + */ + private static function parent_item($uid, $guid, $author, $contact) { + $r = q("SELECT `id`, `parent`, `body`, `wall`, `uri`, `guid`, `private`, `origin`, + `author-name`, `author-link`, `author-avatar`, + `owner-name`, `owner-link`, `owner-avatar` + FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($uid), dbesc($guid)); + + if (!$r) { + $result = self::store_by_guid($guid, $contact["url"], $uid); + + if (!$result) { + $person = self::person_by_handle($author); + $result = self::store_by_guid($guid, $person["url"], $uid); + } + + if ($result) { + logger("Fetched missing item ".$guid." - result: ".$result, LOGGER_DEBUG); + + $r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`, + `author-name`, `author-link`, `author-avatar`, + `owner-name`, `owner-link`, `owner-avatar` + FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($uid), dbesc($guid)); + } + } + + if (!$r) { + logger("parent item not found: parent: ".$guid." - user: ".$uid); + return false; + } else { + logger("parent item found: parent: ".$guid." - user: ".$uid); + return $r[0]; + } + } + + /** + * @brief returns contact details + * + * @param array $contact The default contact if the person isn't found + * @param array $person The record of the person + * @param int $uid The user id + * + * @return array + * 'cid' => contact id + * 'network' => network type + */ + private static function author_contact_by_url($contact, $person, $uid) { + + $r = q("SELECT `id`, `network`, `url` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1", + dbesc(normalise_link($person["url"])), intval($uid)); + if ($r) { + $cid = $r[0]["id"]; + $network = $r[0]["network"]; + + // We are receiving content from a user that possibly is about to be terminated + // This means the user is vital, so we remove a possible termination date. + unmark_for_death($r[0]); + } else { + $cid = $contact["id"]; + $network = NETWORK_DIASPORA; + } + + return array("cid" => $cid, "network" => $network); + } + + /** + * @brief Is the profile a hubzilla profile? + * + * @param string $url The profile link + * + * @return bool is it a hubzilla server? + */ + public static function is_redmatrix($url) { + return(strstr($url, "/channel/")); + } + + /** + * @brief Generate a post link with a given handle and message guid + * + * @param string $addr The user handle + * @param string $guid message guid + * + * @return string the post link + */ + private static function plink($addr, $guid, $parent_guid = '') { + $r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr)); + + // Fallback + if (!Dbm::is_result($r)) { + if ($parent_guid != '') { + return "https://".substr($addr,strpos($addr,"@") + 1)."/posts/".$parent_guid."#".$guid; + } else { + return "https://".substr($addr,strpos($addr,"@") + 1)."/posts/".$guid; + } + } + + // Friendica contacts are often detected as Diaspora contacts in the "fcontact" table + // So we try another way as well. + $s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"]))); + if (Dbm::is_result($s)) { + $r[0]["network"] = $s[0]["network"]; + } + + if ($r[0]["network"] == NETWORK_DFRN) { + return str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/"); + } + + if (self::is_redmatrix($r[0]["url"])) { + return $r[0]["url"]."/?f=&mid=".$guid; + } + + if ($parent_guid != '') { + return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$parent_guid."#".$guid; + } else { + return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid; + } + } + + /** + * @brief Receives account migration + * + * @param array $importer Array of the importer user + * @param object $data The message object + * + * @return bool Success + */ + private static function receiveAccountMigration($importer, $data) { + $old_handle = notags(unxmlify($data->author)); + $new_handle = notags(unxmlify($data->profile->author)); + $signature = notags(unxmlify($data->signature)); + + $contact = self::contact_by_handle($importer["uid"], $old_handle); + if (!$contact) { + logger("cannot find contact for sender: ".$old_handle." and user ".$importer["uid"]); + return false; + } + + logger("Got migration for ".$old_handle.", to ".$new_handle." with user ".$importer["uid"]); + + // Check signature + $signed_text = 'AccountMigration:'.$old_handle.':'.$new_handle; + $key = self::key($old_handle); + if (!rsa_verify($signed_text, $signature, $key, "sha256")) { + logger('No valid signature for migration.'); + return false; + } + + // Update the profile + self::receive_profile($importer, $data->profile); + + // change the technical stuff in contact and gcontact + $data = Probe::uri($new_handle); + if ($data['network'] == NETWORK_PHANTOM) { + logger('Account for '.$new_handle." couldn't be probed."); + return false; + } + + $fields = array('url' => $data['url'], 'nurl' => normalise_link($data['url']), + 'name' => $data['name'], 'nick' => $data['nick'], + 'addr' => $data['addr'], 'batch' => $data['batch'], + 'notify' => $data['notify'], 'poll' => $data['poll'], + 'network' => $data['network']); + + dba::update('contact', $fields, array('addr' => $old_handle)); + + $fields = array('url' => $data['url'], 'nurl' => normalise_link($data['url']), + 'name' => $data['name'], 'nick' => $data['nick'], + 'addr' => $data['addr'], 'connect' => $data['addr'], + 'notify' => $data['notify'], 'photo' => $data['photo'], + 'server_url' => $data['baseurl'], 'network' => $data['network']); + + dba::update('gcontact', $fields, array('addr' => $old_handle)); + + logger('Contacts are updated.'); + + // update items + /// @todo This is an extreme performance killer + $fields = array( + 'owner-link' => array($contact["url"], $data["url"]), + 'author-link' => array($contact["url"], $data["url"]), + ); + foreach ($fields as $n=>$f) { + $r = q("SELECT `id` FROM `item` WHERE `%s` = '%s' AND `uid` = %d LIMIT 1", + $n, dbesc($f[0]), + intval($importer["uid"])); + + if (Dbm::is_result($r)) { + $x = q("UPDATE `item` SET `%s` = '%s' WHERE `%s` = '%s' AND `uid` = %d", + $n, dbesc($f[1]), + $n, dbesc($f[0]), + intval($importer["uid"])); + + if ($x === false) { + return false; + } + } + } + + logger('Items are updated.'); + + return true; + } + + /** + * @brief Processes an account deletion + * + * @param array $importer Array of the importer user + * @param object $data The message object + * + * @return bool Success + */ + private static function receive_account_deletion($importer, $data) { + + /// @todo Account deletion should remove the contact from the global contacts as well + + $author = notags(unxmlify($data->author)); + + $contact = self::contact_by_handle($importer["uid"], $author); + if (!$contact) { + logger("cannot find contact for author: ".$author); + return false; + } + + // We now remove the contact + contact_remove($contact["id"]); + return true; + } + + /** + * @brief Fetch the uri from our database if we already have this item (maybe from ourselves) + * + * @param string $author Author handle + * @param string $guid Message guid + * @param boolean $onlyfound Only return uri when found in the database + * + * @return string The constructed uri or the one from our database + */ + private static function get_uri_from_guid($author, $guid, $onlyfound = false) { + + $r = q("SELECT `uri` FROM `item` WHERE `guid` = '%s' LIMIT 1", dbesc($guid)); + if (Dbm::is_result($r)) { + return $r[0]["uri"]; + } elseif (!$onlyfound) { + return $author.":".$guid; + } + + return ""; + } + + /** + * @brief Fetch the guid from our database with a given uri + * + * @param string $author Author handle + * @param string $uri Message uri + * + * @return string The post guid + */ + private static function get_guid_from_uri($uri, $uid) { + + $r = q("SELECT `guid` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($uri), intval($uid)); + if (Dbm::is_result($r)) { + return $r[0]["guid"]; + } else { + return false; + } + } + + /** + * @brief Find the best importer for a comment, like, ... + * + * @param string $guid The guid of the item + * + * @return array|boolean the origin owner of that post - or false + */ + private static function importer_for_guid($guid) { + $item = dba::fetch_first("SELECT `uid` FROM `item` WHERE `origin` AND `guid` = ? LIMIT 1", $guid); + + if (Dbm::is_result($item)) { + logger("Found user ".$item['uid']." as owner of item ".$guid, LOGGER_DEBUG); + $contact = dba::fetch_first("SELECT * FROM `contact` WHERE `self` AND `uid` = ?", $item['uid']); + if (Dbm::is_result($contact)) { + return $contact; + } + } + return false; + } + + /** + * @brief Processes an incoming comment + * + * @param array $importer Array of the importer user + * @param string $sender The sender of the message + * @param object $data The message object + * @param string $xml The original XML of the message + * + * @return int The message id of the generated comment or "false" if there was an error + */ + private static function receive_comment($importer, $sender, $data, $xml) { + $author = notags(unxmlify($data->author)); + $guid = notags(unxmlify($data->guid)); + $parent_guid = notags(unxmlify($data->parent_guid)); + $text = unxmlify($data->text); + + if (isset($data->created_at)) { + $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); + } else { + $created_at = datetime_convert(); + } + + if (isset($data->thread_parent_guid)) { + $thread_parent_guid = notags(unxmlify($data->thread_parent_guid)); + $thr_uri = self::get_uri_from_guid("", $thread_parent_guid, true); + } else { + $thr_uri = ""; + } + + $contact = self::allowed_contact_by_handle($importer, $sender, true); + if (!$contact) { + return false; + } + + $message_id = self::message_exists($importer["uid"], $guid); + if ($message_id) { + return true; + } + + $parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact); + if (!$parent_item) { + return false; + } + + $person = self::person_by_handle($author); + if (!is_array($person)) { + logger("unable to find author details"); + return false; + } + + // Fetch the contact id - if we know this contact + $author_contact = self::author_contact_by_url($contact, $person, $importer["uid"]); + + $datarray = array(); + + $datarray["uid"] = $importer["uid"]; + $datarray["contact-id"] = $author_contact["cid"]; + $datarray["network"] = $author_contact["network"]; + + $datarray["author-name"] = $person["name"]; + $datarray["author-link"] = $person["url"]; + $datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]); + + $datarray["owner-name"] = $contact["name"]; + $datarray["owner-link"] = $contact["url"]; + $datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]); + + $datarray["guid"] = $guid; + $datarray["uri"] = self::get_uri_from_guid($author, $guid); + + $datarray["type"] = "remote-comment"; + $datarray["verb"] = ACTIVITY_POST; + $datarray["gravity"] = GRAVITY_COMMENT; + + if ($thr_uri != "") { + $datarray["parent-uri"] = $thr_uri; + } else { + $datarray["parent-uri"] = $parent_item["uri"]; + } + + $datarray["object-type"] = ACTIVITY_OBJ_COMMENT; + + $datarray["protocol"] = PROTOCOL_DIASPORA; + $datarray["source"] = $xml; + + $datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at; + + $datarray["plink"] = self::plink($author, $guid, $parent_item['guid']); + + $body = diaspora2bb($text); + + $datarray["body"] = self::replace_people_guid($body, $person["url"]); + + self::fetch_guid($datarray); + + $message_id = item_store($datarray); + + if ($message_id <= 0) { + return false; + } + + if ($message_id) { + logger("Stored comment ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); + } + + // If we are the origin of the parent we store the original data and notify our followers + if ($message_id && $parent_item["origin"]) { + + // Formerly we stored the signed text, the signature and the author in different fields. + // We now store the raw data so that we are more flexible. + dba::insert('sign', array('iid' => $message_id, 'signed_text' => json_encode($data))); + + // notify others + Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $message_id); + } + + return true; + } + + /** + * @brief processes and stores private messages + * + * @param array $importer Array of the importer user + * @param array $contact The contact of the message + * @param object $data The message object + * @param array $msg Array of the processed message, author handle and key + * @param object $mesg The private message + * @param array $conversation The conversation record to which this message belongs + * + * @return bool "true" if it was successful + */ + private static function receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation) { + $author = notags(unxmlify($data->author)); + $guid = notags(unxmlify($data->guid)); + $subject = notags(unxmlify($data->subject)); + + // "diaspora_handle" is the element name from the old version + // "author" is the element name from the new version + if ($mesg->author) { + $msg_author = notags(unxmlify($mesg->author)); + } elseif ($mesg->diaspora_handle) { + $msg_author = notags(unxmlify($mesg->diaspora_handle)); + } else { + return false; + } + + $msg_guid = notags(unxmlify($mesg->guid)); + $msg_conversation_guid = notags(unxmlify($mesg->conversation_guid)); + $msg_text = unxmlify($mesg->text); + $msg_created_at = datetime_convert("UTC", "UTC", notags(unxmlify($mesg->created_at))); + + if ($msg_conversation_guid != $guid) { + logger("message conversation guid does not belong to the current conversation."); + return false; + } + + $body = diaspora2bb($msg_text); + $message_uri = $msg_author.":".$msg_guid; + + $person = self::person_by_handle($msg_author); + + dba::lock('mail'); + + $r = q("SELECT `id` FROM `mail` WHERE `guid` = '%s' AND `uid` = %d LIMIT 1", + dbesc($msg_guid), + intval($importer["uid"]) + ); + if (Dbm::is_result($r)) { + logger("duplicate message already delivered.", LOGGER_DEBUG); + return false; + } + + q("INSERT INTO `mail` (`uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`) + VALUES (%d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')", + intval($importer["uid"]), + dbesc($msg_guid), + intval($conversation["id"]), + dbesc($person["name"]), + dbesc($person["photo"]), + dbesc($person["url"]), + intval($contact["id"]), + dbesc($subject), + dbesc($body), + 0, + 0, + dbesc($message_uri), + dbesc($author.":".$guid), + dbesc($msg_created_at) + ); + + dba::unlock(); + + dba::update('conv', array('updated' => datetime_convert()), array('id' => $conversation["id"])); + + notification(array( + "type" => NOTIFY_MAIL, + "notify_flags" => $importer["notify-flags"], + "language" => $importer["language"], + "to_name" => $importer["username"], + "to_email" => $importer["email"], + "uid" =>$importer["uid"], + "item" => array("subject" => $subject, "body" => $body), + "source_name" => $person["name"], + "source_link" => $person["url"], + "source_photo" => $person["thumb"], + "verb" => ACTIVITY_POST, + "otype" => "mail" + )); + return true; + } + + /** + * @brief Processes new private messages (answers to private messages are processed elsewhere) + * + * @param array $importer Array of the importer user + * @param array $msg Array of the processed message, author handle and key + * @param object $data The message object + * + * @return bool Success + */ + private static function receive_conversation($importer, $msg, $data) { + $author = notags(unxmlify($data->author)); + $guid = notags(unxmlify($data->guid)); + $subject = notags(unxmlify($data->subject)); + $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); + $participants = notags(unxmlify($data->participants)); + + $messages = $data->message; + + if (!count($messages)) { + logger("empty conversation"); + return false; + } + + $contact = self::allowed_contact_by_handle($importer, $msg["author"], true); + if (!$contact) + return false; + + $conversation = null; + + $c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($importer["uid"]), + dbesc($guid) + ); + if ($c) + $conversation = $c[0]; + else { + $r = q("INSERT INTO `conv` (`uid`, `guid`, `creator`, `created`, `updated`, `subject`, `recips`) + VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s')", + intval($importer["uid"]), + dbesc($guid), + dbesc($author), + dbesc($created_at), + dbesc(datetime_convert()), + dbesc($subject), + dbesc($participants) + ); + if ($r) + $c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($importer["uid"]), + dbesc($guid) + ); + + if ($c) + $conversation = $c[0]; + } + if (!$conversation) { + logger("unable to create conversation."); + return false; + } + + foreach ($messages as $mesg) + self::receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation); + + return true; + } + + /** + * @brief Creates the body for a "like" message + * + * @param array $contact The contact that send us the "like" + * @param array $parent_item The item array of the parent item + * @param string $guid message guid + * + * @return string the body + */ + private static function construct_like_body($contact, $parent_item, $guid) { + $bodyverb = t('%1$s likes %2$s\'s %3$s'); + + $ulink = "[url=".$contact["url"]."]".$contact["name"]."[/url]"; + $alink = "[url=".$parent_item["author-link"]."]".$parent_item["author-name"]."[/url]"; + $plink = "[url=".System::baseUrl()."/display/".urlencode($guid)."]".t("status")."[/url]"; + + return sprintf($bodyverb, $ulink, $alink, $plink); + } + + /** + * @brief Creates a XML object for a "like" + * + * @param array $importer Array of the importer user + * @param array $parent_item The item array of the parent item + * + * @return string The XML + */ + private static function construct_like_object($importer, $parent_item) { + $objtype = ACTIVITY_OBJ_NOTE; + $link = ''; + $parent_body = $parent_item["body"]; + + $xmldata = array("object" => array("type" => $objtype, + "local" => "1", + "id" => $parent_item["uri"], + "link" => $link, + "title" => "", + "content" => $parent_body)); + + return xml::from_array($xmldata, $xml, true); + } + + /** + * @brief Processes "like" messages + * + * @param array $importer Array of the importer user + * @param string $sender The sender of the message + * @param object $data The message object + * + * @return int The message id of the generated like or "false" if there was an error + */ + private static function receive_like($importer, $sender, $data) { + $author = notags(unxmlify($data->author)); + $guid = notags(unxmlify($data->guid)); + $parent_guid = notags(unxmlify($data->parent_guid)); + $parent_type = notags(unxmlify($data->parent_type)); + $positive = notags(unxmlify($data->positive)); + + // likes on comments aren't supported by Diaspora - only on posts + // But maybe this will be supported in the future, so we will accept it. + if (!in_array($parent_type, array("Post", "Comment"))) + return false; + + $contact = self::allowed_contact_by_handle($importer, $sender, true); + if (!$contact) + return false; + + $message_id = self::message_exists($importer["uid"], $guid); + if ($message_id) + return true; + + $parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact); + if (!$parent_item) + return false; + + $person = self::person_by_handle($author); + if (!is_array($person)) { + logger("unable to find author details"); + return false; + } + + // Fetch the contact id - if we know this contact + $author_contact = self::author_contact_by_url($contact, $person, $importer["uid"]); + + // "positive" = "false" would be a Dislike - wich isn't currently supported by Diaspora + // We would accept this anyhow. + if ($positive == "true") + $verb = ACTIVITY_LIKE; + else + $verb = ACTIVITY_DISLIKE; + + $datarray = array(); + + $datarray["protocol"] = PROTOCOL_DIASPORA; + + $datarray["uid"] = $importer["uid"]; + $datarray["contact-id"] = $author_contact["cid"]; + $datarray["network"] = $author_contact["network"]; + + $datarray["author-name"] = $person["name"]; + $datarray["author-link"] = $person["url"]; + $datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]); + + $datarray["owner-name"] = $contact["name"]; + $datarray["owner-link"] = $contact["url"]; + $datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]); + + $datarray["guid"] = $guid; + $datarray["uri"] = self::get_uri_from_guid($author, $guid); + + $datarray["type"] = "activity"; + $datarray["verb"] = $verb; + $datarray["gravity"] = GRAVITY_LIKE; + $datarray["parent-uri"] = $parent_item["uri"]; + + $datarray["object-type"] = ACTIVITY_OBJ_NOTE; + $datarray["object"] = self::construct_like_object($importer, $parent_item); + + $datarray["body"] = self::construct_like_body($contact, $parent_item, $guid); + + $message_id = item_store($datarray); + + if ($message_id <= 0) { + return false; + } + + if ($message_id) { + logger("Stored like ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); + } + + // like on comments have the comment as parent. So we need to fetch the toplevel parent + if ($parent_item["id"] != $parent_item["parent"]) { + $toplevel = dba::select('item', array('origin'), array('id' => $parent_item["parent"]), array('limit' => 1)); + $origin = $toplevel["origin"]; + } else { + $origin = $parent_item["origin"]; + } + + // If we are the origin of the parent we store the original data and notify our followers + if ($message_id && $origin) { + + // Formerly we stored the signed text, the signature and the author in different fields. + // We now store the raw data so that we are more flexible. + dba::insert('sign', array('iid' => $message_id, 'signed_text' => json_encode($data))); + + // notify others + Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $message_id); + } + + return true; + } + + /** + * @brief Processes private messages + * + * @param array $importer Array of the importer user + * @param object $data The message object + * + * @return bool Success? + */ + private static function receive_message($importer, $data) { + $author = notags(unxmlify($data->author)); + $guid = notags(unxmlify($data->guid)); + $conversation_guid = notags(unxmlify($data->conversation_guid)); + $text = unxmlify($data->text); + $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); + + $contact = self::allowed_contact_by_handle($importer, $author, true); + if (!$contact) { + return false; + } + + $conversation = null; + + $c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", + intval($importer["uid"]), + dbesc($conversation_guid) + ); + if ($c) { + $conversation = $c[0]; + } else { + logger("conversation not available."); + return false; + } + + $message_uri = $author.":".$guid; + + $person = self::person_by_handle($author); + if (!$person) { + logger("unable to find author details"); + return false; + } + + $body = diaspora2bb($text); + + $body = self::replace_people_guid($body, $person["url"]); + + dba::lock('mail'); + + $r = q("SELECT `id` FROM `mail` WHERE `guid` = '%s' AND `uid` = %d LIMIT 1", + dbesc($guid), + intval($importer["uid"]) + ); + if (Dbm::is_result($r)) { + logger("duplicate message already delivered.", LOGGER_DEBUG); + return false; + } + + q("INSERT INTO `mail` (`uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`) + VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')", + intval($importer["uid"]), + dbesc($guid), + intval($conversation["id"]), + dbesc($person["name"]), + dbesc($person["photo"]), + dbesc($person["url"]), + intval($contact["id"]), + dbesc($conversation["subject"]), + dbesc($body), + 0, + 1, + dbesc($message_uri), + dbesc($author.":".$conversation["guid"]), + dbesc($created_at) + ); + + dba::unlock(); + + dba::update('conv', array('updated' => datetime_convert()), array('id' => $conversation["id"])); + return true; + } + + /** + * @brief Processes participations - unsupported by now + * + * @param array $importer Array of the importer user + * @param object $data The message object + * + * @return bool always true + */ + private static function receive_participation($importer, $data) { + // I'm not sure if we can fully support this message type + return true; + } + + /** + * @brief Processes photos - unneeded + * + * @param array $importer Array of the importer user + * @param object $data The message object + * + * @return bool always true + */ + private static function receive_photo($importer, $data) { + // There doesn't seem to be a reason for this function, since the photo data is transmitted in the status message as well + return true; + } + + /** + * @brief Processes poll participations - unssupported + * + * @param array $importer Array of the importer user + * @param object $data The message object + * + * @return bool always true + */ + private static function receive_poll_participation($importer, $data) { + // We don't support polls by now + return true; + } + + /** + * @brief Processes incoming profile updates + * + * @param array $importer Array of the importer user + * @param object $data The message object + * + * @return bool Success + */ + private static function receive_profile($importer, $data) { + $author = strtolower(notags(unxmlify($data->author))); + + $contact = self::contact_by_handle($importer["uid"], $author); + if (!$contact) + return false; + + $name = unxmlify($data->first_name).((strlen($data->last_name)) ? " ".unxmlify($data->last_name) : ""); + $image_url = unxmlify($data->image_url); + $birthday = unxmlify($data->birthday); + $gender = unxmlify($data->gender); + $about = diaspora2bb(unxmlify($data->bio)); + $location = diaspora2bb(unxmlify($data->location)); + $searchable = (unxmlify($data->searchable) == "true"); + $nsfw = (unxmlify($data->nsfw) == "true"); + $tags = unxmlify($data->tag_string); + + $tags = explode("#", $tags); + + $keywords = array(); + foreach ($tags as $tag) { + $tag = trim(strtolower($tag)); + if ($tag != "") + $keywords[] = $tag; + } + + $keywords = implode(", ", $keywords); + + $handle_parts = explode("@", $author); + $nick = $handle_parts[0]; + + if ($name === "") + $name = $handle_parts[0]; + + if ( preg_match("|^https?://|", $image_url) === 0) + $image_url = "http://".$handle_parts[1].$image_url; + + update_contact_avatar($image_url, $importer["uid"], $contact["id"]); + + // Generic birthday. We don't know the timezone. The year is irrelevant. + + $birthday = str_replace("1000", "1901", $birthday); + + if ($birthday != "") + $birthday = datetime_convert("UTC", "UTC", $birthday, "Y-m-d"); + + // this is to prevent multiple birthday notifications in a single year + // if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year + + if (substr($birthday,5) === substr($contact["bd"],5)) + $birthday = $contact["bd"]; + + $r = q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `name-date` = '%s', `bd` = '%s', + `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d AND `uid` = %d", + dbesc($name), + dbesc($nick), + dbesc($author), + dbesc(datetime_convert()), + dbesc($birthday), + dbesc($location), + dbesc($about), + dbesc($keywords), + dbesc($gender), + intval($contact["id"]), + intval($importer["uid"]) + ); + + $gcontact = array("url" => $contact["url"], "network" => NETWORK_DIASPORA, "generation" => 2, + "photo" => $image_url, "name" => $name, "location" => $location, + "about" => $about, "birthday" => $birthday, "gender" => $gender, + "addr" => $author, "nick" => $nick, "keywords" => $keywords, + "hide" => !$searchable, "nsfw" => $nsfw); + + $gcid = update_gcontact($gcontact); + + link_gcontact($gcid, $importer["uid"], $contact["id"]); + + logger("Profile of contact ".$contact["id"]." stored for user ".$importer["uid"], LOGGER_DEBUG); + + return true; + } + + /** + * @brief Processes incoming friend requests + * + * @param array $importer Array of the importer user + * @param array $contact The contact that send the request + */ + private static function receive_request_make_friend($importer, $contact) { + + $a = get_app(); + + if ($contact["rel"] == CONTACT_IS_SHARING) { + dba::update('contact', array('rel' => CONTACT_IS_FRIEND, 'writable' => true), + array('id' => $contact["id"], 'uid' => $importer["uid"])); + } + // send notification + + $r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1", + intval($importer["uid"]) + ); + + if ($r && !$r[0]["hide-friends"] && !$contact["hidden"] && intval(PConfig::get($importer["uid"], "system", "post_newfriend"))) { + + $self = q("SELECT * FROM `contact` WHERE `self` AND `uid` = %d LIMIT 1", + intval($importer["uid"]) + ); + + // they are not CONTACT_IS_FOLLOWER anymore but that's what we have in the array + + if ($self && $contact["rel"] == CONTACT_IS_FOLLOWER) { + + $arr = array(); + $arr["protocol"] = PROTOCOL_DIASPORA; + $arr["uri"] = $arr["parent-uri"] = item_new_uri($a->get_hostname(), $importer["uid"]); + $arr["uid"] = $importer["uid"]; + $arr["contact-id"] = $self[0]["id"]; + $arr["wall"] = 1; + $arr["type"] = 'wall'; + $arr["gravity"] = 0; + $arr["origin"] = 1; + $arr["author-name"] = $arr["owner-name"] = $self[0]["name"]; + $arr["author-link"] = $arr["owner-link"] = $self[0]["url"]; + $arr["author-avatar"] = $arr["owner-avatar"] = $self[0]["thumb"]; + $arr["verb"] = ACTIVITY_FRIEND; + $arr["object-type"] = ACTIVITY_OBJ_PERSON; + + $A = "[url=".$self[0]["url"]."]".$self[0]["name"]."[/url]"; + $B = "[url=".$contact["url"]."]".$contact["name"]."[/url]"; + $BPhoto = "[url=".$contact["url"]."][img]".$contact["thumb"]."[/img][/url]"; + $arr["body"] = sprintf(t("%1$s is now friends with %2$s"), $A, $B)."\n\n\n".$Bphoto; + + $arr["object"] = self::construct_new_friend_object($contact); + + $arr["last-child"] = 1; + + $arr["allow_cid"] = $user[0]["allow_cid"]; + $arr["allow_gid"] = $user[0]["allow_gid"]; + $arr["deny_cid"] = $user[0]["deny_cid"]; + $arr["deny_gid"] = $user[0]["deny_gid"]; + + $i = item_store($arr); + if ($i) + Worker::add(PRIORITY_HIGH, "notifier", "activity", $i); + } + } + } + + /** + * @brief Creates a XML object for a "new friend" message + * + * @param array $contact Array of the contact + * + * @return string The XML + */ + private static function construct_new_friend_object($contact) { + $objtype = ACTIVITY_OBJ_PERSON; + $link = ''."\n". + ''."\n"; + + $xmldata = array("object" => array("type" => $objtype, + "title" => $contact["name"], + "id" => $contact["url"]."/".$contact["name"], + "link" => $link)); + + return xml::from_array($xmldata, $xml, true); + } + + /** + * @brief Processes incoming sharing notification + * + * @param array $importer Array of the importer user + * @param object $data The message object + * + * @return bool Success + */ + private static function receive_contact_request($importer, $data) { + $author = unxmlify($data->author); + $recipient = unxmlify($data->recipient); + + if (!$author || !$recipient) { + return false; + } + + // the current protocol version doesn't know these fields + // That means that we will assume their existance + if (isset($data->following)) { + $following = (unxmlify($data->following) == "true"); + } else { + $following = true; + } + + if (isset($data->sharing)) { + $sharing = (unxmlify($data->sharing) == "true"); + } else { + $sharing = true; + } + + $contact = self::contact_by_handle($importer["uid"],$author); + + // perhaps we were already sharing with this person. Now they're sharing with us. + // That makes us friends. + if ($contact) { + if ($following) { + logger("Author ".$author." (Contact ".$contact["id"].") wants to follow us.", LOGGER_DEBUG); + self::receive_request_make_friend($importer, $contact); + + // refetch the contact array + $contact = self::contact_by_handle($importer["uid"],$author); + + // If we are now friends, we are sending a share message. + // Normally we needn't to do so, but the first message could have been vanished. + if (in_array($contact["rel"], array(CONTACT_IS_FRIEND))) { + $u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"])); + if ($u) { + logger("Sending share message to author ".$author." - Contact: ".$contact["id"]." - User: ".$importer["uid"], LOGGER_DEBUG); + $ret = self::send_share($u[0], $contact); + } + } + return true; + } else { + logger("Author ".$author." doesn't want to follow us anymore.", LOGGER_DEBUG); + lose_follower($importer, $contact); + return true; + } + } + + if (!$following && $sharing && in_array($importer["page-flags"], array(PAGE_SOAPBOX, PAGE_NORMAL))) { + logger("Author ".$author." wants to share with us - but doesn't want to listen. Request is ignored.", LOGGER_DEBUG); + return false; + } elseif (!$following && !$sharing) { + logger("Author ".$author." doesn't want anything - and we don't know the author. Request is ignored.", LOGGER_DEBUG); + return false; + } elseif (!$following && $sharing) { + logger("Author ".$author." wants to share with us.", LOGGER_DEBUG); + } elseif ($following && $sharing) { + logger("Author ".$author." wants to have a bidirectional conection.", LOGGER_DEBUG); + } elseif ($following && !$sharing) { + logger("Author ".$author." wants to listen to us.", LOGGER_DEBUG); + } + + $ret = self::person_by_handle($author); + + if (!$ret || ($ret["network"] != NETWORK_DIASPORA)) { + logger("Cannot resolve diaspora handle ".$author." for ".$recipient); + return false; + } + + $batch = (($ret["batch"]) ? $ret["batch"] : implode("/", array_slice(explode("/", $ret["url"]), 0, 3))."/receive/public"); + + $r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`nurl`,`batch`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`) + VALUES (%d, '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s',%d,%d)", + intval($importer["uid"]), + dbesc($ret["network"]), + dbesc($ret["addr"]), + datetime_convert(), + dbesc($ret["url"]), + dbesc(normalise_link($ret["url"])), + dbesc($batch), + dbesc($ret["name"]), + dbesc($ret["nick"]), + dbesc($ret["photo"]), + dbesc($ret["pubkey"]), + dbesc($ret["notify"]), + dbesc($ret["poll"]), + 1, + 2 + ); + + // find the contact record we just created + + $contact_record = self::contact_by_handle($importer["uid"],$author); + + if (!$contact_record) { + logger("unable to locate newly created contact record."); + return; + } + + logger("Author ".$author." was added as contact number ".$contact_record["id"].".", LOGGER_DEBUG); + + $def_gid = get_default_group($importer['uid'], $ret["network"]); + + if (intval($def_gid)) + group_add_member($importer["uid"], "", $contact_record["id"], $def_gid); + + update_contact_avatar($ret["photo"], $importer['uid'], $contact_record["id"], true); + + if ($importer["page-flags"] == PAGE_NORMAL) { + + logger("Sending intra message for author ".$author.".", LOGGER_DEBUG); + + $hash = random_string().(string)time(); // Generate a confirm_key + + $ret = q("INSERT INTO `intro` (`uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime`) + VALUES (%d, %d, %d, %d, '%s', '%s', '%s')", + intval($importer["uid"]), + intval($contact_record["id"]), + 0, + 0, + dbesc(t("Sharing notification from Diaspora network")), + dbesc($hash), + dbesc(datetime_convert()) + ); + } else { + + // automatic friend approval + + logger("Does an automatic friend approval for author ".$author.".", LOGGER_DEBUG); + + update_contact_avatar($contact_record["photo"],$importer["uid"],$contact_record["id"]); + + // technically they are sharing with us (CONTACT_IS_SHARING), + // but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX + // we are going to change the relationship and make them a follower. + + if (($importer["page-flags"] == PAGE_FREELOVE) && $sharing && $following) + $new_relation = CONTACT_IS_FRIEND; + elseif (($importer["page-flags"] == PAGE_FREELOVE) && $sharing) + $new_relation = CONTACT_IS_SHARING; + else + $new_relation = CONTACT_IS_FOLLOWER; + + $r = q("UPDATE `contact` SET `rel` = %d, + `name-date` = '%s', + `uri-date` = '%s', + `blocked` = 0, + `pending` = 0, + `writable` = 1 + WHERE `id` = %d + ", + intval($new_relation), + dbesc(datetime_convert()), + dbesc(datetime_convert()), + intval($contact_record["id"]) + ); + + $u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"])); + if ($u) { + logger("Sending share message (Relation: ".$new_relation.") to author ".$author." - Contact: ".$contact_record["id"]." - User: ".$importer["uid"], LOGGER_DEBUG); + $ret = self::send_share($u[0], $contact_record); + + // Send the profile data, maybe it weren't transmitted before + self::send_profile($importer["uid"], array($contact_record)); + } + } + + return true; + } + + /** + * @brief Fetches a message with a given guid + * + * @param string $guid message guid + * @param string $orig_author handle of the original post + * @param string $author handle of the sharer + * + * @return array The fetched item + */ + private static function original_item($guid, $orig_author, $author) { + + // Do we already have this item? + $r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`, + `author-name`, `author-link`, `author-avatar` + FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1", + dbesc($guid)); + + if (Dbm::is_result($r)) { + logger("reshared message ".$guid." already exists on system."); + + // Maybe it is already a reshared item? + // Then refetch the content, if it is a reshare from a reshare. + // If it is a reshared post from another network then reformat to avoid display problems with two share elements + if (self::is_reshare($r[0]["body"], true)) { + $r = array(); + } elseif (self::is_reshare($r[0]["body"], false) || strstr($r[0]["body"], "[share")) { + $r[0]["body"] = diaspora2bb(bb2diaspora($r[0]["body"])); + + $r[0]["body"] = self::replace_people_guid($r[0]["body"], $r[0]["author-link"]); + + // Add OEmbed and other information to the body + $r[0]["body"] = add_page_info_to_body($r[0]["body"], false, true); + + return $r[0]; + } else { + return $r[0]; + } + } + + if (!Dbm::is_result($r)) { + $server = "https://".substr($orig_author, strpos($orig_author, "@") + 1); + logger("1st try: reshared message ".$guid." will be fetched via SSL from the server ".$server); + $item_id = self::store_by_guid($guid, $server); + + if (!$item_id) { + $server = "http://".substr($orig_author, strpos($orig_author, "@") + 1); + logger("2nd try: reshared message ".$guid." will be fetched without SLL from the server ".$server); + $item_id = self::store_by_guid($guid, $server); + } + + if ($item_id) { + $r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`, + `author-name`, `author-link`, `author-avatar` + FROM `item` WHERE `id` = %d AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1", + intval($item_id)); + + if (Dbm::is_result($r)) { + // If it is a reshared post from another network then reformat to avoid display problems with two share elements + if (self::is_reshare($r[0]["body"], false)) { + $r[0]["body"] = diaspora2bb(bb2diaspora($r[0]["body"])); + $r[0]["body"] = self::replace_people_guid($r[0]["body"], $r[0]["author-link"]); + } + + return $r[0]; + } + + } + } + return false; + } + + /** + * @brief Processes a reshare message + * + * @param array $importer Array of the importer user + * @param object $data The message object + * @param string $xml The original XML of the message + * + * @return int the message id + */ + private static function receive_reshare($importer, $data, $xml) { + $author = notags(unxmlify($data->author)); + $guid = notags(unxmlify($data->guid)); + $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); + $root_author = notags(unxmlify($data->root_author)); + $root_guid = notags(unxmlify($data->root_guid)); + /// @todo handle unprocessed property "provider_display_name" + $public = notags(unxmlify($data->public)); + + $contact = self::allowed_contact_by_handle($importer, $author, false); + if (!$contact) { + return false; + } + + $message_id = self::message_exists($importer["uid"], $guid); + if ($message_id) { + return true; + } + + $original_item = self::original_item($root_guid, $root_author, $author); + if (!$original_item) { + return false; + } + + $orig_url = System::baseUrl()."/display/".$original_item["guid"]; + + $datarray = array(); + + $datarray["uid"] = $importer["uid"]; + $datarray["contact-id"] = $contact["id"]; + $datarray["network"] = NETWORK_DIASPORA; + + $datarray["author-name"] = $contact["name"]; + $datarray["author-link"] = $contact["url"]; + $datarray["author-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]); + + $datarray["owner-name"] = $datarray["author-name"]; + $datarray["owner-link"] = $datarray["author-link"]; + $datarray["owner-avatar"] = $datarray["author-avatar"]; + + $datarray["guid"] = $guid; + $datarray["uri"] = $datarray["parent-uri"] = self::get_uri_from_guid($author, $guid); + + $datarray["verb"] = ACTIVITY_POST; + $datarray["gravity"] = GRAVITY_PARENT; + + $datarray["protocol"] = PROTOCOL_DIASPORA; + $datarray["source"] = $xml; + + $prefix = share_header($original_item["author-name"], $original_item["author-link"], $original_item["author-avatar"], + $original_item["guid"], $original_item["created"], $orig_url); + $datarray["body"] = $prefix.$original_item["body"]."[/share]"; + + $datarray["tag"] = $original_item["tag"]; + $datarray["app"] = $original_item["app"]; + + $datarray["plink"] = self::plink($author, $guid); + $datarray["private"] = (($public == "false") ? 1 : 0); + $datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at; + + $datarray["object-type"] = $original_item["object-type"]; + + self::fetch_guid($datarray); + $message_id = item_store($datarray); + + if ($message_id) { + logger("Stored reshare ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); + return true; + } else { + return false; + } + } + + /** + * @brief Processes retractions + * + * @param array $importer Array of the importer user + * @param array $contact The contact of the item owner + * @param object $data The message object + * + * @return bool success + */ + private static function item_retraction($importer, $contact, $data) { + $author = notags(unxmlify($data->author)); + $target_guid = notags(unxmlify($data->target_guid)); + $target_type = notags(unxmlify($data->target_type)); + + $person = self::person_by_handle($author); + if (!is_array($person)) { + logger("unable to find author detail for ".$author); + return false; + } + + if (empty($contact["url"])) { + $contact["url"] = $person["url"]; + } + + // Fetch items that are about to be deleted + $fields = array('uid', 'id', 'parent', 'parent-uri', 'author-link'); + + // When we receive a public retraction, we delete every item that we find. + if ($importer['uid'] == 0) { + $condition = array("`guid` = ? AND NOT `file` LIKE '%%[%%' AND NOT `deleted`", $target_guid); + } else { + $condition = array("`guid` = ? AND `uid` = ? AND NOT `file` LIKE '%%[%%' AND NOT `deleted`", $target_guid, $importer['uid']); + } + $r = dba::select('item', $fields, $condition); + if (!Dbm::is_result($r)) { + logger("Target guid ".$target_guid." was not found on this system for user ".$importer['uid']."."); + return false; + } + + while ($item = dba::fetch($r)) { + // Fetch the parent item + $parent = dba::select('item', array('author-link', 'origin'), array('id' => $item["parent"]), array('limit' => 1)); + + // Only delete it if the parent author really fits + if (!link_compare($parent["author-link"], $contact["url"]) && !link_compare($item["author-link"], $contact["url"])) { + logger("Thread author ".$parent["author-link"]." and item author ".$item["author-link"]." don't fit to expected contact ".$contact["url"], LOGGER_DEBUG); + continue; + } + + // Currently we don't have a central deletion function that we could use in this case. The function "item_drop" doesn't work for that case + dba::update('item', array('deleted' => true, 'title' => '', 'body' => '', + 'edited' => datetime_convert(), 'changed' => datetime_convert()), + array('id' => $item["id"])); + + // Delete the thread - if it is a starting post and not a comment + if ($target_type != 'Comment') { + delete_thread($item["id"], $item["parent-uri"]); + } + + logger("Deleted target ".$target_guid." (".$item["id"].") from user ".$item["uid"]." parent: ".$item["parent"], LOGGER_DEBUG); + + // Now check if the retraction needs to be relayed by us + if ($parent["origin"]) { + // notify others + Worker::add(PRIORITY_HIGH, "notifier", "drop", $item["id"]); + } + } + + return true; + } + + /** + * @brief Receives retraction messages + * + * @param array $importer Array of the importer user + * @param string $sender The sender of the message + * @param object $data The message object + * + * @return bool Success + */ + private static function receive_retraction($importer, $sender, $data) { + $target_type = notags(unxmlify($data->target_type)); + + $contact = self::contact_by_handle($importer["uid"], $sender); + if (!$contact && (in_array($target_type, array("Contact", "Person")))) { + logger("cannot find contact for sender: ".$sender." and user ".$importer["uid"]); + return false; + } + + logger("Got retraction for ".$target_type.", sender ".$sender." and user ".$importer["uid"], LOGGER_DEBUG); + + switch ($target_type) { + case "Comment": + case "Like": + case "Post": + case "Reshare": + case "StatusMessage": + return self::item_retraction($importer, $contact, $data); + + case "Contact": + case "Person": + /// @todo What should we do with an "unshare"? + // Removing the contact isn't correct since we still can read the public items + contact_remove($contact["id"]); + return true; + + default: + logger("Unknown target type ".$target_type); + return false; + } + return true; + } + + /** + * @brief Receives status messages + * + * @param array $importer Array of the importer user + * @param object $data The message object + * @param string $xml The original XML of the message + * + * @return int The message id of the newly created item + */ + private static function receive_status_message($importer, $data, $xml) { + $author = notags(unxmlify($data->author)); + $guid = notags(unxmlify($data->guid)); + $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); + $public = notags(unxmlify($data->public)); + $text = unxmlify($data->text); + $provider_display_name = notags(unxmlify($data->provider_display_name)); + + $contact = self::allowed_contact_by_handle($importer, $author, false); + if (!$contact) { + return false; + } + + $message_id = self::message_exists($importer["uid"], $guid); + if ($message_id) { + return true; + } + + $address = array(); + if ($data->location) { + foreach ($data->location->children() AS $fieldname => $data) { + $address[$fieldname] = notags(unxmlify($data)); + } + } + + $body = diaspora2bb($text); + + $datarray = array(); + + // Attach embedded pictures to the body + if ($data->photo) { + foreach ($data->photo AS $photo) { + $body = "[img]".unxmlify($photo->remote_photo_path). + unxmlify($photo->remote_photo_name)."[/img]\n".$body; + } + + $datarray["object-type"] = ACTIVITY_OBJ_IMAGE; + } else { + $datarray["object-type"] = ACTIVITY_OBJ_NOTE; + + // Add OEmbed and other information to the body + if (!self::is_redmatrix($contact["url"])) { + $body = add_page_info_to_body($body, false, true); + } + } + + /// @todo enable support for polls + //if ($data->poll) { + // foreach ($data->poll AS $poll) + // print_r($poll); + // die("poll!\n"); + //} + + /// @todo enable support for events + + $datarray["uid"] = $importer["uid"]; + $datarray["contact-id"] = $contact["id"]; + $datarray["network"] = NETWORK_DIASPORA; + + $datarray["author-name"] = $contact["name"]; + $datarray["author-link"] = $contact["url"]; + $datarray["author-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]); + + $datarray["owner-name"] = $datarray["author-name"]; + $datarray["owner-link"] = $datarray["author-link"]; + $datarray["owner-avatar"] = $datarray["author-avatar"]; + + $datarray["guid"] = $guid; + $datarray["uri"] = $datarray["parent-uri"] = self::get_uri_from_guid($author, $guid); + + $datarray["verb"] = ACTIVITY_POST; + $datarray["gravity"] = GRAVITY_PARENT; + + $datarray["protocol"] = PROTOCOL_DIASPORA; + $datarray["source"] = $xml; + + $datarray["body"] = self::replace_people_guid($body, $contact["url"]); + + if ($provider_display_name != "") { + $datarray["app"] = $provider_display_name; + } + + $datarray["plink"] = self::plink($author, $guid); + $datarray["private"] = (($public == "false") ? 1 : 0); + $datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at; + + if (isset($address["address"])) { + $datarray["location"] = $address["address"]; + } + + if (isset($address["lat"]) && isset($address["lng"])) { + $datarray["coord"] = $address["lat"]." ".$address["lng"]; + } + + self::fetch_guid($datarray); + $message_id = item_store($datarray); + + if ($message_id) { + logger("Stored item ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); + return true; + } else { + return false; + } + } + + /* ************************************************************************************** * + * Here are all the functions that are needed to transmit data with the Diaspora protocol * + * ************************************************************************************** */ + + /** + * @brief returnes the handle of a contact + * + * @param array $me contact array + * + * @return string the handle in the format user@domain.tld + */ + private static function my_handle($contact) { + if ($contact["addr"] != "") { + return $contact["addr"]; + } + + // Normally we should have a filled "addr" field - but in the past this wasn't the case + // So - just in case - we build the the address here. + if ($contact["nickname"] != "") { + $nick = $contact["nickname"]; + } else { + $nick = $contact["nick"]; + } + + return $nick."@".substr(System::baseUrl(), strpos(System::baseUrl(),"://") + 3); + } + + + /** + * @brief Creates the data for a private message in the new format + * + * @param string $msg The message that is to be transmitted + * @param array $user The record of the sender + * @param array $contact Target of the communication + * @param string $prvkey The private key of the sender + * @param string $pubkey The public key of the receiver + * + * @return string The encrypted data + */ + public static function encode_private_data($msg, $user, $contact, $prvkey, $pubkey) { + + logger("Message: ".$msg, LOGGER_DATA); + + // without a public key nothing will work + if (!$pubkey) { + logger("pubkey missing: contact id: ".$contact["id"]); + return false; + } + + $aes_key = openssl_random_pseudo_bytes(32); + $b_aes_key = base64_encode($aes_key); + $iv = openssl_random_pseudo_bytes(16); + $b_iv = base64_encode($iv); + + $ciphertext = self::aes_encrypt($aes_key, $iv, $msg); + + $json = json_encode(array("iv" => $b_iv, "key" => $b_aes_key)); + + $encrypted_key_bundle = ""; + openssl_public_encrypt($json, $encrypted_key_bundle, $pubkey); + + $json_object = json_encode(array("aes_key" => base64_encode($encrypted_key_bundle), + "encrypted_magic_envelope" => base64_encode($ciphertext))); + + return $json_object; + } + + /** + * @brief Creates the envelope for the "fetch" endpoint and for the new format + * + * @param string $msg The message that is to be transmitted + * @param array $user The record of the sender + * + * @return string The envelope + */ + public static function build_magic_envelope($msg, $user) { + + $b64url_data = base64url_encode($msg); + $data = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data); + + $key_id = base64url_encode(self::my_handle($user)); + $type = "application/xml"; + $encoding = "base64url"; + $alg = "RSA-SHA256"; + $signable_data = $data.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg); + + // Fallback if the private key wasn't transmitted in the expected field + if ($user['uprvkey'] == "") + $user['uprvkey'] = $user['prvkey']; + + $signature = rsa_sign($signable_data, $user["uprvkey"]); + $sig = base64url_encode($signature); + + $xmldata = array("me:env" => array("me:data" => $data, + "@attributes" => array("type" => $type), + "me:encoding" => $encoding, + "me:alg" => $alg, + "me:sig" => $sig, + "@attributes2" => array("key_id" => $key_id))); + + $namespaces = array("me" => "http://salmon-protocol.org/ns/magic-env"); + + return xml::from_array($xmldata, $xml, false, $namespaces); + } + + /** + * @brief Create the envelope for a message + * + * @param string $msg The message that is to be transmitted + * @param array $user The record of the sender + * @param array $contact Target of the communication + * @param string $prvkey The private key of the sender + * @param string $pubkey The public key of the receiver + * @param bool $public Is the message public? + * + * @return string The message that will be transmitted to other servers + */ + private static function build_message($msg, $user, $contact, $prvkey, $pubkey, $public = false) { + + // The message is put into an envelope with the sender's signature + $envelope = self::build_magic_envelope($msg, $user); + + // Private messages are put into a second envelope, encrypted with the receivers public key + if (!$public) { + $envelope = self::encode_private_data($envelope, $user, $contact, $prvkey, $pubkey); + } + + return $envelope; + } + + /** + * @brief Creates a signature for a message + * + * @param array $owner the array of the owner of the message + * @param array $message The message that is to be signed + * + * @return string The signature + */ + private static function signature($owner, $message) { + $sigmsg = $message; + unset($sigmsg["author_signature"]); + unset($sigmsg["parent_author_signature"]); + + $signed_text = implode(";", $sigmsg); + + return base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256")); + } + + /** + * @brief Transmit a message to a target server + * + * @param array $owner the array of the item owner + * @param array $contact Target of the communication + * @param string $envelope The message that is to be transmitted + * @param bool $public_batch Is it a public post? + * @param bool $queue_run Is the transmission called from the queue? + * @param string $guid message guid + * + * @return int Result of the transmission + */ + public static function transmit($owner, $contact, $envelope, $public_batch, $queue_run=false, $guid = "") { + + $a = get_app(); + + $enabled = intval(Config::get("system", "diaspora_enabled")); + if (!$enabled) + return 200; + + $logid = random_string(4); + $dest_url = (($public_batch) ? $contact["batch"] : $contact["notify"]); + if (!$dest_url) { + logger("no url for contact: ".$contact["id"]." batch mode =".$public_batch); + return 0; + } + + logger("transmit: ".$logid."-".$guid." ".$dest_url); + + if (!$queue_run && was_recently_delayed($contact["id"])) { + $return_code = 0; + } else { + if (!intval(Config::get("system", "diaspora_test"))) { + $content_type = (($public_batch) ? "application/magic-envelope+xml" : "application/json"); + + post_url($dest_url."/", $envelope, array("Content-Type: ".$content_type)); + $return_code = $a->get_curl_code(); + } else { + logger("test_mode"); + return 200; + } + } + + logger("transmit: ".$logid."-".$guid." returns: ".$return_code); + + if (!$return_code || (($return_code == 503) && (stristr($a->get_curl_headers(), "retry-after")))) { + logger("queue message"); + + $r = q("SELECT `id` FROM `queue` WHERE `cid` = %d AND `network` = '%s' AND `content` = '%s' AND `batch` = %d LIMIT 1", + intval($contact["id"]), + dbesc(NETWORK_DIASPORA), + dbesc($envelope), + intval($public_batch) + ); + if ($r) { + logger("add_to_queue ignored - identical item already in queue"); + } else { + // queue message for redelivery + add_to_queue($contact["id"], NETWORK_DIASPORA, $envelope, $public_batch); + + // The message could not be delivered. We mark the contact as "dead" + mark_for_death($contact); + } + } elseif (($return_code >= 200) && ($return_code <= 299)) { + // We successfully delivered a message, the contact is alive + unmark_for_death($contact); + } + + return(($return_code) ? $return_code : (-1)); + } + + + /** + * @brief Build the post xml + * + * @param string $type The message type + * @param array $message The message data + * + * @return string The post XML + */ + public static function build_post_xml($type, $message) { + + $data = array($type => $message); + + return xml::from_array($data, $xml); + } + + /** + * @brief Builds and transmit messages + * + * @param array $owner the array of the item owner + * @param array $contact Target of the communication + * @param string $type The message type + * @param array $message The message data + * @param bool $public_batch Is it a public post? + * @param string $guid message guid + * @param bool $spool Should the transmission be spooled or transmitted? + * + * @return int Result of the transmission + */ + private static function build_and_transmit($owner, $contact, $type, $message, $public_batch = false, $guid = "", $spool = false) { + + $msg = self::build_post_xml($type, $message); + + logger('message: '.$msg, LOGGER_DATA); + logger('send guid '.$guid, LOGGER_DEBUG); + + // Fallback if the private key wasn't transmitted in the expected field + if ($owner['uprvkey'] == "") + $owner['uprvkey'] = $owner['prvkey']; + + $envelope = self::build_message($msg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch); + + if ($spool) { + add_to_queue($contact['id'], NETWORK_DIASPORA, $envelope, $public_batch); + return true; + } else + $return_code = self::transmit($owner, $contact, $envelope, $public_batch, false, $guid); + + logger("guid: ".$item["guid"]." result ".$return_code, LOGGER_DEBUG); + + return $return_code; + } + + /** + * @brief sends an account migration + * + * @param array $owner the array of the item owner + * @param array $contact Target of the communication + * @param int $uid User ID + * + * @return int The result of the transmission + */ + public static function sendAccountMigration($owner, $contact, $uid) { + + $old_handle = PConfig::get($uid, 'system', 'previous_addr'); + $profile = self::createProfileData($uid); + + $signed_text = 'AccountMigration:'.$old_handle.':'.$profile['author']; + $signature = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256")); + + $message = array("author" => $old_handle, + "profile" => $profile, + "signature" => $signature); + + logger("Send account migration ".print_r($message, true), LOGGER_DEBUG); + + return self::build_and_transmit($owner, $contact, "account_migration", $message); + } + + /** + * @brief Sends a "share" message + * + * @param array $owner the array of the item owner + * @param array $contact Target of the communication + * + * @return int The result of the transmission + */ + public static function send_share($owner, $contact) { + + /** + * @todo support the different possible combinations of "following" and "sharing" + * Currently, Diaspora only interprets the "sharing" field + * + * Before switching this code productive, we have to check all "send_share" calls if "rel" is set correctly + */ + + /* + switch ($contact["rel"]) { + case CONTACT_IS_FRIEND: + $following = true; + $sharing = true; + case CONTACT_IS_SHARING: + $following = false; + $sharing = true; + case CONTACT_IS_FOLLOWER: + $following = true; + $sharing = false; + } + */ + + $message = array("author" => self::my_handle($owner), + "recipient" => $contact["addr"], + "following" => "true", + "sharing" => "true"); + + logger("Send share ".print_r($message, true), LOGGER_DEBUG); + + return self::build_and_transmit($owner, $contact, "contact", $message); + } + + /** + * @brief sends an "unshare" + * + * @param array $owner the array of the item owner + * @param array $contact Target of the communication + * + * @return int The result of the transmission + */ + public static function send_unshare($owner, $contact) { + + $message = array("author" => self::my_handle($owner), + "recipient" => $contact["addr"], + "following" => "false", + "sharing" => "false"); + + logger("Send unshare ".print_r($message, true), LOGGER_DEBUG); + + return self::build_and_transmit($owner, $contact, "contact", $message); + } + + /** + * @brief Checks a message body if it is a reshare + * + * @param string $body The message body that is to be check + * @param bool $complete Should it be a complete check or a simple check? + * + * @return array|bool Reshare details or "false" if no reshare + */ + public static function is_reshare($body, $complete = true) { + $body = trim($body); + + // Skip if it isn't a pure repeated messages + // Does it start with a share? + if ((strpos($body, "[share") > 0) && $complete) + return(false); + + // Does it end with a share? + if (strlen($body) > (strrpos($body, "[/share]") + 8)) + return(false); + + $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body); + // Skip if there is no shared message in there + if ($body == $attributes) + return(false); + + // If we don't do the complete check we quit here + if (!$complete) + return true; + + $guid = ""; + preg_match("/guid='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $guid = $matches[1]; + + preg_match('/guid="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $guid = $matches[1]; + + if ($guid != "") { + $r = q("SELECT `contact-id` FROM `item` WHERE `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1", + dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA); + if ($r) { + $ret= array(); + $ret["root_handle"] = self::handle_from_contact($r[0]["contact-id"]); + $ret["root_guid"] = $guid; + return($ret); + } + } + + $profile = ""; + preg_match("/profile='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $profile = $matches[1]; + + preg_match('/profile="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $profile = $matches[1]; + + $ret= array(); + + $ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile); + if (($ret["root_handle"] == $profile) || ($ret["root_handle"] == "")) + return(false); + + $link = ""; + preg_match("/link='(.*?)'/ism", $attributes, $matches); + if ($matches[1] != "") + $link = $matches[1]; + + preg_match('/link="(.*?)"/ism', $attributes, $matches); + if ($matches[1] != "") + $link = $matches[1]; + + $ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link); + if (($ret["root_guid"] == $link) || (trim($ret["root_guid"]) == "")) + return(false); + + return($ret); + } + + /** + * @brief Create an event array + * + * @param integer $event_id The id of the event + * + * @return array with event data + */ + private static function build_event($event_id) { + + $r = q("SELECT `guid`, `uid`, `start`, `finish`, `nofinish`, `summary`, `desc`, `location`, `adjust` FROM `event` WHERE `id` = %d", intval($event_id)); + if (!Dbm::is_result($r)) { + return array(); + } + + $event = $r[0]; + + $eventdata = array(); + + $r = q("SELECT `timezone` FROM `user` WHERE `uid` = %d", intval($event['uid'])); + if (!Dbm::is_result($r)) { + return array(); + } + + $user = $r[0]; + + $r = q("SELECT `addr`, `nick` FROM `contact` WHERE `uid` = %d AND `self`", intval($event['uid'])); + if (!Dbm::is_result($r)) { + return array(); + } + + $owner = $r[0]; + + $eventdata['author'] = self::my_handle($owner); + + if ($event['guid']) { + $eventdata['guid'] = $event['guid']; + } + + $mask = 'Y-m-d\TH:i:s\Z'; + + /// @todo - establish "all day" events in Friendica + $eventdata["all_day"] = "false"; + + if (!$event['adjust']) { + $eventdata['timezone'] = $user['timezone']; + + if ($eventdata['timezone'] == "") { + $eventdata['timezone'] = 'UTC'; + } + } + + if ($event['start']) { + $eventdata['start'] = datetime_convert($eventdata['timezone'], "UTC", $event['start'], $mask); + } + if ($event['finish'] && !$event['nofinish']) { + $eventdata['end'] = datetime_convert($eventdata['timezone'], "UTC", $event['finish'], $mask); + } + if ($event['summary']) { + $eventdata['summary'] = html_entity_decode(bb2diaspora($event['summary'])); + } + if ($event['desc']) { + $eventdata['description'] = html_entity_decode(bb2diaspora($event['desc'])); + } + if ($event['location']) { + $location = array(); + $location["address"] = html_entity_decode(bb2diaspora($event['location'])); + $location["lat"] = 0; + $location["lng"] = 0; + $eventdata['location'] = $location; + } + + return $eventdata; + } + + /** + * @brief Create a post (status message or reshare) + * + * @param array $item The item that will be exported + * @param array $owner the array of the item owner + * + * @return array + * 'type' -> Message type ("status_message" or "reshare") + * 'message' -> Array of XML elements of the status + */ + public static function build_status($item, $owner) { + + $cachekey = "diaspora:build_status:".$item['guid']; + + $result = Cache::get($cachekey); + if (!is_null($result)) { + return $result; + } + + $myaddr = self::my_handle($owner); + + $public = (($item["private"]) ? "false" : "true"); + + $created = datetime_convert("UTC", "UTC", $item["created"], 'Y-m-d\TH:i:s\Z'); + + // Detect a share element and do a reshare + if (!$item['private'] && ($ret = self::is_reshare($item["body"]))) { + $message = array("author" => $myaddr, + "guid" => $item["guid"], + "created_at" => $created, + "root_author" => $ret["root_handle"], + "root_guid" => $ret["root_guid"], + "provider_display_name" => $item["app"], + "public" => $public); + + $type = "reshare"; + } else { + $title = $item["title"]; + $body = $item["body"]; + + // convert to markdown + $body = html_entity_decode(bb2diaspora($body)); + + // Adding the title + if (strlen($title)) + $body = "## ".html_entity_decode($title)."\n\n".$body; + + if ($item["attach"]) { + $cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism', $item["attach"], $matches, PREG_SET_ORDER); + if (cnt) { + $body .= "\n".t("Attachments:")."\n"; + foreach ($matches as $mtch) + $body .= "[".$mtch[3]."](".$mtch[1].")\n"; + } + } + + $location = array(); + + if ($item["location"] != "") + $location["address"] = $item["location"]; + + if ($item["coord"] != "") { + $coord = explode(" ", $item["coord"]); + $location["lat"] = $coord[0]; + $location["lng"] = $coord[1]; + } + + $message = array("author" => $myaddr, + "guid" => $item["guid"], + "created_at" => $created, + "public" => $public, + "text" => $body, + "provider_display_name" => $item["app"], + "location" => $location); + + // Diaspora rejects messages when they contain a location without "lat" or "lng" + if (!isset($location["lat"]) || !isset($location["lng"])) { + unset($message["location"]); + } + + if ($item['event-id'] > 0) { + $event = self::build_event($item['event-id']); + if (count($event)) { + $message['event'] = $event; + + /// @todo Once Diaspora supports it, we will remove the body + // $message['text'] = ''; + } + } + + $type = "status_message"; + } + + $msg = array("type" => $type, "message" => $message); + + Cache::set($cachekey, $msg, CACHE_QUARTER_HOUR); + + return $msg; + } + + /** + * @brief Sends a post + * + * @param array $item The item that will be exported + * @param array $owner the array of the item owner + * @param array $contact Target of the communication + * @param bool $public_batch Is it a public post? + * + * @return int The result of the transmission + */ + public static function send_status($item, $owner, $contact, $public_batch = false) { + + $status = self::build_status($item, $owner); + + return self::build_and_transmit($owner, $contact, $status["type"], $status["message"], $public_batch, $item["guid"]); + } + + /** + * @brief Creates a "like" object + * + * @param array $item The item that will be exported + * @param array $owner the array of the item owner + * + * @return array The data for a "like" + */ + private static function construct_like($item, $owner) { + + $p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1", + dbesc($item["thr-parent"])); + if (!Dbm::is_result($p)) + return false; + + $parent = $p[0]; + + $target_type = ($parent["uri"] === $parent["parent-uri"] ? "Post" : "Comment"); + if ($item['verb'] === ACTIVITY_LIKE) { + $positive = "true"; + } elseif ($item['verb'] === ACTIVITY_DISLIKE) { + $positive = "false"; + } + + return(array("author" => self::my_handle($owner), + "guid" => $item["guid"], + "parent_guid" => $parent["guid"], + "parent_type" => $target_type, + "positive" => $positive, + "author_signature" => "")); + } + + /** + * @brief Creates an "EventParticipation" object + * + * @param array $item The item that will be exported + * @param array $owner the array of the item owner + * + * @return array The data for an "EventParticipation" + */ + private static function construct_attend($item, $owner) { + + $p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1", + dbesc($item["thr-parent"])); + if (!Dbm::is_result($p)) + return false; + + $parent = $p[0]; + + switch ($item['verb']) { + case ACTIVITY_ATTEND: + $attend_answer = 'accepted'; + break; + case ACTIVITY_ATTENDNO: + $attend_answer = 'declined'; + break; + case ACTIVITY_ATTENDMAYBE: + $attend_answer = 'tentative'; + break; + default: + logger('Unknown verb '.$item['verb'].' in item '.$item['guid']); + return false; + } + + return(array("author" => self::my_handle($owner), + "guid" => $item["guid"], + "parent_guid" => $parent["guid"], + "status" => $attend_answer, + "author_signature" => "")); + } + + /** + * @brief Creates the object for a comment + * + * @param array $item The item that will be exported + * @param array $owner the array of the item owner + * + * @return array The data for a comment + */ + private static function construct_comment($item, $owner) { + + $cachekey = "diaspora:construct_comment:".$item['guid']; + + $result = Cache::get($cachekey); + if (!is_null($result)) { + return $result; + } + + $p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1", + intval($item["parent"]), + intval($item["parent"]) + ); + + if (!Dbm::is_result($p)) + return false; + + $parent = $p[0]; + + $text = html_entity_decode(bb2diaspora($item["body"])); + $created = datetime_convert("UTC", "UTC", $item["created"], 'Y-m-d\TH:i:s\Z'); + + $comment = array("author" => self::my_handle($owner), + "guid" => $item["guid"], + "created_at" => $created, + "parent_guid" => $parent["guid"], + "text" => $text, + "author_signature" => ""); + + // Send the thread parent guid only if it is a threaded comment + if ($item['thr-parent'] != $item['parent-uri']) { + $comment['thread_parent_guid'] = self::get_guid_from_uri($item['thr-parent'], $item['uid']); + } + + Cache::set($cachekey, $comment, CACHE_QUARTER_HOUR); + + return($comment); + } + + /** + * @brief Send a like or a comment + * + * @param array $item The item that will be exported + * @param array $owner the array of the item owner + * @param array $contact Target of the communication + * @param bool $public_batch Is it a public post? + * + * @return int The result of the transmission + */ + public static function send_followup($item,$owner,$contact,$public_batch = false) { + + if (in_array($item['verb'], array(ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE))) { + $message = self::construct_attend($item, $owner); + $type = "event_participation"; + } elseif (in_array($item["verb"], array(ACTIVITY_LIKE, ACTIVITY_DISLIKE))) { + $message = self::construct_like($item, $owner); + $type = "like"; + } else { + $message = self::construct_comment($item, $owner); + $type = "comment"; + } + + if (!$message) + return false; + + $message["author_signature"] = self::signature($owner, $message); + + return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]); + } + + /** + * @brief Creates a message from a signature record entry + * + * @param array $item The item that will be exported + * @param array $signature The entry of the "sign" record + * + * @return string The message + */ + private static function message_from_signature($item, $signature) { + + // Split the signed text + $signed_parts = explode(";", $signature['signed_text']); + + if ($item["deleted"]) { + $message = array("author" => $signature['signer'], + "target_guid" => $signed_parts[0], + "target_type" => $signed_parts[1]); + } elseif (in_array($item["verb"], array(ACTIVITY_LIKE, ACTIVITY_DISLIKE))) { + $message = array("author" => $signed_parts[4], + "guid" => $signed_parts[1], + "parent_guid" => $signed_parts[3], + "parent_type" => $signed_parts[2], + "positive" => $signed_parts[0], + "author_signature" => $signature['signature'], + "parent_author_signature" => ""); + } else { + // Remove the comment guid + $guid = array_shift($signed_parts); + + // Remove the parent guid + $parent_guid = array_shift($signed_parts); + + // Remove the handle + $handle = array_pop($signed_parts); + + // Glue the parts together + $text = implode(";", $signed_parts); + + $message = array("author" => $handle, + "guid" => $guid, + "parent_guid" => $parent_guid, + "text" => implode(";", $signed_parts), + "author_signature" => $signature['signature'], + "parent_author_signature" => ""); + } + return $message; + } + + /** + * @brief Relays messages (like, comment, retraction) to other servers if we are the thread owner + * + * @param array $item The item that will be exported + * @param array $owner the array of the item owner + * @param array $contact Target of the communication + * @param bool $public_batch Is it a public post? + * + * @return int The result of the transmission + */ + public static function send_relay($item, $owner, $contact, $public_batch = false) { + + if ($item["deleted"]) { + return self::send_retraction($item, $owner, $contact, $public_batch, true); + } elseif (in_array($item["verb"], array(ACTIVITY_LIKE, ACTIVITY_DISLIKE))) { + $type = "like"; + } else { + $type = "comment"; + } + + logger("Got relayable data ".$type." for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG); + + // fetch the original signature + + $r = q("SELECT `signed_text`, `signature`, `signer` FROM `sign` WHERE `iid` = %d LIMIT 1", + intval($item["id"])); + + if (!$r) { + logger("Couldn't fetch signatur for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG); + return false; + } + + $signature = $r[0]; + + // Old way - is used by the internal Friendica functions + /// @todo Change all signatur storing functions to the new format + if ($signature['signed_text'] && $signature['signature'] && $signature['signer']) + $message = self::message_from_signature($item, $signature); + else {// New way + $msg = json_decode($signature['signed_text'], true); + + $message = array(); + if (is_array($msg)) { + foreach ($msg AS $field => $data) { + if (!$item["deleted"]) { + if ($field == "diaspora_handle") { + $field = "author"; + } + if ($field == "target_type") { + $field = "parent_type"; + } + } + + $message[$field] = $data; + } + } else + logger("Signature text for item ".$item["guid"]." (".$item["id"].") couldn't be extracted: ".$signature['signed_text'], LOGGER_DEBUG); + } + + $message["parent_author_signature"] = self::signature($owner, $message); + + logger("Relayed data ".print_r($message, true), LOGGER_DEBUG); + + return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]); + } + + /** + * @brief Sends a retraction (deletion) of a message, like or comment + * + * @param array $item The item that will be exported + * @param array $owner the array of the item owner + * @param array $contact Target of the communication + * @param bool $public_batch Is it a public post? + * @param bool $relay Is the retraction transmitted from a relay? + * + * @return int The result of the transmission + */ + public static function send_retraction($item, $owner, $contact, $public_batch = false, $relay = false) { + + $itemaddr = self::handle_from_contact($item["contact-id"], $item["gcontact-id"]); + + $msg_type = "retraction"; + + if ($item['id'] == $item['parent']) { + $target_type = "Post"; + } elseif (in_array($item["verb"], array(ACTIVITY_LIKE, ACTIVITY_DISLIKE))) { + $target_type = "Like"; + } else { + $target_type = "Comment"; + } + + $message = array("author" => $itemaddr, + "target_guid" => $item['guid'], + "target_type" => $target_type); + + logger("Got message ".print_r($message, true), LOGGER_DEBUG); + + return self::build_and_transmit($owner, $contact, $msg_type, $message, $public_batch, $item["guid"]); + } + + /** + * @brief Sends a mail + * + * @param array $item The item that will be exported + * @param array $owner The owner + * @param array $contact Target of the communication + * + * @return int The result of the transmission + */ + public static function send_mail($item, $owner, $contact) { + + $myaddr = self::my_handle($owner); + + $r = q("SELECT * FROM `conv` WHERE `id` = %d AND `uid` = %d LIMIT 1", + intval($item["convid"]), + intval($item["uid"]) + ); + + if (!Dbm::is_result($r)) { + logger("conversation not found."); + return; + } + $cnv = $r[0]; + + $conv = array( + "author" => $cnv["creator"], + "guid" => $cnv["guid"], + "subject" => $cnv["subject"], + "created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d\TH:i:s\Z'), + "participants" => $cnv["recips"] + ); + + $body = bb2diaspora($item["body"]); + $created = datetime_convert("UTC", "UTC", $item["created"], 'Y-m-d\TH:i:s\Z'); + + $msg = array( + "author" => $myaddr, + "guid" => $item["guid"], + "conversation_guid" => $cnv["guid"], + "text" => $body, + "created_at" => $created, + ); + + if ($item["reply"]) { + $message = $msg; + $type = "message"; + } else { + $message = array( + "author" => $cnv["creator"], + "guid" => $cnv["guid"], + "subject" => $cnv["subject"], + "created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d\TH:i:s\Z'), + "participants" => $cnv["recips"], + "message" => $msg); + + $type = "conversation"; + } + + return self::build_and_transmit($owner, $contact, $type, $message, false, $item["guid"]); + } + + /** + * @brief Create profile data + * + * @param int $uid The user id + * + * @return array The profile data + */ + private static function createProfileData($uid) { + $r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `user`.*, `user`.`prvkey` AS `uprvkey`, `contact`.`addr` + FROM `profile` + INNER JOIN `user` ON `profile`.`uid` = `user`.`uid` + INNER JOIN `contact` ON `profile`.`uid` = `contact`.`uid` + WHERE `user`.`uid` = %d AND `profile`.`is-default` AND `contact`.`self` LIMIT 1", + intval($uid) + ); + + if (!$r) { + return array(); + } + + $profile = $r[0]; + + $handle = $profile["addr"]; + $first = ((strpos($profile['name'],' ') + ? trim(substr($profile['name'],0,strpos($profile['name'],' '))) : $profile['name'])); + $last = (($first === $profile['name']) ? '' : trim(substr($profile['name'], strlen($first)))); + $large = System::baseUrl().'/photo/custom/300/'.$profile['uid'].'.jpg'; + $medium = System::baseUrl().'/photo/custom/100/'.$profile['uid'].'.jpg'; + $small = System::baseUrl().'/photo/custom/50/' .$profile['uid'].'.jpg'; + $searchable = (($profile['publish'] && $profile['net-publish']) ? 'true' : 'false'); + + if ($searchable === 'true') { + $dob = '1000-00-00'; + + if (($profile['dob']) && ($profile['dob'] > '0001-01-01')) + $dob = ((intval($profile['dob'])) ? intval($profile['dob']) : '1000') .'-'. datetime_convert('UTC','UTC',$profile['dob'],'m-d'); + + $about = $profile['about']; + $about = strip_tags(bbcode($about)); + + $location = formatted_location($profile); + $tags = ''; + if ($profile['pub_keywords']) { + $kw = str_replace(',',' ',$profile['pub_keywords']); + $kw = str_replace(' ',' ',$kw); + $arr = explode(' ',$profile['pub_keywords']); + if (count($arr)) { + for ($x = 0; $x < 5; $x ++) { + if (trim($arr[$x])) + $tags .= '#'. trim($arr[$x]) .' '; + } + } + } + $tags = trim($tags); + } + + return array("author" => $handle, + "first_name" => $first, + "last_name" => $last, + "image_url" => $large, + "image_url_medium" => $medium, + "image_url_small" => $small, + "birthday" => $dob, + "gender" => $profile['gender'], + "bio" => $about, + "location" => $location, + "searchable" => $searchable, + "nsfw" => "false", + "tag_string" => $tags); + } + + /** + * @brief Sends profile data + * + * @param int $uid The user id + */ + public static function send_profile($uid, $recips = false) { + + if (!$uid) + return; + + if (!$recips) + $recips = q("SELECT `id`,`name`,`network`,`pubkey`,`notify` FROM `contact` WHERE `network` = '%s' + AND `uid` = %d AND `rel` != %d", + dbesc(NETWORK_DIASPORA), + intval($uid), + intval(CONTACT_IS_SHARING) + ); + if (!$recips) + return; + + $message = self::createProfileData($uid); + + foreach ($recips as $recip) { + logger("Send updated profile data for user ".$uid." to contact ".$recip["id"], LOGGER_DEBUG); + self::build_and_transmit($profile, $recip, "profile", $message, false, "", true); + } + } + + /** + * @brief Stores the signature for likes that are created on our system + * + * @param array $contact The contact array of the "like" + * @param int $post_id The post id of the "like" + * + * @return bool Success + */ + public static function store_like_signature($contact, $post_id) { + + // Is the contact the owner? Then fetch the private key + if (!$contact['self'] || ($contact['uid'] == 0)) { + logger("No owner post, so not storing signature", LOGGER_DEBUG); + return false; + } + + $r = q("SELECT `prvkey` FROM `user` WHERE `uid` = %d LIMIT 1", intval($contact['uid'])); + if (!Dbm::is_result($r)) { + return false; + } + + $contact["uprvkey"] = $r[0]['prvkey']; + + $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($post_id)); + if (!Dbm::is_result($r)) { + return false; + } + + if (!in_array($r[0]["verb"], array(ACTIVITY_LIKE, ACTIVITY_DISLIKE))) { + return false; + } + + $message = self::construct_like($r[0], $contact); + $message["author_signature"] = self::signature($contact, $message); + + /* + * Now store the signature more flexible to dynamically support new fields. + * This will break Diaspora compatibility with Friendica versions prior to 3.5. + */ + dba::insert('sign', array('iid' => $post_id, 'signed_text' => json_encode($message))); + + logger('Stored diaspora like signature'); + return true; + } + + /** + * @brief Stores the signature for comments that are created on our system + * + * @param array $item The item array of the comment + * @param array $contact The contact array of the item owner + * @param string $uprvkey The private key of the sender + * @param int $message_id The message id of the comment + * + * @return bool Success + */ + public static function store_comment_signature($item, $contact, $uprvkey, $message_id) { + + if ($uprvkey == "") { + logger('No private key, so not storing comment signature', LOGGER_DEBUG); + return false; + } + + $contact["uprvkey"] = $uprvkey; + + $message = self::construct_comment($item, $contact); + $message["author_signature"] = self::signature($contact, $message); + + /* + * Now store the signature more flexible to dynamically support new fields. + * This will break Diaspora compatibility with Friendica versions prior to 3.5. + */ + dba::insert('sign', array('iid' => $message_id, 'signed_text' => json_encode($message))); + + logger('Stored diaspora comment signature'); + return true; + } +} diff --git a/src/Util/Lock.php b/src/Util/Lock.php index 8cd38066d1..9bf67d7043 100644 --- a/src/Util/Lock.php +++ b/src/Util/Lock.php @@ -9,9 +9,9 @@ namespace Friendica\Util; */ use Friendica\Core\Config; +use Friendica\Database\Dbm; use Memcache; use dba; -use dbm; /** * @brief This class contain Functions for preventing parallel execution of functions @@ -121,7 +121,7 @@ class Lock { dba::lock('locks'); $lock = dba::select('locks', array('locked', 'pid'), array('name' => $fn_name), array('limit' => 1)); - if (dbm::is_result($lock)) { + if (Dbm::is_result($lock)) { if ($lock['locked']) { // When the process id isn't used anymore, we can safely claim the lock for us. if (!posix_kill($lock['pid'], 0)) { @@ -136,7 +136,7 @@ class Lock { dba::update('locks', array('locked' => true, 'pid' => getmypid()), array('name' => $fn_name)); $got_lock = true; } - } elseif (!dbm::is_result($lock)) { + } elseif (!Dbm::is_result($lock)) { dba::insert('locks', array('name' => $fn_name, 'locked' => true, 'pid' => getmypid())); $got_lock = true; } From 9e99066fd70a9dd9a291a523afba1a390f0e3a0b Mon Sep 17 00:00:00 2001 From: Adam Magness Date: Tue, 7 Nov 2017 22:57:46 -0500 Subject: [PATCH 2/5] Class file relocations Issue #3878 --- boot.php | 7 +- doc/Developer-How-To-Move-Classes-to-src.md | 4 +- doc/autoloader.md | 8 +- include/Contact.php | 47 +- include/ForumManager.php | 3 +- include/NotificationsManager.php | 866 ---- include/Photo.php | 13 +- include/acl_selectors.php | 15 +- include/api.php | 87 +- include/auth.php | 7 +- include/auth_ejabberd.php | 3 +- include/cache.php | 3 +- include/contact_selectors.php | 5 +- include/contact_widgets.php | 5 +- include/conversation.php | 11 +- include/cron.php | 5 +- include/cronjobs.php | 11 +- include/datetime.php | 5 +- include/dba.php | 6 +- include/dbm.php | 112 - include/dbstructure.php | 35 +- include/delivery.php | 29 +- include/dfrn.php | 2966 -------------- include/diaspora.php | 3943 ------------------- include/directory.php | 3 +- include/discover_poco.php | 5 +- include/enotify.php | 11 +- include/event.php | 21 +- include/expire.php | 3 +- include/fcontact.php | 8 +- include/feed.php | 3 +- include/follow.php | 9 +- include/gprobe.php | 5 +- include/group.php | 21 +- include/identity.php | 17 +- include/items.php | 85 +- include/like.php | 11 +- include/message.php | 9 +- include/nav.php | 3 +- include/notifier.php | 19 +- include/oauth.php | 15 +- include/oembed.php | 3 +- include/onepoll.php | 13 +- include/ostatus.php | 31 +- include/plugin.php | 5 +- include/post_update.php | 5 +- include/pubsubpublish.php | 3 +- include/queue.php | 15 +- include/queue_fn.php | 7 +- include/redir.php | 5 +- include/security.php | 17 +- include/session.php | 3 +- include/socgraph.php | 59 +- include/text.php | 19 +- include/threads.php | 29 +- include/uimport.php | 5 +- include/update_gcontact.php | 3 +- include/user.php | 17 +- index.php | 3 +- mod/admin.php | 5 +- mod/allfriends.php | 5 +- mod/api.php | 3 +- mod/attach.php | 5 +- mod/cal.php | 7 +- mod/common.php | 13 +- mod/community.php | 3 +- mod/contactgroup.php | 5 +- mod/contacts.php | 13 +- mod/crepair.php | 7 +- mod/delegate.php | 15 +- mod/dfrn_confirm.php | 27 +- mod/dfrn_notify.php | 13 +- mod/dfrn_poll.php | 29 +- mod/dfrn_request.php | 29 +- mod/directory.php | 5 +- mod/dirfind.php | 2 +- mod/display.php | 37 +- mod/editpost.php | 5 +- mod/events.php | 9 +- mod/friendica.php | 5 +- mod/fsuggest.php | 9 +- mod/group.php | 11 +- mod/ignored.php | 3 +- mod/install.php | 3 +- mod/item.php | 55 +- mod/lockview.php | 11 +- mod/lostpass.php | 7 +- mod/manage.php | 13 +- mod/match.php | 3 +- mod/message.php | 15 +- mod/modexp.php | 3 +- mod/mood.php | 3 +- mod/msearch.php | 5 +- mod/network.php | 19 +- mod/nogroup.php | 5 +- mod/noscrape.php | 9 +- mod/notes.php | 7 +- mod/notice.php | 3 +- mod/notifications.php | 3 +- mod/notify.php | 3 +- mod/openid.php | 3 +- mod/p.php | 3 +- mod/photo.php | 9 +- mod/photos.php | 55 +- mod/ping.php | 23 +- mod/poco.php | 9 +- mod/poke.php | 7 +- mod/post.php | 3 +- mod/profile.php | 11 +- mod/profile_photo.php | 7 +- mod/profiles.php | 31 +- mod/profperm.php | 11 +- mod/proxy.php | 5 +- mod/pubsub.php | 9 +- mod/pubsubhubbub.php | 7 +- mod/qsearch.php | 5 +- mod/receive.php | 3 +- mod/redir.php | 5 +- mod/regmod.php | 9 +- mod/salmon.php | 11 +- mod/search.php | 7 +- mod/settings.php | 29 +- mod/share.php | 3 +- mod/starred.php | 3 +- mod/subthread.php | 9 +- mod/suggest.php | 3 +- mod/tagger.php | 9 +- mod/tagrm.php | 5 +- mod/uexport.php | 7 +- mod/unfollow.php | 7 +- mod/videos.php | 13 +- mod/viewcontacts.php | 7 +- mod/viewsrc.php | 3 +- mod/wall_attach.php | 7 +- mod/wall_upload.php | 5 +- mod/wallmessage.php | 5 +- mod/xrd.php | 3 +- object/Item.php | 3 +- src/App.php | 8 +- src/Core/Config.php | 4 +- src/Core/NotificationsManager.php | 28 +- src/Core/PConfig.php | 6 +- src/Core/Worker.php | 16 +- src/Database/{Dbm.php => DBM.php} | 2 +- src/Network/Probe.php | 8 +- src/Protocol/{Dfrn.php => DFRN.php} | 66 +- src/Protocol/Diaspora.php | 62 +- src/Util/Lock.php | 6 +- update.php | 33 +- view/theme/frio/theme.php | 11 +- view/theme/vier/theme.php | 7 +- 151 files changed, 987 insertions(+), 8742 deletions(-) delete mode 100644 include/NotificationsManager.php delete mode 100644 include/dbm.php delete mode 100644 include/dfrn.php delete mode 100644 include/diaspora.php rename src/Database/{Dbm.php => DBM.php} (99%) rename src/Protocol/{Dfrn.php => DFRN.php} (98%) diff --git a/boot.php b/boot.php index 89a30ce1e3..902454382a 100644 --- a/boot.php +++ b/boot.php @@ -24,6 +24,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\PConfig; +use Friendica\Database\DBM; use Friendica\Util\Lock; require_once 'include/network.php'; @@ -768,7 +769,7 @@ function run_update_function($x) { function check_plugins(App $a) { $r = q("SELECT * FROM `addon` WHERE `installed` = 1"); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $installed = $r; } else { $installed = array(); @@ -1054,7 +1055,7 @@ function current_theme() { $r = q("select theme from user where uid = %d limit 1", intval($a->profile_uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $page_theme = $r[0]['theme']; } } @@ -1176,7 +1177,7 @@ function feed_birthday($uid, $tz) { intval($uid) ); - if (dbm::is_result($p)) { + if (DBM::is_result($p)) { $tmp_dob = substr($p[0]['dob'], 5); if (intval($tmp_dob)) { $y = datetime_convert($tz, $tz, 'now', 'Y'); diff --git a/doc/Developer-How-To-Move-Classes-to-src.md b/doc/Developer-How-To-Move-Classes-to-src.md index 25eb393721..90f99ec380 100644 --- a/doc/Developer-How-To-Move-Classes-to-src.md +++ b/doc/Developer-How-To-Move-Classes-to-src.md @@ -73,7 +73,7 @@ If there are only a handful of references to a single non-namespaced class, just ````php namespace Friendica\Core; ... -if (\dbm::is_result($r)) { +if (\DBM::is_result($r)) { ... } ```` @@ -82,7 +82,7 @@ namespace Friendica\Core; use \dbm; -if (dbm::is_result($r)) { +if (DBM::is_result($r)) { ... } ```` diff --git a/doc/autoloader.md b/doc/autoloader.md index 1a3b9a55b1..e9ceb1aaf5 100644 --- a/doc/autoloader.md +++ b/doc/autoloader.md @@ -104,7 +104,7 @@ class Dfrn { mail_post($a){ ... - Friendica\dfrn::mail($item, $owner); + Friendica\DFRN::mail($item, $owner); ... } ``` @@ -125,12 +125,12 @@ switch($contact['network']) { case NETWORK_DFRN: if ($mail) { $item['body'] = ... - $atom = Dfrn::mail($item, $owner); + $atom = DFRN::mail($item, $owner); } elseif ($fsuggest) { - $atom = Dfrn::fsuggest($item, $owner); + $atom = DFRN::fsuggest($item, $owner); q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item['id'])); } elseif ($relocate) - $atom = Dfrn::relocate($owner, $uid); + $atom = DFRN::relocate($owner, $uid); [...] ``` diff --git a/include/Contact.php b/include/Contact.php index c75de6afc8..cd77bb3bb9 100644 --- a/include/Contact.php +++ b/include/Contact.php @@ -4,9 +4,10 @@ use Friendica\App; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; use Friendica\Network\Probe; use Friendica\Protocol\Diaspora; -use Friendica\Protocol\Dfrn; +use Friendica\Protocol\DFRN; // Included here for completeness, but this is a very dangerous operation. // It is the caller's responsibility to confirm the requestor's intent and @@ -49,7 +50,7 @@ function contact_remove($id) { $r = q("SELECT `uid` FROM `contact` WHERE `id` = %d AND NOT `self` LIMIT 1", intval($id) ); - if (!dbm::is_result($r) || !intval($r[0]['uid'])) { + if (!DBM::is_result($r) || !intval($r[0]['uid'])) { return; } @@ -94,7 +95,7 @@ function terminate_friendship($user,$self,$contact) { } elseif ($contact['network'] === NETWORK_DIASPORA) { Diaspora::send_unshare($user,$contact); } elseif ($contact['network'] === NETWORK_DFRN) { - Dfrn::deliver($user,$contact,'placeholder', 1); + DFRN::deliver($user,$contact,'placeholder', 1); } } @@ -163,7 +164,7 @@ function unmark_for_death($contact) { ); // We don't need to update, we never marked this contact as dead - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -213,7 +214,7 @@ function get_contact_details_by_url($url, $uid = -1, $default = array()) { $r = dba::inArray($s); // Fetch contact data from the contact table for the given user, checking with the alias - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $s = dba::p("SELECT `id`, `id` AS `cid`, 0 AS `gid`, 0 AS `zid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, `self` FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = ?", @@ -222,7 +223,7 @@ function get_contact_details_by_url($url, $uid = -1, $default = array()) { } // Fetch the data from the contact table with "uid=0" (which is filled automatically) - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $s = dba::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` FROM `contact` WHERE `nurl` = ? AND `uid` = 0", @@ -231,7 +232,7 @@ function get_contact_details_by_url($url, $uid = -1, $default = array()) { } // Fetch the data from the contact table with "uid=0" (which is filled automatically) - checked with the alias - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $s = dba::p("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = 0", @@ -240,7 +241,7 @@ function get_contact_details_by_url($url, $uid = -1, $default = array()) { } // Fetch the data from the gcontact table - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $s = dba::p("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self` FROM `gcontact` WHERE `nurl` = ?", @@ -248,7 +249,7 @@ function get_contact_details_by_url($url, $uid = -1, $default = array()) { $r = dba::inArray($s); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { // If there is more than one entry we filter out the connector networks if (count($r) > 1) { foreach ($r AS $id => $result) { @@ -351,20 +352,20 @@ function get_contact_details_by_addr($addr, $uid = -1) { dbesc($addr), intval($uid)); // Fetch the data from the contact table with "uid=0" (which is filled automatically) - if (!dbm::is_result($r)) + if (!DBM::is_result($r)) $r = q("SELECT `id`, 0 AS `cid`, `id` AS `zid`, 0 AS `gid`, `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, `xmpp`, `keywords`, `gender`, `photo`, `thumb`, `micro`, `forum`, `prv`, (`forum` | `prv`) AS `community`, `contact-type`, `bd` AS `birthday`, 0 AS `self` FROM `contact` WHERE `addr` = '%s' AND `uid` = 0", dbesc($addr)); // Fetch the data from the gcontact table - if (!dbm::is_result($r)) + if (!DBM::is_result($r)) $r = q("SELECT 0 AS `id`, 0 AS `cid`, `id` AS `gid`, 0 AS `zid`, 0 AS `uid`, `url`, `nurl`, `alias`, `network`, `name`, `nick`, `addr`, `location`, `about`, '' AS `xmpp`, `keywords`, `gender`, `photo`, `photo` AS `thumb`, `photo` AS `micro`, `community` AS `forum`, 0 AS `prv`, `community`, `contact-type`, `birthday`, 0 AS `self` FROM `gcontact` WHERE `addr` = '%s'", dbesc($addr)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $data = Probe::uri($addr); $profile = get_contact_details_by_url($data['url'], $uid); @@ -486,7 +487,7 @@ function random_profile() { ORDER BY rand() LIMIT 1", dbesc(NETWORK_DFRN)); - if (dbm::is_result($r)) + if (DBM::is_result($r)) return dirname($r[0]['url']); return ''; } @@ -553,12 +554,12 @@ function get_contact($url, $uid = 0, $no_update = false) { $contact = dba::select('contact', array('id', 'avatar-date'), array('nurl' => normalise_link($url), 'uid' => $uid), array('limit' => 1)); // Then the addr (nick@server.tld) - if (!dbm::is_result($contact)) { + if (!DBM::is_result($contact)) { $contact = dba::select('contact', array('id', 'avatar-date'), array('addr' => $url, 'uid' => $uid), array('limit' => 1)); } // Then the alias (which could be anything) - if (!dbm::is_result($contact)) { + if (!DBM::is_result($contact)) { // The link could be provided as http although we stored it as https $ssl_url = str_replace('http://', 'https://', $url); $r = dba::p("SELECT `id`, `avatar-date` FROM `contact` WHERE `alias` IN (?, ?, ?) AND `uid` = ? LIMIT 1", @@ -567,7 +568,7 @@ function get_contact($url, $uid = 0, $no_update = false) { dba::close($r); } - if (dbm::is_result($contact)) { + if (DBM::is_result($contact)) { $contact_id = $contact["id"]; // Update the contact every 7 days @@ -597,7 +598,7 @@ function get_contact($url, $uid = 0, $no_update = false) { // Get data from the gcontact table $gcontacts = dba::select('gcontact', array('name', 'nick', 'url', 'photo', 'addr', 'alias', 'network'), array('nurl' => normalise_link($url)), array('limit' => 1)); - if (!dbm::is_result($gcontacts)) { + if (!DBM::is_result($gcontacts)) { return 0; } @@ -626,7 +627,7 @@ function get_contact($url, $uid = 0, $no_update = false) { $contacts = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d ORDER BY `id` LIMIT 2", dbesc(normalise_link($data["url"])), intval($uid)); - if (!dbm::is_result($contacts)) { + if (!DBM::is_result($contacts)) { return 0; } @@ -635,7 +636,7 @@ function get_contact($url, $uid = 0, $no_update = false) { // Update the newly created contact from data in the gcontact table $gcontact = dba::select('gcontact', array('location', 'about', 'keywords', 'gender'), array('nurl' => normalise_link($data["url"])), array('limit' => 1)); - if (dbm::is_result($gcontact)) { + if (DBM::is_result($gcontact)) { // Only use the information when the probing hadn't fetched these values if ($data['keywords'] != '') { unset($gcontact['keywords']); @@ -663,7 +664,7 @@ function get_contact($url, $uid = 0, $no_update = false) { array('id' => $contact_id), array('limit' => 1)); // This condition should always be true - if (!dbm::is_result($contact)) { + if (!DBM::is_result($contact)) { return $contact_id; } @@ -711,7 +712,7 @@ function blockedContact($cid) { } $blocked = dba::select('contact', array('blocked'), array('id' => $cid), array('limit' => 1)); - if (!dbm::is_result($blocked)) { + if (!DBM::is_result($blocked)) { return false; } return (bool)$blocked['blocked']; @@ -730,7 +731,7 @@ function hiddenContact($cid) { } $hidden = dba::select('contact', array('hidden'), array('id' => $cid), array('limit' => 1)); - if (!dbm::is_result($hidden)) { + if (!DBM::is_result($hidden)) { return false; } return (bool)$hidden['hidden']; @@ -793,7 +794,7 @@ function posts_from_contact_url(App $a, $contact_url) { WHERE `contact`.`nurl` = '%s' AND `contact`.`uid` = 0", dbesc(normalise_link($contact_url))); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return ''; } diff --git a/include/ForumManager.php b/include/ForumManager.php index 8473035aff..039b4f5d24 100644 --- a/include/ForumManager.php +++ b/include/ForumManager.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; /** * @file include/ForumManager.php @@ -93,7 +94,7 @@ class ForumManager { $total = count($contacts); $visible_forums = 10; - if (dbm::is_result($contacts)) { + if (DBM::is_result($contacts)) { $id = 0; diff --git a/include/NotificationsManager.php b/include/NotificationsManager.php deleted file mode 100644 index 5f9419e836..0000000000 --- a/include/NotificationsManager.php +++ /dev/null @@ -1,866 +0,0 @@ -a = get_app(); - } - - /** - * @brief set some extra note properties - * - * @param array $notes array of note arrays from db - * @return array Copy of input array with added properties - * - * Set some extra properties to note array from db: - * - timestamp as int in default TZ - * - date_rel : relative date string - * - msg_html: message as html string - * - msg_plain: message as plain text string - */ - private function _set_extra($notes) { - $rets = array(); - foreach($notes as $n) { - $local_time = datetime_convert('UTC',date_default_timezone_get(),$n['date']); - $n['timestamp'] = strtotime($local_time); - $n['date_rel'] = relative_date($n['date']); - $n['msg_html'] = bbcode($n['msg'], false, false, false, false); - $n['msg_plain'] = explode("\n",trim(html2plain($n['msg_html'], 0)))[0]; - - $rets[] = $n; - } - return $rets; - } - - - /** - * @brief Get all notifications for local_user() - * - * @param array $filter optional Array "column name"=>value: filter query by columns values - * @param string $order optional Space separated list of column to sort by. prepend name with "+" to sort ASC, "-" to sort DESC. Default to "-date" - * @param string $limit optional Query limits - * - * @return array of results or false on errors - */ - public function getAll($filter = array(), $order="-date", $limit="") { - $filter_str = array(); - $filter_sql = ""; - foreach($filter as $column => $value) { - $filter_str[] = sprintf("`%s` = '%s'", $column, dbesc($value)); - } - if (count($filter_str)>0) { - $filter_sql = "AND ".implode(" AND ", $filter_str); - } - - $aOrder = explode(" ", $order); - $asOrder = array(); - foreach($aOrder as $o) { - $dir = "asc"; - if ($o[0]==="-") { - $dir = "desc"; - $o = substr($o,1); - } - if ($o[0]==="+") { - $dir = "asc"; - $o = substr($o,1); - } - $asOrder[] = "$o $dir"; - } - $order_sql = implode(", ", $asOrder); - - if($limit!="") - $limit = " LIMIT ".$limit; - - $r = q("SELECT * FROM `notify` WHERE `uid` = %d $filter_sql ORDER BY $order_sql $limit", - intval(local_user()) - ); - - if (dbm::is_result($r)) - return $this->_set_extra($r); - - return false; - } - - /** - * @brief Get one note for local_user() by $id value - * - * @param int $id - * @return array note values or null if not found - */ - public function getByID($id) { - $r = q("SELECT * FROM `notify` WHERE `id` = %d AND `uid` = %d LIMIT 1", - intval($id), - intval(local_user()) - ); - if (dbm::is_result($r)) { - return $this->_set_extra($r)[0]; - } - return null; - } - - /** - * @brief set seen state of $note of local_user() - * - * @param array $note - * @param bool $seen optional true or false, default true - * @return bool true on success, false on errors - */ - public function setSeen($note, $seen = true) { - return q("UPDATE `notify` SET `seen` = %d WHERE ( `link` = '%s' OR ( `parent` != 0 AND `parent` = %d AND `otype` = '%s' )) AND `uid` = %d", - intval($seen), - dbesc($note['link']), - intval($note['parent']), - dbesc($note['otype']), - intval(local_user()) - ); - } - - /** - * @brief set seen state of all notifications of local_user() - * - * @param bool $seen optional true or false. default true - * @return bool true on success, false on error - */ - public function setAllSeen($seen = true) { - return q("UPDATE `notify` SET `seen` = %d WHERE `uid` = %d", - intval($seen), - intval(local_user()) - ); - } - - /** - * @brief List of pages for the Notifications TabBar - * - * @return array with with notifications TabBar data - */ - public function getTabs() { - $tabs = array( - array( - 'label' => t('System'), - 'url'=>'notifications/system', - 'sel'=> (($this->a->argv[1] == 'system') ? 'active' : ''), - 'id' => 'system-tab', - 'accesskey' => 'y', - ), - array( - 'label' => t('Network'), - 'url'=>'notifications/network', - 'sel'=> (($this->a->argv[1] == 'network') ? 'active' : ''), - 'id' => 'network-tab', - 'accesskey' => 'w', - ), - array( - 'label' => t('Personal'), - 'url'=>'notifications/personal', - 'sel'=> (($this->a->argv[1] == 'personal') ? 'active' : ''), - 'id' => 'personal-tab', - 'accesskey' => 'r', - ), - array( - 'label' => t('Home'), - 'url' => 'notifications/home', - 'sel'=> (($this->a->argv[1] == 'home') ? 'active' : ''), - 'id' => 'home-tab', - 'accesskey' => 'h', - ), - array( - 'label' => t('Introductions'), - 'url' => 'notifications/intros', - 'sel'=> (($this->a->argv[1] == 'intros') ? 'active' : ''), - 'id' => 'intro-tab', - 'accesskey' => 'i', - ), - ); - - return $tabs; - } - - /** - * @brief Format the notification query in an usable array - * - * @param array $notifs The array from the db query - * @param string $ident The notifications identifier (e.g. network) - * @return array - * string 'label' => The type of the notification - * string 'link' => URL to the source - * string 'image' => The avatar image - * string 'url' => The profile url of the contact - * string 'text' => The notification text - * string 'when' => The date of the notification - * string 'ago' => T relative date of the notification - * bool 'seen' => Is the notification marked as "seen" - */ - private function formatNotifs($notifs, $ident = "") { - - $notif = array(); - $arr = array(); - - if (dbm::is_result($notifs)) { - - foreach ($notifs as $it) { - // Because we use different db tables for the notification query - // we have sometimes $it['unseen'] and sometimes $it['seen]. - // So we will have to transform $it['unseen'] - if (array_key_exists('unseen', $it)) { - $it['seen'] = ($it['unseen'] > 0 ? false : true); - } - - // Depending on the identifier of the notification we need to use different defaults - switch ($ident) { - case 'system': - $default_item_label = 'notify'; - $default_item_link = System::baseUrl(true).'/notify/view/'. $it['id']; - $default_item_image = proxy_url($it['photo'], false, PROXY_SIZE_MICRO); - $default_item_url = $it['url']; - $default_item_text = strip_tags(bbcode($it['msg'])); - $default_item_when = datetime_convert('UTC', date_default_timezone_get(), $it['date'], 'r'); - $default_item_ago = relative_date($it['date']); - break; - - case 'home': - $default_item_label = 'comment'; - $default_item_link = System::baseUrl(true).'/display/'.$it['pguid']; - $default_item_image = proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO); - $default_item_url = $it['author-link']; - $default_item_text = sprintf(t("%s commented on %s's post"), $it['author-name'], $it['pname']); - $default_item_when = datetime_convert('UTC', date_default_timezone_get(), $it['created'], 'r'); - $default_item_ago = relative_date($it['created']); - break; - - default: - $default_item_label = (($it['id'] == $it['parent']) ? 'post' : 'comment'); - $default_item_link = System::baseUrl(true).'/display/'.$it['pguid']; - $default_item_image = proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO); - $default_item_url = $it['author-link']; - $default_item_text = (($it['id'] == $it['parent']) - ? sprintf(t("%s created a new post"), $it['author-name']) - : sprintf(t("%s commented on %s's post"), $it['author-name'], $it['pname'])); - $default_item_when = datetime_convert('UTC', date_default_timezone_get(), $it['created'], 'r'); - $default_item_ago = relative_date($it['created']); - - } - - // Transform the different types of notification in an usable array - switch ($it['verb']){ - case ACTIVITY_LIKE: - $notif = array( - 'label' => 'like', - 'link' => System::baseUrl(true).'/display/'.$it['pguid'], - 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), - 'url' => $it['author-link'], - 'text' => sprintf(t("%s liked %s's post"), $it['author-name'], $it['pname']), - 'when' => $default_item_when, - 'ago' => $default_item_ago, - 'seen' => $it['seen'] - ); - break; - - case ACTIVITY_DISLIKE: - $notif = array( - 'label' => 'dislike', - 'link' => System::baseUrl(true).'/display/'.$it['pguid'], - 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), - 'url' => $it['author-link'], - 'text' => sprintf(t("%s disliked %s's post"), $it['author-name'], $it['pname']), - 'when' => $default_item_when, - 'ago' => $default_item_ago, - 'seen' => $it['seen'] - ); - break; - - case ACTIVITY_ATTEND: - $notif = array( - 'label' => 'attend', - 'link' => System::baseUrl(true).'/display/'.$it['pguid'], - 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), - 'url' => $it['author-link'], - 'text' => sprintf(t("%s is attending %s's event"), $it['author-name'], $it['pname']), - 'when' => $default_item_when, - 'ago' => $default_item_ago, - 'seen' => $it['seen'] - ); - break; - - case ACTIVITY_ATTENDNO: - $notif = array( - 'label' => 'attendno', - 'link' => System::baseUrl(true).'/display/'.$it['pguid'], - 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), - 'url' => $it['author-link'], - 'text' => sprintf( t("%s is not attending %s's event"), $it['author-name'], $it['pname']), - 'when' => $default_item_when, - 'ago' => $default_item_ago, - 'seen' => $it['seen'] - ); - break; - - case ACTIVITY_ATTENDMAYBE: - $notif = array( - 'label' => 'attendmaybe', - 'link' => System::baseUrl(true).'/display/'.$it['pguid'], - 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), - 'url' => $it['author-link'], - 'text' => sprintf(t("%s may attend %s's event"), $it['author-name'], $it['pname']), - 'when' => $default_item_when, - 'ago' => $default_item_ago, - 'seen' => $it['seen'] - ); - break; - - case ACTIVITY_FRIEND: - $xmlhead="<"."?xml version='1.0' encoding='UTF-8' ?".">"; - $obj = parse_xml_string($xmlhead.$it['object']); - $it['fname'] = $obj->title; - - $notif = array( - 'label' => 'friend', - 'link' => System::baseUrl(true).'/display/'.$it['pguid'], - 'image' => proxy_url($it['author-avatar'], false, PROXY_SIZE_MICRO), - 'url' => $it['author-link'], - 'text' => sprintf(t("%s is now friends with %s"), $it['author-name'], $it['fname']), - 'when' => $default_item_when, - 'ago' => $default_item_ago, - 'seen' => $it['seen'] - ); - break; - - default: - $notif = array( - 'label' => $default_item_label, - 'link' => $default_item_link, - 'image' => $default_item_image, - 'url' => $default_item_url, - 'text' => $default_item_text, - 'when' => $default_item_when, - 'ago' => $default_item_ago, - 'seen' => $it['seen'] - ); - } - - $arr[] = $notif; - } - } - - return $arr; - - } - - /** - * @brief Total number of network notifications - * @param int|string $seen - * If 0 only include notifications into the query - * which aren't marked as "seen" - * @return int Number of network notifications - */ - private function networkTotal($seen = 0) { - $sql_seen = ""; - - if($seen === 0) - $sql_seen = " AND `item`.`unseen` = 1 "; - - $r = q("SELECT COUNT(*) AS `total` - FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent` - WHERE `item`.`visible` = 1 AND `pitem`.`parent` != 0 AND - `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0 - $sql_seen", - intval(local_user()) - ); - - if (dbm::is_result($r)) - return $r[0]['total']; - - return 0; - } - - /** - * @brief Get network notifications - * - * @param int|string $seen - * If 0 only include notifications into the query - * which aren't marked as "seen" - * @param int $start Start the query at this point - * @param int $limit Maximum number of query results - * - * @return array with - * string 'ident' => Notification identifier - * int 'total' => Total number of available network notifications - * array 'notifications' => Network notifications - */ - public function networkNotifs($seen = 0, $start = 0, $limit = 80) { - $ident = 'network'; - $total = $this->networkTotal($seen); - $notifs = array(); - $sql_seen = ""; - - if($seen === 0) - $sql_seen = " AND `item`.`unseen` = 1 "; - - - $r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`, - `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` AS `object`, - `pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`, `pitem`.`guid` AS `pguid` - FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent` - WHERE `item`.`visible` = 1 AND `pitem`.`parent` != 0 AND - `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0 - $sql_seen - ORDER BY `item`.`created` DESC LIMIT %d, %d ", - intval(local_user()), - intval($start), - intval($limit) - ); - - if (dbm::is_result($r)) - $notifs = $this->formatNotifs($r, $ident); - - $arr = array ( - 'notifications' => $notifs, - 'ident' => $ident, - 'total' => $total, - ); - - return $arr; - } - - /** - * @brief Total number of system notifications - * @param int|string $seen - * If 0 only include notifications into the query - * which aren't marked as "seen" - * @return int Number of system notifications - */ - private function systemTotal($seen = 0) { - $sql_seen = ""; - - if($seen === 0) - $sql_seen = " AND `seen` = 0 "; - - $r = q("SELECT COUNT(*) AS `total` FROM `notify` WHERE `uid` = %d $sql_seen", - intval(local_user()) - ); - - if (dbm::is_result($r)) - return $r[0]['total']; - - return 0; - } - - /** - * @brief Get system notifications - * - * @param int|string $seen - * If 0 only include notifications into the query - * which aren't marked as "seen" - * @param int $start Start the query at this point - * @param int $limit Maximum number of query results - * - * @return array with - * string 'ident' => Notification identifier - * int 'total' => Total number of available system notifications - * array 'notifications' => System notifications - */ - public function systemNotifs($seen = 0, $start = 0, $limit = 80) { - $ident = 'system'; - $total = $this->systemTotal($seen); - $notifs = array(); - $sql_seen = ""; - - if($seen === 0) - $sql_seen = " AND `seen` = 0 "; - - $r = q("SELECT `id`, `url`, `photo`, `msg`, `date`, `seen` FROM `notify` - WHERE `uid` = %d $sql_seen ORDER BY `date` DESC LIMIT %d, %d ", - intval(local_user()), - intval($start), - intval($limit) - ); - - if (dbm::is_result($r)) - $notifs = $this->formatNotifs($r, $ident); - - $arr = array ( - 'notifications' => $notifs, - 'ident' => $ident, - 'total' => $total, - ); - - return $arr; - } - - /** - * @brief Addional SQL query string for the personal notifications - * - * @return string The additional sql query - */ - private function _personal_sql_extra() { - $myurl = System::baseUrl(true) . '/profile/'. $this->a->user['nickname']; - $myurl = substr($myurl,strpos($myurl,'://')+3); - $myurl = str_replace(array('www.','.'),array('','\\.'),$myurl); - $diasp_url = str_replace('/profile/','/u/',$myurl); - $sql_extra = sprintf(" AND ( `item`.`author-link` regexp '%s' OR `item`.`tag` regexp '%s' OR `item`.`tag` regexp '%s' ) ", - dbesc($myurl . '$'), - dbesc($myurl . '\\]'), - dbesc($diasp_url . '\\]') - ); - - return $sql_extra; - } - - /** - * @brief Total number of personal notifications - * @param int|string $seen - * If 0 only include notifications into the query - * which aren't marked as "seen" - * @return int Number of personal notifications - */ - private function personalTotal($seen = 0) { - $sql_seen = ""; - $sql_extra = $this->_personal_sql_extra(); - - if($seen === 0) - $sql_seen = " AND `item`.`unseen` = 1 "; - - $r = q("SELECT COUNT(*) AS `total` - FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent` - WHERE `item`.`visible` = 1 - $sql_extra - $sql_seen - AND `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0 " , - intval(local_user()) - ); - - if (dbm::is_result($r)) - return $r[0]['total']; - - return 0; - } - - /** - * @brief Get personal notifications - * - * @param int|string $seen - * If 0 only include notifications into the query - * which aren't marked as "seen" - * @param int $start Start the query at this point - * @param int $limit Maximum number of query results - * - * @return array with - * string 'ident' => Notification identifier - * int 'total' => Total number of available personal notifications - * array 'notifications' => Personal notifications - */ - public function personalNotifs($seen = 0, $start = 0, $limit = 80) { - $ident = 'personal'; - $total = $this->personalTotal($seen); - $sql_extra = $this->_personal_sql_extra(); - $notifs = array(); - $sql_seen = ""; - - if($seen === 0) - $sql_seen = " AND `item`.`unseen` = 1 "; - - $r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`, - `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` AS `object`, - `pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`, `pitem`.`guid` AS `pguid` - FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent` - WHERE `item`.`visible` = 1 - $sql_extra - $sql_seen - AND `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 0 - ORDER BY `item`.`created` DESC LIMIT %d, %d " , - intval(local_user()), - intval($start), - intval($limit) - ); - - if (dbm::is_result($r)) - $notifs = $this->formatNotifs($r, $ident); - - $arr = array ( - 'notifications' => $notifs, - 'ident' => $ident, - 'total' => $total, - ); - - return $arr; - } - - /** - * @brief Total number of home notifications - * @param int|string $seen - * If 0 only include notifications into the query - * which aren't marked as "seen" - * @return int Number of home notifications - */ - private function homeTotal($seen = 0) { - $sql_seen = ""; - - if($seen === 0) - $sql_seen = " AND `item`.`unseen` = 1 "; - - $r = q("SELECT COUNT(*) AS `total` FROM `item` - WHERE `item`.`visible` = 1 AND - `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 1 - $sql_seen", - intval(local_user()) - ); - - if (dbm::is_result($r)) - return $r[0]['total']; - - return 0; - } - - /** - * @brief Get home notifications - * - * @param int|string $seen - * If 0 only include notifications into the query - * which aren't marked as "seen" - * @param int $start Start the query at this point - * @param int $limit Maximum number of query results - * - * @return array with - * string 'ident' => Notification identifier - * int 'total' => Total number of available home notifications - * array 'notifications' => Home notifications - */ - public function homeNotifs($seen = 0, $start = 0, $limit = 80) { - $ident = 'home'; - $total = $this->homeTotal($seen); - $notifs = array(); - $sql_seen = ""; - - if($seen === 0) - $sql_seen = " AND `item`.`unseen` = 1 "; - - $r = q("SELECT `item`.`id`,`item`.`parent`, `item`.`verb`, `item`.`author-name`, `item`.`unseen`, - `item`.`author-link`, `item`.`author-avatar`, `item`.`created`, `item`.`object` AS `object`, - `pitem`.`author-name` AS `pname`, `pitem`.`author-link` AS `plink`, `pitem`.`guid` AS `pguid` - FROM `item` INNER JOIN `item` AS `pitem` ON `pitem`.`id`=`item`.`parent` - WHERE `item`.`visible` = 1 AND - `item`.`deleted` = 0 AND `item`.`uid` = %d AND `item`.`wall` = 1 - $sql_seen - ORDER BY `item`.`created` DESC LIMIT %d, %d ", - intval(local_user()), - intval($start), - intval($limit) - ); - - if (dbm::is_result($r)) - $notifs = $this->formatNotifs($r, $ident); - - $arr = array ( - 'notifications' => $notifs, - 'ident' => $ident, - 'total' => $total, - ); - - return $arr; - } - - /** - * @brief Total number of introductions - * @param bool $all - * If false only include introductions into the query - * which aren't marked as ignored - * @return int Number of introductions - */ - private function introTotal($all = false) { - $sql_extra = ""; - - if(!$all) - $sql_extra = " AND `ignore` = 0 "; - - $r = q("SELECT COUNT(*) AS `total` FROM `intro` - WHERE `intro`.`uid` = %d $sql_extra AND `intro`.`blocked` = 0 ", - intval($_SESSION['uid']) - ); - - if (dbm::is_result($r)) - return $r[0]['total']; - - return 0; - } - - /** - * @brief Get introductions - * - * @param bool $all - * If false only include introductions into the query - * which aren't marked as ignored - * @param int $start Start the query at this point - * @param int $limit Maximum number of query results - * - * @return array with - * string 'ident' => Notification identifier - * int 'total' => Total number of available introductions - * array 'notifications' => Introductions - */ - public function introNotifs($all = false, $start = 0, $limit = 80) { - $ident = 'introductions'; - $total = $this->introTotal($seen); - $notifs = array(); - $sql_extra = ""; - - if(!$all) - $sql_extra = " AND `ignore` = 0 "; - - /// @todo Fetch contact details by "get_contact_details_by_url" instead of queries to contact, fcontact and gcontact - $r = q("SELECT `intro`.`id` AS `intro_id`, `intro`.*, `contact`.*, - `fcontact`.`name` AS `fname`, `fcontact`.`url` AS `furl`, - `fcontact`.`photo` AS `fphoto`, `fcontact`.`request` AS `frequest`, - `gcontact`.`location` AS `glocation`, `gcontact`.`about` AS `gabout`, - `gcontact`.`keywords` AS `gkeywords`, `gcontact`.`gender` AS `ggender`, - `gcontact`.`network` AS `gnetwork`, `gcontact`.`addr` AS `gaddr` - FROM `intro` - LEFT JOIN `contact` ON `contact`.`id` = `intro`.`contact-id` - LEFT JOIN `gcontact` ON `gcontact`.`nurl` = `contact`.`nurl` - LEFT JOIN `fcontact` ON `intro`.`fid` = `fcontact`.`id` - WHERE `intro`.`uid` = %d $sql_extra AND `intro`.`blocked` = 0 - LIMIT %d, %d", - intval($_SESSION['uid']), - intval($start), - intval($limit) - ); - - if (dbm::is_result($r)) - $notifs = $this->formatIntros($r); - - $arr = array ( - 'ident' => $ident, - 'total' => $total, - 'notifications' => $notifs, - ); - - return $arr; - } - - /** - * @brief Format the notification query in an usable array - * - * @param array $intros The array from the db query - * @return array with the introductions - */ - private function formatIntros($intros) { - $knowyou = ''; - - foreach($intros as $it) { - // There are two kind of introduction. Contacts suggested by other contacts and normal connection requests. - // We have to distinguish between these two because they use different data. - - // Contact suggestions - if($it['fid']) { - - $return_addr = bin2hex($this->a->user['nickname'] . '@' . $this->a->get_hostname() . (($this->a->path) ? '/' . $this->a->path : '')); - - $intro = array( - 'label' => 'friend_suggestion', - 'notify_type' => t('Friend Suggestion'), - 'intro_id' => $it['intro_id'], - 'madeby' => $it['name'], - 'contact_id' => $it['contact-id'], - 'photo' => ((x($it,'fphoto')) ? proxy_url($it['fphoto'], false, PROXY_SIZE_SMALL) : "images/person-175.jpg"), - 'name' => $it['fname'], - 'url' => zrl($it['furl']), - 'hidden' => $it['hidden'] == 1, - 'post_newfriend' => (intval(PConfig::get(local_user(),'system','post_newfriend')) ? '1' : 0), - - 'knowyou' => $knowyou, - 'note' => $it['note'], - 'request' => $it['frequest'] . '?addr=' . $return_addr, - - ); - - // Normal connection requests - } else { - - $it = $this->getMissingIntroData($it); - - // Don't show these data until you are connected. Diaspora is doing the same. - if($it['gnetwork'] === NETWORK_DIASPORA) { - $it['glocation'] = ""; - $it['gabout'] = ""; - $it['ggender'] = ""; - } - $intro = array( - 'label' => (($it['network'] !== NETWORK_OSTATUS) ? 'friend_request' : 'follower'), - 'notify_type' => (($it['network'] !== NETWORK_OSTATUS) ? t('Friend/Connect Request') : t('New Follower')), - 'dfrn_id' => $it['issued-id'], - 'uid' => $_SESSION['uid'], - 'intro_id' => $it['intro_id'], - 'contact_id' => $it['contact-id'], - 'photo' => ((x($it,'photo')) ? proxy_url($it['photo'], false, PROXY_SIZE_SMALL) : "images/person-175.jpg"), - 'name' => $it['name'], - 'location' => bbcode($it['glocation'], false, false), - 'about' => bbcode($it['gabout'], false, false), - 'keywords' => $it['gkeywords'], - 'gender' => $it['ggender'], - 'hidden' => $it['hidden'] == 1, - 'post_newfriend' => (intval(PConfig::get(local_user(),'system','post_newfriend')) ? '1' : 0), - 'url' => $it['url'], - 'zrl' => zrl($it['url']), - 'addr' => $it['gaddr'], - 'network' => $it['gnetwork'], - 'knowyou' => $it['knowyou'], - 'note' => $it['note'], - ); - } - - $arr[] = $intro; - } - - return $arr; - } - - /** - * @brief Check for missing contact data and try to fetch the data from - * from other sources - * - * @param array $arr The input array with the intro data - * - * @return array The array with the intro data - */ - private function getMissingIntroData($arr) { - // If the network and the addr isn't available from the gcontact - // table entry, take the one of the contact table entry - if ($arr['gnetwork'] == "") { - $arr['gnetwork'] = $arr['network']; - } - if ($arr['gaddr'] == "") { - $arr['gaddr'] = $arr['addr']; - } - - // If the network and addr is still not available - // get the missing data data from other sources - if ($arr['gnetwork'] == "" || $arr['gaddr'] == "") { - $ret = get_contact_details_by_url($arr['url']); - - if ($arr['gnetwork'] == "" && $ret['network'] != "") { - $arr['gnetwork'] = $ret['network']; - } - if ($arr['gaddr'] == "" && $ret['addr'] != "") { - $arr['gaddr'] = $ret['addr']; - } - } - - return $arr; - } -} diff --git a/include/Photo.php b/include/Photo.php index 9b9e02142b..1ed90bbf83 100644 --- a/include/Photo.php +++ b/include/Photo.php @@ -7,6 +7,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; +use Friendica\Database\DBM; require_once("include/photos.php"); @@ -630,7 +631,7 @@ class Photo { public function store($uid, $cid, $rid, $filename, $album, $scale, $profile = 0, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '', $desc = '') { $r = dba::select('photo', array('guid'), array("`resource-id` = ? AND `guid` != ?", $rid, ''), array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $guid = $r['guid']; } else { $guid = get_guid(); @@ -643,7 +644,7 @@ class Photo { 'datasize' => strlen($this->imageString()), 'data' => $this->imageString(), 'scale' => $scale, 'profile' => $profile, 'allow_cid' => $allow_cid, 'allow_gid' => $allow_gid, 'deny_cid' => $deny_cid, 'deny_gid' => $deny_gid, 'desc' => $desc); - if (dbm::is_result($x)) { + if (DBM::is_result($x)) { $r = dba::update('photo', $fields, array('id' => $x['id'])); } else { $r = dba::insert('photo', $fields); @@ -713,7 +714,7 @@ function guess_image_type($filename, $fromcurl=false) { */ function update_contact_avatar($avatar, $uid, $cid, $force = false) { $r = q("SELECT `avatar`, `photo`, `thumb`, `micro`, `nurl` FROM `contact` WHERE `id` = %d LIMIT 1", intval($cid)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return false; } else { $data = array($r[0]["photo"], $r[0]["thumb"], $r[0]["micro"]); @@ -730,7 +731,7 @@ function update_contact_avatar($avatar, $uid, $cid, $force = false) { // Update the public contact (contact id = 0) if ($uid != 0) { $pcontact = dba::select('contact', array('id'), array('nurl' => $r[0]['nurl']), array('limit' => 1)); - if (dbm::is_result($pcontact)) { + if (DBM::is_result($pcontact)) { update_contact_avatar($avatar, 0, $pcontact['id'], $force); } } @@ -748,7 +749,7 @@ function import_profile_photo($photo, $uid, $cid, $quit_on_error = false) { intval($uid), intval($cid) ); - if (dbm::is_result($r) && strlen($r[0]['resource-id'])) { + if (DBM::is_result($r) && strlen($r[0]['resource-id'])) { $hash = $r[0]['resource-id']; } else { $hash = photo_new_resource(); @@ -919,7 +920,7 @@ function store_photo(App $a, $uid, $imagedata = "", $url = "") { WHERE `user`.`uid` = %d AND `user`.`blocked` = 0 AND `contact`.`self` = 1 LIMIT 1", intval($uid)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { logger("Can't detect user data for uid ".$uid, LOGGER_DEBUG); return(array()); } diff --git a/include/acl_selectors.php b/include/acl_selectors.php index a5bb1a9cd0..956c2a9f6d 100644 --- a/include/acl_selectors.php +++ b/include/acl_selectors.php @@ -6,6 +6,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Database\DBM; require_once "include/contact_selectors.php"; require_once "include/contact_widgets.php"; @@ -36,7 +37,7 @@ function group_select($selname,$selclass,$preselected = false,$size = 4) { call_hooks($a->module . '_pre_' . $selname, $arr); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { if ((is_array($preselected)) && in_array($rr['id'], $preselected)) { $selected = " selected=\"selected\" "; @@ -159,7 +160,7 @@ function contact_selector($selname, $selclass, $preselected = false, $options) { call_hooks($a->module . '_pre_' . $selname, $arr); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { if ((is_array($preselected)) && in_array($rr['id'], $preselected)) { $selected = " selected=\"selected\" "; @@ -239,7 +240,7 @@ function contact_select($selname, $selclass, $preselected = false, $size = 4, $p $receiverlist = array(); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { if ((is_array($preselected)) && in_array($rr['id'], $preselected)) { $selected = " selected=\"selected\" "; @@ -286,7 +287,7 @@ function prune_deadguys($arr) { $r = q("SELECT `id` FROM `contact` WHERE `id` IN ( " . $str . ") AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 "); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $ret = array(); foreach ($r as $rr) { $ret[] = intval($rr['id']); @@ -342,7 +343,7 @@ function populate_acl($user = null, $show_jotnets = false) { $r = q("SELECT `pubmail` FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $mail_enabled = true; if (intval($r[0]['pubmail'])) { $pubmail_enabled = true; @@ -635,7 +636,7 @@ function acl_lookup(App $a, $out_type = 'json') { } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $forums = array(); foreach ($r as $g) { $entry = array( @@ -689,7 +690,7 @@ function acl_lookup(App $a, $out_type = 'json') { dbesc($search), implode("', '", $known_contacts) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $row) { $contact = get_contact_details_by_url($row['author-link']); diff --git a/include/api.php b/include/api.php index 09ce9d6b26..c304538af7 100644 --- a/include/api.php +++ b/include/api.php @@ -11,6 +11,7 @@ use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\NotificationsManager; use Friendica\Core\Worker; +use Friendica\Database\DBM; require_once 'include/HTTPExceptions.php'; require_once 'include/bbcode.php'; @@ -211,7 +212,7 @@ $called_api = null; dbesc(trim($user)), dbesc($encrypted) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $record = $r[0]; } } @@ -460,7 +461,7 @@ $called_api = null; function api_unique_id_to_url($id) { $r = dba::select('contact', array('url'), array('uid' => 0, 'id' => $id), array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { return $r["url"]; } else { return false; @@ -591,14 +592,14 @@ $called_api = null; api_best_nickname($uinfo); // if the contact wasn't found, fetch it from the contacts with uid = 0 - if (!dbm::is_result($uinfo)) { + if (!DBM::is_result($uinfo)) { $r = array(); if ($url != "") { $r = q("SELECT * FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s' LIMIT 1", dbesc(normalise_link($url))); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $network_name = network_to_name($r[0]['network'], $r[0]['url']); // If no nick where given, extract it from the address @@ -1092,7 +1093,7 @@ $called_api = null; AND `created` > '%s' AND `id` = `parent`", intval(api_user()), dbesc($datefrom)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $posts_day = $r[0]["posts_day"]; } else { $posts_day = 0; @@ -1113,7 +1114,7 @@ $called_api = null; AND `created` > '%s' AND `id` = `parent`", intval(api_user()), dbesc($datefrom)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $posts_week = $r[0]["posts_week"]; } else { $posts_week = 0; @@ -1134,7 +1135,7 @@ $called_api = null; AND `created` > '%s' AND `id` = `parent`", intval(api_user()), dbesc($datefrom)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $posts_month = $r[0]["posts_month"]; } else { $posts_month = 0; @@ -1163,7 +1164,7 @@ $called_api = null; if (requestdata('media_ids')) { $r = q("SELECT `resource-id`, `scale`, `nickname`, `type` FROM `photo` INNER JOIN `user` ON `user`.`uid` = `photo`.`uid` WHERE `resource-id` IN (SELECT `resource-id` FROM `photo` WHERE `id` = %d) AND `scale` > 0 AND `photo`.`uid` = %d ORDER BY `photo`.`width` DESC LIMIT 1", intval(requestdata('media_ids')), api_user()); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $phototypes = Photo::supportedTypes(); $ext = $phototypes[$r[0]['type']]; $_REQUEST['body'] .= "\n\n" . '[url=' . System::baseUrl() . '/photos/' . $r[0]['nickname'] . '/image/' . $r[0]['resource-id'] . ']'; @@ -1258,7 +1259,7 @@ $called_api = null; dbesc(normalise_link($user_info['url'])) ); - if (dbm::is_result($lastwall)) { + if (DBM::is_result($lastwall)) { $lastwall = $lastwall[0]; $in_reply_to = api_in_reply_to($lastwall); @@ -1356,7 +1357,7 @@ $called_api = null; dbesc(normalise_link($user_info['url'])) ); - if (dbm::is_result($lastwall)) { + if (DBM::is_result($lastwall)) { $lastwall = $lastwall[0]; $in_reply_to = api_in_reply_to($lastwall); @@ -1428,11 +1429,11 @@ $called_api = null; if (x($_GET, 'q')) { $r = q("SELECT id FROM `contact` WHERE `uid` = 0 AND `name` = '%s'", dbesc($_GET["q"])); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = q("SELECT `id` FROM `contact` WHERE `uid` = 0 AND `nick` = '%s'", dbesc($_GET["q"])); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $k = 0; foreach ($r AS $user) { $user_info = api_get_user($a, $user["id"], "json"); @@ -1681,7 +1682,7 @@ $called_api = null; ); /// @TODO How about copying this to above methods which don't check $r ? - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { throw new BadRequestException("There is no status with this id."); } @@ -1736,7 +1737,7 @@ $called_api = null; logger('API: api_conversation_show: '.$id); $r = q("SELECT `parent` FROM `item` WHERE `id` = %d", intval($id)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $id = $r[0]["parent"]; } @@ -1769,7 +1770,7 @@ $called_api = null; intval($start), intval($count) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { throw new BadRequestException("There is no status with this id."); } @@ -1827,7 +1828,7 @@ $called_api = null; ); /// @TODO other style than above functions! - if (dbm::is_result($r) && $r[0]['body'] != "") { + if (DBM::is_result($r) && $r[0]['body'] != "") { if (strpos($r[0]['body'], "[/share]") !== false) { $pos = strpos($r[0]['body'], "[share"); $post = substr($r[0]['body'], $pos); @@ -2093,7 +2094,7 @@ $called_api = null; $item = q("SELECT * FROM `item` WHERE `id`=%d AND `uid`=%d LIMIT 1", $itemid, api_user()); - if (!dbm::is_result($item) || count($item) == 0) { + if (!DBM::is_result($item) || count($item) == 0) { throw new BadRequestException("Invalid item."); } @@ -3004,7 +3005,7 @@ $called_api = null; intval(api_user()) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -3138,7 +3139,7 @@ $called_api = null; intval($id)); // error message if specified id is not in database - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { if ($verbose == "true") { $answer = array('result' => 'error', 'message' => 'message id not in database'); return api_format_data("direct_messages_delete", $type, array('$result' => $answer)); @@ -3229,7 +3230,7 @@ $called_api = null; intval($since_id), intval($start), intval($count) ); - if ($verbose == "true" && !dbm::is_result($r)) { + if ($verbose == "true" && !DBM::is_result($r)) { $answer = array('result' => 'error', 'message' => 'no mails available'); return api_format_data("direct_messages_all", $type, array('$result' => $answer)); } @@ -3334,7 +3335,7 @@ $called_api = null; $r = q("SELECT DISTINCT `resource-id` FROM `photo` WHERE `uid` = %d AND `album` = '%s'", intval(api_user()), dbesc($album)); - if (!dbm::is_result($r)) + if (!DBM::is_result($r)) throw new BadRequestException("album not available"); // function for setting the items to "deleted = 1" which ensures that comments, likes etc. are not shown anymore @@ -3345,7 +3346,7 @@ $called_api = null; dbesc($rr['resource-id']) ); - if (!dbm::is_result($photo_item)) { + if (!DBM::is_result($photo_item)) { throw new InternalServerErrorException("problem with deleting items occured"); } drop_item($photo_item[0]['id'],false); @@ -3391,7 +3392,7 @@ $called_api = null; $r = q("SELECT `id` FROM `photo` WHERE `uid` = %d AND `album` = '%s'", intval(api_user()), dbesc($album)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { throw new BadRequestException("album not available"); } // now let's update all photos to the albumname @@ -3431,7 +3432,7 @@ $called_api = null; 'image/gif' => 'gif' ); $data = array('photo'=>array()); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $photo = array(); $photo['id'] = $rr['resource-id']; @@ -3500,7 +3501,7 @@ $called_api = null; intval(api_user()), dbesc($photo_id), dbesc($album)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { throw new BadRequestException("photo not available"); } } @@ -3620,7 +3621,7 @@ $called_api = null; intval(api_user()), dbesc($photo_id) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { throw new BadRequestException("photo not available"); } // now we can perform on the deletion of the photo @@ -3636,7 +3637,7 @@ $called_api = null; dbesc($photo_id) ); - if (!dbm::is_result($photo_item)) { + if (!DBM::is_result($photo_item)) { throw new InternalServerErrorException("problem with deleting items occured"); } // function for setting the items to "deleted = 1" which ensures that comments, likes etc. are not shown anymore @@ -3699,7 +3700,7 @@ $called_api = null; intval(api_user()), intval($profileid)); // error message if specified profile id is not in database - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { throw new BadRequestException("profile_id not available"); } $is_default_profile = $r['profile']; @@ -3804,7 +3805,7 @@ $called_api = null; $contact = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d", intval($cid), intval(api_user())); - $contact_not_found |= !dbm::is_result($contact); + $contact_not_found |= !DBM::is_result($contact); } return $contact_not_found; } @@ -4020,7 +4021,7 @@ $called_api = null; ); // prepare output data for photo - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $data = array('photo' => $r[0]); $data['photo']['id'] = $data['photo']['resource-id']; if ($scale !== false) { @@ -4129,7 +4130,7 @@ $called_api = null; intval(api_user()) ); - if ((! dbm::is_result($r)) || ($r[0]['network'] !== NETWORK_DFRN)) { + if ((! DBM::is_result($r)) || ($r[0]['network'] !== NETWORK_DFRN)) { throw new BadRequestException("Unknown contact"); } @@ -4276,7 +4277,7 @@ $called_api = null; $r = q("SELECT `nick` FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s'", dbesc(normalise_link($profile))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $nick = $r[0]["nick"]; } @@ -4284,7 +4285,7 @@ $called_api = null; $r = q("SELECT `nick` FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s'", dbesc(normalise_link($profile))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $nick = $r[0]["nick"]; } } @@ -4355,7 +4356,7 @@ $called_api = null; intval($item['uid']), dbesc($item['thr-parent'])); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $in_reply_to['status_id'] = intval($r[0]['id']); } else { $in_reply_to['status_id'] = intval($item['parent']); @@ -4369,7 +4370,7 @@ $called_api = null; intval($in_reply_to['status_id']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if ($r[0]['nick'] == "") { $r[0]['nick'] = api_get_nick($r[0]["url"]); } @@ -4503,7 +4504,7 @@ $called_api = null; intval($uid), intval($gid)); // error message if specified gid is not in database - if (!dbm::is_result($r)) + if (!DBM::is_result($r)) throw new BadRequestException("gid not available"); } else @@ -4558,7 +4559,7 @@ $called_api = null; intval($uid), intval($gid)); // error message if specified gid is not in database - if (!dbm::is_result($r)) + if (!DBM::is_result($r)) throw new BadRequestException('gid not available'); // get data of the specified group id and group name @@ -4567,7 +4568,7 @@ $called_api = null; intval($gid), dbesc($name)); // error message if specified gid is not in database - if (!dbm::is_result($rname)) + if (!DBM::is_result($rname)) throw new BadRequestException('wrong group name'); // delete group @@ -4606,7 +4607,7 @@ $called_api = null; intval($uid), dbesc($name)); // error message if specified group name already exists - if (dbm::is_result($rname)) + if (DBM::is_result($rname)) throw new BadRequestException('group name already exists'); // check if specified group name is a deleted group @@ -4614,7 +4615,7 @@ $called_api = null; intval($uid), dbesc($name)); // error message if specified group name already exists - if (dbm::is_result($rname)) + if (DBM::is_result($rname)) $reactivate_group = true; // create group @@ -4845,7 +4846,7 @@ $called_api = null; intval($uid)); // error message if specified id is not in database - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $answer = array('result' => 'error', 'message' => 'message id not in database'); return api_format_data("direct_messages_setseen", $type, array('$result' => $answer)); } @@ -4903,7 +4904,7 @@ $called_api = null; $profile_url = $user_info["url"]; // message if nothing was found - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $success = array('success' => false, 'search_results' => 'problem with query'); } elseif (count($r) == 0) { $success = array('success' => false, 'search_results' => 'nothing found'); @@ -4956,7 +4957,7 @@ $called_api = null; intval($profileid)); // error message if specified gid is not in database - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { throw new BadRequestException("profile_id not available"); } } else { diff --git a/include/auth.php b/include/auth.php index 763596365a..f852ea28a5 100644 --- a/include/auth.php +++ b/include/auth.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; +use Friendica\Database\DBM; require_once('include/security.php'); require_once('include/datetime.php'); @@ -58,7 +59,7 @@ if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params' $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($_SESSION['visitor_id']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $a->contact = $r[0]; } } @@ -81,7 +82,7 @@ if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params' intval($_SESSION['uid']) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { nuke_session(); goaway(System::baseUrl()); } @@ -177,7 +178,7 @@ if (isset($_SESSION) && x($_SESSION,'authenticated') && (!x($_POST,'auth-params' dbesc(trim($_POST['username'])), dbesc($encrypted) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $record = $r[0]; } diff --git a/include/auth_ejabberd.php b/include/auth_ejabberd.php index 1307d57832..6eefd4e947 100755 --- a/include/auth_ejabberd.php +++ b/include/auth_ejabberd.php @@ -34,6 +34,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Database\DBM; if (sizeof($_SERVER["argv"]) == 0) die(); @@ -152,7 +153,7 @@ class exAuth { $sQuery = "SELECT `uid` FROM `user` WHERE `nickname`='".dbesc($sUser)."'"; $this->writeLog(LOG_DEBUG, "using query ". $sQuery); $r = q($sQuery); - $found = dbm::is_result($r); + $found = DBM::is_result($r); } else { $found = false; } diff --git a/include/cache.php b/include/cache.php index 9571eb8d9f..6bdb3e2f66 100644 --- a/include/cache.php +++ b/include/cache.php @@ -7,6 +7,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; +use Friendica\Database\DBM; class Cache { /** @@ -104,7 +105,7 @@ class Cache { dbesc($key) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $cached = $r[0]['v']; $value = @unserialize($cached); diff --git a/include/contact_selectors.php b/include/contact_selectors.php index 4109f38cd1..1e754ac9f7 100644 --- a/include/contact_selectors.php +++ b/include/contact_selectors.php @@ -1,5 +1,6 @@ {$rr['profile-name']}\r\n"; @@ -106,7 +107,7 @@ function network_to_name($s, $profile = "") { INNER JOIN `gserver` ON `gserver`.`nurl` = `gcontact`.`server_url` WHERE `gcontact`.`nurl` = ? AND `platform` != ''", normalise_link($profile)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $networkname = $r['platform']; } } diff --git a/include/contact_widgets.php b/include/contact_widgets.php index 01329513bb..d47cf86c35 100644 --- a/include/contact_widgets.php +++ b/include/contact_widgets.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\PConfig; +use Friendica\Database\DBM; require_once 'include/contact_selectors.php'; @@ -233,11 +234,11 @@ function common_friends_visitor_widget($profile_uid) { if (get_my_url()) { $r = dba::select('contact', array('id'), array('nurl' => normalise_link(get_my_url()), 'uid' => $profile_uid), array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $cid = $r['id']; } else { $r = dba::select('gcontact', array('id'), array('nurl' => normalise_link(get_my_url())), array('limit' => 1)); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $zcid = $r['id']; } } diff --git a/include/conversation.php b/include/conversation.php index d4fc2a40e5..0e814c6665 100644 --- a/include/conversation.php +++ b/include/conversation.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; +use Friendica\Database\DBM; require_once "include/bbcode.php"; require_once "include/acl_selectors.php"; @@ -122,7 +123,7 @@ function localize_item(&$item) { WHERE `item`.`contact-id`=`contact`.`id` AND `item`.`uri`='%s'", dbesc($item['parent-uri'])); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } $obj = $r[0]; @@ -273,7 +274,7 @@ function localize_item(&$item) { AND `item`.`uri`='%s'", dbesc($item['parent-uri'])); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -329,7 +330,7 @@ function localize_item(&$item) { intval($item['uid']) ); - if (dbm::is_result($r) && $r[0]['plink']) { + if (DBM::is_result($r) && $r[0]['plink']) { $target = $r[0]; $Bname = $target['author-name']; $Blink = $target['author-link']; @@ -941,7 +942,7 @@ function best_link_url($item, &$sparkle, $url = '') { $r = dba::select('contact', array('id'), array('network' => NETWORK_DFRN, 'uid' => local_user(), 'nurl' => normalise_link($clean_url), 'pending' => false), array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $best_url = 'redir/' . $r['id']; $sparkle = true; if ($url != '') { @@ -992,7 +993,7 @@ function item_photo_menu($item) { $network = ''; $rel = 0; $r = dba::select('contact', array('id', 'network', 'rel'), array('uid' => local_user(), 'nurl' => normalise_link($item['author-link'])), array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $cid = $r['id']; $network = $r['network']; $rel = $r['rel']; diff --git a/include/cron.php b/include/cron.php index 4b5aac831c..e7c6701514 100644 --- a/include/cron.php +++ b/include/cron.php @@ -2,6 +2,7 @@ use Friendica\Core\Config; use Friendica\Core\Worker; +use Friendica\Database\DBM; function cron_run(&$argv, &$argc){ global $a; @@ -161,7 +162,7 @@ function cron_poll_contacts($argc, $argv) { dbesc(NETWORK_MAIL2) ); - if (!dbm::is_result($contacts)) { + if (!DBM::is_result($contacts)) { return; } @@ -171,7 +172,7 @@ function cron_poll_contacts($argc, $argv) { intval($c['id']) ); - if (!dbm::is_result($res)) { + if (!DBM::is_result($res)) { continue; } diff --git a/include/cronjobs.php b/include/cronjobs.php index e4eb48e770..453db6d014 100644 --- a/include/cronjobs.php +++ b/include/cronjobs.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Database\DBM; use Friendica\Network\Probe; function cronjobs_run(&$argv, &$argc){ @@ -78,7 +79,7 @@ function cronjobs_run(&$argv, &$argc){ */ function cron_update_photo_albums() { $r = q("SELECT `uid` FROM `user` WHERE NOT `account_expired` AND NOT `account_removed`"); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -98,7 +99,7 @@ function cron_expire_and_remove_users() { // delete user records for recently removed accounts $r = q("SELECT * FROM `user` WHERE `account_removed` AND `account_expires_on` < UTC_TIMESTAMP() - INTERVAL 3 DAY"); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $user) { dba::delete('user', array('uid' => $user['uid'])); } @@ -211,7 +212,7 @@ function cron_repair_diaspora(App $a) { $r = q("SELECT `id`, `url` FROM `contact` WHERE `network` = '%s' AND (`batch` = '' OR `notify` = '' OR `poll` = '' OR pubkey = '') ORDER BY RAND() LIMIT 50", dbesc(NETWORK_DIASPORA)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -246,7 +247,7 @@ function cron_repair_database() { // Sometimes there seem to be issues where the "self" contact vanishes. // We haven't found the origin of the problem by now. $r = q("SELECT `uid` FROM `user` WHERE NOT EXISTS (SELECT `uid` FROM `contact` WHERE `contact`.`uid` = `user`.`uid` AND `contact`.`self`)"); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r AS $user) { logger('Create missing self contact for user '.$user['uid']); user_create_self_contact($user['uid']); @@ -262,7 +263,7 @@ function cron_repair_database() { // Update the global contacts for local users $r = q("SELECT `uid` FROM `user` WHERE `verified` AND NOT `blocked` AND NOT `account_removed` AND NOT `account_expired`"); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r AS $user) { update_gcontact_for_user($user["uid"]); } diff --git a/include/datetime.php b/include/datetime.php index faedaf33dc..cb27799798 100644 --- a/include/datetime.php +++ b/include/datetime.php @@ -6,6 +6,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; +use Friendica\Database\DBM; /** * @brief Two-level sort for timezones. @@ -589,7 +590,7 @@ function update_contact_birthdays() { // In-network birthdays are handled within local_delivery $r = q("SELECT * FROM `contact` WHERE `bd` != '' AND `bd` > '0001-01-01' AND SUBSTRING(`bd`, 1, 4) != `bdyear` "); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { logger('update_contact_birthday: ' . $rr['bd']); @@ -611,7 +612,7 @@ function update_contact_birthdays() { dbesc(datetime_convert('UTC','UTC', $nextbd)), dbesc('birthday')); - if (dbm::is_result($s)) { + if (DBM::is_result($s)) { continue; } diff --git a/include/dba.php b/include/dba.php index 74e9d7c061..070722b9ba 100644 --- a/include/dba.php +++ b/include/dba.php @@ -1,7 +1,7 @@ List of processes, separated in their different states - * 'amount' => Number of concurrent database processes - */ - public static function processlist() { - $r = q("SHOW PROCESSLIST"); - $s = array(); - - $processes = 0; - $states = array(); - foreach ($r AS $process) { - $state = trim($process["State"]); - - // Filter out all non blocking processes - if (!in_array($state, array("", "init", "statistics", "updating"))) { - ++$states[$state]; - ++$processes; - } - } - - $statelist = ""; - foreach ($states AS $state => $usage) { - if ($statelist != "") - $statelist .= ", "; - $statelist .= $state.": ".$usage; - } - return(array("list" => $statelist, "amount" => $processes)); - } - - /** - * Checks if $array is a filled array with at least one entry. - * - * @param $array mixed A filled array with at least one entry - * @return Whether $array is a filled array or an object with rows - */ - public static function is_result($array) { - // It could be a return value from an update statement - if (is_bool($array)) { - return $array; - } - - if (is_object($array)) { - return dba::num_rows($array) > 0; - } - - return (is_array($array) && (count($array) > 0)); - } - - /** - * @brief Callback function for "esc_array" - * - * @param mixed $value Array value - * @param string $key Array key - * @param boolean $add_quotation add quotation marks for string values - */ - private static function esc_array_callback(&$value, $key, $add_quotation) { - - if (!$add_quotation) { - if (is_bool($value)) { - $value = ($value ? '1' : '0'); - } else { - $value = dbesc($value); - } - return; - } - - if (is_bool($value)) { - $value = ($value ? 'true' : 'false'); - } elseif (is_float($value) || is_integer($value)) { - $value = (string)$value; - } else { - $value = "'".dbesc($value)."'"; - } - } - - /** - * @brief Escapes a whole array - * - * @param mixed $arr Array with values to be escaped - * @param boolean $add_quotation add quotation marks for string values - */ - public static function esc_array(&$arr, $add_quotation = false) { - array_walk($arr, 'self::esc_array_callback', $add_quotation); - } - - /** - * Checks Converts any date string into a SQL compatible date string - * - * @param string $date a date string in any format - * @return string SQL style date string - */ - public static function date($date = 'now') { - $timestamp = strtotime($date); - - // Don't allow lower date strings as '0001-01-01 00:00:00' - if ($timestamp < -62135596800) { - $timestamp = -62135596800; - } - - return date('Y-m-d H:i:s', (int)$timestamp); - } -} diff --git a/include/dbstructure.php b/include/dbstructure.php index 6a881cdf7f..1df82b1bed 100644 --- a/include/dbstructure.php +++ b/include/dbstructure.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; +use Friendica\Database\DBM; require_once "boot.php"; require_once "include/text.php"; @@ -20,7 +21,7 @@ function convert_to_innodb() { $r = q("SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `engine` = 'MyISAM' AND `table_schema` = '%s'", dbesc(dba::database_name())); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { echo t('There are no tables on MyISAM.')."\n"; return; } @@ -30,7 +31,7 @@ function convert_to_innodb() { echo $sql."\n"; $result = dba::e($sql); - if (!dbm::is_result($result)) { + if (!DBM::is_result($result)) { print_update_error($sql); } } @@ -50,7 +51,7 @@ function update_fail($update_id, $error_message) { ); // No valid result? - if (!dbm::is_result($adminlist)) { + if (!DBM::is_result($adminlist)) { logger(sprintf('Cannot notify administrators about update_id=%d, error_message=%s', $update_id, $error_message), LOGGER_NORMAL); // Don't continue @@ -114,7 +115,7 @@ function table_structure($table) { $table_status = q("SHOW TABLE STATUS WHERE `name` = '%s'", $table); - if (dbm::is_result($table_status)) { + if (DBM::is_result($table_status)) { $table_status = $table_status[0]; } else { $table_status = array(); @@ -123,7 +124,7 @@ function table_structure($table) { $fielddata = array(); $indexdata = array(); - if (dbm::is_result($indexes)) + if (DBM::is_result($indexes)) foreach ($indexes AS $index) { if ($index['Key_name'] != 'PRIMARY' && $index['Non_unique'] == '0' && !isset($indexdata[$index["Key_name"]])) { $indexdata[$index["Key_name"]] = array('UNIQUE'); @@ -137,7 +138,7 @@ function table_structure($table) { $indexdata[$index["Key_name"]][] = $column; } - if (dbm::is_result($structures)) { + if (DBM::is_result($structures)) { foreach ($structures AS $field) { $fielddata[$field["Field"]]["type"] = $field["Type"]; if ($field["Null"] == "NO") { @@ -157,7 +158,7 @@ function table_structure($table) { } } } - if (dbm::is_result($full_columns)) { + if (DBM::is_result($full_columns)) { foreach ($full_columns AS $column) { $fielddata[$column["Field"]]["Collation"] = $column["Collation"]; } @@ -200,7 +201,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { if ($action) { Config::set('system', 'maintenance', 1); - Config::set('system', 'maintenance_reason', sprintf(t(': Database update'), dbm::date().' '.date('e'))); + Config::set('system', 'maintenance_reason', sprintf(t(': Database update'), DBM::date().' '.date('e'))); } $errors = false; @@ -214,7 +215,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { $tables = q("SHOW TABLES"); } - if (dbm::is_result($tables)) { + if (DBM::is_result($tables)) { foreach ($tables AS $table) { $table = current($table); @@ -243,7 +244,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { $sql3 = ""; if (!isset($database[$name])) { $r = db_create_table($name, $structure["fields"], $verbose, $action, $structure['indexes']); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $errors .= print_update_error($name); } $is_new_table = True; @@ -433,7 +434,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { } if ($action) { - Config::set('system', 'maintenance_reason', sprintf(t('%s: updating %s table.'), dbm::date().' '.date('e'), $name)); + Config::set('system', 'maintenance_reason', sprintf(t('%s: updating %s table.'), DBM::date().' '.date('e'), $name)); // Ensure index conversion to unique removes duplicates if ($is_unique && ($temp_name != $name)) { @@ -441,13 +442,13 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { dba::e("SET session old_alter_table=1;"); } else { dba::e("DROP TABLE IF EXISTS `".$temp_name."`;"); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $errors .= print_update_error($sql3); return $errors; } $r = dba::e("CREATE TABLE `".$temp_name."` LIKE `".$name."`;"); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $errors .= print_update_error($sql3); return $errors; } @@ -455,7 +456,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { } $r = @dba::e($sql3); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $errors .= print_update_error($sql3); } if ($is_unique && ($temp_name != $name)) { @@ -463,17 +464,17 @@ function update_structure($verbose, $action, $tables=null, $definition=null) { dba::e("SET session old_alter_table=0;"); } else { $r = dba::e("INSERT INTO `".$temp_name."` SELECT ".$field_list." FROM `".$name."`".$group_by.";"); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $errors .= print_update_error($sql3); return $errors; } $r = dba::e("DROP TABLE `".$name."`;"); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $errors .= print_update_error($sql3); return $errors; } $r = dba::e("RENAME TABLE `".$temp_name."` TO `".$name."`;"); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $errors .= print_update_error($sql3); return $errors; } diff --git a/include/delivery.php b/include/delivery.php index 754257773c..7c5f4648c6 100644 --- a/include/delivery.php +++ b/include/delivery.php @@ -3,8 +3,9 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; +use Friendica\Database\DBM; use Friendica\Protocol\Diaspora; -use Friendica\Protocol\Dfrn; +use Friendica\Protocol\DFRN; require_once 'include/queue_fn.php'; require_once 'include/html2plain.php'; @@ -95,7 +96,7 @@ function delivery_run(&$argv, &$argc){ intval($item_id) ); - if ((!dbm::is_result($r)) || (!intval($r[0]['parent']))) { + if ((!DBM::is_result($r)) || (!intval($r[0]['parent']))) { continue; } @@ -155,7 +156,7 @@ function delivery_run(&$argv, &$argc){ intval($uid) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { continue; } @@ -226,7 +227,7 @@ function delivery_run(&$argv, &$argc){ intval($contact_id) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact = $r[0]; } if ($contact['self']) { @@ -243,12 +244,12 @@ function delivery_run(&$argv, &$argc){ if ($mail) { $item['body'] = fix_private_photos($item['body'],$owner['uid'],null,$message[0]['contact-id']); - $atom = Dfrn::mail($item, $owner); + $atom = DFRN::mail($item, $owner); } elseif ($fsuggest) { - $atom = Dfrn::fsuggest($item, $owner); + $atom = DFRN::fsuggest($item, $owner); q("DELETE FROM `fsuggest` WHERE `id` = %d LIMIT 1", intval($item['id'])); } elseif ($relocate) { - $atom = Dfrn::relocate($owner, $uid); + $atom = DFRN::relocate($owner, $uid); } elseif ($followup) { $msgitems = array(); foreach ($items as $item) { // there is only one item @@ -260,7 +261,7 @@ function delivery_run(&$argv, &$argc){ $msgitems[] = $item; } } - $atom = Dfrn::entries($msgitems,$owner); + $atom = DFRN::entries($msgitems,$owner); } else { $msgitems = array(); foreach ($items as $item) { @@ -289,7 +290,7 @@ function delivery_run(&$argv, &$argc){ $msgitems[] = $item; } } - $atom = Dfrn::entries($msgitems,$owner); + $atom = DFRN::entries($msgitems,$owner); } logger('notifier entry: '.$contact["url"].' '.$target_item["guid"].' entry: '.$atom, LOGGER_DEBUG); @@ -343,13 +344,13 @@ function delivery_run(&$argv, &$argc){ break; } logger('mod-delivery: local delivery'); - Dfrn::import($atom, $x[0]); + DFRN::import($atom, $x[0]); break; } } if (!was_recently_delayed($contact['id'])) { - $deliver_status = Dfrn::deliver($owner,$contact,$atom); + $deliver_status = DFRN::deliver($owner,$contact,$atom); } else { $deliver_status = (-1); } @@ -405,7 +406,7 @@ function delivery_run(&$argv, &$argc){ intval($argv[2]), intval($uid) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $it = $r[0]; } if (!$it) @@ -462,14 +463,14 @@ function delivery_run(&$argv, &$argc){ dbesc($it['parent-uri']), intval($uid)); - if (dbm::is_result($r) && ($r[0]['title'] != '')) { + if (DBM::is_result($r) && ($r[0]['title'] != '')) { $subject = $r[0]['title']; } else { $r = q("SELECT `title` FROM `item` WHERE `parent-uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($it['parent-uri']), intval($uid)); - if (dbm::is_result($r) && ($r[0]['title'] != '')) + if (DBM::is_result($r) && ($r[0]['title'] != '')) $subject = $r[0]['title']; } } diff --git a/include/dfrn.php b/include/dfrn.php deleted file mode 100644 index b4a29615d3..0000000000 --- a/include/dfrn.php +++ /dev/null @@ -1,2966 +0,0 @@ -formatOutput = true; - - $root = self::add_header($doc, $owner, "dfrn:owner", "", false); - - if (! count($items)) { - return trim($doc->saveXML()); - } - - foreach ($items as $item) { - $entry = self::entry($doc, "text", $item, $owner, $item["entry:comment-allow"], $item["entry:cid"]); - $root->appendChild($entry); - } - - return(trim($doc->saveXML())); - } - - /** - * @brief Generate an atom feed for the given user - * - * This function is called when another server is pulling data from the user feed. - * - * @param string $dfrn_id DFRN ID from the requesting party - * @param string $owner_nick Owner nick name - * @param string $last_update Date of the last update - * @param int $direction Can be -1, 0 or 1. - * @param boolean $onlyheader Output only the header without content? (Default is "no") - * - * @return string DFRN feed entries - */ - public static function feed($dfrn_id, $owner_nick, $last_update, $direction = 0, $onlyheader = false) { - - $a = get_app(); - - $sitefeed = ((strlen($owner_nick)) ? false : true); // not yet implemented, need to rewrite huge chunks of following logic - $public_feed = (($dfrn_id) ? false : true); - $starred = false; // not yet implemented, possible security issues - $converse = false; - - if ($public_feed && $a->argc > 2) { - for ($x = 2; $x < $a->argc; $x++) { - if ($a->argv[$x] == 'converse') { - $converse = true; - } - if ($a->argv[$x] == 'starred') { - $starred = true; - } - if ($a->argv[$x] == 'category' && $a->argc > ($x + 1) && strlen($a->argv[$x+1])) { - $category = $a->argv[$x+1]; - } - } - } - - - - // default permissions - anonymous user - - $sql_extra = " AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' "; - - $r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`, `user`.`account-type` - FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` - WHERE `contact`.`self` AND `user`.`nickname` = '%s' LIMIT 1", - dbesc($owner_nick) - ); - - if (! dbm::is_result($r)) { - killme(); - } - - $owner = $r[0]; - $owner_id = $owner['uid']; - $owner_nick = $owner['nickname']; - - $sql_post_table = ""; - - if (! $public_feed) { - - $sql_extra = ''; - switch($direction) { - case (-1): - $sql_extra = sprintf(" AND `issued-id` = '%s' ", dbesc($dfrn_id)); - $my_id = $dfrn_id; - break; - case 0: - $sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id)); - $my_id = '1:' . $dfrn_id; - break; - case 1: - $sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", dbesc($dfrn_id)); - $my_id = '0:' . $dfrn_id; - break; - default: - return false; - break; // NOTREACHED - } - - $r = q("SELECT * FROM `contact` WHERE NOT `blocked` AND `contact`.`uid` = %d $sql_extra LIMIT 1", - intval($owner_id) - ); - - if (! dbm::is_result($r)) { - killme(); - } - - $contact = $r[0]; - require_once('include/security.php'); - $groups = init_groups_visitor($contact['id']); - - if (count($groups)) { - for ($x = 0; $x < count($groups); $x ++) - $groups[$x] = '<' . intval($groups[$x]) . '>' ; - $gs = implode('|', $groups); - } else { - $gs = '<<>>' ; // Impossible to match - } - - $sql_extra = sprintf(" - AND ( `allow_cid` = '' OR `allow_cid` REGEXP '<%d>' ) - AND ( `deny_cid` = '' OR NOT `deny_cid` REGEXP '<%d>' ) - AND ( `allow_gid` = '' OR `allow_gid` REGEXP '%s' ) - AND ( `deny_gid` = '' OR NOT `deny_gid` REGEXP '%s') - ", - intval($contact['id']), - intval($contact['id']), - dbesc($gs), - dbesc($gs) - ); - } - - if ($public_feed) { - $sort = 'DESC'; - } else { - $sort = 'ASC'; - } - - if (! strlen($last_update)) { - $last_update = 'now -30 days'; - } - - if (isset($category)) { - $sql_post_table = sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ", - dbesc(protect_sprintf($category)), intval(TERM_OBJ_POST), intval(TERM_CATEGORY), intval($owner_id)); - //$sql_extra .= file_tag_file_query('item',$category,'category'); - } - - if ($public_feed) { - if (! $converse) { - $sql_extra .= " AND `contact`.`self` = 1 "; - } - } - - $check_date = datetime_convert('UTC','UTC',$last_update,'Y-m-d H:i:s'); - - $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, - `contact`.`name`, `contact`.`network`, `contact`.`photo`, `contact`.`url`, - `contact`.`name-date`, `contact`.`uri-date`, `contact`.`avatar-date`, - `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`, - `sign`.`signed_text`, `sign`.`signature`, `sign`.`signer` - FROM `item` USE INDEX (`uid_wall_changed`) $sql_post_table - STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` - AND (NOT `contact`.`blocked` OR `contact`.`pending`) - LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` - WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`moderated` AND `item`.`parent` != 0 - AND `item`.`wall` AND `item`.`changed` > '%s' - $sql_extra - ORDER BY `item`.`parent` ".$sort.", `item`.`created` ASC LIMIT 0, 300", - intval($owner_id), - dbesc($check_date), - dbesc($sort) - ); - - /* - * Will check further below if this actually returned results. - * We will provide an empty feed if that is the case. - */ - - $items = $r; - - $doc = new DOMDocument('1.0', 'utf-8'); - $doc->formatOutput = true; - - $alternatelink = $owner['url']; - - if (isset($category)) { - $alternatelink .= "/category/".$category; - } - - if ($public_feed) { - $author = "dfrn:owner"; - } else { - $author = "author"; - } - - $root = self::add_header($doc, $owner, $author, $alternatelink, true); - - /// @TODO This hook can't work anymore - // call_hooks('atom_feed', $atom); - - if (!dbm::is_result($items) || $onlyheader) { - $atom = trim($doc->saveXML()); - - call_hooks('atom_feed_end', $atom); - - return $atom; - } - - foreach ($items as $item) { - - // prevent private email from leaking. - if ($item['network'] == NETWORK_MAIL) { - continue; - } - - // public feeds get html, our own nodes use bbcode - - if ($public_feed) { - $type = 'html'; - // catch any email that's in a public conversation and make sure it doesn't leak - if ($item['private']) { - continue; - } - } else { - $type = 'text'; - } - - $entry = self::entry($doc, $type, $item, $owner, true); - $root->appendChild($entry); - - } - - $atom = trim($doc->saveXML()); - - call_hooks('atom_feed_end', $atom); - - return $atom; - } - - /** - * @brief Generate an atom entry for a given item id - * - * @param int $item_id The item id - * @param boolean $conversation Show the conversation. If false show the single post. - * - * @return string DFRN feed entry - */ - public static function itemFeed($item_id, $conversation = false) { - if ($conversation) { - $condition = '`item`.`parent`'; - } else { - $condition = '`item`.`id`'; - } - - $r = q("SELECT `item`.*, `item`.`id` AS `item_id`, - `contact`.`name`, `contact`.`network`, `contact`.`photo`, `contact`.`url`, - `contact`.`name-date`, `contact`.`uri-date`, `contact`.`avatar-date`, - `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`, - `sign`.`signed_text`, `sign`.`signature`, `sign`.`signer` - FROM `item` - STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` - AND (NOT `contact`.`blocked` OR `contact`.`pending`) - LEFT JOIN `sign` ON `sign`.`iid` = `item`.`id` - WHERE %s = %d AND `item`.`visible` AND NOT `item`.`moderated` AND `item`.`parent` != 0 - AND NOT `item`.`private`", - $condition, - intval($item_id) - ); - - if (!dbm::is_result($r)) { - killme(); - } - - $items = $r; - $item = $r[0]; - - $r = q("SELECT `contact`.*, `user`.`nickname`, `user`.`timezone`, `user`.`page-flags`, `user`.`account-type` - FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` - WHERE `contact`.`self` AND `user`.`uid` = %d LIMIT 1", - intval($item['uid']) - ); - - if (!dbm::is_result($r)) { - killme(); - } - - $owner = $r[0]; - - $doc = new DOMDocument('1.0', 'utf-8'); - $doc->formatOutput = true; - $type = 'html'; - - if ($conversation) { - $root = $doc->createElementNS(NAMESPACE_ATOM1, 'feed'); - $doc->appendChild($root); - - $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); - - //$root = self::add_header($doc, $owner, "dfrn:owner", "", false); - - foreach ($items as $item) { - $entry = self::entry($doc, $type, $item, $owner, true, 0); - $root->appendChild($entry); - } - } else { - $root = self::entry($doc, $type, $item, $owner, true, 0, true); - } - - $atom = trim($doc->saveXML()); - return $atom; - } - - /** - * @brief Create XML text for DFRN mails - * - * @param array $item message elements - * @param array $owner Owner record - * - * @return string DFRN mail - * @todo Add type-hints - */ - public static function mail($item, $owner) { - $doc = new DOMDocument('1.0', 'utf-8'); - $doc->formatOutput = true; - - $root = self::add_header($doc, $owner, "dfrn:owner", "", false); - - $mail = $doc->createElement("dfrn:mail"); - $sender = $doc->createElement("dfrn:sender"); - - xml::add_element($doc, $sender, "dfrn:name", $owner['name']); - xml::add_element($doc, $sender, "dfrn:uri", $owner['url']); - xml::add_element($doc, $sender, "dfrn:avatar", $owner['thumb']); - - $mail->appendChild($sender); - - xml::add_element($doc, $mail, "dfrn:id", $item['uri']); - xml::add_element($doc, $mail, "dfrn:in-reply-to", $item['parent-uri']); - xml::add_element($doc, $mail, "dfrn:sentdate", datetime_convert('UTC', 'UTC', $item['created'] . '+00:00' , ATOM_TIME)); - xml::add_element($doc, $mail, "dfrn:subject", $item['title']); - xml::add_element($doc, $mail, "dfrn:content", $item['body']); - - $root->appendChild($mail); - - return(trim($doc->saveXML())); - } - - /** - * @brief Create XML text for DFRN friend suggestions - * - * @param array $item suggestion elements - * @param array $owner Owner record - * - * @return string DFRN suggestions - * @todo Add type-hints - */ - public static function fsuggest($item, $owner) { - $doc = new DOMDocument('1.0', 'utf-8'); - $doc->formatOutput = true; - - $root = self::add_header($doc, $owner, "dfrn:owner", "", false); - - $suggest = $doc->createElement("dfrn:suggest"); - - xml::add_element($doc, $suggest, "dfrn:url", $item['url']); - xml::add_element($doc, $suggest, "dfrn:name", $item['name']); - xml::add_element($doc, $suggest, "dfrn:photo", $item['photo']); - xml::add_element($doc, $suggest, "dfrn:request", $item['request']); - xml::add_element($doc, $suggest, "dfrn:note", $item['note']); - - $root->appendChild($suggest); - - return(trim($doc->saveXML())); - } - - /** - * @brief Create XML text for DFRN relocations - * - * @param array $owner Owner record - * @param int $uid User ID - * - * @return string DFRN relocations - * @todo Add type-hints - */ - public static function relocate($owner, $uid) { - - /* get site pubkey. this could be a new installation with no site keys*/ - $pubkey = Config::get('system','site_pubkey'); - if (! $pubkey) { - $res = new_keypair(1024); - Config::set('system','site_prvkey', $res['prvkey']); - Config::set('system','site_pubkey', $res['pubkey']); - } - - $rp = q("SELECT `resource-id` , `scale`, type FROM `photo` - WHERE `profile` = 1 AND `uid` = %d ORDER BY scale;", $uid); - $photos = array(); - $ext = Photo::supportedTypes(); - - foreach ($rp as $p) { - $photos[$p['scale']] = System::baseUrl().'/photo/'.$p['resource-id'].'-'.$p['scale'].'.'.$ext[$p['type']]; - } - - unset($rp, $ext); - - $doc = new DOMDocument('1.0', 'utf-8'); - $doc->formatOutput = true; - - $root = self::add_header($doc, $owner, "dfrn:owner", "", false); - - $relocate = $doc->createElement("dfrn:relocate"); - - xml::add_element($doc, $relocate, "dfrn:url", $owner['url']); - xml::add_element($doc, $relocate, "dfrn:name", $owner['name']); - xml::add_element($doc, $relocate, "dfrn:addr", $owner['addr']); - xml::add_element($doc, $relocate, "dfrn:avatar", $owner['avatar']); - xml::add_element($doc, $relocate, "dfrn:photo", $photos[4]); - xml::add_element($doc, $relocate, "dfrn:thumb", $photos[5]); - xml::add_element($doc, $relocate, "dfrn:micro", $photos[6]); - xml::add_element($doc, $relocate, "dfrn:request", $owner['request']); - xml::add_element($doc, $relocate, "dfrn:confirm", $owner['confirm']); - xml::add_element($doc, $relocate, "dfrn:notify", $owner['notify']); - xml::add_element($doc, $relocate, "dfrn:poll", $owner['poll']); - xml::add_element($doc, $relocate, "dfrn:sitepubkey", Config::get('system','site_pubkey')); - - $root->appendChild($relocate); - - return(trim($doc->saveXML())); - } - - /** - * @brief Adds the header elements for the DFRN protocol - * - * @param object $doc XML document - * @param array $owner Owner record - * @param string $authorelement Element name for the author - * @param string $alternatelink link to profile or category - * @param bool $public Is it a header for public posts? - * - * @return object XML root object - * @todo Add type-hints - */ - private static function add_header($doc, $owner, $authorelement, $alternatelink = "", $public = false) { - - if ($alternatelink == "") { - $alternatelink = $owner['url']; - } - - $root = $doc->createElementNS(NAMESPACE_ATOM1, 'feed'); - $doc->appendChild($root); - - $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", System::baseUrl()."/profile/".$owner["nick"]); - xml::add_element($doc, $root, "title", $owner["name"]); - - $attributes = array("uri" => "https://friendi.ca", "version" => FRIENDICA_VERSION."-".DB_UPDATE_VERSION); - xml::add_element($doc, $root, "generator", FRIENDICA_PLATFORM, $attributes); - - $attributes = array("rel" => "license", "href" => "http://creativecommons.org/licenses/by/3.0/"); - xml::add_element($doc, $root, "link", "", $attributes); - - $attributes = array("rel" => "alternate", "type" => "text/html", "href" => $alternatelink); - xml::add_element($doc, $root, "link", "", $attributes); - - - if ($public) { - // DFRN itself doesn't uses this. But maybe someone else wants to subscribe to the public feed. - ostatus::hublinks($doc, $root, $owner["nick"]); - - $attributes = array("rel" => "salmon", "href" => System::baseUrl()."/salmon/".$owner["nick"]); - xml::add_element($doc, $root, "link", "", $attributes); - - $attributes = array("rel" => "http://salmon-protocol.org/ns/salmon-replies", "href" => System::baseUrl()."/salmon/".$owner["nick"]); - xml::add_element($doc, $root, "link", "", $attributes); - - $attributes = array("rel" => "http://salmon-protocol.org/ns/salmon-mention", "href" => System::baseUrl()."/salmon/".$owner["nick"]); - xml::add_element($doc, $root, "link", "", $attributes); - } - - // For backward compatibility we keep this element - if ($owner['page-flags'] == PAGE_COMMUNITY) { - xml::add_element($doc, $root, "dfrn:community", 1); - } - - // The former element is replaced by this one - xml::add_element($doc, $root, "dfrn:account_type", $owner["account-type"]); - - /// @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); - $root->appendChild($author); - - return $root; - } - - /** - * @brief Adds the author element in the header for the DFRN protocol - * - * @param object $doc XML document - * @param array $owner Owner record - * @param string $authorelement Element name for the author - * - * @return object XML author object - * @todo Add type-hints - */ - private static function add_author($doc, $owner, $authorelement, $public) { - - // Is the profile hidden or shouldn't be published in the net? Then add the "hide" element - $r = q("SELECT `id` FROM `profile` INNER JOIN `user` ON `user`.`uid` = `profile`.`uid` - WHERE (`hidewall` OR NOT `net-publish`) AND `user`.`uid` = %d", - intval($owner['uid'])); - if (dbm::is_result($r)) { - $hidewall = true; - } else { - $hidewall = false; - } - - $author = $doc->createElement($authorelement); - - $namdate = datetime_convert('UTC', 'UTC', $owner['name-date'].'+00:00', ATOM_TIME); - $uridate = datetime_convert('UTC', 'UTC', $owner['uri-date'].'+00:00', ATOM_TIME); - $picdate = datetime_convert('UTC', 'UTC', $owner['avatar-date'].'+00:00', ATOM_TIME); - - $attributes = array(); - - if (!$public || !$hidewall) { - $attributes = array("dfrn:updated" => $namdate); - } - - xml::add_element($doc, $author, "name", $owner["name"], $attributes); - xml::add_element($doc, $author, "uri", System::baseUrl().'/profile/'.$owner["nickname"], $attributes); - xml::add_element($doc, $author, "dfrn:handle", $owner["addr"], $attributes); - - $attributes = array("rel" => "photo", "type" => "image/jpeg", - "media:width" => 175, "media:height" => 175, "href" => $owner['photo']); - - if (!$public || !$hidewall) { - $attributes["dfrn:updated"] = $picdate; - } - - xml::add_element($doc, $author, "link", "", $attributes); - - $attributes["rel"] = "avatar"; - xml::add_element($doc, $author, "link", "", $attributes); - - if ($hidewall) { - xml::add_element($doc, $author, "dfrn:hide", "true"); - } - - // The following fields will only be generated if the data isn't meant for a public feed - if ($public) { - return $author; - } - - $birthday = feed_birthday($owner['uid'], $owner['timezone']); - - if ($birthday) - xml::add_element($doc, $author, "dfrn:birthday", $birthday); - - // Only show contact details when we are allowed to - $r = q("SELECT `profile`.`about`, `profile`.`name`, `profile`.`homepage`, `user`.`nickname`, - `user`.`timezone`, `profile`.`locality`, `profile`.`region`, `profile`.`country-name`, - `profile`.`pub_keywords`, `profile`.`xmpp`, `profile`.`dob` - FROM `profile` - INNER JOIN `user` ON `user`.`uid` = `profile`.`uid` - WHERE `profile`.`is-default` AND NOT `user`.`hidewall` AND `user`.`uid` = %d", - intval($owner['uid'])); - if (dbm::is_result($r)) { - $profile = $r[0]; - - xml::add_element($doc, $author, "poco:displayName", $profile["name"]); - xml::add_element($doc, $author, "poco:updated", $namdate); - - if (trim($profile["dob"]) > '0001-01-01') { - xml::add_element($doc, $author, "poco:birthday", "0000-".date("m-d", strtotime($profile["dob"]))); - } - - xml::add_element($doc, $author, "poco:note", $profile["about"]); - xml::add_element($doc, $author, "poco:preferredUsername", $profile["nickname"]); - - $savetz = date_default_timezone_get(); - date_default_timezone_set($profile["timezone"]); - xml::add_element($doc, $author, "poco:utcOffset", date("P")); - date_default_timezone_set($savetz); - - if (trim($profile["homepage"]) != "") { - $urls = $doc->createElement("poco:urls"); - xml::add_element($doc, $urls, "poco:type", "homepage"); - xml::add_element($doc, $urls, "poco:value", $profile["homepage"]); - xml::add_element($doc, $urls, "poco:primary", "true"); - $author->appendChild($urls); - } - - if (trim($profile["pub_keywords"]) != "") { - $keywords = explode(",", $profile["pub_keywords"]); - - foreach ($keywords AS $keyword) { - xml::add_element($doc, $author, "poco:tags", trim($keyword)); - } - - } - - if (trim($profile["xmpp"]) != "") { - $ims = $doc->createElement("poco:ims"); - xml::add_element($doc, $ims, "poco:type", "xmpp"); - xml::add_element($doc, $ims, "poco:value", $profile["xmpp"]); - xml::add_element($doc, $ims, "poco:primary", "true"); - $author->appendChild($ims); - } - - if (trim($profile["locality"].$profile["region"].$profile["country-name"]) != "") { - $element = $doc->createElement("poco:address"); - - xml::add_element($doc, $element, "poco:formatted", formatted_location($profile)); - - if (trim($profile["locality"]) != "") { - xml::add_element($doc, $element, "poco:locality", $profile["locality"]); - } - - if (trim($profile["region"]) != "") { - xml::add_element($doc, $element, "poco:region", $profile["region"]); - } - - if (trim($profile["country-name"]) != "") { - xml::add_element($doc, $element, "poco:country", $profile["country-name"]); - } - - $author->appendChild($element); - } - } - - return $author; - } - - /** - * @brief Adds the author elements in the "entry" elements of the DFRN protocol - * - * @param object $doc XML document - * @param string $element Element name for the author - * @param string $contact_url Link of the contact - * @param array $items Item elements - * - * @return object XML author object - * @todo Add type-hints - */ - private static function add_entry_author($doc, $element, $contact_url, $item) { - - $contact = get_contact_details_by_url($contact_url, $item["uid"]); - - $author = $doc->createElement($element); - xml::add_element($doc, $author, "name", $contact["name"]); - xml::add_element($doc, $author, "uri", $contact["url"]); - xml::add_element($doc, $author, "dfrn:handle", $contact["addr"]); - - /// @Todo - /// - Check real image type and image size - /// - Check which of these boths elements we should use - $attributes = array( - "rel" => "photo", - "type" => "image/jpeg", - "media:width" => 80, - "media:height" => 80, - "href" => $contact["photo"]); - xml::add_element($doc, $author, "link", "", $attributes); - - $attributes = array( - "rel" => "avatar", - "type" => "image/jpeg", - "media:width" => 80, - "media:height" => 80, - "href" => $contact["photo"]); - xml::add_element($doc, $author, "link", "", $attributes); - - return $author; - } - - /** - * @brief Adds the activity elements - * - * @param object $doc XML document - * @param string $element Element name for the activity - * @param string $activity activity value - * - * @return object XML activity object - * @todo Add type-hints - */ - private static function create_activity($doc, $element, $activity) { - - if ($activity) { - $entry = $doc->createElement($element); - - $r = parse_xml_string($activity, false); - if (!$r) { - return false; - } - if ($r->type) { - xml::add_element($doc, $entry, "activity:object-type", $r->type); - } - if ($r->id) { - xml::add_element($doc, $entry, "id", $r->id); - } - if ($r->title) { - xml::add_element($doc, $entry, "title", $r->title); - } - - if ($r->link) { - if (substr($r->link, 0, 1) == '<') { - if (strstr($r->link, '&') && (! strstr($r->link, '&'))) { - $r->link = str_replace('&', '&', $r->link); - } - - $r->link = preg_replace('/\/', '', $r->link); - - // XML does need a single element as root element so we add a dummy element here - $data = parse_xml_string("" . $r->link . "", false); - if (is_object($data)) { - foreach ($data->link AS $link) { - $attributes = array(); - foreach ($link->attributes() AS $parameter => $value) { - $attributes[$parameter] = $value; - } - xml::add_element($doc, $entry, "link", "", $attributes); - } - } - } else { - $attributes = array("rel" => "alternate", "type" => "text/html", "href" => $r->link); - xml::add_element($doc, $entry, "link", "", $attributes); - } - } - if ($r->content) { - xml::add_element($doc, $entry, "content", bbcode($r->content), array("type" => "html")); - } - - return $entry; - } - - return false; - } - - /** - * @brief Adds the elements for attachments - * - * @param object $doc XML document - * @param object $root XML root - * @param array $item Item element - * - * @return object XML attachment object - * @todo Add type-hints - */ - private static function get_attachment($doc, $root, $item) { - $arr = explode('[/attach],',$item['attach']); - if (count($arr)) { - foreach ($arr as $r) { - $matches = false; - $cnt = preg_match('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|',$r,$matches); - if ($cnt) { - $attributes = array("rel" => "enclosure", - "href" => $matches[1], - "type" => $matches[3]); - - if (intval($matches[2])) { - $attributes["length"] = intval($matches[2]); - } - - if (trim($matches[4]) != "") { - $attributes["title"] = trim($matches[4]); - } - - xml::add_element($doc, $root, "link", "", $attributes); - } - } - } - } - - /** - * @brief Adds the "entry" elements for the DFRN protocol - * - * @param object $doc XML document - * @param string $type "text" or "html" - * @param array $item Item element - * @param array $owner Owner record - * @param bool $comment Trigger the sending of the "comment" element - * @param int $cid Contact ID of the recipient - * @param bool $single If set, the entry is created as an XML document with a single "entry" element - * - * @return object XML entry object - * @todo Add type-hints - */ - private static function entry($doc, $type, $item, $owner, $comment = false, $cid = 0, $single = false) { - - $mentioned = array(); - - if (!$item['parent']) { - return; - } - - if ($item['deleted']) { - $attributes = array("ref" => $item['uri'], "when" => datetime_convert('UTC','UTC',$item['edited'] . '+00:00',ATOM_TIME)); - return xml::create_element($doc, "at:deleted-entry", "", $attributes); - } - - if (!$single) { - $entry = $doc->createElement("entry"); - } else { - $entry = $doc->createElementNS(NAMESPACE_ATOM1, 'entry'); - $doc->appendChild($entry); - - $entry->setAttribute("xmlns:thr", NAMESPACE_THREAD); - $entry->setAttribute("xmlns:at", NAMESPACE_TOMB); - $entry->setAttribute("xmlns:media", NAMESPACE_MEDIA); - $entry->setAttribute("xmlns:dfrn", NAMESPACE_DFRN); - $entry->setAttribute("xmlns:activity", NAMESPACE_ACTIVITY); - $entry->setAttribute("xmlns:georss", NAMESPACE_GEORSS); - $entry->setAttribute("xmlns:poco", NAMESPACE_POCO); - $entry->setAttribute("xmlns:ostatus", NAMESPACE_OSTATUS); - $entry->setAttribute("xmlns:statusnet", NAMESPACE_STATUSNET); - } - - if ($item['allow_cid'] || $item['allow_gid'] || $item['deny_cid'] || $item['deny_gid']) { - $body = fix_private_photos($item['body'],$owner['uid'],$item,$cid); - } else { - $body = $item['body']; - } - - // Remove the abstract element. It is only locally important. - $body = remove_abstract($body); - - if ($type == 'html') { - $htmlbody = $body; - - if ($item['title'] != "") { - $htmlbody = "[b]".$item['title']."[/b]\n\n".$htmlbody; - } - - $htmlbody = bbcode($htmlbody, false, false, 7); - } - - $author = self::add_entry_author($doc, "author", $item["author-link"], $item); - $entry->appendChild($author); - - $dfrnowner = self::add_entry_author($doc, "dfrn:owner", $item["owner-link"], $item); - $entry->appendChild($dfrnowner); - - if (($item['parent'] != $item['id']) || ($item['parent-uri'] !== $item['uri']) || (($item['thr-parent'] !== '') && ($item['thr-parent'] !== $item['uri']))) { - $parent_item = (($item['thr-parent']) ? $item['thr-parent'] : $item['parent-uri']); - $parent = q("SELECT `guid`,`plink` FROM `item` WHERE `uri` = '%s' AND `uid` = %d", dbesc($parent_item), intval($item['uid'])); - $attributes = array("ref" => $parent_item, "type" => "text/html", - "href" => $parent[0]['plink'], - "dfrn:diaspora_guid" => $parent[0]['guid']); - xml::add_element($doc, $entry, "thr:in-reply-to", "", $attributes); - } - - // Add conversation data. This is used for OStatus - $conversation_href = System::baseUrl()."/display/".$owner["nick"]."/".$item["parent"]; - $conversation_uri = $conversation_href; - - if (isset($parent_item)) { - $r = dba::fetch_first("SELECT `conversation-uri`, `conversation-href` FROM `conversation` WHERE `item-uri` = ?", $item['parent-uri']); - if (dbm::is_result($r)) { - if ($r['conversation-uri'] != '') { - $conversation_uri = $r['conversation-uri']; - } - if ($r['conversation-href'] != '') { - $conversation_href = $r['conversation-href']; - } - } - } - - $attributes = array( - "href" => $conversation_href, - "ref" => $conversation_uri); - - xml::add_element($doc, $entry, "ostatus:conversation", $conversation_uri, $attributes); - - xml::add_element($doc, $entry, "id", $item["uri"]); - xml::add_element($doc, $entry, "title", $item["title"]); - - xml::add_element($doc, $entry, "published", datetime_convert("UTC","UTC",$item["created"]."+00:00",ATOM_TIME)); - xml::add_element($doc, $entry, "updated", datetime_convert("UTC","UTC",$item["edited"]."+00:00",ATOM_TIME)); - - // "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" => System::baseUrl()."/display/".$item["guid"])); - - // "comment-allow" is some old fashioned stuff for old Friendica versions. - // It is included in the rewritten code for completeness - if ($comment) { - xml::add_element($doc, $entry, "dfrn:comment-allow", intval($item['last-child'])); - } - - if ($item['location']) { - xml::add_element($doc, $entry, "dfrn:location", $item['location']); - } - - if ($item['coord']) { - xml::add_element($doc, $entry, "georss:point", $item['coord']); - } - - if (($item['private']) || strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) { - xml::add_element($doc, $entry, "dfrn:private", (($item['private']) ? $item['private'] : 1)); - } - - if ($item['extid']) { - xml::add_element($doc, $entry, "dfrn:extid", $item['extid']); - } - - if ($item['bookmark']) { - xml::add_element($doc, $entry, "dfrn:bookmark", "true"); - } - - if ($item['app']) { - xml::add_element($doc, $entry, "statusnet:notice_info", "", array("local_id" => $item['id'], "source" => $item['app'])); - } - - xml::add_element($doc, $entry, "dfrn:diaspora_guid", $item["guid"]); - - // The signed text contains the content in Markdown, the sender handle and the signatur for the content - // It is needed for relayed comments to Diaspora. - if ($item['signed_text']) { - $sign = base64_encode(json_encode(array('signed_text' => $item['signed_text'],'signature' => $item['signature'],'signer' => $item['signer']))); - xml::add_element($doc, $entry, "dfrn:diaspora_signature", $sign); - } - - xml::add_element($doc, $entry, "activity:verb", construct_verb($item)); - - if ($item['object-type'] != "") { - xml::add_element($doc, $entry, "activity:object-type", $item['object-type']); - } elseif ($item['id'] == $item['parent']) { - xml::add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_NOTE); - } else { - xml::add_element($doc, $entry, "activity:object-type", ACTIVITY_OBJ_COMMENT); - } - - $actobj = self::create_activity($doc, "activity:object", $item['object']); - if ($actobj) { - $entry->appendChild($actobj); - } - - $actarg = self::create_activity($doc, "activity:target", $item['target']); - if ($actarg) { - $entry->appendChild($actarg); - } - - $tags = item_getfeedtags($item); - - if (count($tags)) { - foreach ($tags as $t) { - if (($type != 'html') || ($t[0] != "@")) { - xml::add_element($doc, $entry, "category", "", array("scheme" => "X-DFRN:".$t[0].":".$t[1], "term" => $t[2])); - } - } - } - - if (count($tags)) { - foreach ($tags as $t) { - if ($t[0] == "@") { - $mentioned[$t[1]] = $t[1]; - } - } - } - - foreach ($mentioned AS $mention) { - $r = q("SELECT `forum`, `prv` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s'", - intval($owner["uid"]), - dbesc(normalise_link($mention))); - - if (dbm::is_result($r) && ($r[0]["forum"] || $r[0]["prv"])) { - xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned", - "ostatus:object-type" => ACTIVITY_OBJ_GROUP, - "href" => $mention)); - } else { - xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned", - "ostatus:object-type" => ACTIVITY_OBJ_PERSON, - "href" => $mention)); - } - } - - self::get_attachment($doc, $entry, $item); - - return $entry; - } - - /** - * @brief encrypts data via AES - * - * @param string $data The data that is to be encrypted - * @param string $key The AES key - * - * @return string encrypted data - */ - private static function aes_encrypt($data, $key) { - return openssl_encrypt($data, 'aes-128-ecb', $key, OPENSSL_RAW_DATA); - } - - /** - * @brief decrypts data via AES - * - * @param string $encrypted The encrypted data - * @param string $key The AES key - * - * @return string decrypted data - */ - public static function aes_decrypt($encrypted, $key) { - return openssl_decrypt($encrypted, 'aes-128-ecb', $key, OPENSSL_RAW_DATA); - } - - /** - * @brief Delivers the atom content to the contacts - * - * @param array $owner Owner record - * @param array $contactr Contact record of the receiver - * @param string $atom Content that will be transmitted - * @param bool $dissolve (to be documented) - * - * @return int Deliver status. -1 means an error. - * @todo Add array type-hint for $owner, $contact - */ - public static function deliver($owner,$contact,$atom, $dissolve = false) { - - $a = get_app(); - - $idtosend = $orig_id = (($contact['dfrn-id']) ? $contact['dfrn-id'] : $contact['issued-id']); - - if ($contact['duplex'] && $contact['dfrn-id']) { - $idtosend = '0:' . $orig_id; - } - if ($contact['duplex'] && $contact['issued-id']) { - $idtosend = '1:' . $orig_id; - } - - $rino = Config::get('system', 'rino_encrypt'); - $rino = intval($rino); - - logger("Local rino version: ". $rino, LOGGER_DEBUG); - - $ssl_val = intval(Config::get('system','ssl_policy')); - $ssl_policy = ''; - - switch ($ssl_val) { - case SSL_POLICY_FULL: - $ssl_policy = 'full'; - break; - case SSL_POLICY_SELFSIGN: - $ssl_policy = 'self'; - break; - case SSL_POLICY_NONE: - default: - $ssl_policy = 'none'; - break; - } - - $url = $contact['notify'] . '&dfrn_id=' . $idtosend . '&dfrn_version=' . DFRN_PROTOCOL_VERSION . (($rino) ? '&rino='.$rino : ''); - - logger('dfrn_deliver: ' . $url); - - $ret = z_fetch_url($url); - - if ($ret['errno'] == CURLE_OPERATION_TIMEDOUT) { - return -2; // timed out - } - - $xml = $ret['body']; - - $curl_stat = $a->get_curl_code(); - if (!$curl_stat) { - return -3; // timed out - } - - logger('dfrn_deliver: ' . $xml, LOGGER_DATA); - - if (! $xml) { - return 3; - } - - if (strpos($xml,'status) != 0) || (! strlen($res->challenge)) || (! strlen($res->dfrn_id))) { - return (($res->status) ? $res->status : 3); - } - - $postvars = array(); - $sent_dfrn_id = hex2bin((string) $res->dfrn_id); - $challenge = hex2bin((string) $res->challenge); - $perm = (($res->perm) ? $res->perm : null); - $dfrn_version = (float) (($res->dfrn_version) ? $res->dfrn_version : 2.0); - $rino_remote_version = intval($res->rino); - $page = (($owner['page-flags'] == PAGE_COMMUNITY) ? 1 : 0); - - logger("Remote rino version: ".$rino_remote_version." for ".$contact["url"], LOGGER_DEBUG); - - if ($owner['page-flags'] == PAGE_PRVGROUP) { - $page = 2; - } - - $final_dfrn_id = ''; - - if ($perm) { - if ((($perm == 'rw') && (! intval($contact['writable']))) - || (($perm == 'r') && (intval($contact['writable'])))) { - q("update contact set writable = %d where id = %d", - intval(($perm == 'rw') ? 1 : 0), - intval($contact['id']) - ); - $contact['writable'] = (string) 1 - intval($contact['writable']); - } - } - - if (($contact['duplex'] && strlen($contact['pubkey'])) - || ($owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey'])) - || ($contact['rel'] == CONTACT_IS_SHARING && strlen($contact['pubkey']))) { - openssl_public_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['pubkey']); - openssl_public_decrypt($challenge,$postvars['challenge'],$contact['pubkey']); - } else { - openssl_private_decrypt($sent_dfrn_id,$final_dfrn_id,$contact['prvkey']); - openssl_private_decrypt($challenge,$postvars['challenge'],$contact['prvkey']); - } - - $final_dfrn_id = substr($final_dfrn_id, 0, strpos($final_dfrn_id, '.')); - - if (strpos($final_dfrn_id,':') == 1) { - $final_dfrn_id = substr($final_dfrn_id,2); - } - - if ($final_dfrn_id != $orig_id) { - logger('dfrn_deliver: wrong dfrn_id.'); - // did not decode properly - cannot trust this site - return 3; - } - - $postvars['dfrn_id'] = $idtosend; - $postvars['dfrn_version'] = DFRN_PROTOCOL_VERSION; - if ($dissolve) { - $postvars['dissolve'] = '1'; - } - - - if ((($contact['rel']) && ($contact['rel'] != CONTACT_IS_SHARING) && (! $contact['blocked'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) { - $postvars['data'] = $atom; - $postvars['perm'] = 'rw'; - } else { - $postvars['data'] = str_replace('1','0',$atom); - $postvars['perm'] = 'r'; - } - - $postvars['ssl_policy'] = $ssl_policy; - - if ($page) { - $postvars['page'] = $page; - } - - - if ($rino > 0 && $rino_remote_version > 0 && (! $dissolve)) { - logger('rino version: '. $rino_remote_version); - - switch ($rino_remote_version) { - case 1: - // Deprecated rino version! - $key = openssl_random_pseudo_bytes(16); - $data = self::aes_encrypt($postvars['data'], $key); - break; - case 2: - // RINO 2 based on php-encryption - try { - $key = Crypto::createNewRandomKey(); - } catch (CryptoTestFailed $ex) { - logger('Cannot safely create a key'); - return -4; - } catch (CannotPerformOperation $ex) { - logger('Cannot safely create a key'); - return -5; - } - try { - $data = Crypto::encrypt($postvars['data'], $key); - } catch (CryptoTestFailed $ex) { - logger('Cannot safely perform encryption'); - return -6; - } catch (CannotPerformOperation $ex) { - logger('Cannot safely perform encryption'); - return -7; - } - break; - default: - logger("rino: invalid requested verision '$rino_remote_version'"); - return -8; - } - - $postvars['rino'] = $rino_remote_version; - $postvars['data'] = bin2hex($data); - - //logger('rino: sent key = ' . $key, LOGGER_DEBUG); - - - if ($dfrn_version >= 2.1) { - if (($contact['duplex'] && strlen($contact['pubkey'])) - || ($owner['page-flags'] == PAGE_COMMUNITY && strlen($contact['pubkey'])) - || ($contact['rel'] == CONTACT_IS_SHARING && strlen($contact['pubkey']))) { - openssl_public_encrypt($key,$postvars['key'],$contact['pubkey']); - } else { - openssl_private_encrypt($key,$postvars['key'],$contact['prvkey']); - } - - } else { - if (($contact['duplex'] && strlen($contact['prvkey'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) { - openssl_private_encrypt($key,$postvars['key'],$contact['prvkey']); - } else { - openssl_public_encrypt($key,$postvars['key'],$contact['pubkey']); - } - - } - - logger('md5 rawkey ' . md5($postvars['key'])); - - $postvars['key'] = bin2hex($postvars['key']); - } - - - logger('dfrn_deliver: ' . "SENDING: " . print_r($postvars,true), LOGGER_DATA); - - $xml = post_url($contact['notify'], $postvars); - - logger('dfrn_deliver: ' . "RECEIVED: " . $xml, LOGGER_DATA); - - $curl_stat = $a->get_curl_code(); - if ((!$curl_stat) || (!strlen($xml))) { - return -9; // timed out - } - - if (($curl_stat == 503) && (stristr($a->get_curl_headers(),'retry-after'))) { - return -10; - } - - if (strpos($xml,' NULL_DATE) { - logger("dfrn_deliver: $url back from the dead - removing mark for death"); - require_once('include/Contact.php'); - unmark_for_death($contact); - } - - $res = parse_xml_string($xml); - - if (!isset($res->status)) { - return -11; - } - - if (!empty($res->message)) { - logger('Delivery returned status '.$res->status.' - '.$res->message, LOGGER_DEBUG); - } - - return intval($res->status); - } - - /** - * @brief Add new birthday event for this person - * - * @param array $contact Contact record - * @param string $birthday Birthday of the contact - * @todo Add array type-hint for $contact - */ - private static function birthday_event($contact, $birthday) { - - // Check for duplicates - $r = q("SELECT `id` FROM `event` WHERE `uid` = %d AND `cid` = %d AND `start` = '%s' AND `type` = '%s' LIMIT 1", - intval($contact["uid"]), - intval($contact["id"]), - dbesc(datetime_convert("UTC","UTC", $birthday)), - dbesc("birthday")); - - if (dbm::is_result($r)) { - return; - } - - 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 - * @todo Find good type-hints for all parameter - */ - private static function fetchauthor($xpath, $context, $importer, $element, $onlyfetch, $xml = "") { - - $author = array(); - $author["name"] = $xpath->evaluate($element."/atom:name/text()", $context)->item(0)->nodeValue; - $author["link"] = $xpath->evaluate($element."/atom:uri/text()", $context)->item(0)->nodeValue; - - $r = q("SELECT `id`, `uid`, `url`, `network`, `avatar-date`, `name-date`, `uri-date`, `addr`, - `name`, `nick`, `about`, `location`, `keywords`, `xmpp`, `bdyear`, `bd`, `hidden`, `contact-type` - FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'", - intval($importer["uid"]), dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET)); - - if (dbm::is_result($r)) { - $contact = $r[0]; - $author["contact-id"] = $r[0]["id"]; - $author["network"] = $r[0]["network"]; - } else { - if (!$onlyfetch) { - logger("Contact ".$author["link"]." wasn't found for user ".$importer["uid"]." XML: ".$xml, LOGGER_DEBUG); - } - - $author["contact-id"] = $importer["id"]; - $author["network"] = $importer["network"]; - $onlyfetch = true; - } - - // 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) { - /// @TODO Rewrite these similar if () to one switch - 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) && ($href != "")) { - $avatarlist[$width] = $href; - } - } - if (count($avatarlist) > 0) { - krsort($avatarlist); - $author["avatar"] = current($avatarlist); - } - - if (dbm::is_result($r) && !$onlyfetch) { - logger("Check if contact details for contact " . $r[0]["id"] . " (" . $r[0]["nick"] . ") have to be updated.", LOGGER_DEBUG); - - $poco = array("url" => $contact["url"]); - - // When was the last change to name or uri? - $name_element = $xpath->query($element . "/atom:name", $context)->item(0); - foreach ($name_element->attributes AS $attributes) { - if ($attributes->name == "updated") { - $poco["name-date"] = $attributes->textContent; - } - } - - $link_element = $xpath->query($element . "/atom:link", $context)->item(0); - foreach ($link_element->attributes AS $attributes) { - if ($attributes->name == "updated") { - $poco["uri-date"] = $attributes->textContent; - } - } - - // Update contact data - $value = $xpath->evaluate($element . "/dfrn:handle/text()", $context)->item(0)->nodeValue; - if ($value != "") { - $poco["addr"] = $value; - } - - $value = $xpath->evaluate($element . "/poco:displayName/text()", $context)->item(0)->nodeValue; - if ($value != "") { - $poco["name"] = $value; - } - - $value = $xpath->evaluate($element . "/poco:preferredUsername/text()", $context)->item(0)->nodeValue; - if ($value != "") { - $poco["nick"] = $value; - } - - $value = $xpath->evaluate($element . "/poco:note/text()", $context)->item(0)->nodeValue; - if ($value != "") { - $poco["about"] = $value; - } - - $value = $xpath->evaluate($element . "/poco:address/poco:formatted/text()", $context)->item(0)->nodeValue; - if ($value != "") { - $poco["location"] = $value; - } - - /// @todo Only search for elements with "poco:type" = "xmpp" - $value = $xpath->evaluate($element . "/poco:ims/poco:value/text()", $context)->item(0)->nodeValue; - if ($value != "") { - $poco["xmpp"] = $value; - } - - /// @todo Add support for the following fields that we don't support by now in the contact table: - /// - poco:utcOffset - /// - poco:urls - /// - poco:locality - /// - poco:region - /// - poco:country - - // If the "hide" element is present then the profile isn't searchable. - $hide = intval($xpath->evaluate($element . "/dfrn:hide/text()", $context)->item(0)->nodeValue == "true"); - - logger("Hidden status for contact " . $contact["url"] . ": " . $hide, LOGGER_DEBUG); - - // If the contact isn't searchable then set the contact to "hidden". - // Problem: This can be manually overridden by the user. - if ($hide) { - $contact["hidden"] = true; - } - - // 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)) { - $poco["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); - - $poco["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", "0001-01-01"))) { - $bdyear = date("Y"); - $value = str_replace("0000", $bdyear, $value); - - if (strtotime($value) < time()) { - $value = str_replace($bdyear, $bdyear + 1, $value); - $bdyear = $bdyear + 1; - } - - $poco["bd"] = $value; - } - - $contact = array_merge($contact, $poco); - - 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["url"]); - 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])) { - logger("Difference for contact " . $contact["id"] . " in field '" . $field . "'. New value: '" . $contact[$field] . "', old value '" . $r[0][$field] . "'", LOGGER_DEBUG); - $update = true; - } - } - - foreach ($fields AS $field => $data) { - if ($contact[$field] != $r[0][$field]) { - logger("Difference for contact " . $contact["id"] . " in field '" . $field . "'. New value: '" . $contact[$field] . "', old value '" . $r[0][$field] . "'", LOGGER_DEBUG); - $update = true; - } - } - - if ($update) { - logger("Update contact data for contact " . $contact["id"] . " (" . $contact["nick"] . ")", LOGGER_DEBUG); - - q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `about` = '%s', `location` = '%s', - `addr` = '%s', `keywords` = '%s', `bdyear` = '%s', `bd` = '%s', `hidden` = %d, - `xmpp` = '%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"]), intval($contact["hidden"]), dbesc($contact["xmpp"]), - dbesc(dbm::date($contact["name-date"])), dbesc(dbm::date($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"]))); - - /* - * The generation is a sign for the reliability of the provided data. - * It is used in the socgraph.php to prevent that old contact data - * that was relayed over several servers can overwrite contact - * data that we received directly. - */ - - $poco["generation"] = 2; - $poco["photo"] = $author["avatar"]; - $poco["hide"] = $hide; - $poco["contact-type"] = $contact["contact-type"]; - $gcid = update_gcontact($poco); - - link_gcontact($gcid, $importer["uid"], $contact["id"]); - } - - return($author); - } - - /** - * @brief Transforms activity objects into an XML string - * - * @param object $xpath XPath object - * @param object $activity Activity object - * @param text $element element name - * - * @return string XML string - * @todo Find good type-hints for all parameter - */ - private static 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)); - } - - $links = $xpath->query("atom:link", $activity); - if (is_object($links)) { - foreach ($links AS $link) { - $obj_element->appendChild($obj_doc->importNode($link, true)); - } - } - - $content = $xpath->query("atom:content", $activity)->item(0); - if (is_object($content)) { - $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); - } - - /** - * @brief Processes the mail elements - * - * @param object $xpath XPath object - * @param object $mail mail elements - * @param array $importer Record of the importer user mixed with contact of the content - * @todo Find good type-hints for all parameter - */ - private static function process_mail($xpath, $mail, $importer) { - - logger("Processing mails"); - - /// @TODO Rewrite this to one statement - $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; - - dba::insert('mail', $msg); - - // send notifications. - /// @TODO Arange this mess - $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."); - } - - /** - * @brief Processes the suggestion elements - * - * @param object $xpath XPath object - * @param object $suggestion suggestion elements - * @param array $importer Record of the importer user mixed with contact of the content - * @todo Find good type-hints for all parameter - */ - private static function process_suggestion($xpath, $suggestion, $importer) { - $a = get_app(); - - logger("Processing suggestions"); - - /// @TODO Rewrite this to one statement - $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"]) - ); - - /* - * The valid result means the friend we're about to send a friend - * suggestion already has them in their contact, which means no further - * action is required. - * - * @see https://github.com/friendica/friendica/pull/3254#discussion_r107315246 - */ - if (dbm::is_result($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 (dbm::is_result($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) - ); - - /* - * The valid result means the friend we're about to send a friend - * suggestion already has them in their contact, which means no further - * action is required. - * - * @see https://github.com/friendica/friendica/pull/3254#discussion_r107315246 - */ - if (dbm::is_result($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 no record in fcontact is found, below INSERT statement will not - * link an introduction to it. - */ - if (!dbm::is_result($r)) { - // database record did not get created. Quietly give up. - killme(); - } - - $fid = $r[0]["id"]; - - $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" => System::baseUrl()."/notifications/intros", - "source_name" => $importer["name"], - "source_link" => $importer["url"], - "source_photo" => $importer["photo"], - "verb" => ACTIVITY_REQ_FRIEND, - "otype" => "intro" - )); - - return true; - - } - - /** - * @brief Processes the relocation elements - * - * @param object $xpath XPath object - * @param object $relocation relocation elements - * @param array $importer Record of the importer user mixed with contact of the content - * @todo Find good type-hints for all parameter - */ - private static function process_relocation($xpath, $relocation, $importer) { - - logger("Processing relocations"); - - /// @TODO Rewrite this to one statement - $relocate = array(); - $relocate["uid"] = $importer["importer_uid"]; - $relocate["cid"] = $importer["id"]; - $relocate["url"] = $xpath->query("dfrn:url/text()", $relocation)->item(0)->nodeValue; - $relocate["addr"] = $xpath->query("dfrn:addr/text()", $relocation)->item(0)->nodeValue; - $relocate["name"] = $xpath->query("dfrn:name/text()", $relocation)->item(0)->nodeValue; - $relocate["avatar"] = $xpath->query("dfrn:avatar/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; - - if (($relocate["avatar"] == "") && ($relocate["photo"] != "")) { - $relocate["avatar"] = $relocate["photo"]; - } - - if ($relocate["addr"] == "") { - $relocate["addr"] = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$3@$2", $relocate["url"]); - } - - // update contact - $r = q("SELECT `photo`, `url` FROM `contact` WHERE `id` = %d AND `uid` = %d;", - intval($importer["id"]), - intval($importer["importer_uid"])); - - if (!dbm::is_result($r)) { - logger("Query failed to execute, no result returned in " . __FUNCTION__); - return false; - } - - $old = $r[0]; - - // Update the gcontact entry - $relocate["server_url"] = preg_replace("=(https?://)(.*)/profile/(.*)=ism", "$1$2", $relocate["url"]); - - $x = q("UPDATE `gcontact` SET - `name` = '%s', - `photo` = '%s', - `url` = '%s', - `nurl` = '%s', - `addr` = '%s', - `connect` = '%s', - `notify` = '%s', - `server_url` = '%s' - WHERE `nurl` = '%s';", - dbesc($relocate["name"]), - dbesc($relocate["avatar"]), - dbesc($relocate["url"]), - dbesc(normalise_link($relocate["url"])), - dbesc($relocate["addr"]), - dbesc($relocate["addr"]), - dbesc($relocate["notify"]), - dbesc($relocate["server_url"]), - dbesc(normalise_link($old["url"]))); - - // Update the contact table. We try to find every entry. - $x = q("UPDATE `contact` SET - `name` = '%s', - `avatar` = '%s', - `url` = '%s', - `nurl` = '%s', - `addr` = '%s', - `request` = '%s', - `confirm` = '%s', - `notify` = '%s', - `poll` = '%s', - `site-pubkey` = '%s' - WHERE (`id` = %d AND `uid` = %d) OR (`nurl` = '%s');", - dbesc($relocate["name"]), - dbesc($relocate["avatar"]), - dbesc($relocate["url"]), - dbesc(normalise_link($relocate["url"])), - dbesc($relocate["addr"]), - dbesc($relocate["request"]), - dbesc($relocate["confirm"]), - dbesc($relocate["notify"]), - dbesc($relocate["poll"]), - dbesc($relocate["sitepubkey"]), - intval($importer["id"]), - intval($importer["importer_uid"]), - dbesc(normalise_link($old["url"]))); - - update_contact_avatar($relocate["avatar"], $importer["importer_uid"], $importer["id"], true); - - if ($x === false) { - return false; - } - - // update items - /// @todo This is an extreme performance killer - $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) { - $r = q("SELECT `id` FROM `item` WHERE `%s` = '%s' AND `uid` = %d LIMIT 1", - $n, dbesc($f[0]), - intval($importer["importer_uid"])); - - if (dbm::is_result($r)) { - $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; - } - - /** - * @brief Updates an item - * - * @param array $current the current item record - * @param array $item the new item record - * @param array $importer Record of the importer user mixed with contact of the content - * @param int $entrytype Is it a toplevel entry, a comment or a relayed comment? - * @todo set proper type-hints (array?) - */ - private static 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; - } - - $fields = array('title' => $item["title"], 'body' => $item["body"], - 'tag' => $item["tag"], 'changed' => datetime_convert(), - 'edited' => datetime_convert("UTC", "UTC", $item["edited"])); - - $condition = array("`uri` = ? AND `uid` IN (0, ?)", $item["uri"], $importer["importer_uid"]); - dba::update('item', $fields, $condition); - - create_tags_from_itemuri($item["uri"], $importer["importer_uid"]); - update_thread_uri($item["uri"], $importer["importer_uid"]); - - $changed = true; - - if ($entrytype == DFRN_REPLY_RC) { - Worker::add(PRIORITY_HIGH, "notifier","comment-import", $current["id"]); - } - } - - // update last-child if it changes - if ($item["last-child"] && ($item["last-child"] != $current["last-child"])) { - $r = q("UPDATE `item` SET `last-child` = 0, `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` IN (0, %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` IN (0, %d)", - intval($item["last-child"]), - dbesc(datetime_convert()), - dbesc($item["uri"]), - intval($importer["importer_uid"]) - ); - } - return $changed; - } - - /** - * @brief Detects the entry type of the item - * - * @param array $importer Record of the importer user mixed with contact of the content - * @param array $item the new item record - * - * @return int Is it a toplevel entry, a comment or a relayed comment? - * @todo set proper type-hints (array?) - */ - private static 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 (dbm::is_result($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 (dbm::is_result($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. - */ - - /// @TODO Maybe merge these if() blocks into one? - if ($is_a_remote_action && $community && (!$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; - } - - } - - /** - * @brief Send a "poke" - * - * @param array $item the new item record - * @param array $importer Record of the importer user mixed with contact of the content - * @param int $posted_id The record number of item record that was just posted - * @todo set proper type-hints (array?) - */ - private static 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? - foreach ($xo->link as $l) { - $atts = $l->attributes(); - switch ($atts["rel"]) { - case "alternate": - $Blink = $atts["href"]; - break; - default: - break; - } - } - - if ($Blink && link_compare($Blink, System::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" => System::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"] - )); - } - } - } - - /** - * @brief Processes several actions, depending on the verb - * - * @param int $entrytype Is it a toplevel entry, a comment or a relayed comment? - * @param array $importer Record of the importer user mixed with contact of the content - * @param array $item the new item record - * @param bool $is_like Is the verb a "like"? - * - * @return bool Should the processing of the entries be continued? - * @todo set proper type-hints (array?) - */ - private static function process_verbs($entrytype, $importer, &$item, &$is_like) { - - logger("Process verb ".$item["verb"]." and object-type ".$item["object-type"]." for entrytype ".$entrytype, LOGGER_DEBUG); - - if (($entrytype == DFRN_TOP_LEVEL)) { - // The filling of the the "contact" variable is done for legcy reasons - // The functions below are partly used by ostatus.php as well - where we have this variable - $r = q("SELECT * FROM `contact` WHERE `id` = %d", intval($importer["id"])); - $contact = $r[0]; - $nickname = $contact["nick"]; - - // Big question: Do we need these functions? They were part of the "consume_feed" function. - // This function once was responsible for DFRN and OStatus. - if (activity_match($item["verb"], ACTIVITY_FOLLOW)) { - logger("New follower"); - new_follower($importer, $contact, $item, $nickname); - return false; - } - if (activity_match($item["verb"], ACTIVITY_UNFOLLOW)) { - logger("Lost follower"); - lose_follower($importer, $contact, $item); - return false; - } - if (activity_match($item["verb"], ACTIVITY_REQ_FRIEND)) { - logger("New friend request"); - new_follower($importer, $contact, $item, $nickname, true); - return false; - } - if (activity_match($item["verb"], ACTIVITY_UNFRIEND)) { - logger("Lost sharer"); - lose_sharer($importer, $contact, $item); - return false; - } - } else { - if (($item["verb"] == ACTIVITY_LIKE) - || ($item["verb"] == ACTIVITY_DISLIKE) - || ($item["verb"] == ACTIVITY_ATTEND) - || ($item["verb"] == ACTIVITY_ATTENDNO) - || ($item["verb"] == ACTIVITY_ATTENDMAYBE)) { - $is_like = true; - $item["type"] = "activity"; - $item["gravity"] = GRAVITY_LIKE; - // only one like or dislike per person - // splitted into two queries for performance issues - $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `parent-uri` = '%s' AND NOT `deleted` LIMIT 1", - intval($item["uid"]), - dbesc($item["author-link"]), - dbesc($item["verb"]), - dbesc($item["parent-uri"]) - ); - if (dbm::is_result($r)) { - return false; - } - - $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `author-link` = '%s' AND `verb` = '%s' AND `thr-parent` = '%s' AND NOT `deleted` LIMIT 1", - intval($item["uid"]), - dbesc($item["author-link"]), - dbesc($item["verb"]), - dbesc($item["parent-uri"]) - ); - if (dbm::is_result($r)) { - return false; - } - } else { - $is_like = false; - } - - if (($item["verb"] == ACTIVITY_TAG) && ($item["object-type"] == ACTIVITY_OBJ_TAGTERM)) { - - $xo = parse_xml_string($item["object"],false); - $xt = parse_xml_string($item["target"],false); - - if ($xt->type == ACTIVITY_OBJ_NOTE) { - $r = q("SELECT `id`, `tag` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", - dbesc($xt->id), - intval($importer["importer_uid"]) - ); - - if (!dbm::is_result($r)) { - logger("Query failed to execute, no result returned in " . __FUNCTION__); - return false; - } - - // extract tag, if not duplicate, add to parent item - if ($xo->content) { - if (!(stristr($r[0]["tag"],trim($xo->content)))) { - q("UPDATE `item` SET `tag` = '%s' WHERE `id` = %d", - dbesc($r[0]["tag"] . (strlen($r[0]["tag"]) ? ',' : '') . '#[url=' . $xo->id . ']'. $xo->content . '[/url]'), - intval($r[0]["id"]) - ); - create_tags_from_item($r[0]["id"]); - } - } - } - } - } - return true; - } - - /** - * @brief Processes the link elements - * - * @param object $links link elements - * @param array $item the item record - * @todo set proper type-hints - */ - private static function parse_links($links, &$item) { - $rel = ""; - $href = ""; - $type = ""; - $length = "0"; - $title = ""; - foreach ($links AS $link) { - foreach ($link->attributes AS $attributes) { - /// @TODO Rewrite these repeated (same) if () statements to a switch() - 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 != "") && ($href != "")) { - switch ($rel) { - case "alternate": - $item["plink"] = $href; - break; - case "enclosure": - $enclosure = $href; - if (strlen($item["attach"])) { - $item["attach"] .= ","; - } - - $item["attach"] .= '[attach]href="' . $href . '" length="' . $length . '" type="' . $type . '" title="' . $title . '"[/attach]'; - break; - } - } - } - } - - /** - * @brief Processes the entry elements which contain the items and comments - * - * @param array $header Array of the header elements that always stay the same - * @param object $xpath XPath object - * @param object $entry entry elements - * @param array $importer Record of the importer user mixed with contact of the content - * @todo Add type-hints - */ - private static function process_entry($header, $xpath, $entry, $importer, $xml) { - - logger("Processing entries"); - - $item = $header; - - $item["protocol"] = PROTOCOL_DFRN; - - $item["source"] = $xml; - - // Get the uri - $item["uri"] = $xpath->query("atom:id/text()", $entry)->item(0)->nodeValue; - - $item["edited"] = $xpath->query("atom:updated/text()", $entry)->item(0)->nodeValue; - - $current = 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"]) - ); - - // Is there an existing item? - if (dbm::is_result($current) && edited_timestamp_is_newer($current[0], $item) && - (datetime_convert("UTC","UTC",$item["edited"]) < $current[0]["edited"])) { - logger("Item ".$item["uri"]." already existed.", LOGGER_DEBUG); - return; - } - - // 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["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']); - } - - /// @todo We should check for a repeated post and if we know the repeated author. - - // We don't need the content element since "dfrn:env" is always present - //$item["body"] = $xpath->query("atom:content/text()", $entry)->item(0)->nodeValue; - - $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:bookmark/text()", $entry)->item(0)->nodeValue == "true") { - $item["bookmark"] = true; - } - - $notice_info = $xpath->query("statusnet:notice_info", $entry); - if ($notice_info && ($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) { - $term = ""; - $scheme = ""; - foreach ($category->attributes AS $attributes) { - if ($attributes->name == "term") { - $term = $attributes->textContent; - } - - if ($attributes->name == "scheme") { - $scheme = $attributes->textContent; - } - } - - if (($term != "") && ($scheme != "")) { - $parts = explode(":", $scheme); - if ((count($parts) >= 4) && (array_shift($parts) == "X-DFRN")) { - $termhash = array_shift($parts); - $termurl = implode(":", $parts); - - if (strlen($item["tag"])) { - $item["tag"] .= ","; - } - - $item["tag"] .= $termhash . "[url=" . $termurl . "]" . $term . "[/url]"; - } - } - } - } - - $enclosure = ""; - - $links = $xpath->query("atom:link", $entry); - if ($links) { - self::parse_links($links, $item); - } - - $item['conversation-uri'] = $xpath->query('ostatus:conversation/text()', $entry)->item(0)->nodeValue; - - $conv = $xpath->query('ostatus:conversation', $entry); - if (is_object($conv->item(0))) { - foreach ($conv->item(0)->attributes AS $attributes) { - if ($attributes->name == "ref") { - $item['conversation-uri'] = $attributes->textContent; - } - if ($attributes->name == "href") { - $item['conversation-href'] = $attributes->textContent; - } - } - } - - // 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"]) && ($owner["network"] != "")) { - $item["network"] = $owner["network"]; - } - - if ($item["contact-id"] != $author["contact-id"]) { - $item["contact-id"] = $author["contact-id"]; - } - - if (($item["network"] != $author["network"]) && ($author["network"] != "")) { - $item["network"] = $author["network"]; - } - - /// @TODO maybe remove this old-lost code then? - // This code was taken from the old DFRN code - // When activated, forums don't work. - // And: Why should we disallow commenting by followers? - // the behaviour is now similar to the Diaspora part. - //if ($importer["rel"] == CONTACT_IS_FOLLOWER) { - // logger("Contact ".$importer["id"]." is only follower. Quitting", LOGGER_DEBUG); - // return; - //} - } - - 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; - } - - // Is it an event? - if ($item["object-type"] == ACTIVITY_OBJ_EVENT) { - logger("Item ".$item["uri"]." seems to contain an event.", LOGGER_DEBUG); - $ev = bbtoevent($item["body"]); - if ((x($ev, "desc") || x($ev, "summary")) && x($ev, "start")) { - logger("Event in item ".$item["uri"]." was found.", LOGGER_DEBUG); - /// @TODO Mixure of "/' ahead ... - $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 (dbm::is_result($r)) { - $ev["id"] = $r[0]["id"]; - } - - $event_id = event_store($ev); - logger("Event ".$event_id." was stored", LOGGER_DEBUG); - return; - } - } - } - - if (!self::process_verbs($entrytype, $importer, $item, $is_like)) { - logger("Exiting because 'process_verbs' told us so", LOGGER_DEBUG); - return; - } - - // Update content if 'updated' changes - if (dbm::is_result($current)) { - 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))) { - $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 (dbm::is_result($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 && ($entrytype == DFRN_REPLY_RC)) { - logger("Notifying followers about comment ".$posted_id, LOGGER_DEBUG); - Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $posted_id); - } - - return true; - } - } else { // $entrytype == DFRN_TOP_LEVEL - if (!link_compare($item["owner-link"],$importer["url"])) { - /* - * The item owner info is not our contact. It's OK and is to be expected if this is a tgroup delivery, - * but otherwise there's a possible data mixup on the sender's system. - * 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); - } - } - - /** - * @brief Deletes items - * - * @param object $xpath XPath object - * @param object $deletion deletion elements - * @param array $importer Record of the importer user mixed with contact of the content - * @todo set proper type-hints - */ - private static function process_deletion($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 || !$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 (!dbm::is_result($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 (dbm::is_result($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` IN (0, %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` IN (0, %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` IN (0, %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 (dbm::is_result($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); - Worker::add(PRIORITY_HIGH, "notifier","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 - * @return integer Import status - * @todo set proper type-hints - */ - public static function import($xml, $importer, $sort_by_date = false) { - - if ($xml == "") { - return 400; - } - - $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 - - // The "atom:author" is only present in feeds - if ($xpath->query("/atom:feed/atom:author")->length > 0) { - self::fetchauthor($xpath, $doc->firstChild, $importer, "atom:author", false, $xml); - } - - // Only the "dfrn:owner" in the head section contains all data - if ($xpath->query("/atom:feed/dfrn:owner")->length > 0) { - self::fetchauthor($xpath, $doc->firstChild, $importer, "dfrn:owner", false, $xml); - } - - logger("Import DFRN message for user " . $importer["uid"] . " from contact " . $importer["id"], LOGGER_DEBUG); - - // The account type is new since 3.5.1 - if ($xpath->query("/atom:feed/dfrn:account_type")->length > 0) { - $accounttype = intval($xpath->evaluate("/atom:feed/dfrn:account_type/text()", $context)->item(0)->nodeValue); - - if ($accounttype != $importer["contact-type"]) { - dba::update('contact', array('contact-type' => $accounttype), array('id' => $importer["id"])); - } - } - - // is it a public forum? Private forums aren't supported with this method - // This is deprecated since 3.5.1 - $forum = intval($xpath->evaluate("/atom:feed/dfrn:community/text()", $context)->item(0)->nodeValue); - - if ($forum != $importer["forum"]) { - $condition = array('`forum` != ? AND `id` = ?', $forum, $importer["id"]); - dba::update('contact', array('forum' => $forum), $condition); - } - - // We are processing relocations even if we are ignoring a contact - $relocations = $xpath->query("/atom:feed/dfrn:relocate"); - foreach ($relocations AS $relocation) { - self::process_relocation($xpath, $relocation, $importer); - } - - 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 403; - } - - $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); - } - - $deletions = $xpath->query("/atom:feed/at:deleted-entry"); - foreach ($deletions AS $deletion) { - self::process_deletion($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, $xml); - } - } 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, $xml); - } - } - logger("Import done for user " . $importer["uid"] . " from contact " . $importer["id"], LOGGER_DEBUG); - return 200; - } -} diff --git a/include/diaspora.php b/include/diaspora.php deleted file mode 100644 index ea32295275..0000000000 --- a/include/diaspora.php +++ /dev/null @@ -1,3943 +0,0 @@ -children('http://salmon-protocol.org/ns/magic-env'); - - if (sizeof($children) == 0) { - logger("XML has no children"); - return false; - } - - $handle = ""; - - $data = base64url_decode($children->data); - $type = $children->data->attributes()->type[0]; - - $encoding = $children->encoding; - - $alg = $children->alg; - - $sig = base64url_decode($children->sig); - $key_id = $children->sig->attributes()->key_id[0]; - if ($key_id != "") - $handle = base64url_decode($key_id); - - $b64url_data = base64url_encode($data); - $msg = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data); - - $signable_data = $msg.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg); - - $key = self::key($handle); - - $verify = rsa_verify($signable_data, $sig, $key); - if (!$verify) { - logger('Message did not verify. Discarding.'); - return false; - } - - return $data; - } - - /** - * @brief encrypts data via AES - * - * @param string $key The AES key - * @param string $iv The IV (is used for CBC encoding) - * @param string $data The data that is to be encrypted - * - * @return string encrypted data - */ - private static function aes_encrypt($key, $iv, $data) { - return openssl_encrypt($data, 'aes-256-cbc', str_pad($key, 32, "\0"), OPENSSL_RAW_DATA, str_pad($iv, 16, "\0")); - } - - /** - * @brief decrypts data via AES - * - * @param string $key The AES key - * @param string $iv The IV (is used for CBC encoding) - * @param string $encrypted The encrypted data - * - * @return string decrypted data - */ - private static function aes_decrypt($key, $iv, $encrypted) { - return openssl_decrypt($encrypted,'aes-256-cbc', str_pad($key, 32, "\0"), OPENSSL_RAW_DATA,str_pad($iv, 16, "\0")); - } - - /** - * @brief: Decodes incoming Diaspora message in the new format - * - * @param array $importer Array of the importer user - * @param string $raw raw post message - * - * @return array - * 'message' -> decoded Diaspora XML message - * 'author' -> author diaspora handle - * 'key' -> author public key (converted to pkcs#8) - */ - public static function decode_raw($importer, $raw) { - $data = json_decode($raw); - - // Is it a private post? Then decrypt the outer Salmon - if (is_object($data)) { - $encrypted_aes_key_bundle = base64_decode($data->aes_key); - $ciphertext = base64_decode($data->encrypted_magic_envelope); - - $outer_key_bundle = ''; - @openssl_private_decrypt($encrypted_aes_key_bundle, $outer_key_bundle, $importer['prvkey']); - $j_outer_key_bundle = json_decode($outer_key_bundle); - - if (!is_object($j_outer_key_bundle)) { - logger('Outer Salmon did not verify. Discarding.'); - http_status_exit(400); - } - - $outer_iv = base64_decode($j_outer_key_bundle->iv); - $outer_key = base64_decode($j_outer_key_bundle->key); - - $xml = diaspora::aes_decrypt($outer_key, $outer_iv, $ciphertext); - } else { - $xml = $raw; - } - - $basedom = parse_xml_string($xml); - - if (!is_object($basedom)) { - logger('Received data does not seem to be an XML. Discarding. '.$xml); - http_status_exit(400); - } - - $base = $basedom->children(NAMESPACE_SALMON_ME); - - // Not sure if this cleaning is needed - $data = str_replace(array(" ", "\t", "\r", "\n"), array("", "", "", ""), $base->data); - - // Build the signed data - $type = $base->data[0]->attributes()->type[0]; - $encoding = $base->encoding; - $alg = $base->alg; - $signed_data = $data.'.'.base64url_encode($type).'.'.base64url_encode($encoding).'.'.base64url_encode($alg); - - // This is the signature - $signature = base64url_decode($base->sig); - - // Get the senders' public key - $key_id = $base->sig[0]->attributes()->key_id[0]; - $author_addr = base64_decode($key_id); - $key = diaspora::key($author_addr); - - $verify = rsa_verify($signed_data, $signature, $key); - if (!$verify) { - logger('Message did not verify. Discarding.'); - http_status_exit(400); - } - - return array('message' => (string)base64url_decode($base->data), - 'author' => unxmlify($author_addr), - 'key' => (string)$key); - } - - /** - * @brief: Decodes incoming Diaspora message in the deprecated format - * - * @param array $importer Array of the importer user - * @param string $xml urldecoded Diaspora salmon - * - * @return array - * 'message' -> decoded Diaspora XML message - * 'author' -> author diaspora handle - * 'key' -> author public key (converted to pkcs#8) - */ - public static function decode($importer, $xml) { - - $public = false; - $basedom = parse_xml_string($xml); - - if (!is_object($basedom)) { - logger("XML is not parseable."); - return false; - } - $children = $basedom->children('https://joindiaspora.com/protocol'); - - if ($children->header) { - $public = true; - $author_link = str_replace('acct:','',$children->header->author_id); - } else { - // This happens with posts from a relais - if (!$importer) { - logger("This is no private post in the old format", LOGGER_DEBUG); - return false; - } - - $encrypted_header = json_decode(base64_decode($children->encrypted_header)); - - $encrypted_aes_key_bundle = base64_decode($encrypted_header->aes_key); - $ciphertext = base64_decode($encrypted_header->ciphertext); - - $outer_key_bundle = ''; - openssl_private_decrypt($encrypted_aes_key_bundle,$outer_key_bundle,$importer['prvkey']); - - $j_outer_key_bundle = json_decode($outer_key_bundle); - - $outer_iv = base64_decode($j_outer_key_bundle->iv); - $outer_key = base64_decode($j_outer_key_bundle->key); - - $decrypted = self::aes_decrypt($outer_key, $outer_iv, $ciphertext); - - logger('decrypted: '.$decrypted, LOGGER_DEBUG); - $idom = parse_xml_string($decrypted); - - $inner_iv = base64_decode($idom->iv); - $inner_aes_key = base64_decode($idom->aes_key); - - $author_link = str_replace('acct:','',$idom->author_id); - } - - $dom = $basedom->children(NAMESPACE_SALMON_ME); - - // figure out where in the DOM tree our data is hiding - - if ($dom->provenance->data) - $base = $dom->provenance; - elseif ($dom->env->data) - $base = $dom->env; - elseif ($dom->data) - $base = $dom; - - if (!$base) { - logger('unable to locate salmon data in xml'); - http_status_exit(400); - } - - - // Stash the signature away for now. We have to find their key or it won't be good for anything. - $signature = base64url_decode($base->sig); - - // unpack the data - - // strip whitespace so our data element will return to one big base64 blob - $data = str_replace(array(" ","\t","\r","\n"),array("","","",""),$base->data); - - - // stash away some other stuff for later - - $type = $base->data[0]->attributes()->type[0]; - $keyhash = $base->sig[0]->attributes()->keyhash[0]; - $encoding = $base->encoding; - $alg = $base->alg; - - - $signed_data = $data.'.'.base64url_encode($type).'.'.base64url_encode($encoding).'.'.base64url_encode($alg); - - - // decode the data - $data = base64url_decode($data); - - - if ($public) - $inner_decrypted = $data; - else { - - // Decode the encrypted blob - - $inner_encrypted = base64_decode($data); - $inner_decrypted = self::aes_decrypt($inner_aes_key, $inner_iv, $inner_encrypted); - } - - if (!$author_link) { - logger('Could not retrieve author URI.'); - http_status_exit(400); - } - // Once we have the author URI, go to the web and try to find their public key - // (first this will look it up locally if it is in the fcontact cache) - // This will also convert diaspora public key from pkcs#1 to pkcs#8 - - logger('Fetching key for '.$author_link); - $key = self::key($author_link); - - if (!$key) { - logger('Could not retrieve author key.'); - http_status_exit(400); - } - - $verify = rsa_verify($signed_data,$signature,$key); - - if (!$verify) { - logger('Message did not verify. Discarding.'); - http_status_exit(400); - } - - logger('Message verified.'); - - return array('message' => (string)$inner_decrypted, - 'author' => unxmlify($author_link), - 'key' => (string)$key); - } - - - /** - * @brief Dispatches public messages and find the fitting receivers - * - * @param array $msg The post that will be dispatched - * - * @return int The message id of the generated message, "true" or "false" if there was an error - */ - public static function dispatch_public($msg) { - - $enabled = intval(Config::get("system", "diaspora_enabled")); - if (!$enabled) { - logger("diaspora is disabled"); - return false; - } - - if (!($postdata = self::valid_posting($msg))) { - logger("Invalid posting"); - return false; - } - - $fields = $postdata['fields']; - - // Is it a an action (comment, like, ...) for our own post? - if (isset($fields->parent_guid) && !$postdata["relayed"]) { - $guid = notags(unxmlify($fields->parent_guid)); - $importer = self::importer_for_guid($guid); - if (is_array($importer)) { - logger("delivering to origin: ".$importer["name"]); - $message_id = self::dispatch($importer, $msg, $fields); - return $message_id; - } - } - - // Process item retractions. This has to be done separated from the other stuff, - // since retractions for comments could come even from non followers. - if (!empty($fields) && in_array($fields->getName(), array('retraction'))) { - $target = notags(unxmlify($fields->target_type)); - if (in_array($target, array("Comment", "Like", "Post", "Reshare", "StatusMessage"))) { - logger('processing retraction for '.$target, LOGGER_DEBUG); - $importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE); - $message_id = self::dispatch($importer, $msg, $fields); - return $message_id; - } - } - - // Now distribute it to the followers - $r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN - (SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s') - AND NOT `account_expired` AND NOT `account_removed`", - dbesc(NETWORK_DIASPORA), - dbesc($msg["author"]) - ); - - if (dbm::is_result($r)) { - foreach ($r as $rr) { - logger("delivering to: ".$rr["username"]); - self::dispatch($rr, $msg, $fields); - } - } elseif (!Config::get('system', 'relay_subscribe', false)) { - logger("Unwanted message from ".$msg["author"]." send by ".$_SERVER["REMOTE_ADDR"]." with ".$_SERVER["HTTP_USER_AGENT"].": ".print_r($msg, true), LOGGER_DEBUG); - } else { - // Use a dummy importer to import the data for the public copy - $importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE); - $message_id = self::dispatch($importer, $msg, $fields); - } - - return $message_id; - } - - /** - * @brief Dispatches the different message types to the different functions - * - * @param array $importer Array of the importer user - * @param array $msg The post that will be dispatched - * @param object $fields SimpleXML object that contains the message - * - * @return int The message id of the generated message, "true" or "false" if there was an error - */ - public static function dispatch($importer, $msg, $fields = null) { - - // The sender is the handle of the contact that sent the message. - // This will often be different with relayed messages (for example "like" and "comment") - $sender = $msg["author"]; - - // This is only needed for private postings since this is already done for public ones before - if (is_null($fields)) { - if (!($postdata = self::valid_posting($msg))) { - logger("Invalid posting"); - return false; - } - $fields = $postdata['fields']; - } - - $type = $fields->getName(); - - logger("Received message type ".$type." from ".$sender." for user ".$importer["uid"], LOGGER_DEBUG); - - switch ($type) { - case "account_migration": - return self::receiveAccountMigration($importer, $fields); - - case "account_deletion": - return self::receive_account_deletion($importer, $fields); - - case "comment": - return self::receive_comment($importer, $sender, $fields, $msg["message"]); - - case "contact": - return self::receive_contact_request($importer, $fields); - - case "conversation": - return self::receive_conversation($importer, $msg, $fields); - - case "like": - return self::receive_like($importer, $sender, $fields); - - case "message": - return self::receive_message($importer, $fields); - - case "participation": // Not implemented - return self::receive_participation($importer, $fields); - - case "photo": // Not implemented - return self::receive_photo($importer, $fields); - - case "poll_participation": // Not implemented - return self::receive_poll_participation($importer, $fields); - - case "profile": - return self::receive_profile($importer, $fields); - - case "reshare": - return self::receive_reshare($importer, $fields, $msg["message"]); - - case "retraction": - return self::receive_retraction($importer, $sender, $fields); - - case "status_message": - return self::receive_status_message($importer, $fields, $msg["message"]); - - default: - logger("Unknown message type ".$type); - return false; - } - - return true; - } - - /** - * @brief Checks if a posting is valid and fetches the data fields. - * - * This function does not only check the signature. - * It also does the conversion between the old and the new diaspora format. - * - * @param array $msg Array with the XML, the sender handle and the sender signature - * - * @return bool|array If the posting is valid then an array with an SimpleXML object is returned - */ - private static function valid_posting($msg) { - - $data = parse_xml_string($msg["message"]); - - if (!is_object($data)) { - logger("No valid XML ".$msg["message"], LOGGER_DEBUG); - return false; - } - - $first_child = $data->getName(); - - // Is this the new or the old version? - if ($data->getName() == "XML") { - $oldXML = true; - foreach ($data->post->children() as $child) - $element = $child; - } else { - $oldXML = false; - $element = $data; - } - - $type = $element->getName(); - $orig_type = $type; - - logger("Got message type ".$type.": ".$msg["message"], LOGGER_DATA); - - // All retractions are handled identically from now on. - // In the new version there will only be "retraction". - if (in_array($type, array("signed_retraction", "relayable_retraction"))) - $type = "retraction"; - - if ($type == "request") - $type = "contact"; - - $fields = new SimpleXMLElement("<".$type."/>"); - - $signed_data = ""; - - foreach ($element->children() AS $fieldname => $entry) { - if ($oldXML) { - // Translation for the old XML structure - if ($fieldname == "diaspora_handle") { - $fieldname = "author"; - } - if ($fieldname == "participant_handles") { - $fieldname = "participants"; - } - if (in_array($type, array("like", "participation"))) { - if ($fieldname == "target_type") { - $fieldname = "parent_type"; - } - } - if ($fieldname == "sender_handle") { - $fieldname = "author"; - } - if ($fieldname == "recipient_handle") { - $fieldname = "recipient"; - } - if ($fieldname == "root_diaspora_id") { - $fieldname = "root_author"; - } - if ($type == "status_message") { - if ($fieldname == "raw_message") { - $fieldname = "text"; - } - } - if ($type == "retraction") { - if ($fieldname == "post_guid") { - $fieldname = "target_guid"; - } - if ($fieldname == "type") { - $fieldname = "target_type"; - } - } - } - - if (($fieldname == "author_signature") && ($entry != "")) - $author_signature = base64_decode($entry); - elseif (($fieldname == "parent_author_signature") && ($entry != "")) - $parent_author_signature = base64_decode($entry); - elseif (!in_array($fieldname, array("author_signature", "parent_author_signature", "target_author_signature"))) { - if ($signed_data != "") { - $signed_data .= ";"; - $signed_data_parent .= ";"; - } - - $signed_data .= $entry; - } - if (!in_array($fieldname, array("parent_author_signature", "target_author_signature")) || - ($orig_type == "relayable_retraction")) - xml::copy($entry, $fields, $fieldname); - } - - // This is something that shouldn't happen at all. - if (in_array($type, array("status_message", "reshare", "profile"))) - if ($msg["author"] != $fields->author) { - logger("Message handle is not the same as envelope sender. Quitting this message."); - return false; - } - - // Only some message types have signatures. So we quit here for the other types. - if (!in_array($type, array("comment", "like"))) { - return array("fields" => $fields, "relayed" => false); - } - // No author_signature? This is a must, so we quit. - if (!isset($author_signature)) { - logger("No author signature for type ".$type." - Message: ".$msg["message"], LOGGER_DEBUG); - return false; - } - - if (isset($parent_author_signature)) { - $relayed = true; - - $key = self::key($msg["author"]); - - if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256")) { - logger("No valid parent author signature for parent author ".$msg["author"]. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$parent_author_signature, LOGGER_DEBUG); - return false; - } - } else { - $relayed = false; - } - - $key = self::key($fields->author); - - if (!rsa_verify($signed_data, $author_signature, $key, "sha256")) { - logger("No valid author signature for author ".$fields->author. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$author_signature, LOGGER_DEBUG); - return false; - } else { - return array("fields" => $fields, "relayed" => $relayed); - } - } - - /** - * @brief Fetches the public key for a given handle - * - * @param string $handle The handle - * - * @return string The public key - */ - private static function key($handle) { - $handle = strval($handle); - - logger("Fetching diaspora key for: ".$handle); - - $r = self::person_by_handle($handle); - if ($r) - return $r["pubkey"]; - - return ""; - } - - /** - * @brief Fetches data for a given handle - * - * @param string $handle The handle - * - * @return array the queried data - */ - public static function person_by_handle($handle) { - - $r = q("SELECT * FROM `fcontact` WHERE `network` = '%s' AND `addr` = '%s' LIMIT 1", - dbesc(NETWORK_DIASPORA), - dbesc($handle) - ); - if ($r) { - $person = $r[0]; - logger("In cache ".print_r($r,true), LOGGER_DEBUG); - - // update record occasionally so it doesn't get stale - $d = strtotime($person["updated"]." +00:00"); - if ($d < strtotime("now - 14 days")) - $update = true; - - if ($person["guid"] == "") - $update = true; - } - - if (!$person || $update) { - logger("create or refresh", LOGGER_DEBUG); - $r = Probe::uri($handle, NETWORK_DIASPORA); - - // Note that Friendica contacts will return a "Diaspora person" - // if Diaspora connectivity is enabled on their server - if ($r && ($r["network"] === NETWORK_DIASPORA)) { - self::add_fcontact($r, $update); - $person = $r; - } - } - return $person; - } - - /** - * @brief Updates the fcontact table - * - * @param array $arr The fcontact data - * @param bool $update Update or insert? - * - * @return string The id of the fcontact entry - */ - private static function add_fcontact($arr, $update = false) { - - if ($update) { - $r = q("UPDATE `fcontact` SET - `name` = '%s', - `photo` = '%s', - `request` = '%s', - `nick` = '%s', - `addr` = '%s', - `guid` = '%s', - `batch` = '%s', - `notify` = '%s', - `poll` = '%s', - `confirm` = '%s', - `alias` = '%s', - `pubkey` = '%s', - `updated` = '%s' - WHERE `url` = '%s' AND `network` = '%s'", - dbesc($arr["name"]), - dbesc($arr["photo"]), - dbesc($arr["request"]), - dbesc($arr["nick"]), - dbesc(strtolower($arr["addr"])), - dbesc($arr["guid"]), - dbesc($arr["batch"]), - dbesc($arr["notify"]), - dbesc($arr["poll"]), - dbesc($arr["confirm"]), - dbesc($arr["alias"]), - dbesc($arr["pubkey"]), - dbesc(datetime_convert()), - dbesc($arr["url"]), - dbesc($arr["network"]) - ); - } else { - $r = q("INSERT INTO `fcontact` (`url`,`name`,`photo`,`request`,`nick`,`addr`, `guid`, - `batch`, `notify`,`poll`,`confirm`,`network`,`alias`,`pubkey`,`updated`) - VALUES ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')", - dbesc($arr["url"]), - dbesc($arr["name"]), - dbesc($arr["photo"]), - dbesc($arr["request"]), - dbesc($arr["nick"]), - dbesc($arr["addr"]), - dbesc($arr["guid"]), - dbesc($arr["batch"]), - dbesc($arr["notify"]), - dbesc($arr["poll"]), - dbesc($arr["confirm"]), - dbesc($arr["network"]), - dbesc($arr["alias"]), - dbesc($arr["pubkey"]), - dbesc(datetime_convert()) - ); - } - - return $r; - } - - /** - * @brief get a handle (user@domain.tld) from a given contact id or gcontact id - * - * @param int $contact_id The id in the contact table - * @param int $gcontact_id The id in the gcontact table - * - * @return string the handle - */ - public static function handle_from_contact($contact_id, $gcontact_id = 0) { - $handle = false; - - logger("contact id is ".$contact_id." - gcontact id is ".$gcontact_id, LOGGER_DEBUG); - - if ($gcontact_id != 0) { - $r = q("SELECT `addr` FROM `gcontact` WHERE `id` = %d AND `addr` != ''", - intval($gcontact_id)); - - if (dbm::is_result($r)) { - return strtolower($r[0]["addr"]); - } - } - - $r = q("SELECT `network`, `addr`, `self`, `url`, `nick` FROM `contact` WHERE `id` = %d", - intval($contact_id)); - - if (dbm::is_result($r)) { - $contact = $r[0]; - - logger("contact 'self' = ".$contact['self']." 'url' = ".$contact['url'], LOGGER_DEBUG); - - if ($contact['addr'] != "") { - $handle = $contact['addr']; - } else { - $baseurl_start = strpos($contact['url'],'://') + 3; - $baseurl_length = strpos($contact['url'],'/profile') - $baseurl_start; // allows installations in a subdirectory--not sure how Diaspora will handle - $baseurl = substr($contact['url'], $baseurl_start, $baseurl_length); - $handle = $contact['nick'].'@'.$baseurl; - } - } - - return strtolower($handle); - } - - /** - * @brief get a url (scheme://domain.tld/u/user) from a given Diaspora* - * fcontact guid - * - * @param mixed $fcontact_guid Hexadecimal string guid - * - * @return string the contact url or null - */ - public static function url_from_contact_guid($fcontact_guid) { - logger("fcontact guid is ".$fcontact_guid, LOGGER_DEBUG); - - $r = q("SELECT `url` FROM `fcontact` WHERE `url` != '' AND `network` = '%s' AND `guid` = '%s'", - dbesc(NETWORK_DIASPORA), - dbesc($fcontact_guid) - ); - - if (dbm::is_result($r)) { - return $r[0]['url']; - } - - return null; - } - - /** - * @brief Get a contact id for a given handle - * - * @param int $uid The user id - * @param string $handle The handle in the format user@domain.tld - * - * @return The contact id - */ - private static function contact_by_handle($uid, $handle) { - - // First do a direct search on the contact table - $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `addr` = '%s' LIMIT 1", - intval($uid), - dbesc($handle) - ); - - if (dbm::is_result($r)) { - return $r[0]; - } else { - /* - * We haven't found it? - * We use another function for it that will possibly create a contact entry. - */ - $cid = get_contact($handle, $uid); - - if ($cid > 0) { - /// @TODO Contact retrieval should be encapsulated into an "entity" class like `Contact` - $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($cid)); - - if (dbm::is_result($r)) { - return $r[0]; - } - } - } - - $handle_parts = explode("@", $handle); - $nurl_sql = "%%://".$handle_parts[1]."%%/profile/".$handle_parts[0]; - $r = q("SELECT * FROM `contact` WHERE `network` = '%s' AND `uid` = %d AND `nurl` LIKE '%s' LIMIT 1", - dbesc(NETWORK_DFRN), - intval($uid), - dbesc($nurl_sql) - ); - if (dbm::is_result($r)) { - return $r[0]; - } - - logger("Haven't found contact for user ".$uid." and handle ".$handle, LOGGER_DEBUG); - return false; - } - - /** - * @brief Check if posting is allowed for this contact - * - * @param array $importer Array of the importer user - * @param array $contact The contact that is checked - * @param bool $is_comment Is the check for a comment? - * - * @return bool is the contact allowed to post? - */ - private static function post_allow($importer, $contact, $is_comment = false) { - - /* - * Perhaps we were already sharing with this person. Now they're sharing with us. - * That makes us friends. - * Normally this should have handled by getting a request - but this could get lost - */ - if ($contact["rel"] == CONTACT_IS_FOLLOWER && in_array($importer["page-flags"], array(PAGE_FREELOVE))) { - dba::update('contact', array('rel' => CONTACT_IS_FRIEND, 'writable' => true), - array('id' => $contact["id"], 'uid' => $contact["uid"])); - - $contact["rel"] = CONTACT_IS_FRIEND; - logger("defining user ".$contact["nick"]." as friend"); - } - - // We don't seem to like that person - if ($contact["blocked"] || $contact["readonly"] || $contact["archive"]) { - // Maybe blocked, don't accept. - return false; - // We are following this person? - } elseif (($contact["rel"] == CONTACT_IS_SHARING) || ($contact["rel"] == CONTACT_IS_FRIEND)) { - // Yes, then it is fine. - return true; - // Is it a post to a community? - } elseif (($contact["rel"] == CONTACT_IS_FOLLOWER) && ($importer["page-flags"] == PAGE_COMMUNITY)) { - // That's good - return true; - // Is the message a global user or a comment? - } elseif (($importer["uid"] == 0) || $is_comment) { - // Messages for the global users and comments are always accepted - return true; - } - - return false; - } - - /** - * @brief Fetches the contact id for a handle and checks if posting is allowed - * - * @param array $importer Array of the importer user - * @param string $handle The checked handle in the format user@domain.tld - * @param bool $is_comment Is the check for a comment? - * - * @return array The contact data - */ - private static function allowed_contact_by_handle($importer, $handle, $is_comment = false) { - $contact = self::contact_by_handle($importer["uid"], $handle); - if (!$contact) { - logger("A Contact for handle ".$handle." and user ".$importer["uid"]." was not found"); - // If a contact isn't found, we accept it anyway if it is a comment - if ($is_comment) { - return $importer; - } else { - return false; - } - } - - if (!self::post_allow($importer, $contact, $is_comment)) { - logger("The handle: ".$handle." is not allowed to post to user ".$importer["uid"]); - return false; - } - return $contact; - } - - /** - * @brief Does the message already exists on the system? - * - * @param int $uid The user id - * @param string $guid The guid of the message - * - * @return int|bool message id if the message already was stored into the system - or false. - */ - private static function message_exists($uid, $guid) { - $r = q("SELECT `id` FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", - intval($uid), - dbesc($guid) - ); - - if (dbm::is_result($r)) { - logger("message ".$guid." already exists for user ".$uid); - return $r[0]["id"]; - } - - return false; - } - - /** - * @brief Checks for links to posts in a message - * - * @param array $item The item array - */ - private static function fetch_guid($item) { - $expression = "=diaspora://.*?/post/([0-9A-Za-z\-_@.:]{15,254}[0-9A-Za-z])=ism"; - preg_replace_callback($expression, - function ($match) use ($item) { - return self::fetch_guid_sub($match, $item); - }, $item["body"]); - - preg_replace_callback("&\[url=/posts/([^\[\]]*)\](.*)\[\/url\]&Usi", - function ($match) use ($item) { - return self::fetch_guid_sub($match, $item); - }, $item["body"]); - } - - /** - * @brief Checks for relative /people/* links in an item body to match local - * contacts or prepends the remote host taken from the author link. - * - * @param string $body The item body to replace links from - * @param string $author_link The author link for missing local contact fallback - * - * @return the replaced string - */ - public static function replace_people_guid($body, $author_link) { - $return = preg_replace_callback("&\[url=/people/([^\[\]]*)\](.*)\[\/url\]&Usi", - function ($match) use ($author_link) { - // $match - // 0 => '[url=/people/0123456789abcdef]Foo Bar[/url]' - // 1 => '0123456789abcdef' - // 2 => 'Foo Bar' - $handle = self::url_from_contact_guid($match[1]); - - if ($handle) { - $return = '@[url='.$handle.']'.$match[2].'[/url]'; - } else { - // No local match, restoring absolute remote URL from author scheme and host - $author_url = parse_url($author_link); - $return = '[url='.$author_url['scheme'].'://'.$author_url['host'].'/people/'.$match[1].']'.$match[2].'[/url]'; - } - - return $return; - }, $body); - - return $return; - } - - /** - * @brief sub function of "fetch_guid" which checks for links in messages - * - * @param array $match array containing a link that has to be checked for a message link - * @param array $item The item array - */ - private static function fetch_guid_sub($match, $item) { - if (!self::store_by_guid($match[1], $item["author-link"])) - self::store_by_guid($match[1], $item["owner-link"]); - } - - /** - * @brief Fetches an item with a given guid from a given server - * - * @param string $guid the message guid - * @param string $server The server address - * @param int $uid The user id of the user - * - * @return int the message id of the stored message or false - */ - private static function store_by_guid($guid, $server, $uid = 0) { - $serverparts = parse_url($server); - $server = $serverparts["scheme"]."://".$serverparts["host"]; - - logger("Trying to fetch item ".$guid." from ".$server, LOGGER_DEBUG); - - $msg = self::message($guid, $server); - - if (!$msg) - return false; - - logger("Successfully fetched item ".$guid." from ".$server, LOGGER_DEBUG); - - // Now call the dispatcher - return self::dispatch_public($msg); - } - - /** - * @brief Fetches a message from a server - * - * @param string $guid message guid - * @param string $server The url of the server - * @param int $level Endless loop prevention - * - * @return array - * 'message' => The message XML - * 'author' => The author handle - * 'key' => The public key of the author - */ - private static function message($guid, $server, $level = 0) { - - if ($level > 5) - return false; - - // This will work for new Diaspora servers and Friendica servers from 3.5 - $source_url = $server."/fetch/post/".urlencode($guid); - - logger("Fetch post from ".$source_url, LOGGER_DEBUG); - - $envelope = fetch_url($source_url); - if ($envelope) { - logger("Envelope was fetched.", LOGGER_DEBUG); - $x = self::verify_magic_envelope($envelope); - if (!$x) - logger("Envelope could not be verified.", LOGGER_DEBUG); - else - logger("Envelope was verified.", LOGGER_DEBUG); - } else - $x = false; - - // This will work for older Diaspora and Friendica servers - if (!$x) { - $source_url = $server."/p/".urlencode($guid).".xml"; - logger("Fetch post from ".$source_url, LOGGER_DEBUG); - - $x = fetch_url($source_url); - if (!$x) - return false; - } - - $source_xml = parse_xml_string($x); - - if (!is_object($source_xml)) - return false; - - if ($source_xml->post->reshare) { - // Reshare of a reshare - old Diaspora version - logger("Message is a reshare", LOGGER_DEBUG); - return self::message($source_xml->post->reshare->root_guid, $server, ++$level); - } elseif ($source_xml->getName() == "reshare") { - // Reshare of a reshare - new Diaspora version - logger("Message is a new reshare", LOGGER_DEBUG); - return self::message($source_xml->root_guid, $server, ++$level); - } - - $author = ""; - - // Fetch the author - for the old and the new Diaspora version - if ($source_xml->post->status_message->diaspora_handle) - $author = (string)$source_xml->post->status_message->diaspora_handle; - elseif ($source_xml->author && ($source_xml->getName() == "status_message")) - $author = (string)$source_xml->author; - - // If this isn't a "status_message" then quit - if (!$author) { - logger("Message doesn't seem to be a status message", LOGGER_DEBUG); - return false; - } - - $msg = array("message" => $x, "author" => $author); - - $msg["key"] = self::key($msg["author"]); - - return $msg; - } - - /** - * @brief Fetches the item record of a given guid - * - * @param int $uid The user id - * @param string $guid message guid - * @param string $author The handle of the item - * @param array $contact The contact of the item owner - * - * @return array the item record - */ - private static function parent_item($uid, $guid, $author, $contact) { - $r = q("SELECT `id`, `parent`, `body`, `wall`, `uri`, `guid`, `private`, `origin`, - `author-name`, `author-link`, `author-avatar`, - `owner-name`, `owner-link`, `owner-avatar` - FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", - intval($uid), dbesc($guid)); - - if (!$r) { - $result = self::store_by_guid($guid, $contact["url"], $uid); - - if (!$result) { - $person = self::person_by_handle($author); - $result = self::store_by_guid($guid, $person["url"], $uid); - } - - if ($result) { - logger("Fetched missing item ".$guid." - result: ".$result, LOGGER_DEBUG); - - $r = q("SELECT `id`, `body`, `wall`, `uri`, `private`, `origin`, - `author-name`, `author-link`, `author-avatar`, - `owner-name`, `owner-link`, `owner-avatar` - FROM `item` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", - intval($uid), dbesc($guid)); - } - } - - if (!$r) { - logger("parent item not found: parent: ".$guid." - user: ".$uid); - return false; - } else { - logger("parent item found: parent: ".$guid." - user: ".$uid); - return $r[0]; - } - } - - /** - * @brief returns contact details - * - * @param array $contact The default contact if the person isn't found - * @param array $person The record of the person - * @param int $uid The user id - * - * @return array - * 'cid' => contact id - * 'network' => network type - */ - private static function author_contact_by_url($contact, $person, $uid) { - - $r = q("SELECT `id`, `network`, `url` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1", - dbesc(normalise_link($person["url"])), intval($uid)); - if ($r) { - $cid = $r[0]["id"]; - $network = $r[0]["network"]; - - // We are receiving content from a user that possibly is about to be terminated - // This means the user is vital, so we remove a possible termination date. - unmark_for_death($r[0]); - } else { - $cid = $contact["id"]; - $network = NETWORK_DIASPORA; - } - - return array("cid" => $cid, "network" => $network); - } - - /** - * @brief Is the profile a hubzilla profile? - * - * @param string $url The profile link - * - * @return bool is it a hubzilla server? - */ - public static function is_redmatrix($url) { - return(strstr($url, "/channel/")); - } - - /** - * @brief Generate a post link with a given handle and message guid - * - * @param string $addr The user handle - * @param string $guid message guid - * - * @return string the post link - */ - private static function plink($addr, $guid, $parent_guid = '') { - $r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr)); - - // Fallback - if (!dbm::is_result($r)) { - if ($parent_guid != '') { - return "https://".substr($addr,strpos($addr,"@") + 1)."/posts/".$parent_guid."#".$guid; - } else { - return "https://".substr($addr,strpos($addr,"@") + 1)."/posts/".$guid; - } - } - - // Friendica contacts are often detected as Diaspora contacts in the "fcontact" table - // So we try another way as well. - $s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"]))); - if (dbm::is_result($s)) { - $r[0]["network"] = $s[0]["network"]; - } - - if ($r[0]["network"] == NETWORK_DFRN) { - return str_replace("/profile/".$r[0]["nick"]."/", "/display/".$guid, $r[0]["url"]."/"); - } - - if (self::is_redmatrix($r[0]["url"])) { - return $r[0]["url"]."/?f=&mid=".$guid; - } - - if ($parent_guid != '') { - return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$parent_guid."#".$guid; - } else { - return "https://".substr($addr,strpos($addr,"@")+1)."/posts/".$guid; - } - } - - /** - * @brief Receives account migration - * - * @param array $importer Array of the importer user - * @param object $data The message object - * - * @return bool Success - */ - private static function receiveAccountMigration($importer, $data) { - $old_handle = notags(unxmlify($data->author)); - $new_handle = notags(unxmlify($data->profile->author)); - $signature = notags(unxmlify($data->signature)); - - $contact = self::contact_by_handle($importer["uid"], $old_handle); - if (!$contact) { - logger("cannot find contact for sender: ".$old_handle." and user ".$importer["uid"]); - return false; - } - - logger("Got migration for ".$old_handle.", to ".$new_handle." with user ".$importer["uid"]); - - // Check signature - $signed_text = 'AccountMigration:'.$old_handle.':'.$new_handle; - $key = self::key($old_handle); - if (!rsa_verify($signed_text, $signature, $key, "sha256")) { - logger('No valid signature for migration.'); - return false; - } - - // Update the profile - self::receive_profile($importer, $data->profile); - - // change the technical stuff in contact and gcontact - $data = Probe::uri($new_handle); - if ($data['network'] == NETWORK_PHANTOM) { - logger('Account for '.$new_handle." couldn't be probed."); - return false; - } - - $fields = array('url' => $data['url'], 'nurl' => normalise_link($data['url']), - 'name' => $data['name'], 'nick' => $data['nick'], - 'addr' => $data['addr'], 'batch' => $data['batch'], - 'notify' => $data['notify'], 'poll' => $data['poll'], - 'network' => $data['network']); - - dba::update('contact', $fields, array('addr' => $old_handle)); - - $fields = array('url' => $data['url'], 'nurl' => normalise_link($data['url']), - 'name' => $data['name'], 'nick' => $data['nick'], - 'addr' => $data['addr'], 'connect' => $data['addr'], - 'notify' => $data['notify'], 'photo' => $data['photo'], - 'server_url' => $data['baseurl'], 'network' => $data['network']); - - dba::update('gcontact', $fields, array('addr' => $old_handle)); - - logger('Contacts are updated.'); - - // update items - /// @todo This is an extreme performance killer - $fields = array( - 'owner-link' => array($contact["url"], $data["url"]), - 'author-link' => array($contact["url"], $data["url"]), - ); - foreach ($fields as $n=>$f) { - $r = q("SELECT `id` FROM `item` WHERE `%s` = '%s' AND `uid` = %d LIMIT 1", - $n, dbesc($f[0]), - intval($importer["uid"])); - - if (dbm::is_result($r)) { - $x = q("UPDATE `item` SET `%s` = '%s' WHERE `%s` = '%s' AND `uid` = %d", - $n, dbesc($f[1]), - $n, dbesc($f[0]), - intval($importer["uid"])); - - if ($x === false) { - return false; - } - } - } - - logger('Items are updated.'); - - return true; - } - - /** - * @brief Processes an account deletion - * - * @param array $importer Array of the importer user - * @param object $data The message object - * - * @return bool Success - */ - private static function receive_account_deletion($importer, $data) { - - /// @todo Account deletion should remove the contact from the global contacts as well - - $author = notags(unxmlify($data->author)); - - $contact = self::contact_by_handle($importer["uid"], $author); - if (!$contact) { - logger("cannot find contact for author: ".$author); - return false; - } - - // We now remove the contact - contact_remove($contact["id"]); - return true; - } - - /** - * @brief Fetch the uri from our database if we already have this item (maybe from ourselves) - * - * @param string $author Author handle - * @param string $guid Message guid - * @param boolean $onlyfound Only return uri when found in the database - * - * @return string The constructed uri or the one from our database - */ - private static function get_uri_from_guid($author, $guid, $onlyfound = false) { - - $r = q("SELECT `uri` FROM `item` WHERE `guid` = '%s' LIMIT 1", dbesc($guid)); - if (dbm::is_result($r)) { - return $r[0]["uri"]; - } elseif (!$onlyfound) { - return $author.":".$guid; - } - - return ""; - } - - /** - * @brief Fetch the guid from our database with a given uri - * - * @param string $author Author handle - * @param string $uri Message uri - * - * @return string The post guid - */ - private static function get_guid_from_uri($uri, $uid) { - - $r = q("SELECT `guid` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($uri), intval($uid)); - if (dbm::is_result($r)) { - return $r[0]["guid"]; - } else { - return false; - } - } - - /** - * @brief Find the best importer for a comment, like, ... - * - * @param string $guid The guid of the item - * - * @return array|boolean the origin owner of that post - or false - */ - private static function importer_for_guid($guid) { - $item = dba::fetch_first("SELECT `uid` FROM `item` WHERE `origin` AND `guid` = ? LIMIT 1", $guid); - - if (dbm::is_result($item)) { - logger("Found user ".$item['uid']." as owner of item ".$guid, LOGGER_DEBUG); - $contact = dba::fetch_first("SELECT * FROM `contact` WHERE `self` AND `uid` = ?", $item['uid']); - if (dbm::is_result($contact)) { - return $contact; - } - } - return false; - } - - /** - * @brief Processes an incoming comment - * - * @param array $importer Array of the importer user - * @param string $sender The sender of the message - * @param object $data The message object - * @param string $xml The original XML of the message - * - * @return int The message id of the generated comment or "false" if there was an error - */ - private static function receive_comment($importer, $sender, $data, $xml) { - $author = notags(unxmlify($data->author)); - $guid = notags(unxmlify($data->guid)); - $parent_guid = notags(unxmlify($data->parent_guid)); - $text = unxmlify($data->text); - - if (isset($data->created_at)) { - $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); - } else { - $created_at = datetime_convert(); - } - - if (isset($data->thread_parent_guid)) { - $thread_parent_guid = notags(unxmlify($data->thread_parent_guid)); - $thr_uri = self::get_uri_from_guid("", $thread_parent_guid, true); - } else { - $thr_uri = ""; - } - - $contact = self::allowed_contact_by_handle($importer, $sender, true); - if (!$contact) { - return false; - } - - $message_id = self::message_exists($importer["uid"], $guid); - if ($message_id) { - return true; - } - - $parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact); - if (!$parent_item) { - return false; - } - - $person = self::person_by_handle($author); - if (!is_array($person)) { - logger("unable to find author details"); - return false; - } - - // Fetch the contact id - if we know this contact - $author_contact = self::author_contact_by_url($contact, $person, $importer["uid"]); - - $datarray = array(); - - $datarray["uid"] = $importer["uid"]; - $datarray["contact-id"] = $author_contact["cid"]; - $datarray["network"] = $author_contact["network"]; - - $datarray["author-name"] = $person["name"]; - $datarray["author-link"] = $person["url"]; - $datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]); - - $datarray["owner-name"] = $contact["name"]; - $datarray["owner-link"] = $contact["url"]; - $datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]); - - $datarray["guid"] = $guid; - $datarray["uri"] = self::get_uri_from_guid($author, $guid); - - $datarray["type"] = "remote-comment"; - $datarray["verb"] = ACTIVITY_POST; - $datarray["gravity"] = GRAVITY_COMMENT; - - if ($thr_uri != "") { - $datarray["parent-uri"] = $thr_uri; - } else { - $datarray["parent-uri"] = $parent_item["uri"]; - } - - $datarray["object-type"] = ACTIVITY_OBJ_COMMENT; - - $datarray["protocol"] = PROTOCOL_DIASPORA; - $datarray["source"] = $xml; - - $datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at; - - $datarray["plink"] = self::plink($author, $guid, $parent_item['guid']); - - $body = diaspora2bb($text); - - $datarray["body"] = self::replace_people_guid($body, $person["url"]); - - self::fetch_guid($datarray); - - $message_id = item_store($datarray); - - if ($message_id <= 0) { - return false; - } - - if ($message_id) { - logger("Stored comment ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); - } - - // If we are the origin of the parent we store the original data and notify our followers - if ($message_id && $parent_item["origin"]) { - - // Formerly we stored the signed text, the signature and the author in different fields. - // We now store the raw data so that we are more flexible. - dba::insert('sign', array('iid' => $message_id, 'signed_text' => json_encode($data))); - - // notify others - Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $message_id); - } - - return true; - } - - /** - * @brief processes and stores private messages - * - * @param array $importer Array of the importer user - * @param array $contact The contact of the message - * @param object $data The message object - * @param array $msg Array of the processed message, author handle and key - * @param object $mesg The private message - * @param array $conversation The conversation record to which this message belongs - * - * @return bool "true" if it was successful - */ - private static function receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation) { - $author = notags(unxmlify($data->author)); - $guid = notags(unxmlify($data->guid)); - $subject = notags(unxmlify($data->subject)); - - // "diaspora_handle" is the element name from the old version - // "author" is the element name from the new version - if ($mesg->author) { - $msg_author = notags(unxmlify($mesg->author)); - } elseif ($mesg->diaspora_handle) { - $msg_author = notags(unxmlify($mesg->diaspora_handle)); - } else { - return false; - } - - $msg_guid = notags(unxmlify($mesg->guid)); - $msg_conversation_guid = notags(unxmlify($mesg->conversation_guid)); - $msg_text = unxmlify($mesg->text); - $msg_created_at = datetime_convert("UTC", "UTC", notags(unxmlify($mesg->created_at))); - - if ($msg_conversation_guid != $guid) { - logger("message conversation guid does not belong to the current conversation."); - return false; - } - - $body = diaspora2bb($msg_text); - $message_uri = $msg_author.":".$msg_guid; - - $person = self::person_by_handle($msg_author); - - dba::lock('mail'); - - $r = q("SELECT `id` FROM `mail` WHERE `guid` = '%s' AND `uid` = %d LIMIT 1", - dbesc($msg_guid), - intval($importer["uid"]) - ); - if (dbm::is_result($r)) { - logger("duplicate message already delivered.", LOGGER_DEBUG); - return false; - } - - q("INSERT INTO `mail` (`uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`) - VALUES (%d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')", - intval($importer["uid"]), - dbesc($msg_guid), - intval($conversation["id"]), - dbesc($person["name"]), - dbesc($person["photo"]), - dbesc($person["url"]), - intval($contact["id"]), - dbesc($subject), - dbesc($body), - 0, - 0, - dbesc($message_uri), - dbesc($author.":".$guid), - dbesc($msg_created_at) - ); - - dba::unlock(); - - dba::update('conv', array('updated' => datetime_convert()), array('id' => $conversation["id"])); - - notification(array( - "type" => NOTIFY_MAIL, - "notify_flags" => $importer["notify-flags"], - "language" => $importer["language"], - "to_name" => $importer["username"], - "to_email" => $importer["email"], - "uid" =>$importer["uid"], - "item" => array("subject" => $subject, "body" => $body), - "source_name" => $person["name"], - "source_link" => $person["url"], - "source_photo" => $person["thumb"], - "verb" => ACTIVITY_POST, - "otype" => "mail" - )); - return true; - } - - /** - * @brief Processes new private messages (answers to private messages are processed elsewhere) - * - * @param array $importer Array of the importer user - * @param array $msg Array of the processed message, author handle and key - * @param object $data The message object - * - * @return bool Success - */ - private static function receive_conversation($importer, $msg, $data) { - $author = notags(unxmlify($data->author)); - $guid = notags(unxmlify($data->guid)); - $subject = notags(unxmlify($data->subject)); - $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); - $participants = notags(unxmlify($data->participants)); - - $messages = $data->message; - - if (!count($messages)) { - logger("empty conversation"); - return false; - } - - $contact = self::allowed_contact_by_handle($importer, $msg["author"], true); - if (!$contact) - return false; - - $conversation = null; - - $c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", - intval($importer["uid"]), - dbesc($guid) - ); - if ($c) - $conversation = $c[0]; - else { - $r = q("INSERT INTO `conv` (`uid`, `guid`, `creator`, `created`, `updated`, `subject`, `recips`) - VALUES (%d, '%s', '%s', '%s', '%s', '%s', '%s')", - intval($importer["uid"]), - dbesc($guid), - dbesc($author), - dbesc($created_at), - dbesc(datetime_convert()), - dbesc($subject), - dbesc($participants) - ); - if ($r) - $c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", - intval($importer["uid"]), - dbesc($guid) - ); - - if ($c) - $conversation = $c[0]; - } - if (!$conversation) { - logger("unable to create conversation."); - return false; - } - - foreach ($messages as $mesg) - self::receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation); - - return true; - } - - /** - * @brief Creates the body for a "like" message - * - * @param array $contact The contact that send us the "like" - * @param array $parent_item The item array of the parent item - * @param string $guid message guid - * - * @return string the body - */ - private static function construct_like_body($contact, $parent_item, $guid) { - $bodyverb = t('%1$s likes %2$s\'s %3$s'); - - $ulink = "[url=".$contact["url"]."]".$contact["name"]."[/url]"; - $alink = "[url=".$parent_item["author-link"]."]".$parent_item["author-name"]."[/url]"; - $plink = "[url=".System::baseUrl()."/display/".urlencode($guid)."]".t("status")."[/url]"; - - return sprintf($bodyverb, $ulink, $alink, $plink); - } - - /** - * @brief Creates a XML object for a "like" - * - * @param array $importer Array of the importer user - * @param array $parent_item The item array of the parent item - * - * @return string The XML - */ - private static function construct_like_object($importer, $parent_item) { - $objtype = ACTIVITY_OBJ_NOTE; - $link = ''; - $parent_body = $parent_item["body"]; - - $xmldata = array("object" => array("type" => $objtype, - "local" => "1", - "id" => $parent_item["uri"], - "link" => $link, - "title" => "", - "content" => $parent_body)); - - return xml::from_array($xmldata, $xml, true); - } - - /** - * @brief Processes "like" messages - * - * @param array $importer Array of the importer user - * @param string $sender The sender of the message - * @param object $data The message object - * - * @return int The message id of the generated like or "false" if there was an error - */ - private static function receive_like($importer, $sender, $data) { - $author = notags(unxmlify($data->author)); - $guid = notags(unxmlify($data->guid)); - $parent_guid = notags(unxmlify($data->parent_guid)); - $parent_type = notags(unxmlify($data->parent_type)); - $positive = notags(unxmlify($data->positive)); - - // likes on comments aren't supported by Diaspora - only on posts - // But maybe this will be supported in the future, so we will accept it. - if (!in_array($parent_type, array("Post", "Comment"))) - return false; - - $contact = self::allowed_contact_by_handle($importer, $sender, true); - if (!$contact) - return false; - - $message_id = self::message_exists($importer["uid"], $guid); - if ($message_id) - return true; - - $parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact); - if (!$parent_item) - return false; - - $person = self::person_by_handle($author); - if (!is_array($person)) { - logger("unable to find author details"); - return false; - } - - // Fetch the contact id - if we know this contact - $author_contact = self::author_contact_by_url($contact, $person, $importer["uid"]); - - // "positive" = "false" would be a Dislike - wich isn't currently supported by Diaspora - // We would accept this anyhow. - if ($positive == "true") - $verb = ACTIVITY_LIKE; - else - $verb = ACTIVITY_DISLIKE; - - $datarray = array(); - - $datarray["protocol"] = PROTOCOL_DIASPORA; - - $datarray["uid"] = $importer["uid"]; - $datarray["contact-id"] = $author_contact["cid"]; - $datarray["network"] = $author_contact["network"]; - - $datarray["author-name"] = $person["name"]; - $datarray["author-link"] = $person["url"]; - $datarray["author-avatar"] = ((x($person,"thumb")) ? $person["thumb"] : $person["photo"]); - - $datarray["owner-name"] = $contact["name"]; - $datarray["owner-link"] = $contact["url"]; - $datarray["owner-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]); - - $datarray["guid"] = $guid; - $datarray["uri"] = self::get_uri_from_guid($author, $guid); - - $datarray["type"] = "activity"; - $datarray["verb"] = $verb; - $datarray["gravity"] = GRAVITY_LIKE; - $datarray["parent-uri"] = $parent_item["uri"]; - - $datarray["object-type"] = ACTIVITY_OBJ_NOTE; - $datarray["object"] = self::construct_like_object($importer, $parent_item); - - $datarray["body"] = self::construct_like_body($contact, $parent_item, $guid); - - $message_id = item_store($datarray); - - if ($message_id <= 0) { - return false; - } - - if ($message_id) { - logger("Stored like ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); - } - - // like on comments have the comment as parent. So we need to fetch the toplevel parent - if ($parent_item["id"] != $parent_item["parent"]) { - $toplevel = dba::select('item', array('origin'), array('id' => $parent_item["parent"]), array('limit' => 1)); - $origin = $toplevel["origin"]; - } else { - $origin = $parent_item["origin"]; - } - - // If we are the origin of the parent we store the original data and notify our followers - if ($message_id && $origin) { - - // Formerly we stored the signed text, the signature and the author in different fields. - // We now store the raw data so that we are more flexible. - dba::insert('sign', array('iid' => $message_id, 'signed_text' => json_encode($data))); - - // notify others - Worker::add(PRIORITY_HIGH, "notifier", "comment-import", $message_id); - } - - return true; - } - - /** - * @brief Processes private messages - * - * @param array $importer Array of the importer user - * @param object $data The message object - * - * @return bool Success? - */ - private static function receive_message($importer, $data) { - $author = notags(unxmlify($data->author)); - $guid = notags(unxmlify($data->guid)); - $conversation_guid = notags(unxmlify($data->conversation_guid)); - $text = unxmlify($data->text); - $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); - - $contact = self::allowed_contact_by_handle($importer, $author, true); - if (!$contact) { - return false; - } - - $conversation = null; - - $c = q("SELECT * FROM `conv` WHERE `uid` = %d AND `guid` = '%s' LIMIT 1", - intval($importer["uid"]), - dbesc($conversation_guid) - ); - if ($c) { - $conversation = $c[0]; - } else { - logger("conversation not available."); - return false; - } - - $message_uri = $author.":".$guid; - - $person = self::person_by_handle($author); - if (!$person) { - logger("unable to find author details"); - return false; - } - - $body = diaspora2bb($text); - - $body = self::replace_people_guid($body, $person["url"]); - - dba::lock('mail'); - - $r = q("SELECT `id` FROM `mail` WHERE `guid` = '%s' AND `uid` = %d LIMIT 1", - dbesc($guid), - intval($importer["uid"]) - ); - if (dbm::is_result($r)) { - logger("duplicate message already delivered.", LOGGER_DEBUG); - return false; - } - - q("INSERT INTO `mail` (`uid`, `guid`, `convid`, `from-name`,`from-photo`,`from-url`,`contact-id`,`title`,`body`,`seen`,`reply`,`uri`,`parent-uri`,`created`) - VALUES ( %d, '%s', %d, '%s', '%s', '%s', %d, '%s', '%s', %d, %d, '%s','%s','%s')", - intval($importer["uid"]), - dbesc($guid), - intval($conversation["id"]), - dbesc($person["name"]), - dbesc($person["photo"]), - dbesc($person["url"]), - intval($contact["id"]), - dbesc($conversation["subject"]), - dbesc($body), - 0, - 1, - dbesc($message_uri), - dbesc($author.":".$conversation["guid"]), - dbesc($created_at) - ); - - dba::unlock(); - - dba::update('conv', array('updated' => datetime_convert()), array('id' => $conversation["id"])); - return true; - } - - /** - * @brief Processes participations - unsupported by now - * - * @param array $importer Array of the importer user - * @param object $data The message object - * - * @return bool always true - */ - private static function receive_participation($importer, $data) { - // I'm not sure if we can fully support this message type - return true; - } - - /** - * @brief Processes photos - unneeded - * - * @param array $importer Array of the importer user - * @param object $data The message object - * - * @return bool always true - */ - private static function receive_photo($importer, $data) { - // There doesn't seem to be a reason for this function, since the photo data is transmitted in the status message as well - return true; - } - - /** - * @brief Processes poll participations - unssupported - * - * @param array $importer Array of the importer user - * @param object $data The message object - * - * @return bool always true - */ - private static function receive_poll_participation($importer, $data) { - // We don't support polls by now - return true; - } - - /** - * @brief Processes incoming profile updates - * - * @param array $importer Array of the importer user - * @param object $data The message object - * - * @return bool Success - */ - private static function receive_profile($importer, $data) { - $author = strtolower(notags(unxmlify($data->author))); - - $contact = self::contact_by_handle($importer["uid"], $author); - if (!$contact) - return false; - - $name = unxmlify($data->first_name).((strlen($data->last_name)) ? " ".unxmlify($data->last_name) : ""); - $image_url = unxmlify($data->image_url); - $birthday = unxmlify($data->birthday); - $gender = unxmlify($data->gender); - $about = diaspora2bb(unxmlify($data->bio)); - $location = diaspora2bb(unxmlify($data->location)); - $searchable = (unxmlify($data->searchable) == "true"); - $nsfw = (unxmlify($data->nsfw) == "true"); - $tags = unxmlify($data->tag_string); - - $tags = explode("#", $tags); - - $keywords = array(); - foreach ($tags as $tag) { - $tag = trim(strtolower($tag)); - if ($tag != "") - $keywords[] = $tag; - } - - $keywords = implode(", ", $keywords); - - $handle_parts = explode("@", $author); - $nick = $handle_parts[0]; - - if ($name === "") - $name = $handle_parts[0]; - - if ( preg_match("|^https?://|", $image_url) === 0) - $image_url = "http://".$handle_parts[1].$image_url; - - update_contact_avatar($image_url, $importer["uid"], $contact["id"]); - - // Generic birthday. We don't know the timezone. The year is irrelevant. - - $birthday = str_replace("1000", "1901", $birthday); - - if ($birthday != "") - $birthday = datetime_convert("UTC", "UTC", $birthday, "Y-m-d"); - - // this is to prevent multiple birthday notifications in a single year - // if we already have a stored birthday and the 'm-d' part hasn't changed, preserve the entry, which will preserve the notify year - - if (substr($birthday,5) === substr($contact["bd"],5)) - $birthday = $contact["bd"]; - - $r = q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `addr` = '%s', `name-date` = '%s', `bd` = '%s', - `location` = '%s', `about` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `id` = %d AND `uid` = %d", - dbesc($name), - dbesc($nick), - dbesc($author), - dbesc(datetime_convert()), - dbesc($birthday), - dbesc($location), - dbesc($about), - dbesc($keywords), - dbesc($gender), - intval($contact["id"]), - intval($importer["uid"]) - ); - - $gcontact = array("url" => $contact["url"], "network" => NETWORK_DIASPORA, "generation" => 2, - "photo" => $image_url, "name" => $name, "location" => $location, - "about" => $about, "birthday" => $birthday, "gender" => $gender, - "addr" => $author, "nick" => $nick, "keywords" => $keywords, - "hide" => !$searchable, "nsfw" => $nsfw); - - $gcid = update_gcontact($gcontact); - - link_gcontact($gcid, $importer["uid"], $contact["id"]); - - logger("Profile of contact ".$contact["id"]." stored for user ".$importer["uid"], LOGGER_DEBUG); - - return true; - } - - /** - * @brief Processes incoming friend requests - * - * @param array $importer Array of the importer user - * @param array $contact The contact that send the request - */ - private static function receive_request_make_friend($importer, $contact) { - - $a = get_app(); - - if ($contact["rel"] == CONTACT_IS_SHARING) { - dba::update('contact', array('rel' => CONTACT_IS_FRIEND, 'writable' => true), - array('id' => $contact["id"], 'uid' => $importer["uid"])); - } - // send notification - - $r = q("SELECT `hide-friends` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1", - intval($importer["uid"]) - ); - - if ($r && !$r[0]["hide-friends"] && !$contact["hidden"] && intval(PConfig::get($importer["uid"], "system", "post_newfriend"))) { - - $self = q("SELECT * FROM `contact` WHERE `self` AND `uid` = %d LIMIT 1", - intval($importer["uid"]) - ); - - // they are not CONTACT_IS_FOLLOWER anymore but that's what we have in the array - - if ($self && $contact["rel"] == CONTACT_IS_FOLLOWER) { - - $arr = array(); - $arr["protocol"] = PROTOCOL_DIASPORA; - $arr["uri"] = $arr["parent-uri"] = item_new_uri($a->get_hostname(), $importer["uid"]); - $arr["uid"] = $importer["uid"]; - $arr["contact-id"] = $self[0]["id"]; - $arr["wall"] = 1; - $arr["type"] = 'wall'; - $arr["gravity"] = 0; - $arr["origin"] = 1; - $arr["author-name"] = $arr["owner-name"] = $self[0]["name"]; - $arr["author-link"] = $arr["owner-link"] = $self[0]["url"]; - $arr["author-avatar"] = $arr["owner-avatar"] = $self[0]["thumb"]; - $arr["verb"] = ACTIVITY_FRIEND; - $arr["object-type"] = ACTIVITY_OBJ_PERSON; - - $A = "[url=".$self[0]["url"]."]".$self[0]["name"]."[/url]"; - $B = "[url=".$contact["url"]."]".$contact["name"]."[/url]"; - $BPhoto = "[url=".$contact["url"]."][img]".$contact["thumb"]."[/img][/url]"; - $arr["body"] = sprintf(t("%1$s is now friends with %2$s"), $A, $B)."\n\n\n".$Bphoto; - - $arr["object"] = self::construct_new_friend_object($contact); - - $arr["last-child"] = 1; - - $arr["allow_cid"] = $user[0]["allow_cid"]; - $arr["allow_gid"] = $user[0]["allow_gid"]; - $arr["deny_cid"] = $user[0]["deny_cid"]; - $arr["deny_gid"] = $user[0]["deny_gid"]; - - $i = item_store($arr); - if ($i) - Worker::add(PRIORITY_HIGH, "notifier", "activity", $i); - } - } - } - - /** - * @brief Creates a XML object for a "new friend" message - * - * @param array $contact Array of the contact - * - * @return string The XML - */ - private static function construct_new_friend_object($contact) { - $objtype = ACTIVITY_OBJ_PERSON; - $link = ''."\n". - ''."\n"; - - $xmldata = array("object" => array("type" => $objtype, - "title" => $contact["name"], - "id" => $contact["url"]."/".$contact["name"], - "link" => $link)); - - return xml::from_array($xmldata, $xml, true); - } - - /** - * @brief Processes incoming sharing notification - * - * @param array $importer Array of the importer user - * @param object $data The message object - * - * @return bool Success - */ - private static function receive_contact_request($importer, $data) { - $author = unxmlify($data->author); - $recipient = unxmlify($data->recipient); - - if (!$author || !$recipient) { - return false; - } - - // the current protocol version doesn't know these fields - // That means that we will assume their existance - if (isset($data->following)) { - $following = (unxmlify($data->following) == "true"); - } else { - $following = true; - } - - if (isset($data->sharing)) { - $sharing = (unxmlify($data->sharing) == "true"); - } else { - $sharing = true; - } - - $contact = self::contact_by_handle($importer["uid"],$author); - - // perhaps we were already sharing with this person. Now they're sharing with us. - // That makes us friends. - if ($contact) { - if ($following) { - logger("Author ".$author." (Contact ".$contact["id"].") wants to follow us.", LOGGER_DEBUG); - self::receive_request_make_friend($importer, $contact); - - // refetch the contact array - $contact = self::contact_by_handle($importer["uid"],$author); - - // If we are now friends, we are sending a share message. - // Normally we needn't to do so, but the first message could have been vanished. - if (in_array($contact["rel"], array(CONTACT_IS_FRIEND))) { - $u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"])); - if ($u) { - logger("Sending share message to author ".$author." - Contact: ".$contact["id"]." - User: ".$importer["uid"], LOGGER_DEBUG); - $ret = self::send_share($u[0], $contact); - } - } - return true; - } else { - logger("Author ".$author." doesn't want to follow us anymore.", LOGGER_DEBUG); - lose_follower($importer, $contact); - return true; - } - } - - if (!$following && $sharing && in_array($importer["page-flags"], array(PAGE_SOAPBOX, PAGE_NORMAL))) { - logger("Author ".$author." wants to share with us - but doesn't want to listen. Request is ignored.", LOGGER_DEBUG); - return false; - } elseif (!$following && !$sharing) { - logger("Author ".$author." doesn't want anything - and we don't know the author. Request is ignored.", LOGGER_DEBUG); - return false; - } elseif (!$following && $sharing) { - logger("Author ".$author." wants to share with us.", LOGGER_DEBUG); - } elseif ($following && $sharing) { - logger("Author ".$author." wants to have a bidirectional conection.", LOGGER_DEBUG); - } elseif ($following && !$sharing) { - logger("Author ".$author." wants to listen to us.", LOGGER_DEBUG); - } - - $ret = self::person_by_handle($author); - - if (!$ret || ($ret["network"] != NETWORK_DIASPORA)) { - logger("Cannot resolve diaspora handle ".$author." for ".$recipient); - return false; - } - - $batch = (($ret["batch"]) ? $ret["batch"] : implode("/", array_slice(explode("/", $ret["url"]), 0, 3))."/receive/public"); - - $r = q("INSERT INTO `contact` (`uid`, `network`,`addr`,`created`,`url`,`nurl`,`batch`,`name`,`nick`,`photo`,`pubkey`,`notify`,`poll`,`blocked`,`priority`) - VALUES (%d, '%s', '%s', '%s', '%s','%s','%s','%s','%s','%s','%s','%s','%s',%d,%d)", - intval($importer["uid"]), - dbesc($ret["network"]), - dbesc($ret["addr"]), - datetime_convert(), - dbesc($ret["url"]), - dbesc(normalise_link($ret["url"])), - dbesc($batch), - dbesc($ret["name"]), - dbesc($ret["nick"]), - dbesc($ret["photo"]), - dbesc($ret["pubkey"]), - dbesc($ret["notify"]), - dbesc($ret["poll"]), - 1, - 2 - ); - - // find the contact record we just created - - $contact_record = self::contact_by_handle($importer["uid"],$author); - - if (!$contact_record) { - logger("unable to locate newly created contact record."); - return; - } - - logger("Author ".$author." was added as contact number ".$contact_record["id"].".", LOGGER_DEBUG); - - $def_gid = get_default_group($importer['uid'], $ret["network"]); - - if (intval($def_gid)) - group_add_member($importer["uid"], "", $contact_record["id"], $def_gid); - - update_contact_avatar($ret["photo"], $importer['uid'], $contact_record["id"], true); - - if ($importer["page-flags"] == PAGE_NORMAL) { - - logger("Sending intra message for author ".$author.".", LOGGER_DEBUG); - - $hash = random_string().(string)time(); // Generate a confirm_key - - $ret = q("INSERT INTO `intro` (`uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime`) - VALUES (%d, %d, %d, %d, '%s', '%s', '%s')", - intval($importer["uid"]), - intval($contact_record["id"]), - 0, - 0, - dbesc(t("Sharing notification from Diaspora network")), - dbesc($hash), - dbesc(datetime_convert()) - ); - } else { - - // automatic friend approval - - logger("Does an automatic friend approval for author ".$author.".", LOGGER_DEBUG); - - update_contact_avatar($contact_record["photo"],$importer["uid"],$contact_record["id"]); - - // technically they are sharing with us (CONTACT_IS_SHARING), - // but if our page-type is PAGE_COMMUNITY or PAGE_SOAPBOX - // we are going to change the relationship and make them a follower. - - if (($importer["page-flags"] == PAGE_FREELOVE) && $sharing && $following) - $new_relation = CONTACT_IS_FRIEND; - elseif (($importer["page-flags"] == PAGE_FREELOVE) && $sharing) - $new_relation = CONTACT_IS_SHARING; - else - $new_relation = CONTACT_IS_FOLLOWER; - - $r = q("UPDATE `contact` SET `rel` = %d, - `name-date` = '%s', - `uri-date` = '%s', - `blocked` = 0, - `pending` = 0, - `writable` = 1 - WHERE `id` = %d - ", - intval($new_relation), - dbesc(datetime_convert()), - dbesc(datetime_convert()), - intval($contact_record["id"]) - ); - - $u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($importer["uid"])); - if ($u) { - logger("Sending share message (Relation: ".$new_relation.") to author ".$author." - Contact: ".$contact_record["id"]." - User: ".$importer["uid"], LOGGER_DEBUG); - $ret = self::send_share($u[0], $contact_record); - - // Send the profile data, maybe it weren't transmitted before - self::send_profile($importer["uid"], array($contact_record)); - } - } - - return true; - } - - /** - * @brief Fetches a message with a given guid - * - * @param string $guid message guid - * @param string $orig_author handle of the original post - * @param string $author handle of the sharer - * - * @return array The fetched item - */ - private static function original_item($guid, $orig_author, $author) { - - // Do we already have this item? - $r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`, - `author-name`, `author-link`, `author-avatar` - FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1", - dbesc($guid)); - - if (dbm::is_result($r)) { - logger("reshared message ".$guid." already exists on system."); - - // Maybe it is already a reshared item? - // Then refetch the content, if it is a reshare from a reshare. - // If it is a reshared post from another network then reformat to avoid display problems with two share elements - if (self::is_reshare($r[0]["body"], true)) { - $r = array(); - } elseif (self::is_reshare($r[0]["body"], false) || strstr($r[0]["body"], "[share")) { - $r[0]["body"] = diaspora2bb(bb2diaspora($r[0]["body"])); - - $r[0]["body"] = self::replace_people_guid($r[0]["body"], $r[0]["author-link"]); - - // Add OEmbed and other information to the body - $r[0]["body"] = add_page_info_to_body($r[0]["body"], false, true); - - return $r[0]; - } else { - return $r[0]; - } - } - - if (!dbm::is_result($r)) { - $server = "https://".substr($orig_author, strpos($orig_author, "@") + 1); - logger("1st try: reshared message ".$guid." will be fetched via SSL from the server ".$server); - $item_id = self::store_by_guid($guid, $server); - - if (!$item_id) { - $server = "http://".substr($orig_author, strpos($orig_author, "@") + 1); - logger("2nd try: reshared message ".$guid." will be fetched without SLL from the server ".$server); - $item_id = self::store_by_guid($guid, $server); - } - - if ($item_id) { - $r = q("SELECT `body`, `tag`, `app`, `created`, `object-type`, `uri`, `guid`, - `author-name`, `author-link`, `author-avatar` - FROM `item` WHERE `id` = %d AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1", - intval($item_id)); - - if (dbm::is_result($r)) { - // If it is a reshared post from another network then reformat to avoid display problems with two share elements - if (self::is_reshare($r[0]["body"], false)) { - $r[0]["body"] = diaspora2bb(bb2diaspora($r[0]["body"])); - $r[0]["body"] = self::replace_people_guid($r[0]["body"], $r[0]["author-link"]); - } - - return $r[0]; - } - - } - } - return false; - } - - /** - * @brief Processes a reshare message - * - * @param array $importer Array of the importer user - * @param object $data The message object - * @param string $xml The original XML of the message - * - * @return int the message id - */ - private static function receive_reshare($importer, $data, $xml) { - $author = notags(unxmlify($data->author)); - $guid = notags(unxmlify($data->guid)); - $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); - $root_author = notags(unxmlify($data->root_author)); - $root_guid = notags(unxmlify($data->root_guid)); - /// @todo handle unprocessed property "provider_display_name" - $public = notags(unxmlify($data->public)); - - $contact = self::allowed_contact_by_handle($importer, $author, false); - if (!$contact) { - return false; - } - - $message_id = self::message_exists($importer["uid"], $guid); - if ($message_id) { - return true; - } - - $original_item = self::original_item($root_guid, $root_author, $author); - if (!$original_item) { - return false; - } - - $orig_url = System::baseUrl()."/display/".$original_item["guid"]; - - $datarray = array(); - - $datarray["uid"] = $importer["uid"]; - $datarray["contact-id"] = $contact["id"]; - $datarray["network"] = NETWORK_DIASPORA; - - $datarray["author-name"] = $contact["name"]; - $datarray["author-link"] = $contact["url"]; - $datarray["author-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]); - - $datarray["owner-name"] = $datarray["author-name"]; - $datarray["owner-link"] = $datarray["author-link"]; - $datarray["owner-avatar"] = $datarray["author-avatar"]; - - $datarray["guid"] = $guid; - $datarray["uri"] = $datarray["parent-uri"] = self::get_uri_from_guid($author, $guid); - - $datarray["verb"] = ACTIVITY_POST; - $datarray["gravity"] = GRAVITY_PARENT; - - $datarray["protocol"] = PROTOCOL_DIASPORA; - $datarray["source"] = $xml; - - $prefix = share_header($original_item["author-name"], $original_item["author-link"], $original_item["author-avatar"], - $original_item["guid"], $original_item["created"], $orig_url); - $datarray["body"] = $prefix.$original_item["body"]."[/share]"; - - $datarray["tag"] = $original_item["tag"]; - $datarray["app"] = $original_item["app"]; - - $datarray["plink"] = self::plink($author, $guid); - $datarray["private"] = (($public == "false") ? 1 : 0); - $datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at; - - $datarray["object-type"] = $original_item["object-type"]; - - self::fetch_guid($datarray); - $message_id = item_store($datarray); - - if ($message_id) { - logger("Stored reshare ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); - return true; - } else { - return false; - } - } - - /** - * @brief Processes retractions - * - * @param array $importer Array of the importer user - * @param array $contact The contact of the item owner - * @param object $data The message object - * - * @return bool success - */ - private static function item_retraction($importer, $contact, $data) { - $author = notags(unxmlify($data->author)); - $target_guid = notags(unxmlify($data->target_guid)); - $target_type = notags(unxmlify($data->target_type)); - - $person = self::person_by_handle($author); - if (!is_array($person)) { - logger("unable to find author detail for ".$author); - return false; - } - - if (empty($contact["url"])) { - $contact["url"] = $person["url"]; - } - - // Fetch items that are about to be deleted - $fields = array('uid', 'id', 'parent', 'parent-uri', 'author-link'); - - // When we receive a public retraction, we delete every item that we find. - if ($importer['uid'] == 0) { - $condition = array("`guid` = ? AND NOT `file` LIKE '%%[%%' AND NOT `deleted`", $target_guid); - } else { - $condition = array("`guid` = ? AND `uid` = ? AND NOT `file` LIKE '%%[%%' AND NOT `deleted`", $target_guid, $importer['uid']); - } - $r = dba::select('item', $fields, $condition); - if (!dbm::is_result($r)) { - logger("Target guid ".$target_guid." was not found on this system for user ".$importer['uid']."."); - return false; - } - - while ($item = dba::fetch($r)) { - // Fetch the parent item - $parent = dba::select('item', array('author-link', 'origin'), array('id' => $item["parent"]), array('limit' => 1)); - - // Only delete it if the parent author really fits - if (!link_compare($parent["author-link"], $contact["url"]) && !link_compare($item["author-link"], $contact["url"])) { - logger("Thread author ".$parent["author-link"]." and item author ".$item["author-link"]." don't fit to expected contact ".$contact["url"], LOGGER_DEBUG); - continue; - } - - // Currently we don't have a central deletion function that we could use in this case. The function "item_drop" doesn't work for that case - dba::update('item', array('deleted' => true, 'title' => '', 'body' => '', - 'edited' => datetime_convert(), 'changed' => datetime_convert()), - array('id' => $item["id"])); - - // Delete the thread - if it is a starting post and not a comment - if ($target_type != 'Comment') { - delete_thread($item["id"], $item["parent-uri"]); - } - - logger("Deleted target ".$target_guid." (".$item["id"].") from user ".$item["uid"]." parent: ".$item["parent"], LOGGER_DEBUG); - - // Now check if the retraction needs to be relayed by us - if ($parent["origin"]) { - // notify others - Worker::add(PRIORITY_HIGH, "notifier", "drop", $item["id"]); - } - } - - return true; - } - - /** - * @brief Receives retraction messages - * - * @param array $importer Array of the importer user - * @param string $sender The sender of the message - * @param object $data The message object - * - * @return bool Success - */ - private static function receive_retraction($importer, $sender, $data) { - $target_type = notags(unxmlify($data->target_type)); - - $contact = self::contact_by_handle($importer["uid"], $sender); - if (!$contact && (in_array($target_type, array("Contact", "Person")))) { - logger("cannot find contact for sender: ".$sender." and user ".$importer["uid"]); - return false; - } - - logger("Got retraction for ".$target_type.", sender ".$sender." and user ".$importer["uid"], LOGGER_DEBUG); - - switch ($target_type) { - case "Comment": - case "Like": - case "Post": - case "Reshare": - case "StatusMessage": - return self::item_retraction($importer, $contact, $data); - - case "Contact": - case "Person": - /// @todo What should we do with an "unshare"? - // Removing the contact isn't correct since we still can read the public items - contact_remove($contact["id"]); - return true; - - default: - logger("Unknown target type ".$target_type); - return false; - } - return true; - } - - /** - * @brief Receives status messages - * - * @param array $importer Array of the importer user - * @param object $data The message object - * @param string $xml The original XML of the message - * - * @return int The message id of the newly created item - */ - private static function receive_status_message($importer, $data, $xml) { - $author = notags(unxmlify($data->author)); - $guid = notags(unxmlify($data->guid)); - $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); - $public = notags(unxmlify($data->public)); - $text = unxmlify($data->text); - $provider_display_name = notags(unxmlify($data->provider_display_name)); - - $contact = self::allowed_contact_by_handle($importer, $author, false); - if (!$contact) { - return false; - } - - $message_id = self::message_exists($importer["uid"], $guid); - if ($message_id) { - return true; - } - - $address = array(); - if ($data->location) { - foreach ($data->location->children() AS $fieldname => $data) { - $address[$fieldname] = notags(unxmlify($data)); - } - } - - $body = diaspora2bb($text); - - $datarray = array(); - - // Attach embedded pictures to the body - if ($data->photo) { - foreach ($data->photo AS $photo) { - $body = "[img]".unxmlify($photo->remote_photo_path). - unxmlify($photo->remote_photo_name)."[/img]\n".$body; - } - - $datarray["object-type"] = ACTIVITY_OBJ_IMAGE; - } else { - $datarray["object-type"] = ACTIVITY_OBJ_NOTE; - - // Add OEmbed and other information to the body - if (!self::is_redmatrix($contact["url"])) { - $body = add_page_info_to_body($body, false, true); - } - } - - /// @todo enable support for polls - //if ($data->poll) { - // foreach ($data->poll AS $poll) - // print_r($poll); - // die("poll!\n"); - //} - - /// @todo enable support for events - - $datarray["uid"] = $importer["uid"]; - $datarray["contact-id"] = $contact["id"]; - $datarray["network"] = NETWORK_DIASPORA; - - $datarray["author-name"] = $contact["name"]; - $datarray["author-link"] = $contact["url"]; - $datarray["author-avatar"] = ((x($contact,"thumb")) ? $contact["thumb"] : $contact["photo"]); - - $datarray["owner-name"] = $datarray["author-name"]; - $datarray["owner-link"] = $datarray["author-link"]; - $datarray["owner-avatar"] = $datarray["author-avatar"]; - - $datarray["guid"] = $guid; - $datarray["uri"] = $datarray["parent-uri"] = self::get_uri_from_guid($author, $guid); - - $datarray["verb"] = ACTIVITY_POST; - $datarray["gravity"] = GRAVITY_PARENT; - - $datarray["protocol"] = PROTOCOL_DIASPORA; - $datarray["source"] = $xml; - - $datarray["body"] = self::replace_people_guid($body, $contact["url"]); - - if ($provider_display_name != "") { - $datarray["app"] = $provider_display_name; - } - - $datarray["plink"] = self::plink($author, $guid); - $datarray["private"] = (($public == "false") ? 1 : 0); - $datarray["changed"] = $datarray["created"] = $datarray["edited"] = $created_at; - - if (isset($address["address"])) { - $datarray["location"] = $address["address"]; - } - - if (isset($address["lat"]) && isset($address["lng"])) { - $datarray["coord"] = $address["lat"]." ".$address["lng"]; - } - - self::fetch_guid($datarray); - $message_id = item_store($datarray); - - if ($message_id) { - logger("Stored item ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG); - return true; - } else { - return false; - } - } - - /* ************************************************************************************** * - * Here are all the functions that are needed to transmit data with the Diaspora protocol * - * ************************************************************************************** */ - - /** - * @brief returnes the handle of a contact - * - * @param array $me contact array - * - * @return string the handle in the format user@domain.tld - */ - private static function my_handle($contact) { - if ($contact["addr"] != "") { - return $contact["addr"]; - } - - // Normally we should have a filled "addr" field - but in the past this wasn't the case - // So - just in case - we build the the address here. - if ($contact["nickname"] != "") { - $nick = $contact["nickname"]; - } else { - $nick = $contact["nick"]; - } - - return $nick."@".substr(System::baseUrl(), strpos(System::baseUrl(),"://") + 3); - } - - - /** - * @brief Creates the data for a private message in the new format - * - * @param string $msg The message that is to be transmitted - * @param array $user The record of the sender - * @param array $contact Target of the communication - * @param string $prvkey The private key of the sender - * @param string $pubkey The public key of the receiver - * - * @return string The encrypted data - */ - public static function encode_private_data($msg, $user, $contact, $prvkey, $pubkey) { - - logger("Message: ".$msg, LOGGER_DATA); - - // without a public key nothing will work - if (!$pubkey) { - logger("pubkey missing: contact id: ".$contact["id"]); - return false; - } - - $aes_key = openssl_random_pseudo_bytes(32); - $b_aes_key = base64_encode($aes_key); - $iv = openssl_random_pseudo_bytes(16); - $b_iv = base64_encode($iv); - - $ciphertext = self::aes_encrypt($aes_key, $iv, $msg); - - $json = json_encode(array("iv" => $b_iv, "key" => $b_aes_key)); - - $encrypted_key_bundle = ""; - openssl_public_encrypt($json, $encrypted_key_bundle, $pubkey); - - $json_object = json_encode(array("aes_key" => base64_encode($encrypted_key_bundle), - "encrypted_magic_envelope" => base64_encode($ciphertext))); - - return $json_object; - } - - /** - * @brief Creates the envelope for the "fetch" endpoint and for the new format - * - * @param string $msg The message that is to be transmitted - * @param array $user The record of the sender - * - * @return string The envelope - */ - public static function build_magic_envelope($msg, $user) { - - $b64url_data = base64url_encode($msg); - $data = str_replace(array("\n", "\r", " ", "\t"), array("", "", "", ""), $b64url_data); - - $key_id = base64url_encode(self::my_handle($user)); - $type = "application/xml"; - $encoding = "base64url"; - $alg = "RSA-SHA256"; - $signable_data = $data.".".base64url_encode($type).".".base64url_encode($encoding).".".base64url_encode($alg); - - // Fallback if the private key wasn't transmitted in the expected field - if ($user['uprvkey'] == "") - $user['uprvkey'] = $user['prvkey']; - - $signature = rsa_sign($signable_data, $user["uprvkey"]); - $sig = base64url_encode($signature); - - $xmldata = array("me:env" => array("me:data" => $data, - "@attributes" => array("type" => $type), - "me:encoding" => $encoding, - "me:alg" => $alg, - "me:sig" => $sig, - "@attributes2" => array("key_id" => $key_id))); - - $namespaces = array("me" => "http://salmon-protocol.org/ns/magic-env"); - - return xml::from_array($xmldata, $xml, false, $namespaces); - } - - /** - * @brief Create the envelope for a message - * - * @param string $msg The message that is to be transmitted - * @param array $user The record of the sender - * @param array $contact Target of the communication - * @param string $prvkey The private key of the sender - * @param string $pubkey The public key of the receiver - * @param bool $public Is the message public? - * - * @return string The message that will be transmitted to other servers - */ - private static function build_message($msg, $user, $contact, $prvkey, $pubkey, $public = false) { - - // The message is put into an envelope with the sender's signature - $envelope = self::build_magic_envelope($msg, $user); - - // Private messages are put into a second envelope, encrypted with the receivers public key - if (!$public) { - $envelope = self::encode_private_data($envelope, $user, $contact, $prvkey, $pubkey); - } - - return $envelope; - } - - /** - * @brief Creates a signature for a message - * - * @param array $owner the array of the owner of the message - * @param array $message The message that is to be signed - * - * @return string The signature - */ - private static function signature($owner, $message) { - $sigmsg = $message; - unset($sigmsg["author_signature"]); - unset($sigmsg["parent_author_signature"]); - - $signed_text = implode(";", $sigmsg); - - return base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256")); - } - - /** - * @brief Transmit a message to a target server - * - * @param array $owner the array of the item owner - * @param array $contact Target of the communication - * @param string $envelope The message that is to be transmitted - * @param bool $public_batch Is it a public post? - * @param bool $queue_run Is the transmission called from the queue? - * @param string $guid message guid - * - * @return int Result of the transmission - */ - public static function transmit($owner, $contact, $envelope, $public_batch, $queue_run=false, $guid = "") { - - $a = get_app(); - - $enabled = intval(Config::get("system", "diaspora_enabled")); - if (!$enabled) - return 200; - - $logid = random_string(4); - $dest_url = (($public_batch) ? $contact["batch"] : $contact["notify"]); - if (!$dest_url) { - logger("no url for contact: ".$contact["id"]." batch mode =".$public_batch); - return 0; - } - - logger("transmit: ".$logid."-".$guid." ".$dest_url); - - if (!$queue_run && was_recently_delayed($contact["id"])) { - $return_code = 0; - } else { - if (!intval(Config::get("system", "diaspora_test"))) { - $content_type = (($public_batch) ? "application/magic-envelope+xml" : "application/json"); - - post_url($dest_url."/", $envelope, array("Content-Type: ".$content_type)); - $return_code = $a->get_curl_code(); - } else { - logger("test_mode"); - return 200; - } - } - - logger("transmit: ".$logid."-".$guid." returns: ".$return_code); - - if (!$return_code || (($return_code == 503) && (stristr($a->get_curl_headers(), "retry-after")))) { - logger("queue message"); - - $r = q("SELECT `id` FROM `queue` WHERE `cid` = %d AND `network` = '%s' AND `content` = '%s' AND `batch` = %d LIMIT 1", - intval($contact["id"]), - dbesc(NETWORK_DIASPORA), - dbesc($envelope), - intval($public_batch) - ); - if ($r) { - logger("add_to_queue ignored - identical item already in queue"); - } else { - // queue message for redelivery - add_to_queue($contact["id"], NETWORK_DIASPORA, $envelope, $public_batch); - - // The message could not be delivered. We mark the contact as "dead" - mark_for_death($contact); - } - } elseif (($return_code >= 200) && ($return_code <= 299)) { - // We successfully delivered a message, the contact is alive - unmark_for_death($contact); - } - - return(($return_code) ? $return_code : (-1)); - } - - - /** - * @brief Build the post xml - * - * @param string $type The message type - * @param array $message The message data - * - * @return string The post XML - */ - public static function build_post_xml($type, $message) { - - $data = array($type => $message); - - return xml::from_array($data, $xml); - } - - /** - * @brief Builds and transmit messages - * - * @param array $owner the array of the item owner - * @param array $contact Target of the communication - * @param string $type The message type - * @param array $message The message data - * @param bool $public_batch Is it a public post? - * @param string $guid message guid - * @param bool $spool Should the transmission be spooled or transmitted? - * - * @return int Result of the transmission - */ - private static function build_and_transmit($owner, $contact, $type, $message, $public_batch = false, $guid = "", $spool = false) { - - $msg = self::build_post_xml($type, $message); - - logger('message: '.$msg, LOGGER_DATA); - logger('send guid '.$guid, LOGGER_DEBUG); - - // Fallback if the private key wasn't transmitted in the expected field - if ($owner['uprvkey'] == "") - $owner['uprvkey'] = $owner['prvkey']; - - $envelope = self::build_message($msg, $owner, $contact, $owner['uprvkey'], $contact['pubkey'], $public_batch); - - if ($spool) { - add_to_queue($contact['id'], NETWORK_DIASPORA, $envelope, $public_batch); - return true; - } else - $return_code = self::transmit($owner, $contact, $envelope, $public_batch, false, $guid); - - logger("guid: ".$item["guid"]." result ".$return_code, LOGGER_DEBUG); - - return $return_code; - } - - /** - * @brief sends an account migration - * - * @param array $owner the array of the item owner - * @param array $contact Target of the communication - * @param int $uid User ID - * - * @return int The result of the transmission - */ - public static function sendAccountMigration($owner, $contact, $uid) { - - $old_handle = PConfig::get($uid, 'system', 'previous_addr'); - $profile = self::createProfileData($uid); - - $signed_text = 'AccountMigration:'.$old_handle.':'.$profile['author']; - $signature = base64_encode(rsa_sign($signed_text, $owner["uprvkey"], "sha256")); - - $message = array("author" => $old_handle, - "profile" => $profile, - "signature" => $signature); - - logger("Send account migration ".print_r($message, true), LOGGER_DEBUG); - - return self::build_and_transmit($owner, $contact, "account_migration", $message); - } - - /** - * @brief Sends a "share" message - * - * @param array $owner the array of the item owner - * @param array $contact Target of the communication - * - * @return int The result of the transmission - */ - public static function send_share($owner, $contact) { - - /** - * @todo support the different possible combinations of "following" and "sharing" - * Currently, Diaspora only interprets the "sharing" field - * - * Before switching this code productive, we have to check all "send_share" calls if "rel" is set correctly - */ - - /* - switch ($contact["rel"]) { - case CONTACT_IS_FRIEND: - $following = true; - $sharing = true; - case CONTACT_IS_SHARING: - $following = false; - $sharing = true; - case CONTACT_IS_FOLLOWER: - $following = true; - $sharing = false; - } - */ - - $message = array("author" => self::my_handle($owner), - "recipient" => $contact["addr"], - "following" => "true", - "sharing" => "true"); - - logger("Send share ".print_r($message, true), LOGGER_DEBUG); - - return self::build_and_transmit($owner, $contact, "contact", $message); - } - - /** - * @brief sends an "unshare" - * - * @param array $owner the array of the item owner - * @param array $contact Target of the communication - * - * @return int The result of the transmission - */ - public static function send_unshare($owner, $contact) { - - $message = array("author" => self::my_handle($owner), - "recipient" => $contact["addr"], - "following" => "false", - "sharing" => "false"); - - logger("Send unshare ".print_r($message, true), LOGGER_DEBUG); - - return self::build_and_transmit($owner, $contact, "contact", $message); - } - - /** - * @brief Checks a message body if it is a reshare - * - * @param string $body The message body that is to be check - * @param bool $complete Should it be a complete check or a simple check? - * - * @return array|bool Reshare details or "false" if no reshare - */ - public static function is_reshare($body, $complete = true) { - $body = trim($body); - - // Skip if it isn't a pure repeated messages - // Does it start with a share? - if ((strpos($body, "[share") > 0) && $complete) - return(false); - - // Does it end with a share? - if (strlen($body) > (strrpos($body, "[/share]") + 8)) - return(false); - - $attributes = preg_replace("/\[share(.*?)\]\s?(.*?)\s?\[\/share\]\s?/ism","$1",$body); - // Skip if there is no shared message in there - if ($body == $attributes) - return(false); - - // If we don't do the complete check we quit here - if (!$complete) - return true; - - $guid = ""; - preg_match("/guid='(.*?)'/ism", $attributes, $matches); - if ($matches[1] != "") - $guid = $matches[1]; - - preg_match('/guid="(.*?)"/ism', $attributes, $matches); - if ($matches[1] != "") - $guid = $matches[1]; - - if ($guid != "") { - $r = q("SELECT `contact-id` FROM `item` WHERE `guid` = '%s' AND `network` IN ('%s', '%s') LIMIT 1", - dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA); - if ($r) { - $ret= array(); - $ret["root_handle"] = self::handle_from_contact($r[0]["contact-id"]); - $ret["root_guid"] = $guid; - return($ret); - } - } - - $profile = ""; - preg_match("/profile='(.*?)'/ism", $attributes, $matches); - if ($matches[1] != "") - $profile = $matches[1]; - - preg_match('/profile="(.*?)"/ism', $attributes, $matches); - if ($matches[1] != "") - $profile = $matches[1]; - - $ret= array(); - - $ret["root_handle"] = preg_replace("=https?://(.*)/u/(.*)=ism", "$2@$1", $profile); - if (($ret["root_handle"] == $profile) || ($ret["root_handle"] == "")) - return(false); - - $link = ""; - preg_match("/link='(.*?)'/ism", $attributes, $matches); - if ($matches[1] != "") - $link = $matches[1]; - - preg_match('/link="(.*?)"/ism', $attributes, $matches); - if ($matches[1] != "") - $link = $matches[1]; - - $ret["root_guid"] = preg_replace("=https?://(.*)/posts/(.*)=ism", "$2", $link); - if (($ret["root_guid"] == $link) || (trim($ret["root_guid"]) == "")) - return(false); - - return($ret); - } - - /** - * @brief Create an event array - * - * @param integer $event_id The id of the event - * - * @return array with event data - */ - private static function build_event($event_id) { - - $r = q("SELECT `guid`, `uid`, `start`, `finish`, `nofinish`, `summary`, `desc`, `location`, `adjust` FROM `event` WHERE `id` = %d", intval($event_id)); - if (!dbm::is_result($r)) { - return array(); - } - - $event = $r[0]; - - $eventdata = array(); - - $r = q("SELECT `timezone` FROM `user` WHERE `uid` = %d", intval($event['uid'])); - if (!dbm::is_result($r)) { - return array(); - } - - $user = $r[0]; - - $r = q("SELECT `addr`, `nick` FROM `contact` WHERE `uid` = %d AND `self`", intval($event['uid'])); - if (!dbm::is_result($r)) { - return array(); - } - - $owner = $r[0]; - - $eventdata['author'] = self::my_handle($owner); - - if ($event['guid']) { - $eventdata['guid'] = $event['guid']; - } - - $mask = 'Y-m-d\TH:i:s\Z'; - - /// @todo - establish "all day" events in Friendica - $eventdata["all_day"] = "false"; - - if (!$event['adjust']) { - $eventdata['timezone'] = $user['timezone']; - - if ($eventdata['timezone'] == "") { - $eventdata['timezone'] = 'UTC'; - } - } - - if ($event['start']) { - $eventdata['start'] = datetime_convert($eventdata['timezone'], "UTC", $event['start'], $mask); - } - if ($event['finish'] && !$event['nofinish']) { - $eventdata['end'] = datetime_convert($eventdata['timezone'], "UTC", $event['finish'], $mask); - } - if ($event['summary']) { - $eventdata['summary'] = html_entity_decode(bb2diaspora($event['summary'])); - } - if ($event['desc']) { - $eventdata['description'] = html_entity_decode(bb2diaspora($event['desc'])); - } - if ($event['location']) { - $location = array(); - $location["address"] = html_entity_decode(bb2diaspora($event['location'])); - $location["lat"] = 0; - $location["lng"] = 0; - $eventdata['location'] = $location; - } - - return $eventdata; - } - - /** - * @brief Create a post (status message or reshare) - * - * @param array $item The item that will be exported - * @param array $owner the array of the item owner - * - * @return array - * 'type' -> Message type ("status_message" or "reshare") - * 'message' -> Array of XML elements of the status - */ - public static function build_status($item, $owner) { - - $cachekey = "diaspora:build_status:".$item['guid']; - - $result = Cache::get($cachekey); - if (!is_null($result)) { - return $result; - } - - $myaddr = self::my_handle($owner); - - $public = (($item["private"]) ? "false" : "true"); - - $created = datetime_convert("UTC", "UTC", $item["created"], 'Y-m-d\TH:i:s\Z'); - - // Detect a share element and do a reshare - if (!$item['private'] && ($ret = self::is_reshare($item["body"]))) { - $message = array("author" => $myaddr, - "guid" => $item["guid"], - "created_at" => $created, - "root_author" => $ret["root_handle"], - "root_guid" => $ret["root_guid"], - "provider_display_name" => $item["app"], - "public" => $public); - - $type = "reshare"; - } else { - $title = $item["title"]; - $body = $item["body"]; - - // convert to markdown - $body = html_entity_decode(bb2diaspora($body)); - - // Adding the title - if (strlen($title)) - $body = "## ".html_entity_decode($title)."\n\n".$body; - - if ($item["attach"]) { - $cnt = preg_match_all('/href=\"(.*?)\"(.*?)title=\"(.*?)\"/ism', $item["attach"], $matches, PREG_SET_ORDER); - if (cnt) { - $body .= "\n".t("Attachments:")."\n"; - foreach ($matches as $mtch) - $body .= "[".$mtch[3]."](".$mtch[1].")\n"; - } - } - - $location = array(); - - if ($item["location"] != "") - $location["address"] = $item["location"]; - - if ($item["coord"] != "") { - $coord = explode(" ", $item["coord"]); - $location["lat"] = $coord[0]; - $location["lng"] = $coord[1]; - } - - $message = array("author" => $myaddr, - "guid" => $item["guid"], - "created_at" => $created, - "public" => $public, - "text" => $body, - "provider_display_name" => $item["app"], - "location" => $location); - - // Diaspora rejects messages when they contain a location without "lat" or "lng" - if (!isset($location["lat"]) || !isset($location["lng"])) { - unset($message["location"]); - } - - if ($item['event-id'] > 0) { - $event = self::build_event($item['event-id']); - if (count($event)) { - $message['event'] = $event; - - /// @todo Once Diaspora supports it, we will remove the body - // $message['text'] = ''; - } - } - - $type = "status_message"; - } - - $msg = array("type" => $type, "message" => $message); - - Cache::set($cachekey, $msg, CACHE_QUARTER_HOUR); - - return $msg; - } - - /** - * @brief Sends a post - * - * @param array $item The item that will be exported - * @param array $owner the array of the item owner - * @param array $contact Target of the communication - * @param bool $public_batch Is it a public post? - * - * @return int The result of the transmission - */ - public static function send_status($item, $owner, $contact, $public_batch = false) { - - $status = self::build_status($item, $owner); - - return self::build_and_transmit($owner, $contact, $status["type"], $status["message"], $public_batch, $item["guid"]); - } - - /** - * @brief Creates a "like" object - * - * @param array $item The item that will be exported - * @param array $owner the array of the item owner - * - * @return array The data for a "like" - */ - private static function construct_like($item, $owner) { - - $p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1", - dbesc($item["thr-parent"])); - if (!dbm::is_result($p)) - return false; - - $parent = $p[0]; - - $target_type = ($parent["uri"] === $parent["parent-uri"] ? "Post" : "Comment"); - if ($item['verb'] === ACTIVITY_LIKE) { - $positive = "true"; - } elseif ($item['verb'] === ACTIVITY_DISLIKE) { - $positive = "false"; - } - - return(array("author" => self::my_handle($owner), - "guid" => $item["guid"], - "parent_guid" => $parent["guid"], - "parent_type" => $target_type, - "positive" => $positive, - "author_signature" => "")); - } - - /** - * @brief Creates an "EventParticipation" object - * - * @param array $item The item that will be exported - * @param array $owner the array of the item owner - * - * @return array The data for an "EventParticipation" - */ - private static function construct_attend($item, $owner) { - - $p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1", - dbesc($item["thr-parent"])); - if (!dbm::is_result($p)) - return false; - - $parent = $p[0]; - - switch ($item['verb']) { - case ACTIVITY_ATTEND: - $attend_answer = 'accepted'; - break; - case ACTIVITY_ATTENDNO: - $attend_answer = 'declined'; - break; - case ACTIVITY_ATTENDMAYBE: - $attend_answer = 'tentative'; - break; - default: - logger('Unknown verb '.$item['verb'].' in item '.$item['guid']); - return false; - } - - return(array("author" => self::my_handle($owner), - "guid" => $item["guid"], - "parent_guid" => $parent["guid"], - "status" => $attend_answer, - "author_signature" => "")); - } - - /** - * @brief Creates the object for a comment - * - * @param array $item The item that will be exported - * @param array $owner the array of the item owner - * - * @return array The data for a comment - */ - private static function construct_comment($item, $owner) { - - $cachekey = "diaspora:construct_comment:".$item['guid']; - - $result = Cache::get($cachekey); - if (!is_null($result)) { - return $result; - } - - $p = q("SELECT `guid` FROM `item` WHERE `parent` = %d AND `id` = %d LIMIT 1", - intval($item["parent"]), - intval($item["parent"]) - ); - - if (!dbm::is_result($p)) - return false; - - $parent = $p[0]; - - $text = html_entity_decode(bb2diaspora($item["body"])); - $created = datetime_convert("UTC", "UTC", $item["created"], 'Y-m-d\TH:i:s\Z'); - - $comment = array("author" => self::my_handle($owner), - "guid" => $item["guid"], - "created_at" => $created, - "parent_guid" => $parent["guid"], - "text" => $text, - "author_signature" => ""); - - // Send the thread parent guid only if it is a threaded comment - if ($item['thr-parent'] != $item['parent-uri']) { - $comment['thread_parent_guid'] = self::get_guid_from_uri($item['thr-parent'], $item['uid']); - } - - Cache::set($cachekey, $comment, CACHE_QUARTER_HOUR); - - return($comment); - } - - /** - * @brief Send a like or a comment - * - * @param array $item The item that will be exported - * @param array $owner the array of the item owner - * @param array $contact Target of the communication - * @param bool $public_batch Is it a public post? - * - * @return int The result of the transmission - */ - public static function send_followup($item,$owner,$contact,$public_batch = false) { - - if (in_array($item['verb'], array(ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE))) { - $message = self::construct_attend($item, $owner); - $type = "event_participation"; - } elseif (in_array($item["verb"], array(ACTIVITY_LIKE, ACTIVITY_DISLIKE))) { - $message = self::construct_like($item, $owner); - $type = "like"; - } else { - $message = self::construct_comment($item, $owner); - $type = "comment"; - } - - if (!$message) - return false; - - $message["author_signature"] = self::signature($owner, $message); - - return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]); - } - - /** - * @brief Creates a message from a signature record entry - * - * @param array $item The item that will be exported - * @param array $signature The entry of the "sign" record - * - * @return string The message - */ - private static function message_from_signature($item, $signature) { - - // Split the signed text - $signed_parts = explode(";", $signature['signed_text']); - - if ($item["deleted"]) { - $message = array("author" => $signature['signer'], - "target_guid" => $signed_parts[0], - "target_type" => $signed_parts[1]); - } elseif (in_array($item["verb"], array(ACTIVITY_LIKE, ACTIVITY_DISLIKE))) { - $message = array("author" => $signed_parts[4], - "guid" => $signed_parts[1], - "parent_guid" => $signed_parts[3], - "parent_type" => $signed_parts[2], - "positive" => $signed_parts[0], - "author_signature" => $signature['signature'], - "parent_author_signature" => ""); - } else { - // Remove the comment guid - $guid = array_shift($signed_parts); - - // Remove the parent guid - $parent_guid = array_shift($signed_parts); - - // Remove the handle - $handle = array_pop($signed_parts); - - // Glue the parts together - $text = implode(";", $signed_parts); - - $message = array("author" => $handle, - "guid" => $guid, - "parent_guid" => $parent_guid, - "text" => implode(";", $signed_parts), - "author_signature" => $signature['signature'], - "parent_author_signature" => ""); - } - return $message; - } - - /** - * @brief Relays messages (like, comment, retraction) to other servers if we are the thread owner - * - * @param array $item The item that will be exported - * @param array $owner the array of the item owner - * @param array $contact Target of the communication - * @param bool $public_batch Is it a public post? - * - * @return int The result of the transmission - */ - public static function send_relay($item, $owner, $contact, $public_batch = false) { - - if ($item["deleted"]) { - return self::send_retraction($item, $owner, $contact, $public_batch, true); - } elseif (in_array($item["verb"], array(ACTIVITY_LIKE, ACTIVITY_DISLIKE))) { - $type = "like"; - } else { - $type = "comment"; - } - - logger("Got relayable data ".$type." for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG); - - // fetch the original signature - - $r = q("SELECT `signed_text`, `signature`, `signer` FROM `sign` WHERE `iid` = %d LIMIT 1", - intval($item["id"])); - - if (!$r) { - logger("Couldn't fetch signatur for item ".$item["guid"]." (".$item["id"].")", LOGGER_DEBUG); - return false; - } - - $signature = $r[0]; - - // Old way - is used by the internal Friendica functions - /// @todo Change all signatur storing functions to the new format - if ($signature['signed_text'] && $signature['signature'] && $signature['signer']) - $message = self::message_from_signature($item, $signature); - else {// New way - $msg = json_decode($signature['signed_text'], true); - - $message = array(); - if (is_array($msg)) { - foreach ($msg AS $field => $data) { - if (!$item["deleted"]) { - if ($field == "diaspora_handle") { - $field = "author"; - } - if ($field == "target_type") { - $field = "parent_type"; - } - } - - $message[$field] = $data; - } - } else - logger("Signature text for item ".$item["guid"]." (".$item["id"].") couldn't be extracted: ".$signature['signed_text'], LOGGER_DEBUG); - } - - $message["parent_author_signature"] = self::signature($owner, $message); - - logger("Relayed data ".print_r($message, true), LOGGER_DEBUG); - - return self::build_and_transmit($owner, $contact, $type, $message, $public_batch, $item["guid"]); - } - - /** - * @brief Sends a retraction (deletion) of a message, like or comment - * - * @param array $item The item that will be exported - * @param array $owner the array of the item owner - * @param array $contact Target of the communication - * @param bool $public_batch Is it a public post? - * @param bool $relay Is the retraction transmitted from a relay? - * - * @return int The result of the transmission - */ - public static function send_retraction($item, $owner, $contact, $public_batch = false, $relay = false) { - - $itemaddr = self::handle_from_contact($item["contact-id"], $item["gcontact-id"]); - - $msg_type = "retraction"; - - if ($item['id'] == $item['parent']) { - $target_type = "Post"; - } elseif (in_array($item["verb"], array(ACTIVITY_LIKE, ACTIVITY_DISLIKE))) { - $target_type = "Like"; - } else { - $target_type = "Comment"; - } - - $message = array("author" => $itemaddr, - "target_guid" => $item['guid'], - "target_type" => $target_type); - - logger("Got message ".print_r($message, true), LOGGER_DEBUG); - - return self::build_and_transmit($owner, $contact, $msg_type, $message, $public_batch, $item["guid"]); - } - - /** - * @brief Sends a mail - * - * @param array $item The item that will be exported - * @param array $owner The owner - * @param array $contact Target of the communication - * - * @return int The result of the transmission - */ - public static function send_mail($item, $owner, $contact) { - - $myaddr = self::my_handle($owner); - - $r = q("SELECT * FROM `conv` WHERE `id` = %d AND `uid` = %d LIMIT 1", - intval($item["convid"]), - intval($item["uid"]) - ); - - if (!dbm::is_result($r)) { - logger("conversation not found."); - return; - } - $cnv = $r[0]; - - $conv = array( - "author" => $cnv["creator"], - "guid" => $cnv["guid"], - "subject" => $cnv["subject"], - "created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d\TH:i:s\Z'), - "participants" => $cnv["recips"] - ); - - $body = bb2diaspora($item["body"]); - $created = datetime_convert("UTC", "UTC", $item["created"], 'Y-m-d\TH:i:s\Z'); - - $msg = array( - "author" => $myaddr, - "guid" => $item["guid"], - "conversation_guid" => $cnv["guid"], - "text" => $body, - "created_at" => $created, - ); - - if ($item["reply"]) { - $message = $msg; - $type = "message"; - } else { - $message = array( - "author" => $cnv["creator"], - "guid" => $cnv["guid"], - "subject" => $cnv["subject"], - "created_at" => datetime_convert("UTC", "UTC", $cnv['created'], 'Y-m-d\TH:i:s\Z'), - "participants" => $cnv["recips"], - "message" => $msg); - - $type = "conversation"; - } - - return self::build_and_transmit($owner, $contact, $type, $message, false, $item["guid"]); - } - - /** - * @brief Create profile data - * - * @param int $uid The user id - * - * @return array The profile data - */ - private static function createProfileData($uid) { - $r = q("SELECT `profile`.`uid` AS `profile_uid`, `profile`.* , `user`.*, `user`.`prvkey` AS `uprvkey`, `contact`.`addr` - FROM `profile` - INNER JOIN `user` ON `profile`.`uid` = `user`.`uid` - INNER JOIN `contact` ON `profile`.`uid` = `contact`.`uid` - WHERE `user`.`uid` = %d AND `profile`.`is-default` AND `contact`.`self` LIMIT 1", - intval($uid) - ); - - if (!$r) { - return array(); - } - - $profile = $r[0]; - - $handle = $profile["addr"]; - $first = ((strpos($profile['name'],' ') - ? trim(substr($profile['name'],0,strpos($profile['name'],' '))) : $profile['name'])); - $last = (($first === $profile['name']) ? '' : trim(substr($profile['name'], strlen($first)))); - $large = System::baseUrl().'/photo/custom/300/'.$profile['uid'].'.jpg'; - $medium = System::baseUrl().'/photo/custom/100/'.$profile['uid'].'.jpg'; - $small = System::baseUrl().'/photo/custom/50/' .$profile['uid'].'.jpg'; - $searchable = (($profile['publish'] && $profile['net-publish']) ? 'true' : 'false'); - - if ($searchable === 'true') { - $dob = '1000-00-00'; - - if (($profile['dob']) && ($profile['dob'] > '0001-01-01')) - $dob = ((intval($profile['dob'])) ? intval($profile['dob']) : '1000') .'-'. datetime_convert('UTC','UTC',$profile['dob'],'m-d'); - - $about = $profile['about']; - $about = strip_tags(bbcode($about)); - - $location = formatted_location($profile); - $tags = ''; - if ($profile['pub_keywords']) { - $kw = str_replace(',',' ',$profile['pub_keywords']); - $kw = str_replace(' ',' ',$kw); - $arr = explode(' ',$profile['pub_keywords']); - if (count($arr)) { - for ($x = 0; $x < 5; $x ++) { - if (trim($arr[$x])) - $tags .= '#'. trim($arr[$x]) .' '; - } - } - } - $tags = trim($tags); - } - - return array("author" => $handle, - "first_name" => $first, - "last_name" => $last, - "image_url" => $large, - "image_url_medium" => $medium, - "image_url_small" => $small, - "birthday" => $dob, - "gender" => $profile['gender'], - "bio" => $about, - "location" => $location, - "searchable" => $searchable, - "nsfw" => "false", - "tag_string" => $tags); - } - - /** - * @brief Sends profile data - * - * @param int $uid The user id - */ - public static function send_profile($uid, $recips = false) { - - if (!$uid) - return; - - if (!$recips) - $recips = q("SELECT `id`,`name`,`network`,`pubkey`,`notify` FROM `contact` WHERE `network` = '%s' - AND `uid` = %d AND `rel` != %d", - dbesc(NETWORK_DIASPORA), - intval($uid), - intval(CONTACT_IS_SHARING) - ); - if (!$recips) - return; - - $message = self::createProfileData($uid); - - foreach ($recips as $recip) { - logger("Send updated profile data for user ".$uid." to contact ".$recip["id"], LOGGER_DEBUG); - self::build_and_transmit($profile, $recip, "profile", $message, false, "", true); - } - } - - /** - * @brief Stores the signature for likes that are created on our system - * - * @param array $contact The contact array of the "like" - * @param int $post_id The post id of the "like" - * - * @return bool Success - */ - public static function store_like_signature($contact, $post_id) { - - // Is the contact the owner? Then fetch the private key - if (!$contact['self'] || ($contact['uid'] == 0)) { - logger("No owner post, so not storing signature", LOGGER_DEBUG); - return false; - } - - $r = q("SELECT `prvkey` FROM `user` WHERE `uid` = %d LIMIT 1", intval($contact['uid'])); - if (!dbm::is_result($r)) { - return false; - } - - $contact["uprvkey"] = $r[0]['prvkey']; - - $r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($post_id)); - if (!dbm::is_result($r)) { - return false; - } - - if (!in_array($r[0]["verb"], array(ACTIVITY_LIKE, ACTIVITY_DISLIKE))) { - return false; - } - - $message = self::construct_like($r[0], $contact); - $message["author_signature"] = self::signature($contact, $message); - - /* - * Now store the signature more flexible to dynamically support new fields. - * This will break Diaspora compatibility with Friendica versions prior to 3.5. - */ - dba::insert('sign', array('iid' => $post_id, 'signed_text' => json_encode($message))); - - logger('Stored diaspora like signature'); - return true; - } - - /** - * @brief Stores the signature for comments that are created on our system - * - * @param array $item The item array of the comment - * @param array $contact The contact array of the item owner - * @param string $uprvkey The private key of the sender - * @param int $message_id The message id of the comment - * - * @return bool Success - */ - public static function store_comment_signature($item, $contact, $uprvkey, $message_id) { - - if ($uprvkey == "") { - logger('No private key, so not storing comment signature', LOGGER_DEBUG); - return false; - } - - $contact["uprvkey"] = $uprvkey; - - $message = self::construct_comment($item, $contact); - $message["author_signature"] = self::signature($contact, $message); - - /* - * Now store the signature more flexible to dynamically support new fields. - * This will break Diaspora compatibility with Friendica versions prior to 3.5. - */ - dba::insert('sign', array('iid' => $message_id, 'signed_text' => json_encode($message))); - - logger('Stored diaspora comment signature'); - return true; - } -} diff --git a/include/directory.php b/include/directory.php index a2ccacf125..f56e8dbaa4 100644 --- a/include/directory.php +++ b/include/directory.php @@ -2,6 +2,7 @@ use Friendica\Core\Config; use Friendica\Core\Worker; +use Friendica\Database\DBM; function directory_run(&$argv, &$argc){ $dir = Config::get('system', 'directory'); @@ -36,7 +37,7 @@ function directory_update_all() { WHERE `contact`.`self` AND `profile`.`net-publish` AND `profile`.`is-default` AND NOT `user`.`account_expired` AND `user`.`verified`"); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r AS $user) { Worker::add(PRIORITY_LOW, 'directory', $user['url']); } diff --git a/include/discover_poco.php b/include/discover_poco.php index 0a41c28027..c0ff2a6554 100644 --- a/include/discover_poco.php +++ b/include/discover_poco.php @@ -2,6 +2,7 @@ use Friendica\Core\Config; use Friendica\Core\Worker; +use Friendica\Database\DBM; use Friendica\Network\Probe; require_once 'include/socgraph.php'; @@ -107,7 +108,7 @@ function discover_poco_run(&$argv, &$argc) { function update_server() { $r = q("SELECT `url`, `created`, `last_failure`, `last_contact` FROM `gserver` ORDER BY rand()"); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -213,7 +214,7 @@ function discover_directory($search) { foreach ($j->results as $jj) { // Check if the contact already exists $exists = q("SELECT `id`, `last_contact`, `last_failure`, `updated` FROM `gcontact` WHERE `nurl` = '%s'", normalise_link($jj->url)); - if (dbm::is_result($exists)) { + if (DBM::is_result($exists)) { logger("Profile ".$jj->url." already exists (".$search.")", LOGGER_DEBUG); if (($exists[0]["last_contact"] < $exists[0]["last_failure"]) && diff --git a/include/enotify.php b/include/enotify.php index d823a1ae8c..7de2027ca8 100644 --- a/include/enotify.php +++ b/include/enotify.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; +use Friendica\Database\DBM; require_once('include/Emailer.php'); require_once('include/email.php'); @@ -52,7 +53,7 @@ function notification($params) { array('uid' => $params['uid']), array('limit' => 1)); // There is no need to create notifications for forum accounts - if (!dbm::is_result($user) || in_array($user["page-flags"], array(PAGE_COMMUNITY, PAGE_PRVGROUP))) { + if (!DBM::is_result($user) || in_array($user["page-flags"], array(PAGE_COMMUNITY, PAGE_PRVGROUP))) { return; } } @@ -423,7 +424,7 @@ function notification($params) { $hash = random_string(); $r = q("SELECT `id` FROM `notify` WHERE `hash` = '%s' LIMIT 1", dbesc($hash)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $dups = true; } } while ($dups == true); @@ -743,17 +744,17 @@ function check_item_notification($itemid, $uid, $defaulttype = "") { intval($item[0]['contact-id']), intval($uid) ); - $send_notification = dbm::is_result($r); + $send_notification = DBM::is_result($r); if (!$send_notification) { $tags = q("SELECT `url` FROM `term` WHERE `otype` = %d AND `oid` = %d AND `type` = %d AND `uid` = %d", intval(TERM_OBJ_POST), intval($itemid), intval(TERM_MENTION), intval($uid)); - if (dbm::is_result($tags)) { + if (DBM::is_result($tags)) { foreach ($tags AS $tag) { $r = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND `notify_new_posts`", normalise_link($tag["url"]), intval($uid)); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $send_notification = true; } } diff --git a/include/event.php b/include/event.php index ff67a5766e..8d47b5fba5 100644 --- a/include/event.php +++ b/include/event.php @@ -7,6 +7,7 @@ use Friendica\App; use Friendica\Core\PConfig; use Friendica\Core\System; +use Friendica\Database\DBM; require_once 'include/bbcode.php'; require_once 'include/map.php'; @@ -254,7 +255,7 @@ function event_store($arr) { ); } - if (dbm::is_result($c)) { + if (DBM::is_result($c)) { $contact = $c[0]; } @@ -269,7 +270,7 @@ function event_store($arr) { intval($arr['id']), intval($arr['uid']) ); - if ((! dbm::is_result($r)) || ($r[0]['edited'] === $arr['edited'])) { + if ((! DBM::is_result($r)) || ($r[0]['edited'] === $arr['edited'])) { // Nothing has changed. Grab the item id to return. @@ -277,7 +278,7 @@ function event_store($arr) { intval($arr['id']), intval($arr['uid']) ); - return ((dbm::is_result($r)) ? $r[0]['id'] : 0); + return ((DBM::is_result($r)) ? $r[0]['id'] : 0); } // The event changed. Update it. @@ -310,7 +311,7 @@ function event_store($arr) { intval($arr['id']), intval($arr['uid']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $object = '' . xmlify(ACTIVITY_OBJ_EVENT) . '' . xmlify($arr['uri']) . ''; $object .= '' . xmlify(format_event_bbcode($arr)) . ''; $object .= '' . "\n"; @@ -361,7 +362,7 @@ function event_store($arr) { dbesc($arr['uri']), intval($arr['uid']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $event = $r[0]; } @@ -404,7 +405,7 @@ function event_store($arr) { $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($arr['uid']) ); - //if (dbm::is_result($r)) + //if (DBM::is_result($r)) // $plink = System::baseUrl() . '/display/' . $r[0]['nickname'] . '/' . $item_id; @@ -547,7 +548,7 @@ function event_by_id($owner_uid = 0, $event_params, $sql_extra = '') { intval($event_params["event_id"]) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { return event_remove_duplicates($r); } } @@ -591,7 +592,7 @@ function events_by_date($owner_uid = 0, $event_params, $sql_extra = '') { dbesc($event_params["adjust_finish"]) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { return event_remove_duplicates($r); } } @@ -805,7 +806,7 @@ function events_by_uid($uid = 0, $sql_extra = '') { ); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { return $r; } } @@ -829,7 +830,7 @@ function event_export($uid, $format = 'ical') { // We are allowed to show events. // Get the timezone the user is in. $r = q("SELECT `timezone` FROM `user` WHERE `uid` = %d LIMIT 1", intval($uid)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $timezone = $r[0]['timezone']; } diff --git a/include/expire.php b/include/expire.php index f9f38afacb..7a3549ada6 100644 --- a/include/expire.php +++ b/include/expire.php @@ -2,6 +2,7 @@ use Friendica\Core\Config; use Friendica\Core\Worker; +use Friendica\Database\DBM; function expire_run(&$argv, &$argc){ global $a; @@ -30,7 +31,7 @@ function expire_run(&$argv, &$argc){ return; } elseif (($argc == 2) && (intval($argv[1]) > 0)) { $user = dba::select('user', array('uid', 'username', 'expire'), array('uid' => $argv[1]), array('limit' => 1)); - if (dbm::is_result($user)) { + if (DBM::is_result($user)) { logger('Expire items for user '.$user['uid'].' ('.$user['username'].') - interval: '.$user['expire'], LOGGER_DEBUG); item_expire($user['uid'], $user['expire']); logger('Expire items for user '.$user['uid'].' ('.$user['username'].') - done ', LOGGER_DEBUG); diff --git a/include/fcontact.php b/include/fcontact.php index a559ede300..7e93d067f3 100644 --- a/include/fcontact.php +++ b/include/fcontact.php @@ -1,6 +1,6 @@ $nurl, 'name' => $name, 'photo' => $photo)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $r = q("SELECT `id` FROM `fcontact` WHERE `url` = '%s' LIMIT 1", dbesc($nurl) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) return $r[0]['id']; } diff --git a/include/feed.php b/include/feed.php index fb97c14ba1..22deff535a 100644 --- a/include/feed.php +++ b/include/feed.php @@ -1,4 +1,5 @@ $uid, 'gid' => $gid, 'contact-id' => $member)); } return $r; @@ -157,7 +158,7 @@ function group_get_members($gid) { intval($gid), intval(local_user()) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $ret = $r; } return $ret; @@ -174,7 +175,7 @@ function group_public_members($gid) { intval(local_user()), dbesc(NETWORK_OSTATUS) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $ret = count($r); } return $ret; @@ -190,7 +191,7 @@ function mini_group_select($uid,$gid = 0, $label = "") { intval($uid) ); $grps[] = array('name' => '', 'id' => '0', 'selected' => ''); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $grps[] = array('name' => $rr['name'], 'id' => $rr['id'], 'selected' => (($gid == $rr['id']) ? 'true' : '')); } @@ -248,7 +249,7 @@ function group_side($every="contacts",$each="group",$editmode = "standard", $gro $member_of = groups_containing(local_user(),$cid); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $selected = (($group_id == $rr['id']) ? ' group-selected' : ''); @@ -309,7 +310,7 @@ function expand_groups($a,$check_dead = false, $use_gcontact = false) { $ret = array(); - if (dbm::is_result($r)) + if (DBM::is_result($r)) foreach ($r as $rr) $ret[] = $rr['contact-id']; if ($check_dead && !$use_gcontact) { @@ -338,7 +339,7 @@ function groups_containing($uid,$c) { ); $ret = array(); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $ret[] = $rr['gid']; } diff --git a/include/identity.php b/include/identity.php index ad709841b8..f336891a3c 100644 --- a/include/identity.php +++ b/include/identity.php @@ -8,6 +8,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; require_once 'include/ForumManager.php'; require_once 'include/bbcode.php'; @@ -143,7 +144,7 @@ function get_profiledata_by_nick($nickname, $uid = 0, $profile = 0) { foreach ($_SESSION['remote'] as $visitor) { if ($visitor['uid'] == $uid) { $r = dba::select('contact', array('profile-id'), array('id' => $visitor['cid']), array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $profile = $r['profile-id']; } break; @@ -167,7 +168,7 @@ function get_profiledata_by_nick($nickname, $uid = 0, $profile = 0) { $profile_int ); } - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = dba::fetch_first("SELECT `contact`.`id` AS `contact_id`, `contact`.`photo` as `contact_photo`, `contact`.`thumb` AS `contact_thumb`, `contact`.`micro` AS `contact_micro`, `profile`.`uid` AS `profile_uid`, `profile`.*, @@ -303,7 +304,7 @@ function profile_sidebar($profile, $block = 0) { 'entries' => array(), ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $profile['menu']['entries'][] = array( @@ -382,7 +383,7 @@ function profile_sidebar($profile, $block = 0) { if (is_array($a->profile) && !$a->profile['hide-friends']) { $r = q("SELECT `gcontact`.`updated` FROM `contact` INNER JOIN `gcontact` WHERE `gcontact`.`nurl` = `contact`.`nurl` AND `self` AND `uid` = %d LIMIT 1", intval($a->profile['uid'])); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $updated = date("c", strtotime($r[0]['updated'])); $r = q("SELECT COUNT(*) AS `total` FROM `contact` @@ -395,7 +396,7 @@ function profile_sidebar($profile, $block = 0) { dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $contacts = intval($r[0]['total']); } } @@ -479,12 +480,12 @@ function get_birthdays() { datetime_convert('UTC','UTC','now + 6 days'), datetime_convert('UTC','UTC','now') ); - if (dbm::is_result($s)) { + if (DBM::is_result($s)) { $r = dba::inArray($s); Cache::set($cachekey, $r, CACHE_HOUR); } } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $total = 0; $now = strtotime('now'); $cids = array(); @@ -569,7 +570,7 @@ function get_events() { $r = array(); - if (dbm::is_result($s)) { + if (DBM::is_result($s)) { $now = strtotime('now'); $istoday = false; diff --git a/include/items.php b/include/items.php index e960f89b8c..3ced21cdf3 100644 --- a/include/items.php +++ b/include/items.php @@ -11,7 +11,8 @@ use Friendica\Util\Lock; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\Worker; -use Friendica\Protocol\Dfrn; +use Friendica\Database\DBM; +use Friendica\Protocol\DFRN; require_once 'include/bbcode.php'; require_once 'include/oembed.php'; @@ -429,7 +430,7 @@ function uri_to_guid($uri, $host = "") { */ function store_conversation($arr) { if (in_array($arr['network'], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS))) { - $conversation = array('item-uri' => $arr['uri'], 'received' => dbm::date()); + $conversation = array('item-uri' => $arr['uri'], 'received' => DBM::date()); if (isset($arr['parent-uri']) && ($arr['parent-uri'] != $arr['uri'])) { $conversation['reply-to-uri'] = $arr['parent-uri']; @@ -456,7 +457,7 @@ function store_conversation($arr) { $old_conv = dba::fetch_first("SELECT `item-uri`, `reply-to-uri`, `conversation-uri`, `conversation-href`, `protocol`, `source` FROM `conversation` WHERE `item-uri` = ?", $conversation['item-uri']); - if (dbm::is_result($old_conv)) { + if (DBM::is_result($old_conv)) { // Don't update when only the source has changed. // Only do this when there had been no source before. if ($old_conv['source'] != '') { @@ -570,7 +571,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f $expire_interval = Config::get('system', 'dbclean-expire-days', 0); $r = dba::select('user', array('expire'), array('uid' => $uid), array("limit" => 1)); - if (dbm::is_result($r) && ($r['expire'] > 0) && (($r['expire'] < $expire_interval) || ($expire_interval == 0))) { + if (DBM::is_result($r) && ($r['expire'] > 0) && (($r['expire'] < $expire_interval) || ($expire_interval == 0))) { $expire_interval = $r['expire']; } @@ -596,7 +597,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f dbesc(NETWORK_DFRN), dbesc(NETWORK_OSTATUS) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { // We only log the entries with a different user id than 0. Otherwise we would have too many false positives if ($uid != 0) { logger("Item with uri ".$arr['uri']." already existed for user ".$uid." with id ".$r[0]["id"]." target network ".$r[0]["network"]." - new network: ".$arr['network']); @@ -688,20 +689,20 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f intval($arr['uid']) ); - if (!dbm::is_result($r)) + if (!DBM::is_result($r)) $r = q("SELECT `network` FROM `gcontact` WHERE `network` IN ('%s', '%s', '%s') AND `nurl` = '%s' LIMIT 1", dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS), dbesc(normalise_link($arr['author-link'])) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = q("SELECT `network` FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1", intval($arr['contact-id']), intval($arr['uid']) ); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $arr['network'] = $r[0]["network"]; } @@ -732,7 +733,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f if ($arr["contact-id"] == 0) { $r = q("SELECT `id` FROM `contact` WHERE `self` AND `uid` = %d", intval($uid)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $arr["contact-id"] = $r[0]["id"]; } } @@ -779,7 +780,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f $r = q("SELECT `guid` FROM `item` WHERE `guid` = '%s' AND `network` = '%s' AND `uid` = '%d' LIMIT 1", dbesc($arr['guid']), dbesc($arr['network']), intval($arr['uid'])); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { logger('found item with guid '.$arr['guid'].' for user '.$arr['uid'].' on network '.$arr['network'], LOGGER_DEBUG); return 0; } @@ -808,7 +809,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f intval($arr['uid']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { // is the new message multi-level threaded? // even though we don't support it now, preserve the info @@ -823,7 +824,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f intval($arr['uid']) ); - if (dbm::is_result($z)) { + if (DBM::is_result($z)) { $r = $z; } } @@ -858,7 +859,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f // If its a post from myself then tag the thread as "mention" logger("item_store: Checking if parent ".$parent_id." has to be tagged as mention for user ".$arr['uid'], LOGGER_DEBUG); $u = q("SELECT `nickname` FROM `user` WHERE `uid` = %d", intval($arr['uid'])); - if (dbm::is_result($u)) { + if (DBM::is_result($u)) { $a = get_app(); $self = normalise_link(System::baseUrl() . '/profile/' . $u[0]['nickname']); logger("item_store: 'myself' is ".$self." for parent ".$parent_id." checking against ".$arr['author-link']." and ".$arr['owner-link'], LOGGER_DEBUG); @@ -892,7 +893,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f dbesc(NETWORK_DFRN), intval($arr['uid']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { logger('duplicated item with the same uri found. '.print_r($arr,true)); return 0; } @@ -903,7 +904,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f dbesc($arr['guid']), intval($arr['uid']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { logger('duplicated item with the same guid found. '.print_r($arr,true)); return 0; } @@ -916,7 +917,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f intval($arr['contact-id']), intval($arr['uid']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { logger('duplicated item with the same body found. '.print_r($arr,true)); return 0; } @@ -931,7 +932,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f } else { $isglobal = q("SELECT `global` FROM `item` WHERE `uid` = 0 AND `uri` = '%s'", dbesc($arr["uri"])); - $arr["global"] = (dbm::is_result($isglobal) && count($isglobal) > 0); + $arr["global"] = (DBM::is_result($isglobal) && count($isglobal) > 0); } // ACL settings @@ -973,7 +974,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f */ if ($arr["uid"] == 0) { $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = 0 LIMIT 1", dbesc(trim($arr['uri']))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { logger('Global item already stored. URI: '.$arr['uri'].' on network '.$arr['network'], LOGGER_DEBUG); return 0; } @@ -985,7 +986,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f $r = dba::insert('item', $arr); // When the item was successfully stored we fetch the ID of the item. - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $current_post = dba::lastInsertId(); } else { // This can happen - for example - if there are locking timeouts. @@ -1026,7 +1027,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f dbesc($arr['network']) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { // This shouldn't happen, since COUNT always works when the database connection is there. logger("We couldn't count the stored entries. Very strange ..."); dba::rollback(); @@ -1093,7 +1094,7 @@ function item_store($arr, $force_parent = false, $notify = false, $dontcache = f if (!$deleted && !$dontcache) { $r = q('SELECT * FROM `item` WHERE `id` = %d', intval($current_post)); - if ((dbm::is_result($r)) && (count($r) == 1)) { + if ((DBM::is_result($r)) && (count($r) == 1)) { if ($notify) { call_hooks('post_local_end', $r[0]); } else { @@ -1163,7 +1164,7 @@ function item_set_last_item($arr) { if (!$update && ($arr["network"] == NETWORK_DFRN) && ($arr["parent-uri"] === $arr["uri"])) { $isforum = q("SELECT `forum` FROM `contact` WHERE `id` = %d AND `forum`", intval($arr['contact-id'])); - if (dbm::is_result($isforum)) { + if (DBM::is_result($isforum)) { $update = true; } } @@ -1255,7 +1256,7 @@ function item_body_set_hashtags(&$item) { function get_item_guid($id) { $r = q("SELECT `guid` FROM `item` WHERE `id` = %d LIMIT 1", intval($id)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { return $r[0]["guid"]; } else { /// @TODO This else-block can be elimited again @@ -1277,7 +1278,7 @@ function get_item_id($guid, $uid = 0) { $r = q("SELECT `item`.`id`, `user`.`nickname` FROM `item` INNER JOIN `user` ON `user`.`uid` = `item`.`uid` WHERE `item`.`visible` = 1 AND `item`.`deleted` = 0 AND `item`.`moderated` = 0 AND `item`.`guid` = '%s' AND `item`.`uid` = %d", dbesc($guid), intval($uid)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $id = $r[0]["id"]; $nick = $r[0]["nickname"]; } @@ -1291,7 +1292,7 @@ function get_item_id($guid, $uid = 0) { AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' AND `item`.`private` = 0 AND `item`.`wall` = 1 AND `item`.`guid` = '%s'", dbesc($guid)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $id = $r[0]["id"]; $nick = $r[0]["nickname"]; } @@ -1329,7 +1330,7 @@ function tag_deliver($uid, $item_id) { intval($uid) ); - if (! dbm::is_result($u)) { + if (! DBM::is_result($u)) { return; } @@ -1341,7 +1342,7 @@ function tag_deliver($uid, $item_id) { intval($item_id), intval($uid) ); - if (! dbm::is_result($i)) { + if (! DBM::is_result($i)) { return; } @@ -1398,7 +1399,7 @@ function tag_deliver($uid, $item_id) { $c = q("SELECT `name`, `url`, `thumb` FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($u[0]['uid']) ); - if (! dbm::is_result($c)) { + if (! DBM::is_result($c)) { return; } @@ -1443,7 +1444,7 @@ function tgroup_check($uid, $item) { $u = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($uid) ); - if (! dbm::is_result($u)) { + if (! DBM::is_result($u)) { return false; } @@ -1562,9 +1563,9 @@ function consume_feed($xml, $importer, &$contact, &$hub, $datedir = 0, $pass = 0 WHERE `contact`.`id` = %d AND `user`.`uid` = %d", dbesc($contact["id"]), dbesc($importer["uid"]) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { logger("Now import the DFRN feed"); - Dfrn::import($xml, $r[0], true); + DFRN::import($xml, $r[0], true); return; } } @@ -1602,7 +1603,7 @@ function item_is_remote_self($contact, &$datarray) { if ($contact['remote_self'] == 2) { $r = q("SELECT `id`,`url`,`name`,`thumb` FROM `contact` WHERE `uid` = %d AND `self`", intval($contact['uid'])); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $datarray['contact-id'] = $r[0]["id"]; $datarray['owner-name'] = $r[0]["name"]; @@ -1691,7 +1692,7 @@ function new_follower($importer, $contact, $datarray, $item, $sharing = false) { intval($importer['uid']), dbesc($url) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact_record = $r[0]; update_contact_avatar($photo, $importer["uid"], $contact_record["id"], true); } @@ -1701,7 +1702,7 @@ function new_follower($importer, $contact, $datarray, $item, $sharing = false) { intval($importer['uid']) ); - if (dbm::is_result($r) && !in_array($r[0]['page-flags'], array(PAGE_SOAPBOX, PAGE_FREELOVE, PAGE_COMMUNITY))) { + if (DBM::is_result($r) && !in_array($r[0]['page-flags'], array(PAGE_SOAPBOX, PAGE_FREELOVE, PAGE_COMMUNITY))) { // create notification $hash = random_string(); @@ -1737,7 +1738,7 @@ function new_follower($importer, $contact, $datarray, $item, $sharing = false) { )); } - } elseif (dbm::is_result($r) && in_array($r[0]['page-flags'], array(PAGE_SOAPBOX, PAGE_FREELOVE, PAGE_COMMUNITY))) { + } elseif (DBM::is_result($r) && in_array($r[0]['page-flags'], array(PAGE_SOAPBOX, PAGE_FREELOVE, PAGE_COMMUNITY))) { $r = q("UPDATE `contact` SET `pending` = 0 WHERE `uid` = %d AND `url` = '%s' AND `pending` LIMIT 1", intval($importer['uid']), dbesc($url) @@ -1780,7 +1781,7 @@ function subscribe_to_hub($url, $importer, $contact, $hubmode = 'subscribe') { * through the direct Diaspora protocol. If we try and use * the feed, we'll get duplicates. So don't. */ - if ((! dbm::is_result($r)) || $contact['network'] === NETWORK_DIASPORA) { + if ((! DBM::is_result($r)) || $contact['network'] === NETWORK_DIASPORA) { return; } @@ -1846,7 +1847,7 @@ function fix_private_photos($s, $uid, $item = null, $cid = 0) { intval($uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { /* * Check to see if we should replace this photo link with an embedded image * 1. No need to do so if the photo is public @@ -2017,7 +2018,7 @@ function item_expire($uid, $days, $network = "", $force = false) { intval($days) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { return; } @@ -2100,7 +2101,7 @@ function drop_item($id, $interactive = true) { intval($id) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { if (! $interactive) { return 0; } @@ -2267,7 +2268,7 @@ function drop_item($id, $interactive = true) { dbesc($item['parent-uri']), intval($item['uid']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { dba::update('item', array('last-child' => true), array('id' => $r[0]['id'])); } } @@ -2304,7 +2305,7 @@ function first_post_date($uid, $wall = false) { intval($uid), intval($wall ? 1 : 0) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { // logger('first_post_date: ' . $r[0]['id'] . ' ' . $r[0]['created'], LOGGER_DATA); return substr(datetime_convert('',date_default_timezone_get(), $r[0]['created']),0,10); } @@ -2397,7 +2398,7 @@ function posted_date_widget($url, $uid, $wall) { $ret = list_post_dates($uid, $wall); - if (! dbm::is_result($ret)) { + if (! DBM::is_result($ret)) { return $o; } diff --git a/include/like.php b/include/like.php index a6e67c0ba5..eee89168a9 100644 --- a/include/like.php +++ b/include/like.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; use Friendica\Protocol\Diaspora; /** @@ -71,7 +72,7 @@ function do_like($item_id, $verb) { dbesc($item_id) ); - if (! $item_id || ! dbm::is_result($items)) { + if (! $item_id || ! DBM::is_result($items)) { logger('like: unknown item ' . $item_id); return false; } @@ -89,7 +90,7 @@ function do_like($item_id, $verb) { AND `contact`.`uid` = %d", intval($item['uid']) ); - if (dbm::is_result($owners)) { + if (DBM::is_result($owners)) { $owner_self_contact = $owners[0]; } else { logger('like: unknown owner ' . $item['uid']); @@ -102,7 +103,7 @@ function do_like($item_id, $verb) { $contacts = q("SELECT * FROM `contact` WHERE `id` = %d", intval($author_id) ); - if (dbm::is_result($contacts)) { + if (DBM::is_result($contacts)) { $author_contact = $contacts[0]; } else { logger('like: unknown author ' . $author_id); @@ -119,7 +120,7 @@ function do_like($item_id, $verb) { $contacts = q("SELECT * FROM `contact` WHERE `id` = %d", intval($item_contact_id) ); - if (dbm::is_result($contacts)) { + if (DBM::is_result($contacts)) { $item_contact = $contacts[0]; } else { logger('like: unknown item contact ' . $item_contact_id); @@ -149,7 +150,7 @@ function do_like($item_id, $verb) { ); // If it exists, mark it as deleted - if (dbm::is_result($existing_like)) { + if (DBM::is_result($existing_like)) { $like_item = $existing_like[0]; // Already voted, undo it diff --git a/include/message.php b/include/message.php index 0202604b70..dcc1fbc12e 100644 --- a/include/message.php +++ b/include/message.php @@ -5,6 +5,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; function send_message($recipient=0, $body='', $subject='', $replyto=''){ @@ -42,7 +43,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){ dbesc($replyto), dbesc($replyto) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $convid = $r[0]['convid']; } @@ -67,7 +68,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){ $r = dba::insert('conv', $fields); $r = dba::select('conv', array('id'), array('guid' => $conv_guid, 'uid' => local_user()), array('limit' => 1)); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $convid = $r['id']; } @@ -106,7 +107,7 @@ function send_message($recipient=0, $body='', $subject='', $replyto=''){ dbesc($uri), intval(local_user()) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $post_id = $r[0]['id']; /** @@ -191,7 +192,7 @@ function send_wallmessage($recipient='', $body='', $subject='', $replyto=''){ $r = dba::insert('conv', $fields); $r = dba::select('conv', array('id'), array('guid' => $conv_guid, 'uid' => $recipient['uid']), array('limit' => 1)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { logger('send message: conversation not found.'); return -4; } diff --git a/include/nav.php b/include/nav.php index 478213b4e0..411f0ac5da 100644 --- a/include/nav.php +++ b/include/nav.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; +use Friendica\Database\DBM; function nav(App $a) { @@ -92,7 +93,7 @@ function nav_info(App $a) // user info $r = dba::select('contact', array('micro'), array('uid' => $a->user['uid'], 'self' => true), array('limit' => 1)); $userinfo = array( - 'icon' => (dbm::is_result($r) ? $a->remove_baseurl($r['micro']) : 'images/person-48.jpg'), + 'icon' => (DBM::is_result($r) ? $a->remove_baseurl($r['micro']) : 'images/person-48.jpg'), 'name' => $a->user['username'], ); } else { diff --git a/include/notifier.php b/include/notifier.php index 26d6eeb990..3e9ea66f2c 100644 --- a/include/notifier.php +++ b/include/notifier.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\Worker; +use Friendica\Database\DBM; use Friendica\Network\Probe; use Friendica\Protocol\Diaspora; @@ -158,7 +159,7 @@ function notifier_run(&$argv, &$argc){ intval($item_id) ); - if ((! dbm::is_result($r)) || (! intval($r[0]['parent']))) { + if ((! DBM::is_result($r)) || (! intval($r[0]['parent']))) { return; } @@ -199,7 +200,7 @@ function notifier_run(&$argv, &$argc){ intval($uid) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { return; } @@ -298,7 +299,7 @@ function notifier_run(&$argv, &$argc){ $fields = array('forum', 'prv'); $condition = array('id' => $target_item['contact-id']); $contact = dba::select('contact', $fields, $condition, array('limit' => 1)); - if (!dbm::is_result($contact)) { + if (!DBM::is_result($contact)) { // Should never happen return false; } @@ -335,7 +336,7 @@ function notifier_run(&$argv, &$argc){ intval($uid), dbesc(NETWORK_DFRN) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $recipients_followup[] = $rr['id']; } @@ -423,7 +424,7 @@ function notifier_run(&$argv, &$argc){ $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''", dbesc(normalise_link($thr_parent[0]['author-link'])), intval($uid)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $probed_contact = $r[0]; } else { $probed_contact = Probe::uri($thr_parent[0]['author-link']); @@ -438,7 +439,7 @@ function notifier_run(&$argv, &$argc){ $r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''", dbesc(normalise_link($thr_parent[0]['owner-link'])), intval($uid)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $probed_contact = $r[0]; } else { $probed_contact = Probe::uri($thr_parent[0]['owner-link']); @@ -484,7 +485,7 @@ function notifier_run(&$argv, &$argc){ intval($uid), dbesc(NETWORK_MAIL) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $recipients[] = $rr['id']; } @@ -508,7 +509,7 @@ function notifier_run(&$argv, &$argc){ // delivery loop - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $contact) { if ($contact['self']) { continue; @@ -565,7 +566,7 @@ function notifier_run(&$argv, &$argc){ $r = array_merge($r2,$r1,$r0); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { logger('pubdeliver '.$target_item["guid"].': '.print_r($r,true), LOGGER_DEBUG); foreach ($r as $rr) { diff --git a/include/oauth.php b/include/oauth.php index f89aedf6b7..bb12278685 100644 --- a/include/oauth.php +++ b/include/oauth.php @@ -9,6 +9,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; +use Friendica\Database\DBM; define('REQUEST_TOKEN_DURATION', 300); define('ACCESS_TOKEN_DURATION', 31536000); @@ -28,7 +29,7 @@ class FKOAuthDataStore extends OAuthDataStore { $r = q("SELECT client_id, pw, redirect_uri FROM clients WHERE client_id='%s'", dbesc($consumer_key) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) return new OAuthConsumer($r[0]['client_id'],$r[0]['pw'],$r[0]['redirect_uri']); return null; } @@ -40,7 +41,7 @@ class FKOAuthDataStore extends OAuthDataStore { dbesc($token_type), dbesc($token) ); - if (dbm::is_result($r)){ + if (DBM::is_result($r)){ $ot=new OAuthToken($r[0]['id'],$r[0]['secret']); $ot->scope=$r[0]['scope']; $ot->expires = $r[0]['expires']; @@ -57,7 +58,7 @@ class FKOAuthDataStore extends OAuthDataStore { dbesc($nonce), intval($timestamp) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) return new OAuthToken($r[0]['id'],$r[0]['secret']); return null; } @@ -141,7 +142,7 @@ class FKOAuth1 extends OAuthServer { $r = q("SELECT * FROM `user` WHERE uid=%d AND `blocked` = 0 AND `account_expired` = 0 AND `account_removed` = 0 AND `verified` = 1 LIMIT 1", intval($uid) ); - if (dbm::is_result($r)){ + if (DBM::is_result($r)){ $record = $r[0]; } else { logger('FKOAuth1::loginUser failure: ' . print_r($_SERVER,true), LOGGER_DEBUG); @@ -167,7 +168,7 @@ class FKOAuth1 extends OAuthServer { $r = q("SELECT * FROM `contact` WHERE `uid` = %s AND `self` = 1 LIMIT 1", intval($_SESSION['uid'])); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $a->contact = $r[0]; $a->cid = $r[0]['id']; $_SESSION['cid'] = $a->cid; @@ -224,7 +225,7 @@ class FKOAuth2 extends OAuth2 { $r = q("SELECT client_id, expires, scope FROM tokens WHERE id = '%s'", dbesc($oauth_token)); - if (dbm::is_result($r)) + if (DBM::is_result($r)) return $r[0]; return null; } @@ -252,7 +253,7 @@ class FKOAuth2 extends OAuth2 { $r = q("SELECT id, client_id, redirect_uri, expires, scope FROM auth_codes WHERE id = '%s'", dbesc($code)); - if (dbm::is_result($r)) + if (DBM::is_result($r)) return $r[0]; return null; } diff --git a/include/oembed.php b/include/oembed.php index 715a0ba5bd..18230fe87a 100755 --- a/include/oembed.php +++ b/include/oembed.php @@ -8,6 +8,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\ParseUrl; use Friendica\Core\Config; +use Friendica\Database\DBM; function oembed_replacecb($matches){ $embedurl=$matches[1]; @@ -35,7 +36,7 @@ function oembed_fetch_url($embedurl, $no_rich_type = false){ $r = q("SELECT * FROM `oembed` WHERE `url` = '%s'", dbesc(normalise_link($embedurl))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $txt = $r[0]["content"]; } else { $txt = Cache::get($a->videowidth . $embedurl); diff --git a/include/onepoll.php b/include/onepoll.php index f64ea40ecb..c9fbb1610e 100644 --- a/include/onepoll.php +++ b/include/onepoll.php @@ -2,6 +2,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; +use Friendica\Database\DBM; require_once 'include/follow.php'; @@ -78,7 +79,7 @@ function onepoll_run(&$argv, &$argc) { WHERE `cid` = %d AND updated > UTC_TIMESTAMP() - INTERVAL 1 DAY", intval($contact['id']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if (!$r[0]['total']) { poco_load($contact['id'], $importer_uid, 0, $contact['poco']); } @@ -147,7 +148,7 @@ function onepoll_run(&$argv, &$argc) { intval($importer_uid) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { logger('No self contact for user '.$importer_uid); return; } @@ -331,7 +332,7 @@ function onepoll_run(&$argv, &$argc) { $condition = array("`server` != '' AND `uid` = ?", $importer_uid); $mailconf = dba::select('mailacct', array(), $condition, array('limit' => 1)); - if (dbm::is_result($x) && dbm::is_result($mailconf)) { + if (DBM::is_result($x) && DBM::is_result($mailconf)) { $mailbox = construct_mailbox_name($mailconf); $password = ''; openssl_private_decrypt(hex2bin($mailconf['pass']), $password, $x['prvkey']); @@ -375,7 +376,7 @@ function onepoll_run(&$argv, &$argc) { $condition = array('uid' => $importer_uid, 'uri' => $datarray['uri']); $r = dba::select('item', $fields, $condition, array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { logger("Mail: Seen before ".$msg_uid." for ".$mailconf['user']." UID: ".$importer_uid." URI: ".$datarray['uri'],LOGGER_DEBUG); // Only delete when mails aren't automatically moved or deleted @@ -427,7 +428,7 @@ function onepoll_run(&$argv, &$argc) { $r = q("SELECT `parent-uri` FROM `item` USE INDEX (`uid_uri`) WHERE `uri` IN ($qstr) AND `uid` = %d LIMIT 1", intval($importer_uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $datarray['parent-uri'] = $r[0]['parent-uri']; // Set the parent as the top-level item } } @@ -461,7 +462,7 @@ function onepoll_run(&$argv, &$argc) { dbesc(protect_sprintf($datarray['title'])), intval($importer_uid), dbesc(NETWORK_MAIL)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $datarray['parent-uri'] = $r[0]['parent-uri']; } } diff --git a/include/ostatus.php b/include/ostatus.php index bafa2ddc5d..51ca6e2356 100644 --- a/include/ostatus.php +++ b/include/ostatus.php @@ -6,6 +6,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; +use Friendica\Database\DBM; use Friendica\Network\Probe; use Friendica\Util\Lock; @@ -70,7 +71,7 @@ class ostatus { $importer["uid"], $aliaslink, NETWORK_STATUSNET); $r = dba::select('contact', array(), $condition, array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $found = true; if ($r['blocked']) { $r['id'] = -1; @@ -89,7 +90,7 @@ class ostatus { normalise_link($author["author-link"]), normalise_link($aliaslink), NETWORK_STATUSNET); $r = dba::select('contact', array(), $condition, array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $found = true; if ($r['blocked']) { $r['id'] = -1; @@ -104,7 +105,7 @@ class ostatus { $importer["uid"], $addr, NETWORK_STATUSNET); $r = dba::select('contact', array(), $condition, array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $found = true; if ($r['blocked']) { $r['id'] = -1; @@ -529,7 +530,7 @@ class ostatus { $condition = array('uid' => $item['uid'], 'author-link' => $item['author-link'], 'uri' => $item['uri']); $deleted = dba::select('item', array('id', 'parent-uri'), $condition, array('limit' => 1)); - if (!dbm::is_result($deleted)) { + if (!DBM::is_result($deleted)) { logger('Item from '.$item['author-link'].' with uri '.$item['uri'].' for user '.$item['uid']." wasn't found. We don't delete it. "); return; } @@ -868,7 +869,7 @@ class ostatus { private static function fetchRelated($related, $related_uri, $importer) { $condition = array('`item-uri` = ? AND `protocol` IN (?, ?)', $related_uri, PROTOCOL_DFRN, PROTOCOL_OSTATUS_SALMON); $conversation = dba::select('conversation', array('source', 'protocol'), $condition, array('limit' => 1)); - if (dbm::is_result($conversation)) { + if (DBM::is_result($conversation)) { $stored = true; $xml = $conversation['source']; if (self::process($xml, $importer, $contact, $hub, $stored, false)) { @@ -948,7 +949,7 @@ class ostatus { if ($xml == '') { $condition = array('item-uri' => $related_uri, 'protocol' => PROTOCOL_SPLITTED_CONV); $conversation = dba::select('conversation', array('source'), $condition, array('limit' => 1)); - if (dbm::is_result($conversation)) { + if (DBM::is_result($conversation)) { $stored = true; logger('Got cached XML from conversation for URI '.$related_uri, LOGGER_DEBUG); $xml = $conversation['source']; @@ -1336,7 +1337,7 @@ class ostatus { private static function add_author($doc, $owner) { $r = q("SELECT `homepage`, `publish` FROM `profile` WHERE `uid` = %d AND `is-default` LIMIT 1", intval($owner["uid"])); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $profile = $r[0]; } $author = $doc->createElement("author"); @@ -1493,22 +1494,22 @@ class ostatus { $r = q("SELECT * FROM `contact` WHERE `nurl` = '%s' AND `uid` IN (0, %d) ORDER BY `uid` DESC LIMIT 1", dbesc(normalise_link($url)), intval($owner["uid"])); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact = $r[0]; $contact["uid"] = -1; } - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", dbesc(normalise_link($url))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact = $r[0]; $contact["uid"] = -1; $contact["success_update"] = $contact["updated"]; } } - if (!dbm::is_result($r)) + if (!DBM::is_result($r)) $contact = owner; if (!isset($contact["poll"])) { @@ -1547,7 +1548,7 @@ class ostatus { $r = q("SELECT * FROM `item` WHERE `uid` = %d AND `guid` = '%s' AND NOT `private` AND `network` IN ('%s', '%s', '%s') LIMIT 1", intval($owner["uid"]), dbesc($repeated_guid), dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $repeated_item = $r[0]; } else { return false; @@ -1702,7 +1703,7 @@ class ostatus { $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s'", intval($owner['uid']), dbesc(normalise_link($contact["url"]))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $connect_id = $r[0]['id']; } else { $connect_id = 0; @@ -1886,7 +1887,7 @@ class ostatus { if (isset($parent_item)) { $r = dba::fetch_first("SELECT `conversation-uri`, `conversation-href` FROM `conversation` WHERE `item-uri` = ?", $parent_item); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if ($r['conversation-uri'] != '') { $conversation_uri = $r['conversation-uri']; } @@ -1996,7 +1997,7 @@ class ostatus { FROM `contact` INNER JOIN `user` ON `user`.`uid` = `contact`.`uid` WHERE `contact`.`self` AND `user`.`nickname` = '%s' LIMIT 1", dbesc($owner_nick)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } diff --git a/include/plugin.php b/include/plugin.php index c4daa6c020..2814b24647 100644 --- a/include/plugin.php +++ b/include/plugin.php @@ -8,6 +8,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; +use Friendica\Database\DBM; /** * @brief uninstalls an addon. @@ -77,7 +78,7 @@ function reload_plugins() { if (strlen($plugins)) { $r = q("SELECT * FROM `addon` WHERE `installed` = 1"); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $installed = $r; else $installed = array(); @@ -144,7 +145,7 @@ function register_hook($hook,$file,$function,$priority=0) { dbesc($file), dbesc($function) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) return true; $r = dba::insert('hook', array('hook' => $hook, 'file' => $file, 'function' => $function, 'priority' => $priority)); diff --git a/include/post_update.php b/include/post_update.php index 210ab79fec..1d27f33996 100644 --- a/include/post_update.php +++ b/include/post_update.php @@ -4,6 +4,7 @@ */ use Friendica\Core\Config; +use Friendica\Database\DBM; /** * @brief Calls the post update functions @@ -187,7 +188,7 @@ function post_update_1198() { (`thread`.`uid` IN (SELECT `uid` from `user`) OR `thread`.`uid` = 0)"); logger("Updated threads", LOGGER_DEBUG); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { Config::set("system", "post_update_version", 1198); logger("Done", LOGGER_DEBUG); return true; @@ -245,7 +246,7 @@ function post_update_1206() { FROM `user` INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid` AND `contact`.`self`"); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return false; } foreach ($r AS $user) { diff --git a/include/pubsubpublish.php b/include/pubsubpublish.php index c662198abd..52a707b8bc 100644 --- a/include/pubsubpublish.php +++ b/include/pubsubpublish.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\Worker; +use Friendica\Database\DBM; require_once('include/items.php'); require_once('include/ostatus.php'); @@ -34,7 +35,7 @@ function handle_pubsubhubbub($id) { global $a; $r = q("SELECT * FROM `push_subscriber` WHERE `id` = %d", intval($id)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } diff --git a/include/queue.php b/include/queue.php index 057987c87e..c930cd9cff 100644 --- a/include/queue.php +++ b/include/queue.php @@ -2,8 +2,9 @@ use Friendica\Core\Config; use Friendica\Core\Worker; +use Friendica\Database\DBM; use Friendica\Protocol\Diaspora; -use Friendica\Protocol\Dfrn; +use Friendica\Protocol\DFRN; require_once 'include/queue_fn.php'; require_once 'include/datetime.php'; @@ -35,7 +36,7 @@ function queue_run(&$argv, &$argc) { INNER JOIN `contact` ON `queue`.`cid` = `contact`.`id` WHERE `queue`.`created` < UTC_TIMESTAMP() - INTERVAL 3 DAY"); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { logger('Removing expired queue item for ' . $rr['name'] . ', uid=' . $rr['uid']); logger('Expired queue data: ' . $rr['content'], LOGGER_DATA); @@ -51,7 +52,7 @@ function queue_run(&$argv, &$argc) { call_hooks('queue_predeliver', $a, $r); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $q_item) { logger('Call queue for id '.$q_item['id']); Worker::add(array('priority' => PRIORITY_LOW, 'dont_fork' => true), "queue", (int)$q_item['id']); @@ -68,7 +69,7 @@ function queue_run(&$argv, &$argc) { $r = q("SELECT * FROM `queue` WHERE `id` = %d LIMIT 1", intval($queue_id)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -78,7 +79,7 @@ function queue_run(&$argv, &$argc) { intval($q_item['cid']) ); - if (!dbm::is_result($c)) { + if (!DBM::is_result($c)) { remove_queue_item($q_item['id']); return; } @@ -114,7 +115,7 @@ function queue_run(&$argv, &$argc) { FROM `user` WHERE `uid` = %d LIMIT 1", intval($c[0]['uid']) ); - if (!dbm::is_result($u)) { + if (!DBM::is_result($u)) { remove_queue_item($q_item['id']); return; } @@ -129,7 +130,7 @@ function queue_run(&$argv, &$argc) { switch ($contact['network']) { case NETWORK_DFRN: logger('queue: dfrndelivery: item '.$q_item['id'].' for '.$contact['name'].' <'.$contact['url'].'>'); - $deliver_status = Dfrn::deliver($owner, $contact, $data); + $deliver_status = DFRN::deliver($owner, $contact, $data); if ($deliver_status == (-1)) { update_queue_time($q_item['id']); diff --git a/include/queue_fn.php b/include/queue_fn.php index 475ac1eb09..e6fd14e07c 100644 --- a/include/queue_fn.php +++ b/include/queue_fn.php @@ -1,6 +1,7 @@ $batch_queue)) { logger('add_to_queue: too many queued items for batch server ' . $cid . ' - discarding message'); return; diff --git a/include/redir.php b/include/redir.php index 8c04d711ed..060d0e9bf3 100644 --- a/include/redir.php +++ b/include/redir.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; function auto_redir(App $a, $contact_nick) { @@ -39,7 +40,7 @@ function auto_redir(App $a, $contact_nick) { dbesc($nurl) ); - if ((! dbm::is_result($r)) || $r[0]['id'] == remote_user()) { + if ((! DBM::is_result($r)) || $r[0]['id'] == remote_user()) { return; } @@ -51,7 +52,7 @@ function auto_redir(App $a, $contact_nick) { dbesc($baseurl) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { return; } diff --git a/include/security.php b/include/security.php index c885a7b1b9..18793ce060 100644 --- a/include/security.php +++ b/include/security.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; +use Friendica\Database\DBM; /** * @brief Calculate the hash that is needed for the "Friendica" cookie @@ -87,14 +88,14 @@ function authenticate_success($user_record, $login_initial = false, $interactive $r = dba::fetch_first("SELECT * FROM `user` WHERE `uid` = ? LIMIT 1", intval($_SESSION['submanage']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $master_record = $r; } } $r = dba::select('user', array('uid', 'username', 'nickname'), array('password' => $master_record['password'], 'email' => $master_record['email'], 'account_removed' => false)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $a->identities = dba::inArray($r); } else { $a->identities = array(); @@ -106,7 +107,7 @@ function authenticate_success($user_record, $login_initial = false, $interactive WHERE `user`.`account_removed` = 0 AND `manage`.`uid` = ?", $master_record['uid'] ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $a->identities = array_merge($a->identities, dba::inArray($r)); } @@ -118,7 +119,7 @@ function authenticate_success($user_record, $login_initial = false, $interactive } $r = dba::fetch_first("SELECT * FROM `contact` WHERE `uid` = ? AND `self` LIMIT 1", $_SESSION['uid']); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $a->contact = $r; $a->cid = $r['id']; $_SESSION['cid'] = $a->cid; @@ -209,7 +210,7 @@ function can_write_wall(App $a, $owner) { intval(PAGE_COMMUNITY) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $verified = 2; return true; } @@ -259,7 +260,7 @@ function permissions_sql($owner_id, $remote_verified = false, $groups = null) { intval($remote_user), intval($owner_id) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $remote_verified = true; $groups = init_groups_visitor($remote_user); } @@ -338,7 +339,7 @@ function item_permissions_sql($owner_id, $remote_verified = false, $groups = nul intval($remote_user), intval($owner_id) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $remote_verified = true; $groups = init_groups_visitor($remote_user); } @@ -456,7 +457,7 @@ function init_groups_visitor($contact_id) { WHERE `contact-id` = %d ", intval($contact_id) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) $groups[] = $rr['gid']; } diff --git a/include/session.php b/include/session.php index f53465501c..812de547c4 100644 --- a/include/session.php +++ b/include/session.php @@ -3,6 +3,7 @@ // session info. use Friendica\Core\Config; +use Friendica\Database\DBM; require_once('include/cache.php'); @@ -32,7 +33,7 @@ function ref_session_read($id) { } $r = dba::select('session', array('data'), array('sid' => $id), array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $session_exists = true; return $r['data']; } else { diff --git a/include/socgraph.php b/include/socgraph.php index e5c612e827..e1c0e13856 100644 --- a/include/socgraph.php +++ b/include/socgraph.php @@ -11,6 +11,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\Worker; +use Friendica\Database\DBM; use Friendica\Network\Probe; require_once 'include/datetime.php'; @@ -59,7 +60,7 @@ function poco_load_worker($cid, $uid, $zcid, $url) { $r = q("select `poco`, `uid` from `contact` where `id` = %d limit 1", intval($cid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $url = $r[0]['poco']; $uid = $r[0]['uid']; } @@ -252,7 +253,7 @@ function sanitize_gcontact($gcontact) { $r = q("SELECT `network` FROM `contact` WHERE `uid` = 0 AND `nurl` = '%s' AND `network` != '' AND `network` != '%s' LIMIT 1", dbesc(normalise_link($gcontact['url'])), dbesc(NETWORK_STATUSNET) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $gcontact['network'] = $r[0]["network"]; } @@ -260,7 +261,7 @@ function sanitize_gcontact($gcontact) { $r = q("SELECT `network`, `url` FROM `contact` WHERE `uid` = 0 AND `alias` IN ('%s', '%s') AND `network` != '' AND `network` != '%s' LIMIT 1", dbesc($gcontact['url']), dbesc(normalise_link($gcontact['url'])), dbesc(NETWORK_STATUSNET) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $gcontact['network'] = $r[0]["network"]; } } @@ -273,7 +274,7 @@ function sanitize_gcontact($gcontact) { dbesc(normalise_link($gcontact['url'])) ); - if (dbm::is_result($x)) { + if (DBM::is_result($x)) { if (!isset($gcontact['network']) && ($x[0]["network"] != NETWORK_STATUSNET)) { $gcontact['network'] = $x[0]["network"]; } @@ -305,7 +306,7 @@ function sanitize_gcontact($gcontact) { if ($alternate && ($gcontact['network'] == NETWORK_OSTATUS)) { // Delete the old entry - if it exists $r = q("SELECT `id` FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { q("DELETE FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($orig_profile))); q("DELETE FROM `glink` WHERE `gcid` = %d", intval($r[0]["id"])); } @@ -360,7 +361,7 @@ function link_gcontact($gcid, $uid = 0, $cid = 0, $zcid = 0) { intval($zcid) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { q("INSERT INTO `glink` (`cid`, `uid`, `gcid`, `zcid`, `updated`) VALUES (%d, %d, %d, %d, '%s') ", intval($cid), intval($uid), @@ -454,7 +455,7 @@ function poco_detect_server($profile) { $r = q("SELECT `id` FROM `gserver` WHERE `nurl` = '%s' AND `last_contact` > `last_failure`", dbesc(normalise_link($server_url))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { return $server_url; } @@ -476,7 +477,7 @@ function poco_last_updated($profile, $force = false) { $gcontacts = q("SELECT * FROM `gcontact` WHERE `nurl` = '%s'", dbesc(normalise_link($profile))); - if (!dbm::is_result($gcontacts)) { + if (!DBM::is_result($gcontacts)) { return false; } @@ -688,7 +689,7 @@ function poco_last_updated($profile, $force = false) { } } q("UPDATE `gcontact` SET `updated` = '%s', `last_contact` = '%s' WHERE `nurl` = '%s'", - dbesc(dbm::date($last_updated)), dbesc(dbm::date()), dbesc(normalise_link($profile))); + dbesc(DBM::date($last_updated)), dbesc(DBM::date()), dbesc(normalise_link($profile))); if (($gcontacts[0]["generation"] == 0)) { q("UPDATE `gcontact` SET `generation` = 9 WHERE `nurl` = '%s'", @@ -970,7 +971,7 @@ function poco_check_server($server_url, $network = "", $force = false) { } $servers = q("SELECT * FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url))); - if (dbm::is_result($servers)) { + if (DBM::is_result($servers)) { if ($servers[0]["created"] <= NULL_DATE) { q("UPDATE `gserver` SET `created` = '%s' WHERE `nurl` = '%s'", @@ -1023,7 +1024,7 @@ function poco_check_server($server_url, $network = "", $force = false) { // Quit if there is a timeout. // But we want to make sure to only quit if we are mostly sure that this server url fits. - if (dbm::is_result($servers) && ($orig_server_url == $server_url) && + if (DBM::is_result($servers) && ($orig_server_url == $server_url) && ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT)) { logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG); dba::update('gserver', array('last_failure' => datetime_convert()), array('nurl' => normalise_link($server_url))); @@ -1417,7 +1418,7 @@ function count_common_friends($uid, $cid) { ); // logger("count_common_friends: $uid $cid {$r[0]['total']}"); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { return $r[0]['total']; } return 0; @@ -1450,7 +1451,7 @@ function common_friends($uid, $cid, $start = 0, $limit = 9999, $shuffle = false) intval($limit) ); - /// @TODO Check all calling-findings of this function if they properly use dbm::is_result() + /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() return $r; } @@ -1466,7 +1467,7 @@ function count_common_friends_zcid($uid, $zcid) { intval($uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { return $r[0]['total']; } return 0; @@ -1492,7 +1493,7 @@ function common_friends_zcid($uid, $zcid, $start = 0, $limit = 9999, $shuffle = intval($limit) ); - /// @TODO Check all calling-findings of this function if they properly use dbm::is_result() + /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() return $r; } @@ -1508,7 +1509,7 @@ function count_all_friends($uid, $cid) { intval($uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { return $r[0]['total']; } return 0; @@ -1532,7 +1533,7 @@ function all_friends($uid, $cid, $start = 0, $limit = 80) { intval($limit) ); - /// @TODO Check all calling-findings of this function if they properly use dbm::is_result() + /// @TODO Check all calling-findings of this function if they properly use DBM::is_result() return $r; } @@ -1587,7 +1588,7 @@ function suggestion_query($uid, $start = 0, $limit = 80) { intval($limit) ); - if (dbm::is_result($r) && count($r) >= ($limit -1)) { + if (DBM::is_result($r) && count($r) >= ($limit -1)) { /* * Uncommented because the result of the queries are to big to store it in the cache. * We need to decide if we want to change the db column type or if we want to delete it. @@ -1670,7 +1671,7 @@ function update_suggestions() { dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $base = substr($rr['poco'],0,strrpos($rr['poco'],'/')); if (! in_array($base,$done)) { @@ -1700,7 +1701,7 @@ function poco_fetch_serverlist($poco) { $server_url = str_replace("/index.php", "", $server->url); $r = q("SELECT `nurl` FROM `gserver` WHERE `nurl` = '%s'", dbesc(normalise_link($server_url))); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { logger("Call server check for server ".$server_url, LOGGER_DEBUG); Worker::add(PRIORITY_LOW, "discover_poco", "server", $server_url); } @@ -1762,7 +1763,7 @@ function poco_discover_federation() { function poco_discover_single_server($id) { $r = q("SELECT `poco`, `nurl`, `url`, `network` FROM `gserver` WHERE `id` = %d", intval($id)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return false; } @@ -1837,7 +1838,7 @@ function poco_discover($complete = false) { $last_update = date("c", time() - (60 * 60 * 24 * $requery_days)); $r = q("SELECT `id`, `url`, `network` FROM `gserver` WHERE `last_contact` >= `last_failure` AND `poco` != '' AND `last_poco_query` < '%s' ORDER BY RAND()", dbesc($last_update)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $server) { if (!poco_check_server($server["url"], $server["network"])) { @@ -2083,7 +2084,7 @@ function get_gcontact_id($contact) { $r = q("SELECT `id`, `last_contact`, `last_failure`, `network` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", dbesc(normalise_link($contact["url"]))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $gcontact_id = $r[0]["id"]; // Update every 90 days @@ -2115,7 +2116,7 @@ function get_gcontact_id($contact) { $r = q("SELECT `id`, `network` FROM `gcontact` WHERE `nurl` = '%s' ORDER BY `id` LIMIT 2", dbesc(normalise_link($contact["url"]))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $gcontact_id = $r[0]["id"]; $doprobing = in_array($r[0]["network"], array(NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, "")); @@ -2198,7 +2199,7 @@ function update_gcontact($contact) { fix_alternate_contact_address($contact); if (!isset($contact["updated"])) { - $contact["updated"] = dbm::date(); + $contact["updated"] = DBM::date(); } if ($contact["network"] == NETWORK_TWITTER) { @@ -2241,7 +2242,7 @@ function update_gcontact($contact) { logger("Update gcontact for ".$contact["url"], LOGGER_DEBUG); $condition = array('`nurl` = ? AND (`generation` = 0 OR `generation` >= ?)', normalise_link($contact["url"]), $contact["generation"]); - $contact["updated"] = dbm::date($contact["updated"]); + $contact["updated"] = DBM::date($contact["updated"]); $updated = array('photo' => $contact['photo'], 'name' => $contact['name'], 'nick' => $contact['nick'], 'addr' => $contact['addr'], @@ -2261,7 +2262,7 @@ function update_gcontact($contact) { $r = q("SELECT `id` FROM `contact` WHERE `nurl` = '%s' AND `uid` = 0 ORDER BY `id` LIMIT 1", dbesc(normalise_link($contact["url"]))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { logger("Update public contact ".$r[0]["id"], LOGGER_DEBUG); update_contact_avatar($contact["photo"], 0, $r[0]["id"]); @@ -2416,7 +2417,7 @@ function gs_discover() { $r = q("SELECT `nurl`, `url` FROM `gserver` WHERE `last_contact` >= `last_failure` AND `network` = '%s' AND `last_poco_query` < '%s' ORDER BY RAND() LIMIT 5", dbesc(NETWORK_OSTATUS), dbesc($last_update)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -2436,7 +2437,7 @@ function poco_serverlist() { ORDER BY `last_contact` LIMIT 1000", dbesc(NETWORK_DFRN), dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return false; } diff --git a/include/text.php b/include/text.php index 90d569c62b..9dc3c871fb 100644 --- a/include/text.php +++ b/include/text.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; +use Friendica\Database\DBM; require_once "include/template_processor.php"; require_once "include/friendica_smarty.php"; @@ -525,7 +526,7 @@ function photo_new_resource() { dbesc($resource) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $found = true; } } while ($found == true); @@ -956,7 +957,7 @@ function contact_block() { dbesc(NETWORK_OSTATUS), dbesc(NETWORK_DIASPORA) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $total = intval($r[0]['total']); } if (! $total) { @@ -975,7 +976,7 @@ function contact_block() { dbesc(NETWORK_DIASPORA), intval($shown) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contacts = array(); foreach ($r AS $contact) { $contacts[] = $contact["id"]; @@ -983,7 +984,7 @@ function contact_block() { $r = q("SELECT `id`, `uid`, `addr`, `url`, `name`, `thumb`, `network` FROM `contact` WHERE `id` IN (%s)", dbesc(implode(",", $contacts))); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contacts = sprintf( tt('%d Contact','%d Contacts', $total),$total); $micropro = Array(); foreach ($r as $rr) { @@ -1669,7 +1670,7 @@ function generate_user_guid() { $x = q("SELECT `uid` FROM `user` WHERE `guid` = '%s' LIMIT 1", dbesc($guid) ); - if (! dbm::is_result($x)) { + if (! DBM::is_result($x)) { $found = false; } } while ($found == true); @@ -2023,7 +2024,7 @@ function file_tag_update_pconfig($uid, $file_old, $file_new, $type = 'file') { intval($termtype), intval($uid)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { unset($deleted_tags[$key]); } else { @@ -2053,7 +2054,7 @@ function file_tag_save_file($uid, $item, $file) { intval($item), intval($uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if (! stristr($r[0]['file'],'[' . file_tag_encode($file) . ']')) { q("UPDATE `item` SET `file` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($r[0]['file'] . '[' . file_tag_encode($file) . ']'), @@ -2093,7 +2094,7 @@ function file_tag_unsave_file($uid, $item, $file, $cat = false) { intval($item), intval($uid) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { return false; } @@ -2111,7 +2112,7 @@ function file_tag_unsave_file($uid, $item, $file, $cat = false) { intval($termtype), intval($uid)); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { $saved = PConfig::get($uid,'system','filetags'); PConfig::set($uid, 'system', 'filetags', str_replace($pattern, '', $saved)); } diff --git a/include/threads.php b/include/threads.php index 169a63c7ca..16d4915fdf 100644 --- a/include/threads.php +++ b/include/threads.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; function add_thread($itemid, $onlyshadow = false) { $items = q("SELECT `uid`, `created`, `edited`, `commented`, `received`, `changed`, `wall`, `private`, `pubmail`, @@ -35,7 +36,7 @@ function add_shadow_thread($itemid) { $items = q("SELECT `uid`, `wall`, `private`, `moderated`, `visible`, `contact-id`, `deleted`, `network`, `author-id`, `owner-id` FROM `item` WHERE `id` = %d AND (`parent` = %d OR `parent` = 0) LIMIT 1", intval($itemid), intval($itemid)); - if (!dbm::is_result($items)) { + if (!DBM::is_result($items)) { return; } @@ -67,7 +68,7 @@ function add_shadow_thread($itemid) { $r = q("SELECT `hide-friends` FROM `profile` WHERE `is-default` AND `uid` = %d AND NOT `hide-friends`", $item['uid']); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -75,14 +76,14 @@ function add_shadow_thread($itemid) { $r = q("SELECT `id` FROM `contact` WHERE NOT `hidden` AND NOT `blocked` AND `id` = %d", $item['contact-id']); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } } // Only add a shadow, if the profile isn't hidden $r = q("SELECT `uid` FROM `user` where `uid` = %d AND NOT `hidewall`", $item['uid']); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -94,7 +95,7 @@ function add_shadow_thread($itemid) { $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = 0 LIMIT 1", dbesc($item['uri'])); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { // Preparing public shadow (removing user specific data) require_once("include/items.php"); require_once("include/Contact.php"); @@ -129,7 +130,7 @@ function add_shadow_entry($itemid) { $items = q("SELECT * FROM `item` WHERE `id` = %d", intval($itemid)); - if (!dbm::is_result($items)) { + if (!DBM::is_result($items)) { return; } @@ -147,12 +148,12 @@ function add_shadow_entry($itemid) { // Is there a shadow parent? $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = 0 LIMIT 1", dbesc($item['parent-uri'])); - if (!dbm::is_result($r)) + if (!DBM::is_result($r)) return; // Is there already a shadow entry? $r = q("SELECT `id` FROM `item` WHERE `uri` = '%s' AND `uid` = 0 LIMIT 1", dbesc($item['uri'])); - if (dbm::is_result($r)) + if (DBM::is_result($r)) return; // Preparing public shadow (removing user specific data) @@ -179,7 +180,7 @@ function add_shadow_entry($itemid) { function update_thread_uri($itemuri, $uid) { $messages = q("SELECT `id` FROM `item` WHERE uri ='%s' AND uid=%d", dbesc($itemuri), intval($uid)); - if (dbm::is_result($messages)) { + if (DBM::is_result($messages)) { foreach ($messages as $message) { update_thread($message["id"]); } @@ -190,7 +191,7 @@ function update_thread($itemid, $setmention = false) { $items = q("SELECT `uid`, `guid`, `title`, `body`, `created`, `edited`, `commented`, `received`, `changed`, `wall`, `private`, `pubmail`, `moderated`, `visible`, `spam`, `starred`, `bookmark`, `contact-id`, `gcontact-id`, `deleted`, `origin`, `forum_mode`, `network`, `rendered-html`, `rendered-hash` FROM `item` WHERE `id` = %d AND (`parent` = %d OR `parent` = 0) LIMIT 1", intval($itemid), intval($itemid)); - if (!dbm::is_result($items)) { + if (!DBM::is_result($items)) { return; } @@ -218,7 +219,7 @@ function update_thread($itemid, $setmention = false) { // Updating a shadow item entry $items = q("SELECT `id` FROM `item` WHERE `guid` = '%s' AND `uid` = 0 LIMIT 1", dbesc($item["guid"])); - if (!dbm::is_result($items)) { + if (!DBM::is_result($items)) { return; } @@ -235,7 +236,7 @@ function update_thread($itemid, $setmention = false) { function delete_thread_uri($itemuri, $uid) { $messages = q("SELECT `id` FROM `item` WHERE uri ='%s' AND uid=%d", dbesc($itemuri), intval($uid)); - if (dbm::is_result($messages)) { + if (DBM::is_result($messages)) { foreach ($messages as $message) { delete_thread($message["id"], $itemuri); } @@ -245,7 +246,7 @@ function delete_thread_uri($itemuri, $uid) { function delete_thread($itemid, $itemuri = "") { $item = q("SELECT `uid` FROM `thread` WHERE `iid` = %d", intval($itemid)); - if (!dbm::is_result($item)) { + if (!DBM::is_result($item)) { logger('No thread found for id '.$itemid, LOGGER_DEBUG); return; } @@ -260,7 +261,7 @@ function delete_thread($itemid, $itemuri = "") { dbesc($itemuri), intval($item["uid"]) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { dba::delete('item', array('uri' => $itemuri, 'uid' => 0)); logger("delete_thread: Deleted shadow for item ".$itemuri, LOGGER_DEBUG); } diff --git a/include/uimport.php b/include/uimport.php index fbdbeb58c6..af4f434d4b 100644 --- a/include/uimport.php +++ b/include/uimport.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\PConfig; use Friendica\Core\Worker; +use Friendica\Database\DBM; require_once("include/Photo.php"); define("IMPORT_DEBUG", False); @@ -104,7 +105,7 @@ function import_account(App $a, $file) { notice(t('Error! Cannot check nickname')); return; } - if (dbm::is_result($r) > 0) { + if (DBM::is_result($r) > 0) { notice(sprintf(t("User '%s' already exists on this server!"), $account['user']['nickname'])); return; } @@ -115,7 +116,7 @@ function import_account(App $a, $file) { notice(t('Error! Cannot check nickname')); return; } - if (dbm::is_result($r) > 0) { + if (DBM::is_result($r) > 0) { notice(sprintf(t("User '%s' already exists on this server!"), $account['user']['nickname'])); return; } diff --git a/include/update_gcontact.php b/include/update_gcontact.php index e407466743..cd7a9366fb 100644 --- a/include/update_gcontact.php +++ b/include/update_gcontact.php @@ -2,6 +2,7 @@ use Friendica\Core\Config; use Friendica\Network\Probe; +use Friendica\Database\DBM; function update_gcontact_run(&$argv, &$argc) { global $a; @@ -21,7 +22,7 @@ function update_gcontact_run(&$argv, &$argc) { $r = q("SELECT * FROM `gcontact` WHERE `id` = %d", intval($contact_id)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } diff --git a/include/user.php b/include/user.php index 7eb1058dc0..be03637df9 100644 --- a/include/user.php +++ b/include/user.php @@ -2,6 +2,7 @@ use Friendica\Core\Config; use Friendica\Core\System; +use Friendica\Database\DBM; require_once('include/network.php'); require_once('include/plugin.php'); @@ -125,7 +126,7 @@ function create_user($arr) { $r = q("SELECT * FROM `user` WHERE `email` = '%s' LIMIT 1", dbesc($email) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $result['message'] .= t('Cannot use that email.') . EOL; } @@ -138,7 +139,7 @@ function create_user($arr) { WHERE `nickname` = '%s' LIMIT 1", dbesc($nickname) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL; // Check deleted accounts that had this nickname. Doesn't matter to us, @@ -148,7 +149,7 @@ function create_user($arr) { WHERE `username` = '%s' LIMIT 1", dbesc($nickname) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $result['message'] .= t('Nickname was once registered here and may not be re-used. Please choose another.') . EOL; if(strlen($result['message'])) { @@ -201,7 +202,7 @@ function create_user($arr) { dbesc($username), dbesc($new_password_encoded) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $u = $r[0]; $newuid = intval($r[0]['uid']); } @@ -220,7 +221,7 @@ function create_user($arr) { WHERE `nickname` = '%s' ", dbesc($nickname) ); - if ((dbm::is_result($r)) && (count($r) > 1) && $newuid) { + if ((DBM::is_result($r)) && (count($r) > 1) && $newuid) { $result['message'] .= t('Nickname is already registered. Please choose another.') . EOL; dba::delete('user', array('uid' => $newuid)); return $result; @@ -259,7 +260,7 @@ function create_user($arr) { intval($newuid), dbesc(t('Friends')) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $def_gid = $r[0]['id']; q("UPDATE `user` SET `def_gid` = %d WHERE `uid` = %d", @@ -346,12 +347,12 @@ function user_create_self_contact($uid) { // Only create the entry if it doesn't exist yet $r = q("SELECT `id` FROM `contact` WHERE `uid` = %d AND `self`", intval($uid)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { return; } $r = q("SELECT `uid`, `username`, `nickname` FROM `user` WHERE `uid` = %d", intval($uid)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } diff --git a/index.php b/index.php index 2cd5e7cba5..5915498904 100644 --- a/index.php +++ b/index.php @@ -17,6 +17,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\Worker; +use Friendica\Database\DBM; require_once 'boot.php'; require_once 'object/BaseObject.php'; @@ -117,7 +118,7 @@ if (x($_SESSION,'authenticated') && !x($_SESSION,'language')) { // we didn't loaded user data yet, but we need user language $r = dba::select('user', array('language'), array('uid' => $_SESSION['uid']), array('limit' => 1)); $_SESSION['language'] = $lang; - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $_SESSION['language'] = $r['language']; } } diff --git a/mod/admin.php b/mod/admin.php index 4f156a0c3b..222001ac57 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -10,6 +10,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\Worker; +use Friendica\Database\DBM; require_once("include/enotify.php"); require_once("include/text.php"); @@ -612,7 +613,7 @@ function admin_page_summary(App $a) { dbesc(dba::database_name())); $showwarning = false; $warningtext = array(); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $showwarning = true; $warningtext[] = sprintf(t('Your DB still runs with MyISAM tables. You should change the engine type to InnoDB. As Friendica will use InnoDB only features in the future, you should change this! See here for a guide that may be helpful converting the table engines. You may also use the command php include/dbstructure.php toinnodb of your Friendica installation for an automatic conversion.
'), 'https://dev.mysql.com/doc/refman/5.7/en/converting-tables-to-innodb.html'); } @@ -1337,7 +1338,7 @@ function admin_page_dbsync(App $a) { $failed = array(); $r = q("SELECT `k`, `v` FROM `config` WHERE `cat` = 'database' "); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $upd = intval(substr($rr['k'],7)); if ($upd < 1139 || $rr['v'] === 'success') { diff --git a/mod/allfriends.php b/mod/allfriends.php index 8d849d3755..ce9e68f010 100644 --- a/mod/allfriends.php +++ b/mod/allfriends.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; require_once('include/socgraph.php'); require_once('include/Contact.php'); @@ -31,7 +32,7 @@ function allfriends_content(App $a) { intval(local_user()) ); - if (! dbm::is_result($c)) { + if (! DBM::is_result($c)) { return; } @@ -45,7 +46,7 @@ function allfriends_content(App $a) { $r = all_friends(local_user(), $cid, $a->pager['start'], $a->pager['itemspage']); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { $o .= t('No friends to display.'); return $o; } diff --git a/mod/api.php b/mod/api.php index beb7d71c42..cda97c729c 100644 --- a/mod/api.php +++ b/mod/api.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Database\DBM; require_once('include/api.php'); @@ -17,7 +18,7 @@ function oauth_get_client($request){ AND `tokens`.`id`='%s' AND `tokens`.`scope`='request'", dbesc($token)); - if (!dbm::is_result($r)) + if (!DBM::is_result($r)) return null; return $r[0]; diff --git a/mod/attach.php b/mod/attach.php index 6155a3f99e..6dd9135e51 100644 --- a/mod/attach.php +++ b/mod/attach.php @@ -1,6 +1,7 @@ profile['profile_uid']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact = $r[0]; $remote_contact = true; } @@ -226,7 +227,7 @@ function cal_content(App $a) { $links = array(); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $r = sort_by_date($r); foreach ($r as $rr) { $j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['start'], 'j') : datetime_convert('UTC','UTC',$rr['start'],'j')); @@ -240,7 +241,7 @@ function cal_content(App $a) { $events=array(); // transform the event in a usable array - if (dbm::is_result($r)) + if (DBM::is_result($r)) $r = sort_by_date($r); $events = process_events($r); diff --git a/mod/common.php b/mod/common.php index 87e305e68d..12f1ba2737 100644 --- a/mod/common.php +++ b/mod/common.php @@ -1,6 +1,7 @@ page['aside'] = ""; profile_load($a, "", 0, get_contact_details_by_url($c[0]["url"])); } else { $c = q("SELECT `name`, `url`, `photo` FROM `contact` WHERE `self` = 1 AND `uid` = %d LIMIT 1", intval($uid) ); - /// @TODO Handle $c with dbm::is_result() + /// @TODO Handle $c with DBM::is_result() $vcard_widget .= replace_macros(get_markup_template("vcard-widget.tpl"),array( '$name' => htmlentities($c[0]['name']), @@ -55,7 +56,7 @@ function common_content(App $a) { $a->page['aside'] .= $vcard_widget; } - if (! dbm::is_result($c)) { + if (! DBM::is_result($c)) { return; } @@ -65,13 +66,13 @@ function common_content(App $a) { dbesc(normalise_link(get_my_url())), intval($profile_uid) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $cid = $r[0]['id']; else { $r = q("SELECT `id` FROM `gcontact` WHERE `nurl` = '%s' LIMIT 1", dbesc(normalise_link(get_my_url())) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $zcid = $r[0]['id']; } } @@ -102,7 +103,7 @@ function common_content(App $a) { } - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { return $o; } diff --git a/mod/community.php b/mod/community.php index 83a2fdebf5..d428bddf8c 100644 --- a/mod/community.php +++ b/mod/community.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Database\DBM; function community_init(App $a) { if (! local_user()) { @@ -45,7 +46,7 @@ function community_content(App $a, $update = 0) { $r = community_getitems($a->pager['start'], $a->pager['itemspage']); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { info( t('No results.') . EOL); return $o; } diff --git a/mod/contactgroup.php b/mod/contactgroup.php index 2a44e28896..0c2d6a0cbe 100644 --- a/mod/contactgroup.php +++ b/mod/contactgroup.php @@ -1,6 +1,7 @@ argv[2]), intval(local_user()) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $change = intval($a->argv[2]); } @@ -24,7 +25,7 @@ function contactgroup_content(App $a) { intval($a->argv[1]), intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { killme(); } diff --git a/mod/contacts.php b/mod/contacts.php index 66fbedebef..5c810b179a 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; use Friendica\Network\Probe; require_once 'include/Contact.php'; @@ -24,7 +25,7 @@ function contacts_init(App $a) { intval(local_user()), intval($contact_id) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { $contact_id = 0; } } @@ -183,7 +184,7 @@ function contacts_post(App $a) { intval($profile_id), intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('Could not locate selected profile.') . EOL); return; } @@ -225,7 +226,7 @@ function contacts_post(App $a) { intval($contact_id), intval(local_user()) ); - if($r && dbm::is_result($r)) + if($r && DBM::is_result($r)) $a->data['contact'] = $r[0]; return; @@ -352,7 +353,7 @@ function _contact_drop($contact_id, $orig_record) { WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", intval($a->user['uid']) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return; } @@ -794,7 +795,7 @@ function contacts_content(App $a) { $r = q("SELECT COUNT(*) AS `total` FROM `contact` WHERE `uid` = %d AND `self` = 0 AND `pending` = 0 $sql_extra $sql_extra2 ", intval($_SESSION['uid'])); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $a->set_pager_total($r[0]['total']); $total = $r[0]['total']; } @@ -809,7 +810,7 @@ function contacts_content(App $a) { $contacts = array(); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $contacts[] = _contact_detail_for_template($rr); } diff --git a/mod/crepair.php b/mod/crepair.php index cc930a2f3a..a73429e157 100644 --- a/mod/crepair.php +++ b/mod/crepair.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Database\DBM; require_once("include/contact_selectors.php"); require_once("mod/contacts.php"); @@ -19,7 +20,7 @@ function crepair_init(App $a) { intval(local_user()), intval($contact_id) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { $contact_id = 0; } } @@ -48,7 +49,7 @@ function crepair_post(App $a) { ); } - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { return; } @@ -116,7 +117,7 @@ function crepair_content(App $a) { ); } - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('Contact not found.') . EOL); return; } diff --git a/mod/delegate.php b/mod/delegate.php index 4bccf1142a..684ae19a8a 100644 --- a/mod/delegate.php +++ b/mod/delegate.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; require_once('mod/settings.php'); @@ -29,12 +30,12 @@ function delegate_content(App $a) { $r = q("select `nickname` from user where uid = %d limit 1", intval($id) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $r = q("select id from contact where uid = %d and nurl = '%s' limit 1", intval(local_user()), dbesc(normalise_link(System::baseUrl() . '/profile/' . $r[0]['nickname'])) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { dba::insert('manage', array('uid' => $a->argv[2], 'mid' => local_user())); } } @@ -64,7 +65,7 @@ function delegate_content(App $a) { dbesc($a->user['email']), dbesc($a->user['password']) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $full_managers = $r; $delegates = array(); @@ -75,7 +76,7 @@ function delegate_content(App $a) { intval(local_user()) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $delegates = $r; $uids = array(); @@ -97,14 +98,14 @@ function delegate_content(App $a) { dbesc(NETWORK_DFRN) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('No potential page delegates located.') . EOL); return; } $nicknames = array(); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $nicknames[] = "'" . dbesc(basename($rr['nurl'])) . "'"; } @@ -118,7 +119,7 @@ function delegate_content(App $a) { $r = q("select `uid`, `username`, `nickname` from user where nickname in ( $nicks )"); - if (dbm::is_result($r)) + if (DBM::is_result($r)) foreach($r as $rr) if(! in_array($rr['uid'],$uids)) $potentials[] = $rr; diff --git a/mod/dfrn_confirm.php b/mod/dfrn_confirm.php index f0d5d76305..98bdfbe150 100644 --- a/mod/dfrn_confirm.php +++ b/mod/dfrn_confirm.php @@ -23,6 +23,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; use Friendica\Network\Probe; use Friendica\Protocol\Diaspora; @@ -128,7 +129,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { intval($uid) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { logger('Contact not found in DB.'); notice( t('Contact not found.') . EOL ); notice( t('This may occasionally happen if contact was requested by both persons and it has already been approved.') . EOL ); @@ -419,7 +420,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { ); } - /// @TODO is dbm::is_result() working here? + /// @TODO is DBM::is_result() working here? if ($r === false) { notice( t('Unable to set contact photo.') . EOL); } @@ -429,7 +430,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { $r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($contact_id) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact = $r[0]; } else { $contact = null; @@ -449,7 +450,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { intval($uid) ); - if((dbm::is_result($r)) && ($r[0]['hide-friends'] == 0) && ($activity) && (! $hidden)) { + if((DBM::is_result($r)) && ($r[0]['hide-friends'] == 0) && ($activity) && (! $hidden)) { require_once 'include/items.php'; @@ -560,7 +561,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { $r = q("SELECT * FROM `user` WHERE `nickname` = '%s' LIMIT 1", dbesc($node)); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { $message = sprintf(t('No user record found for \'%s\' '), $node); xml_status(3,$message); // failure // NOTREACHED @@ -591,7 +592,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { dbesc($decrypted_source_url), intval($local_uid) ); - if (!dbm::is_result($ret)) { + if (!DBM::is_result($ret)) { if (strstr($decrypted_source_url,'http:')) { $newurl = str_replace('http:','https:',$decrypted_source_url); } else { @@ -602,7 +603,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { dbesc($newurl), intval($local_uid) ); - if (!dbm::is_result($ret)) { + if (!DBM::is_result($ret)) { // this is either a bogus confirmation (?) or we deleted the original introduction. $message = t('Contact record was not found for you on our site.'); xml_status(3,$message); @@ -637,7 +638,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { $r = q("SELECT * FROM `contact` WHERE `dfrn-id` = '%s' LIMIT 1", dbesc($decrypted_dfrn_id) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $message = t('The ID provided by your system is a duplicate on our system. It should work if you try again.'); xml_status(1,$message); // Birthday paradox - duplicate dfrn-id // NOTREACHED @@ -648,7 +649,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { dbesc($dfrn_pubkey), intval($dfrn_record) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { $message = t('Unable to set your contact credentials on our system.'); xml_status(3,$message); } @@ -669,7 +670,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { $r = q("SELECT `photo` FROM `contact` WHERE `id` = %d LIMIT 1", intval($dfrn_record)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $photo = $r[0]['photo']; } else { $photo = System::baseUrl() . '/images/person-175.jpg'; @@ -725,10 +726,10 @@ function dfrn_confirm_post(App $a, $handsfree = null) { intval($dfrn_record) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $combined = $r[0]; - if((dbm::is_result($r)) && ($r[0]['notify-flags'] & NOTIFY_CONFIRM)) { + if((DBM::is_result($r)) && ($r[0]['notify-flags'] & NOTIFY_CONFIRM)) { $mutual = ($new_relation == CONTACT_IS_FRIEND); notification(array( 'type' => NOTIFY_CONFIRM, @@ -753,7 +754,7 @@ function dfrn_confirm_post(App $a, $handsfree = null) { intval($local_uid) ); - if((dbm::is_result($r)) && ($r[0]['hide-friends'] == 0)) { + if((DBM::is_result($r)) && ($r[0]['hide-friends'] == 0)) { require_once 'include/items.php'; diff --git a/mod/dfrn_notify.php b/mod/dfrn_notify.php index 65e9535c6a..e0e30a2488 100644 --- a/mod/dfrn_notify.php +++ b/mod/dfrn_notify.php @@ -8,7 +8,8 @@ use Friendica\App; use Friendica\Core\Config; -use Friendica\Protocol\Dfrn; +use Friendica\Database\DBM; +use Friendica\Protocol\DFRN; require_once('include/items.php'); require_once('include/event.php'); @@ -46,7 +47,7 @@ function dfrn_notify_post(App $a) { dbesc($dfrn_id), dbesc($challenge) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { logger('dfrn_notify: could not match challenge to dfrn_id ' . $dfrn_id . ' challenge=' . $challenge); xml_status(3, 'Could not match challenge'); } @@ -94,7 +95,7 @@ function dfrn_notify_post(App $a) { dbesc($a->argv[1]) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { logger('dfrn_notify: contact not found for dfrn_id ' . $dfrn_id); xml_status(3, 'Contact not found'); //NOTREACHED @@ -180,7 +181,7 @@ function dfrn_notify_post(App $a) { *we got a key. old code send only the key, without RINO version. * we assume RINO 1 if key and no RINO version */ - $data = Dfrn::aes_decrypt(hex2bin($data), $final_key); + $data = DFRN::aes_decrypt(hex2bin($data), $final_key); break; case 2: try { @@ -212,7 +213,7 @@ function dfrn_notify_post(App $a) { logger('rino: decrypted data: ' . $data, LOGGER_DATA); } - $ret = Dfrn::import($data, $importer); + $ret = DFRN::import($data, $importer); xml_status($ret, 'Processed'); // NOTREACHED @@ -284,7 +285,7 @@ function dfrn_notify_content(App $a) { dbesc($a->argv[1]) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { $status = 1; } diff --git a/mod/dfrn_poll.php b/mod/dfrn_poll.php index 6f3d843810..0e967301eb 100644 --- a/mod/dfrn_poll.php +++ b/mod/dfrn_poll.php @@ -3,7 +3,8 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; -use Friendica\Protocol\Dfrn; +use Friendica\Database\DBM; +use Friendica\Protocol\DFRN; require_once('include/items.php'); require_once('include/auth.php'); @@ -58,7 +59,7 @@ function dfrn_poll_init(App $a) { logger('dfrn_poll: public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $user); header("Content-type: application/atom+xml"); - echo Dfrn::feed('', $user,$last_update, 0, $hidewall); + echo DFRN::feed('', $user,$last_update, 0, $hidewall); killme(); } @@ -90,7 +91,7 @@ function dfrn_poll_init(App $a) { dbesc($a->argv[1]) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $s = fetch_url($r[0]['poll'] . '?dfrn_id=' . $my_id . '&type=profile-check'); @@ -137,7 +138,7 @@ function dfrn_poll_init(App $a) { $r = q("SELECT * FROM `profile_check` WHERE `sec` = '%s' ORDER BY `expire` DESC LIMIT 1", dbesc($sec) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { xml_status(3, 'No ticket'); // NOTREACHED } @@ -148,7 +149,7 @@ function dfrn_poll_init(App $a) { $c = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($r[0]['cid']) ); - if (! dbm::is_result($c)) { + if (! DBM::is_result($c)) { xml_status(3, 'No profile'); } $contact = $c[0]; @@ -201,7 +202,7 @@ function dfrn_poll_init(App $a) { q("DELETE FROM `profile_check` WHERE `expire` < " . intval(time())); $r = q("SELECT * FROM `profile_check` WHERE `dfrn_id` = '%s' ORDER BY `expire` DESC", dbesc($dfrn_id)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { xml_status(1); return; // NOTREACHED } @@ -234,7 +235,7 @@ function dfrn_poll_post(App $a) { $r = q("SELECT * FROM `profile_check` WHERE `sec` = '%s' ORDER BY `expire` DESC LIMIT 1", dbesc($sec) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { xml_status(3, 'No ticket'); // NOTREACHED } @@ -245,7 +246,7 @@ function dfrn_poll_post(App $a) { $c = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($r[0]['cid']) ); - if (! dbm::is_result($c)) { + if (! DBM::is_result($c)) { xml_status(3, 'No profile'); } $contact = $c[0]; @@ -295,7 +296,7 @@ function dfrn_poll_post(App $a) { dbesc($challenge) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { killme(); } @@ -331,7 +332,7 @@ function dfrn_poll_post(App $a) { $r = q("SELECT * FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 $sql_extra LIMIT 1"); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { killme(); } @@ -348,7 +349,7 @@ function dfrn_poll_post(App $a) { $reputation = 0; $text = ''; - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $reputation = $r[0]['rating']; $text = $r[0]['reason']; @@ -387,7 +388,7 @@ function dfrn_poll_post(App $a) { } header("Content-type: application/atom+xml"); - $o = Dfrn::feed($dfrn_id, $a->argv[1], $last_update, $direction); + $o = DFRN::feed($dfrn_id, $a->argv[1], $last_update, $direction); echo $o; killme(); @@ -461,7 +462,7 @@ function dfrn_poll_content(App $a) { dbesc($nickname) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $challenge = ''; $encrypted_id = ''; @@ -508,7 +509,7 @@ function dfrn_poll_content(App $a) { )); } - $profile = ((dbm::is_result($r) && $r[0]['nickname']) ? $r[0]['nickname'] : $nickname); + $profile = ((DBM::is_result($r) && $r[0]['nickname']) ? $r[0]['nickname'] : $nickname); switch($destination_url) { case 'profile': diff --git a/mod/dfrn_request.php b/mod/dfrn_request.php index de48207a64..39b212fbdd 100644 --- a/mod/dfrn_request.php +++ b/mod/dfrn_request.php @@ -16,6 +16,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; +use Friendica\Database\DBM; use Friendica\Network\Probe; require_once 'include/enotify.php'; @@ -95,7 +96,7 @@ function dfrn_request_post(App $a) { dbesc(normalise_link($dfrn_url)) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if(strlen($r[0]['dfrn-id'])) { /* @@ -149,7 +150,7 @@ function dfrn_request_post(App $a) { $photo = $parms["photo"]; // Escape the entire array - dbm::esc_array($parms); + DBM::esc_array($parms); /* * Create a contact record on our site for the other person @@ -189,7 +190,7 @@ function dfrn_request_post(App $a) { dbesc($dfrn_url), $parms['key'] // this was already escaped ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $def_gid = get_default_group(local_user(), $r[0]["network"]); if(intval($def_gid)) group_add_member(local_user(), '', $r[0]['id'], $def_gid); @@ -280,7 +281,7 @@ function dfrn_request_post(App $a) { dbesc(datetime_convert('UTC','UTC','now - 24 hours')), intval($uid) ); - if (dbm::is_result($r) && count($r) > $maxreq) { + if (DBM::is_result($r) && count($r) > $maxreq) { notice( sprintf( t('%s has received too many connection requests today.'), $a->profile['name']) . EOL); notice( t('Spam protection measures have been invoked.') . EOL); notice( t('Friends are advised to please try again in 24 hours.') . EOL); @@ -302,7 +303,7 @@ function dfrn_request_post(App $a) { AND `intro`.`datetime` < UTC_TIMESTAMP() - INTERVAL 30 MINUTE ", dbesc(NETWORK_MAIL2) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { if(! $rr['rel']) { q("DELETE FROM `contact` WHERE `id` = %d AND NOT `self`", @@ -327,7 +328,7 @@ function dfrn_request_post(App $a) { AND `intro`.`datetime` < UTC_TIMESTAMP() - INTERVAL 3 DAY ", dbesc(NETWORK_MAIL2) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { if(! $rr['rel']) { q("DELETE FROM `contact` WHERE `id` = %d AND NOT `self`", @@ -378,7 +379,7 @@ function dfrn_request_post(App $a) { intval($uid) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('This account has not been configured for email. Request failed.') . EOL); return; } @@ -405,7 +406,7 @@ function dfrn_request_post(App $a) { dbesc($poll), intval($uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact_id = $r[0]['id']; $def_gid = get_default_group($uid, $r[0]["network"]); @@ -480,7 +481,7 @@ function dfrn_request_post(App $a) { dbesc($url) ); - if (dbm::is_result($ret)) { + if (DBM::is_result($ret)) { if(strlen($ret[0]['issued-id'])) { notice( t('You have already introduced yourself here.') . EOL ); return; @@ -552,7 +553,7 @@ function dfrn_request_post(App $a) { $parms['issued-id'] = $issued_id; $photo = $parms["photo"]; - dbm::esc_array($parms); + DBM::esc_array($parms); $r = q("INSERT INTO `contact` ( `uid`, `created`, `url`, `nurl`, `addr`, `name`, `nick`, `issued-id`, `photo`, `site-pubkey`, `request`, `confirm`, `notify`, `poll`, `poco`, `network`, `blocked`, `pending` ) VALUES ( %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d )", @@ -584,7 +585,7 @@ function dfrn_request_post(App $a) { $parms['url'], $parms['issued-id'] ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact_record = $r[0]; update_contact_avatar($photo, $uid, $contact_record["id"], true); } @@ -735,7 +736,7 @@ function dfrn_request_content(App $a) { dbesc($_GET['confirm_key']) ); - if (dbm::is_result($intro)) { + if (DBM::is_result($intro)) { $r = q("SELECT `contact`.*, `user`.* FROM `contact` LEFT JOIN `user` ON `contact`.`uid` = `user`.`uid` WHERE `contact`.`id` = %d LIMIT 1", @@ -744,7 +745,7 @@ function dfrn_request_content(App $a) { $auto_confirm = false; - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if(($r[0]['page-flags'] != PAGE_NORMAL) && ($r[0]['page-flags'] != PAGE_PRVGROUP)) $auto_confirm = true; @@ -861,7 +862,7 @@ function dfrn_request_content(App $a) { $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1", intval($a->profile['uid']) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { $mail_disabled = 1; } } diff --git a/mod/directory.php b/mod/directory.php index 98afad77cf..b32a58b359 100644 --- a/mod/directory.php +++ b/mod/directory.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Database\DBM; function directory_init(App $a) { $a->set_pager_itemspage(60); @@ -73,7 +74,7 @@ function directory_content(App $a) { $r = q("SELECT COUNT(*) AS `total` FROM `profile` LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid` WHERE `is-default` = 1 $publish AND `user`.`blocked` = 0 $sql_extra "); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $a->set_pager_total($r[0]['total']); $order = " ORDER BY `name` ASC "; @@ -85,7 +86,7 @@ function directory_content(App $a) { LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid` LEFT JOIN `contact` ON `contact`.`uid` = `user`.`uid` WHERE `is-default` $publish AND `user`.`blocked` = 0 AND `contact`.`self` $sql_extra $order LIMIT ".$limit); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if (in_array('small', $a->argv)) { $photo = 'thumb'; diff --git a/mod/dirfind.php b/mod/dirfind.php index da2f1396ef..5d65813e3c 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -105,7 +105,7 @@ function dirfind_content(App $a, $prefix = "") { $search2 = "%".$search."%"; - /// @TODO These 2 SELECTs are not checked on validity with dbm::is_result() + /// @TODO These 2 SELECTs are not checked on validity with DBM::is_result() $count = q("SELECT count(*) AS `total` FROM `gcontact` LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl` AND `contact`.`network` = `gcontact`.`network` diff --git a/mod/display.php b/mod/display.php index 62cb0445fe..570582343a 100644 --- a/mod/display.php +++ b/mod/display.php @@ -3,7 +3,8 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; -use Friendica\Protocol\Dfrn; +use Friendica\Database\DBM; +use Friendica\Protocol\DFRN; function display_init(App $a) { @@ -40,14 +41,14 @@ function display_init(App $a) { `author-avatar`, `network`, `body`, `uid`, `owner-link` FROM `item` WHERE `visible` AND NOT `deleted` AND NOT `moderated` AND `guid` = ? AND `uid` = ? LIMIT 1", $a->argv[1], local_user()); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $nick = $a->user["nickname"]; $itemuid = local_user(); } } // Is it an item with uid=0? - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = dba::fetch_first("SELECT `id`, `parent`, `author-name`, `author-link`, `author-avatar`, `network`, `body`, `uid`, `owner-link` FROM `item` WHERE `visible` AND NOT `deleted` AND NOT `moderated` @@ -58,7 +59,7 @@ function display_init(App $a) { } // Or is it anywhere on the server? - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = dba::fetch_first("SELECT `item`.`id`, `item`.`parent`, `item`.`author-name`, `item`.`author-link`, `item`.`author-avatar`, `item`.`network`, `item`.`body`, `item`.`uid`, `item`.`owner-link` FROM `item` STRAIGHT_JOIN `user` ON `user`.`uid` = `item`.`uid` @@ -69,7 +70,7 @@ function display_init(App $a) { AND `item`.`guid` = ? LIMIT 1", $a->argv[1]); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if (strstr($_SERVER['HTTP_ACCEPT'], 'application/atom+xml')) { logger('Directly serving XML for id '.$r["id"], LOGGER_DEBUG); @@ -93,7 +94,7 @@ function display_init(App $a) { WHERE `user`.`nickname` = ? AND `profile`.`is-default` AND `contact`.`self` LIMIT 1", $nickname ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $profiledata = $r; } $profiledata["network"] = NETWORK_DFRN; @@ -229,7 +230,7 @@ function display_content(App $a, $update = 0) { $r = dba::fetch_first("SELECT `id`, `parent` FROM `item` WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated` AND `guid` = ? AND `uid` = ?", $a->argv[1], local_user()); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $item_id = $r["id"]; $item_parent = $r["parent"]; $nick = $a->user["nickname"]; @@ -243,7 +244,7 @@ function display_content(App $a, $update = 0) { AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' AND NOT `item`.`private` AND NOT `user`.`hidewall` AND `item`.`guid` = ?", $a->argv[1]); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $item_id = $r["id"]; $item_parent = $r["parent"]; $nick = $r["nickname"]; @@ -256,7 +257,7 @@ function display_content(App $a, $update = 0) { AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' AND NOT `item`.`private` AND `item`.`uid` = 0 AND `item`.`guid` = ?", $a->argv[1]); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $item_id = $r["id"]; $item_parent = $r["parent"]; } @@ -266,7 +267,7 @@ function display_content(App $a, $update = 0) { if ($item_id && !is_numeric($item_id)) { $r = dba::select('item', array('id', 'parent'), array('uri' => $item_id, 'uid' => $a->profile['uid']), array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $item_id = $r["id"]; $item_parent = $r["parent"]; } else { @@ -316,7 +317,7 @@ function display_content(App $a, $update = 0) { $contact_id, $a->profile['uid'] ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact = $r; $remote_contact = true; } @@ -330,7 +331,7 @@ function display_content(App $a, $update = 0) { } $r = dba::fetch_first("SELECT * FROM `contact` WHERE `uid` = ? AND `self` LIMIT 1", $a->profile['uid']); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $a->page_contact = $r; } $is_owner = ((local_user()) && (local_user() == $a->profile['profile_uid']) ? true : false); @@ -379,7 +380,7 @@ function display_content(App $a, $update = 0) { $item_id ); - if (!dbm::is_result($r) && local_user()) { + if (!DBM::is_result($r) && local_user()) { // Check if this is another person's link to a post that we have $r = dba::fetch_first("SELECT `item`.uri FROM `item` WHERE (`item`.`id` = ? OR `item`.`uri` = ?) @@ -387,7 +388,7 @@ function display_content(App $a, $update = 0) { $item_id, $item_id ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $item_uri = $r['uri']; $r = dba::p(item_query()." AND `item`.`uid` = ? @@ -400,12 +401,12 @@ function display_content(App $a, $update = 0) { } } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $s = dba::inArray($r); if ((local_user()) && (local_user() == $a->profile['uid'])) { $unseen = dba::select('item', array('id'), array('parent' => $s[0]['parent'], 'unseen' => true), array('limit' => 1)); - if (dbm::is_result($unseen)) { + if (DBM::is_result($unseen)) { dba::update('item', array('unseen' => false), array('parent' => $s[0]['parent'], 'unseen' => true)); } } @@ -477,7 +478,7 @@ function display_content(App $a, $update = 0) { $item_id, $item_id ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if ($r['deleted']) { notice(t('Item has been removed.') . EOL); } else { @@ -491,7 +492,7 @@ function display_content(App $a, $update = 0) { } function displayShowFeed($item_id, $conversation) { - $xml = Dfrn::itemFeed($item_id, $conversation); + $xml = DFRN::itemFeed($item_id, $conversation); if ($xml == '') { http_status_exit(500); } diff --git a/mod/editpost.php b/mod/editpost.php index cdeb7966e3..57c9339047 100644 --- a/mod/editpost.php +++ b/mod/editpost.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; +use Friendica\Database\DBM; require_once('include/acl_selectors.php'); @@ -27,7 +28,7 @@ function editpost_content(App $a) { intval(local_user()) ); - if (! dbm::is_result($itm)) { + if (! DBM::is_result($itm)) { notice( t('Item not found') . EOL); return; } @@ -72,7 +73,7 @@ function editpost_content(App $a) { $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $mail_enabled = true; if(intval($r[0]['pubmail'])) $pubmail_enabled = true; diff --git a/mod/events.php b/mod/events.php index 056a584e56..b72c8f1884 100644 --- a/mod/events.php +++ b/mod/events.php @@ -8,6 +8,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; require_once 'include/bbcode.php'; require_once 'include/datetime.php'; @@ -339,7 +340,7 @@ function events_content(App $a) { $links = array(); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $r = sort_by_date($r); foreach ($r as $rr) { $j = (($rr['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $rr['start'], 'j') : datetime_convert('UTC', 'UTC', $rr['start'], 'j')); @@ -352,7 +353,7 @@ function events_content(App $a) { $events = array(); // transform the event in a usable array - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $r = sort_by_date($r); $events = process_events($r); } @@ -410,7 +411,7 @@ function events_content(App $a) { intval($event_id), intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $orig_event = $r[0]; } } @@ -545,7 +546,7 @@ function events_content(App $a) { $ev = event_by_id(local_user(), $params); // Delete only real events (no birthdays) - if (dbm::is_result($ev) && $ev[0]['type'] == 'event') { + if (DBM::is_result($ev) && $ev[0]['type'] == 'event') { $del = drop_item($ev[0]['itemid'], false); } diff --git a/mod/friendica.php b/mod/friendica.php index a617c101dc..36fb18c0ac 100644 --- a/mod/friendica.php +++ b/mod/friendica.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; +use Friendica\Database\DBM; function friendica_init(App $a) { if ($a->argv[1] == "json"){ @@ -27,7 +28,7 @@ function friendica_init(App $a) { $visible_plugins = array(); if (is_array($a->plugins) && count($a->plugins)) { $r = q("SELECT * FROM `addon` WHERE `hidden` = 0"); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach($r as $rr) { $visible_plugins[] = $rr['name']; } @@ -85,7 +86,7 @@ function friendica_content(App $a) { $visible_plugins = array(); if (is_array($a->plugins) && count($a->plugins)) { $r = q("SELECT * FROM `addon` WHERE `hidden` = 0"); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach($r as $rr) { $visible_plugins[] = $rr['name']; } diff --git a/mod/fsuggest.php b/mod/fsuggest.php index efaf100efc..124abd464b 100644 --- a/mod/fsuggest.php +++ b/mod/fsuggest.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\Worker; +use Friendica\Database\DBM; function fsuggest_post(App $a) { @@ -19,7 +20,7 @@ function fsuggest_post(App $a) { intval($contact_id), intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('Contact not found.') . EOL); return; } @@ -36,7 +37,7 @@ function fsuggest_post(App $a) { intval($new_contact), intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $x = q("INSERT INTO `fsuggest` ( `uid`,`cid`,`name`,`url`,`request`,`photo`,`note`,`created`) VALUES ( %d, %d, '%s','%s','%s','%s','%s','%s')", @@ -53,7 +54,7 @@ function fsuggest_post(App $a) { dbesc($hash), intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $fsuggest_id = $r[0]['id']; q("UPDATE `fsuggest` SET `note` = '%s' WHERE `id` = %d AND `uid` = %d", dbesc($note), @@ -91,7 +92,7 @@ function fsuggest_content(App $a) { intval($contact_id), intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('Contact not found.') . EOL); return; } diff --git a/mod/group.php b/mod/group.php index 1646043a9f..fcde392d7c 100644 --- a/mod/group.php +++ b/mod/group.php @@ -9,6 +9,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; +use Friendica\Database\DBM; function group_init(App $a) { if (local_user()) { @@ -49,7 +50,7 @@ function group_post(App $a) { intval($a->argv[1]), intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice(t('Group not found.') . EOL); goaway(System::baseUrl() . '/contacts'); return; // NOTREACHED @@ -119,7 +120,7 @@ function group_content(App $a) { $result = null; - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $result = group_rmv(local_user(), $r[0]['name']); } @@ -140,7 +141,7 @@ function group_content(App $a) { intval($a->argv[2]), intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $change = intval($a->argv[2]); } } @@ -154,7 +155,7 @@ function group_content(App $a) { intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice(t('Group not found.') . EOL); goaway(System::baseUrl() . '/contacts'); } @@ -243,7 +244,7 @@ function group_content(App $a) { intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { // Format the data of the contacts who aren't in the contact group foreach ($r as $member) { if (! in_array($member['id'], $preselected)) { diff --git a/mod/ignored.php b/mod/ignored.php index 5c304c2950..9931a556a6 100644 --- a/mod/ignored.php +++ b/mod/ignored.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; function ignored_init(App $a) { @@ -21,7 +22,7 @@ function ignored_init(App $a) { intval(local_user()), intval($message_id) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { killme(); } diff --git a/mod/install.php b/mod/install.php index ed75e624b5..2d0362c952 100755 --- a/mod/install.php +++ b/mod/install.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; require_once "include/Photo.php"; @@ -133,7 +134,7 @@ function install_content(App $a) { if (dba::$connected) { $r = q("SELECT COUNT(*) as `total` FROM `user`"); - if (dbm::is_result($r) && $r[0]['total']) { + if (DBM::is_result($r) && $r[0]['total']) { $tpl = get_markup_template('install.tpl'); return replace_macros($tpl, array( '$title' => $install_title, diff --git a/mod/item.php b/mod/item.php index 61259df74a..587bd90ced 100644 --- a/mod/item.php +++ b/mod/item.php @@ -19,6 +19,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; use Friendica\Network\Probe; use Friendica\Protocol\Diaspora; @@ -107,7 +108,7 @@ function item_post(App $a) { } // if this isn't the real parent of the conversation, find it - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $parid = $r[0]['parent']; $parent_uri = $r[0]['uri']; if ($r[0]['id'] != $r[0]['parent']) { @@ -117,7 +118,7 @@ function item_post(App $a) { } } - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('Unable to locate original post.') . EOL); if (x($_REQUEST, 'return')) { goaway($return_path); @@ -136,13 +137,13 @@ function item_post(App $a) { intval($parent_item['contact-id']), intval($uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $parent_contact = $r[0]; } // If the contact id doesn't fit with the contact, then set the contact to null $thrparent = q("SELECT `author-link`, `network` FROM `item` WHERE `uri` = '%s' LIMIT 1", dbesc($thr_parent)); - if (dbm::is_result($thrparent) && ($thrparent[0]["network"] === NETWORK_OSTATUS) + if (DBM::is_result($thrparent) && ($thrparent[0]["network"] === NETWORK_OSTATUS) && (normalise_link($parent_contact["url"]) != normalise_link($thrparent[0]["author-link"]))) { $parent_contact = get_contact_details_by_url($thrparent[0]["author-link"]); @@ -184,7 +185,7 @@ function item_post(App $a) { intval($profile_uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { logger("Message with URI ".$message_id." already exists for user ".$profile_uid, LOGGER_DEBUG); return; } @@ -226,7 +227,7 @@ function item_post(App $a) { intval($profile_uid), intval($post_id) ); - if (! dbm::is_result($i)) { + if (! DBM::is_result($i)) { killme(); } $orig_post = $i[0]; @@ -237,7 +238,7 @@ function item_post(App $a) { $r = q("SELECT * FROM `user` WHERE `uid` = %d LIMIT 1", intval($profile_uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $user = $r[0]; } @@ -335,7 +336,7 @@ function item_post(App $a) { $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval(local_user()) ); - if (dbm::is_result($r) && intval($r[0]['pubmail'])) { + if (DBM::is_result($r) && intval($r[0]['pubmail'])) { $pubmail_enabled = true; } } @@ -392,7 +393,7 @@ function item_post(App $a) { } } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $author = $r[0]; $contact_id = $author['id']; } @@ -405,7 +406,7 @@ function item_post(App $a) { $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `self` = 1 LIMIT 1", intval($profile_uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact_record = $r[0]; } } @@ -456,7 +457,7 @@ function item_post(App $a) { intval($profile_uid) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { continue; } @@ -488,7 +489,7 @@ function item_post(App $a) { intval($profile_uid), intval($attach) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $r = q("UPDATE `attach` SET `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s' WHERE `uid` = %d AND `id` = %d", dbesc($str_contact_allow), @@ -558,7 +559,7 @@ function item_post(App $a) { $toplevel_parent = q("SELECT `contact`.* FROM `contact` INNER JOIN `item` ON `item`.`contact-id` = `contact`.`id` AND `contact`.`url` = `item`.`author-link` WHERE `item`.`id` = `item`.`parent` AND `item`.`parent` = %d", intval($parent)); - if (dbm::is_result($toplevel_parent)) { + if (DBM::is_result($toplevel_parent)) { if (!empty($toplevel_parent[0]['addr'])) { $toplevel_contact = '@' . $toplevel_parent[0]['addr']; } else { @@ -651,7 +652,7 @@ function item_post(App $a) { intval($profile_uid), intval($mtch) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if (strlen($attachments)) { $attachments .= ','; } @@ -760,7 +761,7 @@ function item_post(App $a) { $datarray['protocol'] = PROTOCOL_DFRN; $r = dba::fetch_first("SELECT `conversation-uri`, `conversation-href` FROM `conversation` WHERE `item-uri` = ?", $datarray['parent-uri']); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if ($r['conversation-uri'] != '') { $datarray['conversation-uri'] = $r['conversation-uri']; } @@ -919,7 +920,7 @@ function item_post(App $a) { intval($datarray['visible']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $post_id = dba::lastInsertId(); } else { logger('mod_item: unable to create post.'); @@ -1157,11 +1158,11 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n $r = q("SELECT `alias`, `name` FROM `contact` WHERE `nurl` = '%s' AND `alias` != '' AND `uid` = 0", normalise_link($matches[1])); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = q("SELECT `alias`, `name` FROM `gcontact` WHERE `nurl` = '%s' AND `alias` != ''", normalise_link($matches[1])); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $data = $r[0]; } else { $data = Probe::uri($matches[1]); @@ -1204,7 +1205,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n ); // Then check in the contact table for the url - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network`, `notify`, `forum`, `prv` FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d AND (`network` != '%s' OR (`notify` != '' AND `alias` != '')) @@ -1216,7 +1217,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n } // Then check in the global contacts for the address - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = q("SELECT `url`, `nick`, `name`, `alias`, `network`, `notify` FROM `gcontact` WHERE `addr` = '%s' AND (`network` != '%s' OR (`notify` != '' AND `alias` != '')) LIMIT 1", @@ -1226,7 +1227,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n } // Then check in the global contacts for the url - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = q("SELECT `url`, `nick`, `name`, `alias`, `network`, `notify` FROM `gcontact` WHERE `nurl` = '%s' AND (`network` != '%s' OR (`notify` != '' AND `alias` != '')) LIMIT 1", @@ -1235,7 +1236,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n ); } - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $probed = Probe::uri($name); if ($result['network'] != NETWORK_PHANTOM) { update_gcontact($probed); @@ -1256,7 +1257,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n } // select someone by attag or nick and the name passed in the current network - if(!dbm::is_result($r) && ($network != "")) + if(!DBM::is_result($r) && ($network != "")) $r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network` FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `network` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1", dbesc($name), dbesc($name), @@ -1265,7 +1266,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n ); //select someone from this user's contacts by name in the current network - if (!dbm::is_result($r) && ($network != "")) { + if (!DBM::is_result($r) && ($network != "")) { $r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network` FROM `contact` WHERE `name` = '%s' AND `network` = '%s' AND `uid` = %d LIMIT 1", dbesc($name), dbesc($network), @@ -1274,7 +1275,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n } // select someone by attag or nick and the name passed in - if(!dbm::is_result($r)) { + if(!DBM::is_result($r)) { $r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network` FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1", dbesc($name), dbesc($name), @@ -1283,7 +1284,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n } // select someone from this user's contacts by name - if(!dbm::is_result($r)) { + if(!DBM::is_result($r)) { $r = q("SELECT `id`, `url`, `nick`, `name`, `alias`, `network` FROM `contact` WHERE `name` = '%s' AND `uid` = %d LIMIT 1", dbesc($name), intval($profile_uid) @@ -1291,7 +1292,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n } } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { if (strlen($inform) && (isset($r[0]["notify"]) || isset($r[0]["id"]))) { $inform .= ','; } diff --git a/mod/lockview.php b/mod/lockview.php index 48227cc1ea..a8cccd955c 100644 --- a/mod/lockview.php +++ b/mod/lockview.php @@ -1,6 +1,7 @@ ' . $rr['name'] . ''; } @@ -62,7 +63,7 @@ function lockview_content(App $a) { $r = q("SELECT `name` FROM `contact` WHERE `id` IN ( %s )", dbesc(implode(', ',$allowed_users)) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) foreach($r as $rr) $l[] = $rr['name']; @@ -72,7 +73,7 @@ function lockview_content(App $a) { $r = q("SELECT `name` FROM `group` WHERE `id` IN ( %s )", dbesc(implode(', ', $deny_groups)) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) foreach($r as $rr) $l[] = '' . $rr['name'] . ''; } @@ -80,7 +81,7 @@ function lockview_content(App $a) { $r = q("SELECT `name` FROM `contact` WHERE `id` IN ( %s )", dbesc(implode(', ',$deny_users)) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) foreach($r as $rr) $l[] = '' . $rr['name'] . ''; diff --git a/mod/lostpass.php b/mod/lostpass.php index e7e1a33bd0..1a30effd4e 100644 --- a/mod/lostpass.php +++ b/mod/lostpass.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; require_once('include/email.php'); require_once('include/enotify.php'); @@ -18,7 +19,7 @@ function lostpass_post(App $a) { dbesc($loginame) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('No valid account found.') . EOL); goaway(System::baseUrl()); } @@ -90,7 +91,7 @@ function lostpass_content(App $a) { $r = q("SELECT * FROM `user` WHERE `pwdreset` = '%s' LIMIT 1", dbesc($hash) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { $o = t("Request could not be verified. \x28You may have previously submitted it.\x29 Password reset failed."); return $o; } @@ -106,7 +107,7 @@ function lostpass_content(App $a) { intval($uid) ); - /// @TODO Is dbm::is_result() okay here? + /// @TODO Is DBM::is_result() okay here? if ($r) { $tpl = get_markup_template('pwdreset.tpl'); $o .= replace_macros($tpl,array( diff --git a/mod/manage.php b/mod/manage.php index 04ead0bb72..72de332fc7 100644 --- a/mod/manage.php +++ b/mod/manage.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; require_once("include/text.php"); @@ -18,7 +19,7 @@ function manage_post(App $a) { $r = q("select * from user where uid = %d limit 1", intval($_SESSION['submanage']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $uid = intval($r[0]['uid']); $orig_record = $r[0]; } @@ -38,7 +39,7 @@ function manage_post(App $a) { $limited_id = 0; $original_id = $uid; - if (dbm::is_result($submanage)) { + if (DBM::is_result($submanage)) { foreach ($submanage as $m) { if ($identity == $m['mid']) { $limited_id = $m['mid']; @@ -59,7 +60,7 @@ function manage_post(App $a) { ); } - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { return; } @@ -128,21 +129,21 @@ function manage_content(App $a) { $r = q("SELECT DISTINCT(`parent`) FROM `notify` WHERE `uid` = %d AND NOT `seen` AND NOT (`type` IN (%d, %d))", intval($id['uid']), intval(NOTIFY_INTRO), intval(NOTIFY_MAIL)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $notifications = sizeof($r); } $r = q("SELECT DISTINCT(`convid`) FROM `mail` WHERE `uid` = %d AND NOT `seen`", intval($id['uid'])); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $notifications = $notifications + sizeof($r); } $r = q("SELECT COUNT(*) AS `introductions` FROM `intro` WHERE NOT `blocked` AND NOT `ignore` AND `uid` = %d", intval($id['uid'])); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $notifications = $notifications + $r[0]["introductions"]; } diff --git a/mod/match.php b/mod/match.php index f268fbc8a4..2824e6b71d 100644 --- a/mod/match.php +++ b/mod/match.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; +use Friendica\Database\DBM; require_once('include/text.php'); require_once('include/socgraph.php'); @@ -33,7 +34,7 @@ function match_content(App $a) { $r = q("SELECT `pub_keywords`, `prv_keywords` FROM `profile` WHERE `is-default` = 1 AND `uid` = %d LIMIT 1", intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { return; } if(! $r[0]['pub_keywords'] && (! $r[0]['prv_keywords'])) { diff --git a/mod/message.php b/mod/message.php index f358ba975a..50ceec704d 100644 --- a/mod/message.php +++ b/mod/message.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; require_once('include/acl_selectors.php'); require_once('include/message.php'); @@ -231,7 +232,7 @@ function message_content(App $a) { intval($a->argv[2]), intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $parent = $r[0]['parent-uri']; $convid = $r[0]['convid']; @@ -288,21 +289,21 @@ function message_content(App $a) { intval(local_user()), intval($a->argv[2]) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = q("SELECT `name`, `url`, `id` FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' LIMIT 1", intval(local_user()), dbesc(normalise_link(base64_decode($a->argv[2]))) ); } - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $r = q("SELECT `name`, `url`, `id` FROM `contact` WHERE `uid` = %d AND `addr` = '%s' LIMIT 1", intval(local_user()), dbesc(base64_decode($a->argv[2])) ); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $prename = $r[0]['name']; $preurl = $r[0]['url']; $preid = $r[0]['id']; @@ -354,13 +355,13 @@ function message_content(App $a) { intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $a->set_pager_total($r[0]['total']); } $r = get_messages(local_user(), $a->pager['start'], $a->pager['itemspage']); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { info( t('No messages.') . EOL); return $o; } @@ -382,7 +383,7 @@ function message_content(App $a) { intval(local_user()), intval($a->argv[1]) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact_id = $r[0]['contact-id']; $convid = $r[0]['convid']; diff --git a/mod/modexp.php b/mod/modexp.php index 3c5d1e3581..f64df0f9cb 100644 --- a/mod/modexp.php +++ b/mod/modexp.php @@ -1,6 +1,7 @@ $rr['name'], diff --git a/mod/network.php b/mod/network.php index e09fdd8fec..662c306f59 100644 --- a/mod/network.php +++ b/mod/network.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Config; use Friendica\Core\PConfig; +use Friendica\Database\DBM; require_once 'include/conversation.php'; require_once 'include/group.php'; @@ -497,9 +498,9 @@ function networkThreadedView(App $a, $update = 0) { $rawmode = (isset($_GET["mode"]) AND ($_GET["mode"] == "raw")); if (isset($_GET["last_received"]) && isset($_GET["last_commented"]) && isset($_GET["last_created"]) && isset($_GET["last_id"])) { - $last_received = dbm::date($_GET["last_received"]); - $last_commented = dbm::date($_GET["last_commented"]); - $last_created = dbm::date($_GET["last_created"]); + $last_received = DBM::date($_GET["last_received"]); + $last_commented = DBM::date($_GET["last_commented"]); + $last_created = DBM::date($_GET["last_created"]); $last_id = intval($_GET["last_id"]); } else { $last_received = ''; @@ -575,7 +576,7 @@ function networkThreadedView(App $a, $update = 0) { // If $cid belongs to a communitity forum or a privat goup,.add a mention to the status editor $condition = array("`id` = ? AND (`forum` OR `prv`)", $cid); $contact = dba::select('contact', array('addr', 'nick'), $condition, array('limit' => 1)); - if (dbm::is_result($contact)) { + if (DBM::is_result($contact)) { if ($contact["addr"] != '') { $content = "!".$contact["addr"]; } else { @@ -628,7 +629,7 @@ function networkThreadedView(App $a, $update = 0) { if ($group) { $r = dba::select('group', array('name'), array('id' => $group, 'uid' => $_SESSION['uid']), array('limit' => 1)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { if ($update) killme(); notice(t('No such group') . EOL); @@ -643,7 +644,7 @@ function networkThreadedView(App $a, $update = 0) { $contact_str = implode(',',$contacts); $self = dba::select('contact', array('id'), array('uid' => $_SESSION['uid'], 'self' => true), array('limit' => 1)); - if (dbm::is_result($self)) { + if (DBM::is_result($self)) { $contact_str_self = $self["id"]; } @@ -664,7 +665,7 @@ function networkThreadedView(App $a, $update = 0) { 'forum', 'prv', 'contact-type', 'addr', 'thumb', 'location'); $condition = array("`id` = ? AND (NOT `blocked` OR `pending`)", $cid); $r = dba::select('contact', $fields, $condition, array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $sql_extra = " AND ".$sql_table.".`contact-id` = ".intval($cid); $entries[0] = array( @@ -808,7 +809,7 @@ function networkThreadedView(App $a, $update = 0) { $parents_str = ''; $date_offset = ""; - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { if (!in_array($rr['item_id'],$parents_arr)) { $parents_arr[] = $rr['item_id']; @@ -835,7 +836,7 @@ function networkThreadedView(App $a, $update = 0) { $parents ); - if (dbm::is_result($thread_items)) { + if (DBM::is_result($thread_items)) { $items = array_merge($items, dba::inArray($thread_items)); } } diff --git a/mod/nogroup.php b/mod/nogroup.php index ecbfb9176e..0486663282 100644 --- a/mod/nogroup.php +++ b/mod/nogroup.php @@ -1,6 +1,7 @@ set_pager_total($r[0]['total']); } $r = contacts_not_grouped(local_user(),$a->pager['start'],$a->pager['itemspage']); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { $contact_details = get_contact_details_by_url($rr['url'], local_user(), $rr); diff --git a/mod/noscrape.php b/mod/noscrape.php index 113ad87462..0269c3f77e 100644 --- a/mod/noscrape.php +++ b/mod/noscrape.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; function noscrape_init(App $a) { @@ -48,7 +49,7 @@ function noscrape_init(App $a) { /// @todo What should this value tell us? $r = q("SELECT `gcontact`.`updated` FROM `contact` INNER JOIN `gcontact` WHERE `gcontact`.`nurl` = `contact`.`nurl` AND `self` AND `uid` = %d LIMIT 1", intval($a->profile['uid'])); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $json_info["updated"] = date("c", strtotime($r[0]['updated'])); } @@ -59,7 +60,7 @@ function noscrape_init(App $a) { dbesc(NETWORK_DIASPORA), dbesc(NETWORK_OSTATUS) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $json_info["contacts"] = intval($r[0]['total']); } } @@ -68,13 +69,13 @@ function noscrape_init(App $a) { $last_active = 0; $condition = array('uid' => $a->profile['uid'], 'self' => true); $contact = dba::select('contact', array('last-item'), $condition, array('limit' => 1)); - if (dbm::is_result($contact)) { + if (DBM::is_result($contact)) { $last_active = strtotime($contact['last-item']); } $condition = array('uid' => $a->profile['uid']); $user = dba::select('user', array('login_date'), $condition, array('limit' => 1)); - if (dbm::is_result($user)) { + if (DBM::is_result($user)) { if ($last_active < strtotime($user['login_date'])) { $last_active = strtotime($user['login_date']); } diff --git a/mod/notes.php b/mod/notes.php index d1810604ca..c5c45be724 100644 --- a/mod/notes.php +++ b/mod/notes.php @@ -1,6 +1,7 @@ set_pager_total($r[0]['total']); $a->set_pager_itemspage(40); } @@ -105,7 +106,7 @@ function notes_content(App $a, $update = false) { $parents_arr = array(); $parents_str = ''; - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach($r as $rr) $parents_arr[] = $rr['item_id']; $parents_str = implode(', ', $parents_arr); @@ -119,7 +120,7 @@ function notes_content(App $a, $update = false) { dbesc($parents_str) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $items = conv_sort($r,"`commented`"); $o .= conversation($a,$items,'notes',$update); diff --git a/mod/notice.php b/mod/notice.php index ff8bed1800..54618bdf8f 100644 --- a/mod/notice.php +++ b/mod/notice.php @@ -4,12 +4,13 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; function notice_init(App $a) { $id = $a->argv[1]; $r = q("SELECT `user`.`nickname` FROM `user` LEFT JOIN `item` ON `item`.`uid` = `user`.`uid` WHERE `item`.`id` = %d", intval($id)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $nick = $r[0]['nickname']; $url = System::baseUrl() . "/display/$nick/$id"; goaway($url); diff --git a/mod/notifications.php b/mod/notifications.php index 271e400df5..fe8422cc4a 100644 --- a/mod/notifications.php +++ b/mod/notifications.php @@ -8,6 +8,7 @@ use Friendica\App; use Friendica\Core\NotificationsManager; use Friendica\Core\System; +use Friendica\Database\DBM; require_once("include/contact_selectors.php"); require_once("include/network.php"); @@ -30,7 +31,7 @@ function notifications_post(App $a) { intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $intro_id = $r[0]['id']; $contact_id = $r[0]['contact-id']; } diff --git a/mod/notify.php b/mod/notify.php index 6f7d222d8b..fae7ebb39b 100644 --- a/mod/notify.php +++ b/mod/notify.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\NotificationsManager; use Friendica\Core\System; +use Friendica\Database\DBM; function notify_init(App $a) { if (! local_user()) { @@ -55,7 +56,7 @@ function notify_content(App $a) { require_once('include/bbcode.php'); $r = $nm->getAll(array('seen'=>0)); - if (dbm::is_result($r) > 0) { + if (DBM::is_result($r) > 0) { foreach ($r as $it) { $notif_content .= replace_macros($not_tpl,array( '$item_link' => System::baseUrl(true).'/notify/view/'. $it['id'], diff --git a/mod/openid.php b/mod/openid.php index 62a7e98e84..45b80638d5 100644 --- a/mod/openid.php +++ b/mod/openid.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; +use Friendica\Database\DBM; require_once('library/openid.php'); @@ -40,7 +41,7 @@ function openid_content(App $a) { dbesc($authid), dbesc(normalise_openid($authid)) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { // successful OpenID login diff --git a/mod/p.php b/mod/p.php index 2f94398404..9c1c2b71de 100644 --- a/mod/p.php +++ b/mod/p.php @@ -5,6 +5,7 @@ This file is part of the Diaspora protocol. It is used for fetching single publi use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; use Friendica\Protocol\Diaspora; function p_init($a){ @@ -51,7 +52,7 @@ function p_init($a){ $r = q("SELECT `user`.`prvkey`, `contact`.`addr`, `user`.`nickname`, `contact`.`nick` FROM `user` INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid` AND `contact`.`self` WHERE `user`.`uid` = %d", intval($item[0]["uid"])); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { header($_SERVER["SERVER_PROTOCOL"].' 404 '.t('Not Found')); killme(); } diff --git a/mod/photo.php b/mod/photo.php index 72b7e8e95a..ece784baec 100644 --- a/mod/photo.php +++ b/mod/photo.php @@ -1,6 +1,7 @@ argv[2]) ); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { q("DELETE FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'", intval($page_owner_uid), dbesc($r[0]['resource-id']) @@ -365,7 +366,7 @@ function photos_post(App $a) { dbesc($r[0]['resource-id']), intval($page_owner_uid) ); - if (dbm::is_result($i)) { + if (DBM::is_result($i)) { q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d", dbesc(datetime_convert()), dbesc(datetime_convert()), @@ -418,7 +419,7 @@ function photos_post(App $a) { dbesc($resource_id), intval($page_owner_uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $ph = new Photo($r[0]['data'], $r[0]['type']); if ($ph->is_valid()) { $rotate_deg = ( (intval($_POST['rotate']) == 1) ? 270 : 90 ); @@ -470,7 +471,7 @@ function photos_post(App $a) { dbesc($resource_id), intval($page_owner_uid) ); - if (dbm::is_result($p)) { + if (DBM::is_result($p)) { $ext = $phototypes[$p[0]['type']]; $r = q("UPDATE `photo` SET `desc` = '%s', `album` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s' WHERE `resource-id` = '%s' AND `uid` = %d", dbesc($desc), @@ -541,7 +542,7 @@ function photos_post(App $a) { intval($page_owner_uid) ); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $old_tag = $r[0]['tag']; $old_inform = $r[0]['inform']; } @@ -608,7 +609,7 @@ function photos_post(App $a) { intval($page_owner_uid) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { //select someone by attag or nick and the name passed in $r = q("SELECT * FROM `contact` WHERE `attag` = '%s' OR `nick` = '%s' AND `uid` = %d ORDER BY `attag` DESC LIMIT 1", dbesc($name), @@ -618,7 +619,7 @@ function photos_post(App $a) { } } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $newname = $r[0]['name']; $profile = $r[0]['url']; $notify = 'cid:' . $r[0]['id']; @@ -775,7 +776,7 @@ function photos_post(App $a) { dbesc($album), intval($page_owner_uid) ); - if ((! dbm::is_result($r)) || ($album == t('Profile Photos'))) { + if ((! DBM::is_result($r)) || ($album == t('Profile Photos'))) { $visible = 1; } else { $visible = 0; @@ -1030,7 +1031,7 @@ function photos_content(App $a) { intval($contact_id), intval($owner_uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $can_post = true; $contact = $r[0]; $remote_contact = true; @@ -1058,7 +1059,7 @@ function photos_content(App $a) { intval($contact_id), intval($owner_uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact = $r[0]; $remote_contact = true; } @@ -1205,7 +1206,7 @@ function photos_content(App $a) { intval($owner_uid), dbesc($album) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $a->set_pager_total(count($r)); $a->set_pager_itemspage(20); } @@ -1264,7 +1265,7 @@ function photos_content(App $a) { $photos = array(); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $twist = 'rotright'; foreach ($r as $rr) { if ($twist == 'rotright') { @@ -1326,13 +1327,13 @@ function photos_content(App $a) { dbesc($datum) ); - if (! dbm::is_result($ph)) { + if (! DBM::is_result($ph)) { $ph = q("SELECT `id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' LIMIT 1", intval($owner_uid), dbesc($datum) ); - if (dbm::is_result($ph)) { + if (DBM::is_result($ph)) { notice(t('Permission denied. Access to this item may be restricted.')); } else { notice(t('Photo not available') . EOL ); @@ -1358,7 +1359,7 @@ function photos_content(App $a) { intval($owner_uid) ); - if (dbm::is_result($prvnxt)) { + if (DBM::is_result($prvnxt)) { foreach ($prvnxt as $z => $entry) { if ($entry['resource-id'] == $ph[0]['resource-id']) { $prv = $z - 1; @@ -1449,7 +1450,7 @@ function photos_content(App $a) { $map = null; - if (dbm::is_result($linked_items)) { + if (DBM::is_result($linked_items)) { $link_item = $linked_items[0]; $r = q("SELECT COUNT(*) AS `total` @@ -1464,7 +1465,7 @@ function photos_content(App $a) { ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $a->set_pager_total($r[0]['total']); } @@ -1607,7 +1608,7 @@ function photos_content(App $a) { } $comments = ''; - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { if (($can_post || can_write_wall($a, $owner_uid)) && $link_item['last-child']) { $comments .= replace_macros($cmnt_tpl, array( '$return_path' => '', @@ -1641,7 +1642,7 @@ function photos_content(App $a) { ); // display comments - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $item) { builtin_activity_puller($item, $conv_responses); @@ -1815,7 +1816,7 @@ function photos_content(App $a) { dbesc('Contact Photos'), dbesc( t('Contact Photos')) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $a->set_pager_total(count($r)); $a->set_pager_itemspage(20); } @@ -1833,7 +1834,7 @@ function photos_content(App $a) { ); $photos = array(); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $twist = 'rotright'; foreach ($r as $rr) { //hide profile photos to others diff --git a/mod/ping.php b/mod/ping.php index f6d5e8cf02..00620ddeb5 100644 --- a/mod/ping.php +++ b/mod/ping.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\PConfig; +use Friendica\Database\DBM; require_once('include/datetime.php'); require_once('include/bbcode.php'); @@ -130,7 +131,7 @@ function ping_init(App $a) intval(local_user()), intval(local_user()) ); - if (dbm::is_result($items_unseen)) { + if (DBM::is_result($items_unseen)) { $arr = array('items' => $items_unseen); call_hooks('network_ping', $arr); @@ -147,7 +148,7 @@ function ping_init(App $a) if (intval(feature_enabled(local_user(), 'groups'))) { // Find out how unseen network posts are spread across groups $group_counts = groups_count_unseen(); - if (dbm::is_result($group_counts)) { + if (DBM::is_result($group_counts)) { foreach ($group_counts as $group_count) { if ($group_count['count'] > 0) { $groups_unseen[] = $group_count; @@ -158,7 +159,7 @@ function ping_init(App $a) if (intval(feature_enabled(local_user(), 'forumlist_widget'))) { $forum_counts = ForumManager::count_unseen_items(); - if (dbm::is_result($forums_counts)) { + if (DBM::is_result($forums_counts)) { foreach ($forums_counts as $forum_count) { if ($forum_count['count'] > 0) { $forums_unseen[] = $forum_count; @@ -197,7 +198,7 @@ function ping_init(App $a) FROM `contact` RIGHT JOIN `register` ON `register`.`uid` = `contact`.`uid` WHERE `contact`.`self` = 1"); - if (dbm::is_result($regs)) { + if (DBM::is_result($regs)) { $register_count = $regs[0]['total']; } } @@ -212,12 +213,12 @@ function ping_init(App $a) dbesc(datetime_convert('UTC', 'UTC', 'now + 7 days')), dbesc(datetime_convert('UTC', 'UTC', 'now')) ); - if (dbm::is_result($ev)) { + if (DBM::is_result($ev)) { Cache::set($cachekey, $ev, CACHE_HOUR); } } - if (dbm::is_result($ev)) { + if (DBM::is_result($ev)) { $all_events = count($ev); if ($all_events) { @@ -255,7 +256,7 @@ function ping_init(App $a) $data['birthdays'] = $birthdays; $data['birthdays-today'] = $birthdays_today; - if (dbm::is_result($notifs)) { + if (DBM::is_result($notifs)) { foreach ($notifs as $notif) { if ($notif['seen'] == 0) { $sysnotify_count ++; @@ -264,7 +265,7 @@ function ping_init(App $a) } // merge all notification types in one array - if (dbm::is_result($intros)) { + if (DBM::is_result($intros)) { foreach ($intros as $intro) { $notif = array( 'href' => System::baseUrl() . '/notifications/intros/' . $intro['id'], @@ -279,7 +280,7 @@ function ping_init(App $a) } } - if (dbm::is_result($mails)) { + if (DBM::is_result($mails)) { foreach ($mails as $mail) { $notif = array( 'href' => System::baseUrl() . '/message/' . $mail['id'], @@ -294,7 +295,7 @@ function ping_init(App $a) } } - if (dbm::is_result($regs)) { + if (DBM::is_result($regs)) { foreach ($regs as $reg) { $notif = array( 'href' => System::baseUrl() . '/admin/users/', @@ -330,7 +331,7 @@ function ping_init(App $a) }; usort($notifs, $sort_function); - if (dbm::is_result($notifs)) { + if (DBM::is_result($notifs)) { // Are the nofications called from the regular process or via the friendica app? $regularnotifications = (intval($_GET['uid']) && intval($_GET['_'])); diff --git a/mod/poco.php b/mod/poco.php index 5610190dc2..c5c5ef4c83 100644 --- a/mod/poco.php +++ b/mod/poco.php @@ -5,6 +5,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Database\DBM; function poco_init(App $a) { $system_mode = false; @@ -18,7 +19,7 @@ function poco_init(App $a) { } if (! x($user)) { $c = q("SELECT * FROM `pconfig` WHERE `cat` = 'system' AND `k` = 'suggestme' AND `v` = 1"); - if (! dbm::is_result($c)) { + if (! DBM::is_result($c)) { http_status_exit(401); } $system_mode = true; @@ -60,7 +61,7 @@ function poco_init(App $a) { where `user`.`nickname` = '%s' and `profile`.`is-default` = 1 limit 1", dbesc($user) ); - if (! dbm::is_result($users) || $users[0]['hidewall'] || $users[0]['hide-friends']) { + if (! DBM::is_result($users) || $users[0]['hidewall'] || $users[0]['hide-friends']) { http_status_exit(404); } @@ -100,7 +101,7 @@ function poco_init(App $a) { dbesc(NETWORK_STATUSNET) ); } - if (dbm::is_result($contacts)) { + if (DBM::is_result($contacts)) { $totalResults = intval($contacts[0]['total']); } else { $totalResults = 0; @@ -195,7 +196,7 @@ function poco_init(App $a) { } if (is_array($contacts)) { - if (dbm::is_result($contacts)) { + if (DBM::is_result($contacts)) { foreach ($contacts as $contact) { if (! isset($contact['generation'])) { if ($global) { diff --git a/mod/poke.php b/mod/poke.php index c02d59c460..848ed817d6 100644 --- a/mod/poke.php +++ b/mod/poke.php @@ -17,6 +17,7 @@ use Friendica\App; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; require_once('include/security.php'); require_once('include/bbcode.php'); @@ -59,7 +60,7 @@ function poke_init(App $a) { intval($uid) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { logger('poke: no contact ' . $contact_id); return; } @@ -73,7 +74,7 @@ function poke_init(App $a) { intval($parent), intval($uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $parent_uri = $r[0]['uri']; $private = $r[0]['private']; $allow_cid = $r[0]['allow_cid']; @@ -166,7 +167,7 @@ function poke_content(App $a) { intval($_GET['c']), intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $name = $r[0]['name']; $id = $r[0]['id']; } diff --git a/mod/post.php b/mod/post.php index bfdc62ab79..8e279644bd 100644 --- a/mod/post.php +++ b/mod/post.php @@ -5,6 +5,7 @@ */ use Friendica\App; +use Friendica\Database\DBM; require_once('include/salmon.php'); require_once('include/crypto.php'); @@ -24,7 +25,7 @@ function post_post(App $a) { AND `account_expired` = 0 AND `account_removed` = 0 LIMIT 1", dbesc($nickname) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { http_status_exit(500); } diff --git a/mod/profile.php b/mod/profile.php index be95fd2509..8a9b8b6666 100644 --- a/mod/profile.php +++ b/mod/profile.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; +use Friendica\Database\DBM; require_once('include/contact_widgets.php'); require_once('include/redir.php'); @@ -17,7 +18,7 @@ function profile_init(App $a) { $which = htmlspecialchars($a->argv[1]); else { $r = q("select nickname from user where blocked = 0 and account_expired = 0 and account_removed = 0 and verified = 1 order by rand() limit 1"); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { goaway(System::baseUrl() . '/profile/' . $r[0]['nickname']); } else { @@ -139,7 +140,7 @@ function profile_content(App $a, $update = 0) { intval($contact_id), intval($a->profile['profile_uid']) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $contact = $r[0]; $remote_contact = true; } @@ -240,7 +241,7 @@ function profile_content(App $a, $update = 0) { intval($a->profile['profile_uid']) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { return ''; } @@ -267,7 +268,7 @@ function profile_content(App $a, $update = 0) { intval(PAGE_COMMUNITY), intval(PAGE_PRVGROUP)); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $sql_extra3 = sprintf(" AND `thread`.`contact-id` = %d ", intval(intval($a->profile['contact_id']))); } @@ -313,7 +314,7 @@ function profile_content(App $a, $update = 0) { // search for new items (update routine) $_SESSION['last_updated'][$last_updated_key] = time(); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach($r as $rr) $parents_arr[] = $rr['item_id']; $parents_str = implode(', ', $parents_arr); diff --git a/mod/profile_photo.php b/mod/profile_photo.php index c68655b756..5f52451414 100644 --- a/mod/profile_photo.php +++ b/mod/profile_photo.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; require_once("include/Photo.php"); @@ -35,7 +36,7 @@ function profile_photo_post(App $a) { intval($_REQUEST['profile']), intval(local_user()) ); - if (dbm::is_result($r) && (! intval($r[0]['is-default']))) + if (DBM::is_result($r) && (! intval($r[0]['is-default']))) $is_default_profile = 0; } @@ -66,7 +67,7 @@ function profile_photo_post(App $a) { dbesc(local_user()), intval($scale)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $base_image = $r[0]; @@ -202,7 +203,7 @@ function profile_photo_content(App $a) { intval(local_user()), dbesc($resource_id) ); - if (!dbm::is_result($r)){ + if (!DBM::is_result($r)){ notice( t('Permission denied.') . EOL ); return; } diff --git a/mod/profiles.php b/mod/profiles.php index b787bc1548..fe26d8f561 100644 --- a/mod/profiles.php +++ b/mod/profiles.php @@ -5,6 +5,7 @@ use Friendica\Core\Config; use Friendica\Core\PConfig; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; use Friendica\Network\Probe; require_once 'include/Contact.php'; @@ -23,7 +24,7 @@ function profiles_init(App $a) { intval($a->argv[2]), intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('Profile not found.') . EOL); goaway('profiles'); return; // NOTREACHED @@ -42,7 +43,7 @@ function profiles_init(App $a) { intval($a->argv[2]), intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { info(t('Profile deleted.').EOL); } @@ -57,7 +58,7 @@ function profiles_init(App $a) { $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d", intval(local_user())); - $num_profiles = (dbm::is_result($r0) ? count($r0) : 0); + $num_profiles = (DBM::is_result($r0) ? count($r0) : 0); $name = t('Profile-') . ($num_profiles + 1); @@ -79,7 +80,7 @@ function profiles_init(App $a) { ); info( t('New profile created.') . EOL); - if (dbm::is_result($r3) && count($r3) == 1) { + if (DBM::is_result($r3) && count($r3) == 1) { goaway('profiles/' . $r3[0]['id']); } @@ -93,14 +94,14 @@ function profiles_init(App $a) { $r0 = q("SELECT `id` FROM `profile` WHERE `uid` = %d", intval(local_user())); - $num_profiles = (dbm::is_result($r0) ? count($r0) : 0); + $num_profiles = (DBM::is_result($r0) ? count($r0) : 0); $name = t('Profile-') . ($num_profiles + 1); $r1 = q("SELECT * FROM `profile` WHERE `uid` = %d AND `id` = %d LIMIT 1", intval(local_user()), intval($a->argv[2]) ); - if(! dbm::is_result($r1)) { + if(! DBM::is_result($r1)) { notice( t('Profile unavailable to clone.') . EOL); killme(); return; @@ -118,7 +119,7 @@ function profiles_init(App $a) { dbesc($name) ); info( t('New profile created.') . EOL); - if ((dbm::is_result($r3)) && (count($r3) == 1)) { + if ((DBM::is_result($r3)) && (count($r3) == 1)) { goaway('profiles/'.$r3[0]['id']); } @@ -133,7 +134,7 @@ function profiles_init(App $a) { intval($a->argv[1]), intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('Profile not found.') . EOL); killme(); return; @@ -180,7 +181,7 @@ function profiles_post(App $a) { intval($a->argv[1]), intval(local_user()) ); - if (! dbm::is_result($orig)) { + if (! DBM::is_result($orig)) { notice( t('Profile not found.') . EOL); return; } @@ -274,13 +275,13 @@ function profiles_post(App $a) { dbesc($newname), intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { $r = q("SELECT * FROM `contact` WHERE `nick` = '%s' AND `uid` = %d LIMIT 1", dbesc($lookup), intval(local_user()) ); } - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $prf = $r[0]['url']; $newname = $r[0]['name']; } @@ -533,7 +534,7 @@ function profile_activity($changed, $value) { intval(local_user()) ); - if (! dbm::is_result($self)) { + if (! DBM::is_result($self)) { return; } @@ -616,7 +617,7 @@ function profiles_content(App $a) { intval($a->argv[1]), intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('Profile not found.') . EOL); return; } @@ -757,7 +758,7 @@ function profiles_content(App $a) { $r = q("SELECT * FROM `profile` WHERE `uid` = %d AND `is-default`=1", local_user() ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { //Go to the default profile. goaway('profiles/' . $r[0]['id']); } @@ -766,7 +767,7 @@ function profiles_content(App $a) { $r = q("SELECT * FROM `profile` WHERE `uid` = %d", local_user()); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $tpl = get_markup_template('profile_entry.tpl'); diff --git a/mod/profperm.php b/mod/profperm.php index 2b3c07526b..d46e15fbf6 100644 --- a/mod/profperm.php +++ b/mod/profperm.php @@ -3,6 +3,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\PConfig; +use Friendica\Database\DBM; function profperm_init(App $a) { @@ -47,7 +48,7 @@ function profperm_content(App $a) { intval($a->argv[2]), intval(local_user()) ); - if (dbm::is_result($r)) + if (DBM::is_result($r)) $change = intval($a->argv[2]); } @@ -57,7 +58,7 @@ function profperm_content(App $a) { intval($a->argv[1]), intval(local_user()) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { notice( t('Invalid profile identifier.') . EOL ); return; } @@ -69,7 +70,7 @@ function profperm_content(App $a) { ); $ingroup = array(); - if (dbm::is_result($r)) + if (DBM::is_result($r)) foreach($r as $member) $ingroup[] = $member['id']; @@ -99,7 +100,7 @@ function profperm_content(App $a) { $members = $r; $ingroup = array(); - if (dbm::is_result($r)) + if (DBM::is_result($r)) foreach($r as $member) $ingroup[] = $member['id']; } @@ -143,7 +144,7 @@ function profperm_content(App $a) { dbesc(NETWORK_DFRN) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $textmode = (($switchtotext && (count($r) > $switchtotext)) ? true : false); foreach($r as $member) { if(! in_array($member['id'],$ingroup)) { diff --git a/mod/proxy.php b/mod/proxy.php index 601fb79637..8b5f0834f2 100644 --- a/mod/proxy.php +++ b/mod/proxy.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; +use Friendica\Database\DBM; define('PROXY_DEFAULT_TIME', 86400); // 1 Day @@ -144,7 +145,7 @@ function proxy_init(App $a) { if (!$direct_cache && ($cachefile == '')) { $r = dba::select('photo', array('data', 'desc'), array('resource-id' => $urlhash), array('limit' => 1)); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $img_str = $r['data']; $mime = $r['desc']; if ($mime == '') { @@ -153,7 +154,7 @@ function proxy_init(App $a) { } } - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { // It shouldn't happen but it does - spaces in URL $_REQUEST['url'] = str_replace(' ', '+', $_REQUEST['url']); $redirects = 0; diff --git a/mod/pubsub.php b/mod/pubsub.php index 60df449b53..1cee91f4db 100644 --- a/mod/pubsub.php +++ b/mod/pubsub.php @@ -1,6 +1,7 @@ argv[2]; $importer = dba::select('user', array(), array('guid' => $guid, 'account_expired' => false, 'account_removed' => false), array('limit' => 1)); - if (!dbm::is_result($importer)) { + if (!DBM::is_result($importer)) { http_status_exit(500); } } diff --git a/mod/redir.php b/mod/redir.php index 998e9cc0bd..b729238426 100644 --- a/mod/redir.php +++ b/mod/redir.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; function redir_init(App $a) { @@ -21,7 +22,7 @@ function redir_init(App $a) { intval(local_user()) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { goaway(System::baseUrl()); } if ($r[0]['network'] !== NETWORK_DFRN) { @@ -36,7 +37,7 @@ function redir_init(App $a) { intval(local_user()) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { goaway(System::baseUrl()); } if ($r[0]['network'] !== NETWORK_DFRN) { diff --git a/mod/regmod.php b/mod/regmod.php index 03cb7fa8fa..d6e122a286 100644 --- a/mod/regmod.php +++ b/mod/regmod.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; require_once('include/enotify.php'); require_once('include/user.php'); @@ -17,7 +18,7 @@ function user_allow($hash) { ); - if (! dbm::is_result($register)) { + if (! DBM::is_result($register)) { return false; } @@ -25,7 +26,7 @@ function user_allow($hash) { intval($register[0]['uid']) ); - if (! dbm::is_result($user)) { + if (! DBM::is_result($user)) { killme(); } @@ -41,7 +42,7 @@ function user_allow($hash) { $r = q("SELECT * FROM `profile` WHERE `uid` = %d AND `is-default` = 1", intval($user[0]['uid']) ); - if (dbm::is_result($r) && $r[0]['net-publish']) { + if (DBM::is_result($r) && $r[0]['net-publish']) { $url = System::baseUrl() . '/profile/' . $user[0]['nickname']; if ($url && strlen(Config::get('system','directory'))) { Worker::add(PRIORITY_LOW, "directory", $url); @@ -77,7 +78,7 @@ function user_deny($hash) { dbesc($hash) ); - if (!dbm::is_result($register)) { + if (!DBM::is_result($register)) { return false; } diff --git a/mod/salmon.php b/mod/salmon.php index 508cd4de65..e664946bb0 100644 --- a/mod/salmon.php +++ b/mod/salmon.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\PConfig; +use Friendica\Database\DBM; require_once('include/salmon.php'); require_once('include/ostatus.php'); @@ -34,7 +35,7 @@ function salmon_post(App $a) { $r = q("SELECT * FROM `user` WHERE `nickname` = '%s' AND `account_expired` = 0 AND `account_removed` = 0 LIMIT 1", dbesc($nick) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { http_status_exit(500); } @@ -158,7 +159,7 @@ function salmon_post(App $a) { dbesc(normalise_link($author_link)), intval($importer['uid']) ); - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { logger('mod-salmon: Author unknown to us.'); if(PConfig::get($importer['uid'],'system','ostatus_autofriend')) { $result = new_contact($importer['uid'],$author_link); @@ -177,8 +178,8 @@ function salmon_post(App $a) { // Have we ignored the person? // If so we can not accept this post. - //if((dbm::is_result($r)) && (($r[0]['readonly']) || ($r[0]['rel'] == CONTACT_IS_FOLLOWER) || ($r[0]['blocked']))) { - if (dbm::is_result($r) && $r[0]['blocked']) { + //if((DBM::is_result($r)) && (($r[0]['readonly']) || ($r[0]['rel'] == CONTACT_IS_FOLLOWER) || ($r[0]['blocked']))) { + if (DBM::is_result($r) && $r[0]['blocked']) { logger('mod-salmon: Ignoring this author.'); http_status_exit(202); // NOTREACHED @@ -187,7 +188,7 @@ function salmon_post(App $a) { // Placeholder for hub discovery. $hub = ''; - $contact_rec = ((dbm::is_result($r)) ? $r[0] : null); + $contact_rec = ((DBM::is_result($r)) ? $r[0] : null); ostatus::import($data,$importer,$contact_rec, $hub); diff --git a/mod/search.php b/mod/search.php index 4abca77bb4..4c3d4586d1 100644 --- a/mod/search.php +++ b/mod/search.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\Config; +use Friendica\Database\DBM; require_once("include/bbcode.php"); require_once('include/security.php'); @@ -19,7 +20,7 @@ function search_saved_searches() { intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $saved = array(); foreach ($r as $rr) { $saved[] = array( @@ -57,7 +58,7 @@ function search_init(App $a) { intval(local_user()), dbesc($search) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { dba::insert('search', array('uid' => local_user(), 'term' => $search)); } } @@ -212,7 +213,7 @@ function search_content(App $a) { intval($a->pager['start']), intval($a->pager['itemspage'])); } - if (! dbm::is_result($r)) { + if (! DBM::is_result($r)) { info( t('No results.') . EOL); return $o; } diff --git a/mod/settings.php b/mod/settings.php index 6c160a21f0..3f5abb4a08 100644 --- a/mod/settings.php +++ b/mod/settings.php @@ -5,6 +5,7 @@ use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Core\Config; use Friendica\Core\PConfig; +use Friendica\Database\DBM; require_once('include/group.php'); require_once('include/socgraph.php'); @@ -228,7 +229,7 @@ function settings_post(App $a) { $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1", intval(local_user()) ); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { dba::insert('mailacct', array('uid' => local_user())); } if (strlen($mail_pass)) { @@ -253,7 +254,7 @@ function settings_post(App $a) { $r = q("SELECT * FROM `mailacct` WHERE `uid` = %d LIMIT 1", intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $eacct = $r[0]; require_once('include/email.php'); $mb = construct_mailbox_name($eacct); @@ -704,7 +705,7 @@ function settings_content(App $a) { dbesc($a->argv[3]), local_user()); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { notice(t("You can't edit this application.")); return; } @@ -735,7 +736,7 @@ function settings_content(App $a) { return; } - /// @TODO validate result with dbm::is_result() + /// @TODO validate result with DBM::is_result() $r = q("SELECT clients.*, tokens.id as oauth_token, (clients.uid=%d) AS my FROM clients LEFT JOIN tokens ON clients.client_id=tokens.client_id @@ -765,7 +766,7 @@ function settings_content(App $a) { $settings_addons = ""; $r = q("SELECT * FROM `hook` WHERE `hook` = 'plugin_settings' "); - if (!dbm::is_result($r)) { + if (!DBM::is_result($r)) { $settings_addons = t('No Plugin settings configured'); } @@ -874,15 +875,15 @@ function settings_content(App $a) { $r = null; } - $mail_server = ((dbm::is_result($r)) ? $r[0]['server'] : ''); - $mail_port = ((dbm::is_result($r) && intval($r[0]['port'])) ? intval($r[0]['port']) : ''); - $mail_ssl = ((dbm::is_result($r)) ? $r[0]['ssltype'] : ''); - $mail_user = ((dbm::is_result($r)) ? $r[0]['user'] : ''); - $mail_replyto = ((dbm::is_result($r)) ? $r[0]['reply_to'] : ''); - $mail_pubmail = ((dbm::is_result($r)) ? $r[0]['pubmail'] : 0); - $mail_action = ((dbm::is_result($r)) ? $r[0]['action'] : 0); - $mail_movetofolder = ((dbm::is_result($r)) ? $r[0]['movetofolder'] : ''); - $mail_chk = ((dbm::is_result($r)) ? $r[0]['last_check'] : NULL_DATE); + $mail_server = ((DBM::is_result($r)) ? $r[0]['server'] : ''); + $mail_port = ((DBM::is_result($r) && intval($r[0]['port'])) ? intval($r[0]['port']) : ''); + $mail_ssl = ((DBM::is_result($r)) ? $r[0]['ssltype'] : ''); + $mail_user = ((DBM::is_result($r)) ? $r[0]['user'] : ''); + $mail_replyto = ((DBM::is_result($r)) ? $r[0]['reply_to'] : ''); + $mail_pubmail = ((DBM::is_result($r)) ? $r[0]['pubmail'] : 0); + $mail_action = ((DBM::is_result($r)) ? $r[0]['action'] : 0); + $mail_movetofolder = ((DBM::is_result($r)) ? $r[0]['movetofolder'] : ''); + $mail_chk = ((DBM::is_result($r)) ? $r[0]['last_check'] : NULL_DATE); $tpl = get_markup_template("settings_connectors.tpl"); diff --git a/mod/share.php b/mod/share.php index 7ddca0f30b..864199f01a 100644 --- a/mod/share.php +++ b/mod/share.php @@ -1,6 +1,7 @@ $v) { @@ -67,7 +68,7 @@ function _uexport_multirow($query) { function _uexport_row($query) { $result = array(); $r = q($query); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { foreach ($r as $rr) { foreach ($rr as $k => $v) { $result[$k] = $v; @@ -139,7 +140,7 @@ function uexport_all(App $a) { $r = q("SELECT count(*) as `total` FROM `item` WHERE `uid` = %d ", intval(local_user()) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $total = $r[0]['total']; } // chunk the output to avoid exhausting memory diff --git a/mod/unfollow.php b/mod/unfollow.php index 607c17d277..58b4397ca5 100644 --- a/mod/unfollow.php +++ b/mod/unfollow.php @@ -2,6 +2,7 @@ use Friendica\App; use Friendica\Core\System; +use Friendica\Database\DBM; require_once 'include/follow.php'; require_once 'include/Contact.php'; @@ -28,7 +29,7 @@ function unfollow_post(App $a) { normalise_link($url), $url, NETWORK_STATUSNET); $contact = dba::select('contact', array(), $condition, array('limit' => 1)); - if (!dbm::is_result($contact)) { + if (!DBM::is_result($contact)) { notice(t("Contact wasn't found or can't be unfollowed.")); } else { if (in_array($contact['network'], array(NETWORK_OSTATUS, NETWORK_DIASPORA))) { @@ -36,7 +37,7 @@ function unfollow_post(App $a) { WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1", intval($uid) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { $self = ""; // Unused parameter terminate_friendship($r[0], $self, $contact); } @@ -68,7 +69,7 @@ function unfollow_content(App $a) { normalise_link($url), $url, NETWORK_STATUSNET); $contact = dba::select('contact', array('url', 'network', 'addr', 'name'), $condition, array('limit' => 1)); - if (!dbm::is_result($contact)) { + if (!DBM::is_result($contact)) { notice(t("You aren't a friend of this contact.").EOL); $submit = ""; // NOTREACHED diff --git a/mod/videos.php b/mod/videos.php index 88d35ea834..bea315c590 100644 --- a/mod/videos.php +++ b/mod/videos.php @@ -4,6 +4,7 @@ use Friendica\App; use Friendica\Core\Config; use Friendica\Core\System; use Friendica\Core\Worker; +use Friendica\Database\DBM; require_once('include/items.php'); require_once('include/acl_selectors.php'); @@ -148,7 +149,7 @@ function videos_post(App $a) { dbesc($video_id) ); - if (dbm::is_result($r)) { + if (DBM::is_result($r)) { q("DELETE FROM `attach` WHERE `uid` = %d AND `id` = '%s'", intval(local_user()), dbesc($video_id) @@ -158,7 +159,7 @@ function videos_post(App $a) { intval(local_user()) ); //echo "
"; var_dump($i); killme();
-			if (dbm::is_result($i)) {
+			if (DBM::is_result($i)) {
 				q("UPDATE `item` SET `deleted` = 1, `edited` = '%s', `changed` = '%s' WHERE `parent-uri` = '%s' AND `uid` = %d",
 					dbesc(datetime_convert()),
 					dbesc(datetime_convert()),
@@ -268,7 +269,7 @@ function videos_content(App $a) {
 					intval($contact_id),
 					intval($owner_uid)
 				);
-				if (dbm::is_result($r)) {
+				if (DBM::is_result($r)) {
 					$can_post = true;
 					$contact = $r[0];
 					$remote_contact = true;
@@ -296,7 +297,7 @@ function videos_content(App $a) {
 				intval($contact_id),
 				intval($owner_uid)
 			);
-			if (dbm::is_result($r)) {
+			if (DBM::is_result($r)) {
 				$contact = $r[0];
 				$remote_contact = true;
 			}
@@ -356,7 +357,7 @@ function videos_content(App $a) {
 		$sql_extra GROUP BY hash",
 		intval($a->data['user']['uid'])
 	);
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		$a->set_pager_total(count($r));
 		$a->set_pager_itemspage(20);
 	}
@@ -374,7 +375,7 @@ function videos_content(App $a) {
 
 
 	$videos = array();
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			if ($a->theme['template_engine'] === 'internal') {
 				$alt_e = template_escape($rr['filename']);
diff --git a/mod/viewcontacts.php b/mod/viewcontacts.php
index 51104c4783..8c35be77d8 100644
--- a/mod/viewcontacts.php
+++ b/mod/viewcontacts.php
@@ -2,6 +2,7 @@
 
 use Friendica\App;
 use Friendica\Core\Config;
+use Friendica\Database\DBM;
 
 require_once('include/Contact.php');
 require_once('include/contact_selectors.php');
@@ -20,7 +21,7 @@ function viewcontacts_init(App $a) {
 			dbesc($nick)
 		);
 
-		if (! dbm::is_result($r)) {
+		if (! DBM::is_result($r)) {
 			return;
 		}
 
@@ -60,7 +61,7 @@ function viewcontacts_content(App $a) {
 		dbesc(NETWORK_DIASPORA),
 		dbesc(NETWORK_OSTATUS)
 	);
-	if (dbm::is_result($r))
+	if (DBM::is_result($r))
 		$a->set_pager_total($r[0]['total']);
 
 	$r = q("SELECT * FROM `contact`
@@ -75,7 +76,7 @@ function viewcontacts_content(App $a) {
 		intval($a->pager['start']),
 		intval($a->pager['itemspage'])
 	);
-	if (!dbm::is_result($r)) {
+	if (!DBM::is_result($r)) {
 		info(t('No contacts.').EOL);
 		return $o;
 	}
diff --git a/mod/viewsrc.php b/mod/viewsrc.php
index 0915895906..a607498442 100644
--- a/mod/viewsrc.php
+++ b/mod/viewsrc.php
@@ -1,6 +1,7 @@
 ',$r[0]['body']);
 			killme();
diff --git a/mod/wall_attach.php b/mod/wall_attach.php
index a060c253cf..931dcb7200 100644
--- a/mod/wall_attach.php
+++ b/mod/wall_attach.php
@@ -2,6 +2,7 @@
 
 use Friendica\App;
 use Friendica\Core\Config;
+use Friendica\Database\DBM;
 
 require_once('include/attach.php');
 require_once('include/datetime.php');
@@ -15,7 +16,7 @@ function wall_attach_post(App $a) {
 		$r = q("SELECT `user`.*, `contact`.`id` FROM `user` LEFT JOIN `contact` on `user`.`uid` = `contact`.`uid`  WHERE `user`.`nickname` = '%s' AND `user`.`blocked` = 0 and `contact`.`self` = 1 LIMIT 1",
 			dbesc($nick)
 		);
-		if (! dbm::is_result($r)) {
+		if (! DBM::is_result($r)) {
 			if ($r_json) {
 				echo json_encode(array('error'=>t('Invalid request.')));
 				killme();
@@ -58,7 +59,7 @@ function wall_attach_post(App $a) {
 					intval($contact_id),
 					intval($page_owner_uid)
 				);
-				if (dbm::is_result($r)) {
+				if (DBM::is_result($r)) {
 					$can_post = true;
 					$visitor = $contact_id;
 				}
@@ -144,7 +145,7 @@ function wall_attach_post(App $a) {
 		dbesc($hash)
 	);
 
-	if (! dbm::is_result($r)) {
+	if (! DBM::is_result($r)) {
 		$msg = t('File upload failed.');
 		if ($r_json) {
 			echo json_encode(array('error'=>$msg));
diff --git a/mod/wall_upload.php b/mod/wall_upload.php
index cbd1b28445..d6cb0c2e1a 100644
--- a/mod/wall_upload.php
+++ b/mod/wall_upload.php
@@ -12,6 +12,7 @@
 use Friendica\App;
 use Friendica\Core\System;
 use Friendica\Core\Config;
+use Friendica\Database\DBM;
 
 require_once 'include/Photo.php';
 
@@ -32,7 +33,7 @@ function wall_upload_post(App $a, $desktopmode = true) {
 				dbesc($nick)
 			);
 
-			if (! dbm::is_result($r)) {
+			if (! DBM::is_result($r)) {
 				if ($r_json) {
 					echo json_encode(array('error'=>t('Invalid request.')));
 					killme();
@@ -88,7 +89,7 @@ function wall_upload_post(App $a, $desktopmode = true) {
 					intval($contact_id),
 					intval($page_owner_uid)
 				);
-				if (dbm::is_result($r)) {
+				if (DBM::is_result($r)) {
 					$can_post = true;
 					$visitor = $contact_id;
 				}
diff --git a/mod/wallmessage.php b/mod/wallmessage.php
index fe3b9a82a6..1ac54c9f8a 100644
--- a/mod/wallmessage.php
+++ b/mod/wallmessage.php
@@ -2,6 +2,7 @@
 
 use Friendica\App;
 use \Friendica\Core\System;
+use Friendica\Database\DBM;
 
 require_once('include/message.php');
 
@@ -25,7 +26,7 @@ function wallmessage_post(App $a) {
 		dbesc($recipient)
 	);
 
-	if (! dbm::is_result($r)) {
+	if (! DBM::is_result($r)) {
 		logger('wallmessage: no recipient');
 		return;
 	}
@@ -88,7 +89,7 @@ function wallmessage_content(App $a) {
 		dbesc($recipient)
 	);
 
-	if (! dbm::is_result($r)) {
+	if (! DBM::is_result($r)) {
 		notice( t('No recipient.') . EOL);
 		logger('wallmessage: no recipient');
 		return;
diff --git a/mod/xrd.php b/mod/xrd.php
index 60f78ed27c..9f88d85eaf 100644
--- a/mod/xrd.php
+++ b/mod/xrd.php
@@ -2,6 +2,7 @@
 
 use Friendica\App;
 use Friendica\Core\System;
+use Friendica\Database\DBM;
 
 require_once('include/crypto.php');
 
@@ -33,7 +34,7 @@ function xrd_init(App $a) {
 	}
 
 	$r = dba::select('user', array(), array('nickname' => $name), array('limit' => 1));
-	if (!dbm::is_result($r)) {
+	if (!DBM::is_result($r)) {
 		killme();
 	}
 
diff --git a/object/Item.php b/object/Item.php
index fa8c893c7f..80bbf255dd 100644
--- a/object/Item.php
+++ b/object/Item.php
@@ -4,6 +4,7 @@ if(class_exists('Item'))
 
 use Friendica\Core\Config;
 use Friendica\Core\PConfig;
+use Friendica\Database\DBM;
 use Friendica\Protocol\Diaspora;
 
 require_once('object/BaseObject.php');
@@ -255,7 +256,7 @@ class Item extends BaseObject {
 					'starred'   =>  t('starred'),
 				);
 				$r = dba::select('thread', array('ignored'), array('uid' => $item['uid'], 'iid' => $item['id']), array('limit' => 1));
-				if (dbm::is_result($r)) {
+				if (DBM::is_result($r)) {
 					$ignore = array(
 						'do'        => t("ignore thread"),
 						'undo'      => t("unignore thread"),
diff --git a/src/App.php b/src/App.php
index 7ff56cee3a..ea44738571 100644
--- a/src/App.php
+++ b/src/App.php
@@ -5,7 +5,7 @@ namespace Friendica;
 use Friendica\Core\System;
 use Friendica\Core\Config;
 use Friendica\Core\PConfig;
-use Friendica\Database\Dbm;
+use Friendica\Database\DBM;
 
 use Cache;
 use dba;
@@ -706,7 +706,7 @@ class App {
 		dba::transaction();
 
 		$r = q('SELECT `pid` FROM `process` WHERE `pid` = %d', intval(getmypid()));
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			dba::insert('process', array('pid' => getmypid(), 'command' => $command, 'created' => datetime_convert()));
 		}
 		dba::commit();
@@ -719,7 +719,7 @@ class App {
 		dba::transaction();
 
 		$r = q('SELECT `pid` FROM `process`');
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			foreach ($r AS $process) {
 				if (!posix_kill($process['pid'], 0)) {
 					q('DELETE FROM `process` WHERE `pid` = %d', intval($process['pid']));
@@ -806,7 +806,7 @@ class App {
 			}
 		}
 
-		$processlist = Dbm::processlist();
+		$processlist = DBM::processlist();
 		if ($processlist['list'] != '') {
 			logger('Processcheck: Processes: ' . $processlist['amount'] . ' - Processlist: ' . $processlist['list'], LOGGER_DEBUG);
 
diff --git a/src/Core/Config.php b/src/Core/Config.php
index 546177ff78..0b889f8e50 100644
--- a/src/Core/Config.php
+++ b/src/Core/Config.php
@@ -1,7 +1,7 @@
  $family, 'k' => $key), array('limit' => 1));
-		if (Dbm::is_result($ret)) {
+		if (DBM::is_result($ret)) {
 			// manage array value
 			$val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret['v']) ? unserialize($ret['v']) : $ret['v']);
 
diff --git a/src/Core/NotificationsManager.php b/src/Core/NotificationsManager.php
index 113091d7ec..936c1f7d23 100644
--- a/src/Core/NotificationsManager.php
+++ b/src/Core/NotificationsManager.php
@@ -8,7 +8,7 @@ namespace Friendica\Core;
 
 use Friendica\Core\Pconfig;
 use Friendica\Core\System;
-use Friendica\Database\Dbm;
+use Friendica\Database\DBM;
 
 require_once 'include/html2plain.php';
 require_once 'include/datetime.php';
@@ -95,7 +95,7 @@ class NotificationsManager {
 				intval(local_user())
 			);
 
-		if (Dbm::is_result($r))
+		if (DBM::is_result($r))
 			return $this->_set_extra($r);
 
 		return false;
@@ -112,7 +112,7 @@ class NotificationsManager {
 			intval($id),
 			intval(local_user())
 		);
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			return $this->_set_extra($r)[0];
 		}
 		return null;
@@ -215,7 +215,7 @@ class NotificationsManager {
 		$notif = array();
 		$arr = array();
 
-		if (Dbm::is_result($notifs)) {
+		if (DBM::is_result($notifs)) {
 
 			foreach ($notifs as $it) {
 				// Because we use different db tables for the notification query
@@ -386,7 +386,7 @@ class NotificationsManager {
 			intval(local_user())
 		);
 
-		if (Dbm::is_result($r))
+		if (DBM::is_result($r))
 			return $r[0]['total'];
 
 		return 0;
@@ -429,7 +429,7 @@ class NotificationsManager {
 				intval($limit)
 		);
 
-		if (Dbm::is_result($r))
+		if (DBM::is_result($r))
 			$notifs = $this->formatNotifs($r, $ident);
 
 		$arr = array (
@@ -458,7 +458,7 @@ class NotificationsManager {
 			intval(local_user())
 		);
 
-		if (Dbm::is_result($r))
+		if (DBM::is_result($r))
 			return $r[0]['total'];
 
 		return 0;
@@ -494,7 +494,7 @@ class NotificationsManager {
 			intval($limit)
 		);
 
-		if (Dbm::is_result($r))
+		if (DBM::is_result($r))
 			$notifs = $this->formatNotifs($r, $ident);
 
 		$arr = array (
@@ -548,7 +548,7 @@ class NotificationsManager {
 			intval(local_user())
 		);
 
-		if (Dbm::is_result($r))
+		if (DBM::is_result($r))
 			return $r[0]['total'];
 
 		return 0;
@@ -592,7 +592,7 @@ class NotificationsManager {
 				intval($limit)
 		);
 
-		if (Dbm::is_result($r))
+		if (DBM::is_result($r))
 			$notifs = $this->formatNotifs($r, $ident);
 
 		$arr = array (
@@ -624,7 +624,7 @@ class NotificationsManager {
 			intval(local_user())
 		);
 
-		if (Dbm::is_result($r))
+		if (DBM::is_result($r))
 			return $r[0]['total'];
 
 		return 0;
@@ -666,7 +666,7 @@ class NotificationsManager {
 				intval($limit)
 		);
 
-		if (Dbm::is_result($r))
+		if (DBM::is_result($r))
 			$notifs = $this->formatNotifs($r, $ident);
 
 		$arr = array (
@@ -696,7 +696,7 @@ class NotificationsManager {
 				intval($_SESSION['uid'])
 		);
 
-		if (Dbm::is_result($r))
+		if (DBM::is_result($r))
 			return $r[0]['total'];
 
 		return 0;
@@ -743,7 +743,7 @@ class NotificationsManager {
 				intval($limit)
 		);
 
-		if (Dbm::is_result($r))
+		if (DBM::is_result($r))
 			$notifs = $this->formatIntros($r);
 
 		$arr = array (
diff --git a/src/Core/PConfig.php b/src/Core/PConfig.php
index 9f6c49bb41..b60dcd1b32 100644
--- a/src/Core/PConfig.php
+++ b/src/Core/PConfig.php
@@ -1,7 +1,7 @@
  $family, 'uid' => $uid));
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			while ($rr = dba::fetch($r)) {
 				$k = $rr['k'];
 				$a->config[$uid][$family][$k] = $rr['v'];
@@ -90,7 +90,7 @@ class PConfig {
 		}
 
 		$ret = dba::select('pconfig', array('v'), array('uid' => $uid, 'cat' => $family, 'k' => $key), array('limit' => 1));
-		if (Dbm::is_result($ret)) {
+		if (DBM::is_result($ret)) {
 			$val = (preg_match("|^a:[0-9]+:{.*}$|s", $ret['v']) ? unserialize($ret['v']) : $ret['v']);
 			$a->config[$uid][$family][$key] = $val;
 			self::$in_db[$uid][$family][$key] = true;
diff --git a/src/Core/Worker.php b/src/Core/Worker.php
index 148b707d14..76bd9fd077 100644
--- a/src/Core/Worker.php
+++ b/src/Core/Worker.php
@@ -5,7 +5,7 @@ use Friendica\App;
 use Friendica\Core\System;
 use Friendica\Core\Config;
 use Friendica\Core\Worker;
-use Friendica\Database\Dbm;
+use Friendica\Database\DBM;
 use Friendica\Util\Lock;
 
 use dba;
@@ -142,7 +142,7 @@ class Worker {
 	 */
 	private static function totalEntries() {
 		$s = dba::fetch_first("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE `executed` <= ? AND NOT `done`", NULL_DATE);
-		if (Dbm::is_result($s)) {
+		if (DBM::is_result($s)) {
 			return $s["total"];
 		} else {
 			return 0;
@@ -157,7 +157,7 @@ class Worker {
 	private static function highestPriority() {
 		$condition = array("`executed` <= ? AND NOT `done`", NULL_DATE);
 		$s = dba::select('workerqueue', array('priority'), $condition, array('limit' => 1, 'order' => array('priority')));
-		if (Dbm::is_result($s)) {
+		if (DBM::is_result($s)) {
 			return $s["priority"];
 		} else {
 			return 0;
@@ -405,7 +405,7 @@ class Worker {
 		if ($max == 0) {
 			// the maximum number of possible user connections can be a system variable
 			$r = dba::fetch_first("SHOW VARIABLES WHERE `variable_name` = 'max_user_connections'");
-			if (Dbm::is_result($r)) {
+			if (DBM::is_result($r)) {
 				$max = $r["Value"];
 			}
 			// Or it can be granted. This overrides the system variable
@@ -441,7 +441,7 @@ class Worker {
 		// We will now check for the system values.
 		// This limit could be reached although the user limits are fine.
 		$r = dba::fetch_first("SHOW VARIABLES WHERE `variable_name` = 'max_connections'");
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			return false;
 		}
 		$max = intval($r["Value"]);
@@ -449,7 +449,7 @@ class Worker {
 			return false;
 		}
 		$r = dba::fetch_first("SHOW STATUS WHERE `variable_name` = 'Threads_connected'");
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			return false;
 		}
 		$used = intval($r["Value"]);
@@ -631,7 +631,7 @@ class Worker {
 				INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid` AND NOT `done`");
 
 		// No active processes at all? Fine
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			return false;
 		}
 		$priorities = array();
@@ -754,7 +754,7 @@ class Worker {
 
 		// There can already be jobs for us in the queue.
 		$r = dba::select('workerqueue', array(), array('pid' => getmypid(), 'done' => false));
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			self::$db_duration += (microtime(true) - $stamp);
 			return dba::inArray($r);
 		}
diff --git a/src/Database/Dbm.php b/src/Database/DBM.php
similarity index 99%
rename from src/Database/Dbm.php
rename to src/Database/DBM.php
index c5db97f0ee..3efa62b73b 100644
--- a/src/Database/Dbm.php
+++ b/src/Database/DBM.php
@@ -7,7 +7,7 @@ use dba;
  *
  * This class contains functions that doesn't need to know if pdo, mysqli or whatever is used.
  */
-class Dbm {
+class DBM {
 	/**
 	 * @brief Return a list of database processes
 	 *
diff --git a/src/Network/Probe.php b/src/Network/Probe.php
index 7e1d28ef8a..84a0344f32 100644
--- a/src/Network/Probe.php
+++ b/src/Network/Probe.php
@@ -11,7 +11,7 @@ namespace Friendica\Network;
 use Friendica\App;
 use Friendica\Core\System;
 use Friendica\Core\Config;
-use Friendica\Database\Dbm;
+use Friendica\Database\DBM;
 
 use dba;
 use Cache;
@@ -397,7 +397,7 @@ class Probe {
 					}
 				}
 
-				$fields['updated'] = Dbm::date();
+				$fields['updated'] = DBM::date();
 
 				$condition = array('nurl' => normalise_link($data["url"]));
 
@@ -420,7 +420,7 @@ class Probe {
 						'confirm' => $data['confirm'],
 						'poco' => $data['poco'],
 						'network' => $data['network'],
-						'success_update' => Dbm::date());
+						'success_update' => DBM::date());
 
 				$fieldnames = array();
 
@@ -1501,7 +1501,7 @@ class Probe {
 
 			$r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1", intval($uid));
 
-			if (Dbm::is_result($x) && Dbm::is_result($r)) {
+			if (DBM::is_result($x) && DBM::is_result($r)) {
 				$mailbox = construct_mailbox_name($r[0]);
 				$password = '';
 				openssl_private_decrypt(hex2bin($r[0]['pass']), $password, $x[0]['prvkey']);
diff --git a/src/Protocol/Dfrn.php b/src/Protocol/DFRN.php
similarity index 98%
rename from src/Protocol/Dfrn.php
rename to src/Protocol/DFRN.php
index d0597603a2..17bef5d6d9 100644
--- a/src/Protocol/Dfrn.php
+++ b/src/Protocol/DFRN.php
@@ -12,7 +12,7 @@ use Friendica\App;
 use Friendica\Core\Config;
 use Friendica\Core\System;
 use Friendica\Core\Worker;
-use Friendica\Database\Dbm;
+use Friendica\Database\DBM;
 
 use dba;
 
@@ -35,7 +35,7 @@ require_once("include/xml.php");
  * @brief This class contain functions to create and send DFRN XML files
  *
  */
-class Dfrn {
+class DFRN {
 
 	const DFRN_TOP_LEVEL = 0;	// Top level posting
 	const DFRN_REPLY = 1;		// Regular reply that is stored locally
@@ -119,7 +119,7 @@ class Dfrn {
 			dbesc($owner_nick)
 		);
 
-		if (! Dbm::is_result($r)) {
+		if (! DBM::is_result($r)) {
 			killme();
 		}
 
@@ -154,7 +154,7 @@ class Dfrn {
 				intval($owner_id)
 			);
 
-			if (! Dbm::is_result($r)) {
+			if (! DBM::is_result($r)) {
 				killme();
 			}
 
@@ -252,7 +252,7 @@ class Dfrn {
 		/// @TODO This hook can't work anymore
 		//	call_hooks('atom_feed', $atom);
 
-		if (!Dbm::is_result($items) || $onlyheader) {
+		if (!DBM::is_result($items) || $onlyheader) {
 			$atom = trim($doc->saveXML());
 
 			call_hooks('atom_feed_end', $atom);
@@ -321,7 +321,7 @@ class Dfrn {
 			intval($item_id)
 		);
 
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			killme();
 		}
 
@@ -334,7 +334,7 @@ class Dfrn {
 			intval($item['uid'])
 		);
 
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			killme();
 		}
 
@@ -582,7 +582,7 @@ class Dfrn {
 		$r = q("SELECT `id` FROM `profile` INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
 				WHERE (`hidewall` OR NOT `net-publish`) AND `user`.`uid` = %d",
 			intval($owner['uid']));
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			$hidewall = true;
 		} else {
 			$hidewall = false;
@@ -638,7 +638,7 @@ class Dfrn {
 				INNER JOIN `user` ON `user`.`uid` = `profile`.`uid`
 				WHERE `profile`.`is-default` AND NOT `user`.`hidewall` AND `user`.`uid` = %d",
 			intval($owner['uid']));
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			$profile = $r[0];
 
 			xml::add_element($doc, $author, "poco:displayName", $profile["name"]);
@@ -929,7 +929,7 @@ class Dfrn {
 
 		if (isset($parent_item)) {
 			$r = dba::fetch_first("SELECT `conversation-uri`, `conversation-href` FROM `conversation` WHERE `item-uri` = ?", $item['parent-uri']);
-			if (Dbm::is_result($r)) {
+			if (DBM::is_result($r)) {
 				if ($r['conversation-uri'] != '') {
 					$conversation_uri = $r['conversation-uri'];
 				}
@@ -1044,7 +1044,7 @@ class Dfrn {
 				intval($owner["uid"]),
 				dbesc(normalise_link($mention)));
 
-			if (Dbm::is_result($r) && ($r[0]["forum"] || $r[0]["prv"])) {
+			if (DBM::is_result($r) && ($r[0]["forum"] || $r[0]["prv"])) {
 				xml::add_element($doc, $entry, "link", "", array("rel" => "mentioned",
 											"ostatus:object-type" => ACTIVITY_OBJ_GROUP,
 											"href" => $mention));
@@ -1356,7 +1356,7 @@ class Dfrn {
 			dbesc(datetime_convert("UTC","UTC", $birthday)),
 			dbesc("birthday"));
 
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			return;
 		}
 
@@ -1402,7 +1402,7 @@ class Dfrn {
 				FROM `contact` WHERE `uid` = %d AND `nurl` = '%s' AND `network` != '%s'",
 			intval($importer["uid"]), dbesc(normalise_link($author["link"])), dbesc(NETWORK_STATUSNET));
 
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			$contact = $r[0];
 			$author["contact-id"] = $r[0]["id"];
 			$author["network"] = $r[0]["network"];
@@ -1444,7 +1444,7 @@ class Dfrn {
 			$author["avatar"] = current($avatarlist);
 		}
 
-		if (Dbm::is_result($r) && !$onlyfetch) {
+		if (DBM::is_result($r) && !$onlyfetch) {
 			logger("Check if contact details for contact " . $r[0]["id"] . " (" . $r[0]["nick"] . ") have to be updated.", LOGGER_DEBUG);
 
 			$poco = array("url" => $contact["url"]);
@@ -1596,7 +1596,7 @@ class Dfrn {
 					dbesc($contact["name"]), dbesc($contact["nick"]), dbesc($contact["about"]), dbesc($contact["location"]),
 					dbesc($contact["addr"]), dbesc($contact["keywords"]), dbesc($contact["bdyear"]),
 					dbesc($contact["bd"]), intval($contact["hidden"]), dbesc($contact["xmpp"]),
-					dbesc(Dbm::date($contact["name-date"])), dbesc(Dbm::date($contact["uri-date"])),
+					dbesc(DBM::date($contact["name-date"])), dbesc(DBM::date($contact["uri-date"])),
 					intval($contact["id"]), dbesc($contact["network"]));
 			}
 
@@ -1765,7 +1765,7 @@ class Dfrn {
 		 *
 		 * @see https://github.com/friendica/friendica/pull/3254#discussion_r107315246
 		 */
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			return false;
 		}
 
@@ -1777,7 +1777,7 @@ class Dfrn {
 			dbesc($suggest["name"]),
 			dbesc($suggest["request"])
 		);
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			$fid = $r[0]["id"];
 
 			// OK, we do. Do we already have an introduction for this person ?
@@ -1793,7 +1793,7 @@ class Dfrn {
 			 *
 			 * @see https://github.com/friendica/friendica/pull/3254#discussion_r107315246
 			 */
-			if (Dbm::is_result($r)) {
+			if (DBM::is_result($r)) {
 				return false;
 			}
 		}
@@ -1815,7 +1815,7 @@ class Dfrn {
 		 * If no record in fcontact is found, below INSERT statement will not
 		 * link an introduction to it.
 		 */
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			// database record did not get created. Quietly give up.
 			killme();
 		}
@@ -1897,7 +1897,7 @@ class Dfrn {
 			intval($importer["id"]),
 			intval($importer["importer_uid"]));
 
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			logger("Query failed to execute, no result returned in " . __FUNCTION__);
 			return false;
 		}
@@ -1973,7 +1973,7 @@ class Dfrn {
 					$n, dbesc($f[0]),
 					intval($importer["importer_uid"]));
 
-			if (Dbm::is_result($r)) {
+			if (DBM::is_result($r)) {
 				$x = q("UPDATE `item` SET `%s` = '%s' WHERE `%s` = '%s' AND `uid` = %d",
 						$n, dbesc($f[1]),
 						$n, dbesc($f[0]),
@@ -2077,7 +2077,7 @@ class Dfrn {
 				LIMIT 1",
 				dbesc($item["parent-uri"])
 			);
-			if (Dbm::is_result($r)) {
+			if (DBM::is_result($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')
@@ -2089,7 +2089,7 @@ class Dfrn {
 					dbesc($r[0]["parent-uri"]),
 					intval($importer["importer_uid"])
 				);
-				if (Dbm::is_result($r)) {
+				if (DBM::is_result($r)) {
 					$is_a_remote_action = true;
 				}
 			}
@@ -2233,7 +2233,7 @@ class Dfrn {
 					dbesc($item["verb"]),
 					dbesc($item["parent-uri"])
 				);
-				if (Dbm::is_result($r)) {
+				if (DBM::is_result($r)) {
 					return false;
 				}
 
@@ -2243,7 +2243,7 @@ class Dfrn {
 					dbesc($item["verb"]),
 					dbesc($item["parent-uri"])
 				);
-				if (Dbm::is_result($r)) {
+				if (DBM::is_result($r)) {
 					return false;
 				}
 			} else {
@@ -2261,7 +2261,7 @@ class Dfrn {
 						intval($importer["importer_uid"])
 					);
 
-					if (!Dbm::is_result($r)) {
+					if (!DBM::is_result($r)) {
 						logger("Query failed to execute, no result returned in " . __FUNCTION__);
 						return false;
 					}
@@ -2362,7 +2362,7 @@ class Dfrn {
 		);
 
 		// Is there an existing item?
-		if (Dbm::is_result($current) && edited_timestamp_is_newer($current[0], $item) &&
+		if (DBM::is_result($current) && edited_timestamp_is_newer($current[0], $item) &&
 			(datetime_convert("UTC","UTC",$item["edited"]) < $current[0]["edited"])) {
 			logger("Item ".$item["uri"]." already existed.", LOGGER_DEBUG);
 			return;
@@ -2597,7 +2597,7 @@ class Dfrn {
 						dbesc($item["uri"]),
 						intval($importer["uid"])
 					);
-					if (Dbm::is_result($r)) {
+					if (DBM::is_result($r)) {
 						$ev["id"] = $r[0]["id"];
 					}
 
@@ -2614,7 +2614,7 @@ class Dfrn {
 		}
 
 		// Update content if 'updated' changes
-		if (Dbm::is_result($current)) {
+		if (DBM::is_result($current)) {
 			if (self::update_content($r[0], $item, $importer, $entrytype)) {
 				logger("Item ".$item["uri"]." was updated.", LOGGER_DEBUG);
 			} else {
@@ -2637,7 +2637,7 @@ class Dfrn {
 					intval($posted_id),
 					intval($importer["importer_uid"])
 				);
-				if (Dbm::is_result($r)) {
+				if (DBM::is_result($r)) {
 					$parent = $r[0]["parent"];
 					$parent_uri = $r[0]["parent-uri"];
 				}
@@ -2732,7 +2732,7 @@ class Dfrn {
 				intval($importer["uid"]),
 				intval($importer["id"])
 			);
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			logger("Item with uri " . $uri . " from contact " . $importer["id"] . " for user " . $importer["uid"] . " wasn't found.", LOGGER_DEBUG);
 			return;
 		} else {
@@ -2762,7 +2762,7 @@ class Dfrn {
 						dbesc($xt->id),
 						intval($importer["importer_uid"])
 					);
-					if (Dbm::is_result($i)) {
+					if (DBM::is_result($i)) {
 
 						// For tags, the owner cannot remove the tag on the author's copy of the post.
 
@@ -2830,7 +2830,7 @@ class Dfrn {
 							dbesc($item["parent-uri"]),
 							intval($importer["uid"])
 					);
-					if (Dbm::is_result($r)) {
+					if (DBM::is_result($r)) {
 						q("UPDATE `item` SET `last-child` = 1 WHERE `id` = %d",
 							intval($r[0]["id"])
 						);
diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php
index 5960d32af8..3253812def 100644
--- a/src/Protocol/Diaspora.php
+++ b/src/Protocol/Diaspora.php
@@ -15,7 +15,7 @@ use Friendica\Core\System;
 use Friendica\Core\Config;
 use Friendica\Core\PConfig;
 use Friendica\Core\Worker;
-use Friendica\Database\Dbm;
+use Friendica\Database\DBM;
 use Friendica\Network\Probe;
 
 use dba;
@@ -459,7 +459,7 @@ class Diaspora {
 			dbesc($msg["author"])
 		);
 
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			foreach ($r as $rr) {
 				logger("delivering to: ".$rr["username"]);
 				self::dispatch($rr, $msg, $fields);
@@ -840,7 +840,7 @@ class Diaspora {
 			$r = q("SELECT `addr` FROM `gcontact` WHERE `id` = %d AND `addr` != ''",
 				intval($gcontact_id));
 
-			if (Dbm::is_result($r)) {
+			if (DBM::is_result($r)) {
 				return strtolower($r[0]["addr"]);
 			}
 		}
@@ -848,7 +848,7 @@ class Diaspora {
 		$r = q("SELECT `network`, `addr`, `self`, `url`, `nick` FROM `contact` WHERE `id` = %d",
 			intval($contact_id));
 
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			$contact = $r[0];
 
 			logger("contact 'self' = ".$contact['self']." 'url' = ".$contact['url'], LOGGER_DEBUG);
@@ -882,7 +882,7 @@ class Diaspora {
 			dbesc($fcontact_guid)
 		);
 
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			return $r[0]['url'];
 		}
 
@@ -905,7 +905,7 @@ class Diaspora {
 			dbesc($handle)
 		);
 
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			return $r[0];
 		} else {
 			/*
@@ -918,7 +918,7 @@ class Diaspora {
 				/// @TODO Contact retrieval should be encapsulated into an "entity" class like `Contact`
 				$r = q("SELECT * FROM `contact` WHERE `id` = %d LIMIT 1", intval($cid));
 
-				if (Dbm::is_result($r)) {
+				if (DBM::is_result($r)) {
 					return $r[0];
 				}
 			}
@@ -931,7 +931,7 @@ class Diaspora {
 			intval($uid),
 			dbesc($nurl_sql)
 		);
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			return $r[0];
 		}
 
@@ -1026,7 +1026,7 @@ class Diaspora {
 			dbesc($guid)
 		);
 
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			logger("message ".$guid." already exists for user ".$uid);
 			return $r[0]["id"];
 		}
@@ -1298,7 +1298,7 @@ class Diaspora {
 		$r = q("SELECT `url`, `nick`, `network` FROM `fcontact` WHERE `addr`='%s' LIMIT 1", dbesc($addr));
 
 		// Fallback
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			if ($parent_guid != '') {
 				return "https://".substr($addr,strpos($addr,"@") + 1)."/posts/".$parent_guid."#".$guid;
 			} else {
@@ -1309,7 +1309,7 @@ class Diaspora {
 		// Friendica contacts are often detected as Diaspora contacts in the "fcontact" table
 		// So we try another way as well.
 		$s = q("SELECT `network` FROM `gcontact` WHERE `nurl`='%s' LIMIT 1", dbesc(normalise_link($r[0]["url"])));
-		if (Dbm::is_result($s)) {
+		if (DBM::is_result($s)) {
 			$r[0]["network"] = $s[0]["network"];
 		}
 
@@ -1396,7 +1396,7 @@ class Diaspora {
 					$n, dbesc($f[0]),
 					intval($importer["uid"]));
 
-			if (Dbm::is_result($r)) {
+			if (DBM::is_result($r)) {
 				$x = q("UPDATE `item` SET `%s` = '%s' WHERE `%s` = '%s' AND `uid` = %d",
 						$n, dbesc($f[1]),
 						$n, dbesc($f[0]),
@@ -1450,7 +1450,7 @@ class Diaspora {
 	private static function get_uri_from_guid($author, $guid, $onlyfound = false) {
 
 		$r = q("SELECT `uri` FROM `item` WHERE `guid` = '%s' LIMIT 1", dbesc($guid));
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			return $r[0]["uri"];
 		} elseif (!$onlyfound) {
 			return $author.":".$guid;
@@ -1470,7 +1470,7 @@ class Diaspora {
 	private static function get_guid_from_uri($uri, $uid) {
 
 		$r = q("SELECT `guid` FROM `item` WHERE `uri` = '%s' AND `uid` = %d LIMIT 1", dbesc($uri), intval($uid));
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			return $r[0]["guid"];
 		} else {
 			return false;
@@ -1487,10 +1487,10 @@ class Diaspora {
 	private static function importer_for_guid($guid) {
 		$item = dba::fetch_first("SELECT `uid` FROM `item` WHERE `origin` AND `guid` = ? LIMIT 1", $guid);
 
-		if (Dbm::is_result($item)) {
+		if (DBM::is_result($item)) {
 			logger("Found user ".$item['uid']." as owner of item ".$guid, LOGGER_DEBUG);
 			$contact = dba::fetch_first("SELECT * FROM `contact` WHERE `self` AND `uid` = ?", $item['uid']);
-			if (Dbm::is_result($contact)) {
+			if (DBM::is_result($contact)) {
 				return $contact;
 			}
 		}
@@ -1664,7 +1664,7 @@ class Diaspora {
 			dbesc($msg_guid),
 			intval($importer["uid"])
 		);
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			logger("duplicate message already delivered.", LOGGER_DEBUG);
 			return false;
 		}
@@ -1977,7 +1977,7 @@ class Diaspora {
 			dbesc($guid),
 			intval($importer["uid"])
 		);
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			logger("duplicate message already delivered.", LOGGER_DEBUG);
 			return false;
 		}
@@ -2419,7 +2419,7 @@ class Diaspora {
 				FROM `item` WHERE `guid` = '%s' AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
 			dbesc($guid));
 
-		if (Dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			logger("reshared message ".$guid." already exists on system.");
 
 			// Maybe it is already a reshared item?
@@ -2441,7 +2441,7 @@ class Diaspora {
 			}
 		}
 
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			$server = "https://".substr($orig_author, strpos($orig_author, "@") + 1);
 			logger("1st try: reshared message ".$guid." will be fetched via SSL from the server ".$server);
 			$item_id = self::store_by_guid($guid, $server);
@@ -2458,7 +2458,7 @@ class Diaspora {
 					FROM `item` WHERE `id` = %d AND `visible` AND NOT `deleted` AND `body` != '' LIMIT 1",
 					intval($item_id));
 
-				if (Dbm::is_result($r)) {
+				if (DBM::is_result($r)) {
 					// If it is a reshared post from another network then reformat to avoid display problems with two share elements
 					if (self::is_reshare($r[0]["body"], false)) {
 						$r[0]["body"] = diaspora2bb(bb2diaspora($r[0]["body"]));
@@ -2589,7 +2589,7 @@ class Diaspora {
 			$condition = array("`guid` = ? AND `uid` = ? AND NOT `file` LIKE '%%[%%' AND NOT `deleted`", $target_guid, $importer['uid']);
 		}
 		$r = dba::select('item', $fields, $condition);
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			logger("Target guid ".$target_guid." was not found on this system for user ".$importer['uid'].".");
 			return false;
 		}
@@ -3231,7 +3231,7 @@ class Diaspora {
 	private static function build_event($event_id) {
 
 		$r = q("SELECT `guid`, `uid`, `start`, `finish`, `nofinish`, `summary`, `desc`, `location`, `adjust` FROM `event` WHERE `id` = %d", intval($event_id));
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			return array();
 		}
 
@@ -3240,14 +3240,14 @@ class Diaspora {
 		$eventdata = array();
 
 		$r = q("SELECT `timezone` FROM `user` WHERE `uid` = %d", intval($event['uid']));
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			return array();
 		}
 
 		$user = $r[0];
 
 		$r = q("SELECT `addr`, `nick` FROM `contact` WHERE `uid` = %d AND `self`", intval($event['uid']));
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			return array();
 		}
 
@@ -3424,7 +3424,7 @@ class Diaspora {
 
 		$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
 			dbesc($item["thr-parent"]));
-		if (!Dbm::is_result($p))
+		if (!DBM::is_result($p))
 			return false;
 
 		$parent = $p[0];
@@ -3456,7 +3456,7 @@ class Diaspora {
 
 		$p = q("SELECT `guid`, `uri`, `parent-uri` FROM `item` WHERE `uri` = '%s' LIMIT 1",
 			dbesc($item["thr-parent"]));
-		if (!Dbm::is_result($p))
+		if (!DBM::is_result($p))
 			return false;
 
 		$parent = $p[0];
@@ -3505,7 +3505,7 @@ class Diaspora {
 			intval($item["parent"])
 		);
 
-		if (!Dbm::is_result($p))
+		if (!DBM::is_result($p))
 			return false;
 
 		$parent = $p[0];
@@ -3727,7 +3727,7 @@ class Diaspora {
 			intval($item["uid"])
 		);
 
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			logger("conversation not found.");
 			return;
 		}
@@ -3886,14 +3886,14 @@ class Diaspora {
 		}
 
 		$r = q("SELECT `prvkey` FROM `user` WHERE `uid` = %d LIMIT 1", intval($contact['uid']));
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			return false;
 		}
 
 		$contact["uprvkey"] = $r[0]['prvkey'];
 
 		$r = q("SELECT * FROM `item` WHERE `id` = %d LIMIT 1", intval($post_id));
-		if (!Dbm::is_result($r)) {
+		if (!DBM::is_result($r)) {
 			return false;
 		}
 
diff --git a/src/Util/Lock.php b/src/Util/Lock.php
index 9bf67d7043..9d96962964 100644
--- a/src/Util/Lock.php
+++ b/src/Util/Lock.php
@@ -9,7 +9,7 @@ namespace Friendica\Util;
  */
 
 use Friendica\Core\Config;
-use Friendica\Database\Dbm;
+use Friendica\Database\DBM;
 use Memcache;
 use dba;
 
@@ -121,7 +121,7 @@ class Lock {
 			dba::lock('locks');
 			$lock = dba::select('locks', array('locked', 'pid'), array('name' => $fn_name), array('limit' => 1));
 
-			if (Dbm::is_result($lock)) {
+			if (DBM::is_result($lock)) {
 				if ($lock['locked']) {
 					// When the process id isn't used anymore, we can safely claim the lock for us.
 					if (!posix_kill($lock['pid'], 0)) {
@@ -136,7 +136,7 @@ class Lock {
 					dba::update('locks', array('locked' => true, 'pid' => getmypid()), array('name' => $fn_name));
 					$got_lock = true;
 				}
-			} elseif (!Dbm::is_result($lock)) {
+			} elseif (!DBM::is_result($lock)) {
 				dba::insert('locks', array('name' => $fn_name, 'locked' => true, 'pid' => getmypid()));
 				$got_lock = true;
 			}
diff --git a/update.php b/update.php
index e1c5a0de08..0b482535df 100644
--- a/update.php
+++ b/update.php
@@ -5,6 +5,7 @@ define('UPDATE_VERSION' , 1235);
 use Friendica\Core\Config;
 use Friendica\Core\PConfig;
 use Friendica\Core\Worker;
+use Friendica\Database\DBM;
 
 /**
  *
@@ -89,7 +90,7 @@ function update_1006() {
 	// create 's' keys for everybody that does not have one
 
 	$r = q("SELECT * FROM `user` WHERE `spubkey` = '' ");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			$sres=openssl_pkey_new(array('encrypt_key' => false ));
 			$sprvkey = '';
@@ -126,7 +127,7 @@ function update_1010() {
 function update_1011() {
 	q("ALTER TABLE `contact` ADD `nick` CHAR( 255 ) NOT NULL AFTER `name` ");
 	$r = q("SELECT * FROM `contact` WHERE 1");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 				q("UPDATE `contact` SET `nick` = '%s' WHERE `id` = %d",
 					dbesc(basename($rr['url'])),
@@ -149,7 +150,7 @@ function update_1014() {
 	require_once('include/Photo.php');
 	q("ALTER TABLE `contact` ADD `micro` TEXT NOT NULL AFTER `thumb` ");
 	$r = q("SELECT * FROM `photo` WHERE `scale` = 4");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			$ph = new Photo($rr['data']);
 			if ($ph->is_valid()) {
@@ -159,7 +160,7 @@ function update_1014() {
 		}
 	}
 	$r = q("SELECT * FROM `contact` WHERE 1");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			if(stristr($rr['thumb'],'avatar'))
 				q("UPDATE `contact` SET `micro` = '%s' WHERE `id` = %d",
@@ -312,7 +313,7 @@ function update_1030() {
 function update_1031() {
 	// Repair any bad links that slipped into the item table
 	$r = q("SELECT `id`, `object` FROM `item` WHERE `object` != '' ");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			if (strstr($rr['object'],'type="http')) {
 				q("UPDATE `item` SET `object` = '%s' WHERE `id` = %d",
@@ -361,7 +362,7 @@ function update_1035() {
 function update_1036() {
 
 	$r = dbq("SELECT * FROM `contact` WHERE `network` = 'dfrn' AND `photo` LIKE '%include/photo%' ");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s' WHERE `id` = %d",
 				dbesc(str_replace('include/photo','photo',$rr['photo'])),
@@ -599,7 +600,7 @@ function update_1073() {
 function update_1074() {
 	q("ALTER TABLE `user` ADD `hidewall` TINYINT( 1) NOT NULL DEFAULT '0' AFTER `blockwall` ");
 	$r = q("SELECT `uid` FROM `profile` WHERE `is-default` = 1 AND `hidewall` = 1");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach($r as $rr)
 			q("UPDATE `user` SET `hidewall` = 1 WHERE `uid` = %d",
 				intval($rr['uid'])
@@ -611,7 +612,7 @@ function update_1074() {
 function update_1075() {
 	q("ALTER TABLE `user` ADD `guid` CHAR( 16 ) NOT NULL AFTER `uid` ");
 	$r = q("SELECT `uid` FROM `user` WHERE 1");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			$found = true;
 			do {
@@ -690,10 +691,10 @@ function update_1082() {
 		ADD INDEX ( `guid` )  ");
 	// make certain the following code is only executed once
 	$r = q("select `id` from `photo` where `guid` != '' limit 1");
-	if (dbm::is_result($r))
+	if (DBM::is_result($r))
 		return;
 	$r = q("SELECT distinct(`resource-id`) FROM `photo` WHERE 1 group by `id`");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			$guid = get_guid();
 			q("update `photo` set `guid` = '%s' where `resource-id` = '%s'",
@@ -736,7 +737,7 @@ function update_1087() {
 	q("ALTER TABLE `item` ADD `commented` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' AFTER `edited` ");
 
 	$r = q("SELECT `id` FROM `item` WHERE `parent` = `id` ");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			$x = q("SELECT max(`created`) AS `cdate` FROM `item` WHERE `parent` = %d LIMIT 1",
 				intval($rr['id'])
@@ -859,7 +860,7 @@ function update_1100() {
 	require_once('include/text.php');
 
 	$r = q("select id, url from contact where url != '' and nurl = '' ");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			q("update contact set nurl = '%s' where id = %d",
 				dbesc(normalise_link($rr['url'])),
@@ -1035,7 +1036,7 @@ function update_1120() {
 	// might be missing on new installs. We'll check.
 
 	$r = q("describe item");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach($r as $rr)
 			if($rr['Field'] == 'spam')
 				return;
@@ -1173,7 +1174,7 @@ function update_1136() {
 	// order in reverse so that we save the newest entry
 
 	$r = q("select * from config where 1 order by id desc");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			$found = false;
 			foreach($arr as $x) {
@@ -1192,7 +1193,7 @@ function update_1136() {
 
 	$arr = array();
 	$r = q("select * from pconfig where 1 order by id desc");
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			$found = false;
 			foreach($arr as $x) {
@@ -1697,7 +1698,7 @@ function update_1190() {
 	);
 
 	// convert old forumlist addon entries in new config entries
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 		foreach ($r as $rr) {
 			$uid = $rr['uid'];
 			$family = $rr['cat'];
diff --git a/view/theme/frio/theme.php b/view/theme/frio/theme.php
index 60bf65042f..70cac3b3a8 100644
--- a/view/theme/frio/theme.php
+++ b/view/theme/frio/theme.php
@@ -11,6 +11,7 @@ use Friendica\App;
 use Friendica\Core\Config;
 use Friendica\Core\PConfig;
 use Friendica\Core\System;
+use Friendica\Database\DBM;
 
 $frio = "view/theme/frio";
 
@@ -225,7 +226,7 @@ function frio_remote_nav($a,&$nav) {
 		// user info
 		$r = q("SELECT `micro` FROM `contact` WHERE `uid` = %d AND `self`", intval($a->user['uid']));
 
-		$r[0]['photo'] = (dbm::is_result($r) ? $a->remove_baseurl($r[0]['micro']) : "images/person-48.jpg");
+		$r[0]['photo'] = (DBM::is_result($r) ? $a->remove_baseurl($r[0]['micro']) : "images/person-48.jpg");
 		$r[0]['name'] = $a->user['username'];
 
 	} elseif (!local_user() && remote_user()) {
@@ -241,9 +242,9 @@ function frio_remote_nav($a,&$nav) {
 		$r = false;
 	}
 
-	if (dbm::is_result($r)) {
+	if (DBM::is_result($r)) {
 			$nav['userinfo'] = array(
-				'icon' => (dbm::is_result($r) ? $r[0]['photo'] : "images/person-48.jpg"),
+				'icon' => (DBM::is_result($r) ? $r[0]['photo'] : "images/person-48.jpg"),
 				'name' => $r[0]['name'],
 			);
 		}
@@ -306,7 +307,7 @@ function frio_acl_lookup(App $a, &$results) {
 		$r = q("SELECT COUNT(*) AS `total` FROM `contact`
 			WHERE `uid` = %d AND NOT `self` AND NOT `pending` $sql_extra $sql_extra2 ",
 			intval($_SESSION['uid']));
-		if (dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			$total = $r[0]["total"];
 		}
 
@@ -318,7 +319,7 @@ function frio_acl_lookup(App $a, &$results) {
 
 		$contacts = array();
 
-		if (dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 			foreach ($r as $rr) {
 				$contacts[] = _contact_detail_for_template($rr);
 			}
diff --git a/view/theme/vier/theme.php b/view/theme/vier/theme.php
index 8aaa1ee0ac..e0c385e5e6 100644
--- a/view/theme/vier/theme.php
+++ b/view/theme/vier/theme.php
@@ -13,6 +13,7 @@ use Friendica\App;
 use Friendica\Core\Config;
 use Friendica\Core\PConfig;
 use Friendica\Core\System;
+use Friendica\Database\DBM;
 
 require_once "include/plugin.php";
 require_once "include/socgraph.php";
@@ -141,7 +142,7 @@ function vier_community_info() {
 		$r = suggestion_query(local_user(), 0, 9);
 
 		$tpl = get_markup_template('ch_directory_item.tpl');
-		if (dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 
 			$aside['$comunity_profiles_title'] = t('Community Profiles');
 			$aside['$comunity_profiles_items'] = array();
@@ -171,7 +172,7 @@ function vier_community_info() {
 				WHERE `is-default` = 1 $publish AND `user`.`blocked` = 0 $order LIMIT %d , %d ",
 				0, 9);
 
-		if (dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 
 			$aside['$lastusers_title'] = t('Last users');
 			$aside['$lastusers_items'] = array();
@@ -381,7 +382,7 @@ function vier_community_info() {
 
 		$tpl = get_markup_template('ch_connectors.tpl');
 
-		if (dbm::is_result($r)) {
+		if (DBM::is_result($r)) {
 
 			$con_services = array();
 			$con_services['title'] = array("", t('Connect Services'), "", "");

From 222696d6480c761a797912dd9602e2fdd9427341 Mon Sep 17 00:00:00 2001
From: Adam Magness 
Date: Wed, 8 Nov 2017 00:10:47 -0500
Subject: [PATCH 3/5] DFRN Update

missing use statement
---
 src/Protocol/DFRN.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php
index 17bef5d6d9..e858c778e9 100644
--- a/src/Protocol/DFRN.php
+++ b/src/Protocol/DFRN.php
@@ -15,6 +15,7 @@ use Friendica\Core\Worker;
 use Friendica\Database\DBM;
 
 use dba;
+use DOMDocument;
 
 require_once("include/Contact.php");
 require_once("include/ostatus.php");

From 4e7268950d47526c6bdca302c7481ab4c9e6cd7a Mon Sep 17 00:00:00 2001
From: Adam Magness 
Date: Wed, 8 Nov 2017 07:02:55 -0500
Subject: [PATCH 4/5] Use Statements

More use statements based on error logs
---
 src/Protocol/DFRN.php     | 1 +
 src/Protocol/Diaspora.php | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php
index e858c778e9..0efb07cbbc 100644
--- a/src/Protocol/DFRN.php
+++ b/src/Protocol/DFRN.php
@@ -16,6 +16,7 @@ use Friendica\Database\DBM;
 
 use dba;
 use DOMDocument;
+use DomXPath;
 
 require_once("include/Contact.php");
 require_once("include/ostatus.php");
diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php
index 3253812def..c790923f91 100644
--- a/src/Protocol/Diaspora.php
+++ b/src/Protocol/Diaspora.php
@@ -19,6 +19,7 @@ use Friendica\Database\DBM;
 use Friendica\Network\Probe;
 
 use dba;
+use SimpleXMLElement;
 
 require_once 'include/items.php';
 require_once 'include/bb2diaspora.php';

From a61ffa92000234f76d9bcbd9f75340ac2862d81b Mon Sep 17 00:00:00 2001
From: Adam Magness 
Date: Wed, 8 Nov 2017 07:48:31 -0500
Subject: [PATCH 5/5] Use more

More use statements based on error logs.
---
 src/Protocol/DFRN.php     | 4 ++--
 src/Protocol/Diaspora.php | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php
index 0efb07cbbc..bfb0d445c9 100644
--- a/src/Protocol/DFRN.php
+++ b/src/Protocol/DFRN.php
@@ -17,9 +17,10 @@ use Friendica\Database\DBM;
 use dba;
 use DOMDocument;
 use DomXPath;
+use ostatus;
+use xml;
 
 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");
@@ -31,7 +32,6 @@ require_once("include/text.php");
 require_once("include/oembed.php");
 require_once("include/html2bbcode.php");
 require_once("include/bbcode.php");
-require_once("include/xml.php");
 
 /**
  * @brief This class contain functions to create and send DFRN XML files
diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php
index c790923f91..c4ac5d924e 100644
--- a/src/Protocol/Diaspora.php
+++ b/src/Protocol/Diaspora.php
@@ -20,6 +20,7 @@ use Friendica\Network\Probe;
 
 use dba;
 use SimpleXMLElement;
+use xml;
 
 require_once 'include/items.php';
 require_once 'include/bb2diaspora.php';
@@ -27,7 +28,6 @@ require_once 'include/Contact.php';
 require_once 'include/Photo.php';
 require_once 'include/socgraph.php';
 require_once 'include/group.php';
-require_once 'include/xml.php';
 require_once 'include/datetime.php';
 require_once 'include/queue_fn.php';
 require_once 'include/cache.php';