Merge branch 'develop' into improvement/move-app-to-src-2
This commit is contained in:
commit
86cae070f2
2
boot.php
2
boot.php
|
@ -40,7 +40,7 @@ define ( 'FRIENDICA_PLATFORM', 'Friendica');
|
|||
define ( 'FRIENDICA_CODENAME', 'Asparagus');
|
||||
define ( 'FRIENDICA_VERSION', '3.5.2-dev' );
|
||||
define ( 'DFRN_PROTOCOL_VERSION', '2.23' );
|
||||
define ( 'DB_UPDATE_VERSION', 1222 );
|
||||
define ( 'DB_UPDATE_VERSION', 1224 );
|
||||
|
||||
/**
|
||||
* @brief Constant with a HTML line break.
|
||||
|
|
|
@ -172,6 +172,11 @@ On error:
|
|||
HTTP 400 BadRequest
|
||||
* on friendica_verbose=true: different JSON returns {"result":"error","message":"xyz"}
|
||||
|
||||
---
|
||||
### externalprofile/show (*)
|
||||
#### Parameters
|
||||
* profileurl: profile url
|
||||
|
||||
---
|
||||
### favorites (*; AUTH)
|
||||
#### Parameters
|
||||
|
|
|
@ -175,6 +175,9 @@ class Probe {
|
|||
return array();
|
||||
|
||||
$host = $parts["host"];
|
||||
if (isset($parts["port"])) {
|
||||
$host .= ':'.$parts["port"];
|
||||
}
|
||||
|
||||
$path_parts = explode("/", trim($parts["path"], "/"));
|
||||
|
||||
|
@ -335,8 +338,10 @@ class Probe {
|
|||
|
||||
if (isset($parts["scheme"]) AND isset($parts["host"]) AND isset($parts["path"])) {
|
||||
|
||||
/// @todo: Ports?
|
||||
$host = $parts["host"];
|
||||
if (isset($parts["port"])) {
|
||||
$host .= ':'.$parts["port"];
|
||||
}
|
||||
|
||||
if ($host == 'twitter.com') {
|
||||
return array("network" => NETWORK_TWITTER);
|
||||
|
@ -789,7 +794,7 @@ class Probe {
|
|||
|
||||
if (sizeof($avatar)) {
|
||||
ksort($avatar);
|
||||
$data["photo"] = array_pop($avatar);
|
||||
$data["photo"] = self::fix_avatar(array_pop($avatar), $data["baseurl"]);
|
||||
}
|
||||
|
||||
if ($dfrn) {
|
||||
|
@ -960,7 +965,7 @@ class Probe {
|
|||
$data["nick"] = $feed_data["header"]["author-nick"];
|
||||
}
|
||||
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"] != "") {
|
||||
$data["alias"] = $feed_data["header"]["author-id"];
|
||||
|
@ -1219,4 +1224,41 @@ class Probe {
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -545,7 +545,7 @@ function acl_lookup(App $a, $out_type = 'json') {
|
|||
|
||||
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` != ''
|
||||
AND NOT (`network` IN ('%s', '%s'))
|
||||
$sql_extra2
|
||||
|
@ -554,7 +554,7 @@ function acl_lookup(App $a, $out_type = 'json') {
|
|||
dbesc(NETWORK_OSTATUS), dbesc(NETWORK_STATUSNET)
|
||||
);
|
||||
} 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` != ''
|
||||
AND NOT (`network` IN ('%s'))
|
||||
$sql_extra2
|
||||
|
@ -564,7 +564,7 @@ function acl_lookup(App $a, $out_type = 'json') {
|
|||
);
|
||||
}
|
||||
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`
|
||||
AND `network` IN ('%s','%s','%s')
|
||||
$sql_extra2
|
||||
|
@ -575,7 +575,7 @@ function acl_lookup(App $a, $out_type = 'json') {
|
|||
dbesc(NETWORK_DIASPORA)
|
||||
);
|
||||
} 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
|
||||
$sql_extra2
|
||||
ORDER BY `name` ASC ",
|
||||
|
@ -619,6 +619,7 @@ function acl_lookup(App $a, $out_type = 'json') {
|
|||
'network' => $g['network'],
|
||||
'link' => $g['url'],
|
||||
'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),
|
||||
);
|
||||
}
|
||||
|
@ -663,6 +664,7 @@ function acl_lookup(App $a, $out_type = 'json') {
|
|||
'network' => $contact['network'],
|
||||
'link' => $contact['url'],
|
||||
'nick' => htmlentities($contact['nick'] ? : $contact['addr']),
|
||||
'addr' => htmlentities(($contact['addr']) ? $contact['addr'] : $contact['url']),
|
||||
'forum' => $contact['forum']
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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)) {
|
||||
$argid = count($called_api);
|
||||
list($user, $null) = explode(".", $a->argv[$argid]);
|
||||
|
@ -1401,6 +1410,7 @@ $called_api = null;
|
|||
|
||||
/// @TODO move to top of file or somewhere better
|
||||
api_register_func('api/users/show','api_users_show');
|
||||
api_register_func('api/externalprofile/show','api_users_show');
|
||||
|
||||
function api_users_search($type) {
|
||||
|
||||
|
|
113
include/dba.php
113
include/dba.php
|
@ -25,11 +25,20 @@ class dba {
|
|||
private static $dbo;
|
||||
private static $relation = array();
|
||||
|
||||
function __construct($server, $user, $pass, $db, $install = false) {
|
||||
function __construct($serveraddr, $user, $pass, $db, $install = false) {
|
||||
$a = get_app();
|
||||
|
||||
$stamp1 = microtime(true);
|
||||
|
||||
$serveraddr = trim($serveraddr);
|
||||
|
||||
$serverdata = explode(':', $serveraddr);
|
||||
$server = $serverdata[0];
|
||||
|
||||
if (count($serverdata) > 1) {
|
||||
$port = trim($serverdata[1]);
|
||||
}
|
||||
|
||||
$server = trim($server);
|
||||
$user = trim($user);
|
||||
$pass = trim($pass);
|
||||
|
@ -55,6 +64,11 @@ class dba {
|
|||
if (class_exists('\PDO') && in_array('mysql', PDO::getAvailableDrivers())) {
|
||||
$this->driver = 'pdo';
|
||||
$connect = "mysql:host=".$server.";dbname=".$db;
|
||||
|
||||
if (isset($port)) {
|
||||
$connect .= ";port=".$port;
|
||||
}
|
||||
|
||||
if (isset($a->config["system"]["db_charset"])) {
|
||||
$connect .= ";charset=".$a->config["system"]["db_charset"];
|
||||
}
|
||||
|
@ -64,7 +78,7 @@ class dba {
|
|||
}
|
||||
} elseif (class_exists('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()) {
|
||||
$this->connected = true;
|
||||
|
||||
|
@ -74,8 +88,8 @@ class dba {
|
|||
}
|
||||
} elseif (function_exists('mysql_connect')) {
|
||||
$this->driver = 'mysql';
|
||||
$this->db = mysql_connect($server,$user,$pass);
|
||||
if ($this->db && mysql_select_db($db,$this->db)) {
|
||||
$this->db = mysql_connect($serveraddr, $user, $pass);
|
||||
if ($this->db && mysql_select_db($db, $this->db)) {
|
||||
$this->connected = true;
|
||||
|
||||
if (isset($a->config["system"]["db_charset"])) {
|
||||
|
@ -484,18 +498,28 @@ class dba {
|
|||
unset($args[0]);
|
||||
|
||||
// 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];
|
||||
} else {
|
||||
$params = $args;
|
||||
}
|
||||
|
||||
// Renumber the array keys to be sure that they fit
|
||||
$i = 0;
|
||||
$args = array();
|
||||
foreach ($params AS $param) {
|
||||
$args[++$i] = $param;
|
||||
}
|
||||
}
|
||||
|
||||
if (!self::$dbo OR !self::$dbo->connected) {
|
||||
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);
|
||||
|
||||
if (x($a->config,'system') && x($a->config['system'], 'db_callstack')) {
|
||||
|
@ -553,9 +577,10 @@ class dba {
|
|||
$values[] = &$args[$param];
|
||||
}
|
||||
|
||||
if (count($values) > 0) {
|
||||
array_unshift($values, $params);
|
||||
|
||||
call_user_func_array(array($stmt, 'bind_param'), $values);
|
||||
}
|
||||
|
||||
if (!$stmt->execute()) {
|
||||
self::$dbo->error = self::$dbo->db->error;
|
||||
|
@ -861,7 +886,7 @@ class dba {
|
|||
|
||||
logger(dba::replace_parameters($sql, $command['param']), LOGGER_DATA);
|
||||
|
||||
if (!self::e($sql, $param)) {
|
||||
if (!self::e($sql, $command['param'])) {
|
||||
self::p("ROLLBACK");
|
||||
return false;
|
||||
}
|
||||
|
@ -889,7 +914,7 @@ class dba {
|
|||
|
||||
logger(dba::replace_parameters($sql, $field_values), LOGGER_DATA);
|
||||
|
||||
if (!self::e($sql, $param)) {
|
||||
if (!self::e($sql, $field_values)) {
|
||||
self::p("ROLLBACK");
|
||||
return false;
|
||||
}
|
||||
|
@ -991,6 +1016,76 @@ class dba {
|
|||
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
|
||||
*
|
||||
|
|
|
@ -399,6 +399,14 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
|
|||
$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) {
|
||||
// Ensure index conversion to unique removes duplicates
|
||||
if ($is_unique) {
|
||||
|
@ -415,7 +423,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
|
|||
if ($ignore != "") {
|
||||
echo "SET session old_alter_table=0;\n";
|
||||
} 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 "RENAME TABLE `".$temp_name."` TO `".$name."`;\n";
|
||||
}
|
||||
|
@ -446,7 +454,7 @@ function update_structure($verbose, $action, $tables=null, $definition=null) {
|
|||
if ($ignore != "") {
|
||||
$db->q("SET session old_alter_table=0;");
|
||||
} 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)) {
|
||||
$errors .= print_update_error($db, $sql3);
|
||||
return $errors;
|
||||
|
@ -879,7 +887,7 @@ function db_definition() {
|
|||
"indexes" => array(
|
||||
"PRIMARY" => array("id"),
|
||||
"addr" => array("addr(32)"),
|
||||
"url" => array("url"),
|
||||
"url" => array("UNIQUE", "url(190)"),
|
||||
)
|
||||
);
|
||||
$database["ffinder"] = array(
|
||||
|
@ -964,7 +972,7 @@ function db_definition() {
|
|||
),
|
||||
"indexes" => array(
|
||||
"PRIMARY" => array("id"),
|
||||
"nurl" => array("nurl(64)"),
|
||||
"nurl" => array("UNIQUE", "nurl(190)"),
|
||||
"name" => array("name(64)"),
|
||||
"nick" => array("nick(32)"),
|
||||
"addr" => array("addr(64)"),
|
||||
|
@ -1034,7 +1042,7 @@ function db_definition() {
|
|||
),
|
||||
"indexes" => array(
|
||||
"PRIMARY" => array("id"),
|
||||
"nurl" => array("nurl(32)"),
|
||||
"nurl" => array("UNIQUE", "nurl(190)"),
|
||||
)
|
||||
);
|
||||
$database["hook"] = array(
|
||||
|
@ -1219,6 +1227,7 @@ function db_definition() {
|
|||
"convid" => array("convid"),
|
||||
"uri" => array("uri(64)"),
|
||||
"parent-uri" => array("parent-uri(64)"),
|
||||
"contactid" => array("contact-id"),
|
||||
)
|
||||
);
|
||||
$database["mailacct"] = array(
|
||||
|
@ -1356,6 +1365,7 @@ function db_definition() {
|
|||
),
|
||||
"indexes" => array(
|
||||
"PRIMARY" => array("id"),
|
||||
"contactid" => array("contact-id"),
|
||||
"uid_contactid" => array("uid", "contact-id"),
|
||||
"uid_profile" => array("uid", "profile"),
|
||||
"uid_album_scale_created" => array("uid", "album(32)", "scale", "created"),
|
||||
|
|
|
@ -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 string $xml urldecoded Diaspora salmon
|
||||
|
@ -203,9 +276,10 @@ class Diaspora {
|
|||
$public = false;
|
||||
$basedom = parse_xml_string($xml);
|
||||
|
||||
if (!is_object($basedom))
|
||||
if (!is_object($basedom)) {
|
||||
logger("XML is not parseable.");
|
||||
return false;
|
||||
|
||||
}
|
||||
$children = $basedom->children('https://joindiaspora.com/protocol');
|
||||
|
||||
if ($children->header) {
|
||||
|
@ -334,6 +408,24 @@ class Diaspora {
|
|||
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
|
||||
$r = q("SELECT `user`.* FROM `user` WHERE `user`.`uid` IN
|
||||
(SELECT `contact`.`uid` FROM `contact` WHERE `contact`.`network` = '%s' AND `contact`.`addr` = '%s')
|
||||
|
@ -345,13 +437,14 @@ class Diaspora {
|
|||
if (dbm::is_result($r)) {
|
||||
foreach ($r as $rr) {
|
||||
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 {
|
||||
// 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);
|
||||
$message_id = self::dispatch($importer,$msg);
|
||||
$message_id = self::dispatch($importer, $msg, $fields);
|
||||
}
|
||||
|
||||
return $message_id;
|
||||
|
@ -362,27 +455,27 @@ class Diaspora {
|
|||
*
|
||||
* @param array $importer Array of the importer user
|
||||
* @param array $msg The post that will be dispatched
|
||||
* @param object $fields SimpleXML object that contains the message
|
||||
*
|
||||
* @return int The message id of the generated message, "true" or "false" if there was an error
|
||||
*/
|
||||
public static function dispatch($importer, $msg) {
|
||||
public static function dispatch($importer, $msg, $fields = null) {
|
||||
|
||||
// The sender is the handle of the contact that sent the message.
|
||||
// This will often be different with relayed messages (for example "like" and "comment")
|
||||
$sender = $msg["author"];
|
||||
|
||||
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");
|
||||
return false;
|
||||
}
|
||||
$fields = $postdata['fields'];
|
||||
}
|
||||
|
||||
$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);
|
||||
|
||||
switch ($type) {
|
||||
|
@ -440,11 +533,10 @@ class Diaspora {
|
|||
* 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 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);
|
||||
|
||||
|
@ -485,34 +577,40 @@ class Diaspora {
|
|||
foreach ($element->children() AS $fieldname => $entry) {
|
||||
if ($oldXML) {
|
||||
// Translation for the old XML structure
|
||||
if ($fieldname == "diaspora_handle")
|
||||
if ($fieldname == "diaspora_handle") {
|
||||
$fieldname = "author";
|
||||
|
||||
if ($fieldname == "participant_handles")
|
||||
}
|
||||
if ($fieldname == "participant_handles") {
|
||||
$fieldname = "participants";
|
||||
|
||||
}
|
||||
if (in_array($type, array("like", "participation"))) {
|
||||
if ($fieldname == "target_type")
|
||||
if ($fieldname == "target_type") {
|
||||
$fieldname = "parent_type";
|
||||
}
|
||||
|
||||
if ($fieldname == "sender_handle")
|
||||
}
|
||||
if ($fieldname == "sender_handle") {
|
||||
$fieldname = "author";
|
||||
|
||||
if ($fieldname == "recipient_handle")
|
||||
}
|
||||
if ($fieldname == "recipient_handle") {
|
||||
$fieldname = "recipient";
|
||||
|
||||
if ($fieldname == "root_diaspora_id")
|
||||
}
|
||||
if ($fieldname == "root_diaspora_id") {
|
||||
$fieldname = "root_author";
|
||||
|
||||
}
|
||||
if ($type == "status_message") {
|
||||
if ($fieldname == "raw_message") {
|
||||
$fieldname = "text";
|
||||
}
|
||||
}
|
||||
if ($type == "retraction") {
|
||||
if ($fieldname == "post_guid")
|
||||
if ($fieldname == "post_guid") {
|
||||
$fieldname = "target_guid";
|
||||
|
||||
if ($fieldname == "type")
|
||||
}
|
||||
if ($fieldname == "type") {
|
||||
$fieldname = "target_type";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (($fieldname == "author_signature") AND ($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.
|
||||
if (!in_array($type, array("comment", "message", "like")))
|
||||
return true;
|
||||
|
||||
if (!in_array($type, array("comment", "like"))) {
|
||||
return array("fields" => $fields, "relayed" => false);
|
||||
}
|
||||
// No author_signature? This is a must, so we quit.
|
||||
if (!isset($author_signature)) {
|
||||
logger("No author signature for type ".$type." - Message: ".$msg["message"], LOGGER_DEBUG);
|
||||
|
@ -549,12 +647,16 @@ class Diaspora {
|
|||
}
|
||||
|
||||
if (isset($parent_author_signature)) {
|
||||
$relayed = true;
|
||||
|
||||
$key = self::key($msg["author"]);
|
||||
|
||||
if (!rsa_verify($signed_data, $parent_author_signature, $key, "sha256")) {
|
||||
logger("No valid parent author signature for parent author ".$msg["author"]. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$parent_author_signature, LOGGER_DEBUG);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$relayed = false;
|
||||
}
|
||||
|
||||
$key = self::key($fields->author);
|
||||
|
@ -562,8 +664,9 @@ class Diaspora {
|
|||
if (!rsa_verify($signed_data, $author_signature, $key, "sha256")) {
|
||||
logger("No valid author signature for author ".$fields->author. " in type ".$type." - signed data: ".$signed_data." - Message: ".$msg["message"]." - Signature ".$author_signature, LOGGER_DEBUG);
|
||||
return false;
|
||||
} else
|
||||
return true;
|
||||
} else {
|
||||
return array("fields" => $fields, "relayed" => $relayed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -592,7 +695,7 @@ class Diaspora {
|
|||
*
|
||||
* @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",
|
||||
dbesc(NETWORK_DIASPORA),
|
||||
|
@ -829,17 +932,20 @@ class Diaspora {
|
|||
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;
|
||||
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;
|
||||
if ($contact["rel"] == CONTACT_IS_FOLLOWER)
|
||||
if (($importer["page-flags"] == PAGE_COMMUNITY) OR $is_comment)
|
||||
// Is it a post to a community? That's good
|
||||
} elseif (($contact["rel"] == CONTACT_IS_FOLLOWER) && ($importer["page-flags"] == PAGE_COMMUNITY)) {
|
||||
return true;
|
||||
|
||||
// Messages for the global users are always accepted
|
||||
if ($importer["uid"] == 0)
|
||||
}
|
||||
// Messages for the global users and comments are always accepted
|
||||
if (($importer["uid"] == 0) || $is_comment) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -857,8 +963,13 @@ class Diaspora {
|
|||
$contact = self::contact_by_handle($importer["uid"], $handle);
|
||||
if (!$contact) {
|
||||
logger("A Contact for handle ".$handle." and user ".$importer["uid"]." was not found");
|
||||
// If a contact isn't found, we accept it anyway if it is a comment
|
||||
if ($is_comment) {
|
||||
return $importer;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!self::post_allow($importer, $contact, $is_comment)) {
|
||||
logger("The handle: ".$handle." is not allowed to post to user ".$importer["uid"]);
|
||||
|
@ -1112,9 +1223,9 @@ class Diaspora {
|
|||
$cid = $r[0]["id"];
|
||||
$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.
|
||||
unmark_for_death($contact);
|
||||
unmark_for_death($r[0]);
|
||||
} else {
|
||||
$cid = $contact["id"];
|
||||
$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
|
||||
*
|
||||
* @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);
|
||||
|
||||
if (dbm::is_result($item)) {
|
||||
logger("Found user ".$item['uid']." as owner of item ".$guid, LOGGER_DEBUG);
|
||||
$contact = dba::fetch_first("SELECT * FROM `contact` WHERE `self` AND `uid` = ?", $item['uid']);
|
||||
if (dbm::is_result($contact)) {
|
||||
$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
|
||||
*/
|
||||
private static function receive_comment($importer, $sender, $data, $xml) {
|
||||
$author = notags(unxmlify($data->author));
|
||||
$guid = notags(unxmlify($data->guid));
|
||||
$parent_guid = notags(unxmlify($data->parent_guid));
|
||||
$text = unxmlify($data->text);
|
||||
$author = notags(unxmlify($data->author));
|
||||
|
||||
if (isset($data->created_at)) {
|
||||
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
|
||||
|
@ -1278,11 +1388,6 @@ class Diaspora {
|
|||
$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);
|
||||
if (!$contact) {
|
||||
return false;
|
||||
|
@ -1383,16 +1488,9 @@ class Diaspora {
|
|||
* @return bool "true" if it was successful
|
||||
*/
|
||||
private static function receive_conversation_message($importer, $contact, $data, $msg, $mesg, $conversation) {
|
||||
$author = notags(unxmlify($data->author));
|
||||
$guid = notags(unxmlify($data->guid));
|
||||
$subject = notags(unxmlify($data->subject));
|
||||
$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
|
||||
// "author" is the element name from the new version
|
||||
|
@ -1404,7 +1502,10 @@ class Diaspora {
|
|||
return false;
|
||||
}
|
||||
|
||||
$msg_guid = notags(unxmlify($mesg->guid));
|
||||
$msg_conversation_guid = notags(unxmlify($mesg->conversation_guid));
|
||||
$msg_text = unxmlify($mesg->text);
|
||||
$msg_created_at = datetime_convert("UTC", "UTC", notags(unxmlify($mesg->created_at)));
|
||||
|
||||
if ($msg_conversation_guid != $guid) {
|
||||
logger("message conversation guid does not belong to the current conversation.");
|
||||
|
@ -1414,42 +1515,8 @@ class Diaspora {
|
|||
$body = diaspora2bb($msg_text);
|
||||
$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);
|
||||
|
||||
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",
|
||||
dbesc($message_uri)
|
||||
);
|
||||
|
@ -1508,10 +1575,10 @@ class Diaspora {
|
|||
* @return bool Success
|
||||
*/
|
||||
private static function receive_conversation($importer, $msg, $data) {
|
||||
$author = notags(unxmlify($data->author));
|
||||
$guid = notags(unxmlify($data->guid));
|
||||
$subject = notags(unxmlify($data->subject));
|
||||
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
|
||||
$author = notags(unxmlify($data->author));
|
||||
$participants = notags(unxmlify($data->participants));
|
||||
|
||||
$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
|
||||
*/
|
||||
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));
|
||||
$guid = notags(unxmlify($data->guid));
|
||||
$parent_guid = notags(unxmlify($data->parent_guid));
|
||||
$parent_type = notags(unxmlify($data->parent_type));
|
||||
$positive = notags(unxmlify($data->positive));
|
||||
|
||||
// likes on comments aren't supported by Diaspora - only on posts
|
||||
// But maybe this will be supported in the future, so we will accept it.
|
||||
|
@ -1715,12 +1782,11 @@ class Diaspora {
|
|||
* @return bool Success?
|
||||
*/
|
||||
private static function receive_message($importer, $data) {
|
||||
$author = notags(unxmlify($data->author));
|
||||
$guid = notags(unxmlify($data->guid));
|
||||
$parent_guid = notags(unxmlify($data->parent_guid));
|
||||
$conversation_guid = notags(unxmlify($data->conversation_guid));
|
||||
$text = unxmlify($data->text);
|
||||
$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);
|
||||
if (!$contact) {
|
||||
|
@ -1775,7 +1841,7 @@ class Diaspora {
|
|||
0,
|
||||
1,
|
||||
dbesc($message_uri),
|
||||
dbesc($author.":".$parent_guid),
|
||||
dbesc($author.":".$conversation["guid"]),
|
||||
dbesc($created_at)
|
||||
);
|
||||
|
||||
|
@ -1844,9 +1910,9 @@ class Diaspora {
|
|||
$name = unxmlify($data->first_name).((strlen($data->last_name)) ? " ".unxmlify($data->last_name) : "");
|
||||
$image_url = unxmlify($data->image_url);
|
||||
$birthday = unxmlify($data->birthday);
|
||||
$location = diaspora2bb(unxmlify($data->location));
|
||||
$about = diaspora2bb(unxmlify($data->bio));
|
||||
$gender = unxmlify($data->gender);
|
||||
$about = diaspora2bb(unxmlify($data->bio));
|
||||
$location = diaspora2bb(unxmlify($data->location));
|
||||
$searchable = (unxmlify($data->searchable) == "true");
|
||||
$nsfw = (unxmlify($data->nsfw) == "true");
|
||||
$tags = unxmlify($data->tag_string);
|
||||
|
@ -2266,12 +2332,13 @@ class Diaspora {
|
|||
* @return int the message id
|
||||
*/
|
||||
private static function receive_reshare($importer, $data, $xml) {
|
||||
$author = notags(unxmlify($data->author));
|
||||
$guid = notags(unxmlify($data->guid));
|
||||
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
|
||||
$root_author = notags(unxmlify($data->root_author));
|
||||
$root_guid = notags(unxmlify($data->root_guid));
|
||||
$guid = notags(unxmlify($data->guid));
|
||||
$author = notags(unxmlify($data->author));
|
||||
/// @todo handle unprocessed property "provider_display_name"
|
||||
$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);
|
||||
if (!$contact) {
|
||||
|
@ -2346,9 +2413,9 @@ class Diaspora {
|
|||
* @return bool success
|
||||
*/
|
||||
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));
|
||||
$target_guid = notags(unxmlify($data->target_guid));
|
||||
$target_type = notags(unxmlify($data->target_type));
|
||||
|
||||
$person = self::person_by_handle($author);
|
||||
if (!is_array($person)) {
|
||||
|
@ -2356,11 +2423,16 @@ class Diaspora {
|
|||
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",
|
||||
dbesc($target_guid),
|
||||
intval($importer["uid"])
|
||||
);
|
||||
if (!$r) {
|
||||
logger("Target guid ".$target_guid." was not found for user ".$importer["uid"]);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2406,7 +2478,7 @@ class Diaspora {
|
|||
$target_type = notags(unxmlify($data->target_type));
|
||||
|
||||
$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"]);
|
||||
return false;
|
||||
}
|
||||
|
@ -2419,7 +2491,7 @@ class Diaspora {
|
|||
case "Post": // "Post" will be supported in a future version
|
||||
case "Reshare":
|
||||
case "StatusMessage":
|
||||
return self::item_retraction($importer, $contact, $data);;
|
||||
return self::item_retraction($importer, $contact, $data);
|
||||
|
||||
case "Contact":
|
||||
case "Person":
|
||||
|
@ -2445,19 +2517,13 @@ class Diaspora {
|
|||
* @return int The message id of the newly created item
|
||||
*/
|
||||
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));
|
||||
$public = notags(unxmlify($data->public));
|
||||
$guid = notags(unxmlify($data->guid));
|
||||
$created_at = datetime_convert("UTC", "UTC", notags(unxmlify($data->created_at)));
|
||||
$public = notags(unxmlify($data->public));
|
||||
$text = unxmlify($data->text);
|
||||
$provider_display_name = notags(unxmlify($data->provider_display_name));
|
||||
|
||||
/// @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);
|
||||
if (!$contact) {
|
||||
return false;
|
||||
|
@ -2475,7 +2541,7 @@ class Diaspora {
|
|||
}
|
||||
}
|
||||
|
||||
$body = diaspora2bb($raw_message);
|
||||
$body = diaspora2bb($text);
|
||||
|
||||
$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["contact-id"] = $contact["id"];
|
||||
$datarray["network"] = NETWORK_DIASPORA;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Config;
|
||||
|
||||
require_once("include/Contact.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_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
|
||||
*
|
||||
|
@ -81,23 +46,43 @@ class ostatus {
|
|||
$author = array();
|
||||
$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;
|
||||
$addr = $xpath->evaluate('atom:author/atom:email/text()', $context)->item(0)->nodeValue;
|
||||
|
||||
$aliaslink = $author["author-link"];
|
||||
|
||||
$alternate = $xpath->query("atom:author/atom:link[@rel='alternate']", $context)->item(0)->attributes;
|
||||
if (is_object($alternate))
|
||||
foreach($alternate AS $attributes)
|
||||
if ($attributes->name == "href")
|
||||
if (is_object($alternate)) {
|
||||
foreach ($alternate AS $attributes) {
|
||||
if (($attributes->name == "href") AND ($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'",
|
||||
intval($importer["uid"]), dbesc(normalise_link($author["author-link"])),
|
||||
dbesc(normalise_link($aliaslink)), dbesc(NETWORK_STATUSNET));
|
||||
if ($r) {
|
||||
if (dbm::is_result($r)) {
|
||||
$contact = $r[0];
|
||||
$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["author-link"] = $contact["url"];
|
||||
}
|
||||
}
|
||||
|
||||
$avatarlist = array();
|
||||
$avatars = $xpath->query("atom:author/atom:link[@rel='avatar']", $context);
|
||||
|
@ -115,7 +100,7 @@ class ostatus {
|
|||
}
|
||||
if (count($avatarlist) > 0) {
|
||||
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;
|
||||
|
@ -1176,7 +1161,7 @@ class ostatus {
|
|||
$arr["owner-name"] = $single_conv->actor->portablecontacts_net->displayName;
|
||||
|
||||
$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-link"] = $arr["owner-link"];
|
||||
|
@ -1241,7 +1226,7 @@ class ostatus {
|
|||
$arr["author-name"] = $single_conv->object->actor->contact->displayName;
|
||||
}
|
||||
$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["verb"] = $single_conv->object->verb;
|
||||
|
@ -2270,6 +2255,9 @@ class ostatus {
|
|||
$root = self::add_header($doc, $owner);
|
||||
|
||||
foreach ($items AS $item) {
|
||||
if (Config::get('system', 'ostatus_debug')) {
|
||||
$item['body'] .= '🍼';
|
||||
}
|
||||
$entry = self::entry($doc, $item, $owner);
|
||||
$root->appendChild($entry);
|
||||
}
|
||||
|
@ -2290,6 +2278,10 @@ class ostatus {
|
|||
$doc = new DOMDocument('1.0', 'utf-8');
|
||||
$doc->formatOutput = true;
|
||||
|
||||
if (Config::get('system', 'ostatus_debug')) {
|
||||
$item['body'] .= '🐟';
|
||||
}
|
||||
|
||||
$entry = self::entry($doc, $item, $owner, true);
|
||||
|
||||
$doc->appendChild($entry);
|
||||
|
|
|
@ -35,6 +35,9 @@ function handle_pubsubhubbub($id) {
|
|||
else
|
||||
$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);
|
||||
|
||||
$params = ostatus::feed($a, $rr['nickname'], $rr['last_update']);
|
||||
|
|
|
@ -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
|
||||
($serverret['errno'] == CURLE_OPERATION_TIMEDOUT)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1023,6 +1024,7 @@ function poco_check_server($server_url, $network = "", $force = false) {
|
|||
// Quit if there is a timeout
|
||||
if ($serverret['errno'] == CURLE_OPERATION_TIMEDOUT) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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)) {
|
||||
// Workaround for bad configured servers (known nginx problem)
|
||||
if (!in_array($serverret["debug"]["http_code"], array("403", "404"))) {
|
||||
$last_failure = datetime_convert();
|
||||
$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 (!$possible_failure) {
|
||||
|
@ -1055,8 +1055,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
|
|||
$data = json_decode($serverret["body"]);
|
||||
if (isset($data->totalResults)) {
|
||||
$poco = $server_url."/poco";
|
||||
$last_contact = datetime_convert();
|
||||
|
||||
$server = poco_detect_poco_data($data);
|
||||
if ($server) {
|
||||
$platform = $server['platform'];
|
||||
|
@ -1073,7 +1071,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
|
|||
$serverret = z_fetch_url($server_url);
|
||||
|
||||
if (!$serverret["success"] OR ($serverret["body"] == "")) {
|
||||
$last_failure = datetime_convert();
|
||||
$failure = true;
|
||||
} else {
|
||||
$server = poco_detect_server_type($serverret["body"]);
|
||||
|
@ -1082,7 +1079,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
|
|||
$network = $server['network'];
|
||||
$version = $server['version'];
|
||||
$site_name = $server['site_name'];
|
||||
$last_contact = datetime_convert();
|
||||
}
|
||||
|
||||
$lines = explode("\n",$serverret["header"]);
|
||||
|
@ -1096,15 +1092,11 @@ function poco_check_server($server_url, $network = "", $force = false) {
|
|||
$network = NETWORK_DIASPORA;
|
||||
$versionparts = explode("-", $version);
|
||||
$version = $versionparts[0];
|
||||
$last_contact = datetime_convert();
|
||||
}
|
||||
|
||||
if(stristr($line,'Server: Mastodon')) {
|
||||
$platform = "Mastodon";
|
||||
$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 = trim($version, '"');
|
||||
$network = NETWORK_OSTATUS;
|
||||
$last_contact = datetime_convert();
|
||||
}
|
||||
|
||||
// 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 = trim($version, '"');
|
||||
$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"]) {
|
||||
$data = json_decode($serverret["body"]);
|
||||
if (isset($data->site->server)) {
|
||||
$last_contact = datetime_convert();
|
||||
|
||||
if (isset($data->site->platform)) {
|
||||
$platform = $data->site->platform->PLATFORM_NAME;
|
||||
$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
|
||||
if (!$failure) {
|
||||
$serverret = z_fetch_url($server_url."/statistics.json");
|
||||
|
@ -1221,9 +1221,6 @@ function poco_check_server($server_url, $network = "", $force = false) {
|
|||
} else {
|
||||
$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'])) {
|
||||
$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"]);
|
||||
|
||||
if (isset($data->version)) {
|
||||
$last_contact = datetime_convert();
|
||||
$network = NETWORK_DFRN;
|
||||
|
||||
$noscrape = $data->no_scrape_url;
|
||||
|
@ -1291,13 +1285,14 @@ function poco_check_server($server_url, $network = "", $force = false) {
|
|||
}
|
||||
|
||||
if ($possible_failure AND !$failure) {
|
||||
$last_failure = datetime_convert();
|
||||
$failure = true;
|
||||
}
|
||||
|
||||
if ($failure) {
|
||||
$last_contact = $orig_last_contact;
|
||||
$last_failure = datetime_convert();
|
||||
} else {
|
||||
$last_contact = datetime_convert();
|
||||
$last_failure = $orig_last_failure;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,22 +78,26 @@ function contact_format(item) {
|
|||
}
|
||||
|
||||
function editor_replace(item) {
|
||||
if(typeof item.replace !== 'undefined') {
|
||||
if (typeof item.replace !== 'undefined') {
|
||||
return '$1$2' + item.replace;
|
||||
}
|
||||
|
||||
if (typeof item.addr !== 'undefined') {
|
||||
return '$1$2' + item.addr + ' ';
|
||||
}
|
||||
|
||||
// $2 ensures that prefix (@,@!) is preserved
|
||||
var id = item.id;
|
||||
|
||||
// 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(' ', '') + ' ';
|
||||
|
||||
}
|
||||
// 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).
|
||||
if(id.length > 16)
|
||||
if (id.length > 16) {
|
||||
id = item.id.substring(0,16);
|
||||
|
||||
}
|
||||
return '$1$2' + item.nick.replace(' ', '') + '+' + id + ' ';
|
||||
}
|
||||
|
||||
|
|
|
@ -279,7 +279,7 @@ function admin_page_blocklist(App $a) {
|
|||
$blocklistform[] = array(
|
||||
'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', '', ''),
|
||||
'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"))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@ function _contact_update_profile($contact_id) {
|
|||
if ($uid != local_user())
|
||||
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
|
||||
if ((in_array($data["network"], array(NETWORK_FEED, NETWORK_PHANTOM))) AND ($data["network"] != $r[0]["network"]))
|
||||
|
|
|
@ -11,29 +11,27 @@ require_once('include/crypto.php');
|
|||
require_once('include/diaspora.php');
|
||||
|
||||
function receive_post(App $a) {
|
||||
|
||||
$enabled = intval(get_config('system','diaspora_enabled'));
|
||||
if(! $enabled) {
|
||||
$enabled = intval(get_config('system', 'diaspora_enabled'));
|
||||
if (!$enabled) {
|
||||
logger('mod-diaspora: disabled');
|
||||
http_status_exit(500);
|
||||
}
|
||||
|
||||
$public = false;
|
||||
|
||||
if(($a->argc == 2) && ($a->argv[1] === 'public')) {
|
||||
if (($a->argc == 2) && ($a->argv[1] === 'public')) {
|
||||
$public = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
|
||||
if($a->argc != 3 || $a->argv[1] !== 'users')
|
||||
if ($a->argc != 3 || $a->argv[1] !== 'users') {
|
||||
http_status_exit(500);
|
||||
|
||||
}
|
||||
$guid = $a->argv[2];
|
||||
|
||||
$r = q("SELECT * FROM `user` WHERE `guid` = '%s' AND `account_expired` = 0 AND `account_removed` = 0 LIMIT 1",
|
||||
dbesc($guid)
|
||||
);
|
||||
if (! dbm::is_result($r)) {
|
||||
if (!dbm::is_result($r)) {
|
||||
http_status_exit(500);
|
||||
}
|
||||
|
||||
|
@ -46,29 +44,34 @@ function receive_post(App $a) {
|
|||
|
||||
$xml = urldecode($_POST['xml']);
|
||||
|
||||
logger('mod-diaspora: new salmon ' . $xml, LOGGER_DATA);
|
||||
|
||||
if(! $xml)
|
||||
if (!$xml) {
|
||||
$postdata = file_get_contents("php://input");
|
||||
if ($postdata == '') {
|
||||
http_status_exit(500);
|
||||
}
|
||||
|
||||
logger('mod-diaspora: message is okay', LOGGER_DEBUG);
|
||||
|
||||
$msg = Diaspora::decode($importer,$xml);
|
||||
logger('mod-diaspora: message is in the new format', LOGGER_DEBUG);
|
||||
$msg = Diaspora::decode_raw($importer, $postdata);
|
||||
} 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 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);
|
||||
}
|
||||
|
||||
logger('mod-diaspora: dispatching', LOGGER_DEBUG);
|
||||
|
||||
$ret = 0;
|
||||
if($public) {
|
||||
if ($public) {
|
||||
Diaspora::dispatch_public($msg);
|
||||
} else {
|
||||
$ret = Diaspora::dispatch($importer,$msg);
|
||||
$ret = Diaspora::dispatch($importer, $msg);
|
||||
}
|
||||
|
||||
http_status_exit(($ret) ? $ret : 200);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
define('UPDATE_VERSION' , 1222);
|
||||
define('UPDATE_VERSION' , 1224);
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
4655
util/messages.po
4655
util/messages.po
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
|
@ -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>
|
||||
|
|
@ -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>
|
Loading…
Reference in New Issue
Block a user