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

6
Vagrantfile vendored
View file

@ -6,8 +6,8 @@ server_timezone = "UTC"
public_folder = "/vagrant" public_folder = "/vagrant"
Vagrant.configure(2) do |config| Vagrant.configure(2) do |config|
# Set server to Debian 10 / Buster 64bit # Set server to Debian 11 / Bullseye 64bit
config.vm.box = "debian/buster64" config.vm.box = "debian/bullseye64"
# Disable automatic box update checking. If you disable this, then # Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs # 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 # 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: "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 # Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options. # 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/mailname string friendica.local"
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Local Only'" debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Local Only'"
apt-get install -qq postfix mailutils libmailutils-dev 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 # Friendica needs git for fetching some dependencies
echo ">>> Installing git" echo ">>> Installing git"
@ -93,13 +93,8 @@ echo ">>> Symlink /var/www to /vagrant"
rm -rf /var/www/ rm -rf /var/www/
ln -fs /vagrant /var/www ln -fs /vagrant /var/www
# install deps with composer # Setup Friendica
echo ">>> Installing php requirements"
apt install unzip
cd /var/www cd /var/www
php bin/composer.phar install
echo ">>> Setup Friendica" echo ">>> Setup Friendica"
# copy the .htaccess-dist file to .htaccess so that rewrite rules work # 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 add "$USER_NICK" "$USER_NICK" "$USER_NICK@friendica.local" en
bin/console user password "$USER_NICK" "$USER_PASSW" 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 # create cronjob - activate if you have enough memory in you dev VM
# cronjob runs as www-data user # cronjob runs as www-data user
echo ">>> Installing cronjob" echo ">>> Installing cronjob"

View file

