Merge branch 'master' into develop

This commit is contained in:
Tobias Diekershoff 2017-06-06 12:20:55 +02:00
commit f3d8da7d33
80 changed files with 62265 additions and 39514 deletions

View file

@ -4,10 +4,12 @@
* @brief Methods for read and write notifications from/to database
* or for formatting notifications
*/
require_once 'include/html2plain.php';
require_once 'include/probe.php';
require_once 'include/datetime.php';
require_once 'include/bbcode.php';
require_once 'include/Contact.php';
/**
* @brief Methods for read and write notifications from/to database
@ -720,10 +722,12 @@ class NotificationsManager {
$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`,
$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`.`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`
@ -786,11 +790,7 @@ class NotificationsManager {
// Normal connection requests
} else {
// Probe the contact url to get missing data
$ret = probe_url($it["url"]);
if ($it['gnetwork'] == "")
$it['gnetwork'] = $ret["network"];
$it = $this->getMissingIntroData($it);
// Don't show these data until you are connected. Diaspora is doing the same.
if($it['gnetwork'] === NETWORK_DIASPORA) {
@ -815,7 +815,7 @@ class NotificationsManager {
'post_newfriend' => (intval(get_pconfig(local_user(),'system','post_newfriend')) ? '1' : 0),
'url' => $it['url'],
'zrl' => zrl($it['url']),
'addr' => $ret['addr'],
'addr' => $it['gaddr'],
'network' => $it['gnetwork'],
'knowyou' => $it['knowyou'],
'note' => $it['note'],
@ -827,4 +827,38 @@ class NotificationsManager {
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;
}
}

View file

@ -778,8 +778,7 @@ function guess_image_type($filename, $fromcurl=false) {
* @return array Returns array of the different avatar sizes
*/
function update_contact_avatar($avatar, $uid, $cid, $force = false) {
$r = q("SELECT `avatar`, `photo`, `thumb`, `micro` FROM `contact` WHERE `id` = %d LIMIT 1", intval($cid));
$r = q("SELECT `avatar`, `photo`, `thumb`, `micro`, `nurl` FROM `contact` WHERE `id` = %d LIMIT 1", intval($cid));
if (!dbm::is_result($r)) {
return false;
} else {
@ -793,6 +792,15 @@ function update_contact_avatar($avatar, $uid, $cid, $force = false) {
q("UPDATE `contact` SET `avatar` = '%s', `photo` = '%s', `thumb` = '%s', `micro` = '%s', `avatar-date` = '%s' WHERE `id` = %d",
dbesc($avatar), dbesc($photos[0]), dbesc($photos[1]), dbesc($photos[2]),
dbesc(datetime_convert()), intval($cid));
// 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)) {
update_contact_avatar($avatar, 0, $pcontact['id'], $force);
}
}
return $photos;
}
}
@ -847,9 +855,30 @@ function import_profile_photo($photo, $uid, $cid, $quit_on_error = false) {
$photo_failure = true;
}
$photo = App::get_baseurl() . '/photo/' . $hash . '-4.' . $img->getExt();
$thumb = App::get_baseurl() . '/photo/' . $hash . '-5.' . $img->getExt();
$micro = App::get_baseurl() . '/photo/' . $hash . '-6.' . $img->getExt();
$suffix = '?ts='.time();
$photo = App::get_baseurl() . '/photo/' . $hash . '-4.' . $img->getExt() . $suffix;
$thumb = App::get_baseurl() . '/photo/' . $hash . '-5.' . $img->getExt() . $suffix;
$micro = App::get_baseurl() . '/photo/' . $hash . '-6.' . $img->getExt() . $suffix;
// Remove the cached photo
$a = get_app();
$basepath = $a->get_basepath();
if (is_dir($basepath."/photo")) {
$filename = $basepath.'/photo/'.$hash.'-4.'.$img->getExt();
if (file_exists($filename)) {
unlink($filename);
}
$filename = $basepath.'/photo/'.$hash.'-5.'.$img->getExt();
if (file_exists($filename)) {
unlink($filename);
}
$filename = $basepath.'/photo/'.$hash.'-6.'.$img->getExt();
if (file_exists($filename)) {
unlink($filename);
}
}
} else {
$photo_failure = true;
}

View file

