1
0
Fork 0

Merge remote-tracking branch 'upstream/develop' into user-contact

This commit is contained in:
Michael 2021-10-02 11:57:43 +00:00
commit 865006682a
54 changed files with 4237 additions and 4188 deletions

View file

@ -33,6 +33,7 @@ return $config
'operators' => [
'=>' => 'align_single_space_minimal',
'=' => 'align_single_space_minimal',
'??' => 'align_single_space_minimal',
],
],
'blank_line_after_namespace' => true,
@ -65,6 +66,7 @@ return $config
'single_import_per_statement' => true,
'single_line_after_imports' => true,
'switch_case_space' => true,
'ternary_operator_spaces' => false,
'visibility_required' => [
'elements' => ['property', 'method']
],

6
Vagrantfile vendored
View file

@ -6,8 +6,8 @@ server_timezone = "UTC"
public_folder = "/vagrant"
Vagrant.configure(2) do |config|
# Set server to Debian 10 / Buster 64bit
config.vm.box = "debian/buster64"
# Set server to Debian 11 / Bullseye 64bit
config.vm.box = "debian/bullseye64"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
@ -24,7 +24,7 @@ Vagrant.configure(2) do |config|
# Share a folder between host and guest
# config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", owner: "www-data", group: "vagrant"
config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", owner: "www-data", group: "www-data"
config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", owner: "www-data", group: "www-data", type: "virtualbox"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.

View file

@ -82,7 +82,7 @@ echo ">>> Installing 'Local Only' postfix"
debconf-set-selections <<< "postfix postfix/mailname string friendica.local"
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Local Only'"
apt-get install -qq postfix mailutils libmailutils-dev
echo -e "friendica1: vagrant\nfriendica2: vagrant\nfriendica3: vagrant\nfriendica4: vagrant\nfriendica5: vagrant" >> /etc/aliases && newaliases
echo -e "$ADMIN_NICK: vagrant\n$USER_NICK: vagrant" >> /etc/aliases && newaliases
# Friendica needs git for fetching some dependencies
echo ">>> Installing git"
@ -93,13 +93,8 @@ echo ">>> Symlink /var/www to /vagrant"
rm -rf /var/www/
ln -fs /vagrant /var/www
# install deps with composer
echo ">>> Installing php requirements"
apt install unzip
# Setup Friendica
cd /var/www
php bin/composer.phar install
echo ">>> Setup Friendica"
# copy the .htaccess-dist file to .htaccess so that rewrite rules work
@ -120,10 +115,6 @@ bin/console user password "$ADMIN_NICK" "$ADMIN_PASSW"
bin/console user add "$USER_NICK" "$USER_NICK" "$USER_NICK@friendica.local" en
bin/console user password "$USER_NICK" "$USER_PASSW"
# set the admin
bin/console config config admin_email ""$ADMIN_NICK@friendica.local""
# create cronjob - activate if you have enough memory in you dev VM
# cronjob runs as www-data user
echo ">>> Installing cronjob"

View file