@ -84,7 +84,6 @@
"Friendica\\Addon\\": "addon/" "Friendica\\Addon\\": "addon/"
}, },
"files": [ "files": [
"include/conversation.php",
"include/dba.php", "include/dba.php",
"include/enotify.php", "include/enotify.php",
"boot.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('enotify_mail', $datarray);
Hook::callAll('check_item_notification', $notification_data); Hook::callAll('check_item_notification', $notification_data);
### include/conversation.php ### src/Content/Conversation.php
Hook::callAll('conversation_start', $cb); Hook::callAll('conversation_start', $cb);
Hook::callAll('render_location', $locate); 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 * 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 * 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) * 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.) * 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) * 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. * 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. 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. 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: What you need to do:
1. Install VirtualBox and vagrant. 1. Install VirtualBox and vagrant.
Please use an up-to-date vagrant version from https://www.vagrantup.com/downloads.html. Please use an up-to-date vagrant version from https://www.vagrantup.com/downloads.html.
2. Git clone your Friendica repository. 2. Git clone your Friendica repository.
Inside, you'll find a "Vagrantfile" and some scripts in the utils folder. Inside, you'll find a `Vagrantfile` and some scripts in the `bin/dev` folder.
3. Run "vagrant up" from inside the friendica clone: Pull the PHP requirements with `bin/composer install`.
$> vagrant up 3. Run `vagrant up` from inside the friendica clone.
Be patient: When it runs for the first time, it downloads an Ubuntu Server image. This will start the virtual machine.
4. Run "vagrant ssh" to log into the virtual machine to log in to the VM: Be patient: When it runs for the first time, it downloads a Debian Server image and installs Friendica.
$> vagrant ssh 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. 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". 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). 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). 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. 7. Check the changes in your browser in the VM.
Debug via the "vagrant ssh" login. Find the Friendica log file `/vagrant/logfile.out` on the VM or in the `logfile.out` in you local Friendica directory.
Find the Friendica log file /vagrant/logfile.out.
8. Commit and push your changes directly back to Github. 8. Commit and push your changes directly back to Github.
If you want to stop vagrant after finishing your work, run the following command 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". to make sure that you can start from scratch with another "vagrant up".
The vagrant Friendica instance contains a test database. Default User Accounts
You will then have the following accounts to login: ---------------------
By default the provision script will setup two user accounts.
* admin, password admin * admin, password admin
* friendica1, password friendica1 * friendica, password friendica
* 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.
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('enotify_mail', $datarray);
Hook::callAll('check_item_notification', $notification_data); Hook::callAll('check_item_notification', $notification_data);
### include/conversation.php ### src/Content/Conversation.php
Hook::callAll('conversation_start', $cb); Hook::callAll('conversation_start', $cb);
Hook::callAll('render_location', $locate); 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 * PHP *Kommandozeilen*-Zugang mit register_argc_argv auf "true" gesetzt in der php.ini-Datei
* Curl, GD, PDO, MySQLi, xml, zip und OpenSSL-Erweiterung * 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) * 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.) * 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] * 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. * 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 // We have to avoid that the post is rejected because of an empty body
if (empty($_REQUEST['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); 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); $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 = []; $retweeted_item = [];
$quoted_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'])) { if (empty($retweeted_item) && ($item['owner-id'] == $item['author-id'])) {
$announce = api_get_announce($item); $announce = api_get_announce($item);
if (!empty($announce)) { 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['text'] = $rt_converted["text"];
$retweeted_status['statusnet_html'] = $rt_converted["html"]; $retweeted_status['statusnet_html'] = $rt_converted["html"];
$retweeted_status['friendica_html'] = $rt_converted["html"];
$retweeted_status['created_at'] = api_date($retweeted_item['created']); $retweeted_status['created_at'] = api_date($retweeted_item['created']);
if (!empty($quoted_status)) { if (!empty($quoted_status)) {
@ -4920,76 +4912,6 @@ function api_get_announce($item)
return array_merge($item, $announce); 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 * @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; $page_uid = 0;
$parent = null; $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]); $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. // We need the editor here to be able to reshare an item.
if ($is_owner && !$update) { if ($is_owner && !$update) {
$o .= status_editor($a, [], 0, true); $o .= DI::conversation()->statusEditor([], 0, true);
} }
$sql_extra = Item::getPermissionsSQLByUserId($page_uid); $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 .= "<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 // Preparing the meta header
$description = trim(BBCode::toPlaintext($item['body'])); $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 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 // Now check that valid personal details have been provided
if (!Security::canWriteToUserWall($profile_uid) && !$allow_comment) { 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.')); notice(DI::l10n()->t('Permission denied.'));
if ($return_path) { if ($return_path) {
DI::baseUrl()->redirect($return_path); DI::baseUrl()->redirect($return_path);
@ -677,7 +678,7 @@ function item_post(App $a) {
$datarray["uri-id"] = -1; $datarray["uri-id"] = -1;
$datarray["author-network"] = Protocol::DFRN; $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]); System::jsonExit(['preview' => $o]);
} }
@ -931,6 +932,7 @@ function drop_item(int $id, string $return = '')
item_redirect_after_action($item, $return); item_redirect_after_action($item, $return);
} else { } else {
Logger::notice('Permission denied.', ['local' => local_user(), 'uid' => $item['uid'], 'cid' => $contact_id]);
notice(DI::l10n()->t('Permission denied.')); notice(DI::l10n()->t('Permission denied.'));
DI::baseUrl()->redirect('display/' . $item['guid']); DI::baseUrl()->redirect('display/' . $item['guid']);
//NOTREACHED //NOTREACHED

View file

@ -57,7 +57,7 @@ function notes_content(App $a, $update = false)
'acl_data' => '', '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, $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); $count = count($notes);
$o .= conversation($a, $notes, 'notes', $update); $o .= DI::conversation()->create($notes, 'notes', $update);
} }
$o .= $pager->renderMinimal($count); $o .= $pager->renderMinimal($count);

View file

@ -1394,15 +1394,15 @@ function photos_content(App $a)
// display comments // display comments
if (DBA::isResult($items)) { if (DBA::isResult($items)) {
foreach ($items as $item) { foreach ($items as $item) {
builtin_activity_puller($item, $conv_responses); DI::conversation()->builtinActivityPuller($item, $conv_responses);
} }
if (!empty($conv_responses['like'][$link_item['uri']])) { 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']])) { 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))) { 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; 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\Database\DBA;
use Friendica\Model\Contact; use Friendica\Model\Contact;
use Friendica\Model\Item as ModelItem;
use Friendica\Model\Tag; use Friendica\Model\Tag;
use Friendica\Model\Post; 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 * A content helper class for displaying items
*/ */
class Item 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 * Return array with details for categories and folders for an item
* *
@ -221,4 +244,261 @@ class Item
return ['replaced' => $replaced, 'contact' => $contact]; 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) public static function removeAttachment($body, $no_link_desc = false)
{ {
return preg_replace_callback("/\s*\[attachment (.*?)\](.*?)\[\/attachment\]\s*/ism", 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]); $attach_data = self::getAttachmentData($match[0]);
if (empty($attach_data['url'])) { if (empty($attach_data['url'])) {
return $match[0]; return $match[0];
} elseif (strpos(str_replace($match[0], '', $body), $attach_data['url']) !== false) {
return '';
} elseif (empty($attach_data['title']) || $no_link_desc) { } elseif (empty($attach_data['title']) || $no_link_desc) {
return " \n[url]" . $attach_data['url'] . "[/url]\n"; return " \n[url]" . $attach_data['url'] . "[/url]\n";
} else { } else {

View file

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

View file

@ -134,6 +134,14 @@ abstract class DI
return self::$dice->create(Content\Item::class); 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 * @return Content\Text\BBCode\Video
*/ */

View file

@ -593,10 +593,7 @@ class DBStructure
// Compare it // Compare it
foreach ($definition AS $name => $structure) { foreach ($definition AS $name => $structure) {
$is_new_table = false; $is_new_table = false;
$group_by = "";
$sql3 = ""; $sql3 = "";
$is_unique = false;
$temp_name = $name;
if (!isset($database[$name])) { if (!isset($database[$name])) {
$r = self::createTable($name, $structure, $verbose, $action); $r = self::createTable($name, $structure, $verbose, $action);
if (!DBA::isResult($r)) { if (!DBA::isResult($r)) {
@ -604,23 +601,6 @@ class DBStructure
} }
$is_new_table = true; $is_new_table = true;
} else { } 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 * Drop the index if it isn't present in the definition
* or the definition differ from current status * 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_') { if ($current_index_definition != $new_index_definition && substr($indexname, 0, 6) != 'local_') {
$sql2 = self::dropIndex($indexname); $sql2 = self::dropIndex($indexname);
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2; $sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else { } else {
$sql3 .= ", " . $sql2; $sql3 .= ", " . $sql2;
} }
@ -647,7 +627,7 @@ class DBStructure
if (!isset($database[$name]["fields"][$fieldname])) { if (!isset($database[$name]["fields"][$fieldname])) {
$sql2 = self::addTableField($fieldname, $parameters); $sql2 = self::addTableField($fieldname, $parameters);
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2; $sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else { } else {
$sql3 .= ", " . $sql2; $sql3 .= ", " . $sql2;
} }
@ -675,7 +655,7 @@ class DBStructure
if ($current_field_definition != $new_field_definition) { if ($current_field_definition != $new_field_definition) {
$sql2 = self::modifyTableField($fieldname, $parameters); $sql2 = self::modifyTableField($fieldname, $parameters);
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2; $sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else { } else {
$sql3 .= ", " . $sql2; $sql3 .= ", " . $sql2;
} }
@ -700,11 +680,9 @@ class DBStructure
if ($current_index_definition != $new_index_definition) { if ($current_index_definition != $new_index_definition) {
$sql2 = self::createIndex($indexname, $fieldnames); $sql2 = self::createIndex($indexname, $fieldnames);
// Fetch the "group by" fields for unique indexes
$group_by = self::groupBy($fieldnames);
if ($sql2 != "") { if ($sql2 != "") {
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2; $sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else { } else {
$sql3 .= ", " . $sql2; $sql3 .= ", " . $sql2;
} }
@ -729,7 +707,7 @@ class DBStructure
$sql2 = self::addForeignKey($name, $fieldname, $parameters); $sql2 = self::addForeignKey($name, $fieldname, $parameters);
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2; $sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else { } else {
$sql3 .= ", " . $sql2; $sql3 .= ", " . $sql2;
} }
@ -740,7 +718,7 @@ class DBStructure
$sql2 = self::dropForeignKey($param['CONSTRAINT_NAME']); $sql2 = self::dropForeignKey($param['CONSTRAINT_NAME']);
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2; $sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else { } else {
$sql3 .= ", " . $sql2; $sql3 .= ", " . $sql2;
} }
@ -752,7 +730,7 @@ class DBStructure
$sql2 = "COMMENT = '" . DBA::escape($structurecomment) . "'"; $sql2 = "COMMENT = '" . DBA::escape($structurecomment) . "'";
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2; $sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else { } else {
$sql3 .= ", " . $sql2; $sql3 .= ", " . $sql2;
} }
@ -764,7 +742,7 @@ class DBStructure
$sql2 = "ENGINE = '" . DBA::escape($structure['engine']) . "'"; $sql2 = "ENGINE = '" . DBA::escape($structure['engine']) . "'";
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2; $sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else { } else {
$sql3 .= ", " . $sql2; $sql3 .= ", " . $sql2;
} }
@ -776,7 +754,7 @@ class DBStructure
$sql2 = "DEFAULT COLLATE utf8mb4_general_ci"; $sql2 = "DEFAULT COLLATE utf8mb4_general_ci";
if ($sql3 == "") { if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2; $sql3 = "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else { } else {
$sql3 .= ", " . $sql2; $sql3 .= ", " . $sql2;
} }
@ -803,7 +781,7 @@ class DBStructure
if ($field_definition['Collation'] != $parameters['Collation']) { if ($field_definition['Collation'] != $parameters['Collation']) {
$sql2 = self::modifyTableField($fieldname, $parameters); $sql2 = self::modifyTableField($fieldname, $parameters);
if (($sql3 == "") || (substr($sql3, -2, 2) == "; ")) { if (($sql3 == "") || (substr($sql3, -2, 2) == "; ")) {
$sql3 .= "ALTER" . $ignore . " TABLE `" . $temp_name . "` " . $sql2; $sql3 .= "ALTER" . $ignore . " TABLE `" . $name . "` " . $sql2;
} else { } else {
$sql3 .= ", " . $sql2; $sql3 .= ", " . $sql2;
} }
@ -816,36 +794,8 @@ class DBStructure
$sql3 .= ";"; $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) { 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"; 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) { 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)); 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); $r = DBA::e($sql3);
if (!DBA::isResult($r)) { if (!DBA::isResult($r)) {
$errors .= self::printUpdateError($sql3); $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); 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 * Renames columns or the primary key of a table
* *

View file

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

View file

@ -1445,11 +1445,11 @@ class Contact
if ($thread_mode) { if ($thread_mode) {
$items = Post::toArray(Post::selectForUser(local_user(), ['uri-id', 'gravity', 'parent-uri-id', 'thr-parent-id', 'author-id'], $condition, $params)); $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 { } else {
$items = Post::toArray(Post::selectForUser(local_user(), Item::DISPLAY_FIELDLIST, $condition, $params)); $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) { if (!$update) {

View file

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

View file

@ -25,7 +25,6 @@ use Friendica\DI;
use Friendica\Core\Renderer; use Friendica\Core\Renderer;
use Friendica\Core\Theme; use Friendica\Core\Theme;
use Friendica\Module\BaseAdmin; use Friendica\Module\BaseAdmin;
use Friendica\Model\Log\ParsedLogIterator;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
class View extends BaseAdmin class View extends BaseAdmin
@ -68,7 +67,7 @@ class View extends BaseAdmin
} }
if (!file_exists($f)) { 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 { } else {
try { try {
$data = DI::parsedLogIterator() $data = DI::parsedLogIterator()
@ -77,12 +76,33 @@ class View extends BaseAdmin
->withFilters($filters) ->withFilters($filters)
->withSearch($search); ->withSearch($search);
} catch (Exception $e) { } 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, [ return Renderer::replaceMacros($t, [
'$title' => DI::l10n()->t('Administration'), '$title' => DI::l10n()->t('Administration'),
'$page' => DI::l10n()->t('View Logs'), '$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, '$data' => $data,
'$q' => $search, '$q' => $search,
'$filters' => $filters, '$filters' => $filters,

View file

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

View file

@ -951,7 +951,7 @@ class Contact extends BaseModule
if (!$update) { if (!$update) {
// We need the editor here to be able to reshare an item. // We need the editor here to be able to reshare an item.
if (local_user()) { 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. // We need the editor here to be able to reshare an item.
if (Session::isAuthenticated()) { 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; 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( $pager = new BoundariesPager(
DI::l10n(), DI::l10n(),

View file

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

View file

@ -132,7 +132,7 @@ class Status extends BaseProfile
'profile_uid' => $profile['uid'], '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 // 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); $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)); $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)); $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')) { if (DI::pConfig()->get(local_user(), 'system', 'infinite_scroll')) {
$o .= HTML::scrollLoader(); $o .= HTML::scrollLoader();

View file

@ -200,7 +200,7 @@ class Index extends BaseSearch
Logger::info('Start Conversation.', ['q' => $search]); 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')) { if (DI::pConfig()->get(local_user(), 'system', 'infinite_scroll')) {
$o .= HTML::scrollLoader(); $o .= HTML::scrollLoader();

View file

@ -39,7 +39,7 @@ class Community extends CommunityModule
$o = ''; $o = '';
if (!empty($_GET['force']) || !DI::pConfig()->get(local_user(), 'system', 'no_auto_update')) { 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); System::htmlUpdateExit($o);

View file

@ -53,7 +53,7 @@ class Network extends NetworkModule
$ordering = '`commented`'; $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); System::htmlUpdateExit($o);

View file

@ -115,7 +115,7 @@ class Profile extends BaseModule
$items = DBA::toArray($items_stmt); $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); 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; self::$baseurl = $host_url;
Logger::info('Probing successful', ['host' => $host]); Logger::info('Probing successful', ['host' => $host]);
@ -625,6 +630,11 @@ class Probe
*/ */
private static function getWebfinger(string $template, string $type, string $uri, string $addr) 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 // First try the address because this is the primary purpose of webfinger
if (!empty($addr)) { if (!empty($addr)) {
$detected = $addr; $detected = $addr;

View file

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

View file

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

View file

@ -49,7 +49,7 @@ class Security
return true; 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 // 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 // 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 // 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) { } elseif ($verified === 1) {
return false; return false;
} else { } else {
$cid = Session::getRemoteContactID($owner); $user = User::getById($owner);
if (!$cid) { if (!$user || $user['blockwall']) {
$verified = 1;
return false; return false;
} }
$r = q("SELECT `contact`.*, `user`.`page-flags` FROM `contact` INNER JOIN `user` on `user`.`uid` = `contact`.`uid` $contact = Contact::getById($cid);
WHERE `contact`.`uid` = %d AND `contact`.`id` = %d AND `contact`.`blocked` = 0 AND `contact`.`pending` = 0 if ($contact || $contact['blocked'] || $contact['readonly'] || $contact['pending']) {
AND `user`.`blockwall` = 0 AND `readonly` = 0 AND (`contact`.`rel` IN (%d , %d) OR `user`.`page-flags` = %d) LIMIT 1", $verified = 1;
intval($owner), return false;
intval($cid), }
intval(Contact::SHARING),
intval(Contact::FRIEND), if (in_array($contact['rel'], [Contact::SHARING, Contact::FRIEND]) || ($user['page-flags'] == User::PAGE_FLAGS_COMMUNITY)) {
intval(User::PAGE_FLAGS_COMMUNITY)
);
if (DBA::isResult($r)) {
$verified = 2; $verified = 2;
return true; return true;
} else { } else {

View file

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

View file

@ -3510,18 +3510,6 @@ class ApiTest extends FixtureTest
$this->markTestIncomplete(); $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. * 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]', 'text' => '[size=xx-large]Test text[/size]',
'try_oembed' => false, 'try_oembed' => false,
// Triggers the diaspora compatible output // Triggers the diaspora compatible output
'simpleHtml' => 3, 'simpleHtml' => BBCode::DIASPORA,
], ],
'bug-2199-diaspora-no-numeric-size' => [ 'bug-2199-diaspora-no-numeric-size' => [
'expectedHtml' => 'Test text', 'expectedHtml' => 'Test text',
'text' => '[size=24]Test text[/size]', 'text' => '[size=24]Test text[/size]',
'try_oembed' => false, 'try_oembed' => false,
// Triggers the diaspora compatible output // Triggers the diaspora compatible output
'simpleHtml' => 3, 'simpleHtml' => BBCode::DIASPORA,
], ],
'bug-7665-audio-tag' => [ '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>', '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>', 'expectedHTML' => '<span class="arbitrary classes">Test</span>',
'text' => '[class=arbitrary classes]Test[/class]', '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\Util\ReversedFileReader;
use Friendica\Model\Log\ParsedLogIterator; use Friendica\Model\Log\ParsedLogIterator;
@ -145,4 +145,16 @@ class ParsedLogIteratorTest extends TestCase
$pls = iterator_to_array($this->pli, false); $pls = iterator_to_array($this->pli, false);
self::assertCount(0, $pls); 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["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["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["[Friendica:Notify]"] = "[Friendica Meldung]";
$a->strings["%s New mail received at %s"] = "%sNeue Nachricht auf %s empfangen"; $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."; $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["Item not found"] = "Beitrag nicht gefunden";
$a->strings["Edit post"] = "Beitrag bearbeiten"; $a->strings["Edit post"] = "Beitrag bearbeiten";
$a->strings["Save"] = "Speichern"; $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["Insert web link"] = "Einen Link einfügen";
$a->strings["web link"] = "Weblink"; $a->strings["web link"] = "Weblink";
$a->strings["Insert video link"] = "Video-Adresse einfügen"; $a->strings["Insert video link"] = "Video-Adresse einfügen";
$a->strings["video link"] = "Video-Link"; $a->strings["video link"] = "Video-Link";
$a->strings["Insert audio link"] = "Audio-Adresse einfügen"; $a->strings["Insert audio link"] = "Audio-Adresse einfügen";
$a->strings["audio link"] = "Audio-Link"; $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["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["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 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["Event title and start time are required."] = "Der Veranstaltungstitel und die Anfangszeit müssen angegeben werden.";
$a->strings["Create New Event"] = "Neue Veranstaltung erstellen"; $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["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["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["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["Please answer the following:"] = "Bitte beantworte folgendes:";
$a->strings["Your Identity Address:"] = "Adresse Deines Profils:"; $a->strings["Your Identity Address:"] = "Adresse Deines Profils:";
$a->strings["Profile URL"] = "Profil URL"; $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["Rotate CCW (left)"] = "Drehen EUS (links)";
$a->strings["This is you"] = "Das bist du"; $a->strings["This is you"] = "Das bist du";
$a->strings["Comment"] = "Kommentar"; $a->strings["Comment"] = "Kommentar";
$a->strings["Select"] = "Auswählen";
$a->strings["Delete"] = "Löschen";
$a->strings["Like"] = "Mag ich"; $a->strings["Like"] = "Mag ich";
$a->strings["I like this (toggle)"] = "Ich mag das (toggle)"; $a->strings["I like this (toggle)"] = "Ich mag das (toggle)";
$a->strings["Dislike"] = "Mag ich nicht"; $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["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["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["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["Remove Item Tag"] = "Gegenstands-Tag entfernen";
$a->strings["Select a tag to remove: "] = "Wähle ein Tag zum Entfernen aus: "; $a->strings["Select a tag to remove: "] = "Wähle ein Tag zum Entfernen aus: ";
$a->strings["Remove"] = "Entfernen"; $a->strings["Remove"] = "Entfernen";
@ -637,6 +568,62 @@ $a->strings["GNU Social Connector"] = "GNU Social Connector";
$a->strings["ActivityPub"] = "ActivityPub"; $a->strings["ActivityPub"] = "ActivityPub";
$a->strings["pnut"] = "pnut"; $a->strings["pnut"] = "pnut";
$a->strings["%s (via %s)"] = "%s (via %s)"; $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["General Features"] = "Allgemeine Features";
$a->strings["Photo Location"] = "Aufnahmeort"; $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."; $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["External link to forum"] = "Externer Link zum Forum";
$a->strings["show less"] = "weniger anzeigen"; $a->strings["show less"] = "weniger anzeigen";
$a->strings["show more"] = "mehr 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["Nothing new here"] = "Keine Neuigkeiten";
$a->strings["Go back"] = "Geh zurück"; $a->strings["Go back"] = "Geh zurück";
$a->strings["Clear notifications"] = "Bereinige Benachrichtigungen"; $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["Log level"] = "Protokoll-Level";
$a->strings["PHP logging"] = "PHP Protokollieren"; $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["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["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.\\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["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["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["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["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"; $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["Personal Notifications"] = "Persönliche Benachrichtigungen";
$a->strings["Home Notifications"] = "Pinnwandbenachrichtigungen"; $a->strings["Home Notifications"] = "Pinnwandbenachrichtigungen";
$a->strings["Show unread"] = "Ungelesene anzeigen"; $a->strings["Show unread"] = "Ungelesene anzeigen";
$a->strings["Show all"] = "Alle anzeigen";
$a->strings["Authorize application connection"] = "Verbindung der Applikation autorisieren"; $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["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"; $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["Monthly posting limit of %d post reached. The post was rejected."] = "Месячный лимит в %d записей достигнут. Запись была отклонена.";
$a->strings["Profile Photos"] = "Фотографии профиля"; $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["[Friendica:Notify]"] = "[Friendica]";
$a->strings["%s New mail received at %s"] = "%s Новая почта получена в %s"; $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."; $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["Item not found"] = "Элемент не найден";
$a->strings["Edit post"] = "Редактировать запись"; $a->strings["Edit post"] = "Редактировать запись";
$a->strings["Save"] = "Сохранить"; $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["Insert web link"] = "Вставить веб-ссылку";
$a->strings["web link"] = "веб-ссылка"; $a->strings["web link"] = "веб-ссылка";
$a->strings["Insert video link"] = "Вставить ссылку видео"; $a->strings["Insert video link"] = "Вставить ссылку видео";
$a->strings["video link"] = "видео-ссылка"; $a->strings["video link"] = "видео-ссылка";
$a->strings["Insert audio link"] = "Вставить ссылку аудио"; $a->strings["Insert audio link"] = "Вставить ссылку аудио";
$a->strings["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["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["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 can not end before it has started."] = "Эвент не может закончится до старта.";
$a->strings["Event title and start time are required."] = "Название мероприятия и время начала обязательны для заполнения."; $a->strings["Event title and start time are required."] = "Название мероприятия и время начала обязательны для заполнения.";
$a->strings["Create New Event"] = "Создать новое мероприятие"; $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["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["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["OStatus support is disabled. Contact can't be added."] = "Поддержка OStatus выключена. Контакт не может быть добавлен.";
$a->strings["Connect/Follow"] = "Подключиться/Подписаться";
$a->strings["Please answer the following:"] = "Пожалуйста, ответьте следующее:"; $a->strings["Please answer the following:"] = "Пожалуйста, ответьте следующее:";
$a->strings["Your Identity Address:"] = "Ваш адрес:"; $a->strings["Your Identity Address:"] = "Ваш адрес:";
$a->strings["Profile URL"] = "URL профиля"; $a->strings["Profile URL"] = "URL профиля";
@ -346,6 +278,8 @@ $a->strings["Rotate CW (right)"] = "Поворот по часовой стре
$a->strings["Rotate CCW (left)"] = "Поворот против часовой стрелки (налево)"; $a->strings["Rotate CCW (left)"] = "Поворот против часовой стрелки (налево)";
$a->strings["This is you"] = "Это вы"; $a->strings["This is you"] = "Это вы";
$a->strings["Comment"] = "Комментировать"; $a->strings["Comment"] = "Комментировать";
$a->strings["Select"] = "Выберите";
$a->strings["Delete"] = "Удалить";
$a->strings["I like this (toggle)"] = "Нравится"; $a->strings["I like this (toggle)"] = "Нравится";
$a->strings["I don't like this (toggle)"] = "Не нравится"; $a->strings["I don't like this (toggle)"] = "Не нравится";
$a->strings["Map"] = "Карта"; $a->strings["Map"] = "Карта";
@ -403,6 +337,8 @@ $a->strings["Social Networks"] = "Социальные сети";
$a->strings["General Social Media Settings"] = "Общие настройки социальных медиа"; $a->strings["General Social Media Settings"] = "Общие настройки социальных медиа";
$a->strings["Accept only top level posts by contacts you follow"] = "Получать начальные записи только от ваших контактов"; $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["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["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["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"; $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["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["No suggestions available. If this is a new site, please try again in 24 hours."] = "Нет предложений. Если это новый сайт, пожалуйста, попробуйте снова через 24 часа.";
$a->strings["Friend Suggestions"] = "Предложения друзей"; $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["Remove Item Tag"] = "Удалить ключевое слово";
$a->strings["Select a tag to remove: "] = "Выберите ключевое слово для удаления: "; $a->strings["Select a tag to remove: "] = "Выберите ключевое слово для удаления: ";
$a->strings["Remove"] = "Удалить"; $a->strings["Remove"] = "Удалить";
@ -614,6 +553,56 @@ $a->strings["GNU Social Connector"] = "GNU Social Connector";
$a->strings["ActivityPub"] = "ActivityPub"; $a->strings["ActivityPub"] = "ActivityPub";
$a->strings["pnut"] = "pnut"; $a->strings["pnut"] = "pnut";
$a->strings["%s (via %s)"] = "%s (через %s)"; $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["General Features"] = "Основные возможности";
$a->strings["Photo Location"] = "Место фотографирования"; $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."] = "Метаданные фотографий обычно вырезаются. Эта настройка получает местоположение (если есть) до вырезки метаданных и связывает с координатами на карте."; $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["Forums"] = "Форумы";
$a->strings["External link to forum"] = "Внешняя ссылка на форум"; $a->strings["External link to forum"] = "Внешняя ссылка на форум";
$a->strings["show more"] = "показать больше"; $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["Nothing new here"] = "Ничего нового здесь";
$a->strings["Go back"] = "Назад"; $a->strings["Go back"] = "Назад";
$a->strings["Clear notifications"] = "Стереть уведомления"; $a->strings["Clear notifications"] = "Стереть уведомления";
@ -977,6 +979,7 @@ $a->strings["bytes"] = "байт";
$a->strings["View on separate page"] = "Посмотреть в отдельной вкладке"; $a->strings["View on separate page"] = "Посмотреть в отдельной вкладке";
$a->strings["[no subject]"] = "[без темы]"; $a->strings["[no subject]"] = "[без темы]";
$a->strings["%1\$s had started following you"] = "%1\$s подписались на вас"; $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 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 %2\$s"] = "%1\$s ответил в своём обсуждении %2\$s";
$a->strings["%1\$s commented in their thread"] = "%1\$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 posts"] = "Записи %s";
$a->strings["%s's comments"] = "Комментарии %s"; $a->strings["%s's comments"] = "Комментарии %s";
$a->strings["Scheduled"] = "Запланировано"; $a->strings["Scheduled"] = "Запланировано";
$a->strings["Content"] = "Содержание";
$a->strings["Only parent users can create additional accounts."] = "Только основные пользователи могут создавать дополнительные учётные записи."; $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["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 (необязательно):"; $a->strings["Your OpenID (optional): "] = "Ваш OpenID (необязательно):";

View file

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

View file

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

View file

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