Merge branch 'develop' into improvement/move-app-to-src-2

This commit is contained in:
Hypolite Petovan 2017-05-07 12:58:11 -04:00 committed by GitHub
commit 86cae070f2
21 changed files with 5720 additions and 5348 deletions

View file

@ -40,7 +40,7 @@ define ( 'FRIENDICA_PLATFORM', 'Friendica');
define ( 'FRIENDICA_CODENAME', 'Asparagus'); define ( 'FRIENDICA_CODENAME', 'Asparagus');
define ( 'FRIENDICA_VERSION', '3.5.2-dev' ); define ( 'FRIENDICA_VERSION', '3.5.2-dev' );
define ( 'DFRN_PROTOCOL_VERSION', '2.23' ); define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
define ( 'DB_UPDATE_VERSION', 1222 ); define ( 'DB_UPDATE_VERSION', 1224 );
/** /**
* @brief Constant with a HTML line break. * @brief Constant with a HTML line break.

View file

@ -172,6 +172,11 @@ On error:
HTTP 400 BadRequest HTTP 400 BadRequest
* on friendica_verbose=true: different JSON returns {"result":"error","message":"xyz"} * on friendica_verbose=true: different JSON returns {"result":"error","message":"xyz"}
---
### externalprofile/show (*)
#### Parameters
* profileurl: profile url
--- ---
### favorites (*; AUTH) ### favorites (*; AUTH)
#### Parameters #### Parameters

View file

@ -175,6 +175,9 @@ class Probe {
return array(); return array();
$host = $parts["host"]; $host = $parts["host"];
if (isset($parts["port"])) {
$host .= ':'.$parts["port"];
}
$path_parts = explode("/", trim($parts["path"], "/")); $path_parts = explode("/", trim($parts["path"], "/"));
@ -335,8 +338,10 @@ class Probe {
if (isset($parts["scheme"]) AND isset($parts["host"]) AND isset($parts["path"])) { if (isset($parts["scheme"]) AND isset($parts["host"]) AND isset($parts["path"])) {
/// @todo: Ports?
$host = $parts["host"]; $host = $parts["host"];
if (isset($parts["port"])) {
$host .= ':'.$parts["port"];
}
if ($host == 'twitter.com') { if ($host == 'twitter.com') {
return array("network" => NETWORK_TWITTER); return array("network" => NETWORK_TWITTER);
@ -789,7 +794,7 @@ class Probe {
if (sizeof($avatar)) { if (sizeof($avatar)) {
ksort($avatar); ksort($avatar);
$data["photo"] = array_pop($avatar); $data["photo"] = self::fix_avatar(array_pop($avatar), $data["baseurl"]);
} }
if ($dfrn) { if ($dfrn) {
@ -960,7 +965,7 @@ class Probe {
$data["nick"] = $feed_data["header"]["author-nick"]; $data["nick"] = $feed_data["header"]["author-nick"];
} }
if ($feed_data["header"]["author-avatar"] != "") { if ($feed_data["header"]["author-avatar"] != "") {
$data["photo"] = ostatus::fix_avatar($feed_data["header"]["author-avatar"], $data["url"]); $data["photo"] = self::fix_avatar($feed_data["header"]["author-avatar"], $data["url"]);
} }
if ($feed_data["header"]["author-id"] != "") { if ($feed_data["header"]["author-id"] != "") {
$data["alias"] = $feed_data["header"]["author-id"]; $data["alias"] = $feed_data["header"]["author-id"];
@ -1219,4 +1224,41 @@ class Probe {
return $data; return $data;
} }
/**
* @brief Mix two paths together to possibly fix missing parts
*
* @param string $avatar Path to the avatar
* @param string $base Another path that is hopefully complete
*
* @return string fixed avatar path
*/
public static function fix_avatar($avatar, $base) {
$base_parts = parse_url($base);
// Remove all parts that could create a problem
unset($base_parts['path']);
unset($base_parts['query']);
unset($base_parts['fragment']);
$avatar_parts = parse_url($avatar);
// Now we mix them
$parts = array_merge($base_parts, $avatar_parts);
// And put them together again
$scheme = isset($parts['scheme']) ? $parts['scheme'] . '://' : '';
$host = isset($parts['host']) ? $parts['host'] : '';
$port = isset($parts['port']) ? ':' . $parts['port'] : '';
$path = isset($parts['path']) ? $parts['path'] : '';
$query = isset($parts['query']) ? '?' . $parts['query'] : '';
$fragment = isset($parts['fragment']) ? '#' . $parts['fragment'] : '';
$fixed = $scheme.$host.$port.$path.$query.$fragment;
logger('Base: '.$base.' - Avatar: '.$avatar.' - Fixed: '.$fixed, LOGGER_DATA);
return $fixed;
}
} }

View file

