Merge remote-tracking branch 'upstream/develop' into quit-on-error

This commit is contained in:
Michael 2018-06-11 03:15:59 +00:00
commit b02cdc8a7f
464 changed files with 47242 additions and 57792 deletions

4
.gitattributes vendored
View File

@ -1,2 +1,2 @@
# Disable LF normalization for all files
* -text
# Disable LF normalization for all files
* -text

126
.gitignore vendored
View File

@ -1,61 +1,65 @@
favicon.*
.htconfig.php
.htpreconfig.php
\#*
include/jquery-1.4.2.min.js
*.log
*.out
*.version*
favicon.*
home.html
addon
*.orig
*~
robots.txt
#ignore documentation, it should be newly built
doc/html
#ignore reports, should be generted with every build
report/
#ignore config files from eclipse, we don't want IDE files in our repository
.project
.buildpath
.externalToolBuilders
.settings
#ignore OSX .DS_Store files
.DS_Store
/nbproject/private/
#ignore smarty cache
/view/smarty3/compiled/
#ignore cache folders
/privacy_image_cache/
/photo/
/proxy/
nbproject
#ignore vagrant dir
.vagrant/
#ignore local folder
/local/
#ignore config files from Visual Studio
/.vs/
/php_friendica.phpproj
/php_friendica.sln
/php_friendica.phpproj.user
#ignore things from transifex-client
venv/
#ignore Composer dependencies
/vendor
/view/asset
#ignore config files from JetBrains
/.idea
favicon.*
.htconfig.php
.htpreconfig.php
\#*
include/jquery-1.4.2.min.js
*.log
*.out
*.version*
favicon.*
home.html
addon
*~
robots.txt
#ignore documentation, it should be newly built
doc/html
#ignore reports, should be generted with every build
report/
#ignore config files from eclipse, we don't want IDE files in our repository
.project
.buildpath
.externalToolBuilders
.settings
#ignore OSX .DS_Store files
.DS_Store
#ignore NetBeans IDE's private files (at least)
/nbproject/private/
#ignore smarty cache
/view/smarty3/compiled/
#ignore cache folders
/privacy_image_cache/
/photo/
/proxy/
nbproject
#ignore vagrant dir
.vagrant/
#ignore local folder
/local/
#ignore config files from Visual Studio
/.vs/
/php_friendica.phpproj
/php_friendica.sln
/php_friendica.phpproj.user
#ignore things from transifex-client
venv/
#ignore Composer dependencies
/vendor
/view/asset
#ignore config files from JetBrains
/.idea
#ignore addons/ directory
addons/

View File

@ -4,7 +4,7 @@ AddType audio/ogg .oga
#AddHandler php53-cgi .php
<FilesMatch "\.(out|log)$">
<IfModule authz_host_module>
<IfModule authz_host_module>
#Apache 2.4
Require all denied
</IfModule>
@ -38,4 +38,3 @@ AddType audio/ogg .oga
RewriteRule ^(.*)$ index.php?pagename=$1 [E=REMOTE_USER:%{HTTP:Authorization},L,QSA]
</IfModule>

View File

@ -7,4 +7,14 @@ php:
- 7.1
- 7.2
install: composer install
services:
- mysql
env:
- USER=travis DB=test
install:
- composer install
before_script:
- mysql -e 'CREATE DATABASE IF NOT EXISTS test;'
# In order to avoid bin/worker.php warnings
- touch .htconfig.php

106
CHANGELOG
View File

@ -1,3 +1,105 @@
Version 2018.05 (2018-06-01)
Friendica Core:
Update to the translations (DE, EN-GB, EN-US, FI, IS, IT, NL, PL, RU, ZN CH) [translation teams]
Update to the documentation [andyhee, annando, fabrixxm, M-arcus, MrPedovan, rudloff, tobiasd]
Enhancements to the DB handling [annando]
Enhancements to the relay system [annando]
Enhancements to the handling of URL that contain unicode characters [annando]
Enhancements to the Vagrant VM configuration [fabrixxm, tobiasd]
Enhancementa to the Babel module [MrPetovan]
Enhancements to the display of the [code] elements [MrPetovan]
Enhancements to the federation (OStatus, diaspora) [annando]
Enhancements to the PHP7.2 compatibility [Alkarex, MrPetovan, Quix0r]
Enhancements to the themes (frio, vier) [astifter, fabrixxm, koyuawsmbrtn, M-arcus, MrPetovan, Quix0r, rabuzarus]
Enhancements to the accessibility using the frio theme [annando]
Enhancements to the display of the registration note and the privacy statements on the registration page [tobiasd]
Enhancements to the UI by clarification of the wording (deletion of items, network widget, invitations) [annando, tobiasd]
Enhancements to the background worker [annando]
Enhancements to the forum display in the sidebar [annando]
Enhancements to the testing system [rudloff, tobiasd]
Enhancements to the display of events [MrPetovan]
Enhancements to the language detection of postings [MrPetovan]
Enhancements to the memcached handling [MrPetovan]
Enhancements to the Dandelion app support [annando]
Enhancements to the API [rudloff]
Enhancements to the systemd timer example [ben-utzer]
Enhancements to the notification emails to better integrate the securemail addon [tobiasd]
Enhancements to the caching/loading mechanisms [MrPetovan]
Enhancements to the sample-nginx configfile to not use $uri in the rewrite rules [anmol26s]
Fixed a bug in the relocation process of a Friendica instance [annando]
Fixed a bug in the shell wrapper for the console [MrPetovan]
Fixed a bug with the console tool po2php [MrPetovan]
Fixed a bug with the console tool blockaccounts [MrPetovan]
Fixed a bug in the ACL [annando, MrPetovan]
Fixed a bug that prevented the deletion of contact groups [annando]
Fixed a bug that made edited mentions and hashtags plaintext [annando]
Fixed a bug that caused the /display page to receive constandly new updates [annando]
Fixed wrong version of a dependency preventing the usage of PHP 5.6 [MrPetovan]
Fixed a bug in OpenID authentification [Quix0r]
Fixed a bug in the item deletion [annando]
Fixed a bug that prevented public comments from being distributed [annando]
Fixed a bug that caused empty profile pictures for public contacts [annando]
Fixed a bug that prevented the display of some postings in the network stream [annando]
Fixed a bug in the display of videos with parameters [annando]
Fixed a bug that caused the display of blocked contacts under some conditions [annando]
Fixed bugs in the installer [annando, M-arcus]
Fixed a bug in the installer running on nginx [astifter]
Fixed a bug with reshares from diaspora* [annando]
Fixed a bug that accounts from diaspora* could join private forums automatically [annando]
Fixed a bug that prevented the selection of displayed profiles for other Friendica contacts [MrPetovan]
Fixed the version sorting in the federation statistics page [annando]
Fixed a bug in the nodeinfo calculation of total comments [annando]
Fixed a bug during registration that prevented the detected language to be saved [tobiasd]
Added an optional module to display the Terms of Service [rabuzarus, tobiasd]
Added testfeed module [MrPetovan]
Added hashtag autocomplete (ported from Hubzilla) [rabuzarus]
Added password exposed check [MrPetovan]
Added preloading config adapter [MrPetovan]
Added a console to unify the PHP utility scripts [MrPetovan]
Added a tool to set user passwords to the console [annando]
Added memcached support [MrPetovan]
Added password exposure check [MrPetovan]
Added hashtag autocompletion [rabuzarus]
Added feedtest module [MrPetovan]
Added dbclean options to the admin panel [annando]
Added the possibility to add the remote_self flag to contacts from diaspora* and Twitter [annando]
Added the possibility of automatic installations [M-arcus]
Added the sending of a notification mail to the admin when a user deletes their account [tobiasd]
Added examples for home.html and home.css files [tobiasd]
Added an option to define after how many days a contact should be archived [annando]
Added parts of the list API [rudloff]
Added support of ALT texts for images [annando]
Removed the connection postings [annando]
Corrected a long standing typo in config variable names; should your bandwidth saver mode stop working please turn it off and on again [abanink]
The execute-ables were moved from /util to /bin [MrPetovan]
The execute-ables for the developers were moved from /util to /bin/dev [MrPetovan]
The last year deprecated themes frost and frost mobile got removed from the Friendica repository. They can be found in the dedicated repository for deprecated themes [tobiasd]
General code refactoring and beautification work [annando, MrPetovan, rudloff]
Switched to cropperjs to better support touch screen devices [rabuzarus]
Use the diaspora transport layer for the DFRN protocol as well [annando]
Friendica Addons:
Updates to the translations (DE, EN_GB, EN_US, ES, FI, FR, IS, IT, NL, PL, RU, ZH_CN) [translation teams]
advancedcontentfilter: new addon with advanced filter capabilities [MrPetova]
catavatar: new addon for profile pictures based on David Revoy's cat-avatar generator [annando, fabrixxm, tobiasd]
languagefilter: better help text [andyhee]
mathjax: fixed the config form and adopted new CDN URL [tobiasd]
NSFW: add hashtag only hiding [MrPetovan]
notifyall: fixed a bug in handling the sender name [tobiasd]
Twitter: fixed a bug during the creation of public contacts [annando]
Twitter: remote self now also works for Twitter contacts [annando]
Twitter: optimizations for sending media [annando]
Closed Issues:
839, 1186, 1729, 2115, 2247, 2781, 2880, 3174, 3395, 3409, 3412,
3611, 3834, 3837, 3979, 4146, 4572, 4601, 4616, 4629, 4647, 4660,
4661, 4663, 4664, 4665, 4666, 4669, 4670, 4681, 4695, 4670, 4689,
4730, 4749, 4760, 4772, 4786, 4790, 4791, 4816, 4867, 4878, 4819,
4860, 4876, 4879, 4886, 4898, 4899, 4902, 4921, 4926, 4927, 4928,
4938, 4943, 4946, 4947, 4965, 4976, 4966, 4994, 4997, 5002, 5014,
5033, 5043, 5050, 5051, 5056, 5063, 5067, 5010, 5111, 5116, 5128,
5137, 5147
Version 3.6 (2018-03-23)
Friendica Core:
Updates to the translations (DE, EN_GB, EN_US, ES, FR, IT, ZH_CN) [translation teams]
@ -93,6 +195,8 @@ Version 3.6 (2018-03-23)
Updates to the translations (DE, EN_GB, ES, FR, IT, NL, ZH_CN) [translation teams]
all bridges don't relay postings anymore that are posted to a public forum [annando]
DAV addon marked unsupported [tobiasd]
communityhome addon marked unsupported [MrPetovan]
yourls addon makrked unsupported [MrPetovan]
Current Weather: fixing a problem with the weathermap link [zeroadam]
NSFW added config examples, reworked the description, now ignores the CW from Mastodon [andyhee, annando, rebeka-catalina]
Twitter support 280 chars limit [annando]
@ -102,7 +206,7 @@ Version 3.6 (2018-03-23)
Public Server reworked [annando]
pageheader settings beautifications [tobiasd]
mailstream settings beautifications [tobiasd]
Membersince is now part of the core [rabuzarus]
Membersince is now part of the core, addon marked unsupported [rabuzarus]
Forum posts are not transmitted over the connectors anymore [annando]
Friendica Dir:

View File

@ -1 +1 @@
2018.05-rc
2018.08-dev

View File

