Merge remote-tracking branch 'upstream/develop' into dfrn-reshare

This commit is contained in:
Michael 2018-04-18 03:12:13 +00:00
commit 88353ce56f
291 changed files with 98692 additions and 89038 deletions

15
.github/issue_template.md vendored Normal file
View file

@ -0,0 +1,15 @@
### Expected behavior
### Actual behavior
### Steps to reproduce the problem
### Friendica version you encountered the problem
see `example.com/friendica` on your Friendica node for the version information.
### Friendica source (git, zip)
### PHP version
### SQL version

3
.gitignore vendored
View file

@ -53,7 +53,8 @@ nbproject
venv/
#ignore Composer dependencies
vendor
/vendor
/view/asset
#ignore config files from JetBrains
/.idea

4
.travis.yml Normal file
View file

@ -0,0 +1,4 @@
---
language: php
php: 5.6
install: composer install

146
CHANGELOG
View file

@ -1,3 +1,129 @@
Version 3.6 (2018-03-23)
Friendica Core:
Updates to the translations (DE, EN_GB, EN_US, ES, FR, IT, ZH_CN) [translation teams]
Updates for the Danish and French regions [Alkarex]
Update for the documentation [andyhee, annando, rabuzarus, ratten, rudloff, silke, tobiasd]
Updates to the themes [Andi-K, annando, fabrixxm, hoergen, rebeka-catalina, rabuzarus]
Enhancements to the ARIA support in frio [rabuzarus]
Enhancements to the DB handling and structure [annando]
Enhancements to the API [annando, fabrixxm, MrPetovan, rudloff]
Enhancements to the support of Open Graph with images [hoergen]
Enhancements to the Diaspora federation (participation signal, relay of dislikes, basic forum support for D*, Birthdays) [annando]
Enhancements to the OStatus federation [annando]
Enhancements to the handling of feed contacts [MrPetovan]
Enhancements to the display of threaded discussions (optional) [MrPetovan]
Enhancements to the display of events [hoergen]
Enhancements to the ACL dialog (selection of forums) [rabuzarus]
Enhancements to the handling of new connections [annando]
Enhancements to the vitality check of contacts [annando]
Enhancements to the daemon script [annando]
Enhancements to the federation stats [annando, tobiasd]
Enhancements to the interaction with public posts [annando]
Enhancements to the structure of the admin panel [tobiasd]
Enhancements to the community page [annando]
Enhancements to the delegation of accounts [annando, MrPetovan]
Enhancements to the user import and server relocation functionality [annando]
Enhancements to the menu layout in the admin panel [tobiasd]
Enhancements to the extraction of strings to be translated [fabrixxm, MrPetovan]
Enhancements to the installation wizard [annando, tobias]
Enhancements to the events [annando, hoergen, MrPetovan, rabuzarus]
Enhancements to the handling of email contacts [annando]
Enhancements to the Vagrant configuration of the development VM [tobias]
Enhancements to the probing of pump.io profiles [annando]
Enhancements to the handling of BBCode tags [MrPetovan]
Enhancements to the OEmbed handling [MrPetovan]
Fixed a bug that triggered the display of activities on the cummunity page [annando]
Fixed a bug with personal notes [annando]
Fixed a display issue of long postings when using the showmore option [annando]
Fixed a bug that caused Twidere to crash on reload [annando]
Fixed a bug in the exported data to the-federation.info [annando]
Fixed a bug in URL completion for feed fragments [annando]
Fixed a bug in the notification system about new registrations [annando]
Fixed the display of dislikes [annando]
Fixed the display of orphans childs in threads [MrPetovan]
Fixed some SQL problems [annando]
Fixed the CLI config script [tobiasd]
Fixed the forum selection on the network display [annando]
Fixed a bug during the import of accounts [annando]
Fixed a problem with UTF8 encoding during account export [annando]
Fixed a problem with archiving "self" contacts [annando]
Fixes to file permissions lintian reported [tobiasd]
Fixed a session problem leading to double login problem [MrPetovan]
Fixed a bug that caused code blocks on Diaspora being displayed wrongly [MrPetovan]
Fixed a bug that suggested it was possible to use some bridges without an account on the other side [annando]
Fixed the situation that an OStatus activity was triggered when publishing a image without sending out a posting for it [annando]
Fixed some issues with the display of exported events on GNU social and diaspora [annando]
Fixed the issue that Atom feeds of forums had no postings listed [annando]
Fixed a problem with the expiration of accounts [annando]
Added Atom feed for conversations [annando]
Added the possibility to address forums with !forumname [annando]
Added option to compare version against upstream version [tobiasd]
Added an optional hint that a global community page is global [tobiasd]
Added an option to always display the preview image in shared articles even if larger ones exist [annando]
Added CLI script to silence accounts on the community page [tobiasd]
Added CLI script to block postings to a node from accounts [tobiasd]
Added account block interface to the admin panel [MrPetovan]
Added browser bookmarklet code snippet [hoergen]
Added an additional feature to display a tag cloud on the profile page [rabuzarus]
Added retrieval of Mastodon server statistics [annando]
Added Atom feed that only contains top level postings of a user [annando]
Added tag following via saved search for #hashtag [annando]
Added PHP version information to the admin panel [MrPetovan]
Added the possibility to change relationships between Friendica contacts [annando]
Added the membersince functionality from the addon to the core [rabuzarus]
Added support of nodeinfo 2.0 [annando]
Removed the long deprecated internal templating engine [annando]
Removed the obsolete mysql support, you have to use MySQLI or PDO [annando]
Removed the unused mood module [annando]
Removed connect link from side panel when it should not be there [annando]
Removed very old updating routines [annando]
Dependencies are now (mostly) handled by composer [MrPetovan, zeroadam]
General code refactoring and beautification work [annando, MrPetovan, tobiasd, zeroadam]
ejabberd logs are now handled by syslog [annando]
Moved the poller script to the "scripts" directory and renamed it to worker [annando]
Threaded display of conversations is now always enabled [annando]
Images send to public forums are now always public as well [annando]
The DB cleanup option now includes the conversation table [annando]
Hash tags now always search locally [annando]
Consistent naming of addons (instead of plugins and addons) [zeroadam]
Community page is split between local and global and always visible for local users [annando]
Updated the credits to include new contributors [tobiasd]
Friendica Addons:
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]
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]
OpenWeatherMap fix broken map link [zeroadam]
CommunityHome added settings to admin panel, removed active users feature [annando, fabrixxm]
General code refactoring and beautification work [annando, MrPetovan, tobiasd, zeroadam]
Public Server reworked [annando]
pageheader settings beautifications [tobiasd]
mailstream settings beautifications [tobiasd]
Membersince is now part of the core [rabuzarus]
Forum posts are not transmitted over the connectors anymore [annando]
Friendica Dir:
Fixed a problem with the maintenance cron [MrPetovan]
Fixed a problem with the location widget [MrPetovan]
Work on the UI [MrPetovan]
Closed Issues:
929, 1050, 1056, 1125, 1215, 1251, 1289, 1312, 1429, 1488, 1540,
1610, 1858, 2786, 2845, 3020, 3039, 3337, 3379, 3394, 3396, 3566,
3583, 3661, 3671, 3680, 3801, 3822, 3824, 3828, 3839, 3855, 3857,
3860, 3863, 3867, 3905, 3911, 3916, 3942, 3946, 3999, 4013, 4020,
4023, 4041, 4042, 4061, 4069, 4070, 4071, 4075, 4078, 4082, 4094,
4105, 4115, 4116, 4137, 4141, 4144, 4150, 4155, 4161, 4163, 4173,
4184, 4199, 4200, 4207, 4227, 4228, 4236, 4251, 4272, 4273, 4278,
4279, 4281, 4290, 4294, 4295, 4296, 4304, 4306, 4319, 4348, 4362,
4368, 4369, 4377, 4390, 4395, 4396, 4409, 4412, 4426, 4431, 4445,
4450, 4452, 4458, 4463, 4481, 4482, 4495, 4497, 4498, 4508, 4518,
4520, 4522, 4535, 4543, 4550, 4555, 4556, 4571, 4575, 4610, 4611,
4620
Version 3.5.4 (2017-10-16)
Friendica Core:
Updates to the translations (DE) [translation teams]
@ -72,7 +198,7 @@ Version 3.5.3 (2017-10-05)
Fixes to buffer, diaspora, libertree, pumpio, gnu social, tumblr, twitter and wppost bridges to redistribute remote_self content [annando]
Fixed a bug in securemail settings form [FuzzJunket]
external poller addons are deprecated, as this is now a core functionality [annando]
Friendica Directory:
Fix a problem with the Vagrant config [tobiasd]
Fix not working node health page [Hypolite]
@ -82,7 +208,7 @@ Version 3.5.3 (2017-10-05)
1257, 2786, 2864, 2872, 2998, 3013, 3018, 3131, 3180, 3234, 3248,
3309, 3313, 3360, 3362, 3391, 3482, 3511, 3512, 3515, 3516, 3529,
3531, 3536, 3545, 3552, 3553, 3560, 3571, 3589, 3592, 3599, 3615,
3616, 3621, 3624, 3636, 3645, 3661, 3684, 3685, 3691, 3696, 3699,
3616, 3621, 3624, 3636, 3645, 3661, 3684, 3685, 3691, 3696, 3699,
3700, 3732
Version 3.5.2 (2017-06-06)
@ -90,7 +216,7 @@ Version 3.5.2 (2017-06-06)
Updates to the translations (DE, EN-GB, EN-US, ES, IT, PT-BR, RU) [translation teams]
Updates to the documentation [annando, beardyunixer, rabuzarus, tobiasd]
Updated the nginx example configuration [beardyunixer]
Code revision and refactoring [annando, hypolite, Quix0r, rebeka-catalina]
Code revision and refactoring [annando, MrPetovan, Quix0r, rebeka-catalina]
Background process is now done by the new worker process [annando]
Added support of Composer for dependencies [Hypolite]
Added support of Web app manifests [Rudloff]
@ -199,8 +325,8 @@ Version 3.5.1 (2017-03-12)
Twitter-bridge now supports quotes and long posts when importing tweets [annando]
Closed Issues
1019, 1163, 1612, 1613, 2103, 2177, 2252, 2260, 2403, 2991, 2614,
2751, 2752, 2772, 2791, 2800, 2804, 2813, 2814, 2816, 2817, 2823,
1019, 1163, 1612, 1613, 2103, 2177, 2252, 2260, 2403, 2991, 2614,
2751, 2752, 2772, 2791, 2800, 2804, 2813, 2814, 2816, 2817, 2823,
2850, 2858, 2865, 2892, 2894, 2895, 2907, 2908, 2914, 2015, 2926,
2948, 2955, 2958, 2963, 2964, 2968, 2987, 2993, 3020, 3052, 3062,
3066, 3091, 3108, 3113, 3116, 3117, 3118, 3126, 3130, 3135, 3155,
@ -304,7 +430,7 @@ Version 3.4.3 (2015-12-22)
Diaspora and OStatus can be enabled only if requirements are satisfied (annando)
Support for additional passwords for ejabberd (annando)
Use proxy for profile photos (annando)
'Reload active themes' in theme admin page (fabrixxm)
'Reload active themes' in theme admin page (fabrixxm)
Install routine checks for ImageMagick and GIF support (fabrixxm)
Install routine checks for availability of "mcrypt_create_iv()" function, needed for RINO2 (fabrixxm)
Only suported themes are shown in admin page (annando)
@ -315,7 +441,7 @@ Version 3.4.3 (2015-12-22)
Show an info message if an empty contact group is shown (issue #1871) (annando)
User setting to disable network page autoupdate (issue #1921) (annando)
Settings to limit or permit access to crawler to search page (annando)
What's new for developers:
What's new for developers:
Themes can show Events entry in navbar (annando)
Themes can now override colorbox (fabrixxm)
Updated Vagrant development VM (silke, hauke)
@ -343,7 +469,7 @@ Version 3.4.3 (2015-12-22)
Fix mention completition popup with TinyMCE (issue #1920) (fabrixxm)
Fix photo cache and proxy when installed in subfolder (ddorian1)
Fix bbcode conversion of the about text for the profile (issue #1607) (annando)
Version 3.4.2 (2015-09-29)
@ -388,8 +514,8 @@ Version 3.4.2 (2015-09-29)
Checks for mcrypt availability before enable or use RINO2 (fabrixm)
Fix following email contacts (issue #1896) (annando)
Parse BBCode in contact request notification email (annando)
Version 3.4.1 (2015-07-06)
Implement server-to-server encryption (RINO) using php-encryption library as "RINO 2", deprecate "RINO 1" (issue #1655) (fabrixxm)

View file

@ -37,10 +37,12 @@ local .htaccess file
- PHP *command line* access with register_argc_argv set to true in the
php.ini file [or see 'poormancron' in section 8]
- curl, gd (with at least jpeg support), mysql, mbstring, xml and openssl extensions
- curl, gd (with at least jpeg support), mysql, mbstring, xml, zip and openssl extensions
- some form of email server or email gateway such that PHP mail() works
- The POSIX module of PHP needs to be activated (e.g. RHEL, CentOS have disabled it)
- Mysql 5.5.3+ or an equivalant alternative for MySQL (MariaDB, Percona Server etc.)
- ability to schedule jobs with cron (Linux/Mac) or Scheduled Tasks
@ -66,7 +68,7 @@ OR
git clone https://github.com/friendica/friendica [web server folder]
cd [web server folder]
php util/composer.phar install
php bin/composer.phar install
3. Create an empty database and note the access details (hostname, username,
password, database name).
@ -113,14 +115,14 @@ tables, so that you can start fresh.
8. Set up a cron job or scheduled task to run the worker once every 5-10
minutes to pick up the recent "public" postings of your friends. Example:
cd /base/directory; /path/to/php scripts/worker.php
cd /base/directory; /path/to/php bin/worker.php
Change "/base/directory", and "/path/to/php" as appropriate for your situation.
If you are using a Linux server, run "crontab -e" and add a line like the
one shown, substituting for your unique paths and settings:
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php scripts/worker.php
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/worker.php
You can generally find the location of PHP by executing "which php". If you
have troubles with this section please contact your hosting provider for
@ -129,24 +131,16 @@ assistance. Friendica will not work correctly if you cannot perform this step.
You should also be sure that $a->config['php_path'] is set correctly, it should
look like (changing it to the correct PHP location)
$a->config['php_path'] = '/usr/local/php53/bin/php'
Alternative: You may be able to use the 'poormancron' addon to perform this
step if you are using a recent Friendica release. 'poormancron' may result in
perfomance and memory issues and is only suitable for small sites with one or
two users and a handful of contacts. To do this, edit the file
".htconfig.php" and look for a line describing your addons. On a fresh
installation, it will look like
$a->config['php_path'] = '/usr/local/php56/bin/php'
$a->config['system']['addon'] = 'js_upload';
Alternative: If you cannot use a cron job as described above, you can use
the frontend worker and an external cron service to trigger the execution
of the worker script. You can enable the frontend worker after the installation
from the admin panel of your node and call
This indicates the "js_upload" addon module is enabled. You may add additional
addons using this same line in the configuration file. Change it to
read
https://example.com/worker
$a->config['system']['addon'] = 'js_upload,poormancron';
and save your changes.
with the service of your choice.
9. (Recommended) Set up a backup plan
@ -293,14 +287,14 @@ cron by using something like
*/10 * * * * cd /var/www/friendica/friendica/ && sudo -u www-data /usr/bin/php
-d suhosin.executor.func.blacklist=none -d suhosin.executor.eval.blacklist=none
-f scripts/worker.php
-f bin/worker.php
This worked well for simple test cases, but the friendica-cron still failed with
a fatal error:
suhosin[22962]: ALERT - function within blacklist called: proc_open() (attacker
'REMOTE_ADDR not set', file '/var/www/friendica/friendica/boot.php', line 1341)
After a while I noticed, that scripts/worker.php calls further php script via
After a while I noticed, that bin/worker.php calls further php script via
proc_open. These scripts themselves also use proc_open and fail, because they
are NOT called with -d suhosin.executor.func.blacklist=none.

View file

@ -27,17 +27,18 @@ The location of the translated files in the source tree is
/view/lang/LNG-CODE/
where LNG-CODE is the language code used, e.g. de for German or fr for French.
The translated strings come as a "message.po" file from transifex which needs to be translated into the PHP file friendica uses.
To do so, place the file in the directory mentioned above and use the "po2php" utility from the util directory of your friendica installation.
To do so, place the file in the directory mentioned above and use the "po2php" command from the console.
*Please note that the console tool has to be called from the base directory of your Friendica installation.*
Assuming you want to convert the German localization which is placed in view/lang/de/message.po you would do the following.
1. Navigate at the command prompt to the base directory of your
friendica installation
2. Execute the po2php script, which will place the translation
2. Execute the po2php command, which will place the translation
in the strings.php file that is used by friendica.
$> php util/po2php.php view/lang/de/messages.po
$> php bin/console.php po2php view/lang/de/messages.po
The output of the script will be placed at view/lang/de/strings.php where
friendica is expecting it, so you can test your translation immediately.
@ -62,7 +63,7 @@ Otherwise your work might get lost, when the translation from Transifex is inclu
Utilities
---------
Additional to the po2php script there are some more utilities for translation in the "util" directory of the friendica source tree.
Additional to the po2php command there are some more utilities for translation in the console.
If you only want to translate friendica into another language you wont need any of these tools most likely but it gives you an idea how the translation process of friendica works.
For further information see the utils/README file.
@ -90,9 +91,9 @@ To update the translation files after you have translated strings of e.g. Espera
$> tx pull -l eo
And then use the `po2php` utility described above to convert the `messages.po` file to the `strings.php` file Friendica is loading.
And then use the `po2php` command described above to convert the `messages.po` file to the `strings.php` file Friendica is loading.
$> php util/po2php.php view/lang/eo/messages.po
$> php bin/console.php po2php view/lang/eo/messages.po
Afterwards, just commit the two changed files to a feature branch of your Friendica repository, push the changes to github and open a pull request for your changes.

View file

@ -1 +1 @@
3.6-dev
2018-05-dev

6
Vagrantfile vendored
View file

@ -17,7 +17,7 @@ Vagrant.configure(2) do |config|
# Create a hostname, don't forget to put it to the `hosts` file
# This will point to the server's default virtual host
# TO DO: Make this work with virtualhost along-side xip.io URL
config.vm.hostname = "friendica.dev"
config.vm.hostname = "friendica.local"
# Create a static IP
config.vm.network :private_network, ip: server_ip
@ -36,8 +36,8 @@ Vagrant.configure(2) do |config|
vb.memory = server_memory
end
# Enable provisioning with a shell script.
config.vm.provision "shell", path: "./util/vagrant_provision.sh"
# Enable provisioning with a shell script.
config.vm.provision "shell", path: "./bin/dev/vagrant_provision.sh"
# run: "always"
# run: "once"
end

View file

@ -13,14 +13,14 @@
* Installation:
*
* - Change it's owner to whichever user is running the server, ie. ejabberd
* $ chown ejabberd:ejabberd /path/to/friendica/scripts/auth_ejabberd.php
* $ chown ejabberd:ejabberd /path/to/friendica/bin/auth_ejabberd.php
*
* - Change the access mode so it is readable only to the user ejabberd and has exec
* $ chmod 700 /path/to/friendica/scripts/auth_ejabberd.php
* $ chmod 700 /path/to/friendica/bin/auth_ejabberd.php
*
* - Edit your ejabberd.cfg file, comment out your auth_method and add:
* {auth_method, external}.
* {extauth_program, "/path/to/friendica/script/auth_ejabberd.php"}.
* {extauth_program, "/path/to/friendica/bin/auth_ejabberd.php"}.
*
* - Restart your ejabberd service, you should be able to login with your friendica auth info
*
@ -33,6 +33,8 @@
*/
use Friendica\App;
use Friendica\BaseObject;
use Friendica\Core\Config;
use Friendica\Util\ExAuth;
if (sizeof($_SERVER["argv"]) == 0) {
@ -53,6 +55,7 @@ require_once "boot.php";
require_once "include/dba.php";
$a = new App(dirname(__DIR__));
BaseObject::setApp($a);
@include ".htconfig.php";
dba::connect($db_host, $db_user, $db_pass, $db_data);

10
bin/console Executable file
View file

@ -0,0 +1,10 @@
#!/bin/bash
dir=$(cd "${0%[/\\]*}" > /dev/null; pwd)
if [[ -d /proc/cygdrive && $(which php) == $(readlink -n /proc/cygdrive)/* ]]; then
# We are in Cgywin using Windows php, so the path must be translated
dir=$(cygpath -m "$dir");
fi
php "${dir}/console.php" "$@"

4
bin/console.bat Executable file
View file

@ -0,0 +1,4 @@
@echo OFF
:: in case DelayedExpansion is on and a path contains !
setlocal DISABLEDELAYEDEXPANSION
php "%~dp0console.php" %*

9
bin/console.php Executable file
View file

@ -0,0 +1,9 @@
#!/usr/bin/env php
<?php
include_once dirname(__DIR__) . '/boot.php';
$a = new Friendica\App(dirname(__DIR__));
\Friendica\BaseObject::setApp($a);
(new Friendica\Core\Console($argv))->execute();

View file

@ -1,7 +1,7 @@
#!/usr/bin/env php
<?php
/**
* @file scripts/daemon.php
* @file bin/daemon.php
* @brief Run the worker from a daemon.
*
* This script was taken from http://php.net/manual/en/function.pcntl-fork.php
@ -104,7 +104,7 @@ while (true) {
set_time_limit(0);
// Call the worker
$cmdline = $php.' scripts/worker.php';
$cmdline = $php.' bin/worker.php';
$executed = false;

View file

@ -1,7 +1,7 @@
#!/bin/bash
#Script to setup the vagrant instance for running friendica
#
#DO NOT RUN on your physical machine as this won't be of any use
#DO NOT RUN on your physical machine as this won't be of any use
#and f.e. deletes your /var/www/ folder!
echo "Friendica configuration settings"
sudo apt-get update
@ -13,6 +13,7 @@ sudo apt-get install virtualbox-guest-x11
echo ">>> Installing *.xip.io self-signed SSL"
SSL_DIR="/etc/ssl/xip.io"
DOMAIN="*.xip.io"
EXTRADOMAIN="friendica.local"
PASSPHRASE="vaprobash"
SUBJ="
C=US
@ -20,6 +21,7 @@ ST=Connecticut
O=Vaprobash
localityName=New Haven
commonName=$DOMAIN
subjectAltName=DNS:$EXTRADOMAIN
organizationalUnitName=
emailAddress=
"
@ -33,18 +35,17 @@ sudo openssl x509 -req -days 365 -in "$SSL_DIR/xip.io.csr" -signkey "$SSL_DIR/xi
echo ">>> Installing Apache2 webserver"
sudo apt-get install -y apache2
sudo a2enmod rewrite actions ssl
sudo cp /vagrant/util/vagrant_vhost.sh /usr/local/bin/vhost
sudo cp /vagrant/bin/dev/vagrant_vhost.sh /usr/local/bin/vhost
sudo chmod guo+x /usr/local/bin/vhost
sudo vhost -s 192.168.22.10.xip.io -d /var/www -p /etc/ssl/xip.io -c xip.io -a friendica-xenial.dev
sudo vhost -s 192.168.22.10.xip.io -d /var/www -p /etc/ssl/xip.io -c xip.io -a friendica.local
sudo a2dissite 000-default
sudo service apache2 restart
#Install php
echo ">>> Installing PHP7"
sudo apt-get install -y php libapache2-mod-php php-cli php-mysql php-curl php-gd php-mbstring php-xml imagemagick php-imagick
sudo apt-get install -y php libapache2-mod-php php-cli php-mysql php-curl php-gd php-mbstring php-xml imagemagick php-imagick php-zip
sudo systemctl restart apache2
#Install mysql
echo ">>> Installing Mysql"
sudo debconf-set-selections <<< "mysql-server mysql-server/root_password password root"
@ -69,8 +70,8 @@ systemctl restart mysql
#configure rudimentary mail server (local delivery only)
#add Friendica accounts for local user accounts, use email address like vagrant@friendica.dev, read the email with 'mail'.
debconf-set-selections <<< "postfix postfix/mailname string friendica-xenial.dev"
#add Friendica accounts for local user accounts, use email address like vagrant@friendica.local, read the email with 'mail'.
debconf-set-selections <<< "postfix postfix/mailname string friendica.local"
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Local Only'"
sudo apt-get install -y postfix mailutils libmailutils-dev
sudo echo -e "friendica1: vagrant\nfriendica2: vagrant\nfriendica3: vagrant\nfriendica4: vagrant\nfriendica5: vagrant" >> /etc/aliases && sudo newaliases
@ -79,19 +80,23 @@ sudo echo -e "friendica1: vagrant\nfriendica2: vagrant\nfriendica3: vagrant\nfri
sudo rm -rf /var/www/
sudo ln -fs /vagrant /var/www
# install deps with composer
sudo apt install unzip
cd /var/www
php bin/composer.phar install
# initial config file for friendica in vagrant
cp /vagrant/util/htconfig.vagrant.php /vagrant/.htconfig.php
# create the friendica database
echo "create database friendica DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci" | mysql -u root -proot
echo "create database friendica DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci" | $MYSQL -u root -proot
# import test database
$MYSQL -uroot -proot friendica < /vagrant/friendica_test_data.sql
# create cronjob - activate if you have enough memory in you dev VM
echo "*/10 * * * * cd /vagrant; /usr/bin/php scripts/worker.php" >> friendicacron
echo "*/10 * * * * cd /vagrant; /usr/bin/php bin/worker.php" >> friendicacron
sudo crontab friendicacron
sudo rm friendicacron
# friendica needs write access to /tmp
sudo chmod 777 /tmp

View file

@ -45,7 +45,7 @@ case "$MODE" in
;;
'default')
cd "$FULLPATH/.."
OUTFILE="$FULLPATH/messages.po"
OUTFILE="$FULLPATH/../util/messages.po"
FINDSTARTDIR="."
# skip addon folder
FINDOPTS="( -wholename */addon -or -wholename */addons-extra -or -wholename */smarty3 ) -prune -o"

View file

@ -1,11 +1,12 @@
#!/usr/bin/env php
<?php
/**
* @file scripts/worker.php
* @file bin/worker.php
* @brief Starts the background processing
*/
use Friendica\App;
use Friendica\BaseObject;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Worker;
@ -26,6 +27,7 @@ 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);
@ -37,7 +39,7 @@ Config::load();
check_db(true);
// Quit when in maintenance
if (Config::get('system', 'maintenance', true)) {
if (Config::get('system', 'maintenance', false, true)) {
return;
}

View file

@ -20,6 +20,7 @@
require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
use Friendica\App;
use Friendica\BaseObject;
use Friendica\Core\Addon;
use Friendica\Core\Cache;
use Friendica\Core\Config;
@ -37,10 +38,10 @@ use Friendica\Util\DateTimeFormat;
require_once 'include/text.php';
define('FRIENDICA_PLATFORM', 'Friendica');
define('FRIENDICA_CODENAME', 'Asparagus');
define('FRIENDICA_VERSION', '3.6-dev');
define('FRIENDICA_CODENAME', 'The Tazmans Flax-lily');
define('FRIENDICA_VERSION', '2018-05-dev');
define('DFRN_PROTOCOL_VERSION', '2.23');
define('DB_UPDATE_VERSION', 1256);
define('DB_UPDATE_VERSION', 1259);
define('NEW_UPDATE_ROUTINE_VERSION', 1170);
/**
@ -211,12 +212,16 @@ define('PAGE_PRVGROUP', 5);
*
* ACCOUNT_TYPE_COMMUNITY - the account is community forum
* Associated page types: PAGE_COMMUNITY, PAGE_PRVGROUP
*
* ACCOUNT_TYPE_RELAY - the account is a relay
* This will only be assigned to contacts, not to user accounts
* @{
*/
define('ACCOUNT_TYPE_PERSON', 0);
define('ACCOUNT_TYPE_ORGANISATION', 1);
define('ACCOUNT_TYPE_NEWS', 2);
define('ACCOUNT_TYPE_COMMUNITY', 3);
define('ACCOUNT_TYPE_RELAY', 4);
/**
* @}
*/
@ -536,6 +541,7 @@ function get_app()
if (empty($a)) {
$a = new App(dirname(__DIR__));
BaseObject::setApp($a);
}
return $a;
@ -947,10 +953,12 @@ function public_contact()
*/
function remote_user()
{
// You cannot be both local and remote
if (local_user()) {
return false;
}
// You cannot be both local and remote.
// Unncommented by rabuzarus because remote authentication to local
// profiles wasn't possible anymore (2018-04-12).
// if (local_user()) {
// return false;
// }
if (x($_SESSION, 'authenticated') && x($_SESSION, 'visitor_id')) {
return intval($_SESSION['visitor_id']);
}

View file

@ -15,6 +15,8 @@
"require": {
"php": ">5.6",
"ext-xml": "*",
"asika/simple-console": "^1.0",
"divineomega/password_exposed": "^2.4",
"ezyang/htmlpurifier": "~4.7.0",
"league/html-to-markdown": "~4.4.1",
"lightopenid/lightopenid": "dev-master",
@ -32,14 +34,15 @@
"npm-asset/jquery-colorbox": "^1.6",
"npm-asset/jquery-datetimepicker": "^2.4.0",
"npm-asset/jgrowl": "^1.4",
"npm-asset/fullcalendar": "^3.0.1"
"npm-asset/fullcalendar": "^3.0.1",
"npm-asset/cropperjs": "1.2.2"
},
"repositories": [
{
"type": "vcs",
"url": "https://github.com/pear/Text_Highlighter"
}
],
{
"type": "vcs",
"url": "https://github.com/pear/Text_Highlighter"
}
],
"autoload": {
"psr-4": {
"Friendica\\": "src/"
@ -53,11 +56,11 @@
"optimize-autoloader": true,
"preferred-install": "dist",
"fxp-asset": {
"installer-paths": {
"npm-asset-library": "vendor/asset",
"bower-asset-library": "vendor/asset"
}
}
"installer-paths": {
"npm-asset-library": "view/asset",
"bower-asset-library": "view/asset"
}
}
},
"archive": {
"exclude": [

747
composer.lock generated
View file

@ -4,8 +4,41 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "3ff4187b4f7167583a3b8caa5f7c2a8a",
"content-hash": "12b8df66213734281765cb6e2c5a786e",
"packages": [
{
"name": "asika/simple-console",
"version": "1.0.3",
"source": {
"type": "git",
"url": "https://github.com/asika32764/php-simple-console.git",
"reference": "0b624c1a999849dc6481a47182e58d593bf65068"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/asika32764/php-simple-console/zipball/0b624c1a999849dc6481a47182e58d593bf65068",
"reference": "0b624c1a999849dc6481a47182e58d593bf65068",
"shasum": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Asika\\SimpleConsole\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Simon Asika",
"email": "asika32764@gmail.com"
}
],
"description": "One file console framework to help you write build scripts.",
"time": "2018-03-08T12:05:40+00:00"
},
{
"name": "bower-asset/Chart-js",
"version": "v2.7.1",
@ -100,6 +133,54 @@
"description": "Minimalistic but perfect custom scrollbar plugin",
"time": "2017-01-10T01:04:09+00:00"
},
{
"name": "divineomega/password_exposed",
"version": "v2.5.1",
"source": {
"type": "git",
"url": "https://github.com/DivineOmega/password_exposed.git",
"reference": "c928bf722eb02398df11076add60df070cb55581"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/DivineOmega/password_exposed/zipball/c928bf722eb02398df11076add60df070cb55581",
"reference": "c928bf722eb02398df11076add60df070cb55581",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^6.3",
"paragonie/certainty": "^1",
"php": ">=5.6",
"rapidwebltd/rw-file-cache-psr-6": "^1.0"
},
"require-dev": {
"fzaninotto/faker": "^1.7",
"phpunit/phpunit": "^5.7",
"satooshi/php-coveralls": "^2.0",
"vimeo/psalm": "^1"
},
"type": "library",
"autoload": {
"psr-4": {
"DivineOmega\\PasswordExposed\\": "src/"
},
"files": [
"src/PasswordExposedFunction.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0-only"
],
"authors": [
{
"name": "Jordan Hall",
"email": "jordan@hall05.co.uk"
}
],
"description": "This PHP package provides a `password_exposed` helper function, that uses the haveibeenpwned.com API to check if a password has been exposed in a data breach.",
"time": "2018-04-02T18:16:36+00:00"
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.7.0",
@ -203,6 +284,187 @@
],
"time": "2017-10-20T06:53:56+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "6.3.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699",
"reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.4",
"php": ">=5.5"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.0 || ^5.0",
"psr/log": "^1.0"
},
"suggest": {
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.2-dev"
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"time": "2017-06-22T18:50:49+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2017-03-20T17:10:46+00:00"
},
{
"name": "league/html-to-markdown",
"version": "4.4.1",
@ -398,6 +660,100 @@
],
"time": "2017-12-18T10:38:51+00:00"
},
{
"name": "npm-asset/cropperjs",
"version": "1.2.2",
"dist": {
"type": "tar",
"url": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.2.2.tgz",
"reference": null,
"shasum": "30dc7a7ce872155b23a33bd10ad4c76c0d613f55"
},
"require-dev": {
"npm-asset/babel-core": ">=6.26.0,<7.0.0",
"npm-asset/babel-plugin-external-helpers": ">=6.22.0,<7.0.0",
"npm-asset/babel-preset-env": ">=1.6.1,<2.0.0",
"npm-asset/cpy-cli": ">=1.0.1,<2.0.0",
"npm-asset/cssnano": ">=3.10.0,<4.0.0",
"npm-asset/del-cli": ">=1.1.0,<2.0.0",
"npm-asset/eslint": ">=4.14.0,<5.0.0",
"npm-asset/eslint-config-airbnb-base": ">=12.1.0,<13.0.0",
"npm-asset/eslint-plugin-import": ">=2.8.0,<3.0.0",
"npm-asset/node-qunit-phantomjs": ">=2.0.0,<3.0.0",
"npm-asset/npm-run-all": ">=4.1.2,<5.0.0",
"npm-asset/postcss-cli": ">=4.1.1,<5.0.0",
"npm-asset/postcss-cssnext": ">=3.0.2,<4.0.0",
"npm-asset/postcss-header": ">=1.0.0,<2.0.0",
"npm-asset/postcss-url": ">=7.3.0,<8.0.0",
"npm-asset/rollup": ">=0.53.3,<0.54.0",
"npm-asset/rollup-plugin-babel": ">=3.0.3,<4.0.0",
"npm-asset/rollup-watch": ">=4.3.1,<5.0.0",
"npm-asset/stylefmt": ">=6.0.0,<7.0.0",
"npm-asset/uglify-js": ">=3.3.4,<4.0.0"
},
"type": "npm-asset-library",
"extra": {
"npm-asset-bugs": {
"url": "https://github.com/fengyuanchen/cropperjs/issues"
},
"npm-asset-files": [
"src",
"dist"
],
"npm-asset-main": "dist/cropper.common.js",
"npm-asset-directories": [],
"npm-asset-repository": {
"type": "git",
"url": "git+https://github.com/fengyuanchen/cropperjs.git"
},
"npm-asset-scripts": {
"build": "npm run build:css && npm run build:js",
"build:css": "postcss src/css/cropper.css -o dist/cropper.css --no-map",
"build:js": "rollup -c",
"clear": "del-cli dist",
"compress": "npm run compress:css && npm run compress:js",
"compress:css": "postcss dist/cropper.css -u cssnano -o dist/cropper.min.css --no-map",
"compress:js": "uglifyjs dist/cropper.js -o dist/cropper.min.js -c -m --comments /^!/",
"copy": "cpy dist/cropper.css docs/css",
"lint": "eslint src/js --fix",
"release": "npm run clear && npm run lint && npm run build && npm run compress && npm run copy && npm test",
"start": "npm-run-all --parallel watch:*",
"test": "node-qunit-phantomjs test/index.html --timeout 10",
"watch:css": "postcss src/css/cropper.css -o docs/css/cropper.css -m -w",
"watch:js": "rollup -c -m -w"
}
},
"license": [
"MIT"
],
"authors": [
{
"name": "Chen Fengyuan",
"url": "http://chenfengyuan.com"
}
],
"description": "JavaScript image cropper.",
"homepage": "https://fengyuanchen.github.io/cropperjs",
"keywords": [
"crop",
"cropper",
"cropper.js",
"cropperjs",
"cropping",
"css",
"development",
"front-end",
"html",
"image",
"javascript",
"move",
"rotate",
"scale",
"web",
"zoom"
],
"time": "2018-01-03T13:39:39+00:00"
},
{
"name": "npm-asset/fullcalendar",
"version": "3.8.2",
@ -937,6 +1293,129 @@
"homepage": "https://github.com/kartik-v/php-date-formatter",
"time": "2016-02-18T15:15:55+00:00"
},
{
"name": "paragonie/certainty",
"version": "v1.0.2",
"source": {
"type": "git",
"url": "https://github.com/paragonie/certainty.git",
"reference": "a2d14f5b0b85c58329dee248d77d34e7e1202a32"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/certainty/zipball/a2d14f5b0b85c58329dee248d77d34e7e1202a32",
"reference": "a2d14f5b0b85c58329dee248d77d34e7e1202a32",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^6",
"paragonie/constant_time_encoding": "^1|^2",
"paragonie/sodium_compat": "^1.6",
"php": "^5.6|^7"
},
"require-dev": {
"phpunit/phpunit": "^5|^6",
"vimeo/psalm": "^1"
},
"bin": [
"bin/certainty-cert-symlink"
],
"type": "library",
"autoload": {
"psr-4": {
"ParagonIE\\Certainty\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com"
}
],
"description": "Up-to-date, verifiable repository for Certificate Authorities",
"keywords": [
"CA-Cert",
"Ed25519",
"Public-Key Infractructure",
"ca",
"ca-cert.pem",
"cacert",
"cacert.pem",
"certificate authority",
"pki",
"ssl",
"tls"
],
"time": "2018-03-12T18:34:23+00:00"
},
{
"name": "paragonie/constant_time_encoding",
"version": "v1.0.2",
"source": {
"type": "git",
"url": "https://github.com/paragonie/constant_time_encoding.git",
"reference": "6111a38faf6fdebc14e36652d22036f379ba58d3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/6111a38faf6fdebc14e36652d22036f379ba58d3",
"reference": "6111a38faf6fdebc14e36652d22036f379ba58d3",
"shasum": ""
},
"require": {
"php": "^5.3|^7"
},
"require-dev": {
"paragonie/random_compat": "^1|^2",
"phpunit/phpunit": "4.*|5.*",
"vimeo/psalm": "^1"
},
"type": "library",
"autoload": {
"psr-4": {
"ParagonIE\\ConstantTime\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com",
"role": "Maintainer"
},
{
"name": "Steve 'Sc00bz' Thomas",
"email": "steve@tobtu.com",
"homepage": "https://www.tobtu.com",
"role": "Original Developer"
}
],
"description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
"keywords": [
"base16",
"base32",
"base32_decode",
"base32_encode",
"base64",
"base64_decode",
"base64_encode",
"bin2hex",
"encoding",
"hex",
"hex2bin",
"rfc4648"
],
"time": "2018-03-10T19:46:06+00:00"
},
{
"name": "paragonie/random_compat",
"version": "v2.0.11",
@ -985,6 +1464,88 @@
],
"time": "2017-09-27T21:40:39+00:00"
},
{
"name": "paragonie/sodium_compat",
"version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/paragonie/sodium_compat.git",
"reference": "1f6e5682eff4a5a6a394b14331a1904f1740e432"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/1f6e5682eff4a5a6a394b14331a1904f1740e432",
"reference": "1f6e5682eff4a5a6a394b14331a1904f1740e432",
"shasum": ""
},
"require": {
"paragonie/random_compat": "^1|^2",
"php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7"
},
"require-dev": {
"phpunit/phpunit": "^3|^4|^5"
},
"suggest": {
"ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.",
"ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security."
},
"type": "library",
"autoload": {
"files": [
"autoload.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"ISC"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com"
},
{
"name": "Frank Denis",
"email": "jedisct1@pureftpd.org"
}
],
"description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists",
"keywords": [
"Authentication",
"BLAKE2b",
"ChaCha20",
"ChaCha20-Poly1305",
"Chapoly",
"Curve25519",
"Ed25519",
"EdDSA",
"Edwards-curve Digital Signature Algorithm",
"Elliptic Curve Diffie-Hellman",
"Poly1305",
"Pure-PHP cryptography",
"RFC 7748",
"RFC 8032",
"Salpoly",
"Salsa20",
"X25519",
"XChaCha20-Poly1305",
"XSalsa20-Poly1305",
"Xchacha20",
"Xsalsa20",
"aead",
"cryptography",
"ecdh",
"elliptic curve",
"elliptic curve cryptography",
"encryption",
"libsodium",
"php",
"public-key cryptography",
"secret-key cryptography",
"side-channel resistant"
],
"time": "2018-02-15T05:50:20+00:00"
},
{
"name": "pear/console_getopt",
"version": "v1.4.1",
@ -1227,6 +1788,190 @@
"homepage": "http://pear.php.net/package/Text_LanguageDetect",
"time": "2017-03-02T16:14:08+00:00"
},
{
"name": "psr/cache",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/cache.git",
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Cache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for caching libraries",
"keywords": [
"cache",
"psr",
"psr-6"
],
"time": "2016-08-06T20:24:11+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "rapidwebltd/rw-file-cache",
"version": "v1.2.5",
"source": {
"type": "git",
"url": "https://github.com/rapidwebltd/RW-File-Cache.git",
"reference": "4a1d5aaefa6ffafec8e2d60787f12bcd9890977e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rapidwebltd/RW-File-Cache/zipball/4a1d5aaefa6ffafec8e2d60787f12bcd9890977e",
"reference": "4a1d5aaefa6ffafec8e2d60787f12bcd9890977e",
"shasum": ""
},
"require": {
"php": ">=5.2.1"
},
"require-dev": {
"phpunit/phpunit": "^5.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"rapidweb\\RWFileCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0-only"
],
"description": "RW File Cache is a PHP File-based Caching Library. Its syntax is designed to closely resemble the PHP memcache extension.",
"homepage": "https://github.com/rapidwebltd/RW-File-Cache",
"keywords": [
"cache",
"caching",
"caching library",
"file cache",
"library",
"php"
],
"time": "2018-01-23T17:20:58+00:00"
},
{
"name": "rapidwebltd/rw-file-cache-psr-6",
"version": "v1.0.0",
"source": {
"type": "git",
"url": "https://github.com/rapidwebltd/RW-File-Cache-PSR-6.git",
"reference": "b74ea201d4c964f0e6db0fb036d1ab28a570df66"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rapidwebltd/RW-File-Cache-PSR-6/zipball/b74ea201d4c964f0e6db0fb036d1ab28a570df66",
"reference": "b74ea201d4c964f0e6db0fb036d1ab28a570df66",
"shasum": ""
},
"require": {
"psr/cache": "^1.0",
"rapidwebltd/rw-file-cache": "^1.2.3"
},
"require-dev": {
"cache/integration-tests": "^0.16.0",
"phpunit/phpunit": "^5.7"
},
"type": "library",
"autoload": {
"psr-4": {
"rapidweb\\RWFileCachePSR6\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-3.0-only"
],
"authors": [
{
"name": "Jordan Hall",
"email": "jordan.hall@rapidweb.biz"
}
],
"description": "PSR-6 adapter for RW File Cache",
"time": "2018-01-30T19:13:45+00:00"
},
{
"name": "smarty/smarty",
"version": "v3.1.31",

View file

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 3.6-dev (Asparagus)
-- DB_UPDATE_VERSION 1256
-- Friendica 2018-05-dev (The Tazmans Flax-lily)
-- DB_UPDATE_VERSION 1259
-- ------------------------------------------
@ -122,9 +122,9 @@ CREATE TABLE IF NOT EXISTS `contact` (
`xmpp` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`attag` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`photo` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`thumb` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`micro` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`photo` varchar(255) DEFAULT '' COMMENT '',
`thumb` varchar(255) DEFAULT '' COMMENT '',
`micro` varchar(255) DEFAULT '' COMMENT '',
`site-pubkey` text COMMENT '',
`issued-id` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`dfrn-id` varchar(255) NOT NULL DEFAULT '' COMMENT '',
@ -397,6 +397,8 @@ CREATE TABLE IF NOT EXISTS `gserver` (
`noscrape` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`network` char(4) NOT NULL DEFAULT '' COMMENT '',
`platform` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`relay-subscribe` boolean NOT NULL DEFAULT '0' COMMENT 'Has the server subscribed to the relay system',
`relay-scope` varchar(10) NOT NULL DEFAULT '' COMMENT 'The scope of messages that the server wants to get',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '',
`last_poco_query` datetime DEFAULT '0001-01-01 00:00:00' COMMENT '',
`last_contact` datetime DEFAULT '0001-01-01 00:00:00' COMMENT '',
@ -405,6 +407,16 @@ CREATE TABLE IF NOT EXISTS `gserver` (
UNIQUE INDEX `nurl` (`nurl`(190))
) DEFAULT COLLATE utf8mb4_general_ci;
--
-- TABLE gserver-tag
--
CREATE TABLE IF NOT EXISTS `gserver-tag` (
`gserver-id` int unsigned NOT NULL DEFAULT 0 COMMENT 'The id of the gserver',
`tag` varchar(100) NOT NULL DEFAULT '' COMMENT 'Tag that the server has subscribed',
PRIMARY KEY(`gserver-id`,`tag`),
INDEX `tag` (`tag`)
) DEFAULT COLLATE utf8mb4_general_ci;
--
-- TABLE hook
--
@ -466,6 +478,7 @@ CREATE TABLE IF NOT EXISTS `item` (
`author-link` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`author-avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`title` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`content-warning` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`body` mediumtext COMMENT '',
`app` varchar(255) NOT NULL DEFAULT '' COMMENT '',
`verb` varchar(100) NOT NULL DEFAULT '' COMMENT '',
@ -1078,3 +1091,4 @@ CREATE TABLE IF NOT EXISTS `workerqueue` (
INDEX `executed` (`executed`)
) DEFAULT COLLATE utf8mb4_general_ci;

View file

@ -1,81 +1,88 @@
Accesskeys in Friendica
Accesskeys reference
=======================
* [Home](help)
For an overview of the modifier key of the different browsers we suggest this [Wikipedia](https://en.wikipedia.org/wiki/Access_key) article.
Access keys are keyboard shortcuts that allow you to easily navigate the user interface.
Access keys are currently not available with the Frio theme.
The specific key combinations depend on how your browser's the modifier key setting.
For an overview of modifier keys in different browsers, have a lookat [Wikipedia](https://en.wikipedia.org/wiki/Access_key) article.
For example, for moving to profile page in Firefox, press these three keys simultaneously.
[Shift] [Alt] [p]
General
-------
* p: profile
* n: network
* c: community
* s: search
* a: admin
* f: notifications
* u: user menu (in themes "vier" and "quattro")
* p - Profile
* n - Network
* c - Community
* s - Search
* a - Admin
* f - Notifications
* u - User menu
/community
../community
--------
* l: Local community
* g: Global community
* l - Local community
* g - Global community
/profile
../profile
--------
* m: Status Messages and Posts
* r: Profile Details
* h: Photo Albums
* v: Videos
* e: Events and Calendar
* t: Personal Notes
* k: View Contacts
* m - Status Messages and Posts
* r - Profile Details
* h - Photo Albums
* v - Videos
* e - Events and Calendar
* t - Personal Notes
* k - View Contacts
/contacts (contact list)
../contacts (contact list)
---------
* g: Suggestions
* l: Show all Contacts
* o: Only show unblocked contacts
* b: Only show blocked contacts
* i: Only show ignored contacts
* y: Only show archived contacts
* h: Only show hidden contacts
* g - Suggestions
* l - Show all Contacts
* o - Only show unblocked contacts
* b - Only show blocked contacts
* i - Only show ignored contacts
* y - Only show archived contacts
* h - Only show hidden contacts
/contacts (single contact view)
../contacts (single contact view)
-------------------------------
* m: Status messages
* o: Profile
* t: Contacts
* d: Common friends
* r: Advanced
* m - Status messages
* o - Profile
* t - Contacts
* d - Common friends
* r - Advanced
/message
../message
--------
* m: New message
* m - New message
/network
../network
--------
* e: Sort by Comment Date
* t: Sort by Post Date
* r: Conversation (Posts that mention or involve you)
* w: New posts
* b: Bookmarks
* m: Favourite Posts
* e - Sort by Comment Date
* t - Sort by Post Date
* r - Conversation (Posts that mention or involve you)
* w - New posts
* b - Bookmarks
* m - Favourite Posts
/notifications
../notifications
--------------
* y: System
* w: Network
* r: Personal
* h: Home
* i: Introductions
* y - System
* w - Network
* r - Personal
* h - Home
* i - Introductions
/settings
../settings
---------
* o: Account
* t: Additional features
* w: Social Networks
* l: Addons
* d: Delegations
* b: Connected apps
* e: Export personal data
* r: Remove account
* o - Account
* t - Additional features
* w - Social Networks
* l - Addons
* d - Delegations
* b - Connected apps
* e - Export personal data
* r - Remove account

View file

@ -7,10 +7,10 @@ Registration
---
Not all Friendica sites allow open registration.
If registration is allowed, you will see a "Register" link immediately below the login prompt on the site home page.
If registration is allowed, you will see a "Register" link immediately below the login prompt on the site's home page.
Following this link will take you to the site registration page.
The strength of our network is that lots of different sites are all completely compatible with each other.
If the site you're visting doesn't allow registration, or you think you might prefer another one, you can find a [list of public servers here](https://dir.friendica.social/servers), and find one that meets your needs.
If the site you're visting doesn't allow registration, or you think you might prefer another one, there is a [list of public servers here](https://dir.friendica.social/servers) and hopefully you will find one that meets your needs.
If you'd like to have your own server, you can do that too.
Visit [the Friendica website](http://friendi.ca/) to download the code with setup instructions.
@ -44,12 +44,12 @@ A nickname is used to generate web addresses for many of your personal pages, an
Due to the way that the nickname is used, it has some limitations.
It must contain only US-ASCII text characters and numbers, and must also start with a text character.
It also must be unique on this system.
This is used in many places to identify your account, and once set - cannot be changed.
This is used in many places to identify your account, and once set it cannot be changed.
###Directory Publishing
The registration form also allows you to choose whether or not to list your account in the online directory.
The registration form also allows you to choose whether or not to list your account in the online directory of your node.
This is like a "phone book" and you may choose to be unlisted.
We recommend that you select 'Yes' so that other people (friends, family, etc.) will be able to find you.
If you choose 'No', you will essentially be invisible and have few opportunities for interaction.
@ -59,7 +59,7 @@ Whichever you choose, this can be changed any time from your Settings page after
Once you have provided the necessary details, click the 'Register' button.
An email will be sent to you providing your account login details.
Please watch your email (including spam folders) for your registration details and initial password.
Please check your email (including spam folders) for your registration details and initial password.
Login Page
---
@ -67,9 +67,9 @@ Login Page
On the 'Login' page, please enter your login information that was provided during registration.
You may use either your nickname or email address as a Login Name.
If you use your account to manage multiple '[Pages](help/Pages)' and these all have the same email address, please enter the nickname for the account you wish to manage.
If you use your account to manage other accounts and these all have the same email address, please enter the nickname for the account you wish to manage.
*If* your account has been OpenID enabled, you may use your OpenID address as a login name and leave the password blank.
If your account has been OpenID enabled, you may use your OpenID address as a login name and leave the password blank.
You will be redirected to your OpenID provider to complete your authorisation.
Otherwise, enter your password.
@ -84,7 +84,7 @@ After your first login, please visit the 'Settings' page from the top menu bar a
Getting Started
---
A ['Tips for New Members'](newmember) link will show up on your network and home pages for two weeks to provide some important Getting Started information.
A link with ['Tips for New Members'](newmember) will show up on your network and home pages for two weeks providing key information for getting started.
Retrieving Personal Data
---
@ -99,6 +99,8 @@ See Also
* [Profiles](help/Profiles)
* [Global Directory](help/Making-Friends#1_1)
* [Groups and Privacy](help/Groups-and-Privacy)
* [Move Account](help/Move-Account)

View file

@ -284,192 +284,221 @@ $b is an array with:
'template' => filename of template
'vars' => array of vars passed to template
### ''acl_lookup_end'
### 'acl_lookup_end'
is called after the other queries have passed.
The registered function can add, change or remove the acl_lookup() variables.
'results' => array of the acl_lookup() vars
### 'prepare_body_init'
Called at the start of prepare_body
Hook data:
'item' => item array (input/output)
### 'prepare_body_content_filter'
Called before the HTML conversion in prepare_body. If the item matches a content filter rule set by an addon, it should
just add the reason to the filter_reasons element of the hook data.
Hook data:
'item' => item array (input)
'filter_reasons' => reasons array (input/output)
### 'prepare_body'
Called after the HTML conversion in prepare_body.
Hook data:
'item' => item array (input)
'html' => converted item body (input/output)
'is_preview' => post preview flag (input)
'filter_reasons' => reasons array (input)
### 'prepare_body_final'
Called at the end of prepare_body.
Hook data:
'item' => item array (input)
'html' => converted item body (input/output)
Complete list of hook callbacks
---
Here is a complete list of all hook callbacks with file locations (as of 14-Feb-2012). Please see the source for details of any hooks not documented above.
boot.php: Addon::callHooks('login_hook',$o);
boot.php: Addon::callHooks('profile_sidebar_enter', $profile);
boot.php: Addon::callHooks('profile_sidebar', $arr);
boot.php: Addon::callHooks("proc_run", $arr);
include/contact_selectors.php: Addon::callHooks('network_to_name', $nets);
include/api.php: Addon::callHooks('logged_in', $a->user);
include/api.php: Addon::callHooks('logged_in', $a->user);
include/queue.php: Addon::callHooks('queue_predeliver', $a, $r);
include/queue.php: Addon::callHooks('queue_deliver', $a, $params);
include/text.php: Addon::callHooks('contact_block_end', $arr);
include/text.php: Addon::callHooks('smilie', $s);
include/text.php: Addon::callHooks('prepare_body_init', $item);
include/text.php: Addon::callHooks('prepare_body', $prep_arr);
include/text.php: Addon::callHooks('prepare_body_final', $prep_arr);
include/nav.php: Addon::callHooks('page_header', $a->page['nav']);
include/auth.php: Addon::callHooks('authenticate', $addon_auth);
include/bbcode.php: Addon::callHooks('bbcode',$Text);
include/oauth.php: Addon::callHooks('logged_in', $a->user);
include/acl_selectors.php: Addon::callHooks($a->module . '_pre_' . $selname, $arr);
include/acl_selectors.php: Addon::callHooks($a->module . '_post_' . $selname, $o);
include/acl_selectors.php: Addon::callHooks('contact_select_options', $x);
include/acl_selectors.php: Addon::callHooks($a->module . '_pre_' . $selname, $arr);
include/acl_selectors.php: Addon::callHooks($a->module . '_post_' . $selname, $o);
include/acl_selectors.php: Addon::callHooks($a->module . '_pre_' . $selname, $arr);
include/acl_selectors.php: Addon::callHooks($a->module . '_post_' . $selname, $o);
include/acl_selectors.php Addon::callHooks('acl_lookup_end', $results);
include/notifier.php: Addon::callHooks('notifier_normal',$target_item);
include/notifier.php: Addon::callHooks('notifier_end',$target_item);
include/items.php: Addon::callHooks('atom_feed', $atom);
include/items.php: Addon::callHooks('atom_feed_end', $atom);
include/items.php: Addon::callHooks('atom_feed_end', $atom);
include/items.php: Addon::callHooks('parse_atom', $arr);
include/items.php: Addon::callHooks('post_remote',$arr);
include/items.php: Addon::callHooks('atom_author', $o);
include/items.php: Addon::callHooks('atom_entry', $o);
include/bb2diaspora.php: Addon::callHooks('bb2diaspora',$Text);
include/cronhooks.php: Addon::callHooks('cron', $d);
include/security.php: Addon::callHooks('logged_in', $a->user);
include/html2bbcode.php: Addon::callHooks('html2bbcode', $text);
include/Contact.php: Addon::callHooks('remove_user',$r[0]);
include/Contact.php: Addon::callHooks('contact_photo_menu', $args);
include/conversation.php: Addon::callHooks('conversation_start',$cb);
include/conversation.php: Addon::callHooks('render_location',$locate);
include/conversation.php: Addon::callHooks('display_item', $arr);
include/conversation.php: Addon::callHooks('render_location',$locate);
include/conversation.php: Addon::callHooks('display_item', $arr);
include/conversation.php: Addon::callHooks('item_photo_menu', $args);
include/conversation.php: Addon::callHooks('jot_tool', $jotplugins);
include/conversation.php: Addon::callHooks('jot_networks', $jotnets);
Here is a complete list of all hook callbacks with file locations (as of 01-Apr-2018). Please see the source for details of any hooks not documented above.
index.php: Addon::callHooks('init_1');
index.php: Addon::callHooks('app_menu', $arr);
index.php: Addon::callHooks('page_content_top', $a->page['content']);
index.php: Addon::callHooks($a->module.'_mod_init', $placeholder);
index.php: Addon::callHooks($a->module.'_mod_init', $placeholder);
index.php: Addon::callHooks($a->module.'_mod_post', $_POST);
index.php: Addon::callHooks($a->module.'_mod_afterpost', $placeholder);
index.php: Addon::callHooks($a->module.'_mod_content', $arr);
index.php: Addon::callHooks($a->module.'_mod_aftercontent', $arr);
index.php: Addon::callHooks('page_end', $a->page['content']);
index.php:Addon::callHooks('app_menu', $arr);
include/api.php: Addon::callHooks('logged_in', $a->user);
include/api.php: Addon::callHooks('authenticate', $addon_auth);
include/api.php: Addon::callHooks('logged_in', $a->user);
index.php:Addon::callHooks('page_end', $a->page['content']);
include/enotify.php: Addon::callHooks('enotify', $h);
include/enotify.php: Addon::callHooks('enotify_store', $datarray);
include/enotify.php: Addon::callHooks('enotify_mail', $datarray);
include/enotify.php: Addon::callHooks('check_item_notification', $notification_data);
mod/photos.php: Addon::callHooks('photo_post_init', $_POST);
include/conversation.php: Addon::callHooks('conversation_start', $cb);
include/conversation.php: Addon::callHooks('render_location', $locate);
include/conversation.php: Addon::callHooks('display_item', $arr);
include/conversation.php: Addon::callHooks('display_item', $arr);
include/conversation.php: Addon::callHooks('item_photo_menu', $args);
include/conversation.php: Addon::callHooks('jot_tool', $jotplugins);
mod/photos.php: Addon::callHooks('photo_post_file',$ret);
include/security.php: Addon::callHooks('logged_in', $a->user);
mod/photos.php: Addon::callHooks('photo_post_end',$foo);
include/text.php: Addon::callHooks('contact_block_end', $arr);
include/text.php: Addon::callHooks('poke_verbs', $arr);
include/text.php: Addon::callHooks('prepare_body_init', $item);
include/text.php: Addon::callHooks('prepare_body_content_filter', $hook_data);
include/text.php: Addon::callHooks('prepare_body', $hook_data);
include/text.php: Addon::callHooks('prepare_body_final', $hook_data);
mod/photos.php: Addon::callHooks('photo_post_end',$foo);
include/items.php: Addon::callHooks('page_info_data', $data);
mod/photos.php: Addon::callHooks('photo_post_end',$foo);
mod/photos.php: Addon::callHooks('photo_post_end',intval($item_id));
mod/photos.php: Addon::callHooks('photo_upload_form',$ret);
mod/friendica.php: Addon::callHooks('about_hook', $o);
mod/editpost.php: Addon::callHooks('jot_tool', $jotplugins);
mod/editpost.php: Addon::callHooks('jot_networks', $jotnets);
mod/parse_url.php: Addon::callHooks('parse_link', $arr);
mod/home.php: Addon::callHooks('home_init',$ret);
mod/home.php: Addon::callHooks("home_content",$o);
mod/contacts.php: Addon::callHooks('contact_edit_post', $_POST);
mod/contacts.php: Addon::callHooks('contact_edit', $arr);
mod/settings.php: Addon::callHooks('addon_settings_post', $_POST);
mod/settings.php: Addon::callHooks('connector_settings_post', $_POST);
mod/settings.php: Addon::callHooks('settings_post', $_POST);
mod/settings.php: Addon::callHooks('addon_settings', $settings_addons);
mod/settings.php: Addon::callHooks('connector_settings', $settings_connectors);
mod/settings.php: Addon::callHooks('settings_form',$o);
mod/register.php: Addon::callHooks('register_account', $newuid);
mod/like.php: Addon::callHooks('post_local_end', $arr);
mod/directory.php: Addon::callHooks('directory_item', $arr);
mod/xrd.php: Addon::callHooks('personal_xrd', $arr);
mod/item.php: Addon::callHooks('post_local_start', $_REQUEST);
mod/ping.php: Addon::callHooks('network_ping', $arr);
mod/item.php: Addon::callHooks('post_local',$datarray);
mod/parse_url.php: Addon::callHooks("parse_link", $arr);
mod/item.php: Addon::callHooks('post_local_end', $datarray);
mod/manage.php: Addon::callHooks('home_init', $ret);
mod/profile.php: Addon::callHooks('profile_advanced',$o);
mod/acl.php: Addon::callHooks('acl_lookup_end', $results);
mod/network.php: Addon::callHooks('network_content_init', $arr);
mod/network.php: Addon::callHooks('network_tabs', $arr);
mod/friendica.php: Addon::callHooks('about_hook', $o);
mod/subthread.php: Addon::callHooks('post_local_end', $arr);
mod/profiles.php: Addon::callHooks('profile_post', $_POST);
mod/profiles.php: Addon::callHooks('profile_edit', $arr);
mod/profiles.php: Addon::callHooks('profile_edit', $arr);
mod/settings.php: Addon::callHooks('addon_settings_post', $_POST);
mod/settings.php: Addon::callHooks('connector_settings_post', $_POST);
mod/settings.php: Addon::callHooks('display_settings_post', $_POST);
mod/settings.php: Addon::callHooks('settings_post', $_POST);
mod/settings.php: Addon::callHooks('addon_settings', $settings_addons);
mod/settings.php: Addon::callHooks('connector_settings', $settings_connectors);
mod/settings.php: Addon::callHooks('display_settings', $o);
mod/settings.php: Addon::callHooks('settings_form', $o);
mod/photos.php: Addon::callHooks('photo_post_init', $_POST);
mod/photos.php: Addon::callHooks('photo_post_file', $ret);
mod/photos.php: Addon::callHooks('photo_post_end', $foo);
mod/photos.php: Addon::callHooks('photo_post_end', $foo);
mod/photos.php: Addon::callHooks('photo_post_end', $foo);
mod/photos.php: Addon::callHooks('photo_post_end', $foo);
mod/photos.php: Addon::callHooks('photo_post_end', intval($item_id));
mod/photos.php: Addon::callHooks('photo_upload_form', $ret);
mod/profile.php: Addon::callHooks('profile_advanced', $o);
mod/home.php: Addon::callHooks('home_init', $ret);
mod/home.php: Addon::callHooks("home_content", $content);
mod/poke.php: Addon::callHooks('post_local_end', $arr);
mod/contacts.php: Addon::callHooks('contact_edit_post', $_POST);
mod/contacts.php: Addon::callHooks('contact_edit', $arr);
mod/tagger.php: Addon::callHooks('post_local_end', $arr);
mod/cb.php: Addon::callHooks('cb_init');
mod/lockview.php: Addon::callHooks('lockview_content', $item);
mod/cb.php: Addon::callHooks('cb_post', $_POST);
mod/uexport.php: Addon::callHooks('uexport_options', $options);
mod/cb.php: Addon::callHooks('cb_afterpost');
mod/register.php: Addon::callHooks('register_post', $arr);
mod/register.php: Addon::callHooks('register_form', $arr);
mod/cb.php: Addon::callHooks('cb_content', $o);
mod/item.php: Addon::callHooks('post_local_start', $_REQUEST);
mod/item.php: Addon::callHooks('post_local', $datarray);
mod/item.php: Addon::callHooks('post_local_end', $datarray);
mod/directory.php: Addon::callHooks('directory_item', $arr);
mod/editpost.php: Addon::callHooks('jot_tool', $jotplugins);
src/Model/Item.php Addon::callHooks('tagged', $arr);
src/Network/FKOAuth1.php: Addon::callHooks('logged_in', $a->user);
src/Render/FriendicaSmartyEngine.php: Addon::callHooks("template_vars", $arr);
src/Model/Item.php: Addon::callHooks('post_local', $item);
src/Model/Item.php: Addon::callHooks('post_remote', $item);
src/Model/Item.php: Addon::callHooks('post_local_end', $posted_item);
src/Model/Item.php: Addon::callHooks('post_remote_end', $posted_item);
src/Model/Item.php: Addon::callHooks('tagged', $arr);
src/Model/Item.php: Addon::callHooks('post_local_end', $new_item);
src/Model/Contact.php: Addon::callHooks('contact_photo_menu', $args);
src/Model/Contact.php: Addon::callHooks('follow', $arr);
src/Model/Profile.php: Addon::callHooks('profile_sidebar_enter', $profile);
src/Model/Profile.php: Addon::callHooks('profile_sidebar', $arr);
src/Model/Profile.php: Addon::callHooks('profile_tabs', $arr);
src/Model/Profile.php: Addon::callHooks('zrl_init', $arr);
src/Model/Event.php: Addon::callHooks('event_updated', $event['id']);
src/Model/Event.php: Addon::callHooks("event_created", $event['id']);
src/Model/User.php: Addon::callHooks('register_account', $uid);
src/Model/User.php: Addon::callHooks('remove_user', $user);
src/Content/Text/BBCode.php: Addon::callHooks('bbcode', $text);
src/Content/Text/BBCode.php: Addon::callHooks('bb2diaspora', $text);
src/Content/Text/HTML.php: Addon::callHooks('html2bbcode', $message);
src/Content/Smilies.php: Addon::callHooks('smilie', $params);
src/Content/Feature.php: Addon::callHooks('isEnabled', $arr);
src/Content/Feature.php: Addon::callHooks('get', $arr);
src/Content/ContactSelector.php: Addon::callHooks('network_to_name', $nets);
src/Content/ContactSelector.php: Addon::callHooks('gender_selector', $select);
src/Content/ContactSelector.php: Addon::callHooks('sexpref_selector', $select);
src/Content/ContactSelector.php: Addon::callHooks('marital_selector', $select);
src/Content/OEmbed.php: Addon::callHooks('oembed_fetch_url', $embedurl, $j);
src/Content/Nav.php: Addon::callHooks('page_header', $a->page['nav']);
src/Content/Nav.php: Addon::callHooks('nav_info', $nav);
src/Worker/Directory.php: Addon::callHooks('globaldir_update', $arr);
src/Worker/Notifier.php: Addon::callHooks('notifier_end', $target_item);
src/Worker/Queue.php: Addon::callHooks('queue_predeliver', $r);
src/Worker/Queue.php: Addon::callHooks('queue_deliver', $params);
src/Module/Login.php: Addon::callHooks('authenticate', $addon_auth);
src/Module/Login.php: Addon::callHooks('login_hook', $o);
src/Module/Logout.php: Addon::callHooks("logging_out");
src/Object/Post.php: Addon::callHooks('render_location', $locate);
src/Object/Post.php: Addon::callHooks('display_item', $arr);
src/Core/ACL.php: Addon::callHooks('contact_select_options', $x);
src/Core/ACL.php: Addon::callHooks($a->module.'_pre_'.$selname, $arr);
src/Core/ACL.php: Addon::callHooks($a->module.'_post_'.$selname, $o);
src/Core/ACL.php: Addon::callHooks($a->module.'_pre_'.$selname, $arr);
src/Core/ACL.php: Addon::callHooks($a->module.'_post_'.$selname, $o);
src/Core/ACL.php: Addon::callHooks('jot_networks', $jotnets);
src/Core/Worker.php: Addon::callHooks("proc_run", $arr);
src/Util/Emailer.php: Addon::callHooks('emailer_send_prepare', $params);
src/Util/Emailer.php: Addon::callHooks("emailer_send", $hookdata);
src/Util/Map.php: Addon::callHooks('generate_map', $arr);
src/Util/Map.php: Addon::callHooks('generate_named_map', $arr);
src/Util/Map.php: Addon::callHooks('Map::getCoordinates', $arr);
src/Util/Network.php: Addon::callHooks('avatar_lookup', $avatar);
src/Util/ParseUrl.php: Addon::callHooks("getsiteinfo", $siteinfo);
src/Protocol/DFRN.php: Addon::callHooks('atom_feed_end', $atom);
src/Protocol/DFRN.php: Addon::callHooks('atom_feed_end', $atom);

View file

@ -12,7 +12,7 @@ It's a command-line tool that downloads required libraries into the `vendor` fol
## How to use Composer
If you don't have Composer installed on your system, Friendica ships with a copy of it at `util/composer.phar`.
If you don't have Composer installed on your system, Friendica ships with a copy of it at `bin/composer.phar`.
For the purpose of this help, all examples will use this path to run Composer commands, however feel free to replace them with your own way of calling Composer.
Composer requires PHP CLI and the following examples assume it's available system-wide.
@ -30,7 +30,7 @@ Here are the typical commands you will have to run to do so:
````
~> git clone https://github.com/friendica/friendica.git friendica
~/friendica> cd friendica
~/friendica> util/composer.phar install
~/friendica> bin/composer.phar install
````
That's it! Composer will take care of fetching all the required libraries in the `vendor` folder and build the autoloader to make those libraries available to Friendica.
@ -42,7 +42,7 @@ Updating Friendica to the current stable or the latest develop version is easy w
````
~> cd friendica
~/friendica> git pull
~/friendica> util/composer.phar install
~/friendica> bin/composer.phar install
````
And that's it. If any library used by Friendica has been upgraded, Composer will fetch the version currently used by Friendica and refresh the autoloader to ensure the best performances.
@ -87,13 +87,13 @@ Or you can specify the exact version of the library if you code requires it, and
To add a library, just add its Packagist identifier to the `require` list and set a target version string.
Then you should run `util/composer.phar update` to add it to your local `vendor` folder and update the `composer.lock` file that specifies the current versions of the dependencies.
Then you should run `bin/composer.phar update` to add it to your local `vendor` folder and update the `composer.lock` file that specifies the current versions of the dependencies.
#### Updating an existing dependency
If a package needs to be updated, whether to the next minor version or to the next major version provided you changed the adequate code in Friendica, simply edit `composer.json` to update the target version string of the relevant library.
Then you should run `util/composer.phar update` to update it in your local `vendor` folder and update the `composer.lock` file that specifies the current versions of the dependencies.
Then you should run `bin/composer.phar update` to update it in your local `vendor` folder and update the `composer.lock` file that specifies the current versions of the dependencies.
Please note that you should commit both `composer.json` and `composer.lock` with your work every time you make a change to the former.
@ -111,7 +111,7 @@ This is because `sudo` doesn't always change the `HOME` environment variable, wh
However, you can temporarily change environment variable for the execution of a single command.
For Composer, this would be:
````
$> COMPOSER_HOME=/var/tmp/composer sudo -u [web user] util/composer.phar [mode]
$> COMPOSER_HOME=/var/tmp/composer sudo -u [web user] bin/composer.phar [mode]
````
## Related

View file

@ -94,7 +94,7 @@ Please remove all the `require_once` mentions of the former file, as they will p
## Miscellaneous tips
When you are done with moving the class, please run `php util/typo.php` from the Friendica base directory to check for obvious mistakes.
When you are done with moving the class, please run `php bin/console.php typo` from the Friendica base directory to check for obvious mistakes.
Howevever, this tool isn't bullet-proof, and a staging install of Friendica is recommended to test your class move without impairing your production server if you host one.
Most of Friendica processes are run in the background, so make sure to turn on your debug log to check for errors that wouldn't show up while simply browsing Friendica.

View file

@ -16,7 +16,6 @@ Whether you feel like an expert or like a newbie - join us with your ideas!
The discussion of Friendica development takes place in the following Friendica forums:
* The main [forum for Friendica development](https://forum.friendi.ca/profile/developers)
* The [forum for Friendica theme development](https://friendica.eu/profile/ftdevs)
## Help other users
@ -61,7 +60,7 @@ If you want to have git automatically update the dependencies with composer, you
}
# `composer install` if the `composer.lock` file gets changed
# to update all the php dependencies
check_run composer.lock "util/composer.phar install --no-dev"
check_run composer.lock "bin/composer.phar install --no-dev"
just place it into `.git/hooks/post-merge` and make it executable.
@ -141,7 +140,7 @@ If you want to get involved here:
* Look at the first steps that were made (e.g. the clean theme).
Ask us to find out whom to talk to about their experiences.
* Talk to design people if you know any.
* Let us know about your plans [in the dev forum](https://forum.friendi.ca/profile/developers) or the [theme developer forum](https://friendica.eu/profile/ftdevs).
* Let us know about your plans [in the dev forum](https://forum.friendi.ca/profile/developers)
Do not worry about cross-posting.
### Client software

View file

@ -30,7 +30,7 @@ User
SSL (Secure Socket Layer) is a technology to encrypt data transfer between computers.
Sometimes your browser warns you about a missing or invalid certificate.
These warnings can have three reasons:
These warnings can have three reasons:
1. The server you are connected to doesn't offer SSL encryption.
2. The server has a self-signed certificate (not recommended).
@ -49,8 +49,8 @@ Generally, you can attach any kind of file to a post.
This is possible by using the "paper-clip"-symbol in the editor.
These files will be linked to your post and can be downloaded by your contacts.
But it's not possible to get a preview for these items.
Because of this, this upload method is only recommended for office or zipped files.
If you want to share content from Dropbox, Owncloud or any other [filehoster](http://en.wikipedia.org/wiki/Comparison_of_file_hosting_services), use the "link"-button (chain-symbol).
Because of this, this upload method is only recommended for office or zipped files.
If you want to share content from Dropbox, Owncloud or any other [filehoster](http://en.wikipedia.org/wiki/Comparison_of_file_hosting_services), use the "link"-button (chain-symbol).
When you're adding URLs of other webpages with the "link"-button, Friendica tries to create a small preview.
If this doesn't work, try to add the link by typing: [url=http://example.com]*self-chosen name*[/url].
@ -58,9 +58,9 @@ If this doesn't work, try to add the link by typing: [url=http://example.com]*se
You can also add video and audio files to posts.
However, instead of a direct upload you have to use one of the following methods:
1. Add the video or audio link of a hoster (Youtube, Vimeo, Soundcloud and anyone else with oembed/opengraph-support). Videos will be shown with a preview image you can click on to start. SoundCloud directly inserts a player to your post.
1. Add the video or audio link of a hoster (Youtube, Vimeo, Soundcloud and anyone else with oembed/opengraph-support). Videos will be shown with a preview image you can click on to start. SoundCloud directly inserts a player to your post.
2. If you have your own server, you can upload multimedia files via FTP and insert the URL.
2. If you have your own server, you can upload multimedia files via FTP and insert the URL.
Friendica uses HTML5 for embedding content.
Therefore, the supported files are dependent on your browser and operating system.
@ -70,7 +70,8 @@ See Wikipedia for more of them ([video](http://en.wikipedia.org/wiki/HTML5_video
<a name="avatars"></a>
### Is it possible to have different avatars per profile?
Yes. On your Edit/Manage Profiles page, you will find a "change profile photo" link.
Yes.
On your Edit/Manage Profiles page, you will find a "change profile photo" link.
Clicking this will take you to a page where you can upload a photograph and select which profile it will be associated with.
To avoid privacy leakage, we only display the photograph associated with your default profile as the avatar in your posts.
@ -111,15 +112,9 @@ After that, your account is deleted.
<a name="hashtag"></a>
### Can I follow a hashtag?
No. The act of 'following' a hashtags is an interesting technology, but presents a few issues.
1. Posts would have to be copied to all sites on the network that are "listening" to that hashtag. This would increase the storage demands to the detriment of small sites. It would make the use of shared hosting practically impossible.
2. Making spam easy (tag spam is a serious issue on Twitter for instance)
3. It creates a natural bias towards large sites which hold more tagged content - if your network uses tagging instead of other conversation federation mechanisms such as groups/forums.
Instead, we offer other mechanisms for wide-area conversations while retaining a 'level playing ground' for both large and small sites, such as forums and community pages and shared tags.
Yes. Simply add the hash tag to your saved searches.
The posts will appear on your network page.
For technical reasons, your answers to such posts won't appear on the "personal" tab in the network page and the whole thread isn't accessible via the API.
<a name="rss"></a>
### How to create a RSS feed of the stream?
@ -130,16 +125,16 @@ If you want to share your public page via rss you can use one of the following l
basic-url.com//feed/[nickname]/posts
Example: Friendica Support
Example: Friendica Support
https://forum.friendi.ca/feed/helpers/posts
#### RSS feed of the conversations at your site
basic-url.com/feed/profilename/comments
Example: Friendica Support
Example: Friendica Support
https://forum.friendi.ca/feed/helpers/comments
<a name="clients"></a>
@ -171,10 +166,15 @@ Depending on the features of the client you might encounter some glitches in usa
### Where I can find help?
If you have problems with your Friendica page, you can ask the community at the [Friendica Support Group](https://forum.friendi.ca/profile/helpers).
If you can't use your default profile you can use an account at a public site [list](https://dir.friendica.social/servers) or you can use the Librelist mailing list.
If you want to use the mailing list, please just send a mail to friendica AT librelist DOT com.
If you can't use your default profile you can use an account at a public site [list](https://dir.friendica.social/servers).
If you are a theme developer, you will find help at this forum: [Friendica Theme Developers](https://friendica.eu/profile/ftdevs).
In case you do not want to set up another account on Friendica, you can also use one of the following channels to reach out for help:
* [Friendica Support Forum](https://forum.friendi.ca/~helpers)
* [Mailing List Archive](http://mailman.friendi.ca/mailman/listinfo/support-friendi.ca) you can subscribe to the list by sending an email to ``support-request(at)friendi.ca?subject=subscribe``
* XMPP/Jabber MUC: support(at)forum.friendi.ca
* IRC: #friendica at irc.freenode.net
* Matrix: #friendi.ca or #friendica at matrix.org
Admin
--------
@ -192,7 +192,7 @@ There you will always find the current stable version of friendica.
Addons are listed at [this page](https://github.com/friendica/friendica-addons).
If you are searching for new themes, you can find them at [Friendica-Themes.com](http://friendica-themes.com/)
If you are searching for new themes, you can find them at [Friendica-Themes.com](http://friendica-themes.com/)
<a name="adminaccount1"></a>
### I've changed my email address now the admin panel is gone?
@ -213,8 +213,8 @@ The listed emails need to be separated by a comma.
Please have a look at the Admin panel under [DB updates](/admin/dbsync/) and follow the link to *check database structure*.
This will start a background process to check if the structure is up to the current definition.
You can manually execute the structure update from the CLI in the base directory of your Friendica installation by running the following script:
You can manually execute the structure update from the CLI in the base directory of your Friendica installation by running the following command:
scripts/dbstructure.php update
bin/console dbstructure update
if there occur any errors, please contact the [support forum](https://forum.friendi.ca/profile/helpers).

View file

@ -13,7 +13,7 @@ Introduction to the workflow with our GitHub repository
3. Fork the Friendica repository from [https://github.com/friendica/friendica.git](https://github.com/friendica/friendica.git).
4. Clone your fork from your GitHub account to your machine.
Follow the instructions provided here: [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/) to create and use your own tracking fork on GitHub
5. Run `util/composer.phar install` in Friendica's folder.
5. Run `bin/composer.phar install` in Friendica's folder.
6. Commit your changes to your fork.
Then go to your GitHub page and create a "Pull request" to notify us to merge your work.
@ -68,7 +68,9 @@ If possible get an experienced Friendica developer to review the code.
Don't hesitate to ask us in case of doubt.
3. Check your code for typos.
There is a PHP script in the *util* directory called *typos.php* for this.
There is a console command called *typo* for this.
$> php bin/console.php typo
Check out how to work with [our Vagrant](help/Vagrant) to save a lot of setup time!

View file

@ -28,7 +28,8 @@ Requirements
* Apache with mod-rewrite enabled and "Options All" so you can use a local .htaccess file
* PHP 5.6+ (PHP 7 is recommended for performance)
* PHP *command line* access with register_argc_argv set to true in the php.ini file
* Curl, GD, PDO, MySQLi, hash, xml and OpenSSL extensions
* Curl, GD, PDO, MySQLi, hash, xml, zip and OpenSSL extensions
* The POSIX module of PHP needs to be activated (e.g. [RHEL, CentOS](http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7) have disabled it)
* some form of email server or email gateway such that PHP mail() works
* Mysql 5.5.3+ or an equivalant alternative for MySQL (MariaDB, Percona Server etc.)
* the ability to schedule jobs with cron (Linux/Mac) or Scheduled Tasks (Windows) (Note: other options are presented in Section 7 of this document.)
@ -38,7 +39,7 @@ Requirements
Installation procedure
---
###Get Friendica
### Get Friendica
Unpack the Friendica files into the root of your web server document area.
If you are able to do so, we recommend using git to clone the source repository rather than to use a packaged tar or zip file.
@ -47,7 +48,7 @@ The Linux commands to clone the repository into a directory "mywebsite" would be
git clone https://github.com/friendica/friendica.git mywebsite
cd mywebsite
util/composer.phar install
bin/composer.phar install
Make sure the folder *view/smarty3* exists and is writable by the webserver user
@ -64,7 +65,7 @@ Clone the addon repository (separately):
If you copy the directory tree to your webserver, make sure that you also copy .htaccess - as "dot" files are often hidden and aren't normally copied.
###Create a database
### Create a database
Create an empty database and note the access details (hostname, username, password, database name).
@ -79,7 +80,7 @@ In this case find the [mysqld] section in your my.cnf file and add the line :
Restart mysql and you should be fine.
###Run the installer
### Run the installer
Point your web browser to the new site and follow the instructions.
Please note any error messages and correct these before continuing.
@ -96,19 +97,19 @@ Registration errors should all be recoverable automatically.
If you get any *critical* failure at this point, it generally indicates the database was not installed correctly.
You might wish to move/rename .htconfig.php to another name and empty (called 'dropping') the database tables, so that you can start fresh.
###Set up the worker
### Set up the worker
Set up a cron job or scheduled task to run the worker once every 5-10 minutes in order to perform background processing.
Example:
cd /base/directory; /path/to/php scripts/worker.php
cd /base/directory; /path/to/php bin/worker.php
Change "/base/directory", and "/path/to/php" as appropriate for your situation.
If you are using a Linux server, run "crontab -e" and add a line like the
one shown, substituting for your unique paths and settings:
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php scripts/worker.php
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/worker.php
You can generally find the location of PHP by executing "which php".
If you run into trouble with this section please contact your hosting provider for assistance.
@ -118,7 +119,8 @@ If it is not possible to set up a cron job then please activate the "frontend wo
Once you have installed Friendica and created an admin account as part of the process, you can access the admin panel of your installation and do most of the server wide configuration from there
###Set up a backup plan
### Set up a backup plan
Bad things will happen.
Let there be a hardware failure, a corrupted database or whatever you can think of.
So once the installation of your Friendica node is done, you should make yourself a backup plan.

View file

@ -3,21 +3,23 @@ Making Friends
* [Home](help)
Friendship in Friendica can take on a great many different meanings.
But let's keep it simple, you want to be friends with somebody.
Friendship in Friendica can sometimes take on different meaning.
But let's keep it simple; you want to be friends with somebody.
How do you do it?
The Directories
---
Friendica has two different kinds of "address book":
The directory of the Friendica server you are registered on and the global directory that collects account information across all Friendica instances.
Friendica has two different kinds of "address book".
The directory of the Friendica server you are registered on and a global directory to which your and other Friendica servers submit account information.
The first thing you can do is look at the **Directory**.
The directory is split up into two parts.
If you click the directory button, you will be presented with a list of all members (who chose to be listed) on your server.
You'll also see a link to the **Global Directory**.
If you click through to the global directory, you will be presented with a list of everybody who chose to be listed across all instances of Friendica.
You'll also see a link to a **Global Directory**.
There are several global directories across the globe that regularly exchange information with each other.
The specific global directory that you see usually depends on where your server is located.
If you click through to the global directory, you will be presented with a list of everybody who choses to be listed across all instances of Friendica.
You will also see a "Show Community Forums" link, which will direct you to Groups, Forums and Fanpages.
You connect to people, groups and forums in the same way, except groups and forums will automatically accept your introduction request, whereas a human will approve you manually.
@ -26,21 +28,18 @@ Connect to other Friendica users
Visit their profile.
Just beneath their profile picture will be the word 'Connect' (we're assuming this is an English language profile).
Click that 'Connect' button.
It will take you to a 'Connect' form.
Click that 'Connect' button and it will take you to a 'Connect' form.
The form is going to ask you for your Identity Address.
This is necessary so that this person's website can find yours.
What do you put in the box?
If your Friendica site is called "demo.friendica.com" and your username/nickname on that site is "bob", you would put in "bob@demo.friendica.com".
If your Friendica site is called "demo.friendica.com" and your username/nickname on that site is "bob", you would enter "bob@demo.friendica.com" in this form.
Notice this looks just like an email address.
It was meant to be that way.
It's meant to be that way.
It's easy for people to remember.
You *could* also put in the URL of your "home" page, such as "http://demo.friendica.com/profile/bob", but the email-style address is certainly easier.
You *could* also put in the URL of your "home" page, such as "http://demo.friendica.com/profile/bob" instead of the email-style address.
When you've submitted the connection page, it will take you back to your own site where you must then login (if necessary) and verify the connection request on *your* site.
Once you've done this, the two websites can communicate with each other to complete the process (after your new friend has approved the request).
@ -51,31 +50,40 @@ This will take you through a similar process.
Connect to users of alternate networks
---
###GNU Social, Twitter, Diaspora
You can also use your Identity Address or other people's Identity Addresses to become friends across networks.
The list of possible networks is growing all the time.
If you know (for instance) "bob" on gnusocial.de (a GNU Social site) you could put bob@gnusocial.de into your Contact page and become friends across networks.
(Or you can put in the URL to Bob's gnusocial.de page if you wish).
###Across the Federation and Fedivese
You can also use your Identity Address or other people's Identity Addresses to become friends across the so-called Federation/Fedivese of open source social media.
Currently, Friendica supports connections with people on diaspora*, Red, Hubzilla, GNU Social, StatusNet, Mastodon, Pleroma, socialhome, and ganggo platforms.
You can do the same for Twitter accounts and Diaspora accounts.
If you know (for instance) "alice" on gnusocial.net (a GNU Social site) you could put alice@gnusocial.net into your Contact page and become friends across networks.
Likwise you can put in the URL to Alice's gnusocial.net page, if you wish.
Note: Some versions of GNU Social software may require the full URL to your profile and may not work with the identity address.
In fact, you can "follow" almost anybody or any website that produces a syndication feed (RSS/Atom,etc.).
If we can find an information stream and a name to attach to the contact, we'll try to connect with them.
People on these networks can also initiate contact with you, if they know your contact details.
###Other social media
If you server provides this functionality, you can also connect with people one
Twitter or important feeds from Tumblr, Wordpress, and many more.
To connect, enter their contact details in the "connect" box on your "Contacts" page.
###Email
If you have supplied your mailbox connection information on your Settings page, you can enter the email address of anybody that has sent you a message recently and have their email messages show up in your social stream.
You can also reply to them from within Friendica.
People can also become friends with you from other networks.
If a friend of yours has an GNU Social account, they can become friends with you by putting your Friendica Identity Address into their GNU Social subscription dialog box.
A similar mechanism is available for Diaspora members, by putting your identity address into their search bar.
Create an email contact with for example Alice on Gmail, enter her email in following format "mailto:alice@gmail.no".
In order to avoid abuse or spam, you must have an email from Alice with the correct email address in your email inbox.
Note: Some versions of GNU Social software may require the full URL to your profile and may not work with the identity address.
Subscribing to mailing lists is done in the same way, but without the use of the "mailto:" prefix.
To subscribe to a mailing list, enter the email in following example format "mailling-list@list-server.net".
###Syndication feeds
You can "follow" almost anybody or any website that produces a syndication feed (RSS/Atom,etc.).
If we can find an information stream and a name to attach to the contact, we'll try to connect with them.
Notification
---
When somebody requests friendship you will receive a notification.
You will need to approve this before the friendship is complete.
You will usually need to approve this before the friendship is complete.
Approval
---
@ -84,16 +92,16 @@ Friendica does not allow this by default, as it would open a gateway for spam.
Unilateral or bilateral friendships
---
When you receive a friendship notification from another Friendica member, you will have the option of allowing them as a "fan" or as a "friend".
If they are a fan, they can see what you have to say, including private communications that you send to them, but not vice versa.
When you receive a friendship notification from another Friendica member, you will have the option of allowing them as a "Follower" or as a "Friend".
If they are a follower, they can see what you have to say, including private communications that you send to them, but not vice versa.
As a friend, you can both communicate with each other.
Diaspora uses a different terminology, and you are given the option of allowing them to "share with you", or being full friends.
diaspora* uses a different terminology, and you are given the option of allowing them to "share with you", or being full friends.
Ignoring, blocking and deleting contacts
---
Once you have become friends, if you find the person constantly sends you spam or worthless information, you can "Ignore" them - without breaking off the friendship or even alerting them to the fact that you aren't interested in anything they are saying.
In many ways they are like a "fan" - but they don't know this.
In many ways they are like a "follower" - but they don't know this.
They think they are a friend.
You can also "block" a person.

View file

@ -57,6 +57,21 @@ The `vier` theme for instance is mobile friendly.
### Registration
#### Register policy
With this drop down selector you can set the nodes registration policy.
You can chose between the following modes:
* **open**: Everybody can register a new account and start using it right away.
* **requires approval**: Everybody can register a new account, but the admin has to approve it before it can be used.
* **closed**: No new registrations are possible.
##### Invitation based registry
Additionally to the setting in the admin panel, you can devide if registrations are only possible using an invitation code or not.
To enable invitation based registration, you have to set the `invitation_only` setting in the [.htconfig.php](/help/htconfig) file.
If you want to use this method, the registration policy has to be set to either *open* or *requires approval*.
#### Check Full Names
You may find a lot of spammers trying to register on your site.
@ -111,6 +126,14 @@ Unauthorised persons will also not be able to request friendship with site membe
Default is false.
Available in version 2.2 or greater.
#### Community pages for Visitors
The community pages show all public postings, separated by their origin being local or the entire network.
With this setting you can select which community pages will be shown to visitors of your Friendica node.
Your local users will always have access to both pages.
**Note**: Several settings, like users hiding their contacts from the public will prevent the postings to show up on the global community page.
#### Allowed Friend Domains
Comma separated list of domains which are allowed to establish friendships with this site.

View file

@ -21,7 +21,7 @@ You can get the latest changes at any time with
cd path/to/friendica
git pull
util/composer.phar install
bin/composer.phar install
The addon tree has to be updated separately like so:

View file

@ -294,6 +294,85 @@ Friendica doesn't allow showing the friends of other users.
---
### lists/ownerships (*; AUTH)
#### Parameters
* list_id: ID of the list
* count: Items per page
* page: Page number
* since_id: Minimum ID
* max_id: Maximum ID
#### Unsupported parameters
* slug
* owner_screen_name
* owner_id
* include_entities
* include_rts
---
### lists/destroy (POST; AUTH)
#### Parameters
* list_id: ID of the list
#### Unsupported parameters
* owner_screen_name
* owner_id
* slug
---
### lists/create (POST; AUTH)
#### Parameters
* name: name of the list
#### Unsupported parameters
* mode
* description
---
### lists/update (POST; AUTH)
#### Parameters
* list_id: ID of the list
* name: name of the list
#### Unsupported parameters
* slug
* name
* mode
* description
* owner_screen_name
* owner_id
---
### lists/statuses (*; AUTH)
#### Parameters
* user_id: ID of the user for whom to return results.
#### Unsupported parameters
* screen_name
* count
* cursor
---
### media/upload (POST,PUT; AUTH)
#### Parameters
@ -1237,7 +1316,6 @@ The following API calls from the Twitter API are not implemented in either Frien
* users/suggestions/:slug/members
* favorites/list
* lists/list
* lists/statuses
* lists/members/destroy
* lists/memberships
* lists/subscribers
@ -1248,13 +1326,9 @@ The following API calls from the Twitter API are not implemented in either Frien
* lists/members/show
* lists/members
* lists/members/create
* lists/destroy
* lists/update
* lists/create
* lists/show
* lists/subscriptions
* lists/members/destroy_all
* lists/ownerships
* saved_searches/show/:id
* saved_searches/create
* saved_searches/destroy/:id

View file

@ -189,178 +189,186 @@ Derzeitige Hooks
Komplette Liste der Hook-Callbacks
---
Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 14-Feb-2012 generiert): Bitte schau in die Quellcodes für Details zu Hooks, die oben nicht dokumentiert sind.
Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Apr-2018 generiert): Bitte schau in die Quellcodes für Details zu Hooks, die oben nicht dokumentiert sind.
boot.php: Addon::callHooks('login_hook',$o);
index.php: Addon::callHooks('init_1');
index.php: Addon::callHooks('app_menu', $arr);
index.php: Addon::callHooks('page_content_top', $a->page['content']);
index.php: Addon::callHooks($a->module.'_mod_init', $placeholder);
index.php: Addon::callHooks($a->module.'_mod_init', $placeholder);
index.php: Addon::callHooks($a->module.'_mod_post', $_POST);
index.php: Addon::callHooks($a->module.'_mod_afterpost', $placeholder);
index.php: Addon::callHooks($a->module.'_mod_content', $arr);
index.php: Addon::callHooks($a->module.'_mod_aftercontent', $arr);
index.php: Addon::callHooks('page_end', $a->page['content']);
boot.php: Addon::callHooks('profile_sidebar_enter', $profile);
include/api.php: Addon::callHooks('logged_in', $a->user);
include/api.php: Addon::callHooks('authenticate', $addon_auth);
include/api.php: Addon::callHooks('logged_in', $a->user);
boot.php: Addon::callHooks('profile_sidebar', $arr);
boot.php: Addon::callHooks("proc_run", $arr);
include/contact_selectors.php: Addon::callHooks('network_to_name', $nets);
include/api.php: Addon::callHooks('logged_in', $a->user);
include/api.php: Addon::callHooks('logged_in', $a->user);
include/queue.php: Addon::callHooks('queue_predeliver', $a, $r);
include/queue.php: Addon::callHooks('queue_deliver', $a, $params);
include/text.php: Addon::callHooks('contact_block_end', $arr);
include/text.php: Addon::callHooks('smilie', $s);
include/text.php: Addon::callHooks('prepare_body_init', $item);
include/text.php: Addon::callHooks('prepare_body', $prep_arr);
include/text.php: Addon::callHooks('prepare_body_final', $prep_arr);
include/nav.php: Addon::callHooks('page_header', $a->page['nav']);
include/auth.php: Addon::callHooks('authenticate', $addon_auth);
include/bbcode.php: Addon::callHooks('bbcode',$Text);
include/oauth.php: Addon::callHooks('logged_in', $a->user);
include/acl_selectors.php: Addon::callHooks($a->module . '_pre_' . $selname, $arr);
include/acl_selectors.php: Addon::callHooks($a->module . '_post_' . $selname, $o);
include/acl_selectors.php: Addon::callHooks('contact_select_options', $x);
include/acl_selectors.php: Addon::callHooks($a->module . '_pre_' . $selname, $arr);
include/acl_selectors.php: Addon::callHooks($a->module . '_post_' . $selname, $o);
include/acl_selectors.php: Addon::callHooks($a->module . '_pre_' . $selname, $arr);
include/acl_selectors.php: Addon::callHooks($a->module . '_post_' . $selname, $o);
include/notifier.php: Addon::callHooks('notifier_normal',$target_item);
include/notifier.php: Addon::callHooks('notifier_end',$target_item);
include/items.php: Addon::callHooks('atom_feed', $atom);
include/items.php: Addon::callHooks('atom_feed_end', $atom);
include/items.php: Addon::callHooks('atom_feed_end', $atom);
include/items.php: Addon::callHooks('parse_atom', $arr);
include/items.php: Addon::callHooks('post_remote',$arr);
include/items.php: Addon::callHooks('atom_author', $o);
include/items.php: Addon::callHooks('atom_entry', $o);
include/bb2diaspora.php: Addon::callHooks('bb2diaspora',$Text);
include/cronhooks.php: Addon::callHooks('cron', $d);
include/security.php: Addon::callHooks('logged_in', $a->user);
include/html2bbcode.php: Addon::callHooks('html2bbcode', $text);
include/Contact.php: Addon::callHooks('remove_user',$r[0]);
include/Contact.php: Addon::callHooks('contact_photo_menu', $args);
include/conversation.php: Addon::callHooks('conversation_start',$cb);
include/conversation.php: Addon::callHooks('render_location',$locate);
include/enotify.php: Addon::callHooks('enotify', $h);
include/enotify.php: Addon::callHooks('enotify_store', $datarray);
include/enotify.php: Addon::callHooks('enotify_mail', $datarray);
include/enotify.php: Addon::callHooks('check_item_notification', $notification_data);
include/conversation.php: Addon::callHooks('conversation_start', $cb);
include/conversation.php: Addon::callHooks('render_location', $locate);
include/conversation.php: Addon::callHooks('display_item', $arr);
include/conversation.php: Addon::callHooks('render_location',$locate);
include/conversation.php: Addon::callHooks('display_item', $arr);
include/conversation.php: Addon::callHooks('item_photo_menu', $args);
include/conversation.php: Addon::callHooks('jot_tool', $jotplugins);
include/conversation.php: Addon::callHooks('jot_networks', $jotnets);
include/security.php: Addon::callHooks('logged_in', $a->user);
index.php: Addon::callHooks('init_1');
include/text.php: Addon::callHooks('contact_block_end', $arr);
include/text.php: Addon::callHooks('poke_verbs', $arr);
include/text.php: Addon::callHooks('prepare_body_init', $item);
include/text.php: Addon::callHooks('prepare_body_content_filter', $hook_data);
include/text.php: Addon::callHooks('prepare_body', $hook_data);
include/text.php: Addon::callHooks('prepare_body_final', $hook_data);
index.php: Addon::callHooks('app_menu', $arr);
include/items.php: Addon::callHooks('page_info_data', $data);
index.php: Addon::callHooks('page_end', $a->page['content']);
mod/directory.php: Addon::callHooks('directory_item', $arr);
mod/photos.php: Addon::callHooks('photo_post_init', $_POST);
mod/xrd.php: Addon::callHooks('personal_xrd', $arr);
mod/photos.php: Addon::callHooks('photo_post_file',$ret);
mod/ping.php: Addon::callHooks('network_ping', $arr);
mod/photos.php: Addon::callHooks('photo_post_end',$foo);
mod/parse_url.php: Addon::callHooks("parse_link", $arr);
mod/photos.php: Addon::callHooks('photo_post_end',$foo);
mod/manage.php: Addon::callHooks('home_init', $ret);
mod/photos.php: Addon::callHooks('photo_post_end',$foo);
mod/acl.php: Addon::callHooks('acl_lookup_end', $results);
mod/photos.php: Addon::callHooks('photo_post_end',intval($item_id));
mod/network.php: Addon::callHooks('network_content_init', $arr);
mod/network.php: Addon::callHooks('network_tabs', $arr);
mod/photos.php: Addon::callHooks('photo_upload_form',$ret);
mod/friendica.php: Addon::callHooks('about_hook', $o);
mod/subthread.php: Addon::callHooks('post_local_end', $arr);
mod/friendica.php: Addon::callHooks('about_hook', $o);
mod/profiles.php: Addon::callHooks('profile_post', $_POST);
mod/profiles.php: Addon::callHooks('profile_edit', $arr);
mod/editpost.php: Addon::callHooks('jot_tool', $jotplugins);
mod/settings.php: Addon::callHooks('addon_settings_post', $_POST);
mod/settings.php: Addon::callHooks('connector_settings_post', $_POST);
mod/settings.php: Addon::callHooks('display_settings_post', $_POST);
mod/settings.php: Addon::callHooks('settings_post', $_POST);
mod/settings.php: Addon::callHooks('addon_settings', $settings_addons);
mod/settings.php: Addon::callHooks('connector_settings', $settings_connectors);
mod/settings.php: Addon::callHooks('display_settings', $o);
mod/settings.php: Addon::callHooks('settings_form', $o);
mod/editpost.php: Addon::callHooks('jot_networks', $jotnets);
mod/photos.php: Addon::callHooks('photo_post_init', $_POST);
mod/photos.php: Addon::callHooks('photo_post_file', $ret);
mod/photos.php: Addon::callHooks('photo_post_end', $foo);
mod/photos.php: Addon::callHooks('photo_post_end', $foo);
mod/photos.php: Addon::callHooks('photo_post_end', $foo);
mod/photos.php: Addon::callHooks('photo_post_end', $foo);
mod/photos.php: Addon::callHooks('photo_post_end', intval($item_id));
mod/photos.php: Addon::callHooks('photo_upload_form', $ret);
mod/parse_url.php: Addon::callHooks('parse_link', $arr);
mod/profile.php: Addon::callHooks('profile_advanced', $o);
mod/home.php: Addon::callHooks('home_init',$ret);
mod/home.php: Addon::callHooks('home_init', $ret);
mod/home.php: Addon::callHooks("home_content", $content);
mod/home.php: Addon::callHooks("home_content",$o);
mod/poke.php: Addon::callHooks('post_local_end', $arr);
mod/contacts.php: Addon::callHooks('contact_edit_post', $_POST);
mod/contacts.php: Addon::callHooks('contact_edit_post', $_POST);
mod/contacts.php: Addon::callHooks('contact_edit', $arr);
mod/contacts.php: Addon::callHooks('contact_edit', $arr);
mod/tagger.php: Addon::callHooks('post_local_end', $arr);
mod/settings.php: Addon::callHooks('addon_settings_post', $_POST);
mod/lockview.php: Addon::callHooks('lockview_content', $item);
mod/settings.php: Addon::callHooks('connector_settings_post', $_POST);
mod/uexport.php: Addon::callHooks('uexport_options', $options);
mod/settings.php: Addon::callHooks('settings_post', $_POST);
mod/register.php: Addon::callHooks('register_post', $arr);
mod/register.php: Addon::callHooks('register_form', $arr);
mod/settings.php: Addon::callHooks('addon_settings', $settings_addons);
mod/item.php: Addon::callHooks('post_local_start', $_REQUEST);
mod/item.php: Addon::callHooks('post_local', $datarray);
mod/item.php: Addon::callHooks('post_local_end', $datarray);
mod/settings.php: Addon::callHooks('connector_settings', $settings_connectors);
mod/editpost.php: Addon::callHooks('jot_tool', $jotplugins);
mod/settings.php: Addon::callHooks('settings_form',$o);
src/Network/FKOAuth1.php: Addon::callHooks('logged_in', $a->user);
mod/register.php: Addon::callHooks('register_account', $newuid);
src/Render/FriendicaSmartyEngine.php: Addon::callHooks("template_vars", $arr);
mod/like.php: Addon::callHooks('post_local_end', $arr);
src/Model/Item.php: Addon::callHooks('post_local', $item);
src/Model/Item.php: Addon::callHooks('post_remote', $item);
src/Model/Item.php: Addon::callHooks('post_local_end', $posted_item);
src/Model/Item.php: Addon::callHooks('post_remote_end', $posted_item);
src/Model/Item.php: Addon::callHooks('tagged', $arr);
src/Model/Item.php: Addon::callHooks('post_local_end', $new_item);
mod/xrd.php: Addon::callHooks('personal_xrd', $arr);
src/Model/Contact.php: Addon::callHooks('contact_photo_menu', $args);
src/Model/Contact.php: Addon::callHooks('follow', $arr);
mod/item.php: Addon::callHooks('post_local_start', $_REQUEST);
src/Model/Profile.php: Addon::callHooks('profile_sidebar_enter', $profile);
src/Model/Profile.php: Addon::callHooks('profile_sidebar', $arr);
src/Model/Profile.php: Addon::callHooks('profile_tabs', $arr);
src/Model/Profile.php: Addon::callHooks('zrl_init', $arr);
mod/item.php: Addon::callHooks('post_local',$datarray);
src/Model/Event.php: Addon::callHooks('event_updated', $event['id']);
src/Model/Event.php: Addon::callHooks("event_created", $event['id']);
mod/item.php: Addon::callHooks('post_local_end', $datarray);
src/Model/User.php: Addon::callHooks('register_account', $uid);
src/Model/User.php: Addon::callHooks('remove_user', $user);
mod/profile.php: Addon::callHooks('profile_advanced',$o);
src/Content/Text/BBCode.php: Addon::callHooks('bbcode', $text);
src/Content/Text/BBCode.php: Addon::callHooks('bb2diaspora', $text);
mod/profiles.php: Addon::callHooks('profile_post', $_POST);
src/Content/Text/HTML.php: Addon::callHooks('html2bbcode', $message);
mod/profiles.php: Addon::callHooks('profile_edit', $arr);
src/Content/Smilies.php: Addon::callHooks('smilie', $params);
mod/tagger.php: Addon::callHooks('post_local_end', $arr);
src/Content/Feature.php: Addon::callHooks('isEnabled', $arr);
src/Content/Feature.php: Addon::callHooks('get', $arr);
mod/cb.php: Addon::callHooks('cb_init');
src/Content/ContactSelector.php: Addon::callHooks('network_to_name', $nets);
src/Content/ContactSelector.php: Addon::callHooks('gender_selector', $select);
src/Content/ContactSelector.php: Addon::callHooks('sexpref_selector', $select);
src/Content/ContactSelector.php: Addon::callHooks('marital_selector', $select);
mod/cb.php: Addon::callHooks('cb_post', $_POST);
src/Content/OEmbed.php: Addon::callHooks('oembed_fetch_url', $embedurl, $j);
mod/cb.php: Addon::callHooks('cb_afterpost');
src/Content/Nav.php: Addon::callHooks('page_header', $a->page['nav']);
src/Content/Nav.php: Addon::callHooks('nav_info', $nav);
mod/cb.php: Addon::callHooks('cb_content', $o);
src/Worker/Directory.php: Addon::callHooks('globaldir_update', $arr);
src/Worker/Notifier.php: Addon::callHooks('notifier_end', $target_item);
src/Worker/Queue.php: Addon::callHooks('queue_predeliver', $r);
src/Worker/Queue.php: Addon::callHooks('queue_deliver', $params);
mod/directory.php: Addon::callHooks('directory_item', $arr);
src/Module/Login.php: Addon::callHooks('authenticate', $addon_auth);
src/Module/Login.php: Addon::callHooks('login_hook', $o);
src/Module/Logout.php: Addon::callHooks("logging_out");
src/Object/Post.php: Addon::callHooks('render_location', $locate);
src/Object/Post.php: Addon::callHooks('display_item', $arr);
src/Core/ACL.php: Addon::callHooks('contact_select_options', $x);
src/Core/ACL.php: Addon::callHooks($a->module.'_pre_'.$selname, $arr);
src/Core/ACL.php: Addon::callHooks($a->module.'_post_'.$selname, $o);
src/Core/ACL.php: Addon::callHooks($a->module.'_pre_'.$selname, $arr);
src/Core/ACL.php: Addon::callHooks($a->module.'_post_'.$selname, $o);
src/Core/ACL.php: Addon::callHooks('jot_networks', $jotnets);
src/Core/Worker.php: Addon::callHooks("proc_run", $arr);
src/Util/Emailer.php: Addon::callHooks('emailer_send_prepare', $params);
src/Util/Emailer.php: Addon::callHooks("emailer_send", $hookdata);
src/Util/Map.php: Addon::callHooks('generate_map', $arr);
src/Util/Map.php: Addon::callHooks('generate_named_map', $arr);
src/Util/Map.php: Addon::callHooks('Map::getCoordinates', $arr);
src/Util/Network.php: Addon::callHooks('avatar_lookup', $avatar);
src/Util/ParseUrl.php: Addon::callHooks("getsiteinfo", $siteinfo);
src/Protocol/DFRN.php: Addon::callHooks('atom_feed_end', $atom);
src/Protocol/DFRN.php: Addon::callHooks('atom_feed_end', $atom);

View file

@ -10,7 +10,7 @@ Nutzer
* **[Ist es möglich, bei mehreren Profilen verschiedene Avatare (Nutzerbilder) zu haben?](help/FAQ#avatars)**
* **[Was ist der Unterschied zwischen blockierten|ignorierten|archivierten|versteckten Kontakten?](help/FAQ#contacts)**
* **[Was passiert, wenn ein Account gelöscht ist? Ist dieser richtig gelöscht?](help/FAQ#removed)**
* **[Kann ich einem hashtag folgen?](help/FAQ#hashtag)**
* **[Kann ich einem Hashtag folgen?](help/FAQ#hashtag)**
* **[Wie kann ich einen RSS-Feed meiner Netzwerkseite (Stream) erstellen?](help/FAQ#rss)**
* **[Gibt es Clients für Friendica?](help/FAQ#clients)**
* **[Wo finde ich Hilfe?](help/FAQ#help)**
@ -29,10 +29,10 @@ Nutzer
<a name="ssl"></a>
### Warum erhalte ich Warnungen über fehlende Zertifikate?
Manchmal erhältst Du eine Browser-Warnung über fehlende Zertifikate.
Manchmal erhältst Du eine Browser-Warnung über fehlende Zertifikate.
Diese Warnungen können drei Gründe haben:
1. der Server, mit dem Du verbunden bist, nutzt kein SSL;
1. der Server, mit dem Du verbunden bist, nutzt kein SSL;
2. der Server hat ein selbst-signiertes Zertifikat (nicht empfohlen)
@ -40,39 +40,39 @@ Diese Warnungen können drei Gründe haben:
*(SSL (Secure Socket Layer) ist eine Technologie, die Daten auf ihrem Weg zwischen zwei Computern verschlüsselt.)*
Wenn Du noch kein SSL-Zertifikat hast, dann gibt es drei Wege, eines zu erhalten: kauf Dir eines, hole Dir ein kostenloses (z.B. bei StartSSL, WoSign, hoffentlich bald auch letsencrypt) oder kreiere Dein eigenes (nicht empfohlen).
Wenn Du noch kein SSL-Zertifikat hast, dann gibt es drei Wege, eines zu erhalten: kauf Dir eines, hole Dir ein kostenloses (z.B. bei StartSSL, WoSign, hoffentlich bald auch letsencrypt) oder kreiere Dein eigenes (nicht empfohlen).
[Weitere Informationen über die Einrichtung von SSL und warum es schlecht ist, selbst-signierte Zertifikate zu nutzen, findest Du hier.](help/SSL)
Sei Dir bewusst, dass Browser-Warnungen über Sicherheitslücken etwas sind, wodurch neue Nutzer schnell das Vertrauen in das gesamte Friendica-Projekt verlieren können.
Aus diesem Grund wird Friendica Red nur SSL-Zertifikate eines anerkannten Anbieters (CA, certificate authority) akzeptieren und nicht zu Seiten verbinden, die kein SSL nutzen.
Unabhängig von den negativen Aspekten von SSL handelt es sich hierbei um eine notwendige Lösung, solange keine etablierte Alternative existiert.
Sei Dir bewusst, dass Browser-Warnungen über Sicherheitslücken etwas sind, wodurch neue Nutzer schnell das Vertrauen in das gesamte Friendica-Projekt verlieren können.
Aus diesem Grund wird Friendica Red nur SSL-Zertifikate eines anerkannten Anbieters (CA, certificate authority) akzeptieren und nicht zu Seiten verbinden, die kein SSL nutzen.
Unabhängig von den negativen Aspekten von SSL handelt es sich hierbei um eine notwendige Lösung, solange keine etablierte Alternative existiert.
Abgesehen davon kann es ohne SSL auch Probleme mit der Verbindung zu Diaspora geben, da einige Diaspora-Pods eine zertifizierte Verbindung benötigen.
Abgesehen davon kann es ohne SSL auch Probleme mit der Verbindung zu Diaspora geben, da einige Diaspora-Pods eine zertifizierte Verbindung benötigen.
Wenn Du Friendica nur für eine bestimmte Gruppe von Leuten auf einem einzelnen Server nutzt, bei dem keine Verbindung zum restlichen Netzwerk besteht, dann benötigst Du kein SSL.
Ebenso benötigst Du SSL nicht, wenn Du ausschließlich öffentliche Beiträge auf Deiner Seite veröffentlichst bzw. empfängst.
Wenn Du Friendica nur für eine bestimmte Gruppe von Leuten auf einem einzelnen Server nutzt, bei dem keine Verbindung zum restlichen Netzwerk besteht, dann benötigst Du kein SSL.
Ebenso benötigst Du SSL nicht, wenn Du ausschließlich öffentliche Beiträge auf Deiner Seite veröffentlichst bzw. empfängst.
Wenn Du zum jetzigen Zeitpunkt noch keinen Server aufgesetzt hast, ist es sinnvoll, die verschiedenen Anbieter in Bezug auf SSL zu vergleichen.
Einige erlauben die Nutzung von freien Zertifikaten oder lassen Dich ihre eigenen Zertifikate mitnutzen.
Andere erlauben nur kostenpflichtige Zertifikate als eigenes Angebot bzw. von anderen Anbietern.
Wenn Du zum jetzigen Zeitpunkt noch keinen Server aufgesetzt hast, ist es sinnvoll, die verschiedenen Anbieter in Bezug auf SSL zu vergleichen.
Einige erlauben die Nutzung von freien Zertifikaten oder lassen Dich ihre eigenen Zertifikate mitnutzen.
Andere erlauben nur kostenpflichtige Zertifikate als eigenes Angebot bzw. von anderen Anbietern.
<a name="upload"></a>
### Wie kann ich Bilder, Dateien, Links, Video und Audio in Beiträge einfügen?
Bilder können direkt im [Beitragseditor](help/Text_editor) vom Computer hochgeladen werden.
Eine Übersicht aller Bilder, die auf Deinem Server liegen, findest Du unter <i>deineSeite.de/photos/profilname</i>.
Bilder können direkt im [Beitragseditor](help/Text_editor) vom Computer hochgeladen werden.
Eine Übersicht aller Bilder, die auf Deinem Server liegen, findest Du unter <i>deineSeite.de/photos/profilname</i>.
Dort kannst Du auch direkt Bilder hochladen und festlegen, ob Deine Kontakte eine Nachricht über das neue Bild bekommen.
Alle Arten von Dateien können grundsätzlich als Anhang in Friendica hochgeladen werden.
Dafür verwendest Du das Büroklammersymbol im Editor.
Sie sind dann direkt an den Beitrag geknüpft, können von den Betrachtern heruntergeladen werden, aber werden nicht als Vorschau angezeigt.
Deshalb eignet sich diese Methode vor allem für Office-Dateien oder gepackte Dateien wie ZIPs, aber weniger für Multimediadateien.
Alle Arten von Dateien können grundsätzlich als Anhang in Friendica hochgeladen werden.
Dafür verwendest Du das Büroklammersymbol im Editor.
Sie sind dann direkt an den Beitrag geknüpft, können von den Betrachtern heruntergeladen werden, aber werden nicht als Vorschau angezeigt.
Deshalb eignet sich diese Methode vor allem für Office-Dateien oder gepackte Dateien wie ZIPs, aber weniger für Multimediadateien.
Wer hingegen Dateien über Dropbox, über eine auf dem eigenen Server installierte Owncloud oder über einen anderen [Filehoster](http://en.wikipedia.org/wiki/Comparison_of_file_hosting_services) einfügen will, verwendet den Link-Button.
Wenn Du mit dem Link-Button (Ketten-Symbol) URLs zu anderen Seiten einfügst, versucht Friendica eine kurze Zusammenfassung als Vorschau abzurufen.
Wenn Du mit dem Link-Button (Ketten-Symbol) URLs zu anderen Seiten einfügst, versucht Friendica eine kurze Zusammenfassung als Vorschau abzurufen.
Manchmal klappts das nicht ... dann verlinke den Beitrag einfach per [url=http://example.com]<i>freigewählter Name</i>[/url] im Editor.
Video- und Audiodateien können zwar in Beiträge eingebunden werden, allerdings geht das nicht über einen direkten Upload im Editor wie bei Fotos.
Video- und Audiodateien können zwar in Beiträge eingebunden werden, allerdings geht das nicht über einen direkten Upload im Editor wie bei Fotos.
Du hast zwei Möglichkeiten:
1. Du kannst bei dem Video- oder Audiobutton die URL von einem Hoster eingeben (Youtube, Vimeo, Soundcloud und alle anderen mit oembed/opengraph-Unterstützung). Bei Videos zeigt Friendica dann ein Vorschaubild in Deinem Beitrag an, nach einem Klick öffnet sich ein eingebetter Player. Bei Soundcloud wird der Player direkt eingebunden.
@ -84,7 +84,7 @@ Zum Konvertieren von Videos in das lizenfreie Videoformat WebM gibt es unter Win
<a name="avatars"></a>
### Ist es möglich, bei mehreren Profilen verschiedene Avatare (Nutzerbilder) zu haben?
Ja.
Ja.
Auf Deiner ["Profile verwalten/editieren"-Seite](../profiles) wählst Du zunächst das gewünschte Profil aus.
Anschließend siehst Du eine Seite mit allen Infos zu diesem Profil.
Klicke nun oben auf den Link "Profilbild ändern" und lade im nächsten Fenster ein Bild von Deinem PC hoch.
@ -93,48 +93,40 @@ Um Deine privaten Daten zu schützen, wird in Beiträgen nur das Bild aus Deinem
<a name="contacts"></a>
### Was ist der Unterschied zwischen blockierten|ignorierten|archivierten|versteckten Kontakten?
Wir verhindern direkte Kommunikation mit blockierten Kontakten.
Sie gehören nicht zu den Empfängern beim Versand von Beiträgen und deren Beiträge werden auch nicht importiert.
Trotzdem werden deren Unterhaltungen mit Deinen Freunden in Deinem Stream sichtbar sein.
Wenn Du einen Kontakt komplett löschst, können sie Dir eine neue Freundschaftsanfrage schicken.
Blockierte Kontakte können das nicht machen.
Sie können nicht mit Dir direkt kommunizieren, nur über Freunde.
Wir verhindern direkte Kommunikation mit blockierten Kontakten.
Sie gehören nicht zu den Empfängern beim Versand von Beiträgen und deren Beiträge werden auch nicht importiert.
Trotzdem werden deren Unterhaltungen mit Deinen Freunden in Deinem Stream sichtbar sein.
Wenn Du einen Kontakt komplett löschst, können sie Dir eine neue Freundschaftsanfrage schicken.
Blockierte Kontakte können das nicht machen.
Sie können nicht mit Dir direkt kommunizieren, nur über Freunde.
Ignorierte Kontakte können weiterhin Beiträge und private Nachrichten von Dir erhalten.
Deren Beiträge und private Nachrichten werden allerdings nicht importiert.
Wie bei blockierten Beiträgen siehst Du auch hier weiterhin die Kommentare dieser Person zu anderen Beiträgen Deiner Freunde.
Ignorierte Kontakte können weiterhin Beiträge und private Nachrichten von Dir erhalten.
Deren Beiträge und private Nachrichten werden allerdings nicht importiert.
Wie bei blockierten Beiträgen siehst Du auch hier weiterhin die Kommentare dieser Person zu anderen Beiträgen Deiner Freunde.
[Ein Erweiterung namens "blockem" kann installiert werden, um alle Beiträge einer bestimmten Person in Deinem Stream zu verstecken bzw. zu verkürzen.
[Ein Erweiterung namens "blockem" kann installiert werden, um alle Beiträge einer bestimmten Person in Deinem Stream zu verstecken bzw. zu verkürzen.
Dabei werden auch Kommentare dieser Person in Beiträgen Deiner Freunde blockiert.]
Ein archivierter Kontakt bedeutet, dass Kommunikation nicht möglich ist und auch nicht versucht wird (das ist z.B. sinnvoll, wenn eine Person zu einem neuen Server gewechselt ist und das alte Profil gelöscht hat).
Ein archivierter Kontakt bedeutet, dass Kommunikation nicht möglich ist und auch nicht versucht wird (das ist z.B. sinnvoll, wenn eine Person zu einem neuen Server gewechselt ist und das alte Profil gelöscht hat).
Anders als beim Blockieren werden existierende Beiträge, die vor der Archivierung erstellt wurden, weiterhin angezeigt.
Ein versteckter Kontakt wird in keiner "Freundeliste" erscheinen (außer für dich).
Trotzdem wird ein versteckter Kontakt normal in Unterhaltungen angezeigt - was für andere Kontakte ein Hinweis sein kann, dass diese Person als versteckter Kontakt in Deiner Liste ist.
Ein versteckter Kontakt wird in keiner "Freundeliste" erscheinen (außer für dich).
Trotzdem wird ein versteckter Kontakt normal in Unterhaltungen angezeigt - was für andere Kontakte ein Hinweis sein kann, dass diese Person als versteckter Kontakt in Deiner Liste ist.
<a name="removed"></a>
### Was passiert, wenn ein Account gelöscht ist? Ist dieser richtig gelöscht?
Wenn Du Deinen Account löschst, wird sofort der gesamte Inhalt auf Deinem Server gelöscht und ein Löschbefehl an alle Deine Kontakte verschickt.
Dadurch wirst Du ebenfalls aus dem globalen Verzeichnis gelöscht.
Dieses Vorgehen setzt voraus, dass Dein Profil für 24 Stunden weiterhin "teilweise" verfügbar sein wird, um eine Verbindung zu allen Deinen Kontakten ermöglicht.
Wenn Du Deinen Account löschst, wird sofort der gesamte Inhalt auf Deinem Server gelöscht und ein Löschbefehl an alle Deine Kontakte verschickt.
Dadurch wirst Du ebenfalls aus dem globalen Verzeichnis gelöscht.
Dieses Vorgehen setzt voraus, dass Dein Profil für 24 Stunden weiterhin "teilweise" verfügbar sein wird, um eine Verbindung zu allen Deinen Kontakten ermöglicht.
Wir können also Dein Profil blockieren und es so erscheinen lassen, als wären alle Daten sofort gelöscht, allerdings warten wir 24 Stunden (bzw. bis alle Deine Kontakte informiert wurden), bevor wir die Daten auch physikalisch löschen.
<a name="hashtag"></a>
### Kann ich einem hashtag folgen?
### Kann ich einem Hashtag folgen?
Nein.
Die Möglichkeit, einem hashtag zu folgen, ist eine interessante Technik, führt aber zu einigen Schwierigkeiten.
1.) Alle Beiträge, die diesen tag nutzen, müssten zu allen Seiten im Netzwerk kopiert werden. Das erhöht den Speicherbedarf und beeinträchtigt kleine Seiten. Die Nutzung von geteilten Hosting-Angeboten (Shared Hosting) wäre praktisch unmöglich.
2.) Die Verbreitung von Spam wäre vereinfacht (tag-Spam ist z.B. bei Twitter ein schwerwiegendes Problem)
3.) Der wichtigste Grund der gegen diese Technik spricht ist, dass sie eine natürliche Ausrichtung auf größere Seiten mit mehr getaggten Inhalten zur Folge hat. Dies kann z.B. aufkommen, wenn Dein Netzwerk tags anstelle von anderen Kommunikationsmitteln wie Gruppen oder Foren nutzt.
Stattdessen bieten wir andere Mechanismen, um globale Unterhaltungen zu erreichen, dabei aber eine angemesse Basis für kleine und große Seiten zu bieten.
Hierzu gehören Foren, Gruppen und geteilte tags.
Ja.
Füge die Tags zu Deinen gespeicherten Suchen hinzu, sie werden automatisch auf der Netzwerk-Seite auftauchen.
Bitte beachte, dass Deine Antworten auf solche Posts aus technischen Gründen nicht unter dem "Persönlich"-Reiter auf der Netzwerk-Seite und der gesamte Thread nicht per API zu sehen sind.
<a name="rss"></a>
### Wie kann ich einen RSS-Feed meiner Netzwerkseite (Stream) erstellen?
@ -145,16 +137,16 @@ Wenn Du die Beiträge Deines Accounts mit RSS teilen willst, dann kannst Du eine
deineSeite.de/feed/[profilname]/posts
Beispiel: Friendica Support
Beispiel: Friendica Support
https://forum.friendi.ca/feed/helpers/posts
#### RSS-Feed all deiner Beiträge und Antworten
deineSeite.de/dfrn_poll/feed/[profilname]/comments
Beispiel: Friendica Support
Beispiel: Friendica Support
https://forum.friendi.ca/feeds/helpers/comments
#### RSS-Feed all deiner Aktivitäten
@ -189,10 +181,15 @@ Hier ist eine Liste von Clients bei denen dies möglich ist, bzw. die speziell f
### Wo finde ich Hilfe?
Wenn Du Probleme mit Deiner Friendica-Seite hast, dann kannst Du die Community in der [Friendica-Support-Gruppe](https://forum.friendi.ca/profile/helpers) oder im [deutschen Friendica-Support-Forum](http://toktan.org/profile/wiki) fragen oder Dir das [deutsche Wiki](http://wiki.toktan.org/doku.php) anschauen.
Wenn Du Deinen Account nicht nutzen kannst, kannst Du entweder einen [Testaccount](https://tryfriendica.de) bzw. einen Account auf einer öffentlichen Seite ([Liste](https://dir.friendica.social/servers)) nutzen, oder Du wählst die Librelist-mailing-Liste.
Wenn Du die Mailing-Liste nutzen willst, schicke eine Mail an friendica AT librelist PUNKT com.
Wenn Du Deinen Account nicht nutzen kannst, kannst Du entweder einen [Testaccount](https://tryfriendica.de) bzw. einen Account auf einer öffentlichen Seite ([Liste](https://dir.friendica.social/servers)) nutzen.
Wenn Du ein Theme-Entwickler bist, wirst Du in diesem Forum Hilfe finden: [Friendica Theme Developers](https://friendica.eu/profile/ftdevs).
Wenn du dir keinen weiteren Friendica Account einrichten willst, kannst du auch gerne über einen der folgenden alternativen Kanäle Hilfe suchen:
* [Friendica Support Forum](https://forum.friendi.ca/~helpers)
* [Mailing List Archive](http://mailman.friendi.ca/mailman/listinfo/support-friendi.ca) you can subscribe to the list by sending an email to ``support-request(at)friendi.ca?subject=subscribe``
* XMPP/Jabber MUC: support(at)forum.friendi.ca
* IRC: #friendica at irc.freenode.net
* Matrix: #friendi.ca or #friendica at matrix.org.
Admin
--------
@ -200,16 +197,16 @@ Admin
<a name="multiple"></a>
### Kann ich mehrere Domains mit den selben Dateien aufsetzen?
Ja, das ist möglich.
Es ist allerdings nicht möglich, eine Datenbank durch zwei Domains zu nutzen.
Solange Du Deine .htconfig.php allerdings so einrichtest, dass das System nicht versucht, eine Installation durchzuführen, kannst Du die richtige Config-Datei in include/$hostname/.htconfig.php hinterlegen.
Ja, das ist möglich.
Es ist allerdings nicht möglich, eine Datenbank durch zwei Domains zu nutzen.
Solange Du Deine .htconfig.php allerdings so einrichtest, dass das System nicht versucht, eine Installation durchzuführen, kannst Du die richtige Config-Datei in include/$hostname/.htconfig.php hinterlegen.
Alle Cache-Aspekte und der Zugriffsschutz können pro Instanz konfiguriert werden.
<a name="sources"></a>
### Wo kann ich den Quellcode von Friendica, Addons und Themes finden?
Du kannst den Friendica-Quellcode [hier](https://github.com/friendica/friendica) finden.
Dort findest Du immer die aktuellste stabile Version von Friendica.
Du kannst den Friendica-Quellcode [hier](https://github.com/friendica/friendica) finden.
Dort findest Du immer die aktuellste stabile Version von Friendica.
Der Quellcode von Friendica Red ist [hier](https://github.com/friendica/red) zu finden.
Addons findest Du auf [dieser Seite](https://github.com/friendica/friendica-addons).
@ -235,8 +232,8 @@ Rufe bitte im Admin Panel den Punkt [DB Updates](/admin/dbsync/) auf und folge d
Damit wird ein Hintergrundprozess gestartet der die Struktur deiner Datenbank überprüft und gegebenenfalls aktualisiert.
Du kannst das Struktur Updatee auch manuell auf der Kommandoeingabe ausführen.
Starte dazu bitte vom Grundverzeichnis deiner Friendica Instanz folgendes Skript:
Starte dazu bitte vom Grundverzeichnis deiner Friendica Instanz folgendes Kommand:
scripts/dbstructure.php update
bin/console dbstructure update
sollten bei der Ausführung Fehler auftreten, kontaktiere bitte das [Support Forum](https://forum.friendi.ca/profile/helpers).

View file

@ -24,8 +24,9 @@ Wir planen, diese Einschränkung in einer zukünftigen Version zu beheben.
- Apache mit einer aktiverten mod-rewrite-Funktion und dem Eintrag "Options All", so dass du die lokale .htaccess-Datei nutzen kannst
- PHP 5.6+. Je neuer, desto besser.
- PHP *Kommandozeilen*-Zugang mit register_argc_argv auf "true" gesetzt in der php.ini-Datei
- Curl, GD, PDO, MySQLi, xml und OpenSSL-Erweiterung
- Curl, GD, PDO, MySQLi, xml, zip und OpenSSL-Erweiterung
- etwas in der Art eines Email-Servers oder eines Gateways wie PHP mail()
- Das POSIX Modul muss aktiviert sein ([CentOS, RHEL](http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7) haben dies z.B. deaktiviert)
- Mysql 5.5.3+
- die Möglichkeit, wiederkehrende Aufgaben mit cron (Linux/Mac) oder "Scheduled Tasks" einzustellen (Windows) [Beachte: andere Optionen sind in Abschnitt 7 dieser Dokumentation zu finden]
- Installation in einer Top-Level-Domain oder Subdomain (ohne eine Verzeichnis/Pfad-Komponente in der URL) wird bevorzugt. Verzeichnispfade sind für diesen Zweck nicht so günstig und wurden auch nicht ausführlich getestet.
@ -49,7 +50,7 @@ Wir planen, diese Einschränkung in einer zukünftigen Version zu beheben.
`cd meinewebseite`
`git pull`
`util/composer.phar install`
`bin/composer.phar install`
- Addons installieren
- zunächst solltest du **in** deinem Webseitenordner sein
@ -86,13 +87,13 @@ Wenn du irgendwelche **kritischen** Fehler zu diesen Zeitpunkt erhalten solltest
7. Erstelle einen Cron job oder einen regelmäßigen Task, um den Poller alle 5-10 Minuten im Hintergrund ablaufen zu lassen. Beispiel:
`cd /base/directory; /path/to/php scripts/worker.php`
`cd /base/directory; /path/to/php bin/worker.php`
Ändere "/base/directory" und "/path/to/php" auf deine Systemvorgaben.
Wenn du einen Linux-Server nutzt, benutze den Befehl "crontab -e" und ergänze eine Zeile wie die Folgende; angepasst an dein System
`*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php scripts/worker.php`
`*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/worker.php`
Du kannst den PHP-Pfad finden, indem du den Befehl „which php“ ausführst.
Wenn du Schwierigkeiten mit diesem Schritt hast, kannst du deinen Hosting-Anbieter kontaktieren.

View file

@ -54,6 +54,20 @@ Das `vier` Theme z.B. unterstützt kleine Anzeigen und benötigt kein zusätzlic
### Registrierung
#### Registrierungsmethode
Diese Einstellung regelt die Art der Registrierung.
Dabei kannst du zwischen den folgenden Optionen wählen:
* **Offen**: Jeder kann ein neues Nutzerkonto anlegen und es sofort benutzen.
* **Bedarf der Zustimmung**: Jeder kann ein Nutzerkonto anlegen. Dieses muss allerdings durch den Admin freigeschaltet werden, bevor es verwendet werden kann.
* **Geschlossen**: Es können keine weiteren Nutzerkonten angelegt werden.
##### Einladungen
Zusätzlich zu den oben genannten Möglichkeiten, kann die Registrierung eines neuen Nutzerkontos an eine Einladung durch einen bestehenden Nutzer gekoppelt werden.
Hierzu muss in der [.htconfig.php](/help/htconfig) Datei die Option `invitation_only` aktiviert und als Registrierungsmethode entweder *Offen* oder *Bedarf der Zustimmung* gewählt werden.
#### Namen auf Vollständigkeit überprüfen
Es kann vorkommen, dass viele Spammer versuchen, sich auf deiner Seite zu registrieren.
@ -108,6 +122,15 @@ Unautorisierte Personen haben ebenfalls nicht die Möglichkeit, Freundschaftsanf
Die Standardeinstellung ist deaktiviert.
Verfügbar in Version 2.2 und höher.
#### Für Besucher verfügbare Gemeinschaftsseiten
Die Gemeinschaftsseiten zeigen all öffentlichen Beiträge.
Es gibt zwei Gemeinschaftsseiten, eine lokale auf der die Beiträge der Nutzer des Knotens gesammelt werden und eine globale auf der alle bekannten Beiträge aus dem gesamten Netzwerk erscheinen.
Mit dieser Einstellung kann geregelt werden, welche dieser beiden Seiten Besucher aufrufen können.
Angemeldete Nutzer des Knotens können grundsätzlich beide Seiten verwenden.
**Hinweis**: Einige Einstellungen, wie z.B. das Verbergen von Kontakten auf der Profilseite, können die Sichtbarkeit der Beiträge auf der Gemeinschaftsseiten beeinflussen.
#### Erlaubte Domains für Kontakte
Kommagetrennte Liste von Domains, welche eine Freundschaft mit dieser Seite eingehen dürfen.

View file

@ -25,8 +25,10 @@ Example: To set the automatic database cleanup process add this line to your .ht
* **allowed_link_protocols** (Array) - Allowed protocols in links URLs, add at your own risk. http is always allowed.
* **always_show_preview** (Boolean) - Only show small preview picures. Default value is false.
* **block_local_dir** (Boolean) - Blocks the access to the directory of the local users.
* **archival_days** (Integer) - Number of days that we try to deliver content before we archive a contact. Defaults to 32.
* **auth_cookie_lifetime** (Integer) - Number of days that should pass without any activity before a user who chose "Remember me" when logging in is considered logged out. Defaults to 7.
* **block_local_dir** (Boolean) - Blocks the access to the directory of the local users.
* **config_adapter** (jit|preload) - Allow to switch the configuration adapter to improve performances at the cost of memory consumption. Default value is "jit"
* **curl_range_bytes** - Maximum number of bytes that should be fetched. Default is 0, which mean "no limit".
* **db_log** - Name of a logfile to log slow database queries
* **db_loglimit** - If a database call lasts longer than this value it is logged
@ -40,6 +42,7 @@ Example: To set the automatic database cleanup process add this line to your .ht
* **diaspora_test** (Boolean) - For development only. Disables the message transfer.
* **disable_email_validation** (Boolean) - Disables the check if a mail address is in a valid format and can be resolved via DNS.
* **disable_url_validation** (Boolean) - Disables the DNS lookup of an URL.
* **disable_password_exposed** (Boolean) - Disable the exposition check against the remote haveibeenpwned API on password change. Default value is false.
* **dlogfile - location of the developer log file
* **dlogip - restricts develop log writes to requests originating from this IP address
* **frontend_worker_timeout** - Value in minutes after we think that a frontend task was killed by the webserver. Default value is 10.
@ -47,6 +50,7 @@ Example: To set the automatic database cleanup process add this line to your .ht
* **ignore_cache** (Boolean) - For development only. Disables the item cache.
* **instances_social_key** - Key to the API of https://instances.social which retrieves data about mastodon servers. See https://instances.social/api/token to get an API key.
* **ipv4_resolve** (Boolean) - Resolve IPV4 addresses only. Don't resolve to IPV6. Default value is false.
* **invitation_only** (Boolean) - If set true registration is only possible after a current member of the node has send an invitation. Default is false.
* **like_no_comment** (Boolean) - Don't update the "commented" value of an item when it is liked.
* **local_block** (Boolean) - Used in conjunction with "block_public".
* **local_search** (Boolean) - Blocks search for users who are not logged in to prevent crawlers from blocking your system.
@ -82,11 +86,6 @@ Example: To set the automatic database cleanup process add this line to your .ht
* **proxy_cache_time** - Time after which the cache is cleared. Default value is one day.
* **pushpoll_frequency** -
* **qsearch_limit** - Default value is 100.
* **relay_server** - Experimental Diaspora feature. Address of the relay server where public posts should be send to. For example https://podrelay.net
* **relay_subscribe** (Boolean) - Enables the receiving of public posts from the relay. They will be included in the search and on the community page when it is set up to show all public items.
* **relay_scope** - Can be "all" or "tags". "all" means that every public post should be received. "tags" means that only posts with selected tags should be received.
* **relay_server_tags** - Comma separated list of tags for the "tags" subscription (see "relay_scrope")
* **relay_user_tags** (Boolean) - If enabled, the tags from the saved searches will used for the "tags" subscription in addition to the "relay_server_tags".
* **remove_multiplicated_lines** (Boolean) - If enabled, multiple linefeeds in items are stripped to a single one.
* **show_unsupported_addons** (Boolean) - Show all addons including the unsupported ones.
* **show_unsupported_themes** (Boolean) - Show all themes including the unsupported ones.

View file

@ -11,16 +11,16 @@ Installation
- Change it's owner to whichever user is running the server, ie. ejabberd
$ chown ejabberd:ejabberd /path/to/friendica/include/auth_ejabberd.php
$ chown ejabberd:ejabberd /path/to/friendica/bin/auth_ejabberd.php
- Change the access mode so it is readable only to the user ejabberd and has exec
$ chmod 700 /path/to/friendica/include/auth_ejabberd.php
$ chmod 700 /path/to/friendica/bin/auth_ejabberd.php
- Edit your ejabberd.cfg file, comment out your auth_method and add:
{auth_method, external}.
{extauth_program, "/path/to/friendica/include/auth_ejabberd.php"}.
{extauth_program, "/path/to/friendica/bin/auth_ejabberd.php"}.
- Disable the module "mod_register" and disable the registration:

View file

@ -6,7 +6,6 @@ To change the look of friendica you have to touch the themes.
The current default theme is [Vier](https://github.com/friendica/friendica/tree/master/view/theme/vier) but there are numerous others.
Have a look at [friendica-themes.com](http://friendica-themes.com) for an overview of the existing themes.
In case none of them suits your needs, there are several ways to change a theme.
If you need help theming, there is a forum @[ftdevs@friendica.eu](https://friendica.eu/profile/ftdevs) where you can ask theme specific questions and present your themes.
So, how to work on the UI of friendica.
@ -206,7 +205,7 @@ Basically what you have to do is identify which template you have to change so i
Adopt the CSS of the theme accordingly.
And iterate the process until you have the theme the way you want it.
*Use the source Luke.* and don't hesitate to ask in @[ftdevs](https://friendica.eu/profile/ftdevs) or @[helpers](https://forum.friendi.ca/profile/helpers).
*Use the source Luke.* and don't hesitate to ask in @[developers](https://forum.friendi.ca/profile/developers) or @[helpers](https://forum.friendi.ca/profile/helpers).
## Special Files

View file

@ -29,20 +29,21 @@ The location of the translated files in the source tree is
/view/lang/LNG-CODE/
where LNG-CODE is the language code used, e.g. de for German or fr for French.
The translated strings come as a "message.po" file from transifex which needs to be translated into the PHP file friendica uses.
To do so, place the file in the directory mentioned above and use the "po2php" utility from the util directory of your friendica installation.
To do so, place the file in the directory mentioned above and use the "po2php" command from the Friendica Console.
Assuming you want to convert the German localization which is placed in view/lang/de/message.po you would do the following.
1. Navigate at the command prompt to the base directory of your
friendica installation
2. Execute the po2php script, which will place the translation
2. Execute the po2php command, which will place the translation
in the strings.php file that is used by friendica.
$> php util/po2php.php view/lang/de/messages.po
$> php bin/console.php po2php view/lang/de/messages.po
The output of the script will be placed at view/lang/de/strings.php where
friendica is expecting it, so you can test your translation immediately.
*Please note that the console tool has to be called from the base directory of your Friendica installation.*
3. Visit your friendica page to check if it still works in the language you
just translated. If not try to find the error, most likely PHP will give
@ -64,7 +65,7 @@ Otherwise your work might get lost, when the translation from Transifex is inclu
Utilities
---------
Additional to the po2php script there are some more utilities for translation in the "util" directory of the friendica source tree.
Additional to the po2php command there are some more utilities for translation in the console.
If you only want to translate friendica into another language you wont need any of these tools most likely but it gives you an idea how the translation process of friendica works.
For further information see the utils/README file.
@ -92,9 +93,9 @@ To update the translation files after you have translated strings of e.g. Espera
$> tx pull -l eo
And then use the `po2php` utility described above to convert the `messages.po` file to the `strings.php` file Friendica is loading.
And then use the `po2php` command described above to convert the `messages.po` file to the `strings.php` file Friendica is loading.
$> php util/po2php.php view/lang/eo/messages.po
$> php bin/console.php po2php view/lang/eo/messages.po
Afterwards, just commit the two changed files to a feature branch of your Friendica repository, push the changes to github and open a pull request for your changes.

File diff suppressed because one or more lines are too long

View file

@ -2,6 +2,11 @@
// If automatic system installation fails:
die('The configuration you did manually contains some mistakes. Please have a look at your .htconfig.php file.');
// If you are doing the configuration manually, please remove the line above
// Copy or rename this file to .htconfig.php
// Why .htconfig.php? Because it contains sensitive information which could

View file

@ -10,6 +10,7 @@ use Friendica\App;
use Friendica\Content\ContactSelector;
use Friendica\Content\Feature;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\L10n;
@ -41,11 +42,9 @@ use Friendica\Util\Network;
use Friendica\Util\XML;
require_once 'include/conversation.php';
require_once 'include/html2plain.php';
require_once 'mod/share.php';
require_once 'mod/item.php';
require_once 'include/security.php';
require_once 'include/html2bbcode.php';
require_once 'mod/wall_upload.php';
require_once 'mod/proxy.php';
@ -224,7 +223,7 @@ function api_login(App $a)
$record = $addon_auth['user_record'];
} else {
$user_id = User::authenticate(trim($user), trim($password));
if ($user_id) {
if ($user_id !== false) {
$record = dba::selectFirst('user', [], ['uid' => $user_id]);
}
}
@ -268,7 +267,7 @@ function api_check_method($method)
* @brief Main API entry point
*
* @param object $a App
* @return string API call result
* @return string|array API call result
*/
function api_call(App $a)
{
@ -388,9 +387,7 @@ function api_call(App $a)
break;
case "json":
header("Content-Type: application/json");
foreach ($return as $rr) {
$json = json_encode($rr);
}
$json = json_encode(end($return));
if (x($_GET, 'callback')) {
$json = $_GET['callback'] . "(" . $json . ")";
}
@ -422,7 +419,7 @@ function api_call(App $a)
*
* @param string $type Return type (xml, json, rss, as)
* @param object $e HTTPException Error object
* @return string error message formatted as $type
* @return string|array error message formatted as $type
*/
function api_error($type, $e)
{
@ -532,7 +529,7 @@ function api_get_user(App $a, $contact_id = null)
// Searching for contact id with uid = 0
if (!is_null($contact_id) && (intval($contact_id) != 0)) {
$user = dbesc(api_unique_id_to_nurl($contact_id));
$user = dbesc(api_unique_id_to_nurl(intval($contact_id)));
if ($user == "") {
throw new BadRequestException("User not found.");
@ -578,16 +575,14 @@ function api_get_user(App $a, $contact_id = null)
$argid = count($called_api);
list($user, $null) = explode(".", $a->argv[$argid]);
if (is_numeric($user)) {
$user = dbesc(api_unique_id_to_nurl($user));
$user = dbesc(api_unique_id_to_nurl(intval($user)));
if ($user == "") {
return false;
}
$url = $user;
$extra_query = "AND `contact`.`nurl` = '%s' ";
if (api_user() !== false) {
$extra_query .= "AND `contact`.`uid`=" . intval(api_user());
if ($user != "") {
$url = $user;
$extra_query = "AND `contact`.`nurl` = '%s' ";
if (api_user() !== false) {
$extra_query .= "AND `contact`.`uid`=" . intval(api_user());
}
}
} else {
$user = dbesc($user);
@ -621,7 +616,9 @@ function api_get_user(App $a, $contact_id = null)
);
// Selecting the id by priority, friendica first
api_best_nickname($uinfo);
if (is_array($uinfo)) {
api_best_nickname($uinfo);
}
// if the contact wasn't found, fetch it from the contacts with uid = 0
if (!DBM::is_result($uinfo)) {
@ -648,6 +645,8 @@ function api_get_user(App $a, $contact_id = null)
'description' => $r[0]["about"],
'profile_image_url' => $r[0]["micro"],
'profile_image_url_https' => $r[0]["micro"],
'profile_image_url_profile_size' => $r[0]["thumb"],
'profile_image_url_large' => $r[0]["photo"],
'url' => $r[0]["url"],
'protected' => false,
'followers_count' => 0,
@ -783,6 +782,8 @@ function api_get_user(App $a, $contact_id = null)
'description' => $description,
'profile_image_url' => $uinfo[0]['micro'],
'profile_image_url_https' => $uinfo[0]['micro'],
'profile_image_url_profile_size' => $uinfo[0]["thumb"],
'profile_image_url_large' => $uinfo[0]["photo"],
'url' => $uinfo[0]['url'],
'protected' => false,
'followers_count' => intval($countfollowers),
@ -978,7 +979,7 @@ function api_create_xml($data, $root_element)
* @param string $type Return type (atom, rss, xml, json)
* @param array $data JSON style array
*
* @return (string|object|array) XML data or JSON data
* @return (string|array) XML data or JSON data
*/
function api_format_data($root_element, $type, $data)
{
@ -989,6 +990,7 @@ function api_format_data($root_element, $type, $data)
$ret = api_create_xml($data, $root_element);
break;
case "json":
default:
$ret = $data;
break;
}
@ -1096,7 +1098,7 @@ function api_statuses_mediap($type)
$purifier = new HTMLPurifier($config);
$txt = $purifier->purify($txt);
}
$txt = html2bbcode($txt);
$txt = HTML::toBBCode($txt);
$a->argv[1]=$user_info['screen_name']; //should be set to username?
@ -1147,7 +1149,7 @@ function api_statuses_update($type)
$purifier = new HTMLPurifier($config);
$txt = $purifier->purify($txt);
$_REQUEST['body'] = html2bbcode($txt);
$_REQUEST['body'] = HTML::toBBCode($txt);
}
} else {
$_REQUEST['body'] = requestdata('status');
@ -1426,7 +1428,7 @@ function api_status_show($type)
$status_info["entities"] = $converted["entities"];
}
if (($lastwall['item_network'] != "") && ($status["source"] == 'web')) {
if (($lastwall['item_network'] != "") && ($status_info["source"] == 'web')) {
$status_info["source"] = ContactSelector::networkToName($lastwall['item_network'], $user_info['url']);
} elseif (($lastwall['item_network'] != "") && (ContactSelector::networkToName($lastwall['item_network'], $user_info['url']) != $status_info["source"])) {
$status_info["source"] = trim($status_info["source"].' ('.ContactSelector::networkToName($lastwall['item_network'], $user_info['url']).')');
@ -1435,15 +1437,15 @@ function api_status_show($type)
// "uid" and "self" are only needed for some internal stuff, so remove it from here
unset($status_info["user"]["uid"]);
unset($status_info["user"]["self"]);
logger('status_info: '.print_r($status_info, true), LOGGER_DEBUG);
if ($type == "raw") {
return $status_info;
}
return api_format_data("statuses", $type, ['status' => $status_info]);
}
logger('status_info: '.print_r($status_info, true), LOGGER_DEBUG);
if ($type == "raw") {
return $status_info;
}
return api_format_data("statuses", $type, ['status' => $status_info]);
}
/**
@ -1627,6 +1629,13 @@ api_register_func('api/users/lookup', 'api_users_lookup', true);
*/
function api_search($type)
{
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
$data = [];
$sql_extra = '';
@ -1665,7 +1674,7 @@ function api_search($type)
$since_id
);
$data['status'] = api_format_items(dba::inArray($r), api_get_user(get_app()));
$data['status'] = api_format_items(dba::inArray($r), $user_info);
return api_format_data("statuses", $type, $data);
}
@ -1687,8 +1696,9 @@ api_register_func('api/search', 'api_search', true);
function api_statuses_home_timeline($type)
{
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) {
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
@ -1698,8 +1708,7 @@ function api_statuses_home_timeline($type)
unset($_REQUEST["screen_name"]);
unset($_GET["screen_name"]);
$user_info = api_get_user($a);
// get last newtork messages
// get last network messages
// params
$count = (x($_REQUEST, 'count') ? $_REQUEST['count'] : 20);
@ -1789,13 +1798,13 @@ api_register_func('api/statuses/friends_timeline', 'api_statuses_home_timeline',
function api_statuses_public_timeline($type)
{
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) {
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
$user_info = api_get_user($a);
// get last newtork messages
// get last network messages
// params
$count = (x($_REQUEST, 'count') ? $_REQUEST['count'] : 20);
@ -1898,13 +1907,12 @@ api_register_func('api/statuses/public_timeline', 'api_statuses_public_timeline'
function api_statuses_networkpublic_timeline($type)
{
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) {
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
$user_info = api_get_user($a);
$since_id = x($_REQUEST, 'since_id') ? $_REQUEST['since_id'] : 0;
$max_id = x($_REQUEST, 'max_id') ? $_REQUEST['max_id'] : 0;
@ -1968,13 +1976,12 @@ api_register_func('api/statuses/networkpublic_timeline', 'api_statuses_networkpu
function api_statuses_show($type)
{
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) {
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
$user_info = api_get_user($a);
// params
$id = intval($a->argv[3]);
@ -2042,13 +2049,12 @@ api_register_func('api/statuses/show', 'api_statuses_show', true);
function api_conversation_show($type)
{
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) {
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
$user_info = api_get_user($a);
// params
$id = intval($a->argv[3]);
$count = (x($_REQUEST, 'count') ? $_REQUEST['count'] : 20);
@ -2255,8 +2261,9 @@ api_register_func('api/statuses/destroy', 'api_statuses_destroy', true, API_METH
function api_statuses_mentions($type)
{
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) {
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
@ -2266,9 +2273,7 @@ function api_statuses_mentions($type)
unset($_REQUEST["screen_name"]);
unset($_GET["screen_name"]);
$user_info = api_get_user($a);
// get last newtork messages
// get last network messages
// params
$since_id = defaults($_REQUEST, 'since_id', 0);
@ -2347,13 +2352,12 @@ api_register_func('api/statuses/replies', 'api_statuses_mentions', true);
function api_statuses_user_timeline($type)
{
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) {
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
$user_info = api_get_user($a);
logger(
"api_statuses_user_timeline: api_user: ". api_user() .
"\nuser_info: ".print_r($user_info, true) .
@ -2517,15 +2521,14 @@ function api_favorites($type)
global $called_api;
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) {
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
$called_api = [];
$user_info = api_get_user($a);
// in friendica starred item are private
// return favorites only for self
logger('api_favorites: self:' . $user_info['self']);
@ -2624,10 +2627,10 @@ function api_format_messages($item, $recipient, $sender)
if ($_GET['getText'] == 'html') {
$ret['text'] = BBCode::convert($item['body'], false);
} elseif ($_GET['getText'] == 'plain') {
$ret['text'] = trim(html2plain(BBCode::convert(api_clean_plain_items($item['body']), false, 2, true), 0));
$ret['text'] = trim(HTML::toPlaintext(BBCode::convert(api_clean_plain_items($item['body']), false, 2, true), 0));
}
} else {
$ret['text'] = $item['title'] . "\n" . html2plain(BBCode::convert(api_clean_plain_items($item['body']), false, 2, true), 0);
$ret['text'] = $item['title'] . "\n" . HTML::toPlaintext(BBCode::convert(api_clean_plain_items($item['body']), false, 2, true), 0);
}
if (x($_GET, 'getUserObjects') && $_GET['getUserObjects'] == 'false') {
unset($ret['sender']);
@ -2650,7 +2653,7 @@ function api_convert_item($item)
// Workaround for ostatus messages where the title is identically to the body
$html = BBCode::convert(api_clean_plain_items($body), false, 2, true);
$statusbody = trim(html2plain($html, 0));
$statusbody = trim(HTML::toPlaintext($html, 0));
// handle data: images
$statusbody = api_format_items_embeded_images($item, $statusbody);
@ -3265,22 +3268,6 @@ function api_help_test($type)
/// @TODO move to top of file or somewhere better
api_register_func('api/help/test', 'api_help_test', false);
/**
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
*/
function api_lists($type)
{
$ret = [];
/// @TODO $ret is not filled here?
return api_format_data('lists', $type, ["lists_list" => $ret]);
}
/// @TODO move to top of file or somewhere better
api_register_func('api/lists', 'api_lists', true);
/**
* Returns all lists the user subscribes to.
*
@ -3298,6 +3285,139 @@ function api_lists_list($type)
/// @TODO move to top of file or somewhere better
api_register_func('api/lists/list', 'api_lists_list', true);
api_register_func('api/lists/subscriptions', 'api_lists_list', true);
/**
* Returns all groups the user owns.
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-ownerships
*/
function api_lists_ownerships($type)
{
$a = get_app();
if (api_user() === false) {
throw new ForbiddenException();
}
// params
$user_info = api_get_user($a);
$uid = $user_info['uid'];
$groups = dba::select('group', [], ['deleted' => 0, 'uid' => $uid]);
// loop through all groups
$lists = [];
foreach ($groups as $group) {
if ($group['visible']) {
$mode = 'public';
} else {
$mode = 'private';
}
$lists[] = [
'name' => $group['name'],
'id' => intval($group['id']),
'id_str' => (string) $group['id'],
'user' => $user_info,
'mode' => $mode
];
}
return api_format_data("lists", $type, ['lists' => ['lists' => $lists]]);
}
/// @TODO move to top of file or somewhere better
api_register_func('api/lists/ownerships', 'api_lists_ownerships', true);
/**
* Returns recent statuses from users in the specified group.
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-ownerships
*/
function api_lists_statuses($type)
{
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
unset($_REQUEST["user_id"]);
unset($_GET["user_id"]);
unset($_REQUEST["screen_name"]);
unset($_GET["screen_name"]);
if (empty($_REQUEST['list_id'])) {
throw new BadRequestException('list_id not specified');
}
// params
$count = (x($_REQUEST, 'count') ? $_REQUEST['count'] : 20);
$page = (x($_REQUEST, 'page') ? $_REQUEST['page'] - 1 : 0);
if ($page < 0) {
$page = 0;
}
$since_id = (x($_REQUEST, 'since_id') ? $_REQUEST['since_id'] : 0);
$max_id = (x($_REQUEST, 'max_id') ? $_REQUEST['max_id'] : 0);
$exclude_replies = (x($_REQUEST, 'exclude_replies') ? 1 : 0);
$conversation_id = (x($_REQUEST, 'conversation_id') ? $_REQUEST['conversation_id'] : 0);
$start = $page * $count;
$sql_extra = '';
if ($max_id > 0) {
$sql_extra .= ' AND `item`.`id` <= ' . intval($max_id);
}
if ($exclude_replies > 0) {
$sql_extra .= ' AND `item`.`parent` = `item`.`id`';
}
if ($conversation_id > 0) {
$sql_extra .= ' AND `item`.`parent` = ' . intval($conversation_id);
}
$statuses = dba::p(
"SELECT `item`.*, `item`.`id` AS `item_id`, `item`.`network` AS `item_network`,
`contact`.`name`, `contact`.`photo`, `contact`.`url`, `contact`.`rel`,
`contact`.`network`, `contact`.`thumb`, `contact`.`dfrn-id`, `contact`.`self`,
`contact`.`id` AS `cid`, `group_member`.`gid`
FROM `item`
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id` AND `contact`.`uid` = `item`.`uid`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
STRAIGHT_JOIN `group_member` ON `group_member`.`contact-id` = `item`.`contact-id`
WHERE `item`.`uid` = ? AND `verb` = ?
AND `item`.`visible` AND NOT `item`.`moderated` AND NOT `item`.`deleted`
$sql_extra
AND `item`.`id`>?
AND `group_member`.`gid` = ?
ORDER BY `item`.`id` DESC LIMIT ".intval($start)." ,".intval($count),
api_user(),
ACTIVITY_POST,
$since_id,
$_REQUEST['list_id']
);
$items = api_format_items(dba::inArray($statuses), $user_info, false, $type);
$data = ['status' => $items];
switch ($type) {
case "atom":
case "rss":
$data = api_rss_extra($a, $data, $user_info);
break;
}
return api_format_data("statuses", $type, $data);
}
/// @TODO move to top of file or somewhere better
api_register_func('api/lists/statuses', 'api_lists_statuses', true);
/**
* Considers friends and followers lists to be private and won't return
@ -3697,7 +3817,7 @@ api_register_func('api/direct_messages/new', 'api_direct_messages_new', true, AP
* @brief delete a direct_message from mail table through api
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string
* @return string|array
* @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/delete-message
*/
function api_direct_messages_destroy($type)
@ -3783,8 +3903,9 @@ api_register_func('api/direct_messages/destroy', 'api_direct_messages_destroy',
function api_direct_messages_box($type, $box, $verbose)
{
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) {
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
@ -3808,7 +3929,6 @@ function api_direct_messages_box($type, $box, $verbose)
unset($_REQUEST["screen_name"]);
unset($_GET["screen_name"]);
$user_info = api_get_user($a);
$profile_url = $user_info["url"];
// pagination
@ -3859,7 +3979,9 @@ function api_direct_messages_box($type, $box, $verbose)
$sender = $user_info;
}
$ret[] = api_format_messages($item, $recipient, $sender);
if (isset($recipient) && isset($sender)) {
$ret[] = api_format_messages($item, $recipient, $sender);
}
}
@ -3977,7 +4099,7 @@ api_register_func('api/oauth/access_token', 'api_oauth_access_token', false);
* @brief delete a complete photoalbum with all containing photos from database through api
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string
* @return string|array
*/
function api_fr_photoalbum_delete($type)
{
@ -4032,7 +4154,7 @@ function api_fr_photoalbum_delete($type)
* @brief update the name of the album for all photos of an album
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string
* @return string|array
*/
function api_fr_photoalbum_update($type)
{
@ -4081,7 +4203,7 @@ function api_fr_photoalbum_update($type)
* @brief list all photos of the authenticated user
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string
* @return string|array
*/
function api_fr_photos_list($type)
{
@ -4127,7 +4249,7 @@ function api_fr_photos_list($type)
* @brief upload a new photo or change an existing photo
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string
* @return string|array
*/
function api_fr_photo_create_update($type)
{
@ -4275,7 +4397,7 @@ function api_fr_photo_create_update($type)
* @brief delete a single photo from the database through api
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string
* @return string|array
*/
function api_fr_photo_delete($type)
{
@ -4358,7 +4480,7 @@ function api_fr_photo_detail($type)
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
*
* @return string
* @return string|array
* @see https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_image
*/
function api_account_update_profile_image($type)
@ -4410,6 +4532,8 @@ function api_account_update_profile_image($type)
$fileext = "jpg";
} elseif ($filetype == "image/png") {
$fileext = "png";
} else {
throw new InternalServerErrorException('Unsupported filetype');
}
// change specified profile or all profiles to the new resource-id
if ($is_default_profile) {
@ -4690,7 +4814,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
logger("photo upload: new profile image upload ended", LOGGER_DEBUG);
}
if ($r) {
if (isset($r) && $r) {
// create entry in 'item'-table on new uploads to enable users to comment/like/dislike the photo
if ($photo_id == null && $mediatype == "photo") {
post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility);
@ -4766,6 +4890,13 @@ function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $f
*/
function prepare_photo_data($type, $scale, $photo_id)
{
$a = get_app();
$user_info = api_get_user($a);
if ($user_info === false) {
throw new ForbiddenException();
}
$scale_sql = ($scale === false ? "" : sprintf("AND scale=%d", intval($scale)));
$data_sql = ($scale === false ? "" : "data, ");
@ -4846,7 +4977,7 @@ function prepare_photo_data($type, $scale, $photo_id)
);
// prepare output of comments
$commentData = api_format_items($r, api_get_user(get_app()), false, $type);
$commentData = api_format_items($r, $user_info, false, $type);
$comments = [];
if ($type == "xml") {
$k = 0;
@ -5221,7 +5352,7 @@ function api_clean_attachments($body)
{
$data = BBCode::getAttachmentData($body);
if (!$data) {
if (empty($data)) {
return $body;
}
$body = "";
@ -5347,6 +5478,7 @@ function api_friendica_group_show($type)
}
// loop through all groups and retrieve all members for adding data in the user array
$grps = [];
foreach ($r as $rr) {
$members = Contact::getByGroupId($rr['id']);
$users = [];
@ -5433,15 +5565,15 @@ function api_friendica_group_delete($type)
}
api_register_func('api/friendica/group_delete', 'api_friendica_group_delete', true, API_METHOD_DELETE);
/**
* Create the specified group with the posted array of contacts.
* Delete a group.
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-destroy
*/
function api_friendica_group_create($type)
function api_lists_destroy($type)
{
$a = get_app();
@ -5451,11 +5583,45 @@ function api_friendica_group_create($type)
// params
$user_info = api_get_user($a);
$name = (x($_REQUEST, 'name') ? $_REQUEST['name'] : "");
$gid = (x($_REQUEST, 'list_id') ? $_REQUEST['list_id'] : 0);
$uid = $user_info['uid'];
$json = json_decode($_POST['json'], true);
$users = $json['user'];
// error if no gid specified
if ($gid == 0) {
throw new BadRequestException('gid not specified');
}
// get data of the specified group id
$group = dba::selectFirst('group', [], ['uid' => $uid, 'id' => $gid]);
// error message if specified gid is not in database
if (!$group) {
throw new BadRequestException('gid not available');
}
if (Group::remove($gid)) {
$list = [
'name' => $group['name'],
'id' => intval($gid),
'id_str' => (string) $gid,
'user' => $user_info
];
return api_format_data("lists", $type, ['lists' => $list]);
}
}
api_register_func('api/lists/destroy', 'api_lists_destroy', true, API_METHOD_DELETE);
/**
* Add a new group to the database.
*
* @param string $name Group name
* @param int $uid User ID
* @param array $users List of users to add to the group
*
* @return array
*/
function group_create($name, $uid, $users = [])
{
// error if no name specified
if ($name == "") {
throw new BadRequestException('group name not specified');
@ -5511,12 +5677,73 @@ function api_friendica_group_create($type)
}
// return success message incl. missing users in array
$status = ($erroraddinguser ? "missing user" : ($reactivate_group ? "reactivated" : "ok"));
$success = ['success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers];
$status = ($erroraddinguser ? "missing user" : ((isset($reactivate_group) && $reactivate_group) ? "reactivated" : "ok"));
return ['success' => true, 'gid' => $gid, 'name' => $name, 'status' => $status, 'wrong users' => $errorusers];
}
/**
* Create the specified group with the posted array of contacts.
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
*/
function api_friendica_group_create($type)
{
$a = get_app();
if (api_user() === false) {
throw new ForbiddenException();
}
// params
$user_info = api_get_user($a);
$name = (x($_REQUEST, 'name') ? $_REQUEST['name'] : "");
$uid = $user_info['uid'];
$json = json_decode($_POST['json'], true);
$users = $json['user'];
$success = group_create($name, $uid, $users);
return api_format_data("group_create", $type, ['result' => $success]);
}
api_register_func('api/friendica/group_create', 'api_friendica_group_create', true, API_METHOD_POST);
/**
* Create a new group.
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-create
*/
function api_lists_create($type)
{
$a = get_app();
if (api_user() === false) {
throw new ForbiddenException();
}
// params
$user_info = api_get_user($a);
$name = (x($_REQUEST, 'name') ? $_REQUEST['name'] : "");
$uid = $user_info['uid'];
$success = group_create($name, $uid);
if ($success['success']) {
$grp = [
'name' => $success['name'],
'id' => intval($success['gid']),
'id_str' => (string) $success['gid'],
'user' => $user_info
];
return api_format_data("lists", $type, ['lists'=>$grp]);
}
}
api_register_func('api/lists/create', 'api_lists_create', true, API_METHOD_POST);
/**
* Update the specified group with the posted array of contacts.
@ -5558,7 +5785,7 @@ function api_friendica_group_update($type)
foreach ($users as $user) {
$found = ($user['cid'] == $cid ? true : false);
}
if (!$found) {
if (!isset($found) || !$found) {
Group::removeMemberByName($uid, $name, $cid);
}
}
@ -5591,6 +5818,54 @@ function api_friendica_group_update($type)
api_register_func('api/friendica/group_update', 'api_friendica_group_update', true, API_METHOD_POST);
/**
* Update information about a group.
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-update
*/
function api_lists_update($type)
{
$a = get_app();
if (api_user() === false) {
throw new ForbiddenException();
}
// params
$user_info = api_get_user($a);
$gid = (x($_REQUEST, 'list_id') ? $_REQUEST['list_id'] : 0);
$name = (x($_REQUEST, 'name') ? $_REQUEST['name'] : "");
$uid = $user_info['uid'];
// error if no gid specified
if ($gid == 0) {
throw new BadRequestException('gid not specified');
}
// get data of the specified group id
$group = dba::selectFirst('group', [], ['uid' => $uid, 'id' => $gid]);
// error message if specified gid is not in database
if (!$group) {
throw new BadRequestException('gid not available');
}
if (Group::update($gid, $name)) {
$list = [
'name' => $name,
'id' => intval($gid),
'id_str' => (string) $gid,
'user' => $user_info
];
return api_format_data("lists", $type, ['lists' => $list]);
}
}
api_register_func('api/lists/update', 'api_lists_update', true, API_METHOD_POST);
/**
*
* @param string $type Return type (atom, rss, xml, json)
@ -5639,7 +5914,7 @@ api_register_func('api/friendica/activity/unattendmaybe', 'api_friendica_activit
* @brief Returns notifications
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string
* @return string|array
*/
function api_friendica_notification($type)
{
@ -5673,13 +5948,14 @@ function api_friendica_notification($type)
* @brief Set notification as seen and returns associated item (if possible)
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string
* @return string|array
*/
function api_friendica_notification_seen($type)
{
$a = get_app();
$user_info = api_get_user($a);
if (api_user() === false) {
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
if ($a->argc!==4) {
@ -5704,7 +5980,6 @@ function api_friendica_notification_seen($type)
);
if ($r!==false) {
// we found the item, return it to the user
$user_info = api_get_user($a);
$ret = api_format_items($r, $user_info, false, $type);
$data = ['status' => $ret];
return api_format_data("status", $type, $data);
@ -5722,7 +5997,7 @@ api_register_func('api/friendica/notification', 'api_friendica_notification', tr
* @brief update a direct_message to seen state
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string (success result=ok, error result=error with error message)
* @return string|array (success result=ok, error result=error with error message)
*/
function api_friendica_direct_messages_setseen($type)
{
@ -5780,7 +6055,7 @@ api_register_func('api/friendica/direct_messages_setseen', 'api_friendica_direct
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @param string $box
* @return string (success: success=true if found and search_result contains found messages,
* @return string|array (success: success=true if found and search_result contains found messages,
* success=false if nothing was found, search_result='nothing found',
* error: result=error with error message)
*/
@ -5828,7 +6103,9 @@ function api_friendica_direct_messages_search($type, $box = "")
$sender = $user_info;
}
$ret[] = api_format_messages($item, $recipient, $sender);
if (isset($recipient) && isset($sender)) {
$ret[] = api_format_messages($item, $recipient, $sender);
}
}
$success = ['success' => true, 'search_results' => $ret];
}
@ -5843,7 +6120,7 @@ api_register_func('api/friendica/direct_messages_search', 'api_friendica_direct_
* @brief return data of all the profiles a user has to the client
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string
* @return string|array
*/
function api_friendica_profile_show($type)
{
@ -5880,19 +6157,20 @@ function api_friendica_profile_show($type)
}
// loop through all returned profiles and retrieve data and users
$k = 0;
$profiles = [];
foreach ($r as $rr) {
$profile = api_format_items_profiles($rr);
// select all users from contact table, loop and prepare standard return for user data
$users = [];
$r = q(
$nurls = q(
"SELECT `id`, `nurl` FROM `contact` WHERE `uid`= %d AND `profile-id` = %d",
intval(api_user()),
intval($rr['profile_id'])
);
foreach ($r as $rr) {
$user = api_get_user($a, $rr['nurl']);
foreach ($nurls as $nurl) {
$user = api_get_user($a, $nurl['nurl']);
($type == "xml") ? $users[$k++ . ":user"] = $user : $users[] = $user;
}
$profile['users'] = $users;
@ -5932,10 +6210,12 @@ function api_saved_searches_list($type)
$result = [];
while ($term = $terms->fetch()) {
$result[] = [
'name' => $term['term'],
'query' => $term['term'],
'created_at' => api_date(time()),
'id' => intval($term['id']),
'id_str' => $term['id'],
'id' => intval($term['id'])
'name' => $term['term'],
'position' => null,
'query' => $term['term']
];
}

View file

@ -443,7 +443,7 @@ These Fields are not added below (yet). They are here to for bug search.
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`,
`item`.`contact-id`, `item`.`uid`, `item`.`id`, `item`.`parent`,
`item`.`uri`, `item`.`thr-parent`, `item`.`parent-uri`,
`item`.`uri`, `item`.`thr-parent`, `item`.`parent-uri`, `item`.`content-warning`,
`item`.`commented`, `item`.`created`, `item`.`edited`, `item`.`received`,
`item`.`verb`, `item`.`object-type`, `item`.`postopts`, `item`.`plink`,
`item`.`guid`, `item`.`wall`, `item`.`private`, `item`.`starred`,
@ -756,7 +756,13 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
list($categories, $folders) = get_cats_and_terms($item);
$profile_name_e = $profile_name;
$item['title_e'] = $item['title'];
if (!empty($item['content-warning']) && PConfig::get(local_user(), 'system', 'disable_cw', false)) {
$title_e = ucfirst($item['content-warning']);
} else {
$title_e = $item['title'];
}
$body_e = $body;
$tags_e = $tags;
$hashtags_e = $hashtags;
@ -781,7 +787,7 @@ function conversation(App $a, $items, $mode, $update, $preview = false, $order =
'sparkle' => $sparkle,
'lock' => $lock,
'thumb' => System::removedBaseUrl(proxy_url($item['author-thumb'], false, PROXY_SIZE_THUMB)),
'title' => $item['title_e'],
'title' => $title_e,
'body' => $body_e,
'tags' => $tags_e,
'hashtags' => $hashtags_e,
@ -1245,7 +1251,7 @@ function format_like($cnt, array $arr, $type, $id) {
break;
case 'attendmaybe':
$phrase = L10n::t('<span %1$s>%2$d people</span> attend maybe', $spanatts, $cnt);
$explikers = L10n::t('%s anttend maybe.', $likers);
$explikers = L10n::t('%s attend maybe.', $likers);
break;
}
@ -1329,6 +1335,7 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false)
$tpl = get_markup_template("jot.tpl");
$o .= replace_macros($tpl,[
'$new_post' => L10n::t('New Post'),
'$return_path' => $query_str,
'$action' => 'item',
'$share' => defaults($x, 'button', L10n::t('Share')),
@ -1643,7 +1650,7 @@ function get_responses($conv_responses, $response_verbs, $ob, $item) {
foreach ($response_verbs as $v) {
$ret[$v] = [];
$ret[$v]['count'] = defaults($conv_responses[$v], $item['uri'], '');
$ret[$v]['list'] = defaults($conv_responses[$v], $item['uri'] . '-l', '');
$ret[$v]['list'] = defaults($conv_responses[$v], $item['uri'] . '-l', []);
$ret[$v]['self'] = defaults($conv_responses[$v], $item['uri'] . '-self', '0');
if (count($ret[$v]['list']) > MAX_LIKERS) {
$ret[$v]['list_part'] = array_slice($ret[$v]['list'], 0, MAX_LIKERS);

View file

@ -13,7 +13,7 @@ use Friendica\Util\DateTimeFormat;
*/
class dba {
public static $connected = true;
public static $connected = false;
private static $_server_info = '';
private static $db;
@ -48,17 +48,14 @@ class dba {
$db = trim($db);
if (!(strlen($server) && strlen($user))) {
self::$connected = false;
self::$db = null;
return false;
}
if ($install) {
if (strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1')) {
if (! dns_get_record($server, DNS_A + DNS_CNAME + DNS_PTR)) {
// 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);
self::$connected = false;
self::$db = null;
return false;
}
}
@ -79,7 +76,6 @@ class dba {
self::$db = @new PDO($connect, $user, $pass);
self::$connected = true;
} catch (PDOException $e) {
self::$connected = false;
}
}
@ -98,13 +94,10 @@ class dba {
// No suitable SQL driver was found.
if (!self::$connected) {
self::$db = null;
if (!$install) {
System::unavailable();
}
}
$a->save_timestamp($stamp1, "network");
return true;
return self::$connected;
}
/**

View file

@ -12,16 +12,14 @@ use Friendica\Database\DBM;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Emailer;
require_once 'include/html2bbcode.php';
/**
* @brief Creates a notification entry and possibly sends a mail
*
* @param array $params Array with the elements:
uid, item, parent, type, otype, verb, event,
link, subject, body, to_name, to_email, source_name,
source_link, activity, preamble, notify_flags,
language, show_in_notification_page
* uid, item, parent, type, otype, verb, event,
* link, subject, body, to_name, to_email, source_name,
* source_link, activity, preamble, notify_flags,
* language, show_in_notification_page
*/
function notification($params)
{
@ -47,10 +45,7 @@ function notification($params)
$hostname = substr($hostname, 0, strpos($hostname, ':'));
}
$sender_email = $a->config['sender_email'];
if (empty($sender_email)) {
$sender_email = L10n::t('noreply').'@'.$hostname;
}
$sender_email = $a->getSenderEmailAddress();
if ($params['type'] != SYSTEM_EMAIL) {
$user = dba::selectFirst('user', ['nickname', 'page-flags'],
@ -362,7 +357,7 @@ function notification($params)
if ($params['type'] == NOTIFY_SYSTEM) {
switch($params['event']) {
case "SYSTEM_REGISTER_REQUEST":
$subject = L10n::t('[Friendica System:Notify] registration request');
$subject = L10n::t('[Friendica System Notify]') . ' ' . L10n::t('registration request');
$preamble = L10n::t('You\'ve received a registration request from \'%1$s\' at %2$s', $params['source_name'], $sitename);
$epreamble = L10n::t('You\'ve received a [url=%1$s]registration request[/url] from %2$s.',
@ -370,7 +365,7 @@ function notification($params)
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]'
);
$body = L10n::t('Full Name: %1$s\nSite Location: %2$s\nLogin Name: %3$s ' . "\x28" . '%4$s' . "\x28",
$body = L10n::t('Full Name: %1$s\nSite Location: %2$s\nLogin Name: %3$s ' . "\x28" . '%4$s' . "\x29",
$params['source_name'],
$siteurl, $params['source_mail'],
$params['source_nick']

File diff suppressed because it is too large Load diff

View file

@ -1,403 +0,0 @@
<?php
/**
* @file include/html2bbcode.php
* @brief Converter for HTML to BBCode
*
* Made by: ike@piratenpartei.de
* Originally made for the syncom project: http://wiki.piratenpartei.de/Syncom
* https://github.com/annando/Syncom
*/
use Friendica\Core\Addon;
use Friendica\Util\Network;
use Friendica\Util\XML;
function node2bbcode(&$doc, $oldnode, $attributes, $startbb, $endbb)
{
do {
$done = node2bbcodesub($doc, $oldnode, $attributes, $startbb, $endbb);
} while ($done);
}
function node2bbcodesub(&$doc, $oldnode, $attributes, $startbb, $endbb)
{
$savestart = str_replace('$', '\x01', $startbb);
$replace = false;
$xpath = new DomXPath($doc);
$list = $xpath->query("//".$oldnode);
foreach ($list as $oldNode) {
$attr = [];
if ($oldNode->attributes->length) {
foreach ($oldNode->attributes as $attribute) {
$attr[$attribute->name] = $attribute->value;
}
}
$replace = true;
$startbb = $savestart;
$i = 0;
foreach ($attributes as $attribute => $value) {
$startbb = str_replace('\x01'.++$i, '$1', $startbb);
if (strpos('*'.$startbb, '$1') > 0) {
if ($replace && (@$attr[$attribute] != '')) {
$startbb = preg_replace($value, $startbb, $attr[$attribute], -1, $count);
// If nothing could be changed
if ($count == 0) {
$replace = false;
}
} else {
$replace = false;
}
} else {
if (@$attr[$attribute] != $value) {
$replace = false;
}
}
}
if ($replace) {
$StartCode = $oldNode->ownerDocument->createTextNode($startbb);
$EndCode = $oldNode->ownerDocument->createTextNode($endbb);
$oldNode->parentNode->insertBefore($StartCode, $oldNode);
if ($oldNode->hasChildNodes()) {
foreach ($oldNode->childNodes as $child) {
$newNode = $child->cloneNode(true);
$oldNode->parentNode->insertBefore($newNode, $oldNode);
}
}
$oldNode->parentNode->insertBefore($EndCode, $oldNode);
$oldNode->parentNode->removeChild($oldNode);
}
}
return($replace);
}
function html2bbcode($message, $basepath = '')
{
$message = str_replace("\r", "", $message);
// Removing code blocks before the whitespace removal processing below
$codeblocks = [];
$message = preg_replace_callback(
'#<pre><code(?: class="([^"]*)")?>(.*)</code></pre>#iUs',
function ($matches) use (&$codeblocks) {
$return = '[codeblock-' . count($codeblocks) . ']';
$prefix = '[code]';
if ($matches[1] != '') {
$prefix = '[code=' . $matches[1] . ']';
}
$codeblocks[] = $prefix . trim($matches[2]) . '[/code]';
return $return;
},
$message
);
$message = str_replace(
[
"<li><p>",
"</p></li>",
],
[
"<li>",
"</li>",
],
$message
);
// remove namespaces
$message = preg_replace('=<(\w+):(.+?)>=', '<removeme>', $message);
$message = preg_replace('=</(\w+):(.+?)>=', '</removeme>', $message);
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$message = mb_convert_encoding($message, 'HTML-ENTITIES', "UTF-8");
@$doc->loadHTML($message);
XML::deleteNode($doc, 'style');
XML::deleteNode($doc, 'head');
XML::deleteNode($doc, 'title');
XML::deleteNode($doc, 'meta');
XML::deleteNode($doc, 'xml');
XML::deleteNode($doc, 'removeme');
$xpath = new DomXPath($doc);
$list = $xpath->query("//pre");
foreach ($list as $node) {
$node->nodeValue = str_replace("\n", "\r", $node->nodeValue);
}
$message = $doc->saveHTML();
$message = str_replace(["\n<", ">\n", "\r", "\n", "\xC3\x82\xC2\xA0"], ["<", ">", "<br />", " ", ""], $message);
$message = preg_replace('= [\s]*=i', " ", $message);
@$doc->loadHTML($message);
node2bbcode($doc, 'html', [], "", "");
node2bbcode($doc, 'body', [], "", "");
// Outlook-Quote - Variant 1
node2bbcode($doc, 'p', ['class'=>'MsoNormal', 'style'=>'margin-left:35.4pt'], '[quote]', '[/quote]');
// Outlook-Quote - Variant 2
node2bbcode($doc, 'div', ['style'=>'border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt'], '[quote]', '[/quote]');
// MyBB-Stuff
node2bbcode($doc, 'span', ['style'=>'text-decoration: underline;'], '[u]', '[/u]');
node2bbcode($doc, 'span', ['style'=>'font-style: italic;'], '[i]', '[/i]');
node2bbcode($doc, 'span', ['style'=>'font-weight: bold;'], '[b]', '[/b]');
/*node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/', 'size'=>'/(\d+)/', 'color'=>'/(.+)/'), '[font=$1][size=$2][color=$3]', '[/color][/size][/font]');
node2bbcode($doc, 'font', array('size'=>'/(\d+)/', 'color'=>'/(.+)/'), '[size=$1][color=$2]', '[/color][/size]');
node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/', 'size'=>'/(.+)/'), '[font=$1][size=$2]', '[/size][/font]');
node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/', 'color'=>'/(.+)/'), '[font=$1][color=$3]', '[/color][/font]');
node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/'), '[font=$1]', '[/font]');
node2bbcode($doc, 'font', array('size'=>'/(\d+)/'), '[size=$1]', '[/size]');
node2bbcode($doc, 'font', array('color'=>'/(.+)/'), '[color=$1]', '[/color]');
*/
// Untested
//node2bbcode($doc, 'span', array('style'=>'/.*font-size:\s*(.+?)[,;].*font-family:\s*(.+?)[,;].*color:\s*(.+?)[,;].*/'), '[size=$1][font=$2][color=$3]', '[/color][/font][/size]');
//node2bbcode($doc, 'span', array('style'=>'/.*font-size:\s*(\d+)[,;].*/'), '[size=$1]', '[/size]');
//node2bbcode($doc, 'span', array('style'=>'/.*font-size:\s*(.+?)[,;].*/'), '[size=$1]', '[/size]');
node2bbcode($doc, 'span', ['style'=>'/.*color:\s*(.+?)[,;].*/'], '[color="$1"]', '[/color]');
//node2bbcode($doc, 'span', array('style'=>'/.*font-family:\s*(.+?)[,;].*/'), '[font=$1]', '[/font]');
//node2bbcode($doc, 'div', array('style'=>'/.*font-family:\s*(.+?)[,;].*font-size:\s*(\d+?)pt.*/'), '[font=$1][size=$2]', '[/size][/font]');
//node2bbcode($doc, 'div', array('style'=>'/.*font-family:\s*(.+?)[,;].*font-size:\s*(\d+?)px.*/'), '[font=$1][size=$2]', '[/size][/font]');
//node2bbcode($doc, 'div', array('style'=>'/.*font-family:\s*(.+?)[,;].*/'), '[font=$1]', '[/font]');
// Importing the classes - interesting for importing of posts from third party networks that were exported from friendica
// Test
//node2bbcode($doc, 'span', array('class'=>'/([\w ]+)/'), '[class=$1]', '[/class]');
node2bbcode($doc, 'span', ['class'=>'type-link'], '[class=type-link]', '[/class]');
node2bbcode($doc, 'span', ['class'=>'type-video'], '[class=type-video]', '[/class]');
node2bbcode($doc, 'strong', [], '[b]', '[/b]');
node2bbcode($doc, 'em', [], '[i]', '[/i]');
node2bbcode($doc, 'b', [], '[b]', '[/b]');
node2bbcode($doc, 'i', [], '[i]', '[/i]');
node2bbcode($doc, 'u', [], '[u]', '[/u]');
node2bbcode($doc, 'big', [], "[size=large]", "[/size]");
node2bbcode($doc, 'small', [], "[size=small]", "[/size]");
node2bbcode($doc, 'blockquote', [], '[quote]', '[/quote]');
node2bbcode($doc, 'br', [], "\n", '');
node2bbcode($doc, 'p', ['class'=>'MsoNormal'], "\n", "");
node2bbcode($doc, 'div', ['class'=>'MsoNormal'], "\r", "");
node2bbcode($doc, 'span', [], "", "");
node2bbcode($doc, 'span', [], "", "");
node2bbcode($doc, 'pre', [], "", "");
node2bbcode($doc, 'div', [], "\r", "\r");
node2bbcode($doc, 'p', [], "\n", "\n");
node2bbcode($doc, 'ul', [], "[list]", "[/list]");
node2bbcode($doc, 'ol', [], "[list=1]", "[/list]");
node2bbcode($doc, 'li', [], "[*]", "");
node2bbcode($doc, 'hr', [], "[hr]", "");
node2bbcode($doc, 'table', [], "", "");
node2bbcode($doc, 'tr', [], "\n", "");
node2bbcode($doc, 'td', [], "\t", "");
//node2bbcode($doc, 'table', array(), "[table]", "[/table]");
//node2bbcode($doc, 'th', array(), "[th]", "[/th]");
//node2bbcode($doc, 'tr', array(), "[tr]", "[/tr]");
//node2bbcode($doc, 'td', array(), "[td]", "[/td]");
//node2bbcode($doc, 'h1', array(), "\n\n[size=xx-large][b]", "[/b][/size]\n");
//node2bbcode($doc, 'h2', array(), "\n\n[size=x-large][b]", "[/b][/size]\n");
//node2bbcode($doc, 'h3', array(), "\n\n[size=large][b]", "[/b][/size]\n");
//node2bbcode($doc, 'h4', array(), "\n\n[size=medium][b]", "[/b][/size]\n");
//node2bbcode($doc, 'h5', array(), "\n\n[size=small][b]", "[/b][/size]\n");
//node2bbcode($doc, 'h6', array(), "\n\n[size=x-small][b]", "[/b][/size]\n");
node2bbcode($doc, 'h1', [], "\n\n[h1]", "[/h1]\n");
node2bbcode($doc, 'h2', [], "\n\n[h2]", "[/h2]\n");
node2bbcode($doc, 'h3', [], "\n\n[h3]", "[/h3]\n");
node2bbcode($doc, 'h4', [], "\n\n[h4]", "[/h4]\n");
node2bbcode($doc, 'h5', [], "\n\n[h5]", "[/h5]\n");
node2bbcode($doc, 'h6', [], "\n\n[h6]", "[/h6]\n");
node2bbcode($doc, 'a', ['href'=>'/mailto:(.+)/'], '[mail=$1]', '[/mail]');
node2bbcode($doc, 'a', ['href'=>'/(.+)/'], '[url=$1]', '[/url]');
node2bbcode($doc, 'img', ['src'=>'/(.+)/', 'width'=>'/(\d+)/', 'height'=>'/(\d+)/'], '[img=$2x$3]$1', '[/img]');
node2bbcode($doc, 'img', ['src'=>'/(.+)/'], '[img]$1', '[/img]');
node2bbcode($doc, 'video', ['src'=>'/(.+)/'], '[video]$1', '[/video]');
node2bbcode($doc, 'audio', ['src'=>'/(.+)/'], '[audio]$1', '[/audio]');
node2bbcode($doc, 'iframe', ['src'=>'/(.+)/'], '[iframe]$1', '[/iframe]');
node2bbcode($doc, 'key', [], '[code]', '[/code]');
node2bbcode($doc, 'code', [], '[code]', '[/code]');
$message = $doc->saveHTML();
// I'm removing something really disturbing
// Don't know exactly what it is
$message = str_replace(chr(194).chr(160), ' ', $message);
$message = str_replace("&nbsp;", " ", $message);
// removing multiple DIVs
$message = preg_replace('=\r *\r=i', "\n", $message);
$message = str_replace("\r", "\n", $message);
Addon::callHooks('html2bbcode', $message);
$message = strip_tags($message);
$message = html_entity_decode($message, ENT_QUOTES, 'UTF-8');
$message = str_replace(["<"], ["&lt;"], $message);
// remove quotes if they don't make sense
$message = preg_replace('=\[/quote\][\s]*\[quote\]=i', "\n", $message);
$message = preg_replace('=\[quote\]\s*=i', "[quote]", $message);
$message = preg_replace('=\s*\[/quote\]=i', "[/quote]", $message);
do {
$oldmessage = $message;
$message = str_replace("\n \n", "\n\n", $message);
} while ($oldmessage != $message);
do {
$oldmessage = $message;
$message = str_replace("\n\n\n", "\n\n", $message);
} while ($oldmessage != $message);
do {
$oldmessage = $message;
$message = str_replace(
[
"[/size]\n\n",
"\n[hr]",
"[hr]\n",
"\n[list",
"[/list]\n",
"\n[/",
"[list]\n",
"[list=1]\n",
"\n[*]"],
[
"[/size]\n",
"[hr]",
"[hr]",
"[list",
"[/list]",
"[/",
"[list]",
"[list=1]",
"[*]"],
$message
);
} while ($message != $oldmessage);
$message = str_replace(
['[b][b]', '[/b][/b]', '[i][i]', '[/i][/i]'],
['[b]', '[/b]', '[i]', '[/i]'],
$message
);
// Handling Yahoo style of mails
$message = str_replace('[hr][b]From:[/b]', '[quote][b]From:[/b]', $message);
// Restore code blocks
$message = preg_replace_callback(
'#\[codeblock-([0-9]+)\]#iU',
function ($matches) use ($codeblocks) {
$return = '';
if (isset($codeblocks[intval($matches[1])])) {
$return = $codeblocks[$matches[1]];
}
return $return;
},
$message
);
$message = trim($message);
if ($basepath != '') {
$message = addHostname($message, $basepath);
}
return $message;
}
/**
* @brief Sub function to complete incomplete URL
*
* @param array $matches Result of preg_replace_callback
* @param string $basepath Basepath that is used to complete the URL
*
* @return string The expanded URL
*/
function addHostnameSub($matches, $basepath)
{
$base = parse_url($basepath);
unset($base['query']);
unset($base['fragment']);
$link = $matches[0];
$url = $matches[1];
$parts = array_merge($base, parse_url($url));
$url2 = Network::unparseURL($parts);
return str_replace($url, $url2, $link);
}
/**
* @brief Complete incomplete URLs in BBCode
*
* @param string $body Body with URLs
* @param string $basepath Basepath that is used to complete the URL
*
* @return string Body with expanded URLs
*/
function addHostname($body, $basepath)
{
$URLSearchString = "^\[\]";
$matches = ["/\[url\=([$URLSearchString]*)\].*?\[\/url\]/ism",
"/\[url\]([$URLSearchString]*)\[\/url\]/ism",
"/\[img\=[0-9]*x[0-9]*\](.*?)\[\/img\]/ism",
"/\[img\](.*?)\[\/img\]/ism",
"/\[zmg\=[0-9]*x[0-9]*\](.*?)\[\/img\]/ism",
"/\[zmg\](.*?)\[\/zmg\]/ism",
"/\[video\](.*?)\[\/video\]/ism",
"/\[audio\](.*?)\[\/audio\]/ism",
];
foreach ($matches as $match) {
$body = preg_replace_callback(
$match,
function ($match) use ($basepath) {
return addHostnameSub($match, $basepath);
},
$body
);
}
return $body;
}

View file

@ -1,246 +0,0 @@
<?php
require_once 'include/html2bbcode.php';
function breaklines($line, $level, $wraplength = 75)
{
if ($wraplength == 0) {
$wraplength = 2000000;
}
$wraplen = $wraplength - $level;
$newlines = [];
do {
$oldline = $line;
$subline = substr($line, 0, $wraplen);
$pos = strrpos($subline, ' ');
if ($pos == 0) {
$pos = strpos($line, ' ');
}
if (($pos > 0) && strlen($line) > $wraplen) {
$newline = trim(substr($line, 0, $pos));
if ($level > 0) {
$newline = str_repeat(">", $level) . ' ' . $newline;
}
$newlines[] = $newline . " ";
$line = substr($line, $pos + 1);
}
} while ((strlen($line) > $wraplen) && !($oldline == $line));
if ($level > 0) {
$line = str_repeat(">", $level) . ' ' . $line;
}
$newlines[] = $line;
return implode($newlines, "\n");
}
function quotelevel($message, $wraplength = 75)
{
$lines = explode("\n", $message);
$newlines = [];
$level = 0;
foreach ($lines as $line) {
$line = trim($line);
$startquote = false;
while (strpos("*" . $line, '[quote]') > 0) {
$level++;
$pos = strpos($line, '[quote]');
$line = substr($line, 0, $pos) . substr($line, $pos + 7);
$startquote = true;
}
$currlevel = $level;
while (strpos("*" . $line, '[/quote]') > 0) {
$level--;
if ($level < 0) {
$level = 0;
}
$pos = strpos($line, '[/quote]');
$line = substr($line, 0, $pos) . substr($line, $pos + 8);
}
if (!$startquote || ($line != '')) {
$newlines[] = breaklines($line, $currlevel, $wraplength);
}
}
return implode($newlines, "\n");
}
function collecturls($message)
{
$pattern = '/<a.*?href="(.*?)".*?>(.*?)<\/a>/is';
preg_match_all($pattern, $message, $result, PREG_SET_ORDER);
$urls = [];
foreach ($result as $treffer) {
$ignore = false;
// A list of some links that should be ignored
$list = ["/user/", "/tag/", "/group/", "/profile/", "/search?search=", "/search?tag=", "mailto:", "/u/", "/node/",
"//facebook.com/profile.php?id=", "//plus.google.com/", "//twitter.com/"];
foreach ($list as $listitem) {
if (strpos($treffer[1], $listitem) !== false) {
$ignore = true;
}
}
if ((strpos($treffer[1], "//twitter.com/") !== false) && (strpos($treffer[1], "/status/") !== false)) {
$ignore = false;
}
if ((strpos($treffer[1], "//plus.google.com/") !== false) && (strpos($treffer[1], "/posts") !== false)) {
$ignore = false;
}
if ((strpos($treffer[1], "//plus.google.com/") !== false) && (strpos($treffer[1], "/photos") !== false)) {
$ignore = false;
}
if (!$ignore) {
$urls[$treffer[1]] = $treffer[1];
}
}
return $urls;
}
function html2plain($html, $wraplength = 75, $compact = false)
{
global $lang;
$message = str_replace("\r", "", $html);
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$message = mb_convert_encoding($message, 'HTML-ENTITIES', "UTF-8");
@$doc->loadHTML($message);
$xpath = new DomXPath($doc);
$list = $xpath->query("//pre");
foreach ($list as $node) {
$node->nodeValue = str_replace("\n", "\r", $node->nodeValue);
}
$message = $doc->saveHTML();
$message = str_replace(["\n<", ">\n", "\r", "\n", "\xC3\x82\xC2\xA0"], ["<", ">", "<br>", " ", ""], $message);
$message = preg_replace('= [\s]*=i', " ", $message);
// Collecting all links
$urls = collecturls($message);
@$doc->loadHTML($message);
node2bbcode($doc, 'html', [], '', '');
node2bbcode($doc, 'body', [], '', '');
// MyBB-Auszeichnungen
/*
node2bbcode($doc, 'span', array('style'=>'text-decoration: underline;'), '_', '_');
node2bbcode($doc, 'span', array('style'=>'font-style: italic;'), '/', '/');
node2bbcode($doc, 'span', array('style'=>'font-weight: bold;'), '*', '*');
node2bbcode($doc, 'strong', array(), '*', '*');
node2bbcode($doc, 'b', array(), '*', '*');
node2bbcode($doc, 'i', array(), '/', '/');
node2bbcode($doc, 'u', array(), '_', '_');
*/
if ($compact) {
node2bbcode($doc, 'blockquote', [], "»", "«");
} else {
node2bbcode($doc, 'blockquote', [], '[quote]', "[/quote]\n");
}
node2bbcode($doc, 'br', [], "\n", '');
node2bbcode($doc, 'span', [], "", "");
node2bbcode($doc, 'pre', [], "", "");
node2bbcode($doc, 'div', [], "\r", "\r");
node2bbcode($doc, 'p', [], "\n", "\n");
//node2bbcode($doc, 'ul', array(), "\n[list]", "[/list]\n");
//node2bbcode($doc, 'ol', array(), "\n[list=1]", "[/list]\n");
node2bbcode($doc, 'li', [], "\n* ", "\n");
node2bbcode($doc, 'hr', [], "\n" . str_repeat("-", 70) . "\n", "");
node2bbcode($doc, 'tr', [], "\n", "");
node2bbcode($doc, 'td', [], "\t", "");
node2bbcode($doc, 'h1', [], "\n\n*", "*\n");
node2bbcode($doc, 'h2', [], "\n\n*", "*\n");
node2bbcode($doc, 'h3', [], "\n\n*", "*\n");
node2bbcode($doc, 'h4', [], "\n\n*", "*\n");
node2bbcode($doc, 'h5', [], "\n\n*", "*\n");
node2bbcode($doc, 'h6', [], "\n\n*", "*\n");
// Problem: there is no reliable way to detect if it is a link to a tag or profile
//node2bbcode($doc, 'a', array('href'=>'/(.+)/'), ' $1 ', ' ', true);
//node2bbcode($doc, 'a', array('href'=>'/(.+)/', 'rel'=>'oembed'), ' $1 ', '', true);
//node2bbcode($doc, 'img', array('alt'=>'/(.+)/'), '$1', '');
//node2bbcode($doc, 'img', array('title'=>'/(.+)/'), '$1', '');
//node2bbcode($doc, 'img', array(), '', '');
if (!$compact) {
node2bbcode($doc, 'img', ['src' => '/(.+)/'], ' [img]$1', '[/img] ');
} else {
node2bbcode($doc, 'img', ['src' => '/(.+)/'], ' ', ' ');
}
node2bbcode($doc, 'iframe', ['src' => '/(.+)/'], ' $1 ', '');
$message = $doc->saveHTML();
if (!$compact) {
$message = str_replace("[img]", "", $message);
$message = str_replace("[/img]", "", $message);
}
// was ersetze ich da?
// Irgendein stoerrisches UTF-Zeug
$message = str_replace(chr(194) . chr(160), ' ', $message);
$message = str_replace("&nbsp;", " ", $message);
// Aufeinanderfolgende DIVs
$message = preg_replace('=\r *\r=i', "\n", $message);
$message = str_replace("\r", "\n", $message);
$message = strip_tags($message);
$message = html_entity_decode($message, ENT_QUOTES, 'UTF-8');
if (!$compact && ($message != '')) {
foreach ($urls as $id => $url) {
if ($url != '' && strpos($message, $url) === false) {
$message .= "\n" . $url . ' ';
}
}
}
$message = str_replace("\n«", "«\n", $message);
$message = str_replace("»\n", "\n»", $message);
do {
$oldmessage = $message;
$message = str_replace("\n\n\n", "\n\n", $message);
} while ($oldmessage != $message);
$message = quotelevel(trim($message), $wraplength);
return trim($message);
}

View file

@ -228,7 +228,7 @@ function add_page_info_to_body($body, $texturl = false, $no_photos = false) {
*
* @TODO find proper type-hints
*/
function consume_feed($xml, $importer, &$contact, &$hub, $datedir = 0, $pass = 0) {
function consume_feed($xml, $importer, $contact, &$hub, $datedir = 0, $pass = 0) {
if ($contact['network'] === NETWORK_OSTATUS) {
if ($pass < 2) {
// Test - remove before flight
@ -290,7 +290,7 @@ function subscribe_to_hub($url, $importer, $contact, $hubmode = 'subscribe') {
return;
}
$push_url = Config::get('system','url') . '/pubsub/' . $r[0]['nickname'] . '/' . $contact['id'];
$push_url = System::baseUrl() . '/pubsub/' . $r[0]['nickname'] . '/' . $contact['id'];
// Use a single verify token, even if multiple hubs
$verify_token = ((strlen($contact['hub-verify'])) ? $contact['hub-verify'] : random_string());

View file

@ -14,6 +14,7 @@ use Friendica\Core\L10n;
use Friendica\Core\PConfig;
use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Model\Event;
use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Render\FriendicaSmarty;
@ -21,7 +22,6 @@ use Friendica\Util\DateTimeFormat;
use Friendica\Util\Map;
require_once "mod/proxy.php";
require_once "include/event.php";
require_once "include/conversation.php";
/**
@ -1062,7 +1062,7 @@ function linkify($s) {
* Load poke verbs
*
* @return array index is present tense verb
value is array containing past tense verb, translation of present, translation of past
* value is array containing past tense verb, translation of present, translation of past
* @hook poke_verbs pokes array
*/
function get_poke_verbs() {
@ -1169,46 +1169,68 @@ function redir_private_images($a, &$item)
}
}
/**
* Sets the "rendered-html" field of the provided item
*
* Body is preserved to avoid side-effects as we modify it just-in-time for spoilers and private image links
*
* @param array $item
* @param bool $update
*
* @todo Remove reference, simply return "rendered-html" and "rendered-hash"
*/
function put_item_in_cache(&$item, $update = false)
{
$body = $item["body"];
$rendered_hash = defaults($item, 'rendered-hash', '');
$rendered_html = defaults($item, 'rendered-html', '');
if ($rendered_hash == ''
|| $item["rendered-html"] == ""
|| $rendered_hash != hash("md5", $item["body"])
|| Config::get("system", "ignore_cache")
) {
// The function "redir_private_images" changes the body.
// I'm not sure if we should store it permanently, so we save the old value.
$body = $item["body"];
$a = get_app();
redir_private_images($a, $item);
$item["rendered-html"] = prepare_text($item["body"]);
$item["rendered-hash"] = hash("md5", $item["body"]);
$item["body"] = $body;
// Force an update if the generated values differ from the existing ones
if ($rendered_hash != $item["rendered-hash"]) {
$update = true;
}
// Only compare the HTML when we forcefully ignore the cache
if (Config::get("system", "ignore_cache") && ($rendered_html != $item["rendered-html"])) {
$update = true;
}
if ($update && ($item["id"] > 0)) {
dba::update('item', ['rendered-html' => $item["rendered-html"], 'rendered-hash' => $item["rendered-hash"]],
['id' => $item["id"]], false);
}
}
$item["body"] = $body;
}
/**
* @brief Given an item array, convert the body element from bbcode to html and add smilie icons.
* If attach is true, also add icons for item attachments.
*
* @param array $item
* @param array $item
* @param boolean $attach
* @param boolean $is_preview
* @return string item body html
* @hook prepare_body_init item array before any work
* @hook prepare_body ('item'=>item array, 'html'=>body string) after first bbcode to html
* @hook prepare_body_content_filter ('item'=>item array, 'filter_reasons'=>string array) before first bbcode to html
* @hook prepare_body ('item'=>item array, 'html'=>body string, 'is_preview'=>boolean, 'filter_reasons'=>string array) after first bbcode to html
* @hook prepare_body_final ('item'=>item array, 'html'=>body string) after attach icons and blockquote special case handling (spoiler, author)
*/
function prepare_body(&$item, $attach = false, $preview = false) {
function prepare_body(array &$item, $attach = false, $is_preview = false)
{
$a = get_app();
Addon::callHooks('prepare_body_init', $item);
@ -1221,42 +1243,58 @@ function prepare_body(&$item, $attach = false, $preview = false) {
// In order to provide theme developers more possibilities, event items
// are treated differently.
if ($item['object-type'] === ACTIVITY_OBJ_EVENT && isset($item['event-id'])) {
$ev = format_event_item($item);
$ev = Event::getItemHTML($item);
return $ev;
}
if (!Config::get('system','suppress_tags')) {
$taglist = dba::p("SELECT `type`, `term`, `url` FROM `term` WHERE `otype` = ? AND `oid` = ? AND `type` IN (?, ?) ORDER BY `tid`",
intval(TERM_OBJ_POST), intval($item['id']), intval(TERM_HASHTAG), intval(TERM_MENTION));
$taglist = dba::p("SELECT `type`, `term`, `url` FROM `term` WHERE `otype` = ? AND `oid` = ? AND `type` IN (?, ?) ORDER BY `tid`",
intval(TERM_OBJ_POST), intval($item['id']), intval(TERM_HASHTAG), intval(TERM_MENTION));
while ($tag = dba::fetch($taglist)) {
if ($tag["url"] == "") {
$tag["url"] = $searchpath.strtolower($tag["term"]);
}
$orig_tag = $tag["url"];
$tag["url"] = best_link_url($item, $sp, $tag["url"]);
if ($tag["type"] == TERM_HASHTAG) {
if ($orig_tag != $tag["url"]) {
$item['body'] = str_replace($orig_tag, $tag["url"], $item['body']);
}
$hashtags[] = "#<a href=\"".$tag["url"]."\" target=\"_blank\">".$tag["term"]."</a>";
$prefix = "#";
} elseif ($tag["type"] == TERM_MENTION) {
$mentions[] = "@<a href=\"".$tag["url"]."\" target=\"_blank\">".$tag["term"]."</a>";
$prefix = "@";
}
$tags[] = $prefix."<a href=\"".$tag["url"]."\" target=\"_blank\">".$tag["term"]."</a>";
while ($tag = dba::fetch($taglist)) {
if ($tag["url"] == "") {
$tag["url"] = $searchpath . strtolower($tag["term"]);
}
dba::close($taglist);
$orig_tag = $tag["url"];
$tag["url"] = best_link_url($item, $sp, $tag["url"]);
if ($tag["type"] == TERM_HASHTAG) {
if ($orig_tag != $tag["url"]) {
$item['body'] = str_replace($orig_tag, $tag["url"], $item['body']);
}
$hashtags[] = "#<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
$prefix = "#";
} elseif ($tag["type"] == TERM_MENTION) {
$mentions[] = "@<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
$prefix = "@";
}
$tags[] = $prefix . "<a href=\"" . $tag["url"] . "\" target=\"_blank\">" . $tag["term"] . "</a>";
}
dba::close($taglist);
$item['tags'] = $tags;
$item['hashtags'] = $hashtags;
$item['mentions'] = $mentions;
// Compile eventual content filter reasons
$filter_reasons = [];
if (!$is_preview && !($item['self'] && local_user() == $item['uid'])) {
if (!empty($item['content-warning']) && (!local_user() || !PConfig::get(local_user(), 'system', 'disable_cw', false))) {
$filter_reasons[] = L10n::t('Content warning: %s', $item['content-warning']);
}
$hook_data = [
'item' => $item,
'filter_reasons' => $filter_reasons
];
Addon::callHooks('prepare_body_content_filter', $hook_data);
$filter_reasons = $hook_data['filter_reasons'];
unset($hook_data);
}
// Update the cached values if there is no "zrl=..." on the links.
$update = (!local_user() && !remote_user() && ($item["uid"] == 0));
@ -1268,9 +1306,17 @@ function prepare_body(&$item, $attach = false, $preview = false) {
put_item_in_cache($item, $update);
$s = $item["rendered-html"];
$prep_arr = ['item' => $item, 'html' => $s, 'preview' => $preview];
Addon::callHooks('prepare_body', $prep_arr);
$s = $prep_arr['html'];
$hook_data = [
'item' => $item,
'html' => $s,
'preview' => $is_preview,
'filter_reasons' => $filter_reasons
];
Addon::callHooks('prepare_body', $hook_data);
$s = $hook_data['html'];
unset($hook_data);
$s = apply_content_filter($s, $filter_reasons);
if (! $attach) {
// Replace the blockquotes with quotes that are used in mails.
@ -1281,62 +1327,55 @@ function prepare_body(&$item, $attach = false, $preview = false) {
$as = '';
$vhead = false;
$arr = explode('[/attach],', $item['attach']);
if (count($arr)) {
foreach ($arr as $r) {
$matches = false;
$icon = '';
$cnt = preg_match_all('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\" title=\"(.*?)\"|',$r ,$matches, PREG_SET_ORDER);
if ($cnt) {
foreach ($matches as $mtch) {
$mime = $mtch[3];
$matches = [];
preg_match_all('|\[attach\]href=\"(.*?)\" length=\"(.*?)\" type=\"(.*?)\"(?: title=\"(.*?)\")?|', $item['attach'], $matches, PREG_SET_ORDER);
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];
}
if (strpos($mime, 'video') !== false) {
if (!$vhead) {
$vhead = true;
$a->page['htmlhead'] .= replace_macros(get_markup_template('videos_head.tpl'), [
'$baseurl' => System::baseUrl(),
]);
$a->page['end'] .= replace_macros(get_markup_template('videos_end.tpl'), [
'$baseurl' => System::baseUrl(),
]);
}
$id = end(explode('/', $the_url));
$as .= replace_macros(get_markup_template('video_top.tpl'), [
'$video' => [
'id' => $id,
'title' => L10n::t('View Video'),
'src' => $the_url,
'mime' => $mime,
],
]);
}
$filetype = strtolower(substr($mime, 0, strpos($mime, '/')));
if ($filetype) {
$filesubtype = strtolower(substr($mime, strpos($mime, '/') + 1));
$filesubtype = str_replace('.', '-', $filesubtype);
} else {
$filetype = 'unkn';
$filesubtype = 'unkn';
}
$title = ((strlen(trim($mtch[4]))) ? escape_tags(trim($mtch[4])) : escape_tags($mtch[1]));
$title .= ' ' . $mtch[2] . ' ' . L10n::t('bytes');
$icon = '<div class="attachtype icon s22 type-' . $filetype . ' subtype-' . $filesubtype . '"></div>';
$as .= '<a href="' . strip_tags($the_url) . '" title="' . $title . '" class="attachlink" target="_blank" >' . $icon . '</a>';
}
}
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];
}
if (strpos($mime, 'video') !== false) {
if (!$vhead) {
$vhead = true;
$a->page['htmlhead'] .= replace_macros(get_markup_template('videos_head.tpl'), [
'$baseurl' => System::baseUrl(),
]);
$a->page['end'] .= replace_macros(get_markup_template('videos_end.tpl'), [
'$baseurl' => System::baseUrl(),
]);
}
$id = end(explode('/', $the_url));
$as .= replace_macros(get_markup_template('video_top.tpl'), [
'$video' => [
'id' => $id,
'title' => L10n::t('View Video'),
'src' => $the_url,
'mime' => $mime,
],
]);
}
$filetype = strtolower(substr($mime, 0, strpos($mime, '/')));
if ($filetype) {
$filesubtype = strtolower(substr($mime, strpos($mime, '/') + 1));
$filesubtype = str_replace('.', '-', $filesubtype);
} else {
$filetype = 'unkn';
$filesubtype = 'unkn';
}
$title = escape_tags(trim(!empty($mtch[4]) ? $mtch[4] : $mtch[1]));
$title .= ' ' . $mtch[2] . ' ' . L10n::t('bytes');
$icon = '<div class="attachtype icon s22 type-' . $filetype . ' subtype-' . $filesubtype . '"></div>';
$as .= '<a href="' . strip_tags($the_url) . '" title="' . $title . '" class="attachlink" target="_blank" >' . $icon . '</a>';
}
if ($as != '') {
$s .= '<div class="body-attach">'.$as.'<div class="clear"></div></div>';
}
@ -1386,10 +1425,39 @@ function prepare_body(&$item, $attach = false, $preview = false) {
$s = preg_replace('|(<img[^>]+src="[^"]+/photo/[0-9a-f]+)-[0-9]|', "$1-" . $ps, $s);
}
$prep_arr = ['item' => $item, 'html' => $s];
Addon::callHooks('prepare_body_final', $prep_arr);
$hook_data = ['item' => $item, 'html' => $s];
Addon::callHooks('prepare_body_final', $hook_data);
return $prep_arr['html'];
return $hook_data['html'];
}
/**
* Given a HTML text and a set of filtering reasons, adds a content hiding header with the provided reasons
*
* Reasons are expected to have been translated already.
*
* @param string $html
* @param array $reasons
* @return string
*/
function apply_content_filter($html, array $reasons)
{
if (count($reasons)) {
$rnd = random_string(8);
$content_filter_html = '<ul class="content-filter-reasons">';
foreach ($reasons as $reason) {
$content_filter_html .= '<li>' . htmlspecialchars($reason) . '</li>' . PHP_EOL;
}
$content_filter_html .= '</ul>
<p><span id="content-filter-wrap-' . $rnd . '" class="fakelink content-filter-button" onclick=openClose(\'content-filter-' . $rnd . '\'); >' .
L10n::t('Click to open/close') .
'</span></p>
<div id="content-filter-' . $rnd . '" class="content-filter-content" style="display: none;">';
$html = $content_filter_html . $html . '</div>';
}
return $html;
}
/**
@ -2023,6 +2091,10 @@ function text_highlight($s, $lang) {
$lang = 'javascript';
}
if ($lang === 'bash') {
$lang = 'sh';
}
// @TODO: Replace Text_Highlighter_Renderer_Html by scrivo/highlight.php
// Autoload the library to make constants available

View file

@ -24,9 +24,7 @@ use Friendica\Module\Login;
require_once 'boot.php';
if (empty($a)) {
$a = new App(__DIR__);
}
$a = new App(__DIR__);
BaseObject::setApp($a);
// We assume that the index.php is called by a frontend process
@ -53,9 +51,13 @@ if (!$install) {
require_once "include/dba.php";
if (!$install) {
dba::connect($db_host, $db_user, $db_pass, $db_data, $install);
$result = dba::connect($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
if (!$result) {
System::unavailable();
}
/**
* Load configs from db. Overwrite configs from .htconfig.php
*/
@ -72,12 +74,13 @@ if (!$install) {
if (Config::get('system', 'force_ssl') && ($a->get_scheme() == "http")
&& (intval(Config::get('system', 'ssl_policy')) == SSL_POLICY_FULL)
&& (substr(System::baseUrl(), 0, 8) == "https://")
) {
&& ($_SERVER['REQUEST_METHOD'] == 'GET')) {
header("HTTP/1.1 302 Moved Temporarily");
header("Location: " . System::baseUrl() . "/" . $a->query_string);
exit();
}
Config::init();
Session::init();
Addon::loadHooks();
Addon::callHooks('init_1');
@ -225,8 +228,36 @@ if (strlen($a->module)) {
*/
// Compatibility with the Android Diaspora client
if ($a->module == "stream") {
$a->module = "network";
if ($a->module == 'stream') {
goaway('network?f=&order=post');
}
if ($a->module == 'conversations') {
goaway('message');
}
if ($a->module == 'commented') {
goaway('network?f=&order=comment');
}
if ($a->module == 'liked') {
goaway('network?f=&order=comment');
}
if ($a->module == 'activity') {
goaway('network/?f=&conv=1');
}
if (($a->module == 'status_messages') && ($a->cmd == 'status_messages/new')) {
goaway('bookmarklet');
}
if (($a->module == 'user') && ($a->cmd == 'user/edit')) {
goaway('settings');
}
if (($a->module == 'tag_followings') && ($a->cmd == 'tag_followings/manage')) {
goaway('search');
}
// Compatibility with the Firefox App

View file

@ -46,8 +46,10 @@ function wk_social_relay()
$server_tags = Config::get('system', 'relay_server_tags');
$tagitems = explode(",", $server_tags);
/// @todo Check if it was better to use "strtolower" on the tags
foreach ($tagitems AS $tag) {
$tags[trim($tag, "# ")] = trim($tag, "# ");
$tag = trim($tag, "# ");
$tags[$tag] = $tag;
}
if (Config::get('system', 'relay_user_tags')) {
@ -62,7 +64,9 @@ function wk_social_relay()
$taglist = [];
foreach ($tags AS $tag) {
$taglist[] = $tag;
if (!empty($tag)) {
$taglist[] = $tag;
}
}
$relay = [

View file

@ -32,7 +32,7 @@ function acl_content(App $a)
$search = $_REQUEST['query'];
}
logger('Searching for ' . $search . ' - type ' . $type, LOGGER_DEBUG);
logger("Searching for ".$search." - type ".$type." conversation ".$conv_id, LOGGER_DEBUG);
if ($search != '') {
$sql_extra = "AND `name` LIKE '%%" . dbesc($search) . "%%'";
@ -239,6 +239,12 @@ function acl_content(App $a)
$items = array_merge($groups, $contacts);
if ($conv_id) {
// In multi threaded posts the conv_id is not the parent of the whole thread
$parent_item = dba::selectFirst('item', ['parent'], ['id' => $conv_id]);
if (DBM::is_result($parent_item)) {
$conv_id = $parent_item['parent'];
}
/*
* if $conv_id is set, get unknown contacts in thread
* but first get known contacts url to filter them out

View file

@ -109,6 +109,9 @@ function admin_post(App $a)
}
$return_path = 'admin/themes/' . $theme;
break;
case 'tos':
admin_page_tos_post($a);
break;
case 'features':
admin_page_features_post($a);
break;
@ -181,7 +184,8 @@ function admin_content(App $a)
'users' => ["admin/users/" , L10n::t("Users") , "users"],
'addons' => ["admin/addons/" , L10n::t("Addons") , "addons"],
'themes' => ["admin/themes/" , L10n::t("Themes") , "themes"],
'features' => ["admin/features/" , L10n::t("Additional features") , "features"] ]],
'features' => ["admin/features/" , L10n::t("Additional features") , "features"],
'tos' => ["admin/tos/" , L10n::t("Terms of Service") , "tos"] ]],
'database' => [ L10n::t('Database'), [
'dbsync' => ["admin/dbsync/" , L10n::t('DB updates') , "dbsync"],
'queue' => ["admin/queue/" , L10n::t('Inspect Queue') , "queue"], ]],
@ -265,6 +269,9 @@ function admin_content(App $a)
case 'deleteitem':
$o = admin_page_deleteitem($a);
break;
case 'tos':
$o = admin_page_tos($a);
break;
default:
notice(L10n::t("Item not found."));
}
@ -281,6 +288,50 @@ function admin_content(App $a)
}
}
/**
* @brief Subpage to define the display of a Terms of Usage page.
*
* @param App $a
* @return string
*/
function admin_page_tos(App $a)
{
$t = get_markup_template('admin/tos.tpl');
return replace_macros($t, [
'$title' => L10n::t('Administration'),
'$page' => L10n::t('Terms of Service'),
'$displaytos' => ['displaytos', L10n::t('Display Terms of Service'), Config::get('system', 'tosdisplay'), L10n::t('Enable the Terms of Service page. If this is enabled a link to the terms will be added to the registration form and the general information page.')],
'$displayprivstatement' => ['displayprivstatement', L10n::t('Display Privacy Statement'), Config::get('system','tosprivstatement'), L10n::t('Show some informations regarding the needed information to operate the node according e.g. to <a href="%s" target="_blank">EU-GDPR</a>.','https://en.wikipedia.org/wiki/General_Data_Protection_Regulation')],
'$tostext' => ['tostext', L10n::t('The Terms of Service'), Config::get('system', 'tostext'), L10n::t('Enter the Terms of Service for your node here. You can use BBCode. Headers of sections should be [h2] and below.')],
'$form_security_token' => get_form_security_token("admin_tos"),
'$submit' => L10n::t('Save Settings'),
]);
}
/**
* @brief Process send data from Admin TOS Page
*
* @param App $a
*/
function admin_page_tos_post(App $a)
{
check_form_security_token_redirectOnErr('/admin/tos', 'admin_tos');
if (!x($_POST, "page_tos")) {
return;
}
$displaytos = ((x($_POST, 'displaytos')) ? True : False);
$displayprivstatement = ((x($_POST, 'displayprivstatement')) ? True : False);
$tostext = ((x($_POST, 'tostext')) ? strip_tags(trim($_POST['tostext'])) : '');
Config::set('system', 'tosdisplay', $displaytos);
Config::set('system', 'tosprivstatement', $displayprivstatement);
Config::set('system', 'tostext', $tostext);
goaway('admin/tos');
return; // NOTREACHED
}
/**
* @brief Subpage to modify the server wide block list via the admin panel.
*
@ -635,8 +686,21 @@ function admin_page_federation(App $a)
$v = $newVv;
}
foreach ($v as $key => $vv)
$v[$key]["version"] = trim(strip_tags($vv["version"]));
// Assure that the versions are sorted correctly
$v2 = [];
$versions = [];
foreach ($v as $vv) {
$version = trim(strip_tags($vv["version"]));
$v2[$version] = $vv;
$versions[] = $version;
}
usort($versions, 'version_compare');
$v = [];
foreach ($versions as $version) {
$v[] = $v2[$version];
}
// the 3rd array item is needed for the JavaScript graphs as JS does
// not like some characters in the names of variables...
@ -718,7 +782,7 @@ function admin_page_summary(App $a)
$warningtext = [];
if (DBM::is_result($r)) {
$showwarning = true;
$warningtext[] = L10n::t('Your DB still runs with MyISAM tables. You should change the engine type to InnoDB. As Friendica will use InnoDB only features in the future, you should change this! See <a href="%s">here</a> for a guide that may be helpful converting the table engines. You may also use the command <tt>php scripts/dbstructure.php toinnodb</tt> of your Friendica installation for an automatic conversion.<br />', 'https://dev.mysql.com/doc/refman/5.7/en/converting-tables-to-innodb.html');
$warningtext[] = L10n::t('Your DB still runs with MyISAM tables. You should change the engine type to InnoDB. As Friendica will use InnoDB only features in the future, you should change this! See <a href="%s">here</a> for a guide that may be helpful converting the table engines. You may also use the command <tt>php bin/console.php dbstructure toinnodb</tt> of your Friendica installation for an automatic conversion.<br />', 'https://dev.mysql.com/doc/refman/5.7/en/converting-tables-to-innodb.html');
}
// Check if github.com/friendica/master/VERSION is higher then
// the local version of Friendica. Check is opt-in, source may be master or devel branch
@ -735,7 +799,7 @@ function admin_page_summary(App $a)
}
if (Config::get('system', 'dbupdate') == DB_UPDATE_FAILED) {
$showwarning = true;
$warningtext[] = L10n::t('The database update failed. Please run "php scripts/dbstructure.php update" from the command line and have a look at the errors that might appear.');
$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);
@ -871,8 +935,9 @@ function admin_page_site_post(App $a)
update_table("gcontact", ['connect', 'addr'], $old_host, $new_host);
// update config
$a->set_baseurl($new_url);
Config::set('system', 'hostname', parse_url($new_url, PHP_URL_HOST));
Config::set('system', 'url', $new_url);
$a->set_baseurl($new_url);
// send relocate
$users = q("SELECT `uid` FROM `user` WHERE `account_removed` = 0 AND `account_expired` = 0");
@ -906,7 +971,7 @@ function admin_page_site_post(App $a)
$daily_registrations = ((x($_POST,'max_daily_registrations')) ? intval(trim($_POST['max_daily_registrations'])) :0);
$abandon_days = ((x($_POST,'abandon_days')) ? intval(trim($_POST['abandon_days'])) : 0);
$register_text = ((x($_POST,'register_text')) ? notags(trim($_POST['register_text'])) : '');
$register_text = ((x($_POST,'register_text')) ? strip_tags(trim($_POST['register_text'])) : '');
$allowed_sites = ((x($_POST,'allowed_sites')) ? notags(trim($_POST['allowed_sites'])) : '');
$allowed_email = ((x($_POST,'allowed_email')) ? notags(trim($_POST['allowed_email'])) : '');
@ -960,11 +1025,19 @@ function admin_page_site_post(App $a)
$only_tag_search = ((x($_POST,'only_tag_search')) ? True : False);
$rino = ((x($_POST,'rino')) ? intval($_POST['rino']) : 0);
$check_new_version_url = ((x($_POST, 'check_new_version_url')) ? notags(trim($_POST['check_new_version_url'])) : 'none');
$worker_queues = ((x($_POST,'worker_queues')) ? intval($_POST['worker_queues']) : 4);
$worker_dont_fork = ((x($_POST,'worker_dont_fork')) ? True : False);
$worker_fastlane = ((x($_POST,'worker_fastlane')) ? True : False);
$worker_frontend = ((x($_POST,'worker_frontend')) ? True : False);
$relay_directly = ((x($_POST,'relay_directly')) ? True : False);
$relay_server = ((x($_POST,'relay_server')) ? notags(trim($_POST['relay_server'])) : '');
$relay_subscribe = ((x($_POST,'relay_subscribe')) ? True : False);
$relay_scope = ((x($_POST,'relay_scope')) ? notags(trim($_POST['relay_scope'])) : '');
$relay_server_tags = ((x($_POST,'relay_server_tags')) ? notags(trim($_POST['relay_server_tags'])) : '');
$relay_user_tags = ((x($_POST,'relay_user_tags')) ? True : False);
// Has the directory url changed? If yes, then resubmit the existing profiles there
if ($global_directory != Config::get('system', 'directory') && ($global_directory != '')) {
Config::set('system', 'directory', $global_directory);
@ -1118,10 +1191,19 @@ function admin_page_site_post(App $a)
Config::set('system', 'basepath', $basepath);
Config::set('system', 'proxy_disabled', $proxy_disabled);
Config::set('system', 'only_tag_search', $only_tag_search);
Config::set('system', 'worker_queues', $worker_queues);
Config::set('system', 'worker_dont_fork', $worker_dont_fork);
Config::set('system', 'worker_fastlane', $worker_fastlane);
Config::set('system', 'frontend_worker', $worker_frontend);
Config::set('system', 'relay_directly', $relay_directly);
Config::set('system', 'relay_server', $relay_server);
Config::set('system', 'relay_subscribe', $relay_subscribe);
Config::set('system', 'relay_scope', $relay_scope);
Config::set('system', 'relay_server_tags', $relay_server_tags);
Config::set('system', 'relay_user_tags', $relay_user_tags);
Config::set('system', 'rino_encrypt', $rino);
info(L10n::t('Site settings updated.') . EOL);
@ -1270,6 +1352,7 @@ function admin_page_site(App $a)
'$portable_contacts' => L10n::t('Auto Discovered Contact Directory'),
'$performance' => L10n::t('Performance'),
'$worker_title' => L10n::t('Worker'),
'$relay_title' => L10n::t('Message Relay'),
'$relocate' => L10n::t('Relocate - WARNING: advanced function. Could make this server unreachable.'),
'$baseurl' => System::baseUrl(true),
// name, label, value, help string, extra data...
@ -1293,7 +1376,7 @@ function admin_page_site(App $a)
'$register_policy' => ['register_policy', L10n::t("Register policy"), $a->config['register_policy'], "", $register_choices],
'$daily_registrations' => ['max_daily_registrations', L10n::t("Maximum Daily Registrations"), Config::get('system', 'max_daily_registrations'), L10n::t("If registration is permitted above, this sets the maximum number of new user registrations to accept per day. If register is set to closed, this setting has no effect.")],
'$register_text' => ['register_text', L10n::t("Register text"), $a->config['register_text'], L10n::t("Will be displayed prominently on the registration page.")],
'$register_text' => ['register_text', L10n::t("Register text"), $a->config['register_text'], L10n::t("Will be displayed prominently on the registration page. You can use BBCode here.")],
'$abandon_days' => ['abandon_days', L10n::t('Accounts abandoned after x days'), Config::get('system','account_abandon_days'), L10n::t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')],
'$allowed_sites' => ['allowed_sites', L10n::t("Allowed friend domains"), Config::get('system','allowed_sites'), L10n::t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")],
'$allowed_email' => ['allowed_email', L10n::t("Allowed email domains"), Config::get('system','allowed_email'), L10n::t("Comma separated list of domains which are allowed in email addresses for registrations to this site. Wildcards are accepted. Empty to allow any domains")],
@ -1301,7 +1384,7 @@ function admin_page_site(App $a)
'$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.")],
'$global_directory' => ['directory', L10n::t("Global directory URL"), Config::get('system','directory'), L10n::t("URL to the global directory. If this is not set, the global directory is completely unavailable to the application.")],
'$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.")],
'$private_addons' => ['private_addons', L10n::t("Disallow public access to addons listed in the apps menu."), Config::get('config','private_addons'), L10n::t("Checking this box will restrict addons listed in the apps menu to members only.")],
@ -1317,17 +1400,17 @@ function admin_page_site(App $a)
'$ostatus_not_able' => L10n::t("OStatus support can only be enabled if threading is enabled."),
'$diaspora_able' => $diaspora_able,
'$diaspora_not_able' => L10n::t("Diaspora support can't be enabled because Friendica was installed into a sub directory."),
'$diaspora_enabled' => ['diaspora_enabled', L10n::t("Enable Diaspora support"), Config::get('system','diaspora_enabled'), L10n::t("Provide built-in Diaspora network compatibility.")],
'$diaspora_enabled' => ['diaspora_enabled', L10n::t("Enable Diaspora support"), Config::get('system', 'diaspora_enabled', $diaspora_able), L10n::t("Provide built-in Diaspora network compatibility.")],
'$dfrn_only' => ['dfrn_only', L10n::t('Only allow Friendica contacts'), Config::get('system','dfrn_only'), L10n::t("All contacts must use Friendica protocols. All other built-in communication protocols disabled.")],
'$verifyssl' => ['verifyssl', L10n::t("Verify SSL"), Config::get('system','verifyssl'), L10n::t("If you wish, you can turn on strict certificate checking. This will mean you cannot connect \x28at all\x29 to self-signed SSL sites.")],
'$proxyuser' => ['proxyuser', L10n::t("Proxy user"), Config::get('system','proxyuser'), ""],
'$proxy' => ['proxy', L10n::t("Proxy URL"), Config::get('system','proxy'), ""],
'$timeout' => ['timeout', L10n::t("Network timeout"), (x(Config::get('system','curl_timeout'))?Config::get('system','curl_timeout'):60), L10n::t("Value is in seconds. Set to 0 for unlimited \x28not recommended\x29.")],
'$maxloadavg' => ['maxloadavg', L10n::t("Maximum Load Average"), ((intval(Config::get('system','maxloadavg')) > 0)?Config::get('system','maxloadavg'):50), L10n::t("Maximum system load before delivery and poll processes are deferred - default 50.")],
'$maxloadavg_frontend' => ['maxloadavg_frontend', L10n::t("Maximum Load Average \x28Frontend\x29"), ((intval(Config::get('system','maxloadavg_frontend')) > 0)?Config::get('system','maxloadavg_frontend'):50), L10n::t("Maximum system load before the frontend quits service - default 50.")],
'$min_memory' => ['min_memory', L10n::t("Minimal Memory"), ((intval(Config::get('system','min_memory')) > 0)?Config::get('system','min_memory'):0), L10n::t("Minimal free memory in MB for the worker. Needs access to /proc/meminfo - default 0 \x28deactivated\x29.")],
'$timeout' => ['timeout', L10n::t("Network timeout"), Config::get('system', 'curl_timeout', 60), L10n::t("Value is in seconds. Set to 0 for unlimited \x28not recommended\x29.")],
'$maxloadavg' => ['maxloadavg', L10n::t("Maximum Load Average"), Config::get('system', 'maxloadavg', 50), L10n::t("Maximum system load before delivery and poll processes are deferred - default 50.")],
'$maxloadavg_frontend' => ['maxloadavg_frontend', L10n::t("Maximum Load Average \x28Frontend\x29"), Config::get('system', 'maxloadavg_frontend', 50), L10n::t("Maximum system load before the frontend quits service - default 50.")],
'$min_memory' => ['min_memory', L10n::t("Minimal Memory"), Config::get('system', 'min_memory', 0), L10n::t("Minimal free memory in MB for the worker. Needs access to /proc/meminfo - default 0 \x28deactivated\x29.")],
'$optimize_max_tablesize'=> ['optimize_max_tablesize', L10n::t("Maximum table size for optimization"), $optimize_max_tablesize, L10n::t("Maximum table size \x28in MB\x29 for the automatic optimization - default 100 MB. Enter -1 to disable it.")],
'$optimize_fragmentation'=> ['optimize_fragmentation', L10n::t("Minimum level of fragmentation"), ((intval(Config::get('system','optimize_fragmentation')) > 0)?Config::get('system','optimize_fragmentation'):30), L10n::t("Minimum fragmenation level to start the automatic optimization - default value is 30%.")],
'$optimize_fragmentation'=> ['optimize_fragmentation', L10n::t("Minimum level of fragmentation"), Config::get('system', 'optimize_fragmentation', 30), L10n::t("Minimum fragmenation level to start the automatic optimization - default value is 30%.")],
'$poco_completion' => ['poco_completion', L10n::t("Periodical check of global contacts"), Config::get('system','poco_completion'), L10n::t("If enabled, the global contacts are checked periodically for missing or outdated data and the vitality of the contacts and servers.")],
'$poco_requery_days' => ['poco_requery_days', L10n::t("Days between requery"), Config::get('system','poco_requery_days'), L10n::t("Number of days after which a server is requeried for his contacts.")],
@ -1349,13 +1432,20 @@ function admin_page_site(App $a)
'$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.")],
'$rino' => ['rino', L10n::t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), L10n::t("Encryption layer between nodes."), [0 => "Disabled", 1 => "Enabled"]],
'$rino' => ['rino', L10n::t("RINO Encryption"), intval(Config::get('system','rino_encrypt')), L10n::t("Encryption layer between nodes."), [0 => L10n::t("Disabled"), 1 => L10n::t("Enabled")]],
'$worker_queues' => ['worker_queues', L10n::t("Maximum number of parallel workers"), Config::get('system','worker_queues'), L10n::t("On shared hosters set this to 2. On larger systems, values of 10 are great. Default value is 4.")],
'$worker_dont_fork' => ['worker_dont_fork', L10n::t("Don't use 'proc_open' with the worker"), Config::get('system','worker_dont_fork'), L10n::t("Enable this if your system doesn't allow the use of 'proc_open'. This can happen on shared hosters. If this is enabled you should increase the frequency of worker calls in your crontab.")],
'$worker_fastlane' => ['worker_fastlane', L10n::t("Enable fastlane"), Config::get('system','worker_fastlane'), L10n::t("When enabed, the fastlane mechanism starts an additional worker if processes with higher priority are blocked by processes of lower priority.")],
'$worker_frontend' => ['worker_frontend', L10n::t('Enable frontend worker'), Config::get('system','frontend_worker'), L10n::t('When enabled the Worker process is triggered when backend access is performed \x28e.g. messages being delivered\x29. On smaller sites you might want to call %s/worker on a regular basis via an external cron job. You should only enable this option if you cannot utilize cron/scheduled jobs on your server.', System::baseUrl())],
'$relay_subscribe' => ['relay_subscribe', L10n::t("Subscribe to relay"), Config::get('system','relay_subscribe'), L10n::t("Enables the receiving of public posts from the relay. They will be included in the search, subscribed tags and on the global community page.")],
'$relay_server' => ['relay_server', L10n::t("Relay server"), Config::get('system', 'relay_server', 'https://relay.diasp.org'), L10n::t("Address of the relay server where public posts should be send to. For example https://relay.diasp.org")],
'$relay_directly' => ['relay_directly', L10n::t("Direct relay transfer"), Config::get('system','relay_directly'), L10n::t("Enables the direct transfer to other servers without using the relay servers")],
'$relay_scope' => ['relay_scope', L10n::t("Relay scope"), Config::get('system','relay_scope'), L10n::t("Can be 'all' or 'tags'. 'all' means that every public post should be received. 'tags' means that only posts with selected tags should be received."), ['' => L10n::t('Disabled'), 'all' => L10n::t('all'), 'tags' => L10n::t('tags')]],
'$relay_server_tags' => ['relay_server_tags', L10n::t("Server tags"), Config::get('system','relay_server_tags'), L10n::t("Comma separated list of tags for the 'tags' subscription.")],
'$relay_user_tags' => ['relay_user_tags', L10n::t("Allow user tags"), Config::get('system', 'relay_user_tags', true), L10n::t("If enabled, the tags from the saved searches will used for the 'tags' subscription in addition to the 'relay_server_tags'.")],
'$form_security_token' => get_form_security_token("admin_site")
]);
}
@ -1508,6 +1598,8 @@ function admin_page_users_post(App $a)
If you are new and do not know anybody here, they may help
you to make some new and interesting friends.
If you ever want to delete your account, you can do so at %1$s/removeme
Thank you and welcome to %4$s.'));
$preamble = sprintf($preamble, $user['username'], $a->config['sitename']);
@ -1568,7 +1660,7 @@ function admin_page_users(App $a)
if ($a->argc > 2) {
$uid = $a->argv[3];
$user = dba::selectFirst('user', ['username', 'blocked'], ['uid' => $uid]);
if (DBM::is_result($user)) {
if (!DBM::is_result($user)) {
notice('User not found' . EOL);
goaway('admin/users');
return ''; // NOTREACHED

View file

@ -3,12 +3,9 @@
* @file mod/babel.php
*/
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\Markdown;
use Friendica\Content\Text;
use Friendica\Core\L10n;
require_once 'include/html2bbcode.php';
function visible_lf($s)
{
return str_replace("\n", '<br />', $s);
@ -16,64 +13,104 @@ function visible_lf($s)
function babel_content()
{
$o = '<h1>Babel Diagnostic</h1>';
$results = [];
if (!empty($_REQUEST['text'])) {
switch (defaults($_REQUEST, 'type', 'bbcode')) {
case 'bbcode':
$bbcode = trim($_REQUEST['text']);
$results[] = [
'title' => L10n::t('Source input'),
'content' => visible_lf($bbcode)
];
$o .= '<form action="babel" method="post">';
$o .= L10n::t("Source \x28bbcode\x29 text:") . EOL;
$o .= '<textarea name="text" cols="80" rows="10">' . htmlspecialchars($_REQUEST['text']) . '</textarea>' . EOL;
$o .= '<input type="submit" name="submit" value="Submit" /></form>';
$html = Text\BBCode::convert($bbcode);
$results[] = [
'title' => L10n::t("BBCode::convert \x28raw HTML\x29"),
'content' => htmlspecialchars($html)
];
$o .= '<br /><br />';
$results[] = [
'title' => L10n::t('BBCode::convert'),
'content' => $html
];
$o .= '<form action="babel" method="post">';
$o .= L10n::t("Source \x28Diaspora\x29 text to convert to BBcode:") . EOL;
$o .= '<textarea name="d2bbtext" cols="80" rows="10">' . htmlspecialchars($_REQUEST['d2bbtext']) . '</textarea>' . EOL;
$o .= '<input type="submit" name="submit" value="Submit" /></form>';
$bbcode2 = Text\HTML::toBBCode($html);
$results[] = [
'title' => L10n::t('BBCode::convert => HTML::toBBCode'),
'content' => visible_lf($bbcode2)
];
$o .= '<br /><br />';
$markdown = Text\BBCode::toMarkdown($bbcode);
$results[] = [
'title' => L10n::t('BBCode::toMarkdown'),
'content' => visible_lf($markdown)
];
if (x($_REQUEST, 'text')) {
$text = trim($_REQUEST['text']);
$o .= '<h2>' . L10n::t('Source input: ') . '</h2>' . EOL . EOL;
$o .= visible_lf($text) . EOL . EOL;
$html2 = Text\Markdown::convert($markdown);
$results[] = [
'title' => L10n::t('BBCode::toMarkdown => Markdown::convert'),
'content' => $html2
];
$html = BBCode::convert($text);
$o .= '<h2>' . L10n::t("bbcode \x28raw HTML\x28: ") . '</h2>' . EOL . EOL;
$o .= htmlspecialchars($html) . EOL . EOL;
$bbcode3 = Text\Markdown::toBBCode($markdown);
$results[] = [
'title' => L10n::t('BBCode::toMarkdown => Markdown::toBBCode'),
'content' => visible_lf($bbcode3)
];
$o .= '<h2>' . L10n::t('bbcode: ') . '</h2>' . EOL . EOL;
$o .= $html . EOL . EOL;
$bbcode4 = Text\HTML::toBBCode($html2);
$results[] = [
'title' => L10n::t('BBCode::toMarkdown => Markdown::convert => HTML::toBBCode'),
'content' => visible_lf($bbcode4)
];
break;
case 'markdown':
$markdown = trim($_REQUEST['text']);
$results[] = [
'title' => L10n::t('Source input \x28Diaspora format\x29'),
'content' => '<pre>' . $markdown . '</pre>'
];
$bbcode = html2bbcode($html);
$o .= '<h2>' . L10n::t('bbcode => html2bbcode: ') . '</h2>' . EOL . EOL;
$o .= visible_lf($bbcode) . EOL . EOL;
$bbcode = Text\Markdown::toBBCode($markdown);
$results[] = [
'title' => L10n::t('Markdown::toBBCode'),
'content' => '<pre>' . $bbcode . '</pre>'
];
break;
case 'html' :
$html = trim($_REQUEST['text']);
$results[] = [
'title' => L10n::t("Raw HTML input"),
'content' => htmlspecialchars($html)
];
$diaspora = BBCode::toMarkdown($text);
$o .= '<h2>' . L10n::t('BBCode::toMarkdown: ') . '</h2>' . EOL . EOL;
$o .= visible_lf($diaspora) . EOL . EOL;
$results[] = [
'title' => L10n::t('HTML Input'),
'content' => $html
];
$html = Markdown::convert($diaspora);
$o .= '<h2>' . L10n::t('BBCode::toMarkdown => Markdown::convert: ') . '</h2>' . EOL . EOL;
$o .= $html . EOL . EOL;
$bbcode = Text\HTML::toBBCode($html);
$results[] = [
'title' => L10n::t('HTML::toBBCode'),
'content' => visible_lf($bbcode)
];
$bbcode = Markdown::toBBCode($diaspora);
$o .= '<h2>' . L10n::t('BBCode::toMarkdown => Markdown::toBBCode: ') . '</h2>' . EOL . EOL;
$o .= visible_lf($bbcode) . EOL . EOL;
$bbcode = html2bbcode($html);
$o .= '<h2>' . L10n::t('bbcode => html2bbcode: ') . '</h2>' . EOL . EOL;
$o .= visible_lf($bbcode) . EOL . EOL;
$text = Text\HTML::toPlaintext($html);
$results[] = [
'title' => L10n::t('HTML::toPlaintext'),
'content' => '<pre>' . $text . '</pre>'
];
}
}
if (x($_REQUEST, 'd2bbtext')) {
$d2bbtext = trim($_REQUEST['d2bbtext']);
$o .= '<h2>' . L10n::t("Source input \x28Diaspora format\x29: ") . '</h2>' . EOL . EOL;
$o .= '<pre>' . $d2bbtext . '</pre>' . EOL . EOL;
$bb = Markdown::toBBCode($d2bbtext);
$o .= '<h2>' . L10n::t('diaspora2bb: ') . '</h2>' . EOL . EOL;
$o .= '<pre>' . $bb . '</pre>' . EOL . EOL;
}
$tpl = get_markup_template('babel.tpl');
$o = replace_macros($tpl, [
'$text' => ['text', L10n::t('Source text'), defaults($_REQUEST, 'text', ''), ''],
'$type_bbcode' => ['type', L10n::t('BBCode'), 'bbcode', '', defaults($_REQUEST, 'type', 'bbcode') == 'bbcode'],
'$type_markdown' => ['type', L10n::t('Markdown'), 'markdown', '', defaults($_REQUEST, 'type', 'bbcode') == 'markdown'],
'$type_html' => ['type', L10n::t('HTML'), 'html', '', defaults($_REQUEST, 'type', 'bbcode') == 'html'],
'$results' => $results
]);
return $o;
}

View file

@ -9,19 +9,19 @@
use Friendica\App;
use Friendica\Content\Feature;
use Friendica\Content\Nav;
use Friendica\Content\Widget;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Model\Contact;
use Friendica\Model\Event;
use Friendica\Model\Group;
use Friendica\Model\Profile;
use Friendica\Protocol\DFRN;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Temporal;
require_once 'include/event.php';
function cal_init(App $a)
{
if ($a->argc > 1) {
@ -64,7 +64,7 @@ function cal_init(App $a)
'$pdesc' => (($profile['pdesc'] != "") ? $profile['pdesc'] : ""),
]);
$cal_widget = widget_events();
$cal_widget = Widget\CalendarExport::getHTML();
if (!x($a->page, 'aside')) {
$a->page['aside'] = '';
@ -82,7 +82,7 @@ function cal_content(App $a)
Nav::setSelected('events');
// get the translation strings for the callendar
$i18n = get_event_strings();
$i18n = Event::getStrings();
$htpl = get_markup_template('event_head.tpl');
$a->page['htmlhead'] .= replace_macros($htpl, [
@ -212,25 +212,25 @@ function cal_content(App $a)
// put the event parametes in an array so we can better transmit them
$event_params = [
'event_id' => (x($_GET, 'id') ? $_GET["id"] : 0),
'start' => $start,
'finish' => $finish,
'adjust_start' => $adjust_start,
'event_id' => intval(defaults($_GET, 'id', 0)),
'start' => $start,
'finish' => $finish,
'adjust_start' => $adjust_start,
'adjust_finish' => $adjust_finish,
'ignored' => $ignored,
'ignore' => $ignored,
];
// get events by id or by date
if (x($_GET, 'id')) {
$r = event_by_id($owner_uid, $event_params, $sql_extra);
if ($event_params['event_id']) {
$r = Event::getListById($owner_uid, $event_params['event-id'], $sql_extra);
} else {
$r = events_by_date($owner_uid, $event_params, $sql_extra);
$r = Event::getListByDate($owner_uid, $event_params, $sql_extra);
}
$links = [];
if (DBM::is_result($r)) {
$r = sort_by_date($r);
$r = Event::sortByDate($r);
foreach ($r as $rr) {
$j = $rr['adjust'] ? DateTimeFormat::local($rr['start'], 'j') : DateTimeFormat::utc($rr['start'], 'j');
if (!x($links, $j)) {
@ -240,7 +240,7 @@ function cal_content(App $a)
}
// transform the event in a usable array
$events = process_events($r);
$events = Event::prepareListForTemplate($r);
if ($a->argv[2] === 'json') {
echo json_encode($events);
@ -306,7 +306,7 @@ function cal_content(App $a)
}
// Get the export data by uid
$evexport = event_export($owner_uid, $format);
$evexport = Event::exportListByUserId($owner_uid, $format);
if (!$evexport["success"]) {
if ($evexport["content"]) {

View file

@ -45,6 +45,14 @@ function contacts_init(App $a)
}
if (DBM::is_result($contact)) {
if ($contact['self']) {
if (($a->argc == 3) && intval($a->argv[1]) && ($a->argv[2] == "posts")) {
goaway('profile/' . $contact['nick']);
} else {
goaway('profile/' . $contact['nick'] . '?tab=profile');
}
}
$a->data['contact'] = $contact;
if (($a->data['contact']['network'] != "") && ($a->data['contact']['network'] != NETWORK_DFRN)) {
@ -579,9 +587,10 @@ function contacts_content(App $a)
$profile_select = ContactSelector::profileAssign($contact['profile-id'], (($contact['network'] !== NETWORK_DFRN) ? true : false));
}
/// @todo Only show the following link with DFRN when the remote version supports it
$follow = '';
$follow_text = '';
if (in_array($contact['network'], [NETWORK_DIASPORA, NETWORK_OSTATUS])) {
if (in_array($contact['network'], [NETWORK_DIASPORA, NETWORK_OSTATUS, NETWORK_DFRN])) {
if ($contact['rel'] == CONTACT_IS_FOLLOWER) {
$follow = System::baseUrl(true) . "/follow?url=" . urlencode($contact["url"]);
$follow_text = L10n::t("Connect/Follow");
@ -939,6 +948,13 @@ function _contact_detail_for_template($rr)
$sparkle = '';
}
if ($rr['self']) {
$dir_icon = 'images/larrow.gif';
$alt_text = L10n::t('This is you');
$url = $rr['url'];
$sparkle = '';
}
return [
'img_hover' => L10n::t('Visit %s\'s profile [%s]', $rr['name'], $rr['url']),
'edit_hover' => L10n::t('Edit contact'),

View file

@ -6,6 +6,7 @@ use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Model\User;
require_once 'mod/settings.php';
@ -28,6 +29,21 @@ function delegate_post(App $a)
check_form_security_token_redirectOnErr('/delegate', 'delegate');
$parent_uid = defaults($_POST, 'parent_user', 0);
$parent_password = defaults($_POST, 'parent_password', '');
if ($parent_uid != 0) {
$user = dba::selectFirst('user', ['nickname'], ['uid' => $parent_uid]);
if (!DBM::is_result($user)) {
notice(L10n::t('Parent user not found.') . EOL);
return;
}
$success = User::authenticate($user['nickname'], trim($parent_password));
if (!$success) {
notice(L10n::t('Permission denied.') . EOL);
return;
}
}
dba::update('user', ['parent-uid' => $parent_uid], ['uid' => local_user()]);
}
@ -70,16 +86,6 @@ function delegate_content(App $a)
goaway(System::baseUrl() . '/delegate');
}
// These people can manage this account/page with full privilege
$full_managers = [];
$r = q("SELECT * FROM `user` WHERE `email` = '%s' AND `password` = '%s' ",
dbesc($a->user['email']),
dbesc($a->user['password'])
);
if (DBM::is_result($r)) {
$full_managers = $r;
}
// find everybody that currently has delegated management to this account/page
$delegates = [];
$r = q("SELECT * FROM `user` WHERE `uid` IN (SELECT `uid` FROM `manage` WHERE `mid` = %d)",
@ -90,10 +96,6 @@ function delegate_content(App $a)
}
$uids = [];
foreach ($full_managers as $rr) {
$uids[] = $rr['uid'];
}
foreach ($delegates as $rr) {
$uids[] = $rr['uid'];
}
@ -153,18 +155,21 @@ function delegate_content(App $a)
}
}
if (!is_null($parent_user)) {
$parent_password = ['parent_password', L10n::t('Parent Password:'), '', L10n::t('Please enter the password of the parent account to legitimize your request.')];
}
$o = replace_macros(get_markup_template('delegate.tpl'), [
'$form_security_token' => get_form_security_token('delegate'),
'$parent_header' => L10n::t('Parent User'),
'$parent_user' => $parent_user,
'$parent_password' => $parent_password,
'$parent_desc' => L10n::t('Parent users have total control about this account, including the account settings. Please double check whom you give this access.'),
'$submit' => L10n::t('Save Settings'),
'$header' => L10n::t('Delegate Page Management'),
'$delegates_header' => L10n::t('Delegates'),
'$base' => System::baseUrl(),
'$desc' => L10n::t('Delegates are able to manage all aspects of this account/page except for basic account settings. Please do not delegate your personal account to anybody that you do not trust completely.'),
'$head_managers' => L10n::t('Existing Page Managers'),
'$managers' => $full_managers,
'$head_delegates' => L10n::t('Existing Page Delegates'),
'$delegates' => $delegates,
'$head_potentials' => L10n::t('Potential Delegates'),

View file

@ -12,12 +12,60 @@ use Friendica\Core\System;
use Friendica\Database\DBM;
use Friendica\Model\Contact;
use Friendica\Protocol\DFRN;
use Friendica\Protocol\Diaspora;
require_once 'include/items.php';
require_once 'include/event.php';
function dfrn_notify_post(App $a) {
logger(__function__, LOGGER_TRACE);
$postdata = file_get_contents('php://input');
if (empty($_POST) || !empty($postdata)) {
$data = json_decode($postdata);
if (is_object($data)) {
$nick = defaults($a->argv, 1, '');
$user = dba::selectFirst('user', [], ['nickname' => $nick, 'account_expired' => false, 'account_removed' => false]);
if (!DBM::is_result($user)) {
System::httpExit(500);
}
$msg = Diaspora::decodeRaw($user, $postdata);
// Check if the user has got this contact
$cid = Contact::getIdForURL($msg['author'], $user['uid']);
if (!$cid) {
// Otherwise there should be a public contact
$cid = Contact::getIdForURL($msg['author']);
if (!$cid) {
logger('Contact not found for address ' . $msg['author']);
System::xmlExit(3, 'Contact not found');
}
}
// We now have some contact, so we fetch it
$importer = dba::fetch_first("SELECT *, `name` as `senderName`
FROM `contact`
WHERE NOT `blocked` AND `id` = ? LIMIT 1",
$cid);
// This should never fail
if (!DBM::is_result($importer)) {
logger('Contact not found for address ' . $msg['author']);
System::xmlExit(3, 'Contact not found');
}
// Set the user id. This is important if this is a public contact
$importer['importer_uid'] = $user['uid'];
// Now we should be able to import it
$ret = DFRN::import($msg['message'], $importer);
System::xmlExit($ret, 'Done');
} else {
require_once 'mod/salmon.php';
salmon_post($a, $postdata);
}
}
$dfrn_id = ((x($_POST,'dfrn_id')) ? notags(trim($_POST['dfrn_id'])) : '');
$dfrn_version = ((x($_POST,'dfrn_version')) ? (float) $_POST['dfrn_version'] : 2.0);
$challenge = ((x($_POST,'challenge')) ? notags(trim($_POST['challenge'])) : '');

View file

@ -12,12 +12,12 @@ use Friendica\Database\DBM;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
function directory_init(App $a) {
function directory_init(App $a)
{
$a->set_pager_itemspage(60);
if(local_user()) {
if (local_user()) {
$a->page['aside'] .= Widget::findPeople();
$a->page['aside'] .= Widget::follow();
} else {
unset($_SESSION['theme']);
@ -25,16 +25,20 @@ function directory_init(App $a) {
}
}
function directory_post(App $a) {
if(x($_POST,'search'))
function directory_post(App $a)
{
if (x($_POST, 'search')) {
$a->data['search'] = $_POST['search'];
}
}
function directory_content(App $a) {
function directory_content(App $a)
{
require_once("mod/proxy.php");
if((Config::get('system','block_public')) && (! local_user()) && (! remote_user()) ||
(Config::get('system','block_local_dir')) && (! local_user()) && (! remote_user())) {
if ((Config::get('system', 'block_public') && !local_user() && !remote_user())
|| (Config::get('system', 'block_local_dir') && !local_user() && !remote_user())
) {
notice(L10n::t('Public access denied.') . EOL);
return;
}
@ -42,18 +46,19 @@ function directory_content(App $a) {
$o = '';
Nav::setSelected('directory');
if(x($a->data,'search'))
if (x($a->data, 'search')) {
$search = notags(trim($a->data['search']));
else
$search = ((x($_GET,'search')) ? notags(trim(rawurldecode($_GET['search']))) : '');
$gdirpath = '';
$dirurl = Config::get('system','directory');
if(strlen($dirurl)) {
$gdirpath = Profile::zrl($dirurl,true);
} else {
$search = ((x($_GET, 'search')) ? notags(trim(rawurldecode($_GET['search']))) : '');
}
if($search) {
$gdirpath = '';
$dirurl = Config::get('system', 'directory');
if (strlen($dirurl)) {
$gdirpath = Profile::zrl($dirurl, true);
}
if ($search) {
$search = dbesc($search);
$sql_extra = " AND ((`profile`.`name` LIKE '%$search%') OR
@ -73,35 +78,34 @@ function directory_content(App $a) {
(`profile`.`prv_keywords` LIKE '%$search%'))";
}
$publish = ((Config::get('system','publish_all')) ? '' : " AND `publish` = 1 " );
$publish = (Config::get('system', 'publish_all') ? '' : " AND `publish` = 1 " );
$r = q("SELECT COUNT(*) AS `total` FROM `profile`
LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
WHERE `is-default` = 1 $publish AND `user`.`blocked` = 0 $sql_extra ");
if (DBM::is_result($r))
$a->set_pager_total($r[0]['total']);
$cnt = dba::fetch_first("SELECT COUNT(*) AS `total` FROM `profile`
LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
WHERE `is-default` $publish AND NOT `user`.`blocked` $sql_extra");
if (DBM::is_result($cnt)) {
$a->set_pager_total($cnt['total']);
}
$order = " ORDER BY `name` ASC ";
$limit = intval($a->pager['start']).",".intval($a->pager['itemspage']);
$limit = intval($a->pager['start'])."," . intval($a->pager['itemspage']);
$r = q("SELECT `profile`.*, `profile`.`uid` AS `profile_uid`, `user`.`nickname`, `user`.`timezone` , `user`.`page-flags`,
$r = dba::p("SELECT `profile`.*, `profile`.`uid` AS `profile_uid`, `user`.`nickname`, `user`.`timezone` , `user`.`page-flags`,
`contact`.`addr`, `contact`.`url` AS profile_url FROM `profile`
LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
LEFT JOIN `contact` ON `contact`.`uid` = `user`.`uid`
WHERE `is-default` $publish AND `user`.`blocked` = 0 AND `contact`.`self` $sql_extra $order LIMIT ".$limit);
WHERE `is-default` $publish AND `user`.`blocked` = 0 AND `contact`.`self` $sql_extra $order LIMIT ".$limit
);
if (DBM::is_result($r)) {
if (in_array('small', $a->argv)) {
$photo = 'thumb';
}
else {
} else {
$photo = 'photo';
}
foreach ($r as $rr) {
while ($rr = dba::fetch($r)) {
$itemurl= '';
$itemurl = (($rr['addr'] != "") ? $rr['addr'] : $rr['profile_url']);
@ -111,16 +115,19 @@ function directory_content(App $a) {
$pdesc = (($rr['pdesc']) ? $rr['pdesc'] . '<br />' : '');
$details = '';
if(strlen($rr['locality']))
if (strlen($rr['locality'])) {
$details .= $rr['locality'];
if(strlen($rr['region'])) {
if(strlen($rr['locality']))
}
if (strlen($rr['region'])) {
if (strlen($rr['locality'])) {
$details .= ', ';
}
$details .= $rr['region'];
}
if(strlen($rr['country-name'])) {
if(strlen($details))
if (strlen($rr['country-name'])) {
if (strlen($details)) {
$details .= ', ';
}
$details .= $rr['country-name'];
}
// if(strlen($rr['dob'])) {
@ -132,20 +139,19 @@ function directory_content(App $a) {
$profile = $rr;
if((x($profile,'address') == 1)
|| (x($profile,'locality') == 1)
|| (x($profile,'region') == 1)
|| (x($profile,'postal-code') == 1)
|| (x($profile,'country-name') == 1))
$location = L10n::t('Location:');
if ((x($profile, 'address') == 1)
|| (x($profile, 'locality') == 1)
|| (x($profile, 'region') == 1)
|| (x($profile, 'postal-code') == 1)
|| (x($profile, 'country-name') == 1)
) {
$location = L10n::t('Location:');
}
$gender = ((x($profile,'gender') == 1) ? L10n::t('Gender:') : False);
$marital = ((x($profile,'marital') == 1) ? L10n::t('Status:') : False);
$homepage = ((x($profile,'homepage') == 1) ? L10n::t('Homepage:') : False);
$about = ((x($profile,'about') == 1) ? L10n::t('About:') : False);
$gender = ((x($profile, 'gender') == 1) ? L10n::t('Gender:') : false);
$marital = ((x($profile, 'marital') == 1) ? L10n::t('Status:') : false);
$homepage = ((x($profile, 'homepage') == 1) ? L10n::t('Homepage:') : false);
$about = ((x($profile, 'about') == 1) ? L10n::t('About:') : false);
$location_e = $location;
@ -154,23 +160,23 @@ function directory_content(App $a) {
];
$entry = [
'id' => $rr['id'],
'url' => $profile_link,
'itemurl' => $itemurl,
'thumb' => proxy_url($rr[$photo], false, PROXY_SIZE_THUMB),
'img_hover' => $rr['name'],
'name' => $rr['name'],
'details' => $details,
'id' => $rr['id'],
'url' => $profile_link,
'itemurl' => $itemurl,
'thumb' => proxy_url($rr[$photo], false, PROXY_SIZE_THUMB),
'img_hover' => $rr['name'],
'name' => $rr['name'],
'details' => $details,
'account_type' => Contact::getAccountType($rr),
'profile' => $profile,
'location' => $location_e,
'tags' => $rr['pub_keywords'],
'gender' => $gender,
'pdesc' => $pdesc,
'marital' => $marital,
'homepage' => $homepage,
'about' => $about,
'photo_menu' => $photo_menu,
'profile' => $profile,
'location' => $location_e,
'tags' => $rr['pub_keywords'],
'gender' => $gender,
'pdesc' => $pdesc,
'marital' => $marital,
'homepage' => $homepage,
'about' => $about,
'photo_menu' => $photo_menu,
];
@ -187,20 +193,21 @@ function directory_content(App $a) {
$entries[] = $arr['entry'];
}
dba::close($r);
$tpl = get_markup_template('directory_header.tpl');
$o .= replace_macros($tpl, [
'$search' => $search,
'$search' => $search,
'$globaldir' => L10n::t('Global Directory'),
'$gdirpath' => $gdirpath,
'$desc' => L10n::t('Find on this site'),
'$contacts' => $entries,
'$finding' => L10n::t('Results for:'),
'$findterm' => (strlen($search) ? $search : ""),
'$title' => L10n::t('Site Directory'),
'$submit' => L10n::t('Find'),
'$paginate' => paginate($a),
'$gdirpath' => $gdirpath,
'$desc' => L10n::t('Find on this site'),
'$contacts' => $entries,
'$finding' => L10n::t('Results for:'),
'$findterm' => (strlen($search) ? $search : ""),
'$title' => L10n::t('Site Directory'),
'$submit' => L10n::t('Find'),
'$paginate' => paginate($a),
]);
} else {
info(L10n::t("No entries \x28some entries may be hidden\x29.") . EOL);

View file

@ -15,6 +15,7 @@ use Friendica\Model\Profile;
use Friendica\Network\Probe;
use Friendica\Protocol\PortableContact;
use Friendica\Util\Network;
use Friendica\Database\DBM;
require_once 'mod/contacts.php';
@ -113,32 +114,22 @@ function dirfind_content(App $a, $prefix = "") {
/// @TODO These 2 SELECTs are not checked on validity with DBM::is_result()
$count = q("SELECT count(*) AS `total` FROM `gcontact`
LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl`
AND `contact`.`network` = `gcontact`.`network`
AND `contact`.`uid` = %d AND NOT `contact`.`blocked`
AND NOT `contact`.`pending` AND `contact`.`rel` IN ('%s', '%s')
WHERE (`contact`.`id` > 0 OR (NOT `gcontact`.`hide` AND `gcontact`.`network` IN ('%s', '%s', '%s') AND
((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)))) AND
(`gcontact`.`url` LIKE '%s' OR `gcontact`.`name` LIKE '%s' OR `gcontact`.`location` LIKE '%s' OR
`gcontact`.`addr` LIKE '%s' OR `gcontact`.`about` LIKE '%s' OR `gcontact`.`keywords` LIKE '%s') $extra_sql",
intval(local_user()), dbesc(CONTACT_IS_SHARING), dbesc(CONTACT_IS_FRIEND),
WHERE NOT `hide` AND `network` IN ('%s', '%s', '%s') AND
((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) AND
(`url` LIKE '%s' OR `name` LIKE '%s' OR `location` LIKE '%s' OR
`addr` LIKE '%s' OR `about` LIKE '%s' OR `keywords` LIKE '%s') $extra_sql",
dbesc(NETWORK_DFRN), dbesc($ostatus), dbesc($diaspora),
dbesc(escape_tags($search2)), dbesc(escape_tags($search2)), dbesc(escape_tags($search2)),
dbesc(escape_tags($search2)), dbesc(escape_tags($search2)), dbesc(escape_tags($search2)));
$results = q("SELECT `contact`.`id` AS `cid`, `gcontact`.`url`, `gcontact`.`name`, `gcontact`.`photo`, `gcontact`.`network`, `gcontact`.`keywords`, `gcontact`.`addr`
$results = q("SELECT `nurl`
FROM `gcontact`
LEFT JOIN `contact` ON `contact`.`nurl` = `gcontact`.`nurl`
AND `contact`.`network` = `gcontact`.`network`
AND `contact`.`uid` = %d AND NOT `contact`.`blocked`
AND NOT `contact`.`pending` AND `contact`.`rel` IN ('%s', '%s')
WHERE (`contact`.`id` > 0 OR (NOT `gcontact`.`hide` AND `gcontact`.`network` IN ('%s', '%s', '%s') AND
((`gcontact`.`last_contact` >= `gcontact`.`last_failure`) OR (`gcontact`.`updated` >= `gcontact`.`last_failure`)))) AND
(`gcontact`.`url` LIKE '%s' OR `gcontact`.`name` LIKE '%s' OR `gcontact`.`location` LIKE '%s' OR
`gcontact`.`addr` LIKE '%s' OR `gcontact`.`about` LIKE '%s' OR `gcontact`.`keywords` LIKE '%s') $extra_sql
GROUP BY `gcontact`.`nurl`
ORDER BY `gcontact`.`updated` DESC LIMIT %d, %d",
intval(local_user()), dbesc(CONTACT_IS_SHARING), dbesc(CONTACT_IS_FRIEND),
WHERE NOT `hide` AND `network` IN ('%s', '%s', '%s') AND
((`last_contact` >= `last_failure`) OR (`updated` >= `last_failure`)) AND
(`url` LIKE '%s' OR `name` LIKE '%s' OR `location` LIKE '%s' OR
`addr` LIKE '%s' OR `about` LIKE '%s' OR `keywords` LIKE '%s') $extra_sql
GROUP BY `nurl`
ORDER BY `updated` DESC LIMIT %d, %d",
dbesc(NETWORK_DFRN), dbesc($ostatus), dbesc($diaspora),
dbesc(escape_tags($search2)), dbesc(escape_tags($search2)), dbesc(escape_tags($search2)),
dbesc(escape_tags($search2)), dbesc(escape_tags($search2)), dbesc(escape_tags($search2)),
@ -148,14 +139,21 @@ function dirfind_content(App $a, $prefix = "") {
$j->items_page = $perpage;
$j->page = $a->pager['page'];
foreach ($results AS $result) {
if (PortableContact::alternateOStatusUrl($result["url"])) {
if (PortableContact::alternateOStatusUrl($result["nurl"])) {
continue;
}
$result = Contact::getDetailsByURL($result["url"], local_user(), $result);
$urlparts = parse_url($result["nurl"]);
// Ignore results that look strange.
// For historic reasons the gcontact table does contain some garbage.
if (!empty($urlparts['query']) || !empty($urlparts['fragment'])) {
continue;
}
$result = Contact::getDetailsByURL($result["nurl"], local_user());
if ($result["name"] == "") {
$urlparts = parse_url($result["url"]);
$result["name"] = end(explode("/", $urlparts["path"]));
}
@ -204,11 +202,10 @@ function dirfind_content(App $a, $prefix = "") {
if ($jj->cid > 0) {
$connlnk = "";
$conntxt = "";
$contact = q("SELECT * FROM `contact` WHERE `id` = %d",
intval($jj->cid));
if ($contact) {
$photo_menu = Contact::photoMenu($contact[0]);
$details = _contact_detail_for_template($contact[0]);
$contact = dba::selectFirst('contact', [], ['id' => $jj->cid]);
if (DBM::is_result($contact)) {
$photo_menu = Contact::photoMenu($contact);
$details = _contact_detail_for_template($contact);
$alt_text = $details['alt_text'];
} else {
$photo_menu = [];
@ -226,7 +223,7 @@ function dirfind_content(App $a, $prefix = "") {
$entry = [
'alt_text' => $alt_text,
'url' => Profile::zrl($jj->url),
'url' => Profile::magicLink($jj->url),
'itemurl' => $itemurl,
'name' => htmlentities($jj->name),
'thumb' => proxy_url($jj->photo, false, PROXY_SIZE_THUMB),

View file

@ -5,6 +5,7 @@
use Friendica\App;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
use Friendica\Core\ACL;
use Friendica\Core\Config;
use Friendica\Core\L10n;
@ -211,7 +212,11 @@ function display_content(App $a, $update = false, $update_uid = 0) {
if ($update) {
$item_id = $_REQUEST['item_id'];
$item = dba::selectFirst('item', ['uid', 'parent'], ['id' => $item_id]);
$a->profile = ['uid' => intval($item['uid']), 'profile_uid' => intval($item['uid'])];
if ($item['uid'] != 0) {
$a->profile = ['uid' => intval($item['uid']), 'profile_uid' => intval($item['uid'])];
} else {
$a->profile = ['uid' => intval($update_uid), 'profile_uid' => intval($update_uid)];
}
$item_parent = $item['parent'];
} else {
$item_id = (($a->argc > 2) ? $a->argv[2] : 0);
@ -367,10 +372,8 @@ function display_content(App $a, $update = false, $update_uid = 0) {
$o .= conversation($a, $items, 'display', $update_uid);
// Preparing the meta header
require_once 'include/html2plain.php';
$description = trim(html2plain(BBCode::convert($s[0]["body"], false), 0, true));
$title = trim(html2plain(BBCode::convert($s[0]["title"], false), 0, true));
$description = trim(HTML::toPlaintext(BBCode::convert($s[0]["body"], false), 0, true));
$title = trim(HTML::toPlaintext(BBCode::convert($s[0]["title"], false), 0, true));
$author_name = $s[0]["author-name"];
$image = $a->remove_baseurl($s[0]["author-thumb"]);

View file

@ -6,17 +6,18 @@
use Friendica\App;
use Friendica\Content\Nav;
use Friendica\Content\Widget\CalendarExport;
use Friendica\Core\ACL;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBM;
use Friendica\Model\Event;
use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Temporal;
require_once 'include/event.php';
require_once 'include/items.php';
function events_init(App $a) {
@ -24,22 +25,22 @@ function events_init(App $a) {
return;
}
if ($a->argc > 1) {
// If it's a json request abort here because we don't
// need the widget data
if ($a->argv[1] === 'json') {
return;
}
$cal_widget = widget_events();
if (! x($a->page,'aside')) {
$a->page['aside'] = '';
}
$a->page['aside'] .= $cal_widget;
// If it's a json request abort here because we don't
// need the widget data
if ($a->argc > 1 && $a->argv[1] === 'json') {
return;
}
if (empty($a->page['aside'])) {
$a->page['aside'] = '';
}
$a->data['user'] = $_SESSION['user'];
$cal_widget = CalendarExport::getHTML();
$a->page['aside'] .= $cal_widget;
return;
}
@ -155,7 +156,6 @@ function events_post(App $a) {
$datarray = [];
$datarray['guid'] = get_guid(32);
$datarray['start'] = $start;
$datarray['finish'] = $finish;
$datarray['summary'] = $summary;
@ -170,18 +170,16 @@ function events_post(App $a) {
$datarray['allow_gid'] = $str_group_allow;
$datarray['deny_cid'] = $str_contact_deny;
$datarray['deny_gid'] = $str_group_deny;
$datarray['private'] = (($private_event) ? 1 : 0);
$datarray['private'] = $private_event;
$datarray['id'] = $event_id;
$datarray['created'] = $created;
$datarray['edited'] = $edited;
if (intval($_REQUEST['preview'])) {
$html = format_event_html($datarray);
$html = Event::getHTML($datarray);
echo $html;
killme();
}
$item_id = event_store($datarray);
$item_id = Event::store($datarray);
if (! $cid) {
Worker::add(PRIORITY_HIGH, "Notifier", "event", $item_id);
@ -222,7 +220,7 @@ function events_content(App $a) {
}
// get the translation strings for the callendar
$i18n = get_event_strings();
$i18n = Event::getStrings();
$htpl = get_markup_template('event_head.tpl');
$a->page['htmlhead'] .= replace_macros($htpl, [
@ -331,25 +329,25 @@ function events_content(App $a) {
// put the event parametes in an array so we can better transmit them
$event_params = [
'event_id' => (x($_GET, 'id') ? $_GET['id'] : 0),
'event_id' => intval(defaults($_GET, 'id', 0)),
'start' => $start,
'finish' => $finish,
'adjust_start' => $adjust_start,
'adjust_finish' => $adjust_finish,
'ignored' => $ignored,
'ignore' => $ignored,
];
// get events by id or by date
if (x($_GET, 'id')) {
$r = event_by_id(local_user(), $event_params);
if ($event_params['event_id']) {
$r = Event::getListById(local_user(), $event_params['event_id']);
} else {
$r = events_by_date(local_user(), $event_params);
$r = Event::getListByDate(local_user(), $event_params);
}
$links = [];
if (DBM::is_result($r)) {
$r = sort_by_date($r);
$r = Event::sortByDate($r);
foreach ($r as $rr) {
$j = $rr['adjust'] ? DateTimeFormat::local($rr['start'], 'j') : DateTimeFormat::utc($rr['start'], 'j');
if (! x($links,$j)) {
@ -362,8 +360,8 @@ function events_content(App $a) {
// transform the event in a usable array
if (DBM::is_result($r)) {
$r = sort_by_date($r);
$events = process_events($r);
$r = Event::sortByDate($r);
$events = Event::prepareListForTemplate($r);
}
if ($a->argc > 1 && $a->argv[1] === 'json'){
@ -372,7 +370,7 @@ function events_content(App $a) {
}
if (x($_GET, 'id')) {
$tpl = get_markup_template("event.tpl");
$tpl = get_markup_template("event.tpl");
} else {
$tpl = get_markup_template("events_js.tpl");
}
@ -543,8 +541,7 @@ function events_content(App $a) {
if ($mode === 'drop' && $event_id) {
$del = 0;
$params = ['event_id' => ($event_id)];
$ev = event_by_id(local_user(), $params);
$ev = Event::getListById(local_user(), $event_id);
// Delete only real events (no birthdays)
if (DBM::is_result($ev) && $ev[0]['type'] == 'event') {

53
mod/feedtest.php Normal file
View file

@ -0,0 +1,53 @@
<?php
/**
* @file_tag_list_to_file mod/feedtest.php
*/
use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Model\Contact;
use Friendica\Protocol\Feed;
use Friendica\Util\Network;
require_once 'boot.php';
require_once 'include/dba.php';
require_once 'include/text.php';
function feedtest_content(App $a)
{
if (!local_user()) {
info(L10n::t('You must be logged in to use this module'));
return;
};
$result = [];
if (!empty($_REQUEST['url'])) {
$url = $_REQUEST['url'];
$importer = dba::selectFirst('user', [], ['uid' => local_user()]);
$contact_id = Contact::getIdForURL($url, local_user(), true);
$contact = dba::selectFirst('contact', [], ['id' => $contact_id]);
$ret = Network::curl($contact['poll']);
$xml = $ret['body'];
$dummy = null;
$import_result = Feed::import($xml, $importer, $contact, $dummy, true);
$result = [
'input' => text_highlight($xml, 'xml'),
'output' => var_export($import_result, true),
];
}
$tpl = get_markup_template('feedtest.tpl');
$o = replace_macros($tpl, [
'$url' => ['url', L10n::t('Source URL'), defaults($_REQUEST, 'url', ''), ''],
'$result' => $result
]);
return $o;
}

View file

@ -9,11 +9,12 @@ use Friendica\Core\System;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
use Friendica\Network\Probe;
use Friendica\Database\DBM;
function follow_post(App $a) {
function follow_post(App $a)
{
if (!local_user()) {
notice(L10n::t('Permission denied.') . EOL);
notice(L10n::t('Permission denied.'));
goaway($_SESSION['return_url']);
// NOTREACHED
}
@ -28,7 +29,7 @@ function follow_post(App $a) {
// Makes the connection request for friendica contacts easier
// This is just a precaution if maybe this page is called somewhere directly via POST
$_SESSION["fastlane"] = $url;
$_SESSION['fastlane'] = $url;
$result = Contact::createFromProbe($uid, $url, true);
@ -38,19 +39,19 @@ function follow_post(App $a) {
}
goaway($return_url);
} elseif ($result['cid']) {
goaway(System::baseUrl().'/contacts/'.$result['cid']);
goaway(System::baseUrl() . '/contacts/' . $result['cid']);
}
info(L10n::t('The contact could not be added.').EOL);
info(L10n::t('The contact could not be added.'));
goaway($return_url);
// NOTREACHED
}
function follow_content(App $a) {
function follow_content(App $a)
{
if (!local_user()) {
notice(L10n::t('Permission denied.') . EOL);
notice(L10n::t('Permission denied.'));
goaway($_SESSION['return_url']);
// NOTREACHED
}
@ -60,121 +61,125 @@ function follow_content(App $a) {
$submit = L10n::t('Submit Request');
// There is a current issue. It seems as if you can't start following a Friendica that is following you
// With Diaspora this works - but Friendica is special, it seems ...
$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND ((`rel` != %d) OR (`network` = '%s')) AND
// Don't try to add a pending contact
$r = q("SELECT `pending` FROM `contact` WHERE `uid` = %d AND ((`rel` != %d) OR (`network` = '%s')) AND
(`nurl` = '%s' OR `alias` = '%s' OR `alias` = '%s') AND
`network` != '%s' LIMIT 1",
intval(local_user()), dbesc(CONTACT_IS_FOLLOWER), dbesc(NETWORK_DFRN), dbesc(normalise_link($url)),
dbesc(normalise_link($url)), dbesc($url), dbesc(NETWORK_STATUSNET));
if ($r) {
notice(L10n::t('You already added this contact.').EOL);
$submit = "";
//goaway($_SESSION['return_url']);
// NOTREACHED
if ($r[0]['pending']) {
notice(L10n::t('You already added this contact.'));
$submit = '';
//goaway($_SESSION['return_url']);
// NOTREACHED
}
}
$ret = Probe::uri($url);
if (($ret["network"] == NETWORK_DIASPORA) && !Config::get('system', 'diaspora_enabled')) {
notice(L10n::t("Diaspora support isn't enabled. Contact can't be added.") . EOL);
$submit = "";
if (($ret['network'] == NETWORK_DIASPORA) && !Config::get('system', 'diaspora_enabled')) {
notice(L10n::t("Diaspora support isn't enabled. Contact can't be added."));
$submit = '';
//goaway($_SESSION['return_url']);
// NOTREACHED
}
if (($ret["network"] == NETWORK_OSTATUS) && Config::get('system', 'ostatus_disabled')) {
notice(L10n::t("OStatus support is disabled. Contact can't be added.") . EOL);
$submit = "";
if (($ret['network'] == NETWORK_OSTATUS) && Config::get('system', 'ostatus_disabled')) {
notice(L10n::t("OStatus support is disabled. Contact can't be added."));
$submit = '';
//goaway($_SESSION['return_url']);
// NOTREACHED
}
if ($ret["network"] == NETWORK_PHANTOM) {
notice(L10n::t("The network type couldn't be detected. Contact can't be added.") . EOL);
$submit = "";
if ($ret['network'] == NETWORK_PHANTOM) {
notice(L10n::t("The network type couldn't be detected. Contact can't be added."));
$submit = '';
//goaway($_SESSION['return_url']);
// NOTREACHED
}
if ($ret["network"] == NETWORK_MAIL) {
$ret["url"] = $ret["addr"];
if ($ret['network'] == NETWORK_MAIL) {
$ret['url'] = $ret['addr'];
}
if ($ret['network'] === NETWORK_DFRN) {
$request = $ret["request"];
if (($ret['network'] === NETWORK_DFRN) && !DBM::is_result($r)) {
$request = $ret['request'];
$tpl = get_markup_template('dfrn_request.tpl');
} else {
$request = System::baseUrl()."/follow";
$request = System::baseUrl() . '/follow';
$tpl = get_markup_template('auto_request.tpl');
}
$r = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND `self` LIMIT 1", intval($uid));
if (!$r) {
notice(L10n::t('Permission denied.') . EOL);
notice(L10n::t('Permission denied.'));
goaway($_SESSION['return_url']);
// NOTREACHED
}
$myaddr = $r[0]["url"];
$myaddr = $r[0]['url'];
$gcontact_id = 0;
// Makes the connection request for friendica contacts easier
$_SESSION["fastlane"] = $ret["url"];
$_SESSION['fastlane'] = $ret['url'];
$r = q("SELECT `id`, `location`, `about`, `keywords` FROM `gcontact` WHERE `nurl` = '%s'",
normalise_link($ret["url"]));
normalise_link($ret['url']));
if (!$r) {
$r = [["location" => "", "about" => "", "keywords" => ""]];
$r = [['location' => '', 'about' => '', 'keywords' => '']];
} else {
$gcontact_id = $r[0]["id"];
$gcontact_id = $r[0]['id'];
}
if ($ret['network'] === NETWORK_DIASPORA) {
$r[0]["location"] = "";
$r[0]["about"] = "";
$r[0]['location'] = '';
$r[0]['about'] = '';
}
$header = L10n::t("Connect/Follow");
$header = L10n::t('Connect/Follow');
$o = replace_macros($tpl, [
'$header' => htmlentities($header),
//'$photo' => proxy_url($ret["photo"], false, PROXY_SIZE_SMALL),
'$desc' => "",
'$pls_answer' => L10n::t('Please answer the following:'),
'$does_know_you' => ['knowyou', L10n::t('Does %s know you?', $ret["name"]), false, '', [L10n::t('No'), L10n::t('Yes')]],
'$add_note' => L10n::t('Add a personal note:'),
'$page_desc' => "",
'$friendica' => "",
'$statusnet' => "",
'$diaspora' => "",
'$diasnote' => "",
'$your_address' => L10n::t('Your Identity Address:'),
'$invite_desc' => "",
'$emailnet' => "",
'$submit' => $submit,
'$cancel' => L10n::t('Cancel'),
'$nickname' => "",
'$name' => $ret["name"],
'$url' => $ret["url"],
'$zrl' => Profile::zrl($ret["url"]),
'$url_label' => L10n::t("Profile URL"),
'$myaddr' => $myaddr,
'$request' => $request,
/*'$location' => Friendica\Content\Text\BBCode::::convert($r[0]["location"]),
'$location_label' => L10n::t("Location:"),
'$about' => Friendica\Content\Text\BBCode::::convert($r[0]["about"], false, false),
'$about_label' => L10n::t("About:"), */
'$keywords' => $r[0]["keywords"],
'$keywords_label' => L10n::t("Tags:")
$o = replace_macros($tpl, [
'$header' => htmlentities($header),
//'$photo' => proxy_url($ret['photo'], false, PROXY_SIZE_SMALL),
'$desc' => '',
'$pls_answer' => L10n::t('Please answer the following:'),
'$does_know_you' => ['knowyou', L10n::t('Does %s know you?', $ret['name']), false, '', [L10n::t('No'), L10n::t('Yes')]],
'$add_note' => L10n::t('Add a personal note:'),
'$page_desc' => '',
'$friendica' => '',
'$statusnet' => '',
'$diaspora' => '',
'$diasnote' => '',
'$your_address' => L10n::t('Your Identity Address:'),
'$invite_desc' => '',
'$emailnet' => '',
'$submit' => $submit,
'$cancel' => L10n::t('Cancel'),
'$nickname' => '',
'$name' => $ret['name'],
'$url' => $ret['url'],
'$zrl' => Profile::zrl($ret['url']),
'$url_label' => L10n::t('Profile URL'),
'$myaddr' => $myaddr,
'$request' => $request,
/*'$location' => Friendica\Content\Text\BBCode::::convert($r[0]['location']),
'$location_label'=> L10n::t('Location:'),
'$about' => Friendica\Content\Text\BBCode::::convert($r[0]['about'], false, false),
'$about_label' => L10n::t('About:'),*/
'$keywords' => $r[0]['keywords'],
'$keywords_label'=> L10n::t('Tags:')
]);
$a->page['aside'] = "";
$a->page['aside'] = '';
Profile::load($a, "", 0, Contact::getDetailsByURL($ret["url"]), false);
$profiledata = Contact::getDetailsByURL($ret['url']);
if ($profiledata) {
Profile::load($a, '', 0, $profiledata, false);
}
if ($gcontact_id <> 0) {
$o .= replace_macros(get_markup_template('section_title.tpl'),
@ -182,7 +187,7 @@ function follow_content(App $a) {
);
// Show last public posts
$o .= Contact::getPostsFromUrl($ret["url"]);
$o .= Contact::getPostsFromUrl($ret['url']);
}
return $o;

View file

@ -86,7 +86,7 @@ function friendica_content(App $a)
$o .= L10n::t('Bug reports and issues: please visit') . ' ' . '<a href="https://github.com/friendica/friendica/issues?state=open">'.L10n::t('the bugtracker at github').'</a>';
$o .= '</p>' . PHP_EOL;
$o .= '<p>';
$o .= L10n::t('Suggestions, praise, donations, etc. - please email "Info" at Friendica - dot com');
$o .= L10n::t('Suggestions, praise, etc. - please email "info" at "friendi - dot - ca');
$o .= '</p>' . PHP_EOL;
$visible_addons = [];
@ -116,6 +116,11 @@ function friendica_content(App $a)
} else {
$o .= '<p>' . L10n::t('No installed addons/apps') . '</p>' . PHP_EOL;
}
if (Config::get('system', 'tosdisplay'))
{
$o .= '<p>'.L10n::t('Read about the <a href="%1$s/tos">Terms of Service</a> of this node.', System::baseurl()).'</p>';
}
$blocklist = Config::get('system', 'blocklist');
if (count($blocklist)) {

View file

@ -397,7 +397,8 @@ function check_funcs(&$checks) {
check_add($ck_funcs, L10n::t('PDO or MySQLi PHP module'), true, true, "");
check_add($ck_funcs, L10n::t('mb_string PHP module'), true, true, "");
check_add($ck_funcs, L10n::t('XML PHP module'), true, true, "");
check_add($ck_funcs, L10n::t('iconv module'), true, true, "");
check_add($ck_funcs, L10n::t('iconv PHP module'), true, true, "");
check_add($ck_funcs, L10n::t('POSIX PHP module'), true, true, "");
if (function_exists('apache_get_modules')) {
if (! in_array('mod_rewrite',apache_get_modules())) {
@ -432,8 +433,12 @@ function check_funcs(&$checks) {
$ck_funcs[4]['help'] = L10n::t('Error: mb_string PHP module required but not installed.');
}
if (! function_exists('iconv_strlen')) {
$ck_funcs[6]['status'] = false;
$ck_funcs[6]['help'] = L10n::t('Error: iconv PHP module required but not installed.');
}
if (! function_exists('posix_kill')) {
$ck_funcs[7]['status'] = false;
$ck_funcs[7]['help'] = L10n::t('Error: iconv PHP module required but not installed.');
$ck_funcs[7]['help'] = L10n::t('Error: POSIX PHP module required but not installed.');
}
$checks = array_merge($checks, $ck_funcs);
@ -442,8 +447,8 @@ function check_funcs(&$checks) {
try {
$xml = new DOMDocument();
} catch (Exception $e) {
$ck_funcs[6]['status'] = false;
$ck_funcs[6]['help'] = L10n::t('Error, XML PHP module required but not installed.');
$ck_funcs[5]['status'] = false;
$ck_funcs[5]['help'] = L10n::t('Error, XML PHP module required but not installed.');
}
}
@ -540,7 +545,7 @@ function load_database_rem($v, $i) {
}
function load_database() {
$errors = DBStructure::update(false, true);
$errors = DBStructure::update(false, true, true);
return $errors;
}

View file

@ -35,28 +35,28 @@ function invite_post(App $a)
}
$recips = ((x($_POST, 'recipients')) ? explode("\n", $_POST['recipients']) : []);
$message = ((x($_POST, 'message')) ? notags(trim($_POST['message'])) : '');
$recipients = !empty($_POST['recipients']) ? explode("\n", $_POST['recipients']) : [];
$message = !empty($_POST['message']) ? notags(trim($_POST['message'])) : '';
$total = 0;
if (Config::get('system', 'invitation_only')) {
$invonly = true;
$x = PConfig::get(local_user(), 'system', 'invites_remaining');
if ((! $x) && (! is_site_admin())) {
$invitation_only = true;
$invites_remaining = PConfig::get(local_user(), 'system', 'invites_remaining');
if ((! $invites_remaining) && (! is_site_admin())) {
return;
}
}
foreach ($recips as $recip) {
$recip = trim($recip);
foreach ($recipients as $recipient) {
$recipient = trim($recipient);
if (! valid_email($recip)) {
notice(L10n::t('%s : Not a valid email address.', $recip) . EOL);
if (! valid_email($recipient)) {
notice(L10n::t('%s : Not a valid email address.', $recipient) . EOL);
continue;
}
if ($invonly && ($x || is_site_admin())) {
if ($invitation_only && ($invites_remaining || is_site_admin())) {
$code = autoname(8) . srand(1000, 9999);
$nmessage = str_replace('$invite_code', $code, $message);
@ -66,9 +66,9 @@ function invite_post(App $a)
);
if (! is_site_admin()) {
$x --;
if ($x >= 0) {
PConfig::set(local_user(), 'system', 'invites_remaining', $x);
$invites_remaining --;
if ($invites_remaining >= 0) {
PConfig::set(local_user(), 'system', 'invites_remaining', $invites_remaining);
} else {
return;
}
@ -77,11 +77,16 @@ function invite_post(App $a)
$nmessage = $message;
}
$res = mail($recip, Email::encodeHeader(L10n::t('Please join us on Friendica'), 'UTF-8'),
$nmessage,
"From: " . $a->user['email'] . "\n"
$additional_headers = 'From: ' . $a->user['email'] . "\n"
. 'Sender: ' . $a->getSenderEmailAddress() . "\n"
. 'Content-type: text/plain; charset=UTF-8' . "\n"
. 'Content-transfer-encoding: 8bit' );
. 'Content-transfer-encoding: 8bit';
$res = mail(
$recipient,
Email::encodeHeader(L10n::t('Please join us on Friendica'), 'UTF-8'),
$nmessage,
$additional_headers);
if ($res) {
$total ++;
@ -92,7 +97,7 @@ function invite_post(App $a)
return;
}
} else {
notice(L10n::t('%s : Message delivery failed.', $recip) . EOL);
notice(L10n::t('%s : Message delivery failed.', $recipient) . EOL);
}
}

View file

@ -808,7 +808,6 @@ function item_post(App $a) {
$link = '<a href="' . System::baseUrl() . '/profile/' . $a->user['nickname'] . '"><img src="' . $author['thumb'] . '" alt="' . $a->user['username'] . '" /></a><br /><br />';
$html = prepare_body($datarray);
$message = '<html><body>' . $link . $html . $disclaimer . '</body></html>';
include_once 'include/html2plain.php';
$params = [
'fromName' => $a->user['username'],
'fromEmail' => $a->user['email'],
@ -816,7 +815,7 @@ function item_post(App $a) {
'replyTo' => $a->user['email'],
'messageSubject' => $subject,
'htmlVersion' => $message,
'textVersion' => html2plain($html.$disclaimer)
'textVersion' => Friendica\Content\Text\HTML::toPlaintext($html.$disclaimer)
];
Emailer::send($params);
}

View file

@ -69,6 +69,7 @@ function lostpass_post(App $a)
notification([
'type' => SYSTEM_EMAIL,
'to_email' => $user['email'],
'uid' => $user['uid'],
'subject' => L10n::t('Password reset requested at %s', $sitename),
'preamble' => $preamble,
'body' => $body
@ -164,6 +165,7 @@ function lostpass_generate_password($user)
notification([
'type' => SYSTEM_EMAIL,
'to_email' => $user['email'],
'uid' => $user['uid'],
'subject' => L10n::t('Your password has been changed at %s', $sitename),
'preamble' => $preamble,
'body' => $body

View file

@ -771,10 +771,15 @@ function networkThreadedView(App $a, $update, $parent)
FROM `item` $sql_post_table
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
AND (`item`.`parent-uri` != `item`.`uri`
OR `contact`.`uid` = `item`.`uid` AND `contact`.`self`
OR `contact`.`rel` IN (%d, %d) AND NOT `contact`.`readonly`)
WHERE `item`.`uid` = %d AND `item`.`visible` AND NOT `item`.`deleted`
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())
);
} else {
@ -783,10 +788,15 @@ function networkThreadedView(App $a, $update, $parent)
STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
AND (NOT `contact`.`blocked` OR `contact`.`pending`)
STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid`
AND (`item`.`parent-uri` != `item`.`uri`
OR `contact`.`uid` = `item`.`uid` AND `contact`.`self`
OR `contact`.`rel` IN (%d, %d) AND NOT `contact`.`readonly`)
WHERE `thread`.`uid` = %d AND `thread`.`visible` AND NOT `thread`.`deleted`
AND NOT `thread`.`moderated`
$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())
);
}
@ -827,9 +837,14 @@ function networkThreadedView(App $a, $update, $parent)
(SELECT SUBSTR(`term`, 2) FROM `search` WHERE `uid` = ? AND `term` LIKE '#%') AND `otype` = ? AND `type` = ? AND `uid` = 0) AS `term`
ON `item`.`id` = `term`.`oid`
STRAIGHT_JOIN `contact` ON `contact`.`id` = `item`.`author-id`
AND (`item`.`parent-uri` != `item`.`uri`
OR `contact`.`uid` = `item`.`uid` AND `contact`.`self`
OR `contact`.`rel` IN (?, ?) AND NOT `contact`.`readonly`)
WHERE `item`.`uid` = 0 AND `item`.$ordering < ? AND `item`.$ordering > ?
AND NOT `contact`.`hidden` AND NOT `contact`.`blocked`" . $sql_tag_nets,
local_user(), TERM_OBJ_POST, TERM_HASHTAG, $top_limit, $bottom_limit);
local_user(), TERM_OBJ_POST, TERM_HASHTAG,
CONTACT_IS_SHARING, CONTACT_IS_FRIEND,
$top_limit, $bottom_limit);
$data = dba::inArray($items);

View file

@ -46,13 +46,11 @@ function oexchange_content(App $a) {
return;
}
require_once('include/html2bbcode.php');
$post = [];
$post['profile_uid'] = local_user();
$post['return'] = '/oexchange/done' ;
$post['body'] = html2bbcode($s);
$post['body'] = Friendica\Content\Text\HTML::toBBCode($s);
$post['type'] = 'wall';
$_REQUEST = $post;

View file

@ -29,12 +29,14 @@ function ostatus_subscribe_content(App $a) {
if (PConfig::get($uid, "ostatus", "legacy_friends") == "") {
if ($_REQUEST["url"] == "") {
PConfig::delete($uid, "ostatus", "legacy_contact");
return $o.L10n::t("No contact provided.");
}
$contact = Probe::uri($_REQUEST["url"]);
if (!$contact) {
PConfig::delete($uid, "ostatus", "legacy_contact");
return $o.L10n::t("Couldn't fetch information for contact.");
}
@ -44,6 +46,7 @@ function ostatus_subscribe_content(App $a) {
$data = Network::curl($api."statuses/friends.json?screen_name=".$contact["nick"]);
if (!$data["success"]) {
PConfig::delete($uid, "ostatus", "legacy_contact");
return $o.L10n::t("Couldn't fetch friends for contact.");
}

View file

@ -9,6 +9,7 @@ use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBM;
use Friendica\Model\Contact;
use Friendica\Model\Photo;
use Friendica\Model\Profile;
use Friendica\Object\Image;
@ -105,18 +106,11 @@ function profile_photo_post(App $a) {
// If setting for the default profile, unset the profile photo flag from any other photos I own
if($is_default_profile) {
if ($is_default_profile) {
$r = q("UPDATE `photo` SET `profile` = 0 WHERE `profile` = 1 AND `resource-id` != '%s' AND `uid` = %d",
dbesc($base_image['resource-id']),
intval(local_user())
);
$r = q("UPDATE `contact` SET `photo` = '%s', `thumb` = '%s', `micro` = '%s' WHERE `self` AND `uid` = %d",
dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-4.' . $Image->getExt()),
dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-5.' . $Image->getExt()),
dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-6.' . $Image->getExt()),
intval(local_user())
);
} else {
$r = q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
dbesc(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-4.' . $Image->getExt()),
@ -126,13 +120,7 @@ function profile_photo_post(App $a) {
);
}
// we'll set the updated profile-photo timestamp even if it isn't the default profile,
// so that browsers will do a cache update unconditionally
$r = q("UPDATE `contact` SET `avatar-date` = '%s' WHERE `self` = 1 AND `uid` = %d",
dbesc(DateTimeFormat::utcNow()),
intval(local_user())
);
Contact::updateSelfFromUserID(local_user(), true);
info(L10n::t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL);
// Update global directory in background
@ -229,10 +217,7 @@ function profile_photo_content(App $a) {
dbesc($resource_id)
);
$r = q("UPDATE `contact` SET `avatar-date` = '%s' WHERE `self` = 1 AND `uid` = %d",
dbesc(DateTimeFormat::utcNow()),
intval(local_user())
);
Contact::updateSelfFromUserID(local_user(), true);
// Update global directory in background
$url = $_SESSION['my_url'];

View file

@ -14,6 +14,7 @@ use Friendica\Core\PConfig;
use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBM;
use Friendica\Model\Contact;
use Friendica\Model\GContact;
use Friendica\Model\Item;
use Friendica\Model\Profile;
@ -485,29 +486,15 @@ function profiles_post(App $a) {
info(L10n::t('Profile updated.') . EOL);
}
if ($namechanged && $is_default) {
$r = q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `self` = 1 AND `uid` = %d",
dbesc($name),
dbesc(DateTimeFormat::utcNow()),
intval(local_user())
);
$r = q("UPDATE `user` set `username` = '%s' where `uid` = %d",
dbesc($name),
intval(local_user())
);
}
if ($is_default) {
$location = Profile::formatLocation(["locality" => $locality, "region" => $region, "country-name" => $country_name]);
if ($namechanged) {
$r = q("UPDATE `user` set `username` = '%s' where `uid` = %d",
dbesc($name),
intval(local_user())
);
}
q("UPDATE `contact` SET `about` = '%s', `location` = '%s', `keywords` = '%s', `gender` = '%s' WHERE `self` AND `uid` = %d",
dbesc($about),
dbesc($location),
dbesc($pub_keywords),
dbesc($gender),
intval(local_user())
);
Contact::updateSelfFromUserID(local_user());
// Update global directory in background
$url = $_SESSION['my_url'];

View file

@ -2,162 +2,136 @@
use Friendica\App;
use Friendica\Database\DBM;
use Friendica\Protocol\OStatus;
function hub_return($valid,$body) {
require_once('include/security.php');
require_once('include/items.php');
if($valid) {
header($_SERVER["SERVER_PROTOCOL"] . ' 200 ' . 'OK');
function hub_return($valid, $body)
{
if ($valid) {
header($_SERVER["SERVER_PROTOCOL"] . ' 200 OK');
echo $body;
killme();
} else {
header($_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
}
else {
header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . 'Not Found');
killme();
}
// NOTREACHED
killme();
}
// when receiving an XML feed, always return OK
function hub_post_return() {
header($_SERVER["SERVER_PROTOCOL"] . ' 200 ' . 'OK');
function hub_post_return()
{
header($_SERVER["SERVER_PROTOCOL"] . ' 200 OK');
killme();
}
function pubsub_init(App $a) {
function pubsub_init(App $a)
{
$nick = (($a->argc > 1) ? notags(trim($a->argv[1])) : '');
$contact_id = (($a->argc > 2) ? intval($a->argv[2]) : 0 );
if($_SERVER['REQUEST_METHOD'] === 'GET') {
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$hub_mode = notags(trim(defaults($_GET, 'hub_mode', '')));
$hub_topic = notags(trim(defaults($_GET, 'hub_topic', '')));
$hub_challenge = notags(trim(defaults($_GET, 'hub_challenge', '')));
$hub_lease = notags(trim(defaults($_GET, 'hub_lease_seconds', '')));
$hub_verify = notags(trim(defaults($_GET, 'hub_verify_token', '')));
$hub_mode = ((x($_GET,'hub_mode')) ? notags(trim($_GET['hub_mode'])) : '');
$hub_topic = ((x($_GET,'hub_topic')) ? notags(trim($_GET['hub_topic'])) : '');
$hub_challenge = ((x($_GET,'hub_challenge')) ? notags(trim($_GET['hub_challenge'])) : '');
$hub_lease = ((x($_GET,'hub_lease_seconds')) ? notags(trim($_GET['hub_lease_seconds'])) : '');
$hub_verify = ((x($_GET,'hub_verify_token')) ? notags(trim($_GET['hub_verify_token'])) : '');
logger('pubsub: Subscription from ' . $_SERVER['REMOTE_ADDR']);
logger('pubsub: data: ' . print_r($_GET,true), LOGGER_DATA);
logger('Subscription from ' . $_SERVER['REMOTE_ADDR'] . ' Mode: ' . $hub_mode . ' Nick: ' . $nick);
logger('Data: ' . print_r($_GET,true), LOGGER_DATA);
$subscribe = (($hub_mode === 'subscribe') ? 1 : 0);
$r = q("SELECT * FROM `user` WHERE `nickname` = '%s' AND `account_expired` = 0 AND `account_removed` = 0 LIMIT 1",
dbesc($nick)
);
if (! DBM::is_result($r)) {
logger('pubsub: local account not found: ' . $nick);
$owner = dba::selectFirst('user', ['uid'], ['nickname' => $nick, 'account_expired' => false, 'account_removed' => false]);
if (!DBM::is_result($owner)) {
logger('Local account not found: ' . $nick);
hub_return(false, '');
}
$condition = ['uid' => $owner['uid'], 'id' => $contact_id, 'blocked' => false, 'pending' => false];
$owner = $r[0];
if (!empty($hub_verify)) {
$condition['hub-verify'] = $hub_verify;
}
$sql_extra = ((strlen($hub_verify)) ? sprintf(" AND `hub-verify` = '%s' ", dbesc($hub_verify)) : '');
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d
AND `blocked` = 0 AND `pending` = 0 $sql_extra LIMIT 1",
intval($contact_id),
intval($owner['uid'])
);
if (! DBM::is_result($r)) {
logger('pubsub: contact '.$contact_id.' not found.');
$contact = dba::selectFirst('contact', ['id', 'poll'], $condition);
if (!DBM::is_result($contact)) {
logger('Contact ' . $contact_id . ' not found.');
hub_return(false, '');
}
if ($hub_topic)
if(! link_compare($hub_topic,$r[0]['poll'])) {
logger('pubsub: hub topic ' . $hub_topic . ' != ' . $r[0]['poll']);
// should abort but let's humour them.
}
$contact = $r[0];
if (!empty($hub_topic) && !link_compare($hub_topic, $contact['poll'])) {
logger('Hub topic ' . $hub_topic . ' != ' . $contact['poll']);
hub_return(false, '');
}
// We must initiate an unsubscribe request with a verify_token.
// Don't allow outsiders to unsubscribe us.
if($hub_mode === 'unsubscribe') {
if(! strlen($hub_verify)) {
logger('pubsub: bogus unsubscribe');
hub_return(false, '');
}
logger('pubsub: unsubscribe success');
if (($hub_mode === 'unsubscribe') && empty($hub_verify)) {
logger('Bogus unsubscribe');
hub_return(false, '');
}
if ($hub_mode)
$r = q("UPDATE `contact` SET `subhub` = %d WHERE `id` = %d",
intval($subscribe),
intval($contact['id'])
);
if (!empty($hub_mode)) {
dba::update('contact', ['subhub' => $subscribe], ['id' => $contact['id']]);
logger($hub_mode . ' success for contact ' . $contact_id . '.');
}
hub_return(true, $hub_challenge);
}
}
require_once('include/security.php');
function pubsub_post(App $a) {
function pubsub_post(App $a)
{
$xml = file_get_contents('php://input');
logger('pubsub: feed arrived from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $a->cmd );
logger('pubsub: user-agent: ' . $_SERVER['HTTP_USER_AGENT'] );
logger('pubsub: data: ' . $xml, LOGGER_DATA);
// if(! stristr($xml,'<?xml')) {
// logger('pubsub_post: bad xml');
// hub_post_return();
// }
logger('Feed arrived from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $a->cmd . ' with user-agent: ' . $_SERVER['HTTP_USER_AGENT']);
logger('Data: ' . $xml, LOGGER_DATA);
$nick = (($a->argc > 1) ? notags(trim($a->argv[1])) : '');
$contact_id = (($a->argc > 2) ? intval($a->argv[2]) : 0 );
$r = q("SELECT * FROM `user` WHERE `nickname` = '%s' AND `account_expired` = 0 AND `account_removed` = 0 LIMIT 1",
dbesc($nick)
);
if (! DBM::is_result($r)) {
$importer = dba::selectFirst('user', [], ['nickname' => $nick, 'account_expired' => false, 'account_removed' => false]);
if (!DBM::is_result($importer)) {
hub_post_return();
}
$importer = $r[0];
$condition = ['id' => $contact_id, 'uid' => $importer['uid'], 'subhub' => true, 'blocked' => false];
$contact = dba::selectFirst('contact', [], $condition);
$r = q("SELECT * FROM `contact` WHERE `subhub` AND `id` = %d AND `uid` = %d
AND (`rel` = %d OR `rel` = %d OR network = '%s') AND NOT `blocked` LIMIT 1",
intval($contact_id),
intval($importer['uid']),
intval(CONTACT_IS_SHARING),
intval(CONTACT_IS_FRIEND),
dbesc(NETWORK_FEED)
);
if (!DBM::is_result($contact)) {
$author = OStatus::salmonAuthor($xml, $importer);
if (!empty($author['contact-id'])) {
$condition = ['id' => $author['contact-id'], 'uid' => $importer['uid'], 'subhub' => true, 'blocked' => false];
$contact = dba::selectFirst('contact', [], $condition);
logger('No record for ' . $nick .' with contact id ' . $contact_id . ' - using '.$author['contact-id'].' instead.');
}
if (!DBM::is_result($contact)) {
logger('Contact ' . $author["author-link"] . ' (' . $contact_id . ') for user ' . $nick . " wasn't found - ignored. XML: " . $xml);
hub_post_return();
}
}
if (! DBM::is_result($r)) {
logger('pubsub: no contact record for "'.$nick.' ('.$contact_id.')" - ignored. '.$xml);
if (!in_array($contact['rel'], [CONTACT_IS_SHARING, CONTACT_IS_FRIEND]) && ($contact['network'] != NETWORK_FEED)) {
logger('Contact ' . $contact['id'] . ' is not expected to share with us - ignored.');
hub_post_return();
}
$contact = $r[0];
// we have no way to match Diaspora guid's with atom post id's and could get duplicates.
// we'll assume that direct delivery is robust (and this is a bad assumption, but the duplicates are messy).
if($r[0]['network'] === NETWORK_DIASPORA)
// We import feeds from OStatus, Friendica and ATOM/RSS.
/// @todo Check if Friendica posts really arrive here - otherwise we can discard some stuff
if (!in_array($contact['network'], [NETWORK_OSTATUS, NETWORK_DFRN, NETWORK_FEED])) {
hub_post_return();
}
logger('Import item for ' . $nick . ' from ' . $contact['nick'] . ' (' . $contact['id'] . ')');
$feedhub = '';
consume_feed($xml, $importer, $contact, $feedhub);
require_once('include/items.php');
consume_feed($xml,$importer,$contact,$feedhub,1,1);
// do it a second time so that any children find their parents.
consume_feed($xml,$importer,$contact,$feedhub,1,2);
// do it a second time for DFRN so that any children find their parents.
if ($contact['network'] === NETWORK_DFRN) {
consume_feed($xml, $importer, $contact, $feedhub);
}
hub_post_return();
}

View file

@ -262,7 +262,7 @@ function register_content(App $a)
'$invite_id' => $invite_id,
'$realpeople' => $realpeople,
'$regtitle' => L10n::t('Registration'),
'$registertext' => x($a->config, 'register_text') ? BBCode::convert($a->config['register_text']) : "",
'$registertext' => BBCode::convert(Config::get('config', 'register_text', '')),
'$fillwith' => $fillwith,
'$fillext' => $fillext,
'$oidlabel' => $oidlabel,
@ -284,6 +284,9 @@ function register_content(App $a)
'$sitename' => $a->get_hostname(),
'$importh' => L10n::t('Import'),
'$importt' => L10n::t('Import your profile to this friendica instance'),
'$showtoslink' => Config::get('system', 'tosdisplay'),
'$tostext' => L10n::t('Terms of Service'),
'$baseurl' => System::baseurl(),
'$form_security_token' => get_form_security_token("register")
]);
return $o;

View file

@ -7,6 +7,8 @@ use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Model\User;
require_once 'include/enotify.php';
function removeme_post(App $a)
{
if (!local_user()) {
@ -29,6 +31,25 @@ function removeme_post(App $a)
return;
}
// send notification to admins so that they can clean um the backups
// send email to admins
$admin_mail_list = "'" . implode("','", array_map(dbesc, explode(",", str_replace(" ", "", $a->config['admin_email'])))) . "'";
$adminlist = q("SELECT uid, language, email FROM user WHERE email IN (%s)",
$admin_mail_list
);
foreach ($adminlist as $admin) {
notification([
'type' => SYSTEM_EMAIL,
'subject' => L10n::t('[Friendica System Notify]') . ' ' . L10n::t('User deleted their account'),
'preamble' => L10n::t('On your Friendica node an user deleted their account. Please ensure that their data is removed from the backups.'),
'body' => L10n::t('The user id is %d', local_user()),
'to_email' => $admin['email'],
'uid' => $admin['uid'],
'language' => $admin['language'] ? $admin['language'] : 'en',
'show_in_notification_page' => false
]);
}
if (User::authenticate($a->user, trim($_POST['qxz_password']))) {
User::remove($a->user['uid']);
// NOTREACHED

View file

@ -13,9 +13,11 @@ use Friendica\Util\Crypto;
require_once 'include/items.php';
function salmon_post(App $a) {
function salmon_post(App $a, $xml = '') {
$xml = file_get_contents('php://input');
if (empty($xml)) {
$xml = file_get_contents('php://input');
}
logger('new salmon ' . $xml, LOGGER_DATA);

View file

@ -14,11 +14,11 @@ use Friendica\Core\PConfig;
use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBM;
use Friendica\Model\Contact;
use Friendica\Model\GContact;
use Friendica\Model\Group;
use Friendica\Model\User;
use Friendica\Protocol\Email;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Temporal;
@ -208,11 +208,11 @@ function settings_post(App $a)
return;
}
if (($a->argc > 1) && ($a->argv[1] == 'connectors'))
{
if (($a->argc > 1) && ($a->argv[1] == 'connectors')) {
check_form_security_token_redirectOnErr('/settings/connectors', 'settings_connectors');
if (x($_POST, 'general-submit')) {
PConfig::set(local_user(), 'system', 'disable_cw', intval($_POST['disable_cw']));
PConfig::set(local_user(), 'system', 'no_intelligent_shortening', intval($_POST['no_intelligent_shortening']));
PConfig::set(local_user(), 'system', 'ostatus_autofriend', intval($_POST['snautofollow']));
PConfig::set(local_user(), 'ostatus', 'default_group', $_POST['group-selection']);
@ -388,13 +388,18 @@ function settings_post(App $a)
if (!x($newpass) || !x($confirm)) {
notice(L10n::t('Empty passwords are not allowed. Password unchanged.') . EOL);
$err = true;
}
}
// check if the old password was supplied correctly before changing it to the new value
if (!User::authenticate(intval(local_user()), $_POST['opassword'])) {
notice(L10n::t('Wrong password.') . EOL);
$err = true;
}
if (!Config::get('system', 'disable_password_exposed', false) && User::isPasswordExposed($newpass)) {
notice(L10n::t('The new password has been exposed in a public data dump, please choose another.') . EOL);
$err = true;
}
// check if the old password was supplied correctly before changing it to the new value
if (!User::authenticate(intval(local_user()), $_POST['opassword'])) {
notice(L10n::t('Wrong password.') . EOL);
$err = true;
}
if (!$err) {
$result = User::updatePassword(local_user(), $newpass);
@ -486,10 +491,7 @@ function settings_post(App $a)
$err = '';
$name_change = false;
if ($username != $a->user['username']) {
$name_change = true;
if (strlen($username) > 40) {
$err .= L10n::t(' Please use a shorter name.');
}
@ -629,14 +631,7 @@ function settings_post(App $a)
intval(local_user())
);
if ($name_change) {
q("UPDATE `contact` SET `name` = '%s', `name-date` = '%s' WHERE `uid` = %d AND `self`",
dbesc($username),
dbesc(DateTimeFormat::utcNow()),
intval(local_user())
);
}
Contact::updateSelfFromUserID(local_user());
if (($old_visibility != $net_publish) || ($page_flags != $old_page_flags)) {
// Update global directory in background
@ -792,6 +787,7 @@ function settings_content(App $a)
}
if (($a->argc > 1) && ($a->argv[1] === 'connectors')) {
$disable_cw = intval(PConfig::get(local_user(), 'system', 'disable_cw'));
$no_intelligent_shortening = intval(PConfig::get(local_user(), 'system', 'no_intelligent_shortening'));
$ostatus_autofriend = intval(PConfig::get(local_user(), 'system', 'ostatus_autofriend'));
$default_group = PConfig::get(local_user(), 'ostatus', 'default_group');
@ -849,6 +845,7 @@ function settings_content(App $a)
'$ostat_enabled' => $ostat_enabled,
'$general_settings' => L10n::t('General Social Media Settings'),
'$disable_cw' => ['disable_cw', L10n::t('Disable Content Warning'), $disable_cw, L10n::t('Users on networks like Mastodon or Pleroma are able to set a content warning field which collapse their post by default. This disables the automatic collapsing and sets the content warning as the post title. Doesn\'t affect any other content filtering you eventually set up.')],
'$no_intelligent_shortening' => ['no_intelligent_shortening', L10n::t('Disable intelligent shortening'), $no_intelligent_shortening, L10n::t('Normally the system tries to find the best link to add to shortened posts. If this option is enabled then every shortened post will always point to the original friendica post.')],
'$ostatus_autofriend' => ['snautofollow', L10n::t("Automatically follow any GNU Social \x28OStatus\x29 followers/mentioners"), $ostatus_autofriend, L10n::t('If you receive a message from an unknown OStatus user, this option decides what to do. If it is checked, a new contact will be created for every unknown user.')],
'$default_group' => Group::displayGroupSelection(local_user(), $default_group, L10n::t("Default group for OStatus contacts")),
@ -1111,7 +1108,7 @@ function settings_content(App $a)
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 publishedin 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 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')]]
]);
} else {
$profile_in_net_dir = '';
@ -1274,7 +1271,7 @@ function settings_content(App $a)
'$detailed_notif' => ['detailed_notif', L10n::t('Show detailled notifications'),
PConfig::get(local_user(), 'system', 'detailed_notif'),
L10n::t('Per default the notificiation are condensed to a single notification per item. When enabled, every notification is displayed.')],
L10n::t('Per default, notifications are condensed to a single notification per item. When enabled every notification is displayed.')],
'$h_advn' => L10n::t('Advanced Account/Page Type Settings'),
'$h_descadvn' => L10n::t('Change the behaviour of this account for special situations'),

View file

@ -33,7 +33,7 @@ function unfollow_post(App $a)
if (!DBM::is_result($contact)) {
notice(L10n::t("Contact wasn't found or can't be unfollowed."));
} else {
if (in_array($contact['network'], [NETWORK_OSTATUS, NETWORK_DIASPORA])) {
if (in_array($contact['network'], [NETWORK_OSTATUS, NETWORK_DIASPORA, NETWORK_DFRN])) {
$r = q("SELECT `contact`.*, `user`.* FROM `contact` INNER JOIN `user` ON `contact`.`uid` = `user`.`uid`
WHERE `user`.`uid` = %d AND `contact`.`self` LIMIT 1",
intval($uid)
@ -75,7 +75,7 @@ function unfollow_content(App $a)
// NOTREACHED
}
if (!in_array($contact['network'], [NETWORK_DIASPORA, NETWORK_OSTATUS])) {
if (!in_array($contact['network'], [NETWORK_DIASPORA, NETWORK_OSTATUS, NETWORK_DFRN])) {
notice(L10n::t("Unfollowing is currently not supported by your network.").EOL);
$submit = "";
// NOTREACHED

21
mods/home.css Normal file
View file

@ -0,0 +1,21 @@
.homeinfocontainer {
display: grid;
grid-template-columns: 33% 33% 33%;
grid-column-gap: 15px;
padding: 10px;
}
.homeinfobox p {
text-align: justify;
}
#c1 {
grid-column-start: 1;
grid-column-end: 2;
}
#c2 {
grid-column-start: 2;
grid-column-end: 3;
}
#c3 {
grid-column-start: 3;
grid-column-end: 4;
}

23
mods/home.html Normal file
View file

@ -0,0 +1,23 @@
<!-- styling for this page is done in the home.css file //-->
<!-- Some node specifiv welcome message //-->
<p>Welcome to this <a href="https://friendi.ca">Friendica</a> node!</p>
<!-- Some general notes about Friendica, the other networks and difficulty to run //-->
<div class="homeinfocontainer">
<div id="c1" class="homeinfobox">
<h4>What is Friendica?</h4>
<p>Friendica is a decentral social network platform everybody can use to setup their own social networking node. It interacts with many other FLOSS microblogging and social networking platforms as well as some walled gardens.</p>
<p><a href="https://friendi.ca">Learn more at friendi.ca</a><br /><a href="https://dir.friendica.social/servers">Find an open Friendica node to join</a></p>
</div>
<div id="c2" class="homeinfobox">
<h4>What other networks does it interact with?</h4>
<p>Every network that speaks either the DFRN2, OStatus or diaspora* protocol. Currently this list includes: diaspora*, friendica, ganggo, GNU social, Hubzilla, Mastodon, Pleroma, postActivi and Socialhome.</p>
<p><a href="http://fediverse.party/">Learn more at fediverse.party</a></p>
</div>
<div id="c3" class="homeinfobox">
<h4>Is it hard to run Friendica?</h4>
<p>No, not at all! You need a LAMP server, most shared hosting services that offer MySQL, PHP and the ability to run cron jobs will do just fine. If you have your own (virtual) server, for a small Friendica server something like a Raspberry2B is sufficenent from the specs.</p>
<p><a href="https://github.com/friendica/friendica">Get the source</a></p>
</div>
</div>

View file

@ -2,6 +2,30 @@ sample-Lighttpd.config
sample-nginx.config
Sample configuration files to use Friendica with Lighttpd
or Nginx. Pleas check software documentation to know how modify
these examples to make them work on your server.
or Nginx. Pleas check software documentation to know how modify
these examples to make them work on your server.
sample-systemd.timer
sample-systemd.service
Sample systemd unit files to start worker.php periodically.
Please place them in the correct location for your system,
typically this is /etc/systemd/system/friendicaworker.timer
and /etc/systemd/system/friendicaworker.service.
Please report problems and improvements to
!helpers@forum.friendi.ca and @utzer@social.yl.ms or open an
issue in Github (https://github.com/friendica/friendica/issues).
This is for usage of systemd instead of cron to start the worker.php
periodically, the solution is work-in-progress and can surely be improved.
home.css
home.html
Example files to customize the landing page of your Friendica node.
The home.html file contains the text of the page, the home.css file
the style information. The login box will be added according to the
other system settings.
Both files have to be placed in the base directory of your Friendica
installation to be used for the landing page.

View file

@ -0,0 +1,9 @@
[Unit]
Description=Friendica Worker
[Service]
#User should be the same as the user the webserver runs under, typically http or www
User=http
#Adapt the path in the following line to your system, use 'which php' to find php path,
#provide the absolute path for worker.php
ExecStart=/usr/bin/php /www/path/bin/worker.php &

10
mods/sample-systemd.timer Normal file
View file

@ -0,0 +1,10 @@
[Unit]
Description=Run Friendica Poller every n minutes
[Timer]
OnBootSec=120
OnUnitActiveSec=120
RemainAfterElapse=False
[Install]
WantedBy=timers.target

8
phpunit.xml Normal file
View file

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

View file

@ -1,66 +0,0 @@
#!/usr/bin/env php
<?php
/**
* @file scripts/dbstructure.php
* @brief Does database updates from the command line
*/
use Friendica\App;
use Friendica\Core\Config;
use Friendica\Database\DBStructure;
require_once "boot.php";
require_once "include/dba.php";
$a = new App(dirname(__DIR__));
@include ".htconfig.php";
dba::connect($db_host, $db_user, $db_pass, $db_data);
unset($db_host, $db_user, $db_pass, $db_data);
if ($_SERVER["argc"] == 2) {
switch ($_SERVER["argv"][1]) {
case "dryrun":
DBStructure::update(true, false);
return;
case "update":
DBStructure::update(true, true);
$build = Config::get('system','build');
if (!x($build)) {
Config::set('system', 'build', DB_UPDATE_VERSION);
$build = DB_UPDATE_VERSION;
}
$stored = intval($build);
$current = intval(DB_UPDATE_VERSION);
// run any left update_nnnn functions in update.php
for ($x = $stored; $x < $current; $x ++) {
$r = run_update_function($x);
if (!$r) {
break;
}
}
Config::set('system','build',DB_UPDATE_VERSION);
return;
case "dumpsql":
DBStructure::printStructure();
return;
case "toinnodb":
DBStructure::convertToInnoDB();
return;
}
}
// print help
echo $_SERVER["argv"][0]." <command>\n";
echo "\n";
echo "Commands:\n";
echo "dryrun show database update schema queries without running them\n";
echo "update update database schema\n";
echo "dumpsql dump database schema\n";
echo "toinnodb convert all tables from MyISAM to InnoDB\n";
killme();

View file

@ -212,12 +212,6 @@ class App
. $this->basepath . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR
. $this->basepath);
if (is_array($_SERVER['argv']) && $_SERVER['argc'] > 1 && substr(end($_SERVER['argv']), 0, 4) == 'http') {
$this->set_baseurl(array_pop($_SERVER['argv']));
$_SERVER['argc'] --;
}
if ((x($_SERVER, 'QUERY_STRING')) && substr($_SERVER['QUERY_STRING'], 0, 9) === 'pagename=') {
$this->query_string = substr($_SERVER['QUERY_STRING'], 9);
@ -868,9 +862,6 @@ class App
array_unshift($args, ((x($this->config, 'php_path')) && (strlen($this->config['php_path'])) ? $this->config['php_path'] : 'php'));
// add baseurl to args. cli scripts can't construct it
$args[] = $this->get_baseurl();
for ($x = 0; $x < count($args); $x ++) {
$args[$x] = escapeshellarg($args[$x]);
}
@ -944,4 +935,136 @@ class App
return true;
}
/**
* @param string $cat Config category
* @param string $k Config key
* @param mixed $default Default value if it isn't set
*/
public function getConfigValue($cat, $k, $default = null)
{
$return = $default;
if ($cat === 'config') {
if (isset($this->config[$k])) {
$return = $this->config[$k];
}
} else {
if (isset($this->config[$cat][$k])) {
$return = $this->config[$cat][$k];
}
}
return $return;
}
/**
* Sets a value in the config cache. Accepts raw output from the config table
*
* @param string $cat Config category
* @param string $k Config key
* @param mixed $v Value to set
*/
public function setConfigValue($cat, $k, $v)
{
// Only arrays are serialized in database, so we have to unserialize sparingly
$value = is_string($v) && preg_match("|^a:[0-9]+:{.*}$|s", $v) ? unserialize($v) : $v;
if ($cat === 'config') {
$this->config[$k] = $value;
} else {
$this->config[$cat][$k] = $value;
}
}
/**
* Deletes a value from the config cache
*
* @param string $cat Config category
* @param string $k Config key
*/
public function deleteConfigValue($cat, $k)
{
if ($cat === 'config') {
if (isset($this->config[$k])) {
unset($this->config[$k]);
}
} else {
if (isset($this->config[$cat][$k])) {
unset($this->config[$cat][$k]);
}
}
}
/**
* Retrieves a value from the user config cache
*
* @param int $uid User Id
* @param string $cat Config category
* @param string $k Config key
* @param mixed $default Default value if key isn't set
*/
public function getPConfigValue($uid, $cat, $k, $default = null)
{
$return = $default;
if (isset($this->config[$uid][$cat][$k])) {
$return = $this->config[$uid][$cat][$k];
}
return $return;
}
/**
* Sets a value in the user config cache
*
* Accepts raw output from the pconfig table
*
* @param int $uid User Id
* @param string $cat Config category
* @param string $k Config key
* @param mixed $v Value to set
*/
public function setPConfigValue($uid, $cat, $k, $v)
{
// Only arrays are serialized in database, so we have to unserialize sparingly
$value = is_string($v) && preg_match("|^a:[0-9]+:{.*}$|s", $v) ? unserialize($v) : $v;
$this->config[$uid][$cat][$k] = $value;
}
/**
* Deletes a value from the user config cache
*
* @param int $uid User Id
* @param string $cat Config category
* @param string $k Config key
*/
public function deletePConfigValue($uid, $cat, $k)
{
if (isset($this->config[$uid][$cat][$k])) {
unset($this->config[$uid][$cat][$k]);
}
}
/**
* Generates the site's default sender email address
*
* @return string
*/
public function getSenderEmailAddress()
{
$sender_email = Config::get('config', 'sender_email');
if (empty($sender_email)) {
$hostname = $this->get_hostname();
if (strpos($hostname, ':')) {
$hostname = substr($hostname, 0, strpos($hostname, ':'));
}
$sender_email = 'noreply@' . $hostname;
}
return $sender_email;
}
}

View file

@ -6,6 +6,9 @@ namespace Friendica;
* All modules in Friendica should extend BaseModule, although not all modules
* need to extend all the methods described here
*
* The filename of the module in src/Module needs to match the class name
* exactly to make the module available.
*
* @author Hypolite Petovan mrpetovan@gmail.com
*/
abstract class BaseModule extends BaseObject

View file

@ -27,7 +27,7 @@ class ContactSelector
$o .= "<select id=\"contact-profile-selector\" class=\"form-control\" $disabled name=\"profile-assign\" >\r\n";
$s = dba::select('profile', ['id', 'profile-name', 'is-default'], ['uid' => $$_SESSION['uid']]);
$s = dba::select('profile', ['id', 'profile-name', 'is-default'], ['uid' => $_SESSION['uid']]);
$r = dba::inArray($s);
if (DBM::is_result($r)) {
@ -123,9 +123,9 @@ class ContactSelector
{
$o = '';
$select = ['', L10n::t('Male'), L10n::t('Female'), L10n::t('Currently Male'), L10n::t('Currently Female'), L10n::t('Mostly Male'), L10n::t('Mostly Female'), L10n::t('Transgender'), L10n::t('Intersex'), L10n::t('Transsexual'), L10n::t('Hermaphrodite'), L10n::t('Neuter'), L10n::t('Non-specific'), L10n::t('Other'), L10n::t('Undecided')];
Addon::callHooks('gender_selector', $select);
$o .= "<select name=\"gender$suffix\" id=\"gender-select$suffix\" size=\"1\" >";
foreach ($select as $selection) {
if ($selection !== 'NOTRANSLATION') {
@ -136,7 +136,7 @@ class ContactSelector
$o .= '</select>';
return $o;
}
/**
* @param string $current optional, default empty
* @param string $suffix optionsl, default empty
@ -145,10 +145,10 @@ class ContactSelector
{
$o = '';
$select = ['', L10n::t('Males'), L10n::t('Females'), L10n::t('Gay'), L10n::t('Lesbian'), L10n::t('No Preference'), L10n::t('Bisexual'), L10n::t('Autosexual'), L10n::t('Abstinent'), L10n::t('Virgin'), L10n::t('Deviant'), L10n::t('Fetish'), L10n::t('Oodles'), L10n::t('Nonsexual')];
Addon::callHooks('sexpref_selector', $select);
$o .= "<select name=\"sexual$suffix\" id=\"sexual-select$suffix\" size=\"1\" >";
foreach ($select as $selection) {
if ($selection !== 'NOTRANSLATION') {
@ -159,7 +159,7 @@ class ContactSelector
$o .= '</select>';
return $o;
}
/**
* @param string $current optional, default empty
*/
@ -167,9 +167,9 @@ class ContactSelector
{
$o = '';
$select = ['', L10n::t('Single'), L10n::t('Lonely'), L10n::t('Available'), L10n::t('Unavailable'), L10n::t('Has crush'), L10n::t('Infatuated'), L10n::t('Dating'), L10n::t('Unfaithful'), L10n::t('Sex Addict'), L10n::t('Friends'), L10n::t('Friends/Benefits'), L10n::t('Casual'), L10n::t('Engaged'), L10n::t('Married'), L10n::t('Imaginarily married'), L10n::t('Partners'), L10n::t('Cohabiting'), L10n::t('Common law'), L10n::t('Happy'), L10n::t('Not looking'), L10n::t('Swinger'), L10n::t('Betrayed'), L10n::t('Separated'), L10n::t('Unstable'), L10n::t('Divorced'), L10n::t('Imaginarily divorced'), L10n::t('Widowed'), L10n::t('Uncertain'), L10n::t('It\'s complicated'), L10n::t('Don\'t care'), L10n::t('Ask me')];
Addon::callHooks('marital_selector', $select);
$o .= '<select name="marital" id="marital-select" size="1" >';
foreach ($select as $selection) {
if ($selection !== 'NOTRANSLATION') {

View file

@ -7,7 +7,7 @@
namespace Friendica\Content\Text;
use DOMDocument;
use DomXPath;
use DOMXPath;
use Exception;
use Friendica\BaseObject;
use Friendica\Content\OEmbed;
@ -20,6 +20,7 @@ use Friendica\Core\PConfig;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Model\Contact;
use Friendica\Model\Event;
use Friendica\Network\Probe;
use Friendica\Object\Image;
use Friendica\Util\Map;
@ -27,8 +28,6 @@ use Friendica\Util\Network;
use Friendica\Util\ParseUrl;
use League\HTMLToMarkdown\HtmlConverter;
require_once "include/event.php";
require_once "include/html2plain.php";
require_once "mod/proxy.php";
class BBCode extends BaseObject
@ -77,10 +76,12 @@ class BBCode extends BaseObject
$picturedata = Image::getInfoFromURL($matches[1]);
if (($picturedata[0] >= 500) && ($picturedata[0] >= $picturedata[1])) {
$post["image"] = $matches[1];
} else {
$post["preview"] = $matches[1];
if ($picturedata) {
if (($picturedata[0] >= 500) && ($picturedata[0] >= $picturedata[1])) {
$post["image"] = $matches[1];
} else {
$post["preview"] = $matches[1];
}
}
}
@ -242,6 +243,9 @@ class BBCode extends BaseObject
$body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $body);
$URLSearchString = "^\[\]";
$body = preg_replace("/\[img\=([$URLSearchString]*)\](.*?)\[\/img\]/ism", '[img]$1[/img]', $body);
if (preg_match_all("(\[url=([$URLSearchString]*)\]\s*\[img\]([$URLSearchString]*)\[\/img\]\s*\[\/url\])ism", $body, $pictures, PREG_SET_ORDER)) {
if ((count($pictures) == 1) && !$has_title) {
// Checking, if the link goes to a picture
@ -267,7 +271,7 @@ class BBCode extends BaseObject
$post["text"] = str_replace($pictures[0][0], "", $body);
} else {
$imgdata = Image::getInfoFromURL($pictures[0][1]);
if (substr($imgdata["mime"], 0, 6) == "image/") {
if ($imgdata && substr($imgdata["mime"], 0, 6) == "image/") {
$post["type"] = "photo";
$post["image"] = $pictures[0][1];
$post["preview"] = $pictures[0][2];
@ -413,7 +417,7 @@ class BBCode extends BaseObject
}
$html = self::convert($post["text"].$post["after"], false, $htmlmode);
$msg = html2plain($html, 0, true);
$msg = HTML::toPlaintext($html, 0, true);
$msg = trim(html_entity_decode($msg, ENT_QUOTES, 'UTF-8'));
$link = "";
@ -681,7 +685,7 @@ class BBCode extends BaseObject
$return = '';
if ($simplehtml == 7) {
$return = self::convertUrlForMastodon($data["url"]);
$return = self::convertUrlForOStatus($data["url"]);
} elseif (($simplehtml != 4) && ($simplehtml != 0)) {
$return = sprintf('<a href="%s" target="_blank">%s</a><br>', $data["url"], $data["title"]);
} else {
@ -709,9 +713,10 @@ class BBCode extends BaseObject
}
if ($data["description"] != "" && $data["description"] != $data["title"]) {
$return .= sprintf('<blockquote>%s</blockquote>', trim(self::convert($data["description"])));
// Sanitize the HTML by converting it to BBCode
$bbcode = HTML::toBBCode($data["description"]);
$return .= sprintf('<blockquote>%s</blockquote>', trim(self::convert($bbcode)));
}
if ($data["type"] == "link") {
$return .= sprintf('<sup><a href="%s">%s</a></sup>', $data['url'], parse_url($data['url'], PHP_URL_HOST));
}
@ -758,33 +763,12 @@ class BBCode extends BaseObject
if (($data["url"] != "") && ($data["title"] != "")) {
$text .= "\n[url=" . $data["url"] . "]" . $data["title"] . "[/url]";
} elseif (($data["url"] != "")) {
$text .= "\n" . $data["url"];
$text .= "\n[url]" . $data["url"] . "[/url]";
}
return $text . "\n" . $data["after"];
}
private static function cleanCss($input)
{
$cleaned = "";
$input = strtolower($input);
for ($i = 0; $i < strlen($input); $i++) {
$char = substr($input, $i, 1);
if (($char >= "a") && ($char <= "z")) {
$cleaned .= $char;
}
if (!(strpos(" #;:0123456789-_.%", $char) === false)) {
$cleaned .= $char;
}
}
return $cleaned;
}
/**
* Converts [url] BBCodes in a format that looks fine on Mastodon. (callback function)
*
@ -792,7 +776,7 @@ class BBCode extends BaseObject
* @param array $match Array with the matching values
* @return string reformatted link including HTML codes
*/
private static function convertUrlForMastodonCallback($match)
private static function convertUrlForOStatusCallback($match)
{
$url = $match[1];
@ -805,34 +789,27 @@ class BBCode extends BaseObject
return $match[0];
}
return self::convertUrlForMastodon($url);
return self::convertUrlForOStatus($url);
}
/**
* @brief Converts [url] BBCodes in a format that looks fine on Mastodon and GNU Social.
* @brief Converts [url] BBCodes in a format that looks fine on OStatus systems.
* @param string $url URL that is about to be reformatted
* @return string reformatted link including HTML codes
*/
private static function convertUrlForMastodon($url)
private static function convertUrlForOStatus($url)
{
$parts = parse_url($url);
$scheme = $parts['scheme'] . '://';
$styled_url = str_replace($scheme, '', $url);
$html = '<a href="%s" class="attachment" rel="nofollow noopener" target="_blank">' .
'<span class="invisible">%s</span>';
if (strlen($styled_url) > 30) {
$html .= '<span class="ellipsis">%s</span>' .
'<span class="invisible">%s</span></a>';
$ellipsis = substr($styled_url, 0, 30);
$rest = substr($styled_url, 30);
return sprintf($html, $url, $scheme, $ellipsis, $rest);
} else {
$html .= '%s</a>';
return sprintf($html, $url, $scheme, $styled_url);
$styled_url = substr($styled_url, 0, 30) . "";
}
$html = '<a href="%s" target="_blank">%s</a>';
return sprintf($html, $url, $styled_url);
}
/*
@ -1127,13 +1104,13 @@ class BBCode extends BaseObject
}
if (stripos(normalise_link($link), 'http://twitter.com/') === 0) {
$text .= '<br /><a href="' . $link . '">' . $link . '</a>';
} else {
$text .= $headline . '<blockquote>' . trim($share[3]) . "</blockquote><br />";
if ($link != "") {
$text .= '<br /><a href="' . $link . '">[l]</a>';
}
} else {
$text .= '<br /><a href="' . $link . '">' . $link . '</a>';
}
break;
@ -1229,7 +1206,7 @@ class BBCode extends BaseObject
$doc = new DOMDocument();
@$doc->loadHTML($body);
$xpath = new DomXPath($doc);
$xpath = new DOMXPath($doc);
$list = $xpath->query("//meta[@name]");
foreach ($list as $node) {
$attr = [];
@ -1318,13 +1295,17 @@ class BBCode extends BaseObject
private static function textHighlightCallback($match)
{
// Fallback in case the language doesn't exist
$return = '[code]' . $match[2] . '[/code]';
if (in_array(strtolower($match[1]),
['php', 'css', 'mysql', 'sql', 'abap', 'diff', 'html', 'perl', 'ruby',
'vbscript', 'avrc', 'dtd', 'java', 'xml', 'cpp', 'python', 'javascript', 'js', 'sh'])
'vbscript', 'avrc', 'dtd', 'java', 'xml', 'cpp', 'python', 'javascript', 'js', 'sh', 'bash'])
) {
return text_highlight($match[2], strtolower($match[1]));
$return = text_highlight($match[2], strtolower($match[1]));
}
return $match[0];
return $return;
}
/**
@ -1401,7 +1382,7 @@ class BBCode extends BaseObject
// After we're finished processing the bbcode we'll
// replace all of the event code with a reformatted version.
$ev = bbtoevent($text);
$ev = Event::fromBBCode($text);
// Replace any html brackets with HTML Entities to prevent executing HTML or script
// Don't use strip_tags here because it breaks [url] search by replacing & with amp
@ -1461,8 +1442,8 @@ class BBCode extends BaseObject
$autolink_regex = "/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism";
$text = preg_replace($autolink_regex, '$1[url]$2[/url]', $text);
if ($simple_html == 7) {
$text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism", 'self::convertUrlForMastodonCallback', $text);
$text = preg_replace_callback("/\[url\=([$URLSearchString]*)\]([$URLSearchString]*)\[\/url\]/ism", 'self::convertUrlForMastodonCallback', $text);
$text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism", 'self::convertUrlForOStatusCallback', $text);
$text = preg_replace_callback("/\[url\=([$URLSearchString]*)\]([$URLSearchString]*)\[\/url\]/ism", 'self::convertUrlForOStatusCallback', $text);
}
} else {
$text = preg_replace("(\[url\]([$URLSearchString]*)\[\/url\])ism", " $1 ", $text);
@ -1562,10 +1543,8 @@ class BBCode extends BaseObject
if (strpos($text, '[/map]') !== false) {
$text = preg_replace_callback(
"/\[map\](.*?)\[\/map\]/ism",
function ($match) {
// the extra space in the following line is intentional
// Whyyy? - @MrPetovan
return str_replace($match[0], '<div class="map" >' . Map::byLocation($match[1]) . '</div>', $match[0]);
function ($match) use ($simple_html) {
return str_replace($match[0], '<p class="map">' . Map::byLocation($match[1], $simple_html) . '</p>', $match[0]);
},
$text
);
@ -1573,16 +1552,14 @@ class BBCode extends BaseObject
if (strpos($text, '[map=') !== false) {
$text = preg_replace_callback(
"/\[map=(.*?)\]/ism",
function ($match) {
// the extra space in the following line is intentional
// Whyyy? - @MrPetovan
return str_replace($match[0], '<div class="map" >' . Map::byCoordinates(str_replace('/', ' ', $match[1])) . '</div>', $match[0]);
function ($match) use ($simple_html) {
return str_replace($match[0], '<p class="map">' . Map::byCoordinates(str_replace('/', ' ', $match[1]), $simple_html) . '</p>', $match[0]);
},
$text
);
}
if (strpos($text, '[map]') !== false) {
$text = preg_replace("/\[map\]/", '<div class="map"></div>', $text);
$text = preg_replace("/\[map\]/", '<p class="map"></p>', $text);
}
// Check for headers
@ -1606,7 +1583,7 @@ class BBCode extends BaseObject
$text = preg_replace("(\[u\](.*?)\[\/u\])ism", '<u>$1</u>', $text);
// Check for strike-through text
$text = preg_replace("(\[s\](.*?)\[\/s\])ism", '<strike>$1</strike>', $text);
$text = preg_replace("(\[s\](.*?)\[\/s\])ism", '<s>$1</s>', $text);
// Check for over-line text
$text = preg_replace("(\[o\](.*?)\[\/o\])ism", '<span class="overline">$1</span>', $text);
@ -1629,7 +1606,7 @@ class BBCode extends BaseObject
$text = preg_replace_callback(
"(\[style=(.*?)\](.*?)\[\/style\])ism",
function ($match) {
return "<span style=\"" . self::cleanCss($match[1]) . ";\">" . $match[2] . "</span>";
return "<span style=\"" . HTML::sanitizeCSS($match[1]) . ";\">" . $match[2] . "</span>";
},
$text
);
@ -1638,7 +1615,7 @@ class BBCode extends BaseObject
$text = preg_replace_callback(
"(\[class=(.*?)\](.*?)\[\/class\])ism",
function ($match) {
return "<span class=\"" . self::cleanCss($match[1]) . "\">" . $match[2] . "</span>";
return "<span class=\"" . HTML::sanitizeCSS($match[1]) . "\">" . $match[2] . "</span>";
},
$text
);
@ -1747,6 +1724,14 @@ class BBCode extends BaseObject
$text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '<img src="$3" style="width: $1px;" >', $text);
$text = preg_replace("/\[zmg\=([0-9]*)x([0-9]*)\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$3" style="width: $1px;" >', $text);
$text = preg_replace_callback("/\[img\=([$URLSearchString]*)\](.*?)\[\/img\]/ism",
function ($matches) {
$matches[1] = proxy_url($matches[1]);
$matches[2] = htmlspecialchars($matches[2], ENT_COMPAT);
return '<img src="' . $matches[1] . '" alt="' . $matches[2] . '">';
},
$text);
// Images
// [img]pathtoimage[/img]
$text = preg_replace_callback(
@ -1843,7 +1828,7 @@ class BBCode extends BaseObject
// start which is always required). Allow desc with a missing summary for compatibility.
if ((x($ev, 'desc') || x($ev, 'summary')) && x($ev, 'start')) {
$sub = format_event_html($ev, $simple_html);
$sub = Event::getHTML($ev, $simple_html);
$text = preg_replace("/\[event\-summary\](.*?)\[\/event\-summary\]/ism", '', $text);
$text = preg_replace("/\[event\-description\](.*?)\[\/event\-description\]/ism", '', $text);
@ -1878,10 +1863,12 @@ class BBCode extends BaseObject
$text = preg_replace_callback("/\[nobb\](.*?)\[\/nobb\]/ism", 'self::unescapeNoparseCallback', $text);
$text = preg_replace_callback("/\[pre\](.*?)\[\/pre\]/ism", 'self::unescapeNoparseCallback', $text);
/// @todo What is the meaning of these lines?
$text = preg_replace('/\[\&amp\;([#a-z0-9]+)\;\]/', '&$1;', $text);
$text = preg_replace('/\&\#039\;/', '\'', $text);
$text = preg_replace('/\&quot\;/', '"', $text);
// Currently deactivated, it made problems with " inside of alt texts.
//$text = preg_replace('/\&quot\;/', '"', $text);
// fix any escaped ampersands that may have been converted into links
$text = preg_replace('/\<([^>]*?)(src|href)=(.*?)\&amp\;(.*?)\>/ism', '<$1$2=$3&$4>', $text);

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