@ -84,7 +84,6 @@
"Friendica\\Addon\\": "addon/"
},
"files": [
"include/conversation.php",
"include/dba.php",
"include/enotify.php",
"boot.php"

View file

@ -526,7 +526,7 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('enotify_mail', $datarray);
Hook::callAll('check_item_notification', $notification_data);
### include/conversation.php
### src/Content/Conversation.php
Hook::callAll('conversation_start', $cb);
Hook::callAll('render_location', $locate);

View file

@ -32,7 +32,8 @@ Due to the large variety of operating systems and PHP platforms in existence we
* PHP *command line* access with register_argc_argv set to true in the php.ini file
* Curl, GD, PDO, mbstrings, MySQLi, hash, xml, zip and OpenSSL extensions
* The POSIX module of PHP needs to be activated (e.g. [RHEL, CentOS](http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7) have disabled it)
* some form of email server or email gateway such that PHP mail() works
* Some form of email server or email gateway such that PHP mail() works.
If you cannot set up your own email server, you can use the [phpmailer](https://github.com/friendica/friendica-addons/tree/develop/phpmailer) addon and use a remote SMTP server.
* MySQL 5.6+ or an equivalent alternative for MySQL (MariaDB, Percona Server etc.)
* ability to schedule jobs with cron (Linux/Mac) or Scheduled Tasks (Windows)
* installation into a top-level domain or sub-domain (without a directory/path component in the URL) is RECOMMENDED. Directory paths will not be as convenient to use and have not been thoroughly tested. This is REQUIRED if you wish to communicate with the Diaspora network.

View file

@ -10,27 +10,27 @@ Getting started
No need to setup up a webserver, database etc. before actually starting.
Vagrant creates a virtual machine for you that you can just run inside VirtualBox and start to work directly on Friendica.
It brings an Ubuntu Xenial (16.04) with PHP 7.0 and MySQL 5.7.16
It brings an Debian Bullseye with PHP 7.4 and MariaDB 10.5.11.
What you need to do:
1. Install VirtualBox and vagrant.
Please use an up-to-date vagrant version from https://www.vagrantup.com/downloads.html.
2. Git clone your Friendica repository.
Inside, you'll find a "Vagrantfile" and some scripts in the utils folder.
3. Run "vagrant up" from inside the friendica clone:
$> vagrant up
Be patient: When it runs for the first time, it downloads an Ubuntu Server image.
4. Run "vagrant ssh" to log into the virtual machine to log in to the VM:
$> vagrant ssh
Inside, you'll find a `Vagrantfile` and some scripts in the `bin/dev` folder.
Pull the PHP requirements with `bin/composer install`.
3. Run `vagrant up` from inside the friendica clone.
This will start the virtual machine.
Be patient: When it runs for the first time, it downloads a Debian Server image and installs Friendica.
4. Run `vagrant ssh` to log into the virtual machine to log in to the VM in case you need to debug something on the server.
5. Open you test installation in a browser.
Go to 192.168.22.10.
Go to friendica.local (or 192.168.22.10).
friendica.local is using a self-signed TLS certificate, so you will need to add an exception to trust the certificate the first time you are visiting the page.
The mysql database is called "friendica", the mysql user and password both are "friendica".
6. Work on Friendica's code in your git clone on your machine (not in the VM).
Your local working directory is set up as a shared directory with the VM (/vagrant).
7. Check the changes in your browser in the VM.
Debug via the "vagrant ssh" login.
Find the Friendica log file /vagrant/logfile.out.
Find the Friendica log file `/vagrant/logfile.out` on the VM or in the `logfile.out` in you local Friendica directory.
8. Commit and push your changes directly back to Github.
If you want to stop vagrant after finishing your work, run the following command
@ -46,13 +46,24 @@ This will not delete the virtual machine.
to make sure that you can start from scratch with another "vagrant up".
The vagrant Friendica instance contains a test database.
You will then have the following accounts to login:
Default User Accounts
---------------------
By default the provision script will setup two user accounts.
* admin, password admin
* friendica1, password friendica1
* friendica2, password friendica2 and so on until friendica5
* friendica1 is connected to all others. friendica1 has two groups: group1 with friendica2 and friendica4, group2 with friendica3 and friendica5.
* friendica2 and friendica3 are connected. friendica4 and friendica5 are connected.
* friendica, password friendica
For further documentation of vagrant, please see [the vagrant*docs*](https://docs.vagrantup.com/v2/).
Trouble Shooting
----------------
If you see a version mis-match for the _VirtualBox Guest Additions_ between host and guest during the initial setup of the Vagrant VM, you will need to install an addon to Vagrant (ref. [Stack Overflow](https://stackoverflow.com/a/38010683)).
Stop the Vagrant VM and run the following command:
$> vagrant plugin install vagrant-vbguest
On the next Vagrant up, the version problem should be fixed.
If `friendica.local` is not resolved, you may need to add an entry to the `/etc/hosts` file (or similar configuration depending on the OS you are using).
For further documentation of vagrant, please see [the vagrant*docs*](https://docs.vagrantup.com/v2/).

View file

@ -220,7 +220,7 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('enotify_mail', $datarray);
Hook::callAll('check_item_notification', $notification_data);
### include/conversation.php
### src/Content/Conversation.php
Hook::callAll('conversation_start', $cb);
Hook::callAll('render_location', $locate);

View file

@ -29,7 +29,8 @@ Requirements
* PHP *Kommandozeilen*-Zugang mit register_argc_argv auf "true" gesetzt in der php.ini-Datei
* Curl, GD, PDO, MySQLi, xml, zip und OpenSSL-Erweiterung
* Das POSIX Modul muss aktiviert sein ([CentOS, RHEL](http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7) haben dies z.B. deaktiviert)
* etwas in der Art eines Email-Servers oder eines Gateways wie PHP mail()
* Einen E-Mail Server, so dass PHP `mail()` funktioniert.
Wenn kein eigener E-Mail Server zur Verfügung steht, kann alternativ das [phpmailer](https://github.com/friendica/friendica-addons/tree/develop/phpmailer) Addon mit einem externen SMTP Account verwendet werden.
* Mysql 5.6+ (oder eine äquivalente Alternative: MariaDB, Percona Server etc.)
* die Möglichkeit, wiederkehrende Aufgaben mit cron (Linux/Mac) oder "Scheduled Tasks" einzustellen (Windows) [Beachte: andere Optionen sind in Abschnitt 7 dieser Dokumentation zu finden]
* Installation in einer Top-Level-Domain oder Subdomain (ohne eine Verzeichnis/Pfad-Komponente in der URL) wird bevorzugt. Verzeichnispfade sind für diesen Zweck nicht so günstig und wurden auch nicht ausführlich getestet.

View file

@ -1188,7 +1188,7 @@ function api_statuses_update($type)
// We have to avoid that the post is rejected because of an empty body
if (empty($_REQUEST['body'])) {
$_REQUEST['body'] = '[hr]';
$_REQUEST['body'] = '[hr]';
}
}
@ -2997,7 +2997,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
list($status_user, $author_user, $owner_user) = api_item_get_user($a, $item);
}
localize_item($item);
DI::contentItem()->localize($item);
$in_reply_to = api_in_reply_to($item);
@ -3053,15 +3053,6 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
$retweeted_item = [];
$quoted_item = [];
if ($item['gravity'] == GRAVITY_PARENT) {
$body = $item['body'];
$retweeted_item = api_share_as_retweet($item);
if ($body != $item['body']) {
$quoted_item = $retweeted_item;
$retweeted_item = [];
}
}
if (empty($retweeted_item) && ($item['owner-id'] == $item['author-id'])) {
$announce = api_get_announce($item);
if (!empty($announce)) {
@ -3119,6 +3110,7 @@ function api_format_item($item, $type = "json", $status_user = null, $author_use
$retweeted_status['text'] = $rt_converted["text"];
$retweeted_status['statusnet_html'] = $rt_converted["html"];
$retweeted_status['friendica_html'] = $rt_converted["html"];
$retweeted_status['created_at'] = api_date($retweeted_item['created']);
if (!empty($quoted_status)) {
@ -4920,76 +4912,6 @@ function api_get_announce($item)
return array_merge($item, $announce);
}
/**
* Return the item shared, if the item contains only the [share] tag
*
* @param array $item Sharer item
* @return array|false Shared item or false if not a reshare
* @throws ImagickException
* @throws InternalServerErrorException
*/
function api_share_as_retweet(&$item)
{
$body = trim($item["body"]);
if (Diaspora::isReshare($body, false) === false) {
if ($item['author-id'] == $item['owner-id']) {
return false;
} else {
// Reshares from OStatus, ActivityPub and Twitter
$reshared_item = $item;
$reshared_item['owner-id'] = $reshared_item['author-id'];
$reshared_item['owner-link'] = $reshared_item['author-link'];
$reshared_item['owner-name'] = $reshared_item['author-name'];
$reshared_item['owner-avatar'] = $reshared_item['author-avatar'];
return $reshared_item;
}
}
$reshared = Item::getShareArray($item);
if (empty($reshared)) {
return false;
}
$reshared_item = $item;
if (empty($reshared['shared']) || empty($reshared['profile']) || empty($reshared['author']) || empty($reshared['avatar']) || empty($reshared['posted'])) {
return false;
}
if (!empty($reshared['comment'])) {
$item['body'] = $reshared['comment'];
}
$reshared_item["share-pre-body"] = $reshared['comment'];
$reshared_item["body"] = $reshared['shared'];
$reshared_item["author-id"] = Contact::getIdForURL($reshared['profile'], 0, false);
$reshared_item["author-name"] = $reshared['author'];
$reshared_item["author-link"] = $reshared['profile'];
$reshared_item["author-avatar"] = $reshared['avatar'];
$reshared_item["plink"] = $reshared['link'] ?? '';
$reshared_item["created"] = $reshared['posted'];
$reshared_item["edited"] = $reshared['posted'];
// Try to fetch the original item
if (!empty($reshared['guid'])) {
$condition = ['guid' => $reshared['guid'], 'uid' => [0, $item['uid']]];
} elseif (!empty($reshared_item['plink']) && ($original_id = Item::searchByLink($reshared_item['plink']))) {
$condition = ['id' => $original_id];
} else {
$condition = [];
}
if (!empty($condition)) {
$original_item = Post::selectFirst([], $condition);
if (DBA::isResult($original_item)) {
$reshared_item = array_merge($reshared_item, $original_item);
}
}
return $reshared_item;
}
/**
*
* @param array $item

File diff suppressed because it is too large Load diff

View file

@ -246,7 +246,7 @@ function display_content(App $a, $update = false, $update_uid = 0)
$page_uid = 0;
$parent = null;
if (!empty($parent_uri_id)) {
if (!local_user() && !empty($parent_uri_id)) {
$parent = Post::selectFirst(['uid'], ['uri-id' => $parent_uri_id, 'wall' => true]);
}
@ -272,7 +272,7 @@ function display_content(App $a, $update = false, $update_uid = 0)
// We need the editor here to be able to reshare an item.
if ($is_owner && !$update) {
$o .= status_editor($a, [], 0, true);
$o .= DI::conversation()->statusEditor([], 0, true);
}
$sql_extra = Item::getPermissionsSQLByUserId($page_uid);
@ -306,7 +306,7 @@ function display_content(App $a, $update = false, $update_uid = 0)
$o .= "<script> var netargs = '?uri_id=" . $item['uri-id'] . "'; </script>";
}
$o .= conversation($a, [$item], 'display', $update_uid, false, 'commented', $item_uid);
$o .= DI::conversation()->create([$item], 'display', $update_uid, false, 'commented', $item_uid);
// Preparing the meta header
$description = trim(BBCode::toPlaintext($item['body']));

View file

@ -177,10 +177,11 @@ function item_post(App $a) {
}
// Allow commenting if it is an answer to a public post
$allow_comment = local_user() && ($profile_uid == 0) && $toplevel_item_id && in_array($toplevel_item['network'], Protocol::FEDERATED);
$allow_comment = local_user() && $toplevel_item_id && in_array($toplevel_item['private'], [Item::PUBLIC, Item::UNLISTED]) && in_array($toplevel_item['network'], Protocol::FEDERATED);
// Now check that valid personal details have been provided
if (!Security::canWriteToUserWall($profile_uid) && !$allow_comment) {
Logger::notice('Permission denied.', ['local' => local_user(), 'profile_uid' => $profile_uid, 'toplevel_item_id' => $toplevel_item_id, 'network' => $toplevel_item['network']]);
notice(DI::l10n()->t('Permission denied.'));
if ($return_path) {
DI::baseUrl()->redirect($return_path);
@ -677,7 +678,7 @@ function item_post(App $a) {
$datarray["uri-id"] = -1;
$datarray["author-network"] = Protocol::DFRN;
$o = conversation($a, [array_merge($contact_record, $datarray)], 'search', false, true);
$o = DI::conversation()->create([array_merge($contact_record, $datarray)], 'search', false, true);
System::jsonExit(['preview' => $o]);
}
@ -931,6 +932,7 @@ function drop_item(int $id, string $return = '')
item_redirect_after_action($item, $return);
} else {
Logger::notice('Permission denied.', ['local' => local_user(), 'uid' => $item['uid'], 'cid' => $contact_id]);
notice(DI::l10n()->t('Permission denied.'));
DI::baseUrl()->redirect('display/' . $item['guid']);
//NOTREACHED

View file

@ -57,7 +57,7 @@ function notes_content(App $a, $update = false)
'acl_data' => '',
];
$o .= status_editor($a, $x, $a->getContactId());
$o .= DI::conversation()->statusEditor($x, $a->getContactId());
}
$condition = ['uid' => local_user(), 'post-type' => Item::PT_PERSONAL_NOTE, 'gravity' => GRAVITY_PARENT,
@ -84,7 +84,7 @@ function notes_content(App $a, $update = false)
$count = count($notes);
$o .= conversation($a, $notes, 'notes', $update);
$o .= DI::conversation()->create($notes, 'notes', $update);
}
$o .= $pager->renderMinimal($count);

View file

@ -1394,15 +1394,15 @@ function photos_content(App $a)
// display comments
if (DBA::isResult($items)) {
foreach ($items as $item) {
builtin_activity_puller($item, $conv_responses);
DI::conversation()->builtinActivityPuller($item, $conv_responses);
}
if (!empty($conv_responses['like'][$link_item['uri']])) {
$like = format_activity($conv_responses['like'][$link_item['uri']]['links'], 'like', $link_item['id']);
$like = DI::conversation()->formatActivity($conv_responses['like'][$link_item['uri']]['links'], 'like', $link_item['id']);
}
if (!empty($conv_responses['dislike'][$link_item['uri']])) {
$dislike = format_activity($conv_responses['dislike'][$link_item['uri']]['links'], 'dislike', $link_item['id']);
$dislike = DI::conversation()->formatActivity($conv_responses['dislike'][$link_item['uri']]['links'], 'dislike', $link_item['id']);
}
if (($can_post || Security::canWriteToUserWall($owner_uid))) {

1226
src/Content/Conversation.php Normal file

File diff suppressed because it is too large Load diff

View file

@ -21,16 +21,39 @@
namespace Friendica\Content;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Protocol;
use Friendica\Core\Session;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Item as ModelItem;
use Friendica\Model\Tag;
use Friendica\Model\Post;
use Friendica\Protocol\Activity;
use Friendica\Util\Profiler;
use Friendica\Util\Strings;
use Friendica\Util\XML;
/**
* A content helper class for displaying items
*/
class Item
{
/** @var Activity */
private $activity;
/** @var L10n */
private $l10n;
/** @var Profiler */
private $profiler;
public function __construct(Profiler $profiler, Activity $activity, L10n $l10n)
{
$this->profiler = $profiler;
$this->activity = $activity;
$this->l10n = $l10n;
}
/**
* Return array with details for categories and folders for an item
*
@ -221,4 +244,261 @@ class Item
return ['replaced' => $replaced, 'contact' => $contact];
}
/**
* Render actions localized
*
* @param $item
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function localize(&$item)
{
$this->profiler->startRecording('rendering');
/// @todo The following functionality needs to be cleaned up.
if (!empty($item['verb'])) {
$xmlhead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">";
if (stristr($item['verb'], Activity::POKE)) {
$verb = urldecode(substr($item['verb'], strpos($item['verb'],'#') + 1));
if (!$verb) {
$this->profiler->stopRecording();
return;
}
if ($item['object-type'] == "" || $item['object-type'] !== Activity\ObjectType::PERSON) {
$this->profiler->stopRecording();
return;
}
$obj = XML::parseString($xmlhead . $item['object']);
$Bname = $obj->title;
$Blink = $obj->id;
$Bphoto = "";
foreach ($obj->link as $l) {
$atts = $l->attributes();
switch ($atts['rel']) {
case "alternate": $Blink = $atts['href'];
case "photo": $Bphoto = $atts['href'];
}
}
$author = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']];
$A = '[url=' . Contact::magicLinkByContact($author) . ']' . $item['author-name'] . '[/url]';
if (!empty($Blink)) {
$B = '[url=' . Contact::magicLink($Blink) . ']' . $Bname . '[/url]';
} else {
$B = '';
}
if ($Bphoto != "" && !empty($Blink)) {
$Bphoto = '[url=' . Contact::magicLink($Blink) . '][img=80x80]' . $Bphoto . '[/img][/url]';
}
/*
* we can't have a translation string with three positions but no distinguishable text
* So here is the translate string.
*/
$txt = $this->l10n->t('%1$s poked %2$s');
// now translate the verb
$poked_t = trim(sprintf($txt, '', ''));
$txt = str_replace($poked_t, $this->l10n->t($verb), $txt);
// then do the sprintf on the translation string
$item['body'] = sprintf($txt, $A, $B) . "\n\n\n" . $Bphoto;
}
if ($this->activity->match($item['verb'], Activity::TAG)) {
$fields = ['author-id', 'author-link', 'author-name', 'author-network',
'verb', 'object-type', 'resource-id', 'body', 'plink'];
$obj = Post::selectFirst($fields, ['uri' => $item['parent-uri']]);
if (!DBA::isResult($obj)) {
$this->profiler->stopRecording();
return;
}
$author_arr = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']];
$author = '[url=' . Contact::magicLinkByContact($author_arr) . ']' . $item['author-name'] . '[/url]';
$author_arr = ['uid' => 0, 'id' => $obj['author-id'],
'network' => $obj['author-network'], 'url' => $obj['author-link']];
$objauthor = '[url=' . Contact::magicLinkByContact($author_arr) . ']' . $obj['author-name'] . '[/url]';
switch ($obj['verb']) {
case Activity::POST:
switch ($obj['object-type']) {
case Activity\ObjectType::EVENT:
$post_type = $this->l10n->t('event');
break;
default:
$post_type = $this->l10n->t('status');
}
break;
default:
if ($obj['resource-id']) {
$post_type = $this->l10n->t('photo');
$m=[]; preg_match("/\[url=([^]]*)\]/", $obj['body'], $m);
$rr['plink'] = $m[1];
} else {
$post_type = $this->l10n->t('status');
}
// Let's break everthing ... ;-)
break;
}
$plink = '[url=' . $obj['plink'] . ']' . $post_type . '[/url]';
$parsedobj = XML::parseString($xmlhead . $item['object']);
$tag = sprintf('#[url=%s]%s[/url]', $parsedobj->id, $parsedobj->content);
$item['body'] = $this->l10n->t('%1$s tagged %2$s\'s %3$s with %4$s', $author, $objauthor, $plink, $tag);
}
}
$matches = null;
if (preg_match_all('/@\[url=(.*?)\]/is', $item['body'], $matches, PREG_SET_ORDER)) {
foreach ($matches as $mtch) {
if (!strpos($mtch[1], 'zrl=')) {
$item['body'] = str_replace($mtch[0], '@[url=' . Contact::magicLink($mtch[1]) . ']', $item['body']);
}
}
}
// add sparkle links to appropriate permalinks
// Only create a redirection to a magic link when logged in
if (!empty($item['plink']) && Session::isAuthenticated() && $item['private'] == ModelItem::PRIVATE) {
$author = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']];
$item['plink'] = Contact::magicLinkByContact($author, $item['plink']);
}
$this->profiler->stopRecording();
}
public function photoMenu($item, string $formSecurityToken)
{
$this->profiler->startRecording('rendering');
$sub_link = '';
$poke_link = '';
$contact_url = '';
$pm_url = '';
$status_link = '';
$photos_link = '';
$posts_link = '';
$block_link = '';
$ignore_link = '';
if (local_user() && local_user() == $item['uid'] && $item['gravity'] == GRAVITY_PARENT && !$item['self'] && !$item['mention']) {
$sub_link = 'javascript:doFollowThread(' . $item['id'] . '); return false;';
}
$author = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']];
$profile_link = Contact::magicLinkByContact($author, $item['author-link']);
$sparkle = (strpos($profile_link, 'redir/') === 0);
$cid = 0;
$pcid = $item['author-id'];
$network = '';
$rel = 0;
$condition = ['uid' => local_user(), 'nurl' => Strings::normaliseLink($item['author-link'])];
$contact = DBA::selectFirst('contact', ['id', 'network', 'rel'], $condition);
if (DBA::isResult($contact)) {
$cid = $contact['id'];
$network = $contact['network'];
$rel = $contact['rel'];
}
if ($sparkle) {
$status_link = $profile_link . '/status';
$photos_link = str_replace('/profile/', '/photos/', $profile_link);
$profile_link = $profile_link . '/profile';
}
if (!empty($pcid)) {
$contact_url = 'contact/' . $pcid;
$posts_link = $contact_url . '/posts';
$block_link = $item['self'] ? '' : $contact_url . '/block?t=' . $formSecurityToken;
$ignore_link = $item['self'] ? '' : $contact_url . '/ignore?t=' . $formSecurityToken;
}
if ($cid && !$item['self']) {
$contact_url = 'contact/' . $cid;
$poke_link = $contact_url . '/poke';
$posts_link = $contact_url . '/posts';
if (in_array($network, [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA])) {
$pm_url = 'message/new/' . $cid;
}
}
if (local_user()) {
$menu = [
$this->l10n->t('Follow Thread') => $sub_link,
$this->l10n->t('View Status') => $status_link,
$this->l10n->t('View Profile') => $profile_link,
$this->l10n->t('View Photos') => $photos_link,
$this->l10n->t('Network Posts') => $posts_link,
$this->l10n->t('View Contact') => $contact_url,
$this->l10n->t('Send PM') => $pm_url,
$this->l10n->t('Block') => $block_link,
$this->l10n->t('Ignore') => $ignore_link
];
if (!empty($item['language'])) {
$menu[$this->l10n->t('Languages')] = 'javascript:alert(\'' . ModelItem::getLanguageMessage($item) . '\');';
}
if ($network == Protocol::DFRN) {
$menu[$this->l10n->t("Poke")] = $poke_link;
}
if ((($cid == 0) || ($rel == Contact::FOLLOWER)) &&
in_array($item['network'], Protocol::FEDERATED)) {
$menu[$this->l10n->t('Connect/Follow')] = 'follow?url=' . urlencode($item['author-link']) . '&auto=1';
}
} else {
$menu = [$this->l10n->t('View Profile') => $item['author-link']];
}
$args = ['item' => $item, 'menu' => $menu];
Hook::callAll('item_photo_menu', $args);
$menu = $args['menu'];
$o = '';
foreach ($menu as $k => $v) {
if (strpos($v, 'javascript:') === 0) {
$v = substr($v, 11);
$o .= '<li role="menuitem"><a onclick="' . $v . '">' . $k . '</a></li>' . PHP_EOL;
} elseif ($v) {
$o .= '<li role="menuitem"><a href="' . $v . '">' . $k . '</a></li>' . PHP_EOL;
}
}
$this->profiler->stopRecording();
return $o;
}
public function visibleActivity($item) {
if (empty($item['verb']) || $this->activity->isHidden($item['verb'])) {
return false;
}
// @TODO below if() block can be rewritten to a single line: $isVisible = allConditionsHere;
if ($this->activity->match($item['verb'], Activity::FOLLOW) &&
$item['object-type'] === Activity\ObjectType::NOTE &&
empty($item['self']) &&
$item['uid'] == local_user()) {
return false;
}
return true;
}
}

View file

@ -424,10 +424,12 @@ class BBCode
public static function removeAttachment($body, $no_link_desc = false)
{
return preg_replace_callback("/\s*\[attachment (.*?)\](.*?)\[\/attachment\]\s*/ism",
function ($match) use ($no_link_desc) {
function ($match) use ($body, $no_link_desc) {
$attach_data = self::getAttachmentData($match[0]);
if (empty($attach_data['url'])) {
return $match[0];
} elseif (strpos(str_replace($match[0], '', $body), $attach_data['url']) !== false) {
return '';
} elseif (empty($attach_data['title']) || $no_link_desc) {
return " \n[url]" . $attach_data['url'] . "[/url]\n";
} else {

View file

@ -23,6 +23,7 @@ namespace Friendica\Core;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Util\Strings;
/**
@ -257,6 +258,12 @@ class Addon
if ($type == "author" || $type == "maintainer") {
$r = preg_match("|([^<]+)<([^>]+)>|", $v, $m);
if ($r) {
if (!empty($m[2]) && empty(parse_url($m[2], PHP_URL_SCHEME))) {
$contact = Contact::getByURL($m[2], false);
if (!empty($contact['url'])) {
$m[2] = $contact['url'];
}
}
$info[$type][] = ['name' => $m[1], 'link' => $m[2]];
} else {
$info[$type][] = ['name' => $v];

View file

@ -134,6 +134,14 @@ abstract class DI
return self::$dice->create(Content\Item::class);
}
/**
* @return Content\Conversation
*/
public static function conversation()
{
return self::$dice->create(Content\Conversation::class);
}
/**
* @return Content\Text\BBCode\Video
*/

View file

@ -593,10 +593,7 @@ class DBStructure
// Compare it
foreach ($definition AS $name => $structure) {
$is_new_table = false;
$group_by = "";
$sql3 = "";
$is_unique = false;
$temp_name = $name;
if (!isset($database[$name])) {
$r = self::createTable($name, $structure, $verbose, $action);
if (!DBA::isResult($r)) {
@ -604,23 +601,6 @@ class DBStructure
}
$is_new_table = true;
} else {
foreach ($structure["indexes"] AS $indexname => $fieldnames) {
if (isset($database[$name]["indexes"][$indexname])) {
$current_index_definition = implode(",", $database[$name]["indexes"][$indexname]);
} else {
$current_index_definition = "__NOT_SET__";
}
$new_index_definition = implode(",", $fieldnames);
if ($current_index_definition != $new_index_definition) {
if ($fieldnames[0] == "UNIQUE") {
$is_unique = true;
if ($ignore == "") {
$temp_name = "temp-" . $name;
}
}
}
}
/*
* Drop the index if it isn't present in the definition
* or the definition differ from current status
@ -636,7 +616,7 @@ class DBStructure
if ($current_index_definition != $new_index_definition && substr($indexname, 0, 6) != 'local_') {
$sql2 = self::dropIndex($indexname);
if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2;
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else {
$sql3 .= ", " . $sql2;
}
@ -647,7 +627,7 @@ class DBStructure
if (!isset($database[$name]["fields"][$fieldname])) {
$sql2 = self::addTableField($fieldname, $parameters);
if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2;
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else {
$sql3 .= ", " . $sql2;
}
@ -675,7 +655,7 @@ class DBStructure
if ($current_field_definition != $new_field_definition) {
$sql2 = self::modifyTableField($fieldname, $parameters);
if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2;
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else {
$sql3 .= ", " . $sql2;
}
@ -700,11 +680,9 @@ class DBStructure
if ($current_index_definition != $new_index_definition) {
$sql2 = self::createIndex($indexname, $fieldnames);
// Fetch the "group by" fields for unique indexes
$group_by = self::groupBy($fieldnames);
if ($sql2 != "") {
if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2;
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else {
$sql3 .= ", " . $sql2;
}
@ -729,7 +707,7 @@ class DBStructure
$sql2 = self::addForeignKey($name, $fieldname, $parameters);
if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2;
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else {
$sql3 .= ", " . $sql2;
}
@ -740,7 +718,7 @@ class DBStructure
$sql2 = self::dropForeignKey($param['CONSTRAINT_NAME']);
if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2;
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else {
$sql3 .= ", " . $sql2;
}
@ -752,7 +730,7 @@ class DBStructure
$sql2 = "COMMENT = '" . DBA::escape($structurecomment) . "'";
if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2;
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else {
$sql3 .= ", " . $sql2;
}
@ -764,7 +742,7 @@ class DBStructure
$sql2 = "ENGINE = '" . DBA::escape($structure['engine']) . "'";
if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2;
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else {
$sql3 .= ", " . $sql2;
}
@ -776,7 +754,7 @@ class DBStructure
$sql2 = "DEFAULT COLLATE utf8mb4_general_ci";
if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2;
$sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else {
$sql3 .= ", " . $sql2;
}
@ -803,7 +781,7 @@ class DBStructure
if ($field_definition['Collation'] != $parameters['Collation']) {
$sql2 = self::modifyTableField($fieldname, $parameters);
if (($sql3 == "") || (substr($sql3, -2, 2) == "; ")) {
$sql3 .= "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2;
$sql3 .= "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else {
$sql3 .= ", " . $sql2;
}
@ -816,36 +794,8 @@ class DBStructure
$sql3 .= ";";
}
$field_list = '';
if ($is_unique && $ignore == '') {
foreach ($database[$name]["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 && ($temp_name != $name)) {
if ($ignore != "") {
echo "SET session old_alter_table=1;\n";
} else {
echo "DROP TABLE IF EXISTS `" . $temp_name . "`;\n";
echo "CREATE TABLE `" . $temp_name . "` LIKE `" . $name . "`;\n";
}
}
echo $sql3 . "\n";
if ($is_unique && ($temp_name != $name)) {
if ($ignore != "") {
echo "SET session old_alter_table=0;\n";
} else {
echo "INSERT INTO `" . $temp_name . "` SELECT " . DBA::anyValueFallback($field_list) . " FROM `" . $name . "`" . $group_by . ";\n";
echo "DROP TABLE `" . $name . "`;\n";
echo "RENAME TABLE `" . $temp_name . "` TO `" . $name . "`;\n";
}
}
}
if ($action) {
@ -853,50 +803,10 @@ class DBStructure
DI::config()->set('system', 'maintenance_reason', DI::l10n()->t('%s: updating %s table.', DateTimeFormat::utcNow() . ' ' . date('e'), $name));
}
// Ensure index conversion to unique removes duplicates
if ($is_unique && ($temp_name != $name)) {
if ($ignore != "") {
DBA::e("SET session old_alter_table=1;");
} else {
$r = DBA::e("DROP TABLE IF EXISTS `" . $temp_name . "`;");
if (!DBA::isResult($r)) {
$errors .= self::printUpdateError($sql3);
return $errors;
}
$r = DBA::e("CREATE TABLE `" . $temp_name . "` LIKE `" . $name . "`;");
if (!DBA::isResult($r)) {
$errors .= self::printUpdateError($sql3);
return $errors;
}
}
}
$r = DBA::e($sql3);
if (!DBA::isResult($r)) {
$errors .= self::printUpdateError($sql3);
}
if ($is_unique && ($temp_name != $name)) {
if ($ignore != "") {
DBA::e("SET session old_alter_table=0;");
} else {
$r = DBA::e("INSERT INTO `" . $temp_name . "` SELECT " . $field_list . " FROM `" . $name . "`" . $group_by . ";");
if (!DBA::isResult($r)) {
$errors .= self::printUpdateError($sql3);
return $errors;
}
$r = DBA::e("DROP TABLE `" . $name . "`;");
if (!DBA::isResult($r)) {
$errors .= self::printUpdateError($sql3);
return $errors;
}
$r = DBA::e("RENAME TABLE `" . $temp_name . "` TO `" . $name . "`;");
if (!DBA::isResult($r)) {
$errors .= self::printUpdateError($sql3);
return $errors;
}
}
}
}
}
}
@ -1060,37 +970,6 @@ class DBStructure
return sprintf("DROP FOREIGN KEY `%s`", $constraint);
}
/**
* Constructs a GROUP BY clause from a UNIQUE index definition.
*
* @param array $fieldnames
* @return string
*/
private static function groupBy(array $fieldnames)
{
if ($fieldnames[0] != "UNIQUE") {
return "";
}
array_shift($fieldnames);
$names = "";
foreach ($fieldnames AS $fieldname) {
if ($names != "") {
$names .= ",";
}
if (preg_match('|(.+)\((\d+)\)|', $fieldname, $matches)) {
$names .= "`" . DBA::escape($matches[1]) . "`";
} else {
$names .= "`" . DBA::escape($fieldname) . "`";
}
}
$sql = sprintf(" GROUP BY %s", $names);
return $sql;
}
/**
* Renames columns or the primary key of a table
*

View file

@ -119,7 +119,8 @@ class APContact
*/
public static function getByURL($url, $update = null)
{
if (empty($url)) {
if (empty($url) || Network::isUrlBlocked($url)) {
Logger::info('Domain is blocked', ['url' => $url]);
return [];
}

View file

@ -1445,11 +1445,11 @@ class Contact
if ($thread_mode) {
$items = Post::toArray(Post::selectForUser(local_user(), ['uri-id', 'gravity', 'parent-uri-id', 'thr-parent-id', 'author-id'], $condition, $params));
$o .= conversation($a, $items, 'contacts', $update, false, 'commented', local_user());
$o .= DI::conversation()->create($items, 'contacts', $update, false, 'commented', local_user());
} else {
$items = Post::toArray(Post::selectForUser(local_user(), Item::DISPLAY_FIELDLIST, $condition, $params));
$o .= conversation($a, $items, 'contact-posts', $update);
$o .= DI::conversation()->create($items, 'contact-posts', $update);
}
if (!$update) {

View file

@ -74,9 +74,7 @@ class Mail
return false;
}
if ($msg['reply']) {
$reply = DBA::selectFirst('mail', ['uri', 'uri-id'], ['parent-uri' => $msg['parent-uri'], 'reply' => false]);
if ($msg['reply'] && DBA::isResult($reply = DBA::selectFirst('mail', ['uri', 'uri-id'], ['parent-uri' => $msg['parent-uri'], 'reply' => false]))) {
$msg['thr-parent'] = $reply['uri'];
$msg['thr-parent-id'] = $reply['uri-id'];
} else {

View file

@ -25,7 +25,6 @@ use Friendica\DI;
use Friendica\Core\Renderer;
use Friendica\Core\Theme;
use Friendica\Module\BaseAdmin;
use Friendica\Model\Log\ParsedLogIterator;
use Psr\Log\LogLevel;
class View extends BaseAdmin
@ -68,7 +67,7 @@ class View extends BaseAdmin
}
if (!file_exists($f)) {
$error = DI::l10n()->t('Error trying to open <strong>%1$s</strong> log file.\r\n<br/>Check to see if file %1$s exist and is readable.', $f);
$error = DI::l10n()->t('Error trying to open <strong>%1$s</strong> log file.<br/>Check to see if file %1$s exist and is readable.', $f);
} else {
try {
$data = DI::parsedLogIterator()
@ -77,12 +76,33 @@ class View extends BaseAdmin
->withFilters($filters)
->withSearch($search);
} catch (Exception $e) {
$error = DI::l10n()->t('Couldn\'t open <strong>%1$s</strong> log file.\r\n<br/>Check to see if file %1$s is readable.', $f);
$error = DI::l10n()->t('Couldn\'t open <strong>%1$s</strong> log file.<br/>Check to see if file %1$s is readable.', $f);
}
}
return Renderer::replaceMacros($t, [
'$title' => DI::l10n()->t('Administration'),
'$page' => DI::l10n()->t('View Logs'),
'$title' => DI::l10n()->t('Administration'),
'$page' => DI::l10n()->t('View Logs'),
'$l10n' => [
'Search' => DI::l10n()->t('Search'),
'Search_in_logs' => DI::l10n()->t('Search in logs'),
'Show_all' => DI::l10n()->t('Show all'),
'Date' => DI::l10n()->t('Date'),
'Level' => DI::l10n()->t('Level'),
'Context' => DI::l10n()->t('Context'),
'Message' => DI::l10n()->t('Message'),
'ALL' => DI::l10n()->t('ALL'),
'View_details' => DI::l10n()->t('View details'),
'Click_to_view_details' => DI::l10n()->t('Click to view details'),
'Event_details' => DI::l10n()->t('Event details'),
'Data' => DI::l10n()->t('Data'),
'Source' => DI::l10n()->t('Source'),
'File' => DI::l10n()->t('File'),
'Line' => DI::l10n()->t('Line'),
'Function' => DI::l10n()->t('Function'),
'UID' => DI::l10n()->t('UID'),
'Process_ID' => DI::l10n()->t('Process ID'),
'Close' => DI::l10n()->t('Close'),
],
'$data' => $data,
'$q' => $search,
'$filters' => $filters,

View file

@ -38,7 +38,6 @@ class Bookmarklet extends BaseModule
{
$_GET['mode'] = 'minimal';
$app = DI::app();
$config = DI::config();
if (!local_user()) {
@ -61,7 +60,7 @@ class Bookmarklet extends BaseModule
'title' => trim($_REQUEST['title'] ?? '', '*'),
'content' => $content
];
$output = status_editor($app, $x, 0, false);
$output = DI::conversation()->statusEditor($x, 0, false);
$output .= "<script>window.resizeTo(800,550);</script>";
} else {
$output = '<h2>' . DI::l10n()->t('The post was created') . '</h2>';

View file

@ -951,7 +951,7 @@ class Contact extends BaseModule
if (!$update) {
// We need the editor here to be able to reshare an item.
if (local_user()) {
$o = status_editor($a, [], 0, true);
$o = DI::conversation()->statusEditor([], 0, true);
}
}

View file

@ -127,7 +127,7 @@ class Community extends BaseModule
// We need the editor here to be able to reshare an item.
if (Session::isAuthenticated()) {
$o .= status_editor(DI::app(), [], 0, true);
$o .= DI::conversation()->statusEditor([], 0, true);
}
}
@ -138,7 +138,7 @@ class Community extends BaseModule
return $o;
}
$o .= conversation(DI::app(), $items, 'community', false, false, 'commented', local_user());
$o .= DI::conversation()->create($items, 'community', false, false, 'commented', local_user());
$pager = new BoundariesPager(
DI::l10n(),

View file

@ -145,7 +145,7 @@ class Network extends BaseModule
'content' => $content,
];
$o .= status_editor($a, $x);
$o .= DI::conversation()->statusEditor($x);
}
if (self::$groupId) {
@ -178,7 +178,7 @@ class Network extends BaseModule
$ordering = '`commented`';
}
$o .= conversation(DI::app(), $items, 'network', false, false, $ordering, local_user());
$o .= DI::conversation()->create($items, 'network', false, false, $ordering, local_user());
if (DI::pConfig()->get(local_user(), 'system', 'infinite_scroll')) {
$o .= HTML::scrollLoader();

View file

@ -132,7 +132,7 @@ class Status extends BaseProfile
'profile_uid' => $profile['uid'],
];
$o .= status_editor($a, $x);
$o .= DI::conversation()->statusEditor($x);
}
// Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
@ -224,7 +224,7 @@ class Status extends BaseProfile
$items = array_merge($items, $pinned);
}
$o .= conversation($a, $items, 'profile', false, false, 'pinned_received', $profile['uid']);
$o .= DI::conversation()->create($items, 'profile', false, false, 'pinned_received', $profile['uid']);
$o .= $pager->renderMinimal(count($items));

View file

@ -79,7 +79,7 @@ class Filed extends BaseSearch
$items = Post::toArray(Post::selectForUser(local_user(), Item::DISPLAY_FIELDLIST, $item_condition, $item_params));
$o .= conversation(DI::app(), $items, 'filed', false, false, '', local_user());
$o .= DI::conversation()->create($items, 'filed', false, false, '', local_user());
if (DI::pConfig()->get(local_user(), 'system', 'infinite_scroll')) {
$o .= HTML::scrollLoader();

View file

@ -200,7 +200,7 @@ class Index extends BaseSearch
Logger::info('Start Conversation.', ['q' => $search]);
$o .= conversation(DI::app(), $items, 'search', false, false, 'commented', local_user());
$o .= DI::conversation()->create($items, 'search', false, false, 'commented', local_user());
if (DI::pConfig()->get(local_user(), 'system', 'infinite_scroll')) {
$o .= HTML::scrollLoader();

View file

@ -39,7 +39,7 @@ class Community extends CommunityModule
$o = '';
if (!empty($_GET['force']) || !DI::pConfig()->get(local_user(), 'system', 'no_auto_update')) {
$o = conversation(DI::app(), self::getItems(), 'community', true, false, 'commented', local_user());
$o = DI::conversation()->create(self::getItems(), 'community', true, false, 'commented', local_user());
}
System::htmlUpdateExit($o);

View file

@ -53,7 +53,7 @@ class Network extends NetworkModule
$ordering = '`commented`';
}
$o = conversation(DI::app(), $items, 'network', $profile_uid, false, $ordering, local_user());
$o = DI::conversation()->create($items, 'network', $profile_uid, false, $ordering, local_user());
}
System::htmlUpdateExit($o);

View file

@ -115,7 +115,7 @@ class Profile extends BaseModule
$items = DBA::toArray($items_stmt);
$o .= conversation($a, $items, 'profile', $a->getProfileOwner(), false, 'received', $a->getProfileOwner());
$o .= DI::conversation()->create($items, 'profile', $a->getProfileOwner(), false, 'received', $a->getProfileOwner());
System::htmlUpdateExit($o);
}

View file

@ -231,6 +231,11 @@ class Probe
}
}
if (Network::isUrlBlocked($host_url)) {
Logger::info('Domain is blocked', ['url' => $host]);
return [];
}
self::$baseurl = $host_url;
Logger::info('Probing successful', ['host' => $host]);
@ -625,6 +630,11 @@ class Probe
*/
private static function getWebfinger(string $template, string $type, string $uri, string $addr)
{
if (Network::isUrlBlocked($template)) {
Logger::info('Domain is blocked', ['url' => $template]);
return [];
}
// First try the address because this is the primary purpose of webfinger
if (!empty($addr)) {
$detected = $addr;

View file

@ -105,7 +105,7 @@ class Post
// Only add will be displayed
if ($item['network'] === Protocol::MAIL && local_user() != $item['uid']) {
continue;
} elseif (!visible_activity($item)) {
} elseif (!DI::contentItem()->visibleActivity($item)) {
continue;
}
@ -279,7 +279,7 @@ class Post
foreach ($response_verbs as $value => $verb) {
$responses[$verb] = [
'self' => $conv_responses[$verb][$item['uri-id']]['self'] ?? 0,
'output' => !empty($conv_responses[$verb][$item['uri-id']]) ? format_activity($conv_responses[$verb][$item['uri-id']]['links'], $verb, $item['uri-id']) : '',
'output' => !empty($conv_responses[$verb][$item['uri-id']]) ? DI::conversation()->formatActivity($conv_responses[$verb][$item['uri-id']]['links'], $verb, $item['uri-id']) : '',
];
}
@ -363,7 +363,7 @@ class Post
$shiny = 'shiny';
}
localize_item($item);
DI::contentItem()->localize($item);
$body_html = Item::prepareBody($item, true);
@ -459,7 +459,7 @@ class Post
'vwall' => DI::l10n()->t('via Wall-To-Wall:'),
'profile_url' => $profile_link,
'name' => $profile_name,
'item_photo_menu_html' => item_photo_menu($item, $formSecurityToken),
'item_photo_menu_html' => DI::contentItem()->photoMenu($item, $formSecurityToken),
'thumb' => DI::baseUrl()->remove(Contact::getAvatarUrlForUrl($item['author-link'], $item['uid'], Proxy::SIZE_THUMB)),
'osparkle' => $osparkle,
'sparkle' => $sparkle,

View file

@ -1146,27 +1146,31 @@ class Feed
if ($item['gravity'] != GRAVITY_PARENT) {
$parent = Post::selectFirst(['guid', 'author-link', 'owner-link'], ['id' => $item['parent']]);
$thrparent = Post::selectFirst(['guid', 'author-link', 'owner-link', 'plink'], ['uid' => $owner["uid"], 'uri' => $item['thr-parent']]);
$thrparent = Post::selectFirst(['guid', 'author-link', 'owner-link', 'plink'], ['uid' => $owner['uid'], 'uri' => $item['thr-parent']]);
if (DBA::isResult($thrparent)) {
$mentioned[$thrparent["author-link"]] = $thrparent["author-link"];
$mentioned[$thrparent["owner-link"]] = $thrparent["owner-link"];
$parent_plink = $thrparent["plink"];
$mentioned[$thrparent['author-link']] = $thrparent['author-link'];
$mentioned[$thrparent['owner-link']] = $thrparent['owner-link'];
$parent_plink = $thrparent['plink'];
} elseif (DBA::isResult($parent)) {
$mentioned[$parent['author-link']] = $parent['author-link'];
$mentioned[$parent['owner-link']] = $parent['owner-link'];
$parent_plink = DI::baseUrl() . '/display/' . $parent['guid'];
} else {
$mentioned[$parent["author-link"]] = $parent["author-link"];
$mentioned[$parent["owner-link"]] = $parent["owner-link"];
$parent_plink = DI::baseUrl()."/display/".$parent["guid"];
DI::logger()->notice('Missing parent and thr-parent for child item', ['item' => $item]);
}
$attributes = [
"ref" => $item['thr-parent'],
"href" => $parent_plink];
XML::addElement($doc, $entry, "thr:in-reply-to", "", $attributes);
if (isset($parent_plink)) {
$attributes = [
'ref' => $item['thr-parent'],
'href' => $parent_plink];
XML::addElement($doc, $entry, 'thr:in-reply-to', '', $attributes);
$attributes = [
"rel" => "related",
"href" => $parent_plink];
XML::addElement($doc, $entry, "link", "", $attributes);
$attributes = [
'rel' => 'related',
'href' => $parent_plink];
XML::addElement($doc, $entry, 'link', '', $attributes);
}
}
// uri-id isn't present for follow entry pseudo-items
@ -1177,7 +1181,7 @@ class Feed
foreach ($tags as $tag) {
if ($tag['type'] == Tag::HASHTAG) {
XML::addElement($doc, $entry, "category", "", ["term" => $tag['name']]);
XML::addElement($doc, $entry, 'category', '', ['term' => $tag['name']]);
}
}

View file

@ -1931,27 +1931,31 @@ class OStatus
if ($item['gravity'] != GRAVITY_PARENT) {
$parent = Post::selectFirst(['guid', 'author-link', 'owner-link'], ['id' => $item['parent']]);
$thrparent = Post::selectFirst(['guid', 'author-link', 'owner-link', 'plink'], ['uid' => $owner["uid"], 'uri' => $item['thr-parent']]);
$thrparent = Post::selectFirst(['guid', 'author-link', 'owner-link', 'plink'], ['uid' => $owner['uid'], 'uri' => $item['thr-parent']]);
if (DBA::isResult($thrparent)) {
$mentioned[$thrparent["author-link"]] = $thrparent["author-link"];
$mentioned[$thrparent["owner-link"]] = $thrparent["owner-link"];
$parent_plink = $thrparent["plink"];
$mentioned[$thrparent['author-link']] = $thrparent['author-link'];
$mentioned[$thrparent['owner-link']] = $thrparent['owner-link'];
$parent_plink = $thrparent['plink'];
} elseif (DBA::isResult($parent)) {
$mentioned[$parent['author-link']] = $parent['author-link'];
$mentioned[$parent['owner-link']] = $parent['owner-link'];
$parent_plink = DI::baseUrl() . '/display/' . $parent['guid'];
} else {
$mentioned[$parent["author-link"]] = $parent["author-link"];
$mentioned[$parent["owner-link"]] = $parent["owner-link"];
$parent_plink = DI::baseUrl()."/display/".$parent["guid"];
DI::logger()->notice('Missing parent and thr-parent for child item', ['item' => $item]);
}
$attributes = [
"ref" => $item['thr-parent'],
"href" => $parent_plink];
XML::addElement($doc, $entry, "thr:in-reply-to", "", $attributes);
if (isset($parent_plink)) {
$attributes = [
'ref' => $item['thr-parent'],
'href' => $parent_plink];
XML::addElement($doc, $entry, 'thr:in-reply-to', '', $attributes);
$attributes = [
"rel" => "related",
"href" => $parent_plink];
XML::addElement($doc, $entry, "link", "", $attributes);
$attributes = [
'rel' => 'related',
'href' => $parent_plink];
XML::addElement($doc, $entry, 'link', '', $attributes);
}
}
if (intval($item['parent']) > 0) {

View file

@ -49,7 +49,7 @@ class Security
return true;
}
if (!empty(Session::getRemoteContactID($owner))) {
if (!empty($cid = Session::getRemoteContactID($owner))) {
// use remembered decision and avoid a DB lookup for each and every display item
// DO NOT use this function if there are going to be multiple owners
// We have a contact-id for an authenticated remote user, this block determines if the contact
@ -60,22 +60,19 @@ class Security
} elseif ($verified === 1) {
return false;
} else {
$cid = Session::getRemoteContactID($owner);
if (!$cid) {
$user = User::getById($owner);
if (!$user || $user['blockwall']) {
$verified = 1;
return false;
}
$r = q("SELECT `contact`.*, `user`.`page-flags` FROM `contact` INNER JOIN `user` on `user`.`uid` = `contact`.`uid`
WHERE `contact`.`uid` = %d AND `contact`.`id` = %d AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0
AND `user`.`blockwall` = 0 AND `readonly` = 0 AND (`contact`.`rel` IN (%d , %d) OR `user`.`page-flags` = %d) LIMIT 1",
intval($owner),
intval($cid),
intval(Contact::SHARING),
intval(Contact::FRIEND),
intval(User::PAGE_FLAGS_COMMUNITY)
);
if (DBA::isResult($r)) {
$contact = Contact::getById($cid);
if ($contact || $contact['blocked'] || $contact['readonly'] || $contact['pending']) {
$verified = 1;
return false;
}
if (in_array($contact['rel'], [Contact::SHARING, Contact::FRIEND]) || ($user['page-flags'] == User::PAGE_FLAGS_COMMUNITY)) {
$verified = 2;
return true;
} else {

View file

@ -95,6 +95,9 @@ class ReversedFileReader implements \Iterator
if ($this->pos == 0) {
return array_pop($buffer);
}
if (is_null($buffer)) {
return null;
}
if (count($buffer) > 1) {
return array_pop($buffer);
}

View file

@ -3510,18 +3510,6 @@ class ApiTest extends FixtureTest
$this->markTestIncomplete();
}
/**
* Test the api_share_as_retweet() function.
*
* @return void
*/
public function testApiShareAsRetweet()
{
$item = ['body' => '', 'author-id' => 1, 'owner-id' => 1];
$result = api_share_as_retweet($item);
self::assertFalse($result);
}
/**
* Test the api_share_as_retweet() function with a valid item.
*

View file

@ -228,14 +228,14 @@ class BBCodeTest extends MockedTest
'text' => '[size=xx-large]Test text[/size]',
'try_oembed' => false,
// Triggers the diaspora compatible output
'simpleHtml' => 3,
'simpleHtml' => BBCode::DIASPORA,
],
'bug-2199-diaspora-no-numeric-size' => [
'expectedHtml' => 'Test text',
'text' => '[size=24]Test text[/size]',
'try_oembed' => false,
// Triggers the diaspora compatible output
'simpleHtml' => 3,
'simpleHtml' => BBCode::DIASPORA,
],
'bug-7665-audio-tag' => [
'expectedHtml' => '<audio src="http://www.cendrones.fr/colloque2017/jonathanbocquet.mp3" controls><a href="http://www.cendrones.fr/colloque2017/jonathanbocquet.mp3">http://www.cendrones.fr/colloque2017/jonathanbocquet.mp3</a></audio>',
@ -282,6 +282,16 @@ class BBCodeTest extends MockedTest
'expectedHTML' => '<span class="arbitrary classes">Test</span>',
'text' => '[class=arbitrary classes]Test[/class]',
],
'bug-10772-duplicated-links' => [
'expectedHTML' => 'Jetzt wird mir klar, warum Kapitalisten jedes Mal durchdrehen wenn Marx und das Kapital ins Gespräch kommt. Soziopathen.<br>Karl Marx - Die ursprüngliche Akkumulation<br><a href="https://wohlstandfueralle.podigee.io/107-urspruengliche-akkumulation" target="_blank" rel="noopener noreferrer">https://wohlstandfueralle.podigee.io/107-urspruengliche-akkumulation</a><br>#Podcast #Kapitalismus',
'text' => "Jetzt wird mir klar, warum Kapitalisten jedes Mal durchdrehen wenn Marx und das Kapital ins Gespräch kommt. Soziopathen.
Karl Marx - Die ursprüngliche Akkumulation
[url=https://wohlstandfueralle.podigee.io/107-urspruengliche-akkumulation]https://wohlstandfueralle.podigee.io/107-urspruengliche-akkumulation[/url]
#[url=https://horche.demkontinuum.de/search?tag=Podcast]Podcast[/url] #[url=https://horche.demkontinuum.de/search?tag=Kapitalismus]Kapitalismus[/url]
[attachment type='link' url='https://wohlstandfueralle.podigee.io/107-urspruengliche-akkumulation' title='Ep. 107: Karl Marx #8 - Die urspr&uuml;ngliche Akkumulation' publisher_name='Wohlstand f&uuml;r Alle' preview='https://images.podigee-cdn.net/0x,s6LXshYO7uhG23H431B30t4hxj1bQuzlTsUlze0F_-H8=/https://cdn.podigee.com/uploads/u8126/bd5fe4f4-38b7-4f3f-b269-6a0080144635.jpg']Wie der Kapitalismus funktioniert und inwieweit Menschen darin ausgebeutet werden, haben wir bereits besprochen. Immer wieder verweisen wir auch darauf, dass der Kapitalismus nicht immer schon existierte, sondern historisiert werden muss.[/attachment]",
'try_oembed' => false,
'simpleHtml' => BBCode::TWITTER,
],
];
}

View file

@ -19,7 +19,7 @@
*
*/
namespace Friendica\Test\src\Object\Log;
namespace Friendica\Test\src\Model\Log;
use Friendica\Util\ReversedFileReader;
use Friendica\Model\Log\ParsedLogIterator;
@ -145,4 +145,16 @@ class ParsedLogIteratorTest extends TestCase
$pls = iterator_to_array($this->pli, false);
self::assertCount(0, $pls);
}
public function testEmptyLogFile()
{
$logfile = dirname(__DIR__) . '/../../datasets/log/empty.friendica.log.txt';
$reader = new ReversedFileReader();
$pli = new ParsedLogIterator($reader);
$pli->open($logfile);
$pls = iterator_to_array($pli, false);
self::assertCount(0, $pls);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -16,101 +16,6 @@ $a->strings["Weekly posting limit of %d post reached. The post was rejected."] =
];
$a->strings["Monthly posting limit of %d post reached. The post was rejected."] = "Das monatliche Limit von %d Beiträgen wurde erreicht. Der Beitrag wurde verworfen.";
$a->strings["Profile Photos"] = "Profilbilder";
$a->strings["%1\$s poked %2\$s"] = "%1\$s stupste %2\$s";
$a->strings["event"] = "Veranstaltung";
$a->strings["status"] = "Status";
$a->strings["photo"] = "Foto";
$a->strings["%1\$s tagged %2\$s's %3\$s with %4\$s"] = "%1\$s hat %2\$ss %3\$s mit %4\$s getaggt";
$a->strings["Select"] = "Auswählen";
$a->strings["Delete"] = "Löschen";
$a->strings["View %s's profile @ %s"] = "Das Profil von %s auf %s betrachten.";
$a->strings["Categories:"] = "Kategorien:";
$a->strings["Filed under:"] = "Abgelegt unter:";
$a->strings["%s from %s"] = "%s von %s";
$a->strings["View in context"] = "Im Zusammenhang betrachten";
$a->strings["Please wait"] = "Bitte warten";
$a->strings["remove"] = "löschen";
$a->strings["Delete Selected Items"] = "Lösche die markierten Beiträge";
$a->strings["You had been addressed (%s)."] = "Du wurdest angeschrieben (%s).";
$a->strings["You are following %s."] = "Du folgst %s.";
$a->strings["Tagged"] = "Verschlagwortet";
$a->strings["%s reshared this."] = "%s hat dies geteilt";
$a->strings["Reshared"] = "Geteilt";
$a->strings["Reshared by %s <%s>"] = "Geteilt von %s <%s>";
$a->strings["%s is participating in this thread."] = "%s ist an der Unterhaltung beteiligt.";
$a->strings["Stored"] = "Gespeichert";
$a->strings["Global"] = "Global";
$a->strings["Relayed"] = "Übermittelt";
$a->strings["Relayed by %s <%s>"] = "Weitergeleitet von %s <%s>";
$a->strings["Fetched"] = "Abgerufen";
$a->strings["Fetched because of %s <%s>"] = "Wegen %s <%s> abgerufen";
$a->strings["Follow Thread"] = "Folge der Unterhaltung";
$a->strings["View Status"] = "Status anschauen";
$a->strings["View Profile"] = "Profil anschauen";
$a->strings["View Photos"] = "Bilder anschauen";
$a->strings["Network Posts"] = "Netzwerkbeiträge";
$a->strings["View Contact"] = "Kontakt anzeigen";
$a->strings["Send PM"] = "Private Nachricht senden";
$a->strings["Block"] = "Sperren";
$a->strings["Ignore"] = "Ignorieren";
$a->strings["Languages"] = "Sprachen";
$a->strings["Poke"] = "Anstupsen";
$a->strings["Connect/Follow"] = "Verbinden/Folgen";
$a->strings["%s likes this."] = "%s mag das.";
$a->strings["%s doesn't like this."] = "%s mag das nicht.";
$a->strings["%s attends."] = "%s nimmt teil.";
$a->strings["%s doesn't attend."] = "%s nimmt nicht teil.";
$a->strings["%s attends maybe."] = "%s nimmt eventuell teil.";
$a->strings["and"] = "und";
$a->strings["and %d other people"] = "und %dandere";
$a->strings["<span %1\$s>%2\$d people</span> like this"] = "<span %1\$s>%2\$d Personen</span> mögen das";
$a->strings["%s like this."] = "%s mögen das.";
$a->strings["<span %1\$s>%2\$d people</span> don't like this"] = "<span %1\$s>%2\$d Personen</span> mögen das nicht";
$a->strings["%s don't like this."] = "%s mögen dies nicht.";
$a->strings["<span %1\$s>%2\$d people</span> attend"] = "<span %1\$s>%2\$d Personen</span> nehmen teil";
$a->strings["%s attend."] = "%s nehmen teil.";
$a->strings["<span %1\$s>%2\$d people</span> don't attend"] = "<span %1\$s>%2\$d Personen</span> nehmen nicht teil";
$a->strings["%s don't attend."] = "%s nehmen nicht teil.";
$a->strings["<span %1\$s>%2\$d people</span> attend maybe"] = "<span %1\$s>%2\$d Personen</span> nehmen eventuell teil";
$a->strings["%s attend maybe."] = "%s nimmt eventuell teil.";
$a->strings["<span %1\$s>%2\$d people</span> reshared this"] = "<span %1\$s>%2\$d Personen</span> haben dies geteilt";
$a->strings["Visible to <strong>everybody</strong>"] = "Für <strong>jedermann</strong> sichtbar";
$a->strings["Please enter a image/video/audio/webpage URL:"] = "Bitte gib eine Bild/Video/Audio/Webseiten-URL ein:";
$a->strings["Tag term:"] = "Tag:";
$a->strings["Save to Folder:"] = "In diesem Ordner speichern:";
$a->strings["Where are you right now?"] = "Wo hältst du dich jetzt gerade auf?";
$a->strings["Delete item(s)?"] = "Einträge löschen?";
$a->strings["New Post"] = "Neuer Beitrag";
$a->strings["Share"] = "Teilen";
$a->strings["Loading..."] = "lädt...";
$a->strings["Upload photo"] = "Foto hochladen";
$a->strings["upload photo"] = "Bild hochladen";
$a->strings["Attach file"] = "Datei anhängen";
$a->strings["attach file"] = "Datei anhängen";
$a->strings["Bold"] = "Fett";
$a->strings["Italic"] = "Kursiv";
$a->strings["Underline"] = "Unterstrichen";
$a->strings["Quote"] = "Zitat";
$a->strings["Code"] = "Code";
$a->strings["Image"] = "Bild";
$a->strings["Link"] = "Link";
$a->strings["Link or Media"] = "Link oder Mediendatei";
$a->strings["Video"] = "Video";
$a->strings["Set your location"] = "Deinen Standort festlegen";
$a->strings["set location"] = "Ort setzen";
$a->strings["Clear browser location"] = "Browser-Standort leeren";
$a->strings["clear location"] = "Ort löschen";
$a->strings["Set title"] = "Titel setzen";
$a->strings["Categories (comma-separated list)"] = "Kategorien (kommasepariert)";
$a->strings["Scheduled at"] = "Geplant für";
$a->strings["Permission settings"] = "Berechtigungseinstellungen";
$a->strings["Permissions"] = "Berechtigungen";
$a->strings["Public post"] = "Öffentlicher Beitrag";
$a->strings["Preview"] = "Vorschau";
$a->strings["Cancel"] = "Abbrechen";
$a->strings["Message"] = "Nachricht";
$a->strings["Browser"] = "Browser";
$a->strings["Open Compose page"] = "Composer Seite öffnen";
$a->strings["[Friendica:Notify]"] = "[Friendica Meldung]";
$a->strings["%s New mail received at %s"] = "%sNeue Nachricht auf %s empfangen";
$a->strings["%1\$s sent you a new private message at %2\$s."] = "%1\$s hat dir eine neue, private Nachricht auf %2\$s geschickt.";
@ -183,14 +88,34 @@ $a->strings["The feed for this item is unavailable."] = "Der Feed für diesen Be
$a->strings["Item not found"] = "Beitrag nicht gefunden";
$a->strings["Edit post"] = "Beitrag bearbeiten";
$a->strings["Save"] = "Speichern";
$a->strings["Loading..."] = "lädt...";
$a->strings["Upload photo"] = "Foto hochladen";
$a->strings["upload photo"] = "Bild hochladen";
$a->strings["Attach file"] = "Datei anhängen";
$a->strings["attach file"] = "Datei anhängen";
$a->strings["Insert web link"] = "Einen Link einfügen";
$a->strings["web link"] = "Weblink";
$a->strings["Insert video link"] = "Video-Adresse einfügen";
$a->strings["video link"] = "Video-Link";
$a->strings["Insert audio link"] = "Audio-Adresse einfügen";
$a->strings["audio link"] = "Audio-Link";
$a->strings["Set your location"] = "Deinen Standort festlegen";
$a->strings["set location"] = "Ort setzen";
$a->strings["Clear browser location"] = "Browser-Standort leeren";
$a->strings["clear location"] = "Ort löschen";
$a->strings["Please wait"] = "Bitte warten";
$a->strings["Permission settings"] = "Berechtigungseinstellungen";
$a->strings["CC: email addresses"] = "Cc: E-Mail-Addressen";
$a->strings["Public post"] = "Öffentlicher Beitrag";
$a->strings["Set title"] = "Titel setzen";
$a->strings["Categories (comma-separated list)"] = "Kategorien (kommasepariert)";
$a->strings["Example: bob@example.com, mary@example.com"] = "Z.B.: bob@example.com, mary@example.com";
$a->strings["Preview"] = "Vorschau";
$a->strings["Cancel"] = "Abbrechen";
$a->strings["Message"] = "Nachricht";
$a->strings["Browser"] = "Browser";
$a->strings["Permissions"] = "Berechtigungen";
$a->strings["Open Compose page"] = "Composer Seite öffnen";
$a->strings["Event can not end before it has started."] = "Die Veranstaltung kann nicht enden, bevor sie beginnt.";
$a->strings["Event title and start time are required."] = "Der Veranstaltungstitel und die Anfangszeit müssen angegeben werden.";
$a->strings["Create New Event"] = "Neue Veranstaltung erstellen";
@ -217,6 +142,7 @@ $a->strings["You already added this contact."] = "Du hast den Kontakt bereits hi
$a->strings["The network type couldn't be detected. Contact can't be added."] = "Der Netzwerktyp wurde nicht erkannt. Der Kontakt kann nicht hinzugefügt werden.";
$a->strings["Diaspora support isn't enabled. Contact can't be added."] = "Diaspora-Unterstützung ist nicht aktiviert. Der Kontakt kann nicht zugefügt werden.";
$a->strings["OStatus support is disabled. Contact can't be added."] = "OStatus-Unterstützung ist nicht aktiviert. Der Kontakt kann nicht zugefügt werden.";
$a->strings["Connect/Follow"] = "Verbinden/Folgen";
$a->strings["Please answer the following:"] = "Bitte beantworte folgendes:";
$a->strings["Your Identity Address:"] = "Adresse Deines Profils:";
$a->strings["Profile URL"] = "Profil URL";
@ -350,6 +276,8 @@ $a->strings["Rotate CW (right)"] = "Drehen US (rechts)";
$a->strings["Rotate CCW (left)"] = "Drehen EUS (links)";
$a->strings["This is you"] = "Das bist du";
$a->strings["Comment"] = "Kommentar";
$a->strings["Select"] = "Auswählen";
$a->strings["Delete"] = "Löschen";
$a->strings["Like"] = "Mag ich";
$a->strings["I like this (toggle)"] = "Ich mag das (toggle)";
$a->strings["Dislike"] = "Mag ich nicht";
@ -545,6 +473,9 @@ $a->strings["If you have moved this profile from another server, and some of you
$a->strings["Resend relocate message to contacts"] = "Umzugsbenachrichtigung erneut an Kontakte senden";
$a->strings["No suggestions available. If this is a new site, please try again in 24 hours."] = "Keine Vorschläge verfügbar. Falls der Server frisch aufgesetzt wurde, versuche es bitte in 24 Stunden noch einmal.";
$a->strings["Friend Suggestions"] = "Kontaktvorschläge";
$a->strings["photo"] = "Foto";
$a->strings["status"] = "Status";
$a->strings["%1\$s tagged %2\$s's %3\$s with %4\$s"] = "%1\$s hat %2\$ss %3\$s mit %4\$s getaggt";
$a->strings["Remove Item Tag"] = "Gegenstands-Tag entfernen";
$a->strings["Select a tag to remove: "] = "Wähle ein Tag zum Entfernen aus: ";
$a->strings["Remove"] = "Entfernen";
@ -637,6 +568,62 @@ $a->strings["GNU Social Connector"] = "GNU Social Connector";
$a->strings["ActivityPub"] = "ActivityPub";
$a->strings["pnut"] = "pnut";
$a->strings["%s (via %s)"] = "%s (via %s)";
$a->strings["%s likes this."] = "%s mag das.";
$a->strings["%s doesn't like this."] = "%s mag das nicht.";
$a->strings["%s attends."] = "%s nimmt teil.";
$a->strings["%s doesn't attend."] = "%s nimmt nicht teil.";
$a->strings["%s attends maybe."] = "%s nimmt eventuell teil.";
$a->strings["%s reshared this."] = "%s hat dies geteilt";
$a->strings["and"] = "und";
$a->strings["and %d other people"] = "und %dandere";
$a->strings["<span %1\$s>%2\$d people</span> like this"] = "<span %1\$s>%2\$d Personen</span> mögen das";
$a->strings["%s like this."] = "%s mögen das.";
$a->strings["<span %1\$s>%2\$d people</span> don't like this"] = "<span %1\$s>%2\$d Personen</span> mögen das nicht";
$a->strings["%s don't like this."] = "%s mögen dies nicht.";
$a->strings["<span %1\$s>%2\$d people</span> attend"] = "<span %1\$s>%2\$d Personen</span> nehmen teil";
$a->strings["%s attend."] = "%s nehmen teil.";
$a->strings["<span %1\$s>%2\$d people</span> don't attend"] = "<span %1\$s>%2\$d Personen</span> nehmen nicht teil";
$a->strings["%s don't attend."] = "%s nehmen nicht teil.";
$a->strings["<span %1\$s>%2\$d people</span> attend maybe"] = "<span %1\$s>%2\$d Personen</span> nehmen eventuell teil";
$a->strings["%s attend maybe."] = "%s nimmt eventuell teil.";
$a->strings["<span %1\$s>%2\$d people</span> reshared this"] = "<span %1\$s>%2\$d Personen</span> haben dies geteilt";
$a->strings["Visible to <strong>everybody</strong>"] = "Für <strong>jedermann</strong> sichtbar";
$a->strings["Please enter a image/video/audio/webpage URL:"] = "Bitte gib eine Bild/Video/Audio/Webseiten-URL ein:";
$a->strings["Tag term:"] = "Tag:";
$a->strings["Save to Folder:"] = "In diesem Ordner speichern:";
$a->strings["Where are you right now?"] = "Wo hältst du dich jetzt gerade auf?";
$a->strings["Delete item(s)?"] = "Einträge löschen?";
$a->strings["New Post"] = "Neuer Beitrag";
$a->strings["Share"] = "Teilen";
$a->strings["Bold"] = "Fett";
$a->strings["Italic"] = "Kursiv";
$a->strings["Underline"] = "Unterstrichen";
$a->strings["Quote"] = "Zitat";
$a->strings["Code"] = "Code";
$a->strings["Image"] = "Bild";
$a->strings["Link"] = "Link";
$a->strings["Link or Media"] = "Link oder Mediendatei";
$a->strings["Video"] = "Video";
$a->strings["Scheduled at"] = "Geplant für";
$a->strings["View %s's profile @ %s"] = "Das Profil von %s auf %s betrachten.";
$a->strings["Categories:"] = "Kategorien:";
$a->strings["Filed under:"] = "Abgelegt unter:";
$a->strings["%s from %s"] = "%s von %s";
$a->strings["View in context"] = "Im Zusammenhang betrachten";
$a->strings["remove"] = "löschen";
$a->strings["Delete Selected Items"] = "Lösche die markierten Beiträge";
$a->strings["You had been addressed (%s)."] = "Du wurdest angeschrieben (%s).";
$a->strings["You are following %s."] = "Du folgst %s.";
$a->strings["Tagged"] = "Verschlagwortet";
$a->strings["Reshared"] = "Geteilt";
$a->strings["Reshared by %s <%s>"] = "Geteilt von %s <%s>";
$a->strings["%s is participating in this thread."] = "%s ist an der Unterhaltung beteiligt.";
$a->strings["Stored"] = "Gespeichert";
$a->strings["Global"] = "Global";
$a->strings["Relayed"] = "Übermittelt";
$a->strings["Relayed by %s <%s>"] = "Weitergeleitet von %s <%s>";
$a->strings["Fetched"] = "Abgerufen";
$a->strings["Fetched because of %s <%s>"] = "Wegen %s <%s> abgerufen";
$a->strings["General Features"] = "Allgemeine Features";
$a->strings["Photo Location"] = "Aufnahmeort";
$a->strings["Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map."] = "Die Foto-Metadaten werden ausgelesen. Dadurch kann der Aufnahmeort (wenn vorhanden) in einer Karte angezeigt werden.";
@ -661,6 +648,19 @@ $a->strings["Forums"] = "Foren";
$a->strings["External link to forum"] = "Externer Link zum Forum";
$a->strings["show less"] = "weniger anzeigen";
$a->strings["show more"] = "mehr anzeigen";
$a->strings["%1\$s poked %2\$s"] = "%1\$s stupste %2\$s";
$a->strings["event"] = "Veranstaltung";
$a->strings["Follow Thread"] = "Folge der Unterhaltung";
$a->strings["View Status"] = "Status anschauen";
$a->strings["View Profile"] = "Profil anschauen";
$a->strings["View Photos"] = "Bilder anschauen";
$a->strings["Network Posts"] = "Netzwerkbeiträge";
$a->strings["View Contact"] = "Kontakt anzeigen";
$a->strings["Send PM"] = "Private Nachricht senden";
$a->strings["Block"] = "Sperren";
$a->strings["Ignore"] = "Ignorieren";
$a->strings["Languages"] = "Sprachen";
$a->strings["Poke"] = "Anstupsen";
$a->strings["Nothing new here"] = "Keine Neuigkeiten";
$a->strings["Go back"] = "Geh zurück";
$a->strings["Clear notifications"] = "Bereinige Benachrichtigungen";
@ -1212,9 +1212,24 @@ $a->strings["Must be writable by web server. Relative to your Friendica top-leve
$a->strings["Log level"] = "Protokoll-Level";
$a->strings["PHP logging"] = "PHP Protokollieren";
$a->strings["To temporarily enable logging of PHP errors and warnings you can prepend the following to the index.php file of your installation. The filename set in the 'error_log' line is relative to the friendica top-level directory and must be writeable by the web server. The option '1' for 'log_errors' and 'display_errors' is to enable these options, set to '0' to disable them."] = "Um die Protokollierung von PHP-Fehlern und Warnungen vorübergehend zu aktivieren, kannst du der Datei index.php deiner Installation Folgendes voranstellen. Der in der Datei 'error_log' angegebene Dateiname ist relativ zum obersten Verzeichnis von Friendica und muss vom Webserver beschreibbar sein. Die Option '1' für 'log_errors' und 'display_errors' aktiviert diese Optionen, ersetze die '1' durch eine '0', um sie zu deaktivieren.";
$a->strings["Error trying to open <strong>%1\$s</strong> log file.\\r\\n<br/>Check to see if file %1\$s exist and is readable."] = "Fehler beim Öffnen der Logdatei <strong>%1\$s</strong>.\\r\\n<br/>Bitte überprüfe ob die Datei %1\$s existiert und gelesen werden kann.";
$a->strings["Couldn't open <strong>%1\$s</strong> log file.\\r\\n<br/>Check to see if file %1\$s is readable."] = "Konnte die Logdatei <strong>%1\$s</strong> nicht öffnen.\\r\\n<br/>Bitte stelle sicher, dass die Datei %1\$s lesbar ist.";
$a->strings["Error trying to open <strong>%1\$s</strong> log file.<br/>Check to see if file %1\$s exist and is readable."] = "Fehler beim Öffnen der Logdatei <strong>%1\$s</strong>.<br/>Bitte überprüfe ob die Datei %1\$s existiert und gelesen werden kann.";
$a->strings["Couldn't open <strong>%1\$s</strong> log file.<br/>Check to see if file %1\$s is readable."] = "Konnte die Logdatei <strong>%1\$s</strong> nicht öffnen.<br/>Bitte stelle sicher, dass die Datei %1\$s lesbar ist.";
$a->strings["View Logs"] = "Protokolle anzeigen";
$a->strings["Search in logs"] = "Logs durchsuchen";
$a->strings["Show all"] = "Alle anzeigen";
$a->strings["Date"] = "Datum";
$a->strings["Level"] = "Level";
$a->strings["Context"] = "Zusammenhang";
$a->strings["ALL"] = "ALLE";
$a->strings["View details"] = "Details anzeigen";
$a->strings["Click to view details"] = "Anklicken zum Anzeigen der Details";
$a->strings["Data"] = "Daten";
$a->strings["File"] = "Datei";
$a->strings["Line"] = "Zeile";
$a->strings["Function"] = "Funktion";
$a->strings["UID"] = "UID";
$a->strings["Process ID"] = "Prozess ID";
$a->strings["Close"] = "Schließen";
$a->strings["Inspect Deferred Worker Queue"] = "Verzögerte Worker-Warteschlange inspizieren";
$a->strings["This page lists the deferred worker jobs. This are jobs that couldn't be executed at the first time."] = "Auf dieser Seite werden die aufgeschobenen Worker-Jobs aufgelistet. Dies sind Jobs, die beim ersten Mal nicht ausgeführt werden konnten.";
$a->strings["Inspect Worker Queue"] = "Worker-Warteschlange inspizieren";
@ -1935,7 +1950,6 @@ $a->strings["System Notifications"] = "Systembenachrichtigungen";
$a->strings["Personal Notifications"] = "Persönliche Benachrichtigungen";
$a->strings["Home Notifications"] = "Pinnwandbenachrichtigungen";
$a->strings["Show unread"] = "Ungelesene anzeigen";
$a->strings["Show all"] = "Alle anzeigen";
$a->strings["Authorize application connection"] = "Verbindung der Applikation autorisieren";
$a->strings["Do you want to authorize this application to access your posts and contacts, and/or create new posts for you?"] = "Möchtest du dieser Anwendung den Zugriff auf Deine Beiträge und Kontakte sowie das Erstellen neuer Beiträge in Deinem Namen gestatten?";
$a->strings["Unsupported or missing response type"] = "Der Typ der Antwort fehlt oder wird nicht unterstützt";

File diff suppressed because it is too large Load diff

View file

@ -20,95 +20,6 @@ $a->strings["Weekly posting limit of %d post reached. The post was rejected."] =
];
$a->strings["Monthly posting limit of %d post reached. The post was rejected."] = "Месячный лимит в %d записей достигнут. Запись была отклонена.";
$a->strings["Profile Photos"] = "Фотографии профиля";
$a->strings["%1\$s poked %2\$s"] = "%1\$s ткнул %2\$s";
$a->strings["event"] = "мероприятие";
$a->strings["status"] = "статус";
$a->strings["photo"] = "фото";
$a->strings["%1\$s tagged %2\$s's %3\$s with %4\$s"] = "%1\$s tagged %2\$s's %3\$s в %4\$s";
$a->strings["Select"] = "Выберите";
$a->strings["Delete"] = "Удалить";
$a->strings["View %s's profile @ %s"] = "Просмотреть профиль %s [@ %s]";
$a->strings["Categories:"] = "Категории:";
$a->strings["Filed under:"] = "В рубрике:";
$a->strings["%s from %s"] = "%s из %s";
$a->strings["View in context"] = "Смотреть в контексте";
$a->strings["Please wait"] = "Пожалуйста, подождите";
$a->strings["remove"] = "удалить";
$a->strings["Delete Selected Items"] = "Удалить выбранные позиции";
$a->strings["You had been addressed (%s)."] = "К вам обратились (%s).";
$a->strings["You are following %s."] = "Вы подписаны на %s.";
$a->strings["Tagged"] = "Отмечено";
$a->strings["%s reshared this."] = "%s поделился этим.";
$a->strings["Reshared"] = "Репост";
$a->strings["%s is participating in this thread."] = "%s участвует в этом обсуждении";
$a->strings["Relayed"] = "Ретранслировано";
$a->strings["Fetched"] = "Загружено";
$a->strings["Follow Thread"] = "Подписаться на обсуждение";
$a->strings["View Status"] = "Просмотреть статус";
$a->strings["View Profile"] = "Просмотреть профиль";
$a->strings["View Photos"] = "Просмотреть фото";
$a->strings["Network Posts"] = "Записи сети";
$a->strings["View Contact"] = "Просмотреть контакт";
$a->strings["Send PM"] = "Отправить ЛС";
$a->strings["Block"] = "Заблокировать";
$a->strings["Ignore"] = "Игнорировать";
$a->strings["Languages"] = "Языки";
$a->strings["Poke"] = "потыкать";
$a->strings["Connect/Follow"] = "Подключиться/Подписаться";
$a->strings["%s likes this."] = "%s нравится это.";
$a->strings["%s doesn't like this."] = "%s не нравится это.";
$a->strings["%s attends."] = "%s посещает.";
$a->strings["%s doesn't attend."] = "%s не посетит.";
$a->strings["%s attends maybe."] = "%s может быть посетит.";
$a->strings["and"] = "и";
$a->strings["and %d other people"] = "и еще %d человек";
$a->strings["<span %1\$s>%2\$d people</span> like this"] = "<span %1\$s>%2\$d людям</span> нравится это";
$a->strings["%s like this."] = "%s нравится это.";
$a->strings["<span %1\$s>%2\$d people</span> don't like this"] = "<span %1\$s>%2\$d людям</span> не нравится это";
$a->strings["%s don't like this."] = "%s не нравится это";
$a->strings["<span %1\$s>%2\$d people</span> attend"] = "<span %1\$s>%2\$d человека</span> посетят";
$a->strings["%s attend."] = "%s посетит.";
$a->strings["<span %1\$s>%2\$d people</span> don't attend"] = "<span %1\$s>%2\$d человек</span> не посетит";
$a->strings["%s don't attend."] = "%s не посетит";
$a->strings["<span %1\$s>%2\$d people</span> attend maybe"] = "<span %1\$s>%2\$d человек</span> может быть посетят";
$a->strings["%s attend maybe."] = "%s может быть посетит.";
$a->strings["<span %1\$s>%2\$d people</span> reshared this"] = "<span %1\$s>%2\$d людей</span> поделились этим";
$a->strings["Visible to <strong>everybody</strong>"] = "Видимое <strong>всем</strong>";
$a->strings["Please enter a image/video/audio/webpage URL:"] = "Пожалуйста, введите адрес картинки/видео/аудио/странички:";
$a->strings["Tag term:"] = "Тег:";
$a->strings["Save to Folder:"] = "Сохранить в папку:";
$a->strings["Where are you right now?"] = "И где вы сейчас?";
$a->strings["Delete item(s)?"] = "Удалить елемент(ты)?";
$a->strings["New Post"] = "Новая запись";
$a->strings["Share"] = "Поделиться";
$a->strings["Loading..."] = "Загрузка...";
$a->strings["Upload photo"] = "Загрузить фото";
$a->strings["upload photo"] = "загрузить фото";
$a->strings["Attach file"] = "Прикрепить файл";
$a->strings["attach file"] = "приложить файл";
$a->strings["Bold"] = "Жирный";
$a->strings["Italic"] = "Kурсивный";
$a->strings["Underline"] = "Подчеркнутый";
$a->strings["Quote"] = "Цитата";
$a->strings["Code"] = "Код";
$a->strings["Image"] = "Изображение / Фото";
$a->strings["Link"] = "Ссылка";
$a->strings["Link or Media"] = "Ссылка или медиа";
$a->strings["Set your location"] = "Задать ваше местоположение";
$a->strings["set location"] = "установить местонахождение";
$a->strings["Clear browser location"] = "Очистить местонахождение браузера";
$a->strings["clear location"] = "убрать местонахождение";
$a->strings["Set title"] = "Установить заголовок";
$a->strings["Categories (comma-separated list)"] = "Категории (список через запятую)";
$a->strings["Scheduled at"] = "Запланировано на";
$a->strings["Permission settings"] = "Настройки разрешений";
$a->strings["Permissions"] = "Разрешения";
$a->strings["Public post"] = "Публичное сообщение";
$a->strings["Preview"] = "Просмотр";
$a->strings["Cancel"] = "Отмена";
$a->strings["Message"] = "Сообщение";
$a->strings["Browser"] = "Браузер";
$a->strings["Open Compose page"] = "Развернуть редактор";
$a->strings["[Friendica:Notify]"] = "[Friendica]";
$a->strings["%s New mail received at %s"] = "%s Новая почта получена в %s";
$a->strings["%1\$s sent you a new private message at %2\$s."] = "%1\$s отправил вам новое личное сообщение на %2\$s.";
@ -181,14 +92,34 @@ $a->strings["The feed for this item is unavailable."] = "Лента недост
$a->strings["Item not found"] = "Элемент не найден";
$a->strings["Edit post"] = "Редактировать запись";
$a->strings["Save"] = "Сохранить";
$a->strings["Loading..."] = "Загрузка...";
$a->strings["Upload photo"] = "Загрузить фото";
$a->strings["upload photo"] = "загрузить фото";
$a->strings["Attach file"] = "Прикрепить файл";
$a->strings["attach file"] = "приложить файл";
$a->strings["Insert web link"] = "Вставить веб-ссылку";
$a->strings["web link"] = "веб-ссылка";
$a->strings["Insert video link"] = "Вставить ссылку видео";
$a->strings["video link"] = "видео-ссылка";
$a->strings["Insert audio link"] = "Вставить ссылку аудио";
$a->strings["audio link"] = "аудио-ссылка";
$a->strings["Set your location"] = "Задать ваше местоположение";
$a->strings["set location"] = "установить местонахождение";
$a->strings["Clear browser location"] = "Очистить местонахождение браузера";
$a->strings["clear location"] = "убрать местонахождение";
$a->strings["Please wait"] = "Пожалуйста, подождите";
$a->strings["Permission settings"] = "Настройки разрешений";
$a->strings["CC: email addresses"] = "Копии на email адреса";
$a->strings["Public post"] = "Публичное сообщение";
$a->strings["Set title"] = "Установить заголовок";
$a->strings["Categories (comma-separated list)"] = "Категории (список через запятую)";
$a->strings["Example: bob@example.com, mary@example.com"] = "Пример: bob@example.com, mary@example.com";
$a->strings["Preview"] = "Просмотр";
$a->strings["Cancel"] = "Отмена";
$a->strings["Message"] = "Сообщение";
$a->strings["Browser"] = "Браузер";
$a->strings["Permissions"] = "Разрешения";
$a->strings["Open Compose page"] = "Развернуть редактор";
$a->strings["Event can not end before it has started."] = "Эвент не может закончится до старта.";
$a->strings["Event title and start time are required."] = "Название мероприятия и время начала обязательны для заполнения.";
$a->strings["Create New Event"] = "Создать новое мероприятие";
@ -215,6 +146,7 @@ $a->strings["You already added this contact."] = "Вы уже добавили
$a->strings["The network type couldn't be detected. Contact can't be added."] = "Тип сети не может быть определен. Контакт не может быть добавлен.";
$a->strings["Diaspora support isn't enabled. Contact can't be added."] = "Поддержка Diaspora не включена. Контакт не может быть добавлен.";
$a->strings["OStatus support is disabled. Contact can't be added."] = "Поддержка OStatus выключена. Контакт не может быть добавлен.";
$a->strings["Connect/Follow"] = "Подключиться/Подписаться";
$a->strings["Please answer the following:"] = "Пожалуйста, ответьте следующее:";
$a->strings["Your Identity Address:"] = "Ваш адрес:";
$a->strings["Profile URL"] = "URL профиля";
@ -346,6 +278,8 @@ $a->strings["Rotate CW (right)"] = "Поворот по часовой стре
$a->strings["Rotate CCW (left)"] = "Поворот против часовой стрелки (налево)";
$a->strings["This is you"] = "Это вы";
$a->strings["Comment"] = "Комментировать";
$a->strings["Select"] = "Выберите";
$a->strings["Delete"] = "Удалить";
$a->strings["I like this (toggle)"] = "Нравится";
$a->strings["I don't like this (toggle)"] = "Не нравится";
$a->strings["Map"] = "Карта";
@ -403,6 +337,8 @@ $a->strings["Social Networks"] = "Социальные сети";
$a->strings["General Social Media Settings"] = "Общие настройки социальных медиа";
$a->strings["Accept only top level posts by contacts you follow"] = "Получать начальные записи только от ваших контактов";
$a->strings["The system does an auto completion of threads when a comment arrives. This has got the side effect that you can receive posts that had been started by a non-follower but had been commented by someone you follow. This setting deactivates this behaviour. When activated, you strictly only will receive posts from people you really do follow."] = "Система автоматически загружает диалоги, когда получает комментарии. Это может приводить к тому, что вы можете видеть записи от людей, на которых вы не подписаны, потому что их прокомментировал кто-то из ваших контактов. Эта настройка отключает такое поведение и вы будете видеть только записи тех людей, на которых подписаны.";
$a->strings["Enable Content Warning"] = "Включить предупреждение о контенте";
$a->strings["Users on networks like Mastodon or Pleroma are able to set a content warning field which collapse their post by default. This enables the automatic collapsing instead of setting the content warning as the post title. Doesn't affect any other content filtering you eventually set up."] = "Пользователи некоторых сетей, таких как Mastodon или Pleroma, могут использовать \"предупреждение о контенте\", сворачивающее их записи. Эта настройка выключает это свёртывание вместо обычного помещения \"предупреждения о контенте\" в заголовок записи. Это не влияет на другие фильтры, которые вы можете настроить.";
$a->strings["Attach the link title"] = "Присоединять заголовок ссылок";
$a->strings["When activated, the title of the attached link will be added as a title on posts to Diaspora. This is mostly helpful with \"remote-self\" contacts that share feed content."] = "Если включено. заголовок добавленной ссылки будет добавлен к записи в Диаспоре как заголовок. Это в основном нужно для контактов \"мой двойник\", которые публикуют содержимое ленты.";
$a->strings["Repair OStatus subscriptions"] = "Починить подписки OStatus";
@ -529,6 +465,9 @@ $a->strings["If you have moved this profile from another server, and some of you
$a->strings["Resend relocate message to contacts"] = "Отправить перемещённые сообщения контактам";
$a->strings["No suggestions available. If this is a new site, please try again in 24 hours."] = "Нет предложений. Если это новый сайт, пожалуйста, попробуйте снова через 24 часа.";
$a->strings["Friend Suggestions"] = "Предложения друзей";
$a->strings["photo"] = "фото";
$a->strings["status"] = "статус";
$a->strings["%1\$s tagged %2\$s's %3\$s with %4\$s"] = "%1\$s tagged %2\$s's %3\$s в %4\$s";
$a->strings["Remove Item Tag"] = "Удалить ключевое слово";
$a->strings["Select a tag to remove: "] = "Выберите ключевое слово для удаления: ";
$a->strings["Remove"] = "Удалить";
@ -614,6 +553,56 @@ $a->strings["GNU Social Connector"] = "GNU Social Connector";
$a->strings["ActivityPub"] = "ActivityPub";
$a->strings["pnut"] = "pnut";
$a->strings["%s (via %s)"] = "%s (через %s)";
$a->strings["%s likes this."] = "%s нравится это.";
$a->strings["%s doesn't like this."] = "%s не нравится это.";
$a->strings["%s attends."] = "%s посещает.";
$a->strings["%s doesn't attend."] = "%s не посетит.";
$a->strings["%s attends maybe."] = "%s может быть посетит.";
$a->strings["%s reshared this."] = "%s поделился этим.";
$a->strings["and"] = "и";
$a->strings["and %d other people"] = "и еще %d человек";
$a->strings["<span %1\$s>%2\$d people</span> like this"] = "<span %1\$s>%2\$d людям</span> нравится это";
$a->strings["%s like this."] = "%s нравится это.";
$a->strings["<span %1\$s>%2\$d people</span> don't like this"] = "<span %1\$s>%2\$d людям</span> не нравится это";
$a->strings["%s don't like this."] = "%s не нравится это";
$a->strings["<span %1\$s>%2\$d people</span> attend"] = "<span %1\$s>%2\$d человека</span> посетят";
$a->strings["%s attend."] = "%s посетит.";
$a->strings["<span %1\$s>%2\$d people</span> don't attend"] = "<span %1\$s>%2\$d человек</span> не посетит";
$a->strings["%s don't attend."] = "%s не посетит";
$a->strings["<span %1\$s>%2\$d people</span> attend maybe"] = "<span %1\$s>%2\$d человек</span> может быть посетят";
$a->strings["%s attend maybe."] = "%s может быть посетит.";
$a->strings["<span %1\$s>%2\$d people</span> reshared this"] = "<span %1\$s>%2\$d людей</span> поделились этим";
$a->strings["Visible to <strong>everybody</strong>"] = "Видимое <strong>всем</strong>";
$a->strings["Please enter a image/video/audio/webpage URL:"] = "Пожалуйста, введите адрес картинки/видео/аудио/странички:";
$a->strings["Tag term:"] = "Тег:";
$a->strings["Save to Folder:"] = "Сохранить в папку:";
$a->strings["Where are you right now?"] = "И где вы сейчас?";
$a->strings["Delete item(s)?"] = "Удалить елемент(ты)?";
$a->strings["New Post"] = "Новая запись";
$a->strings["Share"] = "Поделиться";
$a->strings["Bold"] = "Жирный";
$a->strings["Italic"] = "Kурсивный";
$a->strings["Underline"] = "Подчеркнутый";
$a->strings["Quote"] = "Цитата";
$a->strings["Code"] = "Код";
$a->strings["Image"] = "Изображение / Фото";
$a->strings["Link"] = "Ссылка";
$a->strings["Link or Media"] = "Ссылка или медиа";
$a->strings["Scheduled at"] = "Запланировано на";
$a->strings["View %s's profile @ %s"] = "Просмотреть профиль %s [@ %s]";
$a->strings["Categories:"] = "Категории:";
$a->strings["Filed under:"] = "В рубрике:";
$a->strings["%s from %s"] = "%s из %s";
$a->strings["View in context"] = "Смотреть в контексте";
$a->strings["remove"] = "удалить";
$a->strings["Delete Selected Items"] = "Удалить выбранные позиции";
$a->strings["You had been addressed (%s)."] = "К вам обратились (%s).";
$a->strings["You are following %s."] = "Вы подписаны на %s.";
$a->strings["Tagged"] = "Отмечено";
$a->strings["Reshared"] = "Репост";
$a->strings["%s is participating in this thread."] = "%s участвует в этом обсуждении";
$a->strings["Relayed"] = "Ретранслировано";
$a->strings["Fetched"] = "Загружено";
$a->strings["General Features"] = "Основные возможности";
$a->strings["Photo Location"] = "Место фотографирования";
$a->strings["Photo metadata is normally stripped. This extracts the location (if present) prior to stripping metadata and links it to a map."] = "Метаданные фотографий обычно вырезаются. Эта настройка получает местоположение (если есть) до вырезки метаданных и связывает с координатами на карте.";
@ -637,6 +626,19 @@ $a->strings["Display membership date in profile"] = "Дата вашей рег
$a->strings["Forums"] = "Форумы";
$a->strings["External link to forum"] = "Внешняя ссылка на форум";
$a->strings["show more"] = "показать больше";
$a->strings["%1\$s poked %2\$s"] = "%1\$s ткнул %2\$s";
$a->strings["event"] = "мероприятие";
$a->strings["Follow Thread"] = "Подписаться на обсуждение";
$a->strings["View Status"] = "Просмотреть статус";
$a->strings["View Profile"] = "Просмотреть профиль";
$a->strings["View Photos"] = "Просмотреть фото";
$a->strings["Network Posts"] = "Записи сети";
$a->strings["View Contact"] = "Просмотреть контакт";
$a->strings["Send PM"] = "Отправить ЛС";
$a->strings["Block"] = "Заблокировать";
$a->strings["Ignore"] = "Игнорировать";
$a->strings["Languages"] = "Языки";
$a->strings["Poke"] = "потыкать";
$a->strings["Nothing new here"] = "Ничего нового здесь";
$a->strings["Go back"] = "Назад";
$a->strings["Clear notifications"] = "Стереть уведомления";
@ -977,6 +979,7 @@ $a->strings["bytes"] = "байт";
$a->strings["View on separate page"] = "Посмотреть в отдельной вкладке";
$a->strings["[no subject]"] = "[без темы]";
$a->strings["%1\$s had started following you"] = "%1\$s подписались на вас";
$a->strings["%1\$s replied to you on %2\$s"] = "%1\$s ответил(а) вам на %2\$s";
$a->strings["%1\$s commented in your thread %2\$s"] = "%1\$s ответил в вашем обсуждении %2\$s";
$a->strings["%1\$s commented in their thread %2\$s"] = "%1\$s ответил в своём обсуждении %2\$s";
$a->strings["%1\$s commented in their thread"] = "%1\$s ответил в своём обсуждении";
@ -1779,6 +1782,7 @@ $a->strings["%s's timeline"] = "Лента %s";
$a->strings["%s's posts"] = "Записи %s";
$a->strings["%s's comments"] = "Комментарии %s";
$a->strings["Scheduled"] = "Запланировано";
$a->strings["Content"] = "Содержание";
$a->strings["Only parent users can create additional accounts."] = "Только основные пользователи могут создавать дополнительные учётные записи.";
$a->strings["If you are not familiar with OpenID, please leave that field blank and fill in the rest of the items."] = "Если вы не знакомы с OpenID, пожалуйста, оставьте это поле пустым и заполните остальные элементы.";
$a->strings["Your OpenID (optional): "] = "Ваш OpenID (необязательно):";

View file

@ -9,16 +9,16 @@
{{else}}
<form>
<p>
<input type="search" name="q" value="{{$q}}" placeholder="search"></input>
<input type="Submit" value="search">
<a href="/admin/logs/view">clear</a>
<input type="search" name="q" value="{{$q}}" placeholder="{{$l10n.Search}}"></input>
<input type="submit" value="{{$l10n.Search}}">
<a href="/admin/logs/view">{{$l10n.Show_all}}</a>
</p>
<table>
<thead>
<tr>
<th>Date</th>
<th>{{$l10n.Date}}</th>
<th>
<select name="level" onchange="this.form.submit()">
{{foreach $filtersvalues.level as $v }}
@ -39,22 +39,22 @@
{{/foreach}}
</select>
</th>
<th>Message</th>
<th>{{$l10n.Message}}</th>
</tr>
</thead>
<tbody>
{{foreach $data as $row}}
<tr id="ev-{{$row->id}}" class="log-event"
role="button" tabIndex="0"
aria-label="View details" aria-haspopup="true" aria-expanded="false"
aria-label="{{$l10n.View_details}}" aria-haspopup="true" aria-expanded="false"
style="cursor:pointer;"
title="Click to view details">
title="{{$l10n.Click_to_view_details}}">
<td>{{$row->date}}</td>
<td>{{$row->level}}</td>
<td>{{$row->context}}</td>
<td>{{$row->message}}</td>
</tr>
<tr class="hidden" data-id="ev-{{$row->id}}"><th colspan="4">Data</th></tr>
<tr class="hidden" data-id="ev-{{$row->id}}"><th colspan="4">{{$l10n.Event_details}}</th></tr>
{{foreach $row->getData() as $k=>$v}}
<tr class="hidden" data-id="ev-{{$row->id}}">
<th>{{$k}}</th>
@ -63,7 +63,7 @@
</td>
</tr>
{{/foreach}}
<tr class="hidden" data-id="ev-{{$row->id}}"><th colspan="4">Source</th></tr>
<tr class="hidden" data-id="ev-{{$row->id}}"><th colspan="4">{{$l10n.Source}}</th></tr>
{{foreach $row->getSource() as $k=>$v}}
<tr class="hidden" data-id="ev-{{$row->id}}">
<th>{{$k}}</th>

View file

@ -152,7 +152,7 @@
<form action="{{$baseurl}}/admin/site" method="post">
<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
<h2>{{$relocate}}</h2>
<p>{{$relocate_warning}}</p>
<p>{{$relocate_warning nofilter}}</p>
{{include file="field_input.tpl" field=$relocate_url}}
<input type="hidden" name="page_site" value="{{$submit}}">
<div class="submit"><input type="submit" name="relocate" value="{{$relocate_button}}"/></div>

View file

@ -8,33 +8,33 @@
</div>
{{else}}
<form method="get" class="row">
<div class="col-xs-10">
<div class="col-xs-8">
<div class="form-group form-group-search">
<input accesskey="s" id="nav-search-input-field" class="form-control form-search"
type="text" name="q" data-toggle="tooltip" title="Search in logs"
placeholder="Search" value="{{$q}}">
type="text" name="q" data-toggle="tooltip" title="{{$l10n.Search_in_logs}}"
placeholder="{{$l10n.Search}}" value="{{$q}}">
<button class="btn btn-default btn-sm form-button-search"
type="submit">Search</button>
type="submit">{{$l10n.Search}}</button>
</div>
</div>
<div class="xol-xs-2">
<a href="/admin/logs/view" class="btn btn-default">Show all</a>
<div class="xol-xs-4">
<a href="/admin/logs/view" class="btn btn-default">{{$l10n.Show_all}}</a>
</div>
</form>
<table class="table table-hover">
<thead>
<tr>
<th>Date</th>
<th>{{$l10n.Date}}</th>
<th class="dropdown">
<a class="dropdown-toggle text-nowrap" type="button" id="level" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Level {{if $filters.level}}({{$filters.level}}){{/if}}<span class="caret"></span>
{{$l10n.Level}} {{if $filters.level}}({{$filters.level}}){{/if}}<span class="caret"></span>
</a>
<ul class="dropdown-menu" aria-labelledby="level">
{{foreach $filtersvalues.level as $v }}
<li {{if $filters.level == $v}}class="active"{{/if}}>
<a href="/admin/logs/view?level={{$v}}" data-filter="level" data-filter-value="{{$v}}">
{{if $v == ""}}ALL{{/if}}{{$v}}
{{if $v == ""}}{{$l10n.ALL}}{{/if}}{{$v}}
</a>
</li>
{{/foreach}}
@ -42,26 +42,26 @@
</th>
<th class="dropdown">
<a class="dropdown-toggle text-nowrap" type="button" id="context" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Context {{if $filters.context}}({{$filters.context}}){{/if}}<span class="caret"></span>
{{$l10n.Context}} {{if $filters.context}}({{$filters.context}}){{/if}}<span class="caret"></span>
</a>
<ul class="dropdown-menu" aria-labelledby="context">
{{foreach $filtersvalues.context as $v }}
<li {{if $filters.context == $v}}class="active"{{/if}}>
<a href="/admin/logs/view?context={{$v}}" data-filter="context" data-filter-value="{{$v}}">
{{if $v == ""}}ALL{{/if}}{{$v}}
{{if $v == ""}}{{$l10n.ALL}}{{/if}}{{$v}}
</a>
</li>
{{/foreach}}
</ul>
</th>
<th>Message</th>
<th>{{$l10n.Message}}</th>
</tr>
</thead>
<tbody>
{{foreach $data as $row}}
<tr id="ev-{{$row->id}}" class="log-event"
role="button" tabIndex="0"
aria-label="View details" aria-haspopup="true" aria-expanded="false"
aria-label="{{$l10n.View_details}}" aria-haspopup="true" aria-expanded="false"
data-data="{{$row->data}}" data-source="{{$row->source}}">
<td>{{$row->date}}</td>
<td class="
@ -86,16 +86,16 @@
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">Event details</h4>
<h4 class="modal-title">{{$l10n.Event_details}}</h4>
</div>
<div class="modal-body">
<table class="table main-data">
<thead>
<tr>
<th>Date</th>
<th>Level</th>
<th>Context</th>
<th>Message</th>
<th>{{$l10n.Date}}</th>
<th>{{$l10n.Level}}</th>
<th>{{$l10n.Context}}</th>
<th>{{$l10n.Message}}</th>
</tr>
</thead>
<tbody><tr></tr></tbody>
@ -103,11 +103,11 @@
<table class="table source-data">
<thead>
<tr>
<th>File</th>
<th>Line</th>
<th>Function</th>
<th>UID</th>
<th>Process ID</th>
<th>{{$l10n.File}}</th>
<th>{{$l10n.Line}}</th>
<th>{{$l10n.Function}}</th>
<th>{{$l10n.UID}}</th>
<th>{{$l10n.Process_ID}}</th>
</tr>
</thead>
<tbody>
@ -131,7 +131,7 @@
<div class="modal-footer">
<button type="button" class="btn btn-default" data-previous>&lt;</button>
<button type="button" class="btn btn-default" data-next>&gt;</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-dismiss="modal">{{$l10n.Close}}</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->

View file

@ -339,7 +339,7 @@
<div id="admin-settings-relocate-collapse" class="panel-collapse collapse" role="tabpanel" aria-labelledby="admin-settings-relocate">
<div class="panel-body">
<div class="alert alert-danger alert-dismissible">
{{$relocate_warning}}
{{$relocate_warning nofilter}}
</div>
{{include file="field_input.tpl" field=$relocate_url}}
</div>