@ -6,8 +6,38 @@
*
* This script was taken from http://php.net/manual/en/function.pcntl-fork.php
*/
function shutdown() {
posix_kill(posix_getpid(), SIGHUP);
use Friendica\App;
use Friendica\BaseObject;
use Friendica\Core\Config;
use Friendica\Core\Worker;
// Ensure that daemon.php is executed from the base path of the installation
if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) {
$directory = dirname($_SERVER["argv"][0]);
if (substr($directory, 0, 1) != "/") {
$directory = $_SERVER["PWD"]."/".$directory;
}
$directory = realpath($directory."/..");
chdir($directory);
}
require_once "boot.php";
require_once "include/dba.php";
$a = new App(dirname(__DIR__));
BaseObject::setApp($a);
require_once ".htconfig.php";
dba::connect($db_host, $db_user, $db_pass, $db_data);
Config::load();
if (!isset($pidfile)) {
die('Please specify a pid file in the variable $pidfile in the .htconfig.php. For example:'."\n".
'$pidfile = "/path/to/daemon.pid";'."\n");
}
if (in_array("start", $_SERVER["argv"])) {
@ -30,27 +60,11 @@ if (empty($_SERVER["argv"][0])) {
die("Unexpected script behaviour. This message should never occur.\n");
}
// Fetch the base directory
$directory = dirname($_SERVER["argv"][0]);
$pid = @file_get_contents($pidfile);
if (substr($directory, 0, 1) != "/") {
$directory = $_SERVER["PWD"]."/".$directory;
}
$directory = realpath($directory."/..");
@include($directory."/.htconfig.php");
if (!isset($pidfile)) {
die('Please specify a pid file in the variable $pidfile in the .htconfig.php. For example:'."\n".
'$pidfile = "/path/to/daemon.pid";'."\n");
}
if (in_array($mode, array("stop", "status"))) {
$pid = @file_get_contents($pidfile);
if (!$pid) {
die("Pidfile wasn't found. Is the daemon running?\n");
}
if (empty($pid) && in_array($mode, ["stop", "status"])) {
Config::set('system', 'worker_daemon_mode', false);
die("Pidfile wasn't found. Is the daemon running?\n");
}
if ($mode == "status") {
@ -60,6 +74,7 @@ if ($mode == "status") {
unlink($pidfile);
Config::set('system', 'worker_daemon_mode', false);
die("Daemon process $pid isn't running.\n");
}
@ -68,59 +83,89 @@ if ($mode == "stop") {
unlink($pidfile);
logger("Worker daemon process $pid was killed.", LOGGER_DEBUG);
Config::set('system', 'worker_daemon_mode', false);
die("Worker daemon process $pid was killed.\n");
}
echo "Starting worker daemon.\n";
if (isset($a->config['php_path'])) {
$php = $a->config['php_path'];
} else {
$php = "php";
if (!empty($pid) && posix_kill($pid, 0)) {
die("Daemon process $pid is already running.\n");
}
logger('Starting worker daemon.', LOGGER_DEBUG);
echo "Starting worker daemon.\n";
// Switch over to daemon mode.
if ($pid = pcntl_fork())
if ($pid = pcntl_fork()) {
return; // Parent
}
fclose(STDIN); // Close all of the standard
fclose(STDOUT); // file descriptors as we
fclose(STDERR); // are running as a daemon.
dba::disconnect();
register_shutdown_function('shutdown');
if (posix_setsid() < 0)
if (posix_setsid() < 0) {
return;
}
if ($pid = pcntl_fork())
if ($pid = pcntl_fork()) {
return; // Parent
}
// We lose the database connection upon forking
dba::connect($db_host, $db_user, $db_pass, $db_data);
Config::set('system', 'worker_daemon_mode', true);
// Just to be sure that this script really runs endlessly
set_time_limit(0);
$pid = getmypid();
file_put_contents($pidfile, $pid);
$wait_interval = intval(Config::get('system', 'cron_interval', 5)) * 60;
$do_cron = true;
$last_cron = 0;
// Now running as a daemon.
while (true) {
// Just to be sure that this script really runs endlessly
set_time_limit(0);
// Call the worker
$cmdline = $php.' bin/worker.php';
$executed = false;
if (function_exists('proc_open')) {
$resource = proc_open($cmdline . ' &', array(), $foo, $directory);
if (is_resource($resource)) {
$executed = true;
proc_close($resource);
}
if (!$do_cron && ($last_cron + $wait_interval) < time()) {
logger('Forcing cron worker call.', LOGGER_DEBUG);
$do_cron = true;
}
if (!$executed) {
exec($cmdline.' spawn');
Worker::spawnWorker($do_cron);
if ($do_cron) {
// We force a disconnect and reconnect of the database connection.
// This is done to ensure that the connection don't get lost over time.
dba::disconnect();
dba::connect($db_host, $db_user, $db_pass, $db_data);
$last_cron = time();
}
// Now sleep for 5 minutes
sleep(300);
logger("Sleeping", LOGGER_DEBUG);
$i = 0;
do {
sleep(1);
} while (($i++ < $wait_interval) && !Worker::IPCJobsExists());
if ($i >= $wait_interval) {
$do_cron = true;
logger("Woke up after $wait_interval seconds.", LOGGER_DEBUG);
} else {
$do_cron = false;
logger("Worker jobs are calling to be forked.", LOGGER_DEBUG);
}
}
function shutdown() {
posix_kill(posix_getpid(), SIGHUP);
}

View File

@ -39,9 +39,9 @@ require_once 'include/text.php';
define('FRIENDICA_PLATFORM', 'Friendica');
define('FRIENDICA_CODENAME', 'The Tazmans Flax-lily');
define('FRIENDICA_VERSION', '2018.05-rc');
define('FRIENDICA_VERSION', '2018.08-dev');
define('DFRN_PROTOCOL_VERSION', '2.23');
define('DB_UPDATE_VERSION', 1265);
define('DB_UPDATE_VERSION', 1268);
define('NEW_UPDATE_ROUTINE_VERSION', 1170);
/**
@ -1076,6 +1076,7 @@ function is_site_admin()
$adminlist = explode(",", str_replace(" ", "", $a->config['admin_email']));
//if(local_user() && x($a->user,'email') && x($a->config,'admin_email') && ($a->user['email'] === $a->config['admin_email']))
/// @TODO This if() + 2 returns can be shrinked into one return
if (local_user() && x($a->user, 'email') && x($a->config, 'admin_email') && in_array($a->user['email'], $adminlist)) {
return true;
}
@ -1173,7 +1174,7 @@ function random_digits($digits)
{
$rn = '';
for ($i = 0; $i < $digits; $i++) {
/// @TODO rand() is different to mt_rand() and maybe lesser "random"
/// @TODO Avoid rand/mt_rand, when it comes to cryptography, they are generating predictable (seedable) numbers.
$rn .= rand(0, 9);
}
return $rn;
@ -1187,7 +1188,7 @@ function get_server()
$server = "https://dir.friendica.social";
}
return($server);
return $server;
}
function get_temppath()
@ -1236,7 +1237,7 @@ function get_cachefile($file, $writemode = true)
$cache = get_itemcachepath();
if ((!$cache) || (!is_dir($cache))) {
return("");
return "";
}
$subfolder = $cache . "/" . substr($file, 0, 2);
@ -1250,7 +1251,6 @@ function get_cachefile($file, $writemode = true)
}
}
/// @TODO no need to put braces here
return $cachepath;
}
@ -1357,7 +1357,6 @@ function get_spoolpath()
return "";
}
if (!function_exists('exif_imagetype')) {
function exif_imagetype($file)
{
@ -1395,7 +1394,7 @@ function validate_include(&$file)
}
// Simply return flag
return ($valid);
return $valid;
}
function current_load()

View File

@ -47,7 +47,8 @@
],
"autoload": {
"psr-4": {
"Friendica\\": "src/"
"Friendica\\": "src/",
"Friendica\\Test\\": "tests/"
},
"psr-0": {
"": "library/"
@ -68,5 +69,13 @@
"exclude": [
"log", "cache", "/photo", "/proxy"
]
},
"require-dev": {
"phpunit/dbunit": "^2.0",
"phpdocumentor/reflection-docblock": "^3.0.2",
"phpunit/php-token-stream": "^1.4.2"
},
"scripts": {
"test": "phpunit"
}
}

1379
composer.lock generated

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -51,6 +51,7 @@ Friendica Documentation and Resources
* [Translate Friendica](help/translations)
* [Use Composer](help/Composer)
* [Move classes to `src`](help/Developer-How-To-Move-Classes-to-src)
* [Run tests](help/Tests)
* Reference
* [Twitter/GNU Social API Functions](help/api)
* [Code (Doxygen generated - sets cookies)](doc/html/)
@ -72,4 +73,3 @@ Friendica Documentation and Resources
* [Site/Version Info](friendica)
* [Friendica Credits](credits)

18
doc/Tests.md Normal file
View File

@ -0,0 +1,18 @@
# Themes
* [Home](help)
You can run unit tests with [PHPUnit](https://phpunit.de/):
```bash
phpunit
```
Some tests require access to a MySQL database.
You can specify the database credentials in environment variables:
```bash
USER=database_user PASS=database_password DB=database_name phpunit
```
**Warning**: This will empty all the tables! Never use this on a production database.

View File

@ -56,6 +56,7 @@ Friendica - Dokumentation und Ressourcen
* [Code-Referenz (mit doxygen generiert - setzt Cookies)](doc/html/)
* [Twitter/GNU Social API Functions](help/api) (EN)
* [Translation of Friendica](help/translations) (EN)
* [Run tests](help/Tests) (EN)
**Externe Ressourcen**
@ -72,4 +73,3 @@ Friendica - Dokumentation und Ressourcen
* [Seite/Friendica-Version](friendica)
* [Mitwirkenden bei Friendica](credits)

View File

@ -344,6 +344,14 @@ Mit den folgenden Einstellungen kannst du die Zugriffsdaten für den Datenbank S
$db_pass = 'db_password';
$db_data = 'database_name';
Sollten alle der folgenden Environment-Variablen gesetzt sein, wird Friendica diese anstatt der vorher konfigurierten Werte nutzen.
MYSQL_HOST
MYSQL_PORT
MYSQL_USERNAME
MYSQL_PASSWORD
MYSQL_DATABASE
## Administratoren
Du kannst einen, oder mehrere Accounts, zu Administratoren machen.

View File

@ -124,3 +124,11 @@ The configuration variables db_host, db_user, db_pass and db_data are holding yo
If you need to specify a port to access the database, you can do so by appending ":portnumber" to the db_host variable.
$db_host = 'your.mysqlhost.com:123456';
If all of the following environment variables are set, Friendica will use them instead of the previously configured variables for the db:
MYSQL_HOST
MYSQL_PORT
MYSQL_USERNAME
MYSQL_PASSWORD
MYSQL_DATABASE

View File

@ -24,11 +24,15 @@ $db_data = 'mysqldatabasename';
// Use environment variables for mysql if they are set beforehand
if (!empty(getenv('MYSQL_HOST'))
&& !empty(getenv('MYSQL_PORT'))
&& !empty(getenv('MYSQL_USERNAME'))
&& (!empty(getenv('MYSQL_USERNAME')) || !empty(getenv('MYSQL_USER')))
&& !empty(getenv('MYSQL_PASSWORD'))
&& !empty(getenv('MYSQL_DATABASE'))) {
$db_host = getenv('MYSQL_HOST') . ':' . getenv('MYSQL_PORT');
$db_user = getenv('MYSQL_USERNAME');
if (!empty(getenv('MYSQL_USERNAME'))) {
$db_user = getenv('MYSQL_USERNAME');
} elseif (!empty(getenv('MYSQL_USER'))) {
$db_user = getenv('MYSQL_USER');
}
$db_pass = getenv('MYSQL_PASSWORD');
$db_data = getenv('MYSQL_DATABASE');
}

File diff suppressed because it is too large Load Diff

View File

@ -15,6 +15,7 @@ use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
use Friendica\Model\Item;
use Friendica\Object\Post;
use Friendica\Object\Thread;
use Friendica\Util\DateTimeFormat;
@ -116,7 +117,7 @@ function localize_item(&$item) {
$item['body'] = item_redir_and_replace_images($extracted['body'], $extracted['images'], $item['contact-id']);
}
/// @Separted ???
/// @TODO Separted ???
$xmlhead = "<" . "?xml version='1.0' encoding='UTF-8' ?" . ">";
if (activity_match($item['verb'], ACTIVITY_LIKE)
|| activity_match($item['verb'], ACTIVITY_DISLIKE)
@ -162,22 +163,19 @@ function localize_item(&$item) {
if (activity_match($item['verb'], ACTIVITY_LIKE)) {
$bodyverb = L10n::t('%1$s likes %2$s\'s %3$s');
}
elseif (activity_match($item['verb'], ACTIVITY_DISLIKE)) {
} elseif (activity_match($item['verb'], ACTIVITY_DISLIKE)) {
$bodyverb = L10n::t('%1$s doesn\'t like %2$s\'s %3$s');
}
elseif (activity_match($item['verb'], ACTIVITY_ATTEND)) {
} elseif (activity_match($item['verb'], ACTIVITY_ATTEND)) {
$bodyverb = L10n::t('%1$s attends %2$s\'s %3$s');
}
elseif (activity_match($item['verb'], ACTIVITY_ATTENDNO)) {
} elseif (activity_match($item['verb'], ACTIVITY_ATTENDNO)) {
$bodyverb = L10n::t('%1$s doesn\'t attend %2$s\'s %3$s');
}
elseif (activity_match($item['verb'], ACTIVITY_ATTENDMAYBE)) {
} elseif (activity_match($item['verb'], ACTIVITY_ATTENDMAYBE)) {
$bodyverb = L10n::t('%1$s attends maybe %2$s\'s %3$s');
}
$item['body'] = sprintf($bodyverb, $author, $objauthor, $plink);
$item['body'] = sprintf($bodyverb, $author, $objauthor, $plink);
}
if (activity_match($item['verb'], ACTIVITY_FRIEND)) {
if ($item['object-type']=="" || $item['object-type']!== ACTIVITY_OBJ_PERSON) return;
@ -200,10 +198,10 @@ function localize_item(&$item) {
}
}
$A = '[url=' . Profile::zrl($Alink) . ']' . $Aname . '[/url]';
$B = '[url=' . Profile::zrl($Blink) . ']' . $Bname . '[/url]';
$A = '[url=' . Contact::magicLink($Alink) . ']' . $Aname . '[/url]';
$B = '[url=' . Contact::magicLink($Blink) . ']' . $Bname . '[/url]';
if ($Bphoto != "") {
$Bphoto = '[url=' . Profile::zrl($Blink) . '][img]' . $Bphoto . '[/img][/url]';
$Bphoto = '[url=' . Contact::magicLink($Blink) . '][img]' . $Bphoto . '[/img][/url]';
}
$item['body'] = L10n::t('%1$s is now friends with %2$s', $A, $B)."\n\n\n".$Bphoto;
@ -237,10 +235,10 @@ function localize_item(&$item) {
}
}
$A = '[url=' . Profile::zrl($Alink) . ']' . $Aname . '[/url]';
$B = '[url=' . Profile::zrl($Blink) . ']' . $Bname . '[/url]';
$A = '[url=' . Contact::magicLink($Alink) . ']' . $Aname . '[/url]';
$B = '[url=' . Contact::magicLink($Blink) . ']' . $Bname . '[/url]';
if ($Bphoto != "") {
$Bphoto = '[url=' . Profile::zrl($Blink) . '][img=80x80]' . $Bphoto . '[/img][/url]';
$Bphoto = '[url=' . Contact::magicLink($Blink) . '][img=80x80]' . $Bphoto . '[/img][/url]';
}
/*
@ -272,8 +270,8 @@ function localize_item(&$item) {
$obj = $r[0];
$author = '[url=' . Profile::zrl($item['author-link']) . ']' . $item['author-name'] . '[/url]';
$objauthor = '[url=' . Profile::zrl($obj['author-link']) . ']' . $obj['author-name'] . '[/url]';
$author = '[url=' . Contact::magicLinkById($item['author-id']) . ']' . $item['author-name'] . '[/url]';
$objauthor = '[url=' . Contact::magicLinkById($obj['author-id']) . ']' . $obj['author-name'] . '[/url]';
switch ($obj['verb']) {
case ACTIVITY_POST:
@ -304,8 +302,8 @@ function localize_item(&$item) {
$item['body'] = L10n::t('%1$s tagged %2$s\'s %3$s with %4$s', $author, $objauthor, $plink, $tag );
}
if (activity_match($item['verb'], ACTIVITY_FAVORITE)) {
if (activity_match($item['verb'], ACTIVITY_FAVORITE)) {
if ($item['object-type'] == "") {
return;
}
@ -326,8 +324,8 @@ function localize_item(&$item) {
$target = $r[0];
$Bname = $target['author-name'];
$Blink = $target['author-link'];
$A = '[url=' . Profile::zrl($Alink) . ']' . $Aname . '[/url]';
$B = '[url=' . Profile::zrl($Blink) . ']' . $Bname . '[/url]';
$A = '[url=' . Contact::magicLink($Alink) . ']' . $Aname . '[/url]';
$B = '[url=' . Contact::magicLink($Blink) . ']' . $Bname . '[/url]';
$P = '[url=' . $target['plink'] . ']' . L10n::t('post/item') . '[/url]';
$item['body'] = L10n::t('%1$s marked %2$s\'s %3$s as favorite', $A, $B, $P)."\n";
}
@ -337,7 +335,7 @@ function localize_item(&$item) {
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=' . Profile::zrl($mtch[1]) . ']', $item['body']);
$item['body'] = str_replace($mtch[0], '@[url=' . Contact::magicLink($mtch[1]) . ']', $item['body']);
}
}
}
@ -350,16 +348,7 @@ function localize_item(&$item) {
}
// add sparkle links to appropriate permalinks
$x = stristr($item['plink'],'/display/');
if ($x) {
$sparkle = false;
$y = best_link_url($item, $sparkle);
if (strstr($y, '/redir/')) {
$item['plink'] = $y . '?f=&url=' . $item['plink'];
}
}
$item['plink'] = Contact::magicLinkById($item['author-id'], $item['plink']);
}
/**
@ -394,10 +383,9 @@ function visible_activity($item) {
}
}
if (activity_match($item['verb'], ACTIVITY_FOLLOW) && $item['object-type'] === ACTIVITY_OBJ_NOTE) {
if (!($item['self'] && ($item['uid'] == local_user()))) {
return false;
}
// @TODO below if() block can be rewritten to a single line: $isVisible = allConditionsHere;
if (activity_match($item['verb'], ACTIVITY_FOLLOW) && $item['object-type'] === ACTIVITY_OBJ_NOTE && empty($item['self']) && $item['uid'] == local_user()) {
return false;
}
return true;
@ -405,10 +393,12 @@ function visible_activity($item) {
/**
* @brief SQL query for items
*
* @param int $uid user id
*/
function item_query() {
function item_query($uid = 0) {
return "SELECT " . item_fieldlists() . " FROM `item` " .
item_joins() . " WHERE " . item_condition();
item_joins($uid) . " WHERE " . item_condition();
}
/**
@ -429,7 +419,6 @@ These Fields are not added below (yet). They are here to for bug search.
`item`.`inform`,
`item`.`pubmail`,
`item`.`visible`,
`item`.`spam`,
`item`.`bookmark`,
`item`.`unseen`,
`item`.`deleted`,
@ -437,10 +426,12 @@ These Fields are not added below (yet). They are here to for bug search.
`item`.`mention`,
`item`.`global`,
`item`.`shadow`,
`item`.`author-link`, `item`.`author-name`, `item`.`author-avatar`,
`item`.`owner-link`, `item`.`owner-name`, `item`.`owner-avatar`,
*/
return "`item`.`author-id`, `item`.`author-link`, `item`.`author-name`, `item`.`author-avatar`,
`item`.`owner-id`, `item`.`owner-link`, `item`.`owner-name`, `item`.`owner-avatar`,
return "`item`.`author-id`,
`item`.`owner-id`,
`item`.`contact-id`, `item`.`uid`, `item`.`id`, `item`.`parent`,
`item`.`uri`, `item`.`thr-parent`, `item`.`parent-uri`, `item`.`content-warning`,
`item`.`commented`, `item`.`created`, `item`.`edited`, `item`.`received`,
@ -452,7 +443,9 @@ These Fields are not added below (yet). They are here to for bug search.
`item`.`allow_cid`, `item`.`allow_gid`, `item`.`deny_cid`, `item`.`deny_gid`,
`item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`author`.`thumb` AS `author-thumb`, `owner`.`thumb` AS `owner-thumb`,
`author`.`url` AS `author-link`, `author`.`name` AS `author-name`, `author`.`thumb` AS `author-avatar`,
`owner`.`url` AS `owner-link`, `owner`.`name` AS `owner-name`, `owner`.`thumb` AS `owner-avatar`,
`contact`.`url` AS `contact-link`, `contact`.`name` AS `contact-name`, `contact`.`thumb` AS `contact-avatar`,
`contact`.`network`, `contact`.`url`, `contact`.`name`, `contact`.`writable`,
`contact`.`self`, `contact`.`id` AS `cid`, `contact`.`alias`,
@ -467,16 +460,19 @@ These Fields are not added below (yet). They are here to for bug search.
/**
* @brief SQL join for contacts that are needed for displaying items
*
* @param int $uid user id
*/
function item_joins() {
function item_joins($uid = 0) {
return sprintf("STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND NOT `contact`.`blocked`
AND ((NOT `contact`.`readonly` AND NOT `contact`.`pending` AND (`contact`.`rel` IN (%s, %s)))
OR `contact`.`self` OR (`item`.`id` != `item`.`parent`) OR `contact`.`uid` = 0)
INNER JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id` AND NOT `author`.`blocked`
INNER JOIN `contact` AS `owner` ON `owner`.`id`=`item`.`owner-id` AND NOT `owner`.`blocked`
STRAIGHT_JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id` AND NOT `author`.`blocked`
STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id`=`item`.`owner-id` AND NOT `owner`.`blocked`
LEFT JOIN `user-item` ON `user-item`.`iid` = `item`.`id` AND `user-item`.`uid` = %d
LEFT JOIN `event` ON `event-id` = `event`.`id`",
CONTACT_IS_SHARING, CONTACT_IS_FRIEND
CONTACT_IS_SHARING, CONTACT_IS_FRIEND, intval($uid)
);
}
@ -484,7 +480,7 @@ function item_joins() {
* @brief SQL condition for items that are needed for displaying items
*/
function item_condition() {
return "`item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`";
return "`item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated` AND (`user-item`.`hidden` IS NULL OR NOT `user-item`.`hidden`) ";
}
/**
@ -497,7 +493,7 @@ function item_condition() {
* that are based on unique features of the calling module.
*
*/
function conversation(App $a, $items, $mode, $update, $preview = false, $order = 'commented') {
function conversation(App $a, $items, $mode, $update, $preview = false, $order = 'commented', $uid = 0) {
require_once 'mod/proxy.php';
$ssl_state = ((local_user()) ? true : false);
@ -521,7 +517,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
$previewing = (($preview) ? ' preview ' : '');
if ($mode === 'network') {
$items = conversation_add_children($items, false, $order);
$items = conversation_add_children($items, false, $order, $uid);
$profile_owner = local_user();
if (!$update) {
/*
@ -540,7 +536,6 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
. ((x($_GET, 'bmark')) ? '&bmark=' . $_GET['bmark'] : '')
. ((x($_GET, 'liked')) ? '&liked=' . $_GET['liked'] : '')
. ((x($_GET, 'conv')) ? '&conv=' . $_GET['conv'] : '')
. ((x($_GET, 'spam')) ? '&spam=' . $_GET['spam'] : '')
. ((x($_GET, 'nets')) ? '&nets=' . $_GET['nets'] : '')
. ((x($_GET, 'cmin')) ? '&cmin=' . $_GET['cmin'] : '')
. ((x($_GET, 'cmax')) ? '&cmax=' . $_GET['cmax'] : '')
@ -582,7 +577,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
. " var profile_page = 1; </script>";
}
} elseif ($mode === 'community') {
$items = conversation_add_children($items, true, $order);
$items = conversation_add_children($items, true, $order, $uid);
$profile_owner = 0;
if (!$update) {
$live_update_div = '<div id="live-community"></div>' . "\r\n"
@ -666,6 +661,13 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
continue;
}
if ($item['network'] == NETWORK_FEED) {
$item['author-avatar'] = $item['contact-avatar'];
$item['author-name'] = $item['contact-name'];
$item['owner-avatar'] = $item['contact-avatar'];
$item['owner-name'] = $item['contact-name'];
}
$profile_name = (strlen($item['author-name']) ? $item['author-name'] : $item['name']);
if ($item['author-link'] && !$item['author-name']) {
$profile_name = $item['author-link'];
@ -673,34 +675,10 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
$tags = \Friendica\Model\Term::populateTagsFromItem($item);
$sp = false;
$profile_link = best_link_url($item, $sp);
if ($profile_link === 'mailbox') {
$profile_link = '';
}
$profile_link = Contact::magicLinkbyId($item['author-id']);
if ($sp) {
if (strpos($profile_link, 'redir/') === 0) {
$sparkle = ' sparkle';
} else {
$profile_link = Profile::zrl($profile_link);
}
if (!x($item, 'author-thumb') || ($item['author-thumb'] == "")) {
$author_contact = Contact::getDetailsByURL($item['author-link'], $profile_owner);
if ($author_contact["thumb"]) {
$item['author-thumb'] = $author_contact["thumb"];
} else {
$item['author-thumb'] = $item['author-avatar'];
}
}
if (!isset($item['owner-thumb']) || ($item['owner-thumb'] == "")) {
$owner_contact = Contact::getDetailsByURL($item['owner-link'], $profile_owner);
if ($owner_contact["thumb"]) {
$item['owner-thumb'] = $owner_contact["thumb"];
} else {
$item['owner-thumb'] = $item['owner-avatar'];
}
}
$locate = ['location' => $item['location'], 'coord' => $item['coord'], 'html' => ''];
@ -757,13 +735,13 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
'guid' => (($preview) ? 'Q0' : $item['guid']),
'network' => $item['item_network'],
'network_name' => ContactSelector::networkToName($item['item_network'], $profile_link),
'linktitle' => L10n::t('View %s\'s profile @ %s', $profile_name, ((strlen($item['author-link'])) ? $item['author-link'] : $item['url'])),
'linktitle' => L10n::t('View %s\'s profile @ %s', $profile_name, $item['author-link']),
'profile_url' => $profile_link,
'item_photo_menu' => item_photo_menu($item),
'name' => $profile_name_e,
'sparkle' => $sparkle,
'lock' => $lock,
'thumb' => System::removedBaseUrl(proxy_url($item['author-thumb'], false, PROXY_SIZE_THUMB)),
'thumb' => System::removedBaseUrl(proxy_url($item['author-avatar'], false, PROXY_SIZE_THUMB)),
'title' => $title_e,
'body' => $body_e,
'tags' => $tags_e,
@ -782,7 +760,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
'indent' => '',
'owner_name' => $owner_name_e,
'owner_url' => $owner_url,
'owner_photo' => System::removedBaseUrl(proxy_url($item['owner-thumb'], false, PROXY_SIZE_THUMB)),
'owner_photo' => System::removedBaseUrl(proxy_url($item['owner-avatar'], false, PROXY_SIZE_THUMB)),
'plink' => get_plink($item),
'edpost' => false,
'isstarred' => $isstarred,
@ -885,24 +863,24 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
*
* @return array items with parents and comments
*/
function conversation_add_children($parents, $block_authors, $order) {
function conversation_add_children($parents, $block_authors, $order, $uid) {
$max_comments = Config::get('system', 'max_comments', 100);
$params = ['order' => ['uid', 'commented' => true]];
if ($max_comments > 0) {
$limit = ' LIMIT '.intval($max_comments + 1);
} else {
$limit = '';
$params['limit'] = $max_comments;
}
$items = [];
$block_sql = $block_authors ? "AND NOT `author`.`hidden` AND NOT `author`.`blocked`" : "";
foreach ($parents AS $parent) {
$thread_items = dba::p(item_query()."AND `item`.`parent-uri` = ?
AND `item`.`uid` IN (0, ?) $block_sql
ORDER BY `item`.`uid` ASC, `item`.`commented` DESC" . $limit,
$parent['uri'], local_user());
$condition = ["`item`.`parent-uri` = ? AND `item`.`uid` IN (0, ?) ",
$parent['uri'], local_user()];
if ($block_authors) {
$condition[0] .= "AND NOT `author`.`hidden`";
}
$thread_items = Item::select(local_user(), [], $condition, $params);
$comments = dba::inArray($thread_items);
@ -922,48 +900,6 @@ function conversation_add_children($parents, $block_authors, $order) {
return $items;
}
function best_link_url($item, &$sparkle, $url = '') {
$best_url = '';
$sparkle = false;
$clean_url = normalise_link($item['author-link']);
if (local_user()) {
$condition = [
'network' => NETWORK_DFRN,
'uid' => local_user(),
'nurl' => normalise_link($clean_url),
'pending' => false
];
$contact = dba::selectFirst('contact', ['id'], $condition);
if (DBM::is_result($contact)) {
$best_url = 'redir/' . $contact['id'];
$sparkle = true;
if ($url != '') {
$hostname = get_app()->get_hostname();
if (!strstr($url, $hostname)) {
$best_url .= "?url=".$url;
} else {
$best_url = $url;
}
}
}
}
if (!$best_url) {
if ($url != '') {
$best_url = $url;
} elseif (strlen($item['author-link'])) {
$best_url = $item['author-link'];
} else {
$best_url = $item['url'];
}
}
return $best_url;
}
function item_photo_menu($item) {
$sub_link = '';
$poke_link = '';
@ -977,11 +913,8 @@ function item_photo_menu($item) {
$sub_link = 'javascript:dosubthread(' . $item['id'] . '); return false;';
}
$sparkle = false;
$profile_link = best_link_url($item, $sparkle);
if ($profile_link === 'mailbox') {
$profile_link = '';
}
$profile_link = Contact::magicLinkById($item['author-id']);
$sparkle = (strpos($profile_link, 'redir/') === 0);
$cid = 0;
$network = '';
@ -999,7 +932,7 @@ function item_photo_menu($item) {
$photos_link = $profile_link . '?url=photos';
$profile_link = $profile_link . '?url=profile';
} else {
$profile_link = Profile::zrl($profile_link);
$profile_link = Contact::magicLink($profile_link);
}
if ($cid && !$item['self']) {
@ -1087,17 +1020,14 @@ function builtin_activity_puller($item, &$conv_responses) {
}
if (activity_match($item['verb'], $verb) && ($item['id'] != $item['parent'])) {
$url = $item['author-link'];
if (local_user() && (local_user() == $item['uid']) && ($item['network'] === NETWORK_DFRN) && !$item['self'] && link_compare($item['author-link'], $item['url'])) {
$url = 'redir/' . $item['contact-id'];
$url = Contact::MagicLinkbyId($item['author-id']);
if (strpos($url, 'redir/') === 0) {
$sparkle = ' class="sparkle" ';
} else {
$url = Profile::zrl($url);
}
$url = '<a href="'. $url . '"'. $sparkle .'>' . htmlentities($item['author-name']) . '</a>';
if (!$item['thr-parent']) {
if (!x($item, 'thr-parent')) {
$item['thr-parent'] = $item['parent-uri'];
}
@ -1585,19 +1515,17 @@ function sort_thr_commented(array $a, array $b)
return strcmp($b['commented'], $a['commented']);
}
/// @TODO Add type-hint
function render_location_dummy($item) {
if ($item['location'] != "") {
function render_location_dummy(array $item) {
if (x($item, 'location') && !empty($item['location'])) {
return $item['location'];
}
if ($item['coord'] != "") {
if (x($item, 'coord') && !empty($item['coord'])) {
return $item['coord'];
}
}
/// @TODO Add type-hint
function get_responses($conv_responses, $response_verbs, $ob, $item) {
function get_responses(array $conv_responses, array $response_verbs, $ob, array $item) {
$ret = [];
foreach ($response_verbs as $v) {
$ret[$v] = [];

View File

@ -27,7 +27,7 @@ class dba {
private static $relation = [];
public static function connect($serveraddr, $user, $pass, $db) {
if (!is_null(self::$db)) {
if (!is_null(self::$db) && self::connected()) {
return true;
}
@ -54,16 +54,6 @@ echo "1";
return false;
}
if ($a->mode == App::MODE_INSTALL) {
// server has to be a non-empty string that is not 'localhost' and not an IP
if (strlen($server) && ($server !== 'localhost') && filter_var($server, FILTER_VALIDATE_IP) === false) {
if (! dns_get_record($server, DNS_A + DNS_CNAME)) {
self::$error = L10n::t('Cannot locate DNS info for database server \'%s\'', $server);
return false;
}
}
}
if (class_exists('\PDO') && in_array('mysql', PDO::getAvailableDrivers())) {
self::$driver = 'pdo';
$connect = "mysql:host=".$server.";dbname=".$db;
@ -119,6 +109,35 @@ echo "1";
return $ret;
}
/**
* Disconnects the current database connection
*/
public static function disconnect()
{
if (is_null(self::$db)) {
return;
}
switch (self::$driver) {
case 'pdo':
self::$db = null;
break;
case 'mysqli':
self::$db->close();
self::$db = null;
break;
}
}
/**
* Return the database object.
* @return PDO|mysqli
*/
public static function get_db()
{
return self::$db;
}
/**
* @brief Returns the MySQL server version string
*
@ -1184,29 +1203,9 @@ echo "1";
$condition_string = self::buildCondition($condition);
$order_string = '';
if (isset($params['order'])) {
$order_string = " ORDER BY ";
foreach ($params['order'] AS $fields => $order) {
if (!is_int($fields)) {
$order_string .= "`" . $fields . "` " . ($order ? "DESC" : "ASC") . ", ";
} else {
$order_string .= "`" . $order . "`, ";
}
}
$order_string = substr($order_string, 0, -2);
}
$param_string = self::buildParameter($params);
$limit_string = '';
if (isset($params['limit']) && is_int($params['limit'])) {
$limit_string = " LIMIT " . $params['limit'];
}
if (isset($params['limit']) && is_array($params['limit'])) {
$limit_string = " LIMIT " . intval($params['limit'][0]) . ", " . intval($params['limit'][1]);
}
$sql = "SELECT " . $select_fields . " FROM `" . $table . "`" . $condition_string . $order_string . $limit_string;
$sql = "SELECT " . $select_fields . " FROM `" . $table . "`" . $condition_string . $param_string;
$result = self::p($sql, $condition);
@ -1263,14 +1262,14 @@ echo "1";
* @param array $condition
* @return string
*/
private static function buildCondition(array &$condition = [])
public static function buildCondition(array &$condition = [])
{
$condition_string = '';
if (count($condition) > 0) {
reset($condition);
$first_key = key($condition);
if (is_int($first_key)) {
$condition_string = " WHERE ".array_shift($condition);
$condition_string = " WHERE (" . array_shift($condition) . ")";
} else {
$new_values = [];
$condition_string = "";
@ -1287,7 +1286,7 @@ echo "1";
$condition_string .= "`" . $field . "` = ?";
}
}
$condition_string = " WHERE " . $condition_string;
$condition_string = " WHERE (" . $condition_string . ")";
$condition = $new_values;
}
}
@ -1295,6 +1294,39 @@ echo "1";
return $condition_string;
}
/**
* @brief Returns the SQL parameter string built from the provided parameter array
*
* @param array $params
* @return string
*/
public static function buildParameter(array $params = [])
{
$order_string = '';
if (isset($params['order'])) {
$order_string = " ORDER BY ";
foreach ($params['order'] AS $fields => $order) {
if (!is_int($fields)) {
$order_string .= "`" . $fields . "` " . ($order ? "DESC" : "ASC") . ", ";
} else {
$order_string .= "`" . $order . "`, ";
}
}
$order_string = substr($order_string, 0, -2);
}
$limit_string = '';
if (isset($params['limit']) && is_int($params['limit'])) {
$limit_string = " LIMIT " . $params['limit'];
}
if (isset($params['limit']) && is_array($params['limit'])) {
$limit_string = " LIMIT " . intval($params['limit'][0]) . ", " . intval($params['limit'][1]);
}
return $order_string.$limit_string;
}
/**
* @brief Fills an array with data from a query
*

View File

@ -11,6 +11,7 @@ use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Emailer;
use Friendica\Model\Item;
/**
* @brief Creates a notification entry and possibly sends a mail
@ -129,7 +130,7 @@ function notification($params)
$item = null;
if ($params['otype'] === 'item' && $parent_id) {
$item = dba::selectFirst('item', [], ['id' => $parent_id]);
$item = Item::selectFirst($params['uid'], [], ['id' => $parent_id]);
}
$item_post_type = item_post_type($item);
@ -152,7 +153,7 @@ function notification($params)
}
// "your post"
if (DBM::is_result($item) && $item['owner-name'] == $item['author-name'] && $item['wall']) {
if (DBM::is_result($item) && $item['owner-id'] == $item['author-id'] && $item['wall']) {
$dest_str = L10n::t('%1$s commented on [url=%2$s]your %3$s[/url]',
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$itemlink,
@ -739,7 +740,7 @@ function check_item_notification($itemid, $uid, $defaulttype = "") {
// Only act if it is a "real" post
// We need the additional check for the "local_profile" because of mixed situations on connector networks
$item = q("SELECT `id`, `mention`, `tag`,`parent`, `title`, `body`, `author-name`, `author-link`, `author-avatar`, `guid`,
$item = q("SELECT `id`, `mention`, `tag`,`parent`, `title`, `body`, `author-id`, `guid`,
`parent-uri`, `uri`, `contact-id`
FROM `item` WHERE `id` = %d AND `verb` IN ('%s', '') AND `type` != 'activity' AND
NOT (`author-link` IN ($profile_list)) LIMIT 1",
@ -747,6 +748,8 @@ function check_item_notification($itemid, $uid, $defaulttype = "") {
if (!$item)
return false;
$author = dba::selectFirst('contact', ['name', 'thumb', 'url'], ['id' => $item[0]['author-id']]);
// Generate the notification array
$params = [];
$params["uid"] = $uid;
@ -758,9 +761,9 @@ function check_item_notification($itemid, $uid, $defaulttype = "") {
$params["parent"] = $item[0]["parent"];
$params["link"] = System::baseUrl().'/display/'.urlencode($item[0]["guid"]);
$params["otype"] = 'item';
$params["source_name"] = $item[0]["author-name"];
$params["source_link"] = $item[0]["author-link"];
$params["source_photo"] = $item[0]["author-avatar"];
$params["source_name"] = $author["name"];
$params["source_link"] = $author["url"];
$params["source_photo"] = $author["thumb"];
if ($item[0]["parent-uri"] === $item[0]["uri"]) {
// Send a notification for every new post?

View File

@ -274,6 +274,7 @@ function consume_feed($xml, $importer, $contact, &$hub, $datedir = 0, $pass = 0)
function subscribe_to_hub($url, $importer, $contact, $hubmode = 'subscribe') {
$a = get_app();
$r = null;
if (is_array($importer)) {
$r = q("SELECT `nickname` FROM `user` WHERE `uid` = %d LIMIT 1",
@ -321,7 +322,7 @@ function drop_items($items) {
if (count($items)) {
foreach ($items as $item) {
$owner = Item::deleteById($item);
$owner = Item::deleteForUser(['id' => $item], local_user());
if ($owner && !$uid)
$uid = $owner;
}
@ -393,7 +394,7 @@ function drop_item($id) {
}
// delete the item
Item::deleteById($item['id']);
Item::deleteForUser(['id' => $item['id']], local_user());
goaway(System::baseUrl() . '/' . $_SESSION['return_url']);
//NOTREACHED

View File

@ -254,6 +254,7 @@ function can_write_wall($owner)
return false;
}
/// @TODO $groups should be array
function permissions_sql($owner_id, $remote_verified = false, $groups = null)
{
$local_user = local_user();
@ -275,6 +276,13 @@ function permissions_sql($owner_id, $remote_verified = false, $groups = null)
*/
if ($local_user && $local_user == $owner_id) {
$sql = '';
/**
* Authenticated visitor. Unless pre-verified,
* check that the contact belongs to this $owner_id
* and load the groups the visitor belongs to.
* If pre-verified, the caller is expected to have already
* done this and passed the groups into this function.
*/
} elseif ($remote_user) {
/*
* Authenticated visitor. Unless pre-verified,
@ -298,9 +306,10 @@ function permissions_sql($owner_id, $remote_verified = false, $groups = null)
if ($remote_verified) {
$gs = '<<>>'; // should be impossible to match
if (is_array($groups) && count($groups)) {
foreach ($groups as $g)
if (is_array($groups)) {
foreach ($groups as $g) {
$gs .= '|<' . intval($g) . '>';
}
}
$sql = sprintf(

View File

@ -152,7 +152,7 @@ function autoname($len) {
'nd','ng','nk','nt','rn','rp','rt'];
$noend = ['bl', 'br', 'cl','cr','dr','fl','fr','gl','gr',
'kh', 'kl','kr','mn','pl','pr','rh','tr','qu','wh'];
'kh', 'kl','kr','mn','pl','pr','rh','tr','qu','wh','q'];
$start = mt_rand(0,2);
if ($start == 0) {
@ -178,14 +178,13 @@ function autoname($len) {
$word = substr($word,0,$len);
foreach ($noend as $noe) {
if ((strlen($word) > 2) && (substr($word, -2) == $noe)) {
$word = substr($word, 0, -1);
$noelen = strlen($noe);
if ((strlen($word) > $noelen) && (substr($word, -$noelen) == $noe)) {
$word = autoname($len);
break;
}
}
if (substr($word, -1) == 'q') {
$word = substr($word, 0, -1);
}
return $word;
}
@ -453,7 +452,7 @@ function perms2str($p) {
if (is_array($p)) {
$tmp = $p;
} else {
$tmp = explode(',',$p);
$tmp = explode(',', $p);
}
if (is_array($tmp)) {
@ -962,13 +961,9 @@ function micropro($contact, $redirect = false, $class = '', $textmode = false) {
$redir = false;
if ($redirect) {
$redirect_url = 'redir/' . $contact['id'];
if (local_user() && ($contact['uid'] == local_user()) && ($contact['network'] === NETWORK_DFRN)) {
$redir = true;
$url = $redirect_url;
$url = Contact::magicLink($contact['url']);
if (strpos($url, 'redir/') === 0) {
$sparkle = ' sparkle';
} else {
$url = Profile::zrl($url);
}
}
@ -1301,11 +1296,7 @@ function prepare_body(array &$item, $attach = false, $is_preview = false)
foreach ($matches as $mtch) {
$mime = $mtch[3];
if ((local_user() == $item['uid']) && ($item['contact-id'] != $a->contact['id']) && ($item['network'] == NETWORK_DFRN)) {
$the_url = 'redir/' . $item['contact-id'] . '?f=1&url=' . $mtch[1];
} else {
$the_url = $mtch[1];
}
$the_url = Contact::magicLinkById($item['author-id'], $mtch[1]);
if (strpos($mime, 'video') !== false) {
if (!$vhead) {
@ -1661,10 +1652,11 @@ function bb_translate_video($s) {
$r = preg_match_all("/\[video\](.*?)\[\/video\]/ism",$s,$matches,PREG_SET_ORDER);
if ($r) {
foreach ($matches as $mtch) {
if ((stristr($mtch[1],'youtube')) || (stristr($mtch[1],'youtu.be')))
$s = str_replace($mtch[0],'[youtube]' . $mtch[1] . '[/youtube]',$s);
elseif (stristr($mtch[1],'vimeo'))
$s = str_replace($mtch[0],'[vimeo]' . $mtch[1] . '[/vimeo]',$s);
if ((stristr($mtch[1], 'youtube')) || (stristr($mtch[1], 'youtu.be'))) {
$s = str_replace($mtch[0], '[youtube]' . $mtch[1] . '[/youtube]', $s);
} elseif (stristr($mtch[1], 'vimeo')) {
$s = str_replace($mtch[0], '[vimeo]' . $mtch[1] . '[/vimeo]', $s);
}
}
}
return $s;
@ -1782,7 +1774,7 @@ function file_tag_file_query($table,$s,$type = 'file') {
}
// ex. given music,video return <music><video> or [music][video]
function file_tag_list_to_file($list,$type = 'file') {
function file_tag_list_to_file($list, $type = 'file') {
$tag_list = '';
if (strlen($list)) {
$list_array = explode(",",$list);
@ -1804,7 +1796,7 @@ function file_tag_list_to_file($list,$type = 'file') {
}
// ex. given <music><video>[friends], return music,video or friends
function file_tag_file_to_list($file,$type = 'file') {
function file_tag_file_to_list($file, $type = 'file') {
$matches = false;
$list = '';
if ($type == 'file') {
@ -1830,8 +1822,7 @@ function file_tag_update_pconfig($uid, $file_old, $file_new, $type = 'file') {
if (!intval($uid)) {
return false;
}
if ($file_old == $file_new) {
} elseif ($file_old == $file_new) {
return true;
}
@ -1854,8 +1845,9 @@ function file_tag_update_pconfig($uid, $file_old, $file_new, $type = 'file') {
$check_new_tags = explode(",",file_tag_file_to_list($file_new,$type));
foreach ($check_new_tags as $tag) {
if (! stristr($saved,$lbracket . file_tag_encode($tag) . $rbracket))
if (! stristr($saved,$lbracket . file_tag_encode($tag) . $rbracket)) {
$new_tags[] = $tag;
}
}
$filetags_updated .= file_tag_list_to_file(implode(",",$new_tags),$type);
@ -1865,8 +1857,9 @@ function file_tag_update_pconfig($uid, $file_old, $file_new, $type = 'file') {
$check_deleted_tags = explode(",",file_tag_file_to_list($file_old,$type));
foreach ($check_deleted_tags as $tag) {
if (! stristr($file_new,$lbracket . file_tag_encode($tag) . $rbracket))
if (! stristr($file_new,$lbracket . file_tag_encode($tag) . $rbracket)) {
$deleted_tags[] = $tag;
}
}
foreach ($deleted_tags as $key => $tag) {
@ -1980,17 +1973,22 @@ function protect_sprintf($s) {
return str_replace('%', '%%', $s);
}
/// @TODO Rewrite this
function is_a_date_arg($s) {
$i = intval($s);
if ($i > 1900) {
$y = date('Y');
if ($i <= $y + 1 && strpos($s, '-') == 4) {
$m = intval(substr($s,5));
if ($m > 0 && $m <= 12)
$m = intval(substr($s, 5));
if ($m > 0 && $m <= 12) {
return true;
}
}
}
return false;
}
@ -2008,6 +2006,7 @@ function deindent($text, $chr = "[\t ]", $count = NULL) {
preg_match("|^" . $chr . "*|", $lines[$k], $m);
$count = strlen($m[0]);
}
for ($k = 0; $k < count($lines); $k++) {
$lines[$k] = preg_replace("|^" . $chr . "{" . $count . "}|", "", $lines[$k]);
}

View File

@ -65,7 +65,7 @@ function admin_post(App $a)
case 'addons':
if ($a->argc > 2 &&
is_file("addon/" . $a->argv[2] . "/" . $a->argv[2] . ".php")) {
@include_once("addon/" . $a->argv[2] . "/" . $a->argv[2] . ".php");
include_once "addon/" . $a->argv[2] . "/" . $a->argv[2] . ".php";
if (function_exists($a->argv[2] . '_addon_admin_post')) {
$func = $a->argv[2] . '_addon_admin_post';
$func($a);
@ -555,14 +555,9 @@ function admin_page_deleteitem_post(App $a)
if (strpos($guid, '/')) {
$guid = substr($guid, strrpos($guid, '/') + 1);
}
// Now that we have the GUID get all IDs of the associated entries in the
// item table of the DB and drop those items, which will also delete the
// Now that we have the GUID, drop those items, which will also delete the
// associated threads.
$r = dba::select('item', ['id'], ['guid' => $guid]);
while ($row = dba::fetch($r)) {
Item::deleteById($row['id']);
}
dba::close($r);
Item::delete(['guid' => $guid]);
}
info(L10n::t('Item marked for deletion.') . EOL);
@ -806,7 +801,7 @@ function admin_page_summary(App $a)
$warningtext[] = L10n::t('The database update failed. Please run "php bin/console.php dbstructure update" from the command line and have a look at the errors that might appear.');
}
$last_worker_call = Config::get('system', 'last_poller_execution', false);
$last_worker_call = Config::get('system', 'last_worker_execution', false);
if (!$last_worker_call) {
$showwarning = true;
$warningtext[] = L10n::t('The worker was never executed. Please check your database structure!');
@ -921,6 +916,7 @@ function admin_page_site_post(App $a)
$upds = implode(", ", $upd);
$r = q("UPDATE %s SET %s;", $table_name, $upds);
if (!DBM::is_result($r)) {
notice("Failed updating '$table_name': " . dba::errorMessage());
goaway('admin/site');
@ -932,7 +928,7 @@ function admin_page_site_post(App $a)
update_table("term", ['url'], $old_url, $new_url);
update_table("contact", ['photo', 'thumb', 'micro', 'url', 'nurl', 'alias', 'request', 'notify', 'poll', 'confirm', 'poco', 'avatar'], $old_url, $new_url);
update_table("gcontact", ['url', 'nurl', 'photo', 'server_url', 'notify', 'alias'], $old_url, $new_url);
update_table("item", ['owner-link', 'owner-avatar', 'author-link', 'author-avatar', 'body', 'plink', 'tag'], $old_url, $new_url);
update_table("item", ['owner-link', 'author-link', 'body', 'plink', 'tag'], $old_url, $new_url);
// update profile addresses in the format "user@server.tld"
update_table("contact", ['addr'], $old_host, $new_host);
@ -1302,15 +1298,18 @@ function admin_page_site(App $a)
$user_names = [];
$user_names['---'] = L10n::t('Multi user instance');
$users = q("SELECT `username`, `nickname` FROM `user`");
foreach ($users as $user) {
$user_names[$user['nickname']] = $user['username'];
}
/* Banner */
$banner = Config::get('system', 'banner');
if ($banner == false) {
$banner = '<a href="https://friendi.ca"><img id="logo-img" src="images/friendica-32.png" alt="logo" /></a><span id="logo-text"><a href="https://friendi.ca">Friendica</a></span>';
}
$banner = htmlspecialchars($banner);
$info = Config::get('config', 'info');
$info = htmlspecialchars($info);
@ -1395,7 +1394,7 @@ function admin_page_site(App $a)
'$no_oembed_rich_content' => ['no_oembed_rich_content', L10n::t("No OEmbed rich content"), Config::get('system','no_oembed_rich_content'), L10n::t("Don't show the rich content \x28e.g. embedded PDF\x29, except from the domains listed below.")],
'$allowed_oembed' => ['allowed_oembed', L10n::t("Allowed OEmbed domains"), Config::get('system','allowed_oembed'), L10n::t("Comma separated list of domains which oembed content is allowed to be displayed. Wildcards are accepted.")],
'$block_public' => ['block_public', L10n::t("Block public"), Config::get('system','block_public'), L10n::t("Check to block public access to all otherwise public personal pages on this site unless you are currently logged in.")],
'$force_publish' => ['publish_all', L10n::t("Force publish"), Config::get('system','publish_all'), L10n::t("Check to force all profiles on this site to be listed in the site directory.")],
'$force_publish' => ['publish_all', L10n::t("Force publish"), Config::get('system','publish_all'), L10n::t("Check to force all profiles on this site to be listed in the site directory.") . '<strong>' . L10n::t('Enabling this may violate privacy laws like the GDPR') . '</strong>'],
'$global_directory' => ['directory', L10n::t("Global directory URL"), Config::get('system', 'directory', 'https://dir.friendica.social'), L10n::t("URL to the global directory. If this is not set, the global directory is completely unavailable to the application.")],
'$newuser_private' => ['newuser_private', L10n::t("Private posts by default for new users"), Config::get('system','newuser_private'), L10n::t("Set default post permissions for all new members to the default privacy group rather than public.")],
'$enotify_no_content' => ['enotify_no_content', L10n::t("Don't include post content in email notifications"), Config::get('system','enotify_no_content'), L10n::t("Don't include the content of a post/comment/private message/etc. in the email notifications that are sent out from this site, as a privacy measure.")],
@ -1442,7 +1441,7 @@ function admin_page_site(App $a)
'$max_comments' => ['max_comments', L10n::t("Maximum numbers of comments per post"), Config::get('system','max_comments'), L10n::t("How much comments should be shown for each post? Default value is 100.")],
'$temppath' => ['temppath', L10n::t("Temp path"), Config::get('system','temppath'), L10n::t("If you have a restricted system where the webserver can't access the system temp path, enter another path here.")],
'$basepath' => ['basepath', L10n::t("Base path to installation"), Config::get('system','basepath'), L10n::t("If the system cannot detect the correct path to your installation, enter the correct path here. This setting should only be set if you are using a restricted system and symbolic links to your webroot.")],
'$proxy_disabled' => ['proxy_disabled', L10n::t("Disable picture proxy"), Config::get('system','proxy_disabled'), L10n::t("The picture proxy increases performance and privacy. It shouldn't be used on systems with very low bandwith.")],
'$proxy_disabled' => ['proxy_disabled', L10n::t("Disable picture proxy"), Config::get('system','proxy_disabled'), L10n::t("The picture proxy increases performance and privacy. It shouldn't be used on systems with very low bandwidth.")],
'$only_tag_search' => ['only_tag_search', L10n::t("Only search in tags"), Config::get('system','only_tag_search'), L10n::t("On large systems the text search can slow down the system extremely.")],
'$relocate_url' => ['relocate_url', L10n::t("New base url"), System::baseUrl(), L10n::t("Change base url for this server. Sends relocate message to all Friendica and Diaspora* contacts of all users.")],
@ -1506,9 +1505,12 @@ function admin_page_dbsync(App $a)
if ($a->argc > 2 && intval($a->argv[2])) {
require_once 'update.php';
$func = 'update_' . intval($a->argv[2]);
if (function_exists($func)) {
$retval = $func();
if ($retval === UPDATE_FAILED) {
$o .= L10n::t("Executing %s failed with error: %s", $func, $retval);
} elseif ($retval === UPDATE_SUCCESS) {
@ -1521,11 +1523,13 @@ function admin_page_dbsync(App $a)
$o .= L10n::t('There was no additional update function %s that needed to be called.', $func) . "<br />";
Config::set('database', $func, 'success');
}
return $o;
}
$failed = [];
$r = q("SELECT `k`, `v` FROM `config` WHERE `cat` = 'database' ");
if (DBM::is_result($r)) {
foreach ($r as $rr) {
$upd = intval(substr($rr['k'], 7));
@ -1535,6 +1539,7 @@ function admin_page_dbsync(App $a)
$failed[] = $upd;
}
}
if (!count($failed)) {
$o = replace_macros(get_markup_template('structure_check.tpl'), [
'$base' => System::baseUrl(true),
@ -1769,8 +1774,8 @@ function admin_page_users(App $a)
$e['page-flags-raw'] = $e['page-flags'];
$e['page-flags'] = $page_types[$e['page-flags']];
$e['account-type-raw'] = ($e['page_flags_raw']==0) ? $e['account-type'] : -1;
$e['account-type'] = ($e['page_flags_raw']==0) ? $account_types[$e['account-type']] : "";
$e['account-type-raw'] = ($e['page_flags_raw'] == 0) ? $e['account-type'] : -1;
$e['account-type'] = ($e['page_flags_raw'] == 0) ? $account_types[$e['account-type']] : "";
$e['register_date'] = Temporal::getRelativeDate($e['register_date']);
$e['login_date'] = Temporal::getRelativeDate($e['login_date']);
@ -1921,7 +1926,7 @@ function admin_page_addons(App $a)
$admin_form = "";
if (in_array($addon, $a->addons_admin)) {
@require_once("addon/$addon/$addon.php");
require_once "addon/$addon/$addon.php";
$func = $addon . '_addon_admin';
$func($a, $admin_form);
}
@ -2162,6 +2167,7 @@ function admin_page_themes(App $a)
}
$readme = null;
if (is_file("view/theme/$theme/README.md")) {
$readme = Markdown::convert(file_get_contents("view/theme/$theme/README.md"), false);
} elseif (is_file("view/theme/$theme/README")) {

View File

@ -70,7 +70,7 @@ function allfriends_content(App $a)
} else {
$connlnk = System::baseUrl() . '/follow/?url=' . $rr['url'];
$photo_menu = [
'profile' => [L10n::t("View Profile"), Profile::zrl($rr['url'])],
'profile' => [L10n::t("View Profile"), Contact::magicLink($rr['url'])],
'follow' => [L10n::t("Connect/Follow"), $connlnk]
];
}

View File

@ -171,7 +171,7 @@ function community_content(App $a, $update = 0)
$s = $r;
}
$o .= conversation($a, $s, 'community', $update);
$o .= conversation($a, $s, 'community', $update, false, 'commented', local_user());
if (!$update) {
$o .= alt_pager($a, count($r));

View File

@ -65,7 +65,7 @@ function contacts_init(App $a)
$vcard_widget = replace_macros(get_markup_template("vcard-widget.tpl"), [
'$name' => htmlentities($a->data['contact']['name']),
'$photo' => $a->data['contact']['photo'],
'$url' => ($a->data['contact']['network'] == NETWORK_DFRN) ? "redir/" . $a->data['contact']['id'] : $a->data['contact']['url'],
'$url' => Contact::MagicLink($a->data['contact']['url']),
'$addr' => (($a->data['contact']['addr'] != "") ? ($a->data['contact']['addr']) : ""),
'$network_name' => $networkname,
'$network' => L10n::t('Network:'),
@ -536,11 +536,10 @@ function contacts_content(App $a)
$relation_text = sprintf($relation_text, htmlentities($contact['name']));
if (($contact['network'] === NETWORK_DFRN) && ($contact['rel'])) {
$url = "redir/{$contact['id']}";
$url = Contact::magicLink($contact['url']);
if (strpos($url, 'redir/') === 0) {
$sparkle = ' class="sparkle" ';
} else {
$url = $contact['url'];
$sparkle = '';
}
@ -940,11 +939,11 @@ function _contact_detail_for_template($rr)
default:
break;
}
if (($rr['network'] === NETWORK_DFRN) && ($rr['rel'])) {
$url = "redir/{$rr['id']}";
$url = Contact::magicLink($rr['url']);
if (strpos($url, 'redir/') === 0) {
$sparkle = ' class="sparkle" ';
} else {
$url = $rr['url'];
$sparkle = '';
}

View File

@ -189,7 +189,6 @@ function dfrn_request_post(App $a)
}
// (ignore reply, nothing we can do it failed)
// Old: goaway(Profile::zrl($dfrn_url));
goaway($forwardurl);
return; // NOTREACHED
}

View File

@ -156,7 +156,7 @@ function directory_content(App $a)
$location_e = $location;
$photo_menu = [
'profile' => [L10n::t("View Profile"), Profile::zrl($profile_link)]
'profile' => [L10n::t("View Profile"), Contact::magicLink($profile_link)]
];
$entry = [

View File

@ -11,7 +11,6 @@ use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Model\Contact;
use Friendica\Model\GContact;
use Friendica\Model\Profile;
use Friendica\Network\Probe;
use Friendica\Protocol\PortableContact;
use Friendica\Util\Network;
@ -214,7 +213,7 @@ function dirfind_content(App $a, $prefix = "") {
$connlnk = System::baseUrl().'/follow/?url='.(($jj->connect) ? $jj->connect : $jj->url);
$conntxt = L10n::t('Connect');
$photo_menu = [
'profile' => [L10n::t("View Profile"), Profile::zrl($jj->url)],
'profile' => [L10n::t("View Profile"), Contact::magicLink($jj->url)],
'follow' => [L10n::t("Connect/Follow"), $connlnk]
];
}
@ -223,7 +222,7 @@ function dirfind_content(App $a, $prefix = "") {
$entry = [
'alt_text' => $alt_text,
'url' => Profile::magicLink($jj->url),
'url' => Contact::magicLink($jj->url),
'itemurl' => $itemurl,
'name' => htmlentities($jj->name),
'thumb' => proxy_url($jj->photo, false, PROXY_SIZE_THUMB),

View File

@ -14,6 +14,7 @@ use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Model\Contact;
use Friendica\Model\Group;
use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Protocol\DFRN;
@ -49,8 +50,7 @@ function display_init(App $a)
// Does the local user have this item?
if (local_user()) {
$r = dba::fetch_first("SELECT `id`, `parent`, `author-name`, `author-link`,
`author-avatar`, `network`, `body`, `uid`, `owner-link`
$r = dba::fetch_first("SELECT `id`, `parent`, `author-id`, `body`, `uid`
FROM `item` WHERE `visible` AND NOT `deleted` AND NOT `moderated`
AND `guid` = ? AND `uid` = ? LIMIT 1", $a->argv[1], local_user());
if (DBM::is_result($r)) {
@ -60,8 +60,7 @@ function display_init(App $a)
// Is it an item with uid=0?
if (!DBM::is_result($r)) {
$r = dba::fetch_first("SELECT `id`, `parent`, `author-name`, `author-link`,
`author-avatar`, `network`, `body`, `uid`, `owner-link`
$r = dba::fetch_first("SELECT `id`, `parent`, `author-id`, `body`, `uid`
FROM `item` WHERE `visible` AND NOT `deleted` AND NOT `moderated`
AND NOT `private` AND `uid` = 0
AND `guid` = ? LIMIT 1", $a->argv[1]);
@ -73,8 +72,7 @@ function display_init(App $a)
return;
}
} elseif (($a->argc == 3) && ($nick == 'feed-item')) {
$r = dba::fetch_first("SELECT `id`, `parent`, `author-name`, `author-link`,
`author-avatar`, `network`, `body`, `uid`, `owner-link`
$r = dba::fetch_first("SELECT `id`, `parent`, `author-id`, `body`, `uid`
FROM `item` WHERE `visible` AND NOT `deleted` AND NOT `moderated`
AND NOT `private` AND `uid` = 0
AND `id` = ? LIMIT 1", $a->argv[2]);
@ -87,7 +85,7 @@ function display_init(App $a)
}
if ($r["id"] != $r["parent"]) {
$r = dba::fetch_first("SELECT `id`, `author-name`, `author-link`, `author-avatar`, `network`, `body`, `uid`, `owner-link` FROM `item`
$r = dba::fetch_first("SELECT `id`, `author-id`, `body`, `uid` FROM `item`
WHERE `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
AND `id` = ?", $r["parent"]);
}
@ -117,14 +115,16 @@ function display_init(App $a)
}
function display_fetchauthor($a, $item) {
$author = dba::selectFirst('contact', ['name', 'nick', 'photo', 'network', 'url'], ['id' => $item['author-id']]);
$profiledata = [];
$profiledata["uid"] = -1;
$profiledata["nickname"] = $item["author-name"];
$profiledata["name"] = $item["author-name"];
$profiledata["picdate"] = "";
$profiledata["photo"] = $item["author-avatar"];
$profiledata["url"] = $item["author-link"];
$profiledata["network"] = $item["network"];
$profiledata['uid'] = -1;
$profiledata['nickname'] = $author['nick'];
$profiledata['name'] = $author['name'];
$profiledata['picdate'] = '';
$profiledata['photo'] = $author['photo'];
$profiledata['url'] = $author['url'];
$profiledata['network'] = $author['network'];
// Check for a repeated message
$skip = false;
@ -346,11 +346,10 @@ function display_content(App $a, $update = false, $update_uid = 0) {
return '';
}
$r = dba::p(item_query()."AND `item`.`parent-uri` = (SELECT `parent-uri` FROM `item` WHERE `id` = ?)
AND `item`.`uid` IN (0, ?) $sql_extra
ORDER BY `item`.`uid` ASC, `parent` DESC, `gravity` ASC, `id` ASC",
$item_id, local_user()
);
$condition = ["`item`.`parent-uri` = (SELECT `parent-uri` FROM `item` WHERE `id` = ?)
AND `item`.`uid` IN (0, ?) " . $sql_extra, $item_id, local_user()];
$params = ['order' => ['uid', 'parent' => true, 'gravity', 'id']];
$r = Item::select(local_user(), [], $condition, $params);
if (!DBM::is_result($r)) {
notice(L10n::t('Item not found.') . EOL);
@ -369,7 +368,7 @@ function display_content(App $a, $update = false, $update_uid = 0) {
if (!$update) {
$o .= "<script> var netargs = '?f=&item_id=" . $item_id . "'; </script>";
}
$o .= conversation($a, $items, 'display', $update_uid);
$o .= conversation($a, $items, 'display', $update_uid, false, 'commented', local_user());
// Preparing the meta header
$description = trim(HTML::toPlaintext(BBCode::convert($s[0]["body"], false), 0, true));

View File

@ -433,6 +433,7 @@ function events_content(App $a) {
if (x($_REQUEST, 'location')) {$orig_event['location'] = $_REQUEST['location'];}
if (x($_REQUEST, 'start')) {$orig_event['start'] = $_REQUEST['start'];}
if (x($_REQUEST, 'finish')) {$orig_event['finish'] = $_REQUEST['finish'];}
if (x($_REQUEST,'finish')) $orig_event['finish'] = $_REQUEST['finish'];
$n_checked = ((x($orig_event) && $orig_event['nofinish']) ? ' checked="checked" ' : '');
$a_checked = ((x($orig_event) && $orig_event['adjust']) ? ' checked="checked" ' : '');
@ -545,7 +546,7 @@ function events_content(App $a) {
// Delete only real events (no birthdays)
if (DBM::is_result($ev) && $ev[0]['type'] == 'event') {
$del = Item::deleteById($ev[0]['itemid']);
$del = Item::deleteForUser(['id' => $ev[0]['itemid']], local_user());
}
if ($del == 0) {

View File

@ -72,7 +72,7 @@ function hovercard_content()
'nick' => $contact['nick'],
'addr' => defaults($contact, 'addr', $contact['url']),
'thumb' => proxy_url($contact['thumb'], false, PROXY_SIZE_THUMB),
'url' => $cid ? ('redir/' . $cid) : Profile::zrl($contact['url']),
'url' => Contact::magicLink($contact['url']),
'nurl' => $contact['nurl'], // We additionally store the nurl as identifier
'location' => $contact['location'],
'gender' => $contact['gender'],

View File

@ -877,7 +877,7 @@ function item_content(App $a) {
$o = '';
if (($a->argc == 3) && ($a->argv[1] === 'drop') && intval($a->argv[2])) {
if (is_ajax()) {
$o = Item::deleteById($a->argv[2]);
$o = Item::deleteForUser(['id' => $a->argv[2]], local_user());
} else {
$o = drop_item($a->argv[2]);
}

View File

@ -86,14 +86,14 @@ function match_content(App $a)
$jj->photo = str_replace("http:///photo/", get_server()."/photo/", $jj->photo);
$connlnk = System::baseUrl() . '/follow/?url=' . $jj->url;
$photo_menu = [
'profile' => [L10n::t("View Profile"), Profile::zrl($jj->url)],
'profile' => [L10n::t("View Profile"), Contact::magicLink($jj->url)],
'follow' => [L10n::t("Connect/Follow"), $connlnk]
];
$contact_details = Contact::getDetailsByURL($jj->url, local_user());
$entry = [
'url' => Profile::zrl($jj->url),
'url' => Contact::magicLink($jj->url),
'itemurl' => (($contact_details['addr'] != "") ? $contact_details['addr'] : $jj->url),
'name' => $jj->name,
'details' => $contact_details['location'],

View File

@ -341,11 +341,8 @@ function message_content(App $a)
if ($message['from-url'] == $myprofile) {
$from_url = $myprofile;
$sparkle = '';
} elseif ($message['contact-id'] != 0) {
$from_url = 'redir/' . $message['contact-id'];
$sparkle = ' sparkle';
} else {
$from_url = $message['from-url'] . "?zrl=" . urlencode($myprofile);
$from_url = Contact::magicLink($message['from-url']);
$sparkle = ' sparkle';
}
@ -470,7 +467,7 @@ function render_messages(array $msg, $t)
$rslt .= replace_macros($tpl, [
'$id' => $rr['id'],
'$from_name' => $participants,
'$from_url' => (($rr['network'] === NETWORK_DFRN) ? 'redir/' . $rr['contact-id'] : $rr['url']),
'$from_url' => Contact::magicLink($rr['url']),
'$from_addr' => $contact['addr'],
'$sparkle' => ' sparkle',
'$from_photo' => proxy_url($from_photo, false, PROXY_SIZE_THUMB),

View File

@ -103,7 +103,6 @@ function network_init(App $a)
'/new', //new
'', //starred
'', //bookmarked
'', //spam
];
$tab_args = [
'f=&order=comment', //all
@ -112,7 +111,6 @@ function network_init(App $a)
'', //new
'f=&star=1', //starred
'f=&bmark=1', //bookmarked
'f=&spam=1', //spam
];
$k = array_search('active', $last_sel_tabs);
@ -218,9 +216,8 @@ function saved_searches($search)
* '/network/new', => $new_active = 'active'
* '/network?f=&star=1', => $starred_active = 'active'
* '/network?f=&bmark=1', => $bookmarked_active = 'active'
* '/network?f=&spam=1', => $spam_active = 'active'
*
* @return Array ($no_active, $comment_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active);
* @return Array ($no_active, $comment_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active);
*/
function network_query_get_sel_tab(App $a)
{
@ -230,7 +227,6 @@ function network_query_get_sel_tab(App $a)
$bookmarked_active = '';
$all_active = '';
$conv_active = '';
$spam_active = '';
$postord_active = '';
if (($a->argc > 1 && $a->argv[1] === 'new') || ($a->argc > 2 && $a->argv[2] === 'new')) {
@ -249,11 +245,7 @@ function network_query_get_sel_tab(App $a)
$conv_active = 'active';
}
if (x($_GET, 'spam')) {
$spam_active = 'active';
}
if (($new_active == '') && ($starred_active == '') && ($bookmarked_active == '') && ($conv_active == '') && ($spam_active == '')) {
if (($new_active == '') && ($starred_active == '') && ($bookmarked_active == '') && ($conv_active == '')) {
$no_active = 'active';
}
@ -264,7 +256,7 @@ function network_query_get_sel_tab(App $a)
}
}
return [$no_active, $all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active];
return [$no_active, $all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active];
}
function network_query_get_sel_group(App $a)
@ -345,7 +337,7 @@ function networkConversation($a, $items, $mode, $update, $ordering = '')
// Set this so that the conversation function can find out contact info for our wall-wall items
$a->page_contact = $a->contact;
$o = conversation($a, $items, $mode, $update, false, $ordering);
$o = conversation($a, $items, $mode, $update, false, $ordering, local_user());
if (!$update) {
if (PConfig::get(local_user(), 'system', 'infinite_scroll')) {
@ -456,8 +448,8 @@ function networkFlatView(App $a, $update = 0)
$items = q("SELECT %s FROM `item` $sql_post_table %s
WHERE %s AND `item`.`uid` = %d
ORDER BY `item`.`id` DESC $pager_sql ",
item_fieldlists(), item_joins(), item_condition(),
intval($_SESSION['uid'])
item_fieldlists(), item_joins(local_user()), item_condition(),
intval(local_user())
);
$condition = ['unseen' => true, 'uid' => local_user()];
@ -610,7 +602,7 @@ function networkThreadedView(App $a, $update, $parent)
$sql_tag_nets = (($nets) ? sprintf(" AND `item`.`network` = '%s' ", dbesc($nets)) : '');
if ($gid) {
$group = dba::selectFirst('group', ['name'], ['id' => $gid, 'uid' => $_SESSION['uid']]);
$group = dba::selectFirst('group', ['name'], ['id' => $gid, 'uid' => local_user()]);
if (!DBM::is_result($group)) {
if ($update) {
killme();
@ -626,7 +618,7 @@ function networkThreadedView(App $a, $update, $parent)
$contact_str_self = '';
$contact_str = implode(',', $contacts);
$self = dba::selectFirst('contact', ['id'], ['uid' => $_SESSION['uid'], 'self' => true]);
$self = dba::selectFirst('contact', ['id'], ['uid' => local_user(), 'self' => true]);
if (DBM::is_result($self)) {
$contact_str_self = $self['id'];
}
@ -774,12 +766,15 @@ function networkThreadedView(App $a, $update, $parent)
AND (`item`.`parent-uri` != `item`.`uri`
OR `contact`.`uid` = `item`.`uid` AND `contact`.`self`
OR `contact`.`rel` IN (%d, %d) AND NOT `contact`.`readonly`)
LEFT JOIN `user-item` ON `user-item`.`iid` = `item`.`id` AND `user-item`.`uid` = %d
WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted`
AND (`user-item`.`hidden` IS NULL OR NOT `user-item`.`hidden`)
AND NOT `item`.`moderated` AND $sql_extra4
$sql_extra3 $sql_extra $sql_range $sql_nets
ORDER BY `order_date` DESC LIMIT 100",
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND),
intval(local_user()),
intval(local_user())
);
} else {
@ -791,12 +786,15 @@ function networkThreadedView(App $a, $update, $parent)
AND (`item`.`parent-uri` != `item`.`uri`
OR `contact`.`uid` = `item`.`uid` AND `contact`.`self`
OR `contact`.`rel` IN (%d, %d) AND NOT `contact`.`readonly`)
LEFT JOIN `user-item` ON `user-item`.`iid` = `item`.`id` AND `user-item`.`uid` = %d
WHERE `thread`.`uid` = %d AND `thread`.`visible` AND NOT `thread`.`deleted`
AND NOT `thread`.`moderated`
AND (`user-item`.`hidden` IS NULL OR NOT `user-item`.`hidden`)
$sql_extra2 $sql_extra3 $sql_range $sql_extra $sql_nets
ORDER BY `order_date` DESC $pager_sql",
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND),
intval(local_user()),
intval(local_user())
);
}
@ -922,7 +920,7 @@ function network_tabs(App $a)
// item filter tabs
/// @TODO fix this logic, reduce duplication
/// $a->page['content'] .= '<div class="tabs-wrapper">';
list($no_active, $all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active) = network_query_get_sel_tab($a);
list($no_active, $all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active) = network_query_get_sel_tab($a);
// if no tabs are selected, defaults to comments
if ($no_active == 'active') {
@ -998,7 +996,7 @@ function network_tabs(App $a)
// save selected tab, but only if not in file mode
if (!x($_GET, 'file')) {
PConfig::set(local_user(), 'network.view', 'tab.selected', [
$all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active, $spam_active
$all_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active
]);
}

View File

@ -7,6 +7,7 @@ use Friendica\Content\Nav;
use Friendica\Core\L10n;
use Friendica\Database\DBM;
use Friendica\Model\Profile;
use Friendica\Model\Item;
function notes_init(App $a)
{
@ -26,36 +27,21 @@ function notes_init(App $a)
function notes_content(App $a, $update = false)
{
if (! local_user()) {
if (!local_user()) {
notice(L10n::t('Permission denied.') . EOL);
return;
}
require_once 'include/security.php';
require_once 'include/conversation.php';
$groups = [];
$o = '';
$remote_contact = false;
$contact_id = $_SESSION['cid'];
$contact = $a->contact;
$is_owner = true;
$o ="";
$o .= Profile::getTabs($a, true);
$o = Profile::getTabs($a, true);
if (!$update) {
$o .= '<h3>' . L10n::t('Personal Notes') . '</h3>';
$commpage = false;
$commvisitor = false;
$x = [
'is_owner' => $is_owner,
'is_owner' => true,
'allow_location' => (($a->user['allow_location']) ? true : false),
'default_location' => $a->user['default-location'],
'nickname' => $a->user['nickname'],
@ -71,63 +57,31 @@ function notes_content(App $a, $update = false)
$o .= status_editor($a, $x, $a->contact['id']);
}
// Construct permissions
$condition = ["`uid` = ? AND `type` = 'note' AND `id` = `parent` AND NOT `wall`
AND `allow_cid` = ? AND `contact-id` = ?",
local_user(), '<' . $a->contact['id'] . '>', $a->contact['id']];
// default permissions - anonymous user
$notes = dba::count('item', $condition);
$sql_extra = " AND `item`.`allow_cid` = '<" . $a->contact['id'] . ">' ";
$a->set_pager_total($notes);
$a->set_pager_itemspage(40);
$r = q("SELECT COUNT(*) AS `total`
FROM `item` %s
WHERE %s AND `item`.`uid` = %d AND `item`.`type` = 'note'
AND `contact`.`self` AND `item`.`id` = `item`.`parent` AND NOT `item`.`wall`
$sql_extra ",
item_joins(),
item_condition(),
intval(local_user())
);
$params = ['order' => ['created' => true],
'limit' => [$a->pager['start'], $a->pager['itemspage']]];
$r = Item::select(local_user(), ['item_id'], $condition, $params);
if (DBM::is_result($r)) {
$a->set_pager_total($r[0]['total']);
$a->set_pager_itemspage(40);
}
$parents_arr = [];
$r = q("SELECT `item`.`id` AS `item_id` FROM `item` %s
WHERE %s AND `item`.`uid` = %d AND `item`.`type` = 'note'
AND `item`.`id` = `item`.`parent` AND NOT `item`.`wall`
$sql_extra
ORDER BY `item`.`created` DESC LIMIT %d ,%d ",
item_joins(),
item_condition(),
intval(local_user()),
intval($a->pager['start']),
intval($a->pager['itemspage'])
);
$parents_arr = [];
$parents_str = '';
if (DBM::is_result($r)) {
foreach ($r as $rr) {
while ($rr = dba::fetch($r)) {
$parents_arr[] = $rr['item_id'];
}
$parents_str = implode(', ', $parents_arr);
$r = q("SELECT %s FROM `item` %s
WHERE %s AND `item`.`uid` = %d AND `item`.`parent` IN (%s)
$sql_extra
ORDER BY `parent` DESC, `gravity` ASC, `item`.`id` ASC ",
item_fieldlists(),
item_joins(),
item_condition(),
intval(local_user()),
dbesc($parents_str)
);
if (DBM::is_result($r)) {
$items = conv_sort($r, "`commented`");
dba::close($r);
$condition = ['uid' => local_user(), 'parent' => $parents_arr];
$result = Item::select(local_user(), [], $condition);
if (DBM::is_result($result)) {
$items = conv_sort(dba::inArray($result), 'commented');
$o .= conversation($a, $items, 'notes', $update);
}
}

View File

@ -1,69 +0,0 @@
<?php
/*
This file is part of the Diaspora protocol. It is used for fetching single public posts.
*/
use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Protocol\Diaspora;
function p_init($a){
if ($a->argc != 2) {
header($_SERVER["SERVER_PROTOCOL"].' 510 '.L10n::t('Not Extended'));
killme();
}
$guid = $a->argv[1];
if (strtolower(substr($guid, -4)) != ".xml") {
header($_SERVER["SERVER_PROTOCOL"].' 404 '.L10n::t('Not Found'));
killme();
}
$guid = strtolower(substr($guid, 0, -4));
// Fetch the item
$item = q("SELECT `uid`, `title`, `body`, `guid`, `contact-id`, `private`, `created`, `app`, `location`, `coord`
FROM `item` WHERE `wall` AND NOT `private` AND `guid` = '%s' AND `network` IN ('%s', '%s') AND `id` = `parent` LIMIT 1",
dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA);
if (!$item) {
$r = q("SELECT `author-link`
FROM `item` WHERE `uid` = 0 AND `guid` = '%s' AND `network` IN ('%s', '%s') AND `id` = `parent` LIMIT 1",
dbesc($guid), NETWORK_DFRN, NETWORK_DIASPORA);
if ($r) {
$parts = parse_url($r[0]["author-link"]);
$host = $parts["scheme"]."://".$parts["host"];
if (normalise_link($host) != normalise_link(System::baseUrl())) {
$location = $host."/p/".urlencode($guid).".xml";
header("HTTP/1.1 301 Moved Permanently");
header("Location:".$location);
killme();
}
}
header($_SERVER["SERVER_PROTOCOL"].' 404 '.L10n::t('Not Found'));
killme();
}
// Fetch some data from the author (We could combine both queries - but I think this is more readable)
$r = q("SELECT `user`.`prvkey`, `contact`.`addr`, `user`.`nickname`, `contact`.`nick` FROM `user`
INNER JOIN `contact` ON `contact`.`uid` = `user`.`uid` AND `contact`.`self`
WHERE `user`.`uid` = %d", intval($item[0]["uid"]));
if (!DBM::is_result($r)) {
header($_SERVER["SERVER_PROTOCOL"].' 404 '.L10n::t('Not Found'));
killme();
}
$user = $r[0];
$status = Diaspora::buildStatus($item[0], $user);
$xml = Diaspora::buildPostXml($status["type"], $status["message"]);
header("Content-Type: application/xml; charset=utf-8");
echo $xml;
killme();
}

View File

@ -284,14 +284,7 @@ function photos_post(App $a)
);
// find and delete the corresponding item with all the comments and likes/dislikes
$r = q("SELECT `id` FROM `item` WHERE `resource-id` IN ( $str_res ) AND `uid` = %d",
intval($page_owner_uid)
);
if (DBM::is_result($r)) {
foreach ($r as $rr) {
Item::deleteById($rr['id']);
}
}
Item::deleteForUser(['resource-id' => $res, 'uid' => $page_owner_uid], $page_owner_uid);
// Update the photo albums cache
Photo::clearAlbumCache($page_owner_uid);
@ -344,16 +337,11 @@ function photos_post(App $a)
intval($page_owner_uid),
dbesc($r[0]['resource-id'])
);
$i = q("SELECT `id` FROM `item` WHERE `resource-id` = '%s' AND `uid` = %d LIMIT 1",
dbesc($r[0]['resource-id']),
intval($page_owner_uid)
);
if (DBM::is_result($i)) {
Item::deleteById($i[0]['id']);
// Update the photo albums cache
Photo::clearAlbumCache($page_owner_uid);
}
Item::deleteForUser(['resource-id' => $r[0]['resource-id'], 'uid' => $page_owner_uid], $page_owner_uid);
// Update the photo albums cache
Photo::clearAlbumCache($page_owner_uid);
}
goaway('photos/' . $a->data['user']['nickname']);
@ -1243,9 +1231,11 @@ function photos_content(App $a)
$prevlink = '';
$nextlink = '';
/// @todo This query is totally bad, the whole functionality has to be changed
// The query leads to a really intense used index.
// By now we hide it if someone wants to.
/*
* @todo This query is totally bad, the whole functionality has to be changed
* The query leads to a really intense used index.
* By now we hide it if someone wants to.
*/
if (!Config::get('system', 'no_count', false)) {
$order_field = defaults($_GET, 'order', '');
if ($order_field === 'posted') {
@ -1280,8 +1270,10 @@ function photos_content(App $a)
}
}
if (count($ph) == 1)
if (count($ph) == 1) {
$hires = $lores = $ph[0];
}
if (count($ph) > 1) {
if ($ph[1]['scale'] == 2) {
// original is 640 or less, we can display it directly
@ -1293,6 +1285,7 @@ function photos_content(App $a)
}
$album_link = 'photos/' . $a->data['user']['nickname'] . '/album/' . bin2hex($ph[0]['album']);
$tools = null;
$lock = null;
@ -1319,8 +1312,9 @@ function photos_content(App $a)
]);
}
if ($prevlink)
if ($prevlink) {
$prevlink = [$prevlink, '<div class="icon prev"></div>'] ;
}
$photo = [
'href' => 'photo/' . $hires['resource-id'] . '-' . $hires['scale'] . '.' . $phototypes[$hires['type']],
@ -1544,14 +1538,10 @@ function photos_content(App $a)
continue;
}
$redirect_url = 'redir/' . $item['cid'];
if (local_user() && ($item['contact-uid'] == local_user())
&& ($item['network'] == NETWORK_DFRN) && !$item['self']) {
$profile_url = $redirect_url;
$profile_url = Contact::MagicLinkById($item['cid']);
if (strpos($profile_url, 'redir/') === 0) {
$sparkle = ' sparkle';
} else {
$profile_url = $item['url'];
$sparkle = '';
}
@ -1681,8 +1671,9 @@ function photos_content(App $a)
$twist = false;
foreach ($r as $rr) {
//hide profile photos to others
if (!$is_owner && !remote_user() && ($rr['album'] == L10n::t('Profile Photos')))
if (!$is_owner && !remote_user() && ($rr['album'] == L10n::t('Profile Photos'))) {
continue;
}
$twist = !$twist;

View File

@ -442,7 +442,7 @@ function ping_get_notifications($uid)
do {
$r = q(
"SELECT `notify`.*, `item`.`visible`, `item`.`spam`, `item`.`deleted`
"SELECT `notify`.*, `item`.`visible`, `item`.`deleted`
FROM `notify` LEFT JOIN `item` ON `item`.`id` = `notify`.`iid`
WHERE `notify`.`uid` = %d AND `notify`.`msg` != ''
AND NOT (`notify`.`type` IN (%d, %d))
@ -469,10 +469,6 @@ function ping_get_notifications($uid)
$notification["visible"] = true;
}
if (is_null($notification["spam"])) {
$notification["spam"] = 0;
}
if (is_null($notification["deleted"])) {
$notification["deleted"] = 0;
}
@ -495,7 +491,6 @@ function ping_get_notifications($uid)
$notification["href"] = System::baseUrl() . "/notify/view/" . $notification["id"];
if ($notification["visible"]
&& !$notification["spam"]
&& !$notification["deleted"]
&& !(x($result, $notification["parent"]) && is_array($result[$notification["parent"]]))
) {

View File

@ -43,6 +43,7 @@ function poco_init(App $a) {
echo json_encode($ret);
killme();
}
if ($a->argc > 1 && $a->argv[1] === '@global') {
// List of all profiles that this server recently had data from
$global = true;

View File

@ -337,16 +337,9 @@ function profile_content(App $a, $update = 0)
$parents_arr[] = $rr['item_id'];
}
$parents_str = implode(', ', $parents_arr);
$items = q(item_query() . " AND `item`.`uid` = %d
AND `item`.`parent` IN (%s)
$sql_extra ",
intval($a->profile['profile_uid']),
dbesc($parents_str)
);
$items = conv_sort($items, 'created');
$condition = ['uid' => $a->profile['profile_uid'], 'parent' => $parents_arr];
$result = Item::select($a->profile['profile_uid'], [], $condition);
$items = conv_sort(dba::inArray($result), 'created');
} else {
$items = [];
}
@ -365,7 +358,7 @@ function profile_content(App $a, $update = 0)
}
}
$o .= conversation($a, $items, 'profile', $update);
$o .= conversation($a, $items, 'profile', $update, false, 'commented', local_user());
if (!$update) {
$o .= alt_pager($a, count($items));

View File

@ -4,6 +4,7 @@
*/
use Friendica\App;
use Friendica\Core\System;
use Friendica\Model\Contact;
use Friendica\Model\GContact;
use Friendica\Model\Profile;
@ -12,7 +13,7 @@ function randprof_init(App $a)
$x = GContact::getRandomUrl();
if ($x) {
goaway(Profile::zrl($x));
goaway(Contact::magicLink($x));
}
goaway(System::baseUrl() . '/profile');

View File

@ -1,89 +1,94 @@
<?php
use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
function redir_init(App $a) {
$url = ((x($_GET,'url')) ? $_GET['url'] : '');
$quiet = ((x($_GET,'quiet')) ? '&quiet=1' : '');
$con_url = ((x($_GET,'conurl')) ? $_GET['conurl'] : '');
$url = defaults($_GET, 'url', '');
$quiet = !empty($_GET['quiet']) ? '&quiet=1' : '';
$con_url = defaults($_GET, 'conurl', '');
// traditional DFRN
if (local_user() && ($a->argc > 1) && intval($a->argv[1])) {
$cid = intval($a->argv[1]);
} elseif (local_user() && !empty($con_url)) {
$cid = Contact::getIdForURL($con_url, local_user());
} else {
$cid = 0;
}
if ($con_url || (local_user() && $a->argc > 1 && intval($a->argv[1]))) {
if (!empty($cid)) {
$fields = ['id', 'uid', 'nurl', 'url', 'name', 'network', 'poll', 'issued-id', 'dfrn-id', 'duplex'];
$contact = dba::selectFirst('contact', $fields, ['id' => $cid, 'uid' => [0, local_user()]]);
if (!DBM::is_result($contact)) {
notice(L10n::t('Contact not found.'));
goaway(System::baseUrl());
}
if ($con_url) {
$con_url = str_replace('https', 'http', $con_url);
if ($contact['network'] !== NETWORK_DFRN) {
goaway(($url != '' ? $url : $contact['url']));
}
$r = q("SELECT * FROM `contact` WHERE `nurl` = '%s' AND `uid` = %d LIMIT 1",
dbesc($con_url),
intval(local_user())
);
if ($contact['uid'] == 0) {
$contact_url = $contact['url'];
$contact = dba::selectFirst('contact', $fields, ['nurl' => $contact['nurl'], 'uid' => local_user()]);
if (!DBM::is_result($contact)) {
$target_url = ($url != '' ? $url : $contact_url);
if (!DBM::is_result($r)) {
goaway(System::baseUrl());
}
if ($r[0]['network'] !== NETWORK_DFRN) {
goaway(($url != '' ? $url : $r[0]['url']));
}
$cid = $r[0]['id'];
} else {
$cid = $a->argv[1];
$my_profile = Profile::getMyURL();
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($cid),
intval(local_user())
);
if (!empty($my_profile) && !link_compare($my_profile, $target_url)) {
$separator = strpos($target_url, '?') ? '&' : '?';
if (!DBM::is_result($r)) {
goaway(System::baseUrl());
}
if ($r[0]['network'] !== NETWORK_DFRN) {
goaway(($url != '' ? $url : $r[0]['url']));
$target_url .= $separator . 'zrl=' . urlencode($my_profile);
}
goaway($target_url);
} else {
$cid = $contact['id'];
}
}
$dfrn_id = $orig_id = (($r[0]['issued-id']) ? $r[0]['issued-id'] : $r[0]['dfrn-id']);
$dfrn_id = $orig_id = (($contact['issued-id']) ? $contact['issued-id'] : $contact['dfrn-id']);
if ($r[0]['duplex'] && $r[0]['issued-id']) {
$orig_id = $r[0]['issued-id'];
if ($contact['duplex'] && $contact['issued-id']) {
$orig_id = $contact['issued-id'];
$dfrn_id = '1:' . $orig_id;
}
if ($r[0]['duplex'] && $r[0]['dfrn-id']) {
$orig_id = $r[0]['dfrn-id'];
if ($contact['duplex'] && $contact['dfrn-id']) {
$orig_id = $contact['dfrn-id'];
$dfrn_id = '0:' . $orig_id;
}
$sec = random_string();
q("INSERT INTO `profile_check` ( `uid`, `cid`, `dfrn_id`, `sec`, `expire`)
VALUES( %d, %s, '%s', '%s', %d )",
intval(local_user()),
intval($cid),
dbesc($dfrn_id),
dbesc($sec),
intval(time() + 45)
);
$fields = ['uid' => local_user(), 'cid' => $cid, 'dfrn_id' => $dfrn_id,
'sec' => $sec, 'expire' => time() + 45];
dba::insert('profile_check', $fields);
logger('mod_redir: ' . $r[0]['name'] . ' ' . $sec, LOGGER_DEBUG);
$dest = (($url) ? '&destination_url=' . $url : '');
goaway ($r[0]['poll'] . '?dfrn_id=' . $dfrn_id
logger('mod_redir: ' . $contact['name'] . ' ' . $sec, LOGGER_DEBUG);
$dest = (!empty($url) ? '&destination_url=' . $url : '');
goaway($contact['poll'] . '?dfrn_id=' . $dfrn_id
. '&dfrn_version=' . DFRN_PROTOCOL_VERSION . '&type=profile&sec=' . $sec . $dest . $quiet);
}
if (local_user()) {
$handle = $a->user['nickname'] . '@' . substr(System::baseUrl(),strpos(System::baseUrl(),'://')+3);
$handle = $a->user['nickname'] . '@' . substr(System::baseUrl(), strpos(System::baseUrl(), '://') + 3);
}
if (remote_user()) {
$handle = $_SESSION['handle'];
}
if ($url) {
$url = str_replace('{zid}','&zid=' . $handle,$url);
if (!empty($url)) {
$url = str_replace('{zid}', '&zid=' . $handle, $url);
goaway($url);
}
notice(L10n::t('Contact not found.'));
goaway(System::baseUrl());
}

View File

@ -233,8 +233,8 @@ function register_content(App $a)
$profile_publish = replace_macros($publish_tpl, [
'$instance' => 'reg',
'$pubdesc' => L10n::t('Include your profile in member directory?'),
'$yes_selected' => ' checked="checked" ',
'$no_selected' => '',
'$yes_selected' => '',
'$no_selected' => ' checked="checked"',
'$str_yes' => L10n::t('Yes'),
'$str_no' => L10n::t('No'),
]);

View File

@ -10,6 +10,7 @@ use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Model\Item;
require_once 'include/security.php';
require_once 'include/conversation.php';
@ -197,34 +198,34 @@ function search_content(App $a) {
if ($tag) {
logger("Start tag search for '".$search."'", LOGGER_DEBUG);
$r = q("SELECT %s
FROM `term`
STRAIGHT_JOIN `item` ON `item`.`id`=`term`.`oid` %s
WHERE %s AND (`term`.`uid` = 0 OR (`term`.`uid` = %d AND NOT `term`.`global`))
AND `term`.`otype` = %d AND `term`.`type` = %d AND `term`.`term` = '%s' AND `item`.`verb` = '%s'
AND NOT `author`.`blocked` AND NOT `author`.`hidden`
ORDER BY term.created DESC LIMIT %d , %d ",
item_fieldlists(), item_joins(), item_condition(),
intval(local_user()),
intval(TERM_OBJ_POST), intval(TERM_HASHTAG), dbesc(protect_sprintf($search)), dbesc(ACTIVITY_POST),
intval($a->pager['start']), intval($a->pager['itemspage']));
$condition = ["(`uid` = 0 OR (`uid` = ? AND NOT `global`))
AND `otype` = ? AND `type` = ? AND `term` = ?",
local_user(), TERM_OBJ_POST, TERM_HASHTAG, $search];
$params = ['order' => ['created' => true],
'limit' => [$a->pager['start'], $a->pager['itemspage']]];
$terms = dba::select('term', ['oid'], $condition, $params);
$itemids = [];
while ($term = dba::fetch($terms)) {
$itemids[] = $term['oid'];
}
dba::close($terms);
$items = Item::select(local_user(), [], ['id' => array_reverse($itemids)]);
$r = dba::inArray($items);
} else {
logger("Start fulltext search for '".$search."'", LOGGER_DEBUG);
$sql_extra = sprintf(" AND `item`.`body` REGEXP '%s' ", dbesc(protect_sprintf(preg_quote($search))));
$r = q("SELECT %s
FROM `item` %s
WHERE %s AND (`item`.`uid` = 0 OR (`item`.`uid` = %s AND NOT `item`.`global`))
AND NOT `author`.`blocked` AND NOT `author`.`hidden`
$sql_extra
GROUP BY `item`.`uri`, `item`.`id` ORDER BY `item`.`id` DESC LIMIT %d , %d",
item_fieldlists(), item_joins(), item_condition(),
intval(local_user()),
intval($a->pager['start']), intval($a->pager['itemspage']));
$condition = ["(`uid` = 0 OR (`uid` = ? AND NOT `global`))
AND `body` LIKE CONCAT('%',?,'%')",
local_user(), $search];
$params = ['order' => ['id' => true],
'limit' => [$a->pager['start'], $a->pager['itemspage']]];
$items = Item::select(local_user(), [], $condition, $params);
$r = dba::inArray($items);
}
if (! DBM::is_result($r)) {
if (!DBM::is_result($r)) {
info(L10n::t('No results.') . EOL);
return $o;
}
@ -241,7 +242,7 @@ function search_content(App $a) {
]);
logger("Start Conversation for '".$search."'", LOGGER_DEBUG);
$o .= conversation($a,$r,'search',false);
$o .= conversation($a, $r, 'search', false, false, 'commented', local_user());
$o .= alt_pager($a,count($r));

View File

@ -966,7 +966,7 @@ function settings_content(App $a)
'$noinfo' => ['noinfo', L10n::t("Don't show notices"), $noinfo, ''],
'$infinite_scroll' => ['infinite_scroll', L10n::t("Infinite scroll"), $infinite_scroll, ''],
'$no_auto_update' => ['no_auto_update', L10n::t("Automatic updates only at the top of the network page"), $no_auto_update, L10n::t('When disabled, the network page is updated all the time, which could be confusing while reading.')],
'$bandwidth_saver' => ['bandwidth_saver', L10n::t('Bandwith Saver Mode'), $bandwidth_saver, L10n::t('When enabled, embedded content is not displayed on automatic updates, they only show on page reload.')],
'$bandwidth_saver' => ['bandwidth_saver', L10n::t('Bandwidth Saver Mode'), $bandwidth_saver, L10n::t('When enabled, embedded content is not displayed on automatic updates, they only show on page reload.')],
'$smart_threading' => ['smart_threading', L10n::t('Smart Threading'), $smart_threading, L10n::t('When enabled, suppress extraneous thread indentation while keeping it where it matters. Only works if threading is available and enabled.')],
'$d_tset' => L10n::t('General Theme Settings'),
@ -1091,13 +1091,13 @@ function settings_content(App $a)
$profile_in_dir = '<input type="hidden" name="profile_in_directory" value="1" />';
} else {
$profile_in_dir = replace_macros($opt_tpl, [
'$field' => ['profile_in_directory', L10n::t('Publish your default profile in your local site directory?'), $profile['publish'], L10n::t('Your profile will be published in the global friendica directories (e.g. <a href="%s">%s</a>). Your profile will be visible in public.', Config::get('system', 'directory'), Config::get('system', 'directory')), [L10n::t('No'), L10n::t('Yes')]]
'$field' => ['profile_in_directory', L10n::t('Publish your default profile in your local site directory?'), $profile['publish'], L10n::t('Your profile will be published in this node\'s <a href="%s">local directory</a>. Your profile details may be publicly visible depending on the system settings.', System::baseUrl().'/directory'), [L10n::t('No'), L10n::t('Yes')]]
]);
}
if (strlen(Config::get('system', 'directory'))) {
$profile_in_net_dir = replace_macros($opt_tpl, [
'$field' => ['profile_in_netdirectory', L10n::t('Publish your default profile in the global social directory?'), $profile['net-publish'], L10n::t('Your profile will be published in this node\'s <a href="%s">local directory</a>. Your profile details may be publicly visible depending on the system settings.', System::baseUrl().'/directory'), [L10n::t('No'), L10n::t('Yes')]]
'$field' => ['profile_in_netdirectory', L10n::t('Publish your default profile in the global social directory?'), $profile['net-publish'], L10n::t('Your profile will be published in the global friendica directories (e.g. <a href="%s">%s</a>). Your profile will be visible in public.', Config::get('system', 'directory'), Config::get('system', 'directory')), [L10n::t('No'), L10n::t('Yes')]]
]);
} else {
$profile_in_net_dir = '';
@ -1108,7 +1108,7 @@ function settings_content(App $a)
]);
$hide_wall = replace_macros($opt_tpl, [
'$field' => ['hidewall', L10n::t('Hide your profile details from anonymous viewers?'), $a->user['hidewall'], L10n::t('Anonymous visitors will only see your profile picture, your display name and the nickname you are using on your profile page. Disables posting public messages to Diaspora and other networks.'), [L10n::t('No'), L10n::t('Yes')]],
'$field' => ['hidewall', L10n::t('Hide your profile details from anonymous viewers?'), $a->user['hidewall'], L10n::t('Anonymous visitors will only see your profile picture, your display name and the nickname you are using on your profile page. Your public posts and replies will still be accessible by other means.'), [L10n::t('No'), L10n::t('Yes')]],
]);
$blockwall = replace_macros($opt_tpl, [

View File

@ -5,6 +5,7 @@ use Friendica\Database\DBM;
function share_init(App $a) {
$post_id = (($a->argc > 1) ? intval($a->argv[1]) : 0);
if (!$post_id || !local_user()) {
killme();
}
@ -14,37 +15,44 @@ function share_init(App $a) {
WHERE `item`.`id` = %d LIMIT 1",
intval($post_id)
);
if (!DBM::is_result($r) || ($r[0]['private'] == 1)) {
killme();
}
if (strpos($r[0]['body'], "[/share]") !== false) {
$pos = strpos($r[0]['body'], "[share");
$o = substr($r[0]['body'], $pos);
} else {
$o = share_header($r[0]['author-name'], $r[0]['author-link'], $r[0]['author-avatar'], $r[0]['guid'], $r[0]['created'], $r[0]['plink']);
if ($r[0]['title'])
if ($r[0]['title']) {
$o .= '[b]'.$r[0]['title'].'[/b]'."\n";
}
$o .= $r[0]['body'];
$o.= "[/share]";
$o .= "[/share]";
}
echo $o;
killme();
}
/// @TODO Rewrite to handle over whole record array
function share_header($author, $profile, $avatar, $guid, $posted, $link) {
$header = "[share author='".str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $author).
"' profile='".str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $profile).
"' avatar='".str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $avatar);
$header = "[share author='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $author).
"' profile='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $profile).
"' avatar='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $avatar);
if ($guid) {
$header .= "' guid='".str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $guid);
$header .= "' guid='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $guid);
}
if ($posted) {
$header .= "' posted='".str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $posted);
$header .= "' posted='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $posted);
}
$header .= "' link='".str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $link)."']";
$header .= "' link='" . str_replace(["'", "[", "]"], ["&#x27;", "&#x5B;", "&#x5D;"], $link)."']";
return $header;
}

View File

@ -63,17 +63,19 @@ function subthread_content(App $a) {
WHERE `contact`.`self` = 1 AND `contact`.`uid` = %d LIMIT 1",
intval($owner_uid)
);
if (DBM::is_result($r))
if (DBM::is_result($r)) {
$owner = $r[0];
}
if (! $owner) {
logger('like: no owner');
return;
}
if (! $remote_owner)
if (! $remote_owner) {
$remote_owner = $owner;
}
$contact = null;
// This represents the person posting
@ -85,8 +87,10 @@ function subthread_content(App $a) {
intval($_SESSION['visitor_id']),
intval($owner_uid)
);
if (DBM::is_result($r))
if (DBM::is_result($r)) {
$contact = $r[0];
}
}
if (! $contact) {
return;

View File

@ -79,7 +79,7 @@ function suggest_content(App $a) {
$connlnk = System::baseUrl() . '/follow/?url=' . (($rr['connect']) ? $rr['connect'] : $rr['url']);
$ignlnk = System::baseUrl() . '/suggest?ignore=' . $rr['id'];
$photo_menu = [
'profile' => [L10n::t("View Profile"), Profile::zrl($rr["url"])],
'profile' => [L10n::t("View Profile"), Contact::magicLink($rr["url"])],
'follow' => [L10n::t("Connect/Follow"), $connlnk],
'hide' => [L10n::t('Ignore/Hide'), $ignlnk]
];
@ -87,7 +87,7 @@ function suggest_content(App $a) {
$contact_details = Contact::getDetailsByURL($rr["url"], local_user(), $rr);
$entry = [
'url' => Profile::zrl($rr['url']),
'url' => Contact::magicLink($rr['url']),
'itemurl' => (($contact_details['addr'] != "") ? $contact_details['addr'] : $rr['url']),
'img_hover' => $rr['url'],
'name' => $contact_details['name'],

View File

@ -159,11 +159,13 @@ EOT;
}
$term_objtype = ($item['resource-id'] ? TERM_OBJ_PHOTO : TERM_OBJ_POST);
$t = q("SELECT count(tid) as tcount FROM term WHERE oid=%d AND term='%s'",
intval($item['id']),
dbesc($term)
);
if((! $blocktags) && $t[0]['tcount']==0 ) {
$t = q("SELECT count(tid) as tcount FROM term WHERE oid=%d AND term='%s'",
intval($item['id']),
dbesc($term)
);
if ((!$blocktags) && $t[0]['tcount'] == 0 ) {
q("INSERT INTO term (oid, otype, type, term, url, uid) VALUE (%d, %d, %d, '%s', '%s', %d)",
intval($item['id']),
$term_objtype,
@ -176,26 +178,28 @@ EOT;
// if the original post is on this site, update it.
$r = q("select `tag`,`id`,`uid` from item where `origin` = 1 AND `uri` = '%s' LIMIT 1",
$r = q("SELECT `tag`,`id`,`uid` FROM `item` WHERE `origin`=1 AND `uri`='%s' LIMIT 1",
dbesc($item['uri'])
);
if (DBM::is_result($r)) {
$x = q("SELECT `blocktags` FROM `user` WHERE `uid` = %d limit 1",
$x = q("SELECT `blocktags` FROM `user` WHERE `uid`=%d LIMIT 1",
intval($r[0]['uid'])
);
$t = q("SELECT count(tid) as tcount FROM term WHERE oid=%d AND term='%s'",
$t = q("SELECT COUNT(`tid`) AS `tcount` FROM `term` WHERE `oid`=%d AND `term`='%s'",
intval($r[0]['id']),
dbesc($term)
);
if(count($x) && !$x[0]['blocktags'] && $t[0]['tcount']==0){
q("INSERT INTO term (oid, otype, type, term, url, uid) VALUE (%d, %d, %d, '%s', '%s', %d)",
intval($r[0]['id']),
$term_objtype,
TERM_HASHTAG,
dbesc($term),
dbesc(System::baseUrl() . '/search?tag=' . $term),
intval($owner_uid)
);
if (DBM::is_result($x) && !$x[0]['blocktags'] && $t[0]['tcount'] == 0){
q("INSERT INTO term (`oid`, `otype`, `type`, `term`, `url`, `uid`) VALUE (%d, %d, %d, '%s', '%s', %d)",
intval($r[0]['id']),
$term_objtype,
TERM_HASHTAG,
dbesc($term),
dbesc(System::baseUrl() . '/search?tag=' . $term),
intval($owner_uid)
);
}
}

View File

@ -118,7 +118,7 @@ function unfollow_content(App $a)
'$nickname' => "",
'$name' => $contact["name"],
'$url' => $contact["url"],
'$zrl' => Profile::zrl($contact["url"]),
'$zrl' => Contact::magicLink($contact["url"]),
'$url_label' => L10n::t("Profile URL"),
'$myaddr' => $myaddr,
'$request' => $request,

View File

@ -23,7 +23,7 @@ function update_community_content(App $a) {
$replace = "<img\${1} dst=\"\${2}\"";
$text = preg_replace($pattern, $replace, $text);
if (PConfig::get(local_user(), "system", "bandwith_saver")) {
if (PConfig::get(local_user(), "system", "bandwidth_saver")) {
$replace = "<br />".L10n::t("[Embedded content - reload page to view]")."<br />";
$pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
$text = preg_replace($pattern, $replace, $text);

View File

@ -23,7 +23,7 @@ function update_display_content(App $a)
$replace = "<img\${1} dst=\"\${2}\"";
$text = preg_replace($pattern, $replace, $text);
if (PConfig::get(local_user(), "system", "bandwith_saver")) {
if (PConfig::get(local_user(), "system", "bandwidth_saver")) {
$replace = "<br />" . L10n::t("[Embedded content - reload page to view]") . "<br />";
$pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
$text = preg_replace($pattern, $replace, $text);

View File

@ -29,7 +29,7 @@ function update_network_content(App $a)
$replace = "<img\${1} dst=\"\${2}\"";
$text = preg_replace($pattern, $replace, $text);
if (PConfig::get(local_user(), "system", "bandwith_saver")) {
if (PConfig::get(local_user(), "system", "bandwidth_saver")) {
$replace = "<br />" . L10n::t("[Embedded content - reload page to view]") . "<br />";
$pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
$text = preg_replace($pattern, $replace, $text);

View File

@ -36,7 +36,7 @@ function update_notes_content(App $a) {
$replace = "<img\${1} dst=\"\${2}\"";
$text = preg_replace($pattern, $replace, $text);
if (PConfig::get(local_user(), "system", "bandwith_saver")) {
if (PConfig::get(local_user(), "system", "bandwidth_saver")) {
$replace = "<br />".L10n::t("[Embedded content - reload page to view]")."<br />";
$pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
$text = preg_replace($pattern, $replace, $text);

View File

@ -35,7 +35,7 @@ function update_profile_content(App $a) {
$replace = "<img\${1} dst=\"\${2}\"";
$text = preg_replace($pattern, $replace, $text);
if (PConfig::get(local_user(), "system", "bandwith_saver")) {
if (PConfig::get(local_user(), "system", "bandwidth_saver")) {
$replace = "<br />".L10n::t("[Embedded content - reload page to view]")."<br />";
$pattern = "/<\s*audio[^>]*>(.*?)<\s*\/\s*audio>/i";
$text = preg_replace($pattern, $replace, $text);

View File

@ -169,7 +169,7 @@ function videos_post(App $a) {
);
if (DBM::is_result($i)) {
Item::deleteById($i[0]['id']);
Item::deleteForUser(['id' => $i[0]['id']], local_user());
}
}

View File

@ -96,15 +96,6 @@ function viewcontacts_content(App $a)
continue;
}
$url = $rr['url'];
// route DFRN profiles through the redirect
if ($is_owner && ($rr['network'] === NETWORK_DFRN) && ($rr['rel'])) {
$url = 'redir/' . $rr['id'];
} else {
$url = Profile::zrl($url);
}
$contact_details = Contact::getDetailsByURL($rr['url'], $a->profile['uid'], $rr);
$contacts[] = [
@ -118,7 +109,7 @@ function viewcontacts_content(App $a)
'tags' => $contact_details['keywords'],
'about' => $contact_details['about'],
'account_type' => Contact::getAccountType($contact_details),
'url' => $url,
'url' => Contact::magicLink($rr['url']),
'sparkle' => '',
'itemurl' => (($contact_details['addr'] != "") ? $contact_details['addr'] : $rr['url']),
'network' => ContactSelector::networkToName($rr['network'], $rr['url']),

View File

@ -16,15 +16,15 @@ use Friendica\Database\DBM;
use Friendica\Model\Photo;
use Friendica\Object\Image;
function wall_upload_post(App $a, $desktopmode = true) {
function wall_upload_post(App $a, $desktopmode = true)
{
logger("wall upload: starting new upload", LOGGER_DEBUG);
$r_json = (x($_GET, 'response') && $_GET['response'] == 'json');
$album = (x($_GET, 'album') ? notags(trim($_GET['album'])) : '');
if ($a->argc > 1) {
if (! x($_FILES, 'media')) {
if (!x($_FILES, 'media')) {
$nick = $a->argv[1];
$r = q("SELECT `user`.*, `contact`.`id` FROM `user`
INNER JOIN `contact` on `user`.`uid` = `contact`.`uid`
@ -33,9 +33,9 @@ function wall_upload_post(App $a, $desktopmode = true) {
dbesc($nick)
);
if (! DBM::is_result($r)) {
if (!DBM::is_result($r)) {
if ($r_json) {
echo json_encode(['error'=>L10n::t('Invalid request.')]);
echo json_encode(['error' => L10n::t('Invalid request.')]);
killme();
}
return;
@ -51,7 +51,7 @@ function wall_upload_post(App $a, $desktopmode = true) {
}
} else {
if ($r_json) {
echo json_encode(['error'=>L10n::t('Invalid request.')]);
echo json_encode(['error' => L10n::t('Invalid request.')]);
killme();
}
return;
@ -98,18 +98,18 @@ function wall_upload_post(App $a, $desktopmode = true) {
}
if (! $can_post) {
if (!$can_post) {
if ($r_json) {
echo json_encode(['error'=>L10n::t('Permission denied.')]);
echo json_encode(['error' => L10n::t('Permission denied.')]);
killme();
}
notice(L10n::t('Permission denied.') . EOL);
killme();
}
if (! x($_FILES, 'userfile') && ! x($_FILES, 'media')) {
if (!x($_FILES, 'userfile') && !x($_FILES, 'media')) {
if ($r_json) {
echo json_encode(['error'=>L10n::t('Invalid request.')]);
echo json_encode(['error' => L10n::t('Invalid request.')]);
}
killme();
}
@ -150,9 +150,9 @@ function wall_upload_post(App $a, $desktopmode = true) {
}
}
if ($src=="") {
if ($src == "") {
if ($r_json) {
echo json_encode(['error'=>L10n::t('Invalid request.')]);
echo json_encode(['error' => L10n::t('Invalid request.')]);
killme();
}
notice(L10n::t('Invalid request.').EOL);
@ -185,7 +185,7 @@ function wall_upload_post(App $a, $desktopmode = true) {
if (($maximagesize) && ($filesize > $maximagesize)) {
$msg = L10n::t('Image exceeds size limit of %s', formatBytes($maximagesize));
if ($r_json) {
echo json_encode(['error'=>$msg]);
echo json_encode(['error' => $msg]);
} else {
echo $msg. EOL;
}
@ -196,10 +196,10 @@ function wall_upload_post(App $a, $desktopmode = true) {
$imagedata = @file_get_contents($src);
$Image = new Image($imagedata, $filetype);
if (! $Image->isValid()) {
if (!$Image->isValid()) {
$msg = L10n::t('Unable to process image.');
if ($r_json) {
echo json_encode(['error'=>$msg]);
echo json_encode(['error' => $msg]);
} else {
echo $msg. EOL;
}
@ -211,7 +211,7 @@ function wall_upload_post(App $a, $desktopmode = true) {
@unlink($src);
$max_length = Config::get('system', 'max_image_length');
if (! $max_length) {
if (!$max_length) {
$max_length = MAX_IMAGE_LENGTH;
}
if ($max_length > 0) {
@ -227,7 +227,7 @@ function wall_upload_post(App $a, $desktopmode = true) {
$smallest = 0;
// If we don't have an album name use the Wall Photos album
if (! strlen($album)) {
if (!strlen($album)) {
$album = L10n::t('Wall Photos');
}
@ -235,10 +235,10 @@ function wall_upload_post(App $a, $desktopmode = true) {
$r = Photo::store($Image, $page_owner_uid, $visitor, $hash, $filename, $album, 0, 0, $defperm);
if (! $r) {
if (!$r) {
$msg = L10n::t('Image upload failed.');
if ($r_json) {
echo json_encode(['error'=>$msg]);
echo json_encode(['error' => $msg]);
} else {
echo $msg. EOL;
}
@ -271,7 +271,7 @@ function wall_upload_post(App $a, $desktopmode = true) {
);
if (!$r) {
if ($r_json) {
echo json_encode(['error'=>'']);
echo json_encode(['error' => '']);
killme();
}
return false;
@ -288,28 +288,21 @@ function wall_upload_post(App $a, $desktopmode = true) {
$picture["preview"] = System::baseUrl() . "/photo/{$hash}-{$smallest}." . $Image->getExt();
if ($r_json) {
echo json_encode(['picture'=>$picture]);
echo json_encode(['picture' => $picture]);
killme();
}
logger("upload done", LOGGER_DEBUG);
return $picture;
}
logger("upload done", LOGGER_DEBUG);
if ($r_json) {
echo json_encode(['ok'=>true]);
echo json_encode(['ok' => true]);
killme();
}
/* mod Waitman Gobble NO WARRANTY */
// if we get the signal then return the image url info in BBCODE
if ($_REQUEST['hush']!='yeah') {
echo "\n\n" . '[url=' . System::baseUrl() . '/photos/' . $page_owner_nick . '/image/' . $hash . '][img]' . System::baseUrl() . "/photo/{$hash}-{$smallest}.".$Image->getExt()."[/img][/url]\n\n";
} else {
$m = '[url='.System::baseUrl().'/photos/'.$page_owner_nick.'/image/'.$hash.'][img]'.System::baseUrl()."/photo/{$hash}-{$smallest}.".$Image->getExt()."[/img][/url]";
return($m);
}
/* mod Waitman Gobble NO WARRANTY */
echo "\n\n" . '[url=' . System::baseUrl() . '/photos/' . $page_owner_nick . '/image/' . $hash . '][img]' . System::baseUrl() . "/photo/{$hash}-{$smallest}.".$Image->getExt()."[/img][/url]\n\n";
killme();
// NOTREACHED
}

View File

@ -40,7 +40,9 @@ function worker_init(){
// But since it doesn't destroy anything, we just try to get more execution time in any way.
set_time_limit(0);
if (poller_claim_process($r[0])) {
$fields = ['executed' => DateTimeFormat::utcNow(), 'pid' => getmypid(), 'done' => false];
$condition = ['id' => $r[0]["id"], 'pid' => 0];
if (dba::update('workerqueue', $fields, $condition)) {
Worker::execute($r[0]);
}
}

View File

@ -82,27 +82,22 @@ server {
# rewrite to front controller as default rule
location / {
if ($is_args != "") {
rewrite ^/(.*) /index.php?pagename=$uri&$args last;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?pagename=$1;
}
rewrite ^/(.*) /index.php?pagename=$uri last;
}
# make sure webfinger and other well known services aren't blocked
# by denying dot files and rewrite request to the front controller
location ^~ /.well-known/ {
allow all;
rewrite ^/(.*) /index.php?pagename=$uri&$args last;
}
# statically serve these file types when possible
# otherwise fall back to front controller
# allow browser to cache them
# added .htm for advanced source code editor library
location ~* \.(jpg|jpeg|gif|png|ico|css|js|htm|html|ttf|woff|svg)$ {
expires 30d;
try_files $uri /index.php?pagename=$uri&$args;
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?pagename=$1;
}
}
include mime.types;
# block these file types
location ~* \.(tpl|md|tgz|log|out)$ {

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<phpunit bootstrap="boot.php">
<phpunit bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite>
<directory>tests/</directory>

View File

@ -9,6 +9,8 @@ use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\PConfig;
use Friendica\Core\System;
use Friendica\Database\DBM;
use dba;
use Detection\MobileDetect;
@ -1095,9 +1097,10 @@ class App
return '';
}
if (!$this->current_theme) {
$this->computeCurrentTheme();
}
//// @TODO Compute the current theme only once (this behavior has
/// already been implemented, but it didn't work well -
/// https://github.com/friendica/friendica/issues/5092)
$this->computeCurrentTheme();
return $this->current_theme;
}

View File

@ -9,6 +9,7 @@ use Friendica\App;
use Friendica\Content\Feature;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Model\Contact;
use Friendica\Database\DBM;
use dba;
@ -107,7 +108,7 @@ class ForumManager
$entry = [
'url' => 'network?f=&cid=' . $contact['id'],
'external_url' => 'redir/' . $contact['id'],
'external_url' => Contact::magicLink($contact['url']),
'name' => $contact['name'],
'cid' => $contact['id'],
'selected' => $selected,

View File

@ -74,7 +74,6 @@ class TagCloud
*/
private static function tagadelic($uid, $count = 0, $owner_id = 0, $flags = '', $type = TERM_HASHTAG)
{
$item_condition = item_condition();
$sql_options = item_permissions_sql($uid);
$limit = $count ? sprintf('LIMIT %d', intval($count)) : '';
@ -93,7 +92,8 @@ class TagCloud
LEFT JOIN `item` ON `term`.`oid` = `item`.`id`
WHERE `term`.`uid` = ? AND `term`.`type` = ?
AND `term`.`otype` = ?
AND $item_condition $sql_options
AND `item`.`visible` AND NOT `item`.`deleted` AND NOT `item`.`moderated`
$sql_options
GROUP BY `term` ORDER BY `total` DESC $limit",
$uid,
$type,

View File

@ -40,6 +40,12 @@ class Cache extends \Friendica\BaseObject
self::$driver = new Cache\MemcachedCacheDriver($memcached_hosts);
break;
case 'redis':
$redis_host = Config::get('system', 'redis_host', '127.0.0.1');
$redis_port = Config::get('system', 'redis_port', 6379);
self::$driver = new Cache\RedisCacheDriver($redis_host, $redis_port);
break;
default:
self::$driver = new Cache\DatabaseCacheDriver();
}

View File

@ -0,0 +1,77 @@
<?php
namespace Friendica\Core\Cache;
use Friendica\BaseObject;
use Friendica\Core\Cache;
/**
* Redis Cache Driver. This driver is based on Memcache driver
*
* @author Hypolite Petovan <mrpetovan@gmail.com>
* @author Roland Haeder <roland@mxchange.org>
*/
class RedisCacheDriver extends BaseObject implements ICacheDriver
{
/**
* @var Redis
*/
private $redis;
public function __construct($redis_host, $redis_port)
{
if (!class_exists('Redis', false)) {
throw new \Exception('Redis class isn\'t available');
}
$this->redis = new \Redis();
if (!$this->redis->connect($redis_host, $redis_port)) {
throw new \Exception('Expected Redis server at ' . $redis_host . ':' . $redis_port . ' isn\'t available');
}
}
public function get($key)
{
$return = null;
// We fetch with the hostname as key to avoid problems with other applications
$cached = $this->redis->get(self::getApp()->get_hostname() . ':' . $key);
// @see http://php.net/manual/en/redis.get.php#84275
if (is_bool($cached) || is_double($cached) || is_long($cached)) {
return $return;
}
$value = @unserialize($cached);
// Only return a value if the serialized value is valid.
// We also check if the db entry is a serialized
// boolean 'false' value (which we want to return).
if ($cached === serialize(false) || $value !== false) {
$return = $value;
}
return $return;
}
public function set($key, $value, $duration = Cache::MONTH)
{
// We store with the hostname as key to avoid problems with other applications
return $this->redis->set(
self::getApp()->get_hostname() . ":" . $key,
serialize($value),
time() + $duration
);
}
public function delete($key)
{
return $this->redis->delete($key);
}
public function clear()
{
return true;
}
}

View File

@ -828,7 +828,7 @@ class NotificationsManager extends BaseObject
'contact_id' => $it['contact-id'],
'photo' => ((x($it, 'fphoto')) ? proxy_url($it['fphoto'], false, PROXY_SIZE_SMALL) : "images/person-175.jpg"),
'name' => $it['fname'],
'url' => Profile::zrl($it['furl']),
'url' => Contact::magicLink($it['furl']),
'hidden' => $it['hidden'] == 1,
'post_newfriend' => (intval(PConfig::get(local_user(), 'system', 'post_newfriend')) ? '1' : 0),
'knowyou' => $knowyou,
@ -862,7 +862,7 @@ class NotificationsManager extends BaseObject
'hidden' => $it['hidden'] == 1,
'post_newfriend' => (intval(PConfig::get(local_user(), 'system', 'post_newfriend')) ? '1' : 0),
'url' => $it['url'],
'zrl' => Profile::zrl($it['url']),
'zrl' => Contact::magicLink($it['url']),
'addr' => $it['gaddr'],
'network' => $it['gnetwork'],
'knowyou' => $it['knowyou'],

View File

@ -29,9 +29,7 @@ class PConfig extends BaseObject
public static function init($uid)
{
$a = self::getApp();
if (isset($a->config['system']['config_adapter']) && $a->config['system']['config_adapter'] == 'preload') {
if (Config::get('system', 'config_adapter') == 'preload') {
self::$adapter = new Config\PreloadPConfigAdapter($uid);
} else {
self::$adapter = new Config\JITPConfigAdapter($uid);

View File

@ -53,10 +53,15 @@ class Worker
// We now start the process. This is done after the load check since this could increase the load.
self::startProcess();
// The daemon doesn't need to fork new workers anymore, since we started a process
if (Config::get('system', 'worker_daemon_mode', false)) {
self::IPCSetJobState(false);
}
// Kill stale processes every 5 minutes
$last_cleanup = Config::get('system', 'poller_last_cleaned', 0);
$last_cleanup = Config::get('system', 'worker_last_cleaned', 0);
if (time() > ($last_cleanup + 300)) {
Config::set('system', 'poller_last_cleaned', time());
Config::set('system', 'worker_last_cleaned', time());
self::killStaleWorkers();
}
@ -108,16 +113,16 @@ class Worker
}
// If possible we will fetch new jobs for this worker
if (!$refetched && Lock::set('poller_worker_process', 0)) {
if (!$refetched && Lock::set('worker_process', 0)) {
$stamp = (float)microtime(true);
$refetched = self::findWorkerProcesses($passing_slow);
self::$db_duration += (microtime(true) - $stamp);
Lock::remove('poller_worker_process');
Lock::remove('worker_process');
}
}
// To avoid the quitting of multiple workers only one worker at a time will execute the check
if (Lock::set('poller_worker', 0)) {
if (Lock::set('worker', 0)) {
$stamp = (float)microtime(true);
// Count active workers and compare them with a maximum value that depends on the load
if (self::tooMuchWorkers()) {
@ -130,7 +135,7 @@ class Worker
logger('Memory limit reached, quitting.', LOGGER_DEBUG);
return;
}
Lock::remove('poller_worker');
Lock::remove('worker');
self::$db_duration += (microtime(true) - $stamp);
}
@ -140,6 +145,9 @@ class Worker
return;
}
}
if (Config::get('system', 'worker_daemon_mode', false)) {
self::IPCSetJobState(false);
}
logger("Couldn't select a workerqueue entry, quitting.", LOGGER_DEBUG);
}
@ -244,7 +252,7 @@ class Worker
$stamp = (float)microtime(true);
if (dba::update('workerqueue', ['done' => true], ['id' => $queue["id"]])) {
Config::set('system', 'last_poller_execution', DateTimeFormat::utcNow());
Config::set('system', 'last_worker_execution', DateTimeFormat::utcNow());
}
self::$db_duration = (microtime(true) - $stamp);
@ -285,7 +293,7 @@ class Worker
$stamp = (float)microtime(true);
if (dba::update('workerqueue', ['done' => true], ['id' => $queue["id"]])) {
Config::set('system', 'last_poller_execution', DateTimeFormat::utcNow());
Config::set('system', 'last_worker_execution', DateTimeFormat::utcNow());
}
self::$db_duration = (microtime(true) - $stamp);
} else {
@ -688,7 +696,7 @@ class Worker
logger("Load: ".$load."/".$maxsysload." - processes: ".$active."/".$entries.$processlist." - maximum: ".$queues."/".$maxqueues, LOGGER_DEBUG);
// Are there fewer workers running as possible? Then fork a new one.
if (!Config::get("system", "worker_dont_fork") && ($queues > ($active + 1)) && ($entries > 1)) {
if (!Config::get("system", "worker_dont_fork", false) && ($queues > ($active + 1)) && ($entries > 1)) {
logger("Active workers: ".$active."/".$queues." Fork a new worker.", LOGGER_DEBUG);
self::spawnWorker();
}
@ -851,6 +859,11 @@ class Worker
dba::update('workerqueue', ['executed' => DateTimeFormat::utcNow(), 'pid' => $mypid], $ids);
}
// The daemon doesn't need to fork new workers anymore, since we are inside the worker
if (Config::get('system', 'worker_daemon_mode', false)) {
self::IPCSetJobState(false);
}
return $found;
}
@ -873,7 +886,7 @@ class Worker
dba::close($r);
$stamp = (float)microtime(true);
if (!Lock::set('poller_worker_process')) {
if (!Lock::set('worker_process')) {
return false;
}
self::$lock_duration = (microtime(true) - $stamp);
@ -882,7 +895,7 @@ class Worker
$found = self::findWorkerProcesses($passing_slow);
self::$db_duration += (microtime(true) - $stamp);
Lock::remove('poller_worker_process');
Lock::remove('worker_process');
if ($found) {
$r = dba::select('workerqueue', [], ['pid' => getmypid(), 'done' => false]);
@ -1002,9 +1015,14 @@ class Worker
* @brief Spawns a new worker
* @return void
*/
public static function spawnWorker()
public static function spawnWorker($do_cron = false)
{
$args = ["bin/worker.php", "no_cron"];
$args = ["bin/worker.php"];
if (!$do_cron) {
$args[] = "no_cron";
}
get_app()->proc_run($args);
}
@ -1040,7 +1058,7 @@ class Worker
}
$priority = PRIORITY_MEDIUM;
$dont_fork = Config::get("system", "worker_dont_fork");
$dont_fork = Config::get("system", "worker_dont_fork", false);
$created = DateTimeFormat::utcNow();
$run_parameter = array_shift($args);
@ -1076,14 +1094,20 @@ class Worker
return true;
}
// We tell the daemon that a new job entry exists
if (Config::get('system', 'worker_daemon_mode', false)) {
self::IPCSetJobState(true);
return true;
}
// If there is a lock then we don't have to check for too much worker
if (!Lock::set('poller_worker', 0)) {
if (!Lock::set('worker', 0)) {
return true;
}
// If there are already enough workers running, don't fork another one
$quit = self::tooMuchWorkers();
Lock::remove('poller_worker');
Lock::remove('worker');
if ($quit) {
return true;
@ -1121,4 +1145,33 @@ class Worker
{
return Process::deleteByPid();
}
/**
* Set the flag if some job is waiting
*
* @brief Set the flag if some job is waiting
* @param boolean $jobs Is there a waiting job?
*/
public static function IPCSetJobState($jobs)
{
dba::update('worker-ipc', ['jobs' => $jobs], ['key' => 1], true);
}
/**
* Checks if some worker job waits to be executed
*
* @brief Checks if some worker job waits to be executed
* @return bool
*/
public static function IPCJobsExists()
{
$row = dba::selectFirst('worker-ipc', ['jobs'], ['key' => 1]);
// When we don't have a row, no job is running
if (!DBM::is_result($row)) {
return false;
}
return (bool)$row['jobs'];
}
}

View File

@ -174,7 +174,7 @@ class DBStructure
echo "--\n";
echo "-- TABLE $name\n";
echo "--\n";
self::createTable($name, $structure['fields'], true, false, $structure["indexes"]);
self::createTable($name, $structure, true, false);
echo "\n";
}
@ -251,7 +251,7 @@ class DBStructure
$is_unique = false;
$temp_name = $name;
if (!isset($database[$name])) {
$r = self::createTable($name, $structure["fields"], $verbose, $action, $structure['indexes']);
$r = self::createTable($name, $structure, $verbose, $action);
if (!DBM::is_result($r)) {
$errors .= self::printUpdateError($name);
}
@ -378,6 +378,18 @@ class DBStructure
}
}
if (isset($database[$name]["table_status"]["Engine"]) && isset($structure['engine'])) {
if ($database[$name]["table_status"]["Engine"] != $structure['engine']) {
$sql2 = "ENGINE = '".dbesc($structure['engine'])."'";
if ($sql3 == "") {
$sql3 = "ALTER" . $ignore . " TABLE `".$temp_name."` ".$sql2;
} else {
$sql3 .= ", ".$sql2;
}
}
}
if (isset($database[$name]["table_status"]["Collation"])) {
if ($database[$name]["table_status"]["Collation"] != 'utf8mb4_general_ci') {
$sql2 = "DEFAULT COLLATE utf8mb4_general_ci";
@ -554,20 +566,22 @@ class DBStructure
return($fieldstruct);
}
private static function createTable($name, $fields, $verbose, $action, $indexes=null) {
private static function createTable($name, $structure, $verbose, $action) {
$r = true;
$engine = "";
$comment = "";
$sql_rows = [];
$primary_keys = [];
foreach ($fields AS $fieldname => $field) {
foreach ($structure["fields"] AS $fieldname => $field) {
$sql_rows[] = "`".dbesc($fieldname)."` ".self::FieldCommand($field);
if (x($field,'primary') && $field['primary']!='') {
$primary_keys[] = $fieldname;
}
}
if (!is_null($indexes)) {
foreach ($indexes AS $indexname => $fieldnames) {
if (!is_null($structure["indexes"])) {
foreach ($structure["indexes"] AS $indexname => $fieldnames) {
$sql_index = self::createIndex($indexname, $fieldnames, "");
if (!is_null($sql_index)) {
$sql_rows[] = $sql_index;
@ -575,9 +589,18 @@ class DBStructure
}
}
if (!is_null($structure["engine"])) {
$engine = " ENGINE=" . $structure["engine"];
}
if (!is_null($structure["comment"])) {
$comment = " COMMENT='" . dbesc($structure["comment"]) . "'";
}
$sql = implode(",\n\t", $sql_rows);
$sql = sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n\t", dbesc($name)).$sql."\n) DEFAULT COLLATE utf8mb4_general_ci";
$sql = sprintf("CREATE TABLE IF NOT EXISTS `%s` (\n\t", dbesc($name)).$sql.
"\n)" . $engine . " DEFAULT COLLATE utf8mb4_general_ci" . $comment;
if ($verbose) {
echo $sql.";\n";
}
@ -668,12 +691,12 @@ class DBStructure
"comment" => "registered addons",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"name" => ["type" => "varchar(50)", "not null" => "1", "default" => "", "comment" => ""],
"version" => ["type" => "varchar(50)", "not null" => "1", "default" => "", "comment" => ""],
"installed" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"timestamp" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"plugin_admin" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"name" => ["type" => "varchar(50)", "not null" => "1", "default" => "", "comment" => "addon base (file)name"],
"version" => ["type" => "varchar(50)", "not null" => "1", "default" => "", "comment" => "currently unused"],
"installed" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "currently always 1"],
"hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "currently unused"],
"timestamp" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "file timestamp to check for reloads"],
"plugin_admin" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 = has admin config, 0 = has no admin config"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -683,19 +706,19 @@ class DBStructure
$database["attach"] = [
"comment" => "file attachments",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"hash" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => ""],
"filename" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"filetype" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => ""],
"filesize" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"data" => ["type" => "longblob", "not null" => "1", "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"allow_cid" => ["type" => "mediumtext", "comment" => ""],
"allow_gid" => ["type" => "mediumtext", "comment" => ""],
"deny_cid" => ["type" => "mediumtext", "comment" => ""],
"deny_gid" => ["type" => "mediumtext", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "generated index"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner User id"],
"hash" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => "hash"],
"filename" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "filename of original"],
"filetype" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => "mimetype"],
"filesize" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "size in bytes"],
"data" => ["type" => "longblob", "not null" => "1", "comment" => "file data"],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "creation time"],
"edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "last edit time"],
"allow_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed contact.id '<19><78>"],
"allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed groups"],
"deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"],
"deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied groups"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -730,7 +753,7 @@ class DBStructure
$database["challenge"] = [
"comment" => "",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"challenge" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"dfrn-id" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"expire" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
@ -771,26 +794,26 @@ class DBStructure
$database["contact"] = [
"comment" => "contact table",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner User id"],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"self" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"self" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 if the contact is the user him/her self"],
"remote_self" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"rel" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"rel" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "The kind of the relation between the user and the contact"],
"duplex" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""],
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"nick" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Network protocol of the contact"],
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Name that this contact is known by"],
"nick" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Nick- and user name of the contact"],
"location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"about" => ["type" => "text", "comment" => ""],
"keywords" => ["type" => "text", "comment" => ""],
"keywords" => ["type" => "text", "comment" => "public keywords (interests) of the contact"],
"gender" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
"xmpp" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"attag" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"avatar" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"photo" => ["type" => "varchar(255)", "default" => "", "comment" => ""],
"thumb" => ["type" => "varchar(255)", "default" => "", "comment" => ""],
"micro" => ["type" => "varchar(255)", "default" => "", "comment" => ""],
"photo" => ["type" => "varchar(255)", "default" => "", "comment" => "Link to the profile photo of the contact"],
"thumb" => ["type" => "varchar(255)", "default" => "", "comment" => "Link to the profile photo (thumb size)"],
"micro" => ["type" => "varchar(255)", "default" => "", "comment" => "Link to the profile photo (micro size)"],
"site-pubkey" => ["type" => "text", "comment" => ""],
"issued-id" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"dfrn-id" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
@ -798,8 +821,8 @@ class DBStructure
"nurl" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"addr" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"alias" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"pubkey" => ["type" => "text", "comment" => ""],
"prvkey" => ["type" => "text", "comment" => ""],
"pubkey" => ["type" => "text", "comment" => "RSA public key 4096 bit"],
"prvkey" => ["type" => "text", "comment" => "RSA private key 4096 bit"],
"batch" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"request" => ["type" => "varchar(255)", "comment" => ""],
"notify" => ["type" => "varchar(255)", "comment" => ""],
@ -811,20 +834,20 @@ class DBStructure
"usehub" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"subhub" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"hub-verify" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"last-update" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"success_update" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"failure_update" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"last-update" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "Date of the last try to update the contact info"],
"success_update" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "Date of the last successful contact update"],
"failure_update" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "Date of the last failed update"],
"name-date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"uri-date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"avatar-date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"term-date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"last-item" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"last-item" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "date of the last post"],
"priority" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"blocked" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => ""],
"readonly" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"readonly" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "posts of the contact are readonly"],
"writable" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"forum" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"prv" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"forum" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "contact is a forum"],
"prv" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "contact is a private group"],
"contact-type" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
"hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"archive" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
@ -859,14 +882,14 @@ class DBStructure
$database["conv"] = [
"comment" => "private messages",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"recips" => ["type" => "text", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"creator" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"updated" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"subject" => ["type" => "text", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this conversation"],
"recips" => ["type" => "text", "comment" => "sender_handle;recipient_handle"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner User id"],
"creator" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "handle of creator"],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "creation timestamp"],
"updated" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "edited timestamp"],
"subject" => ["type" => "text", "comment" => "subject of initial message"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -876,13 +899,13 @@ class DBStructure
$database["conversation"] = [
"comment" => "Raw data and structure information for messages",
"fields" => [
"item-uri" => ["type" => "varbinary(255)", "not null" => "1", "primary" => "1", "comment" => ""],
"reply-to-uri" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""],
"conversation-uri" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""],
"conversation-href" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""],
"protocol" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"source" => ["type" => "mediumtext", "comment" => ""],
"received" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"item-uri" => ["type" => "varbinary(255)", "not null" => "1", "primary" => "1", "comment" => "URI of the item"],
"reply-to-uri" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => "URI to which this item is a reply"],
"conversation-uri" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => "GNU Social conversation URI"],
"conversation-href" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => "GNU Social conversation link"],
"protocol" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "The protocol of the item"],
"source" => ["type" => "mediumtext", "comment" => "Original source"],
"received" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "Receiving date"],
],
"indexes" => [
"PRIMARY" => ["item-uri"],
@ -893,26 +916,26 @@ class DBStructure
$database["event"] = [
"comment" => "Events",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner User id"],
"cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "contact_id (ID of the contact in contact table)"],
"uri" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"start" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"finish" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"summary" => ["type" => "text", "comment" => ""],
"desc" => ["type" => "text", "comment" => ""],
"location" => ["type" => "text", "comment" => ""],
"type" => ["type" => "varchar(20)", "not null" => "1", "default" => "", "comment" => ""],
"nofinish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"adjust" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => ""],
"ignore" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"allow_cid" => ["type" => "mediumtext", "comment" => ""],
"allow_gid" => ["type" => "mediumtext", "comment" => ""],
"deny_cid" => ["type" => "mediumtext", "comment" => ""],
"deny_gid" => ["type" => "mediumtext", "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "creation time"],
"edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "last edit time"],
"start" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "event start time"],
"finish" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "event end time"],
"summary" => ["type" => "text", "comment" => "short description or title of the event"],
"desc" => ["type" => "text", "comment" => "event description"],
"location" => ["type" => "text", "comment" => "event location"],
"type" => ["type" => "varchar(20)", "not null" => "1", "default" => "", "comment" => "event or birthday"],
"nofinish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if event does have no end this is 1"],
"adjust" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "adjust to timezone of the recipient (0 or 1)"],
"ignore" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "0 or 1"],
"allow_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed contact.id '<19><78>'"],
"allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed groups"],
"deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"],
"deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied groups"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -922,8 +945,8 @@ class DBStructure
$database["fcontact"] = [
"comment" => "Diaspora compatible contacts - used in the Diaspora implementation",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "unique id"],
"url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
@ -966,9 +989,9 @@ class DBStructure
$database["gcign"] = [
"comment" => "contacts ignored by friend suggestions",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"gcid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["gcontact" => "id"], "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Local User id"],
"gcid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["gcontact" => "id"], "comment" => "gcontact.id of ignored contact"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -979,12 +1002,12 @@ class DBStructure
$database["gcontact"] = [
"comment" => "global contacts",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"nick" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Name that this contact is known by"],
"nick" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Nick- and user name of the contact"],
"url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Link to the contacts profile page"],
"nurl" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Link to the profile photo"],
"connect" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"updated" => ["type" => "datetime", "default" => NULL_DATE, "comment" => ""],
@ -992,19 +1015,19 @@ class DBStructure
"last_failure" => ["type" => "datetime", "default" => NULL_DATE, "comment" => ""],
"location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"about" => ["type" => "text", "comment" => ""],
"keywords" => ["type" => "text", "comment" => ""],
"keywords" => ["type" => "text", "comment" => "puplic keywords (interests)"],
"gender" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
"birthday" => ["type" => "varchar(32)", "not null" => "1", "default" => "0001-01-01", "comment" => ""],
"community" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"community" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 if contact is forum account"],
"contact-type" => ["type" => "tinyint", "not null" => "1", "default" => "-1", "comment" => ""],
"hide" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"nsfw" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""],
"hide" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 = should be hidden from search"],
"nsfw" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 = contact posts nsfw content"],
"network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "social network protocol"],
"addr" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"notify" => ["type" => "varchar(255)", "comment" => ""],
"alias" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"generation" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"server_url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"server_url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "baseurl of the contacts server"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -1019,7 +1042,7 @@ class DBStructure
$database["glink"] = [
"comment" => "'friends of friends' linkages derived from poco",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"gcid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["gcontact" => "id"], "comment" => ""],
@ -1035,11 +1058,11 @@ class DBStructure
$database["group"] = [
"comment" => "privacy groups, group info",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner User id"],
"visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 indicates the member list is not private"],
"deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 indicates the group has been deleted"],
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "human readable name of group"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -1049,9 +1072,9 @@ class DBStructure
$database["group_member"] = [
"comment" => "privacy groups, member info",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"gid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["group" => "id"], "comment" => ""],
"contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"gid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["group" => "id"], "comment" => "groups.id of the associated group"],
"contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "contact.id of the member assigned to the associated group"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -1062,14 +1085,14 @@ class DBStructure
$database["gserver"] = [
"comment" => "Global servers",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"nurl" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"version" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"site_name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"info" => ["type" => "text", "comment" => ""],
"register_policy" => ["type" => "tinyint", "not null" => "1", "default" => "0", "comment" => ""],
"registered-users" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"registered-users" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Number of registered users"],
"poco" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"noscrape" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""],
@ -1100,11 +1123,11 @@ class DBStructure
$database["hook"] = [
"comment" => "addon hook registry",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"hook" => ["type" => "varbinary(100)", "not null" => "1", "default" => "", "comment" => ""],
"file" => ["type" => "varbinary(200)", "not null" => "1", "default" => "", "comment" => ""],
"function" => ["type" => "varbinary(200)", "not null" => "1", "default" => "", "comment" => ""],
"priority" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"hook" => ["type" => "varbinary(100)", "not null" => "1", "default" => "", "comment" => "name of hook"],
"file" => ["type" => "varbinary(200)", "not null" => "1", "default" => "", "comment" => "relative filename of hook handler"],
"function" => ["type" => "varbinary(200)", "not null" => "1", "default" => "", "comment" => "function name of hook handler"],
"priority" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => "not yet implemented - can be used to sort conflicts in hook handling by calling handlers in priority order"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -1114,7 +1137,7 @@ class DBStructure
$database["intro"] = [
"comment" => "",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"fid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["fcontact" => "id"], "comment" => ""],
"contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
@ -1134,68 +1157,67 @@ class DBStructure
"comment" => "All posts",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "relation" => ["thread" => "iid"]],
"guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this item"],
"uri" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner id which owns this copy of the item"],
"contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "contact.id"],
"type" => ["type" => "varchar(20)", "not null" => "1", "default" => "", "comment" => ""],
"wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"wall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "This item was posted to the wall of uid"],
"gravity" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"parent" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["item" => "id"], "comment" => ""],
"parent-uri" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"parent" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["item" => "id"], "comment" => "item.id of the parent to this item if it is a reply of some form; otherwise this must be set to the id of this item"],
"parent-uri" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "uri of the parent to this item"],
"extid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"thr-parent" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"commented" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"received" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"changed" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
"owner-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"owner-link" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"owner-avatar" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
"author-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"author-link" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"author-avatar" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"thr-parent" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "If the parent of this item is not the top-level item in the conversation, the uri of the immediate parent; otherwise set to parent-uri"],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "Creation timestamp."],
"edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "Date of last edit (default is created)"],
"commented" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "Date of last comment/reply to this item"],
"received" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "datetime"],
"changed" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "Date that something in the conversation changed, indicating clients should fetch the conversation again"],
"owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "Link to the contact table with uid=0 of the owner of this item"],
"owner-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Name of the owner of this item"],
"owner-link" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Link to the profile page of the owner of this item"],
"owner-avatar" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Link to the avatar picture of the owner of this item"],
"author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "Link to the contact table with uid=0 of the author of this item"],
"author-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Name of the author of this item"],
"author-link" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Link to the profile page of the author of this item"],
"author-avatar" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Link to the avatar picture of the author of this item"],
"title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "item title"],
"content-warning" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"body" => ["type" => "mediumtext", "comment" => ""],
"app" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"verb" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => ""],
"object-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => ""],
"object" => ["type" => "text", "comment" => ""],
"target-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => ""],
"target" => ["type" => "text", "comment" => ""],
"postopts" => ["type" => "text", "comment" => ""],
"plink" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"resource-id" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
"event-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["event" => "id"], "comment" => ""],
"body" => ["type" => "mediumtext", "comment" => "item body content"],
"app" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "application which generated this item"],
"verb" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams verb"],
"object-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams object type"],
"object" => ["type" => "text", "comment" => "JSON encoded object structure unless it is an implied object (normal post)"],
"target-type" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => "ActivityStreams target type if applicable (URI)"],
"target" => ["type" => "text", "comment" => "JSON encoded target structure if used"],
"postopts" => ["type" => "text", "comment" => "External post connectors add their network name to this comma-separated string to identify that they should be delivered to these networks during delivery"],
"plink" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "permalink or URL to a displayable copy of the message at its source"],
"resource-id" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => "Used to link other tables to items, it identifies the linked resource (e.g. photo) and if set must also set resource_type"],
"event-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["event" => "id"], "comment" => "Used to link to the event.id"],
"tag" => ["type" => "mediumtext", "comment" => ""],
"attach" => ["type" => "mediumtext", "comment" => ""],
"attach" => ["type" => "mediumtext", "comment" => "JSON structure representing attachments to this item"],
"inform" => ["type" => "mediumtext", "comment" => ""],
"file" => ["type" => "mediumtext", "comment" => ""],
"location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"coord" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"allow_cid" => ["type" => "mediumtext", "comment" => ""],
"allow_gid" => ["type" => "mediumtext", "comment" => ""],
"deny_cid" => ["type" => "mediumtext", "comment" => ""],
"deny_gid" => ["type" => "mediumtext", "comment" => ""],
"private" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "text location where this item originated"],
"coord" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "longitude/latitude pair representing location where this item originated"],
"allow_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed contact.id '<19><78>'"],
"allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed groups"],
"deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"],
"deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied groups"],
"private" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "distribution is restricted"],
"pubmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"moderated" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"spam" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"starred" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"bookmark" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"unseen" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => ""],
"deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"origin" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"starred" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item has been favourited"],
"bookmark" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item has been bookmarked"],
"unseen" => ["type" => "boolean", "not null" => "1", "default" => "1", "comment" => "item has not been seen"],
"deleted" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item has been deleted"],
"origin" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "item originated at this site"],
"forum_mode" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"mention" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => ""],
"mention" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "The owner of this item was mentioned in it"],
"network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Network from where the item comes from"],
"rendered-hash" => ["type" => "varchar(32)", "not null" => "1", "default" => "", "comment" => ""],
"rendered-html" => ["type" => "mediumtext", "comment" => ""],
"rendered-html" => ["type" => "mediumtext", "comment" => "item.body converted to html"],
"global" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
],
"indexes" => [
@ -1232,10 +1254,10 @@ class DBStructure
$database["locks"] = [
"comment" => "",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"name" => ["type" => "varchar(128)", "not null" => "1", "default" => "", "comment" => ""],
"locked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"pid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"pid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Process ID"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -1244,23 +1266,23 @@ class DBStructure
$database["mail"] = [
"comment" => "private messages",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"from-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"from-photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"from-url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"contact-id" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "relation" => ["contact" => "id"], "comment" => ""],
"convid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["conv" => "id"], "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner User id"],
"guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this private message"],
"from-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "name of the sender"],
"from-photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "contact photo link of the sender"],
"from-url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "profile linke of the sender"],
"contact-id" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "relation" => ["contact" => "id"], "comment" => "contact.id"],
"convid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["conv" => "id"], "comment" => "conv.id"],
"title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"body" => ["type" => "mediumtext", "comment" => ""],
"seen" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"seen" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if message visited it is 1"],
"reply" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"replied" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"unknown" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"unknown" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if sender not in the contact table this is 1"],
"uri" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"parent-uri" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "creation time of the private message"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -1274,7 +1296,7 @@ class DBStructure
$database["mailacct"] = [
"comment" => "Mail account data for fetching mails",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"server" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"port" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
@ -1295,7 +1317,7 @@ class DBStructure
$database["manage"] = [
"comment" => "table of accounts that can manage each other",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"mid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
],
@ -1307,7 +1329,7 @@ class DBStructure
$database["notify"] = [
"comment" => "notifications",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"hash" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => ""],
"type" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
@ -1315,15 +1337,15 @@ class DBStructure
"photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"msg" => ["type" => "mediumtext", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner User id"],
"link" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"iid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["item" => "id"], "comment" => ""],
"iid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["item" => "id"], "comment" => "item.id"],
"parent" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["item" => "id"], "comment" => ""],
"seen" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"verb" => ["type" => "varchar(100)", "not null" => "1", "default" => "", "comment" => ""],
"otype" => ["type" => "varchar(10)", "not null" => "1", "default" => "", "comment" => ""],
"name_cache" => ["type" => "tinytext", "comment" => ""],
"msg_cache" => ["type" => "mediumtext", "comment" => ""]
"name_cache" => ["type" => "tinytext", "comment" => "Cached bbcode parsing of name"],
"msg_cache" => ["type" => "mediumtext", "comment" => "Cached bbcode parsing of msg"]
],
"indexes" => [
"PRIMARY" => ["id"],
@ -1336,7 +1358,7 @@ class DBStructure
$database["notify-threads"] = [
"comment" => "",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"notify-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["notify" => "id"], "comment" => ""],
"master-parent-item" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["item" => "id"], "comment" => ""],
"parent-item" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
@ -1349,10 +1371,10 @@ class DBStructure
$database["oembed"] = [
"comment" => "cache for OEmbed queries",
"fields" => [
"url" => ["type" => "varbinary(255)", "not null" => "1", "primary" => "1", "comment" => ""],
"maxwidth" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "comment" => ""],
"content" => ["type" => "mediumtext", "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"url" => ["type" => "varbinary(255)", "not null" => "1", "primary" => "1", "comment" => "page url"],
"maxwidth" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "comment" => "Maximum width passed to Oembed"],
"content" => ["type" => "mediumtext", "comment" => "OEmbed data of the page"],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "datetime of creation"],
],
"indexes" => [
"PRIMARY" => ["url", "maxwidth"],
@ -1362,11 +1384,11 @@ class DBStructure
$database["parsed_url"] = [
"comment" => "cache for 'parse_url' queries",
"fields" => [
"url" => ["type" => "varbinary(255)", "not null" => "1", "primary" => "1", "comment" => ""],
"guessing" => ["type" => "boolean", "not null" => "1", "default" => "0", "primary" => "1", "comment" => ""],
"oembed" => ["type" => "boolean", "not null" => "1", "default" => "0", "primary" => "1", "comment" => ""],
"content" => ["type" => "mediumtext", "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"url" => ["type" => "varbinary(255)", "not null" => "1", "primary" => "1", "comment" => "page url"],
"guessing" => ["type" => "boolean", "not null" => "1", "default" => "0", "primary" => "1", "comment" => "is the 'guessing' mode active?"],
"oembed" => ["type" => "boolean", "not null" => "1", "default" => "0", "primary" => "1", "comment" => "is the data the result of oembed?"],
"content" => ["type" => "mediumtext", "comment" => "page data"],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "datetime of creation"],
],
"indexes" => [
"PRIMARY" => ["url", "guessing", "oembed"],
@ -1402,16 +1424,16 @@ class DBStructure
$database["photo"] = [
"comment" => "photo storage",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
"guid" => ["type" => "char(16)", "not null" => "1", "default" => "", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner User id"],
"contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "contact.id"],
"guid" => ["type" => "char(16)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this photo"],
"resource-id" => ["type" => "char(32)", "not null" => "1", "default" => "", "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "creation date"],
"edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "last edited date"],
"title" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"desc" => ["type" => "text", "comment" => ""],
"album" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"album" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "The name of the album to which the photo belongs"],
"filename" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"type" => ["type" => "varchar(30)", "not null" => "1", "default" => "image/jpeg"],
"height" => ["type" => "smallint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
@ -1420,10 +1442,10 @@ class DBStructure
"data" => ["type" => "mediumblob", "not null" => "1", "comment" => ""],
"scale" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"profile" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"allow_cid" => ["type" => "mediumtext", "comment" => ""],
"allow_gid" => ["type" => "mediumtext", "comment" => ""],
"deny_cid" => ["type" => "mediumtext", "comment" => ""],
"deny_gid" => ["type" => "mediumtext", "comment" => ""],
"allow_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed contact.id '<19><78>'"],
"allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed groups"],
"deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"],
"deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied groups"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -1459,7 +1481,7 @@ class DBStructure
$database["poll_result"] = [
"comment" => "data for polls - currently unused",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"poll_id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["poll" => "id"]],
"choice" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
],
@ -1483,14 +1505,14 @@ class DBStructure
$database["profile"] = [
"comment" => "user profiles data",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"profile-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"is-default" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"hide-friends" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "Owner User id"],
"profile-name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Name of the profile"],
"is-default" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Mark this profile as default profile"],
"hide-friends" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Hide friend list from viewers of this profile"],
"name" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"pdesc" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"dob" => ["type" => "varchar(32)", "not null" => "1", "default" => "0000-00-00", "comment" => ""],
"pdesc" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Title or description"],
"dob" => ["type" => "varchar(32)", "not null" => "1", "default" => "0000-00-00", "comment" => "Day of birth"],
"address" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"locality" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"region" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
@ -1523,8 +1545,8 @@ class DBStructure
"xmpp" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"photo" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"thumb" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"publish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"net-publish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"publish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "publish default profile in local directory"],
"net-publish" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "publish profile in global directory"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -1534,9 +1556,9 @@ class DBStructure
$database["profile_check"] = [
"comment" => "DFRN remote auth use",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
"cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "contact.id"],
"dfrn_id" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"sec" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"expire" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
@ -1548,7 +1570,7 @@ class DBStructure
$database["push_subscriber"] = [
"comment" => "Used for OStatus: Contains feed subscribers",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"callback_url" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"topic" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
@ -1567,7 +1589,7 @@ class DBStructure
$database["queue"] = [
"comment" => "Queue for messages that couldn't be delivered",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"cid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "Message receiver"],
"network" => ["type" => "char(4)", "not null" => "1", "default" => "", "comment" => "Receiver's network"],
"guid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Unique GUID of the message"],
@ -1587,7 +1609,7 @@ class DBStructure
$database["register"] = [
"comment" => "registrations requiring admin approval",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"hash" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
@ -1602,7 +1624,7 @@ class DBStructure
$database["search"] = [
"comment" => "",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"term" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
],
@ -1614,7 +1636,7 @@ class DBStructure
$database["session"] = [
"comment" => "web session storage",
"fields" => [
"id" => ["type" => "bigint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "bigint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"sid" => ["type" => "varbinary(255)", "not null" => "1", "default" => "", "comment" => ""],
"data" => ["type" => "text", "comment" => ""],
"expire" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
@ -1628,8 +1650,8 @@ class DBStructure
$database["sign"] = [
"comment" => "Diaspora signatures",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"iid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["item" => "id"], "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"iid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["item" => "id"], "comment" => "item.id"],
"signed_text" => ["type" => "mediumtext", "comment" => ""],
"signature" => ["type" => "text", "comment" => ""],
"signer" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
@ -1666,11 +1688,11 @@ class DBStructure
$database["thread"] = [
"comment" => "Thread related data",
"fields" => [
"iid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "relation" => ["item" => "id"], "comment" => ""],
"iid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "relation" => ["item" => "id"], "comment" => "sequential ID"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "User id"],
"contact-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
"owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
"author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => ""],
"owner-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "Item owner"],
"author-id" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "relation" => ["contact" => "id"], "comment" => "Item author"],
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"edited" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"commented" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
@ -1681,7 +1703,6 @@ class DBStructure
"pubmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"moderated" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"visible" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"spam" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"starred" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"ignored" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"bookmark" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
@ -1724,50 +1745,50 @@ class DBStructure
$database["user"] = [
"comment" => "The local users",
"fields" => [
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"parent-uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "relation" => ["user" => "uid"], "comment" => "The parent user that has full control about this user"],
"guid" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => ""],
"username" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"password" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"guid" => ["type" => "varchar(64)", "not null" => "1", "default" => "", "comment" => "A unique identifier for this user"],
"username" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Name that this user is known by"],
"password" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "encrypted password"],
"legacy_password" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Is the password hash double-hashed?"],
"nickname" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"email" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"nickname" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "nick- and user name"],
"email" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "the users email address"],
"openid" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"timezone" => ["type" => "varchar(128)", "not null" => "1", "default" => "", "comment" => ""],
"language" => ["type" => "varchar(32)", "not null" => "1", "default" => "en", "comment" => ""],
"register_date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"login_date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"default-location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"allow_location" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"theme" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => ""],
"pubkey" => ["type" => "text", "comment" => ""],
"prvkey" => ["type" => "text", "comment" => ""],
"timezone" => ["type" => "varchar(128)", "not null" => "1", "default" => "", "comment" => "PHP-legal timezone"],
"language" => ["type" => "varchar(32)", "not null" => "1", "default" => "en", "comment" => "default language"],
"register_date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "timestamp of registration"],
"login_date" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "timestamp of last login"],
"default-location" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "Default for item.location"],
"allow_location" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 allows to display the location"],
"theme" => ["type" => "varchar(255)", "not null" => "1", "default" => "", "comment" => "user theme preference"],
"pubkey" => ["type" => "text", "comment" => "RSA public key 4096 bit"],
"prvkey" => ["type" => "text", "comment" => "RSA private key 4096 bit"],
"spubkey" => ["type" => "text", "comment" => ""],
"sprvkey" => ["type" => "text", "comment" => ""],
"verified" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"blocked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"blockwall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"hidewall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"blocktags" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"unkmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"verified" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "user is verified through email"],
"blocked" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "1 for user is blocked"],
"blockwall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Prohibit contacts to post to the profile page of the user"],
"hidewall" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Hide profile details from unkown viewers"],
"blocktags" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Prohibit contacts to tag the post of this user"],
"unkmail" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Permit unknown people to send private mails to this user"],
"cntunkmail" => ["type" => "int unsigned", "not null" => "1", "default" => "10", "comment" => ""],
"notify-flags" => ["type" => "smallint unsigned", "not null" => "1", "default" => "65535", "comment" => ""],
"page-flags" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"notify-flags" => ["type" => "smallint unsigned", "not null" => "1", "default" => "65535", "comment" => "email notification options"],
"page-flags" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "page/profile type"],
"account-type" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"prvnets" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"pwdreset" => ["type" => "varchar(255)", "comment" => "Password reset request token"],
"pwdreset_time" => ["type" => "datetime", "comment" => "Timestamp of the last password reset request"],
"maxreq" => ["type" => "int unsigned", "not null" => "1", "default" => "10", "comment" => ""],
"expire" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"account_removed" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"account_removed" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "if 1 the account is removed"],
"account_expired" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => ""],
"account_expires_on" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"expire_notification_sent" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => ""],
"account_expires_on" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "timestamp when account expires and will be deleted"],
"expire_notification_sent" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "timestamp of last warning of account expiration"],
"def_gid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => ""],
"allow_cid" => ["type" => "mediumtext", "comment" => ""],
"allow_gid" => ["type" => "mediumtext", "comment" => ""],
"deny_cid" => ["type" => "mediumtext", "comment" => ""],
"deny_gid" => ["type" => "mediumtext", "comment" => ""],
"allow_cid" => ["type" => "mediumtext", "comment" => "default permission for this user"],
"allow_gid" => ["type" => "mediumtext", "comment" => "default permission for this user"],
"deny_cid" => ["type" => "mediumtext", "comment" => "default permission for this user"],
"deny_gid" => ["type" => "mediumtext", "comment" => "default permission for this user"],
"openidserver" => ["type" => "text", "comment" => ""],
],
"indexes" => [
@ -1778,7 +1799,7 @@ class DBStructure
$database["userd"] = [
"comment" => "Deleted usernames",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => ""],
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "sequential ID"],
"username" => ["type" => "varchar(255)", "not null" => "1", "comment" => ""],
],
"indexes" => [
@ -1786,6 +1807,29 @@ class DBStructure
"username" => ["username(32)"],
]
];
$database["user-item"] = [
"comment" => "User specific item data",
"fields" => [
"iid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "primary" => "1", "relation" => ["item" => "id"], "comment" => "Item id"],
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "default" => "0", "primary" => "1", "relation" => ["user" => "uid"], "comment" => "User id"],
"hidden" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Marker to hide an item from the user"],
],
"indexes" => [
"PRIMARY" => ["uid", "iid"],
]
];
$database["worker-ipc"] = [
"comment" => "Inter process communication between the frontend and the worker",
"fields" => [
"key" => ["type" => "int", "not null" => "1", "primary" => "1", "comment" => ""],
"jobs" => ["type" => "boolean", "comment" => "Flag for outstanding jobs"],
],
"indexes" => [
"PRIMARY" => ["key"],
],
"engine" => "MEMORY",
];
$database["workerqueue"] = [
"comment" => "Background tasks queue entries",
"fields" => [
@ -1795,7 +1839,7 @@ class DBStructure
"created" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "Creation date"],
"pid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Process id of the worker"],
"executed" => ["type" => "datetime", "not null" => "1", "default" => NULL_DATE, "comment" => "Execution date"],
"done" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Marked when the task was done, will be deleted later"],
"done" => ["type" => "boolean", "not null" => "1", "default" => "0", "comment" => "Marked 1 when the task was done - will be deleted later"],
],
"indexes" => [
"PRIMARY" => ["id"],

View File

@ -598,7 +598,7 @@ class Contact extends BaseObject
if ($contact['uid'] != $uid) {
if ($uid == 0) {
$profile_link = Profile::zrl($contact['url']);
$profile_link = self::magicLink($contact['url']);
$menu = ['profile' => [L10n::t('View Profile'), $profile_link, true]];
return $menu;
@ -609,7 +609,7 @@ class Contact extends BaseObject
if (DBM::is_result($contact_own)) {
return self::photoMenu($contact_own, $uid);
} else {
$profile_link = Profile::zrl($contact['url']);
$profile_link = self::magicLink($contact['url']);
$connlnk = 'follow/?url=' . $contact['url'];
$menu = [
'profile' => [L10n::t('View Profile'), $profile_link, true],
@ -944,21 +944,36 @@ class Contact extends BaseObject
'name' => $data['name'],
'nick' => $data['nick']];
// Only fill the pubkey if it was empty before. We have to prevent identity theft.
if (!empty($contact['pubkey'])) {
unset($contact['pubkey']);
} else {
$updated['pubkey'] = $data['pubkey'];
}
if ($data['keywords'] != '') {
$updated['keywords'] = $data['keywords'];
}
if ($data['location'] != '') {
$updated['location'] = $data['location'];
}
if ($data['about'] != '') {
$updated['about'] = $data['about'];
// Update the technical stuff as well - if filled
if ($data['notify'] != '') {
$updated['notify'] = $data['notify'];
}
if ($data['poll'] != '') {
$updated['poll'] = $data['poll'];
}
if ($data['batch'] != '') {
$updated['batch'] = $data['batch'];
}
if ($data['request'] != '') {
$updated['request'] = $data['request'];
}
if ($data['confirm'] != '') {
$updated['confirm'] = $data['confirm'];
}
if ($data['poco'] != '') {
$updated['poco'] = $data['poco'];
}
// Only fill the pubkey if it had been empty before. We have to prevent identity theft.
if (empty($contact['pubkey'])) {
$updated['pubkey'] = $data['pubkey'];
}
if (($data["addr"] != $contact["addr"]) || ($data["alias"] != $contact["alias"])) {
@ -1040,22 +1055,22 @@ class Contact extends BaseObject
}
if (in_array($r[0]["network"], [NETWORK_DFRN, NETWORK_DIASPORA, NETWORK_OSTATUS, ""])) {
$sql = "(`item`.`uid` = 0 OR (`item`.`uid` = %d AND NOT `item`.`global`))";
$sql = "(`item`.`uid` = 0 OR (`item`.`uid` = ? AND NOT `item`.`global`))";
} else {
$sql = "`item`.`uid` = %d";
$sql = "`item`.`uid` = ?";
}
$author_id = intval($r[0]["author-id"]);
$contact = ($r[0]["contact-type"] == ACCOUNT_TYPE_COMMUNITY ? 'owner-id' : 'author-id');
$r = q(item_query() . " AND `item`.`" . $contact . "` = %d AND " . $sql .
" AND `item`.`verb` = '%s' ORDER BY `item`.`created` DESC LIMIT %d, %d",
intval($author_id), intval(local_user()), dbesc(ACTIVITY_POST),
intval($a->pager['start']), intval($a->pager['itemspage'])
);
$condition = ["`$contact` = ? AND `verb` = ? AND " . $sql,
$author_id, ACTIVITY_POST, local_user()];
$params = ['order' => ['created' => true],
'limit' => [$a->pager['start'], $a->pager['itemspage']]];
$r = Item::select(local_user(), [], $condition, $params);
$o = conversation($a, $r, 'contact-posts', false);
$o = conversation($a, dba::inArray($r), 'contact-posts', false);
$o .= alt_pager($a, count($r));
@ -1686,4 +1701,56 @@ class Contact extends BaseObject
$contact_ids = $return;
}
/**
* @brief Returns a magic link to authenticate remote visitors
*
* @param string $contact_url The address of the target contact profile
* @param integer $url An url that we will be redirected to after the authentication
*
* @return string with "redir" link
*/
public static function magicLink($contact_url, $url = '')
{
$cid = self::getIdForURL($contact_url, 0, true);
if (empty($cid)) {
return $url ?: $contact_url; // Equivalent to: ($url != '') ? $url : $contact_url;
}
return self::magicLinkbyId($cid, $url);
}
/**
* @brief Returns a magic link to authenticate remote visitors
*
* @param integer $cid The contact id of the target contact profile
* @param integer $url An url that we will be redirected to after the authentication
*
* @return string with "redir" link
*/
public static function magicLinkbyId($cid, $url = '')
{
$contact = dba::selectFirst('contact', ['network', 'url', 'uid'], ['id' => $cid]);
if ($contact['network'] != NETWORK_DFRN) {
return $url ?: $contact['url']; // Equivalent to ($url != '') ? $url : $contact['url'];
}
// Only redirections to the same host do make sense
if (($url != '') && (parse_url($url, PHP_URL_HOST) != parse_url($contact['url'], PHP_URL_HOST))) {
return $url;
}
if ($contact['uid'] != 0) {
return self::magicLink($contact['url'], $url);
}
$redirect = 'redir/' . $cid;
if ($url != '') {
$redirect .= '?url=' . $url;
}
return $redirect;
}
}

View File

@ -803,10 +803,10 @@ class Event extends BaseObject
/**
* @brief Format an item array with event data to HTML.
*
* @param arr $item Array with item and event data.
* @param array $item Array with item and event data.
* @return string HTML output.
*/
public static function getItemHTML($item) {
public static function getItemHTML(array $item) {
$same_date = false;
$finish = false;
@ -868,12 +868,7 @@ class Event extends BaseObject
$location = self::locationToArray($item['event-location']);
// Construct the profile link (magic-auth).
$sp = false;
$profile_link = best_link_url($item, $sp);
if (!$sp) {
$profile_link = Profile::zrl($profile_link);
}
$profile_link = Contact::magicLinkById($item['author-id']);
$tpl = get_markup_template('event_stream_item.tpl');
$return = replace_macros($tpl, [

View File

@ -33,6 +33,270 @@ require_once 'include/text.php';
class Item extends BaseObject
{
/**
* Retrieve a single record from the item table and returns it in an associative array
*
* @brief Retrieve a single record from a table
* @param integer $uid User ID
* @param array $fields
* @param array $condition
* @param array $params
* @return bool|array
* @see dba::select
*/
public static function selectFirst($uid, array $fields = [], array $condition = [], $params = [])
{
$params['limit'] = 1;
$result = self::select($uid, $fields, $condition, $params);
if (is_bool($result)) {
return $result;
} else {
$row = dba::fetch($result);
dba::close($result);
return $row;
}
}
/**
* @brief Select rows from the item table
*
* @param integer $uid User ID
* @param array $fields Array of selected fields, empty for all
* @param array $condition Array of fields for condition
* @param array $params Array of several parameters
*
* @return boolean|object
*/
public static function select($uid, array $selected = [], array $condition = [], $params = [])
{
$fields = self::fieldlist();
$select_fields = self::constructSelectFields($fields, $selected);
$condition_string = dba::buildCondition($condition);
$condition_string = self::addTablesToFields($condition_string, $fields);
$condition_string = $condition_string . ' AND ' . self::condition(false);
$param_string = self::addTablesToFields(dba::buildParameter($params), $fields);
$table = "`item` " . self::constructJoins($uid, $select_fields . $condition_string . $param_string, false);
$sql = "SELECT " . $select_fields . " FROM " . $table . $condition_string . $param_string;
return dba::p($sql, $condition);
}
/**
* Retrieve a single record from the starting post in the item table and returns it in an associative array
*
* @brief Retrieve a single record from a table
* @param integer $uid User ID
* @param array $fields
* @param array $condition
* @param array $params
* @return bool|array
* @see dba::select
*/
public static function selectFirstThread($uid, array $fields = [], array $condition = [], $params = [])
{
$params['limit'] = 1;
$result = self::selectThread($uid, $fields, $condition, $params);
if (is_bool($result)) {
return $result;
} else {
$row = dba::fetch($result);
dba::close($result);
return $row;
}
}
/**
* @brief Select rows from the starting post in the item table
*
* @param integer $uid User ID
* @param array $fields Array of selected fields, empty for all
* @param array $condition Array of fields for condition
* @param array $params Array of several parameters
*
* @return boolean|object
*/
public static function selectThread($uid, array $selected = [], array $condition = [], $params = [])
{
$fields = self::fieldlist();
$threadfields = ['thread' => ['iid', 'uid', 'contact-id', 'owner-id', 'author-id',
'created', 'edited', 'commented', 'received', 'changed', 'wall', 'private',
'pubmail', 'moderated', 'visible', 'starred', 'ignored', 'bookmark',
'unseen', 'deleted', 'origin', 'forum_mode', 'mention', 'network']];
$select_fields = self::constructSelectFields($fields, $selected);
$condition_string = dba::buildCondition($condition);
$condition_string = self::addTablesToFields($condition_string, $threadfields);
$condition_string = self::addTablesToFields($condition_string, $fields);
$condition_string = $condition_string . ' AND ' . self::condition(true);
$param_string = dba::buildParameter($params);
$param_string = self::addTablesToFields($param_string, $threadfields);
$param_string = self::addTablesToFields($param_string, $fields);
$table = "`thread` " . self::constructJoins($uid, $select_fields . $condition_string . $param_string, true);
$sql = "SELECT " . $select_fields . " FROM " . $table . $condition_string . $param_string;
return dba::p($sql, $condition);
}
/**
* @brief Returns a list of fields that are associated with the item table
*
* @return array field list
*/
private static function fieldlist()
{
$item_fields = ['author-id', 'owner-id', 'contact-id', 'uid', 'id', 'parent',
'uri', 'thr-parent', 'parent-uri', 'content-warning',
'commented', 'created', 'edited', 'received', 'verb', 'object-type', 'postopts', 'plink',
'guid', 'wall', 'private', 'starred', 'origin', 'title', 'body', 'file', 'event-id',
'location', 'coord', 'app', 'attach', 'rendered-hash', 'rendered-html', 'object',
'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid',
'id' => 'item_id', 'network' => 'item_network'];
$author_fields = ['url' => 'author-link', 'name' => 'author-name', 'thumb' => 'author-avatar'];
$owner_fields = ['url' => 'owner-link', 'name' => 'owner-name', 'thumb' => 'owner-avatar'];
$contact_fields = ['url' => 'contact-link', 'name' => 'contact-name', 'thumb' => 'contact-avatar',
'network', 'url', 'name', 'writable', 'self', 'id' => 'cid', 'alias'];
$event_fields = ['created' => 'event-created', 'edited' => 'event-edited',
'start' => 'event-start','finish' => 'event-finish',
'summary' => 'event-summary','desc' => 'event-desc',
'location' => 'event-location', 'type' => 'event-type',
'nofinish' => 'event-nofinish','adjust' => 'event-adjust',
'ignore' => 'event-ignore', 'id' => 'event-id'];
return ['item' => $item_fields, 'author' => $author_fields, 'owner' => $owner_fields,
'contact' => $contact_fields, 'event' => $event_fields];
}
/**
* @brief Returns SQL condition for the "select" functions
*
* @param boolean $thread_mode Called for the items (false) or for the threads (true)
*
* @return string SQL condition
*/
private static function condition($thread_mode)
{
if ($thread_mode) {
$master_table = "`thread`";
} else {
$master_table = "`item`";
}
return "$master_table.`visible` AND NOT $master_table.`deleted` AND NOT $master_table.`moderated` AND (`user-item`.`hidden` IS NULL OR NOT `user-item`.`hidden`) ";
}
/**
* @brief Returns all needed "JOIN" commands for the "select" functions
*
* @param integer $uid User ID
* @param string $sql_commands The parts of the built SQL commands in the "select" functions
* @param boolean $thread_mode Called for the items (false) or for the threads (true)
*
* @return string The SQL joins for the "select" functions
*/
private static function constructJoins($uid, $sql_commands, $thread_mode)
{
if ($thread_mode) {
$master_table = "`thread`";
$master_table_key = "`thread`.`iid`";
$joins = "STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid` ";
} else {
$master_table = "`item`";
$master_table_key = "`item`.`id`";
$joins = '';
}
$joins .= sprintf("STRAIGHT_JOIN `contact` ON `contact`.`id` = $master_table.`contact-id`
AND NOT `contact`.`blocked`
AND ((NOT `contact`.`readonly` AND NOT `contact`.`pending` AND (`contact`.`rel` IN (%s, %s)))
OR `contact`.`self` OR (`item`.`id` != `item`.`parent`) OR `contact`.`uid` = 0)
STRAIGHT_JOIN `contact` AS `author` ON `author`.`id` = $master_table.`author-id` AND NOT `author`.`blocked`
STRAIGHT_JOIN `contact` AS `owner` ON `owner`.`id` = $master_table.`owner-id` AND NOT `owner`.`blocked`
LEFT JOIN `user-item` ON `user-item`.`iid` = $master_table_key AND `user-item`.`uid` = %d",
CONTACT_IS_SHARING, CONTACT_IS_FRIEND, intval($uid));
if (strpos($sql_commands, "`group_member`.") !== false) {
$joins .= " STRAIGHT_JOIN `group_member` ON `group_member`.`contact-id` = $master_table.`contact-id`";
}
if (strpos($sql_commands, "`user`.") !== false) {
$joins .= " STRAIGHT_JOIN `user` ON `user`.`uid` = $master_table.`uid`";
}
if (strpos($sql_commands, "`event`.") !== false) {
$joins .= " LEFT JOIN `event` ON `event-id` = `event`.`id`";
}
return $joins;
}
/**
* @brief Add the field list for the "select" functions
*
* @param array $fields The field definition array
* @param array $selected The array with the selected fields from the "select" functions
*
* @return string The field list
*/
private static function constructSelectFields($fields, $selected)
{
$selection = [];
foreach ($fields as $table => $table_fields) {
foreach ($table_fields as $field => $select) {
if (empty($selected) || in_array($select, $selected)) {
if (is_int($field)) {
$selection[] = "`" . $table . "`.`".$select."`";
} else {
$selection[] = "`" . $table . "`.`" . $field . "` AS `".$select ."`";
}
}
}
}
return implode(", ", $selection);
}
/**
* @brief add table definition to fields in an SQL query
*
* @param string $query SQL query
* @param array $fields The field definition array
*
* @return string the changed SQL query
*/
private static function addTablesToFields($query, $fields)
{
foreach ($fields as $table => $table_fields) {
foreach ($table_fields as $alias => $field) {
if (is_int($alias)) {
$replace_field = $field;
} else {
$replace_field = $alias;
}
$search = "/([^\.])`" . $field . "`/i";
$replace = "$1`" . $table . "`.`" . $replace_field . "`";
$query = preg_replace($search, $replace, $query);
}
}
return $query;
}
/**
* @brief Update existing item entries
*
@ -102,6 +366,32 @@ class Item extends BaseObject
dba::close($items);
}
/**
* @brief Delete an item for an user and notify others about it - if it was ours
*
* @param array $condition The condition for finding the item entries
* @param integer $uid User who wants to delete this item
*/
public static function deleteForUser($condition, $uid)
{
if ($uid == 0) {
return;
}
$items = dba::select('item', ['id', 'uid'], $condition);
while ($item = dba::fetch($items)) {
// "Deleting" global items just means hiding them
if ($item['uid'] == 0) {
dba::update('user-item', ['hidden' => true], ['iid' => $item['id'], 'uid' => $uid], true);
} elseif ($item['uid'] == $uid) {
self::deleteById($item['id'], PRIORITY_HIGH);
} else {
logger('Wrong ownership. Not deleting item ' . $item['id']);
}
}
dba::close($items);
}
/**
* @brief Delete an item and notify others about it - if it was ours
*
@ -110,7 +400,7 @@ class Item extends BaseObject
*
* @return boolean success
*/
public static function deleteById($item_id, $priority = PRIORITY_HIGH)
private static function deleteById($item_id, $priority = PRIORITY_HIGH)
{
// locate item to be deleted
$fields = ['id', 'uri', 'uid', 'parent', 'parent-uri', 'origin',
@ -201,6 +491,13 @@ class Item extends BaseObject
// send the notification upstream/downstream
Worker::add(['priority' => $priority, 'dont_fork' => true], "Notifier", "drop", intval($item['id']));
} elseif ($item['uid'] != 0) {
// When we delete just our local user copy of an item, we have to set a marker to hide it
$global_item = dba::selectFirst('item', ['id'], ['uri' => $item['uri'], 'uid' => 0, 'deleted' => false]);
if (DBM::is_result($global_item)) {
dba::update('user-item', ['hidden' => true], ['iid' => $global_item['id'], 'uid' => $item['uid']], true);
}
}
logger('Item with ID ' . $item_id . " has been deleted.", LOGGER_DEBUG);
@ -533,6 +830,14 @@ class Item extends BaseObject
return 0;
}
//unset($item['author-link']);
//unset($item['author-name']);
//unset($item['author-avatar']);
//unset($item['owner-link']);
unset($item['owner-name']);
unset($item['owner-avatar']);
if ($item['network'] == NETWORK_PHANTOM) {
logger('Missing network. Called by: '.System::callstack(), LOGGER_DEBUG);
@ -1089,8 +1394,9 @@ class Item extends BaseObject
}
// Is this a shadow entry?
if ($item['uid'] == 0)
if ($item['uid'] == 0) {
return;
}
// Is there a shadow parent?
if (!dba::exists('item', ['uri' => $item['parent-uri'], 'uid' => 0])) {
@ -1130,10 +1436,8 @@ class Item extends BaseObject
// If this was a comment to a Diaspora post we don't get our comment back.
// This means that we have to distribute the comment by ourselves.
if ($origin) {
if (dba::exists('item', ['id' => $parent, 'network' => NETWORK_DIASPORA])) {
self::distribute($public_shadow);
}
if ($origin && dba::exists('item', ['id' => $parent, 'network' => NETWORK_DIASPORA])) {
self::distribute($public_shadow);
}
}
@ -1144,14 +1448,14 @@ class Item extends BaseObject
*/
private static function addLanguageInPostopts(&$item)
{
$postopts = "";
if (!empty($item['postopts'])) {
if (strstr($item['postopts'], 'lang=')) {
// do not override
return;
}
$postopts = $item['postopts'];
} else {
$postopts = "";
}
$naked_body = Text\BBCode::toPlaintext($item['body'], false);
@ -1451,8 +1755,7 @@ class Item extends BaseObject
$forum_mode = ($prvgroup ? 2 : 1);
$fields = ['wall' => true, 'origin' => true, 'forum_mode' => $forum_mode, 'contact-id' => $self['id'],
'owner-id' => $owner_id, 'owner-name' => $self['name'], 'owner-link' => $self['url'],
'owner-avatar' => $self['thumb'], 'private' => $private, 'allow_cid' => $user['allow_cid'],
'owner-id' => $owner_id, 'owner-link' => $self['url'], 'private' => $private, 'allow_cid' => $user['allow_cid'],
'allow_gid' => $user['allow_gid'], 'deny_cid' => $user['deny_cid'], 'deny_gid' => $user['deny_gid']];
dba::update('item', $fields, ['id' => $item_id]);
@ -2043,7 +2346,7 @@ EOT;
private static function addThread($itemid, $onlyshadow = false)
{
$fields = ['uid', 'created', 'edited', 'commented', 'received', 'changed', 'wall', 'private', 'pubmail',
'moderated', 'visible', 'spam', 'starred', 'bookmark', 'contact-id',
'moderated', 'visible', 'starred', 'bookmark', 'contact-id',
'deleted', 'origin', 'forum_mode', 'mention', 'network', 'author-id', 'owner-id'];
$condition = ["`id` = ? AND (`parent` = ? OR `parent` = 0)", $itemid, $itemid];
$item = dba::selectFirst('item', $fields, $condition);
@ -2064,7 +2367,7 @@ EOT;
private static function updateThread($itemid, $setmention = false)
{
$fields = ['uid', 'guid', 'title', 'body', 'created', 'edited', 'commented', 'received', 'changed',
'wall', 'private', 'pubmail', 'moderated', 'visible', 'spam', 'starred', 'bookmark', 'contact-id',
'wall', 'private', 'pubmail', 'moderated', 'visible', 'starred', 'bookmark', 'contact-id',
'deleted', 'origin', 'forum_mode', 'network', 'author-id', 'owner-id', 'rendered-html', 'rendered-hash'];
$condition = ["`id` = ? AND (`parent` = ? OR `parent` = 0)", $itemid, $itemid];

View File

@ -90,7 +90,7 @@ class Profile
*/
public static function load(App $a, $nickname, $profile = 0, $profiledata = [], $show_connect = true)
{
$user = dba::selectFirst('user', ['uid'], ['nickname' => $nickname]);
$user = dba::selectFirst('user', ['uid'], ['nickname' => $nickname, 'account_removed' => false]);
if (!DBM::is_result($user) && empty($profiledata)) {
logger('profile error: ' . $a->query_string, LOGGER_DEBUG);
@ -496,7 +496,7 @@ class Profile
$p['photo'] = proxy_url($p['photo'], false, PROXY_SIZE_SMALL);
}
$p['url'] = self::magicLink($p['url']);
$p['url'] = Contact::magicLink($p['url']);
$tpl = get_markup_template('profile_vcard.tpl');
$o .= replace_macros($tpl, [
@ -594,12 +594,8 @@ class Profile
$cids[] = $rr['cid'];
$today = (((strtotime($rr['start'] . ' +00:00') < $now) && (strtotime($rr['finish'] . ' +00:00') > $now)) ? true : false);
$url = $rr['url'];
if ($rr['network'] === NETWORK_DFRN) {
$url = System::baseUrl() . '/redir/' . $rr['cid'];
}
$rr['link'] = $url;
$rr['link'] = Contact::magicLink($rr['url']);
$rr['title'] = $rr['name'];
$rr['date'] = day_translate(DateTimeFormat::convert($rr['start'], $a->timezone, 'UTC', $rr['adjust'] ? $bd_format : $bd_short)) . (($today) ? ' ' . L10n::t('[today]') : '');
$rr['startime'] = null;
@ -1003,29 +999,6 @@ class Profile
}
}
/**
* @brief Returns a magic link to authenticate remote visitors
*
* @param string $contact_url The address of the contact profile
* @param integer $uid The user id, "local_user" is the default
*
* @return string with "redir" link
*/
public static function magicLink($contact_url, $uid = -1)
{
if ($uid == -1) {
$uid = local_user();
}
$condition = ['pending' => false, 'uid' => $uid,
'nurl' => normalise_link($contact_url),
'network' => NETWORK_DFRN, 'self' => false];
$contact = dba::selectFirst('contact', ['id'], $condition);
if (DBM::is_result($contact)) {
return System::baseUrl() . '/redir/' . $contact['id'];
}
return self::zrl($contact_url);
}
public static function zrl($s, $force = false)
{
if (!strlen($s)) {

View File

@ -196,7 +196,7 @@ class Term
$orig_tag = $tag["url"];
$tag["url"] = best_link_url($item, $sp, $tag["url"]);
$tag["url"] = Contact::magicLinkById($item['author-id'], $tag['url']);
if ($tag["type"] == TERM_HASHTAG) {
if ($orig_tag != $tag["url"]) {

View File

@ -331,6 +331,7 @@ class User
$confirm = x($data, 'confirm') ? trim($data['confirm']) : '';
$blocked = x($data, 'blocked') ? intval($data['blocked']) : 0;
$verified = x($data, 'verified') ? intval($data['verified']) : 0;
$language = x($data, 'language') ? notags(trim($data['language'])) : 'en';
$publish = x($data, 'profile_publish_reg') && intval($data['profile_publish_reg']) ? 1 : 0;
$netpublish = strlen(Config::get('system', 'directory')) ? $publish : 0;
@ -466,6 +467,7 @@ class User
'sprvkey' => $sprvkey,
'verified' => $verified,
'blocked' => $blocked,
'language' => $language,
'timezone' => 'UTC',
'register_date' => DateTimeFormat::utcNow(),
'default-location' => ''

View File

@ -13,7 +13,6 @@ use Friendica\Core\L10n;
use Friendica\Core\PConfig;
use Friendica\Database\DBM;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Temporal;
use dba;
@ -71,7 +70,7 @@ class Post extends BaseObject
}
$this->writable = $this->getDataValue('writable') || $this->getDataValue('self');
$this->redirect_url = 'redir/' . $this->getDataValue('cid');
$this->redirect_url = Contact::magicLinkById($this->getDataValue('cid'));
if (!$this->isToplevel()) {
$this->threaded = true;
@ -184,7 +183,7 @@ class Post extends BaseObject
}
// Showing the one or the other text, depending upon if we can only hide it or really delete it.
$delete = $origin ? L10n::t('Delete') : L10n::t('Remove from your stream');
$delete = $origin ? L10n::t('Delete globally') : L10n::t('Remove locally');
$drop = [
'dropping' => $dropping,
@ -199,30 +198,22 @@ class Post extends BaseObject
$filer = (($conv->getProfileOwner() == local_user() && ($item['uid'] != 0)) ? L10n::t("save to folder") : false);
if ($item['network'] == NETWORK_FEED) {
$item['author-avatar'] = $item['contact-avatar'];
$item['author-name'] = $item['contact-name'];
$item['owner-avatar'] = $item['contact-avatar'];
$item['owner-name'] = $item['contact-name'];
}
$diff_author = !link_compare($item['url'], $item['author-link']);
$profile_name = htmlentities(((strlen($item['author-name'])) && $diff_author) ? $item['author-name'] : $item['name']);
if ($item['author-link'] && (!$item['author-name'])) {
$profile_name = $item['author-link'];
}
$sp = false;
$profile_link = best_link_url($item, $sp);
if ($profile_link === 'mailbox') {
$profile_link = '';
}
if ($sp) {
$profile_link = Contact::magicLinkById($item['author-id']);
if (strpos($profile_link, 'redir/') === 0) {
$sparkle = ' sparkle';
} else {
$profile_link = Profile::zrl($profile_link);
}
if (($item['network'] == NETWORK_FEED) || empty($item['author-thumb'])) {
$item['author-thumb'] = $item['author-avatar'];
}
if (($item['network'] == NETWORK_FEED) || empty($item['owner-thumb'])) {
$item['owner-thumb'] = $item['owner-avatar'];
}
$locate = ['location' => $item['location'], 'coord' => $item['coord'], 'html' => ''];
@ -377,7 +368,7 @@ class Post extends BaseObject
'profile_url' => $profile_link,
'item_photo_menu' => item_photo_menu($item),
'name' => $name_e,
'thumb' => $a->remove_baseurl(proxy_url($item['author-thumb'], false, PROXY_SIZE_THUMB)),
'thumb' => $a->remove_baseurl(proxy_url($item['author-avatar'], false, PROXY_SIZE_THUMB)),
'osparkle' => $osparkle,
'sparkle' => $sparkle,
'title' => $title_e,
@ -390,7 +381,7 @@ class Post extends BaseObject
'indent' => $indent,
'shiny' => $shiny,
'owner_url' => $this->getOwnerUrl(),
'owner_photo' => $a->remove_baseurl(proxy_url($item['owner-thumb'], false, PROXY_SIZE_THUMB)),
'owner_photo' => $a->remove_baseurl(proxy_url($item['owner-avatar'], false, PROXY_SIZE_THUMB)),
'owner_name' => htmlentities($owner_name_e),
'plink' => get_plink($item),
'edpost' => Feature::isEnabled($conv->getProfileOwner(), 'edit_posts') ? $edpost : '',
@ -847,7 +838,7 @@ class Post extends BaseObject
// This will have been stored in $a->page_contact by our calling page.
// Put this person as the wall owner of the wall-to-wall notice.
$this->owner_url = Profile::zrl($a->page_contact['url']);
$this->owner_url = Contact::magicLink($a->page_contact['url']);
$this->owner_photo = $a->page_contact['thumb'];
$this->owner_name = $a->page_contact['name'];
$this->wall_to_wall = true;
@ -869,14 +860,7 @@ class Post extends BaseObject
$this->owner_photo = $this->getDataValue('owner-avatar');
$this->owner_name = $this->getDataValue('owner-name');
$this->wall_to_wall = true;
// If it is our contact, use a friendly redirect link
if ($this->getDataValue('network') === NETWORK_DFRN
&& link_compare($this->getDataValue('owner-link'), $this->getDataValue('url'))
) {
$this->owner_url = $this->getRedirectUrl();
} else {
$this->owner_url = Profile::zrl($this->getDataValue('owner-link'));
}
$this->owner_url = Contact::magicLinkById($this->getDataValue('owner-id'));
}
}
}

View File

@ -63,7 +63,7 @@ class DFRN
* @param array $owner Owner record
*
* @return string DFRN entries
* @todo Add type-hints
* @todo Find proper type-hints
*/
public static function entries($items, $owner)
{
@ -81,7 +81,7 @@ class DFRN
$root->appendChild($entry);
}
return(trim($doc->saveXML()));
return trim($doc->saveXML());
}
/**
@ -120,8 +120,6 @@ class DFRN
}
}
// default permissions - anonymous user
$sql_extra = " AND `item`.`allow_cid` = '' AND `item`.`allow_gid` = '' AND `item`.`deny_cid` = '' AND `item`.`deny_gid` = '' ";
@ -134,6 +132,7 @@ class DFRN
);
if (! DBM::is_result($r)) {
logger(sprintf('No contact found for nickname=%d', $owner_nick), LOGGER_WARNING);
killme();
}
@ -169,6 +168,7 @@ class DFRN
);
if (! DBM::is_result($r)) {
logger(sprintf('No contact found for uid=%d', $owner_id), LOGGER_WARNING);
killme();
}
@ -177,8 +177,10 @@ class DFRN
$groups = Group::getIdsByContactId($contact['id']);
if (count($groups)) {
for ($x = 0; $x < count($groups); $x ++)
for ($x = 0; $x < count($groups); $x ++) {
$groups[$x] = '<' . intval($groups[$x]) . '>' ;
}
$gs = implode('|', $groups);
} else {
$gs = '<<>>' ; // Impossible to match
@ -219,10 +221,8 @@ class DFRN
//$sql_extra .= file_tag_file_query('item',$category,'category');
}
if ($public_feed) {
if (! $converse) {
$sql_extra .= " AND `contact`.`self` = 1 ";
}
if ($public_feed && ! $converse) {
$sql_extra .= " AND `contact`.`self` = 1 ";
}
$check_date = DateTimeFormat::utc($last_update);
@ -397,7 +397,7 @@ class DFRN
* @param array $owner Owner record
*
* @return string DFRN mail
* @todo Add type-hints
* @todo Find proper type-hints
*/
public static function mail($item, $owner)
{
@ -423,7 +423,7 @@ class DFRN
$root->appendChild($mail);
return(trim($doc->saveXML()));
return trim($doc->saveXML());
}
/**
@ -433,7 +433,7 @@ class DFRN
* @param array $owner Owner record
*
* @return string DFRN suggestions
* @todo Add type-hints
* @todo Find proper type-hints
*/
public static function fsuggest($item, $owner)
{
@ -452,7 +452,7 @@ class DFRN
$root->appendChild($suggest);
return(trim($doc->saveXML()));
return trim($doc->saveXML());
}
/**
@ -462,7 +462,7 @@ class DFRN
* @param int $uid User ID
*
* @return string DFRN relocations
* @todo Add type-hints
* @todo Find proper type-hints
*/
public static function relocate($owner, $uid)
{
@ -487,7 +487,6 @@ class DFRN
$photos[$p['scale']] = System::baseUrl().'/photo/'.$p['resource-id'].'-'.$p['scale'].'.'.$ext[$p['type']];
}
unset($rp, $ext);
$doc = new DOMDocument('1.0', 'utf-8');
$doc->formatOutput = true;
@ -511,7 +510,7 @@ class DFRN
$root->appendChild($relocate);
return(trim($doc->saveXML()));
return trim($doc->saveXML());
}
/**
@ -524,7 +523,7 @@ class DFRN
* @param bool $public Is it a header for public posts?
*
* @return object XML root object
* @todo Add type-hints
* @todo Find proper type-hints
*/
private static function addHeader($doc, $owner, $authorelement, $alternatelink = "", $public = false)
{
@ -600,7 +599,7 @@ class DFRN
* @param boolean $public boolean
*
* @return object XML author object
* @todo Add type-hints
* @todo Find proper type-hints
*/
private static function addAuthor($doc, $owner, $authorelement, $public)
{
@ -744,7 +743,7 @@ class DFRN
* @param array $item Item elements
*
* @return object XML author object
* @todo Add type-hints
* @todo Find proper type-hints
*/
private static function addEntryAuthor($doc, $element, $contact_url, $item)
{
@ -785,7 +784,7 @@ class DFRN
* @param string $activity activity value
*
* @return object XML activity object
* @todo Add type-hints
* @todo Find proper type-hints
*/
private static function createActivity($doc, $element, $activity)
{
@ -796,12 +795,15 @@ class DFRN
if (!$r) {
return false;
}
if ($r->type) {
XML::addElement($doc, $entry, "activity:object-type", $r->type);
}
if ($r->id) {
XML::addElement($doc, $entry, "id", $r->id);
}
if ($r->title) {
XML::addElement($doc, $entry, "title", $r->title);
}
@ -848,7 +850,7 @@ class DFRN
* @param array $item Item element
*
* @return object XML attachment object
* @todo Add type-hints
* @todo Find proper type-hints
*/
private static function getAttachment($doc, $root, $item)
{
@ -888,9 +890,9 @@ class DFRN
* @param bool $single If set, the entry is created as an XML document with a single "entry" element
*
* @return object XML entry object
* @todo Add type-hints
* @todo Find proper type-hints
*/
private static function entry($doc, $type, $item, $owner, $comment = false, $cid = 0, $single = false)
private static function entry($doc, $type, array $item, array $owner, $comment = false, $cid = 0, $single = false)
{
$mentioned = [];
@ -934,7 +936,7 @@ class DFRN
$htmlbody = $body;
if ($item['title'] != "") {
$htmlbody = "[b]".$item['title']."[/b]\n\n".$htmlbody;
$htmlbody = "[b]" . $item['title'] . "[/b]\n\n" . $htmlbody;
}
$htmlbody = BBCode::convert($htmlbody, false, 7);
@ -1061,6 +1063,7 @@ class DFRN
$tags = Item::getFeedTags($item);
/// @TODO Combine this with similar below if() block?
if (count($tags)) {
foreach ($tags as $t) {
if (($type != 'html') || ($t[0] != "@")) {
@ -1289,7 +1292,6 @@ class DFRN
$postvars['dissolve'] = '1';
}
if ((($contact['rel']) && ($contact['rel'] != CONTACT_IS_SHARING) && (! $contact['blocked'])) || ($owner['page-flags'] == PAGE_COMMUNITY)) {
$postvars['data'] = $atom;
$postvars['perm'] = 'rw';
@ -1571,12 +1573,12 @@ class DFRN
// Until now we aren't serving different sizes - but maybe later
$avatarlist = [];
/// @todo check if "avatar" or "photo" would be the best field in the specification
$avatars = $xpath->query($element."/atom:link[@rel='avatar']", $context);
$avatars = $xpath->query($element . "/atom:link[@rel='avatar']", $context);
foreach ($avatars as $avatar) {
$href = "";
$width = 0;
foreach ($avatar->attributes as $attributes) {
/// @TODO Rewrite these similar if () to one switch
/// @TODO Rewrite these similar if() to one switch
if ($attributes->name == "href") {
$href = $attributes->textContent;
}
@ -1591,6 +1593,7 @@ class DFRN
$avatarlist[$width] = $href;
}
}
if (count($avatarlist) > 0) {
krsort($avatarlist);
$author["avatar"] = current($avatarlist);
@ -2093,6 +2096,9 @@ class DFRN
$condition = ["(`id` = ?) OR (`nurl` = ?)", $importer["id"], normalise_link($old["url"])];
dba::update('contact', $fields, $condition);
// @TODO No dba:update here?
dba::update('contact', $fields, $condition);
Contact::updateAvatar($relocate["avatar"], $importer["importer_uid"], $importer["id"], true);
logger('Contacts are updated.');
@ -2699,7 +2705,7 @@ class DFRN
if (self::updateContent($current, $item, $importer, $entrytype)) {
logger("Item ".$item["uri"]." was updated.", LOGGER_DEBUG);
} else {
logger("Item ".$item["uri"]." already existed.", LOGGER_DEBUG);
logger("Item " . $item["uri"] . " already existed.", LOGGER_DEBUG);
}
return;
}
@ -2775,6 +2781,7 @@ class DFRN
{
logger("Processing deletions");
$uri = null;
foreach ($deletion->attributes as $attributes) {
if ($attributes->name == "ref") {
$uri = $attributes->textContent;
@ -2807,15 +2814,13 @@ class DFRN
}
}
$entrytype = self::getEntryType($importer, $item);
if (!$item["deleted"]) {
logger('deleting item '.$item["id"].' uri='.$uri, LOGGER_DEBUG);
} else {
if ($item["deleted"]) {
return;
}
Item::deleteById($item["id"]);
logger('deleting item '.$item['id'].' uri='.$uri, LOGGER_DEBUG);
Item::delete(['id' => $item['id']]);
}
/**

View File

@ -2785,7 +2785,7 @@ class Diaspora
while ($item = dba::fetch($r)) {
// Fetch the parent item
$parent = dba::selectFirst('item', ['author-link', 'origin'], ['id' => $item["parent"]]);
$parent = dba::selectFirst('item', ['author-link'], ['id' => $item["parent"]]);
// Only delete it if the parent author really fits
if (!link_compare($parent["author-link"], $contact["url"]) && !link_compare($item["author-link"], $contact["url"])) {
@ -2793,7 +2793,7 @@ class Diaspora
continue;
}
Item::deleteById($item["id"]);
Item::delete(['id' => $item['id']]);
logger("Deleted target ".$target_guid." (".$item["id"].") from user ".$item["uid"]." parent: ".$item["parent"], LOGGER_DEBUG);
}

View File

@ -537,13 +537,12 @@ class OStatus
private static function deleteNotice($item)
{
$condition = ['uid' => $item['uid'], 'author-link' => $item['author-link'], 'uri' => $item['uri']];
$deleted = dba::selectFirst('item', ['id', 'parent-uri'], $condition);
if (!DBM::is_result($deleted)) {
logger('Item from '.$item['author-link'].' with uri '.$item['uri'].' for user '.$item['uid']." wasn't found. We don't delete it. ");
if (!dba::exists('item', $condition)) {
logger('Item from '.$item['author-link'].' with uri '.$item['uri'].' for user '.$item['uid']." wasn't found. We don't delete it.");
return;
}
Item::deleteById($deleted["id"]);
Item::delete($condition);
logger('Deleted item with uri '.$item['uri'].' for user '.$item['uid']);
}
@ -1948,7 +1947,7 @@ class OStatus
* @param bool $complete default true
* @return void
*/
private static function entryFooter($doc, $entry, $item, $owner, $complete = true)
private static function entryFooter($doc, $entry, array $item, array $owner, $complete = true)
{
$mentioned = [];
@ -1988,6 +1987,7 @@ class OStatus
if (isset($parent_item)) {
$r = dba::fetch_first("SELECT `conversation-uri`, `conversation-href` FROM `conversation` WHERE `item-uri` = ?", $parent_item);
if (DBM::is_result($r)) {
if ($r['conversation-uri'] != '') {
$conversation_uri = $r['conversation-uri'];
@ -2048,9 +2048,11 @@ class OStatus
}
if ($owner['account-type'] == ACCOUNT_TYPE_COMMUNITY) {
XML::addElement($doc, $entry, "link", "", ["rel" => "mentioned",
"ostatus:object-type" => "http://activitystrea.ms/schema/1.0/group",
"href" => $owner['url']]);
XML::addElement($doc, $entry, "link", "", [
"rel" => "mentioned",
"ostatus:object-type" => "http://activitystrea.ms/schema/1.0/group",
"href" => $owner['url']
]);
}
if (!$item["private"]) {

View File

@ -1321,20 +1321,8 @@ class PortableContact
$version = $data->version;
$site_name = $data->site_name;
$info = $data->info;
$register_policy_str = $data->register_policy;
$register_policy = constant($data->register_policy);
$platform = $data->platform;
switch ($register_policy_str) {
case "REGISTER_CLOSED":
$register_policy = REGISTER_CLOSED;
break;
case "REGISTER_APPROVE":
$register_policy = REGISTER_APPROVE;
break;
case "REGISTER_OPEN":
$register_policy = REGISTER_OPEN;
break;
}
}
}
}

View File

@ -102,7 +102,9 @@ Class Cron {
dba::delete('workerqueue', ['`done` AND `executed` < UTC_TIMESTAMP() - INTERVAL 1 HOUR']);
// Optimizing this table only last seconds
dba::e("OPTIMIZE TABLE `workerqueue`");
if (Config::get('system', 'optimize_workerqueue', false)) {
dba::e("OPTIMIZE TABLE `workerqueue`");
}
Config::set('system', 'last_cron_hourly', time());
}

View File

@ -164,10 +164,11 @@ class Notifier {
if (!in_array($cmd, [Delivery::MAIL, Delivery::SUGGESTION, Delivery::RELOCATION])) {
$parent = $items[0];
$thr_parent = q("SELECT `network`, `author-link`, `owner-link` FROM `item` WHERE `uri` = '%s' AND `uid` = %d",
dbesc($target_item["thr-parent"]), intval($target_item["uid"]));
$fields = ['network', 'author-id', 'owner-id'];
$condition = ['uri' => $target_item["thr-parent"], 'uid' => $target_item["uid"]];
$thr_parent = dba::selectFirst('item', $fields, $condition);
logger('GUID: '.$target_item["guid"].': Parent is '.$parent['network'].'. Thread parent is '.$thr_parent[0]['network'], LOGGER_DEBUG);
logger('GUID: '.$target_item["guid"].': Parent is '.$parent['network'].'. Thread parent is '.$thr_parent['network'], LOGGER_DEBUG);
// This is IMPORTANT!!!!
@ -213,7 +214,7 @@ class Notifier {
}
// Special treatment for forum posts
if (($target_item['author-link'] != $target_item['owner-link']) &&
if (($target_item['author-id'] != $target_item['owner-id']) &&
($owner['id'] != $target_item['contact-id']) &&
($target_item['uri'] === $target_item['parent-uri'])) {
@ -247,7 +248,7 @@ class Notifier {
$target_item['deny_cid'].$target_item['deny_gid']) == 0))
$push_notify = true;
if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) {
if (($thr_parent && ($thr_parent['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) {
$push_notify = true;
if ($parent["network"] == NETWORK_OSTATUS) {
@ -333,37 +334,21 @@ class Notifier {
// If the thread parent is OStatus then do some magic to distribute the messages.
// We have not only to look at the parent, since it could be a Friendica thread.
if (($thr_parent && ($thr_parent[0]['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) {
if (($thr_parent && ($thr_parent['network'] == NETWORK_OSTATUS)) || ($parent['network'] == NETWORK_OSTATUS)) {
$diaspora_delivery = false;
logger('Some parent is OStatus for '.$target_item["guid"]." - Author: ".$thr_parent[0]['author-link']." - Owner: ".$thr_parent[0]['owner-link'], LOGGER_DEBUG);
logger('Some parent is OStatus for '.$target_item["guid"]." - Author: ".$thr_parent['author-id']." - Owner: ".$thr_parent['owner-id'], LOGGER_DEBUG);
// Send a salmon to the parent author
$r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''",
dbesc(normalise_link($thr_parent[0]['author-link'])),
intval($uid));
if (DBM::is_result($r)) {
$probed_contact = $r[0];
} else {
$probed_contact = Probe::uri($thr_parent[0]['author-link']);
}
if ($probed_contact["notify"] != "") {
$probed_contact = dba::selectFirst('contact', ['url', 'notify'], ['id' => $thr_parent['author-id']]);
if (DBM::is_result($probed_contact) && !empty($probed_contact["notify"])) {
logger('Notify parent author '.$probed_contact["url"].': '.$probed_contact["notify"]);
$url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
}
// Send a salmon to the parent owner
$r = q("SELECT `url`, `notify` FROM `contact` WHERE `nurl`='%s' AND `uid` IN (0, %d) AND `notify` != ''",
dbesc(normalise_link($thr_parent[0]['owner-link'])),
intval($uid));
if (DBM::is_result($r)) {
$probed_contact = $r[0];
} else {
$probed_contact = Probe::uri($thr_parent[0]['owner-link']);
}
if ($probed_contact["notify"] != "") {
$probed_contact = dba::selectFirst('contact', ['url', 'notify'], ['id' => $thr_parent['owner-id']]);
if (DBM::is_result($probed_contact) && !empty($probed_contact["notify"])) {
logger('Notify parent owner '.$probed_contact["url"].': '.$probed_contact["notify"]);
$url_recipients[$probed_contact["notify"]] = $probed_contact["notify"];
}

3669
tests/ApiTest.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,14 +7,12 @@ namespace Friendica\Test;
use Friendica\App;
use Friendica\BaseObject;
// backward compatibility
if (!class_exists('\PHPUnit\Framework\TestCase')) {
class_alias('\PHPUnit_Framework_TestCase', '\PHPUnit\Framework\TestCase');
}
use PHPUnit\Framework\TestCase;
/**
* Tests for the BaseObject class.
*/
class BaseObjectTest extends \PHPUnit\Framework\TestCase
class BaseObjectTest extends TestCase
{
/**

63
tests/DatabaseTest.php Normal file
View File

@ -0,0 +1,63 @@
<?php
/**
* DatabaseTest class.
*/
namespace Friendica\Test;
use dba;
use Friendica\Database\DBStructure;
use PHPUnit_Extensions_Database_DB_IDatabaseConnection;
use PHPUnit\DbUnit\DataSet\YamlDataSet;
use PHPUnit\DbUnit\TestCaseTrait;
use PHPUnit\Framework\TestCase;
/**
* Abstract class used by tests that need a database.
*/
abstract class DatabaseTest extends TestCase
{
use TestCaseTrait;
/**
* Get database connection.
*
* This function is executed before each test in order to get a database connection that can be used by tests.
* If no prior connection is available, it tries to create one using the USER, PASS and DB environment variables.
*
* If it could not connect to the database, the test is skipped.
*
* @return PHPUnit_Extensions_Database_DB_IDatabaseConnection
* @see https://phpunit.de/manual/5.7/en/database.html
*/
protected function getConnection()
{
if (!dba::$connected) {
dba::connect('localhost', getenv('USER'), getenv('PASS'), getenv('DB'));
if (dba::$connected) {
$app = get_app();
// We need to do this in order to disable logging
$app->module = 'install';
// Create database structure
DBStructure::update(false, true, true);
} else {
$this->markTestSkipped('Could not connect to the database.');
}
}
return $this->createDefaultDBConnection(dba::get_db(), getenv('DB'));
}
/**
* Get dataset to populate the database with.
* @return YamlDataSet
* @see https://phpunit.de/manual/5.7/en/database.html
*/
protected function getDataSet()
{
return new YamlDataSet(__DIR__ . '/datasets/api.yml');
}
}

View File

@ -5,15 +5,12 @@
namespace Friendica\Test;
// backward compatibility
if (!class_exists('\PHPUnit\Framework\TestCase')) {
class_alias('\PHPUnit_Framework_TestCase', '\PHPUnit\Framework\TestCase');
}
use PHPUnit\Framework\TestCase;
/**
* Tests for text functions.
*/
class TextTest extends \PHPUnit\Framework\TestCase
class TextTest extends TestCase
{
/**

22
tests/bootstrap.php Normal file
View File

@ -0,0 +1,22 @@
<?php
/**
* This file is loaded by PHPUnit before any test.
*/
use PHPUnit\DbUnit\DataSet\YamlDataSet;
use PHPUnit\DbUnit\TestCaseTrait;
use PHPUnit\Framework\TestCase;
require_once __DIR__.'/../boot.php';
require_once __DIR__.'/../include/api.php';
// Backward compatibility
if (!class_exists(TestCase::class)) {
class_alias(PHPUnit_Framework_TestCase::class, TestCase::class);
}
if (!trait_exists(TestCaseTrait::class)) {
class_alias(PHPUnit_Extensions_Database_TestCase_Trait::class, TestCaseTrait::class);
}
if (!class_exists(YamlDataSet::class)) {
class_alias(PHPUnit_Extensions_Database_DataSet_YamlDataSet::class, YamlDataSet::class);
}

204
tests/datasets/api.yml Normal file
View File

@ -0,0 +1,204 @@
---
# Empty these tables
cache:
config:
conversation:
pconfig:
photo:
workerqueue:
mail:
# Populate tables with test data
user:
-
uid: 42
username: Test user
nickname: selfcontact
verified: true
password: $2y$10$DLRNTRmJgKe1cSrFJ5Jb0edCqvXlA9sh/RHdSnfxjbR.04yZRm4Qm
theme: frio
contact:
-
id: 42
uid: 42
name: Self contact
nick: selfcontact
self: true
nurl: http://localhost/profile/selfcontact
url: http://localhost/profile/selfcontact
about: User used in tests
pending: false
blocked: false
rel: 1
network: dfrn
-
id: 43
uid: 0
# Having the same name and nick allows us to test
# the fallback to api_get_nick() in api_get_user()
name: othercontact
nick: othercontact
self: false
nurl: http://localhost/profile/othercontact
url: http://localhost/profile/othercontact
pending: false
blocked: false
rel: 0
network: dfrn
-
id: 44
uid: 0
name: Friend contact
nick: friendcontact
self: false
nurl: http://localhost/profile/friendcontact
url: http://localhost/profile/friendcontact
pending: false
blocked: false
rel: 2
network: dfrn
item:
-
id: 1
visible: true
contact-id: 42
author-id: 42
owner-id: 45
uid: 42
verb: http://activitystrea.ms/schema/1.0/post
unseen: true
body: Parent status
parent: 1
author-link: http://localhost/profile/selfcontact
wall: true
starred: true
origin: true
allow_cid: ''
allow_gid: ''
deny_cid: ''
deny_gid: ''
-
id: 2
visible: true
contact-id: 42
author-id: 42
owner-id: 45
uid: 42
verb: http://activitystrea.ms/schema/1.0/post
unseen: false
body: Reply
parent: 1
author-link: http://localhost/profile/selfcontact
wall: true
starred: false
origin: true
-
id: 3
visible: true
contact-id: 43
author-id: 43
owner-id: 42
uid: 42
verb: http://activitystrea.ms/schema/1.0/post
unseen: false
body: Other user status
parent: 3
author-link: http://localhost/profile/othercontact
wall: true
starred: false
origin: true
-
id: 4
visible: true
contact-id: 44
author-id: 44
owner-id: 42
uid: 42
verb: http://activitystrea.ms/schema/1.0/post
unseen: false
body: Friend user reply
parent: 1
author-link: http://localhost/profile/othercontact
wall: true
starred: false
origin: true
-
id: 5
visible: true
contact-id: 42
author-id: 42
owner-id: 42
uid: 42
verb: http://activitystrea.ms/schema/1.0/post
unseen: false
body: '[share]Shared status[/share]'
parent: 1
author-link: http://localhost/profile/othercontact
wall: true
starred: false
origin: true
allow_cid: ''
allow_gid: ''
deny_cid: ''
deny_gid: ''
-
id: 6
visible: true
contact-id: 44
author-id: 44
owner-id: 42
uid: 42
verb: http://activitystrea.ms/schema/1.0/post
unseen: false
body: Friend user status
parent: 6
author-link: http://localhost/profile/othercontact
wall: true
starred: false
origin: true
thread:
-
iid: 1
visible: true
contact-id: 42
author-id: 42
owner-id: 42
uid: 42
wall: true
-
iid: 3
visible: true
contact-id: 43
author-id: 43
owner-id: 43
uid: 0
wall: true
-
iid: 6
visible: true
contact-id: 44
author-id: 44
owner-id: 44
uid: 0
wall: true
group:
-
id: 1
uid: 42
visible: true
name: Visible list
-
id: 2
uid: 42
visible: false
name: Private list
search:
-
id: 1
term: Saved search
uid: 42

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -65,11 +65,6 @@ $a->strings["You've received a registration request from '%1\$s' at %2\$s"] = "D
$a->strings["You've received a [url=%1\$s]registration request[/url] from %2\$s."] = "Du hast eine [url=%1\$s]Registrierungsanfrage[/url] von %2\$s erhalten.";
$a->strings["Full Name:\t%1\$s\\nSite Location:\t%2\$s\\nLogin Name:\t%3\$s (%4\$s)"] = "Kompletter Name:\t%1\$s\\nURL der Seite:\t%2\$s\\nLogin Name:\t%3\$s (%4\$s)";
$a->strings["Please visit %s to approve or reject the request."] = "Bitte besuche %s um die Anfrage zu bearbeiten.";
$a->strings["Welcome "] = "Willkommen ";
$a->strings["Please upload a profile photo."] = "Bitte lade ein Profilbild hoch.";
$a->strings["Welcome back "] = "Willkommen zurück ";
$a->strings["The form security token was not correct. This probably happened because the form has been opened for too long (>3 hours) before submitting it."] = "Das Sicherheitsmerkmal war nicht korrekt. Das passiert meistens wenn das Formular vor dem Absenden zu lange geöffnet war (länger als 3 Stunden).";
$a->strings["Cannot locate DNS info for database server '%s'"] = "Kann die DNS Informationen für den Datenbankserver '%s' nicht ermitteln.";
$a->strings["Daily posting limit of %d post reached. The post was rejected."] = [
0 => "Das tägliche Limit von %d Beitrag wurde erreicht. Die Nachricht wurde verworfen.",
1 => "Das tägliche Limit von %d Beiträgen wurde erreicht. Der Beitrag wurde verworfen.",
@ -196,6 +191,10 @@ $a->strings["Yes"] = "Ja";
$a->strings["Permission denied."] = "Zugriff verweigert.";
$a->strings["Archives"] = "Archiv";
$a->strings["show more"] = "mehr anzeigen";
$a->strings["Welcome "] = "Willkommen ";
$a->strings["Please upload a profile photo."] = "Bitte lade ein Profilbild hoch.";
$a->strings["Welcome back "] = "Willkommen zurück ";
$a->strings["The form security token was not correct. This probably happened because the form has been opened for too long (>3 hours) before submitting it."] = "Das Sicherheitsmerkmal war nicht korrekt. Das passiert meistens wenn das Formular vor dem Absenden zu lange geöffnet war (länger als 3 Stunden).";
$a->strings["newer"] = "neuer";
$a->strings["older"] = "älter";
$a->strings["first"] = "erste";
@ -352,7 +351,6 @@ $a->strings["Do you really want to delete this suggestion?"] = "Möchtest Du wir
$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["Ignore/Hide"] = "Ignorieren/Verbergen";
$a->strings["Friend Suggestions"] = "Kontaktvorschläge";
$a->strings["[Embedded content - reload page to view]"] = "[Eingebetteter Inhalt - Seite neu laden zum Betrachten]";
$a->strings["This site has exceeded the number of allowed daily account registrations. Please try again tomorrow."] = "Die maximale Anzahl täglicher Registrierungen auf dieser Seite wurde überschritten. Bitte versuche es morgen noch einmal.";
$a->strings["Import"] = "Import";
$a->strings["Move account"] = "Account umziehen";
@ -403,15 +401,6 @@ $a->strings["All Contacts (with secure profile access)"] = "Alle Kontakte (mit g
$a->strings["Account approved."] = "Konto freigegeben.";
$a->strings["Registration revoked for %s"] = "Registrierung für %s wurde zurückgezogen";
$a->strings["Please login."] = "Bitte melde Dich an.";
$a->strings["Remove term"] = "Begriff entfernen";
$a->strings["Saved Searches"] = "Gespeicherte Suchen";
$a->strings["Only logged in users are permitted to perform a search."] = "Nur eingeloggten Benutzern ist das Suchen gestattet.";
$a->strings["Too Many Requests"] = "Zu viele Abfragen";
$a->strings["Only one search per minute is permitted for not logged in users."] = "Es ist nur eine Suchanfrage pro Minute für nicht eingeloggte Benutzer gestattet.";
$a->strings["No results."] = "Keine Ergebnisse.";
$a->strings["Items tagged with: %s"] = "Beiträge die mit %s getaggt sind";
$a->strings["Results for: %s"] = "Ergebnisse für: %s";
$a->strings["%1\$s is following %2\$s's %3\$s"] = "%1\$s folgt %2\$s %3\$s";
$a->strings["Tag removed"] = "Tag entfernt";
$a->strings["Remove Item Tag"] = "Gegenstands-Tag entfernen";
$a->strings["Select a tag to remove: "] = "Wähle ein Tag zum Entfernen aus: ";
@ -449,63 +438,6 @@ $a->strings["Contact not found."] = "Kontakt nicht gefunden.";
$a->strings["Friend suggestion sent."] = "Kontaktvorschlag gesendet.";
$a->strings["Suggest Friends"] = "Kontakte vorschlagen";
$a->strings["Suggest a friend for %s"] = "Schlage %s einen Kontakt vor";
$a->strings["Personal Notes"] = "Persönliche Notizen";
$a->strings["Photo Albums"] = "Fotoalben";
$a->strings["Recent Photos"] = "Neueste Fotos";
$a->strings["Upload New Photos"] = "Neue Fotos hochladen";
$a->strings["everybody"] = "jeder";
$a->strings["Contact information unavailable"] = "Kontaktinformationen nicht verfügbar";
$a->strings["Album not found."] = "Album nicht gefunden.";
$a->strings["Delete Album"] = "Album löschen";
$a->strings["Do you really want to delete this photo album and all its photos?"] = "Möchtest Du wirklich dieses Foto-Album und all seine Foto löschen?";
$a->strings["Delete Photo"] = "Foto löschen";
$a->strings["Do you really want to delete this photo?"] = "Möchtest Du wirklich dieses Foto löschen?";
$a->strings["a photo"] = "einem Foto";
$a->strings["%1\$s was tagged in %2\$s by %3\$s"] = "%1\$s wurde von %3\$s in %2\$s getaggt";
$a->strings["Image upload didn't complete, please try again"] = "Der Upload des Bildes war nicht vollständig. Bitte versuche es erneut.";
$a->strings["Image file is missing"] = "Bilddatei konnte nicht gefunden werden.";
$a->strings["Server can't accept new file upload at this time, please contact your administrator"] = "Der Server kann derzeit keine neuen Datei Uploads akzeptieren. Bitte kontaktiere deinen Administrator.";
$a->strings["Image file is empty."] = "Bilddatei ist leer.";
$a->strings["No photos selected"] = "Keine Bilder ausgewählt";
$a->strings["Access to this item is restricted."] = "Zugriff zu diesem Eintrag wurde eingeschränkt.";
$a->strings["Upload Photos"] = "Bilder hochladen";
$a->strings["New album name: "] = "Name des neuen Albums: ";
$a->strings["or existing album name: "] = "oder existierender Albumname: ";
$a->strings["Do not show a status post for this upload"] = "Keine Status-Mitteilung für diesen Beitrag anzeigen";
$a->strings["Permissions"] = "Berechtigungen";
$a->strings["Show to Groups"] = "Zeige den Gruppen";
$a->strings["Show to Contacts"] = "Zeige den Kontakten";
$a->strings["Edit Album"] = "Album bearbeiten";
$a->strings["Show Newest First"] = "Zeige neueste zuerst";
$a->strings["Show Oldest First"] = "Zeige älteste zuerst";
$a->strings["View Photo"] = "Foto betrachten";
$a->strings["Permission denied. Access to this item may be restricted."] = "Zugriff verweigert. Zugriff zu diesem Eintrag könnte eingeschränkt sein.";
$a->strings["Photo not available"] = "Foto nicht verfügbar";
$a->strings["View photo"] = "Fotos ansehen";
$a->strings["Edit photo"] = "Foto bearbeiten";
$a->strings["Use as profile photo"] = "Als Profilbild verwenden";
$a->strings["Private Message"] = "Private Nachricht";
$a->strings["View Full Size"] = "Betrachte Originalgröße";
$a->strings["Tags: "] = "Tags: ";
$a->strings["[Remove any tag]"] = "[Tag entfernen]";
$a->strings["New album name"] = "Name des neuen Albums";
$a->strings["Caption"] = "Bildunterschrift";
$a->strings["Add a Tag"] = "Tag hinzufügen";
$a->strings["Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"] = "Beispiel: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping";
$a->strings["Do not rotate"] = "Nicht rotieren";
$a->strings["Rotate CW (right)"] = "Drehen US (rechts)";
$a->strings["Rotate CCW (left)"] = "Drehen EUS (links)";
$a->strings["I like this (toggle)"] = "Ich mag das (toggle)";
$a->strings["I don't like this (toggle)"] = "Ich mag das nicht (toggle)";
$a->strings["This is you"] = "Das bist Du";
$a->strings["Comment"] = "Kommentar";
$a->strings["Map"] = "Karte";
$a->strings["View Album"] = "Album betrachten";
$a->strings["Do you really want to delete this video?"] = "Möchtest Du dieses Video wirklich löschen?";
$a->strings["Delete Video"] = "Video Löschen";
$a->strings["No videos selected"] = "Keine Videos ausgewählt";
$a->strings["Recent Videos"] = "Neueste Videos";
$a->strings["Upload New Videos"] = "Neues Video hochladen";
$a->strings["Access to this profile has been restricted."] = "Der Zugriff zu diesem Profil wurde eingeschränkt.";
$a->strings["Events"] = "Veranstaltungen";
$a->strings["View"] = "Ansehen";
@ -552,7 +484,7 @@ $a->strings["Fetch further information for feeds"] = "Weitere Informationen zu F
$a->strings["Fetch information like preview pictures, title and teaser from the feed item. You can activate this if the feed doesn't contain much text. Keywords are taken from the meta header in the feed item and are posted as hash tags."] = "Zusätzliche Informationen wie Vorschaubilder, Titel und Zusammenfassungen vom Feed-Eintrag laden. Du kannst diese Option aktivieren, wenn der Feed nicht all zu viel Text beinhaltet. Schlagwörter werden auf den Meta-Informationen des Feed-Headers bezogen und als Hash-Tags verwendet.";
$a->strings["Disabled"] = "Deaktiviert";
$a->strings["Fetch information"] = "Beziehe Information";
$a->strings["Fetch keywords"] = "Schlüsselwprter abrufen";
$a->strings["Fetch keywords"] = "Schlüsselwörter abrufen";
$a->strings["Fetch information and keywords"] = "Beziehe Information und Schlüsselworte";
$a->strings["Disconnect/Unfollow"] = "Verbindung lösen/Nicht mehr folgen";
$a->strings["Contact"] = "Kontakt";
@ -605,6 +537,7 @@ $a->strings["Only show archived contacts"] = "Nur archivierte Kontakte anzeigen"
$a->strings["Hidden"] = "Verborgen";
$a->strings["Only show hidden contacts"] = "Nur verborgene Kontakte anzeigen";
$a->strings["Search your contacts"] = "Suche in deinen Kontakten";
$a->strings["Results for: %s"] = "Ergebnisse für: %s";
$a->strings["Find"] = "Finde";
$a->strings["Update"] = "Aktualisierungen";
$a->strings["Archive"] = "Archivieren";
@ -619,6 +552,7 @@ $a->strings["Advanced Contact Settings"] = "Fortgeschrittene Kontakteinstellunge
$a->strings["Mutual Friendship"] = "Beidseitige Freundschaft";
$a->strings["is a fan of yours"] = "ist ein Fan von dir";
$a->strings["you are a fan of"] = "Du bist Fan von";
$a->strings["This is you"] = "Das bist Du";
$a->strings["Toggle Blocked status"] = "Geblockt-Status ein-/ausschalten";
$a->strings["Toggle Ignored status"] = "Ignoriert-Status ein-/ausschalten";
$a->strings["Toggle Archive status"] = "Archiviert-Status ein-/ausschalten";
@ -637,22 +571,6 @@ $a->strings["Existing Page Delegates"] = "Vorhandene Bevollmächtigte für die S
$a->strings["Potential Delegates"] = "Potentielle Bevollmächtigte";
$a->strings["Add"] = "Hinzufügen";
$a->strings["No entries."] = "Keine Einträge.";
$a->strings["Event can not end before it has started."] = "Die Veranstaltung kann nicht enden bevor sie beginnt.";
$a->strings["Event title and start time are required."] = "Der Veranstaltungstitel und die Anfangszeit müssen angegeben werden.";
$a->strings["Create New Event"] = "Neue Veranstaltung erstellen";
$a->strings["Event details"] = "Veranstaltungsdetails";
$a->strings["Starting date and Title are required."] = "Anfangszeitpunkt und Titel werden benötigt";
$a->strings["Event Starts:"] = "Veranstaltungsbeginn:";
$a->strings["Required"] = "Benötigt";
$a->strings["Finish date/time is not known or not relevant"] = "Enddatum/-zeit ist nicht bekannt oder nicht relevant";
$a->strings["Event Finishes:"] = "Veranstaltungsende:";
$a->strings["Adjust for viewer timezone"] = "An Zeitzone des Betrachters anpassen";
$a->strings["Description:"] = "Beschreibung";
$a->strings["Title:"] = "Titel:";
$a->strings["Share this event"] = "Veranstaltung teilen";
$a->strings["Basic"] = "Allgemein";
$a->strings["Failed to remove event"] = "Entfernen der Veranstaltung fehlgeschlagen";
$a->strings["Event removed"] = "Veranstaltung enfternt";
$a->strings["You must be logged in to use this module"] = "Du musst eingeloggt sein um dieses Modul benutzen zu können.";
$a->strings["Source URL"] = "URL der Quelle";
$a->strings["Post successful."] = "Beitrag erfolgreich veröffentlicht.";
@ -739,13 +657,6 @@ $a->strings["Source text"] = "Quelltext";
$a->strings["BBCode"] = "BBCode";
$a->strings["Markdown"] = "Markdown";
$a->strings["HTML"] = "HTML";
$a->strings["Community option not available."] = "Optionen für die Gemeinschaftsseite nicht verfügbar.";
$a->strings["Not available."] = "Nicht verfügbar.";
$a->strings["Local Community"] = "Lokale Gemeinschaft";
$a->strings["Posts from local users on this server"] = "Beiträge von Nutzern dieses Servers";
$a->strings["Global Community"] = "Globale Gemeinschaft";
$a->strings["Posts from users of the whole federated network"] = "Beiträge von Nutzern des gesamten föderalen Netzwerks";
$a->strings["This community stream shows all public posts received by this node. They may not reflect the opinions of this nodes users."] = "Diese Gemeinschaftsseite zeigt alle öffentlichen Beiträge, die auf diesem Knoten eingegangen sind. Der Inhalt entspricht nicht zwingend der Meinung der Nutzer dieses Servers.";
$a->strings["This is Friendica, version"] = "Dies ist Friendica, Version";
$a->strings["running at web location"] = "die unter folgender Webadresse zu finden ist";
$a->strings["Please visit <a href=\"https://friendi.ca\">Friendi.ca</a> to learn more about the Friendica project."] = "Bitte besuche <a href=\"https://friendi.ca\">Friendi.ca</a> um mehr über das Friendica Projekt zu erfahren.";
@ -780,29 +691,6 @@ $a->strings["You are cordially invited to join me and other close friends on Fri
$a->strings["You will need to supply this invitation code: \$invite_code"] = "Du benötigst den folgenden Einladungscode: \$invite_code";
$a->strings["Once you have registered, please connect with me via my profile page at:"] = "Sobald Du registriert bist, kontaktiere mich bitte auf meiner Profilseite:";
$a->strings["For more information about the Friendica project and why we feel it is important, please visit http://friendi.ca"] = "Für weitere Informationen über das Friendica Projekt und warum wir es für ein wichtiges Projekt halten, besuche bitte http://friendi.ca.";
$a->strings["add"] = "hinzufügen";
$a->strings["Warning: This group contains %s member from a network that doesn't allow non public messages."] = [
0 => "Warnung: Diese Gruppe beinhaltet %s Person aus einem Netzwerk das keine nicht öffentlichen Beiträge empfangen kann.",
1 => "Warnung: Diese Gruppe beinhaltet %s Personen aus Netzwerken die keine nicht-öffentlichen Beiträge empfangen können.",
];
$a->strings["Messages in this group won't be send to these receivers."] = "Beiträge in dieser Gruppe werden deshalb nicht an diese Personen zugestellt werden.";
$a->strings["No such group"] = "Es gibt keine solche Gruppe";
$a->strings["Group is empty"] = "Gruppe ist leer";
$a->strings["Group: %s"] = "Gruppe: %s";
$a->strings["Private messages to this person are at risk of public disclosure."] = "Private Nachrichten an diese Person könnten an die Öffentlichkeit gelangen.";
$a->strings["Invalid contact."] = "Ungültiger Kontakt.";
$a->strings["Commented Order"] = "Neueste Kommentare";
$a->strings["Sort by Comment Date"] = "Nach Kommentardatum sortieren";
$a->strings["Posted Order"] = "Neueste Beiträge";
$a->strings["Sort by Post Date"] = "Nach Beitragsdatum sortieren";
$a->strings["Personal"] = "Persönlich";
$a->strings["Posts that mention or involve you"] = "Beiträge, in denen es um Dich geht";
$a->strings["New"] = "Neue";
$a->strings["Activity Stream - by date"] = "Aktivitäten-Stream - nach Datum";
$a->strings["Shared Links"] = "Geteilte Links";
$a->strings["Interesting Links"] = "Interessante Links";
$a->strings["Starred"] = "Markierte";
$a->strings["Favourite Posts"] = "Favorisierte Beiträge";
$a->strings["Contact settings applied."] = "Einstellungen zum Kontakt angewandt.";
$a->strings["Contact update failed."] = "Konnte den Kontakt nicht aktualisieren.";
$a->strings["<strong>WARNING: This is highly advanced</strong> and if you enter incorrect information your communications with this contact may stop working."] = "<strong>ACHTUNG: Das sind Experten-Einstellungen!</strong> Wenn Du etwas Falsches eingibst, funktioniert die Kommunikation mit diesem Kontakt evtl. nicht mehr.";
@ -876,24 +764,6 @@ $a->strings["%d message"] = [
0 => "%d Nachricht",
1 => "%d Nachrichten",
];
$a->strings["Group created."] = "Gruppe erstellt.";
$a->strings["Could not create group."] = "Konnte die Gruppe nicht erstellen.";
$a->strings["Group not found."] = "Gruppe nicht gefunden.";
$a->strings["Group name changed."] = "Gruppenname geändert.";
$a->strings["Save Group"] = "Gruppe speichern";
$a->strings["Create a group of contacts/friends."] = "Eine Kontaktgruppe anlegen.";
$a->strings["Group Name: "] = "Gruppenname:";
$a->strings["Group removed."] = "Gruppe entfernt.";
$a->strings["Unable to remove group."] = "Konnte die Gruppe nicht entfernen.";
$a->strings["Delete Group"] = "Gruppe löschen";
$a->strings["Group Editor"] = "Gruppeneditor";
$a->strings["Edit Group Name"] = "Gruppen Name bearbeiten";
$a->strings["Members"] = "Mitglieder";
$a->strings["Remove contact from group"] = "Entferne den Kontakt aus der Gruppe";
$a->strings["Add contact to group"] = "Füge den Kontakt zur Gruppe hinzu";
$a->strings["OpenID protocol error. No ID returned."] = "OpenID Protokollfehler. Keine ID zurückgegeben.";
$a->strings["Account not found and OpenID registration is not permitted on this site."] = "Nutzerkonto wurde nicht gefunden und OpenID-Registrierung ist auf diesem Server nicht gestattet.";
$a->strings["Login failed."] = "Anmeldung fehlgeschlagen.";
$a->strings["Theme settings updated."] = "Themeneinstellungen aktualisiert.";
$a->strings["Information"] = "Information";
$a->strings["Overview"] = "Übersicht";
@ -1083,6 +953,7 @@ $a->strings["Block public"] = "Öffentlichen Zugriff blockieren";
$a->strings["Check to block public access to all otherwise public personal pages on this site unless you are currently logged in."] = "Klicken, um öffentlichen Zugriff auf sonst öffentliche Profile zu blockieren, wenn man nicht eingeloggt ist.";
$a->strings["Force publish"] = "Erzwinge Veröffentlichung";
$a->strings["Check to force all profiles on this site to be listed in the site directory."] = "Klicken, um Anzeige aller Profile dieses Servers im Verzeichnis zu erzwingen.";
$a->strings["Enabling this may violate privacy laws like the GDPR"] = "Wenn du diese Option aktivierst, verstößt das unter Umständen gegen Gesetze wie die EU-DSGVO.";
$a->strings["Global directory URL"] = "URL des weltweiten Verzeichnisses";
$a->strings["URL to the global directory. If this is not set, the global directory is completely unavailable to the application."] = "URL des weltweiten Verzeichnisses. Wenn diese nicht gesetzt ist, ist das Verzeichnis für die Applikation nicht erreichbar.";
$a->strings["Private posts by default for new users"] = "Private Beiträge als Standard für neue Nutzer";
@ -1164,7 +1035,7 @@ $a->strings["If you have a restricted system where the webserver can't access th
$a->strings["Base path to installation"] = "Basis-Pfad zur Installation";
$a->strings["If the system cannot detect the correct path to your installation, enter the correct path here. This setting should only be set if you are using a restricted system and symbolic links to your webroot."] = "Falls das System nicht den korrekten Pfad zu deiner Installation gefunden hat, gib den richtigen Pfad bitte hier ein. Du solltest hier den Pfad nur auf einem eingeschränkten System angeben müssen, bei dem du mit symbolischen Links auf dein Webverzeichnis verweist.";
$a->strings["Disable picture proxy"] = "Bilder Proxy deaktivieren";
$a->strings["The picture proxy increases performance and privacy. It shouldn't be used on systems with very low bandwith."] = "Der Proxy für Bilder verbessert die Leistung und Privatsphäre der Nutzer. Er sollte nicht auf Systemen verwendet werden, die nur über begrenzte Bandbreite verfügen.";
$a->strings["The picture proxy increases performance and privacy. It shouldn't be used on systems with very low bandwidth."] = "Der Proxy für Bilder verbessert die Leistung und Privatsphäre der Nutzer. Er sollte nicht auf Systemen verwendet werden, die nur über begrenzte Bandbreite verfügen.";
$a->strings["Only search in tags"] = "Nur in Tags suchen";
$a->strings["On large systems the text search can slow down the system extremely."] = "Auf großen Knoten kann die Volltext-Suche das System ausbremsen.";
$a->strings["New base url"] = "Neue Basis-URL";
@ -1284,6 +1155,14 @@ $a->strings["Off"] = "Aus";
$a->strings["On"] = "An";
$a->strings["Lock feature %s"] = "Feature festlegen: %s";
$a->strings["Manage Additional Features"] = "Zusätzliche Features Verwalten";
$a->strings["Community option not available."] = "Optionen für die Gemeinschaftsseite nicht verfügbar.";
$a->strings["Not available."] = "Nicht verfügbar.";
$a->strings["Local Community"] = "Lokale Gemeinschaft";
$a->strings["Posts from local users on this server"] = "Beiträge von Nutzern dieses Servers";
$a->strings["Global Community"] = "Globale Gemeinschaft";
$a->strings["Posts from users of the whole federated network"] = "Beiträge von Nutzern des gesamten föderalen Netzwerks";
$a->strings["No results."] = "Keine Ergebnisse.";
$a->strings["This community stream shows all public posts received by this node. They may not reflect the opinions of this nodes users."] = "Diese Gemeinschaftsseite zeigt alle öffentlichen Beiträge, die auf diesem Knoten eingegangen sind. Der Inhalt entspricht nicht zwingend der Meinung der Nutzer dieses Servers.";
$a->strings["Profile not found."] = "Profil nicht gefunden.";
$a->strings["This may occasionally happen if contact was requested by both persons and it has already been approved."] = "Das kann passieren, wenn sich zwei Kontakte gegenseitig eingeladen haben und bereits einer angenommen wurde.";
$a->strings["Response from remote site was not understood."] = "Antwort der Gegenstelle unverständlich.";
@ -1337,12 +1216,70 @@ $a->strings["Friendica"] = "Friendica";
$a->strings["GNU Social (Pleroma, Mastodon)"] = "GNU Social (Pleroma, Mastodon)";
$a->strings["Diaspora (Socialhome, Hubzilla)"] = "Diaspora (Socialhome, Hubzilla)";
$a->strings[" - please do not use this form. Instead, enter %s into your Diaspora search bar."] = " - bitte verwende dieses Formular nicht. Stattdessen suche nach %s in Deiner Diaspora Suchleiste.";
$a->strings["Event can not end before it has started."] = "Die Veranstaltung kann nicht enden bevor sie beginnt.";
$a->strings["Event title and start time are required."] = "Der Veranstaltungstitel und die Anfangszeit müssen angegeben werden.";
$a->strings["Create New Event"] = "Neue Veranstaltung erstellen";
$a->strings["Event details"] = "Veranstaltungsdetails";
$a->strings["Starting date and Title are required."] = "Anfangszeitpunkt und Titel werden benötigt";
$a->strings["Event Starts:"] = "Veranstaltungsbeginn:";
$a->strings["Required"] = "Benötigt";
$a->strings["Finish date/time is not known or not relevant"] = "Enddatum/-zeit ist nicht bekannt oder nicht relevant";
$a->strings["Event Finishes:"] = "Veranstaltungsende:";
$a->strings["Adjust for viewer timezone"] = "An Zeitzone des Betrachters anpassen";
$a->strings["Description:"] = "Beschreibung";
$a->strings["Title:"] = "Titel:";
$a->strings["Share this event"] = "Veranstaltung teilen";
$a->strings["Basic"] = "Allgemein";
$a->strings["Permissions"] = "Berechtigungen";
$a->strings["Failed to remove event"] = "Entfernen der Veranstaltung fehlgeschlagen";
$a->strings["Event removed"] = "Veranstaltung enfternt";
$a->strings["Group created."] = "Gruppe erstellt.";
$a->strings["Could not create group."] = "Konnte die Gruppe nicht erstellen.";
$a->strings["Group not found."] = "Gruppe nicht gefunden.";
$a->strings["Group name changed."] = "Gruppenname geändert.";
$a->strings["Save Group"] = "Gruppe speichern";
$a->strings["Create a group of contacts/friends."] = "Eine Kontaktgruppe anlegen.";
$a->strings["Group Name: "] = "Gruppenname:";
$a->strings["Group removed."] = "Gruppe entfernt.";
$a->strings["Unable to remove group."] = "Konnte die Gruppe nicht entfernen.";
$a->strings["Delete Group"] = "Gruppe löschen";
$a->strings["Group Editor"] = "Gruppeneditor";
$a->strings["Edit Group Name"] = "Gruppen Name bearbeiten";
$a->strings["Members"] = "Mitglieder";
$a->strings["Group is empty"] = "Gruppe ist leer";
$a->strings["Remove contact from group"] = "Entferne den Kontakt aus der Gruppe";
$a->strings["Add contact to group"] = "Füge den Kontakt zur Gruppe hinzu";
$a->strings["Unable to locate original post."] = "Konnte den Originalbeitrag nicht finden.";
$a->strings["Empty post discarded."] = "Leerer Beitrag wurde verworfen.";
$a->strings["This message was sent to you by %s, a member of the Friendica social network."] = "Diese Nachricht wurde dir von %s geschickt, einem Mitglied des Sozialen Netzwerks Friendica.";
$a->strings["You may visit them online at %s"] = "Du kannst sie online unter %s besuchen";
$a->strings["Please contact the sender by replying to this post if you do not wish to receive these messages."] = "Falls Du diese Beiträge nicht erhalten möchtest, kontaktiere bitte den Autor, indem Du auf diese Nachricht antwortest.";
$a->strings["%s posted an update."] = "%s hat ein Update veröffentlicht.";
$a->strings["Remove term"] = "Begriff entfernen";
$a->strings["Saved Searches"] = "Gespeicherte Suchen";
$a->strings["add"] = "hinzufügen";
$a->strings["Warning: This group contains %s member from a network that doesn't allow non public messages."] = [
0 => "Warnung: Diese Gruppe beinhaltet %s Person aus einem Netzwerk das keine nicht öffentlichen Beiträge empfangen kann.",
1 => "Warnung: Diese Gruppe beinhaltet %s Personen aus Netzwerken die keine nicht-öffentlichen Beiträge empfangen können.",
];
$a->strings["Messages in this group won't be send to these receivers."] = "Beiträge in dieser Gruppe werden deshalb nicht an diese Personen zugestellt werden.";
$a->strings["No such group"] = "Es gibt keine solche Gruppe";
$a->strings["Group: %s"] = "Gruppe: %s";
$a->strings["Private messages to this person are at risk of public disclosure."] = "Private Nachrichten an diese Person könnten an die Öffentlichkeit gelangen.";
$a->strings["Invalid contact."] = "Ungültiger Kontakt.";
$a->strings["Commented Order"] = "Neueste Kommentare";
$a->strings["Sort by Comment Date"] = "Nach Kommentardatum sortieren";
$a->strings["Posted Order"] = "Neueste Beiträge";
$a->strings["Sort by Post Date"] = "Nach Beitragsdatum sortieren";
$a->strings["Personal"] = "Persönlich";
$a->strings["Posts that mention or involve you"] = "Beiträge, in denen es um Dich geht";
$a->strings["New"] = "Neue";
$a->strings["Activity Stream - by date"] = "Aktivitäten-Stream - nach Datum";
$a->strings["Shared Links"] = "Geteilte Links";
$a->strings["Interesting Links"] = "Interessante Links";
$a->strings["Starred"] = "Markierte";
$a->strings["Favourite Posts"] = "Favorisierte Beiträge";
$a->strings["Personal Notes"] = "Persönliche Notizen";
$a->strings["Invalid request identifier."] = "Invalid request identifier.";
$a->strings["Discard"] = "Verwerfen";
$a->strings["Notifications"] = "Benachrichtigungen";
@ -1367,6 +1304,58 @@ $a->strings["No introductions."] = "Keine Kontaktanfragen.";
$a->strings["Show unread"] = "Ungelesene anzeigen";
$a->strings["Show all"] = "Alle anzeigen";
$a->strings["No more %s notifications."] = "Keine weiteren %s Benachrichtigungen";
$a->strings["OpenID protocol error. No ID returned."] = "OpenID Protokollfehler. Keine ID zurückgegeben.";
$a->strings["Account not found and OpenID registration is not permitted on this site."] = "Nutzerkonto wurde nicht gefunden und OpenID-Registrierung ist auf diesem Server nicht gestattet.";
$a->strings["Login failed."] = "Anmeldung fehlgeschlagen.";
$a->strings["Photo Albums"] = "Fotoalben";
$a->strings["Recent Photos"] = "Neueste Fotos";
$a->strings["Upload New Photos"] = "Neue Fotos hochladen";
$a->strings["everybody"] = "jeder";
$a->strings["Contact information unavailable"] = "Kontaktinformationen nicht verfügbar";
$a->strings["Album not found."] = "Album nicht gefunden.";
$a->strings["Delete Album"] = "Album löschen";
$a->strings["Do you really want to delete this photo album and all its photos?"] = "Möchtest Du wirklich dieses Foto-Album und all seine Foto löschen?";
$a->strings["Delete Photo"] = "Foto löschen";
$a->strings["Do you really want to delete this photo?"] = "Möchtest Du wirklich dieses Foto löschen?";
$a->strings["a photo"] = "einem Foto";
$a->strings["%1\$s was tagged in %2\$s by %3\$s"] = "%1\$s wurde von %3\$s in %2\$s getaggt";
$a->strings["Image upload didn't complete, please try again"] = "Der Upload des Bildes war nicht vollständig. Bitte versuche es erneut.";
$a->strings["Image file is missing"] = "Bilddatei konnte nicht gefunden werden.";
$a->strings["Server can't accept new file upload at this time, please contact your administrator"] = "Der Server kann derzeit keine neuen Datei Uploads akzeptieren. Bitte kontaktiere deinen Administrator.";
$a->strings["Image file is empty."] = "Bilddatei ist leer.";
$a->strings["No photos selected"] = "Keine Bilder ausgewählt";
$a->strings["Access to this item is restricted."] = "Zugriff zu diesem Eintrag wurde eingeschränkt.";
$a->strings["Upload Photos"] = "Bilder hochladen";
$a->strings["New album name: "] = "Name des neuen Albums: ";
$a->strings["or existing album name: "] = "oder existierender Albumname: ";
$a->strings["Do not show a status post for this upload"] = "Keine Status-Mitteilung für diesen Beitrag anzeigen";
$a->strings["Show to Groups"] = "Zeige den Gruppen";
$a->strings["Show to Contacts"] = "Zeige den Kontakten";
$a->strings["Edit Album"] = "Album bearbeiten";
$a->strings["Show Newest First"] = "Zeige neueste zuerst";
$a->strings["Show Oldest First"] = "Zeige älteste zuerst";
$a->strings["View Photo"] = "Foto betrachten";
$a->strings["Permission denied. Access to this item may be restricted."] = "Zugriff verweigert. Zugriff zu diesem Eintrag könnte eingeschränkt sein.";
$a->strings["Photo not available"] = "Foto nicht verfügbar";
$a->strings["View photo"] = "Fotos ansehen";
$a->strings["Edit photo"] = "Foto bearbeiten";
$a->strings["Use as profile photo"] = "Als Profilbild verwenden";
$a->strings["Private Message"] = "Private Nachricht";
$a->strings["View Full Size"] = "Betrachte Originalgröße";
$a->strings["Tags: "] = "Tags: ";
$a->strings["[Remove any tag]"] = "[Tag entfernen]";
$a->strings["New album name"] = "Name des neuen Albums";
$a->strings["Caption"] = "Bildunterschrift";
$a->strings["Add a Tag"] = "Tag hinzufügen";
$a->strings["Example: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping"] = "Beispiel: @bob, @Barbara_Jensen, @jim@example.com, #California, #camping";
$a->strings["Do not rotate"] = "Nicht rotieren";
$a->strings["Rotate CW (right)"] = "Drehen US (rechts)";
$a->strings["Rotate CCW (left)"] = "Drehen EUS (links)";
$a->strings["I like this (toggle)"] = "Ich mag das (toggle)";
$a->strings["I don't like this (toggle)"] = "Ich mag das nicht (toggle)";
$a->strings["Comment"] = "Kommentar";
$a->strings["Map"] = "Karte";
$a->strings["View Album"] = "Album betrachten";
$a->strings["Requested profile is not available."] = "Das angefragte Profil ist nicht vorhanden.";
$a->strings["%s's timeline"] = "Timeline von %s";
$a->strings["%s's posts"] = "Beiträge von %s";
@ -1479,6 +1468,10 @@ $a->strings["The user id is %d"] = "Die ID des Users lautet %d";
$a->strings["Remove My Account"] = "Konto löschen";
$a->strings["This will completely remove your account. Once this has been done it is not recoverable."] = "Dein Konto wird endgültig gelöscht. Es gibt keine Möglichkeit, es wiederherzustellen.";
$a->strings["Please enter your password for verification:"] = "Bitte gib Dein Passwort zur Verifikation ein:";
$a->strings["Only logged in users are permitted to perform a search."] = "Nur eingeloggten Benutzern ist das Suchen gestattet.";
$a->strings["Too Many Requests"] = "Zu viele Abfragen";
$a->strings["Only one search per minute is permitted for not logged in users."] = "Es ist nur eine Suchanfrage pro Minute für nicht eingeloggte Benutzer gestattet.";
$a->strings["Items tagged with: %s"] = "Beiträge die mit %s getaggt sind";
$a->strings["Account"] = "Nutzerkonto";
$a->strings["Display"] = "Anzeige";
$a->strings["Social Networks"] = "Soziale Netzwerke";
@ -1569,7 +1562,7 @@ $a->strings["Don't show notices"] = "Info-Popups nicht anzeigen";
$a->strings["Infinite scroll"] = "Endloses Scrollen";
$a->strings["Automatic updates only at the top of the network page"] = "Automatische Updates nur, wenn Du oben auf der Netzwerkseite bist.";
$a->strings["When disabled, the network page is updated all the time, which could be confusing while reading."] = "Wenn dies deaktiviert ist, wird die Netzwerk Seite aktualisiert, wann immer neue Beiträge eintreffen, egal an welcher Stelle gerade gelesen wird.";
$a->strings["Bandwith Saver Mode"] = "Bandbreiten-Spar-Modus";
$a->strings["Bandwidth Saver Mode"] = "Bandbreiten-Spar-Modus";
$a->strings["When enabled, embedded content is not displayed on automatic updates, they only show on page reload."] = "Wenn aktiviert, wird der eingebettete Inhalt nicht automatisch aktualisiert. In diesem Fall Seite bitte neu laden.";
$a->strings["Smart Threading"] = "Intelligentes Threading";
$a->strings["When enabled, suppress extraneous thread indentation while keeping it where it matters. Only works if threading is available and enabled."] = "Ist dies aktiviert, werden Einrückungen in Unterhaltungen unterdrückt wo sie nicht benötigt werden. Werden sie benötigt, werden die Threads weiterhin eingerückt.";
@ -1594,13 +1587,13 @@ $a->strings["Requires manual approval of contact requests."] = "Kontaktanfragen
$a->strings["OpenID:"] = "OpenID:";
$a->strings["(Optional) Allow this OpenID to login to this account."] = "(Optional) Erlaube die Anmeldung für dieses Konto mit dieser OpenID.";
$a->strings["Publish your default profile in your local site directory?"] = "Darf Dein Standardprofil im Verzeichnis dieses Servers veröffentlicht werden?";
$a->strings["Your profile will be published in the global friendica directories (e.g. <a href=\"%s\">%s</a>). Your profile will be visible in public."] = "Dein Profil wird in den globalen Friendica Verzeichnissen (z.B. <a href=\"%s\">%s</a>) veröffentlicht. Dein Profil wird öffentlich auffindbar sein.";
$a->strings["Publish your default profile in the global social directory?"] = "Darf Dein Standardprofil im weltweiten Verzeichnis veröffentlicht werden?";
$a->strings["Your profile will be published in this node's <a href=\"%s\">local directory</a>. Your profile details may be publicly visible depending on the system settings."] = "Dein Profil wird im <a href=\"%s\">lokalen Verzeichnis</a> dieses Knotens veröffentlicht. Je nach Systemeinstellungen kann es öffentlich auffindbar sein.";
$a->strings["Publish your default profile in the global social directory?"] = "Darf Dein Standardprofil im weltweiten Verzeichnis veröffentlicht werden?";
$a->strings["Your profile will be published in the global friendica directories (e.g. <a href=\"%s\">%s</a>). Your profile will be visible in public."] = "Dein Profil wird in den globalen Friendica Verzeichnissen (z.B. <a href=\"%s\">%s</a>) veröffentlicht. Dein Profil wird öffentlich auffindbar sein.";
$a->strings["Hide your contact/friend list from viewers of your default profile?"] = "Liste der Kontakte vor Betrachtern des Standardprofils verbergen?";
$a->strings["Your contact list won't be shown in your default profile page. You can decide to show your contact list separately for each additional profile you create"] = "Die Liste deiner Kontakte wird nicht in deinem Standard-Profil angezeigt werden. Du kannst für jedes weitere Profil diese Entscheidung separat einstellen.";
$a->strings["Hide your profile details from anonymous viewers?"] = "Profil-Details vor unbekannten Betrachtern verbergen?";
$a->strings["Anonymous visitors will only see your profile picture, your display name and the nickname you are using on your profile page. Disables posting public messages to Diaspora and other networks."] = "Anonyme Besucher deines Profils werden ausschließlich dein Profilbild, deinen Namen sowie deinen Spitznamen sehen. Ist diese Option aktiv, können keine öffentlichen Beiträge zu Diaspora und anderen Netzwerken veröffentlicht werden.";
$a->strings["Anonymous visitors will only see your profile picture, your display name and the nickname you are using on your profile page. Your public posts and replies will still be accessible by other means."] = "Anonyme Besucher deines Profils werden ausschließlich dein Profilbild, deinen Namen sowie deinen Spitznamen sehen. Deine lffentlichen Beiträge und Kommentare werden weiterhin sichtbar sein.";
$a->strings["Allow friends to post to your profile page?"] = "Dürfen Deine Kontakte auf Deine Pinnwand schreiben?";
$a->strings["Your contacts may write posts on your profile wall. These posts will be distributed to your contacts"] = "Deine Kontakte können Beiträge auf deiner Pinnwand hinterlassen. Diese werden an deine Kontakte verteilt.";
$a->strings["Allow friends to tag your posts?"] = "Dürfen Deine Kontakte Deine Beiträge mit Schlagwörtern versehen?";
@ -1664,6 +1657,13 @@ $a->strings["Change the behaviour of this account for special situations"] = "Ve
$a->strings["Relocate"] = "Umziehen";
$a->strings["If you have moved this profile from another server, and some of your contacts don't receive your updates, try pushing this button."] = "Wenn Du Dein Profil von einem anderen Server umgezogen hast und einige Deiner Kontakte Deine Beiträge nicht erhalten, verwende diesen Button.";
$a->strings["Resend relocate message to contacts"] = "Umzugsbenachrichtigung erneut an Kontakte senden";
$a->strings["%1\$s is following %2\$s's %3\$s"] = "%1\$s folgt %2\$s %3\$s";
$a->strings["[Embedded content - reload page to view]"] = "[Eingebetteter Inhalt - Seite neu laden zum Betrachten]";
$a->strings["Do you really want to delete this video?"] = "Möchtest Du dieses Video wirklich löschen?";
$a->strings["Delete Video"] = "Video Löschen";
$a->strings["No videos selected"] = "Keine Videos ausgewählt";
$a->strings["Recent Videos"] = "Neueste Videos";
$a->strings["Upload New Videos"] = "Neues Video hochladen";
$a->strings["default"] = "Standard";
$a->strings["greenzero"] = "greenzero";
$a->strings["purplezero"] = "purplezero";
@ -2026,6 +2026,32 @@ $a->strings["Errors encountered performing database changes: "] = "Fehler beim
$a->strings["%s: Database update"] = "%s: Datenbank Aktualisierung";
$a->strings["%s: updating %s table."] = "%s: aktualisiere Tabelle %s";
$a->strings["[no subject]"] = "[kein Betreff]";
$a->strings["A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name."] = "Eine gelöschte Gruppe mit diesem Namen wurde wiederbelebt. Bestehende Berechtigungseinstellungen <strong>könnten</strong> auf diese Gruppe oder zukünftige Mitglieder angewandt werden. Falls Du dies nicht möchtest, erstelle bitte eine andere Gruppe mit einem anderen Namen.";
$a->strings["Default privacy group for new contacts"] = "Voreingestellte Gruppe für neue Kontakte";
$a->strings["Everybody"] = "Alle Kontakte";
$a->strings["edit"] = "bearbeiten";
$a->strings["Edit group"] = "Gruppe bearbeiten";
$a->strings["Contacts not in any group"] = "Kontakte in keiner Gruppe";
$a->strings["Create a new group"] = "Neue Gruppe erstellen";
$a->strings["Edit groups"] = "Gruppen bearbeiten";
$a->strings["Drop Contact"] = "Kontakt löschen";
$a->strings["Organisation"] = "Organisation";
$a->strings["News"] = "Nachrichten";
$a->strings["Forum"] = "Forum";
$a->strings["Connect URL missing."] = "Connect-URL fehlt";
$a->strings["The contact could not be added. Please check the relevant network credentials in your Settings -> Social Networks page."] = "Der Kontakt konnte nicht hinzugefügt werden. Bitte überprüfe die Einstellungen unter Einstellungen -> Soziale Netzwerke";
$a->strings["This site is not configured to allow communications with other networks."] = "Diese Seite ist so konfiguriert, dass keine Kommunikation mit anderen Netzwerken erfolgen kann.";
$a->strings["No compatible communication protocols or feeds were discovered."] = "Es wurden keine kompatiblen Kommunikationsprotokolle oder Feeds gefunden.";
$a->strings["The profile address specified does not provide adequate information."] = "Die angegebene Profiladresse liefert unzureichende Informationen.";
$a->strings["An author or name was not found."] = "Es wurde kein Autor oder Name gefunden.";
$a->strings["No browser URL could be matched to this address."] = "Zu dieser Adresse konnte keine passende Browser URL gefunden werden.";
$a->strings["Unable to match @-style Identity Address with a known protocol or email contact."] = "Konnte die @-Adresse mit keinem der bekannten Protokolle oder Email-Kontakte abgleichen.";
$a->strings["Use mailto: in front of address to force email check."] = "Verwende mailto: vor der Email Adresse, um eine Überprüfung der E-Mail-Adresse zu erzwingen.";
$a->strings["The profile address specified belongs to a network which has been disabled on this site."] = "Die Adresse dieses Profils gehört zu einem Netzwerk, mit dem die Kommunikation auf dieser Seite ausgeschaltet wurde.";
$a->strings["Limited profile. This person will be unable to receive direct/personal notifications from you."] = "Eingeschränktes Profil. Diese Person wird keine direkten/privaten Nachrichten von Dir erhalten können.";
$a->strings["Unable to retrieve contact information."] = "Konnte die Kontaktinformationen nicht empfangen.";
$a->strings["%s's birthday"] = "%ss Geburtstag";
$a->strings["Happy Birthday %s"] = "Herzlichen Glückwunsch %s";
$a->strings["Starts:"] = "Beginnt:";
$a->strings["Finishes:"] = "Endet:";
$a->strings["all-day"] = "ganztägig";
@ -2040,14 +2066,9 @@ $a->strings["D g:i A"] = "D H:i";
$a->strings["g:i A"] = "H:i";
$a->strings["Show map"] = "Karte anzeigen";
$a->strings["Hide map"] = "Karte verbergen";
$a->strings["A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name."] = "Eine gelöschte Gruppe mit diesem Namen wurde wiederbelebt. Bestehende Berechtigungseinstellungen <strong>könnten</strong> auf diese Gruppe oder zukünftige Mitglieder angewandt werden. Falls Du dies nicht möchtest, erstelle bitte eine andere Gruppe mit einem anderen Namen.";
$a->strings["Default privacy group for new contacts"] = "Voreingestellte Gruppe für neue Kontakte";
$a->strings["Everybody"] = "Alle Kontakte";
$a->strings["edit"] = "bearbeiten";
$a->strings["Edit group"] = "Gruppe bearbeiten";
$a->strings["Contacts not in any group"] = "Kontakte in keiner Gruppe";
$a->strings["Create a new group"] = "Neue Gruppe erstellen";
$a->strings["Edit groups"] = "Gruppen bearbeiten";
$a->strings["%1\$s is attending %2\$s's %3\$s"] = "%1\$s nimmt an %2\$ss %3\$s teil.";
$a->strings["%1\$s is not attending %2\$s's %3\$s"] = "%1\$s nimmt nicht an %2\$ss %3\$s teil.";
$a->strings["%1\$s may attend %2\$s's %3\$s"] = "%1\$s nimmt eventuell an %2\$ss %3\$s teil.";
$a->strings["Requested account is not available."] = "Das angefragte Profil ist nicht vorhanden.";
$a->strings["Edit profile"] = "Profil bearbeiten";
$a->strings["Atom feed"] = "Atom-Feed";
@ -2102,33 +2123,12 @@ $a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Yo
$a->strings["Registration at %s"] = "Registrierung als %s";
$a->strings["\n\t\t\tDear %1\$s,\n\t\t\t\tThank you for registering at %2\$s. Your account has been created.\n\t\t"] = "\nHallo %1\$s,\n\ndanke für Deine Registrierung auf %2\$s. Dein Account wurde eingerichtet.";
$a->strings["\n\t\t\tThe login details are as follows:\n\n\t\t\tSite Location:\t%3\$s\n\t\t\tLogin Name:\t\t%1\$s\n\t\t\tPassword:\t\t%5\$s\n\n\t\t\tYou may change your password from your account \"Settings\" page after logging\n\t\t\tin.\n\n\t\t\tPlease take a few moments to review the other account settings on that page.\n\n\t\t\tYou may also wish to add some basic information to your default profile\n\t\t\t(on the \"Profiles\" page) so that other people can easily find you.\n\n\t\t\tWe recommend setting your full name, adding a profile photo,\n\t\t\tadding some profile \"keywords\" (very useful in making new friends) - and\n\t\t\tperhaps what country you live in; if you do not wish to be more specific\n\t\t\tthan that.\n\n\t\t\tWe fully respect your right to privacy, and none of these items are necessary.\n\t\t\tIf you are new and do not know anybody here, they may help\n\t\t\tyou to make some new and interesting friends.\n\n\t\t\tIf you ever want to delete your account, you can do so at %3\$s/removeme\n\n\t\t\tThank you and welcome to %2\$s."] = "\nDie Anmelde-Details sind die folgenden:\n\tAdresse der Seite:\t%3\$s\n\tBenutzernamename:\t%1\$s\n\tPasswort:\t%5\$s\n\nDu kannst Dein Passwort unter \"Einstellungen\" ändern, sobald Du Dich\nangemeldet hast.\n\nBitte nimm Dir ein paar Minuten um die anderen Einstellungen auf dieser\nSeite zu kontrollieren.\n\nEventuell magst Du ja auch einige Informationen über Dich in Deinem\nProfil veröffentlichen, damit andere Leute Dich einfacher finden können.\nBearbeite hierfür einfach Dein Standard-Profil (über die Profil-Seite).\n\nWir empfehlen Dir, Deinen kompletten Namen anzugeben und ein zu Dir\npassendes Profilbild zu wählen, damit Dich alte Bekannte wieder finden.\nAußerdem ist es nützlich, wenn Du auf Deinem Profil Schlüsselwörter\nangibst. Das erleichtert es, Leute zu finden, die Deine Interessen teilen.\n\nWir respektieren Deine Privatsphäre - keine dieser Angaben ist nötig.\nWenn Du neu im Netzwerk bist und noch niemanden kennst, dann können sie\nallerdings dabei helfen, neue und interessante Kontakte zu knüpfen.\n\nSolltest du dein Nutzerkonto löschen wollen, kannst du dies unter %3\$s/removeme jederzeit tun.\n\nDanke für Deine Aufmerksamkeit und willkommen auf %2\$s.";
$a->strings["Drop Contact"] = "Kontakt löschen";
$a->strings["Organisation"] = "Organisation";
$a->strings["News"] = "Nachrichten";
$a->strings["Forum"] = "Forum";
$a->strings["Connect URL missing."] = "Connect-URL fehlt";
$a->strings["The contact could not be added. Please check the relevant network credentials in your Settings -> Social Networks page."] = "Der Kontakt konnte nicht hinzugefügt werden. Bitte überprüfe die Einstellungen unter Einstellungen -> Soziale Netzwerke";
$a->strings["This site is not configured to allow communications with other networks."] = "Diese Seite ist so konfiguriert, dass keine Kommunikation mit anderen Netzwerken erfolgen kann.";
$a->strings["No compatible communication protocols or feeds were discovered."] = "Es wurden keine kompatiblen Kommunikationsprotokolle oder Feeds gefunden.";
$a->strings["The profile address specified does not provide adequate information."] = "Die angegebene Profiladresse liefert unzureichende Informationen.";
$a->strings["An author or name was not found."] = "Es wurde kein Autor oder Name gefunden.";
$a->strings["No browser URL could be matched to this address."] = "Zu dieser Adresse konnte keine passende Browser URL gefunden werden.";
$a->strings["Unable to match @-style Identity Address with a known protocol or email contact."] = "Konnte die @-Adresse mit keinem der bekannten Protokolle oder Email-Kontakte abgleichen.";
$a->strings["Use mailto: in front of address to force email check."] = "Verwende mailto: vor der Email Adresse, um eine Überprüfung der E-Mail-Adresse zu erzwingen.";
$a->strings["The profile address specified belongs to a network which has been disabled on this site."] = "Die Adresse dieses Profils gehört zu einem Netzwerk, mit dem die Kommunikation auf dieser Seite ausgeschaltet wurde.";
$a->strings["Limited profile. This person will be unable to receive direct/personal notifications from you."] = "Eingeschränktes Profil. Diese Person wird keine direkten/privaten Nachrichten von Dir erhalten können.";
$a->strings["Unable to retrieve contact information."] = "Konnte die Kontaktinformationen nicht empfangen.";
$a->strings["%s's birthday"] = "%ss Geburtstag";
$a->strings["Happy Birthday %s"] = "Herzlichen Glückwunsch %s";
$a->strings["%1\$s is attending %2\$s's %3\$s"] = "%1\$s nimmt an %2\$ss %3\$s teil.";
$a->strings["%1\$s is not attending %2\$s's %3\$s"] = "%1\$s nimmt nicht an %2\$ss %3\$s teil.";
$a->strings["%1\$s may attend %2\$s's %3\$s"] = "%1\$s nimmt eventuell an %2\$ss %3\$s teil.";
$a->strings["Sharing notification from Diaspora network"] = "Freigabe-Benachrichtigung von Diaspora";
$a->strings["Attachments:"] = "Anhänge:";
$a->strings["%s is now following %s."] = "%s folgt nun %s";
$a->strings["following"] = "folgen";
$a->strings["%s stopped following %s."] = "%s hat aufgehört %s zu folgen";
$a->strings["stopped following"] = "wird nicht mehr gefolgt";
$a->strings["Sharing notification from Diaspora network"] = "Freigabe-Benachrichtigung von Diaspora";
$a->strings["Attachments:"] = "Anhänge:";
$a->strings["(no subject)"] = "(kein Betreff)";
$a->strings["Logged out."] = "Abgemeldet.";
$a->strings["Create a New Account"] = "Neues Konto erstellen";
@ -2145,7 +2145,8 @@ $a->strings["This data is required for communication and is passed on to the nod
$a->strings["At any point in time a logged in user can export their account data from the <a href=\"%1\$s/settings/uexport\">account settings</a>. If the user wants to delete their account they can do so at <a href=\"%1\$s/removeme\">%1\$s/removeme</a>. The deletion of the account will be permanent. Deletion of the data will also be requested from the nodes of the communication partners."] = "Angemeldete Nutzer können ihre Nutzerdaten jederzeit von den <a href=\"%1\$s/settings/uexport\">Kontoeinstellungen</a> aus exportieren. Wenn ein Nutzer wünscht das Nutzerkonto zu löschen, so ist dies jederzeit unter <a href=\"%1\$s/removeme\">%1\$s/removeme</a> möglich. Die Löschung des Nutzerkontos ist permanent. Die Löschung der Daten wird auch von den Knoten der Kommunikationspartner angefordert.";
$a->strings["Privacy Statement"] = "Datenschutzerklärung";
$a->strings["This entry was edited"] = "Dieser Beitrag wurde bearbeitet.";
$a->strings["Remove from your stream"] = "Aus deinem Netzwerkstrom entfernen";
$a->strings["Delete globally"] = "Global löschen";
$a->strings["Remove locally"] = "Lokal entfernen";
$a->strings["save to folder"] = "In Ordner speichern";
$a->strings["I will attend"] = "Ich werde teilnehmen";
$a->strings["I will not attend"] = "Ich werde nicht teilnehmen";
@ -2182,5 +2183,5 @@ $a->strings["Delete this item?"] = "Diesen Beitrag löschen?";
$a->strings["show fewer"] = "weniger anzeigen";
$a->strings["No system theme config value set."] = "Es wurde kein Konfigurationswert für das Systemweite Theme gesetzt.";
$a->strings["toggle mobile"] = "auf/von Mobile Ansicht wechseln";
$a->strings["%s: Updating author-id and owner-id in item and thread table. "] = "%s: Aktualisiere die author-id und owner-id in der Thread Tabelle";
$a->strings["Update %s failed. See error logs."] = "Update %s fehlgeschlagen. Bitte Fehlerprotokoll überprüfen.";
$a->strings["%s: Updating author-id and owner-id in item and thread table. "] = "%s: Aktualisiere die author-id und owner-id in der Thread Tabelle";

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More