mirror of
https://framagit.org/hubzilla/core.git
synced 2026-06-22 17:26:14 -04:00
Compare commits
31 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25620081a1 | ||
|
|
0daccead12 | ||
|
|
e7c83a81c7 | ||
|
|
dcf8830752 | ||
|
|
3d519f478a | ||
|
|
3f0fc40ef8 | ||
|
|
820494c7a6 | ||
|
|
60b82d3690 | ||
|
|
57d9b1b332 | ||
|
|
67f8b78a7d | ||
|
|
aada997601 | ||
|
|
e5dd108bd7 | ||
|
|
ad91ab68ce | ||
|
|
66c3c32154 | ||
|
|
c9ce562369 | ||
|
|
a1f01529a7 | ||
|
|
38985dc4e2 | ||
|
|
e74c52094f | ||
|
|
e05f1f95cf | ||
|
|
b63c5f2785 | ||
|
|
685c569eaf | ||
|
|
b6e3469519 | ||
|
|
16071f300e | ||
|
|
a8de999b7c | ||
|
|
0dcbcf93c2 | ||
|
|
06273e980e | ||
|
|
c879e5de44 | ||
|
|
890290fff0 | ||
|
|
cddae14352 | ||
|
|
b3e6a3c1e2 | ||
|
|
255b6a14a8 |
25
CHANGELOG
25
CHANGELOG
@@ -1,3 +1,28 @@
|
||||
Hubzilla 5.0.2 (2020-11-16)
|
||||
- Fix edge case in acl selector
|
||||
- Fix ping_site()
|
||||
- Fix directory post url
|
||||
- Update russian translation
|
||||
- Implement polling for notifications (default) - SSE can be enabled in /admin/site if desired
|
||||
- DB update to remove hublocs with no hubloc_hash or no hubloc_callback
|
||||
- Do not save actors without an inbox
|
||||
- Fix import_hublocs()
|
||||
|
||||
Addons
|
||||
- Pubcrawl: do not save actors without an inbox
|
||||
- Diaspora: fix issue with diaspora where hublocs without hubloc_hash were stored
|
||||
|
||||
|
||||
Hubzilla 5.0.1 (2020-11-12)
|
||||
- Fix share title size
|
||||
- Fix issue where hublocs could get mixed up between different protocols
|
||||
|
||||
Addons
|
||||
- Pubcrawl: implement authenticated profile fetches which are now partly required in mastodon
|
||||
- Sse: call xchan_query() just once per item
|
||||
- Pubcrawl: reject messages where sender is not the author if ld-signature is not ok
|
||||
|
||||
|
||||
Hubzilla 5.0 (2020-11-05)
|
||||
- Remove unmaintained and deprecated schemas
|
||||
- Deprecate HTML5_Parser library
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
require_once('include/zot.php');
|
||||
|
||||
require_once('include/hubloc.php');
|
||||
|
||||
class Checksites {
|
||||
|
||||
|
||||
@@ -2,12 +2,8 @@
|
||||
|
||||
namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\DReport;
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/queue_fn.php');
|
||||
|
||||
|
||||
class Deliver {
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
@@ -22,72 +18,16 @@ class Deliver {
|
||||
if(! $argv[$x])
|
||||
continue;
|
||||
|
||||
$dresult = null;
|
||||
$r = q("select * from outq where outq_hash = '%s' limit 1",
|
||||
$r = q("select * from outq where outq_hash = '%s'",
|
||||
dbesc($argv[$x])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
|
||||
$notify = json_decode($r[0]['outq_notify'],true);
|
||||
|
||||
// Messages without an outq_msg will need to go via the web, even if it's a
|
||||
// local delivery. This includes conversation requests and refresh packets.
|
||||
|
||||
if(($r[0]['outq_posturl'] === z_root() . '/post') && ($r[0]['outq_msg'])) {
|
||||
logger('deliver: local delivery', LOGGER_DEBUG);
|
||||
|
||||
// local delivery
|
||||
// we should probably batch these and save a few delivery processes
|
||||
|
||||
if($r[0]['outq_msg']) {
|
||||
$m = json_decode($r[0]['outq_msg'],true);
|
||||
if(array_key_exists('message_list',$m)) {
|
||||
foreach($m['message_list'] as $mm) {
|
||||
$msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $mm)))));
|
||||
zot_import($msg,z_root());
|
||||
}
|
||||
}
|
||||
else {
|
||||
$msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $m)))));
|
||||
$dresult = zot_import($msg,z_root());
|
||||
}
|
||||
|
||||
remove_queue_item($r[0]['outq_hash']);
|
||||
|
||||
if($dresult && is_array($dresult)) {
|
||||
|
||||
// delivery reports for local deliveries do not require encryption
|
||||
|
||||
foreach($dresult as $xx) {
|
||||
if(is_array($xx) && array_key_exists('message_id',$xx)) {
|
||||
if(DReport::is_storable($xx)) {
|
||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
|
||||
dbesc($xx['message_id']),
|
||||
dbesc($xx['location']),
|
||||
dbesc($xx['recipient']),
|
||||
dbesc(($xx['name']) ? $xx['name'] : EMPTY_STR),
|
||||
dbesc($xx['status']),
|
||||
dbesc(datetime_convert($xx['date'])),
|
||||
dbesc($xx['sender'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
q("delete from dreport where dreport_queue = '%s'",
|
||||
dbesc($argv[$x])
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// otherwise it's a remote delivery - call queue_deliver() with the $immediate flag
|
||||
|
||||
queue_deliver($r[0],true);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -58,7 +58,8 @@ class Directory {
|
||||
// otherwise send the changes upstream
|
||||
|
||||
$directory = Libzotdir::find_upstream_directory($dirmode);
|
||||
$url = $directory['url'] . '/post';
|
||||
|
||||
$url = $directory['url'] . '/zot';
|
||||
|
||||
// ensure the upstream directory is updated
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Zotlabs\Daemon;
|
||||
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Activity;
|
||||
use Zotlabs\Lib\Queue;
|
||||
|
||||
require_once('include/queue_fn.php');
|
||||
require_once('include/html2plain.php');
|
||||
@@ -734,15 +735,17 @@ class Notifier {
|
||||
}
|
||||
|
||||
if($packet) {
|
||||
queue_insert(array(
|
||||
'hash' => $hash,
|
||||
'account_id' => $channel['channel_account_id'],
|
||||
'channel_id' => $channel['channel_id'],
|
||||
'posturl' => $hub['hubloc_callback'],
|
||||
'driver' => $hub['hubloc_network'],
|
||||
'notify' => $packet,
|
||||
'msg' => (($pmsg) ? json_encode($pmsg) : '')
|
||||
));
|
||||
Queue::insert(
|
||||
[
|
||||
'hash' => $hash,
|
||||
'account_id' => $channel['channel_account_id'],
|
||||
'channel_id' => $channel['channel_id'],
|
||||
'posturl' => $hub['hubloc_callback'],
|
||||
'driver' => $hub['hubloc_network'],
|
||||
'notify' => $packet,
|
||||
'msg' => (($pmsg) ? json_encode($pmsg) : '')
|
||||
]
|
||||
);
|
||||
}
|
||||
else {
|
||||
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
|
||||
@@ -803,7 +806,7 @@ class Notifier {
|
||||
}
|
||||
}
|
||||
|
||||
queue_insert(
|
||||
Queue::insert(
|
||||
[
|
||||
'hash' => $hash,
|
||||
'account_id' => $target_item['aid'],
|
||||
|
||||
@@ -10,6 +10,11 @@ class Ratenotif {
|
||||
|
||||
static public function run($argc,$argv) {
|
||||
|
||||
|
||||
// Deprecated
|
||||
return;
|
||||
|
||||
|
||||
require_once("datetime.php");
|
||||
require_once('include/items.php');
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ class Activity {
|
||||
}
|
||||
else {
|
||||
logger('fetch failed: ' . $url);
|
||||
logger($x['body']);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -1492,6 +1493,14 @@ class Activity {
|
||||
if(! is_array($person_obj))
|
||||
return;
|
||||
|
||||
$inbox = $person_obj['inbox'];
|
||||
|
||||
// invalid identity
|
||||
|
||||
if (! $inbox || strpos($inbox,z_root()) !== false) {
|
||||
return;
|
||||
}
|
||||
|
||||
$name = $person_obj['name'];
|
||||
if(! $name)
|
||||
$name = $person_obj['preferredUsername'];
|
||||
@@ -1539,8 +1548,6 @@ class Activity {
|
||||
$profile = $url;
|
||||
}
|
||||
|
||||
$inbox = $person_obj['inbox'];
|
||||
|
||||
$collections = [];
|
||||
|
||||
if($inbox) {
|
||||
|
||||
@@ -51,7 +51,7 @@ class JSalmon {
|
||||
. base64url_encode($x['encoding'],true) . '.'
|
||||
. base64url_encode($x['alg'],true);
|
||||
|
||||
$key = HTTPSig::get_key(EMPTY_STR,base64url_decode($x['sigs']['key_id']));
|
||||
$key = HTTPSig::get_key(EMPTY_STR,'zot6',base64url_decode($x['sigs']['key_id']));
|
||||
logger('key: ' . print_r($key,true));
|
||||
if($key['portable_id'] && $key['public_key']) {
|
||||
if(rsa_verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
|
||||
|
||||
@@ -93,7 +93,8 @@ class LDSignatures {
|
||||
$d = jsonld_normalize($data,[ 'algorithm' => 'URDNA2015', 'format' => 'application/nquads' ]);
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
logger('normalise error:' . print_r($e,true));
|
||||
// Don't log the exception - this can exhaust memory
|
||||
// logger('normalise error:' . print_r($e,true));
|
||||
logger('normalise error: ' . print_r($data,true));
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ class Share {
|
||||
"' message_id='" . $this->item['mid'] .
|
||||
"']";
|
||||
if($this->item['title'])
|
||||
$bb .= '[b]'.$this->item['title'].'[/b]'."\r\n";
|
||||
$bb .= '[h3][b]'.$this->item['title'].'[/b][/h3]'."\r\n";
|
||||
$bb .= (($is_photo) ? $photo_bb . "\r\n" . $this->item['body'] : $this->item['body']);
|
||||
$bb .= "[/share]";
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ use Zotlabs\Web\HTTPSig;
|
||||
|
||||
class Zotfinger {
|
||||
|
||||
static function exec($resource,$channel = null) {
|
||||
static function exec($resource,$channel = null, $verify = true) {
|
||||
|
||||
if(! $resource) {
|
||||
return false;
|
||||
@@ -41,8 +41,9 @@ class Zotfinger {
|
||||
logger('fetch: ' . print_r($x,true));
|
||||
|
||||
if($x['success']) {
|
||||
|
||||
$result['signature'] = HTTPSig::verify($x);
|
||||
if ($verify) {
|
||||
$result['signature'] = HTTPSig::verify($x, EMPTY_STR, 'zot6');
|
||||
}
|
||||
|
||||
$result['data'] = json_decode($x['body'],true);
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ class Site {
|
||||
$from_email = ((array_key_exists('from_email',$_POST) && trim($_POST['from_email'])) ? trim($_POST['from_email']) : 'Administrator@' . \App::get_hostname());
|
||||
$from_email_name = ((array_key_exists('from_email_name',$_POST) && trim($_POST['from_email_name'])) ? trim($_POST['from_email_name']) : \Zotlabs\Lib\System::get_site_name());
|
||||
|
||||
|
||||
$sse_enabled = ((x($_POST,'sse_enabled')) ? true : false);
|
||||
|
||||
$verifyssl = ((x($_POST,'verifyssl')) ? True : False);
|
||||
$proxyuser = ((x($_POST,'proxyuser')) ? notags(trim($_POST['proxyuser'])) : '');
|
||||
$proxy = ((x($_POST,'proxy')) ? notags(trim($_POST['proxy'])) : '');
|
||||
@@ -151,6 +154,9 @@ class Site {
|
||||
|
||||
set_config('system','no_community_page', $no_community_page);
|
||||
set_config('system','no_utf', $no_utf);
|
||||
|
||||
set_config('system','sse_enabled', $sse_enabled);
|
||||
|
||||
set_config('system','verifyssl', $verifyssl);
|
||||
set_config('system','proxyuser', $proxyuser);
|
||||
set_config('system','proxy', $proxy);
|
||||
@@ -331,6 +337,8 @@ class Site {
|
||||
|
||||
'$directory_server' => (($dir_choices) ? array('directory_server', t("Directory Server URL"), get_config('system','directory_server'), t("Default directory server"), $dir_choices) : null),
|
||||
|
||||
'$sse_enabled' => array('sse_enabled', t('Enable SSE Notifications'), get_config('system', 'sse_enabled', 0), t('If disabled, traditional polling will be used. Warning: this setting might not be suited for shared hosting')),
|
||||
|
||||
'$proxyuser' => array('proxyuser', t("Proxy user"), get_config('system','proxyuser'), ""),
|
||||
'$proxy' => array('proxy', t("Proxy URL"), get_config('system','proxy'), ""),
|
||||
'$timeout' => array('timeout', t("Network timeout"), (x(get_config('system','curl_timeout'))?get_config('system','curl_timeout'):60), t("Value is in seconds. Set to 0 for unlimited (not recommended).")),
|
||||
|
||||
@@ -60,7 +60,7 @@ class Channel extends Controller {
|
||||
|
||||
if(Libzot::is_zot_request()) {
|
||||
|
||||
$sigdata = HTTPSig::verify(file_get_contents('php://input'));
|
||||
$sigdata = HTTPSig::verify(file_get_contents('php://input'), EMPTY_STR, 'zot6');
|
||||
|
||||
if($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
|
||||
$data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'], 'target_url' => $sigdata['signer'] ]));
|
||||
|
||||
@@ -294,8 +294,8 @@ class Connedit extends Controller {
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if(($pr) && (! intval($orig_record[0]['abook_hidden'])) && (intval(get_pconfig($channel['channel_id'],'system','post_newfriend')))) {
|
||||
$xarr = array();
|
||||
$xarr['verb'] = ACTIVITY_FRIEND;
|
||||
$xarr = [];
|
||||
|
||||
$xarr['item_wall'] = 1;
|
||||
$xarr['item_origin'] = 1;
|
||||
$xarr['item_thread_top'] = 1;
|
||||
@@ -305,17 +305,6 @@ class Connedit extends Controller {
|
||||
$xarr['deny_cid'] = $channel['channel_deny_cid'];
|
||||
$xarr['deny_gid'] = $channel['channel_deny_gid'];
|
||||
$xarr['item_private'] = (($xarr['allow_cid']||$xarr['allow_gid']||$xarr['deny_cid']||$xarr['deny_gid']) ? 1 : 0);
|
||||
$obj = array(
|
||||
'type' => ACTIVITY_OBJ_PERSON,
|
||||
'title' => App::$poi['xchan_name'],
|
||||
'id' => App::$poi['xchan_hash'],
|
||||
'link' => array(
|
||||
array('rel' => 'alternate', 'type' => 'text/html', 'href' => App::$poi['xchan_url']),
|
||||
array('rel' => 'photo', 'type' => App::$poi['xchan_photo_mimetype'], 'href' => App::$poi['xchan_photo_l'])
|
||||
),
|
||||
);
|
||||
$xarr['obj'] = json_encode($obj);
|
||||
$xarr['obj_type'] = ACTIVITY_OBJ_PERSON;
|
||||
|
||||
$xarr['body'] = '[zrl=' . $channel['xchan_url'] . ']' . $channel['xchan_name'] . '[/zrl]' . ' ' . t('is now connected to') . ' ' . '[zrl=' . App::$poi['xchan_url'] . ']' . App::$poi['xchan_name'] . '[/zrl]';
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ class Sse extends Controller {
|
||||
public static $ob_hash;
|
||||
public static $sse_id;
|
||||
public static $vnotify;
|
||||
public static $sse_enabled;
|
||||
|
||||
function init() {
|
||||
|
||||
@@ -49,18 +50,86 @@ class Sse extends Controller {
|
||||
$sys = get_sys_channel();
|
||||
$sleep_seconds = 3;
|
||||
|
||||
header("Content-Type: text/event-stream");
|
||||
header("Cache-Control: no-cache");
|
||||
header("Connection: keep-alive");
|
||||
header("X-Accel-Buffering: no");
|
||||
self::$sse_enabled = get_config('system', 'sse_enabled', 0);
|
||||
|
||||
while(true) {
|
||||
if(self::$sse_enabled) {
|
||||
|
||||
/**
|
||||
* Update chat presence indication (if applicable)
|
||||
*/
|
||||
// Server Sent Events
|
||||
|
||||
header("Content-Type: text/event-stream");
|
||||
header("Cache-Control: no-cache");
|
||||
header("Connection: keep-alive");
|
||||
header("X-Accel-Buffering: no");
|
||||
|
||||
while(true) {
|
||||
|
||||
if(! self::$sse_id) {
|
||||
|
||||
// Update chat presence indication
|
||||
|
||||
$r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
|
||||
dbesc(self::$ob_hash),
|
||||
dbesc($_SERVER['REMOTE_ADDR'])
|
||||
);
|
||||
$basic_presence = false;
|
||||
if($r) {
|
||||
$basic_presence = true;
|
||||
q("update chatpresence set cp_last = '%s' where cp_id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
intval($r[0]['cp_id'])
|
||||
);
|
||||
}
|
||||
if(! $basic_presence) {
|
||||
q("insert into chatpresence ( cp_xchan, cp_last, cp_status, cp_client)
|
||||
values( '%s', '%s', '%s', '%s' ) ",
|
||||
dbesc(self::$ob_hash),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc('online'),
|
||||
dbesc($_SERVER['REMOTE_ADDR'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
XConfig::Load(self::$ob_hash);
|
||||
|
||||
$result = XConfig::Get(self::$ob_hash, 'sse', 'notifications', []);
|
||||
$lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
|
||||
|
||||
if($result && !$lock) {
|
||||
echo "event: notifications\n";
|
||||
echo 'data: ' . json_encode($result);
|
||||
echo "\n\n";
|
||||
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
|
||||
unset($result);
|
||||
}
|
||||
|
||||
// always send heartbeat to detect disconnected clients
|
||||
echo "event: heartbeat\n";
|
||||
echo 'data: {}';
|
||||
echo "\n\n";
|
||||
|
||||
ob_end_flush();
|
||||
flush();
|
||||
|
||||
if(connection_status() != CONNECTION_NORMAL || connection_aborted()) {
|
||||
//TODO: this does not seem to be triggered
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'timestamp', NULL_DATE);
|
||||
break;
|
||||
}
|
||||
|
||||
sleep($sleep_seconds);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// Fallback to traditional polling
|
||||
|
||||
if(! self::$sse_id) {
|
||||
|
||||
// Update chat presence indication
|
||||
|
||||
$r = q("select cp_id, cp_room from chatpresence where cp_xchan = '%s' and cp_client = '%s' and cp_room = 0 limit 1",
|
||||
dbesc(self::$ob_hash),
|
||||
dbesc($_SERVER['REMOTE_ADDR'])
|
||||
@@ -90,29 +159,11 @@ class Sse extends Controller {
|
||||
$lock = XConfig::Get(self::$ob_hash, 'sse', 'lock');
|
||||
|
||||
if($result && !$lock) {
|
||||
echo "event: notifications\n";
|
||||
echo 'data: ' . json_encode($result);
|
||||
echo "\n\n";
|
||||
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'notifications', []);
|
||||
unset($result);
|
||||
json_return_and_die($result);
|
||||
}
|
||||
|
||||
// always send heartbeat to detect disconnected clients
|
||||
echo "event: heartbeat\n";
|
||||
echo 'data: {}';
|
||||
echo "\n\n";
|
||||
|
||||
ob_end_flush();
|
||||
flush();
|
||||
|
||||
if(connection_status() != CONNECTION_NORMAL || connection_aborted()) {
|
||||
//TODO: this does not seem to be triggered
|
||||
XConfig::Set(self::$ob_hash, 'sse', 'timestamp', NULL_DATE);
|
||||
break;
|
||||
}
|
||||
|
||||
sleep($sleep_seconds);
|
||||
killme();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class Zot_probe extends \Zotlabs\Web\Controller {
|
||||
|
||||
$o .= '<pre>' . htmlspecialchars($x['header']) . '</pre>' . EOL;
|
||||
|
||||
$o .= 'verify returns: ' . str_replace("\n",EOL,print_r(HTTPSig::verify($x),true)) . EOL;
|
||||
$o .= 'verify returns: ' . str_replace("\n",EOL,print_r(HTTPSig::verify($x, EMPTY_STR, 'zot6'),true)) . EOL;
|
||||
|
||||
$o .= '<pre>' . htmlspecialchars(json_encode(json_decode($x['body']),JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)) . '</pre>' . EOL;
|
||||
|
||||
|
||||
27
Zotlabs/Update/_1239.php
Normal file
27
Zotlabs/Update/_1239.php
Normal file
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Zotlabs\Update;
|
||||
|
||||
class _1239 {
|
||||
|
||||
function run() {
|
||||
|
||||
dbq("START TRANSACTION");
|
||||
|
||||
// remove broken activitypub hubloc entries
|
||||
$r = dbq("DELETE FROM hubloc WHERE hubloc_network = 'activitypub' and hubloc_callback = ''");
|
||||
|
||||
// remove broken hubloc entries from friendica
|
||||
$r1 = dbq("DELETE FROM hubloc WHERE hubloc_hash = ''");
|
||||
|
||||
if($r && $r1) {
|
||||
dbq("COMMIT");
|
||||
return UPDATE_SUCCESS;
|
||||
}
|
||||
|
||||
dbq("ROLLBACK");
|
||||
return UPDATE_FAILED;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -76,7 +76,7 @@ class HTTPSig {
|
||||
|
||||
// See draft-cavage-http-signatures-10
|
||||
|
||||
static function verify($data,$key = '') {
|
||||
static function verify($data,$key = '', $keytype = '') {
|
||||
|
||||
$body = $data;
|
||||
$headers = null;
|
||||
@@ -151,7 +151,7 @@ class HTTPSig {
|
||||
|
||||
$result['signer'] = $sig_block['keyId'];
|
||||
|
||||
$key = self::get_key($key,$result['signer']);
|
||||
$key = self::get_key($key,$keytype,$result['signer']);
|
||||
|
||||
if(! ($key && $key['public_key'])) {
|
||||
return $result;
|
||||
@@ -162,13 +162,26 @@ class HTTPSig {
|
||||
logger('verified: ' . $x, LOGGER_DEBUG);
|
||||
|
||||
if(! $x) {
|
||||
logger('verify failed for ' . $result['signer'] . ' alg=' . $algorithm . (($key['public_key']) ? '' : ' no key'));
|
||||
$sig_block['signature'] = base64_encode($sig_block['signature']);
|
||||
logger('affected sigblock: ' . print_r($sig_block,true));
|
||||
logger('signed_data: ' . print_r($signed_data,true));
|
||||
logger('headers: ' . print_r($headers,true));
|
||||
logger('server: ' . print_r($_SERVER,true));
|
||||
return $result;
|
||||
|
||||
// try again, ignoring the local actor (xchan) cache and refetching the key
|
||||
// from its source
|
||||
|
||||
$fkey = self::get_key($key,$keytype,$result['signer'],true);
|
||||
|
||||
if ($fkey && $fkey['public_key']) {
|
||||
$y = rsa_verify($signed_data,$sig_block['signature'],$fkey['public_key'],$algorithm);
|
||||
logger('verified: (cache reload) ' . $x, LOGGER_DEBUG);
|
||||
}
|
||||
|
||||
if (! $y) {
|
||||
logger('verify failed for ' . $result['signer'] . ' alg=' . $algorithm . (($fkey['public_key']) ? '' : ' no key'));
|
||||
$sig_block['signature'] = base64_encode($sig_block['signature']);
|
||||
logger('affected sigblock: ' . print_r($sig_block,true));
|
||||
logger('headers: ' . print_r($headers,true));
|
||||
logger('server: ' . print_r($_SERVER,true));
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$result['portable_id'] = $key['portable_id'];
|
||||
@@ -187,12 +200,17 @@ class HTTPSig {
|
||||
}
|
||||
|
||||
logger('Content_Valid: ' . (($result['content_valid']) ? 'true' : 'false'));
|
||||
if (! $result['content_valid']) {
|
||||
logger('invalid content signature: data ' . print_r($data,true));
|
||||
logger('invalid content signature: headers ' . print_r($headers,true));
|
||||
logger('invalid content signature: body ' . print_r($body,true));
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
static function get_key($key,$id) {
|
||||
static function get_key($key,$keytype,$id) {
|
||||
|
||||
if($key) {
|
||||
if(function_exists($key)) {
|
||||
@@ -201,6 +219,13 @@ class HTTPSig {
|
||||
return [ 'public_key' => $key ];
|
||||
}
|
||||
|
||||
if($keytype === 'zot6') {
|
||||
$key = self::get_zotfinger_key($id,$force);
|
||||
if($key) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
if(strpos($id,'#') === false) {
|
||||
$key = self::get_webfinger_key($id);
|
||||
}
|
||||
@@ -243,7 +268,7 @@ class HTTPSig {
|
||||
|
||||
$url = ((strpos($id,'#')) ? substr($id,0,strpos($id,'#')) : $id);
|
||||
|
||||
$x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s'",
|
||||
$x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s' and hubloc_network in ('zot6', 'activitypub')",
|
||||
dbesc(str_replace('acct:','',$url)),
|
||||
dbesc($url)
|
||||
);
|
||||
@@ -303,18 +328,15 @@ class HTTPSig {
|
||||
return (($key['public_key']) ? $key : false);
|
||||
}
|
||||
|
||||
|
||||
function get_zotfinger_key($id) {
|
||||
|
||||
$x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s'",
|
||||
$x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_addr = '%s' or hubloc_id_url = '%s' and hubloc_network = 'zot6'",
|
||||
dbesc(str_replace('acct:','',$id)),
|
||||
dbesc($id)
|
||||
);
|
||||
|
||||
$x = Libzot::zot_record_preferred($x);
|
||||
|
||||
if($x && $x['xchan_pubkey']) {
|
||||
return [ 'portable_id' => $x['xchan_hash'], 'public_key' => $x['xchan_pubkey'] , 'hubloc' => $x ];
|
||||
if($x && $x[0]['xchan_pubkey']) {
|
||||
return [ 'portable_id' => $x[0]['xchan_hash'], 'public_key' => $x[0]['xchan_pubkey'] , 'hubloc' => $x[0] ];
|
||||
}
|
||||
|
||||
$wf = Webfinger::exec($id);
|
||||
@@ -330,13 +352,18 @@ class HTTPSig {
|
||||
continue;
|
||||
}
|
||||
if($l['rel'] === 'http://purl.org/zot/protocol/6.0' && array_key_exists('href',$l) && $l['href'] !== EMPTY_STR) {
|
||||
$z = \Zotlabs\Lib\Zotfinger::exec($l['href']);
|
||||
|
||||
// The third argument to Zotfinger::exec() tells it not to verify signatures
|
||||
// Since we're inside a function that is fetching keys with which to verify signatures,
|
||||
// this is necessary to prevent infinite loops.
|
||||
|
||||
$z = \Zotlabs\Lib\Zotfinger::exec($l['href'],null,false);
|
||||
if($z) {
|
||||
$i = Libzot::import_xchan($z['data']);
|
||||
if($i['success']) {
|
||||
$key['portable_id'] = $i['hash'];
|
||||
|
||||
$x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' limit 1",
|
||||
$x = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' and hubloc_network = 'zot6'",
|
||||
dbesc($l['href'])
|
||||
);
|
||||
if($x) {
|
||||
@@ -485,7 +512,6 @@ class HTTPSig {
|
||||
|
||||
if(preg_match('/iv="(.*?)"/ism',$header,$matches))
|
||||
$header = self::decrypt_sigheader($header);
|
||||
|
||||
if(preg_match('/keyId="(.*?)"/ism',$header,$matches))
|
||||
$ret['keyId'] = $matches[1];
|
||||
if(preg_match('/algorithm="(.*?)"/ism',$header,$matches))
|
||||
|
||||
@@ -155,7 +155,7 @@ class Receiver {
|
||||
|
||||
$result = false;
|
||||
|
||||
$this->sigdata = HTTPSig::verify($this->rawdata);
|
||||
$this->sigdata = HTTPSig::verify($this->rawdata, EMPTY_STR, 'zot6');
|
||||
|
||||
if ($this->sigdata && $this->sigdata['header_signed'] && $this->sigdata['header_valid']) {
|
||||
$result = true;
|
||||
|
||||
5
boot.php
5
boot.php
@@ -50,10 +50,10 @@ require_once('include/attach.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
define ( 'PLATFORM_NAME', 'hubzilla' );
|
||||
define ( 'STD_VERSION', '5.0' );
|
||||
define ( 'STD_VERSION', '5.0.2' );
|
||||
define ( 'ZOT_REVISION', '6.0' );
|
||||
|
||||
define ( 'DB_UPDATE_VERSION', 1238 );
|
||||
define ( 'DB_UPDATE_VERSION', 1239 );
|
||||
|
||||
define ( 'PROJECT_BASE', __DIR__ );
|
||||
|
||||
@@ -1207,6 +1207,7 @@ class App {
|
||||
'$metas' => self::$meta->get(),
|
||||
'$plugins' => $x['header'],
|
||||
'$update_interval' => $interval,
|
||||
'$sse_enabled' => get_config('system', 'sse_enabled', 0),
|
||||
'$head_css' => head_get_css(),
|
||||
'$head_js' => head_get_js(),
|
||||
'$linkrel' => head_get_links(),
|
||||
|
||||
@@ -288,30 +288,18 @@ function locations_by_netid($netid) {
|
||||
|
||||
function ping_site($url) {
|
||||
|
||||
$ret = array('success' => false);
|
||||
$ret = array('success' => false);
|
||||
|
||||
$sys = get_sys_channel();
|
||||
|
||||
$m = zot_build_packet($sys, 'ping');
|
||||
$r = zot_zot($url . '/post', $m);
|
||||
if(! $r['success']) {
|
||||
$ret['message'] = 'no answer from ' . $url;
|
||||
return $ret;
|
||||
}
|
||||
$packet_result = json_decode($r['body'], true);
|
||||
if(! $packet_result['success']) {
|
||||
$ret['message'] = 'packet failure from ' . $url;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if($packet_result['success']) {
|
||||
$ret['success'] = true;
|
||||
}
|
||||
else {
|
||||
$ret['message'] = 'unknown error from ' . $url;
|
||||
}
|
||||
$r = Zotlabs\Lib\Zotfinger::exec($url);
|
||||
|
||||
if(! $r['data']) {
|
||||
$ret['message'] = 'no answer from ' . $url;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$ret['success'] = true;
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -210,17 +210,24 @@ function import_hublocs($channel, $hublocs, $seize, $moving = false) {
|
||||
if($channel && $hublocs) {
|
||||
foreach($hublocs as $hubloc) {
|
||||
|
||||
$hash = make_xchan_hash($hubloc['hubloc_guid'],$hubloc['hubloc_guid_sig']);
|
||||
if($hubloc['hubloc_network'] === 'zot' && $hash !== $hubloc['hubloc_hash']) {
|
||||
logger('forged hubloc: ' . print_r($hubloc,true));
|
||||
continue;
|
||||
}
|
||||
// verify the hash. We can only do this if we already stored the xchan corresponding to this hubloc
|
||||
// as we need the public key from there
|
||||
|
||||
if(! array_key_exists('hubloc_primary',$hubloc)) {
|
||||
$hubloc['hubloc_primary'] = (($hubloc['hubloc_flags'] & 0x0001) ? 1 : 0);
|
||||
$hubloc['hubloc_orphancheck'] = (($hubloc['hubloc_flags'] & 0x0004) ? 1 : 0);
|
||||
$hubloc['hubloc_error'] = (($hubloc['hubloc_status'] & 0x0003) ? 1 : 0);
|
||||
$hubloc['hubloc_deleted'] = (($hubloc['hubloc_flags'] & 0x1000) ? 1 : 0);
|
||||
if ($hubloc['hubloc_network'] === 'zot6') {
|
||||
$x = q("select xchan_pubkey from xchan where xchan_guid = '%s' and xchan_hash = '%s'",
|
||||
dbesc($hubloc['hubloc_guid']),
|
||||
dbesc($hubloc['hubloc_hash'])
|
||||
);
|
||||
|
||||
if (! $x) {
|
||||
logger('hubloc could not be verified. ' . print_r($hubloc,true));
|
||||
continue;
|
||||
}
|
||||
$hash = Libzot::make_xchan_hash($hubloc['hubloc_guid'],$x[0]['xchan_pubkey']);
|
||||
if ($hash !== $hubloc['hubloc_hash']) {
|
||||
logger('forged hubloc: ' . print_r($hubloc,true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if($moving && $hubloc['hubloc_hash'] === $channel['channel_hash'] && $hubloc['hubloc_url'] !== z_root()) {
|
||||
@@ -228,17 +235,17 @@ function import_hublocs($channel, $hublocs, $seize, $moving = false) {
|
||||
}
|
||||
|
||||
$arr = [
|
||||
'guid' => $hubloc['hubloc_guid'],
|
||||
'guid_sig' => $hubloc['hubloc_guid_sig'],
|
||||
'url' => $hubloc['hubloc_url'],
|
||||
'url_sig' => $hubloc['hubloc_url_sig'],
|
||||
'sitekey' => ((array_key_exists('hubloc_sitekey',$hubloc)) ? $hubloc['hubloc_sitekey'] : '')
|
||||
'id' => $hubloc['hubloc_guid'],
|
||||
'id_sig' => $hubloc['hubloc_guid_sig'],
|
||||
'location' => $hubloc['hubloc_url'],
|
||||
'location_sig' => $hubloc['hubloc_url_sig']
|
||||
];
|
||||
|
||||
if(($hubloc['hubloc_hash'] === $channel['channel_hash']) && intval($hubloc['hubloc_primary']) && ($seize))
|
||||
if (($hubloc['hubloc_hash'] === $channel['channel_hash']) && intval($hubloc['hubloc_primary']) && ($seize)) {
|
||||
$hubloc['hubloc_primary'] = 0;
|
||||
}
|
||||
|
||||
if(($x = zot_gethub($arr,false)) === false) {
|
||||
if (($x = Libzot::gethub($arr,false)) === false) {
|
||||
unset($hubloc['hubloc_id']);
|
||||
hubloc_store_lowlevel($hubloc);
|
||||
}
|
||||
@@ -1333,7 +1340,7 @@ function sync_files($channel, $files) {
|
||||
'time' => $time,
|
||||
'resource' => $att['hash'],
|
||||
'revision' => 0,
|
||||
'signature' => base64url_encode(rsa_sign($channel['channel_hash'] . '.' . $time, $channel['channel_prvkey']))
|
||||
'signature' => Libzot::sign($channel['channel_hash'] . '.' . $time, $channel['channel_prvkey'])
|
||||
);
|
||||
|
||||
$store_path = $newfname;
|
||||
@@ -1419,7 +1426,7 @@ function sync_files($channel, $files) {
|
||||
'time' => $time,
|
||||
'resource' => $p['resource_id'],
|
||||
'revision' => 0,
|
||||
'signature' => base64url_encode(rsa_sign($channel['channel_hash'] . '.' . $time, $channel['channel_prvkey'])),
|
||||
'signature' => Libzot::sign($channel['channel_hash'] . '.' . $time, $channel['channel_prvkey']),
|
||||
'resolution' => intval($p['imgscale'])
|
||||
);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
use Zotlabs\Lib\Zotfinger;
|
||||
use Zotlabs\Lib\Libzot;
|
||||
use Zotlabs\Lib\Queue;
|
||||
|
||||
/**
|
||||
* @file include/network.php
|
||||
@@ -1437,10 +1438,10 @@ function do_delivery($deliveries, $force = false) {
|
||||
|
||||
|
||||
$x = q("select count(outq_hash) as total from outq where outq_delivered = 0");
|
||||
if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300)) && (! $force)) {
|
||||
if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',3000)) && (! $force)) {
|
||||
logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
|
||||
foreach($deliveries as $d) {
|
||||
update_queue_item($d);
|
||||
Queue::update($d);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3452,7 +3452,7 @@ function build_sync_packet($uid = 0, $packet = null, $groups_changed = false) {
|
||||
|
||||
|
||||
$x = q("select count(outq_hash) as total from outq where outq_delivered = 0");
|
||||
if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300))) {
|
||||
if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',3000))) {
|
||||
logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
|
||||
update_queue_item($hash);
|
||||
continue;
|
||||
@@ -4286,7 +4286,7 @@ function zot_reply_message_request($data) {
|
||||
|
||||
|
||||
$x = q("select count(outq_hash) as total from outq where outq_delivered = 0");
|
||||
if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',300))) {
|
||||
if(intval($x[0]['total']) > intval(get_config('system','force_queue_threshold',3000))) {
|
||||
logger('immediate delivery deferred.', LOGGER_DEBUG, LOG_INFO);
|
||||
update_queue_item($hash);
|
||||
continue;
|
||||
|
||||
@@ -23,10 +23,6 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: es_ES\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1 ? 1 : 0);\n"
|
||||
#: ../../view/theme/redbasic/php/config.php:15 ../../include/text.php:3231
|
||||
#: ../../Zotlabs/Module/Admin/Site.php:187
|
||||
msgid "Default"
|
||||
msgstr "Predeterminado"
|
||||
|
||||
#: ../../view/theme/redbasic/php/config.php:15
|
||||
#: ../../addon/cart/submodules/orderoptions.php:335
|
||||
|
||||
@@ -340,7 +340,13 @@ ACL.prototype.update_view = function(value) {
|
||||
that.list.hide(); //hide acl-list
|
||||
that.info.hide(); //show acl-info
|
||||
that.selected_id = that.contact_ids[that.allow_cid[0]];
|
||||
that.update_select('\\^' + that.selected_id);
|
||||
|
||||
if(that.acl_select.find('option[id="\\^' + that.selected_id + '"]').length === 0) {
|
||||
that.update_view('custom');
|
||||
}
|
||||
else {
|
||||
that.update_select('\\^' + that.selected_id);
|
||||
}
|
||||
|
||||
/* jot acl */
|
||||
$('#jot-perms-icon, #dialog-perms-icon, #' + that.form_id[0].id + ' .jot-perms-icon').removeClass('fa-unlock').addClass('fa-lock');
|
||||
|
||||
@@ -31,6 +31,7 @@ var sse_offset = 0;
|
||||
var sse_type;
|
||||
var sse_partial_result = false;
|
||||
var sse_rmids = [];
|
||||
var sse_fallback_interval;
|
||||
|
||||
var page_cache = {};
|
||||
|
||||
@@ -94,37 +95,56 @@ $(document).ready(function() {
|
||||
|
||||
jQuery.timeago.settings.allowFuture = true;
|
||||
|
||||
if(typeof(window.SharedWorker) === 'undefined') {
|
||||
// notifications with multiple tabs open will not work very well in this scenario
|
||||
var evtSource = new EventSource('/sse');
|
||||
|
||||
evtSource.addEventListener('notifications', function(e) {
|
||||
var obj = JSON.parse(e.data);
|
||||
sse_handleNotifications(obj, false, false);
|
||||
}, false);
|
||||
if(sse_enabled) {
|
||||
if(typeof(window.SharedWorker) === 'undefined') {
|
||||
// notifications with multiple tabs open will not work very well in this scenario
|
||||
var evtSource = new EventSource('/sse');
|
||||
|
||||
document.addEventListener('visibilitychange', function() {
|
||||
if (!document.hidden) {
|
||||
sse_offset = 0;
|
||||
sse_bs_init();
|
||||
evtSource.addEventListener('notifications', function(e) {
|
||||
var obj = JSON.parse(e.data);
|
||||
sse_handleNotifications(obj, false, false);
|
||||
}, false);
|
||||
|
||||
document.addEventListener('visibilitychange', function() {
|
||||
if (!document.hidden) {
|
||||
sse_offset = 0;
|
||||
sse_bs_init();
|
||||
}
|
||||
}, false);
|
||||
|
||||
}
|
||||
else {
|
||||
var myWorker = new SharedWorker('/view/js/sse_worker.js', localUser);
|
||||
|
||||
myWorker.port.onmessage = function(e) {
|
||||
obj = e.data;
|
||||
console.log(obj);
|
||||
sse_handleNotifications(obj, false, false);
|
||||
}
|
||||
}, false);
|
||||
|
||||
myWorker.onerror = function(e) {
|
||||
myWorker.port.close();
|
||||
}
|
||||
|
||||
myWorker.port.start();
|
||||
}
|
||||
}
|
||||
else {
|
||||
var myWorker = new SharedWorker('/view/js/sse_worker.js', localUser);
|
||||
if (!document.hidden)
|
||||
sse_fallback_interval = setInterval(sse_fallback, updateInterval);
|
||||
|
||||
myWorker.port.onmessage = function(e) {
|
||||
obj = e.data;
|
||||
console.log(obj);
|
||||
sse_handleNotifications(obj, false, false);
|
||||
}
|
||||
document.addEventListener('visibilitychange', function() {
|
||||
if (document.hidden) {
|
||||
clearInterval(sse_fallback_interval);
|
||||
}
|
||||
else {
|
||||
sse_offset = 0;
|
||||
sse_bs_init();
|
||||
sse_fallback_interval = setInterval(sse_fallback, updateInterval);
|
||||
}
|
||||
|
||||
myWorker.onerror = function(e) {
|
||||
myWorker.port.close();
|
||||
}
|
||||
|
||||
myWorker.port.start();
|
||||
}, false);
|
||||
}
|
||||
|
||||
$('.notification-link').on('click', { replace: true, followup: false }, sse_bs_notifications);
|
||||
@@ -224,6 +244,8 @@ $(document).ready(function() {
|
||||
cache_next_page();
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
function getConversationSettings() {
|
||||
@@ -1763,8 +1785,6 @@ function sse_bs_init() {
|
||||
}
|
||||
|
||||
function sse_bs_counts() {
|
||||
|
||||
|
||||
if(sse_bs_active)
|
||||
return;
|
||||
|
||||
@@ -2022,3 +2042,15 @@ function sse_setNotificationsStatus() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function sse_fallback() {
|
||||
$.get('/sse', function(obj) {
|
||||
if(! obj)
|
||||
return;
|
||||
|
||||
console.log('sse fallback');
|
||||
console.log(obj);
|
||||
|
||||
sse_handleNotifications(obj, false, false);
|
||||
});
|
||||
}
|
||||
|
||||
1799
view/ru/hmessages.po
1799
view/ru/hmessages.po
File diff suppressed because it is too large
Load Diff
@@ -403,7 +403,6 @@ App::$strings["PHP"] = "";
|
||||
App::$strings["Page content type"] = "Тип содержимого страницы";
|
||||
App::$strings["photo"] = "фото";
|
||||
App::$strings["event"] = "событие";
|
||||
App::$strings["status"] = "статус";
|
||||
App::$strings["comment"] = "комментарий";
|
||||
App::$strings["activity"] = "активность";
|
||||
App::$strings["poll"] = "голосование";
|
||||
@@ -707,7 +706,7 @@ App::$strings["%d years"] = array(
|
||||
App::$strings["timeago.prefixAgo"] = "";
|
||||
App::$strings["timeago.prefixFromNow"] = "через";
|
||||
App::$strings["timeago.suffixAgo"] = "назад";
|
||||
App::$strings["timeago.suffixFromNow"] = "";
|
||||
App::$strings["timeago.suffixFromNow"] = "NONE";
|
||||
App::$strings["less than a minute"] = "менее чем одну минуту";
|
||||
App::$strings["about a minute"] = "около минуты";
|
||||
App::$strings["about an hour"] = "около часа";
|
||||
@@ -803,13 +802,15 @@ App::$strings["__ctx:relative_date__ second"] = array(
|
||||
App::$strings["%1\$s's birthday"] = "День рождения %1\$s";
|
||||
App::$strings["Happy Birthday %1\$s"] = "С Днем рождения %1\$s !";
|
||||
App::$strings["Visible to your default audience"] = "Видно вашей аудитории по умолчанию.";
|
||||
App::$strings["__ctx:acl__ Profile"] = "Профиль";
|
||||
App::$strings["Profile-Based Privacy Groups"] = "Группы конфиденциальности основанные на профиле";
|
||||
App::$strings["Forums"] = "Форумы";
|
||||
App::$strings["Private Forum"] = "Частный форум";
|
||||
App::$strings["Only me"] = "Только мне";
|
||||
App::$strings["Who can see this?"] = "Кто может это видеть?";
|
||||
App::$strings["Share with"] = "Поделиться с";
|
||||
App::$strings["Custom selection"] = "Настраиваемый выбор";
|
||||
App::$strings["Select \"Show\" to allow viewing. \"Don't show\" lets you override and limit the scope of \"Show\"."] = "Нажмите \"Показать\" чтобы разрешить просмотр. \"Не показывать\" позволит вам переопределить и ограничить область показа.";
|
||||
App::$strings["Show"] = "Показать";
|
||||
App::$strings["Don't show"] = "Не показывать";
|
||||
App::$strings["Select \"Allow\" to allow viewing. \"Don't allow\" lets you override and limit the scope of \"Allow\"."] = "Выберите \"Разрешить\" для разрешения просмотра. \"Не разрешать\" позволяет вам переопределить и ограничить разрешения.";
|
||||
App::$strings["Allow"] = "Разрешить";
|
||||
App::$strings["Don't allow"] = "Не разрешать";
|
||||
App::$strings["Permissions"] = "Разрешения";
|
||||
App::$strings["Close"] = "Закрыть";
|
||||
App::$strings["Post permissions %s cannot be changed %s after a post is shared.</br />These permissions set who is allowed to view the post."] = "Разрешения публикации %s не могут быть изменены %s после того, как ею поделились. Эти разрешения устанавливают кому разрешено просматривать эту публикацию.";
|
||||
@@ -1007,6 +1008,7 @@ App::$strings["Validation token"] = "Проверочный токен";
|
||||
App::$strings["No channel."] = "Канала нет.";
|
||||
App::$strings["No connections in common."] = "Общих контактов нет.";
|
||||
App::$strings["View Common Connections"] = "Просмотр общий контактов";
|
||||
App::$strings["__ctx:acl__ Profile"] = "Профиль";
|
||||
App::$strings["network"] = "сеть";
|
||||
App::$strings["Unable to locate original post."] = "Не удалось найти оригинальную публикацию.";
|
||||
App::$strings["Empty post discarded."] = "Пустая публикация отклонена.";
|
||||
@@ -1345,7 +1347,6 @@ App::$strings["Failed to remove event"] = "Не удалось удалить с
|
||||
App::$strings["Unknown App"] = "Неизвестное приложение";
|
||||
App::$strings["Authorize"] = "Авторизовать";
|
||||
App::$strings["Do you authorize the app %s to access your channel data?"] = "Авторизуете ли вы приложение %s для доступа к данным вашего канала?";
|
||||
App::$strings["Allow"] = "Разрешить";
|
||||
App::$strings["Deny"] = "Запретить";
|
||||
App::$strings["Public Stream App"] = "Приложение \"Публичный поток\"";
|
||||
App::$strings["The unmoderated public stream of this hub"] = "Немодерируемый публичный поток с этого хаба";
|
||||
@@ -1686,6 +1687,7 @@ App::$strings["Invalid request."] = "Неверный запрос.";
|
||||
App::$strings["thing"] = "предмет";
|
||||
App::$strings["Channel unavailable."] = "Канал недоступен.";
|
||||
App::$strings["Previous action reversed."] = "Предыдущее действие отменено.";
|
||||
App::$strings["status"] = "статус";
|
||||
App::$strings["%1\$s agrees with %2\$s's %3\$s"] = "%1\$s согласен с %2\$s %3\$s";
|
||||
App::$strings["%1\$s doesn't agree with %2\$s's %3\$s"] = "%1\$s не согласен с %2\$s %3\$s";
|
||||
App::$strings["%1\$s abstains from a decision on %2\$s's %3\$s"] = "%1\$s воздерживается от решения по %2\$s%3\$s";
|
||||
@@ -1701,7 +1703,8 @@ App::$strings["My Bookmarks"] = "Мои закладки";
|
||||
App::$strings["My Connections Bookmarks"] = "Закладки моих контактов";
|
||||
App::$strings["Update to Hubzilla 5.0 step 2"] = "Обновление Hubzilla 5.0, этап 2";
|
||||
App::$strings["To complete the update please run"] = "Для завершения обновления пожалуйста выполните";
|
||||
App::$strings["INFO: this command can take a very long time depending on your DB size."] = "К сведению: эта команда может выполняться очень долго в зависимости от размеры базы данных.";
|
||||
App::$strings["php util/z6convert.php"] = "";
|
||||
App::$strings["from the terminal."] = "из терминала.";
|
||||
App::$strings["Item not available."] = "Элемент недоступен.";
|
||||
App::$strings["Remote Diagnostics App"] = "Приложение \"Удалённая диагностика\"";
|
||||
App::$strings["Perform diagnostics on remote channels"] = "Производит диагностику удалённых каналов";
|
||||
@@ -1711,8 +1714,6 @@ App::$strings["Channel removals are not allowed within 48 hours of changing the
|
||||
App::$strings["Remove This Channel"] = "Удалить этот канал";
|
||||
App::$strings["This channel will be completely removed from the network. "] = "Этот канал будет полностью удалён из сети. ";
|
||||
App::$strings["This action is permanent and can not be undone!"] = "Это действие необратимо и не может быть отменено!";
|
||||
App::$strings["Remove this channel and all its clones from the network"] = "Удалить этот канал и все его клоны из сети";
|
||||
App::$strings["By default only the instance of the channel located on this hub will be removed from the network"] = "По умолчанию только представление канала расположенное на данном хабе будет удалено из сети";
|
||||
App::$strings["Unable to update menu."] = "Невозможно обновить меню.";
|
||||
App::$strings["Unable to create menu."] = "Невозможно создать меню.";
|
||||
App::$strings["Menu Name"] = "Название меню";
|
||||
@@ -2028,6 +2029,8 @@ App::$strings["Sender (From) email address for system generated email."] = "Ад
|
||||
App::$strings["Name of email sender for system generated email."] = "Имя отправителя для генерируемых системой сообщений.";
|
||||
App::$strings["Directory Server URL"] = "URL сервера каталогов";
|
||||
App::$strings["Default directory server"] = "Сервер каталогов по умолчанию";
|
||||
App::$strings["Enable SSE Notifications"] = "Включить уведомления SSE";
|
||||
App::$strings["If disabled, traditional polling will be used. Warning: this setting might not be suited for shared hosting"] = "Если выключено будет использоваться традиционный периодический опрос. Предупреждение: этот режим не подходит для виртуального (shared) хостинга";
|
||||
App::$strings["Proxy user"] = "Имя пользователя proxy-сервера";
|
||||
App::$strings["Proxy URL"] = "URL proxy-сервера";
|
||||
App::$strings["Network timeout"] = "Время ожидания сети";
|
||||
@@ -2453,7 +2456,6 @@ App::$strings["Move this channel (disable all previous locations)"] = "Пере
|
||||
App::$strings["Use this channel nickname instead of the one provided"] = "Использовать псевдоним этого канала вместо предоставленного";
|
||||
App::$strings["Leave blank to keep your existing channel nickname. You will be randomly assigned a similar nickname if either name is already allocated on this site."] = "Оставьте пустым для сохранения существующего псевдонима канала. Вам будет случайным образом назначен похожий псевдоним если такое имя уже выделено на этом сайте.";
|
||||
App::$strings["This process may take several minutes to complete. Please submit the form only once and leave this page open until finished."] = "Процесс может занять несколько минут. Пожалуйста, отправьте форму только один раз и оставьте эту страницу открытой до завершения.";
|
||||
App::$strings["Hub not found."] = "Узел не найден.";
|
||||
App::$strings["Warning: Database versions differ by %1\$d updates."] = "Предупреждение: Версия базы данных отличается от %1\$d обновления.";
|
||||
App::$strings["Import completed"] = "Импорт завершён.";
|
||||
App::$strings["Import Items"] = "Импортировать объекты";
|
||||
@@ -2474,8 +2476,6 @@ App::$strings["Add Card"] = "Добавить карточку";
|
||||
App::$strings["Account removals are not allowed within 48 hours of changing the account password."] = "Удаление канала не разрешается в течении 48 часов после смены пароля у аккаунта.";
|
||||
App::$strings["Remove This Account"] = "Удалить этот аккаунт";
|
||||
App::$strings["This account and all its channels will be completely removed from the network. "] = "Этот аккаунт и все его каналы будут полностью удалены из сети.";
|
||||
App::$strings["Remove this account, all its channels and all its channel clones from the network"] = "Удалить этот аккаунт, все его каналы и их клоны из сети.";
|
||||
App::$strings["By default only the instances of the channels located on this hub will be removed from the network"] = "По умолчанию только представление канала расположенное на данном хабе будет удалено из сети";
|
||||
App::$strings["Unable to find your hub."] = "Невозможно найти ваш сервер";
|
||||
App::$strings["Post successful."] = "Успешно опубликовано.";
|
||||
App::$strings["Authentication failed."] = "Ошибка аутентификации.";
|
||||
@@ -2497,7 +2497,6 @@ App::$strings["Visit your channel homepage"] = "Посетить страниц
|
||||
App::$strings["View your connections and/or add somebody whose address you already know"] = "Просмотреть ваши контакты и / или добавить кого-то чей адрес в уже знаете";
|
||||
App::$strings["View your personal stream (this may be empty until you add some connections)"] = "Ваш персональный поток (может быть пуст пока вы не добавите контакты)";
|
||||
App::$strings["View the public stream. Warning: this content is not moderated"] = "Просмотр публичного потока. Предупреждение: этот контент не модерируется";
|
||||
App::$strings["Forums"] = "Форумы";
|
||||
App::$strings["Notes"] = "Записки";
|
||||
App::$strings["Suggestions"] = "Рекомендации";
|
||||
App::$strings["See more..."] = "Просмотреть больше...";
|
||||
@@ -2602,6 +2601,7 @@ App::$strings["via"] = "через";
|
||||
App::$strings["Attendance Options"] = "Параметры посещаемости";
|
||||
App::$strings["Voting Options"] = "Параметры голосования";
|
||||
App::$strings["Pinned post"] = "Прикреплённая заметка";
|
||||
App::$strings["Don't show"] = "Не показывать";
|
||||
App::$strings["Events Tools"] = "Инструменты для событий";
|
||||
App::$strings["Export Calendar"] = "Экспортировать календарь";
|
||||
App::$strings["Import Calendar"] = "Импортировать календарь";
|
||||
@@ -2630,7 +2630,7 @@ App::$strings["Show posts to this forum"] = "Показывать публика
|
||||
App::$strings["Show forums"] = "Показывать форумы";
|
||||
App::$strings["Starred Posts"] = "Отмеченные публикации";
|
||||
App::$strings["Show posts that I have starred"] = "Показывать публикации которые я отметил";
|
||||
App::$strings["Personal Posts"] = "Личные публикации";
|
||||
App::$strings["Personal Posts"] = "Свои публикации";
|
||||
App::$strings["Show posts that mention or involve me"] = "Показывать публикации где вы были упомянуты или привлечены";
|
||||
App::$strings["Show posts that I have filed to %s"] = "Показывать публикации которые я добавил в %s";
|
||||
App::$strings["Show filed post categories"] = "Показывать категории добавленных публикаций";
|
||||
@@ -2753,6 +2753,7 @@ App::$strings["commented on %s's post"] = "прокомментировал пу
|
||||
App::$strings["repeated %s's post"] = "разместил публикацию %s";
|
||||
App::$strings["edited a post dated %s"] = "отредактировал публикацию датированную %s";
|
||||
App::$strings["edited a comment dated %s"] = "отредактировал комментарий датированный %s";
|
||||
App::$strings["created an event"] = "создано событие";
|
||||
App::$strings["(No Title)"] = "(нет заголовка)";
|
||||
App::$strings["Wiki page create failed."] = "Не удалось создать страницу Wiki.";
|
||||
App::$strings["Wiki not found."] = "Wiki не найдена.";
|
||||
|
||||
@@ -95,6 +95,7 @@
|
||||
</div>
|
||||
|
||||
<h3>{{$advanced}}</h3>
|
||||
{{include file="field_checkbox.tpl" field=$sse_enabled}}
|
||||
{{include file="field_input.tpl" field=$imagick_path}}
|
||||
{{include file="field_input.tpl" field=$proxy}}
|
||||
{{include file="field_input.tpl" field=$proxyuser}}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
{{$plugins}}
|
||||
<script>
|
||||
var updateInterval = {{$update_interval}};
|
||||
var sse_enabled = {{$sse_enabled}};
|
||||
var localUser = {{if $local_channel}}{{$local_channel}}{{else}}false{{/if}};
|
||||
var zid = {{if $zid}}'{{$zid}}'{{else}}null{{/if}};
|
||||
var justifiedGalleryActive = false;
|
||||
|
||||
Reference in New Issue
Block a user