@ -545,7 +545,7 @@ function acl_lookup(App $a, $out_type = 'json') {
if ($type == '') { if ($type == '') {
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact` $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != '' WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
AND NOT (`network` IN ('%s', '%s')) AND NOT (`network` IN ('%s', '%s'))
$sql_extra2 $sql_extra2
@ -554,7 +554,7 @@ function acl_lookup(App $a, $out_type = 'json') {
dbesc(NETWORK_OSTATUS), dbesc(NETWORK_STATUSNET) dbesc(NETWORK_OSTATUS), dbesc(NETWORK_STATUSNET)
); );
} elseif ($type == 'c') { } elseif ($type == 'c') {
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact` $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != '' WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
AND NOT (`network` IN ('%s')) AND NOT (`network` IN ('%s'))
$sql_extra2 $sql_extra2
@ -564,7 +564,7 @@ function acl_lookup(App $a, $out_type = 'json') {
); );
} }
elseif ($type == 'm') { elseif ($type == 'm') {
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag` FROM `contact` $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr` FROM `contact`
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive`
AND `network` IN ('%s','%s','%s') AND `network` IN ('%s','%s','%s')
$sql_extra2 $sql_extra2
@ -575,7 +575,7 @@ function acl_lookup(App $a, $out_type = 'json') {
dbesc(NETWORK_DIASPORA) dbesc(NETWORK_DIASPORA)
); );
} elseif ($type == 'a') { } elseif ($type == 'a') {
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `forum`, `prv` FROM `contact` $r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
WHERE `uid` = %d AND `pending` = 0 WHERE `uid` = %d AND `pending` = 0
$sql_extra2 $sql_extra2
ORDER BY `name` ASC ", ORDER BY `name` ASC ",
@ -619,6 +619,7 @@ function acl_lookup(App $a, $out_type = 'json') {
'network' => $g['network'], 'network' => $g['network'],
'link' => $g['url'], 'link' => $g['url'],
'nick' => htmlentities(($g['attag']) ? $g['attag'] : $g['nick']), 'nick' => htmlentities(($g['attag']) ? $g['attag'] : $g['nick']),
'addr' => htmlentities(($g['addr']) ? $g['addr'] : $g['url']),
'forum' => ((x($g, 'forum') || x($g, 'prv')) ? 1 : 0), 'forum' => ((x($g, 'forum') || x($g, 'prv')) ? 1 : 0),
); );
} }
@ -663,6 +664,7 @@ function acl_lookup(App $a, $out_type = 'json') {
'network' => $contact['network'], 'network' => $contact['network'],
'link' => $contact['url'], 'link' => $contact['url'],
'nick' => htmlentities($contact['nick'] ? : $contact['addr']), 'nick' => htmlentities($contact['nick'] ? : $contact['addr']),
'addr' => htmlentities(($contact['addr']) ? $contact['addr'] : $contact['url']),
'forum' => $contact['forum'] 'forum' => $contact['forum']
); );
} }

View file

@ -526,6 +526,15 @@ $called_api = null;
} }
} }
if (is_null($user) && x($_GET, 'profileurl')) {
$user = dbesc(normalise_link($_GET['profileurl']));
$nick = $user;
$extra_query = "AND `contact`.`nurl` = '%s' ";
if (api_user() !== false) {
$extra_query .= "AND `contact`.`uid`=".intval(api_user());
}
}
if (is_null($user) AND ($a->argc > (count($called_api) - 1)) AND (count($called_api) > 0)) { if (is_null($user) AND ($a->argc > (count($called_api) - 1)) AND (count($called_api) > 0)) {
$argid = count($called_api); $argid = count($called_api);
list($user, $null) = explode(".", $a->argv[$argid]); list($user, $null) = explode(".", $a->argv[$argid]);
@ -1401,6 +1410,7 @@ $called_api = null;
/// @TODO move to top of file or somewhere better /// @TODO move to top of file or somewhere better
api_register_func('api/users/show','api_users_show'); api_register_func('api/users/show','api_users_show');
api_register_func('api/externalprofile/show','api_users_show');
function api_users_search($type) { function api_users_search($type) {

View file

@ -25,11 +25,20 @@ class dba {
private static $dbo; private static $dbo;
private static $relation = array(); private static $relation = array();
function __construct($server, $user, $pass, $db, $install = false) { function __construct($serveraddr, $user, $pass, $db, $install = false) {
$a = get_app(); $a = get_app();
$stamp1 = microtime(true); $stamp1 = microtime(true);
$serveraddr = trim($serveraddr);
$serverdata = explode(':', $serveraddr);
$server = $serverdata[0];
if (count($serverdata) > 1) {
$port = trim($serverdata[1]);
}
$server = trim($server); $server = trim($server);
$user = trim($user); $user = trim($user);
$pass = trim($pass); $pass = trim($pass);
@ -55,6 +64,11 @@ class dba {
if (class_exists('\PDO') && in_array('mysql', PDO::getAvailableDrivers())) { if (class_exists('\PDO') && in_array('mysql', PDO::getAvailableDrivers())) {
$this->driver = 'pdo'; $this->driver = 'pdo';
$connect = "mysql:host=".$server.";dbname=".$db; $connect = "mysql:host=".$server.";dbname=".$db;
if (isset($port)) {
$connect .= ";port=".$port;
}
if (isset($a->config["system"]["db_charset"])) { if (isset($a->config["system"]["db_charset"])) {
$connect .= ";charset=".$a->config["system"]["db_charset"]; $connect .= ";charset=".$a->config["system"]["db_charset"];
} }
@ -64,7 +78,7 @@ class dba {
} }
} elseif (class_exists('mysqli')) { } elseif (class_exists('mysqli')) {
$this->driver = 'mysqli'; $this->driver = 'mysqli';
$this->db = @new mysqli($server,$user,$pass,$db); $this->db = @new mysqli($server, $user, $pass, $db, $port);
if (!mysqli_connect_errno()) { if (!mysqli_connect_errno()) {
$this->connected = true; $this->connected = true;
@ -74,8 +88,8 @@ class dba {
} }
} elseif (function_exists('mysql_connect')) { } elseif (function_exists('mysql_connect')) {
$this->driver = 'mysql'; $this->driver = 'mysql';
$this->db = mysql_connect($server,$user,$pass); $this->db = mysql_connect($serveraddr, $user, $pass);
if ($this->db && mysql_select_db($db,$this->db)) { if ($this->db && mysql_select_db($db, $this->db)) {
$this->connected = true; $this->connected = true;
if (isset($a->config["system"]["db_charset"])) { if (isset($a->config["system"]["db_charset"])) {
@ -484,18 +498,28 @@ class dba {
unset($args[0]); unset($args[0]);
// When the second function parameter is an array then use this as the parameter array // When the second function parameter is an array then use this as the parameter array
if ((count($args) == 1) AND (is_array($args[1]))) { if ((count($args) > 0) AND (is_array($args[1]))) {
$params = $args[1]; $params = $args[1];
} else {
$params = $args;
}
// Renumber the array keys to be sure that they fit
$i = 0; $i = 0;
$args = array();
foreach ($params AS $param) { foreach ($params AS $param) {
$args[++$i] = $param; $args[++$i] = $param;
} }
}
if (!self::$dbo OR !self::$dbo->connected) { if (!self::$dbo OR !self::$dbo->connected) {
return false; return false;
} }
if (substr_count($sql, '?') != count($args)) {
// Question: Should we continue or stop the query here?
logger('Parameter mismatch. Query "'.$sql.'" - Parameters '.print_r($args, true), LOGGER_DEBUG);
}
$sql = self::$dbo->any_value_fallback($sql); $sql = self::$dbo->any_value_fallback($sql);
if (x($a->config,'system') && x($a->config['system'], 'db_callstack')) { if (x($a->config,'system') && x($a->config['system'], 'db_callstack')) {
@ -553,9 +577,10 @@ class dba {
$values[] = &$args[$param]; $values[] = &$args[$param];
} }
if (count($values) > 0) {
array_unshift($values, $params); array_unshift($values, $params);
call_user_func_array(array($stmt, 'bind_param'), $values); call_user_func_array(array($stmt, 'bind_param'), $values);
}
if (!$stmt->execute()) { if (!$stmt->execute()) {
self::$dbo->error = self::$dbo->db->error; self::$dbo->error = self::$dbo->db->error;
@ -861,7 +886,7 @@ class dba {
logger(dba::replace_parameters($sql, $command['param']), LOGGER_DATA); logger(dba::replace_parameters($sql, $command['param']), LOGGER_DATA);
if (!self::e($sql, $param)) { if (!self::e($sql, $command['param'])) {
self::p("ROLLBACK"); self::p("ROLLBACK");
return false; return false;
} }
@ -889,7 +914,7 @@ class dba {
logger(dba::replace_parameters($sql, $field_values), LOGGER_DATA); logger(dba::replace_parameters($sql, $field_values), LOGGER_DATA);
if (!self::e($sql, $param)) { if (!self::e($sql, $field_values)) {
self::p("ROLLBACK"); self::p("ROLLBACK");
return false; return false;
} }
@ -991,6 +1016,76 @@ class dba {
return self::e($sql, $params); return self::e($sql, $params);
} }
/**
* @brief Select rows from a table
*
* @param string $table Table name
* @param array $fields array of selected fields
* @param array $condition array of fields for condition
* @param array $params array of several parameters
*
* @return boolean|object If "limit" is equal "1" only a single row is returned, else a query object is returned
*
* Example:
* $table = "item";
* $fields = array("id", "uri", "uid", "network");
* $condition = array("uid" => 1, "network" => 'dspr');
* $params = array("order" => array("id", "received" => true), "limit" => 1);
*
* $data = dba::select($table, $fields, $condition, $params);
*/
static public function select($table, $fields = array(), $condition = array(), $params = array()) {
if ($table == '') {
return false;
}
if (count($fields) > 0) {
$select_fields = "`".implode("`, `", array_values($fields))."`";
} else {
$select_fields = "*";
}
if (count($condition) > 0) {
$condition_string = " WHERE `".implode("` = ? AND `", array_keys($condition))."` = ?";
} else {
$condition_string = "";
}
$param_string = '';
$single_row = false;
if (isset($params['order'])) {
$param_string .= " ORDER BY ";
foreach ($params['order'] AS $fields => $order) {
if (!is_int($fields)) {
$param_string .= "`".$fields."` ".($order ? "DESC" : "ASC").", ";
} else {
$param_string .= "`".$order."`, ";
}
}
$param_string = substr($param_string, 0, -2);
}
if (isset($params['limit'])) {
if (is_int($params['limit'])) {
$param_string .= " LIMIT ".$params['limit'];
$single_row =($params['limit'] == 1);
}
}
$sql = "SELECT ".$select_fields." FROM `".$table."`".$condition_string.$param_string;
$result = self::p($sql, $condition);
if (is_bool($result) OR !$single_row) {
return $result;
} else {
$row = self::fetch($result);
self::close($result);
return $row;
}
}
/** /**
* @brief Closes the current statement * @brief Closes the current statement
* *

View file

@ -399,6 +399,14 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
$sql3 .= ";"; $sql3 .= ";";
} }
$field_list = '';
if ($is_unique && $ignore == '') {
foreach ($structure['fields'] AS $fieldname => $parameters) {
$field_list .= 'ANY_VALUE(`' . $fieldname . '`),';
}
$field_list = rtrim($field_list, ',');
}
if ($verbose) { if ($verbose) {
// Ensure index conversion to unique removes duplicates // Ensure index conversion to unique removes duplicates
if ($is_unique) { if ($is_unique) {
@ -415,7 +423,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
if ($ignore != "") { if ($ignore != "") {
echo "SET session old_alter_table=0;\n"; echo "SET session old_alter_table=0;\n";
} else { } else {
echo "INSERT INTO `".$temp_name."` SELECT * FROM `".$name."`".$group_by.";\n"; echo "INSERT INTO `".$temp_name."` SELECT ".$field_list." FROM `".$name."`".$group_by.";\n";
echo "DROP TABLE `".$name."`;\n"; echo "DROP TABLE `".$name."`;\n";
echo "RENAME TABLE `".$temp_name."` TO `".$name."`;\n"; echo "RENAME TABLE `".$temp_name."` TO `".$name."`;\n";
} }
@ -446,7 +454,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
if ($ignore != "") { if ($ignore != "") {
$db->q("SET session old_alter_table=0;"); $db->q("SET session old_alter_table=0;");
} else { } else {
$r = $db->q("INSERT INTO `".$temp_name."` SELECT * FROM `".$name."`".$group_by.";"); $r = $db->q("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($db, $sql3); $errors .= print_update_error($db, $sql3);
return $errors; return $errors;
@ -879,7 +887,7 @@ function db_definition() {
"indexes" => array( "indexes" => array(
"PRIMARY" => array("id"), "PRIMARY" => array("id"),
"addr" => array("addr(32)"), "addr" => array("addr(32)"),
"url" => array("url"), "url" => array("UNIQUE", "url(190)"),
) )
); );
$database["ffinder"] = array( $database["ffinder"] = array(
@ -964,7 +972,7 @@ function db_definition() {
), ),
"indexes" => array( "indexes" => array(
"PRIMARY" => array("id"), "PRIMARY" => array("id"),
"nurl" => array("nurl(64)"), "nurl" => array("UNIQUE", "nurl(190)"),
"name" => array("name(64)"), "name" => array("name(64)"),
"nick" => array("nick(32)"), "nick" => array("nick(32)"),
"addr" => array("addr(64)"), "addr" => array("addr(64)"),
@ -1034,7 +1042,7 @@ function db_definition() {
), ),
"indexes" => array( "indexes" => array(
"PRIMARY" => array("id"), "PRIMARY" => array("id"),
"nurl" => array("nurl(32)"), "nurl" => array("UNIQUE", "nurl(190)"),
) )
); );
$database["hook"] = array( $database["hook"] = array(
@ -1219,6 +1227,7 @@ function db_definition() {
"convid" => array("convid"), "convid" => array("convid"),
"uri" => array("uri(64)"), "uri" => array("uri(64)"),
"parent-uri" => array("parent-uri(64)"), "parent-uri" => array("parent-uri(64)"),
"contactid" => array("contact-id"),
) )
); );
$database["mailacct"] = array( $database["mailacct"] = array(
@ -1356,6 +1365,7 @@ function db_definition() {
), ),
"indexes" => array( "indexes" => array(
"PRIMARY" => array("id"), "PRIMARY" => array("id"),
"contactid" => array("contact-id"),
"uid_contactid" => array("uid", "contact-id"), "uid_contactid" => array("uid", "contact-id"),
"uid_profile" => array("uid", "profile"), "uid_profile" => array("uid", "profile"),
"uid_album_scale_created" => array("uid", "album(32)", "scale", "created"), "uid_album_scale_created" => array("uid", "album(32)", "scale", "created"),

View file

@ -188,7 +188,80 @@ class Diaspora {
} }
/** /**
* @brief: Decodes incoming Diaspora message * @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.');
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 array $importer Array of the importer user
* @param string $xml urldecoded Diaspora salmon * @param string $xml urldecoded Diaspora salmon
@ -203,9 +276,10 @@ class Diaspora {
$public = false; $public = false;
$basedom = parse_xml_string($xml); $basedom = parse_xml_string($xml);
if (!is_object($basedom)) if (!is_object($basedom)) {
logger("XML is not parseable.");
return false; return false;
}
$children = $basedom->children('https://joindiaspora.com/protocol'); $children = $basedom->children('https://joindiaspora.com/protocol');
if ($children->header) { if ($children->header) {
@ -334,6 +408,24 @@ class Diaspora {
return false; 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) AND !$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;
}
}
// Now distribute it to the followers // Now distribute it to the followers
$r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN $r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN
(SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s') (SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s')
@ -345,13 +437,14 @@ class Diaspora {
if (dbm::is_result($r)) { if (dbm::is_result($r)) {
foreach ($r as $rr) { foreach ($r as $rr) {
logger("delivering to: ".$rr["username"]); logger("delivering to: ".$rr["username"]);
self::dispatch($rr,$msg); 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 { } else {
// Use a dummy importer to import the data for the public copy // Use a dummy importer to import the data for the public copy
// or for comments from unknown people
$importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE); $importer = array("uid" => 0, "page-flags" => PAGE_FREELOVE);
$message_id = self::dispatch($importer,$msg); $message_id = self::dispatch($importer, $msg, $fields);
} }
return $message_id; return $message_id;
@ -362,27 +455,27 @@ class Diaspora {
* *
* @param array $importer Array of the importer user * @param array $importer Array of the importer user
* @param array $msg The post that will be dispatched * @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 * @return int The message id of the generated message, "true" or "false" if there was an error
*/ */
public static function dispatch($importer, $msg) { public static function dispatch($importer, $msg, $fields = null) {
// The sender is the handle of the contact that sent the message. // 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") // This will often be different with relayed messages (for example "like" and "comment")
$sender = $msg["author"]; $sender = $msg["author"];
if (!self::valid_posting($msg, $fields)) { // 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"); logger("Invalid posting");
return false; return false;
} }
$fields = $postdata['fields'];
}
$type = $fields->getName(); $type = $fields->getName();
$social_relay = Config::get('system', 'relay_subscribe', false);
if (!$social_relay AND ($type == 'message')) {
logger("Unwanted message from ".$sender." send by ".$_SERVER["REMOTE_ADDR"]." with ".$_SERVER["HTTP_USER_AGENT"].": ".print_r($msg, true), LOGGER_DEBUG);
}
logger("Received message type ".$type." from ".$sender." for user ".$importer["uid"], LOGGER_DEBUG); logger("Received message type ".$type." from ".$sender." for user ".$importer["uid"], LOGGER_DEBUG);
switch ($type) { switch ($type) {
@ -440,11 +533,10 @@ class Diaspora {
* It also does the conversion between the old and the new diaspora format. * It also does the conversion between the old and the new diaspora format.
* *
* @param array $msg Array with the XML, the sender handle and the sender signature * @param array $msg Array with the XML, the sender handle and the sender signature
* @param object $fields SimpleXML object that contains the posting when it is valid
* *
* @return bool Is the posting valid? * @return bool|array If the posting is valid then an array with an SimpleXML object is returned
*/ */
private static function valid_posting($msg, &$fields) { private static function valid_posting($msg) {
$data = parse_xml_string($msg["message"], false); $data = parse_xml_string($msg["message"], false);
@ -485,34 +577,40 @@ class Diaspora {
foreach ($element->children() AS $fieldname => $entry) { foreach ($element->children() AS $fieldname => $entry) {
if ($oldXML) { if ($oldXML) {
// Translation for the old XML structure // Translation for the old XML structure
if ($fieldname == "diaspora_handle") if ($fieldname == "diaspora_handle") {
$fieldname = "author"; $fieldname = "author";
}
if ($fieldname == "participant_handles") if ($fieldname == "participant_handles") {
$fieldname = "participants"; $fieldname = "participants";
}
if (in_array($type, array("like", "participation"))) { if (in_array($type, array("like", "participation"))) {
if ($fieldname == "target_type") if ($fieldname == "target_type") {
$fieldname = "parent_type"; $fieldname = "parent_type";
} }
}
if ($fieldname == "sender_handle") if ($fieldname == "sender_handle") {
$fieldname = "author"; $fieldname = "author";
}
if ($fieldname == "recipient_handle") if ($fieldname == "recipient_handle") {
$fieldname = "recipient"; $fieldname = "recipient";
}
if ($fieldname == "root_diaspora_id") if ($fieldname == "root_diaspora_id") {
$fieldname = "root_author"; $fieldname = "root_author";
}
if ($type == "status_message") {
if ($fieldname == "raw_message") {
$fieldname = "text";
}
}
if ($type == "retraction") { if ($type == "retraction") {
if ($fieldname == "post_guid") if ($fieldname == "post_guid") {
$fieldname = "target_guid"; $fieldname = "target_guid";
}
if ($fieldname == "type") if ($fieldname == "type") {
$fieldname = "target_type"; $fieldname = "target_type";
} }
} }
}
if (($fieldname == "author_signature") AND ($entry != "")) if (($fieldname == "author_signature") AND ($entry != ""))
$author_signature = base64_decode($entry); $author_signature = base64_decode($entry);
@ -539,9 +637,9 @@ class Diaspora {
} }
// Only some message types have signatures. So we quit here for the other types. // Only some message types have signatures. So we quit here for the other types.
if (!in_array($type, array("comment", "message", "like"))) if (!in_array($type, array("comment", "like"))) {
return true; return array("fields" => $fields, "relayed" => false);
}
// No author_signature? This is a must, so we quit. // No author_signature? This is a must, so we quit.
if (!isset($author_signature)) { if (!isset($author_signature)) {
logger("No author signature for type ".$type." - Message: ".$msg["message"], LOGGER_DEBUG); logger("No author signature for type ".$type." - Message: ".$msg["message"], LOGGER_DEBUG);
@ -549,12 +647,16 @@ class Diaspora {
} }
if (isset($parent_author_signature)) { if (isset($parent_author_signature)) {
$relayed = true;
$key = self::key($msg["author"]); $key = self::key($msg["author"]);
if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256")) { 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); 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; return false;
} }
} else {
$relayed = false;
} }
$key = self::key($fields->author); $key = self::key($fields->author);
@ -562,8 +664,9 @@ class Diaspora {
if (!rsa_verify($signed_data, $author_signature, $key, "sha256")) { 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); 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; return false;
} else } else {
return true; return array("fields" => $fields, "relayed" => $relayed);
}
} }
/** /**
@ -592,7 +695,7 @@ class Diaspora {
* *
* @return array the queried data * @return array the queried data
*/ */
private static function person_by_handle($handle) { public static function person_by_handle($handle) {
$r = q("SELECT * FROM `fcontact` WHERE `network` = '%s' AND `addr` = '%s' LIMIT 1", $r = q("SELECT * FROM `fcontact` WHERE `network` = '%s' AND `addr` = '%s' LIMIT 1",
dbesc(NETWORK_DIASPORA), dbesc(NETWORK_DIASPORA),
@ -829,17 +932,20 @@ class Diaspora {
logger("defining user ".$contact["nick"]." as friend"); logger("defining user ".$contact["nick"]." as friend");
} }
if (($contact["blocked"]) || ($contact["readonly"]) || ($contact["archive"])) // We don't seem to like that person
if ($contact["blocked"] || $contact["readonly"] || $contact["archive"]) {
return false; return false;
if ($contact["rel"] == CONTACT_IS_SHARING || $contact["rel"] == CONTACT_IS_FRIEND) // We are following this person? Then it is okay
} elseif (($contact["rel"] == CONTACT_IS_SHARING) || ($contact["rel"] == CONTACT_IS_FRIEND)) {
return true; return true;
if ($contact["rel"] == CONTACT_IS_FOLLOWER) // Is it a post to a community? That's good
if (($importer["page-flags"] == PAGE_COMMUNITY) OR $is_comment) } elseif (($contact["rel"] == CONTACT_IS_FOLLOWER) && ($importer["page-flags"] == PAGE_COMMUNITY)) {
return true; return true;
}
// Messages for the global users are always accepted // Messages for the global users and comments are always accepted
if ($importer["uid"] == 0) if (($importer["uid"] == 0) || $is_comment) {
return true; return true;
}
return false; return false;
} }
@ -857,8 +963,13 @@ class Diaspora {
$contact = self::contact_by_handle($importer["uid"], $handle); $contact = self::contact_by_handle($importer["uid"], $handle);
if (!$contact) { if (!$contact) {
logger("A Contact for handle ".$handle." and user ".$importer["uid"]." was not found"); 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; return false;
} }
}
if (!self::post_allow($importer, $contact, $is_comment)) { if (!self::post_allow($importer, $contact, $is_comment)) {
logger("The handle: ".$handle." is not allowed to post to user ".$importer["uid"]); logger("The handle: ".$handle." is not allowed to post to user ".$importer["uid"]);
@ -1112,9 +1223,9 @@ class Diaspora {
$cid = $r[0]["id"]; $cid = $r[0]["id"];
$network = $r[0]["network"]; $network = $r[0]["network"];
// We are receiving content from a user that is about to be terminated // 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. // This means the user is vital, so we remove a possible termination date.
unmark_for_death($contact); unmark_for_death($r[0]);
} else { } else {
$cid = $contact["id"]; $cid = $contact["id"];
$network = NETWORK_DIASPORA; $network = NETWORK_DIASPORA;
@ -1229,24 +1340,23 @@ class Diaspora {
} }
/** /**
* @brief Find the best importer for a comment * @brief Find the best importer for a comment, like, ...
* *
* @param array $importer Array of the importer user
* @param string $guid The guid of the item * @param string $guid The guid of the item
* *
* @return array the importer that fits the best * @return array|boolean the origin owner of that post - or false
*/ */
private static function importer_for_comment($importer, $guid) { private static function importer_for_guid($guid) {
$item = dba::fetch_first("SELECT `uid` FROM `item` WHERE `origin` AND `guid` = ? LIMIT 1", $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); 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']); $contact = dba::fetch_first("SELECT * FROM `contact` WHERE `self` AND `uid` = ?", $item['uid']);
if (dbm::is_result($contact)) { if (dbm::is_result($contact)) {
$importer = $contact; return $contact;
} }
} }
return $importer; return false;
} }
/** /**
@ -1260,10 +1370,10 @@ class Diaspora {
* @return int The message id of the generated comment or "false" if there was an error * @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) { private static function receive_comment($importer, $sender, $data, $xml) {
$author = notags(unxmlify($data->author));
$guid = notags(unxmlify($data->guid)); $guid = notags(unxmlify($data->guid));
$parent_guid = notags(unxmlify($data->parent_guid)); $parent_guid = notags(unxmlify($data->parent_guid));
$text = unxmlify($data->text); $text = unxmlify($data->text);
$author = notags(unxmlify($data->author));
if (isset($data->created_at)) { if (isset($data->created_at)) {
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
@ -1278,11 +1388,6 @@ class Diaspora {
$thr_uri = ""; $thr_uri = "";
} }
// Find the best importer when there was no importer found
if ($importer["uid"] == 0) {
$importer = self::importer_for_comment($importer, $parent_guid);
}
$contact = self::allowed_contact_by_handle($importer, $sender, true); $contact = self::allowed_contact_by_handle($importer, $sender, true);
if (!$contact) { if (!$contact) {
return false; return false;
@ -1383,16 +1488,9 @@ class Diaspora {
* @return bool "true" if it was successful * @return bool "true" if it was successful
*/ */
private static function receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation) { private static function receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation) {
$author = notags(unxmlify($data->author));
$guid = notags(unxmlify($data->guid)); $guid = notags(unxmlify($data->guid));
$subject = notags(unxmlify($data->subject)); $subject = notags(unxmlify($data->subject));
$author = notags(unxmlify($data->author));
$msg_guid = notags(unxmlify($mesg->guid));
$msg_parent_guid = notags(unxmlify($mesg->parent_guid));
$msg_parent_author_signature = notags(unxmlify($mesg->parent_author_signature));
$msg_author_signature = notags(unxmlify($mesg->author_signature));
$msg_text = unxmlify($mesg->text);
$msg_created_at = datetime_convert("UTC", "UTC", notags(unxmlify($mesg->created_at)));
// "diaspora_handle" is the element name from the old version // "diaspora_handle" is the element name from the old version
// "author" is the element name from the new version // "author" is the element name from the new version
@ -1404,7 +1502,10 @@ class Diaspora {
return false; return false;
} }
$msg_guid = notags(unxmlify($mesg->guid));
$msg_conversation_guid = notags(unxmlify($mesg->conversation_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) { if ($msg_conversation_guid != $guid) {
logger("message conversation guid does not belong to the current conversation."); logger("message conversation guid does not belong to the current conversation.");
@ -1414,42 +1515,8 @@ class Diaspora {
$body = diaspora2bb($msg_text); $body = diaspora2bb($msg_text);
$message_uri = $msg_author.":".$msg_guid; $message_uri = $msg_author.":".$msg_guid;
$author_signed_data = $msg_guid.";".$msg_parent_guid.";".$msg_text.";".unxmlify($mesg->created_at).";".$msg_author.";".$msg_conversation_guid;
$author_signature = base64_decode($msg_author_signature);
if (strcasecmp($msg_author,$msg["author"]) == 0) {
$person = $contact;
$key = $msg["key"];
} else {
$person = self::person_by_handle($msg_author); $person = self::person_by_handle($msg_author);
if (is_array($person) && x($person, "pubkey")) {
$key = $person["pubkey"];
} else {
logger("unable to find author details");
return false;
}
}
if (!rsa_verify($author_signed_data, $author_signature, $key, "sha256")) {
logger("verification failed.");
return false;
}
if ($msg_parent_author_signature) {
$owner_signed_data = $msg_guid.";".$msg_parent_guid.";".$msg_text.";".unxmlify($mesg->created_at).";".$msg_author.";".$msg_conversation_guid;
$parent_author_signature = base64_decode($msg_parent_author_signature);
$key = $msg["key"];
if (!rsa_verify($owner_signed_data, $parent_author_signature, $key, "sha256")) {
logger("owner verification failed.");
return false;
}
}
$r = q("SELECT `id` FROM `mail` WHERE `uri` = '%s' LIMIT 1", $r = q("SELECT `id` FROM `mail` WHERE `uri` = '%s' LIMIT 1",
dbesc($message_uri) dbesc($message_uri)
); );
@ -1508,10 +1575,10 @@ class Diaspora {
* @return bool Success * @return bool Success
*/ */
private static function receive_conversation($importer, $msg, $data) { private static function receive_conversation($importer, $msg, $data) {
$author = notags(unxmlify($data->author));
$guid = notags(unxmlify($data->guid)); $guid = notags(unxmlify($data->guid));
$subject = notags(unxmlify($data->subject)); $subject = notags(unxmlify($data->subject));
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
$author = notags(unxmlify($data->author));
$participants = notags(unxmlify($data->participants)); $participants = notags(unxmlify($data->participants));
$messages = $data->message; $messages = $data->message;
@ -1616,11 +1683,11 @@ class Diaspora {
* @return int The message id of the generated like or "false" if there was an error * @return int The message id of the generated like or "false" if there was an error
*/ */
private static function receive_like($importer, $sender, $data) { private static function receive_like($importer, $sender, $data) {
$positive = notags(unxmlify($data->positive));
$guid = notags(unxmlify($data->guid));
$parent_type = notags(unxmlify($data->parent_type));
$parent_guid = notags(unxmlify($data->parent_guid));
$author = notags(unxmlify($data->author)); $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 // 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. // But maybe this will be supported in the future, so we will accept it.
@ -1715,12 +1782,11 @@ class Diaspora {
* @return bool Success? * @return bool Success?
*/ */
private static function receive_message($importer, $data) { private static function receive_message($importer, $data) {
$author = notags(unxmlify($data->author));
$guid = notags(unxmlify($data->guid)); $guid = notags(unxmlify($data->guid));
$parent_guid = notags(unxmlify($data->parent_guid)); $conversation_guid = notags(unxmlify($data->conversation_guid));
$text = unxmlify($data->text); $text = unxmlify($data->text);
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); $created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
$author = notags(unxmlify($data->author));
$conversation_guid = notags(unxmlify($data->conversation_guid));
$contact = self::allowed_contact_by_handle($importer, $author, true); $contact = self::allowed_contact_by_handle($importer, $author, true);
if (!$contact) { if (!$contact) {
@ -1775,7 +1841,7 @@ class Diaspora {
0, 0,
1, 1,
dbesc($message_uri), dbesc($message_uri),
dbesc($author.":".$parent_guid), dbesc($author.":".$conversation["guid"]),
dbesc($created_at) dbesc($created_at)
); );
@ -1844,9 +1910,9 @@ class Diaspora {
$name = unxmlify($data->first_name).((strlen($data->last_name)) ? " ".unxmlify($data->last_name) : ""); $name = unxmlify($data->first_name).((strlen($data->last_name)) ? " ".unxmlify($data->last_name) : "");
$image_url = unxmlify($data->image_url); $image_url = unxmlify($data->image_url);
$birthday = unxmlify($data->birthday); $birthday = unxmlify($data->birthday);
$location = diaspora2bb(unxmlify($data->location));
$about = diaspora2bb(unxmlify($data->bio));
$gender = unxmlify($data->gender); $gender = unxmlify($data->gender);
$about = diaspora2bb(unxmlify($data->bio));
$location = diaspora2bb(unxmlify($data->location));
$searchable = (unxmlify($data->searchable) == "true"); $searchable = (unxmlify($data->searchable) == "true");
$nsfw = (unxmlify($data->nsfw) == "true"); $nsfw = (unxmlify($data->nsfw) == "true");
$tags = unxmlify($data->tag_string); $tags = unxmlify($data->tag_string);
@ -2266,12 +2332,13 @@ class Diaspora {
* @return int the message id * @return int the message id
*/ */
private static function receive_reshare($importer, $data, $xml) { 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_author = notags(unxmlify($data->root_author));
$root_guid = notags(unxmlify($data->root_guid)); $root_guid = notags(unxmlify($data->root_guid));
$guid = notags(unxmlify($data->guid)); /// @todo handle unprocessed property "provider_display_name"
$author = notags(unxmlify($data->author));
$public = notags(unxmlify($data->public)); $public = notags(unxmlify($data->public));
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
$contact = self::allowed_contact_by_handle($importer, $author, false); $contact = self::allowed_contact_by_handle($importer, $author, false);
if (!$contact) { if (!$contact) {
@ -2346,9 +2413,9 @@ class Diaspora {
* @return bool success * @return bool success
*/ */
private static function item_retraction($importer, $contact, $data) { private static function item_retraction($importer, $contact, $data) {
$target_type = notags(unxmlify($data->target_type));
$target_guid = notags(unxmlify($data->target_guid));
$author = notags(unxmlify($data->author)); $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); $person = self::person_by_handle($author);
if (!is_array($person)) { if (!is_array($person)) {
@ -2356,11 +2423,16 @@ class Diaspora {
return false; return false;
} }
if (!isset($contact["url"])) {
$contact["url"] = $person["url"];
}
$r = q("SELECT `id`, `parent`, `parent-uri`, `author-link` FROM `item` WHERE `guid` = '%s' AND `uid` = %d AND NOT `file` LIKE '%%[%%' LIMIT 1", $r = q("SELECT `id`, `parent`, `parent-uri`, `author-link` FROM `item` WHERE `guid` = '%s' AND `uid` = %d AND NOT `file` LIKE '%%[%%' LIMIT 1",
dbesc($target_guid), dbesc($target_guid),
intval($importer["uid"]) intval($importer["uid"])
); );
if (!$r) { if (!$r) {
logger("Target guid ".$target_guid." was not found for user ".$importer["uid"]);
return false; return false;
} }
@ -2406,7 +2478,7 @@ class Diaspora {
$target_type = notags(unxmlify($data->target_type)); $target_type = notags(unxmlify($data->target_type));
$contact = self::contact_by_handle($importer["uid"], $sender); $contact = self::contact_by_handle($importer["uid"], $sender);
if (!$contact) { if (!$contact AND (in_array($target_type, array("Contact", "Person")))) {
logger("cannot find contact for sender: ".$sender." and user ".$importer["uid"]); logger("cannot find contact for sender: ".$sender." and user ".$importer["uid"]);
return false; return false;
} }
@ -2419,7 +2491,7 @@ class Diaspora {
case "Post": // "Post" will be supported in a future version case "Post": // "Post" will be supported in a future version
case "Reshare": case "Reshare":
case "StatusMessage": case "StatusMessage":
return self::item_retraction($importer, $contact, $data);; return self::item_retraction($importer, $contact, $data);
case "Contact": case "Contact":
case "Person": case "Person":
@ -2445,19 +2517,13 @@ class Diaspora {
* @return int The message id of the newly created item * @return int The message id of the newly created item
*/ */
private static function receive_status_message($importer, $data, $xml) { private static function receive_status_message($importer, $data, $xml) {
$raw_message = unxmlify($data->raw_message);
$guid = notags(unxmlify($data->guid));
$author = notags(unxmlify($data->author)); $author = notags(unxmlify($data->author));
$public = notags(unxmlify($data->public)); $guid = notags(unxmlify($data->guid));
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at))); $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)); $provider_display_name = notags(unxmlify($data->provider_display_name));
/// @todo enable support for polls
//if ($data->poll) {
// foreach ($data->poll AS $poll)
// print_r($poll);
// die("poll!\n");
//}
$contact = self::allowed_contact_by_handle($importer, $author, false); $contact = self::allowed_contact_by_handle($importer, $author, false);
if (!$contact) { if (!$contact) {
return false; return false;
@ -2475,7 +2541,7 @@ class Diaspora {
} }
} }
$body = diaspora2bb($raw_message); $body = diaspora2bb($text);
$datarray = array(); $datarray = array();
@ -2496,6 +2562,15 @@ class Diaspora {
} }
} }
/// @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["uid"] = $importer["uid"];
$datarray["contact-id"] = $contact["id"]; $datarray["contact-id"] = $contact["id"];
$datarray["network"] = NETWORK_DIASPORA; $datarray["network"] = NETWORK_DIASPORA;

View file

@ -4,6 +4,7 @@
*/ */
use Friendica\App; use Friendica\App;
use Friendica\Core\Config;
require_once("include/Contact.php"); require_once("include/Contact.php");
require_once("include/threads.php"); require_once("include/threads.php");
@ -29,42 +30,6 @@ class ostatus {
const OSTATUS_DEFAULT_POLL_TIMEFRAME = 1440; // given in minutes const OSTATUS_DEFAULT_POLL_TIMEFRAME = 1440; // given in minutes
const OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS = 14400; // given in minutes const OSTATUS_DEFAULT_POLL_TIMEFRAME_MENTIONS = 14400; // given in minutes
/**
* @brief Mix two paths together to possibly fix missing parts
*
* @param string $avatar Path to the avatar
* @param string $base Another path that is hopefully complete
*
* @return string fixed avatar path
*/
public static function fix_avatar($avatar, $base) {
$base_parts = parse_url($base);
// Remove all parts that could create a problem
unset($base_parts['path']);
unset($base_parts['query']);
unset($base_parts['fragment']);
$avatar_parts = parse_url($avatar);
// Now we mix them
$parts = array_merge($base_parts, $avatar_parts);
// And put them together again
$scheme = isset($parts['scheme']) ? $parts['scheme'] . '://' : '';
$host = isset($parts['host']) ? $parts['host'] : '';
$port = isset($parts['port']) ? ':' . $parts['port'] : '';
$path = isset($parts['path']) ? $parts['path'] : '';
$query = isset($parts['query']) ? '?' . $parts['query'] : '';
$fragment = isset($parts['fragment']) ? '#' . $parts['fragment'] : '';
$fixed = $scheme.$host.$port.$path.$query.$fragment;
logger('Base: '.$base.' - Avatar: '.$avatar.' - Fixed: '.$fixed, LOGGER_DATA);
return $fixed;
}
/** /**
* @brief Fetches author data * @brief Fetches author data
* *
@ -81,23 +46,43 @@ class ostatus {
$author = array(); $author = array();
$author["author-link"] = $xpath->evaluate('atom:author/atom:uri/text()', $context)->item(0)->nodeValue; $author["author-link"] = $xpath->evaluate('atom:author/atom:uri/text()', $context)->item(0)->nodeValue;
$author["author-name"] = $xpath->evaluate('atom:author/atom:name/text()', $context)->item(0)->nodeValue; $author["author-name"] = $xpath->evaluate('atom:author/atom:name/text()', $context)->item(0)->nodeValue;
$addr = $xpath->evaluate('atom:author/atom:email/text()', $context)->item(0)->nodeValue;
$aliaslink = $author["author-link"]; $aliaslink = $author["author-link"];
$alternate = $xpath->query("atom:author/atom:link[@rel='alternate']", $context)->item(0)->attributes; $alternate = $xpath->query("atom:author/atom:link[@rel='alternate']", $context)->item(0)->attributes;
if (is_object($alternate)) if (is_object($alternate)) {
foreach($alternate AS $attributes) foreach ($alternate AS $attributes) {
if ($attributes->name == "href") if (($attributes->name == "href") AND ($attributes->textContent != "")) {
$author["author-link"] = $attributes->textContent; $author["author-link"] = $attributes->textContent;
}
}
}
$author["contact-id"] = $contact["id"];
if ($author["author-link"] != "") {
if ($aliaslink == "") {
$aliaslink = $author["author-link"];
}
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'", $r = q("SELECT * FROM `contact` WHERE `uid` = %d AND `nurl` IN ('%s', '%s') AND `network` != '%s'",
intval($importer["uid"]), dbesc(normalise_link($author["author-link"])), intval($importer["uid"]), dbesc(normalise_link($author["author-link"])),
dbesc(normalise_link($aliaslink)), dbesc(NETWORK_STATUSNET)); dbesc(normalise_link($aliaslink)), dbesc(NETWORK_STATUSNET));
if ($r) { if (dbm::is_result($r)) {
$contact = $r[0]; $contact = $r[0];
$author["contact-id"] = $r[0]["id"]; $author["contact-id"] = $r[0]["id"];
} else $author["author-link"] = $r[0]["url"];
}
} elseif ($addr != "") {
// Should not happen
$contact = dba::fetch_first("SELECT * FROM `contact` WHERE `uid` = ? AND `addr` = ? AND `network` != ?",
$importer["uid"], $addr, NETWORK_STATUSNET);
if (dbm::is_result($contact)) {
$author["contact-id"] = $contact["id"]; $author["contact-id"] = $contact["id"];
$author["author-link"] = $contact["url"];
}
}
$avatarlist = array(); $avatarlist = array();
$avatars = $xpath->query("atom:author/atom:link[@rel='avatar']", $context); $avatars = $xpath->query("atom:author/atom:link[@rel='avatar']", $context);
@ -115,7 +100,7 @@ class ostatus {
} }
if (count($avatarlist) > 0) { if (count($avatarlist) > 0) {
krsort($avatarlist); krsort($avatarlist);
$author["author-avatar"] = self::fix_avatar(current($avatarlist), $author["author-link"]); $author["author-avatar"] = Probe::fix_avatar(current($avatarlist), $author["author-link"]);
} }
$displayname = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue; $displayname = $xpath->evaluate('atom:author/poco:displayName/text()', $context)->item(0)->nodeValue;
@ -1176,7 +1161,7 @@ class ostatus {
$arr["owner-name"] = $single_conv->actor->portablecontacts_net->displayName; $arr["owner-name"] = $single_conv->actor->portablecontacts_net->displayName;
$arr["owner-link"] = $actor; $arr["owner-link"] = $actor;
$arr["owner-avatar"] = self::fix_avatar($single_conv->actor->image->url, $arr["owner-link"]); $arr["owner-avatar"] = Probe::fix_avatar($single_conv->actor->image->url, $arr["owner-link"]);
$arr["author-name"] = $arr["owner-name"]; $arr["author-name"] = $arr["owner-name"];
$arr["author-link"] = $arr["owner-link"]; $arr["author-link"] = $arr["owner-link"];
@ -1241,7 +1226,7 @@ class ostatus {
$arr["author-name"] = $single_conv->object->actor->contact->displayName; $arr["author-name"] = $single_conv->object->actor->contact->displayName;
} }
$arr["author-link"] = $single_conv->object->actor->url; $arr["author-link"] = $single_conv->object->actor->url;
$arr["author-avatar"] = self::fix_avatar($single_conv->object->actor->image->url, $arr["author-link"]); $arr["author-avatar"] = Probe::fix_avatar($single_conv->object->actor->image->url, $arr["author-link"]);
$arr["app"] = $single_conv->object->provider->displayName."#"; $arr["app"] = $single_conv->object->provider->displayName."#";
//$arr["verb"] = $single_conv->object->verb; //$arr["verb"] = $single_conv->object->verb;
@ -2270,6 +2255,9 @@ class ostatus {
$root = self::add_header($doc, $owner); $root = self::add_header($doc, $owner);
foreach ($items AS $item) { foreach ($items AS $item) {
if (Config::get('system', 'ostatus_debug')) {
$item['body'] .= '🍼';
}
$entry = self::entry($doc, $item, $owner); $entry = self::entry($doc, $item, $owner);
$root->appendChild($entry); $root->appendChild($entry);
} }
@ -2290,6 +2278,10 @@ class ostatus {
$doc = new DOMDocument('1.0', 'utf-8'); $doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true; $doc->formatOutput = true;
if (Config::get('system', 'ostatus_debug')) {
$item['body'] .= '🐟';
}
$entry = self::entry($doc, $item, $owner, true); $entry = self::entry($doc, $item, $owner, true);
$doc->appendChild($entry); $doc->appendChild($entry);

View file

@ -35,6 +35,9 @@ function handle_pubsubhubbub($id) {
else else
$rr = $r[0]; $rr = $r[0];
/// @todo Check server status with poco_check_server()
// Before this can be done we need a way to safely detect the server url.
logger("Generate feed of user ".$rr['nickname']." to ".$rr['callback_url']." - last updated ".$rr['last_update'], LOGGER_DEBUG); logger("Generate feed of user ".$rr['nickname']." to ".$rr['callback_url']." - last updated ".$rr['last_update'], LOGGER_DEBUG);
$params = ostatus::feed($a, $rr['nickname'], $rr['last_update']); $params = ostatus::feed($a, $rr['nickname'], $rr['last_update']);

View file

@ -1009,6 +1009,7 @@ function poco_check_server($server_url, $network = "", $force = false) {
if (dbm::is_result($servers) AND ($orig_server_url == $server_url) AND if (dbm::is_result($servers) AND ($orig_server_url == $server_url) AND
($serverret['errno'] == CURLE_OPERATION_TIMEDOUT)) { ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG); logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG);
dba::p("UPDATE `gserver` SET `last_failure` = ? WHERE `nurl` = ?", datetime_convert(), normalise_link($server_url));
return false; return false;
} }
@ -1023,6 +1024,7 @@ function poco_check_server($server_url, $network = "", $force = false) {
// Quit if there is a timeout // Quit if there is a timeout
if ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT) { if ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT) {
logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG); logger("Connection to server ".$server_url." timed out.", LOGGER_DEBUG);
dba::p("UPDATE `gserver` SET `last_failure` = ? WHERE `nurl` = ?", datetime_convert(), normalise_link($server_url));
return false; return false;
} }
@ -1032,12 +1034,10 @@ function poco_check_server($server_url, $network = "", $force = false) {
if (!$serverret["success"] OR ($serverret["body"] == "") OR (sizeof($xmlobj) == 0) OR !is_object($xmlobj)) { if (!$serverret["success"] OR ($serverret["body"] == "") OR (sizeof($xmlobj) == 0) OR !is_object($xmlobj)) {
// Workaround for bad configured servers (known nginx problem) // Workaround for bad configured servers (known nginx problem)
if (!in_array($serverret["debug"]["http_code"], array("403", "404"))) { if (!in_array($serverret["debug"]["http_code"], array("403", "404"))) {
$last_failure = datetime_convert();
$failure = true; $failure = true;
} }
$possible_failure = true; $possible_failure = true;
} elseif ($network == NETWORK_DIASPORA) }
$last_contact = datetime_convert();
// If the server has no possible failure we reset the cached data // If the server has no possible failure we reset the cached data
if (!$possible_failure) { if (!$possible_failure) {
@ -1055,8 +1055,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
$data = json_decode($serverret["body"]); $data = json_decode($serverret["body"]);
if (isset($data->totalResults)) { if (isset($data->totalResults)) {
$poco = $server_url."/poco"; $poco = $server_url."/poco";
$last_contact = datetime_convert();
$server = poco_detect_poco_data($data); $server = poco_detect_poco_data($data);
if ($server) { if ($server) {
$platform = $server['platform']; $platform = $server['platform'];
@ -1073,7 +1071,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
$serverret = z_fetch_url($server_url); $serverret = z_fetch_url($server_url);
if (!$serverret["success"] OR ($serverret["body"] == "")) { if (!$serverret["success"] OR ($serverret["body"] == "")) {
$last_failure = datetime_convert();
$failure = true; $failure = true;
} else { } else {
$server = poco_detect_server_type($serverret["body"]); $server = poco_detect_server_type($serverret["body"]);
@ -1082,7 +1079,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
$network = $server['network']; $network = $server['network'];
$version = $server['version']; $version = $server['version'];
$site_name = $server['site_name']; $site_name = $server['site_name'];
$last_contact = datetime_convert();
} }
$lines = explode("\n",$serverret["header"]); $lines = explode("\n",$serverret["header"]);
@ -1096,15 +1092,11 @@ function poco_check_server($server_url, $network = "", $force = false) {
$network = NETWORK_DIASPORA; $network = NETWORK_DIASPORA;
$versionparts = explode("-", $version); $versionparts = explode("-", $version);
$version = $versionparts[0]; $version = $versionparts[0];
$last_contact = datetime_convert();
} }
if(stristr($line,'Server: Mastodon')) { if(stristr($line,'Server: Mastodon')) {
$platform = "Mastodon"; $platform = "Mastodon";
$network = NETWORK_OSTATUS; $network = NETWORK_OSTATUS;
// Mastodon doesn't reveal version numbers
$version = "";
$last_contact = datetime_convert();
} }
} }
} }
@ -1123,7 +1115,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
$version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]); $version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]);
$version = trim($version, '"'); $version = trim($version, '"');
$network = NETWORK_OSTATUS; $network = NETWORK_OSTATUS;
$last_contact = datetime_convert();
} }
// Test for GNU Social // Test for GNU Social
@ -1135,7 +1126,19 @@ function poco_check_server($server_url, $network = "", $force = false) {
$version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]); $version = str_replace(chr(239).chr(187).chr(191), "", $serverret["body"]);
$version = trim($version, '"'); $version = trim($version, '"');
$network = NETWORK_OSTATUS; $network = NETWORK_OSTATUS;
$last_contact = datetime_convert(); }
// Test for Mastodon
$serverret = z_fetch_url($server_url."/api/v1/instance");
if ($serverret["success"] AND ($serverret["body"] != '')) {
$data = json_decode($serverret["body"]);
if (isset($data->version)) {
$platform = "Mastodon";
$version = $data->version;
$site_name = $data->title;
$info = $data->description;
$network = NETWORK_OSTATUS;
}
} }
} }
@ -1145,8 +1148,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
if ($serverret["success"]) { if ($serverret["success"]) {
$data = json_decode($serverret["body"]); $data = json_decode($serverret["body"]);
if (isset($data->site->server)) { if (isset($data->site->server)) {
$last_contact = datetime_convert();
if (isset($data->site->platform)) { if (isset($data->site->platform)) {
$platform = $data->site->platform->PLATFORM_NAME; $platform = $data->site->platform->PLATFORM_NAME;
$version = $data->site->platform->STD_VERSION; $version = $data->site->platform->STD_VERSION;
@ -1193,7 +1194,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
} }
} }
// Query statistics.json. Optional package for Diaspora, Friendica and Redmatrix // Query statistics.json. Optional package for Diaspora, Friendica and Redmatrix
if (!$failure) { if (!$failure) {
$serverret = z_fetch_url($server_url."/statistics.json"); $serverret = z_fetch_url($server_url."/statistics.json");
@ -1221,9 +1221,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
} else { } else {
$register_policy = REGISTER_CLOSED; $register_policy = REGISTER_CLOSED;
} }
if (isset($data->version))
$last_contact = datetime_convert();
} }
} }
@ -1248,8 +1245,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
if (isset($server['site_name'])) { if (isset($server['site_name'])) {
$site_name = $server['site_name']; $site_name = $server['site_name'];
} }
$last_contact = datetime_convert();
} }
} }
@ -1265,7 +1260,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
$data = json_decode($serverret["body"]); $data = json_decode($serverret["body"]);
if (isset($data->version)) { if (isset($data->version)) {
$last_contact = datetime_convert();
$network = NETWORK_DFRN; $network = NETWORK_DFRN;
$noscrape = $data->no_scrape_url; $noscrape = $data->no_scrape_url;
@ -1291,13 +1285,14 @@ function poco_check_server($server_url, $network = "", $force = false) {
} }
if ($possible_failure AND !$failure) { if ($possible_failure AND !$failure) {
$last_failure = datetime_convert();
$failure = true; $failure = true;
} }
if ($failure) { if ($failure) {
$last_contact = $orig_last_contact; $last_contact = $orig_last_contact;
$last_failure = datetime_convert();
} else { } else {
$last_contact = datetime_convert();
$last_failure = $orig_last_failure; $last_failure = $orig_last_failure;
} }

View file

@ -78,22 +78,26 @@ function contact_format(item) {
} }
function editor_replace(item) { function editor_replace(item) {
if(typeof item.replace !== 'undefined') { if (typeof item.replace !== 'undefined') {
return '$1$2' + item.replace; return '$1$2' + item.replace;
} }
if (typeof item.addr !== 'undefined') {
return '$1$2' + item.addr + ' ';
}
// $2 ensures that prefix (@,@!) is preserved // $2 ensures that prefix (@,@!) is preserved
var id = item.id; var id = item.id;
// don't add the id if it is empty (the id empty eg. if there are unknow contacts in thread) // don't add the id if it is empty (the id empty eg. if there are unknow contacts in thread)
if(id.length < 1) if (id.length < 1) {
return '$1$2' + item.nick.replace(' ', '') + ' '; return '$1$2' + item.nick.replace(' ', '') + ' ';
}
// 16 chars of hash should be enough. Full hash could be used if it can be done in a visually appealing way. // 16 chars of hash should be enough. Full hash could be used if it can be done in a visually appealing way.
// 16 chars is also the minimum length in the backend (otherwise it's interpreted as a local id). // 16 chars is also the minimum length in the backend (otherwise it's interpreted as a local id).
if(id.length > 16) if (id.length > 16) {
id = item.id.substring(0,16); id = item.id.substring(0,16);
}
return '$1$2' + item.nick.replace(' ', '') + '+' + id + ' '; return '$1$2' + item.nick.replace(' ', '') + '+' + id + ' ';
} }

View file

@ -279,7 +279,7 @@ function admin_page_blocklist(App $a) {
$blocklistform[] = array( $blocklistform[] = array(
'domain' => array("domain[$id]", t('Blocked domain'), $b['domain'], '', t('The blocked domain'), 'required', '', ''), 'domain' => array("domain[$id]", t('Blocked domain'), $b['domain'], '', t('The blocked domain'), 'required', '', ''),
'reason' => array("reason[$id]", t("Reason for the block"), $b['reason'], t('The reason why you blocked this domain.').'('.$b['domain'].')', 'required', '', ''), 'reason' => array("reason[$id]", t("Reason for the block"), $b['reason'], t('The reason why you blocked this domain.').'('.$b['domain'].')', 'required', '', ''),
'delete' => array("delete[$id]", t("Delete domain").' ('.$b['domain'].')', False , "Check to delete this entry from the blocklist") 'delete' => array("delete[$id]", t("Delete domain").' ('.$b['domain'].')', False , t("Check to delete this entry from the blocklist"))
); );
} }
} }

View file

@ -262,7 +262,7 @@ function _contact_update_profile($contact_id) {
if ($uid != local_user()) if ($uid != local_user())
return; return;
$data = probe_url($r[0]["url"]); $data = Probe::uri($r[0]["url"], "", 0, false);
// "Feed" or "Unknown" is mostly a sign of communication problems // "Feed" or "Unknown" is mostly a sign of communication problems
if ((in_array($data["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) AND ($data["network"] != $r[0]["network"])) if ((in_array($data["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) AND ($data["network"] != $r[0]["network"]))

View file

@ -11,29 +11,27 @@ require_once('include/crypto.php');
require_once('include/diaspora.php'); require_once('include/diaspora.php');
function receive_post(App $a) { function receive_post(App $a) {
$enabled = intval(get_config('system', 'diaspora_enabled'));
$enabled = intval(get_config('system','diaspora_enabled')); if (!$enabled) {
if(! $enabled) {
logger('mod-diaspora: disabled'); logger('mod-diaspora: disabled');
http_status_exit(500); http_status_exit(500);
} }
$public = false; $public = false;
if(($a->argc == 2) && ($a->argv[1] === 'public')) { if (($a->argc == 2) && ($a->argv[1] === 'public')) {
$public = true; $public = true;
} } else {
else {
if($a->argc != 3 || $a->argv[1] !== 'users') if ($a->argc != 3 || $a->argv[1] !== 'users') {
http_status_exit(500); http_status_exit(500);
}
$guid = $a->argv[2]; $guid = $a->argv[2];
$r = q("SELECT * FROM `user` WHERE `guid` = '%s' AND `account_expired` = 0 AND `account_removed` = 0 LIMIT 1", $r = q("SELECT * FROM `user` WHERE `guid` = '%s' AND `account_expired` = 0 AND `account_removed` = 0 LIMIT 1",
dbesc($guid) dbesc($guid)
); );
if (! dbm::is_result($r)) { if (!dbm::is_result($r)) {
http_status_exit(500); http_status_exit(500);
} }
@ -46,29 +44,34 @@ function receive_post(App $a) {
$xml = urldecode($_POST['xml']); $xml = urldecode($_POST['xml']);
logger('mod-diaspora: new salmon ' . $xml, LOGGER_DATA); if (!$xml) {
$postdata = file_get_contents("php://input");
if(! $xml) if ($postdata == '') {
http_status_exit(500); http_status_exit(500);
}
logger('mod-diaspora: message is okay', LOGGER_DEBUG); logger('mod-diaspora: message is in the new format', LOGGER_DEBUG);
$msg = Diaspora::decode_raw($importer, $postdata);
$msg = Diaspora::decode($importer,$xml); } else {
logger('mod-diaspora: message is in the old format', LOGGER_DEBUG);
$msg = Diaspora::decode($importer, $xml);
}
logger('mod-diaspora: decoded', LOGGER_DEBUG); logger('mod-diaspora: decoded', LOGGER_DEBUG);
logger('mod-diaspora: decoded msg: ' . print_r($msg,true), LOGGER_DATA); logger('mod-diaspora: decoded msg: ' . print_r($msg, true), LOGGER_DATA);
if(! is_array($msg)) if (!is_array($msg)) {
http_status_exit(500); http_status_exit(500);
}
logger('mod-diaspora: dispatching', LOGGER_DEBUG); logger('mod-diaspora: dispatching', LOGGER_DEBUG);
$ret = 0; $ret = 0;
if($public) { if ($public) {
Diaspora::dispatch_public($msg); Diaspora::dispatch_public($msg);
} else { } else {
$ret = Diaspora::dispatch($importer,$msg); $ret = Diaspora::dispatch($importer, $msg);
} }
http_status_exit(($ret) ? $ret : 200); http_status_exit(($ret) ? $ret : 200);

View file

@ -1,6 +1,6 @@
<?php <?php
define('UPDATE_VERSION' , 1222); define('UPDATE_VERSION' , 1224);
/** /**
* *

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,86 @@
<script>
// update pending count //
$(function(){
$("nav").bind('nav-update', function(e,data){
var elm = $('#pending-update');
var register = $(data).find('register').text();
if (register=="0") { register = ""; }
elm.html(register);
});
});
</script>
<div class="widget">
<h3><a href="{{$admurl}}">{{$admtxt}}</a></h3>
<ul role="menu">
{{foreach $subpages as $name => $item}}
<li role="menuitem" class="{{$item.2}}">
<a href="{{$item.0}}" {{if $item.accesskey}}accesskey="{{$item.accesskey}}"{{/if}}>
{{$item.1}}
{{if $name == "users"}}
<span id="pending-update" class="badge pull-right"></span>
{{/if}}
</a>
</li>
{{/foreach}}
</ul>
{{if $admin.update}}
<ul role="menu">
<li role="menuitem" class="{{$admin.update.2}}">
<a href="{{$admin.update.0}}" {{if $admin.update.accesskey}}accesskey="{{$admin.update.accesskey}}"{{/if}}>
{{$admin.update.1}}
</a>
</li>
</ul>
{{/if}}
</div>
{{if $admin.plugins_admin}}
<div class="widget">
<h3>{{$plugadmtxt}}</h3>
<ul role="menu">
{{foreach $admin.plugins_admin as $name => $item}}
<li role="menuitem" class="{{$item.2}}">
<a href="{{$item.0}}" {{if $item.accesskey}}accesskey="{{$item.accesskey}}"{{/if}}>
{{$item.1}}
</a>
</li>
{{/foreach}}
</ul>
</div>
{{/if}}
<div class="widget">
<h3>{{$logtxt}}</h3>
<ul role="menu">
<li role="menuitem" class="{{$admin.logs.2}}">
<a href="{{$admin.logs.0}}" {{if $admin.logs.accesskey}}accesskey="{{$admin.logs.accesskey}}"{{/if}}>
{{$admin.logs.1}}
</a>
</li>
<li role="menuitem" class="{{$admin.viewlogs.2}}">
<a href="{{$admin.viewlogs.0}}" {{if $admin.viewlogs.accesskey}}accesskey="{{$admin.viewlogs.accesskey}}"{{/if}}>
{{$admin.viewlogs.1}}
</a>
</li>
</ul>
</div>
<div class="widget">
<h3>{{$diagnosticstxt}}</h3>
<ul role="menu">
<li role="menuitem" class="{{$admin.diagnostics_probe.2}}">
<a href="{{$admin.diagnostics_probe.0}}" {{if $admin.diagnostics_probe.accesskey}}accesskey="{{$admin.diagnostics_probe.accesskey}}"{{/if}}>
{{$admin.diagnostics_probe.1}}
</a>
</li>
<li role="menuitem" class="{{$admin.diagnostics_webfinger.2}}">
<a href="{{$admin.diagnostics_webfinger.0}}" {{if $admin.viewlogs.accesskey}}accesskey="{{$admin.diagnostics_webfinger.accesskey}}"{{/if}}>
{{$admin.diagnostics_webfinger.1}}
</a>
</li>
</ul>
</div>

View file

@ -0,0 +1,12 @@
<div class="widget{{if $class}} {{$class}}{{/if}}">
{{if $title}}<h3>{{$title}}</h3>{{/if}}
{{if $desc}}<div class="desc">{{$desc}}</div>{{/if}}
<ul role="menu">
{{foreach $items as $item}}
<li role="menuitem" class="{{if $item.selected}}selected{{/if}}"><a href="{{$item.url}}" {{if $item.accesskey}}accesskey="{{$item.accesskey}}"{{/if}}>{{$item.label}}</a></li>
{{/foreach}}
</ul>
</div>