Merge pull request #1 from friendica/develop

Mega update to today
This commit is contained in:
realkinetix 2020-08-17 14:26:27 -07:00 committed by GitHub
commit aa0b485f3d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1395 changed files with 251756 additions and 188255 deletions

View file

@ -1,36 +1,14 @@
codecov:
branch: develop
comment: off
ci:
- drone.friendi.ca
coverage:
precision: 2
round: down
range: "70...100"
status:
patch:
default: off
source:
target: 80%
flags: source
backend:
target: 80%
flags: backend
project:
default: off
source:
flags: source
backend:
flags: backend
project: off
patch: off
flags:
source:
paths:
- src/
backend:
paths:
- mod/
- include/
binary:
paths:
- bin/
tests:
paths:
- tests/
comment: off

11
.gitignore vendored
View file

@ -1,12 +1,11 @@
favicon.*
.htconfig.php
.htpreconfig.php
/.htconfig.php
/.htpreconfig.php
\#*
*.log
*.out
*.version*
home.html
*~
robots.txt
@ -34,6 +33,9 @@ report/
#ignore NetBeans IDE's private files (at least)
/nbproject/private/
Ignore config files from VSCode
/.vscode/
#ignore smarty cache
/view/smarty3/compiled/
@ -74,3 +76,6 @@ venv/
#ignore filesystem storage default path
/storage
#Ignore log folder
/log

View file

@ -8,10 +8,10 @@ php:
services:
- mysql
- redis-server
- redis
- memcached
env:
- MYSQL_HOST=localhost MYSQL_PORT=3306 MYSQL_USERNAME=travis MYSQL_PASSWORD= MYSQL_DATABASE=test
- MYSQL_HOST=localhost MYSQL_PORT=3306 MYSQL_USERNAME=travis MYSQL_PASSWORD="" MYSQL_DATABASE=test
install:
- composer install
@ -19,6 +19,13 @@ before_script:
- cp config/local-sample.config.php config/local.config.php
- mysql -e 'CREATE DATABASE IF NOT EXISTS test;'
- mysql -utravis test < database.sql
- echo "extension=redis.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- echo "extension=memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini
- pecl channel-update pecl.php.net
- pecl config-set preferred_state beta
- phpenv config-add .travis/redis.ini
- phpenv config-add .travis/memcached.ini
script:
- vendor/bin/parallel-lint --exclude vendor/ --exclude view/asset/ .
- vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-clover clover.xml
after_success: bash <(curl -s https://codecov.io/bash)

4
.travis/apcu.ini Normal file
View file

@ -0,0 +1,4 @@
extension="apcu.so"
apc.enabled = 1
apc.enable_cli = 1

1
.travis/memcached.ini Normal file
View file

@ -0,0 +1 @@
extension="memcached.so"

1
.travis/redis.ini Normal file
View file

@ -0,0 +1 @@
extension="redis.so"

454
CHANGELOG
View file

@ -1,3 +1,453 @@
Version 2020.09 (unreleased)
Version 2020.07 (2020-07-12)
Friendica Core:
Update to the translations: DE, EN GB, EN US, FR, ET, NL, PL, RU, ZH-CN [translation teams]
Updates to the themes (frio, vier) [MrPetovan]
Updated the shipped composer version, and the dependency list [annando, MrPetovan, tobiasd]
Updates to the documentation [MrPetovan]
General code refactoring and enhancements [AlfredSK, annando, MrPetovan]
Replace charged terms with "allowlist", "denylist" and "blocklist" [MrPetovan]
Enhanced the comment distribution in threads that involve diaspora*, AP and DFRN actors [annando]
Enhanced the profile probing mechanism [annando, MrPetovan]
Enhanced the post update process of the database [annando]
Enhanced the database performance [annando]
Enhanced ActivityPub attachment handling [MrPetovan]
Enhanced security of redirections [annando]
Enhanced database performance [annando]
Enhanced the handling of BBCode [pre] tags [MrPetovan]
Enhanced Markdown to BBCode conversion [MrPetovan]
Enhanced the speed of the network page [annando]
Fixed a problem recognising logins via the API [MrPetovan]
Fixed a problem with handling local diaspora* URLs [MrPetovan]
Fixed a problem with implicit mentions [annando]
Fixed a problem with the password reset token security [lynn-stephenson]
Fixed a problem with receiving non-public posts via ActivityPub [annando]
Fixed a problem with the photo endpoint of the API [MrPetovan]
Fixed a problem with pressing the ESC key in the frio-theme [MrPetovan]
Fixed a problem with the display if post categories [annando]
Fixed a problem with validation of feeds [annando]
Fixed a problem that prevented AP activities being fetched sometimes [annando]
Renamed the -q option of the console user delete command to -y [MrPetovan]
Added notification count to page title [MrPetovan]
Added handling of relative URLs during feed detection [MrPetovan]
Added entities [nupplaphil]
Friendica Addons:
Update to the translations (EN GB, NB NO, NL, PL, RU, ZH CN) [translation teams]
blockbot:
The list of accepted user agents was enhanced [annando]
Diaspora*:
Enhanced conntector settings [MrPetovan]
PHP Mailer SMTP:
Updated phpmailer version [dependabot]
showmore_dyn:
New addon to collapse long post depending on their actual height [wiwie]
twitter:
Enhaceed the handling of mobile twitter URLs [annando]
Enhanced the handling of quoted tweets [MrPetovan]
added HTML error code handling [MrPetovan]
various:
enhancements to the probe mechanism [MrPetovan]
Closed Issues:
3084, 3884, 8287, 8314, 8374, 8400, 8425, 8432, 8458, 8470, 8477,
8482, 8488, 8489, 8490, 8493, 8495, 8498, 8511, 8517, 8523, 8527,
8551, 8553, 8560, 8564, 8565, 8568, 8578, 8586, 8593, 8606, 8610,
8612, 8626, 8664, 8672, 8683, 8685, 8691, 8694, 8702, 8709, 8714,
8717, 8722, 8726, 8732, 8736, 8743, 8744, 8746, 8756, 8766, 8769,
8781, 8800, 8807, 8808, 8827, 8829, 8836, 8844, 8846, 8857, 8866
Version 2020.03 "Red Hot Poker" (2020-03-30)
Friendica Core:
Updates to the translations (DE, FR, JA, NL, PL, RU, ZH-CN) [translation teams]
Updates to the documentation [AlfredSK, annando, MrPetovan]
Updates to the themes (all) [AlfredSK, annando, MrPetovan, ozero]
General code refactoring and enhancements [annando, MrPetovan, nupplaphil, tobiasd]
Enhanced the performance in several background tasks [annando]
Enhanced the display of contact relations (Twitter) [annando]
Enhanced the permission selection for uploaded photos [annando]
Enhanced the access control during composing a posting [MrPetovan]
Enhanced the accessibility [annando, MrPetovan]
Enhanced the delegation process [annando]
Enhanced the contact management links [annando]
Enhanced the pagination on the community page [MrPetovan]
Enhanced the remote following page [annando]
Enhanced the generated node statistics [AlfredSK]
Enhanced the federation statistics page in the admin panel [annando]
Enhanced the probing mechanism [annando]
Enhanced the federation with Zot [annando]
Enhanced the permission selections for events [MrPetovan]
Enhanced the logging format of the date-time entries [MrPetovan]
Fixed a problem with the uninstalling of addons [annando]
Fixed a problem with the XML escaping in postings [MrPetovan]
Fixed a problem with the Markdown parser [MrPetovan]
Fixed AP federation problems with GNU social [annando]
Fixed AP federation problems with Peertube [annando]
Fixed a problem with the update process of the database [annando]
Fixed problems in the generation of notification emails [nupplaphil]
Fixed a problem with automatic contact approvals [annando]
Fixed a problem with following items [annando]
Fixed the redirection in the photo album after actions there [MrPetovan]
Fixed redirection from notifications for non logged in users [nupplaphil]
Fixed a problem with image permissions in comments [annando]
Fixed a problem leading to random deletion of postings [MrPetovan, SpcCw]
Fixed a problem while transmitting XML in CODE blocks [annando]
All target _blank links now have the rel no-opener no-referrer [MrPetovan]
The "more action" menu in Frio was moved to the action buttons [annando]
Replacement of the "hide_wall" option with more clear options [annando]
Replaced most of all fixed profile field with free form profile fields [MrPetovan]
Removed the "compose on new page" option in Frio [MrPetovan]
Removed multiple profiles in favour of custom profile fields [MrPetovan]
Added an option to hide the dislike reaction [MrPetovan]
Added user group filter to contact listings [MrPetovan]
Added folding to the widgets in the side bar [annando]
Added user management functionality to the Friendica console [nupplaphil]
Added api/friendica/events endpoint to the API [MrPetovan]
Added api/friendica/events endpoint to the API [MrPetovan]
Added custom profile fields [MrPetovan]
Added AP type audio for the federation with Funkwhale [annando]
Friendica Addons:
Update to the translations (CS, DE, FR, PL, RU, ZH-CN) [translation teams]
General code refactoring and enhancements [AndyHee, annando, MrPetovan, nupplaphil]
blockbot:
Ensure that good agents are allowlisted [valvin1]
markdown:
Addon to use Markdown while composing a posting was added [annando]
showmore:
Functionality is ignored by screen readers [annando]
twitter:
Added fetching of contact relations [annando]
unicode emoticons:
Extended the list of supported emoticons [loma-one]
Closed Issues:
4599, 5562, 6205, 6418, 6757, 7558, 7560, 7771, 7808, 7817, 7892,
7964, 7968, 7978, 7984, 7991, 7992, 7994, 8002, 8008, 8014, 8058,
8067, 8081, 8084, 8087, 8090, 8097, 8098, 8103, 8136, 8151, 8153,
8157, 8160, 8164, 8165, 8167, 8172, 8173, 8181, 8182, 8185, 8187,
8193, 8197, 8205, 8206, 8216, 8219, 8229, 8233, 8234, 8238, 8245,
8248, 8251, 8252, 8254, 8255, 8264, 8268, 8275, 8280, 8286, 8288,
8289, 8290, 8299, 8303, 8305, 8310, 8318, 8321, 8338, 8339, 8341,
8342, 8358, 8371, 8383, 8393, 8396, 8404, 8412, 8417, 8449, 8467
Version 2019.12 (2019-12-23)
Friendica Core:
Updates to the translations (CS, DE, ET, JA, NL, PL) [translation teams]
Updates to the documentation [copiis, MrPetovan, stom79, tobiasd]
Updates to the themes (all) [annando, hoergen, MrPetovan, tobiasd]
General code refactoring and enhancements [annando, MrPetovan, nupplaphil, tobiasd]
Enhanced the manage functionality [annando]
Enhanced the federation with ActivityPub and Diaspora* protocol detection and contact requests [annando]
Enhanced federation with pixelfed and peertube [annando]
Enhanced how the API handles quoted postings [annando]
Enhanced the attachment removal by the API [annando]
Enhanced the 2FA field for mobile devices [nupplaphil]
Enhanced handling of re-shares [annando]
Enhanced the ACL dialog [annando, MrPetovan]
Enhanced transmission of postings by email and email handling in general [annando]
Enhanced the updating process of contacts [annando]
Enhanced the import of RSS/Atom feeds [annando]
Enhanced the registration form for require approval setups [tobiasd]
Enhanced the follow process for the Diaspora* protocol [annando]
Enhanced the display of the saved searched [AlfredSK]
Enhanced the display of image titles [annando]
Enhanced the handling of OpenID [annando]
Enhanced the Vagrant devel VM [tobiasd]
Enhanced handling of HTML special entities [nathilia-peirce]
Enhanced hashes by using HMAC [nathilia-peirce]
Enhancements to the ActivityPub implementation [annando]
Fixed a problem with delivery of direct messages over ActivityPub [annando]
Fixed some problems with the remote auth functionality [annando]
Fixed an issue that prevented notifications for deleted postings be deleted themselves [annando]
Fixed a problem connecting to forums [annando]
Fixed messages in the admin panel [nupplaphil]
Fixed a problem when the log-file was not write-able [nupplaphil]
Fixed a problem with the caching directory for the password exposure check [MrPetovan]
Fixed a bug with detecting the browser language [nupplaphil]
Smart threading is now the default, but can be switched off by the user [annando]
Clarification: Posted order is now arrival order [annando]
Added router configuration file [nupplaphil]
Added drone.io as CI service [nupplaphil]
Added the ability to pin postings on account walls [annando]
Added various new API endpoints [annando, MrPetovan]
Added hooks for the email fetching process [annando]
Added support for nodeinfo 2 [annando]
Added export and import of followed contact data [tobiasd]
Added links to tag and category overview in the footer of postings [tobiasd]
Added config switch to use BCC instead of CC for ActivityPub delivery of non-public postings [annando]
Friendica Addons:
Update to the translations (CA, DE, ET) [translation teams]
buffer
marked as unsupported [annando]
Discourse
New addon to integrate Discourse discussions [annando]
gnot
UI improvements [tobiasd]
js_upload
The addon got rewritten to adopt the new ACL [MrPetovan]
mailstream:
Support for new img format was added [mexon]
BB Code is now included as plaintext [mexon]
Logging format is enhanced [mexon]
ActivityPub "announce" notifications are not included [mexon]
Closed Issues:
989, 1071, 1188, 1334, 2537, 3229, 3231, 3385, 4112, 4442, 4451,
5048, 5568, 5802, 6865, 7190, 7308, 7316, 7418, 7613, 7657, 7659,
7664, 7671, 7679, 7681, 7682, 7685, 7688, 7691, 7702, 7707, 7709,
7718, 7733, 7740, 7747, 7756, 7766, 7773, 7776, 7778, 7781, 7821,
7825, 7834, 7863, 7868, 7880, 7888, 7889, 7902, 7914, 7920, 7946,
7953, 7978
Version 2019.09 (2019-09-29)
Friendica Core:
Update to the translations (CS, DE, EN GB, EN US, FR, JA, NL, PL) [translation teams]
Update to the themes (frio, vier) [JeroenED, MrPetovan, tobiasd, vinzv]
Update to the documentation [annando, tobiasd, guzzisti, vinzv]
Enhanced the log output of the background process [annando]
Enhanced the vcard translation in the profile [JeroenED]
Enhanced the delivery count [annando]
Enhanced ActivityPub envelopes [MrPetovan]
Enhanced communication about deleted accounts via AP [annando]
Enhanced the following process [annando]
Enhanced the tests [nupplaphil]
Enhanced the front-end worker [annando]
Enhanced the img format to allow alternative texts [annando]
Enhanced the detection of supported protocols for contacts [annando]
Enhanced the re-share of items [annando]
Enhanced 2FA process [MrPetovan]
Enhanced server wide theme settings [MrPetovan]
Enhanced config loading process [MrPetovan, nupplaphil]
Enhanced handling of emoticons [MrPetovan]
Enhanced performance [annando]
Fixed a bug in the admin panel leading to orphaned options [tobiasd]
Fixed a problem that could lead to duplicated Pleroma contacts [annando]
Fixed a problem with the hide profile setting [annando]
Fixed the problem sending out the post when hitting the enter key in the ACL dialog [MrPetovan]
Fixed a bug in HTML special character escaping of event titles [MrPetovan]
Fixed a bug in HTML special character conversion in item titles [MrPetovan]
Fixed a bug in the auto linker for URLs [MrPetovan]
Fixed a bug that prevented the display of images in some postings from diaspora* [MrPetovan]
Fixed a bug in setting the permissions on uploaded images [annando]
Fixed a bug that lead to potentially unwanted importing threads started by contacts of contacts [annando]
Fixed implicit self mentions [MrPetovan]
Fixed display of register links on closed nodes landing pages [MrPetovan]
Fixed the display of [spoiler] tags [MrPetovan]
Fixed an issue with photo permissions in private mails [annando]
Fixed a bug in the process of following Pleroma accounts [annando]
Fixed a bug that caused notifications about locally deleted items [annando]
Fixed the link to the source of an event [MrPetovan]
Fixed a problem that caused authors from twitter postings having no profile pic [annando]
Fixed a bug in BBCode -> Markdown conversation for font size [annando]
Fixed a BBCode parser problem with the audio tag [MrPetovan]
Fixed a session problem [annando]
Fixed a problem with the auto-installer [nupplaphil]
Fixed a bug with magic links redirection for non profiles [annando]
General code cleaning [annando, MrPetovan, nupplaphil]
Removed contacts auto completion (in /contacts [MrPetovan]
Replaced FontAwesome by ForkAwesome in frio theme [vinzv]
Added new compose page for the frio theme [MrPetovan]
Added new console command: lock [nupplaphil]
Added new additional feature to show trending tags on community page [MrPetovan]
Added support of image descriptions [annando]
Added support of wildcards to server block lists [MrPetovan]
Added app specific passwords when using 2FA [MrPetovan]
Added fetching of postings via URL to interact with public postings [annando]
Added opt-out flag for federated search engines and associated header information for profiles [annando]
Friendica Addons:
Update to the translation (CS, DE, EN GB, EN US, ES, FR, JA, NL SV) [translation teams]
General code cleanup [nupplaphil, Quix0r]
blockbot:
Added translations
Added more bots [annando]
Added admin panel settings [annando]
tumblr:
Changed used URLs to https adopting tumblrs change [annando]
twitter:
Enhanced handling of multi image postings [annando]
Enhanced display of quoted tweets [MrPetovan]
Added alternative text support for images [annando]
Closed Issues:
870, 1605, 2199, 3239, 3816, 4117, 4815, 5721, 6384, 6521, 6553,
6675, 7212, 7235, 7285, 7293, 7314, 7317, 7337, 7338, 7346, 7350,
7367, 7383, 7396, 7397, 7401, 7406, 7408, 7426, 7428, 7456, 7442,
7457, 7468, 7471, 7473, 7488, 7497, 7498, 7501, 7507, 7521, 7526,
7527, 7536, 7542, 7545, 7576, 7586, 7594, 7597, 7603, 7610, 7618,
7629, 7635, 7638, 7663, 7665, 7672
Version 2019.06 (2019-06-23)
Friendica Core:
Update to the tranlation (CS, DE, EN-GB, EN-US, ET, FR, IT, PL, PT-BR, SV) [translation teams]
Update to the documentation [nupplaphil, realkinetix, MrPetovan]
Update to the themes (frio, vier) [BinkaDroid, MrPetovan, tobiasd]
Enhancements to the API [annando, MrPetovan]
Enhancements to the way reshares are handled [annando]
Enhancements to the redis configuration [nupplaphil]
Enhancements to the federation stats display in the admin panel [tobiasd]
Enhancements to the processing of changed storage engine [MrPetovan]
Enhancements to ActivityPub support [annando, MrPetovan]
Enhancements to code security [MrPetovan]
Enhancements to delivery counter [annando]
Fixed the notification order [JeroenED]
Fixed the timezone of Friendica logs [nupplaphil]
Fixed tag completion painfully slow [AlfredSK]
Fixed a regression in notifications [MrPetovan, annando]
Fixed an issue with smilies and code blocks [MrPetovan]
Fixed an AP issue with unavailable local profiles [MrPetovan]
Fixed an issue with the File to Folder feature [MrPetovan]
Fixed an issue with the legacy storage engine [fabrixxm]
Fixed an issue with the theme and addon path items [MrPetovan]
Fixed an issue occuring when the BasePath was not set [tobiasd]
Fixed an issue with additionally opened Sessions [MrPetovan]
Fixed an issue with legacy loglevel mapping [nupplaphil]
Fixed contact suggestions [annando]
Fixed an issue with frio hovercard [nupplaphil]
Fixed event interaction federation [annando]
Fixed remote image permission [deantownsley]
General Code cleaning and restructuring [annando, nupplaphil, tobiasd]
Added frio color scheme sharing [JeroenED]
Added syslog and stream Logger [nupplaphil]
Added storage move cronjob [MrPetovan]
Added collapsible panel for connector permission fields [MrPetovan]
Added rule-based router [MrPetovan]
Added Estonian translation [Rain Hawk]
Added APCu caching [nupplaphil]
Added BlockServer command to the Friendica console [nupplaphil]
Added reshare count [annando]
Added rule-based router [MrPetovan, nupplaphil]
Added themed error pages with mascot [MrPetovan, lostinlight]
Added contact relationship filter [MrPetovan]
Added native reshares and reshare count [annando]
Removed the old queue mechanism (deferred workers are now used) [annando]
Removed BasePath and Hostname settings from the admin panel [nupplaphil]
Remove support for defunct F-Droid Friendica app [MrPetovan]
Friendica Addons:
Update to the tranlation (ET, SV, ZH_CN) [translation teams]
botdetection:
Added a new addon for preventing access by bots [nupplaphil, annando]
buffer:
Traces of Google+ were removed [annando]
curweather:
Fixed a problem with the display of the correct temperature unit [tobiasd]
fromgplus:
Deprecated the addon as Google+ was closed [tobiasd]
fortunate:
Deprecated addon for incompatibility with latest Friendica version [MrPetovan]
phpmailer:
Added a new addon to use external SMTP for email [M-arcus, kecalcze, MrPetovan]
pledgie:
Deprecated addon as service was discontinued [M-arcus]
xmpp:
Marked addon as unsupported because of various incompatibilities with themes [MrPetovan]
Closed Issues:
838, 1012, 2209, 2528, 3309, 3717, 3816, 3869, 4453, 4999, 5011,
5047, 5276, 5850, 5983, 6245, 6303, 6319, 6379, 6410, 6477, 6478,
6720, 6799, 6813, 6819, 6861, 6864, 6879, 6903, 6916, 6917, 6918,
6921, 6927, 6929, 6936, 6938, 6941, 6943, 6947, 6948, 6950, 6952,
6983, 6999, 7012, 7020, 7023, 7031, 7036, 7047, 7106, 7110, 7112,
7119, 7128, 7130, 7131, 7141, 7142, 7150, 7171, 7183, 7196, 7209,
7223, 7226, 7240, 7241, 7249, 7264, 7269, 7271, 7275, 7300, 7303
Version 2019.04 (2019-04-28)
Friendica Core:
Fixed a privacy problem with postings accessed by feed [MrPetovan]
Version 2019.03 (2019-03-22)
Friendica Core:
Update to the translation (CS, DE, EN-GB, EN-US, ES, FR, IT, PL, SV, ZH-CN) [translation teams]
Update to the documentation [Aditoo17, JeroenED, m4sk1n, softmetz, tobiasd]
Update to the themes (duepuntozero, frio, smoothy, quattro, vier) [lxiter, MrPetovan, nupplaphil, rabuzarus, tobiasd]
Enhancements to the API [jasonscheng]
Enhancements to the Vagrant development VM [JeroenED]
Enhancements to the storage of gender, sexual preferences and maritial status [JeroenED]
Enhancements to the wording of notifications [MrPetovan]
Enhancements to the display of contacts in the profile [MrPetovan]
Enhancements to the handling of local links [lxiter]
Enhancements to the explicit and implicit mentioning in conversations [annando, MrPetovan]
Enhancements to the warnings in the admin panel [tobiasd]
Enhancements to the AP implementation [annando]
Enhancements to the worker process [annando]
Enhancements to the testing process [MrPetovan, nupplaphil]
Enhancements to the LibreJS compatibility [tobiasd]
Enhancements to the federated display of postings [MrPetovan]
Enhancements to the photo menu [annando]
Enhancements to the probing of contacts [annando]
Fixed several bugs with weird tagging in code blocks [lxiter]
Fixed a bug during contact entries update [rabuzarus]
Fixed several PHP warnings and errors [annando, MrPetovan, tobiasd]
Fixed an issue when Friendica is installed in a subdirectory [rabuzarus]
Fixed several issues in the handling of the Markdown parsing from and to d* [lxiter, MrPetovan]
Fixed a bug that prevented blocked contacts from being removed from groups [MrPetovan]
Fixed a bug in the ACL with preselected items [lxiter]
Fixed an issue with polling Events via AP [annando]
Fixed a memory issue with the JSON-LD parser [annando]
Fixed an issue with the forced DB structure update [nupplaphil]
Fixed an issue with wrongly encoded HTML entities in URLs [annando]
Fixed an issue with the rotation of images in the gallery [nupplaphil]
Fixed issues with redirs in the photo menu of Friendica contacts [tobiasd]
Fixed an issue with sending out notification mails to the admin [nupplaphil]
Fixed an the issue, that the API was ignoring the globalsilence setting [nupplaphil]
Fixed issues with the autolinker of URLs in postings [MrPetovan]
Fixed an issue resulting in multible emails after successful updates of the database [nupplaphil]
Fixed a timeout issue during detection process of the remote profile [annando]
Fixed an issue with postings from blocked servers [annando, MrPetovan]
Fixed an issue with the paging of stored folders [MrPetovan]
Fixed an issue with notifications about interactions with Friendica contacts [annando]
Fixed an issue that caused double postings of images uploaded to the gallery [annando]
Fixed an issue handling legacy config files [nupplaphil]
Fixed an issue that caused notifications about interaction with a locally deleted posting [annando]
If the node does not want to publish information, nodeinfo now returns 404 instead of non-existing entries [nupplaphil]
General Code cleaning and restructuring [annando, JeroenED, MrPetovan, nupplaphil]
Switched logging engine to monolog [nupplaphil]
Added plugable storage backend [fabrixxm, nupplaphil]
Added item delivery indicator to posting header [MrPetovan]
Added URL parameter to force a specific language [JeroenED]
Added live preview of attachments to frio [rabuzarus]
Added a "friendica_author" field to the API results which holds the real author [annando]
Added support for AP with forum postings [annando]
Added a summary of articles send over AP [annando]
Friendica Addons:
Updates to the translations (CS, DE, EN-GB, ES, FR, NL, PL, SV) [translation teams]
Updated documentation [softmetz, tobiasd]
blackout:
Fix applying the translations [JeroenED, tobiasd]
Fixed some templating of the settings [tobiasd]
blogger:
The addon was marked as unsupported as it does currently not work (needs OAuth support) [annando]
cookienotice:
Added new addon to display a cookie usage notice in the browser [lxiter]
forumdirectory:
Fixed a theming issue with frio [rabuzarus]
js_upload:
Fixed a missing extionsion index [nupplaphil]
mailstream:
Fixed a curl issue [MrPetovan]
piwik:
Make it clear that Piwik is now Matomo but the addon supports both [tobiasd]
securemail:
updated the addon dependencies [MrPetovan]
twitter:
@ mentions are now stripped from the posts send to Twitter [MrPetovan]
Closed Issues:
1777, 2487, 3218, 3506, 3837, 4496, 5884, 6087, 6161, 6167, 6205,
6232, 6263, 6274, 6292, 6337, 6338, 6375, 6378, 6382, 6384, 6386,
6403, 6405, 6449, 6468, 6472, 6489, 6491, 6492, 6495, 6498, 6501,
6503, 6505, 6511, 6514, 6521, 6522, 6529, 6532, 6533, 6544, 6545,
6551, 6553, 6537, 6558, 6552, 6561, 6570, 6575, 6585, 6603, 6610,
6629, 6630, 6633, 6635, 6652, 6656, 6658, 6667, 6668, 6669, 6672,
6674, 6676, 6677, 6679, 6691, 6710, 6711, 6714, 6716, 6733, 6758,
6772, 6778, 6785, 6788, 6800, 6805, 6812, 6819, 6822, 6823, 6840,
6855, 6866, 6874, 6891, 6901, 6913
Version 2019.01 (2019-01-21)
Friendica Core:
Update to the translation (CS, DE, EN-UK, EN-US, FR, NB-NO, NL, PL) [translation teams]
@ -512,7 +962,7 @@ Version 3.5.3 (2017-10-05)
Updates to the documentation [tobiasd]
Code revision and refactoring [Hypolite]
pumpio, twitter bridges adopted to new background mechanism [annando]
Leistungsschutzrecht has a new source list, and a whitelist [annando]
Leistungsschutzrecht has a new source list, and an allowlist [annando]
retriever marked unsupported due to unwanted side-effects [annando]
Unicode emoji added [annando]
Enhancement to the general content filter [annando]
@ -974,7 +1424,7 @@ Version 3.3.1 (2014-11-06)
Set default location to empty for new users. Suppress warning on user creation (issue #1193) (fabrixxm)
Correctly build urls with queries (issue #1190) (fabrixxm)
Optionally use keywords in feed as post tags with "remote self" (annando)
A blacklist of keywords to not use can be defined (annando)
A denylist of keywords to not use can be defined (annando)
"remote self" works also with Friendica and Diaspora contacts (annando)
Show exact post time after 12 hours (FX7)
Optionally redirect from non-SSL to SSL (annando)

View file

@ -1,18 +1,21 @@
23n
Abinoam P. Marques Jr.
Abraham Pérez Hernández
Abrax
Adam Clark
Adam Jurkiewicz
Adam Magness
Aditoo
Aditoo17
AgnesElisa
Albert
Alberto Díaz Tormo
Aleksandr "M.O.Z.G" Dikov
Alex
Alexander An
Alexander Fortin
Alexander Kampmann
Alexandre Alapetite
Alexey Adamov
AlfredSK
Andi
Andi Stadler
@ -23,10 +26,11 @@ André Alves
André Lohan
Andy
Andy Hee
AndyHee
Angristan
Anthronaut
Antron Samurai
Arian - Cazare Muncitori
Asher Pen
Athalbert
aweiher
axelt
@ -38,10 +42,14 @@ Beluga
Ben
Ben Roberts
ben-utzer
BinkaDroid
Bjoessi
bufalo1973
ButterflyOfFire
Calango Jr
Carlos Solís
Carsten Pfeiffer
Casper
Cat Gray
Chris Case
Christian González
@ -61,6 +69,7 @@ David Martín Miranda
David Rabel
Dean Townsley
Denis Chenu
dependabot[bot]
Devlon Duthie
Diego Souza
Domovoy
@ -75,6 +84,7 @@ emilia.krawczyk
Eric Côté
erik
Erkan Yilmaz
Eugene Veresk
Fabian Dost
Fabio Comuni
felixgilles
@ -91,13 +101,13 @@ Gert Cauwenberg
GLComo
greeneyedred
Gregory Smith
guzzisti
Haakon Meland Eriksen
Hans Meine
hauke
Hauke
Hauke Altmann
Hauke Zühl
Herbert Thielen
hlad
hoergen
Hubert Kościański
Hypolite Petovan
@ -110,6 +120,8 @@ Jens Tautenhahn
jensp
Jeroen De Meerleer
jeroenpraat
Joan Bar
JOduMonT
Johannes Schwab
John Brazil
Jonatan Nyberg
@ -117,18 +129,24 @@ Jonny Tischbein
Josef Moravek
juanman
julia.domagalska
Julio Cova
Karel
Karolina
Keenan Pepper
Keith Fernie
Klaus Weidenbach
Koyu Berteon
kPherox
Kris
Lea1995polish
Leberwurscht
Leonard Lausen
Lionel Triay
loma-one
loma1
Lorem Ipsum
Ludovic Grossard
Lynn Stephenson
maase2
Magdalena Gazda
Mai Anh Nguyen
@ -156,18 +174,23 @@ Michalina
Mike Macgirvin
miqrogroove
mytbk
nathilia-peirce
Nicola Spanti
Olaf Conradi
Oliver
Olivier
Olivier Mehani
Olivier Migeot
ozero dien
Paolo Wave
Pascal
Pascal Deklerck
Pavel Morozov
PerigGouanvic
peter
Peter Liebetrau
peturisfeld
Phigger Phigger
Philipp
Philipp Holzer
Pierre Rudloff
@ -177,17 +200,21 @@ R C
Rabuzarus
Radek
Rafael Garau
Rain Hawk
Rainulf Pineda
Ralf Thees
Ralph
Ratten
rcmaniac
rebeka-catalina
René Wagner
repat
Ricardo Pereira
Rik 4
RJ Madsen
Roland Häder
Rui Andrada
rwa
RyDroid
S.Krumbholz
Sakałoŭ Alaksiej
@ -201,13 +228,17 @@ Seth
Silke Meyer
Simon L'nu
Simó Albert i Beltran
softmetz
soko1
SpencerDub
St John Karp
Stanislav N.
Steffen K9
StefOfficiel
steve jobs
Sveinn í Felli
Sven Anders
Sylke Vicious
Sylvain Lagacé
szymon.filip
Sérgio Lima
@ -219,13 +250,15 @@ Thomas
Thomas Willingham
thorsten23
Tim Stahel
TiMESPLiNTER
Tino
Tobias Diekershoff
Tobias Hößl
tomacat
Tom
tomamplius
tomtom84
Tony Baldwin
Torbjörn Andersson
TORminator
trebor
tschlotfeldt
@ -233,12 +266,16 @@ Tubuntu
Tupambae.org
U-SOUND\mike
ufic
Ulf Rompe
Unknown
Valvin
Valvin A
Vasudev Kamath
Vasya Novikov
Vinzenz Vietzke
vislav
vladimir N
Vladimir Núñez
VVelox
Vít Šesták 'v6ak'
Waldemar Stoczkowski

View file

@ -1,347 +0,0 @@
# Friendica Installation
We've tried very hard to ensure that Friendica will run on commodity hosting
platforms - such as those used to host Wordpress blogs and Drupal websites.
But be aware that Friendica is more than a simple web application. It is a
complex communications system which more closely resembles an email server than
a web server. For reliability and performance, messages are delivered in the
background and are queued for later delivery when sites are down. This kind of
functionality requires a bit more of the host system than the typical blog.
Not every PHP/MySQL hosting provider will be able to support Friendica. Many will.
But please review the requirements and confirm these with your hosting provider
prior to installation.
Before you begin: Choose a domain name or subdomain name for your server.
Put some thought into this - because changing it is currently not-supported.
Things will break, and some of your friends may have difficulty communicating with you.
We plan to address this limitation in a future release. Also decide if you wish
to connect with members of the Diaspora network, as this will impact the
installation requirements.
Decide if you will use SSL and obtain an SSL cert. Communications with the
Diaspora network MAY require both SSL AND an SSL cert signed by a CA which is
recognized by major browsers. Friendica will work with self-signed certs but
Diaspora communication may not. For best results, install your cert PRIOR to
installing Friendica and when visiting your site for the initial installation in
step 5, please use the https: link. (Use the http: or non-SSL link if your cert
is self-signed).
## 1. Requirements
- Apache with mod-rewrite enabled and "Options All" so you can use a local .htaccess file
- PHP 5.6.1+ (PHP 7.1+ recommended for performance and official support).
- PHP *command line* with `register_argc_argv = true` in php.ini
- 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)
- Composer for a Git install
- Mysql 5.6+ or an equivalent alternative for MySQL (MariaDB 10.0.5+, Percona Server etc.)
- Ability to schedule jobs with cron (Linux/Mac) or Scheduled Tasks (Windows)
- Installation into a top-level domain or sub-domain (without a directory/path
component in the URL) is preferred. This is REQUIRED if you wish to communicate
with the Diaspora network.
- For alternative server configurations (such as Nginx server and MariaDB database
engine), refer to the [Friendica wiki](https://github.com/friendica/friendica/wiki).
This guide will walk you through the manual installation process of Friendica.
If this is nothing for you, you might be interested in:
* the Friendica Docker image (https://github.com/friendica/docker) or
* how install Friendica with YunoHost (https://github.com/YunoHost-Apps/friendica_ynh).
## 2. Install Friendica sources
Unpack the Friendica files into the root of your web server document area.
If you copy the directory tree to your webserver, make sure that you also copy
`.htaccess-dist` - as "dot" files are often hidden and aren't normally copied.
OR
Clone the friendica/friendica GitHub repository and import dependencies
git clone https://github.com/friendica/friendica -b master [web server folder]
cd [web server folder]
bin/composer.phar install --no-dev
Make sure the folder view/smarty3 exists and is writable by the webserver user,
in this case `www-data`
mkdir view/smarty3
chown www-data:www-data view/smarty3
chmod 775 view/smarty3
Get the addons by going into your website folder.
cd mywebsite
Clone the addon repository (separately):
git clone https://github.com/friendica/friendica-addons.git -b master addon
If you want to use the development version of Friendica you can switch to the
develop branch in the repository by running
git checkout develop
bin/composer.phar install
cd addon
git checkout develop
Please be aware that the develop branch is unstable.
Exercise caution when pulling.
If you encounter a bug, please let us know.
Either way, if you use Apache, copy `.htaccess-dist` to `.htaccess` to enable
URL rewriting.
## 3. Database
Create an empty database and note the access details (hostname, username, password,
database name).
- Friendica needs the permission to create and delete fields and tables in its
own database.
- Please check the additional notes if running on MySQ 5.7.17 or newer
## 4. Config
If you know in advance that it will be impossible for the web server to write or
create files in the `config/` directory, please create an empty file called
`local.config.php` in it and make it writable by the web server.
## 5a. Install Wizard
Visit your website with a web browser and follow the instructions.
Please note any error messages and correct these before continuing.
If you are using SSL with a known signature authority (recommended), use the
https: link to your website. If you are using a self-signed cert or no cert,
use the http: link.
If you need to specify a port for the connection to the database, you can do so
in the host name setting for the database.
## 5b. Manual install
*If* the automated installation fails for any reason, please check the following:
- `config/local.config.php` exists
- If not, copy `config/local-sample.config.php` to `config/local.config.php`
and edit it with your settings.
- Database is populated.
- If not, import the contents of `database.sql` with phpMyAdmin or the mysql
command line tool.
## 6. Register the admin account
At this point visit your website again, and register your personal account with
the same email as in the `config.admin_email` config value.
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 delete/rename
`config/local.config.php` to another name and drop all the database tables so
that you can start fresh.
## 7. Background tasks (IMPORTANT)
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 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 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 assistance.
Friendica will not work correctly if you cannot perform this step.
You should also be sure that `config.php_path` is set correctly, it should look
like this: (changing it to the correct PHP location)
'config' => [
'php_path' => '/usr/local/php56/bin/php',
]
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:
https://example.com/worker
with the service of your choice.
## 8. (Recommended) 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.
The most important file is the `config/local.config.php` file in the base directory.
As it stores all your data, you should also have a recent dump of your Friendica
database at hand, should you have to recover your node.
## 9. (Optional) Reverse-proxying and HTTPS
Friendica looks for some well-known HTTP headers indicating a reverse-proxy
terminating an HTTPS connection.
While the standard from RFC 7239 specifies the use of the `Forwaded` header.
Forwarded: for=192.0.2.1; proto=https; by=192.0.2.2
Friendica also supports a number on non-standard headers in common use.
X-Forwarded-Proto: https
Front-End-Https: on
X-Forwarded-Ssl: on
It is however preferable to use the standard approach if configuring a new server.
## Troubleshooting
### "System is currently unavailable. Please try again later"
Check your database settings.
It usually means your database could not be opened or accessed.
If the database resides on the same machine, check that the database server name
is "localhost".
### 500 Internal Error
This could be the result of one of our Apache directives not being supported by
your version of Apache. Examine your apache server logs.
You might remove the line "Options -Indexes" from the .htaccess file if you are
using a Windows server as this has been known to cause problems.
Also check your file permissions. Your website and all contents must generally
be world-readable.
It is likely that your web server reported the source of the problem in its error log files.
Please review these system error logs to determine what caused the problem.
Often this will need to be resolved with your hosting provider or (if self-hosted)
your web server configuration.
### 400 and 4xx "File not found" errors
First check your file permissions.
Your website and all contents must generally be world-readable.
Ensure that mod-rewite is installed and working, and that your `.htaccess` file
is being used. To verify the latter, create a file `test.out` containing the
word "test" in the top directory of Friendica, make it world readable and point
your web browser to
http://yoursitenamehere.com/test.out
This file should be blocked. You should get a permission denied message.
If you see the word "test" your Apache configuration is not allowing your
`.htaccess` file to be used (there are rules in this file to block access to any
file with .out at the end, as these are typically used for system logs).
Make certain the `.htaccess` file exists and is readable by everybody, then look
for the existence of "AllowOverride None" in the Apache server configuration for your site.
This will need to be changed to "AllowOverride All".
If you do not see the word "test", your `.htaccess` is working, but it is likely
that mod-rewrite is not installed in your web server or is not working.
On most Linux flavors:
% a2enmod rewrite
% /etc/init.d/apache2 restart
Consult your hosting provider, experts on your particular Linux distribution or
(if Windows) the provider of your Apache server software if you need to change
either of these and can not figure out how. There is a lot of help available on
the web. Search "mod-rewrite" along with the name of your operating system
distribution or Apache package (if using Windows).
### Unable to write the file config/local.config.php due to permissions issues
Create an empty `config/local.config.php`file with that name and give it
world-write permission.
On Linux:
% touch config/local.config.php
% chmod 664 config/local.config.php
Retry the installation. As soon as the database has been created,
******* this is important *********
% chmod 644 config/local.config.php
### Suhosin issues
Some configurations with "suhosin" security are configured without an ability to
run external processes. Friendica requires this ability. Following are some notes
provided by one of our members.
> On my server I use the php protection system Suhosin [http://www.hardened-php.net/suhosin/].
> One of the things it does is to block certain functions like proc_open, as
> configured in `/etc/php5/conf.d/suhosin.ini`:
>
> suhosin.executor.func.blacklist = proc_open, ...
>
> For those sites like Friendica that really need these functions they can be
> enabled, e.g. in `/etc/apache2/sites-available/friendica`:
>
> <Directory /var/www/friendica/>
> php_admin_value suhosin.executor.func.blacklist none
> php_admin_value suhosin.executor.eval.blacklist none
> </Directory>
>
> This enables every function for Friendica if accessed via browser, but not for
> the cronjob that is called via php command line. I attempted to enable it for
> 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 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 `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`.
>
> So the simple solution is to put the correct parameters into `config/local.config.php`:
>
> 'config' => [
> //Location of PHP command line processor
> 'php_path' => '/usr/bin/php -d suhosin.executor.func.blacklist=none \
> -d suhosin.executor.eval.blacklist=none',
> ],
>
> This is obvious as soon as you notice that the friendica-cron uses `proc_open`
> to execute PHP scripts that also use `proc_open`, but it took me quite some time to find that out.
> I hope this saves some time for other people using suhosin with function blacklists.
### Unable to create all mysql tables on MySQL 5.7.17 or newer
If the setup fails to create all the database tables and/or manual creation from
the command line fails, with this error:
ERROR 1067 (42000) at line XX: Invalid default value for 'created'
You need to adjust your my.cnf and add the following setting under the [mysqld]
section:
sql_mode = '';
After that, restart mysql and try again.

View file

@ -1,5 +1,5 @@
Friendica Communications Server
Copyright (c) 2010-2019 the Friendica Project
Copyright (c) 2010-2020 the Friendica Project
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by

View file

@ -13,29 +13,34 @@ With Friendica, you can also fully interact with anyone on Twitter, post on Face
Join today and [get your Friendica profile!](https://dir.friendica.social/servers 'Join Friendica today!')
Have a look at the [installation documentation](doc/Install.md) for further information about installing and using Friendica.
### Friendica Screenshots
| ![Frio theme in mobile browser](/images/screenshots/friendica-frio-mobile-profle-1.png?raw=true "Frio theme in mobile browser") ![Frio theme in mobile browser](/images/screenshots/friendica-frio-mobile-profle-2.png?raw=true "Frio theme in mobile browser")
| ![Frio theme in mobile browser](images/screenshots/friendica-frio-mobile-profle-1.png?raw=true "Frio theme in mobile browser") ![Frio theme in mobile browser](images/screenshots/friendica-frio-mobile-profle-2.png?raw=true "Frio theme in mobile browser")
|:--:|
|*Frio theme, mobile browser. Timeline and composer view.*|
|![Frio theme in desktop browser](/images/screenshots/friendica-frio-green-profle-1.png?raw=true "Frio theme in desktop browser")
|![Frio theme in desktop browser](images/screenshots/friendica-frio-green-profle-1.png?raw=true "Frio theme in desktop browser")
|*Frio theme, desktop browser. Timeline view, contact info popped up, control menu open.*|
|![Frio theme in desktop browser](/images/screenshots/friendica-frio-green-profle-2.png?raw=true "Frio theme in desktop browser")
|![Frio theme in desktop browser](images/screenshots/friendica-frio-green-profle-2.png?raw=true "Frio theme in desktop browser")
|*Frio theme, desktop browser. Menu open for controlling individual posts.*|
|![Frio theme in desktop browser](/images/screenshots/friendica-frio-red-profle-3.png?raw=true "Frio theme in desktop browser")
|![Frio theme in desktop browser](images/screenshots/friendica-frio-red-profle-3.png?raw=true "Frio theme in desktop browser")
|*Frio theme, desktop browser. Profile view, notification menu open.*|
|![Frio theme in desktop browser](/images/screenshots/friendica-frio-red-profle-2.png?raw=true "Frio theme in desktop browser")
|![Frio theme in desktop browser](images/screenshots/friendica-frio-red-profle-2.png?raw=true "Frio theme in desktop browser")
|*Number of new posts, in total and by group.*|
|![Frio theme in desktop browser](/images/screenshots/friendica-frio-red-profle-1.png?raw=true "Frio theme in desktop browser")
|![Frio theme in desktop browser](images/screenshots/friendica-frio-red-profle-1.png?raw=true "Frio theme in desktop browser")
|*Calender with popup of event.*|
|![Frio theme default colour in standard browser on tablet](/images/screenshots/friendica-frio-default-profile-1.png?raw=true "Frio theme default colour in standard browser on tablet")
|![Frio theme default colour in standard browser on tablet](images/screenshots/friendica-frio-default-profile-1.png?raw=true "Frio theme default colour in standard browser on tablet")
|*Notifications menu and private messages counter, standard browser on tablet.*|
|![Frio theme in desktop browser](/images/screenshots/friendica-frio-brown-profile-2.png?raw=true "Frio theme in desktop browser")
|![Frio theme in desktop browser](images/screenshots/friendica-frio-brown-profile-2.png?raw=true "Frio theme in desktop browser")
|*Number of visible contacts, standard browser.*|
|![Frio theme in desktop browser](/images/screenshots/friendica-frio-brown-profile-1.png?raw=true "Frio theme in desktop browser")
|![Frio theme in desktop browser](images/screenshots/friendica-frio-brown-profile-1.png?raw=true "Frio theme in desktop browser")
|*Network posts chronologically ordered, standard browser.*|
|![Vier theme in desktop browser](/images/screenshots/friendica-vier-profile.png?raw=true "Vier theme in desktop browser")
|![Vier theme in desktop browser](images/screenshots/friendica-vier-profile.png?raw=true "Vier theme in desktop browser")
|*Vier theme, desktop browser. Public timeline view.*|
|![Vier theme in desktop browser](/images/screenshots/friendica-vier-community.png?raw=true "Vier theme in desktop browser")
|![Vier theme in desktop browser](images/screenshots/friendica-vier-community.png?raw=true "Vier theme in desktop browser")
|*Vier theme, desktop browser. Community post displayed.*|
## Endorsements
- [![Awesome Humane Tech](images/humane-tech-badge.svg)](https://github.com/humanetech-community/awesome-humane-tech) On August 12th 2020, Friendica was added to [the curated Awesome Humane Tech directory](https://github.com/humanetech-community/awesome-humane-tech) in [the "Fediverse" category](https://github.com/humanetech-community/awesome-humane-tech#fediverse).

View file

@ -1 +1 @@
2019.03-dev
2020.09-dev

4
Vagrantfile vendored
View file

@ -6,8 +6,8 @@ server_timezone = "UTC"
public_folder = "/vagrant"
Vagrant.configure(2) do |config|
# Set server to Ubuntu 16.04
config.vm.box = "ubuntu/xenial64"
# Set server to Debian 10 / Buster 64bit
config.vm.box = "debian/buster64"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs

279
autotest.sh Executable file
View file

@ -0,0 +1,279 @@
#!/usr/bin/env bash
#
# This script is used for autotesting the Friendica codebase with different
# types of tests and environments.
#
# Currently, there are three types of autotesting possibilities:
# - "USEDOCKER=true ./autotest.sh" will start a database docker container for testing
# - "./autotest.sh" on the Drone CI environment will use the database container of the drone CI pipeline
# - "./autotest.sh" on a local environment will try to use the local database instance for testing
#
# You can specify a database (mysql, mariadb currently) for the db backend of Friendica ("./autotest.sh mysql")
# And you can specify some parameters for the test, like:
# - NOCOVERAGE=true ... Don't create a coverage XML (this is only useful if you will send coverage to codecov.io)
# - NOINSTALL=true ... Skip the whole Friendica installation process (e.g. you just test Caching drivers)
# - TEST_SELECTION= ... Specify which tests are used to run (based on the test-labeling)
# - XDEBUG_CONFIG= ... Set some XDEBUG specific environment settings for development
DATABASENAME=${MYSQL_DATABASE:-test}
DATABASEUSER=${MYSQL_USERNAME:-friendica}
DATABASEHOST=${MYSQL_HOST:-localhost}
BASEDIR=$PWD
DBCONFIGS="mysql mariadb"
TESTS="REDIS MEMCACHE MEMCACHED APCU NODB"
export MYSQL_DATABASE="$DATABASENAME"
export MYSQL_USERNAME="$DATABASEUSER"
export MYSQL_PASSWORD="friendica"
if [ -z "$PHP_EXE" ]; then
PHP_EXE=php
fi
PHP=$(which "$PHP_EXE")
# Use the Friendica internal composer
COMPOSER="$BASEDIR/bin/composer.phar"
set -e
_XDEBUG_CONFIG=$XDEBUG_CONFIG
unset XDEBUG_CONFIG
function show_syntax() {
echo -e "Syntax: ./autotest.sh [dbconfigname] [testfile]\n" >&2
echo -e "\t\"dbconfigname\" can be one of: $DBCONFIGS" >&2
echo -e "\t\"testfile\" is the name of a test file, for example lib/template.php" >&2
echo -e "\nDatabase environment variables:\n" >&2
echo -e "\t\"MYSQL_HOST\" Mysql Hostname (Default: localhost)" >&2
echo -e "\t\"MYSQL_USDRNAME\" Mysql Username (Default: friendica)" >&2
echo -e "\t\"MYSQL_DATABASE\" Mysql Database (Default: test)" >&2
echo -e "\nOther environment variables:\n" >&2
echo -e "\t\"TEST_SELECTION\" test a specific group of tests, can be one of: $TESTS" >&2
echo -e "\t\"NOINSTALL\" If set to true, skip the db and install process" >&2
echo -e "\t\"NOCOVERAGE\" If set to true, don't create a coverage output" >&2
echo -e "\t\"USEDOCKER\" If set to true, the DB server will be executed inside a docker container" >&2
echo -e "\nExample: NOCOVERAGE=true ./autotest.sh mysql src/Core/Cache/MemcacheTest.php" >&2
echo "will run the test suite from \"tests/src/Core/Cache/MemcacheTest.php\" without a Coverage" >&2
echo -e "\nIf no arguments are specified, all tests will be run with all database configs" >&2
}
if [ -x "$PHP" ]; then
echo "Using PHP executable $PHP"
else
echo "Could not find PHP executable $PHP_EXE" >&2
exit 3
fi
echo "Installing depdendencies"
$PHP "$COMPOSER" install
PHPUNIT="$BASEDIR/vendor/bin/phpunit"
if [ -x "$PHPUNIT" ]; then
echo "Using PHPUnit executable $PHPUNIT"
else
echo "Could not find PHPUnit executable after composer $PHPUNIT" >&2
exit 3
fi
if ! [ \( -w config -a ! -f config/local.config.php \) -o \( -f config/local.config.php -a -w config/local.config.php \) ]; then
echo "Please enable write permissions on config and config/config.php" >&2
exit 1
fi
if [ "$1" ]; then
FOUND=0
for DBCONFIG in $DBCONFIGS; do
if [ "$1" = "$DBCONFIG" ]; then
FOUND=1
break
fi
done
if [ $FOUND = 0 ]; then
echo -e "Unknown database config name \"$1\"\n" >&2
show_syntax
exit 2
fi
fi
# Back up existing (dev) config if one exists and backup not already there
if [ -f config/local.config.php ] && [ ! -f config/local.config-autotest-backup.php ]; then
mv config/local.config.php config/local.config-autotest-backup.php
fi
function cleanup_config() {
if [ -n "$DOCKER_CONTAINER_ID" ]; then
echo "Kill the docker $DOCKER_CONTAINER_ID"
docker stop "$DOCKER_CONTAINER_ID"
docker rm -f "$DOCKER_CONTAINER_ID"
fi
cd "$BASEDIR"
# Restore existing config
if [ -f config/local.config-autotest-backup.php ]; then
mv config/local.config-autotest-backup.php config/local.config.php
fi
}
# restore config on exit
trap cleanup_config EXIT
function execute_tests() {
DB=$1
echo "Setup environment for $DB testing ..."
# back to root folder
cd "$BASEDIR"
# backup current config
if [ -f config/local.config.php ]; then
mv config/local.config.php config/local.config-autotest-backup.php
fi
if [ -z "$NOINSTALL" ]; then
#drop database
if [ "$DB" == "mysql" ]; then
if [ -n "$USEDOCKER" ]; then
echo "Fire up the mysql docker"
DOCKER_CONTAINER_ID=$(docker run \
-e MYSQL_ROOT_PASSWORD=friendica \
-e MYSQL_USER="$DATABASEUSER" \
-e MYSQL_PASSWORD=friendica \
-e MYSQL_DATABASE="$DATABASENAME" \
-d mysql)
DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID")
else
if [ -z "$DRONE" ]; then # no need to drop the DB when we are on CI
if [ "mysql" != "$(mysql --version | grep -o mysql)" ]; then
echo "Your mysql binary is not provided by mysql"
echo "To use the docker container set the USEDOCKER environment variable"
exit 3
fi
mysql -u "$DATABASEUSER" -pfriendica -e "DROP DATABASE IF EXISTS $DATABASENAME" -h $DATABASEHOST || true
mysql -u "$DATABASEUSER" -pfriendica -e "CREATE DATABASE $DATABASENAME DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci" -h $DATABASEHOST
else
DATABASEHOST=mysql
fi
fi
echo "Waiting for MySQL $DATABASEHOST initialization..."
if ! bin/wait-for-connection $DATABASEHOST 3306 300; then
echo "[ERROR] Waited 300 seconds, no response" >&2
exit 1
fi
echo "MySQL is up."
fi
if [ "$DB" == "mariadb" ]; then
if [ -n "$USEDOCKER" ]; then
echo "Fire up the mariadb docker"
DOCKER_CONTAINER_ID=$(docker run \
-e MYSQL_ROOT_PASSWORD=friendica \
-e MYSQL_USER="$DATABASEUSER" \
-e MYSQL_PASSWORD=friendica \
-e MYSQL_DATABASE="$DATABASENAME" \
-d mariadb)
DATABASEHOST=$(docker inspect --format="{{.NetworkSettings.IPAddress}}" "$DOCKER_CONTAINER_ID")
else
if [ -z "$DRONE" ]; then # no need to drop the DB when we are on CI
if [ "MariaDB" != "$(mysql --version | grep -o MariaDB)" ]; then
echo "Your mysql binary is not provided by mysql"
echo "To use the docker container set the USEDOCKER environment variable"
exit 3
fi
mysql -u "$DATABASEUSER" -pfriendica -e "DROP DATABASE IF EXISTS $DATABASENAME" -h $DATABASEHOST || true
mysql -u "$DATABASEUSER" -pfriendica -e "CREATE DATABASE $DATABASENAME DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci" -h $DATABASEHOST
else
DATABASEHOST=mariadb
fi
fi
echo "Waiting for MariaDB $DATABASEHOST initialization..."
if ! bin/wait-for-connection $DATABASEHOST 3306 300; then
echo "[ERROR] Waited 300 seconds, no response" >&2
exit 1
fi
echo "MariaDB is up."
fi
if [ -n "$USEDOCKER" ]; then
echo "Initialize database..."
docker exec $DOCKER_CONTAINER_ID mysql -u root -pfriendica -e 'CREATE DATABASE IF NOT EXISTS $DATABASENAME;'
fi
export MYSQL_HOST="$DATABASEHOST"
#call installer
echo "Installing Friendica..."
"$PHP" ./bin/console.php autoinstall --dbuser="$DATABASEUSER" --dbpass=friendica --dbdata="$DATABASENAME" --dbhost="$DATABASEHOST" --url=https://friendica.local --admin=admin@friendica.local
fi
#test execution
echo "Testing..."
rm -fr "coverage-html"
mkdir "coverage-html"
if [[ "$_XDEBUG_CONFIG" ]]; then
export XDEBUG_CONFIG=$_XDEBUG_CONFIG
fi
COVER=''
if [ -z "$NOCOVERAGE" ]; then
COVER="--coverage-clover tests/autotest-clover.xml"
else
echo "No coverage"
fi
# per default, there is no cache installed
GROUP='--exclude-group REDIS,MEMCACHE,MEMCACHED,APCU'
if [ "$TEST_SELECTION" == "REDIS" ]; then
GROUP="--group REDIS"
fi
if [ "$TEST_SELECTION" == "MEMCACHE" ]; then
GROUP="--group MEMCACHE"
fi
if [ "$TEST_SELECTION" == "MEMCACHED" ]; then
GROUP="--group MEMCACHED"
fi
if [ "$TEST_SELECTION" == "APCU" ]; then
GROUP="--group APCU"
fi
if [ "$TEST_SELECTION" == "NODB" ]; then
GROUP="--exclude-group DB,SLOWDB"
fi
INPUT="$BASEDIR/tests"
if [ -n "$2" ]; then
INPUT="$INPUT/$2"
fi
echo "${PHPUNIT[@]}" --configuration tests/phpunit.xml $GROUP $COVER --log-junit "autotest-results.xml" "$INPUT" "$3"
"${PHPUNIT[@]}" --configuration tests/phpunit.xml $GROUP $COVER --log-junit "autotest-results.xml" "$INPUT" "$3"
RESULT=$?
if [ -n "$DOCKER_CONTAINER_ID" ]; then
echo "Kill the docker $DOCKER_CONTAINER_ID"
docker stop $DOCKER_CONTAINER_ID
docker rm -f $DOCKER_CONTAINER_ID
unset $DOCKER_CONTAINER_ID
fi
}
#
# Start the test execution
#
if [ -z "$1" ] && [ -n "$TEST_SELECTION" ]; then
# run all known database configs
for DBCONFIG in $DBCONFIGS; do
execute_tests "$DBCONFIG"
done
else
FILENAME="$2"
if [ -n "$2" ] && [ ! -f "tests/$FILENAME" ] && [ "${FILENAME:0:2}" != "--" ]; then
FILENAME="../$FILENAME"
fi
execute_tests "$1" "$FILENAME" "$3"
fi

View file

@ -1,6 +1,23 @@
#!/usr/bin/env php
<?php
/*
/**
* @copyright Copyright (C) 2020, Friendica
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* ejabberd extauth script for the integration with friendica
*
* Originally written for joomla by Dalibor Karlovic <dado@krizevci.info>
@ -18,9 +35,11 @@
* - Change the access mode so it is readable only to the user ejabberd and has exec
* $ 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/bin/auth_ejabberd.php"}.
* - Edit your ejabberd.yml file and add after "shaper:":
*
* auth_method: [external]
* extauth_program: "/path/to/friendica/bin/auth_ejabberd.php"
* auth_use_cache: false
*
* - Restart your ejabberd service, you should be able to login with your friendica auth info
*
@ -32,11 +51,10 @@
*
*/
use Friendica\App;
use Friendica\Core\Config;
use Friendica\Factory;
use Friendica\Util\BasePath;
use Dice\Dice;
use Friendica\App\Mode;
use Friendica\Util\ExAuth;
use Psr\Log\LoggerInterface;
if (sizeof($_SERVER["argv"]) == 0) {
die();
@ -54,14 +72,14 @@ chdir($directory);
require dirname(__DIR__) . '/vendor/autoload.php';
$basedir = BasePath::create(dirname(__DIR__), $_SERVER);
$configLoader = new Config\ConfigCacheLoader($basedir);
$config = Factory\ConfigFactory::createCache($configLoader);
$logger = Factory\LoggerFactory::create('auth_ejabberd', $config);
$dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
$dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['auth_ejabberd']]);
$a = new App($config, $logger);
\Friendica\DI::init($dice);
if ($a->getMode()->isNormal()) {
$appMode = $dice->create(Mode::class);
if ($appMode->isNormal()) {
$oAuth = new ExAuth();
$oAuth->readStdin();
}

Binary file not shown.

View file

@ -1,18 +1,31 @@
#!/usr/bin/env php
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
use Dice\Dice;
use Psr\Log\LoggerInterface;
require dirname(__DIR__) . '/vendor/autoload.php';
use Friendica\Core\Config;
use Friendica\Factory;
use Friendica\Util\BasePath;
$dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
$dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['console']]);
$basedir = BasePath::create(dirname(__DIR__), $_SERVER);
$configLoader = new Config\ConfigCacheLoader($basedir);
$config = Factory\ConfigFactory::createCache($configLoader);
$logger = Factory\LoggerFactory::create('console', $config);
$a = new Friendica\App($config, $logger);
\Friendica\BaseObject::setApp($a);
(new Friendica\Core\Console($argv))->execute();
(new Friendica\Core\Console($dice, $argv))->execute();

View file

@ -1,18 +1,34 @@
#!/usr/bin/env php
<?php
/**
* @file bin/daemon.php
* @brief Run the worker from a daemon.
* @copyright Copyright (C) 2020, Friendica
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Run the worker from a daemon.
*
* This script was taken from http://php.net/manual/en/function.pcntl-fork.php
*/
use Friendica\App;
use Friendica\Core\Config;
use Dice\Dice;
use Friendica\Core\Logger;
use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\Factory;
use Friendica\Util\BasePath;
use Friendica\DI;
use Psr\Log\LoggerInterface;
// Get options
$shortopts = 'f';
@ -33,20 +49,19 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) {
require dirname(__DIR__) . '/vendor/autoload.php';
$basedir = BasePath::create(dirname(__DIR__), $_SERVER);
$configLoader = new Config\ConfigCacheLoader($basedir);
$config = Factory\ConfigFactory::createCache($configLoader);
$logger = Factory\LoggerFactory::create('daemon', $config);
$dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
$dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['daemon']]);
$a = new App($config, $logger);
DI::init($dice);
$a = DI::app();
if ($a->getMode()->isInstall()) {
if (DI::mode()->isInstall()) {
die("Friendica isn't properly installed yet.\n");
}
Config::load();
DI::config()->load();
if (empty(Config::get('system', 'pidfile'))) {
if (empty(DI::config()->get('system', 'pidfile'))) {
die(<<<TXT
Please set system.pidfile in config/local.config.php. For example:
@ -57,7 +72,7 @@ TXT
);
}
$pidfile = Config::get('system', 'pidfile');
$pidfile = DI::config()->get('system', 'pidfile');
if (in_array("start", $_SERVER["argv"])) {
$mode = "start";
@ -88,7 +103,7 @@ if (is_readable($pidfile)) {
}
if (empty($pid) && in_array($mode, ["stop", "status"])) {
Config::set('system', 'worker_daemon_mode', false);
DI::config()->set('system', 'worker_daemon_mode', false);
die("Pidfile wasn't found. Is the daemon running?\n");
}
@ -99,7 +114,7 @@ if ($mode == "status") {
unlink($pidfile);
Config::set('system', 'worker_daemon_mode', false);
DI::config()->set('system', 'worker_daemon_mode', false);
die("Daemon process $pid isn't running.\n");
}
@ -108,9 +123,9 @@ if ($mode == "stop") {
unlink($pidfile);
$logger->notice("Worker daemon process was killed", ["pid" => $pid]);
Logger::notice("Worker daemon process was killed", ["pid" => $pid]);
Config::set('system', 'worker_daemon_mode', false);
DI::config()->set('system', 'worker_daemon_mode', false);
die("Worker daemon process $pid was killed.\n");
}
@ -118,7 +133,7 @@ if (!empty($pid) && posix_kill($pid, 0)) {
die("Daemon process $pid is already running.\n");
}
$logger->notice('Starting worker daemon.', ["pid" => $pid]);
Logger::notice('Starting worker daemon.', ["pid" => $pid]);
if (!$foreground) {
echo "Starting worker daemon.\n";
@ -150,15 +165,15 @@ if (!$foreground) {
file_put_contents($pidfile, $pid);
// We lose the database connection upon forking
$a->loadDatabase();
DBA::reconnect();
}
Config::set('system', 'worker_daemon_mode', true);
DI::config()->set('system', 'worker_daemon_mode', true);
// Just to be sure that this script really runs endlessly
set_time_limit(0);
$wait_interval = intval(Config::get('system', 'cron_interval', 5)) * 60;
$wait_interval = intval(DI::config()->get('system', 'cron_interval', 5)) * 60;
$do_cron = true;
$last_cron = 0;
@ -166,7 +181,7 @@ $last_cron = 0;
// Now running as a daemon.
while (true) {
if (!$do_cron && ($last_cron + $wait_interval) < time()) {
$logger->info('Forcing cron worker call.', ["pid" => $pid]);
Logger::info('Forcing cron worker call.', ["pid" => $pid]);
$do_cron = true;
}
@ -180,7 +195,7 @@ while (true) {
$last_cron = time();
}
$logger->info("Sleeping", ["pid" => $pid]);
Logger::info("Sleeping", ["pid" => $pid]);
$start = time();
do {
$seconds = (time() - $start);
@ -197,10 +212,10 @@ while (true) {
if ($timeout) {
$do_cron = true;
$logger->info("Woke up after $wait_interval seconds.", ["pid" => $pid, 'sleep' => $wait_interval]);
Logger::info("Woke up after $wait_interval seconds.", ["pid" => $pid, 'sleep' => $wait_interval]);
} else {
$do_cron = false;
$logger->info("Worker jobs are calling to be forked.", ["pid" => $pid]);
Logger::info("Worker jobs are calling to be forked.", ["pid" => $pid]);
}
}

View file

@ -5,16 +5,13 @@ command -v uglifyjs >/dev/null 2>&1 || { echo >&2 "I require UglifyJS but it's n
MINIFY_CMD=uglifyjs
JSFILES=(
"view/js/acl.js"
"view/js/ajaxupload.js"
"view/js/country.js"
"view/js/main.js"
"vendor/asset/base64/base64.min.js"
"view/theme/frost/js/acl.js"
"view/theme/frost/js/jquery.divgrow-1.3.1.f1.js"
"view/theme/frost/js/main.js"
"view/theme/frost/js/theme.js"
"view/theme/frost-mobile/js/acl.js"
"view/theme/frost-mobile/js/jquery.divgrow-1.3.1.f1.js"
"view/theme/frost-mobile/js/main.js"
"view/theme/frost-mobile/js/theme.js"

View file

@ -16,14 +16,12 @@ DOMAIN="*.xip.io"
EXTRADOMAIN="friendica.local"
PASSPHRASE="vaprobash"
SUBJ="
C=US
ST=Connecticut
O=Vaprobash
localityName=New Haven
commonName=$DOMAIN
C=US/
ST=Connecticut/
O=Vaprobash/
localityName=New Haven/
commonName=$DOMAIN/
subjectAltName=DNS:$EXTRADOMAIN
organizationalUnitName=
emailAddress=
"
sudo mkdir -p "$SSL_DIR"
sudo openssl genrsa -out "$SSL_DIR/xip.io.key" 4096
@ -37,9 +35,9 @@ sudo apt-get install -y apache2
sudo a2enmod rewrite actions ssl
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.local
sudo a2dissite 000-default
sudo service apache2 restart
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"
@ -48,9 +46,9 @@ sudo systemctl restart apache2
#Install mysql
echo ">>> Installing Mysql"
sudo debconf-set-selections <<< "mysql-server mysql-server/root_password password root"
sudo debconf-set-selections <<< "mysql-server mysql-server/root_password_again password root"
sudo apt-get install -qq mysql-server
sudo debconf-set-selections <<< "mariadb-server mariadb-server/root_password password root"
sudo debconf-set-selections <<< "mariadb-server mariadb-server/root_password_again password root"
sudo apt-get install -qq mariadb-server
# enable remote access
# setting the mysql bind-address to allow connections from everywhere
sed -i "s/bind-address.*/bind-address = 0.0.0.0/" /etc/mysql/my.cnf
@ -76,6 +74,9 @@ 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
# Friendica needs git for fetching some dependencies
sudo apt-get install -y git
#make the vagrant directory the docroot
sudo rm -rf /var/www/
sudo ln -fs /vagrant /var/www
@ -83,7 +84,7 @@ sudo ln -fs /vagrant /var/www
# install deps with composer
sudo apt install unzip
cd /var/www
php bin/composer.phar install
sudo -u www-data php bin/composer.phar install
# initial config file for friendica in vagrant
cp /vagrant/mods/local.config.vagrant.php /vagrant/config/local.config.php

View file

@ -32,7 +32,7 @@ case "$MODE" in
mkdir -p "$FULLPATH/../addon/$ADDONNAME/lang/C"
OUTFILE="$FULLPATH/../addon/$ADDONNAME/lang/C/messages.po"
FINDSTARTDIR="."
FINDOPTS=
FINDOPTS="-path ./vendor -prune -or"
;;
'single')
FULLPATH=$PWD
@ -40,7 +40,7 @@ case "$MODE" in
mkdir -p "$FULLPATH/lang/C"
OUTFILE="$FULLPATH/lang/C/messages.po"
FINDSTARTDIR="."
FINDOPTS=
FINDOPTS="-path ./vendor -prune -or"
echo "Extract strings for single addon '$ADDONNAME'"
;;
'default')
@ -48,9 +48,9 @@ case "$MODE" in
OUTFILE="$FULLPATH/../view/lang/C/messages.po"
FINDSTARTDIR="."
# skip addon folder
FINDOPTS="( -wholename */addon -or -wholename */addons -or -wholename */addons-extra -or -wholename */smarty3 ) -prune -o"
FINDOPTS="( -path ./addon -or -path ./addons -or -path ./addons-extra -or -path ./tests -or -path ./view/lang -or -path ./view/smarty3 -or -path ./vendor ) -prune -or"
F9KVERSION=$(sed -n "s/.*'FRIENDICA_VERSION'.*'\([0-9.]*\)'.*/\1/p" ./boot.php);
F9KVERSION=$(cat ./VERSION);
echo "Friendica version $F9KVERSION"
;;
esac
@ -58,44 +58,54 @@ esac
KEYWORDS="-k -kt -ktt:1,2"
echo "extract strings to $OUTFILE.."
echo "Extract strings to $OUTFILE.."
rm "$OUTFILE"; touch "$OUTFILE"
for f in $(find "$FINDSTARTDIR" $FINDOPTS -name "*.php" -type f)
find_result=$(find "$FINDSTARTDIR" $FINDOPTS -name "*.php" -type f)
total_files=$(wc -l <<< "${find_result}")
for file in $find_result
do
if [ ! -d "$f" ]
((count++))
echo -ne " \r"
echo -ne "Reading file $count/$total_files..."
# On Windows, find still outputs the name of pruned folders
if [ ! -d "$file" ]
then
xgettext $KEYWORDS -j -o "$OUTFILE" --from-code=UTF-8 "$f"
xgettext $KEYWORDS -j -o "$OUTFILE" --from-code=UTF-8 "$file" || exit 1
sed -i "s/CHARSET/UTF-8/g" "$OUTFILE"
fi
done
echo -ne "\n"
echo "setup base info.."
case "$MODE" in
echo "Interpolate metadata.."
sed -i "s/^\"Plural-Forms.*$//g" "$OUTFILE"
case "$MODE" in
'addon'|'single')
sed -i "s/SOME DESCRIPTIVE TITLE./ADDON $ADDONNAME/g" "$OUTFILE"
sed -i "s/YEAR THE PACKAGE'S COPYRIGHT HOLDER//g" "$OUTFILE"
sed -i "s/FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.//g" "$OUTFILE"
sed -i "s/PACKAGE VERSION//g" "$OUTFILE"
sed -i "s/PACKAGE/Friendica $ADDONNAME addon/g" "$OUTFILE"
sed -i "s/CHARSET/UTF-8/g" "$OUTFILE"
sed -i "s/^\"Plural-Forms.*$//g" "$OUTFILE"
;;
'default')
sed -i "s/SOME DESCRIPTIVE TITLE./FRIENDICA Distributed Social Network/g" "$OUTFILE"
sed -i "s/YEAR THE PACKAGE'S COPYRIGHT HOLDER/2010, 2011, 2012, 2013 the Friendica Project/g" "$OUTFILE"
sed -i "s/YEAR THE PACKAGE'S COPYRIGHT HOLDER/2010-$(date +%Y) the Friendica Project/g" "$OUTFILE"
sed -i "s/FIRST AUTHOR <EMAIL@ADDRESS>, YEAR./Mike Macgirvin, 2010/g" "$OUTFILE"
sed -i "s/PACKAGE VERSION/$F9KVERSION/g" "$OUTFILE"
sed -i "s/PACKAGE/Friendica/g" "$OUTFILE"
sed -i "s/CHARSET/UTF-8/g" "$OUTFILE"
sed -i "s/^\"Plural-Forms.*$//g" "$OUTFILE"
;;
esac
if [ "" != "$1" -a "$MODE" == "default" ]
then
UPDATEFILE="$(readlink -f ${FULLPATH}/$1)"
echo "merging new strings to $UPDATEFILE.."
echo "Merging new strings to $UPDATEFILE.."
msgmerge -U $OUTFILE $UPDATEFILE
fi
echo "done."
echo "Done."

View file

@ -1,10 +1,22 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* File: testargs.php
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Purpose:
* During installation we need to check if register_argc_argv is
* enabled for the command line PHP processor, because otherwise
* deliveries will fail. So we will do a shell exec of php and

63
bin/wait-for-connection Executable file
View file

@ -0,0 +1,63 @@
#!/usr/bin/php
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This script tries to connect to a database for a given interval
* Useful in case of installation e.g. to wait for the database to not generate unnecessary errors
*
* Usage: php bin/wait-for-connection {HOST} {PORT} [{TIMEOUT}]
*/
$timeout = 60;
switch ($argc) {
case 4:
$timeout = (float)$argv[3];
case 3:
$host = $argv[1];
$port = (int)$argv[2];
break;
default:
fwrite(STDERR, 'Usage: '.$argv[0].' host port [timeout]'."\n");
exit(2);
}
if ($timeout < 0) {
fwrite(STDERR, 'Timeout must be greater than zero'."\n");
exit(2);
}
if ($port < 1) {
fwrite(STDERR, 'Port must be an integer greater than zero'."\n");
exit(2);
}
$socketTimeout = (float)ini_get('default_socket_timeout');
if ($socketTimeout > $timeout) {
$socketTimeout = $timeout;
}
$stopTime = time() + $timeout;
do {
$sock = @fsockopen($host, $port, $errno, $errstr, $socketTimeout);
if ($sock !== false) {
fclose($sock);
fwrite(STDOUT, "\n");
exit(0);
}
sleep(1);
fwrite(STDOUT, '.');
} while (time() < $stopTime);
fwrite(STDOUT, "\n");
exit(1);

View file

@ -1,16 +1,32 @@
#!/usr/bin/env php
<?php
/**
* @file bin/worker.php
* @brief Starts the background processing
* @copyright Copyright (C) 2020, Friendica
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Starts the background processing
*/
use Dice\Dice;
use Friendica\App;
use Friendica\Core\Config;
use Friendica\Core\Update;
use Friendica\Core\Worker;
use Friendica\Factory;
use Friendica\Util\BasePath;
use Friendica\DI;
use Psr\Log\LoggerInterface;
// Get options
$shortopts = 'sn';
@ -31,22 +47,21 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) {
require dirname(__DIR__) . '/vendor/autoload.php';
$basedir = BasePath::create(dirname(__DIR__), $_SERVER);
$configLoader = new Config\ConfigCacheLoader($basedir);
$config = Factory\ConfigFactory::createCache($configLoader);
$logger = Factory\LoggerFactory::create('worker', $config);
$dice = (new Dice())->addRules(include __DIR__ . '/../static/dependencies.config.php');
$dice = $dice->addRule(LoggerInterface::class,['constructParams' => ['worker']]);
$a = new App($config, $logger);
DI::init($dice);
$a = DI::app();
// Check the database structure and possibly fixes it
Update::check($a->getBasePath(), true);
Update::check($a->getBasePath(), true, DI::mode());
// Quit when in maintenance
if (!$a->getMode()->has(App\Mode::MAINTENANCEDISABLED)) {
if (!DI::mode()->has(App\Mode::MAINTENANCEDISABLED)) {
return;
}
$a->setBaseURL(Config::get('system', 'url'));
DI::baseUrl()->saveByURL(DI::config()->get('system', 'url'));
$spawn = array_key_exists('s', $options) || array_key_exists('spawn', $options);

367
boot.php
View file

@ -1,11 +1,21 @@
<?php
/**
* @file boot.php
* This file defines some global constants and includes the central App class.
*/
/**
* Friendica
* @copyright Copyright (C) 2020, Friendica
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Friendica is a communications platform for integrated social communications
* utilising decentralised communications and linkage to several indie social
@ -17,25 +27,23 @@
* easily as email does today.
*/
use Friendica\App;
use Friendica\BaseObject;
use Friendica\Core\Config;
use Friendica\Core\PConfig;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\DI;
use Friendica\Model\Contact;
use Friendica\Model\Notify;
use Friendica\Util\BasePath;
use Friendica\Util\DateTimeFormat;
define('FRIENDICA_PLATFORM', 'Friendica');
define('FRIENDICA_CODENAME', 'The Tazmans Flax-lily');
define('FRIENDICA_VERSION', '2019.03-dev');
define('FRIENDICA_CODENAME', 'Red Hot Poker');
define('FRIENDICA_VERSION', '2020.09-dev');
define('DFRN_PROTOCOL_VERSION', '2.23');
define('NEW_UPDATE_ROUTINE_VERSION', 1170);
/**
* @brief Constant with a HTML line break.
* Constant with a HTML line break.
*
* Contains a HTML line break (br) element and a real carriage return with line
* feed for the source.
@ -44,7 +52,7 @@ define('NEW_UPDATE_ROUTINE_VERSION', 1170);
define('EOL', "<br />\r\n");
/**
* @brief Image storage quality.
* Image storage quality.
*
* Lower numbers save space at cost of image detail.
* For ease of upgrade, please do not change here. Set system.jpegquality = n in config/local.config.php,
@ -81,17 +89,6 @@ define('MAX_IMAGE_LENGTH', -1);
*/
define('DEFAULT_DB_ENGINE', 'InnoDB');
/**
* @name SSL Policy
*
* SSL redirection policies
* @{
*/
define('SSL_POLICY_NONE', 0);
define('SSL_POLICY_FULL', 1);
define('SSL_POLICY_SELFSIGN', 2);
/* @}*/
/** @deprecated since version 2019.03, please use \Friendica\Module\Register::CLOSED instead */
define('REGISTER_CLOSED', \Friendica\Module\Register::CLOSED);
/** @deprecated since version 2019.03, please use \Friendica\Module\Register::APPROVE instead */
@ -153,111 +150,31 @@ define('MAX_LIKERS', 75);
* Email notification options
* @{
*/
define('NOTIFY_INTRO', 1);
define('NOTIFY_CONFIRM', 2);
define('NOTIFY_WALL', 4);
define('NOTIFY_COMMENT', 8);
define('NOTIFY_MAIL', 16);
define('NOTIFY_SUGGEST', 32);
define('NOTIFY_PROFILE', 64);
define('NOTIFY_TAGSELF', 128);
define('NOTIFY_TAGSHARE', 256);
define('NOTIFY_POKE', 512);
define('NOTIFY_SHARE', 1024);
/** @deprecated since 2020.03, use Notify\Type::INTRO instead */
define('NOTIFY_INTRO', Notify\Type::INTRO);
/** @deprecated since 2020.03, use Notify\Type::CONFIRM instead */
define('NOTIFY_CONFIRM', Notify\Type::CONFIRM);
/** @deprecated since 2020.03, use Notify\Type::WALL instead */
define('NOTIFY_WALL', Notify\Type::WALL);
/** @deprecated since 2020.03, use Notify\Type::COMMENT instead */
define('NOTIFY_COMMENT', Notify\Type::COMMENT);
/** @deprecated since 2020.03, use Notify\Type::MAIL instead */
define('NOTIFY_MAIL', Notify\Type::MAIL);
/** @deprecated since 2020.03, use Notify\Type::SUGGEST instead */
define('NOTIFY_SUGGEST', Notify\Type::SUGGEST);
/** @deprecated since 2020.03, use Notify\Type::PROFILE instead */
define('NOTIFY_PROFILE', Notify\Type::PROFILE);
/** @deprecated since 2020.03, use Notify\Type::TAG_SELF instead */
define('NOTIFY_TAGSELF', Notify\Type::TAG_SELF);
/** @deprecated since 2020.03, use Notify\Type::TAG_SHARE instead */
define('NOTIFY_TAGSHARE', Notify\Type::TAG_SHARE);
/** @deprecated since 2020.03, use Notify\Type::POKE instead */
define('NOTIFY_POKE', Notify\Type::POKE);
/** @deprecated since 2020.03, use Notify\Type::SHARE instead */
define('NOTIFY_SHARE', Notify\Type::SHARE);
define('SYSTEM_EMAIL', 16384);
define('NOTIFY_SYSTEM', 32768);
/* @}*/
/**
* @name Term
*
* Tag/term types
* @{
*/
define('TERM_UNKNOWN', 0);
define('TERM_HASHTAG', 1);
define('TERM_MENTION', 2);
define('TERM_CATEGORY', 3);
define('TERM_PCATEGORY', 4);
define('TERM_FILE', 5);
define('TERM_SAVEDSEARCH', 6);
define('TERM_CONVERSATION', 7);
define('TERM_OBJ_POST', 1);
define('TERM_OBJ_PHOTO', 2);
/**
* @name Namespaces
*
* Various namespaces we may need to parse
* @{
*/
define('NAMESPACE_ZOT', 'http://purl.org/zot');
define('NAMESPACE_DFRN', 'http://purl.org/macgirvin/dfrn/1.0');
define('NAMESPACE_THREAD', 'http://purl.org/syndication/thread/1.0');
define('NAMESPACE_TOMB', 'http://purl.org/atompub/tombstones/1.0');
define('NAMESPACE_ACTIVITY', 'http://activitystrea.ms/spec/1.0/');
define('NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/');
define('NAMESPACE_MEDIA', 'http://purl.org/syndication/atommedia');
define('NAMESPACE_SALMON_ME', 'http://salmon-protocol.org/ns/magic-env');
define('NAMESPACE_OSTATUSSUB', 'http://ostatus.org/schema/1.0/subscribe');
define('NAMESPACE_GEORSS', 'http://www.georss.org/georss');
define('NAMESPACE_POCO', 'http://portablecontacts.net/spec/1.0');
define('NAMESPACE_FEED', 'http://schemas.google.com/g/2010#updates-from');
define('NAMESPACE_OSTATUS', 'http://ostatus.org/schema/1.0');
define('NAMESPACE_STATUSNET', 'http://status.net/schema/api/1/');
define('NAMESPACE_ATOM1', 'http://www.w3.org/2005/Atom');
define('NAMESPACE_MASTODON', 'http://mastodon.social/schema/1.0');
/* @}*/
/**
* @name Activity
*
* Activity stream defines
* @{
*/
define('ACTIVITY_LIKE', NAMESPACE_ACTIVITY_SCHEMA . 'like');
define('ACTIVITY_DISLIKE', NAMESPACE_DFRN . '/dislike');
define('ACTIVITY_ATTEND', NAMESPACE_ZOT . '/activity/attendyes');
define('ACTIVITY_ATTENDNO', NAMESPACE_ZOT . '/activity/attendno');
define('ACTIVITY_ATTENDMAYBE', NAMESPACE_ZOT . '/activity/attendmaybe');
define('ACTIVITY_OBJ_HEART', NAMESPACE_DFRN . '/heart');
define('ACTIVITY_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'make-friend');
define('ACTIVITY_REQ_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'request-friend');
define('ACTIVITY_UNFRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'remove-friend');
define('ACTIVITY_FOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'follow');
define('ACTIVITY_UNFOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'stop-following');
define('ACTIVITY_JOIN', NAMESPACE_ACTIVITY_SCHEMA . 'join');
define('ACTIVITY_POST', NAMESPACE_ACTIVITY_SCHEMA . 'post');
define('ACTIVITY_UPDATE', NAMESPACE_ACTIVITY_SCHEMA . 'update');
define('ACTIVITY_TAG', NAMESPACE_ACTIVITY_SCHEMA . 'tag');
define('ACTIVITY_FAVORITE', NAMESPACE_ACTIVITY_SCHEMA . 'favorite');
define('ACTIVITY_UNFAVORITE', NAMESPACE_ACTIVITY_SCHEMA . 'unfavorite');
define('ACTIVITY_SHARE', NAMESPACE_ACTIVITY_SCHEMA . 'share');
define('ACTIVITY_DELETE', NAMESPACE_ACTIVITY_SCHEMA . 'delete');
define('ACTIVITY_POKE', NAMESPACE_ZOT . '/activity/poke');
define('ACTIVITY_OBJ_BOOKMARK', NAMESPACE_ACTIVITY_SCHEMA . 'bookmark');
define('ACTIVITY_OBJ_COMMENT', NAMESPACE_ACTIVITY_SCHEMA . 'comment');
define('ACTIVITY_OBJ_NOTE', NAMESPACE_ACTIVITY_SCHEMA . 'note');
define('ACTIVITY_OBJ_PERSON', NAMESPACE_ACTIVITY_SCHEMA . 'person');
define('ACTIVITY_OBJ_IMAGE', NAMESPACE_ACTIVITY_SCHEMA . 'image');
define('ACTIVITY_OBJ_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'photo');
define('ACTIVITY_OBJ_VIDEO', NAMESPACE_ACTIVITY_SCHEMA . 'video');
define('ACTIVITY_OBJ_P_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'profile-photo');
define('ACTIVITY_OBJ_ALBUM', NAMESPACE_ACTIVITY_SCHEMA . 'photo-album');
define('ACTIVITY_OBJ_EVENT', NAMESPACE_ACTIVITY_SCHEMA . 'event');
define('ACTIVITY_OBJ_GROUP', NAMESPACE_ACTIVITY_SCHEMA . 'group');
define('ACTIVITY_OBJ_TAGTERM', NAMESPACE_DFRN . '/tagterm');
define('ACTIVITY_OBJ_PROFILE', NAMESPACE_DFRN . '/profile');
define('ACTIVITY_OBJ_QUESTION', 'http://activityschema.org/object/question');
/** @deprecated since 2020.12, use Notify\Type::SYSTEM instead */
define('NOTIFY_SYSTEM', Notify\Type::SYSTEM);
/* @}*/
/**
@ -312,70 +229,7 @@ if (!defined('CURLE_OPERATION_TIMEDOUT')) {
}
/**
* @brief Retrieve the App structure
*
* Useful in functions which require it but don't get it passed to them
*
* @deprecated since version 2018.09
* @see BaseObject::getApp()
* @return App
*/
function get_app()
{
return BaseObject::getApp();
}
/**
* Return the provided variable value if it exists and is truthy or the provided
* default value instead.
*
* Works with initialized variables and potentially uninitialized array keys
*
* Usages:
* - defaults($var, $default)
* - defaults($array, 'key', $default)
*
* @param array $args
* @brief Returns a defaut value if the provided variable or array key is falsy
* @return mixed
*/
function defaults(...$args)
{
if (count($args) < 2) {
throw new BadFunctionCallException('defaults() requires at least 2 parameters');
}
if (count($args) > 3) {
throw new BadFunctionCallException('defaults() cannot use more than 3 parameters');
}
if (count($args) === 3 && is_null($args[1])) {
throw new BadFunctionCallException('defaults($arr, $key, $def) $key is null');
}
// The default value always is the last argument
$return = array_pop($args);
if (count($args) == 2 && is_array($args[0]) && !empty($args[0][$args[1]])) {
$return = $args[0][$args[1]];
}
if (count($args) == 1 && !empty($args[0])) {
$return = $args[0];
}
return $return;
}
/**
* @brief Used to end the current process, after saving session state.
* @deprecated
*/
function killme()
{
exit();
}
/**
* @brief Returns the user id of locally logged in user or false.
* Returns the user id of locally logged in user or false.
*
* @return int|bool user id or false
*/
@ -388,7 +242,7 @@ function local_user()
}
/**
* @brief Returns the public contact id of logged in user or false.
* Returns the public contact id of logged in user or false.
*
* @return int|bool public contact id or false
*/
@ -399,10 +253,10 @@ function public_contact()
if (!$public_contact_id && !empty($_SESSION['authenticated'])) {
if (!empty($_SESSION['my_address'])) {
// Local user
$public_contact_id = intval(Contact::getIdForURL($_SESSION['my_address'], 0, true));
$public_contact_id = intval(Contact::getIdForURL($_SESSION['my_address'], 0, false));
} elseif (!empty($_SESSION['visitor_home'])) {
// Remote user
$public_contact_id = intval(Contact::getIdForURL($_SESSION['visitor_home'], 0, true));
$public_contact_id = intval(Contact::getIdForURL($_SESSION['visitor_home'], 0, false));
}
} elseif (empty($_SESSION['authenticated'])) {
$public_contact_id = false;
@ -412,31 +266,25 @@ function public_contact()
}
/**
* @brief Returns contact id of authenticated site visitor or false
* Returns public contact id of authenticated site visitor or false
*
* @return int|bool visitor_id or false
*/
function remote_user()
{
// 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 (empty($_SESSION)) {
if (empty($_SESSION['authenticated'])) {
return false;
}
if (!empty($_SESSION['authenticated']) && !empty($_SESSION['visitor_id'])) {
if (!empty($_SESSION['visitor_id'])) {
return intval($_SESSION['visitor_id']);
}
return false;
}
/**
* @brief Show an error message to user.
* Show an error message to user.
*
* This function save text in session, to be shown to the user at next page load
*
@ -448,7 +296,7 @@ function notice($s)
return;
}
$a = \get_app();
$a = DI::app();
if (empty($_SESSION['sysmsg'])) {
$_SESSION['sysmsg'] = [];
}
@ -458,7 +306,7 @@ function notice($s)
}
/**
* @brief Show an info message to user.
* Show an info message to user.
*
* This function save text in session, to be shown to the user at next page load
*
@ -466,11 +314,7 @@ function notice($s)
*/
function info($s)
{
$a = \get_app();
if (local_user() && PConfig::get(local_user(), 'system', 'ignore_info')) {
return;
}
$a = DI::app();
if (empty($_SESSION['sysmsg_info'])) {
$_SESSION['sysmsg_info'] = [];
@ -504,7 +348,7 @@ function feed_birthday($uid, $tz)
$tz = 'UTC';
}
$profile = DBA::selectFirst('profile', ['dob'], ['is-default' => true, 'uid' => $uid]);
$profile = DBA::selectFirst('profile', ['dob'], ['uid' => $uid]);
if (DBA::isResult($profile)) {
$tmp_dob = substr($profile['dob'], 5);
if (intval($tmp_dob)) {
@ -523,52 +367,19 @@ function feed_birthday($uid, $tz)
}
/**
* @brief Check if current user has admin role.
* Check if current user has admin role.
*
* @return bool true if user is an admin
*/
function is_site_admin()
{
$a = \get_app();
$a = DI::app();
$admin_email = Config::get('config', 'admin_email');
$admin_email = DI::config()->get('config', 'admin_email');
$adminlist = explode(',', str_replace(' ', '', $admin_email));
return local_user() && $admin_email && in_array(defaults($a->user, 'email', ''), $adminlist);
}
/**
* @brief Returns querystring as string from a mapped array.
*
* @param array $params mapped array with query parameters
* @param string $name of parameter, default null
*
* @return string
*/
function build_querystring($params, $name = null)
{
$ret = "";
foreach ($params as $key => $val) {
if (is_array($val)) {
/// @TODO maybe not compare against null, use is_null()
if ($name == null) {
$ret .= build_querystring($val, $key);
} else {
$ret .= build_querystring($val, $name . "[$key]");
}
} else {
$val = urlencode($val);
/// @TODO maybe not compare against null, use is_null()
if ($name != null) {
/// @TODO two string concated, can be merged to one
$ret .= $name . "[$key]" . "=$val&";
} else {
$ret .= "$key=$val&";
}
}
}
return $ret;
return local_user() && $admin_email && in_array($a->user['email'] ?? '', $adminlist);
}
function explode_querystring($query)
@ -625,22 +436,9 @@ function curPageURL()
return $pageURL;
}
function get_server()
{
$server = Config::get("system", "directory");
if ($server == "") {
$server = "https://dir.friendica.social";
}
return $server;
}
function get_temppath()
{
$a = \get_app();
$temppath = Config::get("system", "temppath");
$temppath = DI::config()->get("system", "temppath");
if (($temppath != "") && System::isDirectoryUsable($temppath)) {
// We have a temp path and it is usable
@ -656,7 +454,7 @@ function get_temppath()
$temppath = BasePath::getRealPath($temppath);
// To avoid any interferences with other systems we create our own directory
$new_temppath = $temppath . "/" . $a->getHostName();
$new_temppath = $temppath . "/" . DI::baseUrl()->getHostname();
if (!is_dir($new_temppath)) {
/// @TODO There is a mkdir()+chmod() upwards, maybe generalize this (+ configurable) into a function/method?
mkdir($new_temppath);
@ -664,7 +462,7 @@ function get_temppath()
if (System::isDirectoryUsable($new_temppath)) {
// The new path is usable, we are happy
Config::set("system", "temppath", $new_temppath);
DI::config()->set("system", "temppath", $new_temppath);
return $new_temppath;
} else {
// We can't create a subdirectory, strange.
@ -714,7 +512,7 @@ function clear_cache($basepath = "", $path = "")
return;
}
$cachetime = (int) Config::get('system', 'itemcache_duration');
$cachetime = (int) DI::config()->get('system', 'itemcache_duration');
if ($cachetime == 0) {
$cachetime = 86400;
}
@ -738,12 +536,12 @@ function clear_cache($basepath = "", $path = "")
function get_itemcachepath()
{
// Checking, if the cache is deactivated
$cachetime = (int) Config::get('system', 'itemcache_duration');
$cachetime = (int) DI::config()->get('system', 'itemcache_duration');
if ($cachetime < 0) {
return "";
}
$itemcache = Config::get('system', 'itemcache');
$itemcache = DI::config()->get('system', 'itemcache');
if (($itemcache != "") && System::isDirectoryUsable($itemcache)) {
return BasePath::getRealPath($itemcache);
}
@ -757,7 +555,7 @@ function get_itemcachepath()
}
if (System::isDirectoryUsable($itemcache)) {
Config::set("system", "itemcache", $itemcache);
DI::config()->set("system", "itemcache", $itemcache);
return $itemcache;
}
}
@ -765,13 +563,13 @@ function get_itemcachepath()
}
/**
* @brief Returns the path where spool files are stored
* Returns the path where spool files are stored
*
* @return string Spool path
*/
function get_spoolpath()
{
$spoolpath = Config::get('system', 'spoolpath');
$spoolpath = DI::config()->get('system', 'spoolpath');
if (($spoolpath != "") && System::isDirectoryUsable($spoolpath)) {
// We have a spool path and it is usable
return $spoolpath;
@ -789,7 +587,7 @@ function get_spoolpath()
if (System::isDirectoryUsable($spoolpath)) {
// The new path is usable, we are happy
Config::set("system", "spoolpath", $spoolpath);
DI::config()->set("system", "spoolpath", $spoolpath);
return $spoolpath;
} else {
// We can't create a subdirectory, strange.
@ -841,22 +639,3 @@ function validate_include(&$file)
// Simply return flag
return $valid;
}
/**
* PHP 5 compatible dirname() with count parameter
*
* @see http://php.net/manual/en/function.dirname.php#113193
*
* @deprecated with PHP 7
* @param string $path
* @param int $levels
* @return string
*/
function rdirname($path, $levels = 1)
{
if ($levels > 1) {
return dirname(rdirname($path, --$levels));
} else {
return dirname($path);
}
}

View file

@ -13,7 +13,7 @@
"issues": "https://github.com/friendica/friendica/issues"
},
"require": {
"php": ">=5.6.1",
"php": ">=7.0",
"ext-ctype": "*",
"ext-curl": "*",
"ext-dom": "*",
@ -27,30 +27,43 @@
"ext-simplexml": "*",
"ext-xml": "*",
"asika/simple-console": "^1.0",
"divineomega/password_exposed": "^2.4",
"ezyang/htmlpurifier": "~4.7.0",
"bacon/bacon-qr-code": "^1.0",
"divineomega/password_exposed": "^2.8",
"ezyang/htmlpurifier": "^4.7",
"friendica/json-ld": "^1.0",
"league/html-to-markdown": "~4.8.0",
"league/html-to-markdown": "^4.8",
"level-2/dice": "^4",
"lightopenid/lightopenid": "dev-master",
"michelf/php-markdown": "^1.7",
"mobiledetect/mobiledetectlib": "2.8.*",
"paragonie/random_compat": "^2.0",
"pear/Text_LanguageDetect": "1.*",
"mobiledetect/mobiledetectlib": "^2.8",
"monolog/monolog": "^1.25",
"nikic/fast-route": "^1.3",
"paragonie/hidden-string": "^1.0",
"pear/console_table": "^1.3",
"pear/text_languagedetect": "1.*",
"pragmarx/google2fa": "^5.0",
"pragmarx/recovery": "^0.1.0",
"psr/container": "^1.0",
"seld/cli-prompt": "^1.0",
"smarty/smarty": "^3.1",
"fxp/composer-asset-plugin": "~1.3",
"fxp/composer-asset-plugin": "^1.4",
"bower-asset/base64": "^1.0",
"bower-asset/Chart-js": "^2.7",
"bower-asset/perfect-scrollbar": "^0.6",
"bower-asset/vue": "^2.5",
"bower-asset/chart-js": "^2.8",
"bower-asset/dompurify": "^1.0",
"bower-asset/fork-awesome": "^1.1",
"bower-asset/vue": "^2.6",
"npm-asset/cropperjs": "1.2.2",
"npm-asset/es-jquery-sortable": "^0.9.13",
"npm-asset/fullcalendar": "^3.10",
"npm-asset/imagesloaded": "4.1.4",
"npm-asset/jquery": "^2.0",
"npm-asset/jquery-colorbox": "^1.6",
"npm-asset/jquery-datetimepicker": "^2.4.0",
"npm-asset/jquery-datetimepicker": "^2.5",
"npm-asset/jgrowl": "^1.4",
"npm-asset/fullcalendar": "^3.0.1",
"npm-asset/cropperjs": "1.2.2",
"npm-asset/imagesloaded": "4.1.4",
"monolog/monolog": "^1.24"
"npm-asset/moment": "^2.24",
"npm-asset/perfect-scrollbar": "0.6.16",
"npm-asset/textcomplete": "^0.18.2",
"npm-asset/typeahead.js": "^0.11.1"
},
"repositories": [
{
@ -61,7 +74,6 @@
"autoload": {
"psr-4": {
"Friendica\\": "src/",
"Friendica\\Test\\": "tests/",
"Friendica\\Addon\\": "addon/"
},
"psr-0": {
@ -71,12 +83,18 @@
"include/conversation.php",
"include/dba.php",
"include/enotify.php",
"include/items.php",
"include/text.php",
"boot.php"
]
},
"autoload-dev": {
"psr-4": {
"Friendica\\Test\\": "tests/"
}
},
"config": {
"platform": {
"php": "7.0"
},
"autoloader-suffix": "Friendica",
"optimize-autoloader": true,
"preferred-install": "dist",
@ -89,16 +107,28 @@
},
"archive": {
"exclude": [
"log", "cache", "/photo", "/proxy"
"/.*",
"/*file",
"!/.htaccess-dist",
"/tests",
"/*.xml",
"/composer.*",
"/log",
"/cache",
"/photo",
"/proxy",
"/addon",
"!/vendor",
"!/view/asset"
]
},
"require-dev": {
"phpunit/dbunit": "^2.0",
"phpdocumentor/reflection-docblock": "^3.0.2",
"phpunit/php-token-stream": "^1.4.2",
"mikey179/vfsStream": "^1.6",
"mikey179/vfsstream": "^1.6",
"mockery/mockery": "^1.2",
"johnkary/phpunit-speedtrap": "1.1"
"johnkary/phpunit-speedtrap": "1.1",
"jakub-onderka/php-parallel-lint": "^1.0"
},
"scripts": {
"test": "phpunit"

1870
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,7 @@
*
* Then set the following for your MySQL installation
*
* If you're unsure about what any of the config keys below do, please check the config/defaults.config.php file for
* If you're unsure about what any of the config keys below do, please check the static/defaults.config.php file for
* detailed documentation of their data type and behavior.
*/

File diff suppressed because it is too large Load diff

1449
doc/API-Entities.md Normal file

File diff suppressed because it is too large Load diff

703
doc/API-Friendica.md Normal file
View file

@ -0,0 +1,703 @@
# Friendica API
* [Home](help)
* [Using the APIs](help/api)
## Overview
Friendica provides the following specific endpoints.
Authentication is the same as described in [Using the APIs](help/api#Authentication).
## Entities
These endpoints uses the [Friendica API entities](help/API-Entities).
## Endpoints
### GET api/friendica/events
Returns a list of [Event](help/API-Entities#Event) entities for the current logged in user.
#### Parameters
- `since_id`: (optional) minimum event id for pagination
- `count`: maximum number of items returned, default 20
### GET api/externalprofile/show
Returns a [Contact](help/API-Entities#Contact) entity for the provided profile URL.
#### Parameters
- `profileurl`: Profile URL
### GET api/statuses/public_timeline
Returns a list of public [Items](help/API-Entities#Item) posted on this node.
Equivalent of the local community page.
#### Parameters
* `count`: Items per page (default: 20)
* `page`: page number
* `since_id`: minimum id
* `max_id`: maximum id
* `exclude_replies`: don't show replies (default: false)
* `conversation_id`: Shows all statuses of a given conversation.
* `include_entities`: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* `trim_user`
### GET api/statuses/networkpublic_timeline
Returns a list of public [Items](help/API-Entities#Item) this node is aware of.
Equivalent of the global community page.
#### Parameters
* `count`: Items per page (default: 20)
* `page`: page number
* `since_id`: minimum id
* `max_id`: maximum id
* `exclude_replies`: don't show replies (default: false)
* `conversation_id`: Shows all statuses of a given conversation.
* `include_entities`: "true" shows entities for pictures and links (Default: false)
### GET api/statuses/replies
#### Parameters
* `count`: Items per page (default: 20)
* `page`: page number
* `since_id`: minimum id
* `max_id`: maximum id
* `include_entities`: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* `include_rts`
* `trim_user`
* `contributor_details`
---
### GET api/conversation/show
Unofficial Twitter command. It shows all direct answers (excluding the original post) to a given id.
#### Parameters
* `id`: id of the post
* `count`: Items per page (default: 20)
* `page`: page number
* `since_id`: minimum id
* `max_id`: maximum id
* `include_entities`: "true" shows entities for pictures and links (Default: false)
#### Unsupported parameters
* `include_rts`
* `trim_user`
* `contributor_details`
### GET api/statusnet/conversation
Alias of [`api/conversation/show`](#GET+api%2Fconversation%2Fshow).
### GET api/statusnet/config
Returns the public Friendica node configuration.
### GET api/gnusocial/config
Alias of [`api/statusnet/config`](#GET+api%2Fstatusnet%2Fconfig).
### GET api/statusnet/version
Returns a fake static StatusNet protocol version.
### GET api/gnusocial/version
Alias of [`api/statusnet/version`](#GET+api%2Fstatusnet%2Fversion).
---
### POST api/friendica/activity/[verb]
Add or remove an activity from an item.
'verb' can be one of:
* `like`
* `dislike`
* `attendyes`
* `attendno`
* `attendmaybe`
To remove an activity, prepend the verb with "un", eg. "unlike" or "undislike"
Attend verbs disable eachother: that means that if "attendyes" was added to an item, adding "attendno" remove previous "attendyes".
Attend verbs should be used only with event-related items (there is no check at the moment).
#### Parameters
* `id`: item id
#### Return values
On success:
json:
```"ok"```
xml:
```<ok>true</ok>```
On error:
HTTP 400 BadRequest
---
### GET api/direct_messages
Deprecated Twitter received direct message list endpoint.
#### Parameters
* `count`: Items per page (default: 20)
* `page`: page number
* `since_id`: minimum id
* `max_id`: maximum id
* `getText`: Defines the format of the status field. Can be "html" or "plain"
* `include_entities`: "true" shows entities for pictures and links (Default: false)
* `friendica_verbose`: "true" enables different error returns (default: "false")
#### Unsupported parameters
* `skip_status`
### GET api/direct_messages/all
Returns all [Private Messages](help/API-Entities#Private+message).
#### Parameters
* `count`: Items per page (default: 20)
* `page`: page number
* `since_id`: minimum id
* `max_id`: maximum id
* `getText`: Defines the format of the status field. Can be "html" or "plain"
* `friendica_verbose`: "true" enables different error returns (default: "false")
### GET api/direct_messages/conversation
Returns all replies of a single private message conversation. Returns [Private Messages](help/API-Entities#Private+message)
#### Parameters
* `count`: Items per page (default: 20)
* `page`: page number
* `since_id`: minimum id
* `max_id`: maximum id
* `getText`: Defines the format of the status field. Can be "html" or "plain"
* `uri`: URI of the conversation
* `friendica_verbose`: "true" enables different error returns (default: "false")
### GET api/direct_messages/sent
Deprecated Twitter sent direct message list endpoint. Returns [Private Messages](help/API-Entities#Private+message).
#### Parameters
* `count`: Items per page (default: 20)
* `page`: page number
* `since_id`: minimum id
* `max_id`: maximum id
* `getText`: Defines the format of the status field. Can be "html" or "plain"
* `include_entities`: "true" shows entities for pictures and links (Default: false)
* `friendica_verbose`: "true" enables different error returns (default: "false")
### POST/PUT api/direct_messages/new
Deprecated Twitter direct message submission endpoint.
#### Parameters
* `user_id`: id of the user
* `screen_name`: screen name (for technical reasons, this value is not unique!)
* `text`: The message
* `replyto`: ID of the replied direct message
* `title`: Title of the direct message
### POST/DELETE api/direct_messages/destroy
Deprecated Twitter direct message deletion endpoint.
#### Parameters
* `id`: id of the message to be deleted
* `include_entities`: optional, currently not yet implemented
* `friendica_parenturi`: optional, can be used for increased safety to delete only intended messages
* `friendica_verbose`: "true" enables different error returns (default: "false")
#### Return values
On success:
* JSON return as defined for Twitter API not yet implemented
* on friendica_verbose=true: JSON return {"result":"ok","message":"message deleted"}
On error:
HTTP 400 BadRequest
* on friendica_verbose=true: different JSON returns {"result":"error","message":"xyz"}
### GET api/friendica/direct_messages_setseen
#### Parameters
* `id`: id of the message to be updated as seen
#### Return values
On success:
* JSON return `{"result": "ok", "message": "message set to seen"}`
On error:
* different JSON returns `{"result": "error", "message": "xyz"}`
### GET api/friendica/direct_messages_search (GET; AUTH)
Returns [Private Messages](help/API-Entities#Private+message) matching the provided search string.
#### Parameters
* `searchstring`: string for which the API call should search as '%searchstring%' in field 'body' of all messages of the authenticated user (caption ignored)
* `getText` (optional): `plain`|`html` If ommited, the title is prepended to the plaintext body in the `text` attribute of the private message objects.
* `getUserObjects` (optional): `true`|`false` If `false`, the `sender` and `recipient` attributes of the private message object are absent.
#### Return values
Returns only tested with JSON, XML might work as well.
On success:
* JSON return `{"success":"true", "search_results": array of found messages}`
* JSOn return `{"success":"false", "search_results": "nothing found"}`
On error:
* different JSON returns `{"result": "error", "message": "searchstring not specified"}`
---
### GET api/friendica/group_show
Return all or a specified group of the user with the containing contacts as array.
#### Parameters
* `gid`: optional, if not given, API returns all groups of the user
#### Return values
Array of:
* `name`: name of the group
* `gid`: id of the group
* `user`: array of [Contacts](help/API-Entities#Contact)
### POST/PUT api/friendica/group_create
Create the group with the posted array of contacts as members.
#### Parameters
* `name`: name of the group to be created
#### POST data
JSON data as Array like the result of [GET api/friendica/group_show](#GET+api%2Ffriendica%2Fgroup_show):
* `gid`
* `name`
* List of [Contacts](help/API-Entities#Contact)
#### Return values
Array of:
* `success`: true if successfully created or reactivated
* `gid`: gid of the created group
* `name`: name of the created group
* `status`: "missing user" | "reactivated" | "ok"
* `wrong users`: array of users, which were not available in the contact table
### POST api/friendica/group_update
Update the group with the posted array of contacts as members (post all members of the group to the call; function will remove members not posted).
#### Parameters
* `gid`: id of the group to be changed
* `name`: name of the group to be changed
#### POST data
JSON data as array like the result of [GET api/friendica/group_show](#GET+api%2Ffriendica%2Fgroup_show):
* `gid`
* `name`
* List of [Contacts](help/API-Entities#Contact)
#### Return values
Array of:
* `success`: true if successfully updated
* `gid`: gid of the changed group
* `name`: name of the changed group
* `status`: "missing user" | "ok"
* `wrong users`: array of users, which were not available in the contact table
### POST/DELETE api/friendica/group_delete
Delete the specified group of contacts; API call need to include the correct gid AND name of the group to be deleted.
#### Parameters
* `gid`: id of the group to be deleted
* `name`: name of the group to be deleted
#### Return values
Array of:
* `success`: true if successfully deleted
* `gid`: gid of the deleted group
* `name`: name of the deleted group
* `status`: "deleted" if successfully deleted
* `wrong users`: empty array
---
### GET api/friendica/notifications
Return last 50 [Notifications](help/API-Entities#Notification) for the current user, ordered by date with unseen item on top.
#### Parameters
none
### POST api/friendica/notifications/seen
Set notification as seen.
#### Parameters
- `id`: id of the notification to set seen
#### Return values
If the note is linked to an item, returns an [Item](help/API-Entities#Item).
Otherwise, a success status is returned:
* `success` (json) | `<status>success</status>` (xml)
---
### GET api/friendica/photo
Returns a [Photo](help/API-Entities#Photo).
#### Parameters
* `photo_id`: Resource id of a photo.
* `scale`: (optional) scale value of the photo
Returns data of a picture with the given resource.
If 'scale' isn't provided, returned data include full url to each scale of the photo.
If 'scale' is set, returned data include image data base64 encoded.
possibile scale value are:
* 0: original or max size by server settings
* 1: image with or height at <= 640
* 2: image with or height at <= 320
* 3: thumbnail 160x160
* 4: Profile image at 300x300
* 5: Profile image at 80x80
* 6: Profile image at 48x48
An image used as profile image has only scale 4-6, other images only 0-3
#### Return values
json:
```json
{
"id": "photo id",
"created": "date(YYYY-MM-DD HH:MM:SS)",
"edited": "date(YYYY-MM-DD HH:MM:SS)",
"title": "photo title",
"desc": "photo description",
"album": "album name",
"filename": "original file name",
"type": "mime type",
"height": "number",
"width": "number",
"profile": "1 if is profile photo",
"link": {
"<scale>": "url to image",
...
},
// if 'scale' is set
"datasize": "size in byte",
"data": "base64 encoded image data"
}
```
xml:
```xml
<photo>
<id>photo id</id>
<created>date(YYYY-MM-DD HH:MM:SS)</created>
<edited>date(YYYY-MM-DD HH:MM:SS)</edited>
<title>photo title</title>
<desc>photo description</desc>
<album>album name</album>
<filename>original file name</filename>
<type>mime type</type>
<height>number</height>
<width>number</width>
<profile>1 if is profile photo</profile>
<links type="array">
<link type="mime type" scale="scale number" href="image url"/>
...
</links>
</photo>
```
### GET api/friendica/photos/list
Returns the API user's [Photo List Items](help/API-Entities#Photo+List+Item).
#### Return values
json:
```json
[
{
"id": "resource_id",
"album": "album name",
"filename": "original file name",
"type": "image mime type",
"thumb": "url to thumb sized image"
},
...
]
```
xml:
```xml
<photos type="array">
<photo id="resource_id"
album="album name"
filename="original file name"
type="image mime type">
"url to thumb sized image"
</photo>
...
</photos>
```
### POST api/friendica/photo/create
Alias of [`api/friendica/photo/update`](#POST+api%2Ffriendica%2Fphoto%2Fupdate)
### POST api/friendica/photo/update
Saves data for the scales 0-2 to database (see above for scale description).
Call adds non-public entries to items table to enable authenticated contacts to comment/like the photo.
Client should pay attention to the fact that updated access rights are not transferred to the contacts. i.e. public photos remain publicly visible if they have been commented/liked before setting visibility back to a limited group.
Currently it is best to inform user that updating rights is not the right way to do this, and offer a solution to add photo as a new photo with the new rights instead.
#### Parameters
* `photo_id` (optional): if specified the photo with this id will be updated
* `media` (optional): image data as base64, only optional if photo_id is specified (new upload must have media)
* `desc` (optional): description for the photo, updated when photo_id is specified
* `album`: name of the album to be deleted (always necessary)
* `album_new` (optional): can be used to change the album of a single photo if photo_id is specified
* `allow_cid`/`allow_gid`/`deny_cid`/`deny_gid` (optional):
- on create: empty string or omitting = public photo, specify in format ```<x><y><z>``` for private photo
- on update: keys need to be present with empty values for changing a private photo to public
#### Return values
On success:
* new photo uploaded: JSON return with photo data (see [GET api/friendica/photo](#GET+api%2Ffriendica%2Fphoto))
* photo updated - changed photo data: JSON return with photo data (see [GET api/friendica/photo](#GET+api%2Ffriendica%2Fphoto))
* photo updated - changed info: JSON return `{"result": "updated", "message":"Image id 'xyz' has been updated."}`
* photo updated - nothing changed: JSON return `{"result": "cancelled","message": "Nothing to update for image id 'xyz'."}`
On error:
* 403 FORBIDDEN: if not authenticated
* 400 BADREQUEST: "no albumname specified", "no media data submitted", "photo not available", "acl data invalid"
* 500 INTERNALSERVERERROR: "image size exceeds PHP config settings, file was rejected by server",
"image size exceeds Friendica Config setting (uploaded size: x)",
"unable to process image data",
"image upload failed",
"unknown error - uploading photo failed, see Friendica log for more information",
"unknown error - update photo entry in database failed",
"unknown error - this error on uploading or updating a photo should never happen"
### DELETE api/friendica/photo/delete
Deletes a single image with the specified id, is not reversible -> ensure that client is asking user for being sure to do this
Sets item table entries for this photo to deleted = 1.
#### Parameters
* `photo_id`: id of the photo to be deleted
#### Return values
On success:
* JSON return
```json
{
"result": "deleted",
"message": "photo with id 'xyz' has been deleted from server."
}
```
On error:
* 403 FORBIDDEN: if not authenticated
* 400 BADREQUEST: "no photo_id specified", "photo not available"
* 500 INTERNALSERVERERROR: "unknown error on deleting photo", "problem with deleting items occurred"
---
### POST/DELETE api/friendica/photoalbum/delete
Deletes all images with the specified album name, is not reversible -> ensure that client is asking user for being sure to do this.
#### Parameters
* `album`: name of the album to be deleted
#### Return values
On success:
* JSON return
```json
{
"result": "deleted",
"message": "album 'xyz' with all containing photos has been deleted."
}
```
On error:
* 403 FORBIDDEN: if not authenticated
* 400 BADREQUEST: "no albumname specified", "album not available"
* 500 INTERNALSERVERERROR: "problem with deleting item occured", "unknown error - deleting from database failed"
### POST/PUT api/friendica/photoalbum/update
Changes the album name to album_new for all photos in album.
#### Parameters
* `album`: name of the album to be updated
* `album_new`: new name of the album
#### Return values
On success:
* JSON return
```json
{
"result": "updated",
"message":"album 'abc' with all containing photos has been renamed to 'xyz'."
}
```
On error:
* 403 FORBIDDEN: if not authenticated
* 400 BADREQUEST: "no albumname specified", "no new albumname specified", "album not available"
* 500 INTERNALSERVERERROR: "unknown error - updating in database failed"
---
### GET api/friendica/profile/show
Returns the [Profile](help/API-Entities#Profile) data of the authenticated user.
#### Return values
On success: Array of:
* `global_dir`: URL of the global directory set in server settings
* `friendica_owner`: user data of the authenticated user
* `profiles`: array of the profile data
On error:
HTTP 403 Forbidden: when no authentication was provided
HTTP 400 Bad Request: if given profile_id is not in the database or is not assigned to the authenticated user
General description of profile data in API returns:
- hide_friends: true if friends are hidden
- profile_photo
- profile_thumb
- publish: true if published on the server's local directory
- net_publish: true if published to global_dir
- fullname
- date_of_birth
- description
- xmpp
- homepage
- address
- locality
- region
- postal_code
- country
- pub_keywords
- custom_fields: list of public custom fields
---
### GET api/friendica/remoteauth
Similar as /redir, redirects to `url` after DFRN authentication.
#### Parameters
- `c_url`: url of remote contact to auth to
- `url`: string, url to redirect after auth
## Deprecated endpoints
- POST api/statuses/mediap

81
doc/API-GNU-Social.md Normal file
View file

@ -0,0 +1,81 @@
# GNU Social API
* [Home](help)
* [Using the APIs](help/api)
## Overview
Friendica provides the following endpoints defined in [the official GNU Social Twitter-like API reference](https://gnusocial.net/doc/twitterapi).
Authentication is the same as described in [Using the APIs](help/api#Authentication).
## Entities
These endpoints use the [Friendica API entities](help/API-Entities).
## Implemented endpoints
- GET api/account/rate_limit_status
- POST api/account/update_profile_image
- GET api/account/verify_credentials
- GET api/direct_messages
- POST/DELETE api/direct_messages/destroy
- POST api/direct_messages/new
- GET api/direct_messages/sent
- GET api/favorites
- POST api/favorites/create/:id
- POST api/favorites/destroy/:id
- GET api/followers/ids
- POST api/friendships/destroy
- GET api/friends/ids
- GET/POST api/help/test
- POST api/oauth/access_token
- POST api/oauth/request_token
- GET api/search
- GET api/statuses/show/:id
- POST api/statuses/destroy/:id
- GET api/statuses/followers
- GET api/statuses/friends
- GET api/statuses/friends_timeline
- GET api/statuses/friends_timeline/:username
- GET api/statuses/home_timeline
- GET api/statuses/mentions
- GET api/statuses/replies
- GET api/statuses/replies/:username
- POST api/statuses/retweet/:id
- GET api/statuses/public_timeline
- POST api/statuses/update
- GET api/statuses/user_timeline
- GET api/users/show
## Non-implemented endpoints
- statuses/retweeted_to_me
- statuses/retweeted_by_me
- statuses/retweets_of_me
- friendships/create
- friendships/exists
- friendships/show
- account/end_session
- account/update_delivery_device
- account/update_profile_background_image
- notifications/follow
- notifications/leave
- blocks/create
- blocks/destroy
- blocks/exists
- blocks/blocking
- oauth/authorize
- statusnet/groups/timeline
- statusnet/groups/show
- statusnet/groups/create
- statusnet/groups/join
- statusnet/groups/leave
- statusnet/groups/list
- statusnet/groups/list_all
- statusnet/groups/membership
- statusnet/groups/is_member
- statusnet/tags/timeline
- statusnet/media/upload
- statusnet/config

39
doc/API-Mastodon.md Normal file
View file

@ -0,0 +1,39 @@
# Mastodon API
* [Home](help)
* [Using the APIs](help/api)
## Overview
Friendica provides the following endpoints defined in [the official Mastodon API reference](https://docs.joinmastodon.org/api/).
Authentication is the same as described in [Using the APIs](help/api#Authentication).
## Entities
These endpoints use the [Mastodon API entities](https://docs.joinmastodon.org/entities/).
## Implemented endpoints
- [`GET /api/v1/custom_emojis`](https://docs.joinmastodon.org/methods/instance/custom_emojis/)
- Doesn't return unicode emojis since they aren't using an image URL
- [`GET /api/v1/follow_requests`](https://docs.joinmastodon.org/methods/accounts/follow_requests#pending-follows)
- Returned IDs are specific to follow requests
- [`POST /api/v1/follow_requests/:id/authorize`](https://docs.joinmastodon.org/methods/accounts/follow_requests#accept-follow)
- `:id` is a follow request ID, not a regular account id
- [`POST /api/v1/follow_requests/:id/reject`](https://docs.joinmastodon.org/methods/accounts/follow_requests#reject-follow)
- `:id` is a follow request ID, not a regular account id
- `POST /api/v1/follow_requests/:id/ignore`
- Friendica-specific, hides the follow request from the list and prevents the remote contact from retrying.
- `:id` is a follow request ID, not a regular account id
- Returns a [Relationship](https://docs.joinmastodon.org/entities/relationship) object.
- [`GET /api/v1/instance`](https://docs.joinmastodon.org/methods/instance#fetch-instance)
- [`GET /api/v1/instance/peers`](https://docs.joinmastodon.org/methods/instance#list-of-connected-domains)
## Non-implemented endpoints
- [`GET /api/v1/instance/activity`](https://docs.joinmastodon.org/methods/instance#weekly-activity)

306
doc/API-Twitter.md Normal file
View file

@ -0,0 +1,306 @@
# Twitter API
* [Home](help)
* [Using the APIs](help/api)
## Overview
Friendica provides the following endpoints defined in the [official Twitter API reference](https://developer.twitter.com/en/docs/api-reference-index).
Authentication is the same as described in [Using the APIs](help/api#Authentication).
## Entities
These endpoints use the [Friendica API entities](help/API-Entities).
## Different behaviour
* `screen_name`: The nick name in Friendica is only unique in each network but not for all networks. The users are searched in the following priority: Friendica, StatusNet/GNU Social, Diaspora, pump.io, Twitter. If no contact was found by this way, then the first contact is taken.
* `include_entities`: Default is "false". If set to "true" then the plain text is formatted so that links are having descriptions.
## Friendica-specific return values
* `cid`: Contact id of the user (important for "contact_allow" and "contact_deny")
* `network`: network of the user
## Unsupported parameters
* `cursor`
* `trim_user`
* `contributor_details`
* `place_id`
* `display_coordinates`
* `include_rts`: To-Do
* `include_my_retweet`: Retweets in Friendica are implemented in a different way
## Implemented endpoints
- [POST api/oauth/access_token](https://developer.twitter.com/en/docs/basics/authentication/api-reference/access_token)
- Unsupported parameters:
- `x_auth_password`
- `x_auth_username`
- `x_auth_mode`
- [POST api/oauth/request_token](https://developer.twitter.com/en/docs/basics/authentication/api-reference/request_token)
- Unsupported parameter:
- `x_auth_access_type`
- [GET api/account/verify_credentials](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-verify_credentials)
- Unsupported parameter:
- `include_email`
- [POST api/account/update_profile](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile)
- Unsupported parameters:
- `url`
- `location`
- `profile_link_color`
- `include_entities`
- `skip_status`
- [POST api/account/update_profile_image](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_image)
- Additional parameter:
- `profile_id` (optional): Numerical id of the profile for which the image should be used, default is changing the default profile.
- [POST api/statuses/update](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update)
- Unsupported parameter:
- `display_coordinates`
- [POST api/statuses/update_with_media (deprecated)](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update_with_media)
- [POST api/media/upload](https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload)
- Additional return value:
- `image.friendica_preview_url`: image preview url
- [POST api/media/metadata/create](https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-metadata-create)
- [GET api/users/show](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-show)
- [GET api/users/search](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-search)
- Unsupported parameters:
- `page`
- `count`
- `include_entities`
- [GET api/users/lookup](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-lookup)
- Unsupported parameters:
- `screen_name`
- `include_entities`
- [GET api/search/tweets](https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets)
- Unsupported parameters:
- `geocode`
- `lang`
- `locale`
- `result_type`
- `until`
- `include_entities`
- [GET api/saved_searches/list](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-saved_searches-list)
- [GET api/statuses/home_timeline](https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline)
- Alias: `GET api/statuses/friends_timeline`
- [GET api/statuses/user_timeline](https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-user_timeline)
- [GET api/statuses/mentions (deprecated)](https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-mentions_timeline)
- [GET api/statuses/show/:id](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-show-id)
- [POST api/statuses/retweet/:id](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-retweet-id)
- [POST api/statuses/destroy/:id](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-destroy-id)
- [GET api/statuses/followers (deprecated)](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-followers-list)
- Alias: `GET api/statuses/friends`
- [GET api/favorites (deprecated)](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-favorites-list)
- Unsupported parameters:
- `user_id`: Favorites aren't returned for other users than self
- `screen_name`: Favorites aren't returned for other users than self
- [POST api/favorites/create](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-favorites-create)
- [POST api/favorites/destroy](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-favorites-destroy)
- [GET api/lists/list](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-list)
- [GET api/lists/ownerships](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-ownerships)
- Unsupported parameters:
- `slug`
- `owner_screen_name`
- `owner_id`
- `include_entities`
- [GET api/lists/statuses](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-statuses)
- Unsupported parameters:
- `screen_name`
- `count`
- [GET api/lists/subscriptions](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-subscriptions)
- [POST api/lists/update](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-update)
- Unsupported parameters:
- `slug`
- `name`
- `mode`
- `description`
- `owner_screen_name`
- `owner_id`
- [POST api/lists/create](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-create)
- Unsupported parameters:
- `mode`
- `description`
- [POST api/lists/destroy](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-destroy)
- Unsupported parameters:
- `owner_screen_name`
- `owner_id`
- `slug`
- [GET api/blocks/list](https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-blocks-list)
- [GET api/friendships/incoming](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-incoming)
- Unsupported parameters
- `stringify_ids`
- - [GET api/followers/ids](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-followers-ids)
- [GET api/followers/list](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-followers-list)
- [GET api/friends/ids](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friends-ids)
- [GET api/friends/list](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friends-list)
- Additional parameters:
- `since_id`: You can use the `next_cursor` value to load the next page.
- `max_id`: You can use the inverse of the `previous_cursor` value to load the previous page.
- Unsupported parameter:
- `skip_status`: No status is returned even if it isn't set to true.
- Caveats:
- `cursor` trumps `since_id` trumps `max_id` if any combination is provided.
- `user_id` must be the ID of a contact associated with a local user account.
- `screen_name` must be associated with a local user account.
- `screen_name` trumps `user_id` if both are provided (undocumented Twitter behavior).
- Will succeed but return an empty array for users hiding their contact lists.
- [POST api/friendships/destroy](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-destroy)
## Non-implemented endpoints
- [GET oauth/authenticate](https://developer.twitter.com/en/docs/basics/authentication/api-reference/authenticate)
- [GET oauth/authorize](https://developer.twitter.com/en/docs/basics/authentication/api-reference/authorize)
- [POST oauth/invalidate_token](https://developer.twitter.com/en/docs/basics/authentication/api-reference/invalidate_access_token)
- [POST oauth2/invalidate_token](https://developer.twitter.com/en/docs/basics/authentication/api-reference/invalidate_bearer_token)
- [POST oauth2/token](https://developer.twitter.com/en/docs/basics/authentication/api-reference/token)
- [GET lists/members](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-members)
- [GET lists/members/show](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-members-show)
- [GET lists/memberships](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-memberships)
- [GET lists/show](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-show)
- [GET lists/subscribers](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-subscribers)
- [GET lists/subscribers/show](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-subscribers-show)
- [POST lists/members/create](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-members-create)
- [POST lists/members/create_all](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-members-create_all)
- [POST lists/members/destroy](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-members-destroy)
- [POST lists/members/destroy_all](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-members-destroy_all)
- [POST lists/subscribers/create](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-subscribers-create)
- [POST lists/subscribers/destroy](https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-subscribers-destroy)
- [GET friendships/lookup](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-lookup)
- [GET friendships/no_retweets/ids](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-no_retweets-ids)
- [GET friendships/outgoing](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-outgoing)
- [GET friendships/show](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friendships-show)
- [GET users/suggestions (deprecated)](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-suggestions)
- [GET users/suggestions/:slug (deprecated)](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-suggestions-slug)
- [GET users/suggestions/:slug/members (deprecated)](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-suggestions-slug-members)
- [POST friendships/create](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-create)
- [POST friendships/update](https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-update)
- [GET account/settings](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-settings)
- [GET saved_searches/show/:id](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-saved_searches-show-id)
- [GET users/profile_banner](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-users-profile_banner)
- [POST account/remove_profile_banner](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-remove_profile_banner)
- [POST account/settings](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-settings)
- [POST account/update_profile_background_image (deprecated)](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_background_image)
- [POST account/update_profile_banner](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_banner)
- [POST saved_searches/create](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-saved_searches-create)
- [POST saved_searches/destroy/:id](https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-saved_searches-destroy-id)
- [GET blocks/ids](https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-blocks-ids)
- [GET mutes/users/ids](https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-mutes-users-ids)
- [GET mutes/users/list](https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/get-mutes-users-list)
- [POST blocks/create](https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-blocks-create)
- [POST blocks/destroy](https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-blocks-destroy)
- [POST mutes/users/create](https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-mutes-users-create)
- [POST mutes/users/destroy](https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-mutes-users-destroy)
- [POST users/report_spam](https://developer.twitter.com/en/docs/accounts-and-users/mute-block-report-users/api-reference/post-users-report_spam)
- [GET collections/entries](https://developer.twitter.com/en/docs/tweets/curate-a-collection/api-reference/get-collections-entries)
- [GET collections/list](https://developer.twitter.com/en/docs/tweets/curate-a-collection/api-reference/get-collections-list)
- [GET collections/show](https://developer.twitter.com/en/docs/tweets/curate-a-collection/api-reference/get-collections-show)
- [POST collections/create](https://developer.twitter.com/en/docs/tweets/curate-a-collection/api-reference/post-collections-create)
- [POST collections/destroy](https://developer.twitter.com/en/docs/tweets/curate-a-collection/api-reference/post-collections-destroy)
- [POST collections/entries/add](https://developer.twitter.com/en/docs/tweets/curate-a-collection/api-reference/post-collections-entries-add)
- [POST collections/entries/curate](https://developer.twitter.com/en/docs/tweets/curate-a-collection/api-reference/post-collections-entries-curate)
- [POST collections/entries/move](https://developer.twitter.com/en/docs/tweets/curate-a-collection/api-reference/post-collections-entries-move)
- [POST collections/entries/remove](https://developer.twitter.com/en/docs/tweets/curate-a-collection/api-reference/post-collections-entries-remove)
- [POST collections/update](https://developer.twitter.com/en/docs/tweets/curate-a-collection/api-reference/post-collections-update)
- [POST statuses/filter](https://developer.twitter.com/en/docs/tweets/filter-realtime/api-reference/post-statuses-filter)
- [GET statuses/mentions_timeline](https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-mentions_timeline)
- [GET favorites/list](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-favorites-list)
- [GET statuses/lookup](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-lookup)
- [GET statuses/oembed](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-oembed)
- [GET statuses/retweeters/ids](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-retweeters-ids)
- [GET statuses/retweets/:id](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-retweets-id)
- [GET statuses/retweets_of_me](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-retweets_of_me)
- [POST statuses/unretweet/:id](https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-unretweet-id)
- [GET statuses/sample](https://developer.twitter.com/en/docs/tweets/sample-realtime/api-reference/get-statuses-sample)
- [GET compliance/firehose](https://developer.twitter.com/en/docs/tweets/compliance/api-reference/compliance-firehose)
- [DELETE custom_profiles/destroy.json](https://developer.twitter.com/en/docs/direct-messages/custom-profiles/api-reference/delete-profile)
- [GET custom_profiles/:id](https://developer.twitter.com/en/docs/direct-messages/custom-profiles/api-reference/get-profile)
- [GET custom_profiles/list](https://developer.twitter.com/en/docs/direct-messages/custom-profiles/api-reference/get-profile-list)
- [POST custom_profiles/new.json](https://developer.twitter.com/en/docs/direct-messages/custom-profiles/api-reference/new-profile)
- [DELETE direct_messages/events/destroy](https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/delete-message-event)
- [GET direct_messages/events/list](https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/list-events)
- [GET direct_messages/events/show](https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/get-event)
- [POST direct_messages/events/new (message_create)](https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/new-event)
- [POST direct_messages/indicate_typing](https://developer.twitter.com/en/docs/direct-messages/typing-indicator-and-read-receipts/api-reference/new-typing-indicator)
- [POST direct_messages/mark_read](https://developer.twitter.com/en/docs/direct-messages/typing-indicator-and-read-receipts/api-reference/new-read-receipt)
- [DELETE direct_messages/welcome_messages/destroy](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/delete-welcome-message)
- [DELETE direct_messages/welcome_messages/rules/destroy](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/delete-welcome-message-rule)
- [PUT direct_messages/welcome_messages/update](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/update-welcome-message)
- [GET direct_messages/welcome_messages/list](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/list-welcome-messages)
- [GET direct_messages/welcome_messages/rules/list](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/list-welcome-message-rules)
- [GET direct_messages/welcome_messages/rules/show](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/get-welcome-message-rule)
- [GET direct_messages/welcome_messages/show](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/get-welcome-message)
- [POST direct_messages/welcome_messages/new](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/new-welcome-message)
- [POST direct_messages/welcome_messages/rules/new](https://developer.twitter.com/en/docs/direct-messages/welcome-messages/api-reference/new-welcome-message-rule)
- [GET media/upload (STATUS)](https://developer.twitter.com/en/docs/media/upload-media/api-reference/get-media-upload-status)
- [POST media/subtitles/create](https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-subtitles-create)
- [POST media/subtitles/delete](https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-subtitles-delete)
- [POST media/upload (APPEND)](https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload-append)
- [POST media/upload (FINALIZE)](https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload-finalize)
- [POST media/upload (INIT)](https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload-init)
- [GET trends/available](https://developer.twitter.com/en/docs/trends/locations-with-trending-topics/api-reference/get-trends-available)
- [GET trends/closest](https://developer.twitter.com/en/docs/trends/locations-with-trending-topics/api-reference/get-trends-closest)
- [GET trends/place](https://developer.twitter.com/en/docs/trends/trends-for-location/api-reference/get-trends-place)
- [GET geo/id/:place_id](https://developer.twitter.com/en/docs/geo/place-information/api-reference/get-geo-id-place_id)
- [GET geo/reverse_geocode](https://developer.twitter.com/en/docs/geo/places-near-location/api-reference/get-geo-reverse_geocode)
- [GET geo/search](https://developer.twitter.com/en/docs/geo/places-near-location/api-reference/get-geo-search)

View file

@ -99,7 +99,7 @@ See Also
* [Profiles](help/Profiles)
* [Global Directory](help/Making-Friends#1_1)
* [Global Directory](help/Making-Friends#The+Directories)
* [Groups and Privacy](help/Groups-and-Privacy)

View file

@ -17,22 +17,24 @@ namespace Friendica\Model\Storage;
```php
interface IStorage
{
public static function get($ref);
public static function put($data, $ref = "");
public static function delete($ref);
public static function getOptions();
public static function saveOptions($data);
public function get(string $reference);
public function put(string $data, string $reference = '');
public function delete(string $reference);
public function getOptions();
public function saveOptions(array $data);
public function __toString();
public static function getName();
}
```
- `get($ref)` returns data pointed by `$ref`
- `put($data, $ref)` saves data in `$data` to position `$ref`, or a new position if `$ref` is empty.
- `delete($ref)` delete data pointed by `$ref`
- `get(string $reference)` returns data pointed by `$reference`
- `put(string $data, string $reference)` saves data in `$data` to position `$reference`, or a new position if `$reference` is empty.
- `delete(string $reference)` delete data pointed by `$reference`
Each storage backend can have options the admin can set in admin page.
- `getOptions()` returns an array with details about each option to build the interface.
- `saveOptions($data)` get `$data` from admin page, validate it and save it.
- `saveOptions(array $data)` get `$data` from admin page, validate it and save it.
The array returned by `getOptions()` is defined as:
@ -50,7 +52,7 @@ The info array for each option is defined as:
'type',
define the field used in form, and the type of data.
one of 'checkbox', 'combobox', 'custom', 'datetime', 'input', 'intcheckbox', 'password', 'radio', 'richtext', 'select', 'select_raw', 'textarea', 'yesno'
one of 'checkbox', 'combobox', 'custom', 'datetime', 'input', 'intcheckbox', 'password', 'radio', 'richtext', 'select', 'select_raw', 'textarea'
'label',
@ -71,7 +73,6 @@ Optional. Depends on which 'type' this option is:
- 'select': array `[ value => label ]` of choices
- 'intcheckbox': value of input element
- 'select_raw': prebuild html string of `<option >` tags
- 'yesno': array `[ 'label no', 'label yes']`
Each label should be translatable
@ -84,11 +85,38 @@ See doxygen documentation of `IStorage` interface for details about each method.
Each backend must be registered in the system when the plugin is installed, to be aviable.
`Friendica\Core\StorageManager::register($name, $class)` is used to register the backend class.
The `$name` must be univocal and will be shown to admin.
`DI::facStorage()->register(string $class)` is used to register the backend class.
When the plugin is uninstalled, registered backends must be unregistered using
`Friendica\Core\StorageManager::unregister($class)`.
`DI::facStorage()->unregister(string $class)`.
You have to register a new hook in your addon, listening on `storage_instance(App $a, array $data)`.
In case `$data['name']` is your storage class name, you have to instance a new instance of your `Friendica\Model\Storage\IStorage` class.
Set the instance of your class as `$data['storage']` to pass it back to the backend.
This is necessary because it isn't always clear, if you need further construction arguments.
## Adding tests
**Currently testing is limited to core Friendica only, this shows theoretically how tests should work in the future**
Each new Storage class should be added to the test-environment at [Storage Tests](https://github.com/friendica/friendica/tree/develop/tests/src/Model/Storage/).
Add a new test class which's naming convention is `StorageClassTest`, which extend the `StorageTest` in the same directory.
Override the two necessary instances:
```php
use Friendica\Model\Storage\IStorage;
abstract class StorageTest
{
// returns an instance of your newly created storage class
abstract protected function getInstance();
// Assertion for the option array you return for your new StorageClass
abstract protected function assertOption(IStorage $storage);
}
```
## Example
@ -107,65 +135,96 @@ namespace Friendica\Addon\samplestorage;
use Friendica\Model\Storage\IStorage;
use Friendica\Core\Config;
use Friendica\Core\Config\IConfig;
use Friendica\Core\L10n;
class SampleStorageBackend implements IStorage
{
public static function get($ref)
const NAME = 'Sample Storage';
/** @var IConfig */
private $config;
/** @var L10n */
private $l10n;
/**
* SampleStorageBackend constructor.
* @param IConfig $config The configuration of Friendica
*
* You can add here every dynamic class as dependency you like and add them to a private field
* Friendica automatically creates these classes and passes them as argument to the constructor
*/
public function __construct(IConfig $config, L10n $l10n)
{
// we return alwais the same image data. Which file we load is defined by
$this->config = $config;
$this->l10n = $l10n;
}
public function get(string $reference)
{
// we return always the same image data. Which file we load is defined by
// a config key
$filename = Config::get("storage", "samplestorage", "sample.jpg");
$filename = $this->config->get('storage', 'samplestorage', 'sample.jpg');
return file_get_contents($filename);
}
public static function put($data, $ref = "")
public function put(string $data, string $reference = '')
{
if ($ref === "") {
$ref = "sample";
if ($reference === '') {
$reference = 'sample';
}
// we don't save $data !
return $ref;
return $reference;
}
public static function delete($ref)
public function delete(string $reference)
{
// we pretend to delete the data
return true;
}
public static function getOptions()
public function getOptions()
{
$filename = Config::get("storage", "samplestorage", "sample.jpg");
$filename = $this->config->get('storage', 'samplestorage', 'sample.jpg');
return [
"filename" => [
"input", // will use a simple text input
L10n::t("The file to return"), // the label
'filename' => [
'input', // will use a simple text input
$this->l10n->t('The file to return'), // the label
$filename, // the current value
L10n::t("Enter the path to a file"), // the help text
// no extra data for "input" type..
$this->l10n->t('Enter the path to a file'), // the help text
// no extra data for 'input' type..
],
];
}
public static function saveOptions($data)
public function saveOptions(array $data)
{
// the keys in $data are the same keys we defined in getOptions()
$newfilename = trim($data["filename"]);
$newfilename = trim($data['filename']);
// this function should always validate the data.
// in this example we check if file exists
if (!file_exists($newfilename)) {
// in case of error we return an array with
// ["optionname" => "error message"]
return ["filename" => "The file doesn't exists"];
// ['optionname' => 'error message']
return ['filename' => 'The file doesn\'t exists'];
}
Config::set("storage", "samplestorage", $newfilename);
$this->config->set('storage', 'samplestorage', $newfilename);
// no errors, return empty array
return [];
}
public function __toString()
{
return self::NAME;
}
public static function getName()
{
return self::NAME;
}
}
```
@ -182,23 +241,59 @@ The file is `addon/samplestorage/samplestorage.php`
* Author: Alice <https://alice.social/~alice>
*/
use Friendica\Core\StorageManager;
use Friendica\Addon\samplestorage\SampleStorageBackend;
use Friendica\DI;
function samplestorage_install()
{
// on addon install, we register our class with name "Sample Storage".
// note: we use `::class` property, which returns full class name as string
// this save us the problem of correctly escape backslashes in class name
StorageManager::register("Sample Storage", SampleStorageBackend::class);
DI::storageManager()->register(SampleStorageBackend::class);
}
function samplestorage_unistall()
{
// when the plugin is uninstalled, we unregister the backend.
StorageManager::unregister("Sample Storage");
DI::storageManager()->unregister(SampleStorageBackend::class);
}
function samplestorage_storage_instance(\Friendica\App $a, array $data)
{
if ($data['name'] === SampleStorageBackend::getName()) {
// instance a new sample storage instance and pass it back to the core for usage
$data['storage'] = new SampleStorageBackend(DI::config(), DI::l10n(), DI::cache());
}
}
```
**Theoretically - until tests for Addons are enabled too - create a test class with the name `addon/tests/SampleStorageTest.php`:
```php
use Friendica\Model\Storage\IStorage;
use Friendica\Test\src\Model\Storage\StorageTest;
class SampleStorageTest extends StorageTest
{
// returns an instance of your newly created storage class
protected function getInstance()
{
// create a new SampleStorageBackend instance with all it's dependencies
// Have a look at DatabaseStorageTest or FilesystemStorageTest for further insights
return new SampleStorageBackend();
}
// Assertion for the option array you return for your new StorageClass
protected function assertOption(IStorage $storage)
{
$this->assertEquals([
'filename' => [
'input',
'The file to return',
'sample.jpg',
'Enter the path to a file'
],
], $storage->getOptions());
}
}
```

View file

@ -7,48 +7,65 @@ Please see the sample addon 'randplace' for a working example of using some of t
Addons work by intercepting event hooks - which must be registered.
Modules work by intercepting specific page requests (by URL path).
Addon names cannot contain spaces or other punctuation and are used as filenames and function names.
You may supply a "friendly" name within the comment block.
Each addon must contain both an install and an uninstall function based on the addon name.
For instance "addon1name_install()".
These two functions take no arguments and are usually responsible for registering (and unregistering) event hooks that your addon will require.
The install and uninstall functions will also be called (i.e. re-installed) if the addon changes after installation.
## Naming
Addon names are used in file paths and functions names, and as such:
- Can't contain spaces or punctuation.
- Can't start with a number.
## Metadata
You can provide human-readable information about your addon in the first multi-line comment of your addon file.
Here's the structure:
```php
/**
* Name: {Human-readable name}
* Description: {Short description}
* Version: 1.0
* Author: {Author1 Name}
* Author: {Author2 Name} <{Author profile link}>
* Maintainer: {Maintainer1 Name}
* Maintainer: {Maintainer2 Name} <{Maintainer profile link}>
* Status: {Unsupported|Arbitrary status}
*/
```
You can also provide a longer documentation in a `README` or `README.md` file.
The latter will be converted from Markdown to HTML in the addon detail page.
## Install/Uninstall
If your addon uses hooks, they have to be registered in a `<addon>_install()` function.
This function also allows to perform arbitrary actions your addon needs to function properly.
Uninstalling an addon automatically unregisters any hook it registered, but if you need to provide specific uninstallation steps, you can add them in a `<addon>_uninstall()` function.
The install and uninstall functions will be called (i.e. re-installed) if the addon changes after installation.
Therefore your uninstall should not destroy data and install should consider that data may already exist.
Future extensions may provide for "setup" amd "remove".
Addons should contain a comment block with the four following parameters:
/*
* Name: My Great Addon
* Description: This is what my addon does. It's really cool.
* Version: 1.0
* Author: John Q. Public <john@myfriendicasite.com>
*/
Please also add a README or README.md file to the addon directory.
It will be displayed in the admin panel and should include some further information in addition to the header information.
## PHP addon hooks
Register your addon hooks during installation.
\Friendica\Core\Hook::register($hookname, $file, $function);
$hookname is a string and corresponds to a known Friendica PHP hook.
`$hookname` is a string and corresponds to a known Friendica PHP hook.
$file is a pathname relative to the top-level Friendica directory.
This *should* be 'addon/*addon_name*/*addon_name*.php' in most cases.
`$file` is a pathname relative to the top-level Friendica directory.
This *should* be 'addon/*addon_name*/*addon_name*.php' in most cases and can be shortened to `__FILE__`.
$function is a string and is the name of the function which will be executed when the hook is called.
`$function` is a string and is the name of the function which will be executed when the hook is called.
### Arguments
Your hook callback functions will be called with at least one and possibly two arguments
function myhook_function(App $a, &$b) {
function <addon>_<hookname>(App $a, &$b) {
}
If you wish to make changes to the calling data, you must declare them as reference variables (with `&`) during function declaration.
#### $a
@ -67,6 +84,12 @@ $b can be called anything you like.
This is information specific to the hook currently being processed, and generally contains information that is being immediately processed or acted on that you can use, display, or alter.
Remember to declare it with `&` if you wish to alter it.
## Admin settings
Your addon can provide user-specific settings via the `addon_settings` PHP hook, but it can also provide node-wide settings in the administration page of your addon.
Simply declare a `<addon>_addon_admin(App $a)` function to display the form and a `<addon>_addon_admin_post(App $a)` function to process the data from the form.
## Global stylesheets
If your addon requires adding a stylesheet on all pages of Friendica, add the following hook:
@ -81,7 +104,7 @@ function <addon>_install()
function <addon>_head(App $a)
{
$a->registerStylesheet(__DIR__ . '/relative/path/to/addon/stylesheet.css');
\Friendica\DI::page()->registerStylesheet(__DIR__ . '/relative/path/to/addon/stylesheet.css');
}
```
@ -103,7 +126,7 @@ function <addon>_install()
function <addon>_footer(App $a)
{
$a->registerFooterScript(__DIR__ . '/relative/path/to/addon/script.js');
\Friendica\DI::page()->registerFooterScript(__DIR__ . '/relative/path/to/addon/script.js');
}
```
@ -132,11 +155,11 @@ No additional data is provided.
## Modules
Addons may also act as "modules" and intercept all page requests for a given URL path.
In order for a addon to act as a module it needs to define a function "addon_name_module()" which takes no arguments and needs not do anything.
In order for a addon to act as a module it needs to declare an empty function `<addon>_module()`.
If this function exists, you will now receive all page requests for "http://my.web.site/addon_name" - with any number of URL components as additional arguments.
If this function exists, you will now receive all page requests for `https://my.web.site/<addon>` - with any number of URL components as additional arguments.
These are parsed into an array $a->argv, with a corresponding $a->argc indicating the number of URL components.
So http://my.web.site/addon/arg1/arg2 would look for a module named "addon" and pass its module functions the $a App structure (which is available to many components).
So `https://my.web.site/addon/arg1/arg2` would look for a module named "addon" and pass its module functions the $a App structure (which is available to many components).
This will include:
```php
@ -144,9 +167,9 @@ $a->argc = 3
$a->argv = array(0 => 'addon', 1 => 'arg1', 2 => 'arg2');
```
Your module functions will often contain the function addon_name_content(App $a), which defines and returns the page body content.
They may also contain addon_name_post(App $a) which is called before the _content function and typically handles the results of POST forms.
You may also have addon_name_init(App $a) which is called very early on and often does module initialisation.
To display a module page, you need to declare the function `<addon>_content(App $a)`, which defines and returns the page body content.
They may also contain `<addon>_post(App $a)` which is called before the `<addon>_content` function and typically handles the results of POST forms.
You may also have `<addon>_init(App $a)` which is called before `<addon>_content` and should include common logic to your module.
## Templates
@ -158,9 +181,11 @@ Put your tpl files in the *templates/* subfolder of your addon.
In your code, like in the function addon_name_content(), load the template file and execute it passing needed values:
```php
use Friendica\Core\Renderer;
# load template file. first argument is the template name,
# second is the addon path relative to friendica top folder
$tpl = Renderer::getMarkupTemplate('mytemplate.tpl', 'addon/addon_name/');
$tpl = Renderer::getMarkupTemplate('mytemplate.tpl', __DIR__);
# apply template. first argument is the loaded template,
# second an array of 'name' => 'values' to pass to template
@ -335,6 +360,7 @@ Called from `Emailer::send()` before building the mime message.
- **htmlVersion**: html version of the message
- **textVersion**: text only version of the message
- **additionalMailHeader**: additions to the smtp mail header
- **sent**: default false, if set to true in the hook, the default mailer will be skipped.
### emailer_send
Called before calling PHP's `mail()`.
@ -344,6 +370,7 @@ Called before calling PHP's `mail()`.
- **subject**
- **body**
- **headers**
- **sent**: default false, if set to true in the hook, the default mailer will be skipped.
### load_config
Called during `App` initialization to allow addons to load their own configuration file(s) with `App::loadConfigFile()`.
@ -411,6 +438,47 @@ Hook data:
visitor => array with the contact record of the visitor
url => the query string
### jot_networks
Called when displaying the post permission screen.
Hook data is a list of form fields that need to be displayed along the ACL.
Form field array structure is:
- **type**: `checkbox` or `select`.
- **field**: Standard field data structure to be used by `field_checkbox.tpl` and `field_select.tpl`.
For `checkbox`, **field** is:
- [0] (String): Form field name; Mandatory.
- [1]: (String): Form field label; Optional, default is none.
- [2]: (Boolean): Whether the checkbox should be checked by default; Optional, default is false.
- [3]: (String): Additional help text; Optional, default is none.
- [4]: (String): Additional HTML attributes; Optional, default is none.
For `select`, **field** is:
- [0] (String): Form field name; Mandatory.
- [1] (String): Form field label; Optional, default is none.
- [2] (Boolean): Default value to be selected by default; Optional, default is none.
- [3] (String): Additional help text; Optional, default is none.
- [4] (Array): Associative array of options. Item key is option value, item value is option label; Mandatory.
### route_collection
Called just before dispatching the router.
Hook data is a `\FastRoute\RouterCollector` object that should be used to add addon routes pointing to classes.
**Notice**: The class whose name is provided in the route handler must be reachable via auto-loader.
### probe_detect
Called before trying to detect the target network of a URL.
If any registered hook function sets the `result` key of the hook data array, it will be returned immediately.
Hook functions should also return immediately if the hook data contains an existing result.
Hook data:
- **uri** (input): the profile URI.
- **network** (input): the target network (can be empty for auto-detection).
- **uid** (input): the user to return the contact data for (can be empty for public contacts).
- **result** (output): Set by the hook function to indicate a successful detection.
## Complete list of hook callbacks
Here is a complete list of all hook callbacks with file locations (as of 24-Sep-2018). Please see the source for details of any hooks not documented above.
@ -419,14 +487,14 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('init_1');
Hook::callAll('app_menu', $arr);
Hook::callAll('page_content_top', $a->page['content']);
Hook::callAll('page_content_top', DI::page()['content']);
Hook::callAll($a->module.'_mod_init', $placeholder);
Hook::callAll($a->module.'_mod_init', $placeholder);
Hook::callAll($a->module.'_mod_post', $_POST);
Hook::callAll($a->module.'_mod_afterpost', $placeholder);
Hook::callAll($a->module.'_mod_content', $arr);
Hook::callAll($a->module.'_mod_aftercontent', $arr);
Hook::callAll('page_end', $a->page['content']);
Hook::callAll('page_end', DI::page()['content']);
### include/api.php
@ -450,20 +518,6 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('item_photo_menu', $args);
Hook::callAll('jot_tool', $jotplugins);
### include/text.php
Hook::callAll('contact_block_end', $arr);
Hook::callAll('poke_verbs', $arr);
Hook::callAll('put_item_in_cache', $hook_data);
Hook::callAll('prepare_body_init', $item);
Hook::callAll('prepare_body_content_filter', $hook_data);
Hook::callAll('prepare_body', $hook_data);
Hook::callAll('prepare_body_final', $hook_data);
### include/items.php
Hook::callAll('page_info_data', $data);
### mod/directory.php
Hook::callAll('directory_item', $arr);
@ -480,7 +534,7 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll("parse_link", $arr);
### mod/manage.php
### src/Module/Delegation.php
Hook::callAll('home_init', $ret);
@ -550,10 +604,6 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('post_local_end', $arr);
### mod/lockview.php
Hook::callAll('lockview_content', $item);
### mod/uexport.php
Hook::callAll('uexport_options', $options);
@ -586,6 +636,7 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('load_config');
Hook::callAll('head');
Hook::callAll('footer');
Hook::callAll('route_collection');
### src/Model/Item.php
@ -595,6 +646,11 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('post_remote_end', $posted_item);
Hook::callAll('tagged', $arr);
Hook::callAll('post_local_end', $new_item);
Hook::callAll('put_item_in_cache', $hook_data);
Hook::callAll('prepare_body_init', $item);
Hook::callAll('prepare_body_content_filter', $hook_data);
Hook::callAll('prepare_body', $hook_data);
Hook::callAll('prepare_body_final', $hook_data);
### src/Model/Contact.php
@ -619,6 +675,14 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('register_account', $uid);
Hook::callAll('remove_user', $user);
### src/Module/PermissionTooltip.php
Hook::callAll('lockview_content', $item);
### src/Content/ContactBlock.php
Hook::callAll('contact_block_end', $arr);
### src/Content/Text/BBCode.php
Hook::callAll('bbcode', $text);
@ -640,9 +704,6 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
### src/Content/ContactSelector.php
Hook::callAll('network_to_name', $nets);
Hook::callAll('gender_selector', $select);
Hook::callAll('sexpref_selector', $select);
Hook::callAll('marital_selector', $select);
### src/Content/OEmbed.php
@ -650,9 +711,17 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
### src/Content/Nav.php
Hook::callAll('page_header', $a->page['nav']);
Hook::callAll('page_header', DI::page()['nav']);
Hook::callAll('nav_info', $nav);
### src/Core/Authentication.php
Hook::callAll('logged_in', $a->user);
### src/Core/StorageManager
Hook::callAll('storage_instance', $data);
### src/Worker/Directory.php
Hook::callAll('globaldir_update', $arr);
@ -661,14 +730,8 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('notifier_end', $target_item);
### src/Worker/Queue.php
Hook::callAll('queue_predeliver', $r);
Hook::callAll('queue_deliver', $params);
### src/Module/Login.php
Hook::callAll('authenticate', $addon_auth);
Hook::callAll('login_hook', $o);
### src/Module/Logout.php
@ -692,11 +755,16 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
### src/Core/Authentication.php
Hook::callAll('logged_in', $a->user);
Hook::callAll('authenticate', $addon_auth);
### src/Core/Hook.php
self::callSingle(self::getApp(), 'hook_fork', $fork_hook, $hookdata);
### src/Core/L10n/L10n.php
Hook::callAll('poke_verbs', $arr);
### src/Core/Worker.php
Hook::callAll("proc_run", $arr);
@ -725,6 +793,11 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
Hook::callAll('atom_feed_end', $atom);
Hook::callAll('atom_feed_end', $atom);
### src/Protocol/Email.php
Hook::callAll('email_getmessage', $message);
Hook::callAll('email_getmessage_end', $ret);
### view/js/main.js
document.dispatchEvent(new Event('postprocess_liveupdate'));

View file

@ -65,17 +65,17 @@ table.bbcodes > * > tr > th {
<td><a href="http://friendi.ca" target="external-link">Friendica</a></td>
</tr>
<tr>
<td>[img]https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg[/img]</td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg" alt="Immagine/foto"></td>
<td>[img]https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg[/img]</td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg" alt="Immagine/foto"></td>
</tr>
<tr>
<td>[img=https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg]The Friendica Logo[/img]</td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg" alt="The Friendica Logo"></td>
<td>[img=https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg]The Friendica Logo[/img]</td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg" alt="The Friendica Logo"></td>
</tr>
<tr>
<td>[img=64x32]https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg[/img]<br>
<td>[img=64x32]https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg[/img]<br>
<br>Note: provided height is simply discarded.</td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg" style="width: 64px;"></td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg" style="width: 64px;"></td>
</tr>
<tr>
<td>[size=xx-small]small text[/size]</td>
@ -113,17 +113,17 @@ table.bbcodes > * > tr > th {
<tr>
<td>[bookmark]http://friendi.ca[/bookmark]<br><br>
#^[url]http://friendi.ca[/url]</td>
<td><span class="oembed link"><h4>Friendica: <a href="http://friendi.ca" rel="oembed"></a><a href="http://friendi.ca" target="_blank">http://friendi.ca</a></h4></span></td>
<td><span class="oembed link"><h4>Friendica: <a href="http://friendi.ca" rel="oembed"></a><a href="http://friendi.ca" target="_blank" rel="noopener noreferrer">http://friendi.ca</a></h4></span></td>
</tr>
<tr>
<td>[bookmark=http://friendi.ca]Bookmark[/bookmark]<br><br>
#^[url=http://friendi.ca]Bookmark[/url]<br><br>
#[url=http://friendi.ca]^[/url][url=http://friendi.ca]Bookmark[/url]</td>
<td><span class="oembed link"><h4>Friendica: <a href="http://friendi.ca" rel="oembed"></a><a href="http://friendi.ca" target="_blank">Bookmark</a></h4></span></td>
<td><span class="oembed link"><h4>Friendica: <a href="http://friendi.ca" rel="oembed"></a><a href="http://friendi.ca" target="_blank" rel="noopener noreferrer">Bookmark</a></h4></span></td>
</tr>
<tr>
<td>[url=/posts/f16d77b0630f0134740c0cc47a0ea02a]Diaspora post with GUID[/url]</td>
<td><a href="/display/f16d77b0630f0134740c0cc47a0ea02a" target="_blank">Diaspora post with GUID</a></td>
<td><a href="/display/f16d77b0630f0134740c0cc47a0ea02a" target="_blank" rel="noopener noreferrer">Diaspora post with GUID</a></td>
</tr>
<tr>
<td>#Friendica</td>
@ -602,6 +602,9 @@ While taking pictures in the woods I had a really strange encounter...</td>
The [abstract] element is not working with connectors where we post HTML directly, like Tumblr, Wordpress or Pump.io.
For the native connections--that is to e.g. Friendica, Hubzilla, Diaspora or GNU Social--the full posting is used and the contacts instance will display the posting as desired.
For postings that are delivered via ActivityPub, the text from the abstract is placed in the summary field.
On Mastodon this field is used for the content warning.
## Special
<table class="bbcodes">
@ -610,15 +613,34 @@ For the native connections--that is to e.g. Friendica, Hubzilla, Diaspora or GNU
<th>Result</th>
</tr>
<tr>
<td>If you need to put literal bbcode in a message, [noparse], [nobb] or [pre] are used to escape bbcode:
<td>If you need to put literal BBCode in a message, [noparse], [nobb] or [pre] blocks prevent BBCode conversion:
<ul>
<li>[noparse][b]bold[/b][/noparse]</li>
<li>[nobb][b]bold[/b][/nobb]</li>
<li>[pre][b]bold[/b][/pre]</li>
</ul>
Note: [code] has priority over [noparse], [nobb] and [pre] which makes them display as BBCode tags in code blocks instead of being removed.
[code] blocks inside [noparse] will still be converted to a code block.
</td>
<td>[b]bold[/b]</td>
</tr>
<tr>
<td>Additionally, [noparse] and [pre] blocks prevent mention and hashtag conversion to links:
<ul>
<li>[noparse]@user@domain.tld #hashtag[/noparse]</li>
<li>[pre]@user@domain.tld #hashtag[/pre]</li>
</ul>
</td>
<td>@user@domain.tld #hashtag</td>
</tr>
<tr>
<td>Additionally, [pre] blocks preserve spaces:
<ul>
<li>[pre]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Spaces[/pre]</li>
</ul>
</td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Spaces</td>
</tr>
<tr>
<td>[nosmile] is used to disable smilies on a post by post basis<br>
<br>

View file

@ -43,7 +43,7 @@ At first you have to get the current version. You can either pull it from [Githu
$> cd /var/www/virtual/YOURSPACE/html/addon; git pull
Or you can download a tar archive here: [jappixmini.tgz](https://github.com/friendica/friendica-addons/blob/master/jappixmini.tgz) (click at „view raw“).
Or you can download a tar archive here: [jappixmini.tgz](https://github.com/friendica/friendica-addons/blob/stable/jappixmini.tgz) (click at „view raw“).
Just unpack the file and rename the directory to „jappixmini“.
Next, upload this directory and the .tgz-file into your addon directory of your friendica installation.

View file

@ -33,15 +33,24 @@ return [
### Configuration location
The `config` directory holds key configuration files:
The `config` directory holds key configuration files and can have different config files.
All of them have to end with `.config.php` and must not include `-sample` in their name.
- `defaults.config.php` holds the default values for all the configuration keys that can only be set in `local.config.php`.
- `settings.config.php` holds the default values for some configuration keys that are set through the admin settings page.
Some examples of common known configuration files:
- `local.config.php` holds the current node custom configuration.
- `addon.config.php` is optional and holds the custom configuration for specific addons.
Addons can define their own default configuration values in `addon/[addon]/config/[addon].config.php` which is loaded when the addon is activated.
### Static Configuration location
The `static` directory holds the codebase default configurations files.
They must not be changed by users, because they can get changed from release to release.
Currently, the following configurations are included:
- `defaults.config.php` holds the default values for all the configuration keys that can only be set in `local.config.php`.
- `settings.config.php` holds the default values for some configuration keys that are set through the admin settings page.
#### Migrating from .htconfig.php to config/local.config.php
The legacy `.htconfig.php` configuration file is still supported, but is deprecated and will be removed in a subsequent Friendica release.
@ -292,7 +301,7 @@ Or it is for testing purposes only.
**Attention:** Please be warned that you shouldn't use one of these values without the knowledge what it could trigger.
Especially don't do that with undocumented values.
These configurations keys and their default value are listed in `config/defaults.config.php` and should be overwritten in `config/local.config.php`.
These configurations keys and their default value are listed in `static/defaults.config.php` and should be overwritten in `config/local.config.php`.
## Administrator Options

View file

@ -0,0 +1,239 @@
Domain-Driven-Design
==============
* [Home](help)
* [Developer Intro](help/Developers-Intro)
Friendica uses class structures inspired by Domain-Driven-Design programming patterns.
This page is meant to explain what it means in practical terms for Friendica development.
## Inspiration
- https://designpatternsphp.readthedocs.io/en/latest/Structural/DependencyInjection/README.html
- https://designpatternsphp.readthedocs.io/en/latest/Creational/SimpleFactory/README.html
- https://designpatternsphp.readthedocs.io/en/latest/More/Repository/README.html
- https://designpatternsphp.readthedocs.io/en/latest/Creational/FactoryMethod/README.html
- https://designpatternsphp.readthedocs.io/en/latest/Creational/Prototype/README.html
## Core concepts
### Models and Collections
Instead of anonymous arrays of arrays of database field values, we have Models and collections to take full advantage of PHP type hints.
Before:
```php
function doSomething(array $intros)
{
foreach ($intros as $intro) {
$introId = $intro['id'];
}
}
$intros = \Friendica\Database\DBA::selectToArray('intros', [], ['uid' => local_user()]);
doSomething($intros);
```
After:
```php
function doSomething(\Friendica\Collection\Introductions $intros)
{
foreach ($intros as $intro) {
/** @var $intro \Friendica\Model\Introduction */
$introId = $intro->id;
}
}
/** @var $intros \Friendica\Collection\Introductions */
$intros = \Friendica\DI::intro()->select(['uid' => local_user()]);
doSomething($intros);
```
### Dependency Injection
Under this concept, we want class objects to carry with them the dependencies they will use.
Instead of calling global/static function/methods, objects use their own class members.
Before:
```php
class Model
{
public $id;
function save()
{
return \Friendica\Database\DBA::update('table', get_object_vars($this), ['id' => $this->id]);
}
}
```
After:
```php
class Model
{
/**
* @var \Friendica\Database\Database
*/
protected $dba;
public $id;
function __construct(\Friendica\Database\Database $dba)
{
$this->dba = $dba;
}
function save()
{
return $this->dba->update('table', get_object_vars($this), ['id' => $this->id]);
}
}
```
The main advantage is testability.
Another one is avoiding dependency circles and avoid implicit initializing.
In the first example the method `save()` has to be tested with the `DBA::update()` method, which may or may not have dependencies itself.
In the second example we can mock `\Friendica\Database\Database`, e.g. overload the class by replacing its methods by placeholders, which allows us to test only `Model::save()` and nothing else implicitly.
The main drawback is lengthy constructors for dependency-heavy classes.
To alleviate this issue we are using [DiCe](https://r.je/dice) to simplify the instantiation of the higher level objects Friendica uses.
We also added a convenience factory named `\Friendica\DI` that creates some of the most common objects used in modules.
### Factories
Since we added a bunch of parameters to class constructors, instantiating objects has become cumbersome.
To keep it simple, we are using Factories.
Factories are classes used to generate other objects, centralizing the dependencies required in their constructor.
Factories encapsulate more or less complex creation of objects and create them redundancy free.
Before:
```php
$model = new Model(\Friendica\DI::dba());
$model->id = 1;
$model->key = 'value';
$model->save();
```
After:
```php
class Factory
{
/**
* @var \Friendica\Database\Database
*/
protected $dba;
function __construct(\Friendica\Database\Database $dba)
{
$this->dba;
}
public function create()
{
return new Model($this->dba);
}
}
$model = \Friendica\DI::factory()->create();
$model->id = 1;
$model->key = 'value';
$model->save();
```
Here, `DI::factory()` returns an instance of `Factory` that can then be used to create a `Model` object without having to care about its dependencies.
### Repositories
Last building block of our code architecture, repositories are meant as the interface between models and how they are stored.
In Friendica they are stored in a relational database but repositories allow models not to have to care about it.
Repositories also act as factories for the Model they are managing.
Before:
```php
class Model
{
/**
* @var \Friendica\Database\Database
*/
protected $dba;
public $id;
function __construct(\Friendica\Database\Database $dba)
{
$this->dba = $dba;
}
function save()
{
return $this->dba->update('table', get_object_vars($this), ['id' => $this->id]);
}
}
class Factory
{
/**
* @var \Friendica\Database\Database
*/
protected $dba;
function __construct(\Friendica\Database\Database $dba)
{
$this->dba;
}
public function create()
{
return new Model($this->dba);
}
}
$model = \Friendica\DI::factory()->create();
$model->id = 1;
$model->key = 'value';
$model->save();
```
After:
```php
class Model {
public $id;
}
class Repository extends Factory
{
/**
* @var \Friendica\Database\Database
*/
protected $dba;
function __construct(\Friendica\Database\Database $dba)
{
$this->dba;
}
public function create()
{
return new Model($this->dba);
}
public function save(Model $model)
{
return $this->dba->update('table', get_object_vars($model), ['id' => $model->id]);
}
}
$model = \Friendica\DI::repository()->create();
$model->id = 1;
$model->key = 'value';
\Friendica\DI::repository()->save($model);
```

View file

@ -41,6 +41,8 @@ If you have seen Friendica you probably have ideas to improve it, haven't you?
## Programming
Friendica uses an implementation of [Domain-Driven-Design](help/Developer-Domain-Driven-Design), please make sure to check out the provided links for hints at the expected code architecture.
### Composer
Friendica uses [Composer](https://getcomposer.org) to manage dependencies libraries and the class autoloader both for libraries and namespaced Friendica classes.
@ -81,6 +83,7 @@ Here's a few primers if you are new to Friendica or to the PSR-2 coding standard
* No closing PHP tag
* No trailing spaces
* Array declarations use the new square brackets syntax
* Quoting style is single quotes by default, except for needed string interpolation, SQL query strings by convention and comments that should stay in natural language.
Don't worry, you don't have to know by heart the PSR-2 coding standards to start contributing to Friendica.
There are a few tools you can use to check or fix your files before you commit.
@ -151,5 +154,5 @@ If you are interested in improving those clients, please contact the developers
* Android / LinageOS: **Friendiqa** [src](https://git.friendi.ca/lubuwest/Friendiqa)/[Google Play](https://play.google.com/store/apps/details?id=org.qtproject.friendiqa) developed by [Marco R](https://freunde.ma-nic.de/profile/marco)
* iOS: *currently no client*
* SailfishOS: **Friendiy** [src](https://kirgroup.com/projects/fabrixxm/harbour-friendly) - developed by [Fabio](https://kirgroup.com/profile/fabrixxm/?tab=profile)
* Windows: **Friendica Mobile** for Windows versions [before 8.1](http://windowsphone.com/s?appid=e3257730-c9cf-4935-9620-5261e3505c67) and [Windows 10](https://www.microsoft.com/store/apps/9nblggh0fhmn) - developed by [Gerhard Seeber](http://mozartweg.dyndns.org/friendica/profile/gerhard/?tab=profile)
* SailfishOS: **Friendiy** [src](https://kirgroup.com/projects/fabrixxm/harbour-friendly) - developed by [Fabio](https://kirgroup.com/profile/fabrixxm/profile)
* Windows: **Friendica Mobile** for Windows versions [before 8.1](http://windowsphone.com/s?appid=e3257730-c9cf-4935-9620-5261e3505c67) and [Windows 10](https://www.microsoft.com/store/apps/9nblggh0fhmn) - developed by [Gerhard Seeber](http://mozartweg.dyndns.org/friendica/profile/gerhard/profile)

View file

@ -0,0 +1,23 @@
# Export / Import of followed Contacts
* [Home](help)
In addition to [move your account](help/Move-Account) you can export and import the list of accounts you follow.
The exported list is stored as CSV file that is compatible to the format used by other platforms as e.g. Mastodon or Pleroma.
## Export of followed Contacts
To export the list of accounts that you follow, go to the [Settings Export personal date](settings/userexport) and click the [Export Contacts to CSV](settings/userexport/contact).
## Import of followed Contacts
To import contacts from a CSV file, go to the [Settings page](settings).
At the bottom of the *account settings* page you'll find the *import contacts* section.
Upload the CSV file there.
### Supported File Format
The CSV file *must* contain at least one column.
In the first column the table should contain either the handle or URL of an followed account.
(one account per row.)
Other columns in the CSV file will be ignored.

View file

@ -91,16 +91,6 @@ in German:
https://social.example.com/profile/example?lang=de.
If the question mark is already in the url you need to do it using a ampersand.
Example:
https://social.example.com/profile/example?tab=profile
in German:
https://social.example.com/profile/example?tab=profile&lang=de.
When a certain language is forced, the language remains until session is closed.
<a name="contacts"></a>
@ -126,16 +116,15 @@ A **hidden contact** will not be displayed in any "friend list" (except to you).
However a hidden contact will appear normally in conversations and this may expose his/her hidden status to anybody who can see the conversation.
<a name="removed"></a>
### What happens when an account is removed? Is it truly deleted?
### What happens when an account is removed?
If you delete your account, we will immediately remove all your content on **your** server.
If you remove your account, it will be scheduled for permanent deletion in *seven days*.
As soon as you activate the deletion process you won't be able to login any more.
Only the administrator of your node can halt this process prior to permanent deletion.
Then Friendica issues requests to all your contacts to remove you.
This will also remove you from the global directory.
Doing this requires your account and profile still to be "partially" available for up to 24 hours in order to establish contact with all your friends.
We can block it in several ways so that it appears empty and all profile information erased, but will then wait for 24 hours (or after all of your contacts have been notified) before we can physically remove it.
After that, your account is deleted.
After the elapsed time of seven days, all your posts, messages, photos, and personal information stored on your node will be deleted.
Your node will also issue removal requests to all your contacts; this will also remove your profile from the global directory if you are listed.
Your username cannot be reissued for future sign-ups for security reasons.
<a name="hashtag"></a>
### Can I follow a hashtag?
@ -172,7 +161,9 @@ Friendica is using a [Twitter/GNU Social compatible API](help/api), which means
Here is a list of known working clients:
* Android
* [Friendiqa](https://github.com/lubuwest/friendiqa) (available in Google Playstore or from a binary repository you can add to [F-Droid](https://freunde.ma-nic.de/display/3e98eba8185a13c5bdbf3d1539646854))
* [Friendiqa](https://git.friendi.ca/lubuwest/Friendiqa) (available in Google Playstore or from a binary repository you can add to [F-Droid](https://freunde.ma-nic.de/display/3e98eba8185a13c5bdbf3d1539646854))
* [Fedilab](https://fedilab.app/) (available in F-Droid and Google stores)
* [DiCa](https://dica.mixi.cool/)
* AndStatus
* Twidere
* Mustard and Mustard-Mod

View file

@ -40,7 +40,7 @@ You are not required to do this, but the alternative is to log out and log back
This could get cumbersome if you manage several different forums/identities.
You may also appoint a delegate to manage your forum.
Do this by visiting the [Delegation Setup Page](delegate).
Do this by visiting the [Delegation Setup Page](settings/delegation).
This will provide you with a list of contacts on this system under "Potential Delegates".
Selecting one or more persons will give them access to manage your forum.
They will be able to edit contacts, profiles, and all content for this account/page.

View file

@ -22,7 +22,7 @@ Our Git Branches
There are two relevant branches in the main repo on GitHub:
1. master: This branch contains stable releases only.
1. stable: This branch contains stable releases only.
2. develop: This branch contains the latest code.
This is what you want to work with.
@ -43,7 +43,7 @@ Release branches
A release branch is created when the develop branch contains all features it should have.
A release branch is used for a few things.
1. It allows last-minute bug fixing before the release goes to master branch.
1. It allows last-minute bug fixing before the release goes to stable branch.
2. It allows meta-data changes (README, CHANGELOG, etc.) for version bumps and documentation changes.
3. It makes sure the develop branch can receive new features that are **not** part of this release.

View file

@ -21,6 +21,7 @@ Friendica Documentation and Resources
* [Chats](help/Chats)
* Further information
* [Move your account](help/Move-Account)
* [Export / Import of followed Contacts](help/Export-Import-Contacts)
* [Delete your account](help/Remove-Account)
* [Frequently asked questions (FAQ)](help/FAQ)
@ -44,6 +45,7 @@ Friendica Documentation and Resources
* [Help on Vagrant](help/Vagrant)
* [Bugs and Issues](help/Bugs-and-Issues)
* Code structure
* [Domain-Driven-Design](help/Developer-Domain-Driven-Design)
* [Addon Development](help/Addons)
* [Theme Development](help/themes)
* [Smarty 3 Templates](help/smarty3-templates)
@ -54,7 +56,7 @@ Friendica Documentation and Resources
* [Move classes to `src`](help/Developer-How-To-Move-Classes-to-src)
* [Run tests](help/Tests)
* Reference
* [Twitter/GNU Social API Functions](help/api)
* [API endpoints](help/api)
* [Code (Doxygen generated - sets cookies)](doc/html/)
* [Protocol Documentation](help/Protocol)
* [Database schema documentation](help/database)

View file

@ -1,44 +1,55 @@
Friendica Installation
===============
# Friendica Installation
We've tried very hard to ensure that Friendica will run on commodity hosting platforms - such as those used to host Wordpress blogs and Drupal websites.
We offer a manual and an automatic installation.
But be aware that Friendica is more than a simple web application.
It is a complex communications system which more closely resembles an email server than a web server.
For reliability and performance, messages are delivered in the background and are queued for later delivery when sites are down.
This kind of functionality requires a bit more of the host system than the typical blog.
Not every PHP/MySQL hosting provider will be able to support Friendica.
Many will.
But **please** review the requirements and confirm these with your hosting provider prior to installation.
Also if you encounter installation issues, please let us know via the [helper](http://forum.friendi.ca/profile/helpers) or the [developer](https://forum.friendi.ca/profile/developers) forum or [file an issue](https://github.com/friendica/friendica/issues).
But **please** review the [requirements](#Requirements) and confirm these with your hosting provider prior to installation.
## Support
If you encounter installation issues, please let us know via the [helper](http://forum.friendi.ca/profile/helpers) or the [developer](https://forum.friendi.ca/profile/developers) forum or [file an issue](https://github.com/friendica/friendica/issues).
Please be as clear as you can about your operating environment and provide as much detail as possible about any error messages you may see, so that we can prevent it from happening in the future.
Due to the large variety of operating systems and PHP platforms in existence we may have only limited ability to debug your PHP installation or acquire any missing modules - but we will do our best to solve any general code issues.
If you do not have a Friendica account yet, you can register a temporary one at [tryfriendica.de](https://tryfriendica.de) and join the forums mentioned above from there.
The account will expire after 7 days, but you can ask the server admin to keep your account longer, should the problem not be resolved after that.
Before you begin: Choose a domain name or subdomain name for your server.
Put some thought into this. Changing it after installation is currently not supported.
Things will break, and some of your friends may have difficulty communicating with you.
We plan to address this limitation in a future release.
## Prerequisites
* Choose a domain name or subdomain name for your server. Put some thought into this. While changing it after installation is supported, things still might break.
* Setup HTTPS on your domain.
Requirements
---
### Requirements
* Apache with mod-rewrite enabled and "Options All" so you can use a local .htaccess file
* PHP 5.6.1+ (PHP 7 is recommended for performance)
* Apache with mod-rewrite enabled and "Options All" so you can use a local `.htaccess` file
* PHP 7+ (PHP 7.1+ is recommended for performance and official support)
* PHP *command line* access with register_argc_argv set to true in the php.ini file
* 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 equivalent 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.)
* Installation into a top-level domain or sub-domain (without a directory/path component in the URL) is preferred. Directory paths will not be as convenient to use and have not been thoroughly tested.
* If your hosting provider doesn't allow Unix shell access, you might have trouble getting everything to work.
* MySQL 5.6+ or an equivalent alternative for MySQL (MariaDB, Percona Server etc.)
* ability to schedule jobs with cron (Linux/Mac) or Scheduled Tasks (Windows)
* installation into a top-level domain or sub-domain (without a directory/path component in the URL) is RECOMMENDED. Directory paths will not be as convenient to use and have not been thoroughly tested. This is REQUIRED if you wish to communicate with the Diaspora network.
Installation procedure
---
**If your hosting provider doesn't allow Unix shell access, you might have trouble getting everything to work.**
For alternative server configurations (such as Nginx server and MariaDB database engine), refer to the [Friendica wiki](https://github.com/friendica/friendica/wiki).
### Optional
* PHP ImageMagick extension (php-imagick) for animated GIF support.
* [Composer](https://getcomposer.org/) for a git install
## Installation procedure
### Alternative Installation Methods
@ -46,20 +57,26 @@ This guide will walk you through the manual installation process of Friendica.
If this is nothing for you, you might be interested in
* the [Friendica Docker image](https://github.com/friendica/docker) or
* how [install Friendica with YunoHost](https://github.com/YunoHost-Apps/friendica_ynh).
* how to [install Friendica with YunoHost](https://github.com/YunoHost-Apps/friendica_ynh).
### 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.
If you copy the directory tree to your webserver, make sure that you also copy `.htaccess-dist` - as "dot" files are often hidden and aren't normally copied.
**OR**
Clone the [friendica/friendica GitHub repository](https://github.com/friendica/friendica) and import dependencies.
This makes the software much easier to update.
The Linux commands to clone the repository into a directory "mywebsite" would be
git clone https://github.com/friendica/friendica.git -b master mywebsite
git clone https://github.com/friendica/friendica.git -b stable mywebsite
cd mywebsite
bin/composer.phar install
bin/composer.phar install --no-dev
Make sure the folder *view/smarty3* exists and is writable by the webserver user, in this case `www-data`
Make sure the folder *view/smarty3* exists and is writable by the webserver user, in this case *www-data*
mkdir view/smarty3
chown www-data:www-data view/smarty3
@ -71,9 +88,7 @@ Get the addons by going into your website folder.
Clone the addon repository (separately):
git clone https://github.com/friendica/friendica-addons.git -b master addon
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.
git clone https://github.com/friendica/friendica-addons.git -b stable addon
If you want to use the development version of Friendica you can switch to the develop branch in the repository by running
@ -82,7 +97,8 @@ If you want to use the development version of Friendica you can switch to the de
cd addon
git checkout develop
please be aware that the develop branch may break your Friendica node at any time.
**Be aware that the develop branch is unstable and may break your Friendica node at any time.**
You should have a recent backup before updating.
If you encounter a bug, please let us know.
### Create a database
@ -91,26 +107,21 @@ Create an empty database and note the access details (hostname, username, passwo
Friendica needs the permission to create and delete fields and tables in its own database.
With newer releases of MySQL (5.7.17 or newer), you might need to set the sql_mode to '' (blank).
Use this setting when the installer is unable to create all the needed tables due to a timestamp format problem.
In this case find the [mysqld] section in your my.cnf file and add the line :
Please check the [troubleshooting](#Troubleshooting) section if running on MySQL 5.7.17 or newer.
sql_mode = ''
### Option A: Run the installer
Restart mysql and you should be fine.
### Option A: Run the manual installer
Point your web browser to the new site and follow the instructions.
Before you point your web browser to the new site you need to copy `.htaccess-dist` to `.htaccess` for Apache installs.
Follow the instructions.
Please note any error messages and correct these before continuing.
If you need to specify a port for the connection to the database, you can do so in the host name setting for the database.
*If* the manual installation fails for any reason, check the following:
* Does "config/local.config.php" exist? If not, edit config/local-sample.config.php and change the system settings.
* Does `config/local.config.php` exist? If not, edit `config/local-sample.config.php` and change the system settings.
* Rename to `config/local.config.php`.
* Is the database is populated? If not, import the contents of `database.sql` with phpmyadmin or the mysql command line.
* Is the database populated? If not, import the contents of `database.sql` with phpmyadmin or the mysql command line.
At this point visit your website again, and register your personal account.
Registration errors should all be recoverable automatically.
@ -142,7 +153,7 @@ If you wish to include all optional checks, use `-a` like this statement:
#### B.1: Config file
You can use a prepared config file like [local-sample.config.php](config/local-sample.config.php).
You can use a prepared config file like [local-sample.config.php](/config/local-sample.config.php).
Navigate to the main Friendica directory and execute the following command:
@ -203,18 +214,18 @@ Navigate to the main Friendica directory and execute the following command:
### Prepare .htaccess file
Copy .htaccess-dist to .htaccess (be careful under Windows) to have working mod-rewrite again. If you have installed Friendica into a sub directory, like /friendica/ set this path in RewriteBase accordingly.
Copy `.htaccess-dist` to `.htaccess` (be careful under Windows) to have working mod-rewrite again. If you have installed Friendica into a sub directory, like */friendica/* set this path in `RewriteBase` accordingly.
Example:
cp .htacces-dist .htaccess
*Note*: Do **not** rename the .htaccess-dist file as it is tracked by GIT and renaming will cause a dirty working directory.
*Note*: Do **not** rename the `.htaccess-dist` file as it is tracked by GIT and renaming will cause a dirty working directory.
### Verify the "host-meta" page is working
Friendica should respond automatically to important addresses under the /.well-known/ rewrite path.
One critical URL would look like, for example, https://example.com/.well-known/host-meta
Friendica should respond automatically to important addresses under the */.well-known/* rewrite path.
One critical URL would look like, for example: https://example.com/.well-known/host-meta
It must be visible to the public and must respond with an XML file that is automatically customized to your site.
If that URL is not working, it is possible that some other software is using the /.well-known/ path.
@ -222,13 +233,23 @@ Other symptoms may include an error message in the Admin settings that says "hos
This is a severe configuration issue that prevents server to server communication."
Another common error related to host-meta is the "Invalid profile URL."
Check for a .well-known directory that did not come with Friendica.
Check for a `.well-known` directory that did not come with Friendica.
The preferred configuration is to remove the directory, however this is not always possible.
If there is any /.well-known/.htaccess file, it could interfere with this Friendica core requirement.
You should remove any RewriteRules from that file, or remove that whole file if appropriate.
It may be necessary to chmod the /.well-known/.htaccess file if you were not given write permissions by default.
### Set up the worker
## Register the admin account
At this point visit your website again, and register your personal account with the same email as in the `config.admin_email` config value.
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 delete/rename `config/local.config.php` to another name and drop all the database tables so that you can start fresh.
## Post Install Configuration
### (REQUIRED) Background tasks
Set up a cron job or scheduled task to run the worker once every 5-10 minutes in order to perform background processing.
Example:
@ -237,6 +258,8 @@ Example:
Change "/base/directory", and "/path/to/php" as appropriate for your situation.
#### cron job for worker
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:
@ -250,10 +273,24 @@ 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.
#### worker alternative: daemon
Otherwise, youll need to use the command line on your remote server and start the Friendica daemon (background task) using the following command:
cd /path/to/friendica; php bin/daemon.php start
Once started, you can check the daemon status using the following command:
cd /path/to/friendica; php bin/daemon.php status
After a server restart or any other failure, the daemon needs to be restarted.
This could be achieved by a cronjob.
### (RECOMMENDED) Logging & Log Rotation
At this point it is recommended that you set up logging and logrotation.
To do so please visit [Settings](help/Settings) and search the 'Logs' section for more information.
### Set up a backup plan
### (RECOMMENDED) Set up a backup plan
Bad things will happen.
Let there be a hardware failure, a corrupted database or whatever you can think of.
@ -261,3 +298,155 @@ So once the installation of your Friendica node is done, you should make yoursel
The most important file is the `config/local.config.php` file.
As it stores all your data, you should also have a recent dump of your Friendica database at hand, should you have to recover your node.
### (OPTIONAL) Reverse-proxying and HTTPS
Friendica looks for some well-known HTTP headers indicating a reverse-proxy
terminating an HTTPS connection.
While the standard from RFC 7239 specifies the use of the `Forwarded` header.
Forwarded: for=192.0.2.1; proto=https; by=192.0.2.2
Friendica also supports a number on non-standard headers in common use.
X-Forwarded-Proto: https
Front-End-Https: on
X-Forwarded-Ssl: on
It is however preferable to use the standard approach if configuring a new server.
## Troubleshooting
### "System is currently unavailable. Please try again later"
Check your database settings.
It usually means your database could not be opened or accessed.
If the database resides on the same machine, check that the database server name is "localhost".
### 500 Internal Error
This could be the result of one of our Apache directives not being supported by your version of Apache. Examine your apache server logs.
You might remove the line "Options -Indexes" from the `.htaccess` file if you are using a Windows server as this has been known to cause problems.
Also check your file permissions. Your website and all contents must generally be world-readable.
It is likely that your web server reported the source of the problem in its error log files.
Please review these system error logs to determine what caused the problem.
Often this will need to be resolved with your hosting provider or (if self-hosted) your web server configuration.
### 400 and 4xx "File not found" errors
First check your file permissions.
Your website and all contents must generally be world-readable.
Ensure that mod-rewite is installed and working, and that your `.htaccess` file
is being used. To verify the latter, create a file `test.out` containing the
word "test" in the top directory of Friendica, make it world readable and point
your web browser to
http://yoursitenamehere.com/test.out
This file should be blocked. You should get a permission denied message.
If you see the word "test" your Apache configuration is not allowing your
`.htaccess` file to be used (there are rules in this file to block access to any
file with .out at the end, as these are typically used for system logs).
Make certain the `.htaccess` file exists and is readable by everybody, then look
for the existence of "AllowOverride None" in the Apache server configuration for your site.
This will need to be changed to "AllowOverride All".
If you do not see the word "test", your `.htaccess` is working, but it is likely
that mod-rewrite is not installed in your web server or is not working.
On most Linux flavors:
% a2enmod rewrite
% /etc/init.d/apache2 restart
Consult your hosting provider, experts on your particular Linux distribution or
(if Windows) the provider of your Apache server software if you need to change
either of these and can not figure out how. There is a lot of help available on
the web. Search "mod-rewrite" along with the name of your operating system
distribution or Apache package (if using Windows).
### Unable to write the file config/local.config.php due to permissions issues
Create an empty `config/local.config.php`file and apply world-write permission.
On Linux:
% touch config/local.config.php
% chmod 664 config/local.config.php
Retry the installation. As soon as the database has been created,
******* this is important *********
% chmod 644 config/local.config.php
### Suhosin issues
Some configurations with "suhosin" security are configured without an ability to
run external processes. Friendica requires this ability. Following are some notes
provided by one of our members.
> On my server I use the php protection system Suhosin [http://www.hardened-php.net/suhosin/].
> One of the things it does is to block certain functions like proc_open, as
> configured in `/etc/php5/conf.d/suhosin.ini`:
>
> suhosin.executor.func.blacklist = proc_open, ...
>
> For those sites like Friendica that really need these functions they can be
> enabled, e.g. in `/etc/apache2/sites-available/friendica`:
>
> <Directory /var/www/friendica/>
> php_admin_value suhosin.executor.func.blacklist none
> php_admin_value suhosin.executor.eval.blacklist none
> </Directory>
>
> This enables every function for Friendica if accessed via browser, but not for
> the cronjob that is called via php command line. I attempted to enable it for
> 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 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 `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`.
>
> So the simple solution is to put the correct parameters into `config/local.config.php`:
>
> 'config' => [
> //Location of PHP command line processor
> 'php_path' => '/usr/bin/php -d suhosin.executor.func.blacklist=none \
> -d suhosin.executor.eval.blacklist=none',
> ],
>
> This is obvious as soon as you notice that the friendica-cron uses `proc_open`
> to execute PHP scripts that also use `proc_open`, but it took me quite some time to find that out.
> I hope this saves some time for other people using suhosin with function blocklists.
### Unable to create all mysql tables on MySQL 5.7.17 or newer
If the setup fails to create all the database tables and/or manual creation from
the command line fails, with this error:
ERROR 1067 (42000) at line XX: Invalid default value for 'created'
You need to adjust your my.cnf and add the following setting under the [mysqld]
section:
sql_mode = '';
After that, restart mysql and try again.

View file

@ -4,9 +4,7 @@ Friendica Message Flow
This page documents some of the details of how messages get from one person to another in the Friendica network.
There are multiple paths, using multiple protocols and message formats.
Those attempting to understand these message flows should become familiar with (at the minimum) the [DFRN protocol document](https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf) and the message passing elements of the OStatus stack (salmon and Pubsubhubbub).
Most message passing involves the file include/items.php, which has functions for several feed-related import/export activities.
Those attempting to understand these message flows should become familiar with (at the minimum) the [DFRN protocol document](https://github.com/friendica/friendica/blob/stable/spec/dfrn2.pdf) and the message passing elements of the OStatus stack (salmon and Pubsubhubbub).
When a message is posted, all immediate deliveries to all networks are made using include/notifier.php, which chooses how (and to whom) to deliver the message.
This file also invokes the local side of all deliveries including DFRN-notify.

View file

@ -1,77 +0,0 @@
Profiles
========
* [Home](help)
Friendica has unlimited profiles.
You may use different profiles to present different aspects of yourself to different audiences.
Default / public profile
---
You always have a profile known as your "default" or "public" profile.
This profile is always available to the general public and usually cannot be hidden.
You may, and probably should restrict the personal information you make available on your public profile.
That said, if you want other friends to be able to find you, it helps to have the following information in your public profile:
* Your real name
* A photo of **you**
* Your location, preferably at least the country.
In addition, if you'd like to meet people that share some general interests with you, add some "Public Keywords" to your profile.
Such as "music, linux, photography" or whatever.
You can add as many keywords as you like.
Your default or public profile is also shown to contacts on other networks, since they do not have the ability to view your private profiles.
Only members of the Friendica network can see alternate/ private profiles.
Alternate/ private profiles
---
To create an alternate profile, select "Profiles" from the menu of your Friendica site.
You may edit an existing profile, change the profile photo, or create a new profile.
You may also "clone" your existing profile if you only wish to change a few items but don't wish to enter all the information again.
To assign a profile to specific persons, select the person from your "Contacts" page and click the pencil "Edit" icon.
You will find a dropdown box listing the various profiles available.
If this box is not selectable, the person is not in a supported network and cannot be assigned a specific profile.
Once a profile has been selected, when the person views your profile from one of the "magic profile links" on their site, they will see the private profile you have assigned.
If they are not logged into their site or view your profile from elsewhere, they will see your public profile.
A magic profile link is indicated by a special cursor when hovering over a contact's name or photo.
Currently this cursor is a hand next to a small padlock.
These magic cursors indicate that by following the link, you are able to access special areas of the other person's pages which are only available to friends and may not be available to the general public.
You may also discover that (assuming you have the proper permissions) you may be able to post directly on the other person's profile (often called a "wall-to-wall" post).
You may also be able to comment directly on posts from while visiting the other person's profile page.
There are two settings which allow you to publish your profile to a directory and ensure that it can be found by others.
You can change these through settings on the "Settings" page.
One setting allows you to publish your profile in the site directory of this Friendica server.
Another option (this may have been disabled by the site admin) allows you to publish your profile in a [Global Directory](Making-Friends.md#the-directories).
If you do not wish to be visible to any of these directories, do not published your profile.
Although you may have multiple profiles, you only have one profile photo.
This is intentional; it avoids confusion by potentially seeing different profile pictures of a contact depending on what website you visit or conversation you participate in.
You can always can use the free text information boxes within a profile such as "Tell us about yourself" and link other photos for yourself.
Keywords and Directory Search
---
On the site Directory page, you may search for people with published profiles who are on this site.
The search is typically for your nickname or part of your full name.
However this search will also match against other profile fields - such as gender, location, "about", work, and education.
You may also include "Keywords" in your default profile - which may be used to search for common interests with other members.
You have two sets of keywords available - public and private.
Private keywords are *not* visible on your profile, but will bring up your profile when matched in a search of the site directory.
Public keywords are used in the friend suggestion tool and although they aren't readily visible, they may be seen by viewing the HTML of your profile page.
Directory searches are also able to use "boolean" logic so that you can search for "+lesbian +Florida" and find those who's sexual preference (or keywords) contain the world "lesbian" and that live in Florida.
See the section on "Topical Tags" on the [Tags-and-Mentions](help/Tags-and-Mentions) page for more information on performing boolean searches.
On your Contacts page is a link to "Find People with Shared Interests" (unless your site administrator has disabled the global directory).
This will combine both your public and private keywords, and find people in the global directory who have matching and/or similar keywords.
Private keywords are not identified or stored on the global directory.
The more keywords you provide, the more relevant the search results that are returned.
These are sorted by relevance.
You may discover that you are the first person on the list - because you are very likely the most relevant match for your keywords in the directory.

View file

@ -15,6 +15,6 @@ Remember the link at the top of this page will bring you back here.
Once you've added some groups, <a href="help/Quick-Start-andfinally">move on to the next section</a>.
<iframe src="http://dir.friendica.social/directory" width="950" height="600"></iframe>
<iframe src="https://dir.friendica.social/forum" width="950" height="600"></iframe>

View file

@ -3,17 +3,19 @@ If you're not already logged in, do so in the frame below.
Once you've logged in (or if you are already logged in), you'll now be looking at your profile page.
This is a bit like your Facebook wall.
This is a bit like a Facebook wall.
It's where all your status messgages are kept, and where your friends come to post on your wall.
To write your status, simply click in the box that says "share".
When you do this, the box will expand.
You can see some formatting options at the top such as Bold, Italics and Underline, as well as ways to add links and pictures.
At the bottom you'll find some more links.
To write your status, simply click on the Pencil & Paper icon in the top right (in the Frio theme), or click in the box that says "share" (other themes).
When you do this, the posting dialog box will appear or the share box will expand.
You can see some formatting options such as Bold, Italics and Underline, as well as ways to add links, pictures (dependent on the theme), and a paperclip icon to attach or embed content.
You can use these to upload pictures and files from your computer, share websites with a bit of preview text, or embed video and audio files from elsewhere on the web.
With the Frio theme, the browser tab can be used to upload and post media from your account.
You can also set your post location here.
Once you've finished writing your post, click on the padlock icon to select who can see it.
If you do not use the padlock icon, your post will be public.
Once you've finished writing your post, click on the padlock icon or permissions tab to select who can see it.
If you do not change anything, your post will be public.
This means it will appear to anybody who views your profile, and in the community tab if your site has it enabled, as well as in the network tab of any of your contacts.
Play around with this a bit, then when you're ready to move on, we'll take a look at the <a href="help/Quick-Start-network">Network Tab</a>

View file

@ -11,13 +11,13 @@ with your web browser.
You will need to be logged in at the time.
You will be asked for your password to confirm the request.
If this matches your stored password, your account will immediately be blocked to all probing.
Unlike some social networks we do **not** hold onto it for a grace period in case you change your mind.
All your content and user data, etc is instantly removed.
For all intents and purposes, the account is gone in moments.
If this matches your stored password, your account will immediately be marked as deleted.
There is no grace period, this action cannot be reverted.
Most of your content and user data will be deleted shortly in the background.
We then send out an "unfriend" signal to all of your contacts.
This signal deletes all content on those networks.
Unfortunately, due to limitations of the other networks, this only works well with Friendica contacts.
We allow four days for this, in case some servers were down and the unfriend signal was queued.
After this, we finish off deleting the account.
We then send out a notification about the account removal to all of your contacts so that they can do the same with their copy of your data.
For technical reasons some of your user data is still needed to transmit this removal message.
This remaining data will be deleted after a period of around seven days.
To disallow impersonation we have to save your used nickname, so that it can't be used again to register on this node.

View file

@ -73,7 +73,7 @@ With Apache, enable the modules rewrite and ssl (with a shared hosting provider,
sudo a2enmod rewrite ssl
Add the following lines to the .htaccess file in the root folder of your Friendica instance (thanks to [url=https://github.com/AlfredSK]AlfredSK[/url]):
Add the following lines to the .htaccess file in the root folder of your Friendica instance (thanks to [AlfredSK](https://github.com/AlfredSK)):
RewriteEngine On
RewriteCond %{SERVER_PORT} 80

View file

@ -74,7 +74,7 @@ You can chose between the following modes:
##### Invitation based registry
Additionally to the setting in the admin panel, you can decide 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 [config/local.config.php](/help/Config) file.
To enable invitation based registration, you have to set the `invitation_only` setting to `true` in the `system` section of the [config/local.config.php](/help/Config) file.
If you want to use this method, the registration policy has to be set to either *open* or *requires approval*.
#### Check Full Names
@ -169,7 +169,6 @@ Your local users will always have access to both pages.
Comma separated list of domains which are allowed to establish friendships with this site.
Wildcards are accepted.
(Wildcard support on Windows platforms requires PHP5.3).
By default, any (valid) domain may establish friendships with this site.
This is useful if you want to setup a closed network for educational groups, cooperatives and similar communities that don't want to communicate with the rest of the network.
@ -179,7 +178,6 @@ This is useful if you want to setup a closed network for educational groups, coo
Comma separated list of domains which are allowed in email addresses for registrations to this site.
This can lockout those who are not part of this organisation from registering here.
Wildcards are accepted.
(Wildcard support on Windows platforms requires PHP5.3).
By default, any (valid) email address is allowed in registrations.
#### Allow Users to set remote_self

View file

@ -11,71 +11,85 @@ Creating posts
Here you can find an overview of the different ways to create and edit your post.
One click on "Share" text box on top of your Home or Network page, and the post editor shows up:
One click on the Pencil & Paper icon in the top right of your Home or Network page, or the "Share" text box, and the post editor shows up.
Below are examples of the post editor in 3 of Friendica's common themes:
<figure>
<img src="doc/img/friendica_editor.png" alt="default editor">
<figcaption>Default post editor, with default Friendica theme (duepuntozero)</figcaption>
<img src="doc/img/editor_frio.png" alt="frio editor">
<figcaption>Post editor, with the <b>Frio</b> (popular default) theme.</figcaption>
</figure>
<p style="clear:both;"></p>
<figure>
<img src="doc/img/editor_vier.png" alt="vier editor" width="675">
<figcaption>Post editor, with the <b>Vier</b> theme.</figcaption>
</figure>
<p style="clear:both;"></p>
<figure>
<img src="doc/img/editor_dpzero.png" alt="duepuntozero editor">
<figcaption>Post editor, with the <b>Duepuntozero</b> theme.</figcaption>
</figure>
Post title is optional, you can set it clicking on "Set title".
Post title is optional, you can set it by clicking on "Set title".
Posts can optionally be in one or more categories. Write categories name separated by a comma to file your new post.
Posts can optionally be in one or more categories. Write category names separated by a comma to file your new post.
The Big Empty Textarea is where you write your new post.
You can simply enter your text there and click "Share" button, and your new post will be public on your profile page and shared to your contact.
You can simply enter your text there and click the "Share" button, and your new post will be public on your profile page and shared to your contact.
If plain text is not so exciting to you, Friendica understands BBCode to spice up your posts: bold, italic, images, links, lists..
See [BBCode tags reference](help/BBCode) page to see all what you can do.
The icons under the text area are there to help you to write posts quickly:
The icons under the text area are there to help you to write posts quickly, but vary depending on the theme:
<img src="doc/img/camera.png" width="32" height="32" alt="editor" align="left" style="padding-bottom: 20px;"> Upload a picture from your computer. The image will be uploaded and correct bbcode tag will be added to your post.*
With the Frio theme, the Underline, Italics and Bold buttons should be self-explanatory.
<img src="doc/img/camera.png" width="32" height="32" alt="editor" align="left"> Upload a picture from your computer. The image will be uploaded and correct bbcode tag will be added to your post.* In the Frio theme, use the <b>Browser</b> tab instead to Upload and/or attach content to your post.
<p style="clear:both;"></p>
<img src="doc/img/paper_clip.png" width="32" height="32" alt="paper_clip" align="left"> Add files from your computer. Same as picture, but for generic attachment to the post.*
<img src="doc/img/paper_clip.png" width="32" height="32" alt="paper_clip" align="left"> This depends on the theme: For Frio, this is to attach remote content - put in a URL to embed in your post, including video or audio content. For other themes: Add files from your computer. Same as picture, but for generic attachment to the post.*
<p style="clear:both;"></p>
<img src="doc/img/chain.png" width="32" height="32" alt="chain" align="left"> Add a web address (url). Enter an url and Friendica will add to your post a link to the url and an excerpt from the web site, if possible.
<img src="doc/img/chain.png" width="32" height="32" alt="chain" align="left"> Add a web address (url). Enter a URL and Friendica will add to your post a link to the url and an excerpt from the web site, if possible.
<p style="clear:both;"></p>
<img src="doc/img/video.png" width="32" height="32" alt="video" align="left"> Add a video. Enter the url to a video (ogg) or to a video page on youtube or vimeo, and it will be embedded in your post with a preview. Friendica is using [HTML5](http://en.wikipedia.org/wiki/HTML5_video) for embedding content. Therefore, the supported files are depending on your browser and operating system (OS). Some filetypes are WebM, MP4 and OGG.*
<img src="doc/img/video.png" width="32" height="32" alt="video" align="left"> Add a video. Enter the url to a video (ogg) or to a video page on youtube or vimeo, and it will be embedded in your post with a preview. (In the Frio theme, this is done with the paperclip as mentioned above.) Friendica is using [HTML5](http://en.wikipedia.org/wiki/HTML5_video) for embedding content. Therefore, the supported files are depending on your browser and operating system (OS). Some filetypes are WebM, MP4 and OGG.*
<p style="clear:both;"></p>
<img src="doc/img/mic.png" width="32" height="32" alt="mic" align="left" style="padding-bottom: 20px;"> Add an audio. Same as video, but for audio. Depending on your browser and operation system MP3, OGG and AAC are supported. Additionally, you are able to add URLs from audiohosters like Soundcloud.
<img src="doc/img/mic.png" width="32" height="32" alt="mic" align="left"> Add an audio. Same as video, but for audio. Depending on your browser and operation system MP3, OGG and AAC are supported. Additionally, you are able to add URLs from audiohosters like Soundcloud.
<p style="clear:both;"></p>
<img src="doc/img/globe.png" width="32" height="32" alt="globe" align="left"> Set your geographic location. This location will be added into a Google Maps search. That's why a note like "New York" or "10004" is already enough.
<img src="doc/img/globe.png" width="32" height="32" alt="globe" align="left"> <b>Or</b> <img src="doc/img/frio_location.png" width="32" height="32" alt="location" align="none"> Set your geographic location. This location will be added into a Google Maps search. That's why a note like "New York" or "10004" is already enough.
<p style="clear:both;"></p>
<br />
<p style="clear:both;"></p>
<i>* how to [upload](help/FAQ#upload) files</i>
Those icons can change with themes. Some examples:
These icons can change depending on the theme. Some examples:
<table>
<tr>
<td>Darkbubble: </td>
<td>Vier: </td>
<td><img src="doc/img/vier_icons.png" alt="vier.png" style="vertical-align:middle;"></td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Smoothly: </td>
<td><img src="doc/img/editor_darkbubble.png" alt="darkbubble.png" style="vertical-align:middle;"></td>
<td><i>(inkl. smoothly, testbubble)</i></td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Frost: </td>
<td><img src="doc/img/editor_frost.png" alt="frost.png" style="vertical-align:middle;"> </td>
<td>&nbsp;</td>
</tr>
<tr>
<td>Vier: </td>
<td><img src="doc/img/editor_vier.png" alt="vier.png" style="vertical-align:middle;"></td>
<td><i>(inkl. dispy)</i></td>
</tr>
</table>
<p style="clear:both;">&nbsp;</p>
<i><b>*</b> how to [upload](help/FAQ#upload) files</i>
<p style="clear:both;">&nbsp;</p>
**<img src="doc/img/lock.png" width="32" height="32" alt="lock icon" style="vertical-align:middle;"> The lock**
**<img src="doc/img/lock.png" width="32" height="32" alt="lock icon" style="vertical-align:middle;"> The Lock / Permissions**
The last button, the Lock, is the most important feature in Friendica. If the lock is open, your post will be public, and will shows up on your profile page when strangers visit it.
In Frio, the Permissions tab, or in other themes, the Lock button, is the most important feature in Friendica. If the lock is open, your post will be public, and will show up on your profile page when strangers visit it.
Click on it and the *Permission settings* window (aka "*Access Control Selector*" or "*ACL Selector*") pops up. There you can select who can see the post.
@ -95,4 +109,4 @@ Click again on "show" or "don't show" to switch it off.
You can search for contacts or groups with the search box.
See also [Group and Privacy](help/Groups-and-Privacy)
See also [Group and Privacy](help/Groups-and-Privacy)

View file

@ -0,0 +1,74 @@
# Configuring two-factor authentication
* [Home](help)
You can configure two-factor authentication using a mobile app.
A time-based one-time password (TOTP) application automatically generates an authentication code that changes after a certain period of time.
**Tip**: To configure authentication via TOTP on multiple devices, during setup, scan the QR code using each device at the same time.
If 2FA is already enabled and you want to add another device, you must re-configure 2FA from your security settings.
## Enabling two-factor authentication
### 1. Download an authenticator app
Any authenticator app should work with Friendica.
Notheless, we recommend:
- For iOS, [Matt Rubin's MIT-licensed Authenticator app](https://mattrubin.me/authenticator).
- For Android, [andOTP](https://github.com/andOTP/andOTP).
### 2. Record your one-use recovery codes
From your [two-factor authentication user settings](/settings/2fa), enter your password and click on "Enable two-factor authentication".
You will be presented with a list of one-use recovery codes.
Please save those in the same place you are saving your Friendica password (ideally, in a password manager like [KeePass](https://keepass.info)).
When you're done, click on "Next".
### 3. Setup your authenticator app
You have three methods to setup your authenticator app:
1. Scan the QR Code with your device camera.
This will automatically configure your account on the app.
2. Click/tap on the provided **totp://** URl.
Ideally your authenticator app should be called with this URL and set up your account.
3. Enter your account settings manually.
Friendica is using default settings for token type, code digit count and hashing algorithm but you may be required to enter them in your app.
**Tip**: If you have multiple devices, configure them all at this point.
Then verify your app is correctly configured by submitting a code provided by your app.
This will conclude two-factor authentication configuration.
**Note:** If you leave this screen at any point without having submitted a verification code, two-factor authentication won't be enabled on your account.
To complete the configuration, just come back to your [two-factor authentication user settings](/settings/2fa) and click on "Finish configuration" after entering your current password.
## Disabling two-factor authentication
You can disable two-factor authentication at any time by going to your [two-factor authentication user settings](/settings/2fa) and click on "Disable two-factor authentication" after entering your current password.
You should remove your Friendica account from your authenticator app as it won't work again even if you reenable two-factor authentication.
In this case you will have to configure your authenticator app again using the process above.
## Managing your one-time recovery codes
When two-factor authentication is enabled, you can show your recovery codes, including the ones you've already used.
You can freely regenerate a new set of fresh recovery codes, just be sure to replace the previous ones where you saved them as they won't be active anymore.
## Third-party applications and API
Third-party applications using the Friendica API can't accept two-factor time-based authentication codes.
Instead, if you enabled two-factor authentication, you have to generate app-specific randomly generated long passwords to use in your apps instead of your regular account password.
**Note**: Your regular password won't work at all when prompted in third-party apps if you enabled two-factor authentication.
You can generate as many app-specific passwords as you want, they will be shown once to you just after you generated it.
Just copy and paste it in your third-party app in the Friendica account password input field at this point.
We recommend generating a single app-specific password for each separate third-party app you are using, using a meaningul description of the target app (like "Frienqa on my Fairphone 2").
You can also revoke any and all app-specific password you generated this way.
This may log you out of the third-party application(s) you used the revoked app-specific password to log in with.

View file

@ -6,8 +6,15 @@ Updating Friendica
## Using a Friendica archive
If you installed Friendica in the ``path/to/friendica`` folder:
1. Unpack the new Friendica archive in ``path/to/friendica_new``.
2. Copy ``config/local.config.php``, ``photo/`` and ``proxy/`` from ``path/to/friendica`` to ``path/to/friendica_new``.
2. Copy the following items from ``path/to/friendica`` to ``path/to/friendica_new``:
* ``config/local.config.php``
* ``proxy/``
The following items only need to be copied if they are located inside your friendica path:
* your storage folder as set in **Admin -> Site -> File Upload -> Storage base path**
* your item cache as set in **Admin -> Site -> Performance -> Path to item cache**
* your temp folder as set in **Admin -> Site -> Advanced -> Temp path**
3. Rename the ``path/to/friendica`` folder to ``path/to/friendica_old``.
4. Rename the ``path/to/friendica_new`` folder to ``path/to/friendica``.
5. Check your site. Note: it may go into maintenance mode to update the database schema.
@ -21,7 +28,7 @@ You can get the latest changes at any time with
cd path/to/friendica
git pull
bin/composer.phar install
bin/composer.phar install --no-dev
The addon tree has to be updated separately like so:
@ -29,11 +36,11 @@ The addon tree has to be updated separately like so:
git pull
For both repositories:
The default branch to use is the ``master`` branch, which is the stable version of Friendica.
The default branch to use is the ``stable`` branch, which is the stable version of Friendica.
It is updated about four times a year on a fixed schedule.
If you want to use and test bleeding edge code please checkout the ``develop`` branch.
The new features and fixes will be merged from ``develop`` into ``master`` after a release candidate period before each release.
The new features and fixes will be merged from ``develop`` into ``stable`` after a release candidate period before each release.
Warning: The ``develop`` branch is unstable, and breaks on average once a month for at most 24 hours until a patch is submitted and merged.
Be sure to pull frequently if you choose the ``develop`` branch.
@ -69,4 +76,4 @@ DROP TABLE <table_name>;
RENAME TABLE <table_name>_new TO <table_name>;
```
This method is slower overall, but it is better suited for large numbers of duplicates.
This method is slower overall, but it is better suited for large numbers of duplicates.

1422
doc/api.md

File diff suppressed because it is too large Load diff

View file

@ -47,8 +47,10 @@ The code will be something like:
// mod/network.php
<?php
use Friendica\App;
function network_content(App $a) {
$itemsmanager = new Friendica\ItemsManager();
$itemsmanager = new \Friendica\ItemsManager();
$items = $itemsmanager->getAll();
// pass $items to template
@ -117,6 +119,8 @@ If your code is in same namespace as the class you need, you don't need to prepe
namespace Friendica;
use Friendica\Protocol\DFRN;
// this is the same content of current include/delivery.php,
// but has been declared to be in "Friendica" namespace

View file

@ -18,9 +18,6 @@ Database Tables
| [event](help/database/db_event) | Events |
| [fcontact](help/database/db_fcontact) | friend suggestion stuff |
| [fsuggest](help/database/db_fsuggest) | friend suggestion stuff |
| [gcign](help/database/db_gcign) | contacts ignored by friend suggestions |
| [gcontact](help/database/db_gcontact) | global contacts |
| [glink](help/database/db_glink) | "friends of friends" linkages derived from poco |
| [group](help/database/db_group) | privacy groups, group info |
| [group_member](help/database/db_group_member) | privacy groups, member info |
| [gserver](help/database/db_gserver) | |

View file

@ -67,6 +67,6 @@ Table contact
| bd | | date | NO | | 0001-01-01 | |
| notify_new_posts | | tinyint(1) | NO | | 0 | |
| fetch_further_information | | tinyint(1) | NO | | 0 | |
| ffi_keyword_blacklist | | mediumtext | NO | | NULL | |
| ffi_keyword_denylist | | mediumtext | NO | | NULL | |
Return to [database documentation](help/database)

View file

@ -1,10 +0,0 @@
Table gcign
===========
| Field | Description | Type | Null | Key | Default | Extra |
| ----- | ------------------------------ | ------- | ---- | --- | ------- | --------------- |
| id | sequential ID | int(11) | NO | PRI | NULL | auto_increment |
| uid | local user.id | int(11) | NO | MUL | 0 | |
| gcid | gcontact.id of ignored contact | int(11) | NO | MUL | 0 | |
Return to [database documentation](help/database)

View file

@ -1,32 +0,0 @@
Table gcontact
==============
| Field |Description | Type | Null | Key | Default | Extra |
|--------------|------------------------------------|------------------|------|-----|---------------------|----------------|
| id | sequential ID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | Name that this contact is known by | varchar(255) | NO | | | |
| nick | Nick- and user name of the contact | varchar(255) | NO | | | |
| url | Link to the contacts profile page | varchar(255) | NO | | | |
| nurl | | varchar(255) | NO | MUL | | |
| photo | Link to the profile photo | varchar(255) | NO | | | |
| connect | | varchar(255) | NO | | | |
| created | | datetime | NO | | 0001-01-01 00:00:00 | |
| updated | | datetime | YES | MUL | 0001-01-01 00:00:00 | |
| last_contact | | datetime | YES | | 0001-01-01 00:00:00 | |
| last_failure | | datetime | YES | | 0001-01-01 00:00:00 | |
| location | | varchar(255) | NO | | | |
| about | | text | NO | | NULL | |
| keywords | puplic keywords (interests) | text | NO | | NULL | |
| gender | | varchar(32) | NO | | | |
| birthday | | varchar(32) | NO | | 0001-01-01 | |
| community | 1 if contact is forum account | tinyint(1) | NO | | 0 | |
| hide | 1 = should be hidden from search | tinyint(1) | NO | | 0 | |
| nsfw | 1 = contact posts nsfw content | tinyint(1) | NO | | 0 | |
| network | social network protocol | varchar(255) | NO | | | |
| addr | | varchar(255) | NO | | | |
| notify | | text | NO | | | |
| alias | | varchar(255) | NO | | | |
| generation | | tinyint(3) | NO | | 0 | |
| server_url | baseurl of the contacts server | varchar(255) | NO | | | |
Return to [database documentation](help/database)

View file

@ -1,13 +0,0 @@
Table glink
===========
| Field | Description | Type | Null | Key | Default | Extra |
|---------|------------------|------------------|------|-----|---------------------|----------------|
| id | sequential ID | int(10) unsigned | NO | PRI | NULL | auto_increment |
| cid | | int(11) | NO | MUL | 0 | |
| uid | | int(11) | NO | | 0 | |
| gcid | | int(11) | NO | MUL | 0 | |
| zcid | | int(11) | NO | MUL | 0 | |
| updated | | datetime | NO | | 0001-01-01 00:00:00 | |
Return to [database documentation](help/database)

View file

@ -9,36 +9,36 @@ Table profile
| is-default | Mark this profile as default profile | tinyint(1) | NO | | 0 | |
| hide-friends | Hide friend list from viewers of this profile | tinyint(1) | NO | | 0 | |
| name | | varchar(255) | NO | | | |
| pdesc | Title or description | varchar(255) | NO | | | |
| pdesc | Deprecated | varchar(255) | NO | | | |
| dob | Day of birth | varchar(32) | NO | | 0001-01-01 | |
| address | | varchar(255) | NO | | | |
| locality | | varchar(255) | NO | | | |
| region | | varchar(255) | NO | | | |
| postal-code | | varchar(32) | NO | | | |
| country-name | | varchar(255) | NO | | | |
| hometown | | varchar(255) | NO | MUL | | |
| gender | | varchar(32) | NO | | | |
| marital | | varchar(255) | NO | | | |
| with | | text | NO | | NULL | |
| howlong | | datetime | NO | | 0001-01-01 00:00:00 | |
| sexual | | varchar(255) | NO | | | |
| politic | | varchar(255) | NO | | | |
| religion | | varchar(255) | NO | | | |
| hometown | Deprecated | varchar(255) | NO | MUL | | |
| gender | Deprecated | varchar(32) | NO | | | |
| marital | Deprecated | varchar(255) | NO | | | |
| with | Deprecated | text | NO | | NULL | |
| howlong | Deprecated | datetime | NO | | 0001-01-01 00:00:00 | |
| sexual | Deprecated | varchar(255) | NO | | | |
| politic | Deprecated | varchar(255) | NO | | | |
| religion | Deprecated | varchar(255) | NO | | | |
| pub_keywords | | text | NO | | NULL | |
| prv_keywords | | text | NO | | NULL | |
| likes | | text | NO | | NULL | |
| dislikes | | text | NO | | NULL | |
| about | | text | NO | | NULL | |
| summary | | varchar(255) | NO | | | |
| music | | text | NO | | NULL | |
| book | | text | NO | | NULL | |
| tv | | text | NO | | NULL | |
| film | | text | NO | | NULL | |
| interest | | text | NO | | NULL | |
| romance | | text | NO | | NULL | |
| work | | text | NO | | NULL | |
| education | | text | NO | | NULL | |
| contact | | text | NO | | NULL | |
| likes | Deprecated | text | NO | | NULL | |
| dislikes | Deprecated | text | NO | | NULL | |
| about | Profile description | text | NO | | | |
| summary | Deprecated | varchar(255) | NO | | | |
| music | Deprecated | text | NO | | NULL | |
| book | Deprecated | text | NO | | NULL | |
| tv | Deprecated | text | NO | | NULL | |
| film | Deprecated | text | NO | | NULL | |
| interest | Deprecated | text | NO | | NULL | |
| romance | Deprecated | text | NO | | NULL | |
| work | Deprecated | text | NO | | NULL | |
| education | Deprecated | text | NO | | NULL | |
| contact | Deprecated | text | NO | | NULL | |
| homepage | | varchar(255) | NO | | | |
| photo | | varchar(255) | NO | | | |
| thumb | | varchar(255) | NO | | | |

View file

@ -109,8 +109,6 @@ Ein ['Tipp für neue Mitglieder'](newmember)-Link zeigt sich in den ersten beide
## Schau Dir ebenfalls folgende Seiten an
* [Profile](help/Profiles)
* [Gruppen und Privatssphäre](help/Groups-and-Privacy)
* [Account löschen](help/Remove-Account)

View file

@ -195,14 +195,14 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('init_1');
Hook::callAll('app_menu', $arr);
Hook::callAll('page_content_top', $a->page['content']);
Hook::callAll('page_content_top', DI::page()['content']);
Hook::callAll($a->module.'_mod_init', $placeholder);
Hook::callAll($a->module.'_mod_init', $placeholder);
Hook::callAll($a->module.'_mod_post', $_POST);
Hook::callAll($a->module.'_mod_afterpost', $placeholder);
Hook::callAll($a->module.'_mod_content', $arr);
Hook::callAll($a->module.'_mod_aftercontent', $arr);
Hook::callAll('page_end', $a->page['content']);
Hook::callAll('page_end', DI::page()['content']);
### include/api.php
@ -226,20 +226,6 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('item_photo_menu', $args);
Hook::callAll('jot_tool', $jotplugins);
### include/text.php
Hook::callAll('contact_block_end', $arr);
Hook::callAll('poke_verbs', $arr);
Hook::callAll('put_item_in_cache', $hook_data);
Hook::callAll('prepare_body_init', $item);
Hook::callAll('prepare_body_content_filter', $hook_data);
Hook::callAll('prepare_body', $hook_data);
Hook::callAll('prepare_body_final', $hook_data);
### include/items.php
Hook::callAll('page_info_data', $data);
### mod/directory.php
Hook::callAll('directory_item', $arr);
@ -256,7 +242,7 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll("parse_link", $arr);
### mod/manage.php
### src/Module/Delegation.php
Hook::callAll('home_init', $ret);
@ -326,10 +312,6 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('post_local_end', $arr);
### mod/lockview.php
Hook::callAll('lockview_content', $item);
### mod/uexport.php
Hook::callAll('uexport_options', $options);
@ -365,6 +347,11 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('post_remote_end', $posted_item);
Hook::callAll('tagged', $arr);
Hook::callAll('post_local_end', $new_item);
Hook::callAll('put_item_in_cache', $hook_data);
Hook::callAll('prepare_body_init', $item);
Hook::callAll('prepare_body_content_filter', $hook_data);
Hook::callAll('prepare_body', $hook_data);
Hook::callAll('prepare_body_final', $hook_data);
### src/Model/Contact.php
@ -387,6 +374,10 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('register_account', $uid);
Hook::callAll('remove_user', $user);
### src/Content/ContactBlock.php
Hook::callAll('contact_block_end', $arr);
### src/Content/Text/BBCode.php
@ -409,9 +400,6 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
### src/Content/ContactSelector.php
Hook::callAll('network_to_name', $nets);
Hook::callAll('gender_selector', $select);
Hook::callAll('sexpref_selector', $select);
Hook::callAll('marital_selector', $select);
### src/Content/OEmbed.php
@ -419,12 +407,20 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
### src/Content/Nav.php
Hook::callAll('page_header', $a->page['nav']);
Hook::callAll('page_header', DI::page()['nav']);
Hook::callAll('nav_info', $nav);
### src/Core/Authentication.php
Hook::callAll('logged_in', $a->user);
### src/Core/StorageManager
Hook::callAll('storage_instance', $data);
### src/Module/PermissionTooltip.php
Hook::callAll('lockview_content', $item);
### src/Worker/Directory.php
@ -434,11 +430,6 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('notifier_end', $target_item);
### src/Worker/Queue.php
Hook::callAll('queue_predeliver', $r);
Hook::callAll('queue_deliver', $params);
### src/Module/Login.php
Hook::callAll('authenticate', $addon_auth);
@ -462,13 +453,25 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll($a->module.'_post_'.$selname, $o);
Hook::callAll('jot_networks', $jotnets);
### src/Core/Authentication.php
Hook::callAll('logged_in', $a->user);
### src/Core/Hook.php
self::callSingle(self::getApp(), 'hook_fork', $fork_hook, $hookdata);
### src/Core/L10n/L10n.php
Hook::callAll('poke_verbs', $arr);
### src/Core/Worker.php
Hook::callAll("proc_run", $arr);
### src/Util/Emailer.php
Hook::callAll('emailer_send_prepare', $params);
Hook::callAll('emailer_send_prepare', $email);
Hook::callAll("emailer_send", $hookdata);
### src/Util/Map.php
@ -489,3 +492,8 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
Hook::callAll('atom_feed_end', $atom);
Hook::callAll('atom_feed_end', $atom);
### src/Protocol/Email.php
Hook::callAll('email_getmessage', $message);
Hook::callAll('email_getmessage_end', $ret);

View file

@ -65,17 +65,17 @@ table.bbcodes > * > tr > th {
<td><a href="http://friendi.ca" target="external-link">Friendica</a></td>
</tr>
<tr>
<td>[img]https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg[/img]</td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg" alt="Immagine/foto"></td>
<td>[img]https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg[/img]</td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg" alt="Immagine/foto"></td>
</tr>
<tr>
<td>[img=https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg]Das Friendica Logo[/img]</td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg" alt="Das Friendica Logo"></td>
<td>[img=https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg]Das Friendica Logo[/img]</td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg" alt="Das Friendica Logo"></td>
</tr>
<tr>
<td>[img=64x32]https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg[/img]<br>
<td>[img=64x32]https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg[/img]<br>
<br>Note: provided height is simply discarded.</td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg" style="width: 64px;"></td>
<td><img src="https://raw.githubusercontent.com/friendica/friendica/stable/images/friendica-32.jpg" style="width: 64px;"></td>
</tr>
<tr>
<td>[size=xx-small]kleiner Text[/size]</td>
@ -113,17 +113,17 @@ table.bbcodes > * > tr > th {
<tr>
<td>[bookmark]http://friendi.ca[/bookmark]<br><br>
#^[url]http://friendi.ca[/url]</td>
<td><span class="oembed link"><h4>Friendica: <a href="http://friendi.ca" rel="oembed"></a><a href="http://friendi.ca" target="_blank">http://friendi.ca</a></h4></span></td>
<td><span class="oembed link"><h4>Friendica: <a href="http://friendi.ca" rel="oembed"></a><a href="http://friendi.ca" target="_blank" rel="noopener noreferrer">http://friendi.ca</a></h4></span></td>
</tr>
<tr>
<td>[bookmark=http://friendi.ca]Lesezeichen[/bookmark]<br><br>
#^[url=http://friendi.ca]Lesezeichen[/url]<br><br>
#[url=http://friendi.ca]^[/url][url=http://friendi.ca]Lesezeichen[/url]</td>
<td><span class="oembed link"><h4>Friendica: <a href="http://friendi.ca" rel="oembed"></a><a href="http://friendi.ca" target="_blank">Lesezeichen</a></h4></span></td>
<td><span class="oembed link"><h4>Friendica: <a href="http://friendi.ca" rel="oembed"></a><a href="http://friendi.ca" target="_blank" rel="noopener noreferrer">Lesezeichen</a></h4></span></td>
</tr>
<tr>
<td>[url=/posts/f16d77b0630f0134740c0cc47a0ea02a]Diaspora Beitrag mit GUID[/url]</td>
<td><a href="/display/f16d77b0630f0134740c0cc47a0ea02a" target="_blank">Diaspora Beitrag mit GUID</a></td>
<td><a href="/display/f16d77b0630f0134740c0cc47a0ea02a" target="_blank" rel="noopener noreferrer">Diaspora Beitrag mit GUID</a></td>
</tr>
<tr>
<td>#Friendica</td>
@ -580,6 +580,9 @@ F&uuml;r Verbindungen zu Netzwerken, zu denen Friendica den HTML Code postet, wi
Bei nativen Verbindungen; das hei&szlig;t zu z.B. Friendica, Hubzilla, Diaspora oder GNU Social Kontakten; wird der ungek&uuml;rzte Beitrag &uuml;bertragen.
Die Instanz des Kontakts k&uuml;mmert sich um die Darstellung.
Wird ein Beitrag über das ActivityPub Protokoll &uuml;bermittelt, wird der Text des Abstracts f&uuml;r das "summary" (Zusammenfassung) Feld verwendet.
Dieses Feld wird von Mastodon f&uuml;r die Inhaltswarnung (content warning) verwendet.
## Special
<table class="bbcodes">

View file

@ -25,13 +25,13 @@ In den ersten Zeilen wird Dir Dein Name und Deine aktuelle IP-Adresse angezeigt.
Rechts im Fenster siehst Du alle Teilnehmer des Chats.
Unten hast Du ein Eingabefeld, um Beiträge zu schreiben.
Weiter Informationen zu IRC findest Du zum Beispiel auf <a href="http://wiki.ubuntuusers.de/IRC" target="_blank">ubuntuusers.de</a>, in <a href="https://de.wikipedia.org/wiki/Internet_Relay_Chat" target="_blank">Wikipedia</a> oder bei <a href="http://www.irchelp.org/" target="_blank">icrhelp.org</a> (in Englisch).
Weiter Informationen zu IRC findest Du zum Beispiel auf <a href="http://wiki.ubuntuusers.de/IRC" target="_blank" rel="noopener noreferrer">ubuntuusers.de</a>, in <a href="https://de.wikipedia.org/wiki/Internet_Relay_Chat" target="_blank" rel="noopener noreferrer">Wikipedia</a> oder bei <a href="http://www.irchelp.org/" target="_blank" rel="noopener noreferrer">icrhelp.org</a> (in Englisch).
## Jappix Mini
Das Jappix Mini Addon erlaubt das Erstellen einer Chatbox für Jabber/XMPP-Kontakte.
Ein Jabber/XMPP Account sollte vor der Installation bereits vorhanden sein.
Die ausführliche Anleitung dazu und eine Kontrolle, ob Du nicht sogar schon über Deinen E-Mail Anbieter einen Jabber-Account hast, findest Du unter <a href="http://einfachjabber.de" target="_blank">einfachjabber.de</a>.
Die ausführliche Anleitung dazu und eine Kontrolle, ob Du nicht sogar schon über Deinen E-Mail Anbieter einen Jabber-Account hast, findest Du unter <a href="http://einfachjabber.de" target="_blank" rel="noopener noreferrer">einfachjabber.de</a>.
Einige Server zum Anmelden eines neuen Accounts:
@ -49,7 +49,7 @@ Per Git:
cd /var/www/&lt;Pfad zu Deiner friendica-Installation&gt;/addon; git pull
</p>
oder als normaler Download von hier: https://github.com/friendica/friendica-addons/blob/master/jappixmini.tgz (auf „view raw“ klicken)
oder als normaler Download von hier: https://github.com/friendica/friendica-addons/blob/stable/jappixmini.tgz (auf „view raw“ klicken)
Entpacke diese Datei (ggf. den entpackten Ordner in „jappixmini“ umbenennen) und lade sowohl den entpackten Ordner komplett als auch die .tgz Datei in den Addon Ordner Deiner Friendica Installation hoch.

View file

@ -26,4 +26,4 @@ Dies gilt vor allem für Übersetzungen, da wir hier möglicherweise nicht alle
Außerdem: **teste Deine Änderungen!** Vergiss nicht, dass eine simple Fehlerlösung einen anderen Fehler auslösen kann.
Lass Deine Änderungen von einem erfahrenen Friendica-Entwickler gegenprüfen.
Eine ausführliche Anleitung zu Git findest Du unter <a href="https://git-scm.com/book/de/v1" target="_blank">https://git-scm.com/book/de/v1</a>.
Eine ausführliche Anleitung zu Git findest Du unter <a href="https://git-scm.com/book/de/v1" target="_blank" rel="noopener noreferrer">https://git-scm.com/book/de/v1</a>.

View file

@ -0,0 +1,23 @@
# Export / Import von gefolgten Kontakte
* [Home](help)
Zusätzlich zum [Umziehen des Accounts](help/Move-Account) kannst du die Liste der von dir gefolgten Kontakte exportieren und importieren.
Die exportierte Liste wird als CSV Datei in einem zu anderen Plattformen, z.B. Mastodon oder Pleroma, kompatiblen Format gespeichert.
## Export der gefolgten Kontakte
Um die Liste der Kontakte *denen du folgst* zu exportieren, geht die [Einstellungen Persönliche Daten exportieren](settings/userexport) und klicke den [Exportiere Kontakte als CSV](settings/userexport/contact) an.
## Import der gefolgten Kontakte
Um die Kontakt CSV Datei zu importieren, gehe in die [Einstellungen](settings).
Am Ende der Einstellungen zum Nutzerkonto findest du den Abschnitt "Kontakte Importieren".
Hier kannst du die CSV Datei auswählen und hoch laden.
### Unterstütztes Datei Format
Die CSV Datei *muss* mindestens eine Spalte beinhalten.
In der ersten Spalte der Tabelle sollte *sollte* entweder das Handle oder die URL des gefolgten Kontakts.
(Ein Kontakt pro Zeile.)
Alle anderen Spalten der CSV Datei werden beim Importieren ignoriert.

View file

@ -106,16 +106,6 @@ auf Deutsch:
https://social.example.com/profile/example?lang=de.
Wenn das Fragezeichen bereits in der URL verwendet wird, werden die einzelnen URL Parameter mit einem kaufmännischen Und getrennt werden.
Ein Beispiel:
https://social.example.com/profile/example?tab=profile
auf Deutsch:
https://social.example.com/profile/example?tab=profile&lang=de.
<a name="contacts"></a>
### Was ist der Unterschied zwischen blockierten|ignorierten|archivierten|versteckten Kontakten?
@ -188,7 +178,9 @@ Das bedeutet, dass du jeden Twitter/GNU Social Client verwenden kannst in dem du
Hier ist eine Liste von Clients bei denen dies möglich ist, bzw. die speziell für Friendica entwickelt werden:
* Android
* [Friendiqa](https://github.com/lubuwest/friendiqa) (Gibt es im Google Playstore oder als [binary Repository](https://freunde.ma-nic.de/display/3e98eba8185a13c5bdbf3d1539646854) für F-Droid)
* [Friendiqa](https://git.friendi.ca/lubuwest/Friendiqa) (Gibt es im Google Playstore oder als [binary Repository](https://freunde.ma-nic.de/display/3e98eba8185a13c5bdbf3d1539646854) für F-Droid)
* [Fedilab](https://gitlab.com/tom79/mastalab) (Gibt es im F-Droid und dem Google Play Store)
* [DiCa](https://dica.mixi.cool/) (Gibt es bei Google Play)
* AndStatus
* Twidere
* Mustard and Mustard-Mod

View file

@ -38,7 +38,7 @@ Du musst das nicht machen, die Alternative ist allerdings, Dich immer wieder aus
Und das kann umständlich sein, wenn Du mehrere verschiedene Foren/Identitäten verwaltest.
Du kannst ebenso jemanden wählen, der Dein Forum verwaltet.
Mach das, indem Du die [Delegations-Setup-Seite](/delegate) besuchst.
Mach das, indem Du die [Delegations-Setup-Seite](/settings/delegation) besuchst.
Dort wird Dir eine Liste an "Potentiellen Bevollmächtigen" angezeigt.
Die Auswahl einer oder mehrerer Personen gibt diesen die Möglichkeit, Dein Forum zu verwalten.
Sie können Kontakte, Profile und alle Inhalte Deines Accounts/deiner Seite bearbeiten.

View file

@ -9,7 +9,6 @@ Friendica - Dokumentation und Ressourcen
* [Beiträge erstellen](help/Text_editor)
* [Referenz der BBCode Elemente](help/BBCode)
* [Beiträge kommentieren, einordnen und löschen](help/Text_comment)
* [Profile](help/Profiles)
* [Referenz der Accesskeys](help/Accesskeys)
* [Veranstaltungen](help/events)
* Du und andere Nutzer
@ -21,6 +20,7 @@ Friendica - Dokumentation und Ressourcen
* [Chats](help/Chats)
* Weiterführende Informationen
* [Account umziehen](help/Move-Account)
* [Export / Import gefolgter Kontakte](help/Export-Import-Contacts)
* [Account löschen](help/Remove-Account)
* [Bugs und Probleme](help/Bugs-and-Issues)
* [Häufig gestellte Fragen (FAQ)](help/FAQ)

View file

@ -28,12 +28,12 @@ Requirements
---
* Apache mit einer aktiverten mod-rewrite-Funktion und dem Eintrag "Options All", so dass du die lokale .htaccess-Datei nutzen kannst
* PHP 5.6.1+ (PHP 7 ist aufgrund der Performance empfohlen)
* PHP 7+ (PHP 7.1+ wird für Performance und offiziellen Support empfohlen)
* PHP *Kommandozeilen*-Zugang mit register_argc_argv auf "true" gesetzt in der php.ini-Datei
* Curl, GD, PDO, MySQLi, xml, zip und OpenSSL-Erweiterung
* Das POSIX Modul muss aktiviert sein ([CentOS, RHEL](http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7http://www.bigsoft.co.uk/blog/index.php/2014/12/08/posix-php-commands-not-working-under-centos-7) haben dies z.B. deaktiviert)
* etwas in der Art eines Email-Servers oder eines Gateways wie PHP mail()
* Mysql 5.5.3+ (oder eine äquivalente Alternative: MariaDB, Percona Server etc.)
* Mysql 5.6+ (oder eine äquivalente Alternative: MariaDB, Percona Server etc.)
* die Möglichkeit, wiederkehrende Aufgaben mit cron (Linux/Mac) oder "Scheduled Tasks" einzustellen (Windows) [Beachte: andere Optionen sind in Abschnitt 7 dieser Dokumentation zu finden]
* 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.
@ -55,7 +55,7 @@ Wenn du die Möglichkeit hierzu hast, empfehlen wir dir "git" zu nutzen, um die
Das macht die Aktualisierung wesentlich einfacher.
Der Linux-Code, mit dem man die Dateien direkt in ein Verzeichnis wie "meinewebseite" kopiert, ist
git clone https://github.com/friendica/friendica.git -b master mywebsite
git clone https://github.com/friendica/friendica.git -b stable mywebsite
cd mywebsite
bin/composer.phar install
@ -70,7 +70,7 @@ Falls Addons installiert werden sollen: Gehe in den Friendica-Ordner
Und die Addon Repository klonst:
git clone https://github.com/friendica/friendica-addons.git -b master addon
git clone https://github.com/friendica/friendica-addons.git -b stable addon
Um das Addon-Verzeichnis aktuell zu halten, solltest du in diesem Pfad ein "git pull"-Befehl eintragen
@ -107,6 +107,7 @@ Starte MySQL dann neu und es sollte klappen.
### Option A: Der manuelle Installer
Besuche deine Webseite mit deinem Browser und befolge die Anleitung.
Bevor du dies tust, kopiere die Datei `.htaccess-dist` nach `.htaccess`, wenn du den Apache Webserver verwendest.
Bitte beachte jeden Fehler und korrigiere diese, bevor du fortfährst.
Falls du einen Port für die Datenbankverbindung angeben musst, kannst du diesen in der Host-Eingabe Zeile angeben.

View file

@ -6,9 +6,7 @@ Friendica Nachrichtenfluss
Diese Seite soll einige Infos darüber dokumentieren, wie Nachrichten innerhalb von Friendica von einer Person zur anderen übertragen werden.
Es gibt verschiedene Pfade, die verschiedene Protokolle und Nachrichtenformate nutzen.
Diejenigen, die den Nachrichtenfluss genauer verstehen wollen, sollten sich mindestens mit dem DFRN-Protokoll ([Dokument mit den DFRN Spezifikationen](https://github.com/friendica/friendica/blob/master/spec/dfrn2.pdf)) und den Elementen zur Nachrichtenverarbeitung des OStatus Stack informieren (salmon und Pubsubhubbub).
Der Großteil der Nachrichtenverarbeitung nutzt die Datei include/items.php, welche Funktionen für verschiedene Feed-bezogene Import-/Exportaktivitäten liefert.
Diejenigen, die den Nachrichtenfluss genauer verstehen wollen, sollten sich mindestens mit dem DFRN-Protokoll ([Dokument mit den DFRN Spezifikationen](https://github.com/friendica/friendica/blob/stable/spec/dfrn2.pdf)) und den Elementen zur Nachrichtenverarbeitung des OStatus Stack informieren (salmon und Pubsubhubbub).
Wenn eine Nachricht veröffentlicht wird, werden alle Übermittlungen an alle Netzwerke mit include/notifier.php durchgeführt, welche entscheidet, wie und an wen die Nachricht geliefert wird.
Diese Datei bindet dabei die lokale Bearbeitung aller Übertragungen ein inkl. dfrn-notify.

View file

@ -1,79 +0,0 @@
Profile
========
* [Zur Startseite der Hilfe](help)
Mit Friendica kann eine unbegrenzte Anzahl an Profilen angelegt werden.
Du kannst verschiedene Profile nutzen, um verschiedenen Gruppen verschiedene Seiten von dir zu zeigen.
Du hast immer ein Profil, das als dein "Standard"- (default) oder "öffentliches" (public) Profil angelegt ist.
Dieses Profil ist immer für die Öffentlichkeit zugänglich und kann nicht versteckt werden (hier mag es einige wenige Ausnahmen auf privaten oder getrennten Seiten geben).
Du kannst und solltest die Informationen, die du in deinem öffentlichen Profil veröffentlichst, begrenzen.
Das bedeutet, dass du folgende Informationen in dein öffentlichen Profil eintragen solltest, wenn du willst, dass Freunde dich finden können ...
* Dein richtiger Name
* Ein Foto von **dir**
* Dein geographischer Standort; zumindest das Land, in dem du lebst.
Ohne diese Basisinformationen kannst du hier sehr einsam sein.
Die meisten Leute, auch deine besten Freunde, werden nicht versuchen, einen Account mit Spitznamen und ohne Foto zu verbinden.
Wenn du außerdem Leute mit gleichen Interessen treffen willst, dann nimm dir etwas Zeit und trage einige Stichworte ein.
Zum Beispiel etwas wie "Musik, Linux, Photographie" oder andere Dinge.
Du kannst so viele Stichworte eintragen, wie du willst.
Dein "Standard-" oder "öffentliches" Profil wird außerdem Kontakten in anderen Netzwerken gezeigt, auch wenn sie nicht die Möglichkeit haben, die privaten Profile einzusehen.
Nur Mitglieder des Friendica-Netzwerks können alternative oder private Profile sehen.
Um ein alternatives Profil zu erstellen, gehe auf "Profil verwalten/editieren".
Du kannst entweder ein bestehendes Profil bearbeiten, das Foto ändern, oder ein neues Profil erstellen.
Du kannst ebenfalls einen Klon eines bestehenden Profils erstellen, falls du nur einige wenige Einstellungen ändern, aber nicht alle Daten noch mal eingeben willst.
Um bestimmten Personen ein Profil zuzuweisen, wähle die Person über "Kontakte" und klicke auf das Bearbeiten-Symbol (Stift).
Du wirst ein Auswahlmenü mit verschiedenen vorhandenen Profilen angezeigt bekommen.
Wenn diese Auswahl nicht angezeigt wird, dann ist die Person in einem nicht unterstützten Netzwerk und kann dadurch auch kein Profil zugewiesen bekommen.
Wenn eine befreundete Person auf den "magischen Profillink" klickt, sieht sie das private Profil, das du dieser Person zugewiesen hast.
Wenn sie nicht eingeloggt ist oder das Profil von woanders angeschaut wird, wird nur das öffentliche Profil angezeigt.
Ein "magischer Profillink" erscheint, wenn man mit der Maus über den Kontaktnamen oder das Foto geht.
Der Cursor wird zur Hand und auf dem Bild erscheint ein Pfeil, der nach unten zeigt.
Dieser "magische Cursor" zeigt an, dass du ein spezielles Profil angezeigt bekommst, das nur für Freunde, aber nicht für die Öffentlichkeit sichtbar ist.
Du wirst außerdem möglicherweise entdecken (vorausgesetzt, du hast die nötigen Zugriffsrechte), dass du direkt auf die Seite einer anderen Person schreiben kannst (oft wird diese Beitragsart "wall-to-wall" genannt).
Ebenso kannst du die Möglichkeit haben, direkt Beiträge zu kommentieren, während du die Seite der anderen Person besuchst.
Es gibt zwei Einstellungen, welche erlauben, dein Profil ins Verzeichnis einzutragen, so dass du von anderen Personen gefunden werden kannst.
Du kannst diese Einstellungen auf deiner "Einstellungen"-Seite ändern.
Die eine Einstellung erlaubt dir, dein Profil im Verzeichnis dieses Servers zu veröffentlichen.
Die zweite Option erlaubt es dir, dich in das globale Friendica-Verzeichnis einzutragen.
Dies ist ein riesiges Verzeichnis, dass alle Personen von vielen Friendica-Installationen weltweit umfasst.
Wenn du für andere nicht sichtbar sein willst, dann kannst du dein Profil einfach unveröffentlicht lassen.
Außerdem hast du möglicherweise mehrere Profile, aber nur ein Profilfoto. Dies ist beabsichtigt.
In frühen Tests haben wir mit verschiedenen Fotos für jedes Profil experimentiert und herausgefunden, dass es sehr verwirrend für die Nutzer ist.
Sie sehen möglicherweise je nach Profil, Seite oder Unterhaltung verschiedene Fotos und merken, dass es unterschiedliche Profile gibt, die sie nicht einsehen können.
(Du kannst aber die Rich-Text-Infoboxen in deinem Profil nutzen und dort weitere Bilder in das Feld "Erzähle uns ein bisschen von dir …" einfügen.)
**Schlüsselwörter und Verzeichnissuche**
Auf der Verzeichnisseite willst du vielleicht nach Personen deines Servers suchen, die ihre Profile veröffentlicht haben.
Die Suche richtet sich normalerweise nach deinem Spitznamen oder Teilen deines richtigen Namens.
Darüber hinaus wird dieses Feld auch andere Felder deines Profils wie Geschlecht, Ort, "über mich", Arbeit und Bildung finden.
Du kannst zudem auch "Schlüsselwörter" in dein Standardprofil eintragen, so dass dich andere Personen über deine Interessen finden können.
Du hast zwei Schlüsselwortarten zur Auswahl - öffentlich und privat. Private Schlüsselwörter werden *nicht* jedem angezeigt.
Du kannst diese Schlüsselwörter nutzen, um andere Personen zu finden, die ebenfalls in einer bestimmten Gruppe sind oder z.B. das Fischen mögen, ohne dass es jeder in einem öffentlichen Profil sieht.
Öffentliche Schlüsselwörter werden auf der "Kontaktvorschläge"-Seite genutzt.
Auch wenn die Schlüsselwörter hier nicht direkt angezeigt werden, kann es trotzdem sein, dass diese im HTML-Code der Seite gesehen werden könnten.
In der Verzeichnis-Suche kannst du ebenfalls die "booleasche"-Logik zu nutzen. Mit "+lesbisch +Florida" kannst du Leute finden, deren sexuelle Einstellung (oder andere Schlüsselwörter) das Wort "lesbisch" enthält und die in Florida leben.
Schau dir den Bereich über "Thematische Tags" auf der "[Tags und Erwähnungen-Seite](help/Tags-and-Mentions) für weitere Informationen, um booleansche Suchen durchzuführen.
Auf deiner Kontaktseite ist der Link "Ähnliche Interessen", um damit andere Leute zu finden (falls dein Seitenadministrator das globale Verzeichnis nicht ausgeschaltet hat).
Hierfür werden die Schlüsselwörter aus deinen öffentlichen und privaten Profilen genutzt, um Personen im globalen Verzeichnis zu finden, die gleiche oder ähnliche Schlüsselwörter haben (deine privaten Schlüsselwörter werden nicht in das globale Verzeichnis übertragen oder gespeichert).
Je mehr Schlüsselwörter du einträgst, umso genauer ist die Suche. Das Suchergebnis ist nach Relevanz sortiert.
Gegebenenfalls stehst du ganz oben auf der Liste - schließlich bist du die Person, die am besten zu deinen Schlüsselwörtern passt.

View file

@ -21,6 +21,6 @@ Solltest Du beim Stöbern durch die vielen Gruppen nicht wieder hierher zurück
Wenn Du einige Gruppen hinzugefügt hast, gehe <a href="help/Quick-Start-andfinally">weiter zum nächsten Schritt</a>.
<iframe src="https://dir.friendica.social/home" width="950" height="600"></iframe>
<iframe src="https://dir.friendica.social/forum" width="950" height="600"></iframe>

View file

@ -10,24 +10,14 @@ Wir freuen uns nicht, wenn Leute Friendica verlassen, aber wenn du deinen Accoun
in deinem Webbrowser. Du musst dabei eingeloggt sein.
Du wirst nach deinem Passwort gefragt, um die Anfrage zu bestätigen.
Wenn dieses mit deinem gespeichertem Passwort übereinstimmt, dann wird dein Account sofort gelöscht.
Anders als andere Netzwerke, behalten wir die Daten **nicht** für eine gewisse Zeit, falls du deine Meinung noch änderst.
Deine Nutzerdetails, deine Unterhaltungen, deine Photos, deine Freunde - alles; wird sofort gelöscht und du wirst ausgeloggt.
Wenn dieses mit deinem gespeichertem Passwort übereinstimmt, dann wird dein Account als "gelöscht" markiert.
Dies passiert sofort und kann nicht rückgängig gemacht werden.
Die meisten Deiner Inhalte und Benutzerdaten werden kurzfristig danach durch Hintergrundprozesse gelöscht.
Wenn Beiträge ablaufen, schicken wir Mitteilungen an Friendica, um diese zu löschen.
Diaspora hat keine automatische Löschfunktion, so dass diese Funktion in dem Netzwerk deaktiviert ist.
Und hoffentlich ist klar, dass das Löschen auch in anderen Netzwerken nicht funktioniert.
Wenn du manuell einen Beitrag bzw. eine Reihe von Beiträgen löschst, dann senden wir individuelle Mitteilungen zu Friendica und Diaspora für jeden gelöschten Post.
Parallel dazu senden wir eine Mitteilung an die Server deiner Kontakte, damit sie deine dort vorliegenden Daten ebenfalls löschen.
Wir haben keinen Einfluss darauf, wie sorgfältig und ob überhaupt diese Systeme der Löschaufforderung nachgehen.
Diaspora versäumt dieses oft.
Aus technischen Gründen benötigen wir für die Übetragung dieser Mitteilung ein paar Benutzerdaten.
Diese Daten werden dann nach einer Frist von etwa sieben Tagen ebenfalls gelöscht.
Wenn du einen Beitrag löscht, aber jemand diesem Beitrag folgt, wird es trotzdem gelöscht.
Dein Wunsch hat Priorität.
Wenn du deinen Account löscht, dann löschen wir alle Beiträge, dein Profil, die Nutzerdaten etc. sofort.
Um einen Gesamtlöschauftrag zu versenden, bräuchten wir zunächst noch deinen Account; auch, um deinen Freunden zu zeigen, wer diese Anfrage stellt.
Das können wir nicht tun, wenn du keinen Account mehr hast.
Deine Freunde können möglicherweise noch deine Beiträge sehen, wenn dein Account gelöscht wurde, aber es gibt keinen öffentlichen Ort in Friendica mehr, wo diese angeschaut werden können.
Wenn du Freunde bei Diaspora hast, kann es sein, dass deine Beiträge weiterhin vorhanden und für andere aus diesem Netzwerk sichtbar sind.
Wir speichern deinen Benutzernamen dauerhaft, damit sich niemand einen Account unter deinem Spitznamen anlegen kann.

View file

@ -160,7 +160,7 @@ Angemeldete Nutzer des Knotens können grundsätzlich beide Seiten verwenden.
#### Erlaubte Domains für Kontakte
Kommagetrennte Liste von Domains, welche eine Freundschaft mit dieser Seite eingehen dürfen.
Wildcards werden akzeptiert (Wildcard-Unterstützung unter Windows benötigt PHP5.3) Standardmäßig sind alle gültigen Domains erlaubt.
Wildcards werden akzeptiert Standardmäßig sind alle gültigen Domains erlaubt.
Mit dieser Option kann man einfach geschlossene Netzwerke, z.B. im schulischen Bereich aufbauen, aus denen nicht mit dem Rest des Netzwerks kommuniziert werden soll.
@ -168,7 +168,7 @@ Mit dieser Option kann man einfach geschlossene Netzwerke, z.B. im schulischen B
Kommagetrennte Liste von Domains, welche bei der Registrierung als Part der Email-Adresse erlaubt sind.
Das grenzt Leute aus, die nicht Teil der Gruppe oder Organisation sind.
Wildcards werden akzeptiert (Wildcard-Unterstützung unter Windows benötigt PHP5.3) Standardmäßig sind alle gültigen Email-Adressen erlaubt.
Wildcards werden akzeptiert Standardmäßig sind alle gültigen Email-Adressen erlaubt.
#### Nutzern erlauben das remote_self Flag zu setzen

View file

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
doc/img/frio_location.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

BIN
doc/img/vier_icons.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -39,7 +39,7 @@ They are initialized with an array of data, depending on the tyle of the field.
All of these take an array holding the values, e.g. for a one line text input field, which is required and should be used to type email addesses use something along the lines of:
'$adminmail' => array('adminmail', L10n::t('Site administrator email address'), $adminmail, L10n::t('Your account email address must match this in order to use the web admin panel.'), 'required', '', 'email'),
'$adminmail' => array('adminmail', DI::l10n()->t('Site administrator email address'), $adminmail, DI::l10n()->t('Your account email address must match this in order to use the web admin panel.'), 'required', '', 'email'),
To evaluate the input value, you can then use the $_POST array, more precisely the $_POST['adminemail'] variable.
@ -80,7 +80,7 @@ Field parameter:
### field_input.tpl
A single line input field for textual input.
A single line input field for any type of input.
Field parameter:
0. Name of the field,
@ -89,7 +89,7 @@ Field parameter:
3. Help text for the input box,
4. if set to "required" modern browser will check that this input box is filled when submitting the form,
5. if set to "autofocus" modern browser will put the cursur into this box once the page is loaded,
6. if set to "email" or "url" modern browser will check that the filled in value corresponds to an email address or URL.
6. if set, it will be used for the input type, default is `text` (possible types: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#%3Cinput%3E_types).
### field_intcheckbox.tpl
@ -177,14 +177,4 @@ Field parameter:
1. Label for the input box,
2. Current text for the box,
3. Help text for the input box.
### field_yesno.tpl
A button that has two states *yes* or *no*.
Field parameter:
0. Name of the input field,
1. Label for the button,
2. Current value,
3. Help text for the button
4. if set to an array of two values, these two will be used, otherwise "off" and "on".
4. if set to "required" modern browser will check that this input box is filled when submitting the form,

View file

@ -3,7 +3,7 @@
* [Home](help)
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.
The current default theme is [Vier](https://github.com/friendica/friendica/tree/stable/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.
@ -108,17 +108,17 @@ The _post functions handle the processing of the send form, in this case they sa
To make your own variation appear in the menu, all you need to do is to create a new CSS file in the deriv directoy and include it in the array in the config.php:
$colorset = array(
'default'=>L10n::t('default'),
'greenzero'=>L10n::t('greenzero'),
'purplezero'=>L10n::t('purplezero'),
'easterbunny'=>L10n::t('easterbunny'),
'darkzero'=>L10n::t('darkzero'),
'comix'=>L10n::t('comix'),
'slackr'=>L10n::t('slackr'),
'default'=>DI::l10n()->t('default'),
'greenzero'=>DI::l10n()->t('greenzero'),
'purplezero'=>DI::l10n()->t('purplezero'),
'easterbunny'=>DI::l10n()->t('easterbunny'),
'darkzero'=>DI::l10n()->t('darkzero'),
'comix'=>DI::l10n()->t('comix'),
'slackr'=>DI::l10n()->t('slackr'),
);
the 1st part of the line is the name of the CSS file (without the .css) the 2nd part is the common name of the variant.
Calling the L10n::t() function with the common name makes the string translateable.
Calling the DI::l10n()->t() function with the common name makes the string translateable.
The selected 1st part will be saved in the database by the theme_post function.
function theme_post(App $a){
@ -129,7 +129,7 @@ The selected 1st part will be saved in the database by the theme_post function.
// if the one specific submit button was pressed then proceed
if (isset($_POST['duepuntozero-settings-submit'])){
// and save the selection key into the personal config of the user
PConfig::set(local_user(), 'duepuntozero', 'colorset', $_POST['duepuntozero_colorset']);
DI::pConfig()->set(local_user(), 'duepuntozero', 'colorset', $_POST['duepuntozero_colorset']);
}
}
@ -137,12 +137,12 @@ Now that this information is set in the database, what should friendica do with
For this, have a look at the theme.php file of the *duepunto zero*.
There you'll find somethink alike
$colorset = PConfig::get( local_user(), 'duepuntozero','colorset');
$colorset = DI::pConfig()->get( local_user(), 'duepuntozero','colorset');
if (!$colorset)
$colorset = Config::get('duepuntozero', 'colorset');
$colorset = DI::config()->get('duepuntozero', 'colorset');
if ($colorset) {
if ($colorset == 'greenzero')
$a->page['htmlhead'] .= '<link rel="stylesheet" href="view/theme/duepuntozero/deriv/greenzero.css" type="text/css" media="screen" />'."\n";
DI::page()['htmlhead'] .= '<link rel="stylesheet" href="view/theme/duepuntozero/deriv/greenzero.css" type="text/css" media="screen" />'."\n";
/* some more variants */
}
@ -281,7 +281,7 @@ which declares *duepuntozero* as parent of the theme.
If you want to add something to the HTML header of the theme, one way to do so is by adding it to the theme.php file.
To do so, add something alike
$a->page['htmlhead'] .= <<< EOT
DI::page()['htmlhead'] .= <<< EOT
/* stuff you want to add to the header */
EOT;

View file

@ -8,7 +8,7 @@ Friendica translations
The Friendica translation process is based on `gettext` PO files.
Basic worflow:
1. `xgettext` is used to collect translation strings across the project in the master PO file located in `view/lang/C/messages.po`.
1. `xgettext` is used to collect translation strings across the project in the authoritative PO file located in `view/lang/C/messages.po`.
2. This file makes translations strings available at [the Transifex Friendica page](https://www.transifex.com/Friendica/friendica/dashboard/).
3. The translation itself is done at Transifex by volunteers.
4. The resulting PO files by languages are manually updated in `view/lang/<language>/messages.po`.
@ -73,14 +73,14 @@ Then run `bin/console po2php view/lang/<language>/messages.po` to update the rel
### Basic usage
- `Friendica\Core\L10n::t('Label')` => `Label`
- `Friendica\Core\L10n::t('Label %s', 'test')` => `Label test`
- `Friendica\DI::l10n()->t('Label')` => `Label`
- `Friendica\DI::l10n()->t('Label %s', 'test')` => `Label test`
### Plural
- `Friendica\Core\L10n::tt('Label', 'Labels', 1)` => `Label`
- `Friendica\Core\L10n::tt('Label', 'Labels', 3)` => `Labels`
- `Friendica\Core\L10n::tt('%d Label', '%d Labels', 1)` => `1 Label`
- `Friendica\Core\L10n::tt('%d Label', '%d Labels', 3)` => `3 Labels`
- `Friendica\Core\L10n::tt('%d Label', 'Labels %2%s %3%s', 1, 'test', 'test2')` => `Label test test2`
- `Friendica\Core\L10n::tt('%d Label', 'Labels %2%s %3%s', 3, 'test', 'test2')` => `Labels test test2`
- `Friendica\DI::l10n()->tt('Label', 'Labels', 1)` => `Label`
- `Friendica\DI::l10n()->tt('Label', 'Labels', 3)` => `Labels`
- `Friendica\DI::l10n()->tt('%d Label', '%d Labels', 1)` => `1 Label`
- `Friendica\DI::l10n()->tt('%d Label', '%d Labels', 3)` => `3 Labels`
- `Friendica\DI::l10n()->tt('%d Label', 'Labels %2%s %3%s', 1, 'test', 'test2')` => `Label test test2`
- `Friendica\DI::l10n()->tt('%d Label', 'Labels %2%s %3%s', 3, 'test', 'test2')` => `Labels test test2`

File diff suppressed because one or more lines are too long

BIN
images/discourse.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="110" height="20" viewBox="0 0 110 20" id="humane-tech-badge" version="1.1" inkscape:version="0.91 r13725" sodipodi:docname="humane-tech-badge.svg">
<defs id="defs4" />
<sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="4" inkscape:cx="133.140625" inkscape:cy="8.8445333895091" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="false" inkscape:window-width="1983" inkscape:window-height="1128" inkscape:window-x="65" inkscape:window-y="24" inkscape:window-maximized="1" />
<metadata id="metadata7">
<rdf:RDF>
<cc:Work rdf:about="https://humanetech.com">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<cc:license rdf:resource="http://creativecommons.org/licenses/by-nc-nd/4.0/" />
<dc:subject>Humane Technology Badge</dc:subject>
<dc:description>This badge when displayed on a code repository indicates the software is considered to be 'humane', as defined by The Center for Humane Technology (https://humanetech.com).</dc:description>
<dc:creator rdf:href="https://github.com/aschrijver">Arnold Schrijver</dc:creator>
</cc:Work>
<cc:License rdf:about="http://creativecommons.org/licenses/by-nc-nd/4.0/">
<cc:permits rdf:resource="http://creativecommons.org/ns#Reproduction" />
<cc:permits rdf:resource="http://creativecommons.org/ns#Distribution" />
<cc:requires rdf:resource="http://creativecommons.org/ns#Notice" />
<cc:requires rdf:resource="http://creativecommons.org/ns#Attribution" />
<cc:prohibits rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
</cc:License>
</rdf:RDF>
</metadata>
<g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1">
<rect style="fill:none;fill-opacity:1;stroke:#f33;stroke-width:10.3667802811;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" id="rect4139" width="98.63321685791" height="10.133219718933" x="6.1833915710449" y="5.1833901405334" />
<rect style="fill:#fcc;fill-opacity:1;stroke:#fcc;stroke-width:8.7014474869;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" id="rect4139-1" width="20.125642776489" height="11.875650405884" x="4.4371752738953" y="4.3476815223694" />
<g style="font-style:normal;font-weight:normal;font-size:26px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#f33;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="text4171" transform="matrix(0.81571369806664,0,0,0.84575215906809,2.5866412998766,2.2115384615385)">
<path d="M 15.392578125,17.5791015625 Q 13.6533203125,14.544921875 8.359375,11.47265625 5.896484375,10.0380859375 5.896484375,7.7783203125 5.896484375,6.826171875 6.2392578125,5.9501953125 6.5947265625,5.07421875 7.29296875,4.388671875 7.9658203125,3.728515625 8.841796875,3.34765625 9.6669921875,2.9921875 10.64453125,2.9921875 11.6220703125,2.9921875 12.447265625,3.34765625 13.310546875,3.7158203125 13.99609375,4.388671875 14.6689453125,5.048828125 15.0244140625,5.9248046875 15.392578125,6.7880859375 15.392578125,7.7783203125 15.392578125,6.7880859375 15.748046875,5.9248046875 16.1162109375,5.048828125 16.7890625,4.388671875 17.474609375,3.7158203125 18.337890625,3.34765625 19.1630859375,2.9921875 20.140625,2.9921875 21.1181640625,2.9921875 21.943359375,3.34765625 22.8193359375,3.728515625 23.4921875,4.388671875 24.1904296875,5.07421875 24.533203125,5.9501953125 24.888671875,6.826171875 24.888671875,7.7783203125 24.888671875,10.0634765625 22.42578125,11.47265625 17.1318359375,14.544921875 15.392578125,17.5791015625 Z" id="path4266" inkscape:connector-curvature="0" />
</g>
<rect style="fill:#fcc;fill-opacity:1;stroke:none;stroke-width:6.0879998207;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" id="rect4145" width="6.25" height="20.5" x="23.75" y="0" />
<g transform="scale(0.98208273317227,1.0182441521702)" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:black;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="text4147">
<path d="M 35.842449240386,9.4841952230781 Q 36.180519717745,8.5922646019608 36.684028939344,8.189457224682 37.194731149822,7.7866498474032 37.89964406006,7.7866498474032 38.475083170459,7.7866498474032 38.870697558857,8.0168254915625 39.273504936136,8.2470011357218 39.525259546936,8.6498085130006 39.777014157735,9.0526158902794 39.884908990934,9.5992830451578 39.999996813014,10.145950200036 39.999996813014,10.778933221474 L 39.999996813014,15.71332359314 38.345609370619,15.71332359314 38.345609370619,11.354372331873 Q 38.345609370619,10.901214032434 38.288065459579,10.527178610675 38.230521548539,10.145950200036 38.09385475982,9.879809611477 37.9571879711,9.6064760340378 37.734205315821,9.4554232675582 37.518415649422,9.3043705010787 37.209117127582,9.3043705010787 36.907011594623,9.3043705010787 36.662449972704,9.4698092453182 36.417888350785,9.6280550006777 36.238063628785,9.9301605336368 36.065431895666,10.225073077716 35.964730051346,10.642266432755 35.871221195906,11.052266798913 35.871221195906,11.548583031632 L 35.871221195906,15.71332359314 34.209640764631,15.71332359314 34.209640764631,5.0389280952513 35.871221195906,5.0389280952513 35.871221195906,7.9520885916427 Q 35.871221195906,8.182264235802 35.864028207026,8.4196328688413 35.856835218146,8.6498085130006 35.849642229266,8.85840519052 35.842449240386,9.0598088791594 35.835256251507,9.2252476233989 35.828063262627,9.3906863676384 35.820870273747,9.4841952230781 L 35.842449240386,9.4841952230781 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start" id="path4224" />
<path d="M 43.172104830854,7.9305096250027 43.172104830854,12.29665387515 Q 43.172104830854,12.749812174588 43.229648741893,13.131040585227 43.287192652933,13.505076006986 43.423859441653,13.778409584425 43.560526230372,14.044550172985 43.776315896772,14.195602939464 43.992105563171,14.346655705944 44.30140408501,14.346655705944 44.603509617969,14.346655705944 44.848071239889,14.188409950584 45.092632861808,14.022971206345 45.265264594927,13.728058662266 45.445089316927,13.425953129306 45.538598172367,13.015952763148 45.639300016686,12.598759408109 45.639300016686,12.10244317539 L 45.639300016686,7.9305096250027 47.300880447961,7.9305096250027 47.300880447961,13.972620284185 Q 47.300880447961,14.217181906104 47.300880447961,14.490515483543 47.308073436841,14.756656072102 47.315266425721,15.001217694022 47.322459414601,15.238586327061 47.329652403481,15.43279702682 47.336845392361,15.6198147377 47.344038381241,15.71332359314 L 45.761580827646,15.71332359314 Q 45.754387838766,15.62700772658 45.740001861006,15.4399900157 45.732808872126,15.245779315941 45.718422894366,15.015603671782 45.711229905486,14.785428027622 45.704036916606,14.555252383463 45.696843927726,14.325076739304 45.696843927726,14.166830983944 L 45.668071972206,14.166830983944 Q 45.337194483727,15.051568616182 44.826492273249,15.45437599346 44.31579006277,15.857183370739 43.610877152532,15.857183370739 43.035438042134,15.857183370739 42.632630664855,15.62700772658 42.237016276456,15.396832082421 41.985261665657,15.001217694022 41.733507054858,14.598410316743 41.618419232778,14.051743161865 41.510524399579,13.505076006986 41.510524399579,12.872092985548 L 41.510524399579,7.9305096250027 43.172104830854,7.9305096250027 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start" id="path4226" />
<path d="M 52.760358929634,15.71332359314 52.760358929634,11.347179342993 Q 52.760358929634,10.894021043554 52.710008007474,10.519985621795 52.659657085314,10.138757211156 52.544569263235,9.872616622597 52.429481441155,9.5992830451578 52.242463730276,9.4482302786782 52.055446019396,9.2971775121987 51.789305430837,9.2971775121987 51.537550820038,9.2971775121987 51.328954142518,9.4626162564382 51.120357464999,9.6208620117977 50.969304698519,9.9229675447568 50.82544492092,10.217880088836 50.73912905436,10.635073443875 50.66000617668,11.045073810033 50.66000617668,11.541390042752 L 50.66000617668,15.71332359314 48.998425745405,15.71332359314 48.998425745405,9.6712129339576 Q 48.998425745405,9.4194583231583 48.991232756525,9.1533177345991 48.991232756525,8.8871771460399 48.984039767645,8.6498085130006 48.976846778765,8.4052468910813 48.969653789885,8.2182291802019 48.962460801005,8.0240184804425 48.955267812125,7.9305096250027 L 50.530532376841,7.9305096250027 Q 50.544918354601,8.0168254915625 50.552111343481,8.2110361913219 50.566497321241,8.3980539022014 50.580883299001,8.6282295463607 50.595269276761,8.85840519052 50.60246226564,9.0885808346793 50.60965525452,9.3187564788386 50.60965525452,9.4770022341982 L 50.63123422116,9.4770022341982 Q 50.940532742999,8.5850716130808 51.393691042438,8.182264235802 51.854042330757,7.7794568585232 52.494218341075,7.7794568585232 53.227903206833,7.7794568585232 53.666675528511,8.2182291802019 54.11264083907,8.6498085130006 54.26369360555,9.4770022341982 L 54.29965854995,9.4770022341982 Q 54.472290283069,8.9950719792396 54.666500982828,8.6713874796405 54.867904671468,8.3477029800415 55.105273304507,8.1534922802821 55.342641937546,7.9520885916427 55.623168503866,7.8657727250829 55.903695070185,7.7794568585232 56.234572558664,7.7794568585232 56.759660746902,7.7794568585232 57.119310190901,8.0096325026825 57.48615262378,8.2398081468418 57.709135279059,8.6426155241206 57.939310923219,9.0454229013994 58.040012767538,9.5920900562778 58.147907600738,10.138757211156 58.147907600738,10.771740232594 L 58.147907600738,15.71332359314 56.500713147223,15.71332359314 56.500713147223,11.347179342993 Q 56.500713147223,10.894021043554 56.450362225063,10.519985621795 56.400011302903,10.138757211156 56.284923480824,9.872616622597 56.169835658744,9.5992830451578 55.982817947865,9.4482302786782 55.802993225865,9.2971775121987 55.536852637306,9.2971775121987 55.292291015387,9.2971775121987 55.083694337867,9.4554232675582 54.882290649228,9.6064760340378 54.731237882748,9.8941955892369 54.580185116269,10.174722155556 54.493869249709,10.570336543955 54.414746372029,10.965950932354 54.400360394269,11.447881187312 L 54.400360394269,15.71332359314 52.760358929634,15.71332359314 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start" id="path4228" />
<path d="M 61.204928735271,15.857183370739 Q 60.744577446952,15.857183370739 60.377735014074,15.70613060426 60.018085570075,15.5478848489 59.766330959275,15.252972304821 59.514576348476,14.950866771862 59.377909559757,14.512094450183 59.241242771037,14.073322128505 59.241242771037,13.512268995866 59.241242771037,12.821742063388 59.435453470796,12.35419778619 59.636857159436,11.879460520111 59.974927636795,11.591740964912 60.320191103034,11.296828420833 60.780542391352,11.167354620993 61.240893679671,11.030687832274 61.758788879029,11.023494843394 L 63.132649755105,10.994722887874 63.132649755105,10.599108499475 Q 63.132649755105,10.174722155556 63.067912855186,9.8941955892369 63.010368944146,9.6064760340378 62.888088133186,9.4266513120383 62.773000311106,9.2468265900388 62.600368577987,9.174896701239 62.427736844867,9.0957738235593 62.204754189588,9.0957738235593 61.996157512069,9.0957738235593 61.830718767829,9.1461247457191 61.67247301247,9.196475667879 61.55019220151,9.3259494677186 61.43510437943,9.4482302786782 61.363174490631,9.6640199450776 61.291244601831,9.872616622597 61.262472646311,10.196301122196 L 59.528962326236,10.095599277876 Q 59.600892215036,9.5848970673978 59.787909925915,9.1677037123591 59.982120625675,8.7433173684403 60.312998114154,8.4340188466012 60.643875602633,8.1247203247622 61.132998846471,7.9592815805227 61.62212209031,7.7866498474032 62.276684078388,7.7866498474032 62.873702155426,7.7866498474032 63.334053443745,7.9664745694026 63.801597720943,8.1462992914021 64.125282220542,8.505948735401 64.448966720141,8.85840519052 64.621598453261,9.3763003898785 64.79423018638,9.8941955892369 64.79423018638,10.577529532835 L 64.79423018638,13.411567151546 Q 64.79423018638,13.684900728986 64.81580915302,13.900690395385 64.83738811966,14.116480061784 64.88773904182,14.267532828264 64.94528295286,14.411392605864 65.04598479718,14.490515483543 65.153879630379,14.562445372343 65.319318374619,14.562445372343 65.506336085498,14.562445372343 65.686160807498,14.519287439063 L 65.686160807498,15.61262174882 Q 65.686160807498,15.61262174882 65.420020218939,15.6917446265 65.297739407979,15.7277095709 65.182651585899,15.74928853754 65.06756376382,15.770867504179 64.9308969751,15.785253481939 64.80142317526,15.799639459699 64.621598453261,15.799639459699 63.995808420703,15.799639459699 63.693702887744,15.425604037941 63.398790343665,15.051568616182 63.341246432625,14.325076739304 L 63.305281488225,14.325076739304 Q 62.974403999746,15.051568616182 62.456508800387,15.45437599346 61.938613601029,15.857183370739 61.204928735271,15.857183370739 Z M 63.132649755105,12.10963616427 62.283877067268,12.12402214203 Q 62.017736478709,12.13840811979 61.780367845669,12.18156605307 61.54299921263,12.21753099747 61.363174490631,12.34700479731 61.183349768631,12.469285608269 61.075454935431,12.706654241309 60.967560102232,12.944022874348 60.967560102232,13.354023240507 60.967560102232,13.907883384265 61.176156779751,14.181216961704 61.391946446151,14.447357550263 61.73720991239,14.447357550263 62.053701423109,14.447357550263 62.312649022788,14.281918806024 62.578789611347,14.116480061784 62.758614333346,13.850339473225 62.938439055346,13.577005895786 63.031947910786,13.224549440667 63.132649755105,12.872092985548 63.132649755105,12.505250552669 L 63.132649755105,12.10963616427 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start" id="path4230" />
<path d="M 70.59897011891,15.71332359314 70.59897011891,11.347179342993 Q 70.59897011891,10.894021043554 70.54142620787,10.519985621795 70.48388229683,10.138757211156 70.347215508111,9.872616622597 70.210548719391,9.5992830451578 69.987566064112,9.4482302786782 69.771776397713,9.2971775121987 69.462477875873,9.2971775121987 69.160372342914,9.2971775121987 68.915810720995,9.4626162564382 68.671249099076,9.6208620117977 68.491424377076,9.9229675447568 68.318792643957,10.217880088836 68.218090799637,10.635073443875 68.124581944197,11.045073810033 68.124581944197,11.541390042752 L 68.124581944197,15.71332359314 66.463001512922,15.71332359314 66.463001512922,9.6712129339576 Q 66.463001512922,9.4194583231583 66.455808524042,9.1533177345991 66.455808524042,8.8871771460399 66.448615535162,8.6498085130006 66.441422546282,8.4052468910813 66.434229557402,8.2182291802019 66.427036568522,8.0240184804425 66.419843579642,7.9305096250027 L 68.002301133238,7.9305096250027 Q 68.016687110998,8.0168254915625 68.023880099878,8.2110361913219 68.031073088758,8.3980539022014 68.045459066518,8.6282295463607 68.059845044278,8.85840519052 68.067038033158,9.0885808346793 68.074231022038,9.3187564788386 68.074231022038,9.4770022341982 L 68.095809988677,9.4770022341982 Q 68.433880466036,8.5850716130808 68.937389687635,8.182264235802 69.448091898113,7.7794568585232 70.153004808351,7.7794568585232 70.72844391875,7.7794568585232 71.124058307149,8.0096325026825 71.526865684427,8.2398081468418 71.778620295227,8.6426155241206 72.030374906026,9.0454229013994 72.138269739226,9.5920900562778 72.253357561305,10.138757211156 72.253357561305,10.771740232594 L 72.253357561305,15.71332359314 70.59897011891,15.71332359314 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start" id="path4232" />
<path d="M 76.475643386133,15.857183370739 Q 75.785116453655,15.857183370739 75.231256309897,15.61262174882 74.677396166138,15.360867138021 74.28897476662,14.857357916422 73.900553367101,14.346655705944 73.691956689581,13.584198884666 73.490553000942,12.814549074508 73.490553000942,11.785951664671 73.490553000942,10.671038388275 73.735114622861,9.9085815669969 73.97967624478,9.1461247457191 74.389676610939,8.6785804685205 74.806869965978,8.2038432024419 75.346344131976,7.9952465249225 75.893011286855,7.7866498474032 76.497222352773,7.7866498474032 77.252486185171,7.7866498474032 77.784767362289,8.1103343470022 78.317048539408,8.4268258577213 78.655119016767,9.0022649681196 79.000382483006,9.5777040785179 79.158628238365,10.383318833075 79.324066982605,11.181740598753 79.324066982605,12.15279409755 L 79.324066982605,12.21033800859 75.231256309897,12.21033800859 Q 75.231256309897,12.699461252429 75.295993209817,13.123847596347 75.367923098616,13.541040951386 75.526168853976,13.850339473225 75.684414609335,14.152445006184 75.936169220135,14.332269728184 76.195116819814,14.504901461303 76.554766263813,14.504901461303 76.993538585491,14.504901461303 77.266872162931,14.281918806024 77.54739872925,14.051743161865 77.662486551329,13.577005895786 L 79.223365138285,13.742444640025 Q 79.115470305085,14.073322128505 78.921259605326,14.447357550263 78.734241894446,14.821392972022 78.417750383727,15.137884482741 78.101258873008,15.44718300458 77.62652160693,15.6557796821 77.151784340851,15.857183370739 76.475643386133,15.857183370739 Z M 76.475643386133,9.0598088791594 Q 76.223888775334,9.0598088791594 76.000906120054,9.1677037123591 75.777923464775,9.2684055566788 75.612484720536,9.4985812008381 75.454238965176,9.7215638561174 75.353537120856,10.081213300116 75.252835276537,10.440862744115 75.238449298777,10.944371965714 L 77.720030462369,10.944371965714 Q 77.669679540209,10.002090422437 77.34599504061,9.534546145238 77.022310541011,9.0598088791594 76.475643386133,9.0598088791594 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start" id="path4234" />
<path d="M 85.589160971344,15.842797392979 Q 84.855476105586,15.842797392979 84.459861717187,15.360867138021 84.071440317668,14.871743894182 84.071440317668,13.886304417625 L 84.071440317668,9.2971775121987 83.25863257423,9.2971775121987 83.25863257423,7.9305096250027 84.150563195348,7.9305096250027 84.668458394706,6.1034904494882 85.711441782303,6.1034904494882 85.711441782303,7.9305096250027 86.91986391414,7.9305096250027 86.91986391414,9.2971775121987 85.711441782303,9.2971775121987 85.711441782303,13.339637262747 Q 85.711441782303,13.907883384265 85.884073515423,14.181216961704 86.063898237422,14.447357550263 86.430740670301,14.447357550263 86.581793436781,14.447357550263 86.70407424774,14.418585594743 86.83354804758,14.389813639224 86.991793802939,14.346655705944 L 86.991793802939,15.59823577106 Q 86.6824952811,15.72051658202 86.337231814861,15.778060493059 85.999161337502,15.842797392979 85.589160971344,15.842797392979 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start" id="path4236" />
<path d="M 90.602672805078,15.857183370739 Q 89.9121458726,15.857183370739 89.358285728842,15.61262174882 88.804425585084,15.360867138021 88.416004185565,14.857357916422 88.027582786046,14.346655705944 87.818986108527,13.584198884666 87.617582419887,12.814549074508 87.617582419887,11.785951664671 87.617582419887,10.671038388275 87.862144041806,9.9085815669969 88.106705663726,9.1461247457191 88.516706029885,8.6785804685205 88.933899384923,8.2038432024419 89.473373550922,7.9952465249225 90.0200407058,7.7866498474032 90.624251771718,7.7866498474032 91.379515604116,7.7866498474032 91.911796781234,8.1103343470022 92.444077958353,8.4268258577213 92.782148435712,9.0022649681196 93.127411901951,9.5777040785179 93.28565765731,10.383318833075 93.45109640155,11.181740598753 93.45109640155,12.15279409755 L 93.45109640155,12.21033800859 89.358285728842,12.21033800859 Q 89.358285728842,12.699461252429 89.423022628762,13.123847596347 89.494952517562,13.541040951386 89.653198272921,13.850339473225 89.811444028281,14.152445006184 90.06319863908,14.332269728184 90.322146238759,14.504901461303 90.681795682758,14.504901461303 91.120568004437,14.504901461303 91.393901581876,14.281918806024 91.674428148195,14.051743161865 91.789515970275,13.577005895786 L 93.35039455723,13.742444640025 Q 93.24249972403,14.073322128505 93.048289024271,14.447357550263 92.861271313392,14.821392972022 92.544779802673,15.137884482741 92.228288291954,15.44718300458 91.753551025875,15.6557796821 91.278813759796,15.857183370739 90.602672805078,15.857183370739 Z M 90.602672805078,9.0598088791594 Q 90.350918194279,9.0598088791594 90.127935539,9.1677037123591 89.90495288372,9.2684055566788 89.739514139481,9.4985812008381 89.581268384121,9.7215638561174 89.480566539802,10.081213300116 89.379864695482,10.440862744115 89.365478717722,10.944371965714 L 91.847059881315,10.944371965714 Q 91.796708959155,10.002090422437 91.473024459556,9.534546145238 91.149339959957,9.0598088791594 90.602672805078,9.0598088791594 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start" id="path4238" />
<path d="M 97.378470051102,15.857183370739 Q 96.616013229825,15.857183370739 96.047767108306,15.56946381554 95.479520986788,15.281744260341 95.098292576149,14.756656072102 94.72425715439,14.231567883864 94.537239443511,13.497883018106 94.350221732631,12.757005163468 94.350221732631,11.865074542351 94.350221732631,10.894021043554 94.551625421271,10.138757211156 94.76022209879,9.3763003898785 95.148643498309,8.85840519052 95.537064897828,8.3333170022815 96.105311019346,8.0599834248424 96.680750129744,7.7866498474032 97.400049017742,7.7866498474032 98.01864606142,7.7866498474032 98.500576316379,7.9880535360426 98.982506571338,8.189457224682 99.327770037577,8.5419136798009 99.680226492696,8.8871771460399 99.896016159095,9.3619144121185 100.11180582549,9.8366516781971 100.19092870317,10.383318833075 L 98.522155283019,10.484020677395 Q 98.450225394219,9.8870026003569 98.1696988279,9.534546145238 97.889172261581,9.174896701239 97.364084073342,9.174896701239 96.695136107504,9.174896701239 96.393030574545,9.8438446670771 96.090925041586,10.512792632915 96.090925041586,11.785951664671 96.090925041586,14.476129505783 97.392856028862,14.476129505783 97.867593294941,14.476129505783 98.18408480566,14.116480061784 98.500576316379,13.749637628905 98.579699194059,13.030338740908 L 100.24127962533,13.123847596347 Q 100.18373571429,13.663321762346 99.967946047895,14.159637995064 99.759349370375,14.648761238903 99.399699926376,15.029989649542 99.047243471257,15.404025071301 98.536541260779,15.63420071546 98.03303203918,15.857183370739 97.378470051102,15.857183370739 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start" id="path4240" />
<path d="M 103.08250813931,9.4841952230781 Q 103.42057861667,8.5922646019608 103.92408783827,8.189457224682 104.43479004875,7.7866498474032 105.13970295899,7.7866498474032 105.71514206938,7.7866498474032 106.11075645778,8.0168254915625 106.51356383506,8.2470011357218 106.76531844586,8.6498085130006 107.01707305666,9.0526158902794 107.12496788986,9.5992830451578 107.24005571194,10.145950200036 107.24005571194,10.778933221474 L 107.24005571194,15.71332359314 105.58566826954,15.71332359314 105.58566826954,11.354372331873 Q 105.58566826954,10.901214032434 105.52812435851,10.527178610675 105.47058044747,10.145950200036 105.33391365875,9.879809611477 105.19724687003,9.6064760340378 104.97426421475,9.4554232675582 104.75847454835,9.3043705010787 104.44917602651,9.3043705010787 104.14707049355,9.3043705010787 103.90250887163,9.4698092453182 103.65794724971,9.6280550006777 103.47812252771,9.9301605336368 103.30549079459,10.225073077716 103.20478895027,10.642266432755 103.11128009483,11.052266798913 103.11128009483,11.548583031632 L 103.11128009483,15.71332359314 101.44969966356,15.71332359314 101.44969966356,5.0389280952513 103.11128009483,5.0389280952513 103.11128009483,7.9520885916427 Q 103.11128009483,8.182264235802 103.10408710595,8.4196328688413 103.09689411707,8.6498085130006 103.08970112819,8.85840519052 103.08250813931,9.0598088791594 103.07531515043,9.2252476233989 103.06812216155,9.3906863676384 103.06092917267,9.4841952230781 L 103.08250813931,9.4841952230781 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start" id="path4242" />
</g>
<g transform="scale(0.98208273317227,1.0182441521702)" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:0.9411764706;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" id="text4147-1">
<path d="M 35.559284262359,8.8569664862007 Q 35.897354739718,7.9650358650833 36.400863961317,7.5622284878045 36.911566171795,7.1594211105257 37.616479082033,7.1594211105257 38.191918192431,7.1594211105257 38.58753258083,7.389596754685 38.990339958109,7.6197723988444 39.242094568908,8.0225797761232 39.493849179707,8.425387153402 39.601744012907,8.9720543082803 39.716831834987,9.5187214631587 39.716831834987,10.151704484597 L 39.716831834987,15.086094856262 38.062444392592,15.086094856262 38.062444392592,10.727143594995 Q 38.062444392592,10.273985295556 38.004900481552,9.8999498737976 37.947356570512,9.5187214631587 37.810689781792,9.2525808745995 37.674022993073,8.9792472971603 37.451040337794,8.8281945306808 37.235250671394,8.6771417642012 36.925952149555,8.6771417642012 36.623846616596,8.6771417642012 36.379284994677,8.8425805084407 36.134723372757,9.0008262638003 35.954898650758,9.3029317967594 35.782266917638,9.5978443408385 35.681565073319,10.015037695877 35.588056217879,10.425038062036 35.588056217879,10.921354294755 L 35.588056217879,15.086094856262 33.926475786604,15.086094856262 33.926475786604,4.4116993583739 35.588056217879,4.4116993583739 35.588056217879,7.3248598547652 Q 35.588056217879,7.5550354989246 35.580863228999,7.7924041319638 35.573670240119,8.0225797761232 35.566477251239,8.2311764536425 35.559284262359,8.4325801422819 35.552091273479,8.5980188865215 35.544898284599,8.763457630761 35.537705295719,8.8569664862007 L 35.559284262359,8.8569664862007 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:0.9411764706" id="path4245" />
<path d="M 42.888939852826,7.3032808881253 42.888939852826,11.669425138272 Q 42.888939852826,12.122583437711 42.946483763866,12.50381184835 43.004027674906,12.877847270109 43.140694463626,13.151180847548 43.277361252345,13.417321436107 43.493150918745,13.568374202587 43.708940585144,13.719426969066 44.018239106983,13.719426969066 44.320344639942,13.719426969066 44.564906261861,13.561181213707 44.809467883781,13.395742469467 44.9820996169,13.100829925388 45.1619243389,12.798724392429 45.255433194339,12.38872402627 45.356135038659,11.971530671231 45.356135038659,11.475214438513 L 45.356135038659,7.3032808881253 47.017715469934,7.3032808881253 47.017715469934,13.345391547307 Q 47.017715469934,13.589953169227 47.017715469934,13.863286746666 47.024908458814,14.129427335225 47.032101447694,14.373988957144 47.039294436574,14.611357590184 47.046487425454,14.805568289943 47.053680414334,14.992586000822 47.060873403214,15.086094856262 L 45.478415849619,15.086094856262 Q 45.471222860739,14.999778989702 45.456836882979,14.812761278823 45.449643894099,14.618550579064 45.435257916339,14.388374934904 45.428064927459,14.158199290745 45.420871938579,13.928023646586 45.413678949699,13.697848002426 45.413678949699,13.539602247067 L 45.384906994179,13.539602247067 Q 45.0540295057,14.424339879304 44.543327295221,14.827147256583 44.032625084743,15.229954633862 43.327712174505,15.229954633862 42.752273064107,15.229954633862 42.349465686828,14.999778989702 41.953851298429,14.769603345543 41.70209668763,14.373988957144 41.450342076831,13.971181579866 41.335254254751,13.424514424987 41.227359421551,12.877847270109 41.227359421551,12.244864248671 L 41.227359421551,7.3032808881253 42.888939852826,7.3032808881253 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:0.9411764706" id="path4247" />
<path d="M 52.477193951607,15.086094856262 52.477193951607,10.719950606115 Q 52.477193951607,10.266792306677 52.426843029447,9.8927568849176 52.376492107287,9.5115284742787 52.261404285207,9.2453878857195 52.146316463128,8.9720543082803 51.959298752248,8.8210015418008 51.772281041369,8.6699487753212 51.50614045281,8.6699487753212 51.25438584201,8.6699487753212 51.045789164491,8.8353875195608 50.837192486972,8.9936332749203 50.686139720492,9.2957388078794 50.542279942892,9.5906513519585 50.455964076333,10.007844706997 50.376841198653,10.417845073156 50.376841198653,10.914161305875 L 50.376841198653,15.086094856262 48.715260767378,15.086094856262 48.715260767378,9.0439841970801 Q 48.715260767378,8.7922295862809 48.708067778498,8.5260889977217 48.708067778498,8.2599484091625 48.700874789618,8.0225797761232 48.693681800738,7.7780181542039 48.686488811858,7.5910004433244 48.679295822978,7.396789743565 48.672102834098,7.3032808881253 L 50.247367398813,7.3032808881253 Q 50.261753376573,7.389596754685 50.268946365453,7.5838074544445 50.283332343213,7.7708251653239 50.297718320973,8.0010008094832 50.312104298733,8.2311764536425 50.319297287613,8.4613520978019 50.326490276493,8.6915277419612 50.326490276493,8.8497734973207 L 50.348069243133,8.8497734973207 Q 50.657367764972,7.9578428762034 51.110526064411,7.5550354989246 51.570877352729,7.1522281216457 52.211053363048,7.1522281216457 52.944738228805,7.1522281216457 53.383510550484,7.5910004433244 53.829475861043,8.0225797761232 53.980528627522,8.8497734973207 L 54.016493571922,8.8497734973207 Q 54.189125305042,8.3678432423621 54.383336004801,8.0441587427631 54.58473969344,7.7204742431641 54.82210832648,7.5262635434046 55.059476959519,7.3248598547652 55.340003525838,7.2385439882055 55.620530092157,7.1522281216457 55.951407580636,7.1522281216457 56.476495768875,7.1522281216457 56.836145212874,7.3824037658051 57.202987645753,7.6125794099644 57.425970301032,8.0153867872432 57.656145945191,8.418194164522 57.756847789511,8.9648613194004 57.864742622711,9.5115284742787 57.864742622711,10.144511495717 L 57.864742622711,15.086094856262 56.217548169196,15.086094856262 56.217548169196,10.719950606115 Q 56.217548169196,10.266792306677 56.167197247036,9.8927568849176 56.116846324876,9.5115284742787 56.001758502796,9.2453878857195 55.886670680717,8.9720543082803 55.699652969837,8.8210015418008 55.519828247838,8.6699487753212 55.253687659279,8.6699487753212 55.009126037359,8.6699487753212 54.80052935984,8.8281945306808 54.5991256712,8.9792472971603 54.448072904721,9.2669668523595 54.297020138241,9.5474934186786 54.210704271682,9.9431078070775 54.131581394002,10.338722195476 54.117195416242,10.820652450435 L 54.117195416242,15.086094856262 52.477193951607,15.086094856262 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:0.9411764706" id="path4249" />
<path d="M 60.921763757244,15.229954633862 Q 60.461412468925,15.229954633862 60.094570036046,15.078901867382 59.734920592047,14.920656112023 59.483165981248,14.625743567944 59.231411370449,14.323638034984 59.094744581729,13.884865713306 58.95807779301,13.446093391627 58.95807779301,12.885040258989 58.95807779301,12.194513326511 59.152288492769,11.726969049312 59.353692181408,11.252231783234 59.691762658767,10.964512228034 60.037026125006,10.669599683955 60.497377413325,10.540125884116 60.957728701644,10.403459095396 61.475623901002,10.396266106516 L 62.849484777078,10.367494150996 62.849484777078,9.9718797625974 Q 62.849484777078,9.5474934186786 62.784747877158,9.2669668523595 62.727203966118,8.9792472971603 62.604923155159,8.7994225751609 62.489835333079,8.6195978531614 62.31720359996,8.5476679643616 62.14457186684,8.4685450866818 61.921589211561,8.4685450866818 61.712992534041,8.4685450866818 61.547553789802,8.5188960088417 61.389308034442,8.5692469310015 61.267027223483,8.6987207308412 61.151939401403,8.8210015418008 61.080009512603,9.0367912082002 61.008079623803,9.2453878857195 60.979307668284,9.5690723853186 L 59.245797348209,9.4683705409989 Q 59.317727237009,8.9576683305204 59.504744947888,8.5404749754816 59.698955647647,8.1160886315629 60.029833136126,7.8067901097238 60.360710624605,7.4974915878847 60.849833868444,7.3320528436452 61.338957112283,7.1594211105257 61.993519100361,7.1594211105257 62.590537177399,7.1594211105257 63.050888465717,7.3392458325252 63.518432742916,7.5190705545247 63.842117242515,7.8787199985236 64.165801742114,8.2311764536425 64.338433475234,8.749071653001 64.511065208353,9.2669668523595 64.511065208353,9.9503007959574 L 64.511065208353,12.784338414669 Q 64.511065208353,13.057671992108 64.532644174993,13.273461658508 64.554223141633,13.489251324907 64.604574063793,13.640304091386 64.662117974833,13.784163868986 64.762819819152,13.863286746666 64.870714652352,13.935216635466 65.036153396592,13.935216635466 65.223171107471,13.935216635466 65.40299582947,13.892058702186 L 65.40299582947,14.985393011943 Q 65.40299582947,14.985393011943 65.136855240911,15.064515889622 65.014574429952,15.100480834022 64.899486607872,15.122059800662 64.784398785792,15.143638767302 64.647731997073,15.158024745062 64.518258197233,15.172410722822 64.338433475234,15.172410722822 63.712643442675,15.172410722822 63.410537909716,14.798375301063 63.115625365637,14.424339879304 63.058081454597,13.697848002426 L 63.022116510198,13.697848002426 Q 62.691239021718,14.424339879304 62.17334382236,14.827147256583 61.655448623002,15.229954633862 60.921763757244,15.229954633862 Z M 62.849484777078,11.482407427393 62.000712089241,11.496793405153 Q 61.734571500681,11.511179382913 61.497202867642,11.554337316193 61.259834234603,11.590302260593 61.080009512603,11.719776060432 60.900184790604,11.842056871392 60.792289957404,12.079425504431 60.684395124204,12.31679413747 60.684395124204,12.726794503629 60.684395124204,13.280654647388 60.892991801724,13.553988224827 61.108781468123,13.820128813386 61.454044934362,13.820128813386 61.770536445081,13.820128813386 62.02948404476,13.654690069146 62.29562463332,13.489251324907 62.475449355319,13.223110736348 62.655274077319,12.949777158909 62.748782932758,12.59732070379 62.849484777078,12.244864248671 62.849484777078,11.878021815792 L 62.849484777078,11.482407427393 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:0.9411764706" id="path4251" />
<path d="M 70.315805140883,15.086094856262 70.315805140883,10.719950606115 Q 70.315805140883,10.266792306677 70.258261229843,9.8927568849176 70.200717318803,9.5115284742787 70.064050530083,9.2453878857195 69.927383741364,8.9720543082803 69.704401086085,8.8210015418008 69.488611419685,8.6699487753212 69.179312897846,8.6699487753212 68.877207364887,8.6699487753212 68.632645742968,8.8353875195608 68.388084121048,8.9936332749203 68.208259399049,9.2957388078794 68.035627665929,9.5906513519585 67.93492582161,10.007844706997 67.84141696617,10.417845073156 67.84141696617,10.914161305875 L 67.84141696617,15.086094856262 66.179836534895,15.086094856262 66.179836534895,9.0439841970801 Q 66.179836534895,8.7922295862809 66.172643546015,8.5260889977217 66.172643546015,8.2599484091625 66.165450557135,8.0225797761232 66.158257568255,7.7780181542039 66.151064579375,7.5910004433244 66.143871590495,7.396789743565 66.136678601615,7.3032808881253 L 67.71913615521,7.3032808881253 Q 67.73352213297,7.389596754685 67.74071512185,7.5838074544445 67.74790811073,7.7708251653239 67.76229408849,8.0010008094832 67.77668006625,8.2311764536425 67.78387305513,8.4613520978019 67.79106604401,8.6915277419612 67.79106604401,8.8497734973207 L 67.81264501065,8.8497734973207 Q 68.150715488009,7.9578428762034 68.654224709608,7.5550354989246 69.164926920086,7.1522281216457 69.869839830324,7.1522281216457 70.445278940722,7.1522281216457 70.840893329121,7.3824037658051 71.2437007064,7.6125794099644 71.495455317199,8.0153867872432 71.747209927998,8.418194164522 71.855104761198,8.9648613194004 71.970192583278,9.5115284742787 71.970192583278,10.144511495717 L 71.970192583278,15.086094856262 70.315805140883,15.086094856262 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:0.9411764706" id="path4253" />
<path d="M 76.192478408106,15.229954633862 Q 75.501951475628,15.229954633862 74.948091331869,14.985393011943 74.394231188111,14.733638401143 74.005809788592,14.230129179545 73.617388389073,13.719426969066 73.408791711554,12.956970147789 73.207388022915,12.187320337631 73.207388022915,11.158722927794 73.207388022915,10.043809651397 73.451949644834,9.2813528301194 73.696511266753,8.5188960088417 74.106511632912,8.0513517316431 74.523704987951,7.5766144655645 75.063179153949,7.3680177880451 75.609846308827,7.1594211105257 76.214057374746,7.1594211105257 76.969321207143,7.1594211105257 77.501602384262,7.4831056101248 78.03388356138,7.7995971208438 78.371954038739,8.3750362312421 78.717217504978,8.9504753416404 78.875463260338,9.756090096198 79.040902004577,10.554511861876 79.040902004577,11.525565360673 L 79.040902004577,11.583109271713 74.948091331869,11.583109271713 Q 74.948091331869,12.072232515551 75.012828231789,12.49661885947 75.084758120589,12.913812214509 75.243003875948,13.223110736348 75.401249631308,13.525216269307 75.653004242107,13.705040991306 75.911951841787,13.877672724426 76.271601285785,13.877672724426 76.710373607464,13.877672724426 76.983707184903,13.654690069146 77.264233751222,13.424514424987 77.379321573302,12.949777158909 L 78.940200160258,13.115215903148 Q 78.832305327058,13.446093391627 78.638094627298,13.820128813386 78.451076916419,14.194164235145 78.1345854057,14.510655745864 77.818093894981,14.819954267703 77.343356628902,15.028550945222 76.868619362824,15.229954633862 76.192478408106,15.229954633862 Z M 76.192478408106,8.4325801422819 Q 75.940723797306,8.4325801422819 75.717741142027,8.5404749754816 75.494758486748,8.6411768198013 75.329319742508,8.8713524639606 75.171073987149,9.09433511924 75.070372142829,9.4539845632389 74.969670298509,9.8136340072379 74.955284320749,10.317143228836 L 77.436865484342,10.317143228836 Q 77.386514562182,9.3748616855592 77.062830062583,8.9073174083605 76.739145562984,8.4325801422819 76.192478408106,8.4325801422819 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:0.9411764706" id="path4255" />
<path d="M 85.305995993316,15.215568656102 Q 84.572311127558,15.215568656102 84.17669673916,14.733638401143 83.788275339641,14.244515157305 83.788275339641,13.259075680748 L 83.788275339641,8.6699487753212 82.975467596203,8.6699487753212 82.975467596203,7.3032808881253 83.86739821732,7.3032808881253 84.385293416679,5.4762617126107 85.428276804276,5.4762617126107 85.428276804276,7.3032808881253 86.636698936112,7.3032808881253 86.636698936112,8.6699487753212 85.428276804276,8.6699487753212 85.428276804276,12.712408525869 Q 85.428276804276,13.280654647388 85.600908537395,13.553988224827 85.780733259395,13.820128813386 86.147575692274,13.820128813386 86.298628458753,13.820128813386 86.420909269713,13.791356857866 86.550383069552,13.762584902346 86.708628824912,13.719426969066 L 86.708628824912,14.971007034183 Q 86.399330303073,15.093287845142 86.054066836834,15.150831756182 85.715996359475,15.215568656102 85.305995993316,15.215568656102 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:0.9411764706" id="path4257" />
<path d="M 90.319507827051,15.229954633862 Q 89.628980894573,15.229954633862 89.075120750815,14.985393011943 88.521260607056,14.733638401143 88.132839207537,14.230129179545 87.744417808019,13.719426969066 87.535821130499,12.956970147789 87.33441744186,12.187320337631 87.33441744186,11.158722927794 87.33441744186,10.043809651397 87.578979063779,9.2813528301194 87.823540685698,8.5188960088417 88.233541051857,8.0513517316431 88.650734406896,7.5766144655645 89.190208572894,7.3680177880451 89.736875727773,7.1594211105257 90.341086793691,7.1594211105257 91.096350626089,7.1594211105257 91.628631803207,7.4831056101248 92.160912980326,7.7995971208438 92.498983457685,8.3750362312421 92.844246923923,8.9504753416404 93.002492679283,9.756090096198 93.167931423523,10.554511861876 93.167931423523,11.525565360673 L 93.167931423523,11.583109271713 89.075120750815,11.583109271713 Q 89.075120750815,12.072232515551 89.139857650734,12.49661885947 89.211787539534,12.913812214509 89.370033294894,13.223110736348 89.528279050253,13.525216269307 89.780033661053,13.705040991306 90.038981260732,13.877672724426 90.398630704731,13.877672724426 90.837403026409,13.877672724426 91.110736603849,13.654690069146 91.391263170168,13.424514424987 91.506350992247,12.949777158909 L 93.067229579203,13.115215903148 Q 92.959334746003,13.446093391627 92.765124046244,13.820128813386 92.578106335364,14.194164235145 92.261614824645,14.510655745864 91.945123313926,14.819954267703 91.470386047848,15.028550945222 90.995648781769,15.229954633862 90.319507827051,15.229954633862 Z M 90.319507827051,8.4325801422819 Q 90.067753216252,8.4325801422819 89.844770560972,8.5404749754816 89.621787905693,8.6411768198013 89.456349161454,8.8713524639606 89.298103406094,9.09433511924 89.197401561774,9.4539845632389 89.096699717455,9.8136340072379 89.082313739695,10.317143228836 L 91.563894903287,10.317143228836 Q 91.513543981127,9.3748616855592 91.189859481528,8.9073174083605 90.866174981929,8.4325801422819 90.319507827051,8.4325801422819 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:0.9411764706" id="path4259" />
<path d="M 97.095305073075,15.229954633862 Q 96.332848251797,15.229954633862 95.764602130279,14.942235078663 95.196356008761,14.654515523463 94.815127598122,14.129427335225 94.441092176363,13.604339146987 94.254074465483,12.870654281229 94.067056754604,12.129776426591 94.067056754604,11.237845805474 94.067056754604,10.266792306677 94.268460443243,9.5115284742787 94.477057120763,8.749071653001 94.865478520282,8.2311764536425 95.2538999198,7.7060882654041 95.822146041319,7.4327546879649 96.397585151717,7.1594211105257 97.116884039715,7.1594211105257 97.735481083393,7.1594211105257 98.217411338352,7.3608247991651 98.69934159331,7.5622284878045 99.044605059549,7.9146849429235 99.397061514668,8.2599484091625 99.612851181068,8.7346856752411 99.828640847467,9.2094229413196 99.907763725147,9.756090096198 L 98.238990304992,9.8567919405177 Q 98.167060416192,9.2597738634795 97.886533849873,8.9073174083605 97.606007283553,8.5476679643616 97.080919095315,8.5476679643616 96.411971129477,8.5476679643616 96.109865596518,9.2166159301996 95.807760063559,9.8855638960376 95.807760063559,11.158722927794 95.807760063559,13.848900768906 97.109691050835,13.848900768906 97.584428316914,13.848900768906 97.900919827633,13.489251324907 98.217411338352,13.122408892028 98.296534216031,12.40311000403 L 99.958114647306,12.49661885947 Q 99.900570736267,13.036093025468 99.684781069867,13.532409258187 99.476184392348,14.021532502025 99.116534948349,14.402760912664 98.76407849323,14.776796334423 98.253376282752,15.006971978582 97.749867061153,15.229954633862 97.095305073075,15.229954633862 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:0.9411764706" id="path4261" />
<path d="M 102.79934316128,8.8569664862007 Q 103.13741363864,7.9650358650833 103.64092286024,7.5622284878045 104.15162507072,7.1594211105257 104.85653798096,7.1594211105257 105.43197709136,7.1594211105257 105.82759147976,7.389596754685 106.23039885703,7.6197723988444 106.48215346783,8.0225797761232 106.73390807863,8.425387153402 106.84180291183,8.9720543082803 106.95689073391,9.5187214631587 106.95689073391,10.151704484597 L 106.95689073391,15.086094856262 105.30250329152,15.086094856262 105.30250329152,10.727143594995 Q 105.30250329152,10.273985295556 105.24495938048,9.8999498737976 105.18741546944,9.5187214631587 105.05074868072,9.2525808745995 104.914081892,8.9792472971603 104.69109923672,8.8281945306808 104.47530957032,8.6771417642012 104.16601104848,8.6771417642012 103.86390551552,8.6771417642012 103.6193438936,8.8425805084407 103.37478227168,9.0008262638003 103.19495754968,9.3029317967594 103.02232581656,9.5978443408385 102.92162397224,10.015037695877 102.8281151168,10.425038062036 102.8281151168,10.921354294755 L 102.8281151168,15.086094856262 101.16653468553,15.086094856262 101.16653468553,4.4116993583739 102.8281151168,4.4116993583739 102.8281151168,7.3248598547652 Q 102.8281151168,7.5550354989246 102.82092212792,7.7924041319638 102.81372913904,8.0225797761232 102.80653615016,8.2311764536425 102.79934316128,8.4325801422819 102.7921501724,8.5980188865215 102.78495718352,8.763457630761 102.77776419464,8.8569664862007 L 102.79934316128,8.8569664862007 Z" style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:condensed;font-size:14.7312412262px;line-height:125%;font-family:'Liberation Sans Narrow';-inkscape-font-specification:'Liberation Sans Narrow, Bold Condensed';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:white;fill-opacity:0.9411764706" id="path4263" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 49 KiB

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,28 @@
<?php
/**
* @copyright Copyright (C) 2020, Friendica
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
use Friendica\Database\DBA;
/**
* @brief execute SQL query with printf style args - deprecated
* execute SQL query with printf style args - deprecated
*
* Please use the DBA:: functions instead:
* DBA::select, DBA::exists, DBA::insert
@ -18,7 +37,7 @@ function q($sql) {
$args = func_get_args();
unset($args[0]);
if (!DBA::$connected) {
if (!DBA::connected()) {
return false;
}

File diff suppressed because it is too large Load diff

View file

@ -1,524 +0,0 @@
<?php
/**
* @file include/items.php
*/
use Friendica\BaseObject;
use Friendica\Content\Feature;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\PConfig;
use Friendica\Core\Protocol;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Item;
use Friendica\Protocol\DFRN;
use Friendica\Protocol\Feed;
use Friendica\Protocol\OStatus;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\ParseUrl;
use Friendica\Util\Strings;
use Friendica\Util\Temporal;
require_once 'mod/share.php';
function add_page_info_data(array $data, $no_photos = false)
{
Hook::callAll('page_info_data', $data);
if (empty($data['type'])) {
return '';
}
// It maybe is a rich content, but if it does have everything that a link has,
// then treat it that way
if (($data["type"] == "rich") && is_string($data["title"]) &&
is_string($data["text"]) && !empty($data["images"])) {
$data["type"] = "link";
}
$data["title"] = defaults($data, "title", "");
if ((($data["type"] != "link") && ($data["type"] != "video") && ($data["type"] != "photo")) || ($data["title"] == $data["url"])) {
return "";
}
if ($no_photos && ($data["type"] == "photo")) {
return "";
}
// Escape some bad characters
$data["url"] = str_replace(["[", "]"], ["&#91;", "&#93;"], htmlentities($data["url"], ENT_QUOTES, 'UTF-8', false));
$data["title"] = str_replace(["[", "]"], ["&#91;", "&#93;"], htmlentities($data["title"], ENT_QUOTES, 'UTF-8', false));
$text = "[attachment type='".$data["type"]."'";
if (empty($data["text"])) {
$data["text"] = $data["title"];
}
if (empty($data["text"])) {
$data["text"] = $data["url"];
}
if (!empty($data["url"])) {
$text .= " url='".$data["url"]."'";
}
if (!empty($data["title"])) {
$text .= " title='".$data["title"]."'";
}
// Only embedd a picture link when it seems to be a valid picture ("width" is set)
if (!empty($data["images"]) && !empty($data["images"][0]["width"])) {
$preview = str_replace(["[", "]"], ["&#91;", "&#93;"], htmlentities($data["images"][0]["src"], ENT_QUOTES, 'UTF-8', false));
// if the preview picture is larger than 500 pixels then show it in a larger mode
// But only, if the picture isn't higher than large (To prevent huge posts)
if (!Config::get('system', 'always_show_preview') && ($data["images"][0]["width"] >= 500)
&& ($data["images"][0]["width"] >= $data["images"][0]["height"])) {
$text .= " image='".$preview."'";
} else {
$text .= " preview='".$preview."'";
}
}
$text .= "]".$data["text"]."[/attachment]";
$hashtags = "";
if (isset($data["keywords"]) && count($data["keywords"])) {
$hashtags = "\n";
foreach ($data["keywords"] as $keyword) {
/// @TODO make a positive list of allowed characters
$hashtag = str_replace([" ", "+", "/", ".", "#", "'", "", "`", "(", ")", "", ""],
["", "", "", "", "", "", "", "", "", "", "", ""], $keyword);
$hashtags .= "#[url=" . System::baseUrl() . "/search?tag=" . $hashtag . "]" . $hashtag . "[/url] ";
}
}
return "\n".$text.$hashtags;
}
function query_page_info($url, $photo = "", $keywords = false, $keyword_blacklist = "")
{
$data = ParseUrl::getSiteinfoCached($url, true);
if ($photo != "") {
$data["images"][0]["src"] = $photo;
}
Logger::log('fetch page info for ' . $url . ' ' . print_r($data, true), Logger::DEBUG);
if (!$keywords && isset($data["keywords"])) {
unset($data["keywords"]);
}
if (($keyword_blacklist != "") && isset($data["keywords"])) {
$list = explode(", ", $keyword_blacklist);
foreach ($list as $keyword) {
$keyword = trim($keyword);
$index = array_search($keyword, $data["keywords"]);
if ($index !== false) {
unset($data["keywords"][$index]);
}
}
}
return $data;
}
function add_page_keywords($url, $photo = "", $keywords = false, $keyword_blacklist = "")
{
$data = query_page_info($url, $photo, $keywords, $keyword_blacklist);
$tags = "";
if (isset($data["keywords"]) && count($data["keywords"])) {
foreach ($data["keywords"] as $keyword) {
$hashtag = str_replace([" ", "+", "/", ".", "#", "'"],
["", "", "", "", "", ""], $keyword);
if ($tags != "") {
$tags .= ", ";
}
$tags .= "#[url=" . System::baseUrl() . "/search?tag=" . $hashtag . "]" . $hashtag . "[/url]";
}
}
return $tags;
}
function add_page_info($url, $no_photos = false, $photo = "", $keywords = false, $keyword_blacklist = "")
{
$data = query_page_info($url, $photo, $keywords, $keyword_blacklist);
$text = '';
if (is_array($data)) {
$text = add_page_info_data($data, $no_photos);
}
return $text;
}
function add_page_info_to_body($body, $texturl = false, $no_photos = false)
{
Logger::log('add_page_info_to_body: fetch page info for body ' . $body, Logger::DEBUG);
$URLSearchString = "^\[\]";
// Fix for Mastodon where the mentions are in a different format
$body = preg_replace("/\[url\=([$URLSearchString]*)\]([#!@])(.*?)\[\/url\]/ism",
'$2[url=$1]$3[/url]', $body);
// Adding these spaces is a quick hack due to my problems with regular expressions :)
preg_match("/[^!#@]\[url\]([$URLSearchString]*)\[\/url\]/ism", " " . $body, $matches);
if (!$matches) {
preg_match("/[^!#@]\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", " " . $body, $matches);
}
// Convert urls without bbcode elements
if (!$matches && $texturl) {
preg_match("/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", " ".$body, $matches);
// Yeah, a hack. I really hate regular expressions :)
if ($matches) {
$matches[1] = $matches[2];
}
}
if ($matches) {
$footer = add_page_info($matches[1], $no_photos);
}
// Remove the link from the body if the link is attached at the end of the post
if (isset($footer) && (trim($footer) != "") && (strpos($footer, $matches[1]))) {
$removedlink = trim(str_replace($matches[1], "", $body));
if (($removedlink == "") || strstr($body, $removedlink)) {
$body = $removedlink;
}
$removedlink = preg_replace("/\[url\=" . preg_quote($matches[1], '/') . "\](.*?)\[\/url\]/ism", '', $body);
if (($removedlink == "") || strstr($body, $removedlink)) {
$body = $removedlink;
}
}
// Add the page information to the bottom
if (isset($footer) && (trim($footer) != "")) {
$body .= $footer;
}
return $body;
}
/**
*
* consume_feed - process atom feed and update anything/everything we might need to update
*
* $xml = the (atom) feed to consume - RSS isn't as fully supported but may work for simple feeds.
*
* $importer = the contact_record (joined to user_record) of the local user who owns this relationship.
* It is this person's stuff that is going to be updated.
* $contact = the person who is sending us stuff. If not set, we MAY be processing a "follow" activity
* from an external network and MAY create an appropriate contact record. Otherwise, we MUST
* have a contact record.
* $hub = should we find a hub declation in the feed, pass it back to our calling process, who might (or
* might not) try and subscribe to it.
* $datedir sorts in reverse order
* $pass - by default ($pass = 0) we cannot guarantee that a parent item has been
* imported prior to its children being seen in the stream unless we are certain
* of how the feed is arranged/ordered.
* With $pass = 1, we only pull parent items out of the stream.
* With $pass = 2, we only pull children (comments/likes).
*
* So running this twice, first with pass 1 and then with pass 2 will do the right
* thing regardless of feed ordering. This won't be adequate in a fully-threaded
* model where comments can have sub-threads. That would require some massive sorting
* to get all the feed items into a mostly linear ordering, and might still require
* recursion.
*
* @param $xml
* @param array $importer
* @param array $contact
* @param $hub
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function consume_feed($xml, array $importer, array $contact, &$hub)
{
if ($contact['network'] === Protocol::OSTATUS) {
Logger::log("Consume OStatus messages ", Logger::DEBUG);
OStatus::import($xml, $importer, $contact, $hub);
return;
}
if ($contact['network'] === Protocol::FEED) {
Logger::log("Consume feeds", Logger::DEBUG);
Feed::import($xml, $importer, $contact, $hub);
return;
}
if ($contact['network'] === Protocol::DFRN) {
Logger::log("Consume DFRN messages", Logger::DEBUG);
$dfrn_importer = DFRN::getImporter($contact["id"], $importer["uid"]);
if (!empty($dfrn_importer)) {
Logger::log("Now import the DFRN feed");
DFRN::import($xml, $dfrn_importer, true);
return;
}
}
}
function subscribe_to_hub($url, array $importer, array $contact, $hubmode = 'subscribe')
{
/*
* Diaspora has different message-ids in feeds than they do
* through the direct Diaspora protocol. If we try and use
* the feed, we'll get duplicates. So don't.
*/
if ($contact['network'] === Protocol::DIASPORA) {
return;
}
// Without an importer we don't have a user id - so we quit
if (empty($importer)) {
return;
}
$user = DBA::selectFirst('user', ['nickname'], ['uid' => $importer['uid']]);
// No user, no nickname, we quit
if (!DBA::isResult($user)) {
return;
}
$push_url = System::baseUrl() . '/pubsub/' . $user['nickname'] . '/' . $contact['id'];
// Use a single verify token, even if multiple hubs
$verify_token = ((strlen($contact['hub-verify'])) ? $contact['hub-verify'] : Strings::getRandomHex());
$params= 'hub.mode=' . $hubmode . '&hub.callback=' . urlencode($push_url) . '&hub.topic=' . urlencode($contact['poll']) . '&hub.verify=async&hub.verify_token=' . $verify_token;
Logger::log('subscribe_to_hub: ' . $hubmode . ' ' . $contact['name'] . ' to hub ' . $url . ' endpoint: ' . $push_url . ' with verifier ' . $verify_token);
if (!strlen($contact['hub-verify']) || ($contact['hub-verify'] != $verify_token)) {
DBA::update('contact', ['hub-verify' => $verify_token], ['id' => $contact['id']]);
}
$postResult = Network::post($url, $params);
Logger::log('subscribe_to_hub: returns: ' . $postResult->getReturnCode(), Logger::DEBUG);
return;
}
function drop_items(array $items)
{
$uid = 0;
if (!local_user() && !remote_user()) {
return;
}
if (!empty($items)) {
foreach ($items as $item) {
$owner = Item::deleteForUser(['id' => $item], local_user());
if ($owner && !$uid) {
$uid = $owner;
}
}
}
}
function drop_item($id, $return = '')
{
$a = BaseObject::getApp();
// locate item to be deleted
$fields = ['id', 'uid', 'guid', 'contact-id', 'deleted', 'gravity', 'parent'];
$item = Item::selectFirstForUser(local_user(), $fields, ['id' => $id]);
if (!DBA::isResult($item)) {
notice(L10n::t('Item not found.') . EOL);
$a->internalRedirect('network');
}
if ($item['deleted']) {
return 0;
}
$contact_id = 0;
// check if logged in user is either the author or owner of this item
if (!empty($_SESSION['remote'])) {
foreach ($_SESSION['remote'] as $visitor) {
if ($visitor['uid'] == $item['uid'] && $visitor['cid'] == $item['contact-id']) {
$contact_id = $visitor['cid'];
break;
}
}
}
if ((local_user() == $item['uid']) || $contact_id) {
// Check if we should do HTML-based delete confirmation
if (!empty($_REQUEST['confirm'])) {
// <form> can't take arguments in its "action" parameter
// so add any arguments as hidden inputs
$query = explode_querystring($a->query_string);
$inputs = [];
foreach ($query['args'] as $arg) {
if (strpos($arg, 'confirm=') === false) {
$arg_parts = explode('=', $arg);
$inputs[] = ['name' => $arg_parts[0], 'value' => $arg_parts[1]];
}
}
return Renderer::replaceMacros(Renderer::getMarkupTemplate('confirm.tpl'), [
'$method' => 'get',
'$message' => L10n::t('Do you really want to delete this item?'),
'$extra_inputs' => $inputs,
'$confirm' => L10n::t('Yes'),
'$confirm_url' => $query['base'],
'$confirm_name' => 'confirmed',
'$cancel' => L10n::t('Cancel'),
]);
}
// Now check how the user responded to the confirmation query
if (!empty($_REQUEST['canceled'])) {
$a->internalRedirect('display/' . $item['guid']);
}
$is_comment = ($item['gravity'] == GRAVITY_COMMENT) ? true : false;
$parentitem = null;
if (!empty($item['parent'])){
$fields = ['guid'];
$parentitem = Item::selectFirstForUser(local_user(), $fields, ['id' => $item['parent']]);
}
// delete the item
Item::deleteForUser(['id' => $item['id']], local_user());
$return_url = hex2bin($return);
// removes update_* from return_url to ignore Ajax refresh
$return_url = str_replace("update_", "", $return_url);
// Check if delete a comment
if ($is_comment) {
// Return to parent guid
if (!empty($parentitem)) {
$a->internalRedirect('display/' . $parentitem['guid']);
//NOTREACHED
}
// In case something goes wrong
else {
$a->internalRedirect('network');
//NOTREACHED
}
}
else {
// if unknown location or deleting top level post called from display
if (empty($return_url) || strpos($return_url, 'display') !== false) {
$a->internalRedirect('network');
//NOTREACHED
} else {
$a->internalRedirect($return_url);
//NOTREACHED
}
}
} else {
notice(L10n::t('Permission denied.') . EOL);
$a->internalRedirect('display/' . $item['guid']);
//NOTREACHED
}
}
/* arrange the list in years */
function list_post_dates($uid, $wall)
{
$dnow = DateTimeFormat::localNow('Y-m-d');
$dthen = Item::firstPostDate($uid, $wall);
if (!$dthen) {
return [];
}
// Set the start and end date to the beginning of the month
$dnow = substr($dnow, 0, 8) . '01';
$dthen = substr($dthen, 0, 8) . '01';
$ret = [];
/*
* Starting with the current month, get the first and last days of every
* month down to and including the month of the first post
*/
while (substr($dnow, 0, 7) >= substr($dthen, 0, 7)) {
$dyear = intval(substr($dnow, 0, 4));
$dstart = substr($dnow, 0, 8) . '01';
$dend = substr($dnow, 0, 8) . Temporal::getDaysInMonth(intval($dnow), intval(substr($dnow, 5)));
$start_month = DateTimeFormat::utc($dstart, 'Y-m-d');
$end_month = DateTimeFormat::utc($dend, 'Y-m-d');
$str = L10n::getDay(DateTimeFormat::utc($dnow, 'F'));
if (empty($ret[$dyear])) {
$ret[$dyear] = [];
}
$ret[$dyear][] = [$str, $end_month, $start_month];
$dnow = DateTimeFormat::utc($dnow . ' -1 month', 'Y-m-d');
}
return $ret;
}
function posted_date_widget($url, $uid, $wall)
{
$o = '';
if (!Feature::isEnabled($uid, 'archives')) {
return $o;
}
// For former Facebook folks that left because of "timeline"
/*
* @TODO old-lost code?
if ($wall && intval(PConfig::get($uid, 'system', 'no_wall_archive_widget')))
return $o;
*/
$visible_years = PConfig::get($uid, 'system', 'archive_visible_years', 5);
$ret = list_post_dates($uid, $wall);
if (!DBA::isResult($ret)) {
return $o;
}
$cutoff_year = intval(DateTimeFormat::localNow('Y')) - $visible_years;
$cutoff = ((array_key_exists($cutoff_year, $ret))? true : false);
$o = Renderer::replaceMacros(Renderer::getMarkupTemplate('posted_date_widget.tpl'),[
'$title' => L10n::t('Archives'),
'$size' => $visible_years,
'$cutoff_year' => $cutoff_year,
'$cutoff' => $cutoff,
'$url' => $url,
'$dates' => $ret,
'$showmore' => L10n::t('show more')
]);
return $o;
}

View file

@ -1,297 +0,0 @@
<?php
/**
* @file include/text.php
*/
use Friendica\App;
use Friendica\Content\Smilies;
use Friendica\Content\Text\BBCode;
use Friendica\Core\Protocol;
use Friendica\Model\Contact;
use Friendica\Model\FileTag;
use Friendica\Util\Strings;
use Friendica\Util\XML;
/**
* Turn user/group ACLs stored as angle bracketed text into arrays
*
* @param string $s
* @return array
*/
function expand_acl($s) {
// turn string array of angle-bracketed elements into numeric array
// e.g. "<1><2><3>" => array(1,2,3);
$ret = [];
if (strlen($s)) {
$t = str_replace('<', '', $s);
$a = explode('>', $t);
foreach ($a as $aa) {
if (intval($aa)) {
$ret[] = intval($aa);
}
}
}
return $ret;
}
/**
* Wrap ACL elements in angle brackets for storage
* @param string $item
*/
function sanitise_acl(&$item) {
if (intval($item)) {
$item = '<' . intval(Strings::escapeTags(trim($item))) . '>';
} else {
unset($item);
}
}
/**
* Convert an ACL array to a storable string
*
* Normally ACL permissions will be an array.
* We'll also allow a comma-separated string.
*
* @param string|array $p
* @return string
*/
function perms2str($p) {
$ret = '';
if (is_array($p)) {
$tmp = $p;
} else {
$tmp = explode(',', $p);
}
if (is_array($tmp)) {
array_walk($tmp, 'sanitise_acl');
$ret = implode('', $tmp);
}
return $ret;
}
/**
* for html,xml parsing - let's say you've got
* an attribute foobar="class1 class2 class3"
* and you want to find out if it contains 'class3'.
* you can't use a normal sub string search because you
* might match 'notclass3' and a regex to do the job is
* possible but a bit complicated.
* pass the attribute string as $attr and the attribute you
* are looking for as $s - returns true if found, otherwise false
*
* @param string $attr attribute value
* @param string $s string to search
* @return boolean True if found, False otherwise
*/
function attribute_contains($attr, $s) {
$a = explode(' ', $attr);
return (count($a) && in_array($s,$a));
}
/**
* Compare activity uri. Knows about activity namespace.
*
* @param string $haystack
* @param string $needle
* @return boolean
*/
function activity_match($haystack,$needle) {
return (($haystack === $needle) || ((basename($needle) === $haystack) && strstr($needle, NAMESPACE_ACTIVITY_SCHEMA)));
}
/**
* quick and dirty quoted_printable encoding
*
* @param string $s
* @return string
*/
function qp($s) {
return str_replace("%", "=", rawurlencode($s));
}
/**
* @brief Find any non-embedded images in private items and add redir links to them
*
* @param App $a
* @param array &$item The field array of an item row
*/
function redir_private_images($a, &$item)
{
$matches = [];
$cnt = preg_match_all('|\[img\](http[^\[]*?/photo/[a-fA-F0-9]+?(-[0-9]\.[\w]+?)?)\[\/img\]|', $item['body'], $matches, PREG_SET_ORDER);
if ($cnt) {
foreach ($matches as $mtch) {
if (strpos($mtch[1], '/redir') !== false) {
continue;
}
if ((local_user() == $item['uid']) && ($item['private'] == 1) && ($item['contact-id'] != $a->contact['id']) && ($item['network'] == Protocol::DFRN)) {
$img_url = 'redir?f=1&quiet=1&url=' . urlencode($mtch[1]) . '&conurl=' . urlencode($item['author-link']);
$item['body'] = str_replace($mtch[0], '[img]' . $img_url . '[/img]', $item['body']);
}
}
}
}
/**
* @brief Given a text string, convert from bbcode to html and add smilie icons.
*
* @param string $text String with bbcode.
* @return string Formattet HTML.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function prepare_text($text) {
if (stristr($text, '[nosmile]')) {
$s = BBCode::convert($text);
} else {
$s = Smilies::replace(BBCode::convert($text));
}
return trim($s);
}
/**
* return array with details for categories and folders for an item
*
* @param array $item
* @return array
*
* [
* [ // categories array
* {
* 'name': 'category name',
* 'removeurl': 'url to remove this category',
* 'first': 'is the first in this array? true/false',
* 'last': 'is the last in this array? true/false',
* } ,
* ....
* ],
* [ //folders array
* {
* 'name': 'folder name',
* 'removeurl': 'url to remove this folder',
* 'first': 'is the first in this array? true/false',
* 'last': 'is the last in this array? true/false',
* } ,
* ....
* ]
* ]
*/
function get_cats_and_terms($item)
{
$categories = [];
$folders = [];
$matches = [];
$first = true;
$cnt = preg_match_all('/<(.*?)>/', $item['file'], $matches, PREG_SET_ORDER);
if ($cnt) {
foreach ($matches as $mtch) {
$categories[] = [
'name' => XML::escape(FileTag::decode($mtch[1])),
'url' => "#",
'removeurl' => ((local_user() == $item['uid'])?'filerm/' . $item['id'] . '?f=&cat=' . XML::escape(FileTag::decode($mtch[1])):""),
'first' => $first,
'last' => false
];
$first = false;
}
}
if (count($categories)) {
$categories[count($categories) - 1]['last'] = true;
}
if (local_user() == $item['uid']) {
$matches = [];
$first = true;
$cnt = preg_match_all('/\[(.*?)\]/', $item['file'], $matches, PREG_SET_ORDER);
if ($cnt) {
foreach ($matches as $mtch) {
$folders[] = [
'name' => XML::escape(FileTag::decode($mtch[1])),
'url' => "#",
'removeurl' => ((local_user() == $item['uid']) ? 'filerm/' . $item['id'] . '?f=&term=' . XML::escape(FileTag::decode($mtch[1])) : ""),
'first' => $first,
'last' => false
];
$first = false;
}
}
}
if (count($folders)) {
$folders[count($folders) - 1]['last'] = true;
}
return [$categories, $folders];
}
/**
* return number of bytes in size (K, M, G)
* @param string $size_str
* @return int
*/
function return_bytes($size_str) {
switch (substr ($size_str, -1)) {
case 'M': case 'm': return (int)$size_str * 1048576;
case 'K': case 'k': return (int)$size_str * 1024;
case 'G': case 'g': return (int)$size_str * 1073741824;
default: return $size_str;
}
}
function bb_translate_video($s) {
$matches = null;
$r = preg_match_all("/\[video\](.*?)\[\/video\]/ism",$s,$matches,PREG_SET_ORDER);
if ($r) {
foreach ($matches as $mtch) {
if ((stristr($mtch[1], 'youtube')) || (stristr($mtch[1], 'youtu.be'))) {
$s = str_replace($mtch[0], '[youtube]' . $mtch[1] . '[/youtube]', $s);
} elseif (stristr($mtch[1], 'vimeo')) {
$s = str_replace($mtch[0], '[vimeo]' . $mtch[1] . '[/vimeo]', $s);
}
}
}
return $s;
}
function undo_post_tagging($s) {
$matches = null;
$cnt = preg_match_all('/([!#@])\[url=(.*?)\](.*?)\[\/url\]/ism', $s, $matches, PREG_SET_ORDER);
if ($cnt) {
foreach ($matches as $mtch) {
if (in_array($mtch[1], ['!', '@'])) {
$contact = Contact::getDetailsByURL($mtch[2]);
$mtch[3] = empty($contact['addr']) ? $mtch[2] : $contact['addr'];
}
$s = str_replace($mtch[0], $mtch[1] . $mtch[3],$s);
}
}
return $s;
}
/// @TODO Rewrite this
function is_a_date_arg($s) {
$i = intval($s);
if ($i > 1900) {
$y = date('Y');
if ($i <= $y + 1 && strpos($s, '-') == 4) {
$m = intval(substr($s, 5));
if ($m > 0 && $m <= 12) {
return true;
}
}
}
return false;
}

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