@ -456,10 +456,13 @@ $called_api = null;
* Contact url or False if contact id is unknown
*/
function api_unique_id_to_url($id) {
$r = q("SELECT `url` FROM `contact` WHERE `uid` = 0 AND `id` = %d LIMIT 1",
intval($id));
$r = dba::select('contact', array('url'), array('uid' => 0, 'id' => $id), array('limit' => 1));
return (dbm::is_result($r) && $r[0]["url"]);
if (dbm::is_result($r)) {
return $r["url"];
} else {
return false;
}
}
/**
@ -2286,6 +2289,11 @@ $called_api = null;
$statushtml = "<h4>" . bbcode($item['title']) . "</h4>\n" . $statushtml;
}
// feeds without body should contain the link
if (($item['network'] == NETWORK_FEED) && (strlen($item['body']) == 0)) {
$statushtml .= bbcode($item['plink']);
}
$entities = api_get_entitities($statustext, $body);
return array(
@ -3027,8 +3035,9 @@ $called_api = null;
api_best_nickname($r);
$recipient = api_get_user($a, $r[0]['nurl']);
} else
} else {
$recipient = api_get_user($a, $_POST['user_id']);
}
$replyto = '';
$sub = '';
@ -3740,8 +3749,7 @@ $called_api = null;
proc_run(PRIORITY_LOW, "include/directory.php", $url);
}
require_once 'include/profile_update.php';
profile_change();
proc_run(PRIORITY_LOW, 'include/profile_update.php', api_user());
// output for client
if ($data) {

View file

@ -122,6 +122,8 @@ function cron_poll_contacts($argc, $argv) {
$force = true;
}
$min_poll_interval = Config::get('system', 'min_poll_interval', 1);
$sql_extra = (($manual_id) ? " AND `id` = $manual_id " : "");
reload_plugins();
@ -195,7 +197,7 @@ function cron_poll_contacts($argc, $argv) {
$contact['priority'] = (($poll_interval !== false) ? intval($poll_interval) : 3);
}
if ($contact['priority'] AND !$force) {
if (($contact['priority'] >= 0) AND !$force) {
$update = false;
$t = $contact['last-update'];
@ -225,11 +227,16 @@ function cron_poll_contacts($argc, $argv) {
}
break;
case 1:
default:
if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + 1 hour")) {
$update = true;
}
break;
case 0:
default:
if (datetime_convert('UTC', 'UTC', 'now') > datetime_convert('UTC', 'UTC', $t . " + ".$min_poll_interval." minute")) {
$update = true;
}
break;
}
if (!$update) {
continue;

View file

@ -459,6 +459,27 @@ class dba {
return $sql;
}
/**
* @brief beautifies the query - useful for "SHOW PROCESSLIST"
*
* This is safe when we bind the parameters later.
* The parameter values aren't part of the SQL.
*
* @param string $sql An SQL string without the values
* @return string The input SQL string modified if necessary.
*/
public function clean_query($sql) {
$search = array("\t", "\n", "\r", " ");
$replace = array(' ', ' ', ' ', ' ');
do {
$oldsql = $sql;
$sql = str_replace($search, $replace, $sql);
} while ($oldsql != $sql);
return $sql;
}
/**
* @brief Replaces the ? placeholders with the parameters in the $args array
*
@ -521,6 +542,7 @@ class dba {
logger('Parameter mismatch. Query "'.$sql.'" - Parameters '.print_r($args, true), LOGGER_DEBUG);
}
$sql = self::$dbo->clean_query($sql);
$sql = self::$dbo->any_value_fallback($sql);
if (x($a->config,'system') && x($a->config['system'], 'db_callstack')) {
@ -708,6 +730,9 @@ class dba {
* @return int Number of rows
*/
static public function num_rows($stmt) {
if (!is_object($stmt)) {
return 0;
}
switch (self::$dbo->driver) {
case 'pdo':
return $stmt->rowCount();
@ -1200,6 +1225,7 @@ function q($sql) {
unset($args[0]);
if ($db && $db->connected) {
$sql = $db->clean_query($sql);
$sql = $db->any_value_fallback($sql);
$stmt = @vsprintf($sql,$args); // Disabled warnings
//logger("dba: q: $stmt", LOGGER_ALL);
@ -1237,6 +1263,7 @@ function qu($sql) {
unset($args[0]);
if ($db && $db->connected) {
$sql = $db->clean_query($sql);
$sql = $db->any_value_fallback($sql);
$stmt = @vsprintf($sql,$args); // Disabled warnings
if ($stmt === false)

View file

@ -19,7 +19,7 @@ function dbclean_run(&$argv, &$argc) {
if ($stage == 0) {
for ($i = 1; $i <= 7; $i++) {
if (!Config::get('system', 'finished-dbclean-'.$i)) {
if (!Config::get('system', 'finished-dbclean-'.$i, false)) {
proc_run(PRIORITY_LOW, 'include/dbclean.php', $i);
}
}
@ -40,131 +40,178 @@ function remove_orphans($stage = 0) {
$limit = 1000;
if ($stage == 1) {
logger("Deleting old global item entries from item table without user copy");
$r = dba::p("SELECT `id` FROM `item` WHERE `uid` = 0
AND NOT EXISTS (SELECT `guid` FROM `item` AS `i` WHERE `item`.`guid` = `i`.`guid` AND `i`.`uid` != 0)
AND `received` < UTC_TIMESTAMP() - INTERVAL 90 DAY LIMIT ".intval($limit));
$last_id = Config::get('system', 'dbclean-last-id-1', 0);
logger("Deleting old global item entries from item table without user copy. Last ID: ".$last_id);
$r = dba::p("SELECT `id` FROM `item` WHERE `uid` = 0 AND
NOT EXISTS (SELECT `guid` FROM `item` AS `i` WHERE `item`.`guid` = `i`.`guid` AND `i`.`uid` != 0) AND
`received` < UTC_TIMESTAMP() - INTERVAL 90 DAY AND `id` >= ?
ORDER BY `id` LIMIT ".intval($limit), $last_id);
$count = dba::num_rows($r);
if ($count > 0) {
logger("found global item orphans: ".$count);
while ($orphan = dba::fetch($r)) {
$last_id = $orphan["id"];
dba::delete('item', array('id' => $orphan["id"]));
}
} else {
logger("No global item orphans found");
}
dba::close($r);
logger("Done deleting ".$count." old global item entries from item table without user copy");
logger("Done deleting ".$count." old global item entries from item table without user copy. Last ID: ".$last_id);
Config::set('system', 'dbclean-last-id-1', $last_id);
// We will eventually set this value when we found a good way to delete these items in another way.
// if ($count < $limit) {
// Config::set('system', 'finished-dbclean-1', true);
// }
} elseif ($stage == 2) {
logger("Deleting items without parents");
$r = dba::p("SELECT `id` FROM `item` WHERE NOT EXISTS (SELECT `id` FROM `item` AS `i` WHERE `item`.`parent` = `i`.`id`) LIMIT ".intval($limit));
$last_id = Config::get('system', 'dbclean-last-id-2', 0);
logger("Deleting items without parents. Last ID: ".$last_id);
$r = dba::p("SELECT `id` FROM `item`
WHERE NOT EXISTS (SELECT `id` FROM `item` AS `i` WHERE `item`.`parent` = `i`.`id`)
AND `id` >= ? ORDER BY `id` LIMIT ".intval($limit), $last_id);
$count = dba::num_rows($r);
if ($count > 0) {
logger("found item orphans without parents: ".$count);
while ($orphan = dba::fetch($r)) {
$last_id = $orphan["id"];
dba::delete('item', array('id' => $orphan["id"]));
}
} else {
logger("No item orphans without parents found");
}
dba::close($r);
logger("Done deleting ".$count." items without parents");
logger("Done deleting ".$count." items without parents. Last ID: ".$last_id);
Config::set('system', 'dbclean-last-id-2', $last_id);
if ($count < $limit) {
Config::set('system', 'finished-dbclean-2', true);
}
} elseif ($stage == 3) {
logger("Deleting orphaned data from thread table");
$r = dba::p("SELECT `iid` FROM `thread` WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`parent` = `thread`.`iid`) LIMIT ".intval($limit));
$last_id = Config::get('system', 'dbclean-last-id-3', 0);
logger("Deleting orphaned data from thread table. Last ID: ".$last_id);
$r = dba::p("SELECT `iid` FROM `thread`
WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`parent` = `thread`.`iid`) AND `iid` >= ?
ORDER BY `iid` LIMIT ".intval($limit), $last_id);
$count = dba::num_rows($r);
if ($count > 0) {
logger("found thread orphans: ".$count);
while ($orphan = dba::fetch($r)) {
$last_id = $orphan["iid"];
dba::delete('thread', array('iid' => $orphan["iid"]));
}
} else {
logger("No thread orphans found");
}
dba::close($r);
logger("Done deleting ".$count." orphaned data from thread table");
logger("Done deleting ".$count." orphaned data from thread table. Last ID: ".$last_id);
Config::set('system', 'dbclean-last-id-3', $last_id);
if ($count < $limit) {
Config::set('system', 'finished-dbclean-3', true);
}
} elseif ($stage == 4) {
logger("Deleting orphaned data from notify table");
$r = dba::p("SELECT `iid` FROM `notify` WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `notify`.`iid`) LIMIT ".intval($limit));
$last_id = Config::get('system', 'dbclean-last-id-4', 0);
logger("Deleting orphaned data from notify table. Last ID: ".$last_id);
$r = dba::p("SELECT `iid`, `id` FROM `notify`
WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `notify`.`iid`) AND `id` >= ?
ORDER BY `id` LIMIT ".intval($limit), $last_id);
$count = dba::num_rows($r);
if ($count > 0) {
logger("found notify orphans: ".$count);
while ($orphan = dba::fetch($r)) {
$last_id = $orphan["id"];
dba::delete('notify', array('iid' => $orphan["iid"]));
}
} else {
logger("No notify orphans found");
}
dba::close($r);
logger("Done deleting ".$count." orphaned data from notify table");
logger("Done deleting ".$count." orphaned data from notify table. Last ID: ".$last_id);
Config::set('system', 'dbclean-last-id-4', $last_id);
if ($count < $limit) {
Config::set('system', 'finished-dbclean-4', true);
}
} elseif ($stage == 5) {
logger("Deleting orphaned data from notify-threads table");
$r = dba::p("SELECT `id` FROM `notify-threads` WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`parent` = `notify-threads`.`master-parent-item`) LIMIT ".intval($limit));
$last_id = Config::get('system', 'dbclean-last-id-5', 0);
logger("Deleting orphaned data from notify-threads table. Last ID: ".$last_id);
$r = dba::p("SELECT `id` FROM `notify-threads`
WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`parent` = `notify-threads`.`master-parent-item`) AND `id` >= ?
ORDER BY `id` LIMIT ".intval($limit), $last_id);
$count = dba::num_rows($r);
if ($count > 0) {
logger("found notify-threads orphans: ".$count);
while ($orphan = dba::fetch($r)) {
$last_id = $orphan["id"];
dba::delete('notify-threads', array('id' => $orphan["id"]));
}
} else {
logger("No notify-threads orphans found");
}
dba::close($r);
logger("Done deleting ".$count." orphaned data from notify-threads table");
logger("Done deleting ".$count." orphaned data from notify-threads table. Last ID: ".$last_id);
Config::set('system', 'dbclean-last-id-5', $last_id);
if ($count < $limit) {
Config::set('system', 'finished-dbclean-5', true);
}
} elseif ($stage == 6) {
logger("Deleting orphaned data from sign table");
$r = dba::p("SELECT `iid` FROM `sign` WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `sign`.`iid`) LIMIT ".intval($limit));
$last_id = Config::get('system', 'dbclean-last-id-6', 0);
logger("Deleting orphaned data from sign table. Last ID: ".$last_id);
$r = dba::p("SELECT `iid`, `id` FROM `sign`
WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `sign`.`iid`) AND `id` >= ?
ORDER BY `id` LIMIT ".intval($limit), $last_id);
$count = dba::num_rows($r);
if ($count > 0) {
logger("found sign orphans: ".$count);
while ($orphan = dba::fetch($r)) {
$last_id = $orphan["id"];
dba::delete('sign', array('iid' => $orphan["iid"]));
}
} else {
logger("No sign orphans found");
}
dba::close($r);
logger("Done deleting ".$count." orphaned data from sign table");
logger("Done deleting ".$count." orphaned data from sign table. Last ID: ".$last_id);
Config::set('system', 'dbclean-last-id-6', $last_id);
if ($count < $limit) {
Config::set('system', 'finished-dbclean-6', true);
}
} elseif ($stage == 7) {
logger("Deleting orphaned data from term table");
$r = dba::p("SELECT `oid` FROM `term` WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `term`.`oid`) LIMIT ".intval($limit));
$last_id = Config::get('system', 'dbclean-last-id-7', 0);
logger("Deleting orphaned data from term table. Last ID: ".$last_id);
$r = dba::p("SELECT `oid`, `tid` FROM `term`
WHERE NOT EXISTS (SELECT `id` FROM `item` WHERE `item`.`id` = `term`.`oid`) AND `tid` >= ?
ORDER BY `tid` LIMIT ".intval($limit), $last_id);
$count = dba::num_rows($r);
if ($count > 0) {
logger("found term orphans: ".$count);
while ($orphan = dba::fetch($r)) {
$last_id = $orphan["tid"];
dba::delete('term', array('oid' => $orphan["oid"]));
}
} else {
logger("No term orphans found");
}
dba::close($r);
logger("Done deleting ".$count." orphaned data from term table");
logger("Done deleting ".$count." orphaned data from term table. Last ID: ".$last_id);
Config::set('system', 'dbclean-last-id-7', $last_id);
if ($count < $limit) {
Config::set('system', 'finished-dbclean-7', true);

View file

@ -8,7 +8,11 @@ require_once "include/text.php";
define('NEW_UPDATE_ROUTINE_VERSION', 1170);
/**
const DB_UPDATE_NOT_CHECKED = 0; // Database check wasn't executed before
const DB_UPDATE_SUCCESSFUL = 1; // Database check was successful
const DB_UPDATE_FAILED = 2; // Database check failed
/*
* Converts all tables from MyISAM to InnoDB
*/
function convert_to_innodb() {
@ -480,6 +484,12 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
Config::set('system', 'maintenance_reason', '');
}
if ($errors) {
Config::set('system', 'dbupdate', DB_UPDATE_FAILED);
} else {
Config::set('system', 'dbupdate', DB_UPDATE_SUCCESSFUL);
}
return $errors;
}
@ -808,7 +818,7 @@ function db_definition() {
$database["conv"] = array(
"fields" => array(
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"guid" => array("type" => "varchar(64)", "not null" => "1", "default" => ""),
"guid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"recips" => array("type" => "text"),
"uid" => array("type" => "int(11)", "not null" => "1", "default" => "0", "relation" => array("user" => "uid")),
"creator" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -1205,7 +1215,7 @@ function db_definition() {
"fields" => array(
"id" => array("type" => "int(10) unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"),
"uid" => array("type" => "int(10) unsigned", "not null" => "1", "default" => "0", "relation" => array("user" => "uid")),
"guid" => array("type" => "varchar(64)", "not null" => "1", "default" => ""),
"guid" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"from-name" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"from-photo" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
"from-url" => array("type" => "varchar(255)", "not null" => "1", "default" => ""),
@ -1732,6 +1742,8 @@ function db_definition() {
),
"indexes" => array(
"PRIMARY" => array("id"),
"pid" => array("pid"),
"priority_created" => array("priority", "created"),
)
);

View file

@ -1395,7 +1395,7 @@ class Diaspora {
$message_id = self::message_exists($importer["uid"], $guid);
if ($message_id) {
return $message_id;
return true;
}
$parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact);
@ -1454,6 +1454,10 @@ class Diaspora {
$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);
}
@ -1472,7 +1476,7 @@ class Diaspora {
proc_run(PRIORITY_HIGH, "include/notifier.php", "comment-import", $message_id);
}
return $message_id;
return true;
}
/**
@ -1623,7 +1627,7 @@ class Diaspora {
}
if (!$conversation) {
logger("unable to create conversation.");
return;
return false;
}
foreach ($messages as $mesg)
@ -1701,7 +1705,7 @@ class Diaspora {
$message_id = self::message_exists($importer["uid"], $guid);
if ($message_id)
return $message_id;
return true;
$parent_item = self::parent_item($importer["uid"], $parent_guid, $author, $contact);
if (!$parent_item)
@ -1754,8 +1758,13 @@ class Diaspora {
$message_id = item_store($datarray);
if ($message_id)
if ($message_id <= 0) {
return false;
}
if ($message_id) {
logger("Stored like ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
}
// If we are the origin of the parent we store the original data and notify our followers
if ($message_id AND $parent_item["origin"]) {
@ -1771,7 +1780,7 @@ class Diaspora {
proc_run(PRIORITY_HIGH, "include/notifier.php", "comment-import", $message_id);
}
return $message_id;
return true;
}
/**
@ -2348,7 +2357,7 @@ class Diaspora {
$message_id = self::message_exists($importer["uid"], $guid);
if ($message_id) {
return $message_id;
return true;
}
$original_item = self::original_item($root_guid, $root_author, $author);
@ -2399,9 +2408,10 @@ class Diaspora {
if ($message_id) {
logger("Stored reshare ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
return true;
} else {
return false;
}
return $message_id;
}
/**
@ -2532,7 +2542,7 @@ class Diaspora {
$message_id = self::message_exists($importer["uid"], $guid);
if ($message_id) {
return $message_id;
return true;
}
$address = array();
@ -2616,9 +2626,10 @@ class Diaspora {
if ($message_id) {
logger("Stored item ".$datarray["guid"]." with message id ".$message_id, LOGGER_DEBUG);
return true;
} else {
return false;
}
return $message_id;
}
/* ************************************************************************************** *

View file

@ -152,7 +152,9 @@ function get_profiledata_by_nick($nickname, $uid = 0, $profile = 0) {
if ($profile) {
$profile_int = intval($profile);
$r = q("SELECT `contact`.`id` AS `contact_id`, `profile`.`uid` AS `profile_uid`, `profile`.*,
$r = q("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`.*,
`contact`.`avatar-date` AS picdate, `contact`.`addr`, `user`.*
FROM `profile`
INNER JOIN `contact` on `contact`.`uid` = `profile`.`uid` AND `contact`.`self`
@ -163,7 +165,9 @@ function get_profiledata_by_nick($nickname, $uid = 0, $profile = 0) {
);
}
if (!dbm::is_result($r)) {
$r = q("SELECT `contact`.`id` AS `contact_id`, `profile`.`uid` AS `profile_uid`, `profile`.*,
$r = q("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`.*,
`contact`.`avatar-date` AS picdate, `contact`.`addr`, `user`.*
FROM `profile`
INNER JOIN `contact` ON `contact`.`uid` = `profile`.`uid` AND `contact`.`self`
@ -365,9 +369,9 @@ function profile_sidebar($profile, $block = 0) {
'fullname' => $profile['name'],
'firstname' => $firstname,
'lastname' => $lastname,
'photo300' => App::get_baseurl() . '/photo/custom/300/' . $profile['uid'] . '.jpg',
'photo100' => App::get_baseurl() . '/photo/custom/100/' . $profile['uid'] . '.jpg',
'photo50' => App::get_baseurl() . '/photo/custom/50/' . $profile['uid'] . '.jpg',
'photo300' => $profile['contact_photo'],
'photo100' => $profile['contact_thumb'],
'photo50' => $profile['contact_micro'],
);
else
$diaspora = false;
@ -410,9 +414,9 @@ function profile_sidebar($profile, $block = 0) {
else
$p["address"] = bbcode($p["location"]);
if (isset($p["photo"]))
if (isset($p["photo"])) {
$p["photo"] = proxy_url($p["photo"], false, PROXY_SIZE_SMALL);
}
if ($a->theme['template_engine'] === 'internal')
$location = template_escape($location);

View file

@ -2076,7 +2076,7 @@ function item_expire($uid, $days, $network = "", $force = false) {
drop_item($item['id'], false);
}
proc_run(PRIORITY_HIGH, "include/notifier.php", "expire", $uid);
proc_run(PRIORITY_LOW, "include/notifier.php", "expire", $uid);
}
@ -2099,7 +2099,7 @@ function drop_items($items) {
// multiple threads may have been deleted, send an expire notification
if ($uid) {
proc_run(PRIORITY_HIGH, "include/notifier.php", "expire", $uid);
proc_run(PRIORITY_LOW, "include/notifier.php", "expire", $uid);
}
}
@ -2290,11 +2290,12 @@ function drop_item($id, $interactive = true) {
}
}
// send the notification upstream/downstream
// The priority depends on how the deletion is done.
$drop_id = intval($item['id']);
$priority = ($interactive ? PRIORITY_HIGH : PRIORITY_LOW);
// send the notification upstream/downstream as the case may be
proc_run(PRIORITY_HIGH, "include/notifier.php", "drop", $drop_id);
proc_run($priority, "include/notifier.php", "drop", $drop_id);
if (! $interactive) {
return $owner;

View file

@ -55,6 +55,17 @@ function notifier_run(&$argv, &$argc){
return;
}
// Inherit the priority
$queue = dba::select('workerqueue', array('priority'), array('pid' => getmypid()), array('limit' => 1));
if (dbm::is_result($queue)) {
$priority = (int)$queue['priority'];
logger('inherited priority: '.$priority);
} else {
// Normally this shouldn't happen.
$priority = PRIORITY_HIGH;
logger('no inherited priority! Something is wrong.');
}
logger('notifier: invoked: ' . print_r($argv,true), LOGGER_DEBUG);
$cmd = $argv[1];
@ -348,7 +359,7 @@ function notifier_run(&$argv, &$argc){
// a delivery fork. private groups (forum_mode == 2) do not uplink
if ((intval($parent['forum_mode']) == 1) && (! $top_level) && ($cmd !== 'uplink')) {
proc_run(PRIORITY_HIGH,'include/notifier.php','uplink',$item_id);
proc_run($priority, 'include/notifier.php', 'uplink', $item_id);
}
$conversants = array();
@ -487,7 +498,7 @@ function notifier_run(&$argv, &$argc){
}
logger("Deliver ".$target_item["guid"]." to ".$contact['url']." via network ".$contact['network'], LOGGER_DEBUG);
proc_run(PRIORITY_HIGH,'include/delivery.php', $cmd, $item_id, $contact['id']);
proc_run($priority, 'include/delivery.php', $cmd, $item_id, $contact['id']);
}
}
@ -552,7 +563,7 @@ function notifier_run(&$argv, &$argc){
if ((! $mail) && (! $fsuggest) && (! $followup)) {
logger('notifier: delivery agent: '.$rr['name'].' '.$rr['id'].' '.$rr['network'].' '.$target_item["guid"]);
proc_run(PRIORITY_HIGH,'include/delivery.php',$cmd,$item_id,$rr['id']);
proc_run($priority, 'include/delivery.php', $cmd, $item_id, $rr['id']);
}
}
}
@ -592,7 +603,7 @@ function notifier_run(&$argv, &$argc){
}
// Handling the pubsubhubbub requests
proc_run(PRIORITY_HIGH,'include/pubsubpublish.php');
proc_run(PRIORITY_HIGH, 'include/pubsubpublish.php');
}
logger('notifier: calling hooks', LOGGER_DEBUG);

View file

@ -647,6 +647,9 @@ class ostatus {
$item_id = self::completion($conversation, $importer["uid"], $item, $self);
if (!$item_id) {
// Store the conversation data. This is normally done in "item_store"
// but since something went wrong, we want to be sure to save the data.
store_conversation($item);
logger("Error storing item", LOGGER_DEBUG);
continue;
}
@ -840,6 +843,30 @@ class ostatus {
return $base_url."/conversation/".$conversation_id;
}
/**
* @brief Fetches a shared object from a given conversation object
*
* Sometimes GNU Social seems to fail when returning shared objects.
* Then they don't contains all needed data.
* We then try to find this object in the conversation
*
* @param string $id Message id
* @param object $conversation Conversation object
*
* @return object The shared object
*/
private function shared_object($id, $conversation) {
if (!is_array($conversation->items)) {
return false;
}
foreach ($conversation->items AS $single_conv) {
if ($single_conv->id == $id) {
return $single_conv;
}
}
return false;
}
/**
* @brief Fetches actor details of a given actor and user id
*
@ -910,8 +937,6 @@ class ostatus {
($item["verb"] == ACTIVITY_LIKE) OR ($conversation_url == "")) {
$item_stored = item_store($item, $all_threads);
return $item_stored;
} elseif (count($item) > 0) {
$item = store_conversation($item);
}
// Get the parent
@ -921,14 +946,6 @@ class ostatus {
STRAIGHT_JOIN `item` ON `item`.`parent` = `thritem`.`parent`
WHERE `term`.`uid` = %d AND `term`.`otype` = %d AND `term`.`type` = %d AND `term`.`url` = '%s'",
intval($uid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), dbesc($conversation_url));
/* 2016-10-23: The old query will be kept until we are sure that the query above is a good and fast replacement
$parents = q("SELECT `id`, `parent`, `uri`, `contact-id`, `type`, `verb`, `visible` FROM `item` WHERE `id` IN
(SELECT `parent` FROM `item` WHERE `id` IN
(SELECT `oid` FROM `term` WHERE `uid` = %d AND `otype` = %d AND `type` = %d AND `url` = '%s'))",
intval($uid), intval(TERM_OBJ_POST), intval(TERM_CONVERSATION), dbesc($conversation_url));
*/
if ($parents)
$parent = $parents[0];
elseif (count($item) > 0) {
@ -1205,42 +1222,52 @@ class ostatus {
if (is_array($single_conv->object))
$single_conv->object = $single_conv->object[0];
logger("Found reshared item ".$single_conv->object->id);
// $single_conv->object->context->conversation;
if (isset($single_conv->object->object->id))
$arr["uri"] = $single_conv->object->object->id;
else
$arr["uri"] = $single_conv->object->id;
if (isset($single_conv->object->object->url))
$plink = self::convert_href($single_conv->object->object->url);
else
$plink = self::convert_href($single_conv->object->url);
if (isset($single_conv->object->object->content))
$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->object->content));
else
$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->content));
$arr["plink"] = $plink;
$arr["created"] = $single_conv->object->published;
$arr["edited"] = $single_conv->object->published;
$arr["author-name"] = $single_conv->object->actor->displayName;
if ($arr["owner-name"] == '') {
$arr["author-name"] = $single_conv->object->actor->contact->displayName;
// Sometimes GNU Social doesn't returns a complete object
if (!isset($single_conv->object->actor->url)) {
$object = self::shared_object($single_conv->object->id, $conversation);
if (is_object($object)) {
$single_conv->object = $object;
}
}
$arr["author-link"] = $single_conv->object->actor->url;
$arr["author-avatar"] = Probe::fixAvatar($single_conv->object->actor->image->url, $arr["author-link"]);
$arr["app"] = $single_conv->object->provider->displayName."#";
//$arr["verb"] = $single_conv->object->verb;
if (isset($single_conv->object->actor->url)) {
logger("Found reshared item ".$single_conv->object->id);
$arr["location"] = $single_conv->object->location->displayName;
$arr["coord"] = trim($single_conv->object->location->lat." ".$single_conv->object->location->lon);
// $single_conv->object->context->conversation;
if (isset($single_conv->object->object->id)) {
$arr["uri"] = $single_conv->object->object->id;
} else {
$arr["uri"] = $single_conv->object->id;
}
if (isset($single_conv->object->object->url)) {
$plink = self::convert_href($single_conv->object->object->url);
} else {
$plink = self::convert_href($single_conv->object->url);
}
if (isset($single_conv->object->object->content)) {
$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->object->content));
} else {
$arr["body"] = add_page_info_to_body(html2bbcode($single_conv->object->content));
}
$arr["plink"] = $plink;
$arr["created"] = $single_conv->object->published;
$arr["edited"] = $single_conv->object->published;
$arr["author-name"] = $single_conv->object->actor->displayName;
if ($arr["owner-name"] == '') {
$arr["author-name"] = $single_conv->object->actor->contact->displayName;
}
$arr["author-link"] = $single_conv->object->actor->url;
$arr["author-avatar"] = Probe::fixAvatar($single_conv->object->actor->image->url, $arr["author-link"]);
$arr["app"] = $single_conv->object->provider->displayName."#";
//$arr["verb"] = $single_conv->object->verb;
$arr["location"] = $single_conv->object->location->displayName;
$arr["coord"] = trim($single_conv->object->location->lat." ".$single_conv->object->location->lon);
}
}
if ($arr["location"] == "")
@ -1251,26 +1278,19 @@ class ostatus {
// Copy fields from given item array
if (isset($item["uri"]) AND (($item["uri"] == $arr["uri"]) OR ($item["uri"] == $single_conv->id))) {
$copy_fields = array("owner-name", "owner-link", "owner-avatar", "author-name", "author-link", "author-avatar",
"gravity", "body", "object-type", "object", "verb", "created", "edited", "coord", "tag",
"title", "attach", "app", "type", "location", "contact-id", "uri");
foreach ($copy_fields AS $field)
if (isset($item[$field]))
$arr[$field] = $item[$field];
logger('Use stored item array for item with URI '.$item["uri"], LOGGER_DEBUG);
$newitem = item_store($item);
$item = array();
$item_stored = $newitem;
} else {
$newitem = item_store($arr);
}
$newitem = item_store($arr);
if (!$newitem) {
logger("Item wasn't stored ".print_r($arr, true), LOGGER_DEBUG);
continue;
}
if (isset($item["uri"]) AND ($item["uri"] == $arr["uri"])) {
$item = array();
$item_stored = $newitem;
}
logger('Stored new item '.$plink.' for parent '.$arr["parent-uri"].' under id '.$newitem, LOGGER_DEBUG);
// Add the conversation entry (but don't fetch the whole conversation)

View file

@ -73,24 +73,34 @@ function poller_run($argv, $argc){
while ($r = poller_worker_process()) {
if (!poller_claim_process($r[0])) {
continue;
}
// Check free memory
if ($a->min_memory_reached()) {
logger('Memory limit reached, quitting.', LOGGER_DEBUG);
return;
}
// Count active workers and compare them with a maximum value that depends on the load
if (poller_too_much_workers()) {
logger('Active worker limit reached, quitting.', LOGGER_DEBUG);
return;
}
if (!poller_execute($r[0])) {
logger('Process execution failed, quitting.', LOGGER_DEBUG);
return;
}
// Quit the poller once every hour
if (time() > ($starttime + 3600))
if (time() > ($starttime + 3600)) {
logger('Process lifetime reachted, quitting.', LOGGER_DEBUG);
return;
}
}
logger("Couldn't select a workerqueue entry, quitting.", LOGGER_DEBUG);
}
/**
@ -108,43 +118,22 @@ function poller_execute($queue) {
// Quit when in maintenance
if (Config::get('system', 'maintenance', true)) {
logger("Maintenance mode - quit process ".$mypid, LOGGER_DEBUG);
return false;
}
// Constantly check the number of parallel database processes
if ($a->max_processes_reached()) {
logger("Max processes reached for process ".$mypid, LOGGER_DEBUG);
return false;
}
// Constantly check the number of available database connections to let the frontend be accessible at any time
if (poller_max_connections_reached()) {
logger("Max connection reached for process ".$mypid, LOGGER_DEBUG);
return false;
}
if (!dba::update('workerqueue', array('executed' => datetime_convert(), 'pid' => $mypid),
array('id' => $queue["id"], 'pid' => 0))) {
logger("Couldn't update queue entry ".$queue["id"]." - skip this execution", LOGGER_DEBUG);
dba::commit();
return true;
}
// Assure that there are no tasks executed twice
$id = q("SELECT `pid`, `executed` FROM `workerqueue` WHERE `id` = %d", intval($queue["id"]));
if (!$id) {
logger("Queue item ".$queue["id"]." vanished - skip this execution", LOGGER_DEBUG);
dba::commit();
return true;
} elseif ((strtotime($id[0]["executed"]) <= 0) OR ($id[0]["pid"] == 0)) {
logger("Entry for queue item ".$queue["id"]." wasn't stored - skip this execution", LOGGER_DEBUG);
dba::commit();
return true;
} elseif ($id[0]["pid"] != $mypid) {
logger("Queue item ".$queue["id"]." is to be executed by process ".$id[0]["pid"]." and not by me (".$mypid.") - skip this execution", LOGGER_DEBUG);
dba::commit();
return true;
}
dba::commit();
$argv = json_decode($queue["parameter"]);
// Check for existance and validity of the include file
@ -163,7 +152,6 @@ function poller_execute($queue) {
if (function_exists($funcname)) {
poller_exec_function($queue, $funcname, $argv);
dba::delete('workerqueue', array('id' => $queue["id"]));
} else {
logger("Function ".$funcname." does not exist");
@ -432,6 +420,29 @@ function poller_too_much_workers() {
$slope = $maxworkers / pow($maxsysload, $exponent);
$queues = ceil($slope * pow(max(0, $maxsysload - $load), $exponent));
// Create a list of queue entries grouped by their priority
$listitem = array();
// Adding all processes with no workerqueue entry
$processes = dba::p("SELECT COUNT(*) AS `running` FROM `process` WHERE NOT EXISTS (SELECT id FROM `workerqueue` WHERE `workerqueue`.`pid` = `process`.`pid`)");
if ($process = dba::fetch($processes)) {
$listitem[0] = "0:".$process["running"];
}
dba::close($processes);
// Now adding all processes with workerqueue entries
$entries = dba::p("SELECT COUNT(*) AS `entries`, `priority` FROM `workerqueue` GROUP BY `priority`");
while ($entry = dba::fetch($entries)) {
$processes = dba::p("SELECT COUNT(*) AS `running` FROM `process` INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid` WHERE `priority` = ?", $entry["priority"]);
if ($process = dba::fetch($processes)) {
$listitem[$entry["priority"]] = $entry["priority"].":".$process["running"]."/".$entry["entries"];
}
dba::close($processes);
}
dba::close($entries);
$processlist = implode(', ', $listitem);
$s = q("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE `executed` <= '%s'", dbesc(NULL_DATE));
$entries = $s[0]["total"];
@ -449,27 +460,6 @@ function poller_too_much_workers() {
}
}
// Create a list of queue entries grouped by their priority
$running = array(PRIORITY_CRITICAL => 0,
PRIORITY_HIGH => 0,
PRIORITY_MEDIUM => 0,
PRIORITY_LOW => 0,
PRIORITY_NEGLIGIBLE => 0);
$r = q("SELECT COUNT(*) AS `running`, `priority` FROM `process` INNER JOIN `workerqueue` ON `workerqueue`.`pid` = `process`.`pid` GROUP BY `priority`");
if (dbm::is_result($r))
foreach ($r AS $process)
$running[$process["priority"]] = $process["running"];
$processlist = "";
$r = q("SELECT COUNT(*) AS `entries`, `priority` FROM `workerqueue` GROUP BY `priority`");
if (dbm::is_result($r))
foreach ($r as $entry) {
if ($processlist != "")
$processlist .= ", ";
$processlist .= $entry["priority"].":".$running[$entry["priority"]]."/".$entry["entries"];
}
logger("Load: ".$load."/".$maxsysload." - processes: ".$active."/".$entries." (".$processlist.") - maximum: ".$queues."/".$maxqueues, LOGGER_DEBUG);
// Are there fewer workers running as possible? Then fork a new one.
@ -552,12 +542,12 @@ function poller_passing_slow(&$highest_priority) {
*/
function poller_worker_process() {
dba::transaction();
// Check if we should pass some low priority process
$highest_priority = 0;
if (poller_passing_slow($highest_priority)) {
dba::e('LOCK TABLES `workerqueue` WRITE');
// Are there waiting processes with a higher priority than the currently highest?
$r = q("SELECT * FROM `workerqueue`
WHERE `executed` <= '%s' AND `priority` < %d
@ -573,15 +563,72 @@ function poller_worker_process() {
ORDER BY `priority`, `created` LIMIT 1",
dbesc(NULL_DATE),
intval($highest_priority));
if (dbm::is_result($r)) {
return $r;
}
} else {
dba::e('LOCK TABLES `workerqueue` WRITE');
}
// If there is no result (or we shouldn't pass lower processes) we check without priority limit
if (($highest_priority == 0) OR !dbm::is_result($r)) {
if (!dbm::is_result($r)) {
$r = q("SELECT * FROM `workerqueue` WHERE `executed` <= '%s' ORDER BY `priority`, `created` LIMIT 1", dbesc(NULL_DATE));
}
// We only unlock the tables here, when we got no data
if (!dbm::is_result($r)) {
dba::e('UNLOCK TABLES');
}
return $r;
}
/**
* @brief Assigns a workerqueue entry to the current process
*
* When we are sure that the table locks are working correctly, we can remove the checks from here
*
* @param array $queue Workerqueue entry
*
* @return boolean "true" if the claiming was successful
*/
function poller_claim_process($queue) {
$mypid = getmypid();
$success = dba::update('workerqueue', array('executed' => datetime_convert(), 'pid' => $mypid),
array('id' => $queue["id"], 'pid' => 0));
dba::e('UNLOCK TABLES');
if (!$success) {
logger("Couldn't update queue entry ".$queue["id"]." - skip this execution", LOGGER_DEBUG);
return false;
}
// Assure that there are no tasks executed twice
$id = q("SELECT `pid`, `executed` FROM `workerqueue` WHERE `id` = %d", intval($queue["id"]));
if (!$id) {
logger("Queue item ".$queue["id"]." vanished - skip this execution", LOGGER_DEBUG);
return false;
} elseif ((strtotime($id[0]["executed"]) <= 0) OR ($id[0]["pid"] == 0)) {
logger("Entry for queue item ".$queue["id"]." wasn't stored - skip this execution", LOGGER_DEBUG);
return false;
} elseif ($id[0]["pid"] != $mypid) {
logger("Queue item ".$queue["id"]." is to be executed by process ".$id[0]["pid"]." and not by me (".$mypid.") - skip this execution", LOGGER_DEBUG);
return false;
}
return true;
}
/**
* @brief Removes a workerqueue entry from the current process
*/
function poller_unclaim_process() {
$mypid = getmypid();
dba::update('workerqueue', array('executed' => NULL_DATE, 'pid' => 0), array('pid' => $mypid));
}
/**
* @brief Call the front end worker
*/
@ -678,6 +725,8 @@ function poller_run_cron() {
if (array_search(__file__,get_included_files())===0){
poller_run($_SERVER["argv"],$_SERVER["argc"]);
poller_unclaim_process();
get_app()->end_process();
killme();

View file

@ -1,6 +1,12 @@
<?php
require_once('include/diaspora.php');
function profile_change() {
Diaspora::send_profile(local_user());
function profile_update_run(&$argv, &$argc) {
if ($argc != 2) {
return;
}
$uid = intval($argv[1]);
Diaspora::send_profile($uid);
}