Merge branch '2019.03-RC'

This commit is contained in:
Tobias Diekershoff 2019-03-22 20:53:21 +01:00
commit 854cc3e472
505 changed files with 63760 additions and 51050 deletions

View file

@ -1,36 +1,10 @@
codecov:
branch: develop
comment: off
coverage:
status:
patch:
default: off
source:
target: 80%
flags: source
backend:
target: 80%
flags: backend
project:
default: off
source:
flags: source
backend:
flags: backend
default:
target: auto
threshold: null
base: auto
flags:
source:
paths:
- src/
backend:
paths:
- mod/
- include/
binary:
paths:
- bin/
tests:
paths:
- tests/
comment: off

3
.gitignore vendored
View file

@ -71,3 +71,6 @@ venv/
#ignore .htaccess
.htaccess
#ignore filesystem storage default path
/storage

View file

@ -1,11 +1,10 @@
---
language: php
## Friendica supports PHP version >= 5.6.1
## Friendica officially supports PHP version >= 7.1
php:
- 5.6
- 7.0
- 7.1
- 7.2
- 7.3
services:
- mysql

View file

@ -1,3 +1,92 @@
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]

View file

@ -1,11 +1,11 @@
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
@ -23,7 +23,6 @@ André Alves
André Lohan
Andy
Andy Hee
AndyHee
Angristan
Anthronaut
Arian - Cazare Muncitori
@ -93,10 +92,8 @@ greeneyedred
Gregory Smith
Haakon Meland Eriksen
Hans Meine
hauke
Hauke
Hauke Altmann
Hauke Zühl
Herbert Thielen
hoergen
Hubert Kościański
@ -167,6 +164,7 @@ Pascal
Pascal Deklerck
Pavel Morozov
PerigGouanvic
Peter Liebetrau
peturisfeld
Philipp
Philipp Holzer
@ -201,6 +199,7 @@ Seth
Silke Meyer
Simon L'nu
Simó Albert i Beltran
softmetz
soko1
St John Karp
Stanislav N.
@ -233,12 +232,14 @@ Tubuntu
Tupambae.org
U-SOUND\mike
ufic
Ulf Rompe
Unknown
Vasudev Kamath
Vasya Novikov
Vinzenz Vietzke
vislav
vladimir N
Vladimir Núñez
VVelox
Vít Šesták 'v6ak'
Waldemar Stoczkowski

View file

@ -1 +1 @@
2019.01
2019.03

View file

@ -32,7 +32,7 @@
*
*/
use Friendica\App;
use Friendica\Factory;
use Friendica\Util\ExAuth;
if (sizeof($_SERVER["argv"]) == 0) {
@ -51,7 +51,7 @@ chdir($directory);
require dirname(__DIR__) . '/vendor/autoload.php';
$a = new App(dirname(__DIR__));
$a = Factory\DependencyFactory::setUp('auth_ejabbered', dirname(__DIR__));
if ($a->getMode()->isNormal()) {
$oAuth = new ExAuth();

View file

@ -3,7 +3,9 @@
require dirname(__DIR__) . '/vendor/autoload.php';
$a = new Friendica\App(dirname(__DIR__));
use Friendica\Factory;
$a = Factory\DependencyFactory::setUp('console', dirname(__DIR__));
\Friendica\BaseObject::setApp($a);
(new Friendica\Core\Console($argv))->execute();

View file

@ -7,11 +7,11 @@
* This script was taken from http://php.net/manual/en/function.pcntl-fork.php
*/
use Friendica\App;
use Friendica\Core\Config;
use Friendica\Core\Logger;
use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\Factory;
// Get options
$shortopts = 'f';
@ -32,7 +32,7 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) {
require dirname(__DIR__) . '/vendor/autoload.php';
$a = new App(dirname(__DIR__));
$a = Factory\DependencyFactory::setUp('daemon', dirname(__DIR__));
if ($a->getMode()->isInstall()) {
die("Friendica isn't properly installed yet.\n");
@ -102,7 +102,7 @@ if ($mode == "stop") {
unlink($pidfile);
Logger::log("Worker daemon process $pid was killed.", Logger::DEBUG);
Logger::notice("Worker daemon process was killed", ["pid" => $pid]);
Config::set('system', 'worker_daemon_mode', false);
die("Worker daemon process $pid was killed.\n");
@ -112,7 +112,7 @@ if (!empty($pid) && posix_kill($pid, 0)) {
die("Daemon process $pid is already running.\n");
}
Logger::log('Starting worker daemon.', Logger::DEBUG);
Logger::notice('Starting worker daemon.', ["pid" => $pid]);
if (!$foreground) {
echo "Starting worker daemon.\n";
@ -144,7 +144,9 @@ if (!$foreground) {
file_put_contents($pidfile, $pid);
// We lose the database connection upon forking
$a->loadDatabase();
/// @todo refactoring during https://github.com/friendica/friendica/issues/6720
$basePath = \Friendica\Util\BasePath::create(dirname(__DIR__), $_SERVER);
Factory\DBFactory::init($basePath, $a->getConfigCache(), $a->getProfiler(), $_SERVER);
}
Config::set('system', 'worker_daemon_mode', true);
@ -160,7 +162,7 @@ $last_cron = 0;
// Now running as a daemon.
while (true) {
if (!$do_cron && ($last_cron + $wait_interval) < time()) {
Logger::log('Forcing cron worker call.', Logger::DEBUG);
Logger::info('Forcing cron worker call.', ["pid" => $pid]);
$do_cron = true;
}
@ -174,7 +176,7 @@ while (true) {
$last_cron = time();
}
Logger::log("Sleeping", Logger::DEBUG);
Logger::info("Sleeping", ["pid" => $pid]);
$start = time();
do {
$seconds = (time() - $start);
@ -191,10 +193,10 @@ while (true) {
if ($timeout) {
$do_cron = true;
Logger::log("Woke up after $wait_interval seconds.", Logger::DEBUG);
Logger::info("Woke up after $wait_interval seconds.", ["pid" => $pid, 'sleep' => $wait_interval]);
} else {
$do_cron = false;
Logger::log("Worker jobs are calling to be forked.", Logger::DEBUG);
Logger::info("Worker jobs are calling to be forked.", ["pid" => $pid]);
}
}

View file

@ -4,10 +4,12 @@
* @file bin/worker.php
* @brief Starts the background processing
*/
use Friendica\App;
use Friendica\Core\Config;
use Friendica\Core\Worker;
use Friendica\Core\Update;
use Friendica\Core\Worker;
use Friendica\Factory;
// Get options
$shortopts = 'sn';
@ -28,10 +30,10 @@ if (!file_exists("boot.php") && (sizeof($_SERVER["argv"]) != 0)) {
require dirname(__DIR__) . '/vendor/autoload.php';
$a = new App(dirname(__DIR__));
$a = Factory\DependencyFactory::setUp('worker', dirname(__DIR__));
// Check the database structure and possibly fixes it
Update::check(true);
Update::check($a->getBasePath(), true);
// Quit when in maintenance
if (!$a->getMode()->has(App\Mode::MAINTENANCEDISABLED)) {
@ -44,7 +46,7 @@ $spawn = array_key_exists('s', $options) || array_key_exists('spawn', $options);
if ($spawn) {
Worker::spawnWorker();
killme();
exit();
}
$run_cron = !array_key_exists('n', $options) && !array_key_exists('no_cron', $options);

View file

@ -19,23 +19,19 @@
use Friendica\App;
use Friendica\BaseObject;
use Friendica\Core\Addon;
use Friendica\Core\Cache;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\PConfig;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Core\Update;
use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Conversation;
use Friendica\Model\Term;
use Friendica\Util\BasePath;
use Friendica\Util\DateTimeFormat;
define('FRIENDICA_PLATFORM', 'Friendica');
define('FRIENDICA_CODENAME', 'The Tazmans Flax-lily');
define('FRIENDICA_VERSION', '2019.01');
define('FRIENDICA_CODENAME', 'Dalmatian Bellflower');
define('FRIENDICA_VERSION', '2019.03');
define('DFRN_PROTOCOL_VERSION', '2.23');
define('NEW_UPDATE_ROUTINE_VERSION', 1170);
@ -97,18 +93,12 @@ define('SSL_POLICY_FULL', 1);
define('SSL_POLICY_SELFSIGN', 2);
/* @}*/
/**
* @name Register
*
* Registration policies
* @{
*/
define('REGISTER_CLOSED', 0);
define('REGISTER_APPROVE', 1);
define('REGISTER_OPEN', 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 */
define('REGISTER_APPROVE', \Friendica\Module\Register::APPROVE);
/** @deprecated since version 2019.03, please use \Friendica\Module\Register::OPEN instead */
define('REGISTER_OPEN', \Friendica\Module\Register::OPEN);
/**
* @name CP
@ -182,23 +172,27 @@ 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);
/** @deprecated since 2019.03, use Term::UNKNOWN instead */
define('TERM_UNKNOWN', Term::UNKNOWN);
/** @deprecated since 2019.03, use Term::HASHTAG instead */
define('TERM_HASHTAG', Term::HASHTAG);
/** @deprecated since 2019.03, use Term::MENTION instead */
define('TERM_MENTION', Term::MENTION);
/** @deprecated since 2019.03, use Term::CATEGORY instead */
define('TERM_CATEGORY', Term::CATEGORY);
/** @deprecated since 2019.03, use Term::PCATEGORY instead */
define('TERM_PCATEGORY', Term::PCATEGORY);
/** @deprecated since 2019.03, use Term::FILE instead */
define('TERM_FILE', Term::FILE);
/** @deprecated since 2019.03, use Term::SAVEDSEARCH instead */
define('TERM_SAVEDSEARCH', Term::SAVEDSEARCH);
/** @deprecated since 2019.03, use Term::CONVERSATION instead */
define('TERM_CONVERSATION', Term::CONVERSATION);
define('TERM_OBJ_POST', 1);
define('TERM_OBJ_PHOTO', 2);
/** @deprecated since 2019.03, use Term::OBJECT_TYPE_POST instead */
define('TERM_OBJ_POST', Term::OBJECT_TYPE_POST);
/** @deprecated since 2019.03, use Term::OBJECT_TYPE_PHOTO instead */
define('TERM_OBJ_PHOTO', Term::OBJECT_TYPE_PHOTO);
/**
* @name Namespaces
@ -653,18 +647,18 @@ function get_temppath()
$temppath = Config::get("system", "temppath");
if (($temppath != "") && App::isDirectoryUsable($temppath)) {
if (($temppath != "") && System::isDirectoryUsable($temppath)) {
// We have a temp path and it is usable
return App::getRealPath($temppath);
return BasePath::getRealPath($temppath);
}
// We don't have a working preconfigured temp path, so we take the system path.
$temppath = sys_get_temp_dir();
// Check if it is usable
if (($temppath != "") && App::isDirectoryUsable($temppath)) {
if (($temppath != "") && System::isDirectoryUsable($temppath)) {
// Always store the real path, not the path through symlinks
$temppath = App::getRealPath($temppath);
$temppath = BasePath::getRealPath($temppath);
// To avoid any interferences with other systems we create our own directory
$new_temppath = $temppath . "/" . $a->getHostName();
@ -673,7 +667,7 @@ function get_temppath()
mkdir($new_temppath);
}
if (App::isDirectoryUsable($new_temppath)) {
if (System::isDirectoryUsable($new_temppath)) {
// The new path is usable, we are happy
Config::set("system", "temppath", $new_temppath);
return $new_temppath;
@ -755,8 +749,8 @@ function get_itemcachepath()
}
$itemcache = Config::get('system', 'itemcache');
if (($itemcache != "") && App::isDirectoryUsable($itemcache)) {
return App::getRealPath($itemcache);
if (($itemcache != "") && System::isDirectoryUsable($itemcache)) {
return BasePath::getRealPath($itemcache);
}
$temppath = get_temppath();
@ -767,7 +761,7 @@ function get_itemcachepath()
mkdir($itemcache);
}
if (App::isDirectoryUsable($itemcache)) {
if (System::isDirectoryUsable($itemcache)) {
Config::set("system", "itemcache", $itemcache);
return $itemcache;
}
@ -783,7 +777,7 @@ function get_itemcachepath()
function get_spoolpath()
{
$spoolpath = Config::get('system', 'spoolpath');
if (($spoolpath != "") && App::isDirectoryUsable($spoolpath)) {
if (($spoolpath != "") && System::isDirectoryUsable($spoolpath)) {
// We have a spool path and it is usable
return $spoolpath;
}
@ -798,7 +792,7 @@ function get_spoolpath()
mkdir($spoolpath);
}
if (App::isDirectoryUsable($spoolpath)) {
if (System::isDirectoryUsable($spoolpath)) {
// The new path is usable, we are happy
Config::set("system", "spoolpath", $spoolpath);
return $spoolpath;

View file

@ -14,10 +14,17 @@
},
"require": {
"php": ">=5.6.1",
"ext-ctype": "*",
"ext-curl": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"asika/simple-console": "^1.0",
"divineomega/password_exposed": "^2.4",
@ -27,19 +34,22 @@
"lightopenid/lightopenid": "dev-master",
"michelf/php-markdown": "^1.7",
"mobiledetect/mobiledetectlib": "2.8.*",
"monolog/monolog": "^1.24",
"paragonie/random_compat": "^2.0",
"pear/Text_LanguageDetect": "1.*",
"pear/text_languagedetect": "1.*",
"psr/container": "^1.0",
"seld/cli-prompt": "^1.0",
"smarty/smarty": "^3.1",
"fxp/composer-asset-plugin": "~1.3",
"bower-asset/base64": "^1.0",
"bower-asset/Chart-js": "^2.7",
"bower-asset/chart-js": "^2.7",
"bower-asset/perfect-scrollbar": "^0.6",
"bower-asset/vue": "^2.5",
"npm-asset/jquery": "^2.0",
"npm-asset/jquery-colorbox": "^1.6",
"npm-asset/jquery-datetimepicker": "^2.4.0",
"npm-asset/jgrowl": "^1.4",
"npm-asset/moment": "^2.20.1",
"npm-asset/fullcalendar": "^3.0.1",
"npm-asset/cropperjs": "1.2.2",
"npm-asset/imagesloaded": "4.1.4"
@ -53,7 +63,8 @@
"autoload": {
"psr-4": {
"Friendica\\": "src/",
"Friendica\\Test\\": "tests/"
"Friendica\\Test\\": "tests/",
"Friendica\\Addon\\": "addon/"
},
"psr-0": {
"": "library/"
@ -87,7 +98,7 @@
"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"
},

219
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "51f7b3ab622038d7ef62ed03c06b48d0",
"content-hash": "8897c1f6912cc9b889534a8c59deead1",
"packages": [
{
"name": "asika/simple-console",
@ -809,6 +809,84 @@
],
"time": "2018-09-01T15:05:15+00:00"
},
{
"name": "monolog/monolog",
"version": "1.24.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
"reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Seldaek/monolog/zipball/bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266",
"reference": "bfc9ebb28f97e7a24c45bdc3f0ff482e47bb0266",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"psr/log": "~1.0"
},
"provide": {
"psr/log-implementation": "1.0.0"
},
"require-dev": {
"aws/aws-sdk-php": "^2.4.9 || ^3.0",
"doctrine/couchdb": "~1.0@dev",
"graylog2/gelf-php": "~1.0",
"jakub-onderka/php-parallel-lint": "0.9",
"php-amqplib/php-amqplib": "~2.4",
"php-console/php-console": "^3.1.3",
"phpunit/phpunit": "~4.5",
"phpunit/phpunit-mock-objects": "2.3.0",
"ruflin/elastica": ">=0.90 <3.0",
"sentry/sentry": "^0.13",
"swiftmailer/swiftmailer": "^5.3|^6.0"
},
"suggest": {
"aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
"doctrine/couchdb": "Allow sending log messages to a CouchDB server",
"ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
"ext-mongo": "Allow sending log messages to a MongoDB server",
"graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
"mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver",
"php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
"php-console/php-console": "Allow sending log messages to Google Chrome",
"rollbar/rollbar": "Allow sending log messages to Rollbar",
"ruflin/elastica": "Allow sending log messages to an Elastic Search server",
"sentry/sentry": "Allow sending log messages to a Sentry server"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Monolog\\": "src/Monolog"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "Sends your logs to files, sockets, inboxes, databases and various web services",
"homepage": "http://github.com/Seldaek/monolog",
"keywords": [
"log",
"logging",
"psr-3"
],
"time": "2018-11-05T09:00:11+00:00"
},
{
"name": "npm-asset/cropperjs",
"version": "1.2.2",
@ -948,32 +1026,18 @@
},
{
"name": "npm-asset/fullcalendar",
"version": "3.9.0",
"version": "3.10.0",
"dist": {
"type": "tar",
"url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-3.9.0.tgz",
"url": "https://registry.npmjs.org/fullcalendar/-/fullcalendar-3.10.0.tgz",
"reference": null,
"shasum": "b608a9989f3416f0b1d526c6bdfeeaf2ac79eda5"
},
"require": {
"npm-asset/jquery": ">=2,<4.0",
"npm-asset/moment": ">=2.20.1,<3.0.0"
"shasum": "cc5e87d518fd6550e142816a31dd191664847919"
},
"type": "npm-asset-library",
"extra": {
"npm-asset-bugs": {
"url": "https://fullcalendar.io/wiki/Reporting-Bugs/"
},
"npm-asset-files": [
"dist/*.js",
"dist/*.css",
"dist/*.d.ts",
"dist/locale/*.js",
"README.*",
"LICENSE.*",
"CHANGELOG.*",
"CONTRIBUTING.*"
],
"npm-asset-main": "dist/fullcalendar.js",
"npm-asset-directories": [],
"npm-asset-repository": {
@ -983,7 +1047,7 @@
"npm-asset-scripts": {
"clean": "gulp clean",
"dist": "gulp dist",
"lint": "gulp lint",
"lint": "gulp lint-and-example-repos",
"test": "gulp test:single"
}
},
@ -1005,7 +1069,7 @@
"full-sized",
"jquery-plugin"
],
"time": "2018-03-05T03:30:23+00:00"
"time": "2019-01-11T02:39:12+00:00"
},
{
"name": "npm-asset/imagesloaded",
@ -1804,6 +1868,55 @@
],
"time": "2016-08-06T20:24:11+00:00"
},
{
"name": "psr/container",
"version": "1.0.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"time": "2017-02-14T16:28:37+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
@ -1854,6 +1967,53 @@
],
"time": "2016-08-06T14:39:51+00:00"
},
{
"name": "psr/log",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
"reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for logging libraries",
"homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
"time": "2018-11-20T15:27:04+00:00"
},
{
"name": "seld/cli-prompt",
"version": "1.0.3",
@ -2525,6 +2685,7 @@
"testing",
"xunit"
],
"abandoned": true,
"time": "2016-12-02T14:39:14+00:00"
},
{
@ -2915,6 +3076,7 @@
"mock",
"xunit"
],
"abandoned": true,
"time": "2017-06-30T09:13:00+00:00"
},
{
@ -3018,7 +3180,7 @@
}
],
"description": "Provides the functionality to compare PHP values for equality",
"homepage": "https://github.com/sebastianbergmann/comparator",
"homepage": "http://www.github.com/sebastianbergmann/comparator",
"keywords": [
"comparator",
"compare",
@ -3120,7 +3282,7 @@
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
"homepage": "https://github.com/sebastianbergmann/environment",
"homepage": "http://www.github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
@ -3188,7 +3350,7 @@
}
],
"description": "Provides the functionality to export PHP variables for visualization",
"homepage": "https://github.com/sebastianbergmann/exporter",
"homepage": "http://www.github.com/sebastianbergmann/exporter",
"keywords": [
"export",
"exporter"
@ -3240,7 +3402,7 @@
}
],
"description": "Snapshotting of global state",
"homepage": "https://github.com/sebastianbergmann/global-state",
"homepage": "http://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
@ -3342,7 +3504,7 @@
}
],
"description": "Provides functionality to recursively process PHP variables",
"homepage": "https://github.com/sebastianbergmann/recursion-context",
"homepage": "http://www.github.com/sebastianbergmann/recursion-context",
"time": "2016-11-19T07:33:16+00:00"
},
{
@ -3607,10 +3769,17 @@
"prefer-lowest": false,
"platform": {
"php": ">=5.6.1",
"ext-ctype": "*",
"ext-curl": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-openssl": "*",
"ext-simplexml": "*",
"ext-xml": "*"
},
"platform-dev": []

View file

@ -34,7 +34,7 @@
use Friendica\Database\DBA;
if (!defined('DB_UPDATE_VERSION')) {
define('DB_UPDATE_VERSION', 1293);
define('DB_UPDATE_VERSION', 1304);
}
return [
@ -99,6 +99,8 @@ return [
"allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed groups"],
"deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"],
"deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied groups"],
"backend-class" => ["type" => "tinytext", "comment" => "Storage backend class"],
"backend-ref" => ["type" => "text", "comment" => "Storage backend data reference"],
],
"indexes" => [
"PRIMARY" => ["id"],
@ -707,6 +709,8 @@ return [
"iid" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "relation" => ["item" => "id"], "comment" => "Item id"],
"postopts" => ["type" => "text", "comment" => "External post connectors add their network name to this comma-separated string to identify that they should be delivered to these networks during delivery"],
"inform" => ["type" => "mediumtext", "comment" => "Additional receivers of the linked item"],
"queue_count" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Initial number of delivery recipients, used as item.delivery_queue_count"],
"queue_done" => ["type" => "mediumint", "not null" => "1", "default" => "0", "comment" => "Number of successful deliveries, used as item.delivery_queue_done"],
],
"indexes" => [
"PRIMARY" => ["iid"],
@ -955,6 +959,9 @@ return [
"allow_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of allowed groups"],
"deny_cid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied contact.id"],
"deny_gid" => ["type" => "mediumtext", "comment" => "Access Control - list of denied groups"],
"backend-class" => ["type" => "tinytext", "comment" => "Storage backend class"],
"backend-ref" => ["type" => "text", "comment" => "Storage backend data reference"],
"updated" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => ""]
],
"indexes" => [
"PRIMARY" => ["id"],
@ -1359,7 +1366,7 @@ return [
"comment" => "Background tasks queue entries",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Auto incremented worker task id"],
"parameter" => ["type" => "mediumblob", "comment" => "Task command"],
"parameter" => ["type" => "mediumtext", "comment" => "Task command"],
"priority" => ["type" => "tinyint unsigned", "not null" => "1", "default" => "0", "comment" => "Task priority"],
"created" => ["type" => "datetime", "not null" => "1", "default" => DBA::NULL_DATETIME, "comment" => "Creation date"],
"pid" => ["type" => "int unsigned", "not null" => "1", "default" => "0", "comment" => "Process id of the worker"],
@ -1370,13 +1377,23 @@ return [
],
"indexes" => [
"PRIMARY" => ["id"],
"pid" => ["pid"],
"parameter" => ["parameter(64)"],
"priority_created_next_try" => ["priority", "created", "next_try"],
"done_priority_executed_next_try" => ["done", "priority", "executed", "next_try"],
"done_executed_next_try" => ["done", "executed", "next_try"],
"done_parameter" => ["done", "parameter(64)"],
"done_executed" => ["done", "executed"],
"done_priority_created" => ["done", "priority", "created"],
"done_priority_next_try" => ["done", "priority", "next_try"],
"done_next_try" => ["done", "next_try"]
"done_pid_next_try" => ["done", "pid", "next_try"],
"done_pid_priority_created" => ["done", "pid", "priority", "created"]
]
],
"storage" => [
"comment" => "Data stored by Database storage backend",
"fields" => [
"id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1", "comment" => "Auto incremented image data id"],
"data" => ["type" => "longblob", "not null" => "1", "comment" => "file data"]
],
"indexes" => [
"PRIMARY" => ["id"]
]
]
];

View file

@ -135,6 +135,15 @@ return [
// Disables the check if a mail address is in a valid format and can be resolved via DNS.
'disable_email_validation' => false,
// disable_implicit_mentions (Boolean) since 2019.03
// Implicit mentions are mentions in the body of replies that are redundant in a thread-enabled system like Friendica.
// This config key disables the gathering of implicit mentions in incoming and outgoing posts.
// Also disables the default automatic removal of implicit mentions from the body of incoming posts.
// Also disables the default automatic addition of implicit mentions in the body of outgoing posts.
// Disabling implicit mentions also affects the "explicit_mentions" additional feature by limiting it
// to the replied-to post author mention in the comment boxes.
'disable_implicit_mentions' => false,
// disable_url_validation (Boolean)
// Disables the DNS lookup of an URL.
'disable_url_validation' => false,
@ -393,6 +402,14 @@ return [
// Number of worker tasks that are fetched in a single query.
'worker_fetch_limit' => 1,
// worker_jpm (Boolean)
// If enabled, it prints out the jobs per minute.
'worker_jpm' => false,
// worker_jpm_range (String)
// List of minutes for the jobs per minute (JPM) calculation
'worker_jpm_range' => '1, 10, 60',
// worker_load_exponent (Integer)
// Default 3, which allows only 25% of the maximum worker queues when server load reaches around 37% of maximum load.
// For a linear response where 25% of worker queues are allowed at 75% of maximum load, set this to 1.
@ -421,4 +438,13 @@ return [
// Must be writable by the ejabberd process. if set then it will prevent the running of multiple processes.
'lockpath' => '',
],
'debug' => [
// ap_inbox_log (Boolean)
// Logs every call to /inbox as a JSON file in Friendica's temporary directory
'ap_inbox_log' => false,
// total_ap_delivery (Boolean)
// Deliver via AP to every possible receiver and we suppress the delivery to these contacts with other protocols
'total_ap_delivery' => false,
]
];

View file

@ -34,7 +34,7 @@ return [
'config' => [
'admin_email' => '',
'sitename' => 'Friendica Social Network',
'register_policy' => REGISTER_OPEN,
'register_policy' => \Friendica\Module\Register::OPEN,
'register_text' => '',
],
'system' => [

View file

@ -16,10 +16,11 @@ return [
'info' => '',
// register_policy (Constant)
// Your choices are REGISTER_OPEN, REGISTER_APPROVE, or REGISTER_CLOSED.
// Be certain to create your own personal account before setting REGISTER_CLOSED.
// REGISTER_APPROVE requires you set system.admin_email to the email address of an already registered person who can authorize and/or approve/deny the request.
'register_policy' => REGISTER_CLOSED,
// Your choices are OPEN, APPROVE, or CLOSED.
// Be certain to create your own personal account before setting CLOSED.
// APPROVE requires you set system.admin_email to the email address of an
// already registered person who can authorize and/or approve/deny the request.
'register_policy' => \Friendica\Module\Register::CLOSED,
// register_text (String)
// Will be displayed prominently on the registration page.
@ -43,6 +44,10 @@ return [
// Themes users can change to in their settings.
'allowed_themes' => 'quattro,vier,duepuntozero,smoothly',
// debugging (boolean)
// Enable/Disable Debugging (logging)
'debugging' => false,
// default_timezone (String)
// Choose a default timezone. See https://secure.php.net/manual/en/timezones.php
// It only applies to timestamps for anonymous viewers.
@ -66,6 +71,16 @@ return [
// Two-letters ISO 639-1 code.
'language' => 'en',
// logfile (String)
// The logfile for storing logs.
// Can be a full path or a relative path to the Friendica home directory
'logfile' => 'friendica.log',
// loglevel (String)
// The loglevel for all logs.
// Has to be one of these values: emergency, alert, critical, error, warning, notice, info, debug
'loglevel' => 'notice',
// max_image_length (Integer)
// An alternate way of limiting picture upload sizes.
// Specify the maximum pixel length that pictures are allowed to be (for non-square pictures, it will apply to the longest side).
@ -87,6 +102,10 @@ return [
// 0 to use internal default (100MB)
'optimize_max_tablesize' => -1,
// maxloadavg (Integer)
// Maximum system load before delivery and poll processes are deferred.
'maxloadavg' => 20,
// rino_encrypt (Integer)
// Server-to-server private message encryption (RINO).
// Encryption will only be provided if this setting is set to a non zero value on both servers.

View file

@ -1,6 +1,6 @@
-- ------------------------------------------
-- Friendica 2019.01-rc (The Tazmans Flax-lily)
-- DB_UPDATE_VERSION 1293
-- Friendica 2019.03-dev (The Tazmans Flax-lily)
-- DB_UPDATE_VERSION 1300
-- ------------------------------------------
@ -64,6 +64,8 @@ CREATE TABLE IF NOT EXISTS `attach` (
`allow_gid` mediumtext COMMENT 'Access Control - list of allowed groups',
`deny_cid` mediumtext COMMENT 'Access Control - list of denied contact.id',
`deny_gid` mediumtext COMMENT 'Access Control - list of denied groups',
`backend-class` tinytext COMMENT 'Storage backend class',
`backend-ref` text COMMENT 'Storage backend data reference',
PRIMARY KEY(`id`)
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='file attachments';
@ -641,6 +643,8 @@ CREATE TABLE IF NOT EXISTS `item-delivery-data` (
`iid` int unsigned NOT NULL COMMENT 'Item id',
`postopts` text COMMENT 'External post connectors add their network name to this comma-separated string to identify that they should be delivered to these networks during delivery',
`inform` mediumtext COMMENT 'Additional receivers of the linked item',
`queue_count` mediumint NOT NULL DEFAULT 0 COMMENT 'Initial number of delivery recipients, used as item.delivery_queue_count',
`queue_done` mediumint NOT NULL DEFAULT 0 COMMENT 'Number of successful deliveries, used as item.delivery_queue_done',
PRIMARY KEY(`iid`)
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Delivery data for items';
@ -873,6 +877,9 @@ CREATE TABLE IF NOT EXISTS `photo` (
`allow_gid` mediumtext COMMENT 'Access Control - list of allowed groups',
`deny_cid` mediumtext COMMENT 'Access Control - list of denied contact.id',
`deny_gid` mediumtext COMMENT 'Access Control - list of denied groups',
`backend-class` tinytext COMMENT 'Storage backend class',
`backend-ref` text COMMENT 'Storage backend data reference',
`updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'edited timestamp',
PRIMARY KEY(`id`),
INDEX `contactid` (`contact-id`),
INDEX `uid_contactid` (`uid`,`contact-id`),
@ -1254,7 +1261,7 @@ CREATE TABLE IF NOT EXISTS `worker-ipc` (
--
CREATE TABLE IF NOT EXISTS `workerqueue` (
`id` int unsigned NOT NULL auto_increment COMMENT 'Auto incremented worker task id',
`parameter` mediumblob COMMENT 'Task command',
`parameter` mediumtext COMMENT 'Task command',
`priority` tinyint unsigned NOT NULL DEFAULT 0 COMMENT 'Task priority',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'Creation date',
`pid` int unsigned NOT NULL DEFAULT 0 COMMENT 'Process id of the worker',
@ -1272,4 +1279,13 @@ CREATE TABLE IF NOT EXISTS `workerqueue` (
INDEX `done_next_try` (`done`,`next_try`)
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Background tasks queue entries';
--
-- TABLE storage
--
CREATE TABLE IF NOT EXISTS `storage` (
`id` int unsigned NOT NULL auto_increment COMMENT 'Auto incremented image data id',
`data` longblob NOT NULL COMMENT 'file data',
PRIMARY KEY(`id`)
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Data stored by Database storage backend';

204
doc/AddonStorageBackend.md Normal file
View file

@ -0,0 +1,204 @@
Friendica Storage Backend Addon development
===========================================
* [Home](help)
Storage backends can be added via addons.
A storage backend is implemented as a class, and the plugin register the class to make it avaiable to the system.
## The Storage Backend Class
The class must live in `Friendica\Addon\youraddonname` namespace, where `youraddonname` the folder name of your addon.
The class must implement `Friendica\Model\Storage\IStorage` interface. All method in the interface must be implemented:
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);
}
```
- `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`
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.
The array returned by `getOptions()` is defined as:
[
'option1name' => [ ..info.. ],
'option2name' => [ ..info.. ],
...
]
An empty array can be returned if backend doesn't have any options.
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'
'label',
Translatable label of the field. This label will be shown in admin page
value,
Current value of the option
'help text',
Translatable description for the field. Will be shown in admin page
extra data
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
];
See doxygen documentation of `IStorage` interface for details about each method.
## Register a storage backend class
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.
When the plugin is uninstalled, registered backends must be unregistered using
`Friendica\Core\StorageManager::unregister($class)`.
## Example
Here an hypotetical addon which register an unusefull storage backend.
Let's call it `samplestorage`.
This backend will discard all data we try to save and will return always the same image when we ask for some data.
The image returned can be set by the administrator in admin page.
First, the backend class.
The file will be `addon/samplestorage/SampleStorageBackend.php`:
```php
<?php
namespace Friendica\Addon\samplestorage;
use Friendica\Model\Storage\IStorage;
use Friendica\Core\Config;
use Friendica\Core\L10n;
class SampleStorageBackend implements IStorage
{
public static function get($ref)
{
// we return alwais the same image data. Which file we load is defined by
// a config key
$filename = Config::get("storage", "samplestorage", "sample.jpg");
return file_get_contents($filename);
}
public static function put($data, $ref = "")
{
if ($ref === "") {
$ref = "sample";
}
// we don't save $data !
return $ref;
}
public static function delete($ref)
{
// we pretend to delete the data
return true;
}
public static function getOptions()
{
$filename = Config::get("storage", "samplestorage", "sample.jpg");
return [
"filename" => [
"input", // will use a simple text input
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..
];
}
public static function saveOptions($data)
{
// the keys in $data are the same keys we defined in getOptions()
$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"];
}
Config::set("storage", "samplestorage", $newfilename);
// no errors, return empty array
return [];
}
}
```
Now the plugin main file. Here we register and unregister the backend class.
The file is `addon/samplestorage/samplestorage.php`
```php
<?php
/**
* Name: Sample Storage Addon
* Description: A sample addon which implements an unusefull storage backend
* Version: 1.0.0
* Author: Alice <https://alice.social/~alice>
*/
use Friendica\Core\StorageManager;
use Friendica\Addon\samplestorage\SampleStorageBackend;
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);
}
function samplestorage_unistall()
{
// when the plugin is uninstalled, we unregister the backend.
StorageManager::unregister("Sample Storage");
}
```

View file

@ -32,7 +32,7 @@ It will be displayed in the admin panel and should include some further informat
Register your addon hooks during installation.
Addon::registerHook($hookname, $file, $function);
\Friendica\Core\Hook::register($hookname, $file, $function);
$hookname is a string and corresponds to a known Friendica PHP hook.
@ -74,7 +74,7 @@ If your addon requires adding a stylesheet on all pages of Friendica, add the fo
```php
function <addon>_install()
{
Addon::registerHook('head', __FILE__, '<addon>_head');
\Friendica\Core\Hook::register('head', __FILE__, '<addon>_head');
...
}
@ -97,7 +97,7 @@ If your addon requires adding a script on all pages of Friendica, add the follow
```php
function <addon>_install()
{
Addon::registerHook('footer', __FILE__, '<addon>_footer');
\Friendica\Core\Hook::register('footer', __FILE__, '<addon>_footer');
...
}
@ -417,281 +417,281 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
### index.php
Addon::callHooks('init_1');
Addon::callHooks('app_menu', $arr);
Addon::callHooks('page_content_top', $a->page['content']);
Addon::callHooks($a->module.'_mod_init', $placeholder);
Addon::callHooks($a->module.'_mod_init', $placeholder);
Addon::callHooks($a->module.'_mod_post', $_POST);
Addon::callHooks($a->module.'_mod_afterpost', $placeholder);
Addon::callHooks($a->module.'_mod_content', $arr);
Addon::callHooks($a->module.'_mod_aftercontent', $arr);
Addon::callHooks('page_end', $a->page['content']);
Hook::callAll('init_1');
Hook::callAll('app_menu', $arr);
Hook::callAll('page_content_top', $a->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']);
### include/api.php
Addon::callHooks('logged_in', $a->user);
Addon::callHooks('authenticate', $addon_auth);
Addon::callHooks('logged_in', $a->user);
Hook::callAll('logged_in', $a->user);
Hook::callAll('authenticate', $addon_auth);
Hook::callAll('logged_in', $a->user);
### include/enotify.php
Addon::callHooks('enotify', $h);
Addon::callHooks('enotify_store', $datarray);
Addon::callHooks('enotify_mail', $datarray);
Addon::callHooks('check_item_notification', $notification_data);
Hook::callAll('enotify', $h);
Hook::callAll('enotify_store', $datarray);
Hook::callAll('enotify_mail', $datarray);
Hook::callAll('check_item_notification', $notification_data);
### include/conversation.php
Addon::callHooks('conversation_start', $cb);
Addon::callHooks('render_location', $locate);
Addon::callHooks('display_item', $arr);
Addon::callHooks('display_item', $arr);
Addon::callHooks('item_photo_menu', $args);
Addon::callHooks('jot_tool', $jotplugins);
Hook::callAll('conversation_start', $cb);
Hook::callAll('render_location', $locate);
Hook::callAll('display_item', $arr);
Hook::callAll('display_item', $arr);
Hook::callAll('item_photo_menu', $args);
Hook::callAll('jot_tool', $jotplugins);
### include/text.php
Addon::callHooks('contact_block_end', $arr);
Addon::callHooks('poke_verbs', $arr);
Addon::callHooks('put_item_in_cache', $hook_data);
Addon::callHooks('prepare_body_init', $item);
Addon::callHooks('prepare_body_content_filter', $hook_data);
Addon::callHooks('prepare_body', $hook_data);
Addon::callHooks('prepare_body_final', $hook_data);
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
Addon::callHooks('page_info_data', $data);
Hook::callAll('page_info_data', $data);
### mod/directory.php
Addon::callHooks('directory_item', $arr);
Hook::callAll('directory_item', $arr);
### mod/xrd.php
Addon::callHooks('personal_xrd', $arr);
Hook::callAll('personal_xrd', $arr);
### mod/ping.php
Addon::callHooks('network_ping', $arr);
Hook::callAll('network_ping', $arr);
### mod/parse_url.php
Addon::callHooks("parse_link", $arr);
Hook::callAll("parse_link", $arr);
### mod/manage.php
Addon::callHooks('home_init', $ret);
Hook::callAll('home_init', $ret);
### mod/acl.php
Addon::callHooks('acl_lookup_end', $results);
Hook::callAll('acl_lookup_end', $results);
### mod/network.php
Addon::callHooks('network_content_init', $arr);
Addon::callHooks('network_tabs', $arr);
Hook::callAll('network_content_init', $arr);
Hook::callAll('network_tabs', $arr);
### mod/friendica.php
Addon::callHooks('about_hook', $o);
Hook::callAll('about_hook', $o);
### mod/subthread.php
Addon::callHooks('post_local_end', $arr);
Hook::callAll('post_local_end', $arr);
### mod/profiles.php
Addon::callHooks('profile_post', $_POST);
Addon::callHooks('profile_edit', $arr);
Hook::callAll('profile_post', $_POST);
Hook::callAll('profile_edit', $arr);
### mod/settings.php
Addon::callHooks('addon_settings_post', $_POST);
Addon::callHooks('connector_settings_post', $_POST);
Addon::callHooks('display_settings_post', $_POST);
Addon::callHooks('settings_post', $_POST);
Addon::callHooks('addon_settings', $settings_addons);
Addon::callHooks('connector_settings', $settings_connectors);
Addon::callHooks('display_settings', $o);
Addon::callHooks('settings_form', $o);
Hook::callAll('addon_settings_post', $_POST);
Hook::callAll('connector_settings_post', $_POST);
Hook::callAll('display_settings_post', $_POST);
Hook::callAll('settings_post', $_POST);
Hook::callAll('addon_settings', $settings_addons);
Hook::callAll('connector_settings', $settings_connectors);
Hook::callAll('display_settings', $o);
Hook::callAll('settings_form', $o);
### mod/photos.php
Addon::callHooks('photo_post_init', $_POST);
Addon::callHooks('photo_post_file', $ret);
Addon::callHooks('photo_post_end', $foo);
Addon::callHooks('photo_post_end', $foo);
Addon::callHooks('photo_post_end', $foo);
Addon::callHooks('photo_post_end', $foo);
Addon::callHooks('photo_post_end', intval($item_id));
Addon::callHooks('photo_upload_form', $ret);
Hook::callAll('photo_post_init', $_POST);
Hook::callAll('photo_post_file', $ret);
Hook::callAll('photo_post_end', $foo);
Hook::callAll('photo_post_end', $foo);
Hook::callAll('photo_post_end', $foo);
Hook::callAll('photo_post_end', $foo);
Hook::callAll('photo_post_end', intval($item_id));
Hook::callAll('photo_upload_form', $ret);
### mod/profile.php
Addon::callHooks('profile_advanced', $o);
Hook::callAll('profile_advanced', $o);
### mod/home.php
Addon::callHooks('home_init', $ret);
Addon::callHooks("home_content", $content);
Hook::callAll('home_init', $ret);
Hook::callAll("home_content", $content);
### mod/poke.php
Addon::callHooks('post_local_end', $arr);
Hook::callAll('post_local_end', $arr);
### mod/contacts.php
Addon::callHooks('contact_edit_post', $_POST);
Addon::callHooks('contact_edit', $arr);
Hook::callAll('contact_edit_post', $_POST);
Hook::callAll('contact_edit', $arr);
### mod/tagger.php
Addon::callHooks('post_local_end', $arr);
Hook::callAll('post_local_end', $arr);
### mod/lockview.php
Addon::callHooks('lockview_content', $item);
Hook::callAll('lockview_content', $item);
### mod/uexport.php
Addon::callHooks('uexport_options', $options);
Hook::callAll('uexport_options', $options);
### mod/register.php
Addon::callHooks('register_post', $arr);
Addon::callHooks('register_form', $arr);
Hook::callAll('register_post', $arr);
Hook::callAll('register_form', $arr);
### mod/item.php
Addon::callHooks('post_local_start', $_REQUEST);
Addon::callHooks('post_local', $datarray);
Addon::callHooks('post_local_end', $datarray);
Hook::callAll('post_local_start', $_REQUEST);
Hook::callAll('post_local', $datarray);
Hook::callAll('post_local_end', $datarray);
### mod/editpost.php
Addon::callHooks('jot_tool', $jotplugins);
Hook::callAll('jot_tool', $jotplugins);
### src/Network/FKOAuth1.php
Addon::callHooks('logged_in', $a->user);
Hook::callAll('logged_in', $a->user);
### src/Render/FriendicaSmartyEngine.php
Addon::callHooks("template_vars", $arr);
Hook::callAll("template_vars", $arr);
### src/App.php
Addon::callHooks('load_config');
Addon::callHooks('head');
Addon::callHooks('footer');
Hook::callAll('load_config');
Hook::callAll('head');
Hook::callAll('footer');
### src/Model/Item.php
Addon::callHooks('post_local', $item);
Addon::callHooks('post_remote', $item);
Addon::callHooks('post_local_end', $posted_item);
Addon::callHooks('post_remote_end', $posted_item);
Addon::callHooks('tagged', $arr);
Addon::callHooks('post_local_end', $new_item);
Hook::callAll('post_local', $item);
Hook::callAll('post_remote', $item);
Hook::callAll('post_local_end', $posted_item);
Hook::callAll('post_remote_end', $posted_item);
Hook::callAll('tagged', $arr);
Hook::callAll('post_local_end', $new_item);
### src/Model/Contact.php
Addon::callHooks('contact_photo_menu', $args);
Addon::callHooks('follow', $arr);
Hook::callAll('contact_photo_menu', $args);
Hook::callAll('follow', $arr);
### src/Model/Profile.php
Addon::callHooks('profile_sidebar_enter', $profile);
Addon::callHooks('profile_sidebar', $arr);
Addon::callHooks('profile_tabs', $arr);
Addon::callHooks('zrl_init', $arr);
Addon::callHooks('magic_auth_success', $arr);
Hook::callAll('profile_sidebar_enter', $profile);
Hook::callAll('profile_sidebar', $arr);
Hook::callAll('profile_tabs', $arr);
Hook::callAll('zrl_init', $arr);
Hook::callAll('magic_auth_success', $arr);
### src/Model/Event.php
Addon::callHooks('event_updated', $event['id']);
Addon::callHooks("event_created", $event['id']);
Hook::callAll('event_updated', $event['id']);
Hook::callAll("event_created", $event['id']);
### src/Model/User.php
Addon::callHooks('register_account', $uid);
Addon::callHooks('remove_user', $user);
Hook::callAll('register_account', $uid);
Hook::callAll('remove_user', $user);
### src/Content/Text/BBCode.php
Addon::callHooks('bbcode', $text);
Addon::callHooks('bb2diaspora', $text);
Hook::callAll('bbcode', $text);
Hook::callAll('bb2diaspora', $text);
### src/Content/Text/HTML.php
Addon::callHooks('html2bbcode', $message);
Hook::callAll('html2bbcode', $message);
### src/Content/Smilies.php
Addon::callHooks('smilie', $params);
Hook::callAll('smilie', $params);
### src/Content/Feature.php
Addon::callHooks('isEnabled', $arr);
Addon::callHooks('get', $arr);
Hook::callAll('isEnabled', $arr);
Hook::callAll('get', $arr);
### src/Content/ContactSelector.php
Addon::callHooks('network_to_name', $nets);
Addon::callHooks('gender_selector', $select);
Addon::callHooks('sexpref_selector', $select);
Addon::callHooks('marital_selector', $select);
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
Addon::callHooks('oembed_fetch_url', $embedurl, $j);
Hook::callAll('oembed_fetch_url', $embedurl, $j);
### src/Content/Nav.php
Addon::callHooks('page_header', $a->page['nav']);
Addon::callHooks('nav_info', $nav);
Hook::callAll('page_header', $a->page['nav']);
Hook::callAll('nav_info', $nav);
### src/Worker/Directory.php
Addon::callHooks('globaldir_update', $arr);
Hook::callAll('globaldir_update', $arr);
### src/Worker/Notifier.php
Addon::callHooks('notifier_end', $target_item);
Hook::callAll('notifier_end', $target_item);
### src/Worker/Queue.php
Addon::callHooks('queue_predeliver', $r);
Addon::callHooks('queue_deliver', $params);
Hook::callAll('queue_predeliver', $r);
Hook::callAll('queue_deliver', $params);
### src/Module/Login.php
Addon::callHooks('authenticate', $addon_auth);
Addon::callHooks('login_hook', $o);
Hook::callAll('authenticate', $addon_auth);
Hook::callAll('login_hook', $o);
### src/Module/Logout.php
Addon::callHooks("logging_out");
Hook::callAll("logging_out");
### src/Object/Post.php
Addon::callHooks('render_location', $locate);
Addon::callHooks('display_item', $arr);
Hook::callAll('render_location', $locate);
Hook::callAll('display_item', $arr);
### src/Core/ACL.php
Addon::callHooks('contact_select_options', $x);
Addon::callHooks($a->module.'_pre_'.$selname, $arr);
Addon::callHooks($a->module.'_post_'.$selname, $o);
Addon::callHooks($a->module.'_pre_'.$selname, $arr);
Addon::callHooks($a->module.'_post_'.$selname, $o);
Addon::callHooks('jot_networks', $jotnets);
Hook::callAll('contact_select_options', $x);
Hook::callAll($a->module.'_pre_'.$selname, $arr);
Hook::callAll($a->module.'_post_'.$selname, $o);
Hook::callAll($a->module.'_pre_'.$selname, $arr);
Hook::callAll($a->module.'_post_'.$selname, $o);
Hook::callAll('jot_networks', $jotnets);
### src/Core/Authentication.php
Addon::callHooks('logged_in', $a->user);
Hook::callAll('logged_in', $a->user);
### src/Core/Hook.php
@ -699,31 +699,31 @@ Here is a complete list of all hook callbacks with file locations (as of 24-Sep-
### src/Core/Worker.php
Addon::callHooks("proc_run", $arr);
Hook::callAll("proc_run", $arr);
### src/Util/Emailer.php
Addon::callHooks('emailer_send_prepare', $params);
Addon::callHooks("emailer_send", $hookdata);
Hook::callAll('emailer_send_prepare', $params);
Hook::callAll("emailer_send", $hookdata);
### src/Util/Map.php
Addon::callHooks('generate_map', $arr);
Addon::callHooks('generate_named_map', $arr);
Addon::callHooks('Map::getCoordinates', $arr);
Hook::callAll('generate_map', $arr);
Hook::callAll('generate_named_map', $arr);
Hook::callAll('Map::getCoordinates', $arr);
### src/Util/Network.php
Addon::callHooks('avatar_lookup', $avatar);
Hook::callAll('avatar_lookup', $avatar);
### src/Util/ParseUrl.php
Addon::callHooks("getsiteinfo", $siteinfo);
Hook::callAll("getsiteinfo", $siteinfo);
### src/Protocol/DFRN.php
Addon::callHooks('atom_feed_end', $atom);
Addon::callHooks('atom_feed_end', $atom);
Hook::callAll('atom_feed_end', $atom);
Hook::callAll('atom_feed_end', $atom);
### view/js/main.js

View file

@ -68,6 +68,10 @@ table.bbcodes > * > tr > th {
<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>
</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>
</tr>
<tr>
<td>[img=64x32]https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg[/img]<br>
<br>Note: provided height is simply discarded.</td>

View file

@ -142,7 +142,7 @@ $a->config['register_policy'] = REGISTER_CLOSED;
</pre></td>
<td><pre>
'config' => [
'register_policty' => REGISTER_CLOSED,
'register_policy' => \Friendica\Module\Register::CLOSED,
],
</pre></td>
</tr>
@ -242,7 +242,7 @@ register_policty = REGISTER_CLOSED
</pre></td>
<td><pre>
'config' => [
'register_policty' => REGISTER_CLOSED,
'register_policy' => \Friendica\Module\Register::CLOSED,
],
</pre></td>
</tr>

View file

@ -8,6 +8,7 @@ User
* **[Why do I getting warnings about certificates?](help/FAQ#ssl)**
* **[How can I upload images, files, links, videos and sound files to posts?](help/FAQ#upload)**
* **[Is it possible to have different avatars per profile?](help/FAQ#avatars)**
* **[How can I view Friendica in a certain language?](help/FAQ#language)**
* **[What is the difference between blocked|ignored|archived|hidden contacts?](help/FAQ#contacts)**
* **[What happens when an account is removed? Is it truly deleted?](help/FAQ#removed)**
* **[Can I subscribe to a hashtag?](help/FAQ#hashtag)**
@ -75,6 +76,33 @@ On your Edit/Manage Profiles page, you will find a "change profile photo" link.
Clicking this will take you to a page where you can upload a photograph and select which profile it will be associated with.
To avoid privacy leakage, we only display the photograph associated with your default profile as the avatar in your posts.
<a name="language"></a>
### How can I view Friendica in a certain language?
You can do this by adding the `lang` parameter to the url in your url bar.
The data in the parameter is a [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code.
A question mark is required for the separation between url and parameters.
Example:
https://social.example.com/profile/example
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>
### What is the difference between blocked|ignored|archived|hidden contacts?
@ -144,7 +172,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://gitlab.com/tom79/mastalab) (available in F-Droid and Google stores)
* [DiCa](https://dica.mixi.cool/)
* AndStatus
* Twidere
* Mustard and Mustard-Mod

View file

@ -47,6 +47,7 @@ Friendica Documentation and Resources
* [Addon Development](help/Addons)
* [Theme Development](help/themes)
* [Smarty 3 Templates](help/smarty3-templates)
* [Storage backend addon](help/AddonStorageBackend)
* How To
* [Translate Friendica](help/translations)
* [Use Composer](help/Composer)

View file

@ -18,10 +18,8 @@ If you do not have a Friendica account yet, you can register a temporary one at
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.
Put some thought into this.
While changing it after installation is supported, things still might break.
Requirements
---
@ -57,7 +55,7 @@ The Linux commands to clone the repository into a directory "mywebsite" would be
git clone https://github.com/friendica/friendica.git -b master 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`

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

@ -101,6 +101,32 @@ Default is false.
### File upload
#### File storage backend
Set the backend used by Friendica to store uploaded file data.
Two storage backends are avaiable with Friendica:
- **Database** : Data is stored in a dedicated table in database (`storage`)
- **Filesystem** : Data is stored as file on the filesystem.
More storage backends can be avaiable from third-party addons.
If you use those, please refer to the documentation of those addons for further information.
Default value is 'Database (legacy)': it's the legacy way used to store data directly in database.
Existing data can be moved to the current active backend using the ['storage move' console command](help/tools)
If selected backend has configurable options, new fields are shown here.
##### Filesystem: Storage base path
The base path where Filesystem storage backend saves data.
For maximum security, this path should be outside the folder tree served by the web server: this way files can't be downloaded bypassing the privacy checks.
Default value is `storage`, that is the `storage` folder in Friendica code root folder.
#### Maximum Image Size
Maximum size in bytes of uploaded images.

View file

@ -21,7 +21,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:
@ -69,4 +69,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.

View file

@ -379,6 +379,18 @@ Friendica doesn't allow showing the friends of other users.
* media: image data
#### Return values
Object of:
* media_id: a media identifier (integer)
* media_id_string: a media identifier (string)
* size: size in byte
* image.w: image width
* image.h: image height
* image.image_type: image mime type
* image.friendica_preview_url: image preview url
---
### oauth/request_token (*)
@ -642,9 +654,11 @@ Returned status object is conform to GNU Social/Twitter api.
Friendica adds some addictional fields:
- author: a user object, it's the author of the item. In case of a reshare for legacy reasons the "user" field doesn't show the real author. This field always contains the real author of a post.
- owner: a user object, it's the owner of the item.
- private: boolean, true if the item is marked as private
- activities: map with activities related to the item. Every activity is a list of user objects.
- comments: comment numbers
This properties are prefixed with "friendica_" in JSON responses and namespaced under "http://friendi.ca/schema/api/1/" in XML responses
@ -654,6 +668,9 @@ JSON:
[
{
// ...
'friendica_author' : {
// user object
},
'friendica_owner' : {
// user object
},
@ -669,7 +686,8 @@ JSON:
'attendyes': [],
'attendno': [],
'attendmaybe': []
}
},
'friendica_comments': 12
},
// ...
]
@ -695,6 +713,7 @@ XML:
<friendica:attendno/>
<friendica:attendmaybe/>
</friendica:activities>
<friendica:comments>21</friendica:comments>
</status>
<!-- ... -->
</statuses>
@ -744,6 +763,7 @@ Friendica doesn't allow showing followers of other users.
* count: alias for the rpp parameter
* since_id: returns statuses with ids greater than the given id
* max_id: returns statuses with ids lower or equal to the given id
* exclude_replies: don't show replies (default: false)
#### Unsupported parameters

View file

@ -26,7 +26,7 @@ Addons sollten einen Kommentarblock mit den folgenden vier Parametern enthalten:
Registriere deine Addon-Hooks während der Installation.
Addon::registerHook($hookname, $file, $function);
\Friendica\Core\Hook::register($hookname, $file, $function);
$hookname ist ein String und entspricht einem bekannten Friendica-Hook.
@ -193,299 +193,299 @@ Eine komplette Liste aller Hook-Callbacks mit den zugehörigen Dateien (am 01-Ap
### index.php
Addon::callHooks('init_1');
Addon::callHooks('app_menu', $arr);
Addon::callHooks('page_content_top', $a->page['content']);
Addon::callHooks($a->module.'_mod_init', $placeholder);
Addon::callHooks($a->module.'_mod_init', $placeholder);
Addon::callHooks($a->module.'_mod_post', $_POST);
Addon::callHooks($a->module.'_mod_afterpost', $placeholder);
Addon::callHooks($a->module.'_mod_content', $arr);
Addon::callHooks($a->module.'_mod_aftercontent', $arr);
Addon::callHooks('page_end', $a->page['content']);
Hook::callAll('init_1');
Hook::callAll('app_menu', $arr);
Hook::callAll('page_content_top', $a->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']);
### include/api.php
Addon::callHooks('logged_in', $a->user);
Addon::callHooks('authenticate', $addon_auth);
Addon::callHooks('logged_in', $a->user);
Hook::callAll('logged_in', $a->user);
Hook::callAll('authenticate', $addon_auth);
Hook::callAll('logged_in', $a->user);
### include/enotify.php
Addon::callHooks('enotify', $h);
Addon::callHooks('enotify_store', $datarray);
Addon::callHooks('enotify_mail', $datarray);
Addon::callHooks('check_item_notification', $notification_data);
Hook::callAll('enotify', $h);
Hook::callAll('enotify_store', $datarray);
Hook::callAll('enotify_mail', $datarray);
Hook::callAll('check_item_notification', $notification_data);
### include/conversation.php
Addon::callHooks('conversation_start', $cb);
Addon::callHooks('render_location', $locate);
Addon::callHooks('display_item', $arr);
Addon::callHooks('display_item', $arr);
Addon::callHooks('item_photo_menu', $args);
Addon::callHooks('jot_tool', $jotplugins);
Hook::callAll('conversation_start', $cb);
Hook::callAll('render_location', $locate);
Hook::callAll('display_item', $arr);
Hook::callAll('display_item', $arr);
Hook::callAll('item_photo_menu', $args);
Hook::callAll('jot_tool', $jotplugins);
### include/text.php
Addon::callHooks('contact_block_end', $arr);
Addon::callHooks('poke_verbs', $arr);
Addon::callHooks('put_item_in_cache', $hook_data);
Addon::callHooks('prepare_body_init', $item);
Addon::callHooks('prepare_body_content_filter', $hook_data);
Addon::callHooks('prepare_body', $hook_data);
Addon::callHooks('prepare_body_final', $hook_data);
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
Addon::callHooks('page_info_data', $data);
Hook::callAll('page_info_data', $data);
### mod/directory.php
Addon::callHooks('directory_item', $arr);
Hook::callAll('directory_item', $arr);
### mod/xrd.php
Addon::callHooks('personal_xrd', $arr);
Hook::callAll('personal_xrd', $arr);
### mod/ping.php
Addon::callHooks('network_ping', $arr);
Hook::callAll('network_ping', $arr);
### mod/parse_url.php
Addon::callHooks("parse_link", $arr);
Hook::callAll("parse_link", $arr);
### mod/manage.php
Addon::callHooks('home_init', $ret);
Hook::callAll('home_init', $ret);
### mod/acl.php
Addon::callHooks('acl_lookup_end', $results);
Hook::callAll('acl_lookup_end', $results);
### mod/network.php
Addon::callHooks('network_content_init', $arr);
Addon::callHooks('network_tabs', $arr);
Hook::callAll('network_content_init', $arr);
Hook::callAll('network_tabs', $arr);
### mod/friendica.php
Addon::callHooks('about_hook', $o);
Hook::callAll('about_hook', $o);
### mod/subthread.php
Addon::callHooks('post_local_end', $arr);
Hook::callAll('post_local_end', $arr);
### mod/profiles.php
Addon::callHooks('profile_post', $_POST);
Addon::callHooks('profile_edit', $arr);
Hook::callAll('profile_post', $_POST);
Hook::callAll('profile_edit', $arr);
### mod/settings.php
Addon::callHooks('addon_settings_post', $_POST);
Addon::callHooks('connector_settings_post', $_POST);
Addon::callHooks('display_settings_post', $_POST);
Addon::callHooks('settings_post', $_POST);
Addon::callHooks('addon_settings', $settings_addons);
Addon::callHooks('connector_settings', $settings_connectors);
Addon::callHooks('display_settings', $o);
Addon::callHooks('settings_form', $o);
Hook::callAll('addon_settings_post', $_POST);
Hook::callAll('connector_settings_post', $_POST);
Hook::callAll('display_settings_post', $_POST);
Hook::callAll('settings_post', $_POST);
Hook::callAll('addon_settings', $settings_addons);
Hook::callAll('connector_settings', $settings_connectors);
Hook::callAll('display_settings', $o);
Hook::callAll('settings_form', $o);
### mod/photos.php
Addon::callHooks('photo_post_init', $_POST);
Addon::callHooks('photo_post_file', $ret);
Addon::callHooks('photo_post_end', $foo);
Addon::callHooks('photo_post_end', $foo);
Addon::callHooks('photo_post_end', $foo);
Addon::callHooks('photo_post_end', $foo);
Addon::callHooks('photo_post_end', intval($item_id));
Addon::callHooks('photo_upload_form', $ret);
Hook::callAll('photo_post_init', $_POST);
Hook::callAll('photo_post_file', $ret);
Hook::callAll('photo_post_end', $foo);
Hook::callAll('photo_post_end', $foo);
Hook::callAll('photo_post_end', $foo);
Hook::callAll('photo_post_end', $foo);
Hook::callAll('photo_post_end', intval($item_id));
Hook::callAll('photo_upload_form', $ret);
### mod/profile.php
Addon::callHooks('profile_advanced', $o);
Hook::callAll('profile_advanced', $o);
### mod/home.php
Addon::callHooks('home_init', $ret);
Addon::callHooks("home_content", $content);
Hook::callAll('home_init', $ret);
Hook::callAll("home_content", $content);
### mod/poke.php
Addon::callHooks('post_local_end', $arr);
Hook::callAll('post_local_end', $arr);
### mod/contacts.php
Addon::callHooks('contact_edit_post', $_POST);
Addon::callHooks('contact_edit', $arr);
Hook::callAll('contact_edit_post', $_POST);
Hook::callAll('contact_edit', $arr);
### mod/tagger.php
Addon::callHooks('post_local_end', $arr);
Hook::callAll('post_local_end', $arr);
### mod/lockview.php
Addon::callHooks('lockview_content', $item);
Hook::callAll('lockview_content', $item);
### mod/uexport.php
Addon::callHooks('uexport_options', $options);
Hook::callAll('uexport_options', $options);
### mod/register.php
Addon::callHooks('register_post', $arr);
Addon::callHooks('register_form', $arr);
Hook::callAll('register_post', $arr);
Hook::callAll('register_form', $arr);
### mod/item.php
Addon::callHooks('post_local_start', $_REQUEST);
Addon::callHooks('post_local', $datarray);
Addon::callHooks('post_local_end', $datarray);
Hook::callAll('post_local_start', $_REQUEST);
Hook::callAll('post_local', $datarray);
Hook::callAll('post_local_end', $datarray);
### mod/editpost.php
Addon::callHooks('jot_tool', $jotplugins);
Hook::callAll('jot_tool', $jotplugins);
### src/Network/FKOAuth1.php
Addon::callHooks('logged_in', $a->user);
Hook::callAll('logged_in', $a->user);
### src/Render/FriendicaSmartyEngine.php
Addon::callHooks("template_vars", $arr);
Hook::callAll("template_vars", $arr);
### src/Model/Item.php
Addon::callHooks('post_local', $item);
Addon::callHooks('post_remote', $item);
Addon::callHooks('post_local_end', $posted_item);
Addon::callHooks('post_remote_end', $posted_item);
Addon::callHooks('tagged', $arr);
Addon::callHooks('post_local_end', $new_item);
Hook::callAll('post_local', $item);
Hook::callAll('post_remote', $item);
Hook::callAll('post_local_end', $posted_item);
Hook::callAll('post_remote_end', $posted_item);
Hook::callAll('tagged', $arr);
Hook::callAll('post_local_end', $new_item);
### src/Model/Contact.php
Addon::callHooks('contact_photo_menu', $args);
Addon::callHooks('follow', $arr);
Hook::callAll('contact_photo_menu', $args);
Hook::callAll('follow', $arr);
### src/Model/Profile.php
Addon::callHooks('profile_sidebar_enter', $profile);
Addon::callHooks('profile_sidebar', $arr);
Addon::callHooks('profile_tabs', $arr);
Addon::callHooks('zrl_init', $arr);
Hook::callAll('profile_sidebar_enter', $profile);
Hook::callAll('profile_sidebar', $arr);
Hook::callAll('profile_tabs', $arr);
Hook::callAll('zrl_init', $arr);
### src/Model/Event.php
Addon::callHooks('event_updated', $event['id']);
Addon::callHooks("event_created", $event['id']);
Hook::callAll('event_updated', $event['id']);
Hook::callAll("event_created", $event['id']);
### src/Model/User.php
Addon::callHooks('register_account', $uid);
Addon::callHooks('remove_user', $user);
Hook::callAll('register_account', $uid);
Hook::callAll('remove_user', $user);
### src/Content/Text/BBCode.php
Addon::callHooks('bbcode', $text);
Addon::callHooks('bb2diaspora', $text);
Hook::callAll('bbcode', $text);
Hook::callAll('bb2diaspora', $text);
### src/Content/Text/HTML.php
Addon::callHooks('html2bbcode', $message);
Hook::callAll('html2bbcode', $message);
### src/Content/Smilies.php
Addon::callHooks('smilie', $params);
Hook::callAll('smilie', $params);
### src/Content/Feature.php
Addon::callHooks('isEnabled', $arr);
Addon::callHooks('get', $arr);
Hook::callAll('isEnabled', $arr);
Hook::callAll('get', $arr);
### src/Content/ContactSelector.php
Addon::callHooks('network_to_name', $nets);
Addon::callHooks('gender_selector', $select);
Addon::callHooks('sexpref_selector', $select);
Addon::callHooks('marital_selector', $select);
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
Addon::callHooks('oembed_fetch_url', $embedurl, $j);
Hook::callAll('oembed_fetch_url', $embedurl, $j);
### src/Content/Nav.php
Addon::callHooks('page_header', $a->page['nav']);
Addon::callHooks('nav_info', $nav);
Hook::callAll('page_header', $a->page['nav']);
Hook::callAll('nav_info', $nav);
### src/Core/Authentication.php
Addon::callHooks('logged_in', $a->user);
Hook::callAll('logged_in', $a->user);
### src/Worker/Directory.php
Addon::callHooks('globaldir_update', $arr);
Hook::callAll('globaldir_update', $arr);
### src/Worker/Notifier.php
Addon::callHooks('notifier_end', $target_item);
Hook::callAll('notifier_end', $target_item);
### src/Worker/Queue.php
Addon::callHooks('queue_predeliver', $r);
Addon::callHooks('queue_deliver', $params);
Hook::callAll('queue_predeliver', $r);
Hook::callAll('queue_deliver', $params);
### src/Module/Login.php
Addon::callHooks('authenticate', $addon_auth);
Addon::callHooks('login_hook', $o);
Hook::callAll('authenticate', $addon_auth);
Hook::callAll('login_hook', $o);
### src/Module/Logout.php
Addon::callHooks("logging_out");
Hook::callAll("logging_out");
### src/Object/Post.php
Addon::callHooks('render_location', $locate);
Addon::callHooks('display_item', $arr);
Hook::callAll('render_location', $locate);
Hook::callAll('display_item', $arr);
### src/Core/ACL.php
Addon::callHooks('contact_select_options', $x);
Addon::callHooks($a->module.'_pre_'.$selname, $arr);
Addon::callHooks($a->module.'_post_'.$selname, $o);
Addon::callHooks($a->module.'_pre_'.$selname, $arr);
Addon::callHooks($a->module.'_post_'.$selname, $o);
Addon::callHooks('jot_networks', $jotnets);
Hook::callAll('contact_select_options', $x);
Hook::callAll($a->module.'_pre_'.$selname, $arr);
Hook::callAll($a->module.'_post_'.$selname, $o);
Hook::callAll($a->module.'_pre_'.$selname, $arr);
Hook::callAll($a->module.'_post_'.$selname, $o);
Hook::callAll('jot_networks', $jotnets);
### src/Core/Worker.php
Addon::callHooks("proc_run", $arr);
Hook::callAll("proc_run", $arr);
### src/Util/Emailer.php
Addon::callHooks('emailer_send_prepare', $params);
Addon::callHooks("emailer_send", $hookdata);
Hook::callAll('emailer_send_prepare', $params);
Hook::callAll("emailer_send", $hookdata);
### src/Util/Map.php
Addon::callHooks('generate_map', $arr);
Addon::callHooks('generate_named_map', $arr);
Addon::callHooks('Map::getCoordinates', $arr);
Hook::callAll('generate_map', $arr);
Hook::callAll('generate_named_map', $arr);
Hook::callAll('Map::getCoordinates', $arr);
### src/Util/Network.php
Addon::callHooks('avatar_lookup', $avatar);
Hook::callAll('avatar_lookup', $avatar);
### src/Util/ParseUrl.php
Addon::callHooks("getsiteinfo", $siteinfo);
Hook::callAll("getsiteinfo", $siteinfo);
### src/Protocol/DFRN.php
Addon::callHooks('atom_feed_end', $atom);
Addon::callHooks('atom_feed_end', $atom);
Hook::callAll('atom_feed_end', $atom);
Hook::callAll('atom_feed_end', $atom);

View file

@ -68,6 +68,10 @@ table.bbcodes > * > tr > th {
<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>
</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>
</tr>
<tr>
<td>[img=64x32]https://raw.githubusercontent.com/friendica/friendica/master/images/friendica-32.jpg[/img]<br>
<br>Note: provided height is simply discarded.</td>

View file

@ -188,7 +188,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

@ -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

@ -12,7 +12,7 @@ Die zweite Zahl steht für die Anzahl der Aufgaben, die die Worker noch vor sich
Die Worker arbeiten Hintergrundprozesse ab.
Die Aufgaben der Worker sind priorisiert und werden anhand dieser Prioritäten abgearbeitet.
Desweiteren findest du eine Übersicht über die Accounts auf dem Friendica Knoten, die unter dem Punkt "Nutzer" moderiert werden können.
Des weiteren findest du eine Übersicht über die Accounts auf dem Friendica Knoten, die unter dem Punkt "Nutzer" moderiert werden können.
Sowie eine Liste der derzeit aktivierten Addons.
Diese Liste ist verlinkt, so dass du schnellen Zugriff auf die Informationsseiten der einzelnen Addons hast.
Abschließend findest du auf der Startseite des Admin Panels die installierte Version von Friendica.
@ -47,7 +47,7 @@ Mehr Informationen zum Übersetzungsprozess von Friendica findest du [auf dieser
Hier kann das Theme bestimmt werden, welches standardmäßig zum Anzeigen der Seite verwendet werden soll.
Nutzer können in ihren Einstellungen andere Themes wählen.
Derzeit ist das "duepunto zero" Theme das vorausgewählte Theme.
Derzeit ist das "vier" Theme das vorausgewählte Theme.
Für mobile Geräte kannst du ein spezielles Theme wählen, wenn das Standardtheme ungeeignet für mobile Geräte sein sollte.
Das `vier` Theme z.B. unterstützt kleine Anzeigen und benötigt kein zusätzliches mobiles Theme.
@ -92,6 +92,32 @@ Standardmäßig ist hier "false" gesetzt.
### Datei hochladen
#### Datenspeicher Backend
Legt das Datenspeicher Backend fest, mit dem Friendica hoch geladene Daten speichert.
Zwei Speicher Backends sind standardmäßig bei Friendica verfügbar:
- **Database** : Die Daten werden in einer speziellen Tabelle in der Datenbank (`storage`) gespeichert.
- **Filesystem** : Die Daten werden als Dateien im Dateisystem gespeichert.
Weitere Speicher Backends können als Addons von Drittanbietern verfügbar sein.
Falls ein solches verwendet wird, sei an dieser Stelle nur auf deren Dokumentation für weitere Informationen verwiesen.
Die Grundeinstellung ist 'Datenbank (legacy)': Dies ist die alte Methode von Friendica Daten direkt in der Datenbank abzulegen.
Bestehende Daten können zum aktuell ausgewählten Backend verschoben werden.
Hierfür kann der ['storage move'](help/tools) Befehl der Friendica Konsole verwendet werden.
Sollte das ausgewählte Speicher Backand zusätzliche Konfigurationsparameter besitzen, werden nach der Auswahl des Backends hier weitere Felder angezeigt.
##### Dateipfad zum Speicher
Der Basispfad unter dem das Filesystem Datenspeicher Backend die Daten speichern soll.
Um zu verhindern, dass Daten unter Umgehung der Privatsphären-Einstellungen herunter geladen werden, sollte dieser Pfad außerhalb der Verzeichnisstruktur des Webservers liegen.
Die Grundeinstellung ist `storage`, das ist das `storage` Unterverzeichnis innerhalb des Friendica Verzeichnisses.
#### Maximale Bildgröße
Maximale Bild-Dateigröße in Byte. Standardmäßig ist 0 gesetzt, was bedeutet, dass kein Limit gesetzt ist.

View file

@ -9,6 +9,7 @@ Friendica Tools
Friendica has a build in command console you can find in the *bin* directory.
The console provides the following commands:
* cache: Manage node cache
* config: Edit site config
* createdoxygen: Generate Doxygen headers
* dbstructure: Do database updates
@ -24,6 +25,8 @@ The console provides the following commands:
* php2po: Generate a messages.po file from a strings.php file
* po2php: Generate a strings.php file from a messages.po file
* typo: Checks for parse errors in Friendica files
* postupdate: Execute pending post update scripts (can last days)
* storage: Manage storage backend
Please consult *bin/console help* on the command line interface of your server for details about the commands.
@ -53,7 +56,7 @@ In */etc/fail2ban/jail.local* create a section for Friendica:
And create a filter definition in */etc/fail2ban/filter.d/friendica.conf*:
[Definition]
failregex = ^.*Login\.php.*failed login attempt.*from IP <HOST>.*$
failregex = ^.*authenticate\: failed login attempt.*\"ip\"\:\"<HOST>\".*$
ignoreregex =
Additionally you have to define the number of failed logins before the ban should be activated.

View file

@ -11,9 +11,9 @@ use Friendica\Content\ContactSelector;
use Friendica\Content\Feature;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
use Friendica\Core\Addon;
use Friendica\Core\Authentication;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\NotificationsManager;
@ -31,6 +31,7 @@ use Friendica\Model\User;
use Friendica\Network\FKOAuth1;
use Friendica\Network\HTTPException;
use Friendica\Network\HTTPException\BadRequestException;
use Friendica\Network\HTTPException\ExpectationFailedException;
use Friendica\Network\HTTPException\ForbiddenException;
use Friendica\Network\HTTPException\InternalServerErrorException;
use Friendica\Network\HTTPException\MethodNotAllowedException;
@ -55,6 +56,8 @@ define('API_METHOD_GET', 'GET');
define('API_METHOD_POST', 'POST,PUT');
define('API_METHOD_DELETE', 'POST,DELETE');
define('API_LOG_PREFIX', 'API {action} - ');
$API = [];
$called_api = [];
@ -83,7 +86,8 @@ function api_user()
* @brief Get source name from API client
*
* @return string
* Client source name, default to "api" if unset/unknown
* Client source name, default to "api" if unset/unknown
* @throws Exception
*/
function api_source()
{
@ -97,9 +101,9 @@ function api_source()
return "Twidere";
}
Logger::log("Unrecognized user-agent ".$_SERVER['HTTP_USER_AGENT'], Logger::DEBUG);
Logger::info(API_LOG_PREFIX . 'Unrecognized user-agent', ['module' => 'api', 'action' => 'source', 'http_user_agent' => $_SERVER['HTTP_USER_AGENT']]);
} else {
Logger::log("Empty user-agent", Logger::DEBUG);
Logger::info(API_LOG_PREFIX . 'Empty user-agent', ['module' => 'api', 'action' => 'source']);
}
return "api";
@ -110,6 +114,7 @@ function api_source()
*
* @param string $str Source date, as UTC
* @return string Date in UTC formatted as "D M d H:i:s +0000 Y"
* @throws Exception
*/
function api_date($str)
{
@ -155,15 +160,17 @@ function api_register_func($path, $func, $auth = false, $method = API_METHOD_ANY
*
* @brief Login API user
*
* @param object $a App
* @hook 'authenticate'
* array $addon_auth
* 'username' => username from login form
* 'password' => password from login form
* 'authenticated' => return status,
* 'user_record' => return authenticated user record
* @hook 'logged_in'
* array $user logged user record
* @param App $a App
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @hook 'authenticate'
* array $addon_auth
* 'username' => username from login form
* 'password' => password from login form
* 'authenticated' => return status,
* 'user_record' => return authenticated user record
* @hook 'logged_in'
* array $user logged user record
*/
function api_login(App $a)
{
@ -174,14 +181,14 @@ function api_login(App $a)
list($consumer, $token) = $oauth1->verify_request($request);
if (!is_null($token)) {
$oauth1->loginUser($token->uid);
Addon::callHooks('logged_in', $a->user);
Hook::callAll('logged_in', $a->user);
return;
}
echo __FILE__.__LINE__.__FUNCTION__ . "<pre>";
var_dump($consumer, $token);
die();
} catch (Exception $e) {
Logger::log($e);
Logger::warning(API_LOG_PREFIX . 'error', ['module' => 'api', 'action' => 'login', 'exception' => $e->getMessage()]);
}
// workaround for HTTP-auth in CGI mode
@ -195,7 +202,7 @@ function api_login(App $a)
}
if (empty($_SERVER['PHP_AUTH_USER'])) {
Logger::log('API_login: ' . print_r($_SERVER, true), Logger::DEBUG);
Logger::debug(API_LOG_PREFIX . 'failed', ['module' => 'api', 'action' => 'login', 'parameters' => $_SERVER]);
header('WWW-Authenticate: Basic realm="Friendica"');
throw new UnauthorizedException("This API requires login");
}
@ -224,7 +231,7 @@ function api_login(App $a)
* Addons should never set 'authenticated' except to indicate success - as hooks may be chained
* and later addons should not interfere with an earlier one that succeeded.
*/
Addon::callHooks('authenticate', $addon_auth);
Hook::callAll('authenticate', $addon_auth);
if ($addon_auth['authenticated'] && count($addon_auth['user_record'])) {
$record = $addon_auth['user_record'];
@ -236,7 +243,7 @@ function api_login(App $a)
}
if (!DBA::isResult($record)) {
Logger::log('API_login failure: ' . print_r($_SERVER, true), Logger::DEBUG);
Logger::debug(API_LOG_PREFIX . 'failed', ['module' => 'api', 'action' => 'login', 'parameters' => $_SERVER]);
header('WWW-Authenticate: Basic realm="Friendica"');
//header('HTTP/1.0 401 Unauthorized');
//die('This api requires login');
@ -247,7 +254,7 @@ function api_login(App $a)
$_SESSION["allow_api"] = true;
Addon::callHooks('logged_in', $a->user);
Hook::callAll('logged_in', $a->user);
}
/**
@ -273,8 +280,9 @@ function api_check_method($method)
*
* @brief Main API entry point
*
* @param object $a App
* @param App $a App
* @return string|array API call result
* @throws Exception
*/
function api_call(App $a)
{
@ -309,76 +317,16 @@ function api_call(App $a)
api_login($a);
}
Logger::log('API call for ' . $a->user['username'] . ': ' . $a->query_string);
Logger::log('API parameters: ' . print_r($_REQUEST, true));
Logger::info(API_LOG_PREFIX . 'username {username}', ['module' => 'api', 'action' => 'call', 'username' => $a->user['username']]);
Logger::debug(API_LOG_PREFIX . 'parameters', ['module' => 'api', 'action' => 'call', 'parameters' => $_REQUEST]);
$stamp = microtime(true);
$return = call_user_func($info['func'], $type);
$duration = (float) (microtime(true) - $stamp);
Logger::log("API call duration: " . round($duration, 2) . "\t" . $a->query_string, Logger::DEBUG);
if (Config::get("system", "profiler")) {
$duration = microtime(true)-$a->performance["start"];
Logger::info(API_LOG_PREFIX . 'username {username}', ['module' => 'api', 'action' => 'call', 'username' => $a->user['username'], 'duration' => round($duration, 2)]);
/// @TODO round() really everywhere?
Logger::log(
parse_url($a->query_string, PHP_URL_PATH) . ": " . sprintf(
"Database: %s/%s, Cache %s/%s, Network: %s, I/O: %s, Other: %s, Total: %s",
round($a->performance["database"] - $a->performance["database_write"], 3),
round($a->performance["database_write"], 3),
round($a->performance["cache"], 3),
round($a->performance["cache_write"], 3),
round($a->performance["network"], 2),
round($a->performance["file"], 2),
round($duration - ($a->performance["database"]
+ $a->performance["cache"] + $a->performance["cache_write"]
+ $a->performance["network"] + $a->performance["file"]), 2),
round($duration, 2)
),
Logger::DEBUG
);
if (Config::get("rendertime", "callstack")) {
$o = "Database Read:\n";
foreach ($a->callstack["database"] as $func => $time) {
$time = round($time, 3);
if ($time > 0) {
$o .= $func . ": " . $time . "\n";
}
}
$o .= "\nDatabase Write:\n";
foreach ($a->callstack["database_write"] as $func => $time) {
$time = round($time, 3);
if ($time > 0) {
$o .= $func . ": " . $time . "\n";
}
}
$o = "Cache Read:\n";
foreach ($a->callstack["cache"] as $func => $time) {
$time = round($time, 3);
if ($time > 0) {
$o .= $func . ": " . $time . "\n";
}
}
$o .= "\nCache Write:\n";
foreach ($a->callstack["cache_write"] as $func => $time) {
$time = round($time, 3);
if ($time > 0) {
$o .= $func . ": " . $time . "\n";
}
}
$o .= "\nNetwork:\n";
foreach ($a->callstack["network"] as $func => $time) {
$time = round($time, 3);
if ($time > 0) {
$o .= $func . ": " . $time . "\n";
}
}
Logger::log($o, Logger::DEBUG);
}
}
$a->getProfiler()->saveLog($a->getLogger(), API_LOG_PREFIX . 'performance');
if (false === $return) {
/*
@ -413,7 +361,7 @@ function api_call(App $a)
}
}
Logger::log('API call not implemented: ' . $a->query_string);
Logger::warning(API_LOG_PREFIX . 'not implemented', ['module' => 'api', 'action' => 'call']);
throw new NotImplementedException();
} catch (HTTPException $e) {
header("HTTP/1.1 {$e->httpcode} {$e->httpdesc}");
@ -463,11 +411,15 @@ function api_error($type, $e)
/**
* @brief Set values for RSS template
*
* @param App $a
* @param App $a
* @param array $arr Array to be passed to template
* @param array $user_info User info
* @return array
* @todo find proper type-hints
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @todo find proper type-hints
*/
function api_rss_extra(App $a, $arr, $user_info)
{
@ -495,7 +447,8 @@ function api_rss_extra(App $a, $arr, $user_info)
*
* @param int $id Contact id
* @return bool|string
* Contact url or False if contact id is unknown
* Contact url or False if contact id is unknown
* @throws Exception
*/
function api_unique_id_to_nurl($id)
{
@ -511,8 +464,13 @@ function api_unique_id_to_nurl($id)
/**
* @brief Get user info array.
*
* @param object $a App
* @param App $a App
* @param int|string $contact_id Contact ID or URL
* @return array|bool
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_get_user(App $a, $contact_id = null)
{
@ -522,7 +480,7 @@ function api_get_user(App $a, $contact_id = null)
$extra_query = "";
$url = "";
Logger::log("api_get_user: Fetching user data for user ".$contact_id, Logger::DEBUG);
Logger::info(API_LOG_PREFIX . 'Fetching data for user {user}', ['module' => 'api', 'action' => 'get_user', 'user' => $contact_id]);
// Searching for contact URL
if (!is_null($contact_id) && (intval($contact_id) == 0)) {
@ -606,7 +564,7 @@ function api_get_user(App $a, $contact_id = null)
}
}
Logger::log("api_get_user: user ".$user, Logger::DEBUG);
Logger::info(API_LOG_PREFIX . 'getting user {user}', ['module' => 'api', 'action' => 'get_user', 'user' => $user]);
if (!$user) {
if (api_user() === false) {
@ -618,7 +576,7 @@ function api_get_user(App $a, $contact_id = null)
}
}
Logger::log('api_user: ' . $extra_query . ', user: ' . $user);
Logger::info(API_LOG_PREFIX . 'found user {user}', ['module' => 'api', 'action' => 'get_user', 'user' => $user, 'extra_query' => $extra_query]);
// user info
$uinfo = q(
@ -805,30 +763,36 @@ function api_get_user(App $a, $contact_id = null)
/**
* @brief return api-formatted array for item's author and owner
*
* @param object $a App
* @param array $item item from db
* @param App $a App
* @param array $item item from db
* @return array(array:author, array:owner)
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_item_get_user(App $a, $item)
{
$status_user = api_get_user($a, defaults($item, 'author-id', null));
$author_user = $status_user;
$status_user["protected"] = defaults($item, 'private', 0);
if (defaults($item, 'thr-parent', '') == defaults($item, 'uri', '')) {
$owner_user = api_get_user($a, defaults($item, 'owner-id', null));
} else {
$owner_user = $status_user;
$owner_user = $author_user;
}
return ([$status_user, $owner_user]);
return ([$status_user, $author_user, $owner_user]);
}
/**
* @brief walks recursively through an array with the possibility to change value and key
*
* @param array $array The array to walk through
* @param string $callback The callback function
* @param array $array The array to walk through
* @param callable $callback The callback function
*
* @return array the transformed array
*/
@ -930,7 +894,7 @@ function api_create_xml(array $data, $root_element)
* @param string $type Return type (atom, rss, xml, json)
* @param array $data JSON style array
*
* @return (string|array) XML data or JSON data
* @return array|string (string|array) XML data or JSON data
*/
function api_format_data($root_element, $type, $data)
{
@ -945,7 +909,6 @@ function api_format_data($root_element, $type, $data)
$ret = $data;
break;
}
return $ret;
}
@ -956,9 +919,16 @@ function api_format_data($root_element, $type, $data)
/**
* Returns an HTTP 200 OK response code and a representation of the requesting user if authentication was successful;
* returns a 401 status code and an error message if not.
*
* @see https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/get-account-verify_credentials
*
* @param string $type Return type (atom, rss, xml, json)
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_account_verify_credentials($type)
{
@ -985,10 +955,12 @@ function api_account_verify_credentials($type)
// - Adding last status
if (!$skip_status) {
$user_info["status"] = api_status_show("raw");
if (!count($user_info["status"])) {
unset($user_info["status"]);
} else {
unset($user_info["status"]["user"]);
if (isset($user_info["status"])) {
if (!is_array($user_info["status"]) || !count($user_info["status"])) {
unset($user_info["status"]);
} else {
unset($user_info["status"]["user"]);
}
}
}
@ -1006,6 +978,7 @@ api_register_func('api/account/verify_credentials', 'api_account_verify_credenti
* Get data from $_POST or $_GET
*
* @param string $k
* @return null
*/
function requestdata($k)
{
@ -1024,6 +997,11 @@ function requestdata($k)
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_statuses_mediap($type)
{
@ -1071,6 +1049,12 @@ api_register_func('api/statuses/mediap', 'api_statuses_mediap', true, API_METHOD
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws TooManyRequestsException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update
*/
function api_statuses_update($type)
@ -1213,6 +1197,11 @@ api_register_func('api/statuses/update_with_media', 'api_statuses_update', true,
* Uploads an image to Friendica.
*
* @return array
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/media/upload-media/api-reference/post-media-upload
*/
function api_media_upload()
@ -1242,8 +1231,9 @@ function api_media_upload()
$returndata["media_id_string"] = (string)$media["id"];
$returndata["size"] = $media["size"];
$returndata["image"] = ["w" => $media["width"],
"h" => $media["height"],
"image_type" => $media["type"]];
"h" => $media["height"],
"image_type" => $media["type"],
"friendica_preview_url" => $media["preview"]];
Logger::log("Media uploaded: " . print_r($returndata, true), Logger::DEBUG);
@ -1257,7 +1247,12 @@ api_register_func('api/media/upload', 'api_media_upload', true, API_METHOD_POST)
*
* @param string $type Return type (atom, rss, xml, json)
*
* @param int $item_id
* @return array|string
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_status_show($type, $item_id = 0)
{
@ -1267,12 +1262,6 @@ function api_status_show($type, $item_id = 0)
Logger::log('api_status_show: user_info: '.print_r($user_info, true), Logger::DEBUG);
if ($type == "raw") {
$privacy_sql = "AND NOT `private`";
} else {
$privacy_sql = "";
}
if (!empty($item_id)) {
// Get the item with the given id
$condition = ['id' => $item_id];
@ -1281,6 +1270,11 @@ function api_status_show($type, $item_id = 0)
$condition = ['owner-id' => $user_info['pid'], 'uid' => api_user(),
'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]];
}
if ($type == "raw") {
$condition['private'] = false;
}
$lastwall = Item::selectFirst(Item::ITEM_FIELDLIST, $condition, ['order' => ['id' => true]]);
if (DBA::isResult($lastwall)) {
@ -1356,6 +1350,11 @@ function api_status_show($type, $item_id = 0)
* The author's most recent status will be returned inline.
*
* @param string $type Return type (atom, rss, xml, json)
* @return array|string
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-show
*/
function api_users_show($type)
@ -1432,6 +1431,10 @@ api_register_func('api/externalprofile/show', 'api_users_show');
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-users-search
*/
function api_users_search($type)
@ -1480,7 +1483,11 @@ api_register_func('api/users/search', 'api_users_search');
* @param string $type Return format: json or xml
*
* @return array|string
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws NotFoundException if the results are empty.
* @throws UnauthorizedException
*/
function api_users_lookup($type)
{
@ -1513,52 +1520,85 @@ api_register_func('api/users/lookup', 'api_users_lookup', true);
*
* @return array|string
* @throws BadRequestException if the "q" parameter is missing.
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_search($type)
{
$a = \get_app();
$user_info = api_get_user($a);
if (api_user() === false || $user_info === false) {
throw new ForbiddenException();
}
$data = [];
if (api_user() === false || $user_info === false) { throw new ForbiddenException(); }
if (empty($_REQUEST['q'])) {
throw new BadRequestException("q parameter is required.");
throw new BadRequestException('q parameter is required.');
}
$searchTerm = trim(rawurldecode($_REQUEST['q']));
$data = [];
$data['status'] = [];
$count = 15;
$exclude_replies = !empty($_REQUEST['exclude_replies']);
if (!empty($_REQUEST['rpp'])) {
$count = $_REQUEST['rpp'];
} elseif (!empty($_REQUEST['count'])) {
$count = $_REQUEST['count'];
} else {
$count = 15;
}
$since_id = defaults($_REQUEST, 'since_id', 0);
$max_id = defaults($_REQUEST, 'max_id', 0);
$page = (!empty($_REQUEST['page']) ? $_REQUEST['page'] - 1 : 0);
$start = $page * $count;
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
if (preg_match('/^#(\w+)$/', $searchTerm, $matches) === 1 && isset($matches[1])) {
$searchTerm = $matches[1];
$condition = ["`oid` > ?
AND (`uid` = 0 OR (`uid` = ? AND NOT `global`))
AND `otype` = ? AND `type` = ? AND `term` = ?",
$since_id, local_user(), TERM_OBJ_POST, TERM_HASHTAG, $searchTerm];
if ($max_id > 0) {
$condition[0] .= ' AND `oid` <= ?';
$condition[] = $max_id;
}
$terms = DBA::select('term', ['oid'], $condition, []);
$itemIds = [];
while ($term = DBA::fetch($terms)) {
$itemIds[] = $term['oid'];
}
DBA::close($terms);
$condition = ["`gravity` IN (?, ?) AND `item`.`id` > ?
AND (`item`.`uid` = 0 OR (`item`.`uid` = ? AND NOT `item`.`global`))
AND `item`.`body` LIKE CONCAT('%',?,'%')",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id, api_user(), $_REQUEST['q']];
if (empty($itemIds)) {
return api_format_data('statuses', $type, $data);
}
if ($max_id > 0) {
$condition[0] .= " AND `item`.`id` <= ?";
$condition[] = $max_id;
$preCondition = ['`id` IN (' . implode(', ', $itemIds) . ')'];
if ($exclude_replies) {
$preCondition[] = '`id` = `parent`';
}
$condition = [implode(' AND ', $preCondition)];
} else {
$condition = ["`id` > ?
" . ($exclude_replies ? " AND `id` = `parent` " : ' ') . "
AND (`uid` = 0 OR (`uid` = ? AND NOT `global`))
AND `body` LIKE CONCAT('%',?,'%')",
$since_id, api_user(), $_REQUEST['q']];
if ($max_id > 0) {
$condition[0] .= ' AND `id` <= ?';
$condition[] = $max_id;
}
}
$params = ['order' => ['id' => true], 'limit' => [$start, $count]];
$statuses = Item::selectForUser(api_user(), [], $condition, $params);
$data['status'] = api_format_items(Item::inArray($statuses), $user_info);
return api_format_data("statuses", $type, $data);
bindComments($data['status']);
return api_format_data('statuses', $type, $data);
}
/// @TODO move to top of file or somewhere better
@ -1568,10 +1608,16 @@ api_register_func('api/search', 'api_search', true);
/**
* Returns the most recent statuses posted by the user and the users they follow.
*
* @see https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline
* @see https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-home_timeline
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @todo Optional parameters
* @todo Add reply info
*/
@ -1639,6 +1685,8 @@ function api_statuses_home_timeline($type)
Item::update(['unseen' => false], ['unseen' => true, 'id' => $idarray]);
}
}
bindComments($ret);
$data = ['status' => $ret];
switch ($type) {
@ -1652,6 +1700,7 @@ function api_statuses_home_timeline($type)
return api_format_data("statuses", $type, $data);
}
/// @TODO move to top of file or somewhere better
api_register_func('api/statuses/home_timeline', 'api_statuses_home_timeline', true);
api_register_func('api/statuses/friends_timeline', 'api_statuses_home_timeline', true);
@ -1662,6 +1711,11 @@ api_register_func('api/statuses/friends_timeline', 'api_statuses_home_timeline',
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_statuses_public_timeline($type)
{
@ -1688,7 +1742,7 @@ function api_statuses_public_timeline($type)
$start = $page * $count;
if ($exclude_replies && !$conversation_id) {
$condition = ["`gravity` IN (?, ?) AND `iid` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall`",
$condition = ["`gravity` IN (?, ?) AND `iid` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall` AND NOT `author`.`hidden`",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
if ($max_id > 0) {
@ -1701,7 +1755,7 @@ function api_statuses_public_timeline($type)
$r = Item::inArray($statuses);
} else {
$condition = ["`gravity` IN (?, ?) AND `id` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall` AND `item`.`origin`",
$condition = ["`gravity` IN (?, ?) AND `id` > ? AND NOT `private` AND `wall` AND NOT `user`.`hidewall` AND `item`.`origin` AND NOT `author`.`hidden`",
GRAVITY_PARENT, GRAVITY_COMMENT, $since_id];
if ($max_id > 0) {
@ -1721,6 +1775,8 @@ function api_statuses_public_timeline($type)
$ret = api_format_items($r, $user_info, false, $type);
bindComments($ret);
$data = ['status' => $ret];
switch ($type) {
case "atom":
@ -1743,7 +1799,11 @@ api_register_func('api/statuses/public_timeline', 'api_statuses_public_timeline'
*
* @param string $type Return format: json, xml, atom, rss
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_statuses_networkpublic_timeline($type)
{
@ -1778,6 +1838,8 @@ function api_statuses_networkpublic_timeline($type)
$ret = api_format_items(Item::inArray($statuses), $user_info, false, $type);
bindComments($ret);
$data = ['status' => $ret];
switch ($type) {
case "atom":
@ -1798,6 +1860,12 @@ api_register_func('api/statuses/networkpublic_timeline', 'api_statuses_networkpu
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/get-statuses-show-id
*/
function api_statuses_show($type)
@ -1871,6 +1939,12 @@ api_register_func('api/statuses/show', 'api_statuses_show', true);
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @todo nothing to say?
*/
function api_conversation_show($type)
@ -1903,7 +1977,7 @@ function api_conversation_show($type)
$id = intval(defaults($a->argv, 4, 0));
}
Logger::log('API: api_conversation_show: '.$id);
Logger::info(API_LOG_PREFIX . '{subaction}', ['module' => 'api', 'action' => 'conversation', 'subaction' => 'show', 'id' => $id]);
// try to fetch the item for the local user - or the public item, if there is no local one
$item = Item::selectFirst(['parent-uri'], ['id' => $id]);
@ -1948,6 +2022,12 @@ api_register_func('api/statusnet/conversation', 'api_conversation_show', true);
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-retweet-id
*/
function api_statuses_repeat($type)
@ -2015,6 +2095,12 @@ api_register_func('api/statuses/retweet', 'api_statuses_repeat', true, API_METHO
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-destroy-id
*/
function api_statuses_destroy($type)
@ -2056,6 +2142,12 @@ api_register_func('api/statuses/destroy', 'api_statuses_destroy', true, API_METH
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see http://developer.twitter.com/doc/get/statuses/mentions
*/
function api_statuses_mentions($type)
@ -2123,8 +2215,12 @@ api_register_func('api/statuses/replies', 'api_statuses_mentions', true);
*
* @param string $type Either "json" or "xml"
* @return string|array
* @throws BadRequestException
* @throws ForbiddenException
* @see https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-user_timeline
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/tweets/timelines/api-reference/get-statuses-user_timeline
*/
function api_statuses_user_timeline($type)
{
@ -2181,6 +2277,8 @@ function api_statuses_user_timeline($type)
$ret = api_format_items(Item::inArray($statuses), $user_info, true, $type);
bindComments($ret);
$data = ['status' => $ret];
switch ($type) {
case "atom":
@ -2202,6 +2300,12 @@ api_register_func('api/statuses/user_timeline', 'api_statuses_user_timeline', tr
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://web.archive.org/web/20131019055350/https://dev.twitter.com/docs/api/1/post/favorites/create/%3Aid
*/
function api_favorites_create_destroy($type)
@ -2279,6 +2383,11 @@ api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true,
* @param string $type Return type (atom, rss, xml, json)
*
* @return string|array
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_favorites($type)
{
@ -2295,7 +2404,7 @@ function api_favorites($type)
// in friendica starred item are private
// return favorites only for self
Logger::log('api_favorites: self:' . $user_info['self']);
Logger::info(API_LOG_PREFIX . 'for {self}', ['module' => 'api', 'action' => 'favorites', 'self' => $user_info['self']]);
if ($user_info['self'] == 0) {
$ret = [];
@ -2326,6 +2435,8 @@ function api_favorites($type)
$ret = api_format_items(Item::inArray($statuses), $user_info, false, $type);
}
bindComments($ret);
$data = ['status' => $ret];
switch ($type) {
case "atom":
@ -2348,6 +2459,7 @@ api_register_func('api/favorites', 'api_favorites', true);
* @param array $sender
*
* @return array
* @throws InternalServerErrorException
*/
function api_format_messages($item, $recipient, $sender)
{
@ -2405,6 +2517,7 @@ function api_format_messages($item, $recipient, $sender)
* @param array $item
*
* @return array
* @throws InternalServerErrorException
*/
function api_convert_item($item)
{
@ -2480,6 +2593,7 @@ function api_convert_item($item)
* @param string $body
*
* @return array
* @throws InternalServerErrorException
*/
function api_get_attachments(&$body)
{
@ -2518,6 +2632,7 @@ function api_get_attachments(&$body)
* @param string $bbcode
*
* @return array
* @throws InternalServerErrorException
* @todo Links at the first character of the post
*/
function api_get_entitities(&$text, $bbcode)
@ -2662,7 +2777,7 @@ function api_get_entitities(&$text, $bbcode)
$entities["media"][] = [
"id" => $start+1,
"id_str" => (string)$start+1,
"id_str" => (string) ($start + 1),
"indices" => [$start, $start+strlen($url)],
"media_url" => Strings::normaliseLink($media_url),
"media_url_https" => $media_url,
@ -2728,12 +2843,16 @@ function api_contactlink_to_array($txt)
/**
* @brief return likes, dislikes and attend status for item
*
* @param array $item array
* @param array $item array
* @param string $type Return type (atom, rss, xml, json)
*
* @return array
* likes => int count,
* dislikes => int count
* likes => int count,
* dislikes => int count
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_format_items_activities($item, $type = "json")
{
@ -2800,8 +2919,9 @@ function api_format_items_activities($item, $type = "json")
/**
* @brief return data from profiles
*
* @param array $profile_row array containing data from db table 'profile'
* @param array $profile_row array containing data from db table 'profile'
* @return array
* @throws InternalServerErrorException
*/
function api_format_items_profiles($profile_row)
{
@ -2852,10 +2972,15 @@ function api_format_items_profiles($profile_row)
/**
* @brief format items to be returned by api
*
* @param array $r array of items
* @param array $r array of items
* @param array $user_info
* @param bool $filter_user filter items by $user_info
* @param string $type Return type (atom, rss, xml, json)
* @param string $type Return type (atom, rss, xml, json)
* @return array
* @throws BadRequestException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_format_items($r, $user_info, $filter_user = false, $type = "json")
{
@ -2863,9 +2988,9 @@ function api_format_items($r, $user_info, $filter_user = false, $type = "json")
$ret = [];
foreach ($r as $item) {
foreach ((array)$r as $item) {
localize_item($item);
list($status_user, $owner_user) = api_item_get_user($a, $item);
list($status_user, $author_user, $owner_user) = api_item_get_user($a, $item);
// Look if the posts are matching if they should be filtered by user id
if ($filter_user && ($status_user["id"] != $user_info["id"])) {
@ -2897,6 +3022,7 @@ function api_format_items($r, $user_info, $filter_user = false, $type = "json")
$geo => null,
'favorited' => $item['starred'] ? true : false,
'user' => $status_user,
'friendica_author' => $author_user,
'friendica_owner' => $owner_user,
'friendica_private' => $item['private'] == 1,
//'entities' => NULL,
@ -2940,6 +3066,7 @@ function api_format_items($r, $user_info, $filter_user = false, $type = "json")
$retweeted_status['friendica_activities'] = api_format_items_activities($retweeted_item, $type);
$retweeted_status['created_at'] = api_date($retweeted_item['created']);
$status['retweeted_status'] = $retweeted_status;
$status['friendica_author'] = $retweeted_status['friendica_author'];
}
}
@ -2970,6 +3097,7 @@ function api_format_items($r, $user_info, $filter_user = false, $type = "json")
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws Exception
*/
function api_account_rate_limit_status($type)
{
@ -3045,6 +3173,11 @@ api_register_func('api/lists/subscriptions', 'api_lists_list', true);
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-ownerships
*/
function api_lists_ownerships($type)
@ -3089,6 +3222,11 @@ api_register_func('api/lists/ownerships', 'api_lists_ownerships', true);
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/get-lists-ownerships
*/
function api_lists_statuses($type)
@ -3166,7 +3304,11 @@ api_register_func('api/lists/statuses', 'api_lists_statuses', true);
*
* @param string $qtype Either "friends" or "followers"
* @return boolean|array
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_statuses_f($qtype)
{
@ -3250,12 +3392,14 @@ function api_statuses_f($qtype)
/**
* Returns the user's friends.
*
* @brief Returns the list of friends of the provided user
* @brief Returns the list of friends of the provided user
*
* @deprecated By Twitter API in favor of friends/list
*
* @param string $type Either "json" or "xml"
* @return boolean|string|array
* @throws BadRequestException
* @throws ForbiddenException
*/
function api_statuses_friends($type)
{
@ -3269,12 +3413,14 @@ function api_statuses_friends($type)
/**
* Returns the user's followers.
*
* @brief Returns the list of followers of the provided user
* @brief Returns the list of followers of the provided user
*
* @deprecated By Twitter API in favor of friends/list
*
* @param string $type Either "json" or "xml"
* @return boolean|string|array
* @throws BadRequestException
* @throws ForbiddenException
*/
function api_statuses_followers($type)
{
@ -3297,6 +3443,8 @@ api_register_func('api/statuses/followers', 'api_statuses_followers', true);
* @param string $type Either "json" or "xml"
*
* @return boolean|string|array
* @throws BadRequestException
* @throws ForbiddenException
*/
function api_blocks_list($type)
{
@ -3318,6 +3466,8 @@ api_register_func('api/blocks/list', 'api_blocks_list', true);
* @param string $type Either "json" or "xml"
*
* @return boolean|string|array
* @throws BadRequestException
* @throws ForbiddenException
*/
function api_friendships_incoming($type)
{
@ -3343,6 +3493,7 @@ api_register_func('api/friendships/incoming', 'api_friendships_incoming', true);
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws InternalServerErrorException
*/
function api_statusnet_config($type)
{
@ -3352,7 +3503,7 @@ function api_statusnet_config($type)
$server = $a->getHostName();
$logo = System::baseUrl() . '/images/friendica-64.png';
$email = Config::get('config', 'admin_email');
$closed = intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED ? 'true' : 'false';
$closed = intval(Config::get('config', 'register_policy')) === \Friendica\Module\Register::CLOSED ? 'true' : 'false';
$private = Config::get('system', 'block_public') ? 'true' : 'false';
$textlimit = (string) Config::get('config', 'api_import_size', Config::get('config', 'max_import_size', 200000));
$ssl = Config::get('system', 'have_ssl') ? 'true' : 'false';
@ -3402,6 +3553,12 @@ api_register_func('api/statusnet/version', 'api_statusnet_version', false);
*
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string|void
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @todo use api_format_data() to return data
*/
function api_ff_ids($type)
@ -3444,6 +3601,8 @@ function api_ff_ids($type)
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @see https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-friends-ids
*/
function api_friends_ids($type)
@ -3457,6 +3616,8 @@ function api_friends_ids($type)
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @see https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/get-followers-ids
*/
function api_followers_ids($type)
@ -3474,6 +3635,12 @@ api_register_func('api/followers/ids', 'api_followers_ids', true);
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws NotFoundException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/new-message
*/
function api_direct_messages_new($type)
@ -3513,7 +3680,6 @@ function api_direct_messages_new($type)
}
$replyto = '';
$sub = '';
if (!empty($_REQUEST['replyto'])) {
$r = q(
'SELECT `parent-uri`, `title` FROM `mail` WHERE `uid`=%d AND `id`=%d',
@ -3562,7 +3728,12 @@ api_register_func('api/direct_messages/new', 'api_direct_messages_new', true, AP
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array
* @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/delete-message
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/delete-message
*/
function api_direct_messages_destroy($type)
{
@ -3643,7 +3814,12 @@ api_register_func('api/direct_messages/destroy', 'api_direct_messages_destroy',
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array
* @see https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-destroy.html
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws NotFoundException
* @see https://developer.twitter.com/en/docs/accounts-and-users/follow-search-get-users/api-reference/post-friendships-destroy.html
*/
function api_friendships_destroy($type)
{
@ -3656,7 +3832,7 @@ function api_friendships_destroy($type)
$contact_id = defaults($_REQUEST, 'user_id');
if (empty($contact_id)) {
Logger::log("No user_id specified", Logger::DEBUG);
Logger::notice(API_LOG_PREFIX . 'No user_id specified', ['module' => 'api', 'action' => 'friendships_destroy']);
throw new BadRequestException("no user_id specified");
}
@ -3664,7 +3840,7 @@ function api_friendships_destroy($type)
$contact = DBA::selectFirst('contact', ['url'], ['id' => $contact_id, 'uid' => 0, 'self' => false]);
if(!DBA::isResult($contact)) {
Logger::log("No contact found for ID" . $contact_id, Logger::DEBUG);
Logger::notice(API_LOG_PREFIX . 'No contact found for ID {contact}', ['module' => 'api', 'action' => 'friendships_destroy', 'contact' => $contact_id]);
throw new NotFoundException("no contact found to given ID");
}
@ -3676,12 +3852,12 @@ function api_friendships_destroy($type)
$contact = DBA::selectFirst('contact', [], $condition);
if (!DBA::isResult($contact)) {
Logger::log("Not following Contact", Logger::DEBUG);
Logger::notice(API_LOG_PREFIX . 'Not following contact', ['module' => 'api', 'action' => 'friendships_destroy']);
throw new NotFoundException("Not following Contact");
}
if (!in_array($contact['network'], Protocol::NATIVE_SUPPORT)) {
Logger::log("Not supported", Logger::DEBUG);
Logger::notice(API_LOG_PREFIX . 'Not supported for {network}', ['module' => 'api', 'action' => 'friendships_destroy', 'network' => $contact['network']]);
throw new ExpectationFailedException("Not supported");
}
@ -3692,7 +3868,7 @@ function api_friendships_destroy($type)
Contact::terminateFriendship($owner, $contact, $dissolve);
}
else {
Logger::log("No owner found", Logger::DEBUG);
Logger::notice(API_LOG_PREFIX . 'No owner {uid} found', ['module' => 'api', 'action' => 'friendships_destroy', 'uid' => $uid]);
throw new NotFoundException("Error Processing Request");
}
@ -3721,6 +3897,11 @@ api_register_func('api/friendships/destroy', 'api_friendships_destroy', true, AP
* @param string $verbose
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_direct_messages_box($type, $box, $verbose)
{
@ -3826,6 +4007,8 @@ function api_direct_messages_box($type, $box, $verbose)
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/get-sent-message
*/
function api_direct_messages_sentbox($type)
@ -3840,6 +4023,8 @@ function api_direct_messages_sentbox($type)
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @see https://developer.twitter.com/en/docs/direct-messages/sending-and-receiving/api-reference/get-messages
*/
function api_direct_messages_inbox($type)
@ -3853,6 +4038,8 @@ function api_direct_messages_inbox($type)
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
*/
function api_direct_messages_all($type)
{
@ -3865,6 +4052,8 @@ function api_direct_messages_all($type)
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
*/
function api_direct_messages_conversation($type)
{
@ -3890,10 +4079,10 @@ function api_oauth_request_token()
$r = $oauth1->fetch_request_token(OAuthRequest::from_request());
} catch (Exception $e) {
echo "error=" . OAuthUtil::urlencode_rfc3986($e->getMessage());
killme();
exit();
}
echo $r;
killme();
exit();
}
/**
@ -3909,10 +4098,10 @@ function api_oauth_access_token()
$r = $oauth1->fetch_access_token(OAuthRequest::from_request());
} catch (Exception $e) {
echo "error=". OAuthUtil::urlencode_rfc3986($e->getMessage());
killme();
exit();
}
echo $r;
killme();
exit();
}
/// @TODO move to top of file or somewhere better
@ -3925,6 +4114,9 @@ api_register_func('api/oauth/access_token', 'api_oauth_access_token', false);
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array
* @throws BadRequestException
* @throws ForbiddenException
* @throws InternalServerErrorException
*/
function api_fr_photoalbum_delete($type)
{
@ -3961,7 +4153,7 @@ function api_fr_photoalbum_delete($type)
}
// now let's delete all photos from the album
$result = DBA::delete('photo', ['uid' => api_user(), 'album' => $album]);
$result = Photo::delete(['uid' => api_user(), 'album' => $album]);
// return success of deletion or error message
if ($result) {
@ -3977,6 +4169,9 @@ function api_fr_photoalbum_delete($type)
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array
* @throws BadRequestException
* @throws ForbiddenException
* @throws InternalServerErrorException
*/
function api_fr_photoalbum_update($type)
{
@ -3995,11 +4190,11 @@ function api_fr_photoalbum_update($type)
throw new BadRequestException("no new albumname specified");
}
// check if album is existing
if (!DBA::exists('photo', ['uid' => api_user(), 'album' => $album])) {
if (!Photo::exists(['uid' => api_user(), 'album' => $album])) {
throw new BadRequestException("album not available");
}
// now let's update all photos to the albumname
$result = DBA::update('photo', ['album' => $album_new], ['uid' => api_user(), 'album' => $album]);
$result = Photo::update(['album' => $album_new], ['uid' => api_user(), 'album' => $album]);
// return success of updating or error message
if ($result) {
@ -4016,6 +4211,8 @@ function api_fr_photoalbum_update($type)
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array
* @throws ForbiddenException
* @throws InternalServerErrorException
*/
function api_fr_photos_list($type)
{
@ -4062,6 +4259,11 @@ function api_fr_photos_list($type)
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws NotFoundException
*/
function api_fr_photo_create_update($type)
{
@ -4099,14 +4301,8 @@ function api_fr_photo_create_update($type)
} else {
$mode = "update";
// check if photo is existing in database
$r = q(
"SELECT `id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' AND `album` = '%s'",
intval(api_user()),
DBA::escape($photo_id),
DBA::escape($album)
);
if (!DBA::isResult($r)) {
// check if photo is existing in databasei
if (!Photo::exists(['resource-id' => $photo_id, 'uid' => api_user(), 'album' => $album])) {
throw new BadRequestException("photo not available");
}
}
@ -4135,47 +4331,40 @@ function api_fr_photo_create_update($type)
// now let's do the changes in update-mode
if ($mode == "update") {
$sql_extra = "";
$updated_fields = [];
if (!is_null($desc)) {
$sql_extra .= (($sql_extra != "") ? " ," : "") . "`desc` = '$desc'";
$updated_fields['desc'] = $desc;
}
if (!is_null($album_new)) {
$sql_extra .= (($sql_extra != "") ? " ," : "") . "`album` = '$album_new'";
$updated_fields['album'] = $album_new;
}
if (!is_null($allow_cid)) {
$allow_cid = trim($allow_cid);
$sql_extra .= (($sql_extra != "") ? " ," : "") . "`allow_cid` = '$allow_cid'";
$updated_fields['allow_cid'] = $allow_cid;
}
if (!is_null($deny_cid)) {
$deny_cid = trim($deny_cid);
$sql_extra .= (($sql_extra != "") ? " ," : "") . "`deny_cid` = '$deny_cid'";
$updated_fields['deny_cid'] = $deny_cid;
}
if (!is_null($allow_gid)) {
$allow_gid = trim($allow_gid);
$sql_extra .= (($sql_extra != "") ? " ," : "") . "`allow_gid` = '$allow_gid'";
$updated_fields['allow_gid'] = $allow_gid;
}
if (!is_null($deny_gid)) {
$deny_gid = trim($deny_gid);
$sql_extra .= (($sql_extra != "") ? " ," : "") . "`deny_gid` = '$deny_gid'";
$updated_fields['deny_gid'] = $deny_gid;
}
$result = false;
if ($sql_extra != "") {
if (count($updated_fields) > 0) {
$nothingtodo = false;
$result = q(
"UPDATE `photo` SET %s, `edited`='%s' WHERE `uid` = %d AND `resource-id` = '%s' AND `album` = '%s'",
$sql_extra,
DateTimeFormat::utcNow(), // update edited timestamp
intval(api_user()),
DBA::escape($photo_id),
DBA::escape($album)
);
$result = Photo::update($updated_fields, ['uid' => api_user(), 'resource-id' => $photo_id, 'album' => $album]);
} else {
$nothingtodo = true;
}
@ -4209,12 +4398,16 @@ function api_fr_photo_create_update($type)
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array
* @throws BadRequestException
* @throws ForbiddenException
* @throws InternalServerErrorException
*/
function api_fr_photo_delete($type)
{
if (api_user() === false) {
throw new ForbiddenException();
}
// input params
$photo_id = defaults($_REQUEST, 'photo_id', null);
@ -4223,17 +4416,14 @@ function api_fr_photo_delete($type)
if ($photo_id == null) {
throw new BadRequestException("no photo_id specified");
}
// check if photo is existing in database
$r = q(
"SELECT `id` FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'",
intval(api_user()),
DBA::escape($photo_id)
);
if (!DBA::isResult($r)) {
if (!Photo::exists(['resource-id' => $photo_id, 'uid' => api_user()])) {
throw new BadRequestException("photo not available");
}
// now we can perform on the deletion of the photo
$result = DBA::delete('photo', ['uid' => api_user(), 'resource-id' => $photo_id]);
$result = Photo::delete(['uid' => api_user(), 'resource-id' => $photo_id]);
// return success of deletion or error message
if ($result) {
@ -4261,6 +4451,10 @@ function api_fr_photo_delete($type)
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array
* @throws BadRequestException
* @throws ForbiddenException
* @throws InternalServerErrorException
* @throws NotFoundException
*/
function api_fr_photo_detail($type)
{
@ -4289,7 +4483,12 @@ function api_fr_photo_detail($type)
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
*
* @return string|array
* @see https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_image
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws NotFoundException
* @see https://developer.twitter.com/en/docs/accounts-and-users/manage-account-settings/api-reference/post-account-update_profile_image
*/
function api_account_update_profile_image($type)
{
@ -4343,10 +4542,10 @@ function api_account_update_profile_image($type)
// change specified profile or all profiles to the new resource-id
if ($is_default_profile) {
$condition = ["`profile` AND `resource-id` != ? AND `uid` = ?", $data['photo']['id'], api_user()];
DBA::update('photo', ['profile' => false], $condition);
Photo::update(['profile' => false], $condition);
} else {
$fields = ['photo' => System::baseUrl() . '/photo/' . $data['photo']['id'] . '-4.' . $filetype,
'thumb' => System::baseUrl() . '/photo/' . $data['photo']['id'] . '-5.' . $filetype];
$fields = ['photo' => System::baseUrl() . '/photo/' . $data['photo']['id'] . '-4.' . $fileext,
'thumb' => System::baseUrl() . '/photo/' . $data['photo']['id'] . '-5.' . $fileext];
DBA::update('profile', $fields, ['id' => $_REQUEST['profile'], 'uid' => api_user()]);
}
@ -4385,6 +4584,11 @@ api_register_func('api/account/update_profile_image', 'api_account_update_profil
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_account_update_profile($type)
{
@ -4419,6 +4623,8 @@ api_register_func('api/account/update_profile', 'api_account_update_profile', tr
/**
*
* @param string $acl_string
* @return bool
* @throws Exception
*/
function check_acl_input($acl_string)
{
@ -4455,6 +4661,12 @@ function check_acl_input($acl_string)
* @param integer $profile
* @param boolean $visibility
* @param string $photo_id
* @return array
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws NotFoundException
*/
function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $desc, $profile = 0, $visibility = false, $photo_id = null)
{
@ -4613,6 +4825,7 @@ function save_media_to_database($mediatype, $media, $type, $album, $allow_cid, $
* @param string $deny_gid
* @param string $filetype
* @param boolean $visibility
* @throws InternalServerErrorException
*/
function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $filetype, $visibility = false)
{
@ -4665,6 +4878,12 @@ function post_photo_item($hash, $allow_cid, $deny_cid, $allow_gid, $deny_gid, $f
* @param string $photo_id
*
* @return array
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws NotFoundException
* @throws UnauthorizedException
*/
function prepare_photo_data($type, $scale, $photo_id)
{
@ -4816,7 +5035,7 @@ function api_friendica_remoteauth()
'sec' => $sec, 'expire' => time() + 45];
DBA::insert('profile_check', $fields);
Logger::log($contact['name'] . ' ' . $sec, Logger::DEBUG);
Logger::info(API_LOG_PREFIX . 'for contact {contact}', ['module' => 'api', 'action' => 'friendica_remoteauth', 'contact' => $contact['name'], 'hey' => $sec]);
$dest = ($url ? '&destination_url=' . $url : '');
System::externalRedirect(
@ -4832,6 +5051,8 @@ api_register_func('api/friendica/remoteauth', 'api_friendica_remoteauth', true);
*
* @param array $item Sharer item
* @return array|false Shared item or false if not a reshare
* @throws ImagickException
* @throws InternalServerErrorException
*/
function api_share_as_retweet(&$item)
{
@ -4943,6 +5164,7 @@ function api_share_as_retweet(&$item)
* @param string $profile
*
* @return string|false
* @throws InternalServerErrorException
* @todo remove trailing junk from profile url
* @todo pump.io check has to check the website
*/
@ -5027,6 +5249,7 @@ function api_get_nick($profile)
* @param array $item
*
* @return array
* @throws Exception
*/
function api_in_reply_to($item)
{
@ -5065,7 +5288,7 @@ function api_in_reply_to($item)
// https://github.com/friendica/friendica/issues/1010
// This is a bugfix for that.
if (intval($in_reply_to['status_id']) == intval($item['id'])) {
Logger::log('this message should never appear: id: '.$item['id'].' similar to reply-to: '.$in_reply_to['status_id'], Logger::DEBUG);
Logger::warning(API_LOG_PREFIX . 'ID {id} is similar to reply-to {reply-to}', ['module' => 'api', 'action' => 'in_reply_to', 'id' => $item['id'], 'reply-to' => $in_reply_to['status_id']]);
$in_reply_to['status_id'] = null;
$in_reply_to['user_id'] = null;
$in_reply_to['status_id_str'] = null;
@ -5082,6 +5305,7 @@ function api_in_reply_to($item)
* @param string $text
*
* @return string
* @throws InternalServerErrorException
*/
function api_clean_plain_items($text)
{
@ -5108,6 +5332,7 @@ function api_clean_plain_items($text)
* @param string $body The original body
*
* @return string Cleaned body
* @throws InternalServerErrorException
*/
function api_clean_attachments($body)
{
@ -5136,7 +5361,7 @@ function api_clean_attachments($body)
*
* @param array $contacts
*
* @return array
* @return void
*/
function api_best_nickname(&$contacts)
{
@ -5206,6 +5431,11 @@ function api_best_nickname(&$contacts)
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_friendica_group_show($type)
{
@ -5271,6 +5501,11 @@ api_register_func('api/friendica/group_show', 'api_friendica_group_show', true);
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_friendica_group_delete($type)
{
@ -5332,6 +5567,11 @@ api_register_func('api/friendica/group_delete', 'api_friendica_group_delete', tr
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-destroy
*/
function api_lists_destroy($type)
@ -5376,10 +5616,11 @@ api_register_func('api/lists/destroy', 'api_lists_destroy', true, API_METHOD_DEL
* Add a new group to the database.
*
* @param string $name Group name
* @param int $uid User ID
* @param int $uid User ID
* @param array $users List of users to add to the group
*
* @return array
* @throws BadRequestException
*/
function group_create($name, $uid, $users = [])
{
@ -5449,6 +5690,11 @@ function group_create($name, $uid, $users = [])
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_friendica_group_create($type)
{
@ -5477,6 +5723,11 @@ api_register_func('api/friendica/group_create', 'api_friendica_group_create', tr
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-create
*/
function api_lists_create($type)
@ -5512,6 +5763,11 @@ api_register_func('api/lists/create', 'api_lists_create', true, API_METHOD_POST)
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_friendica_group_update($type)
{
@ -5585,6 +5841,11 @@ api_register_func('api/friendica/group_update', 'api_friendica_group_update', tr
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
* @see https://developer.twitter.com/en/docs/accounts-and-users/create-manage-lists/api-reference/post-lists-update
*/
function api_lists_update($type)
@ -5632,6 +5893,10 @@ api_register_func('api/lists/update', 'api_lists_update', true, API_METHOD_POST)
* @param string $type Return type (atom, rss, xml, json)
*
* @return array|string
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
*/
function api_friendica_activity($type)
{
@ -5676,7 +5941,10 @@ api_register_func('api/friendica/activity/unattendmaybe', 'api_friendica_activit
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array
*/
* @throws BadRequestException
* @throws ForbiddenException
* @throws InternalServerErrorException
*/
function api_friendica_notification($type)
{
$a = \get_app();
@ -5701,7 +5969,6 @@ function api_friendica_notification($type)
$notes = $xmlnotes;
}
return api_format_data("notes", $type, ['note' => $notes]);
}
@ -5712,6 +5979,11 @@ function api_friendica_notification($type)
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_friendica_notification_seen($type)
{
@ -5757,6 +6029,11 @@ api_register_func('api/friendica/notification', 'api_friendica_notification', tr
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array (success result=ok, error result=error with error message)
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_friendica_direct_messages_setseen($type)
{
@ -5801,11 +6078,16 @@ api_register_func('api/friendica/direct_messages_setseen', 'api_friendica_direct
/**
* @brief search for direct_messages containing a searchstring through api
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @param string $box
* @return string|array (success: success=true if found and search_result contains found messages,
* success=false if nothing was found, search_result='nothing found',
* error: result=error with error message)
* error: result=error with error message)
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_friendica_direct_messages_search($type, $box = "")
{
@ -5869,6 +6151,11 @@ api_register_func('api/friendica/direct_messages_search', 'api_friendica_direct_
*
* @param string $type Known types are 'atom', 'rss', 'xml' and 'json'
* @return string|array
* @throws BadRequestException
* @throws ForbiddenException
* @throws ImagickException
* @throws InternalServerErrorException
* @throws UnauthorizedException
*/
function api_friendica_profile_show($type)
{
@ -5950,6 +6237,7 @@ api_register_func('api/friendica/profile/show', 'api_friendica_profile_show', tr
* @param string $type Return format: json or xml
*
* @return string|array
* @throws Exception
*/
function api_saved_searches_list($type)
{
@ -5975,6 +6263,42 @@ function api_saved_searches_list($type)
/// @TODO move to top of file or somewhere better
api_register_func('api/saved_searches/list', 'api_saved_searches_list', true);
/*
* Bind comment numbers(friendica_comments: Int) on each statuses page of *_timeline / favorites / search
*
* @brief Number of comments
*
* @param object $data [Status, Status]
*
* @return void
*/
function bindComments(&$data)
{
if (count($data) == 0) {
return;
}
$ids = [];
$comments = [];
foreach ($data as $item) {
$ids[] = $item['id'];
}
$idStr = DBA::escape(implode(', ', $ids));
$sql = "SELECT `parent`, COUNT(*) as comments FROM `item` WHERE `parent` IN ($idStr) AND `deleted` = ? AND `gravity`= ? GROUP BY `parent`";
$items = DBA::p($sql, 0, GRAVITY_COMMENT);
$itemsData = DBA::toArray($items);
foreach ($itemsData as $item) {
$comments[$item['parent']] = $item['comments'];
}
foreach ($data as $idx => $item) {
$id = $item['id'];
$data[$idx]['friendica_comments'] = isset($comments[$id]) ? $comments[$id] : 0;
}
}
/*
@TODO Maybe open to implement?
To.Do:

View file

@ -8,8 +8,8 @@ use Friendica\Content\ContactSelector;
use Friendica\Content\Feature;
use Friendica\Content\Pager;
use Friendica\Content\Text\BBCode;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\PConfig;
@ -117,6 +117,10 @@ function item_redir_and_replace_images($body, $images, $cid) {
/**
* Render actions localized
*
* @param $item
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function localize_item(&$item)
{
@ -172,6 +176,7 @@ function localize_item(&$item)
$plink = '[url=' . $obj['plink'] . ']' . $post_type . '[/url]';
$bodyverb = '';
if (activity_match($item['verb'], ACTIVITY_LIKE)) {
$bodyverb = L10n::t('%1$s likes %2$s\'s %3$s');
} elseif (activity_match($item['verb'], ACTIVITY_DISLIKE)) {
@ -205,8 +210,8 @@ function localize_item(&$item)
foreach ($links->link as $l) {
$atts = $l->attributes();
switch ($atts['rel']) {
case "alternate": $Blink = $atts['href'];
case "photo": $Bphoto = $atts['href'];
case "alternate": $Blink = $atts['href']; break;
case "photo": $Bphoto = $atts['href']; break;
}
}
@ -360,13 +365,15 @@ function localize_item(&$item)
// Only create a redirection to a magic link when logged in
if (!empty($item['plink']) && (local_user() || remote_user())) {
$item['plink'] = Contact::magicLinkbyContact($author, $item['plink']);
$item['plink'] = Contact::magicLinkByContact($author, $item['plink']);
}
}
/**
* Count the total of comments on this item and its desendants
* @TODO proper type-hint + doc-tag
* @param $item
* @return int
*/
function count_descendants($item) {
$total = count($item['children']);
@ -436,7 +443,17 @@ function conv_get_blocklist()
* The $mode parameter decides between the various renderings and also
* figures out how to determine page owner and other contextual items
* that are based on unique features of the calling module.
*
* @param App $a
* @param array $items
* @param Pager $pager
* @param $mode
* @param $update
* @param bool $preview
* @param string $order
* @param int $uid
* @return string
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function conversation(App $a, array $items, Pager $pager, $mode, $update, $preview = false, $order = 'commented', $uid = 0)
{
@ -543,7 +560,7 @@ function conversation(App $a, array $items, Pager $pager, $mode, $update, $previ
}
$cb = ['items' => $items, 'mode' => $mode, 'update' => $update, 'preview' => $preview];
Addon::callHooks('conversation_start',$cb);
Hook::callAll('conversation_start',$cb);
$items = $cb['items'];
@ -608,14 +625,14 @@ function conversation(App $a, array $items, Pager $pager, $mode, $update, $previ
$author = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']];
$profile_link = Contact::magicLinkbyContact($author);
$profile_link = Contact::magicLinkByContact($author);
if (strpos($profile_link, 'redir/') === 0) {
$sparkle = ' sparkle';
}
$locate = ['location' => $item['location'], 'coord' => $item['coord'], 'html' => ''];
Addon::callHooks('render_location',$locate);
Hook::callAll('render_location',$locate);
$location = ((strlen($locate['html'])) ? $locate['html'] : render_location_dummy($locate));
@ -643,21 +660,12 @@ function conversation(App $a, array $items, Pager $pager, $mode, $update, $previ
list($categories, $folders) = get_cats_and_terms($item);
$profile_name_e = $profile_name;
if (!empty($item['content-warning']) && PConfig::get(local_user(), 'system', 'disable_cw', false)) {
$title_e = ucfirst($item['content-warning']);
$title = ucfirst($item['content-warning']);
} else {
$title_e = $item['title'];
$title = $item['title'];
}
$body_e = $body;
$tags_e = $tags['tags'];
$hashtags_e = $tags['hashtags'];
$mentions_e = $tags['mentions'];
$location_e = $location;
$owner_name_e = $owner_name;
$tmp_item = [
'template' => $tpl,
'id' => ($preview ? 'P0' : $item['id']),
@ -667,27 +675,28 @@ function conversation(App $a, array $items, Pager $pager, $mode, $update, $previ
'linktitle' => L10n::t('View %s\'s profile @ %s', $profile_name, $item['author-link']),
'profile_url' => $profile_link,
'item_photo_menu' => item_photo_menu($item),
'name' => $profile_name_e,
'name' => $profile_name,
'sparkle' => $sparkle,
'lock' => $lock,
'thumb' => System::removedBaseUrl(ProxyUtils::proxifyUrl($item['author-avatar'], false, ProxyUtils::SIZE_THUMB)),
'title' => $title_e,
'body' => $body_e,
'tags' => $tags_e,
'hashtags' => $hashtags_e,
'mentions' => $mentions_e,
'title' => $title,
'body' => $body,
'tags' => $tags['tags'],
'hashtags' => $tags['hashtags'],
'mentions' => $tags['mentions'],
'implicit_mentions' => $tags['implicit_mentions'],
'txt_cats' => L10n::t('Categories:'),
'txt_folders' => L10n::t('Filed under:'),
'has_cats' => ((count($categories)) ? 'true' : ''),
'has_folders' => ((count($folders)) ? 'true' : ''),
'categories' => $categories,
'folders' => $folders,
'text' => strip_tags($body_e),
'text' => strip_tags($body),
'localtime' => DateTimeFormat::local($item['created'], 'r'),
'ago' => (($item['app']) ? L10n::t('%s from %s', Temporal::getRelativeDate($item['created']),$item['app']) : Temporal::getRelativeDate($item['created'])),
'location' => $location_e,
'location' => $location,
'indent' => '',
'owner_name' => $owner_name_e,
'owner_name' => $owner_name,
'owner_url' => $owner_url,
'owner_photo' => System::removedBaseUrl(ProxyUtils::proxifyUrl($item['owner-avatar'], false, ProxyUtils::SIZE_THUMB)),
'plink' => Item::getPlink($item),
@ -706,7 +715,7 @@ function conversation(App $a, array $items, Pager $pager, $mode, $update, $previ
];
$arr = ['item' => $item, 'output' => $tmp_item];
Addon::callHooks('display_item', $arr);
Hook::callAll('display_item', $arr);
$threads[$threadsid]['id'] = $item['id'];
$threads[$threadsid]['network'] = $item['network'];
@ -743,7 +752,7 @@ function conversation(App $a, array $items, Pager $pager, $mode, $update, $previ
/// @todo Check if this call is needed or not
$arr = ['item' => $item];
Addon::callHooks('display_item', $arr);
Hook::callAll('display_item', $arr);
$item['pagedrop'] = $page_dropping;
@ -783,7 +792,11 @@ function conversation(App $a, array $items, Pager $pager, $mode, $update, $previ
*
* @param array $parents Parent items
*
* @param $block_authors
* @param $order
* @param $uid
* @return array items with parents and comments
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function conversation_add_children(array $parents, $block_authors, $order, $uid) {
$max_comments = Config::get('system', 'max_comments', 100);
@ -830,6 +843,8 @@ function item_photo_menu($item) {
$status_link = '';
$photos_link = '';
$posts_link = '';
$block_link = '';
$ignore_link = '';
if (local_user() && local_user() == $item['uid'] && $item['parent'] == $item['id'] && !$item['self']) {
$sub_link = 'javascript:dosubthread(' . $item['id'] . '); return false;';
@ -837,10 +852,11 @@ function item_photo_menu($item) {
$author = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']];
$profile_link = Contact::magicLinkbyContact($author);
$profile_link = Contact::magicLinkByContact($author, $item['author-link']);
$sparkle = (strpos($profile_link, 'redir/') === 0);
$cid = 0;
$pcid = Contact::getIdForURL($item['author-link'], 0, true);
$network = '';
$rel = 0;
$condition = ['uid' => local_user(), 'nurl' => Strings::normaliseLink($item['author-link'])];
@ -852,9 +868,16 @@ function item_photo_menu($item) {
}
if ($sparkle) {
$status_link = $profile_link . '?url=status';
$photos_link = $profile_link . '?url=photos';
$profile_link = $profile_link . '?url=profile';
$status_link = $profile_link . '?tab=status';
$photos_link = str_replace('/profile/', '/photos/', $profile_link);
$profile_link = $profile_link . '?=profile';
}
if (!empty($pcid)) {
$contact_url = 'contact/' . $pcid;
$posts_link = 'contact/' . $pcid . '/posts';
$block_link = 'contact/' . $pcid . '/block';
$ignore_link = 'contact/' . $pcid . '/ignore';
}
if ($cid && !$item['self']) {
@ -875,7 +898,9 @@ function item_photo_menu($item) {
L10n::t('View Photos') => $photos_link,
L10n::t('Network Posts') => $posts_link,
L10n::t('View Contact') => $contact_url,
L10n::t('Send PM') => $pm_url
L10n::t('Send PM') => $pm_url,
L10n::t('Block') => $block_link,
L10n::t('Ignore') => $ignore_link
];
if ($network == Protocol::DFRN) {
@ -892,7 +917,7 @@ function item_photo_menu($item) {
$args = ['item' => $item, 'menu' => $menu];
Addon::callHooks('item_photo_menu', $args);
Hook::callAll('item_photo_menu', $args);
$menu = $args['menu'];
@ -912,13 +937,14 @@ function item_photo_menu($item) {
* @brief Checks item to see if it is one of the builtin activities (like/dislike, event attendance, consensus items, etc.)
* Increments the count of each matching activity and adds a link to the author as needed.
*
* @param array $item
* @param array $item
* @param array &$conv_responses (already created with builtin activity structure)
* @return void
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function builtin_activity_puller($item, &$conv_responses) {
foreach ($conv_responses as $mode => $v) {
$url = '';
$sparkle = '';
switch ($mode) {
@ -944,7 +970,7 @@ function builtin_activity_puller($item, &$conv_responses) {
if (activity_match($item['verb'], $verb) && ($item['id'] != $item['parent'])) {
$author = ['uid' => 0, 'id' => $item['author-id'],
'network' => $item['author-network'], 'url' => $item['author-link']];
$url = Contact::magicLinkbyContact($author);
$url = Contact::magicLinkByContact($author);
if (strpos($url, 'redir/') === 0) {
$sparkle = ' class="sparkle" ';
}
@ -985,11 +1011,13 @@ function builtin_activity_puller($item, &$conv_responses) {
/**
* Format the vote text for a profile item
* @param int $cnt = number of people who vote the item
* @param array $arr = array of pre-linked names of likers/dislikers
*
* @param int $cnt = number of people who vote the item
* @param array $arr = array of pre-linked names of likers/dislikers
* @param string $type = one of 'like, 'dislike', 'attendyes', 'attendno', 'attendmaybe'
* @param int $id = item id
* @param int $id = item id
* @return string formatted text
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function format_like($cnt, array $arr, $type, $id) {
$o = '';
@ -1022,23 +1050,19 @@ function format_like($cnt, array $arr, $type, $id) {
if ($cnt > 1) {
$total = count($arr);
if ($total >= MAX_LIKERS) {
$arr = array_slice($arr, 0, MAX_LIKERS - 1);
}
if ($total < MAX_LIKERS) {
$last = L10n::t('and') . ' ' . $arr[count($arr)-1];
$arr2 = array_slice($arr, 0, -1);
$str = implode(', ', $arr2) . ' ' . $last;
$likers = implode(', ', $arr2) . ' ' . $last;
} else {
$arr = array_slice($arr, 0, MAX_LIKERS - 1);
$likers = implode(', ', $arr);
$likers .= L10n::t('and %d other people', $total - MAX_LIKERS);
}
if ($total >= MAX_LIKERS) {
$str = implode(', ', $arr);
$str .= L10n::t('and %d other people', $total - MAX_LIKERS);
}
$likers = $str;
$spanatts = "class=\"fakelink\" onclick=\"openClose('{$type}list-$id');\"";
$explikers = '';
switch ($type) {
case 'like':
$phrase = L10n::t('<span %1$s>%2$d people</span> like this', $spanatts, $cnt);
@ -1062,10 +1086,9 @@ function format_like($cnt, array $arr, $type, $id) {
break;
}
$expanded .= "\t" . '<div class="wall-item-' . $type . '-expanded" id="' . $type . 'list-' . $id . '" style="display: none;" >' . $explikers . EOL . '</div>';
$expanded .= "\t" . '<p class="wall-item-' . $type . '-expanded" id="' . $type . 'list-' . $id . '" style="display: none;" >' . $explikers . EOL . '</p>';
}
$phrase .= EOL;
$o .= Renderer::replaceMacros(Renderer::getMarkupTemplate('voting_fakelink.tpl'), [
'$phrase' => $phrase,
'$type' => $type,
@ -1097,7 +1120,7 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false)
]);
$jotplugins = '';
Addon::callHooks('jot_tool', $jotplugins);
Hook::callAll('jot_tool', $jotplugins);
// Private/public post links for the non-JS ACL form
$private_post = 1;
@ -1199,8 +1222,8 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false)
*
* @param array $item_list
* @param array $parent
* @param bool $recursive
* @return type
* @param bool $recursive
* @return array
*/
function get_item_children(array &$item_list, array $parent, $recursive = true)
{
@ -1330,6 +1353,7 @@ function smart_flatten_conversation(array $parent)
* @param array $item_list A list of items belonging to one or more conversations
* @param string $order Either on "created" or "commented"
* @return array
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function conv_sort(array $item_list, $order)
{
@ -1425,7 +1449,7 @@ function sort_thr_created_rev(array $a, array $b)
*
* @param array $a
* @param array $b
* @return type
* @return int
*/
function sort_thr_commented(array $a, array $b)
{
@ -1442,7 +1466,7 @@ function render_location_dummy(array $item) {
}
}
function get_responses(array $conv_responses, array $response_verbs, $ob, array $item) {
function get_responses(array $conv_responses, array $response_verbs, array $item, Post $ob = null) {
$ret = [];
foreach ($response_verbs as $v) {
$ret[$v] = [];
@ -1473,6 +1497,7 @@ function get_responses(array $conv_responses, array $response_verbs, $ob, array
function get_response_button_text($v, $count)
{
$return = '';
switch ($v) {
case 'like':
$return = L10n::tt('Like', 'Likes', $count);

View file

@ -9,8 +9,9 @@ use Friendica\Database\DBA;
* DBA::select, DBA::exists, DBA::insert
* DBA::delete, DBA::update, DBA::p, DBA::e
*
* @param $args Query parameters (1 to N parameters of different types)
* @param $sql
* @return array|bool Query array
* @throws Exception
* @deprecated
*/
function q($sql) {

View file

@ -4,15 +4,15 @@
*/
use Friendica\Content\Text\BBCode;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Item;
use Friendica\Model\User;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Emailer;
use Friendica\Util\Strings;
@ -21,18 +21,20 @@ use Friendica\Util\Strings;
* @brief Creates a notification entry and possibly sends a mail
*
* @param array $params Array with the elements:
* uid, item, parent, type, otype, verb, event,
* link, subject, body, to_name, to_email, source_name,
* source_link, activity, preamble, notify_flags,
* language, show_in_notification_page
* uid, item, parent, type, otype, verb, event,
* link, subject, body, to_name, to_email, source_name,
* source_link, activity, preamble, notify_flags,
* language, show_in_notification_page
* @return bool
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function notification($params)
{
$a = \get_app();
// Temporary logging for finding the origin
if (!isset($params['language']) || !isset($params['uid'])) {
Logger::log('Missing parameters.' . System::callstack());
if (!isset($params['uid'])) {
Logger::notice('Missing parameters "uid".', ['params' => $params, 'callstack' => System::callstack()]);
}
// Ensure that the important fields are set at any time
@ -40,8 +42,8 @@ function notification($params)
$user = DBA::selectFirst('user', $fields, ['uid' => $params['uid']]);
if (!DBA::isResult($user)) {
Logger::log('Unknown user ' . $params['uid']);
return;
Logger::error('Unknown user', ['uid' => $params['uid']]);
return false;
}
$params['notify_flags'] = defaults($params, 'notify_flags', $user['notify-flags']);
@ -76,8 +78,8 @@ function notification($params)
['uid' => $params['uid']]);
// There is no need to create notifications for forum accounts
if (!DBA::isResult($user) || in_array($user["page-flags"], [Contact::PAGE_COMMUNITY, Contact::PAGE_PRVGROUP])) {
return;
if (!DBA::isResult($user) || in_array($user["page-flags"], [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP])) {
return false;
}
$nickname = $user["nickname"];
} else {
@ -118,6 +120,12 @@ function notification($params)
}
$epreamble = '';
$preamble = '';
$subject = '';
$sitelink = '';
$tsitelink = '';
$hsitelink = '';
$itemlink = '';
if ($params['type'] == NOTIFY_MAIL) {
$itemlink = $siteurl.'/message/'.$params['item']['id'];
@ -126,19 +134,19 @@ function notification($params)
$subject = L10n::t('[Friendica:Notify] New mail received at %s', $sitename);
$preamble = L10n::t('%1$s sent you a new private message at %2$s.', $params['source_name'], $sitename);
$epreamble = L10n::t('%1$s sent you %2$s.', '[url='.$params['source_link'].']'.$params['source_name'].'[/url]', '[url=$itemlink]'.L10n::t('a private message').'[/url]');
$epreamble = L10n::t('%1$s sent you %2$s.', '[url='.$params['source_link'].']'.$params['source_name'].'[/url]', '[url=' . $itemlink . ']'.L10n::t('a private message').'[/url]');
$sitelink = L10n::t('Please visit %s to view and/or reply to your private messages.');
$tsitelink = sprintf($sitelink, $siteurl.'/message/'.$params['item']['id']);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'/message/'.$params['item']['id'].'">'.$sitename.'</a>');
}
if ($params['type'] == NOTIFY_COMMENT) {
$thread = Item::selectFirstThreadForUser($params['uid'] ,['ignored'], ['iid' => $parent_id]);
if (DBA::isResult($thread) && $thread["ignored"]) {
Logger::log("Thread ".$parent_id." will be ignored", Logger::DEBUG);
if ($params['type'] == NOTIFY_COMMENT || $params['type'] == NOTIFY_TAGSELF) {
$thread = Item::selectFirstThreadForUser($params['uid'], ['ignored'], ['iid' => $parent_id]);
if (DBA::isResult($thread) && $thread['ignored']) {
Logger::log('Thread ' . $parent_id . ' will be ignored', Logger::DEBUG);
L10n::popLang();
return;
return false;
}
// Check to see if there was already a tag notify or comment notify for this post.
@ -147,13 +155,11 @@ function notification($params)
'link' => $params['link'], 'uid' => $params['uid']];
if (DBA::exists('notify', $condition)) {
L10n::popLang();
return;
return false;
}
// if it's a post figure out who's post it is.
$item = null;
if ($params['otype'] === 'item' && $parent_id) {
$item = Item::selectFirstForUser($params['uid'], Item::ITEM_FIELDLIST, ['id' => $parent_id]);
}
@ -162,44 +168,92 @@ function notification($params)
$itemlink = $item['plink'];
// "a post"
$dest_str = L10n::t('%1$s commented on [url=%2$s]a %3$s[/url]',
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$itemlink,
$item_post_type
);
// "George Bull's post"
if ($item) {
$dest_str = L10n::t('%1$s commented on [url=%2$s]%3$s\'s %4$s[/url]',
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
if ($params['type'] == NOTIFY_TAGSELF) {
$dest_str = L10n::t('%1$s tagged you on [url=%2$s]a %3$s[/url]',
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$itemlink,
$item['author-name'],
$item_post_type
);
} else {
$dest_str = L10n::t('%1$s commented on [url=%2$s]a %3$s[/url]',
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$itemlink,
$item_post_type
);
}
// "George Bull's post"
if (DBA::isResult($item)) {
if ($params['type'] == NOTIFY_TAGSELF) {
$dest_str = L10n::t('%1$s tagged you on [url=%2$s]%3$s\'s %4$s[/url]',
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$itemlink,
$item['author-name'],
$item_post_type
);
} else {
$dest_str = L10n::t('%1$s commented on [url=%2$s]%3$s\'s %4$s[/url]',
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$itemlink,
$item['author-name'],
$item_post_type
);
}
}
// "your post"
if (DBA::isResult($item) && $item['owner-id'] == $item['author-id'] && $item['wall']) {
$dest_str = L10n::t('%1$s commented on [url=%2$s]your %3$s[/url]',
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$itemlink,
$item_post_type
);
if ($params['type'] == NOTIFY_TAGSELF) {
$dest_str = L10n::t('%1$s tagged you on [url=%2$s]your %3$s[/url]',
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$itemlink,
$item_post_type
);
} else {
$dest_str = L10n::t('%1$s commented on [url=%2$s]your %3$s[/url]',
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$itemlink,
$item_post_type
);
}
}
// Some mail softwares relies on subject field for threading.
// "their post"
if (DBA::isResult($item) && $item['author-link'] == $params['source_link']) {
if ($params['type'] == NOTIFY_TAGSELF) {
$dest_str = L10n::t('%1$s tagged you on [url=%2$s]their %3$s[/url]',
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$itemlink,
$item_post_type
);
} else {
$dest_str = L10n::t('%1$s commented on [url=%2$s]their %3$s[/url]',
'[url=' . $params['source_link'] . ']' . $params['source_name'] . '[/url]',
$itemlink,
$item_post_type
);
}
}
// Some mail software relies on subject field for threading.
// So, we cannot have different subjects for notifications of the same thread.
// Before this we have the name of the replier on the subject rendering
// differents subjects for messages on the same thread.
// different subjects for messages on the same thread.
if ($params['type'] == NOTIFY_TAGSELF) {
$subject = L10n::t('[Friendica:Notify] %s tagged you', $params['source_name']);
$subject = L10n::t('[Friendica:Notify] Comment to conversation #%1$d by %2$s', $parent_id, $params['source_name']);
$preamble = L10n::t('%1$s tagged you at %2$s', $params['source_name'], $sitename);
} else {
$subject = L10n::t('[Friendica:Notify] Comment to conversation #%1$d by %2$s', $parent_id, $params['source_name']);
$preamble = L10n::t('%s commented on an item/conversation you have been following.', $params['source_name']);
}
$preamble = L10n::t('%s commented on an item/conversation you have been following.', $params['source_name']);
$epreamble = $dest_str;
$sitelink = L10n::t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$hsitelink = sprintf($sitelink, '<a href="' . $siteurl . '">' . $sitename . '</a>');
$itemlink = $params['link'];
}
@ -218,21 +272,6 @@ function notification($params)
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_TAGSELF) {
$subject = L10n::t('[Friendica:Notify] %s tagged you', $params['source_name']);
$preamble = L10n::t('%1$s tagged you at %2$s', $params['source_name'], $sitename);
$epreamble = L10n::t('%1$s [url=%2$s]tagged you[/url].',
'[url='.$params['source_link'].']'.$params['source_name'].'[/url]',
$params['link']
);
$sitelink = L10n::t('Please visit %s to view and/or reply to the conversation.');
$tsitelink = sprintf($sitelink, $siteurl);
$hsitelink = sprintf($sitelink, '<a href="'.$siteurl.'">'.$sitename.'</a>');
$itemlink = $params['link'];
}
if ($params['type'] == NOTIFY_SHARE) {
$subject = L10n::t('[Friendica:Notify] %s shared a new post', $params['source_name']);
@ -414,16 +453,21 @@ function notification($params)
// It will be used by the system to send emails to users (like
// password reset, invitations and so) using one look (but without
// add a notification to the user, with could be inexistent)
$subject = $params['subject'];
if (!isset($params['subject'])) {
Logger::warning('subject isn\'t set.', ['type' => $params['type']]);
}
$subject = defaults($params, 'subject', '');
$preamble = $params['preamble'];
if (!isset($params['preamble'])) {
Logger::warning('preamble isn\'t set.', ['type' => $params['type'], 'subject' => $subject]);
}
$preamble = defaults($params, 'preamble', '');
$body = $params['body'];
if (!isset($params['body'])) {
Logger::warning('body isn\'t set.', ['type' => $params['type'], 'subject' => $subject, 'preamble' => $preamble]);
}
$body = defaults($params, 'body', '');
$sitelink = "";
$tsitelink = "";
$hsitelink = "";
$itemlink = "";
$show_in_notification_page = false;
}
@ -441,7 +485,7 @@ function notification($params)
'itemlink' => $itemlink
];
Addon::callHooks('enotify', $h);
Hook::callAll('enotify', $h);
$subject = $h['subject'];
@ -454,6 +498,8 @@ function notification($params)
$hsitelink = $h['hsitelink'];
$itemlink = $h['itemlink'];
$notify_id = 0;
if ($show_in_notification_page) {
Logger::log("adding notification entry", Logger::DEBUG);
do {
@ -481,11 +527,11 @@ function notification($params)
$datarray['otype'] = $params['otype'];
$datarray['abort'] = false;
Addon::callHooks('enotify_store', $datarray);
Hook::callAll('enotify_store', $datarray);
if ($datarray['abort']) {
L10n::popLang();
return False;
return false;
}
// create notification entry in DB
@ -584,7 +630,7 @@ function notification($params)
$datarray['subject'] = $subject;
$datarray['headers'] = $additional_mail_header;
Addon::callHooks('enotify_mail', $datarray);
Hook::callAll('enotify_mail', $datarray);
// check whether sending post content in email notifications is allowed
// always true for SYSTEM_EMAIL
@ -634,8 +680,7 @@ function notification($params)
L10n::popLang();
// use the Emailer class to send the message
return Emailer::send(
[
return Emailer::send([
'uid' => $params['uid'],
'fromName' => $sender_name,
'fromEmail' => $sender_email,
@ -644,8 +689,8 @@ function notification($params)
'messageSubject' => $datarray['subject'],
'htmlVersion' => $email_html_body,
'textVersion' => $email_text_body,
'additionalMailHeader' => $datarray['headers']]
);
'additionalMailHeader' => $datarray['headers']
]);
}
L10n::popLang();
@ -656,6 +701,7 @@ function notification($params)
* @brief Checks for users who should be notified
*
* @param int $itemid ID of the item for which the check should be done
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function check_user_notification($itemid) {
// fetch all users in the thread
@ -671,13 +717,15 @@ function check_user_notification($itemid) {
/**
* @brief Checks for item related notifications and sends them
*
* @param int $itemid ID of the item for which the check should be done
* @param int $uid User ID
* @param int $itemid ID of the item for which the check should be done
* @param int $uid User ID
* @param string $defaulttype (Optional) Forces a notification with this type.
* @return bool
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function check_item_notification($itemid, $uid, $defaulttype = "") {
$notification_data = ["uid" => $uid, "profiles" => []];
Addon::callHooks('check_item_notification', $notification_data);
Hook::callAll('check_item_notification', $notification_data);
$profiles = $notification_data["profiles"];
@ -736,9 +784,9 @@ function check_item_notification($itemid, $uid, $defaulttype = "") {
'author-link', 'author-name', 'author-avatar', 'author-id',
'guid', 'parent-uri', 'uri', 'contact-id', 'network'];
$condition = ['id' => $itemid, 'gravity' => [GRAVITY_PARENT, GRAVITY_COMMENT]];
$item = Item::selectFirst($fields, $condition);
$item = Item::selectFirstForUser($uid, $fields, $condition);
if (!DBA::isResult($item) || in_array($item['author-id'], $contacts)) {
return;
return false;
}
// Generate the notification array

View file

@ -5,8 +5,8 @@
use Friendica\BaseObject;
use Friendica\Content\Feature;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\PConfig;
@ -24,10 +24,11 @@ use Friendica\Util\ParseUrl;
use Friendica\Util\Strings;
use Friendica\Util\Temporal;
require_once 'mod/share.php';
require_once __DIR__ . '/../mod/share.php';
function add_page_info_data(array $data, $no_photos = false)
{
Addon::callHooks('page_info_data', $data);
Hook::callAll('page_info_data', $data);
if (empty($data['type'])) {
return '';
@ -242,26 +243,26 @@ function add_page_info_to_body($body, $texturl = false, $no_photos = false)
* 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, $datedir = 0, $pass = 0)
function consume_feed($xml, array $importer, array $contact, &$hub)
{
if ($contact['network'] === Protocol::OSTATUS) {
if ($pass < 2) {
// Test - remove before flight
//$tempfile = tempnam(get_temppath(), "ostatus2");
//file_put_contents($tempfile, $xml);
Logger::log("Consume OStatus messages ", Logger::DEBUG);
OStatus::import($xml, $importer, $contact, $hub);
}
Logger::log("Consume OStatus messages ", Logger::DEBUG);
OStatus::import($xml, $importer, $contact, $hub);
return;
}
if ($contact['network'] === Protocol::FEED) {
if ($pass < 2) {
Logger::log("Consume feeds", Logger::DEBUG);
Feed::import($xml, $importer, $contact, $hub);
}
Logger::log("Consume feeds", Logger::DEBUG);
Feed::import($xml, $importer, $contact, $hub);
return;
}
@ -293,8 +294,6 @@ function subscribe_to_hub($url, array $importer, array $contact, $hubmode = 'sub
return;
}
$a = BaseObject::getApp();
$user = DBA::selectFirst('user', ['nickname'], ['uid' => $importer['uid']]);
// No user, no nickname, we quit

View file

@ -4,31 +4,14 @@
*/
use Friendica\App;
use Friendica\Content\ContactSelector;
use Friendica\Content\Feature;
use Friendica\Content\Smilies;
use Friendica\Content\Text\BBCode;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\PConfig;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Event;
use Friendica\Model\Item;
use Friendica\Render\FriendicaSmarty;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Map;
use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Core\Logger;
use Friendica\Core\Renderer;
use Friendica\Model\FileTag;
use Friendica\Util\Strings;
use Friendica\Util\XML;
use Friendica\Content\Text\HTML;
/**
* Turn user/group ACLs stored as angle bracketed text into arrays
@ -139,7 +122,7 @@ function qp($s) {
*/
function redir_private_images($a, &$item)
{
$matches = false;
$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) {
@ -160,6 +143,7 @@ function redir_private_images($a, &$item)
*
* @param string $text String with bbcode.
* @return string Formattet HTML.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function prepare_text($text) {
if (stristr($text, '[nosmile]')) {
@ -203,7 +187,7 @@ function get_cats_and_terms($item)
$categories = [];
$folders = [];
$matches = false;
$matches = [];
$first = true;
$cnt = preg_match_all('/<(.*?)>/', $item['file'], $matches, PREG_SET_ORDER);
if ($cnt) {
@ -224,7 +208,7 @@ function get_cats_and_terms($item)
}
if (local_user() == $item['uid']) {
$matches = false;
$matches = [];
$first = true;
$cnt = preg_match_all('/\[(.*?)\]/', $item['file'], $matches, PREG_SET_ORDER);
if ($cnt) {
@ -251,7 +235,7 @@ function get_cats_and_terms($item)
/**
* return number of bytes in size (K, M, G)
* @param string $size_str
* @return number
* @return int
*/
function return_bytes($size_str) {
switch (substr ($size_str, -1)) {

View file

@ -4,14 +4,15 @@
* Friendica
*/
use Friendica\Factory;
if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
die('Vendor path not found. Please execute "bin/composer.phar --no-dev install" on the command line in the web root.');
}
require __DIR__ . '/vendor/autoload.php';
// We assume that the index.php is called by a frontend process
// The value is set to "true" by default in App
$a = new Friendica\App(__DIR__, false);
$a = Factory\DependencyFactory::setUp('index', __DIR__, false);
$a->runFrontend();

View file

@ -91,7 +91,6 @@ abstract class OAuthSignatureMethod {
*/
public function check_signature($request, $consumer, $token, $signature) {
$built = $this->build_signature($request, $consumer, $token);
//echo "<pre>"; var_dump($signature, $built, ($built == $signature)); killme();
return ($built == $signature);
}
}
@ -296,7 +295,6 @@ class OAuthRequest {
$http_url = substr($http_url, 0, strpos($http_url,$parameters['pagename'])+strlen($parameters['pagename']));
unset( $parameters['pagename'] );
//echo "<pre>".__function__."\n"; var_dump($http_method, $http_url, $parameters, $_SERVER['REQUEST_URI']); killme();
return new OAuthRequest($http_method, $http_url, $parameters);
}
@ -561,7 +559,6 @@ class OAuthServer {
public function verify_request(&$request) {
$this->get_version($request);
$consumer = $this->get_consumer($request);
//echo __file__.__line__.__function__."<pre>"; var_dump($consumer); die();
$token = $this->get_token($request, $consumer, "access");
$this->check_signature($request, $consumer, $token);
return array($consumer, $token);

View file

@ -27,7 +27,6 @@ function _well_known_init(App $a)
}
}
System::httpExit(404);
killme();
}
function wk_social_relay()

View file

@ -5,7 +5,7 @@
use Friendica\App;
use Friendica\Content\Widget;
use Friendica\Core\ACL;
use Friendica\Core\Addon;
use Friendica\Core\Hook;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Database\DBA;
@ -34,7 +34,7 @@ function acl_content(App $a)
$search = $_REQUEST['query'];
}
Logger::log("Searching for ".$search." - type ".$type." conversation ".$conv_id, Logger::DEBUG);
Logger::info('ACL {action} - {subaction}', ['module' => 'acl', 'action' => 'content', 'subaction' => 'search', 'search' => $search, 'type' => $type, 'conversation' => $conv_id]);
if ($search != '') {
$sql_extra = "AND `name` LIKE '%%" . DBA::escape($search) . "%%'";
@ -305,7 +305,7 @@ function acl_content(App $a)
'search' => $search,
];
Addon::callHooks('acl_lookup_end', $results);
Hook::callAll('acl_lookup_end', $results);
$o = [
'tot' => $results['tot'],

View file

@ -15,6 +15,7 @@ use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\Renderer;
use Friendica\Core\StorageManager;
use Friendica\Core\System;
use Friendica\Core\Theme;
use Friendica\Core\Update;
@ -25,13 +26,17 @@ use Friendica\Model\Contact;
use Friendica\Model\Item;
use Friendica\Model\Register;
use Friendica\Model\User;
use Friendica\Module;
use Friendica\Module\Login;
use Friendica\Module\Tos;
use Friendica\Protocol\PortableContact;
use Friendica\Util\Arrays;
use Friendica\Util\BasePath;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Strings;
use Friendica\Util\Temporal;
use Psr\Log\LogLevel;
/**
* Sets the current theme for theme settings pages.
@ -61,7 +66,8 @@ function admin_init(App $a)
* return the HTML for the pages of the admin panel.
*
* @param App $a
*
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_post(App $a)
{
@ -160,6 +166,7 @@ function admin_post(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_content(App $a)
{
@ -300,8 +307,7 @@ function admin_content(App $a)
if ($a->isAjax()) {
echo $o;
killme();
return '';
exit();
} else {
return $o;
}
@ -312,6 +318,7 @@ function admin_content(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_tos(App $a)
{
@ -334,6 +341,7 @@ function admin_page_tos(App $a)
* @brief Process send data from Admin TOS Page
*
* @param App $a
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_tos_post(App $a)
{
@ -366,6 +374,7 @@ function admin_page_tos_post(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_blocklist(App $a)
{
@ -406,6 +415,7 @@ function admin_page_blocklist(App $a)
* @brief Process send data from Admin Blocklist Page
*
* @param App $a
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_blocklist_post(App $a)
{
@ -450,6 +460,8 @@ function admin_page_blocklist_post(App $a)
* @brief Process data send by the contact block admin page
*
* @param App $a
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_contactblock_post(App $a)
{
@ -482,6 +494,7 @@ function admin_page_contactblock_post(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_contactblock(App $a)
{
@ -534,6 +547,7 @@ function admin_page_contactblock(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_deleteitem(App $a)
{
@ -558,6 +572,7 @@ function admin_page_deleteitem(App $a)
* URLs like the full /display URL to make the process more easy for the admin.
*
* @param App $a
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_deleteitem_post(App $a)
{
@ -597,6 +612,7 @@ function admin_page_deleteitem_post(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_federation(App $a)
{
@ -783,6 +799,7 @@ function admin_page_federation(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_queue(App $a)
{
@ -825,7 +842,9 @@ function admin_page_queue(App $a)
* The returned string holds the content of the page.
*
* @param App $a
* @param $deferred
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_workerqueue(App $a, $deferred)
{
@ -875,6 +894,7 @@ function admin_page_workerqueue(App $a, $deferred)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_summary(App $a)
{
@ -897,7 +917,7 @@ function admin_page_summary(App $a)
}
if (Config::get('system', 'dbupdate', DBStructure::UPDATE_NOT_CHECKED) == DBStructure::UPDATE_NOT_CHECKED) {
DBStructure::update(false, true);
DBStructure::update($a->getBasePath(), false, true);
}
if (Config::get('system', 'dbupdate') == DBStructure::UPDATE_FAILED) {
$showwarning = true;
@ -918,6 +938,10 @@ function admin_page_summary(App $a)
$showwarning = true;
$warningtext[] = L10n::t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from <code>.htconfig.php</code>. See <a href="%s">the Config help page</a> for help with the transition.', $a->getBaseURL() . '/help/Config');
}
if (file_exists('config/local.ini.php')) {
$showwarning = true;
$warningtext[] = L10n::t('Friendica\'s configuration now is stored in config/local.config.php, please copy config/local-sample.config.php and move your config from <code>config/local.ini.php</code>. See <a href="%s">the Config help page</a> for help with the transition.', $a->getBaseURL() . '/help/Config');
}
// Check server vitality
if (!admin_page_server_vital()) {
@ -993,6 +1017,7 @@ function admin_page_summary(App $a)
* @brief Process send data from Admin Site Page
*
* @param App $a
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_site_post(App $a)
{
@ -1085,7 +1110,7 @@ function admin_page_site_post(App $a)
$banner = (!empty($_POST['banner']) ? trim($_POST['banner']) : false);
$shortcut_icon = (!empty($_POST['shortcut_icon']) ? Strings::escapeTags(trim($_POST['shortcut_icon'])) : '');
$touch_icon = (!empty($_POST['touch_icon']) ? Strings::escapeTags(trim($_POST['touch_icon'])) : '');
$info = (!empty($_POST['info']) ? trim($_POST['info']) : false);
$additional_info = (!empty($_POST['additional_info']) ? trim($_POST['additional_info']) : '');
$language = (!empty($_POST['language']) ? Strings::escapeTags(trim($_POST['language'])) : '');
$theme = (!empty($_POST['theme']) ? Strings::escapeTags(trim($_POST['theme'])) : '');
$theme_mobile = (!empty($_POST['theme_mobile']) ? Strings::escapeTags(trim($_POST['theme_mobile'])) : '');
@ -1124,14 +1149,14 @@ function admin_page_site_post(App $a)
$proxyuser = (!empty($_POST['proxyuser']) ? Strings::escapeTags(trim($_POST['proxyuser'])) : '');
$proxy = (!empty($_POST['proxy']) ? Strings::escapeTags(trim($_POST['proxy'])) : '');
$timeout = (!empty($_POST['timeout']) ? intval(trim($_POST['timeout'])) : 60);
$maxloadavg = (!empty($_POST['maxloadavg']) ? intval(trim($_POST['maxloadavg'])) : 50);
$maxloadavg = (!empty($_POST['maxloadavg']) ? intval(trim($_POST['maxloadavg'])) : 20);
$maxloadavg_frontend = (!empty($_POST['maxloadavg_frontend']) ? intval(trim($_POST['maxloadavg_frontend'])) : 50);
$min_memory = (!empty($_POST['min_memory']) ? intval(trim($_POST['min_memory'])) : 0);
$optimize_max_tablesize = (!empty($_POST['optimize_max_tablesize']) ? intval(trim($_POST['optimize_max_tablesize'])) : 100);
$optimize_fragmentation = (!empty($_POST['optimize_fragmentation']) ? intval(trim($_POST['optimize_fragmentation'])) : 30);
$poco_completion = (!empty($_POST['poco_completion']) ? intval(trim($_POST['poco_completion'])) : false);
$poco_requery_days = (!empty($_POST['poco_requery_days']) ? intval(trim($_POST['poco_requery_days'])) : 7);
$poco_discovery = (!empty($_POST['poco_discovery']) ? intval(trim($_POST['poco_discovery'])) : 0);
$poco_discovery = (!empty($_POST['poco_discovery']) ? intval(trim($_POST['poco_discovery'])) : PortableContact::DISABLED);
$poco_discovery_since = (!empty($_POST['poco_discovery_since']) ? intval(trim($_POST['poco_discovery_since'])) : 30);
$poco_local_search = !empty($_POST['poco_local_search']);
$nodeinfo = !empty($_POST['nodeinfo']);
@ -1171,6 +1196,45 @@ function admin_page_site_post(App $a)
$relay_user_tags = !empty($_POST['relay_user_tags']);
$active_panel = (!empty($_POST['active_panel']) ? "#" . Strings::escapeTags(trim($_POST['active_panel'])) : '');
/**
* @var $storagebackend \Friendica\Model\Storage\IStorage
*/
$storagebackend = Strings::escapeTags(trim(defaults($_POST, 'storagebackend', '')));
if (!StorageManager::setBackend($storagebackend)) {
info(L10n::t('Invalid storage backend setting value.'));
}
// save storage backend form
if (!is_null($storagebackend) && $storagebackend != "") {
$storage_opts = $storagebackend::getOptions();
$storage_form_prefix=preg_replace('|[^a-zA-Z0-9]|' ,'', $storagebackend);
$storage_opts_data = [];
foreach($storage_opts as $name => $info) {
$fieldname = $storage_form_prefix . '_' . $name;
switch ($info[0]) { // type
case 'checkbox':
case 'yesno':
$value = !empty($_POST[$fieldname]);
break;
default:
$value = defaults($_POST, $fieldname, '');
}
$storage_opts_data[$name] = $value;
}
unset($name);
unset($info);
$storage_form_errors = $storagebackend::saveOptions($storage_opts_data);
if (count($storage_form_errors)) {
foreach($storage_form_errors as $name => $err) {
notice('Storage backend, ' . $storage_opts[$name][1] . ': ' . $err);
}
$a->internalRedirect('admin/site' . $active_panel);
}
}
// Has the directory url changed? If yes, then resubmit the existing profiles there
if ($global_directory != Config::get('system', 'directory') && ($global_directory != '')) {
Config::set('system', 'directory', $global_directory);
@ -1244,10 +1308,10 @@ function admin_page_site_post(App $a)
Config::set('system', 'banner', $banner);
}
if ($info == "") {
if (empty($additional_info)) {
Config::delete('config', 'info');
} else {
Config::set('config', 'info', $info);
Config::set('config', 'info', $additional_info);
}
Config::set('system', 'language', $language);
Config::set('system', 'theme', $theme);
@ -1315,7 +1379,7 @@ function admin_page_site_post(App $a)
Config::set('system', 'dbclean-expire-unclaimed', $dbclean_unclaimed);
if ($itemcache != '') {
$itemcache = App::getRealPath($itemcache);
$itemcache = BasePath::getRealPath($itemcache);
}
Config::set('system', 'itemcache', $itemcache);
@ -1323,13 +1387,13 @@ function admin_page_site_post(App $a)
Config::set('system', 'max_comments', $max_comments);
if ($temppath != '') {
$temppath = App::getRealPath($temppath);
$temppath = BasePath::getRealPath($temppath);
}
Config::set('system', 'temppath', $temppath);
if ($basepath != '') {
$basepath = App::getRealPath($basepath);
$basepath = BasePath::getRealPath($basepath);
}
Config::set('system', 'basepath' , $basepath);
@ -1363,6 +1427,7 @@ function admin_page_site_post(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_site(App $a)
{
@ -1415,10 +1480,10 @@ function admin_page_site(App $a)
];
$poco_discovery_choices = [
"0" => L10n::t("Disabled"),
"1" => L10n::t("Users"),
"2" => L10n::t("Users, Global Contacts"),
"3" => L10n::t("Users, Global Contacts/fallback"),
PortableContact::DISABLED => L10n::t("Disabled"),
PortableContact::USERS => L10n::t("Users"),
PortableContact::USERS_GCONTACTS => L10n::t("Users, Global Contacts"),
PortableContact::USERS_GCONTACTS_FALLBACK => L10n::t("Users, Global Contacts/fallback"),
];
$poco_discovery_since_choices = [
@ -1444,7 +1509,7 @@ function admin_page_site(App $a)
$banner = '<a href="https://friendi.ca"><img id="logo-img" src="images/friendica-32.png" alt="logo" /></a><span id="logo-text"><a href="https://friendi.ca">Friendica</a></span>';
}
$info = Config::get('config', 'info');
$additional_info = Config::get('config', 'info');
// Automatically create temporary paths
get_temppath();
@ -1454,9 +1519,9 @@ function admin_page_site(App $a)
/* Register policy */
$register_choices = [
REGISTER_CLOSED => L10n::t("Closed"),
REGISTER_APPROVE => L10n::t("Requires approval"),
REGISTER_OPEN => L10n::t("Open")
Module\Register::CLOSED => L10n::t("Closed"),
Module\Register::APPROVE => L10n::t("Requires approval"),
Module\Register::OPEN => L10n::t("Open")
];
$ssl_choices = [
@ -1482,6 +1547,36 @@ function admin_page_site(App $a)
$optimize_max_tablesize = -1;
}
/* storage backend */
$storage_backends = StorageManager::listBackends();
/**
* @var $storage_current_backend \Friendica\Model\Storage\IStorage
*/
$storage_current_backend = StorageManager::getBackend();
$storage_backends_choices = [
'' => L10n::t('Database (legacy)')
];
foreach($storage_backends as $name=>$class) {
$storage_backends_choices[$class] = $name;
}
unset($storage_backends);
// build storage config form,
$storage_form_prefix=preg_replace('|[^a-zA-Z0-9]|' ,'', $storage_current_backend);
$storage_form = [];
if (!is_null($storage_current_backend) && $storage_current_backend != "") {
foreach ($storage_current_backend::getOptions() as $name => $info) {
$type = $info[0];
$info[0] = $storage_form_prefix . '_' . $name;
$info['type'] = $type;
$info['field'] = 'field_' . $type . '.tpl';
$storage_form[$name] = $info;
}
}
$t = Renderer::getMarkupTemplate('admin/site.tpl');
return Renderer::replaceMacros($t, [
'$title' => L10n::t('Administration'),
@ -1507,7 +1602,7 @@ function admin_page_site(App $a)
'$banner' => ['banner', L10n::t("Banner/Logo"), $banner, ""],
'$shortcut_icon' => ['shortcut_icon', L10n::t("Shortcut icon"), Config::get('system', 'shortcut_icon'), L10n::t("Link to an icon that will be used for browsers.")],
'$touch_icon' => ['touch_icon', L10n::t("Touch icon"), Config::get('system', 'touch_icon'), L10n::t("Link to an icon that will be used for tablets and mobiles.")],
'$info' => ['info', L10n::t('Additional Info'), $info, L10n::t('For public servers: you can add additional information here that will be listed at %s/servers.', get_server())],
'$additional_info' => ['additional_info', L10n::t('Additional Info'), $additional_info, L10n::t('For public servers: you can add additional information here that will be listed at %s/servers.', get_server())],
'$language' => ['language', L10n::t("System language"), Config::get('system', 'language'), "", $lang_choices],
'$theme' => ['theme', L10n::t("System theme"), Config::get('system', 'theme'), L10n::t("Default system theme - may be over-ridden by user profiles - <a href='#' id='cnftheme'>change theme settings</a>"), $theme_choices],
'$theme_mobile' => ['theme_mobile', L10n::t("Mobile system theme"), Config::get('system', 'mobile-theme', '---'), L10n::t("Theme for mobile devices"), $theme_choices_mobile],
@ -1515,6 +1610,9 @@ function admin_page_site(App $a)
'$force_ssl' => ['force_ssl', L10n::t("Force SSL"), Config::get('system', 'force_ssl'), L10n::t("Force all Non-SSL requests to SSL - Attention: on some systems it could lead to endless loops.")],
'$hide_help' => ['hide_help', L10n::t("Hide help entry from navigation menu"), Config::get('system', 'hide_help'), L10n::t("Hides the menu entry for the Help pages from the navigation menu. You can still access it calling /help directly.")],
'$singleuser' => ['singleuser', L10n::t("Single user instance"), Config::get('system', 'singleuser', '---'), L10n::t("Make this instance multi-user or single-user for the named user"), $user_names],
'$storagebackend' => ['storagebackend', L10n::t("File storage backend"), $storage_current_backend, L10n::t('The backend used to store uploaded data. If you change the storage backend, you can manually move the existing files. If you do not do so, the files uploaded before the change will still be available at the old backend. Please see <a href="/help/Settings#1_2_3_1">the settings documentation</a> for more information about the choices and the moving procedure.'), $storage_backends_choices],
'$storageform' => $storage_form,
'$maximagesize' => ['maximagesize', L10n::t("Maximum image size"), Config::get('system', 'maximagesize'), L10n::t("Maximum size in bytes of uploaded images. Default is 0, which means no limits.")],
'$maximagelength' => ['maximagelength', L10n::t("Maximum image length"), Config::get('system', 'max_image_length'), L10n::t("Maximum length in pixels of the longest side of uploaded images. Default is -1, which means no limits.")],
'$jpegimagequality' => ['jpegimagequality', L10n::t("JPEG image quality"), Config::get('system', 'jpeg_quality'), L10n::t("Uploaded JPEGS will be saved at this quality setting [0-100]. Default is 100, which is full quality.")],
@ -1553,7 +1651,7 @@ function admin_page_site(App $a)
'$proxyuser' => ['proxyuser', L10n::t("Proxy user"), Config::get('system', 'proxyuser'), ""],
'$proxy' => ['proxy', L10n::t("Proxy URL"), Config::get('system', 'proxy'), ""],
'$timeout' => ['timeout', L10n::t("Network timeout"), Config::get('system', 'curl_timeout', 60), L10n::t("Value is in seconds. Set to 0 for unlimited \x28not recommended\x29.")],
'$maxloadavg' => ['maxloadavg', L10n::t("Maximum Load Average"), Config::get('system', 'maxloadavg', 50), L10n::t("Maximum system load before delivery and poll processes are deferred - default 50.")],
'$maxloadavg' => ['maxloadavg', L10n::t("Maximum Load Average"), Config::get('system', 'maxloadavg', 20), L10n::t("Maximum system load before delivery and poll processes are deferred - default %d.", 20)],
'$maxloadavg_frontend' => ['maxloadavg_frontend', L10n::t("Maximum Load Average \x28Frontend\x29"), Config::get('system', 'maxloadavg_frontend', 50), L10n::t("Maximum system load before the frontend quits service - default 50.")],
'$min_memory' => ['min_memory', L10n::t("Minimal Memory"), Config::get('system', 'min_memory', 0), L10n::t("Minimal free memory in MB for the worker. Needs access to /proc/meminfo - default 0 \x28deactivated\x29.")],
'$optimize_max_tablesize' => ['optimize_max_tablesize', L10n::t("Maximum table size for optimization"), $optimize_max_tablesize, L10n::t("Maximum table size \x28in MB\x29 for the automatic optimization. Enter -1 to disable it.")],
@ -1561,7 +1659,7 @@ function admin_page_site(App $a)
'$poco_completion' => ['poco_completion', L10n::t("Periodical check of global contacts"), Config::get('system', 'poco_completion'), L10n::t("If enabled, the global contacts are checked periodically for missing or outdated data and the vitality of the contacts and servers.")],
'$poco_requery_days' => ['poco_requery_days', L10n::t("Days between requery"), Config::get('system', 'poco_requery_days'), L10n::t("Number of days after which a server is requeried for his contacts.")],
'$poco_discovery' => ['poco_discovery', L10n::t("Discover contacts from other servers"), (string)intval(Config::get('system', 'poco_discovery')), L10n::t("Periodically query other servers for contacts. You can choose between 'users': the users on the remote system, 'Global Contacts': active contacts that are known on the system. The fallback is meant for Redmatrix servers and older friendica servers, where global contacts weren't available. The fallback increases the server load, so the recommened setting is 'Users, Global Contacts'."), $poco_discovery_choices],
'$poco_discovery' => ['poco_discovery', L10n::t("Discover contacts from other servers"), (string)intval(Config::get('system', 'poco_discovery')), L10n::t("Periodically query other servers for contacts. You can choose between 'users': the users on the remote system, 'Global Contacts': active contacts that are known on the system. The fallback is meant for Redmatrix servers and older friendica servers, where global contacts weren't available. The fallback increases the server load, so the recommended setting is 'Users, Global Contacts'."), $poco_discovery_choices],
'$poco_discovery_since' => ['poco_discovery_since', L10n::t("Timeframe for fetching global contacts"), (string)intval(Config::get('system', 'poco_discovery_since')), L10n::t("When the discovery is activated, this value defines the timeframe for the activity of the global contacts that are fetched from other servers."), $poco_discovery_since_choices],
'$poco_local_search' => ['poco_local_search', L10n::t("Search the local directory"), Config::get('system', 'poco_local_search'), L10n::t("Search the local directory instead of the global directory. When searching locally, every search will be executed on the global directory in the background. This improves the search results when the search is repeated.")],
@ -1613,7 +1711,8 @@ function admin_page_site(App $a)
*
* @param App $a
* @return string
* */
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_dbsync(App $a)
{
$o = '';
@ -1629,7 +1728,7 @@ function admin_page_dbsync(App $a)
}
if (($a->argc > 2) && (intval($a->argv[2]) || ($a->argv[2] === 'check'))) {
$retval = DBStructure::update(false, true);
$retval = DBStructure::update($a->getBasePath(), false, true);
if ($retval === '') {
$o .= L10n::t("Database structure update %s was successfully applied.", DB_UPDATE_VERSION) . "<br />";
Config::set('database', 'last_successful_update', DB_UPDATE_VERSION);
@ -1703,6 +1802,7 @@ function admin_page_dbsync(App $a)
* @brief Process data send by Users admin page
*
* @param App $a
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_users_post(App $a)
{
@ -1820,6 +1920,7 @@ function admin_page_users_post(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_users(App $a)
{
@ -1897,17 +1998,18 @@ function admin_page_users(App $a)
$adminlist = explode(",", str_replace(" ", "", Config::get('config', 'admin_email')));
$_setup_users = function ($e) use ($adminlist) {
$page_types = [
Contact::PAGE_NORMAL => L10n::t('Normal Account Page'),
Contact::PAGE_SOAPBOX => L10n::t('Soapbox Page'),
Contact::PAGE_COMMUNITY => L10n::t('Public Forum'),
Contact::PAGE_FREELOVE => L10n::t('Automatic Friend Page'),
Contact::PAGE_PRVGROUP => L10n::t('Private Forum')
User::PAGE_FLAGS_NORMAL => L10n::t('Normal Account Page'),
User::PAGE_FLAGS_SOAPBOX => L10n::t('Soapbox Page'),
User::PAGE_FLAGS_COMMUNITY => L10n::t('Public Forum'),
User::PAGE_FLAGS_FREELOVE => L10n::t('Automatic Friend Page'),
User::PAGE_FLAGS_PRVGROUP => L10n::t('Private Forum')
];
$account_types = [
Contact::ACCOUNT_TYPE_PERSON => L10n::t('Personal Page'),
Contact::ACCOUNT_TYPE_ORGANISATION => L10n::t('Organisation Page'),
Contact::ACCOUNT_TYPE_NEWS => L10n::t('News Page'),
Contact::ACCOUNT_TYPE_COMMUNITY => L10n::t('Community Forum')
User::ACCOUNT_TYPE_PERSON => L10n::t('Personal Page'),
User::ACCOUNT_TYPE_ORGANISATION => L10n::t('Organisation Page'),
User::ACCOUNT_TYPE_NEWS => L10n::t('News Page'),
User::ACCOUNT_TYPE_COMMUNITY => L10n::t('Community Forum'),
User::ACCOUNT_TYPE_RELAY => L10n::t('Relay'),
];
$e['page_flags_raw'] = $e['page-flags'];
@ -2018,6 +2120,7 @@ function admin_page_users(App $a)
* @param App $a
* @param array $addons_admin A list of admin addon names
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_addons(App $a, array $addons_admin)
{
@ -2223,6 +2326,7 @@ function rebuild_theme_table($themes)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_themes(App $a)
{
@ -2393,6 +2497,7 @@ function admin_page_themes(App $a)
* @brief Prosesses data send by Logs admin page
*
* @param App $a
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_logs_post(App $a)
{
@ -2401,7 +2506,7 @@ function admin_page_logs_post(App $a)
$logfile = (!empty($_POST['logfile']) ? Strings::escapeTags(trim($_POST['logfile'])) : '');
$debugging = !empty($_POST['debugging']);
$loglevel = (!empty($_POST['loglevel']) ? intval(trim($_POST['loglevel'])) : 0);
$loglevel = defaults($_POST, 'loglevel', LogLevel::ERROR);
Config::set('system', 'logfile', $logfile);
Config::set('system', 'debugging', $debugging);
@ -2428,16 +2533,16 @@ function admin_page_logs_post(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_logs(App $a)
{
$log_choices = [
Logger::WARNING => 'Warning',
Logger::INFO => 'Info',
Logger::TRACE => 'Trace',
Logger::DEBUG => 'Debug',
Logger::DATA => 'Data',
Logger::ALL => 'All'
LogLevel::ERROR => 'Error',
LogLevel::WARNING => 'Warning',
LogLevel::NOTICE => 'Notice',
LogLevel::INFO => 'Info',
LogLevel::DEBUG => 'Debug',
];
if (ini_get('log_errors')) {
@ -2484,6 +2589,7 @@ function admin_page_logs(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_viewlogs(App $a)
{
@ -2527,6 +2633,7 @@ function admin_page_viewlogs(App $a)
* @brief Prosesses data send by the features admin page
*
* @param App $a
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_features_post(App $a)
{
@ -2574,6 +2681,7 @@ function admin_page_features_post(App $a)
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function admin_page_features(App $a)
{

View file

@ -60,8 +60,6 @@ function allfriends_content(App $a)
//get further details of the contact
$contact_details = Model\Contact::getDetailsByURL($rr['url'], $uid, $rr);
$photo_menu = '';
$connlnk = '';
// $rr[cid] is only available for common contacts. So if the contact is a common one, use contact_photo_menu to generate the photo_menu
// If the contact is not common to the user, Connect/Follow' will be added to the photo menu

View file

@ -1,7 +1,5 @@
<?php
use Friendica\App;
function amcd_content()
{
echo <<< JSON
@ -47,5 +45,5 @@ function amcd_content()
}
}
JSON;
killme();
exit();
}

View file

@ -6,16 +6,13 @@ use Friendica\App;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Module\Login;
require_once 'include/api.php';
function oauth_get_client($request)
function oauth_get_client(OAuthRequest $request)
{
$params = $request->get_parameters();
$token = $params['oauth_token'];
@ -59,7 +56,7 @@ function api_content(App $a)
} catch (Exception $e) {
echo "<pre>";
var_dump($e);
killme();
exit();
}
if (!empty($_POST['oauth_yes'])) {
@ -79,7 +76,7 @@ function api_content(App $a)
$glue = "?";
}
$a->internalRedirect($consumer->callback_url . $glue . 'oauth_token=' . OAuthUtil::urlencode_rfc3986($params['oauth_token']) . '&oauth_verifier=' . OAuthUtil::urlencode_rfc3986($verifier));
killme();
exit();
}
$tpl = Renderer::getMarkupTemplate("oauth_authorize_done.tpl");
@ -117,5 +114,5 @@ function api_content(App $a)
}
echo api_call($a);
killme();
exit();
}

View file

@ -1,54 +0,0 @@
<?php
/**
* @file mod/attach.php
*/
use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Database\DBA;
use Friendica\Util\Security;
function attach_init(App $a)
{
if ($a->argc != 2) {
notice(L10n::t('Item not available.') . EOL);
return;
}
$item_id = intval($a->argv[1]);
// Check for existence, which will also provide us the owner uid
$r = DBA::selectFirst('attach', [], ['id' => $item_id]);
if (!DBA::isResult($r)) {
notice(L10n::t('Item was not found.'). EOL);
return;
}
$sql_extra = Security::getPermissionsSQLByUserId($r['uid']);
// Now we'll see if we can access the attachment
$r = q("SELECT * FROM `attach` WHERE `id` = '%d' $sql_extra LIMIT 1",
DBA::escape($item_id)
);
if (!DBA::isResult($r)) {
notice(L10n::t('Permission denied.') . EOL);
return;
}
// Use quotes around the filename to prevent a "multiple Content-Disposition"
// error in Chrome for filenames with commas in them
header('Content-type: ' . $r[0]['filetype']);
header('Content-length: ' . $r[0]['filesize']);
if (isset($_GET['attachment']) && $_GET['attachment'] === '0') {
header('Content-disposition: filename="' . $r[0]['filename'] . '"');
} else {
header('Content-disposition: attachment; filename="' . $r[0]['filename'] . '"');
}
echo $r[0]['data'];
killme();
// NOTREACHED
}

View file

@ -72,6 +72,21 @@ function babel_content()
'title' => L10n::t('BBCode::toMarkdown => Markdown::convert => HTML::toBBCode'),
'content' => visible_whitespace($bbcode4)
];
$item = [
'body' => $bbcode,
'tag' => '',
];
\Friendica\Model\Item::setHashtags($item);
$results[] = [
'title' => L10n::t('Item Body'),
'content' => visible_whitespace($item['body'])
];
$results[] = [
'title' => L10n::t('Item Tags'),
'content' => $item['tag']
];
break;
case 'markdown':
$markdown = trim($_REQUEST['text']);
@ -83,7 +98,7 @@ function babel_content()
$html = Text\Markdown::convert($markdown);
$results[] = [
'title' => L10n::t('Markdown::convert (raw HTML)'),
'content' => htmlspecialchars($html)
'content' => visible_whitespace(htmlspecialchars($html))
];
$results[] = [

View file

@ -20,7 +20,7 @@ function bookmarklet_content(App $a)
{
if (!local_user()) {
$o = '<h2>' . L10n::t('Login') . '</h2>';
$o .= Login::form($a->query_string, intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED ? false : true);
$o .= Login::form($a->query_string, intval(Config::get('config', 'register_policy')) === \Friendica\Module\Register::CLOSED ? false : true);
return $o;
}

View file

@ -23,7 +23,6 @@ use Friendica\Model\Profile;
use Friendica\Protocol\DFRN;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Temporal;
use Friendica\Util\Security;
function cal_init(App $a)
{
@ -244,7 +243,7 @@ function cal_content(App $a)
if (!empty($a->argv[2]) && ($a->argv[2] === 'json')) {
echo json_encode($events);
killme();
exit();
}
// links: array('href', 'text', 'extra css classes', 'title')
@ -286,7 +285,7 @@ function cal_content(App $a)
if (!empty($_GET['id'])) {
echo $o;
killme();
exit();
}
return $o;
@ -331,7 +330,7 @@ function cal_content(App $a)
header('Content-type: text/calendar');
header('content-disposition: attachment; filename="' . L10n::t('calendar') . '-' . $nick . '.' . $evexport["extension"] . '"');
echo $evexport["content"];
killme();
exit();
}
return;

View file

@ -14,6 +14,7 @@ use Friendica\Core\Renderer;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Item;
use Friendica\Model\User;
function community_init(App $a)
{
@ -44,16 +45,16 @@ function community_content(App $a, $update = 0)
if ($a->argc > 2) {
switch ($a->argv[2]) {
case 'person':
$accounttype = Contact::ACCOUNT_TYPE_PERSON;
$accounttype = User::ACCOUNT_TYPE_PERSON;
break;
case 'organisation':
$accounttype = Contact::ACCOUNT_TYPE_ORGANISATION;
$accounttype = User::ACCOUNT_TYPE_ORGANISATION;
break;
case 'news':
$accounttype = Contact::ACCOUNT_TYPE_NEWS;
$accounttype = User::ACCOUNT_TYPE_NEWS;
break;
case 'community':
$accounttype = Contact::ACCOUNT_TYPE_COMMUNITY;
$accounttype = User::ACCOUNT_TYPE_COMMUNITY;
break;
}
}
@ -218,9 +219,9 @@ function community_getitems($start, $itemspage, $content, $accounttype)
}
$r = DBA::p("SELECT `item`.`uri`, `author`.`url` AS `author-link` FROM `thread`
INNER JOIN `user` ON `user`.`uid` = `thread`.`uid` AND NOT `user`.`hidewall`
INNER JOIN `item` ON `item`.`id` = `thread`.`iid`
INNER JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id`
STRAIGHT_JOIN `user` ON `user`.`uid` = `thread`.`uid` AND NOT `user`.`hidewall`
STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid`
STRAIGHT_JOIN `contact` AS `author` ON `author`.`id`=`item`.`author-id`
WHERE `thread`.`visible` AND NOT `thread`.`deleted` AND NOT `thread`.`moderated`
AND NOT `thread`.`private` AND `thread`.`wall` AND `thread`.`origin` $sql_accounttype
ORDER BY `thread`.`commented` DESC LIMIT ?, ?", $values);

View file

@ -1,53 +0,0 @@
<?php
use Friendica\App;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Group;
function contactgroup_content(App $a)
{
if (!local_user()) {
killme();
}
$change = null;
if (($a->argc > 2) && intval($a->argv[1]) && intval($a->argv[2])) {
$r = q("SELECT `id` FROM `contact` WHERE `id` = %d AND `uid` = %d and `self` = 0 and `blocked` = 0 AND `pending` = 0 LIMIT 1",
intval($a->argv[2]),
intval(local_user())
);
if (DBA::isResult($r)) {
$change = intval($a->argv[2]);
}
}
if (($a->argc > 1) && (intval($a->argv[1]))) {
$r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1",
intval($a->argv[1]),
intval(local_user())
);
if (!DBA::isResult($r)) {
killme();
}
$group = $r[0];
$members = Contact::getByGroupId($group['id']);
$preselected = [];
if (count($members)) {
foreach ($members as $member) {
$preselected[] = $member['id'];
}
}
if (!empty($change)) {
if (in_array($change, $preselected)) {
Group::removeMember($group['id'], $change);
} else {
Group::addMember($group['id'], $change);
}
}
}
killme();
}

View file

@ -5,7 +5,7 @@
* (only contributors to the git repositories for friendica core and the
* addons repository will be listed though ATM)
*/
use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;

View file

@ -19,20 +19,6 @@ function crepair_init(App $a)
if (!local_user()) {
return;
}
$contact = null;
if (($a->argc == 2) && intval($a->argv[1])) {
$contact = DBA::selectFirst('contact', [], ['uid' => local_user(), 'id' => $a->argv[1]]);
}
if (empty($a->page['aside'])) {
$a->page['aside'] = '';
}
if (DBA::isResult($contact)) {
$a->data['contact'] = $contact;
Model\Profile::load($a, "", 0, Model\Contact::getDetailsByURL($contact["url"]));
}
}
function crepair_post(App $a)
@ -55,6 +41,7 @@ function crepair_post(App $a)
$name = defaults($_POST, 'name' , $contact['name']);
$nick = defaults($_POST, 'nick' , '');
$url = defaults($_POST, 'url' , '');
$alias = defaults($_POST, 'alias' , '');
$request = defaults($_POST, 'request' , '');
$confirm = defaults($_POST, 'confirm' , '');
$notify = defaults($_POST, 'notify' , '');
@ -64,20 +51,22 @@ function crepair_post(App $a)
$remote_self = defaults($_POST, 'remote_self', false);
$nurl = Strings::normaliseLink($url);
$r = q("UPDATE `contact` SET `name` = '%s', `nick` = '%s', `url` = '%s', `nurl` = '%s', `request` = '%s', `confirm` = '%s', `notify` = '%s', `poll` = '%s', `attag` = '%s' , `remote_self` = %d
WHERE `id` = %d AND `uid` = %d",
DBA::escape($name),
DBA::escape($nick),
DBA::escape($url),
DBA::escape($nurl),
DBA::escape($request),
DBA::escape($confirm),
DBA::escape($notify),
DBA::escape($poll),
DBA::escape($attag),
intval($remote_self),
intval($contact['id']),
local_user()
$r = DBA::update(
'contact',
[
'name' => $name,
'nick' => $nick,
'url' => $url,
'nurl' => $nurl,
'alias' => $alias,
'request' => $request,
'confirm' => $confirm,
'notify' => $notify,
'poll' => $poll,
'attag' => $attag,
'remote_self' => $remote_self,
],
['id' => $contact['id'], 'uid' => local_user()]
);
if ($photo) {
@ -114,6 +103,15 @@ function crepair_content(App $a)
return;
}
if (empty($a->page['aside'])) {
$a->page['aside'] = '';
}
if (DBA::isResult($contact)) {
$a->data['contact'] = $contact;
Model\Profile::load($a, "", 0, Model\Contact::getDetailsByURL($contact["url"]));
}
$warning = L10n::t('<strong>WARNING: This is highly advanced</strong> and if you enter incorrect information your communications with this contact may stop working.');
$info = L10n::t('Please use your browser \'Back\' button <strong>now</strong> if you are uncertain what to do on this page.');
@ -162,6 +160,7 @@ function crepair_content(App $a)
'$nick' => ['nick', L10n::t('Account Nickname'), $contact['nick']],
'$attag' => ['attag', L10n::t('@Tagname - overrides Name/Nickname'), $contact['attag']],
'$url' => ['url', L10n::t('Account URL'), $contact['url']],
'$alias' => ['alias', L10n::t('Account URL Alias'), $contact['alias']],
'$request' => ['request', L10n::t('Friend Request URL'), $contact['request']],
'confirm' => ['confirm', L10n::t('Friend Confirm URL'), $contact['confirm']],
'notify' => ['notify', L10n::t('Notification Endpoint URL'), $contact['notify']],

View file

@ -11,14 +11,13 @@ use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\User;
use Friendica\Util\Security;
use Friendica\Util\Strings;
require_once 'mod/settings.php';
function delegate_init(App $a)
{
return settings_init($a);
settings_init($a);
}
function delegate_post(App $a)

View file

@ -202,11 +202,11 @@ function dfrn_confirm_post(App $a, $handsfree = null)
$params['duplex'] = 1;
}
if ($user['page-flags'] == Contact::PAGE_COMMUNITY) {
if ($user['page-flags'] == User::PAGE_FLAGS_COMMUNITY) {
$params['page'] = 1;
}
if ($user['page-flags'] == Contact::PAGE_PRVGROUP) {
if ($user['page-flags'] == User::PAGE_FLAGS_PRVGROUP) {
$params['page'] = 2;
}

View file

@ -12,6 +12,7 @@ use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\User;
use Friendica\Protocol\DFRN;
use Friendica\Protocol\Diaspora;
use Friendica\Util\Strings;
@ -253,7 +254,6 @@ function dfrn_notify_content(App $a) {
*/
$dfrn_id = Strings::escapeTags(trim($_GET['dfrn_id']));
$dfrn_version = (float) $_GET['dfrn_version'];
$rino_remote = (!empty($_GET['rino']) ? intval($_GET['rino']) : 0);
$type = "";
$last_update = "";
@ -281,7 +281,7 @@ function dfrn_notify_content(App $a) {
$user = DBA::selectFirst('user', ['uid'], ['nickname' => $a->argv[1]]);
if (!DBA::isResult($user)) {
Logger::log('User not found for nickname ' . $a->argv[1]);
killme();
exit();
}
$condition = [];
@ -300,6 +300,7 @@ function dfrn_notify_content(App $a) {
break;
default:
$status = 1;
$my_id = '';
break;
}
@ -313,7 +314,7 @@ function dfrn_notify_content(App $a) {
$importer = DFRN::getImporter($contact['id'], $user['uid']);
if (empty($importer)) {
Logger::log('No importer data found for user ' . $a->argv[1] . ' and contact ' . $dfrn_id);
killme();
exit();
}
Logger::log("Remote rino version: ".$rino_remote." for ".$importer["url"], Logger::DATA);
@ -352,7 +353,7 @@ function dfrn_notify_content(App $a) {
$rino = $rino_remote;
}
if (($importer['rel'] && ($importer['rel'] != Contact::SHARING)) || ($importer['page-flags'] == Contact::PAGE_COMMUNITY)) {
if (($importer['rel'] && ($importer['rel'] != Contact::SHARING)) || ($importer['page-flags'] == User::PAGE_FLAGS_COMMUNITY)) {
$perm = 'rw';
} else {
$perm = 'r';
@ -370,6 +371,6 @@ function dfrn_notify_content(App $a) {
. "\t" . '<challenge>' . $challenge . '</challenge>' . "\r\n"
. '</dfrn_notify>' . "\r\n";
killme();
exit();
}
}

View file

@ -28,7 +28,6 @@ function dfrn_poll_init(App $a)
$challenge = defaults($_GET, 'challenge' , '');
$sec = defaults($_GET, 'sec' , '');
$dfrn_version = (float) defaults($_GET, 'dfrn_version' , 2.0);
$perm = defaults($_GET, 'perm' , 'r');
$quiet = !empty($_GET['quiet']);
// Possibly it is an OStatus compatible server that requests a user feed
@ -37,7 +36,7 @@ function dfrn_poll_init(App $a)
$nickname = $a->argv[1];
header("Content-type: application/atom+xml");
echo OStatus::feed($nickname, $last_update, 10);
killme();
exit();
}
$direction = -1;
@ -71,7 +70,7 @@ function dfrn_poll_init(App $a)
Logger::log('dfrn_poll: public feed request from ' . $_SERVER['REMOTE_ADDR'] . ' for ' . $user);
header("Content-type: application/atom+xml");
echo DFRN::feed('', $user, $last_update, 0, $hidewall);
killme();
exit();
}
if (($type === 'profile') && (!strlen($sec))) {
@ -198,7 +197,7 @@ function dfrn_poll_init(App $a)
header("Content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?><dfrn_poll><status>0</status><challenge>$decoded_challenge</challenge><sec>$sec</sec></dfrn_poll>";
killme();
exit();
// NOTREACHED
} else {
// old protocol
@ -290,7 +289,7 @@ function dfrn_poll_post(App $a)
header("Content-type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?><dfrn_poll><status>0</status><challenge>$decoded_challenge</challenge><sec>$sec</sec></dfrn_poll>";
killme();
exit();
// NOTREACHED
}
}
@ -307,7 +306,7 @@ function dfrn_poll_post(App $a)
);
if (!DBA::isResult($r)) {
killme();
exit();
}
$type = $r[0]['type'];
@ -319,15 +318,12 @@ function dfrn_poll_post(App $a)
switch ($direction) {
case -1:
$sql_extra = sprintf(" AND `issued-id` = '%s' ", DBA::escape($dfrn_id));
$my_id = $dfrn_id;
break;
case 0:
$sql_extra = sprintf(" AND `issued-id` = '%s' AND `duplex` = 1 ", DBA::escape($dfrn_id));
$my_id = '1:' . $dfrn_id;
break;
case 1:
$sql_extra = sprintf(" AND `dfrn-id` = '%s' AND `duplex` = 1 ", DBA::escape($dfrn_id));
$my_id = '0:' . $dfrn_id;
break;
default:
$a->internalRedirect();
@ -336,7 +332,7 @@ function dfrn_poll_post(App $a)
$r = q("SELECT * FROM `contact` WHERE `blocked` = 0 AND `pending` = 0 $sql_extra LIMIT 1");
if (!DBA::isResult($r)) {
killme();
exit();
}
$contact = $r[0];
@ -368,7 +364,7 @@ function dfrn_poll_post(App $a)
<description>$text</description>
</reputation>
";
killme();
exit();
// NOTREACHED
} else {
// Update the writable flag if it changed
@ -391,7 +387,7 @@ function dfrn_poll_post(App $a)
header("Content-type: application/atom+xml");
$o = DFRN::feed($dfrn_id, $a->argv[1], $last_update, $direction);
echo $o;
killme();
exit();
}
}
@ -420,7 +416,7 @@ function dfrn_poll_content(App $a)
DBA::delete('challenge', ["`expire` < ?", time()]);
if ($type !== 'profile') {
$r = q("INSERT INTO `challenge` ( `challenge`, `dfrn-id`, `expire` , `type`, `last_update` )
q("INSERT INTO `challenge` ( `challenge`, `dfrn-id`, `expire` , `type`, `last_update` )
VALUES( '%s', '%s', '%s', '%s', '%s' ) ",
DBA::escape($hash),
DBA::escape($dfrn_id),
@ -573,7 +569,7 @@ function dfrn_poll_content(App $a)
. "\t" . '<dfrn_id>' . $encrypted_id . '</dfrn_id>' . "\r\n"
. "\t" . '<challenge>' . $challenge . '</challenge>' . "\r\n"
. '</dfrn_poll>' . "\r\n";
killme();
exit();
// NOTREACHED
}
}

View file

@ -34,9 +34,9 @@ function dfrn_request_init(App $a)
{
if ($a->argc > 1) {
$which = $a->argv[1];
Profile::load($a, $which);
}
Profile::load($a, $which);
return;
}
@ -54,6 +54,9 @@ function dfrn_request_init(App $a)
* in order to link our friend request with our own server cell.
* After logging in, we click 'submit' to approve the linkage.
*
* @param App $a
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function dfrn_request_post(App $a)
{
@ -165,7 +168,7 @@ function dfrn_request_post(App $a)
$r = q("SELECT `id`, `network` FROM `contact` WHERE `uid` = %d AND `url` = '%s' AND `site-pubkey` = '%s' LIMIT 1",
intval(local_user()),
DBA::escape($dfrn_url),
$parms['key'] // this was already escaped
defaults($parms, 'key', '') // Potentially missing
);
if (DBA::isResult($r)) {
Group::addMember(User::getDefaultGroup(local_user(), $r[0]["network"]), $r[0]['id']);
@ -184,8 +187,8 @@ function dfrn_request_post(App $a)
$dfrn_request = $contact_record['request'];
}
if (strlen($dfrn_request) && strlen($confirm_key)) {
$s = Network::fetchUrl($dfrn_request . '?confirm_key=' . $confirm_key);
if (!empty($dfrn_request) && strlen($confirm_key)) {
Network::fetchUrl($dfrn_request . '?confirm_key=' . $confirm_key);
}
// (ignore reply, nothing we can do it failed)
@ -227,7 +230,6 @@ function dfrn_request_post(App $a)
}
$nickname = $a->profile['nickname'];
$notify_flags = $a->profile['notify-flags'];
$uid = $a->profile['uid'];
$maxreq = intval($a->profile['maxreq']);
$contact_record = null;
@ -268,8 +270,6 @@ function dfrn_request_post(App $a)
}
}
$real_name = !empty($_POST['realname']) ? Strings::escapeTags(trim($_POST['realname'])) : '';
$url = trim($_POST['dfrn_url']);
if (!strlen($url)) {
notice(L10n::t("Invalid locator") . EOL);
@ -417,7 +417,7 @@ function dfrn_request_post(App $a)
$hash = Strings::getRandomHex() . (string) time(); // Generate a confirm_key
if (is_array($contact_record)) {
$ret = q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime`)
q("INSERT INTO `intro` ( `uid`, `contact-id`, `blocked`, `knowyou`, `note`, `hash`, `datetime`)
VALUES ( %d, %d, 1, %d, '%s', '%s', '%s' )",
intval($uid),
intval($contact_record['id']),
@ -544,7 +544,7 @@ function dfrn_request_content(App $a)
$auto_confirm = false;
if (DBA::isResult($r)) {
if ($r[0]['page-flags'] != Contact::PAGE_NORMAL && $r[0]['page-flags'] != Contact::PAGE_PRVGROUP) {
if ($r[0]['page-flags'] != User::PAGE_FLAGS_NORMAL && $r[0]['page-flags'] != User::PAGE_FLAGS_PRVGROUP) {
$auto_confirm = true;
}
@ -572,7 +572,7 @@ function dfrn_request_content(App $a)
'node' => $r[0]['nickname'],
'dfrn_id' => $r[0]['issued-id'],
'intro_id' => $intro[0]['id'],
'duplex' => (($r[0]['page-flags'] == Contact::PAGE_FREELOVE) ? 1 : 0),
'duplex' => (($r[0]['page-flags'] == User::PAGE_FLAGS_FREELOVE) ? 1 : 0),
];
dfrn_confirm_post($a, $handsfree);
}
@ -583,14 +583,13 @@ function dfrn_request_content(App $a)
// If we are auto_confirming, this record will have already been nuked
// in dfrn_confirm_post()
$r = q("UPDATE `intro` SET `blocked` = 0 WHERE `hash` = '%s'",
q("UPDATE `intro` SET `blocked` = 0 WHERE `hash` = '%s'",
DBA::escape($_GET['confirm_key'])
);
}
}
killme();
return; // NOTREACHED
exit();
} else {
// Normal web request. Display our user's introduction form.
if ((Config::get('system', 'block_public')) && (!local_user()) && (!remote_user())) {
@ -624,7 +623,7 @@ function dfrn_request_content(App $a)
* because nobody is going to read the comments and
* it doesn't matter if they know you or not.
*/
if ($a->profile['page-flags'] == Contact::PAGE_NORMAL) {
if ($a->profile['page-flags'] == User::PAGE_FLAGS_NORMAL) {
$tpl = Renderer::getMarkupTemplate('dfrn_request.tpl');
} else {
$tpl = Renderer::getMarkupTemplate('auto_request.tpl');
@ -655,6 +654,4 @@ function dfrn_request_content(App $a)
]);
return $o;
}
return; // Somebody is fishing.
}

View file

@ -7,8 +7,8 @@ use Friendica\App;
use Friendica\Content\Nav;
use Friendica\Content\Pager;
use Friendica\Content\Widget;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Database\DBA;
@ -45,6 +45,8 @@ function directory_content(App $a)
}
$o = '';
$entries = [];
Nav::setSelected('directory');
if (!empty($a->data['search'])) {
@ -98,7 +100,7 @@ function directory_content(App $a)
$limit = $pager->getStart()."," . $pager->getItemsPerPage();
$r = DBA::p("SELECT `profile`.*, `profile`.`uid` AS `profile_uid`, `user`.`nickname`, `user`.`timezone` , `user`.`page-flags`,
`contact`.`addr`, `contact`.`url` AS profile_url FROM `profile`
`contact`.`addr`, `contact`.`url` AS `profile_url` FROM `profile`
LEFT JOIN `user` ON `user`.`uid` = `profile`.`uid`
LEFT JOIN `contact` ON `contact`.`uid` = `user`.`uid`
WHERE `is-default` $publish AND NOT `user`.`blocked` AND NOT `user`.`account_removed` AND `contact`.`self`
@ -112,114 +114,117 @@ function directory_content(App $a)
}
while ($rr = DBA::fetch($r)) {
$itemurl= '';
$itemurl = (($rr['addr'] != "") ? $rr['addr'] : $rr['profile_url']);
$profile_link = $rr['profile_url'];
$pdesc = (($rr['pdesc']) ? $rr['pdesc'] . '<br />' : '');
$details = '';
if (strlen($rr['locality'])) {
$details .= $rr['locality'];
}
if (strlen($rr['region'])) {
if (strlen($rr['locality'])) {
$details .= ', ';
}
$details .= $rr['region'];
}
if (strlen($rr['country-name'])) {
if (strlen($details)) {
$details .= ', ';
}
$details .= $rr['country-name'];
}
// if(strlen($rr['dob'])) {
// if(($years = age($rr['dob'],$rr['timezone'],'')) != 0)
// $details .= '<br />' . L10n::t('Age: ') . $years;
// }
// if(strlen($rr['gender']))
// $details .= '<br />' . L10n::t('Gender: ') . $rr['gender'];
$profile = $rr;
if (!empty($profile['address'])
|| !empty($profile['locality'])
|| !empty($profile['region'])
|| !empty($profile['postal-code'])
|| !empty($profile['country-name'])
) {
$location = L10n::t('Location:');
} else {
$location = '';
}
$gender = (!empty($profile['gender']) ? L10n::t('Gender:') : false);
$marital = (!empty($profile['marital']) ? L10n::t('Status:') : false);
$homepage = (!empty($profile['homepage']) ? L10n::t('Homepage:') : false);
$about = (!empty($profile['about']) ? L10n::t('About:') : false);
$location_e = $location;
$photo_menu = [
'profile' => [L10n::t("View Profile"), Contact::magicLink($profile_link)]
];
$entry = [
'id' => $rr['id'],
'url' => Contact::magicLInk($profile_link),
'itemurl' => $itemurl,
'thumb' => ProxyUtils::proxifyUrl($rr[$photo], false, ProxyUtils::SIZE_THUMB),
'img_hover' => $rr['name'],
'name' => $rr['name'],
'details' => $details,
'account_type' => Contact::getAccountType($rr),
'profile' => $profile,
'location' => $location_e,
'tags' => $rr['pub_keywords'],
'gender' => $gender,
'pdesc' => $pdesc,
'marital' => $marital,
'homepage' => $homepage,
'about' => $about,
'photo_menu' => $photo_menu,
];
$arr = ['contact' => $rr, 'entry' => $entry];
Addon::callHooks('directory_item', $arr);
unset($profile);
unset($location);
if (!$arr['entry']) {
continue;
}
$entries[] = $arr['entry'];
$entries[] = format_directory_entry($rr, $photo);
}
DBA::close($r);
$tpl = Renderer::getMarkupTemplate('directory_header.tpl');
$o .= Renderer::replaceMacros($tpl, [
'$search' => $search,
'$globaldir' => L10n::t('Global Directory'),
'$gdirpath' => $gdirpath,
'$desc' => L10n::t('Find on this site'),
'$contacts' => $entries,
'$finding' => L10n::t('Results for:'),
'$findterm' => (strlen($search) ? $search : ""),
'$title' => L10n::t('Site Directory'),
'$submit' => L10n::t('Find'),
'$paginate' => $pager->renderFull($total),
]);
} else {
info(L10n::t("No entries \x28some entries may be hidden\x29.") . EOL);
}
$tpl = Renderer::getMarkupTemplate('directory_header.tpl');
$o .= Renderer::replaceMacros($tpl, [
'$search' => $search,
'$globaldir' => L10n::t('Global Directory'),
'$gdirpath' => $gdirpath,
'$desc' => L10n::t('Find on this site'),
'$contacts' => $entries,
'$finding' => L10n::t('Results for:'),
'$findterm' => (strlen($search) ? $search : ""),
'$title' => L10n::t('Site Directory'),
'$search_mod' => 'directory',
'$submit' => L10n::t('Find'),
'$paginate' => $pager->renderFull($total),
]);
return $o;
}
/**
* Format contact/profile/user data from the database into an usable
* array for displaying directory entries.
*
* @param array $arr The directory entry from the database.
* @param string $photo_size Avatar size (thumb, photo or micro).
*
* @return array
*/
function format_directory_entry(array $arr, $photo_size = 'photo')
{
$itemurl = (($arr['addr'] != "") ? $arr['addr'] : $arr['profile_url']);
$profile_link = $arr['profile_url'];
$pdesc = (($arr['pdesc']) ? $arr['pdesc'] . '<br />' : '');
$details = '';
if (strlen($arr['locality'])) {
$details .= $arr['locality'];
}
if (strlen($arr['region'])) {
if (strlen($arr['locality'])) {
$details .= ', ';
}
$details .= $arr['region'];
}
if (strlen($arr['country-name'])) {
if (strlen($details)) {
$details .= ', ';
}
$details .= $arr['country-name'];
}
$profile = $arr;
if (!empty($profile['address'])
|| !empty($profile['locality'])
|| !empty($profile['region'])
|| !empty($profile['postal-code'])
|| !empty($profile['country-name'])
) {
$location = L10n::t('Location:');
} else {
$location = '';
}
$gender = (!empty($profile['gender']) ? L10n::t('Gender:') : false);
$marital = (!empty($profile['marital']) ? L10n::t('Status:') : false);
$homepage = (!empty($profile['homepage']) ? L10n::t('Homepage:') : false);
$about = (!empty($profile['about']) ? L10n::t('About:') : false);
$location_e = $location;
$photo_menu = [
'profile' => [L10n::t("View Profile"), Contact::magicLink($profile_link)]
];
$entry = [
'id' => $arr['id'],
'url' => Contact::magicLInk($profile_link),
'itemurl' => $itemurl,
'thumb' => ProxyUtils::proxifyUrl($arr[$photo_size], false, ProxyUtils::SIZE_THUMB),
'img_hover' => $arr['name'],
'name' => $arr['name'],
'details' => $details,
'account_type' => Contact::getAccountType($arr),
'profile' => $profile,
'location' => $location_e,
'tags' => $arr['pub_keywords'],
'gender' => $gender,
'pdesc' => $pdesc,
'marital' => $marital,
'homepage' => $homepage,
'about' => $about,
'photo_menu' => $photo_menu,
];
$hook = ['contact' => $arr, 'entry' => $entry];
Hook::callAll('directory_item', $hook);
unset($profile);
unset($location);
return $hook['entry'];
}

View file

@ -179,21 +179,19 @@ function dirfind_content(App $a, $prefix = "") {
// Add found profiles from the global directory to the local directory
Worker::add(PRIORITY_LOW, 'DiscoverPoCo', "dirsearch", urlencode($search));
} else {
} elseif (strlen(Config::get('system','directory'))) {
$p = (($pager->getPage() != 1) ? '&p=' . $pager->getPage() : '');
if (strlen(Config::get('system','directory'))) {
$x = Network::fetchUrl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search));
}
$x = Network::fetchUrl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search));
$j = json_decode($x);
$pager->setItemsPerPage($j->items_page);
}
if (!empty($j->results)) {
$id = 0;
$entries = [];
foreach ($j->results as $jj) {
$alt_text = "";

View file

@ -19,10 +19,10 @@ use Friendica\Model\Contact;
use Friendica\Model\Group;
use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Module\Objects;
use Friendica\Protocol\ActivityPub;
use Friendica\Protocol\DFRN;
use Friendica\Util\Strings;
use Friendica\Module\Objects;
function display_init(App $a)
{
@ -35,7 +35,6 @@ function display_init(App $a)
}
$nick = (($a->argc > 1) ? $a->argv[1] : '');
$profiledata = [];
if ($a->argc == 3) {
if (substr($a->argv[2], -5) == '.atom') {
@ -96,7 +95,7 @@ function display_init(App $a)
}
if ($item["id"] != $item["parent"]) {
$item = Item::selectFirstForUser(local_user(), $fields, ['id' => $item["parent"]]);
$item = Item::selectFirstForUser($item_user, $fields, ['id' => $item["parent"]]);
}
$profiledata = display_fetchauthor($a, $item);
@ -157,7 +156,6 @@ function display_fetchauthor($a, $item)
}
if (!$skip) {
$author = "";
preg_match("/author='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$profiledata["name"] = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
@ -166,7 +164,6 @@ function display_fetchauthor($a, $item)
if (!empty($matches[1])) {
$profiledata["name"] = html_entity_decode($matches[1],ENT_QUOTES,'UTF-8');
}
$profile = "";
preg_match("/profile='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$profiledata["url"] = $matches[1];
@ -175,7 +172,6 @@ function display_fetchauthor($a, $item)
if (!empty($matches[1])) {
$profiledata["url"] = $matches[1];
}
$avatar = "";
preg_match("/avatar='(.*?)'/ism", $attributes, $matches);
if (!empty($matches[1])) {
$profiledata["photo"] = $matches[1];
@ -287,22 +283,25 @@ function display_content(App $a, $update = false, $update_uid = 0)
$is_remote_contact = false;
$item_uid = local_user();
$parent = Item::selectFirst(['uid'], ['uri' => $item_parent_uri, 'wall' => true]);
if (DBA::isResult($parent)) {
$a->profile['uid'] = defaults($a->profile, 'uid', $parent['uid']);
$a->profile['profile_uid'] = defaults($a->profile, 'profile_uid', $parent['uid']);
$is_remote_contact = Contact::isFollower(remote_user(), $a->profile['profile_uid']);
}
if (isset($item_parent_uri)) {
$parent = Item::selectFirst(['uid'], ['uri' => $item_parent_uri, 'wall' => true]);
if (DBA::isResult($parent)) {
$a->profile['uid'] = defaults($a->profile, 'uid', $parent['uid']);
$a->profile['profile_uid'] = defaults($a->profile, 'profile_uid', $parent['uid']);
$is_remote_contact = Contact::isFollower(remote_user(), $a->profile['profile_uid']);
if ($is_remote_contact) {
$cdata = Contact::getPublicAndUserContacID(remote_user(), $a->profile['profile_uid']);
if (!empty($cdata['user'])) {
$groups = Group::getIdsByContactId($cdata['user']);
$remote_cid = $cdata['user'];
$item_uid = $parent['uid'];
if ($is_remote_contact) {
$cdata = Contact::getPublicAndUserContacID(remote_user(), $a->profile['profile_uid']);
if (!empty($cdata['user'])) {
$groups = Group::getIdsByContactId($cdata['user']);
$remote_cid = $cdata['user'];
$item_uid = $parent['uid'];
}
}
}
}
$page_contact = DBA::selectFirst('contact', [], ['self' => true, 'uid' => $a->profile['uid']]);
if (DBA::isResult($page_contact)) {
$a->page_contact = $page_contact;
@ -426,5 +425,5 @@ function displayShowFeed($item_id, $conversation)
}
header("Content-type: application/atom+xml");
echo $xml;
killme();
exit();
}

View file

@ -2,10 +2,9 @@
/**
* @file mod/editpost.php
*/
use Friendica\App;
use Friendica\Content\Feature;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
@ -64,25 +63,6 @@ function editpost_content(App $a)
$jotplugins = '';
$jotnets = '';
$mail_disabled = ((function_exists('imap_open') && !Config::get('system', 'imap_disabled')) ? 0 : 1);
$mail_enabled = false;
$pubmail_enabled = false;
if (!$mail_disabled) {
$r = q("SELECT * FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1",
intval(local_user())
);
if (DBA::isResult($r)) {
$mail_enabled = true;
if (intval($r[0]['pubmail'])) {
$pubmail_enabled = true;
}
}
}
Hook::callAll('jot_tool', $jotplugins);
$tpl = Renderer::getMarkupTemplate("jot.tpl");

View file

@ -117,7 +117,7 @@ function events_post(App $a)
notice(L10n::t('Event can not end before it has started.') . EOL);
if (intval($_REQUEST['preview'])) {
echo L10n::t('Event can not end before it has started.');
killme();
exit();
}
$a->internalRedirect($onerror_path);
}
@ -126,7 +126,7 @@ function events_post(App $a)
notice(L10n::t('Event title and start time are required.') . EOL);
if (intval($_REQUEST['preview'])) {
echo L10n::t('Event title and start time are required.');
killme();
exit();
}
$a->internalRedirect($onerror_path);
}
@ -213,14 +213,14 @@ function events_content(App $a)
}
if (($a->argc > 2) && ($a->argv[1] === 'ignore') && intval($a->argv[2])) {
$r = q("UPDATE `event` SET `ignore` = 1 WHERE `id` = %d AND `uid` = %d",
q("UPDATE `event` SET `ignore` = 1 WHERE `id` = %d AND `uid` = %d",
intval($a->argv[2]),
intval(local_user())
);
}
if (($a->argc > 2) && ($a->argv[1] === 'unignore') && intval($a->argv[2])) {
$r = q("UPDATE `event` SET `ignore` = 0 WHERE `id` = %d AND `uid` = %d",
q("UPDATE `event` SET `ignore` = 0 WHERE `id` = %d AND `uid` = %d",
intval($a->argv[2]),
intval(local_user())
);
@ -300,21 +300,6 @@ function events_content(App $a)
$y = 2100;
}
$nextyear = $y;
$nextmonth = $m + 1;
if ($nextmonth > 12) {
$nextmonth = 1;
$nextyear ++;
}
$prevyear = $y;
if ($m > 1) {
$prevmonth = $m - 1;
} else {
$prevmonth = 12;
$prevyear --;
}
$dim = Temporal::getDaysInMonth($y, $m);
$start = sprintf('%d-%d-%d %d:%d:%d', $y, $m, 1, 0, 0, 0);
$finish = sprintf('%d-%d-%d %d:%d:%d', $y, $m, $dim, 23, 59, 59);
@ -414,7 +399,7 @@ function events_content(App $a)
if (!empty($_GET['id'])) {
echo $o;
killme();
exit();
}
return $o;
@ -526,7 +511,7 @@ function events_content(App $a)
'$s_text' => L10n::t('Event Starts:') . ' <span class="required" title="' . L10n::t('Required') . '">*</span>',
'$s_dsel' => Temporal::getDateTimeField(
new DateTime(),
DateTime::createFromFormat('Y', $syear+5),
DateTime::createFromFormat('Y', intval($syear) + 5),
DateTime::createFromFormat('Y-m-d H:i', "$syear-$smonth-$sday $shour:$sminute"),
L10n::t('Event Starts:'),
'start_text',
@ -541,7 +526,7 @@ function events_content(App $a)
'$f_text' => L10n::t('Event Finishes:'),
'$f_dsel' => Temporal::getDateTimeField(
new DateTime(),
DateTime::createFromFormat('Y', $fyear+5),
DateTime::createFromFormat('Y', intval($fyear) + 5),
DateTime::createFromFormat('Y-m-d H:i', "$fyear-$fmonth-$fday $fhour:$fminute"),
L10n::t('Event Finishes:'),
'finish_text',

View file

@ -14,22 +14,22 @@ use Friendica\Object\Image;
/**
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function fbrowser_content(App $a)
{
if (!local_user()) {
killme();
exit();
}
if ($a->argc == 1) {
killme();
exit();
}
$template_file = "filebrowser.tpl";
$mode = "";
if (!empty($_GET['mode'])) {
$mode = "?mode=".$_GET['mode'];
}
$o = '';
switch ($a->argv[1]) {
case "image":
@ -53,12 +53,11 @@ function fbrowser_content(App $a)
$albums = array_map("_map_folder1", $albums);
}
$album = "";
if ($a->argc==3) {
if ($a->argc == 3) {
$album = hex2bin($a->argv[2]);
$sql_extra = sprintf("AND `album` = '%s' ", DBA::escape($album));
$sql_extra2 = "";
$path[]=[$a->argv[2], $album];
$path[] = [$a->argv[2], $album];
}
$r = q("SELECT `resource-id`, ANY_VALUE(`id`) AS `id`, ANY_VALUE(`filename`) AS `filename`, ANY_VALUE(`type`) AS `type`,
@ -116,8 +115,7 @@ function fbrowser_content(App $a)
function _map_files2($rr)
{
$a = \get_app();
list($m1,$m2) = explode("/", $rr['filetype']);
list($m1, $m2) = explode("/", $rr['filetype']);
$filetype = ( (file_exists("images/icons/$m1.png"))?$m1:"zip");
$filename_e = $rr['filename'];
@ -146,6 +144,6 @@ function fbrowser_content(App $a)
return $o;
} else {
echo $o;
killme();
exit();
}
}

View file

@ -35,7 +35,7 @@ function feedtest_content(App $a)
$import_result = Feed::import($xml, $importer, $contact, $dummy, true);
$result = [
'input' => text_highlight($xml, 'xml'),
'input' => $xml,
'output' => var_export($import_result, true),
];
}

View file

@ -4,14 +4,12 @@ This file is part of the Diaspora protocol. It is used for fetching single publi
*/
use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Protocol\Diaspora;
use Friendica\Model\Item;
use Friendica\Model\User;
use Friendica\Util\Strings;
use Friendica\Util\XML;
use Friendica\Database\DBA;
function fetch_init(App $a)
@ -40,7 +38,7 @@ function fetch_init(App $a)
header("HTTP/1.1 301 Moved Permanently");
header("Location:".$location);
killme();
exit();
}
}
@ -60,5 +58,5 @@ function fetch_init(App $a)
header("Content-Type: application/magic-envelope+xml; charset=utf-8");
echo Diaspora::buildMagicEnvelope($xml, $user);
killme();
exit();
}

View file

@ -13,7 +13,7 @@ use Friendica\Util\XML;
function filer_content(App $a)
{
if (! local_user()) {
killme();
exit();
}
$term = XML::unescape(trim(defaults($_GET, 'term', '')));
@ -38,5 +38,5 @@ function filer_content(App $a)
echo $o;
}
killme();
exit();
}

View file

@ -2,7 +2,6 @@
use Friendica\App;
use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\Model\FileTag;
use Friendica\Util\XML;
@ -10,10 +9,10 @@ function filerm_content(App $a)
{
if (! local_user())
{
killme();
exit();
}
$term = XML::unescape(trim($_GET['term']));
$term = XML::unescape(trim(defaults($_GET, 'term', '')));
$cat = XML::unescape(trim(defaults($_GET, 'cat', '')));
$category = (($cat) ? true : false);
@ -37,5 +36,5 @@ function filerm_content(App $a)
}
$a->internalRedirect('/network?f=&file=' . rawurlencode($term));
killme();
exit();
}

View file

@ -12,7 +12,6 @@ use Friendica\Model\Contact;
use Friendica\Model\Profile;
use Friendica\Network\Probe;
use Friendica\Database\DBA;
use Friendica\Util\Proxy as ProxyUtils;
use Friendica\Util\Strings;
function follow_post(App $a)
@ -61,7 +60,16 @@ function follow_content(App $a)
}
$uid = local_user();
$url = Strings::escapeTags(trim($_REQUEST['url']));
$url = Strings::escapeTags(trim(defaults($_REQUEST, 'url', '')));
// Issue 6874: Allow remote following from Peertube
if (strpos($url, 'acct:') === 0) {
$url = str_replace('acct:', '', $url);
}
if (!$url) {
$a->internalRedirect($return_path);
}
$submit = L10n::t('Submit Request');

View file

@ -6,43 +6,52 @@
use Friendica\App;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Module\Register;
function friendica_init(App $a)
{
if (!empty($a->argv[1]) && ($a->argv[1] == "json")) {
$register_policies = ['REGISTER_CLOSED', 'REGISTER_APPROVE', 'REGISTER_OPEN'];
$register_policies = [
Register::CLOSED => 'REGISTER_CLOSED',
Register::APPROVE => 'REGISTER_APPROVE',
Register::OPEN => 'REGISTER_OPEN'
];
$register_policy = $register_policies[intval(Config::get('config', 'register_policy'))];
if ($register_policy == 'REGISTER_OPEN' && Config::get('config', 'invitation_only')) {
$register_policy_int = intval(Config::get('config', 'register_policy'));
if ($register_policy_int !== Register::CLOSED && Config::get('config', 'invitation_only')) {
$register_policy = 'REGISTER_INVITATION';
} else {
$register_policy = $register_policies[$register_policy_int];
}
$sql_extra = '';
if (!empty($a->config['admin_nickname'])) {
$sql_extra = sprintf(" AND `nickname` = '%s' ", DBA::escape(Config::get('config', 'admin_nickname')));
$condition = [];
$admin = false;
if (!empty(Config::get('config', 'admin_nickname'))) {
$condition['nickname'] = Config::get('config', 'admin_nickname');
}
if (!empty(Config::get('config', 'admin_email'))) {
$adminlist = explode(",", str_replace(" ", "", Config::get('config', 'admin_email')));
$r = q("SELECT `username`, `nickname` FROM `user` WHERE `email` = '%s' $sql_extra", DBA::escape($adminlist[0]));
$admin = [
'name' => $r[0]['username'],
'profile'=> System::baseUrl() . '/profile/' . $r[0]['nickname'],
];
} else {
$admin = false;
$condition['email'] = $adminlist[0];
$administrator = DBA::selectFirst('user', ['username', 'nickname'], $condition);
if (DBA::isResult($administrator)) {
$admin = [
'name' => $administrator['username'],
'profile'=> System::baseUrl() . '/profile/' . $administrator['nickname'],
];
}
}
$visible_addons = Addon::getVisibleList();
Config::load('feature_lock');
$locked_features = [];
if (!empty($a->config['feature_lock'])) {
foreach ($a->config['feature_lock'] as $k => $v) {
$featureLock = Config::get('config', 'feature_lock');
if (isset($featureLock)) {
foreach ($featureLock as $k => $v) {
if ($k === 'config_loaded') {
continue;
}
@ -68,7 +77,7 @@ function friendica_init(App $a)
header('Content-type: application/json; charset=utf-8');
echo json_encode($data);
killme();
exit();
}
}
@ -126,7 +135,7 @@ function friendica_content(App $a)
$o .= '</tbody></table></div>' . PHP_EOL;
}
Addon::callHooks('about_hook', $o);
Hook::callAll('about_hook', $o);
return $o;
}

View file

@ -23,15 +23,11 @@ function fsuggest_post(App $a)
$contact_id = intval($a->argv[1]);
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($contact_id),
intval(local_user())
);
if (! DBA::isResult($r)) {
$contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]);
if (! DBA::isResult($contact)) {
notice(L10n::t('Contact not found.') . EOL);
return;
}
$contact = $r[0];
$new_contact = intval($_POST['suggest']);
@ -45,14 +41,14 @@ function fsuggest_post(App $a)
intval(local_user())
);
if (DBA::isResult($r)) {
$x = q("INSERT INTO `fsuggest` ( `uid`,`cid`,`name`,`url`,`request`,`photo`,`note`,`created`)
q("INSERT INTO `fsuggest` ( `uid`,`cid`,`name`,`url`,`request`,`photo`,`note`,`created`)
VALUES ( %d, %d, '%s','%s','%s','%s','%s','%s')",
intval(local_user()),
intval($contact_id),
DBA::escape($r[0]['name']),
DBA::escape($r[0]['url']),
DBA::escape($r[0]['request']),
DBA::escape($r[0]['photo']),
DBA::escape($contact['name']),
DBA::escape($contact['url']),
DBA::escape($contact['request']),
DBA::escape($contact['photo']),
DBA::escape($hash),
DBA::escape(DateTimeFormat::utcNow())
);
@ -61,7 +57,7 @@ function fsuggest_post(App $a)
intval(local_user())
);
if (DBA::isResult($r)) {
$fsuggest_id = $r[0]['id'];
$fsuggest_id = $contact['id'];
q("UPDATE `fsuggest` SET `note` = '%s' WHERE `id` = %d AND `uid` = %d",
DBA::escape($note),
intval($fsuggest_id),
@ -88,16 +84,11 @@ function fsuggest_content(App $a)
$contact_id = intval($a->argv[1]);
$r = q(
"SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($contact_id),
intval(local_user())
);
if (! DBA::isResult($r)) {
$contact = DBA::selectFirst('contact', [], ['id' => $contact_id, 'uid' => local_user()]);
if (! DBA::isResult($contact)) {
notice(L10n::t('Contact not found.') . EOL);
return;
}
$contact = $r[0];
$o = '<h3>' . L10n::t('Suggest Friends') . '</h3>';

View file

@ -1,318 +0,0 @@
<?php
/**
* @file mod/group.php
* @brief The group module (create and rename contact groups, add and
* remove contacts to the contact groups
*/
use Friendica\App;
use Friendica\BaseModule;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\PConfig;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model;
use Friendica\Module;
use Friendica\Util\Security;
use Friendica\Util\Strings;
function group_init(App $a) {
if (local_user()) {
$a->page['aside'] = Model\Group::sidebarWidget('contacts', 'group', 'extended', (($a->argc > 1) ? $a->argv[1] : 'everyone'));
}
}
function group_post(App $a) {
if (!local_user()) {
notice(L10n::t('Permission denied.') . EOL);
return;
}
if (($a->argc == 2) && ($a->argv[1] === 'new')) {
BaseModule::checkFormSecurityTokenRedirectOnError('/group/new', 'group_edit');
$name = Strings::escapeTags(trim($_POST['groupname']));
$r = Model\Group::create(local_user(), $name);
if ($r) {
info(L10n::t('Group created.') . EOL);
$r = Model\Group::getIdByName(local_user(), $name);
if ($r) {
$a->internalRedirect('group/' . $r);
}
} else {
notice(L10n::t('Could not create group.') . EOL);
}
$a->internalRedirect('group');
return; // NOTREACHED
}
if (($a->argc == 2) && intval($a->argv[1])) {
BaseModule::checkFormSecurityTokenRedirectOnError('/group', 'group_edit');
$r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($a->argv[1]),
intval(local_user())
);
if (!DBA::isResult($r)) {
notice(L10n::t('Group not found.') . EOL);
$a->internalRedirect('contact');
return; // NOTREACHED
}
$group = $r[0];
$groupname = Strings::escapeTags(trim($_POST['groupname']));
if (strlen($groupname) && ($groupname != $group['name'])) {
$r = q("UPDATE `group` SET `name` = '%s' WHERE `uid` = %d AND `id` = %d",
DBA::escape($groupname),
intval(local_user()),
intval($group['id'])
);
if ($r) {
info(L10n::t('Group name changed.') . EOL);
}
}
$a->page['aside'] = Model\Group::sidebarWidget();
}
return;
}
function group_content(App $a) {
$change = false;
if (!local_user()) {
notice(L10n::t('Permission denied') . EOL);
return;
}
// With no group number provided we jump to the unassigned contacts as a starting point
if ($a->argc == 1) {
$a->internalRedirect('group/none');
}
// Switch to text mode interface if we have more than 'n' contacts or group members
$switchtotext = PConfig::get(local_user(), 'system', 'groupedit_image_limit');
if (is_null($switchtotext)) {
$switchtotext = Config::get('system', 'groupedit_image_limit', 400);
}
$tpl = Renderer::getMarkupTemplate('group_edit.tpl');
$context = [
'$submit' => L10n::t('Save Group'),
'$submit_filter' => L10n::t('Filter'),
];
if (($a->argc == 2) && ($a->argv[1] === 'new')) {
return Renderer::replaceMacros($tpl, $context + [
'$title' => L10n::t('Create a group of contacts/friends.'),
'$gname' => ['groupname', L10n::t('Group Name: '), '', ''],
'$gid' => 'new',
'$form_security_token' => BaseModule::getFormSecurityToken("group_edit"),
]);
}
$nogroup = false;
if (($a->argc == 2) && ($a->argv[1] === 'none')) {
$id = -1;
$nogroup = true;
$group = [
'id' => $id,
'name' => L10n::t('Contacts not in any group'),
];
$members = [];
$preselected = [];
$entry = [];
$context = $context + [
'$title' => $group['name'],
'$gname' => ['groupname', L10n::t('Group Name: '), $group['name'], ''],
'$gid' => $id,
'$editable' => 0,
];
}
if (($a->argc == 3) && ($a->argv[1] === 'drop')) {
BaseModule::checkFormSecurityTokenRedirectOnError('/group', 'group_drop', 't');
if (intval($a->argv[2])) {
$r = q("SELECT `name` FROM `group` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($a->argv[2]),
intval(local_user())
);
$result = null;
if (DBA::isResult($r)) {
$result = Model\Group::removeByName(local_user(), $r[0]['name']);
}
if ($result) {
info(L10n::t('Group removed.') . EOL);
} else {
notice(L10n::t('Unable to remove group.') . EOL);
}
}
$a->internalRedirect('group');
// NOTREACHED
}
if (($a->argc > 2) && intval($a->argv[1]) && intval($a->argv[2])) {
BaseModule::checkFormSecurityTokenForbiddenOnError('group_member_change', 't');
$r = q("SELECT `id` FROM `contact` WHERE `id` = %d AND `uid` = %d and `self` = 0 and `blocked` = 0 AND `pending` = 0 LIMIT 1",
intval($a->argv[2]),
intval(local_user())
);
if (DBA::isResult($r)) {
$change = intval($a->argv[2]);
}
}
if (($a->argc > 1) && intval($a->argv[1])) {
$r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1",
intval($a->argv[1]),
intval(local_user())
);
if (!DBA::isResult($r)) {
notice(L10n::t('Group not found.') . EOL);
$a->internalRedirect('contact');
}
$group = $r[0];
$members = Model\Contact::getByGroupId($group['id']);
$preselected = [];
$entry = [];
$id = 0;
if (count($members)) {
foreach ($members as $member) {
$preselected[] = $member['id'];
}
}
if ($change) {
if (in_array($change, $preselected)) {
Model\Group::removeMember($group['id'], $change);
} else {
Model\Group::addMember($group['id'], $change);
}
$members = Model\Contact::getByGroupId($group['id']);
$preselected = [];
if (count($members)) {
foreach ($members as $member) {
$preselected[] = $member['id'];
}
}
}
$drop_tpl = Renderer::getMarkupTemplate('group_drop.tpl');
$drop_txt = Renderer::replaceMacros($drop_tpl, [
'$id' => $group['id'],
'$delete' => L10n::t('Delete Group'),
'$form_security_token' => BaseModule::getFormSecurityToken("group_drop"),
]);
$context = $context + [
'$title' => $group['name'],
'$gname' => ['groupname', L10n::t('Group Name: '), $group['name'], ''],
'$gid' => $group['id'],
'$drop' => $drop_txt,
'$form_security_token' => BaseModule::getFormSecurityToken('group_edit'),
'$edit_name' => L10n::t('Edit Group Name'),
'$editable' => 1,
];
}
if (!isset($group)) {
return;
}
$groupeditor = [
'label_members' => L10n::t('Members'),
'members' => [],
'label_contacts' => L10n::t('All Contacts'),
'group_is_empty' => L10n::t('Group is empty'),
'contacts' => [],
];
$sec_token = addslashes(BaseModule::getFormSecurityToken('group_member_change'));
// Format the data of the group members
foreach ($members as $member) {
if ($member['url']) {
$entry = Module\Contact::getContactTemplateVars($member);
$entry['label'] = 'members';
$entry['photo_menu'] = '';
$entry['change_member'] = [
'title' => L10n::t("Remove contact from group"),
'gid' => $group['id'],
'cid' => $member['id'],
'sec_token' => $sec_token
];
$groupeditor['members'][] = $entry;
} else {
Model\Group::removeMember($group['id'], $member['id']);
}
}
if ($nogroup) {
$r = Model\Contact::getUngroupedList(local_user());
} else {
$r = q("SELECT * FROM `contact` WHERE `uid` = %d AND NOT `blocked` AND NOT `pending` AND NOT `self` ORDER BY `name` ASC",
intval(local_user())
);
$context['$desc'] = L10n::t('Click on a contact to add or remove.');
}
if (DBA::isResult($r)) {
// Format the data of the contacts who aren't in the contact group
foreach ($r as $member) {
if (!in_array($member['id'], $preselected)) {
$entry = Module\Contact::getContactTemplateVars($member);
$entry['label'] = 'contacts';
if (!$nogroup)
$entry['photo_menu'] = [];
if (!$nogroup) {
$entry['change_member'] = [
'title' => L10n::t("Add contact to group"),
'gid' => $group['id'],
'cid' => $member['id'],
'sec_token' => $sec_token
];
}
$groupeditor['contacts'][] = $entry;
}
}
}
$context['$groupeditor'] = $groupeditor;
// If there are to many contacts we could provide an alternative view mode
$total = count($groupeditor['members']) + count($groupeditor['contacts']);
$context['$shortmode'] = (($switchtotext && ($total > $switchtotext)) ? true : false);
if ($change) {
$tpl = Renderer::getMarkupTemplate('groupeditor.tpl');
echo Renderer::replaceMacros($tpl, $context);
killme();
}
return Renderer::replaceMacros($tpl, $context);
}

View file

@ -8,6 +8,7 @@ use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
use Friendica\Model\User;
function hcard_init(App $a)
{
@ -29,7 +30,7 @@ function hcard_init(App $a)
Profile::load($a, $which, $profile);
if (!empty($a->profile['page-flags']) && ($a->profile['page-flags'] == Contact::PAGE_COMMUNITY)) {
if (!empty($a->profile['page-flags']) && ($a->profile['page-flags'] == User::PAGE_FLAGS_COMMUNITY)) {
$a->page['htmlhead'] .= '<meta name="friendica.community" content="true" />';
}
if (!empty($a->profile['openidserver'])) {

View file

@ -33,6 +33,7 @@ function help_content(App $a)
Nav::setSelected('help');
$text = '';
$filename = '';
if ($a->argc > 1) {
$path = '';
@ -83,7 +84,7 @@ function help_content(App $a)
$level = intval($level);
if ($level < $lastlevel) {
for ($k = $level; $k < $lastlevel; $k++) {
$toc .= "</ul>";
$toc .= "</ul></li>";
}
for ($k = $level + 1; $k < count($idnum); $k++) {
@ -92,7 +93,7 @@ function help_content(App $a)
}
if ($level > $lastlevel) {
$toc .= "<ul>";
$toc .= "<li><ul>";
}
$idnum[$level] ++;

View file

@ -3,8 +3,8 @@
* @file mod/home.php
*/
use Friendica\App;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\System;
@ -14,7 +14,7 @@ if(! function_exists('home_init')) {
function home_init(App $a) {
$ret = [];
Addon::callHooks('home_init',$ret);
Hook::callAll('home_init',$ret);
if (local_user() && ($a->user['nickname'])) {
$a->internalRedirect('network');
@ -48,10 +48,10 @@ function home_content(App $a) {
}
}
$login = Login::form($a->query_string, intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED ? 0 : 1);
$login = Login::form($a->query_string, intval(Config::get('config', 'register_policy')) === \Friendica\Module\Register::CLOSED ? 0 : 1);
$content = '';
Addon::callHooks("home_content",$content);
Hook::callAll("home_content",$content);
$tpl = Renderer::getMarkupTemplate('home.tpl');
@ -61,7 +61,4 @@ function home_content(App $a) {
'$login' => $login,
'$content' => $content
]);
return $o;
}}

View file

@ -41,13 +41,12 @@ function hovercard_content()
if ($datatype == 'tpl') {
$templatecontent = get_template_content('hovercard.tpl');
echo $templatecontent;
killme();
exit();
}
// If a contact is connected the url is internally changed to 'redir/CID'. We need the pure url to search for
// the contact. So we strip out the contact id from the internal url and look in the contact table for
// the real url (nurl)
$cid = 0;
if (strpos($profileurl, 'redir/') === 0) {
$cid = intval(substr($profileurl, 6));
$remote_contact = DBA::selectFirst('contact', ['nurl'], ['id' => $cid]);
@ -127,16 +126,19 @@ function hovercard_content()
* @brief Get the raw content of a template file
*
* @param string $template The name of the template
* @param string $root Directory of the template
* @param string $root Directory of the template
*
* @return string|bool Output the raw content if existent, otherwise false
* @throws Exception
*/
function get_template_content($template, $root = '')
{
// We load the whole template system to get the filename.
// Maybe we can do it a little bit smarter if I get time.
$t = Renderer::getMarkupTemplate($template, $root);
$filename = $t->filename;
$templateEngine = Renderer::getTemplateEngine();
$template = $templateEngine->getTemplateFile($template, $root);
$filename = $template->filename;
// Get the content of the template file
if (file_exists($filename)) {

View file

@ -1,27 +1,26 @@
<?php
use Friendica\App;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Item;
function ignored_init(App $a)
{
if (!local_user()) {
killme();
exit();
}
if ($a->argc > 1) {
$message_id = intval($a->argv[1]);
}
if (!$message_id) {
killme();
if (empty($message_id)) {
exit();
}
$thread = Item::selectFirstThreadForUser(local_user(), ['uid', 'ignored'], ['iid' => $message_id]);
if (!DBA::isResult($thread)) {
killme();
exit();
}
// Numeric values are needed for the json output further below
@ -49,5 +48,5 @@ function ignored_init(App $a)
// the json doesn't really matter, it will either be 0 or 1
echo json_encode($ignored);
killme();
exit();
}

View file

@ -13,10 +13,8 @@ use Friendica\Core\L10n;
use Friendica\Core\PConfig;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Module\Register;
use Friendica\Protocol\Email;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Security;
use Friendica\Util\Strings;
function invite_post(App $a)
@ -44,6 +42,8 @@ function invite_post(App $a)
$message = !empty($_POST['message']) ? Strings::escapeTags(trim($_POST['message'])) : '';
$total = 0;
$invitation_only = false;
$invites_remaining = null;
if (Config::get('system', 'invitation_only')) {
$invitation_only = true;
@ -126,14 +126,14 @@ function invite_content(App $a) {
$dirloc = Config::get('system', 'directory');
if (strlen($dirloc)) {
if (intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED) {
if (intval(Config::get('config', 'register_policy')) === Register::CLOSED) {
$linktxt = L10n::t('Visit %s for a list of public sites that you can join. Friendica members on other sites can all connect with each other, as well as with members of many other social networks.', $dirloc . '/servers');
} else {
$linktxt = L10n::t('To accept this invitation, please visit and register at %s or any other public Friendica website.', System::baseUrl())
. "\r\n" . "\r\n" . L10n::t('Friendica sites all inter-connect to create a huge privacy-enhanced social web that is owned and controlled by its members. They can also connect with many traditional social networks. See %s for a list of alternate Friendica sites you can join.', $dirloc . '/servers');
}
} else { // there is no global directory URL defined
if (intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED) {
if (intval(Config::get('config', 'register_policy')) === Register::CLOSED) {
$o = L10n::t('Our apologies. This system is not currently configured to connect with other public sites or invite members.');
return $o;
} else {

View file

@ -19,8 +19,8 @@ use Friendica\App;
use Friendica\Content\Pager;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
@ -31,6 +31,9 @@ use Friendica\Model\Contact;
use Friendica\Model\Conversation;
use Friendica\Model\FileTag;
use Friendica\Model\Item;
use Friendica\Model\Photo;
use Friendica\Model\Attach;
use Friendica\Model\Term;
use Friendica\Protocol\Diaspora;
use Friendica\Protocol\Email;
use Friendica\Util\DateTimeFormat;
@ -38,6 +41,8 @@ use Friendica\Util\Emailer;
use Friendica\Util\Security;
use Friendica\Util\Strings;
require_once 'include/items.php';
function item_post(App $a) {
if (!local_user() && !remote_user()) {
return 0;
@ -50,10 +55,10 @@ function item_post(App $a) {
drop_items($arr_drop);
$json = ['success' => 1];
echo json_encode($json);
killme();
exit();
}
Addon::callHooks('post_local_start', $_REQUEST);
Hook::callAll('post_local_start', $_REQUEST);
Logger::log('postvars ' . print_r($_REQUEST, true), Logger::DATA);
@ -79,13 +84,13 @@ function item_post(App $a) {
}
// Is this a reply to something?
$thr_parent = intval(defaults($_REQUEST, 'parent', 0));
$toplevel_item_id = intval(defaults($_REQUEST, 'parent', 0));
$thr_parent_uri = trim(defaults($_REQUEST, 'parent_uri', ''));
$thr_parent_contact = null;
$thread_parent_id = 0;
$thread_parent_contact = null;
$parent = 0;
$parent_item = null;
$toplevel_item = null;
$parent_user = null;
$parent_contact = null;
@ -94,42 +99,41 @@ function item_post(App $a) {
$profile_uid = defaults($_REQUEST, 'profile_uid', local_user());
$posttype = defaults($_REQUEST, 'post_type', Item::PT_ARTICLE);
if ($thr_parent || $thr_parent_uri) {
if ($thr_parent) {
$parent_item = Item::selectFirst([], ['id' => $thr_parent]);
if ($toplevel_item_id || $thr_parent_uri) {
if ($toplevel_item_id) {
$toplevel_item = Item::selectFirst([], ['id' => $toplevel_item_id]);
} elseif ($thr_parent_uri) {
$parent_item = Item::selectFirst([], ['uri' => $thr_parent_uri, 'uid' => $profile_uid]);
$toplevel_item = Item::selectFirst([], ['uri' => $thr_parent_uri, 'uid' => $profile_uid]);
}
// if this isn't the real parent of the conversation, find it
if (DBA::isResult($parent_item)) {
// if this isn't the top-level parent of the conversation, find it
if (DBA::isResult($toplevel_item)) {
// The URI and the contact is taken from the direct parent which needn't to be the top parent
$thr_parent_uri = $parent_item['uri'];
$thr_parent_contact = Contact::getDetailsByURL($parent_item["author-link"]);
$thread_parent_id = $toplevel_item['id'];
$thr_parent_uri = $toplevel_item['uri'];
$thread_parent_contact = Contact::getDetailsByURL($toplevel_item["author-link"]);
if ($parent_item['id'] != $parent_item['parent']) {
$parent_item = Item::selectFirst(Item::ITEM_FIELDLIST, ['id' => $parent_item['parent']]);
if ($toplevel_item['id'] != $toplevel_item['parent']) {
$toplevel_item = Item::selectFirst(Item::ITEM_FIELDLIST, ['id' => $toplevel_item['parent']]);
}
}
if (!DBA::isResult($parent_item)) {
if (!DBA::isResult($toplevel_item)) {
notice(L10n::t('Unable to locate original post.') . EOL);
if (!empty($_REQUEST['return'])) {
$a->internalRedirect($return_path);
}
killme();
exit();
}
$parent = $parent_item['id'];
$parent_user = $parent_item['uid'];
$parent_contact = Contact::getDetailsByURL($parent_item["author-link"]);
$toplevel_item_id = $toplevel_item['id'];
$parent_user = $toplevel_item['uid'];
$objecttype = ACTIVITY_OBJ_COMMENT;
}
if ($parent) {
Logger::log('mod_item: item_post parent=' . $parent);
if ($toplevel_item_id) {
Logger::info('mod_item: item_post parent=' . $toplevel_item_id);
}
$post_id = intval(defaults($_REQUEST, 'post_id', 0));
@ -158,7 +162,7 @@ function item_post(App $a) {
}
// Allow commenting if it is an answer to a public post
$allow_comment = local_user() && ($profile_uid == 0) && $parent && in_array($parent_item['network'], [Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]);
$allow_comment = local_user() && ($profile_uid == 0) && $toplevel_item_id && in_array($toplevel_item['network'], [Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA, Protocol::DFRN]);
// Now check that valid personal details have been provided
if (!Security::canWriteToUserWall($profile_uid) && !$allow_comment) {
@ -168,7 +172,7 @@ function item_post(App $a) {
$a->internalRedirect($return_path);
}
killme();
exit();
}
// Init post instance
@ -181,13 +185,47 @@ function item_post(App $a) {
$user = DBA::selectFirst('user', [], ['uid' => $profile_uid]);
if (!DBA::isResult($user) && !$parent) {
if (!DBA::isResult($user) && !$toplevel_item_id) {
return 0;
}
$categories = '';
$postopts = '';
$emailcc = '';
$body = defaults($_REQUEST, 'body', '');
$has_attachment = defaults($_REQUEST, 'has_attachment', 0);
// If we have a speparate attachment, we need to add it to the body.
if (!empty($has_attachment)) {
$attachment_type = defaults($_REQUEST, 'attachment_type', '');
$attachment_title = defaults($_REQUEST, 'attachment_title', '');
$attachment_text = defaults($_REQUEST, 'attachment_text', '');
$attachment_url = hex2bin(defaults($_REQUEST, 'attachment_url', ''));
$attachment_img_src = hex2bin(defaults($_REQUEST, 'attachment_img_src', ''));
$attachment_img_width = defaults($_REQUEST, 'attachment_img_width', 0);
$attachment_img_height = defaults($_REQUEST, 'attachment_img_height', 0);
$attachment = [
'type' => $attachment_type,
'title' => $attachment_title,
'text' => $attachment_text,
'url' => $attachment_url,
];
if (!empty($attachment_img_src)) {
$attachment['images'] = [
0 => [
'src' => $attachment_img_src,
'width' => $attachment_img_width,
'height' => $attachment_img_height
]
];
}
$att_bbcode = add_page_info_data($attachment);
$body .= $att_bbcode;
}
if (!empty($orig_post)) {
$str_group_allow = $orig_post['allow_gid'];
@ -201,7 +239,7 @@ function item_post(App $a) {
$app = $orig_post['app'];
$categories = $orig_post['file'];
$title = Strings::escapeTags(trim($_REQUEST['title']));
$body = Strings::escapeHtml(trim($_REQUEST['body']));
$body = Strings::escapeHtml(trim($body));
$private = $orig_post['private'];
$pubmail_enabled = $orig_post['pubmail'];
$network = $orig_post['network'];
@ -237,7 +275,7 @@ function item_post(App $a) {
$coord = Strings::escapeTags(trim(defaults($_REQUEST, 'coord' , '')));
$verb = Strings::escapeTags(trim(defaults($_REQUEST, 'verb' , '')));
$emailcc = Strings::escapeTags(trim(defaults($_REQUEST, 'emailcc' , '')));
$body = Strings::escapeHtml(trim(defaults($_REQUEST, 'body' , '')));
$body = Strings::escapeHtml(trim($body));
$network = Strings::escapeTags(trim(defaults($_REQUEST, 'network' , Protocol::DFRN)));
$guid = System::createUUID();
@ -251,21 +289,21 @@ function item_post(App $a) {
// If this is a comment, set the permissions from the parent.
if ($parent_item) {
if ($toplevel_item) {
// for non native networks use the network of the original post as network of the item
if (($parent_item['network'] != Protocol::DIASPORA)
&& ($parent_item['network'] != Protocol::OSTATUS)
if (($toplevel_item['network'] != Protocol::DIASPORA)
&& ($toplevel_item['network'] != Protocol::OSTATUS)
&& ($network == "")) {
$network = $parent_item['network'];
$network = $toplevel_item['network'];
}
$str_contact_allow = $parent_item['allow_cid'];
$str_group_allow = $parent_item['allow_gid'];
$str_contact_deny = $parent_item['deny_cid'];
$str_group_deny = $parent_item['deny_gid'];
$private = $parent_item['private'];
$str_contact_allow = $toplevel_item['allow_cid'];
$str_group_allow = $toplevel_item['allow_gid'];
$str_contact_deny = $toplevel_item['deny_cid'];
$str_group_deny = $toplevel_item['deny_gid'];
$private = $toplevel_item['private'];
$wall = $parent_item['wall'];
$wall = $toplevel_item['wall'];
}
$pubmail_enabled = defaults($_REQUEST, 'pubmail_enable', false) && !$private;
@ -279,13 +317,13 @@ function item_post(App $a) {
if (!strlen($body)) {
if ($preview) {
killme();
exit();
}
info(L10n::t('Empty post discarded.') . EOL);
if (!empty($_REQUEST['return'])) {
$a->internalRedirect($return_path);
}
killme();
exit();
}
}
@ -346,12 +384,8 @@ function item_post(App $a) {
$tags = BBCode::getTags($body);
// Add a tag if the parent contact is from ActivityPub or OStatus (This will notify them)
if ($parent && in_array($thr_parent_contact['network'], [Protocol::OSTATUS, Protocol::ACTIVITYPUB])) {
$contact = '@[url=' . $thr_parent_contact['url'] . ']' . $thr_parent_contact['nick'] . '[/url]';
if (!stripos(implode($tags), '[url=' . $thr_parent_contact['url'] . ']')) {
$tags[] = $contact;
}
if ($thread_parent_id && !\Friendica\Content\Feature::isEnabled($uid, 'explicit_mentions')) {
$tags = item_add_implicit_mentions($tags, $thread_parent_contact, $thread_parent_id);
}
$tagged = [];
@ -364,7 +398,7 @@ function item_post(App $a) {
foreach ($tags as $tag) {
$tag_type = substr($tag, 0, 1);
if ($tag_type == '#') {
if ($tag_type == Term::TAG_CHARACTER[Term::HASHTAG]) {
continue;
}
@ -384,14 +418,14 @@ function item_post(App $a) {
continue;
}
$success = handle_tag($a, $body, $inform, $str_tags, local_user() ? local_user() : $profile_uid, $tag, $network);
$success = handle_tag($body, $inform, $str_tags, local_user() ? local_user() : $profile_uid, $tag, $network);
if ($success['replaced']) {
$tagged[] = $tag;
}
// When the forum is private or the forum is addressed with a "!" make the post private
if (is_array($success['contact']) && (!empty($success['contact']['prv']) || ($tag_type == '!'))) {
if (is_array($success['contact']) && (!empty($success['contact']['prv']) || ($tag_type == Term::TAG_CHARACTER[Term::EXCLUSIVE_MENTION]))) {
$private_forum = $success['contact']['prv'];
$only_to_forum = ($tag_type == '!');
$only_to_forum = ($tag_type == Term::TAG_CHARACTER[Term::EXCLUSIVE_MENTION]);
$private_id = $success['contact']['id'];
$forum_contact = $success['contact'];
} elseif (is_array($success['contact']) && !empty($success['contact']['forum']) &&
@ -406,7 +440,7 @@ function item_post(App $a) {
$original_contact_id = $contact_id;
if (!$parent && count($forum_contact) && ($private_forum || $only_to_forum)) {
if (!$toplevel_item_id && count($forum_contact) && ($private_forum || $only_to_forum)) {
// we tagged a forum in a top level post. Now we change the post
$private = $private_forum;
@ -456,16 +490,18 @@ function item_post(App $a) {
// Ensure to only modify photos that you own
$srch = '<' . intval($original_contact_id) . '>';
$condition = ['allow_cid' => $srch, 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '',
'resource-id' => $image_uri, 'uid' => $profile_uid];
if (!DBA::exists('photo', $condition)) {
$condition = [
'allow_cid' => $srch, 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '',
'resource-id' => $image_uri, 'uid' => $profile_uid
];
if (!Photo::exists($condition)) {
continue;
}
$fields = ['allow_cid' => $str_contact_allow, 'allow_gid' => $str_group_allow,
'deny_cid' => $str_contact_deny, 'deny_gid' => $str_group_deny];
$condition = ['resource-id' => $image_uri, 'uid' => $profile_uid];
DBA::update('photo', $fields, $condition);
Photo::update($fields, $condition);
}
}
}
@ -486,14 +522,14 @@ function item_post(App $a) {
$condition = ['allow_cid' => $srch, 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '',
'id' => $attach];
if (!DBA::exists('attach', $condition)) {
if (!Attach::exists($condition)) {
continue;
}
$fields = ['allow_cid' => $str_contact_allow, 'allow_gid' => $str_group_allow,
'deny_cid' => $str_contact_deny, 'deny_gid' => $str_group_deny];
$condition = ['id' => $attach];
DBA::update('attach', $fields, $condition);
Attach::update($fields, $condition);
}
}
}
@ -536,8 +572,8 @@ function item_post(App $a) {
if (preg_match_all('/(\[attachment\]([0-9]+)\[\/attachment\])/',$body,$match)) {
foreach ($match[2] as $mtch) {
$fields = ['id', 'filename', 'filesize', 'filetype'];
$attachment = DBA::selectFirst('attach', $fields, ['id' => $mtch]);
if (DBA::isResult($attachment)) {
$attachment = Attach::selectFirst($fields, ['id' => $mtch]);
if ($attachment !== false) {
if (strlen($attachments)) {
$attachments .= ',';
}
@ -557,7 +593,7 @@ function item_post(App $a) {
$network = Protocol::DFRN;
}
$gravity = ($parent ? GRAVITY_COMMENT : GRAVITY_PARENT);
$gravity = ($toplevel_item_id ? GRAVITY_COMMENT : GRAVITY_PARENT);
// even if the post arrived via API we are considering that it
// originated on this site by default for determining relayability.
@ -569,12 +605,12 @@ function item_post(App $a) {
$origin = $_REQUEST['origin'];
}
$notify_type = ($parent ? 'comment-new' : 'wall-new');
$notify_type = ($toplevel_item_id ? 'comment-new' : 'wall-new');
$uri = ($message_id ? $message_id : Item::newURI($api_source ? $profile_uid : $uid, $guid));
// Fallback so that we alway have a parent uri
if (!$thr_parent_uri || !$parent) {
if (!$thr_parent_uri || !$toplevel_item_id) {
$thr_parent_uri = $uri;
}
@ -632,7 +668,7 @@ function item_post(App $a) {
* 'self' if true indicates the owner is posting on their own wall
* If parent is 0 it is a top-level post.
*/
$datarray['parent'] = $parent;
$datarray['parent'] = $toplevel_item_id;
$datarray['self'] = $self;
// This triggers posts via API and the mirror functions
@ -676,7 +712,7 @@ function item_post(App $a) {
exit();
}
Addon::callHooks('post_local',$datarray);
Hook::callAll('post_local',$datarray);
if (!empty($datarray['cancel'])) {
Logger::log('mod_item: post cancelled by addon.');
@ -690,7 +726,7 @@ function item_post(App $a) {
}
echo json_encode($json);
killme();
exit();
}
if ($orig_post) {
@ -718,9 +754,7 @@ function item_post(App $a) {
Logger::log('return: ' . $return_path);
$a->internalRedirect($return_path);
}
killme();
} else {
$post_id = 0;
exit();
}
unset($datarray['edit']);
@ -752,7 +786,7 @@ function item_post(App $a) {
FileTag::updatePconfig($uid, $categories_old, $categories_new, 'category');
// These notifications are sent if someone else is commenting other your wall
if ($parent) {
if ($toplevel_item_id) {
if ($contact_record != $author) {
notification([
'type' => NOTIFY_COMMENT,
@ -768,8 +802,8 @@ function item_post(App $a) {
'source_photo' => $datarray['author-avatar'],
'verb' => ACTIVITY_POST,
'otype' => 'item',
'parent' => $parent,
'parent_uri' => $parent_item['uri']
'parent' => $toplevel_item_id,
'parent_uri' => $toplevel_item['uri']
]);
}
} else {
@ -792,7 +826,7 @@ function item_post(App $a) {
}
}
Addon::callHooks('post_local_end', $datarray);
Hook::callAll('post_local_end', $datarray);
if (strlen($emailcc) && $profile_uid == local_user()) {
$erecips = explode(',', $emailcc);
@ -871,7 +905,7 @@ function item_post_return($baseurl, $api_source, $return_path)
Logger::log('post_json: ' . print_r($json, true), Logger::DEBUG);
echo json_encode($json);
killme();
exit();
}
function item_content(App $a)
@ -897,7 +931,7 @@ function item_content(App $a)
if ($a->isAjax()) {
// ajax return: [<item id>, 0 (no perm) | <owner id>]
echo json_encode([intval($a->argv[2]), intval($o)]);
killme();
exit();
}
}
@ -906,26 +940,27 @@ function item_content(App $a)
/**
* This function removes the tag $tag from the text $body and replaces it with
* the appropiate link.
* the appropriate link.
*
* @param App $a Application instance @TODO is unused in this function's scope (excluding included files)
* @param unknown_type $body the text to replace the tag in
* @param string $inform a comma-seperated string containing everybody to inform
* @param string $str_tags string to add the tag to
* @param App $a
* @param string $body the text to replace the tag in
* @param string $inform a comma-seperated string containing everybody to inform
* @param string $str_tags string to add the tag to
* @param integer $profile_uid
* @param string $tag the tag to replace
* @param string $network The network of the post
* @param string $tag the tag to replace
* @param string $network The network of the post
*
* @return boolean true if replaced, false if not replaced
* @return array|bool ['replaced' => $replaced, 'contact' => $contact];
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $network = "")
function handle_tag(&$body, &$inform, &$str_tags, $profile_uid, $tag, $network = "")
{
$replaced = false;
$r = null;
$tag_type = '@';
//is it a person tag?
if ((strpos($tag, '@') === 0) || (strpos($tag, '!') === 0)) {
if (Term::isType($tag, Term::MENTION, Term::IMPLICIT_MENTION, Term::EXCLUSIVE_MENTION)) {
$tag_type = substr($tag, 0, 1);
//is it already replaced?
if (strpos($tag, '[url=')) {
@ -958,7 +993,6 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n
return $replaced;
}
$stat = false;
//get the person's name
$name = substr($tag, 1);
@ -1049,7 +1083,7 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n
* Status.Net seems to require the numeric ID URL in a mention if the person isn't
* subscribed to you. But the nickname URL is OK if they are. Grrr. We'll tag both.
*/
if (strlen($alias)) {
if (!empty($alias)) {
$newtag = '@[url=' . $alias . ']' . $newname . '[/url]';
if (!stripos($str_tags, '[url=' . $alias . ']')) {
if (strlen($str_tags)) {
@ -1063,3 +1097,34 @@ function handle_tag(App $a, &$body, &$inform, &$str_tags, $profile_uid, $tag, $n
return ['replaced' => $replaced, 'contact' => $contact];
}
function item_add_implicit_mentions(array $tags, array $thread_parent_contact, $thread_parent_id)
{
if (Config::get('system', 'disable_implicit_mentions')) {
// Add a tag if the parent contact is from ActivityPub or OStatus (This will notify them)
if (in_array($thread_parent_contact['network'], [Protocol::OSTATUS, Protocol::ACTIVITYPUB])) {
$contact = Term::TAG_CHARACTER[Term::MENTION] . '[url=' . $thread_parent_contact['url'] . ']' . $thread_parent_contact['nick'] . '[/url]';
if (!stripos(implode($tags), '[url=' . $thread_parent_contact['url'] . ']')) {
$tags[] = $contact;
}
}
} else {
$implicit_mentions = [
$thread_parent_contact['url'] => $thread_parent_contact['nick']
];
$parent_terms = Term::tagArrayFromItemId($thread_parent_id, [Term::MENTION, Term::IMPLICIT_MENTION]);
foreach ($parent_terms as $parent_term) {
$implicit_mentions[$parent_term['url']] = $parent_term['term'];
}
foreach ($implicit_mentions as $url => $label) {
if ($url != \Friendica\Model\Profile::getMyURL() && !stripos(implode($tags), '[url=' . $url . ']')) {
$tags[] = Term::TAG_CHARACTER[Term::IMPLICIT_MENTION] . '[url=' . $url . ']' . $label . '[/url]';
}
}
}
return $tags;
}

View file

@ -1,7 +1,6 @@
<?php
use Friendica\App;
use Friendica\Core\System;
use Friendica\Model\Item;
use Friendica\Util\Strings;
@ -28,7 +27,7 @@ function like_content(App $a) {
$return_path = defaults($_REQUEST, 'return', '');
like_content_return($a, $return_path);
killme(); // NOTREACHED
exit();
}
@ -46,6 +45,4 @@ function like_content_return(App $a, $return_path) {
$a->internalRedirect($return_path . $rand);
}
killme();
}

View file

@ -3,7 +3,7 @@
* @file mod/lockview.php
*/
use Friendica\App;
use Friendica\Core\Addon;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Database\DBA;
use Friendica\Model\Item;
@ -19,11 +19,11 @@ function lockview_content(App $a)
}
if (!$item_id) {
killme();
exit();
}
if (!in_array($type, ['item','photo','event'])) {
killme();
exit();
}
$fields = ['uid', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid'];
@ -37,14 +37,14 @@ function lockview_content(App $a)
}
if (!DBA::isResult($item)) {
killme();
exit();
}
Addon::callHooks('lockview_content', $item);
Hook::callAll('lockview_content', $item);
if ($item['uid'] != local_user()) {
echo L10n::t('Remote privacy information not available.') . '<br />';
killme();
exit();
}
if (isset($item['private'])
@ -55,7 +55,7 @@ function lockview_content(App $a)
&& empty($item['deny_gid']))
{
echo L10n::t('Remote privacy information not available.') . '<br />';
killme();
exit();
}
$allowed_users = expand_acl($item['allow_cid']);
@ -111,6 +111,6 @@ function lockview_content(App $a)
}
echo $o . implode(', ', $l);
killme();
exit();
}

View file

@ -81,7 +81,6 @@ function lostpass_post(App $a)
function lostpass_content(App $a)
{
$o = '';
if ($a->argc > 1) {
$pwdreset_token = $a->argv[1];
@ -127,7 +126,6 @@ function lostpass_form()
function lostpass_generate_password($user)
{
$o = '';
$a = \get_app();
$new_password = User::generateNewPassword();
$result = User::updatePassword($user['uid'], $new_password);

View file

@ -4,10 +4,9 @@
*/
use Friendica\App;
use Friendica\Core\Authentication;
use Friendica\Core\Addon;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
function manage_post(App $a) {
@ -116,7 +115,7 @@ function manage_post(App $a) {
}
$ret = [];
Addon::callHooks('home_init',$ret);
Hook::callAll('home_init',$ret);
$a->internalRedirect('profile/' . $a->user['nickname'] );
// NOTREACHED

View file

@ -24,5 +24,5 @@ function manifest_content(App $a) {
echo $o;
killme();
exit();
}

View file

@ -25,6 +25,9 @@ use Friendica\Util\Proxy as ProxyUtils;
* @param App $a App
*
* @return string
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws Exception
*/
function match_content(App $a)
{
@ -72,7 +75,7 @@ function match_content(App $a)
$profile = $msearch->results[$i];
// Already known contact
if (Contact::getIdForURL($profile->url, local_user(), true)) {
if (!$profile || Contact::getIdForURL($profile->url, local_user(), true)) {
continue;
}

View file

@ -185,7 +185,6 @@ function message_content(App $a)
);
if (DBA::isResult($r)) {
$parent = $r[0]['parent-uri'];
$convid = $r[0]['convid'];
if (DBA::delete('mail', ['parent-uri' => $parent, 'uid' => local_user()])) {
info(L10n::t('Conversation removed.') . EOL);
@ -230,7 +229,6 @@ function message_content(App $a)
if (DBA::isResult($r)) {
$prename = $r[0]['name'];
$preurl = $r[0]['url'];
$preid = $r[0]['id'];
$preselect = [$preid];
} else {

View file

@ -6,7 +6,7 @@ use Friendica\Database\DBA;
function modexp_init(App $a) {
if($a->argc != 2)
killme();
exit();
$nick = $a->argv[1];
$r = q("SELECT `spubkey` FROM `user` WHERE `nickname` = '%s' LIMIT 1",
@ -14,7 +14,7 @@ function modexp_init(App $a) {
);
if (! DBA::isResult($r)) {
killme();
exit();
}
$lines = explode("\n",$r[0]['spubkey']);
@ -30,7 +30,7 @@ function modexp_init(App $a) {
header("Content-type: application/magic-public-key");
echo 'RSA' . '.' . $m . '.' . $e;
killme();
exit();
}

View file

@ -20,6 +20,8 @@ function msearch_post(App $a)
exit();
}
$total = 0;
$count_stmt = DBA::p(
"SELECT COUNT(*) AS `total`
FROM `profile`
@ -29,7 +31,6 @@ function msearch_post(App $a)
AND MATCH(`pub_keywords`) AGAINST (?)",
$search
);
if (DBA::isResult($count_stmt)) {
$row = DBA::fetch($count_stmt);
$total = $row['total'];

View file

@ -12,7 +12,6 @@ use Friendica\Content\Pager;
use Friendica\Content\Widget;
use Friendica\Content\Text\HTML;
use Friendica\Core\ACL;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
@ -25,6 +24,7 @@ use Friendica\Model\Contact;
use Friendica\Model\Group;
use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Model\Term;
use Friendica\Module\Login;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Proxy as ProxyUtils;
@ -201,15 +201,16 @@ function saved_searches($search)
* Return selected tab from query
*
* urls -> returns
* '/network' => $no_active = 'active'
* '/network?f=&order=comment' => $comment_active = 'active'
* '/network?f=&order=post' => $postord_active = 'active'
* '/network?f=&conv=1', => $conv_active = 'active'
* '/network/new', => $new_active = 'active'
* '/network?f=&star=1', => $starred_active = 'active'
* '/network?f=&bmark=1', => $bookmarked_active = 'active'
* '/network' => $no_active = 'active'
* '/network?f=&order=comment' => $comment_active = 'active'
* '/network?f=&order=post' => $postord_active = 'active'
* '/network?f=&conv=1', => $conv_active = 'active'
* '/network/new', => $new_active = 'active'
* '/network?f=&star=1', => $starred_active = 'active'
* '/network?f=&bmark=1', => $bookmarked_active = 'active'
*
* @return Array ($no_active, $comment_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active);
* @param App $a
* @return array ($no_active, $comment_active, $postord_active, $conv_active, $new_active, $starred_active, $bookmarked_active);
*/
function network_query_get_sel_tab(App $a)
{
@ -265,9 +266,11 @@ function network_query_get_sel_group(App $a)
/**
* @brief Sets the pager data and returns SQL
*
* @param App $a The global App
* @param App $a The global App
* @param Pager $pager
* @param integer $update Used for the automatic reloading
* @return string SQL with the appropriate LIMIT clause
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function networkPager(App $a, Pager $pager, $update)
{
@ -301,6 +304,7 @@ function networkPager(App $a, Pager $pager, $update)
* @brief Sets items as seen
*
* @param array $condition The array with the SQL condition
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function networkSetSeen($condition)
{
@ -311,7 +315,7 @@ function networkSetSeen($condition)
$unseen = Item::exists($condition);
if ($unseen) {
$r = Item::update(['unseen' => false], $condition);
Item::update(['unseen' => false], $condition);
}
}
@ -320,9 +324,13 @@ function networkSetSeen($condition)
*
* @param App $a The global App
* @param array $items Items of the conversation
* @param Pager $pager
* @param string $mode Display mode for the conversation
* @param integer $update Used for the automatic reloading
* @param string $ordering
* @return string HTML of the conversation
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function networkConversation(App $a, $items, Pager $pager, $mode, $update, $ordering = '')
{
@ -355,7 +363,7 @@ function network_content(App $a, $update = 0, $parent = 0)
/// @TODO Is this really necessary? $a is already available to hooks
$arr = ['query' => $a->query_string];
Addon::callHooks('network_content_init', $arr);
Hook::callAll('network_content_init', $arr);
$flat_mode = false;
@ -387,10 +395,12 @@ function network_content(App $a, $update = 0, $parent = 0)
/**
* @brief Get the network content in flat view
*
* @param Pager $pager
* @param App $a The global App
* @param integer $update Used for the automatic reloading
* @return string HTML of the network content in flat view
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @global Pager $pager
*/
function networkFlatView(App $a, $update = 0)
{
@ -398,12 +408,6 @@ function networkFlatView(App $a, $update = 0)
// Rawmode is used for fetching new content at the end of the page
$rawmode = (isset($_GET['mode']) && ($_GET['mode'] == 'raw'));
if (isset($_GET['last_id'])) {
$last_id = intval($_GET['last_id']);
} else {
$last_id = 0;
}
$o = '';
$file = defaults($_GET, 'file', '');
@ -440,14 +444,15 @@ function networkFlatView(App $a, $update = 0)
$pager = new Pager($a->query_string);
/// @TODO Figure out why this variable is unused
$pager_sql = networkPager($a, $pager, $update);
networkPager($a, $pager, $update);
$item_params = ['order' => ['id' => true]];
if (strlen($file)) {
$condition = ["`term` = ? AND `otype` = ? AND `type` = ? AND `uid` = ?",
$file, TERM_OBJ_POST, TERM_FILE, local_user()];
$params = ['order' => ['tid' => true], 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
$result = DBA::select('term', ['oid'], $condition);
$term_condition = ["`term` = ? AND `otype` = ? AND `type` = ? AND `uid` = ?",
$file, Term::OBJECT_TYPE_POST, Term::FILE, local_user()];
$term_params = ['order' => ['tid' => true], 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
$result = DBA::select('term', ['oid'], $term_condition, $term_params);
$posts = [];
while ($term = DBA::fetch($result)) {
@ -458,18 +463,16 @@ function networkFlatView(App $a, $update = 0)
if (count($posts) == 0) {
return '';
}
$condition = ['uid' => local_user(), 'id' => $posts];
$item_condition = ['uid' => local_user(), 'id' => $posts];
} else {
$condition = ['uid' => local_user()];
$item_condition = ['uid' => local_user()];
$item_params['limit'] = [$pager->getStart(), $pager->getItemsPerPage()];
networkSetSeen(['unseen' => true, 'uid' => local_user()]);
}
$params = ['order' => ['id' => true], 'limit' => [$pager->getStart(), $pager->getItemsPerPage()]];
$result = Item::selectForUser(local_user(), [], $condition, $params);
$result = Item::selectForUser(local_user(), [], $item_condition, $item_params);
$items = Item::inArray($result);
$condition = ['unseen' => true, 'uid' => local_user()];
networkSetSeen($condition);
$o .= networkConversation($a, $items, $pager, 'network-new', $update);
return $o;
@ -478,11 +481,13 @@ function networkFlatView(App $a, $update = 0)
/**
* @brief Get the network content in threaded view
*
* @global Pager $pager
* @param App $a The global App
* @param integer $update Used for the automatic reloading
* @param integer $parent
* @return string HTML of the network content in flat view
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @global Pager $pager
*/
function networkThreadedView(App $a, $update, $parent)
{
@ -521,7 +526,7 @@ function networkThreadedView(App $a, $update, $parent)
}
} elseif (intval($a->argv[$x])) {
$gid = intval($a->argv[$x]);
$default_permissions = ['allow_gid' => '<' . $gid . '>'];
$default_permissions['allow_gid'] = [$gid];
}
}
}
@ -535,20 +540,28 @@ function networkThreadedView(App $a, $update, $parent)
$order = Strings::escapeTags(defaults($_GET, 'order', 'comment'));
$nets = defaults($_GET, 'nets' , '');
$allowedCids = [];
if ($cid) {
$default_permissions = ['allow_cid' => '<' . intval($cid) . '>'];
$allowedCids[] = (int) $cid;
} elseif ($nets) {
$condition = [
'uid' => local_user(),
'network' => $nets,
'self' => false,
'blocked' => false,
'pending' => false,
'archive' => false,
'rel' => [Contact::SHARING, Contact::FRIEND],
];
$contactStmt = DBA::select('contact', ['id'], $condition);
while ($contact = DBA::fetch($contactStmt)) {
$allowedCids[] = (int) $contact['id'];
}
DBA::close($contactStmt);
}
if ($nets) {
$r = DBA::select('contact', ['id'], ['uid' => local_user(), 'network' => $nets], ['self' => false]);
$str = '';
while ($rr = DBA::fetch($r)) {
$str .= '<' . $rr['id'] . '>';
}
if (strlen($str)) {
$default_permissions = ['allow_cid' => $str];
}
if (count($allowedCids)) {
$default_permissions['allow_cid'] = $allowedCids;
}
if (!$update && !$rawmode) {
@ -610,7 +623,6 @@ function networkThreadedView(App $a, $update, $parent)
$sql_extra3 = '';
$sql_table = '`thread`';
$sql_parent = '`iid`';
$sql_order = '';
if ($update) {
$sql_table = '`item`';
@ -625,7 +637,7 @@ function networkThreadedView(App $a, $update, $parent)
$group = DBA::selectFirst('group', ['name'], ['id' => $gid, 'uid' => local_user()]);
if (!DBA::isResult($group)) {
if ($update) {
killme();
exit();
}
notice(L10n::t('No such group') . EOL);
$a->internalRedirect('network/0');
@ -941,6 +953,7 @@ function networkThreadedView(App $a, $update, $parent)
*
* @param App $a The global App
* @return string Html of the networktab
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function network_tabs(App $a)
{
@ -1024,7 +1037,7 @@ function network_tabs(App $a)
}
$arr = ['tabs' => $tabs];
Addon::callHooks('network_tabs', $arr);
Hook::callAll('network_tabs', $arr);
$tpl = Renderer::getMarkupTemplate('common_tabs.tpl');
@ -1040,13 +1053,17 @@ function network_tabs(App $a)
* of the page to make the correct asynchronous call. This is obtained through the Pager that was instantiated in
* networkThreadedView or networkFlatView.
*
* @global Pager $pager
* @param App $a
* @param App $a
* @param string $htmlhead The head tag HTML string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @global Pager $pager
*/
function network_infinite_scroll_head(App $a, &$htmlhead)
{
/// @TODO this will have to be converted to a static property of the converted Module\Network class
/**
* @var $pager Pager
*/
global $pager;
if (PConfig::get(local_user(), 'system', 'infinite_scroll')

View file

@ -15,7 +15,7 @@ function newmember_content(App $a)
$o .= L10n::t('We would like to offer some tips and links to help make your experience enjoyable. Click any item to visit the relevant page. A link to this page will be visible from your home page for two weeks after your initial registration and then will quietly disappear.');
$o .= '<h4>' . L10n::t('Getting Started') . '</h4>';
$o .= '<ul>';
$o .= '<li> ' . '<a target="newmember" href="help/guide">' . L10n::t('Friendica Walk-Through') . '</a><br />' . L10n::t('On your <em>Quick Start</em> page - find a brief introduction to your profile and network tabs, make some new connections, and find some groups to join.') . '</li>' . EOL;
$o .= '<li> ' . '<a target="newmember" href="help/Quick-Start-guide">' . L10n::t('Friendica Walk-Through') . '</a><br />' . L10n::t('On your <em>Quick Start</em> page - find a brief introduction to your profile and network tabs, make some new connections, and find some groups to join.') . '</li>' . EOL;
$o .= '</ul>';
$o .= '<h4>' . L10n::t('Settings') . '</h4>';
$o .= '<ul>';

View file

@ -12,7 +12,12 @@ use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Util\Network;
function nodeinfo_wellknown(App $a) {
if (!Config::get('system', 'nodeinfo')) {
System::httpExit(404);
}
$nodeinfo = ['links' => [['rel' => 'http://nodeinfo.diaspora.software/ns/schema/1.0',
'href' => System::baseUrl().'/nodeinfo/1.0']]];
@ -24,12 +29,10 @@ function nodeinfo_wellknown(App $a) {
function nodeinfo_init(App $a) {
if (!Config::get('system', 'nodeinfo')) {
System::httpExit(404);
killme();
}
if (($a->argc != 2) || ($a->argv[1] != '1.0')) {
System::httpExit(404);
killme();
}
$smtp = (function_exists('imap_open') && !Config::get('system', 'imap_disabled') && !Config::get('system', 'dfrn_only'));
@ -61,7 +64,7 @@ function nodeinfo_init(App $a) {
$nodeinfo['usage'] = [];
$nodeinfo['openRegistrations'] = intval(Config::get('config', 'register_policy')) !== REGISTER_CLOSED;
$nodeinfo['openRegistrations'] = intval(Config::get('config', 'register_policy')) !== \Friendica\Module\Register::CLOSED;
$nodeinfo['metadata'] = ['nodeName' => Config::get('config', 'sitename')];
@ -149,7 +152,6 @@ function nodeinfo_cron() {
$addon = 'statistics_json';
$addons = Config::get('system', 'addon');
$addons_arr = [];
if ($addons) {
$addons_arr = explode(',',str_replace(' ', '',$addons));

View file

@ -3,12 +3,7 @@
* @file mod/nogroup.php
*/
use Friendica\App;
use Friendica\Content\ContactSelector;
use Friendica\Core\L10n;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Group;
use Friendica\Core\System;
function nogroup_init(App $a)
{

View file

@ -9,13 +9,14 @@ use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
use Friendica\Model\User;
function noscrape_init(App $a)
{
if ($a->argc > 1) {
$which = $a->argv[1];
} else {
killme();
exit();
}
$profile = 0;
@ -32,7 +33,7 @@ function noscrape_init(App $a)
'guid' => $a->profile['guid'],
'key' => $a->profile['pubkey'],
'homepage' => System::baseUrl()."/profile/{$which}",
'comm' => ($a->profile['account-type'] == Contact::ACCOUNT_TYPE_COMMUNITY),
'comm' => ($a->profile['account-type'] == User::ACCOUNT_TYPE_COMMUNITY),
'account-type' => $a->profile['account-type'],
];

View file

@ -17,13 +17,7 @@ function notes_init(App $a)
return;
}
$profile = 0;
$which = $a->user['nickname'];
Nav::setSelected('home');
//Profile::load($a, $which, $profile);
}

View file

@ -6,7 +6,6 @@
use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Database\DBA;
function notice_init(App $a)

View file

@ -92,6 +92,8 @@ function notifications_content(App $a)
$notif_header = L10n::t('Notifications');
$all = false;
// Get introductions
if ((($a->argc > 1) && ($a->argv[1] == 'intros')) || (($a->argc == 1))) {
Nav::setSelected('introductions');

View file

@ -48,7 +48,7 @@ function notify_init(App $a)
$r = $nm->setAllSeen();
$j = json_encode(['result' => ($r) ? 'success' : 'fail']);
echo $j;
killme();
exit();
}
}
@ -58,6 +58,8 @@ function notify_content(App $a)
return Login::form();
}
$notif_content = '';
$nm = new NotificationsManager();
$notif_tpl = Renderer::getMarkupTemplate('notifications.tpl');

View file

@ -17,7 +17,7 @@ function oexchange_init(App $a) {
$o = Renderer::replaceMacros($tpl, ['$base' => System::baseUrl()]);
echo $o;
killme();
exit();
}
}

View file

@ -8,7 +8,6 @@ use Friendica\Core\Authentication;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Util\Strings;
@ -64,7 +63,7 @@ function openid_content(App $a) {
// Successful OpenID login - but we can't match it to an existing account.
// New registration?
if (intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED) {
if (intval(Config::get('config', 'register_policy')) === \Friendica\Module\Register::CLOSED) {
notice(L10n::t('Account not found and OpenID registration is not permitted on this site.') . EOL);
$a->internalRedirect();
}
@ -94,17 +93,17 @@ function openid_content(App $a) {
}
}
}
if ($nick) {
if (!empty($nick)) {
$args .= '&nickname=' . urlencode($nick);
}
elseif ($first) {
elseif (!empty($first)) {
$args .= '&nickname=' . urlencode($first);
}
if ($photosq) {
if (!empty($photosq)) {
$args .= '&photo=' . urlencode($photosq);
}
elseif ($photo) {
elseif (!empty($photo)) {
$args .= '&photo=' . urlencode($photo);
}

View file

@ -17,5 +17,5 @@ function opensearch_content(App $a) {
echo $o;
killme();
exit();
}

View file

@ -10,8 +10,9 @@
* @see ParseUrl::getSiteinfo() for more information about scraping embeddable content
*/
use Friendica\App;
use Friendica\Core\Addon;
use Friendica\Core\Hook;
use Friendica\Core\Logger;
use Friendica\Core\System;
use Friendica\Util\Network;
use Friendica\Util\ParseUrl;
@ -19,6 +20,8 @@ function parse_url_content(App $a)
{
$text = null;
$str_tags = '';
$format = '';
$ret= ['success' => false, 'contentType' => ''];
$br = "\n";
@ -43,6 +46,10 @@ function parse_url_content(App $a)
}
}
if (isset($_GET['format']) && $_GET['format'] == 'json') {
$format = 'json';
}
// Add url scheme if it is missing
$arrurl = parse_url($url);
if (empty($arrurl['scheme'])) {
@ -73,23 +80,36 @@ function parse_url_content(App $a)
}
}
$type = null;
$content_type = '';
$bbcode = '';
if (array_key_exists('Content-Type', $hdrs)) {
$type = $hdrs['Content-Type'];
}
if ($type) {
if (stripos($type, 'image/') !== false) {
echo $br . '[img]' . $url . '[/img]' . $br;
exit();
$content_type = 'image';
$bbcode = $br . '[img]' . $url . '[/img]' . $br;
}
if (stripos($type, 'video/') !== false) {
echo $br . '[video]' . $url . '[/video]' . $br;
exit();
$content_type = 'video';
$bbcode = $br . '[video]' . $url . '[/video]' . $br;
}
if (stripos($type, 'audio/') !== false) {
echo $br . '[audio]' . $url . '[/audio]' . $br;
exit();
$content_type = 'audio';
$bbcode = $br . '[audio]' . $url . '[/audio]' . $br;
}
}
if (!empty($content_type)) {
if ($format == 'json') {
$ret['contentType'] = $content_type;
$ret['data'] = ['url' => $url];
$ret['success'] = true;
System::jsonExit($ret);
}
echo $bbcode;
exit();
}
}
@ -97,7 +117,7 @@ function parse_url_content(App $a)
$arr = ['url' => $url, 'text' => ''];
Addon::callHooks('parse_link', $arr);
Hook::callAll('parse_link', $arr);
if (strlen($arr['text'])) {
echo $arr['text'];
@ -130,6 +150,14 @@ function parse_url_content(App $a)
exit();
}
if ($format == 'json') {
$ret['data'] = $siteinfo;
$ret['contentType'] = 'attachment';
$ret['success'] = true;
System::jsonExit($ret);
}
// Format it as BBCode attachment
$info = add_page_info_data($siteinfo);
@ -144,18 +172,18 @@ function parse_url_content(App $a)
* Note: We have moved the function to ParseUrl.php. This function is only for
* legacy support and will be remove in the future
*
* @param type $url The url of the page which should be scraped
* @param type $no_guessing If true the parse doens't search for
* preview pictures
* @param type $do_oembed The false option is used by the function fetch_oembed()
* to avoid endless loops
* @param string $url The url of the page which should be scraped
* @param bool $no_guessing If true the parse doens't search for
* preview pictures
* @param bool $do_oembed The false option is used by the function fetch_oembed()
* to avoid endless loops
*
* @return array which contains needed data for embedding
*
* @see ParseUrl::getSiteinfoCached()
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @see ParseUrl::getSiteinfoCached()
*
* @todo Remove this function after all Addons has been changed to use
* ParseUrl::getSiteinfoCached
* @deprecated since version 3.6 use ParseUrl::getSiteinfoCached instead
*/
function parseurl_getsiteinfo_cached($url, $no_guessing = false, $do_oembed = true)
{

View file

@ -1,208 +0,0 @@
<?php
/**
* @file mod/photo.php
*/
use Friendica\App;
use Friendica\Database\DBA;
use Friendica\Object\Image;
use Friendica\Util\Security;
function photo_init(App $a)
{
global $_SERVER;
$prvcachecontrol = false;
$file = "";
switch ($a->argc) {
case 4:
$person = $a->argv[3];
$customres = intval($a->argv[2]);
$type = $a->argv[1];
break;
case 3:
$person = $a->argv[2];
$type = $a->argv[1];
break;
case 2:
$photo = $a->argv[1];
$file = $photo;
break;
case 1:
default:
killme();
// NOTREACHED
}
if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
header('HTTP/1.1 304 Not Modified');
header("Last-Modified: " . gmdate("D, d M Y H:i:s", time()) . " GMT");
if (!empty($_SERVER['HTTP_IF_NONE_MATCH'])) {
header('Etag: ' . $_SERVER['HTTP_IF_NONE_MATCH']);
}
header("Expires: " . gmdate("D, d M Y H:i:s", time() + (31536000)) . " GMT");
header("Cache-Control: max-age=31536000");
if (function_exists('header_remove')) {
header_remove('Last-Modified');
header_remove('Expires');
header_remove('Cache-Control');
}
exit;
}
$default = 'images/person-300.jpg';
$public = true;
if (isset($type)) {
// Profile photos
switch ($type) {
case 'profile':
case 'custom':
$resolution = 4;
break;
case 'micro':
$resolution = 6;
$default = 'images/person-48.jpg';
break;
case 'avatar':
default:
$resolution = 5;
$default = 'images/person-80.jpg';
break;
}
$uid = str_replace(['.jpg', '.png', '.gif'], ['', '', ''], $person);
foreach (Image::supportedTypes() AS $m => $e) {
$uid = str_replace('.' . $e, '', $uid);
}
$r = q("SELECT * FROM `photo` WHERE `scale` = %d AND `uid` = %d AND `profile` = 1 LIMIT 1",
intval($resolution),
intval($uid)
);
if (DBA::isResult($r)) {
$data = $r[0]['data'];
$mimetype = $r[0]['type'];
}
if (empty($data)) {
$data = file_get_contents($default);
$mimetype = 'image/jpeg';
}
} else {
// Other photos
$resolution = 0;
$photo = str_replace(['.jpg', '.png', '.gif'], ['', '', ''], $photo);
foreach (Image::supportedTypes() AS $m => $e) {
$photo = str_replace('.' . $e, '', $photo);
}
if (substr($photo, -2, 1) == '-') {
$resolution = intval(substr($photo, -1, 1));
$photo = substr($photo, 0, -2);
}
// check if the photo exists and get the owner of the photo
$r = q("SELECT `uid` FROM `photo` WHERE `resource-id` = '%s' LIMIT 1",
DBA::escape($photo),
intval($resolution)
);
if (DBA::isResult($r)) {
$sql_extra = Security::getPermissionsSQLByUserId($r[0]['uid']);
// Now we'll see if we can access the photo
$r = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `scale` <= %d $sql_extra ORDER BY scale DESC LIMIT 1",
DBA::escape($photo),
intval($resolution)
);
if (DBA::isResult($r)) {
$resolution = $r[0]['scale'];
$data = $r[0]['data'];
$mimetype = $r[0]['type'];
$public = $r[0]['allow_cid'] == '' && $r[0]['allow_gid'] == '' && $r[0]['deny_cid'] == '' && $r[0]['deny_gid'] == '';
} else {
// The picure exists. We already checked with the first query.
// obviously, this is not an authorized viev!
$data = file_get_contents('images/nosign.jpg');
$mimetype = 'image/jpeg';
$prvcachecontrol = true;
$public = false;
}
}
}
if (empty($data)) {
if (isset($resolution)) {
switch ($resolution) {
case 4:
$data = file_get_contents('images/person-300.jpg');
$mimetype = 'image/jpeg';
break;
case 5:
$data = file_get_contents('images/person-80.jpg');
$mimetype = 'image/jpeg';
break;
case 6:
$data = file_get_contents('images/person-48.jpg');
$mimetype = 'image/jpeg';
break;
default:
killme();
// NOTREACHED
break;
}
}
}
// Resize only if its not a GIF and it is supported by the library
if ($mimetype != "image/gif" && in_array($mimetype, Image::supportedTypes())) {
$Image = new Image($data, $mimetype);
if ($Image->isValid()) {
if (isset($customres) && $customres > 0 && $customres < 500) {
$Image->scaleToSquare($customres);
}
$data = $Image->asString();
$mimetype = $Image->getType();
}
}
if (function_exists('header_remove')) {
header_remove('Pragma');
header_remove('pragma');
}
header("Content-type: " . $mimetype);
if ($prvcachecontrol) {
// it is a private photo that they have no permission to view.
// tell the browser not to cache it, in case they authenticate
// and subsequently have permission to see it
header("Cache-Control: no-store, no-cache, must-revalidate");
} else {
header("Last-Modified: " . gmdate("D, d M Y H:i:s", time()) . " GMT");
header('Etag: "' . md5($data) . '"');
header("Expires: " . gmdate("D, d M Y H:i:s", time() + (31536000)) . " GMT");
header("Cache-Control: max-age=31536000");
}
echo $data;
// If the photo is public and there is an existing photo directory store the photo there
if ($public and $file != '') {
// If the photo path isn't there, try to create it
$basepath = $a->getBasePath();
if (!is_dir($basepath . "/photo")) {
if (is_writable($basepath)) {
mkdir($basepath . "/photo");
}
}
if (is_dir($basepath . "/photo")) {
file_put_contents($basepath . "/photo/" . $file, $data);
}
}
killme();
// NOTREACHED
}

View file

@ -9,13 +9,12 @@ use Friendica\Content\Nav;
use Friendica\Content\Pager;
use Friendica\Content\Text\BBCode;
use Friendica\Core\ACL;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Group;
@ -154,7 +153,7 @@ function photos_post(App $a)
$visitor = 0;
$page_owner_uid = $a->data['user']['uid'];
$community_page = $a->data['user']['page-flags'] == Contact::PAGE_COMMUNITY;
$community_page = $a->data['user']['page-flags'] == User::PAGE_FLAGS_COMMUNITY;
if (local_user() && (local_user() == $page_owner_uid)) {
$can_post = true;
@ -185,7 +184,7 @@ function photos_post(App $a)
if (!$can_post) {
notice(L10n::t('Permission denied.') . EOL);
killme();
exit();
}
$owner_record = User::getOwnerDataById($page_owner_uid);
@ -193,7 +192,7 @@ function photos_post(App $a)
if (!$owner_record) {
notice(L10n::t('Contact information unavailable') . EOL);
Logger::log('photos_post: unable to locate contact record for page owner. uid=' . $page_owner_uid);
killme();
exit();
}
if ($a->argc > 3 && $a->argv[2] === 'album') {
@ -281,19 +280,15 @@ function photos_post(App $a)
if (DBA::isResult($r)) {
foreach ($r as $rr) {
$res[] = "'" . DBA::escape($rr['rid']) . "'";
$res[] = $rr['rid'];
}
} else {
$a->internalRedirect($_SESSION['photo_return']);
return; // NOTREACHED
}
$str_res = implode(',', $res);
// remove the associated photos
q("DELETE FROM `photo` WHERE `resource-id` IN ($str_res) AND `uid` = %d",
intval($page_owner_uid)
);
Photo::delete(['resource-id' => $res, 'uid' => $page_owner_uid]);
// find and delete the corresponding item with all the comments and likes/dislikes
Item::deleteForUser(['resource-id' => $res, 'uid' => $page_owner_uid], $page_owner_uid);
@ -348,10 +343,7 @@ function photos_post(App $a)
}
if (DBA::isResult($r)) {
q("DELETE FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s'",
intval($page_owner_uid),
DBA::escape($r[0]['resource-id'])
);
Photo::delete(['uid' => $page_owner_uid, 'resource-id' => $r[0]['resource-id']]);
Item::deleteForUser(['resource-id' => $r[0]['resource-id'], 'uid' => $page_owner_uid], $page_owner_uid);
@ -384,13 +376,10 @@ function photos_post(App $a)
if (!empty($_POST['rotate']) && (intval($_POST['rotate']) == 1 || intval($_POST['rotate']) == 2)) {
Logger::log('rotate');
$r = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d AND `scale` = 0 LIMIT 1",
DBA::escape($resource_id),
intval($page_owner_uid)
);
$photo = Photo::getPhotoForUser($page_owner_uid, $resource_id);
if (DBA::isResult($r)) {
$image = new Image($r[0]['data'], $r[0]['type']);
if (DBA::isResult($photo)) {
$image = Photo::getImageForPhoto($photo);
if ($image->isValid()) {
$rotate_deg = ((intval($_POST['rotate']) == 1) ? 270 : 90);
@ -399,26 +388,14 @@ function photos_post(App $a)
$width = $image->getWidth();
$height = $image->getHeight();
$x = q("UPDATE `photo` SET `data` = '%s', `height` = %d, `width` = %d WHERE `resource-id` = '%s' AND `uid` = %d AND `scale` = 0",
DBA::escape($image->asString()),
intval($height),
intval($width),
DBA::escape($resource_id),
intval($page_owner_uid)
);
Photo::update(['height' => $height, 'width' => $width], ['resource-id' => $resource_id, 'uid' => $page_owner_uid, 'scale' => 0], $image);
if ($width > 640 || $height > 640) {
$image->scaleDown(640);
$width = $image->getWidth();
$height = $image->getHeight();
$x = q("UPDATE `photo` SET `data` = '%s', `height` = %d, `width` = %d WHERE `resource-id` = '%s' AND `uid` = %d AND `scale` = 1",
DBA::escape($image->asString()),
intval($height),
intval($width),
DBA::escape($resource_id),
intval($page_owner_uid)
);
Photo::update(['height' => $height, 'width' => $width], ['resource-id' => $resource_id, 'uid' => $page_owner_uid, 'scale' => 1], $image);
}
if ($width > 320 || $height > 320) {
@ -426,50 +403,37 @@ function photos_post(App $a)
$width = $image->getWidth();
$height = $image->getHeight();
$x = q("UPDATE `photo` SET `data` = '%s', `height` = %d, `width` = %d WHERE `resource-id` = '%s' AND `uid` = %d AND `scale` = 2",
DBA::escape($image->asString()),
intval($height),
intval($width),
DBA::escape($resource_id),
intval($page_owner_uid)
);
Photo::update(['height' => $height, 'width' => $width], ['resource-id' => $resource_id, 'uid' => $page_owner_uid, 'scale' => 2], $image);
}
}
}
}
$p = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d ORDER BY `scale` DESC",
DBA::escape($resource_id),
intval($page_owner_uid)
);
$photos_stmt = DBA::select('photo', [], ['resource-id' => $resource_id, 'uid' => $page_owner_uid], ['order' => ['scale' => true]]);
if (DBA::isResult($p)) {
$ext = $phototypes[$p[0]['type']];
$r = q("UPDATE `photo` SET `desc` = '%s', `album` = '%s', `allow_cid` = '%s', `allow_gid` = '%s', `deny_cid` = '%s', `deny_gid` = '%s' WHERE `resource-id` = '%s' AND `uid` = %d",
DBA::escape($desc),
DBA::escape($albname),
DBA::escape($str_contact_allow),
DBA::escape($str_group_allow),
DBA::escape($str_contact_deny),
DBA::escape($str_group_deny),
DBA::escape($resource_id),
intval($page_owner_uid)
$photos = DBA::toArray($photos_stmt);
if (DBA::isResult($photos)) {
$photo = $photos[0];
$ext = $phototypes[$photo['type']];
Photo::update(
['desc' => $desc, 'album' => $albname, 'allow_cid' => $str_contact_allow, 'allow_gid' => $str_group_allow, 'deny_cid' => $str_contact_deny, 'deny_gid' => $str_group_deny],
['resource-id' => $resource_id, 'uid' => $page_owner_uid]
);
// Update the photo albums cache if album name was changed
if ($albname !== $origaname) {
Photo::clearAlbumCache($page_owner_uid);
}
/* Don't make the item visible if the only change was the album name */
$visibility = 0;
if ($photo['desc'] !== $desc || strlen($rawtags)) {
$visibility = 1;
}
}
/* Don't make the item visible if the only change was the album name */
$visibility = 0;
if ($p[0]['desc'] !== $desc || strlen($rawtags)) {
$visibility = 1;
}
if (!$item_id) {
if (DBA::isResult($photos) && !$item_id) {
// Create item container
$title = '';
$uri = Item::newURI($page_owner_uid);
@ -481,7 +445,7 @@ function photos_post(App $a)
$arr['parent-uri'] = $uri;
$arr['post-type'] = Item::PT_IMAGE;
$arr['wall'] = 1;
$arr['resource-id'] = $p[0]['resource-id'];
$arr['resource-id'] = $photo['resource-id'];
$arr['contact-id'] = $owner_record['id'];
$arr['owner-name'] = $owner_record['name'];
$arr['owner-link'] = $owner_record['url'];
@ -490,15 +454,15 @@ function photos_post(App $a)
$arr['author-link'] = $owner_record['url'];
$arr['author-avatar'] = $owner_record['thumb'];
$arr['title'] = $title;
$arr['allow_cid'] = $p[0]['allow_cid'];
$arr['allow_gid'] = $p[0]['allow_gid'];
$arr['deny_cid'] = $p[0]['deny_cid'];
$arr['deny_gid'] = $p[0]['deny_gid'];
$arr['allow_cid'] = $photo['allow_cid'];
$arr['allow_gid'] = $photo['allow_gid'];
$arr['deny_cid'] = $photo['deny_cid'];
$arr['deny_gid'] = $photo['deny_gid'];
$arr['visible'] = $visibility;
$arr['origin'] = 1;
$arr['body'] = '[url=' . System::baseUrl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $p[0]['resource-id'] . ']'
. '[img]' . System::baseUrl() . '/photo/' . $p[0]['resource-id'] . '-' . $p[0]['scale'] . '.'. $ext . '[/img]'
$arr['body'] = '[url=' . System::baseUrl() . '/photos/' . $a->data['user']['nickname'] . '/image/' . $photo['resource-id'] . ']'
. '[img]' . System::baseUrl() . '/photo/' . $photo['resource-id'] . '-' . $photo['scale'] . '.'. $ext . '[/img]'
. '[/url]';
$item_id = Item::insert($arr);
@ -556,7 +520,6 @@ function photos_post(App $a)
$taginfo[] = [$newname, $profile, $salmon];
} else {
$newname = $name;
$alias = '';
$tagcid = 0;
if (strrpos($newname, '+')) {
@ -566,7 +529,7 @@ function photos_post(App $a)
if ($tagcid) {
$r = q("SELECT * FROM `contact` WHERE `id` = %d AND `uid` = %d LIMIT 1",
intval($tagcid),
intval($profile_uid)
intval($page_owner_uid)
);
} else {
$newname = str_replace('_',' ',$name);
@ -637,7 +600,7 @@ function photos_post(App $a)
Item::update($fields, $condition);
$best = 0;
foreach ($p as $scales) {
foreach ($photos as $scales) {
if (intval($scales['scale']) == 2) {
$best = 2;
break;
@ -667,10 +630,10 @@ function photos_post(App $a)
$arr['author-link'] = $owner_record['url'];
$arr['author-avatar'] = $owner_record['thumb'];
$arr['title'] = '';
$arr['allow_cid'] = $p[0]['allow_cid'];
$arr['allow_gid'] = $p[0]['allow_gid'];
$arr['deny_cid'] = $p[0]['deny_cid'];
$arr['deny_gid'] = $p[0]['deny_gid'];
$arr['allow_cid'] = $photo['allow_cid'];
$arr['allow_gid'] = $photo['allow_gid'];
$arr['deny_cid'] = $photo['deny_cid'];
$arr['deny_gid'] = $photo['deny_gid'];
$arr['visible'] = 1;
$arr['verb'] = ACTIVITY_TAG;
$arr['gravity'] = GRAVITY_PARENT;
@ -679,21 +642,21 @@ function photos_post(App $a)
$arr['tag'] = $tagged[4];
$arr['inform'] = $tagged[2];
$arr['origin'] = 1;
$arr['body'] = L10n::t('%1$s was tagged in %2$s by %3$s', '[url=' . $tagged[1] . ']' . $tagged[0] . '[/url]', '[url=' . System::baseUrl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . ']' . L10n::t('a photo') . '[/url]', '[url=' . $owner_record['url'] . ']' . $owner_record['name'] . '[/url]');
$arr['body'] .= "\n\n" . '[url=' . System::baseUrl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . ']' . '[img]' . System::baseUrl() . "/photo/" . $p[0]['resource-id'] . '-' . $best . '.' . $ext . '[/img][/url]' . "\n";
$arr['body'] = L10n::t('%1$s was tagged in %2$s by %3$s', '[url=' . $tagged[1] . ']' . $tagged[0] . '[/url]', '[url=' . System::baseUrl() . '/photos/' . $owner_record['nickname'] . '/image/' . $photo['resource-id'] . ']' . L10n::t('a photo') . '[/url]', '[url=' . $owner_record['url'] . ']' . $owner_record['name'] . '[/url]') ;
$arr['body'] .= "\n\n" . '[url=' . System::baseUrl() . '/photos/' . $owner_record['nickname'] . '/image/' . $photo['resource-id'] . ']' . '[img]' . System::baseUrl() . "/photo/" . $photo['resource-id'] . '-' . $best . '.' . $ext . '[/img][/url]' . "\n" ;
$arr['object'] = '<object><type>' . ACTIVITY_OBJ_PERSON . '</type><title>' . $tagged[0] . '</title><id>' . $tagged[1] . '/' . $tagged[0] . '</id>';
$arr['object'] .= '<link>' . XML::escape('<link rel="alternate" type="text/html" href="' . $tagged[1] . '" />' . "\n");
if ($tagged[3]) {
$arr['object'] .= XML::escape('<link rel="photo" type="'.$p[0]['type'].'" href="' . $tagged[3]['photo'] . '" />' . "\n");
$arr['object'] .= XML::escape('<link rel="photo" type="' . $photo['type'] . '" href="' . $tagged[3]['photo'] . '" />' . "\n");
}
$arr['object'] .= '</link></object>' . "\n";
$arr['target'] = '<target><type>' . ACTIVITY_OBJ_IMAGE . '</type><title>' . $p[0]['desc'] . '</title><id>'
. System::baseUrl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . '</id>';
$arr['target'] .= '<link>' . XML::escape('<link rel="alternate" type="text/html" href="' . System::baseUrl() . '/photos/' . $owner_record['nickname'] . '/image/' . $p[0]['resource-id'] . '" />' . "\n" . '<link rel="preview" type="'.$p[0]['type'].'" href="' . System::baseUrl() . "/photo/" . $p[0]['resource-id'] . '-' . $best . '.' . $ext . '" />') . '</link></target>';
$arr['target'] = '<target><type>' . ACTIVITY_OBJ_IMAGE . '</type><title>' . $photo['desc'] . '</title><id>'
. System::baseUrl() . '/photos/' . $owner_record['nickname'] . '/image/' . $photo['resource-id'] . '</id>';
$arr['target'] .= '<link>' . XML::escape('<link rel="alternate" type="text/html" href="' . System::baseUrl() . '/photos/' . $owner_record['nickname'] . '/image/' . $photo['resource-id'] . '" />' . "\n" . '<link rel="preview" type="' . $photo['type'] . '" href="' . System::baseUrl() . "/photo/" . $photo['resource-id'] . '-' . $best . '.' . $ext . '" />') . '</link></target>';
$item_id = Item::insert($arr);
Item::insert($arr);
}
}
}
@ -703,7 +666,7 @@ function photos_post(App $a)
// default post action - upload a photo
Addon::callHooks('photo_post_init', $_POST);
Hook::callAll('photo_post_init', $_POST);
// Determine the album to use
$album = !empty($_REQUEST['album']) ? Strings::escapeTags(trim($_REQUEST['album'])) : '';
@ -727,10 +690,7 @@ function photos_post(App $a)
* they acquire comments, likes, dislikes, and/or tags
*/
$r = q("SELECT * FROM `photo` WHERE `album` = '%s' AND `uid` = %d AND `created` > UTC_TIMESTAMP() - INTERVAL 3 HOUR ",
DBA::escape($album),
intval($page_owner_uid)
);
$r = Photo::select([], ['`album` = ? AND `uid` = ? AND `created` > UTC_TIMESTAMP() - INTERVAL 3 HOUR', $album, $page_owner_uid]);
if (!DBA::isResult($r) || ($album == L10n::t('Profile Photos'))) {
$visible = 1;
@ -754,7 +714,7 @@ function photos_post(App $a)
$ret = ['src' => '', 'filename' => '', 'filesize' => 0, 'type' => ''];
Addon::callHooks('photo_post_file', $ret);
Hook::callAll('photo_post_file', $ret);
if (!empty($ret['src']) && !empty($ret['filesize'])) {
$src = $ret['src'];
@ -794,7 +754,7 @@ function photos_post(App $a)
}
@unlink($src);
$foo = 0;
Addon::callHooks('photo_post_end', $foo);
Hook::callAll('photo_post_end', $foo);
return;
}
@ -810,7 +770,7 @@ function photos_post(App $a)
notice(L10n::t('Image exceeds size limit of %s', Strings::formatBytes($maximagesize)) . EOL);
@unlink($src);
$foo = 0;
Addon::callHooks('photo_post_end', $foo);
Hook::callAll('photo_post_end', $foo);
return;
}
@ -818,7 +778,7 @@ function photos_post(App $a)
notice(L10n::t('Image file is empty.') . EOL);
@unlink($src);
$foo = 0;
Addon::callHooks('photo_post_end', $foo);
Hook::callAll('photo_post_end', $foo);
return;
}
@ -833,8 +793,8 @@ function photos_post(App $a)
notice(L10n::t('Unable to process image.') . EOL);
@unlink($src);
$foo = 0;
Addon::callHooks('photo_post_end',$foo);
killme();
Hook::callAll('photo_post_end',$foo);
exit();
}
$exif = $image->orient($src);
@ -860,7 +820,7 @@ function photos_post(App $a)
if (!$r) {
Logger::log('mod/photos.php: photos_post(): image store failed', Logger::DEBUG);
notice(L10n::t('Image upload failed.') . EOL);
killme();
exit();
}
if ($width > 640 || $height > 640) {
@ -919,7 +879,7 @@ function photos_post(App $a)
// Update the photo albums cache
Photo::clearAlbumCache($page_owner_uid);
Addon::callHooks('photo_post_end', $item_id);
Hook::callAll('photo_post_end', $item_id);
// addon uploaders should call "killme()" [e.g. exit] within the photo_post_end hook
// if they do not wish to be redirected
@ -980,7 +940,7 @@ function photos_content(App $a)
$owner_uid = $a->data['user']['uid'];
$community_page = (($a->data['user']['page-flags'] == Contact::PAGE_COMMUNITY) ? true : false);
$community_page = (($a->data['user']['page-flags'] == User::PAGE_FLAGS_COMMUNITY) ? true : false);
if (local_user() && (local_user() == $owner_uid)) {
$can_post = true;
@ -1082,7 +1042,7 @@ function photos_content(App $a)
'addon_text' => $uploader,
'default_upload' => true];
Addon::callHooks('photo_upload_form',$ret);
Hook::callAll('photo_upload_form',$ret);
$default_upload_box = Renderer::replaceMacros(Renderer::getMarkupTemplate('photos_default_uploader_box.tpl'), []);
$default_upload_submit = Renderer::replaceMacros(Renderer::getMarkupTemplate('photos_default_uploader_submit.tpl'), [
@ -1604,7 +1564,7 @@ function photos_content(App $a)
}
$response_verbs = ['like'];
$response_verbs[] = 'dislike';
$responses = get_responses($conv_responses, $response_verbs, '', $link_item);
$responses = get_responses($conv_responses, $response_verbs, $link_item);
$paginate = $pager->renderFull($total);
}
@ -1678,7 +1638,6 @@ function photos_content(App $a)
}
$twist = !$twist;
$ext = $phototypes[$rr['type']];
$alt_e = $rr['filename'];

View file

@ -10,5 +10,5 @@ function phpinfo_content()
}
phpinfo();
killme();
exit();
}

View file

@ -4,12 +4,11 @@
*/
use Friendica\App;
use Friendica\Content\Feature;
use Friendica\Content\ForumManager;
use Friendica\Content\Text\BBCode;
use Friendica\Core\Addon;
use Friendica\Core\Cache;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\PConfig;
use Friendica\Core\System;
@ -31,30 +30,31 @@ use Friendica\Util\XML;
*
* Expected JSON structure:
* {
* "result": {
* "intro": 0,
* "mail": 0,
* "net": 0,
* "home": 0,
* "register": 0,
* "all-events": 0,
* "all-events-today": 0,
* "events": 0,
* "events-today": 0,
* "birthdays": 0,
* "birthdays-today": 0,
* "groups": [ ],
* "forums": [ ],
* "notify": 0,
* "notifications": [ ],
* "sysmsgs": {
* "notice": [ ],
* "info": [ ]
* }
* }
* }
* "result": {
* "intro": 0,
* "mail": 0,
* "net": 0,
* "home": 0,
* "register": 0,
* "all-events": 0,
* "all-events-today": 0,
* "events": 0,
* "events-today": 0,
* "birthdays": 0,
* "birthdays-today": 0,
* "groups": [ ],
* "forums": [ ],
* "notify": 0,
* "notifications": [ ],
* "sysmsgs": {
* "notice": [ ],
* "info": [ ]
* }
* }
* }
*
* @param App $a The Friendica App instance
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function ping_init(App $a)
{
@ -115,7 +115,7 @@ function ping_init(App $a)
header("Content-type: text/xml");
echo XML::fromArray($data, $xml);
}
killme();
exit();
}
$notifs = ping_get_notifications(local_user());
@ -129,7 +129,7 @@ function ping_init(App $a)
if (DBA::isResult($items)) {
$items_unseen = Item::inArray($items);
$arr = ['items' => $items_unseen];
Addon::callHooks('network_ping', $arr);
Hook::callAll('network_ping', $arr);
foreach ($items_unseen as $item) {
if ($item['wall']) {
@ -188,7 +188,7 @@ function ping_init(App $a)
);
$mail_count = count($mails);
if (intval(Config::get('config', 'register_policy')) === REGISTER_APPROVE && is_site_admin()) {
if (intval(Config::get('config', 'register_policy')) === \Friendica\Module\Register::APPROVE && is_site_admin()) {
$regs = Friendica\Model\Register::getPending();
if (DBA::isResult($regs)) {
@ -386,7 +386,7 @@ function ping_init(App $a)
echo XML::fromArray(["result" => $data], $xml);
}
killme();
exit();
}
/**
@ -394,6 +394,7 @@ function ping_init(App $a)
*
* @param int $uid User id
* @return array Associative array of notifications
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function ping_get_notifications($uid)
{
@ -480,8 +481,8 @@ function ping_get_notifications($uid)
* @param array $notifs Complete list of notification
* @param array $sysmsgs List of system notice messages
* @param array $sysmsgs_info List of system info messages
* @param array $groups_unseen List of unseen group messages
* @param array $forums_unseen List of unseen forum messages
* @param array $groups_unseen List of unseen group items
* @param array $forums_unseen List of unseen forum items
*
* @return array XML-transform ready data array
*/

View file

@ -26,9 +26,9 @@ function poco_init(App $a) {
}
if ($a->argc > 1) {
$user = Strings::escapeTags(trim($a->argv[1]));
$nickname = Strings::escapeTags(trim($a->argv[1]));
}
if (empty($user)) {
if (empty($nickname)) {
$c = q("SELECT * FROM `pconfig` WHERE `cat` = 'system' AND `k` = 'suggestme' AND `v` = 1");
if (!DBA::isResult($c)) {
System::httpExit(401);
@ -46,7 +46,7 @@ function poco_init(App $a) {
$ret = PortableContact::serverlist();
header('Content-type: application/json');
echo json_encode($ret);
killme();
exit();
}
if ($a->argc > 1 && $a->argv[1] === '@global') {
@ -70,7 +70,7 @@ function poco_init(App $a) {
if (! $system_mode && ! $global) {
$users = q("SELECT `user`.*,`profile`.`hide-friends` from user left join profile on `user`.`uid` = `profile`.`uid`
where `user`.`nickname` = '%s' and `profile`.`is-default` = 1 limit 1",
DBA::escape($user)
DBA::escape($nickname)
);
if (! DBA::isResult($users) || $users[0]['hidewall'] || $users[0]['hide-friends']) {
System::httpExit(404);
@ -378,12 +378,12 @@ function poco_init(App $a) {
if ($format === 'xml') {
header('Content-type: text/xml');
echo Renderer::replaceMacros(Renderer::getMarkupTemplate('poco_xml.tpl'), XML::arrayEscape(['$response' => $ret]));
killme();
exit();
}
if ($format === 'json') {
header('Content-type: application/json');
echo json_encode($ret);
killme();
exit();
} else {
System::httpExit(500);
}

View file

@ -14,12 +14,11 @@
*/
use Friendica\App;
use Friendica\Core\Addon;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Database\DBA;
use Friendica\Model\Item;
use Friendica\Util\Strings;
@ -129,9 +128,9 @@ function poke_init(App $a)
$arr['object'] .= XML::escape('<link rel="photo" type="image/jpeg" href="' . $target['photo'] . '" />' . "\n");
$arr['object'] .= '</link></object>' . "\n";
$item_id = Item::insert($arr);
Item::insert($arr);
Addon::callHooks('post_local_end', $arr);
Hook::callAll('post_local_end', $arr);
return;
}
@ -143,9 +142,6 @@ function poke_content(App $a)
return;
}
$name = '';
$id = '';
if (empty($_GET['c'])) {
return;
}

View file

@ -21,5 +21,5 @@ function pretheme_init(App $a) {
echo json_encode(['img' => Theme::getScreenshot($theme), 'desc' => $desc, 'version' => $version, 'credits' => $credits]);
}
killme();
exit();
}

View file

@ -12,7 +12,7 @@ function probe_content(App $a)
if (!local_user()) {
System::httpExit(403, ["title" => L10n::t("Public access denied."),
"description" => L10n::t("Only logged in users are permitted to perform a probing.")]);
killme();
exit();
}
$o = '<div class="generic-page-wrapper">';

View file

@ -1,325 +0,0 @@
<?php
/**
* @file mod/profile.php
*/
use Friendica\App;
use Friendica\Content\Nav;
use Friendica\Content\Pager;
use Friendica\Content\Widget;
use Friendica\Core\ACL;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\PConfig;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Group;
use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Module\Login;
use Friendica\Protocol\ActivityPub;
use Friendica\Protocol\DFRN;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Security;
use Friendica\Util\Strings;
use Friendica\Util\XML;
function profile_init(App $a)
{
if (empty($a->page['aside'])) {
$a->page['aside'] = '';
}
if ($a->argc < 2) {
System::httpExit(400);
}
$which = filter_var($a->argv[1], FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_BACKTICK);
$profile = 0;
if (local_user() && $a->argc > 2 && $a->argv[2] === 'view') {
$which = $a->user['nickname'];
$profile = filter_var($a->argv[1], FILTER_SANITIZE_NUMBER_INT);
} else {
DFRN::autoRedir($a, $which);
}
if (ActivityPub::isRequest()) {
$user = DBA::selectFirst('user', ['uid'], ['nickname' => $which]);
if (DBA::isResult($user)) {
$data = ActivityPub\Transmitter::getProfile($user['uid']);
header('Content-Type: application/activity+json');
echo json_encode($data);
exit();
}
}
Profile::load($a, $which, $profile);
$blocked = !local_user() && !remote_user() && Config::get('system', 'block_public');
$userblock = !local_user() && !remote_user() && $a->profile['hidewall'];
if (!empty($a->profile['page-flags']) && $a->profile['page-flags'] == Contact::PAGE_COMMUNITY) {
$a->page['htmlhead'] .= '<meta name="friendica.community" content="true" />';
}
if (!empty($a->profile['openidserver'])) {
$a->page['htmlhead'] .= '<link rel="openid.server" href="' . $a->profile['openidserver'] . '" />' . "\r\n";
}
if (!empty($a->profile['openid'])) {
$delegate = strstr($a->profile['openid'], '://') ? $a->profile['openid'] : 'https://' . $a->profile['openid'];
$a->page['htmlhead'] .= '<link rel="openid.delegate" href="' . $delegate . '" />' . "\r\n";
}
// site block
if (!$blocked && !$userblock) {
$keywords = str_replace(['#', ',', ' ', ',,'], ['', ' ', ',', ','], defaults($a->profile, 'pub_keywords', ''));
if (strlen($keywords)) {
$a->page['htmlhead'] .= '<meta name="keywords" content="' . $keywords . '" />' . "\r\n";
}
}
$a->page['htmlhead'] .= '<meta name="dfrn-global-visibility" content="' . ($a->profile['net-publish'] ? 'true' : 'false') . '" />' . "\r\n";
$a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . System::baseUrl() . '/dfrn_poll/' . $which . '" title="DFRN: ' . L10n::t('%s\'s timeline', $a->profile['username']) . '"/>' . "\r\n";
$a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . System::baseUrl() . '/feed/' . $which . '/" title="' . L10n::t('%s\'s posts', $a->profile['username']) . '"/>' . "\r\n";
$a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . System::baseUrl() . '/feed/' . $which . '/comments" title="' . L10n::t('%s\'s comments', $a->profile['username']) . '"/>' . "\r\n";
$a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . System::baseUrl() . '/feed/' . $which . '/activity" title="' . L10n::t('%s\'s timeline', $a->profile['username']) . '"/>' . "\r\n";
$uri = urlencode('acct:' . $a->profile['nickname'] . '@' . $a->getHostName() . ($a->getURLPath() ? '/' . $a->getURLPath() : ''));
$a->page['htmlhead'] .= '<link rel="lrdd" type="application/xrd+xml" href="' . System::baseUrl() . '/xrd/?uri=' . $uri . '" />' . "\r\n";
header('Link: <' . System::baseUrl() . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false);
$dfrn_pages = ['request', 'confirm', 'notify', 'poll'];
foreach ($dfrn_pages as $dfrn) {
$a->page['htmlhead'] .= "<link rel=\"dfrn-{$dfrn}\" href=\"" . System::baseUrl() . "/dfrn_{$dfrn}/{$which}\" />\r\n";
}
$a->page['htmlhead'] .= '<link rel="dfrn-poco" href="' . System::baseUrl() . "/poco/{$which}\" />\r\n";
}
function profile_content(App $a, $update = 0)
{
$category = $datequery = $datequery2 = '';
if ($a->argc > 2) {
for ($x = 2; $x < $a->argc; $x ++) {
if (is_a_date_arg($a->argv[$x])) {
if ($datequery) {
$datequery2 = Strings::escapeHtml($a->argv[$x]);
} else {
$datequery = Strings::escapeHtml($a->argv[$x]);
}
} else {
$category = $a->argv[$x];
}
}
}
if (empty($category)) {
$category = defaults($_GET, 'category', '');
}
$hashtags = defaults($_GET, 'tag', '');
if (Config::get('system', 'block_public') && !local_user() && !remote_user()) {
return Login::form();
}
$groups = [];
$remote_cid = null;
$tab = 'posts';
$o = '';
if ($update) {
// Ensure we've got a profile owner if updating.
$a->profile['profile_uid'] = $update;
} elseif ($a->profile['profile_uid'] == local_user()) {
Nav::setSelected('home');
}
$remote_contact = Contact::isFollower(remote_user(), $a->profile['profile_uid']);
$is_owner = local_user() == $a->profile['profile_uid'];
$last_updated_key = "profile:" . $a->profile['profile_uid'] . ":" . local_user() . ":" . remote_user();
if ($remote_contact) {
$cdata = Contact::getPublicAndUserContacID(remote_user(), $a->profile['profile_uid']);
if (!empty($cdata['user'])) {
$groups = Group::getIdsByContactId($cdata['user']);
$remote_cid = $cdata['user'];
}
}
if (!empty($a->profile['hidewall']) && !$is_owner && !$remote_contact) {
notice(L10n::t('Access to this profile has been restricted.') . EOL);
return;
}
if (!$update) {
$tab = false;
if (!empty($_GET['tab'])) {
$tab = Strings::escapeTags(trim($_GET['tab']));
}
$o .= Profile::getTabs($a, $is_owner, $a->profile['nickname']);
if ($tab === 'profile') {
$o .= Profile::getAdvanced($a);
Addon::callHooks('profile_advanced', $o);
return $o;
}
$o .= Widget::commonFriendsVisitor($a->profile['profile_uid']);
$commpage = $a->profile['page-flags'] == Contact::PAGE_COMMUNITY;
$commvisitor = $commpage && $remote_contact;
$a->page['aside'] .= posted_date_widget(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], $a->profile['profile_uid'], true);
$a->page['aside'] .= Widget::categories(System::baseUrl(true) . '/profile/' . $a->profile['nickname'], (!empty($category) ? XML::escape($category) : ''));
$a->page['aside'] .= Widget::tagCloud();
if (Security::canWriteToUserWall($a->profile['profile_uid'])) {
$x = [
'is_owner' => $is_owner,
'allow_location' => ($is_owner || $commvisitor) && $a->profile['allow_location'],
'default_location' => $is_owner ? $a->user['default-location'] : '',
'nickname' => $a->profile['nickname'],
'lockstate' => is_array($a->user)
&& (strlen($a->user['allow_cid'])
|| strlen($a->user['allow_gid'])
|| strlen($a->user['deny_cid'])
|| strlen($a->user['deny_gid'])
) ? 'lock' : 'unlock',
'acl' => $is_owner ? ACL::getFullSelectorHTML($a->user, true) : '',
'bang' => '',
'visitor' => $is_owner || $commvisitor ? 'block' : 'none',
'profile_uid' => $a->profile['profile_uid'],
];
$o .= status_editor($a, $x);
}
}
// Get permissions SQL - if $remote_contact is true, our remote user has been pre-verified and we already have fetched his/her groups
$sql_extra = Item::getPermissionsSQLByUserId($a->profile['profile_uid'], $remote_contact, $groups, $remote_cid);
$sql_extra2 = '';
if ($update) {
$last_updated = (defaults($_SESSION['last_updated'], $last_updated_key, 0));
// If the page user is the owner of the page we should query for unseen
// items. Otherwise use a timestamp of the last succesful update request.
if ($is_owner || !$last_updated) {
$sql_extra4 = " AND `item`.`unseen`";
} else {
$gmupdate = gmdate(DateTimeFormat::MYSQL, $last_updated);
$sql_extra4 = " AND `item`.`received` > '" . $gmupdate . "'";
}
$items = q("SELECT DISTINCT(`parent-uri`) AS `uri`, `item`.`created`
FROM `item` INNER JOIN `contact` ON `contact`.`id` = `item`.`contact-id`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
WHERE `item`.`uid` = %d AND `item`.`visible` AND
(NOT `item`.`deleted` OR `item`.`gravity` = %d)
AND NOT `item`.`moderated` AND `item`.`wall`
$sql_extra4
$sql_extra
ORDER BY `item`.`created` DESC",
intval($a->profile['profile_uid']), intval(GRAVITY_ACTIVITY)
);
if (!DBA::isResult($items)) {
return '';
}
$pager = new Pager($a->query_string);
} else {
$sql_post_table = "";
if (!empty($category)) {
$sql_post_table = sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
DBA::escape(Strings::protectSprintf($category)), intval(TERM_OBJ_POST), intval(TERM_CATEGORY), intval($a->profile['profile_uid']));
}
if (!empty($hashtags)) {
$sql_post_table .= sprintf("INNER JOIN (SELECT `oid` FROM `term` WHERE `term` = '%s' AND `otype` = %d AND `type` = %d AND `uid` = %d ORDER BY `tid` DESC) AS `term` ON `item`.`id` = `term`.`oid` ",
DBA::escape(Strings::protectSprintf($hashtags)), intval(TERM_OBJ_POST), intval(TERM_HASHTAG), intval($a->profile['profile_uid']));
}
if (!empty($datequery)) {
$sql_extra2 .= Strings::protectSprintf(sprintf(" AND `thread`.`created` <= '%s' ", DBA::escape(DateTimeFormat::convert($datequery, 'UTC', date_default_timezone_get()))));
}
if (!empty($datequery2)) {
$sql_extra2 .= Strings::protectSprintf(sprintf(" AND `thread`.`created` >= '%s' ", DBA::escape(DateTimeFormat::convert($datequery2, 'UTC', date_default_timezone_get()))));
}
// Does the profile page belong to a forum?
// If not then we can improve the performance with an additional condition
$condition = ['uid' => $a->profile['profile_uid'], 'page-flags' => [Contact::PAGE_COMMUNITY, Contact::PAGE_PRVGROUP]];
if (!DBA::exists('user', $condition)) {
$sql_extra3 = sprintf(" AND `thread`.`contact-id` = %d ", intval(intval($a->profile['contact_id'])));
} else {
$sql_extra3 = "";
}
// check if we serve a mobile device and get the user settings
// accordingly
if ($a->is_mobile) {
$itemspage_network = PConfig::get(local_user(), 'system', 'itemspage_mobile_network', 10);
} else {
$itemspage_network = PConfig::get(local_user(), 'system', 'itemspage_network', 20);
}
// now that we have the user settings, see if the theme forces
// a maximum item number which is lower then the user choice
if (($a->force_max_items > 0) && ($a->force_max_items < $itemspage_network)) {
$itemspage_network = $a->force_max_items;
}
$pager = new Pager($a->query_string, $itemspage_network);
$pager_sql = sprintf(" LIMIT %d, %d ", $pager->getStart(), $pager->getItemsPerPage());
$items = q("SELECT `item`.`uri`
FROM `thread`
STRAIGHT_JOIN `item` ON `item`.`id` = `thread`.`iid`
$sql_post_table
STRAIGHT_JOIN `contact` ON `contact`.`id` = `thread`.`contact-id`
AND NOT `contact`.`blocked` AND NOT `contact`.`pending`
WHERE `thread`.`uid` = %d AND `thread`.`visible`
AND NOT `thread`.`deleted`
AND NOT `thread`.`moderated`
AND `thread`.`wall`
$sql_extra3 $sql_extra $sql_extra2
ORDER BY `thread`.`created` DESC $pager_sql",
intval($a->profile['profile_uid'])
);
}
// Set a time stamp for this page. We will make use of it when we
// search for new items (update routine)
$_SESSION['last_updated'][$last_updated_key] = time();
if ($is_owner && !$update && !Config::get('theme', 'hide_eventlist')) {
$o .= Profile::getBirthdays();
$o .= Profile::getEventsReminderHTML();
}
if ($is_owner) {
$unseen = Item::exists(['wall' => true, 'unseen' => true, 'uid' => local_user()]);
if ($unseen) {
$r = Item::update(['unseen' => false],
['wall' => true, 'unseen' => true, 'uid' => local_user()]);
}
}
$o .= conversation($a, $items, $pager, 'profile', $update, false, 'created', $a->profile['profile_uid']);
if (!$update) {
$o .= $pager->renderMinimal(count($items));
}
return $o;
}

View file

@ -15,7 +15,6 @@ use Friendica\Model\Contact;
use Friendica\Model\Photo;
use Friendica\Model\Profile;
use Friendica\Object\Image;
use Friendica\Util\Security;
use Friendica\Util\Strings;
function profile_photo_init(App $a)
@ -73,14 +72,12 @@ function profile_photo_post(App $a)
$srcW = $_POST['xfinal'] - $srcX;
$srcH = $_POST['yfinal'] - $srcY;
$r = q("SELECT * FROM `photo` WHERE `resource-id` = '%s' AND `uid` = %d AND `scale` = %d LIMIT 1", DBA::escape($image_id),
DBA::escape(local_user()), intval($scale));
$base_image = Photo::selectFirst([], ['resource-id' => $image_id, 'uid' => local_user(), 'scale' => $scale]);
$path = 'profile/' . $a->user['nickname'];
if (DBA::isResult($r)) {
$base_image = $r[0];
if (DBA::isResult($base_image)) {
$Image = new Image($base_image['data'], $base_image['type']);
$Image = Photo::getImageForPhoto($base_image);
if ($Image->isValid()) {
$Image->crop(300, $srcX, $srcY, $srcW, $srcH);
@ -112,11 +109,11 @@ function profile_photo_post(App $a)
// If setting for the default profile, unset the profile photo flag from any other photos I own
if ($is_default_profile) {
$r = q("UPDATE `photo` SET `profile` = 0 WHERE `profile` = 1 AND `resource-id` != '%s' AND `uid` = %d",
q("UPDATE `photo` SET `profile` = 0 WHERE `profile` = 1 AND `resource-id` != '%s' AND `uid` = %d",
DBA::escape($base_image['resource-id']), intval(local_user())
);
} else {
$r = q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
q("update profile set photo = '%s', thumb = '%s' where id = %d and uid = %d",
DBA::escape(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-4.' . $Image->getExt()),
DBA::escape(System::baseUrl() . '/photo/' . $base_image['resource-id'] . '-5.' . $Image->getExt()),
intval($_REQUEST['profile']), intval(local_user())
@ -194,9 +191,14 @@ function profile_photo_content(App $a)
$resource_id = $a->argv[2];
//die(":".local_user());
$r = Photo::select([], ["resource-id" => $resource_id, "uid" => local_user()], ["order" => ["scale"=>false]]);
/*
$r = q("SELECT * FROM `photo` WHERE `uid` = %d AND `resource-id` = '%s' ORDER BY `scale` ASC", intval(local_user()),
DBA::escape($resource_id)
);
*/
if (!DBA::isResult($r)) {
notice(L10n::t('Permission denied.') . EOL);
@ -213,9 +215,9 @@ function profile_photo_content(App $a)
// set an already uloaded photo as profile photo
// if photo is in 'Profile Photos', change it in db
if (($r[0]['album'] == L10n::t('Profile Photos')) && ($havescale)) {
$r = q("UPDATE `photo` SET `profile`=0 WHERE `profile`=1 AND `uid`=%d", intval(local_user()));
q("UPDATE `photo` SET `profile`=0 WHERE `profile`=1 AND `uid`=%d", intval(local_user()));
$r = q("UPDATE `photo` SET `profile`=1 WHERE `uid` = %d AND `resource-id` = '%s'", intval(local_user()),
q("UPDATE `photo` SET `profile`=1 WHERE `uid` = %d AND `resource-id` = '%s'", intval(local_user()),
DBA::escape($resource_id)
);
@ -230,7 +232,8 @@ function profile_photo_content(App $a)
$a->internalRedirect('profile/' . $a->user['nickname']);
return; // NOTREACHED
}
$ph = new Image($r[0]['data'], $r[0]['type']);
$ph = Photo::getImageForPhoto($r[0]);
$imagecrop = profile_photo_crop_ui_head($a, $ph);
// go ahead as we have jus uploaded a new photo to crop
}
@ -272,8 +275,6 @@ function profile_photo_content(App $a)
]);
return $o;
}
return; // NOTREACHED
}
function profile_photo_crop_ui_head(App $a, Image $image)

View file

@ -8,8 +8,8 @@ use Friendica\BaseModule;
use Friendica\Content\ContactSelector;
use Friendica\Content\Feature;
use Friendica\Content\Nav;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\PConfig;
use Friendica\Core\Renderer;
@ -19,6 +19,7 @@ use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\GContact;
use Friendica\Model\Profile;
use Friendica\Model\User;
use Friendica\Module\Login;
use Friendica\Network\Probe;
use Friendica\Util\DateTimeFormat;
@ -48,12 +49,12 @@ function profiles_init(App $a) {
// move every contact using this profile as their default to the user default
$r = q("UPDATE `contact` SET `profile-id` = (SELECT `profile`.`id` AS `profile-id` FROM `profile` WHERE `profile`.`is-default` = 1 AND `profile`.`uid` = %d LIMIT 1) WHERE `profile-id` = %d AND `uid` = %d ",
q("UPDATE `contact` SET `profile-id` = (SELECT `profile`.`id` AS `profile-id` FROM `profile` WHERE `profile`.`is-default` = 1 AND `profile`.`uid` = %d LIMIT 1) WHERE `profile-id` = %d AND `uid` = %d ",
intval(local_user()),
intval($a->argv[2]),
intval(local_user())
);
$r = q("DELETE FROM `profile` WHERE `id` = %d AND `uid` = %d",
q("DELETE FROM `profile` WHERE `id` = %d AND `uid` = %d",
intval($a->argv[2]),
intval(local_user())
);
@ -79,7 +80,7 @@ function profiles_init(App $a) {
$r1 = q("SELECT `name`, `photo`, `thumb` FROM `profile` WHERE `uid` = %d AND `is-default` = 1 LIMIT 1",
intval(local_user()));
$r2 = q("INSERT INTO `profile` (`uid` , `profile-name` , `name`, `photo`, `thumb`)
q("INSERT INTO `profile` (`uid` , `profile-name` , `name`, `photo`, `thumb`)
VALUES ( %d, '%s', '%s', '%s', '%s' )",
intval(local_user()),
DBA::escape($name),
@ -117,8 +118,7 @@ function profiles_init(App $a) {
);
if(! DBA::isResult($r1)) {
notice(L10n::t('Profile unavailable to clone.') . EOL);
killme();
return;
exit();
}
unset($r1[0]['id']);
$r1[0]['is-default'] = 0;
@ -150,8 +150,7 @@ function profiles_init(App $a) {
);
if (! DBA::isResult($r)) {
notice(L10n::t('Profile not found.') . EOL);
killme();
return;
exit();
}
Profile::load($a, $a->user['nickname'], $r[0]['id']);
@ -186,7 +185,7 @@ function profiles_post(App $a) {
$namechanged = false;
Addon::callHooks('profile_post', $_POST);
Hook::callAll('profile_post', $_POST);
if (($a->argc > 1) && ($a->argv[1] !== "new") && intval($a->argv[1])) {
$orig = q("SELECT * FROM `profile` WHERE `id` = %d AND `uid` = %d LIMIT 1",
@ -339,57 +338,45 @@ function profiles_post(App $a) {
$hide_friends = (($_POST['hide-friends'] == 1) ? 1: 0);
PConfig::set(local_user(), 'system', 'detailled_profile', (($_POST['detailled_profile'] == 1) ? 1: 0));
PConfig::set(local_user(), 'system', 'detailled_profile', (($_POST['detailed_profile'] == 1) ? 1: 0));
$changes = [];
$value = '';
if ($is_default) {
if ($marital != $orig[0]['marital']) {
$changes[] = '[color=#ff0000]&hearts;[/color] ' . L10n::t('Marital Status');
$value = $marital;
}
if ($withchanged) {
$changes[] = '[color=#ff0000]&hearts;[/color] ' . L10n::t('Romantic Partner');
$value = strip_tags($with);
}
if ($likes != $orig[0]['likes']) {
$changes[] = L10n::t('Likes');
$value = $likes;
}
if ($dislikes != $orig[0]['dislikes']) {
$changes[] = L10n::t('Dislikes');
$value = $dislikes;
}
if ($work != $orig[0]['work']) {
$changes[] = L10n::t('Work/Employment');
}
if ($religion != $orig[0]['religion']) {
$changes[] = L10n::t('Religion');
$value = $religion;
}
if ($politic != $orig[0]['politic']) {
$changes[] = L10n::t('Political Views');
$value = $politic;
}
if ($gender != $orig[0]['gender']) {
$changes[] = L10n::t('Gender');
$value = $gender;
}
if ($sexual != $orig[0]['sexual']) {
$changes[] = L10n::t('Sexual Preference');
$value = $sexual;
}
if ($xmpp != $orig[0]['xmpp']) {
$changes[] = L10n::t('XMPP');
$value = $xmpp;
}
if ($homepage != $orig[0]['homepage']) {
$changes[] = L10n::t('Homepage');
$value = $homepage;
}
if ($interest != $orig[0]['interest']) {
$changes[] = L10n::t('Interests');
$value = $interest;
}
if ($address != $orig[0]['address']) {
$changes[] = L10n::t('Address');
@ -400,9 +387,6 @@ function profiles_post(App $a) {
if ($locality != $orig[0]['locality'] || $region != $orig[0]['region']
|| $country_name != $orig[0]['country-name']) {
$changes[] = L10n::t('Location');
$comma1 = ((($locality) && ($region || $country_name)) ? ', ' : ' ');
$comma2 = (($region && $country_name) ? ', ' : '');
$value = $locality . $comma1 . $region . $comma2 . $country_name;
}
}
@ -487,7 +471,7 @@ function profiles_post(App $a) {
if ($is_default) {
if ($namechanged) {
$r = q("UPDATE `user` set `username` = '%s' where `uid` = %d",
q("UPDATE `user` set `username` = '%s' where `uid` = %d",
DBA::escape($name),
intval(local_user())
);
@ -549,20 +533,20 @@ function profiles_content(App $a) {
]);
$personal_account = !(in_array($a->user["page-flags"],
[Contact::PAGE_COMMUNITY, Contact::PAGE_PRVGROUP]));
[User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP]));
$detailled_profile = (PConfig::get(local_user(), 'system', 'detailled_profile') AND $personal_account);
$detailed_profile = (PConfig::get(local_user(), 'system', 'detailled_profile') AND $personal_account);
$is_default = (($r[0]['is-default']) ? 1 : 0);
$tpl = Renderer::getMarkupTemplate("profile_edit.tpl");
$o .= Renderer::replaceMacros($tpl, [
'$personal_account' => $personal_account,
'$detailled_profile' => $detailled_profile,
'$detailled_profile' => $detailed_profile,
'$details' => [
'detailled_profile', //Name
'detailed_profile', //Name
L10n::t('Show more profile fields:'), //Label
$detailled_profile, //Value
$detailed_profile, //Value
'', //Help string
[L10n::t('No'), L10n::t('Yes')] //Off - On strings
],
@ -618,11 +602,11 @@ function profiles_content(App $a) {
'$postal_code' => ['postal_code', L10n::t('Postal/Zip Code:'), $r[0]['postal-code']],
'$country_name' => ['country_name', L10n::t('Country:'), $r[0]['country-name']],
'$age' => ((intval($r[0]['dob'])) ? '(' . L10n::t('Age: ') . Temporal::getAgeByTimezone($r[0]['dob'],$a->user['timezone'],$a->user['timezone']) . ')' : ''),
'$gender' => ContactSelector::gender($r[0]['gender']),
'$marital' => ['selector' => ContactSelector::maritalStatus($r[0]['marital']), 'value' => $r[0]['marital']],
'$gender' => L10n::t(ContactSelector::gender($r[0]['gender'])),
'$marital' => ['selector' => ContactSelector::maritalStatus($r[0]['marital']), 'value' => L10n::t($r[0]['marital'])],
'$with' => ['with', L10n::t("Who: \x28if applicable\x29"), strip_tags($r[0]['with']), L10n::t('Examples: cathy123, Cathy Williams, cathy@example.com')],
'$howlong' => ['howlong', L10n::t('Since [date]:'), ($r[0]['howlong'] <= DBA::NULL_DATETIME ? '' : DateTimeFormat::local($r[0]['howlong']))],
'$sexual' => ['selector' => ContactSelector::sexualPreference($r[0]['sexual']), 'value' => $r[0]['sexual']],
'$sexual' => ['selector' => ContactSelector::sexualPreference($r[0]['sexual']), 'value' => L10n::t($r[0]['sexual'])],
'$about' => ['about', L10n::t('Tell us about yourself...'), $r[0]['about']],
'$xmpp' => ['xmpp', L10n::t("XMPP \x28Jabber\x29 address:"), $r[0]['xmpp'], L10n::t("The XMPP address will be propagated to your contacts so that they can follow you.")],
'$homepage' => ['homepage', L10n::t('Homepage URL:'), $r[0]['homepage']],
@ -645,7 +629,7 @@ function profiles_content(App $a) {
]);
$arr = ['profile' => $r[0], 'entry' => $o];
Addon::callHooks('profile_edit', $arr);
Hook::callAll('profile_edit', $arr);
return $o;
} else {

View file

@ -165,7 +165,7 @@ function profperm_content(App $a) {
if (!empty($change)) {
echo $o;
killme();
exit();
}
$o .= '</div>';
return $o;

View file

@ -17,7 +17,7 @@ function hub_return($valid, $body)
} else {
System::httpExit(404);
}
killme();
exit();
}
// when receiving an XML feed, always return OK
@ -36,7 +36,6 @@ function pubsub_init(App $a)
$hub_mode = Strings::escapeTags(trim(defaults($_GET, 'hub_mode', '')));
$hub_topic = Strings::escapeTags(trim(defaults($_GET, 'hub_topic', '')));
$hub_challenge = Strings::escapeTags(trim(defaults($_GET, 'hub_challenge', '')));
$hub_lease = Strings::escapeTags(trim(defaults($_GET, 'hub_lease_seconds', '')));
$hub_verify = Strings::escapeTags(trim(defaults($_GET, 'hub_verify_token', '')));
Logger::log('Subscription from ' . $_SERVER['REMOTE_ADDR'] . ' Mode: ' . $hub_mode . ' Nick: ' . $nick);

View file

@ -33,7 +33,6 @@ function pubsubhubbub_init(App $a) {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$hub_mode = post_var('hub_mode');
$hub_callback = post_var('hub_callback');
$hub_verify = post_var('hub_verify');
$hub_verify_token = post_var('hub_verify_token');
$hub_secret = post_var('hub_secret');
$hub_topic = post_var('hub_topic');
@ -136,5 +135,5 @@ function pubsubhubbub_init(App $a) {
System::httpExit(202);
}
killme();
exit();
}

View file

@ -3,10 +3,8 @@
* @file mod/randprof.php
*/
use Friendica\App;
use Friendica\Core\System;
use Friendica\Model\Contact;
use Friendica\Model\GContact;
use Friendica\Model\Profile;
function randprof_init(App $a)
{

View file

@ -12,8 +12,10 @@ use Friendica\Database\DBA;
use Friendica\Protocol\Diaspora;
/**
* @param object $a App
* @param App $a App
* @return void
* @throws ImagickException
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function receive_post(App $a)
{

View file

@ -3,7 +3,6 @@
use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;

View file

@ -1,289 +0,0 @@
<?php
/**
* @file mod/register.php
*/
use Friendica\App;
use Friendica\BaseModule;
use Friendica\Content\Text\BBCode;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\PConfig;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Core\Worker;
use Friendica\Model;
use Friendica\Module\Tos;
use Friendica\Util\Strings;
function register_post(App $a)
{
BaseModule::checkFormSecurityTokenRedirectOnError('/register', 'register');
$verified = 0;
$blocked = 1;
$arr = ['post' => $_POST];
Addon::callHooks('register_post', $arr);
$max_dailies = intval(Config::get('system', 'max_daily_registrations'));
if ($max_dailies) {
$r = q("select count(*) as total from user where register_date > UTC_TIMESTAMP - INTERVAL 1 day");
if ($r && $r[0]['total'] >= $max_dailies) {
return;
}
}
switch (Config::get('config', 'register_policy')) {
case REGISTER_OPEN:
$blocked = 0;
$verified = 1;
break;
case REGISTER_APPROVE:
$blocked = 1;
$verified = 0;
break;
default:
case REGISTER_CLOSED:
if (empty($_SESSION['authenticated']) && empty($_SESSION['administrator'])) {
notice(L10n::t('Permission denied.') . EOL);
return;
}
$blocked = 1;
$verified = 0;
break;
}
$netpublish = !empty($_POST['profile_publish_reg']);
$arr = $_POST;
$arr['blocked'] = $blocked;
$arr['verified'] = $verified;
$arr['language'] = L10n::detectLanguage();
try {
$result = Model\User::create($arr);
} catch (Exception $e) {
notice($e->getMessage());
return;
}
$user = $result['user'];
if ($netpublish && intval(Config::get('config', 'register_policy')) !== REGISTER_APPROVE) {
$url = $a->getBaseUrl() . '/profile/' . $user['nickname'];
Worker::add(PRIORITY_LOW, "Directory", $url);
}
$using_invites = Config::get('system', 'invitation_only');
$num_invites = Config::get('system', 'number_invites');
$invite_id = (!empty($_POST['invite_id']) ? Strings::escapeTags(trim($_POST['invite_id'])) : '');
if (intval(Config::get('config', 'register_policy')) === REGISTER_OPEN) {
if ($using_invites && $invite_id) {
Model\Register::deleteByHash($invite_id);
PConfig::set($user['uid'], 'system', 'invites_remaining', $num_invites);
}
// Only send a password mail when the password wasn't manually provided
if (empty($_POST['password1']) || empty($_POST['confirm'])) {
$res = Model\User::sendRegisterOpenEmail(
$user,
Config::get('config', 'sitename'),
$a->getBaseUrl(),
$result['password']
);
if ($res) {
info(L10n::t('Registration successful. Please check your email for further instructions.') . EOL);
$a->internalRedirect();
} else {
notice(
L10n::t('Failed to send email message. Here your accout details:<br> login: %s<br> password: %s<br><br>You can change your password after login.',
$user['email'],
$result['password'])
. EOL
);
}
} else {
info(L10n::t('Registration successful.') . EOL);
$a->internalRedirect();
}
} elseif (intval(Config::get('config', 'register_policy')) === REGISTER_APPROVE) {
if (!strlen(Config::get('config', 'admin_email'))) {
notice(L10n::t('Your registration can not be processed.') . EOL);
$a->internalRedirect();
}
Model\Register::createForApproval($user['uid'], Config::get('system', 'language'), $_POST['permonlybox']);
// invite system
if ($using_invites && $invite_id) {
Model\Register::deleteByHash($invite_id);
PConfig::set($user['uid'], 'system', 'invites_remaining', $num_invites);
}
// send email to admins
$admin_mail_list = "'" . implode("','", array_map(['Friendica\Database\DBA', 'escape'], explode(",", str_replace(" ", "", Config::get('config', 'admin_email'))))) . "'";
$adminlist = q("SELECT uid, language, email FROM user WHERE email IN (%s)",
$admin_mail_list
);
// send notification to admins
foreach ($adminlist as $admin) {
notification([
'type' => NOTIFY_SYSTEM,
'event' => 'SYSTEM_REGISTER_REQUEST',
'source_name' => $user['username'],
'source_mail' => $user['email'],
'source_nick' => $user['nickname'],
'source_link' => $a->getBaseUrl() . "/admin/users/",
'link' => $a->getBaseUrl() . "/admin/users/",
'source_photo' => $a->getBaseUrl() . "/photo/avatar/" . $user['uid'] . ".jpg",
'to_email' => $admin['email'],
'uid' => $admin['uid'],
'language' => $admin['language'] ? $admin['language'] : 'en',
'show_in_notification_page' => false
]);
}
// send notification to the user, that the registration is pending
Model\User::sendRegisterPendingEmail(
$user,
Config::get('config', 'sitename'),
$a->getBaseURL(),
$result['password']
);
info(L10n::t('Your registration is pending approval by the site owner.') . EOL);
$a->internalRedirect();
}
return;
}
function register_content(App $a)
{
// logged in users can register others (people/pages/groups)
// even with closed registrations, unless specifically prohibited by site policy.
// 'block_extended_register' blocks all registrations, period.
$block = Config::get('system', 'block_extended_register');
if (local_user() && ($block)) {
notice("Permission denied." . EOL);
return;
}
if ((!local_user()) && (intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED)) {
notice("Permission denied." . EOL);
return;
}
$max_dailies = intval(Config::get('system', 'max_daily_registrations'));
if ($max_dailies) {
$r = q("select count(*) as total from user where register_date > UTC_TIMESTAMP - INTERVAL 1 day");
if ($r && $r[0]['total'] >= $max_dailies) {
Logger::log('max daily registrations exceeded.');
notice(L10n::t('This site has exceeded the number of allowed daily account registrations. Please try again tomorrow.') . EOL);
return;
}
}
if (!empty($_SESSION['theme'])) {
unset($_SESSION['theme']);
}
if (!empty($_SESSION['mobile-theme'])) {
unset($_SESSION['mobile-theme']);
}
$username = defaults($_REQUEST, 'username' , '');
$email = defaults($_REQUEST, 'email' , '');
$openid_url = defaults($_REQUEST, 'openid_url', '');
$nickname = defaults($_REQUEST, 'nickname' , '');
$photo = defaults($_REQUEST, 'photo' , '');
$invite_id = defaults($_REQUEST, 'invite_id' , '');
$noid = Config::get('system', 'no_openid');
if ($noid) {
$fillwith = '';
$fillext = '';
$oidlabel = '';
} else {
$fillwith = L10n::t("You may \x28optionally\x29 fill in this form via OpenID by supplying your OpenID and clicking 'Register'.");
$fillext = L10n::t('If you are not familiar with OpenID, please leave that field blank and fill in the rest of the items.');
$oidlabel = L10n::t("Your OpenID \x28optional\x29: ");
}
if (Config::get('system', 'publish_all')) {
$profile_publish = '<input type="hidden" name="profile_publish_reg" value="1" />';
} else {
$publish_tpl = Renderer::getMarkupTemplate("profile_publish.tpl");
$profile_publish = Renderer::replaceMacros($publish_tpl, [
'$instance' => 'reg',
'$pubdesc' => L10n::t('Include your profile in member directory?'),
'$yes_selected' => '',
'$no_selected' => ' checked="checked"',
'$str_yes' => L10n::t('Yes'),
'$str_no' => L10n::t('No'),
]);
}
$r = q("SELECT COUNT(*) AS `contacts` FROM `contact`");
$passwords = !$r[0]["contacts"];
$tpl = Renderer::getMarkupTemplate("register.tpl");
$arr = ['template' => $tpl];
Addon::callHooks('register_form', $arr);
$tpl = $arr['template'];
$tos = new Tos();
$o = Renderer::replaceMacros($tpl, [
'$invitations' => Config::get('system', 'invitation_only'),
'$permonly' => intval(Config::get('config', 'register_policy')) === REGISTER_APPROVE,
'$permonlybox' => ['permonlybox', L10n::t('Note for the admin'), '', L10n::t('Leave a message for the admin, why you want to join this node')],
'$invite_desc' => L10n::t('Membership on this site is by invitation only.'),
'$invite_label' => L10n::t('Your invitation code: '),
'$invite_id' => $invite_id,
'$regtitle' => L10n::t('Registration'),
'$registertext' => BBCode::convert(Config::get('config', 'register_text', '')),
'$fillwith' => $fillwith,
'$fillext' => $fillext,
'$oidlabel' => $oidlabel,
'$openid' => $openid_url,
'$namelabel' => L10n::t('Your Full Name ' . "\x28" . 'e.g. Joe Smith, real or real-looking' . "\x29" . ': '),
'$addrlabel' => L10n::t("Your Email Address: \x28Initial information will be send there, so this has to be an existing address.\x29"),
'$passwords' => $passwords,
'$password1' => ['password1', L10n::t('New Password:'), '', L10n::t('Leave empty for an auto generated password.')],
'$password2' => ['confirm', L10n::t('Confirm:'), '', ''],
'$nickdesc' => L10n::t('Choose a profile nickname. This must begin with a text character. Your profile address on this site will then be \'<strong>nickname@%s</strong>\'.', $a->getHostName()),
'$nicklabel' => L10n::t('Choose a nickname: '),
'$photo' => $photo,
'$publish' => $profile_publish,
'$regbutt' => L10n::t('Register'),
'$username' => $username,
'$email' => $email,
'$nickname' => $nickname,
'$sitename' => $a->getHostName(),
'$importh' => L10n::t('Import'),
'$importt' => L10n::t('Import your profile to this friendica instance'),
'$showtoslink' => Config::get('system', 'tosdisplay'),
'$tostext' => L10n::t('Terms of Service'),
'$showprivstatement' => Config::get('system', 'tosprivstatement'),
'$privstatement' => $tos->privacy_complete,
'$baseurl' => System::baseurl(),
'$form_security_token' => BaseModule::getFormSecurityToken("register"),
'$explicit_content' => Config::get('system', 'explicit_content', false),
'$explicit_content_note' => L10n::t('Note: This node explicitly contains adult content')
]);
return $o;
}

View file

@ -82,7 +82,7 @@ function regmod_content(App $a)
{
if (!local_user()) {
info(L10n::t('Please login.') . EOL);
return Login::form($a->query_string, intval(Config::get('config', 'register_policy')) === REGISTER_CLOSED ? 0 : 1);
return Login::form($a->query_string, intval(Config::get('config', 'register_policy')) === \Friendica\Module\Register::CLOSED ? 0 : 1);
}
if (!is_site_admin() || !empty($_SESSION['submanage'])) {

View file

@ -7,7 +7,6 @@ use Friendica\App;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\User;
use Friendica\Util\Strings;

View file

@ -57,7 +57,7 @@ function repair_ostatus_content(App $a) {
$o .= "<p>".L10n::t("Keep this window open until done.")."</p>";
$result = Contact::createFromProbe($uid, $r[0]["url"], true);
Contact::createFromProbe($uid, $r[0]["url"], true);
$a->page['htmlhead'] = '<meta http-equiv="refresh" content="1; URL='.System::baseUrl().'/repair_ostatus?counter='.$counter.'">';

View file

@ -26,5 +26,5 @@ function robots_txt_init(App $a)
foreach ($allDisalloweds as $disallowed) {
echo 'Disallow: ' . $disallowed . PHP_EOL;
}
killme();
exit();
}

View file

@ -22,5 +22,5 @@ function rsd_xml_content(App $a)
</service>
</rsd>';
killme();
exit();
}

View file

@ -23,7 +23,6 @@ function salmon_post(App $a, $xml = '') {
Logger::log('new salmon ' . $xml, Logger::DATA);
$nick = (($a->argc > 1) ? Strings::escapeTags(trim($a->argv[1])) : '');
$mentions = (($a->argc > 2 && $a->argv[2] === 'mention') ? true : false);
$r = q("SELECT * FROM `user` WHERE `nickname` = '%s' AND `account_expired` = 0 AND `account_removed` = 0 LIMIT 1",
DBA::escape($nick)
@ -185,7 +184,7 @@ function salmon_post(App $a, $xml = '') {
// Placeholder for hub discovery.
$hub = '';
$contact_rec = ((DBA::isResult($r)) ? $r[0] : null);
$contact_rec = ((DBA::isResult($r)) ? $r[0] : []);
OStatus::import($data, $importer, $contact_rec, $hub);

View file

@ -4,7 +4,6 @@
*/
use Friendica\App;
use Friendica\Content\Feature;
use Friendica\Content\Nav;
use Friendica\Content\Pager;
use Friendica\Content\Text\HTML;
@ -102,7 +101,7 @@ function search_content(App $a) {
System::httpExit(403,
["title" => L10n::t("Public access denied."),
"description" => L10n::t("Only logged in users are permitted to perform a search.")]);
killme();
exit();
//notice(L10n::t('Public access denied.').EOL);
//return;
}
@ -127,7 +126,7 @@ function search_content(App $a) {
System::httpExit(429,
["title" => L10n::t("Too Many Requests"),
"description" => L10n::t("Only one search per minute is permitted for not logged in users.")]);
killme();
exit();
}
Cache::set("remote_search:".$remote, json_encode(["time" => time(), "accesses" => $resultdata->accesses + 1]), Cache::HOUR);
} else

View file

@ -8,8 +8,8 @@ use Friendica\BaseModule;
use Friendica\Content\Feature;
use Friendica\Content\Nav;
use Friendica\Core\ACL;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\PConfig;
@ -215,7 +215,7 @@ function settings_post(App $a)
if (($a->argc > 1) && ($a->argv[1] == 'addon')) {
BaseModule::checkFormSecurityTokenRedirectOnError('/settings/addon', 'settings_addon');
Addon::callHooks('addon_settings_post', $_POST);
Hook::callAll('addon_settings_post', $_POST);
return;
}
@ -297,7 +297,7 @@ function settings_post(App $a)
}
}
Addon::callHooks('connector_settings_post', $_POST);
Hook::callAll('connector_settings_post', $_POST);
return;
}
@ -367,12 +367,12 @@ function settings_post(App $a)
}
Theme::install($theme);
$r = q("UPDATE `user` SET `theme` = '%s' WHERE `uid` = %d",
q("UPDATE `user` SET `theme` = '%s' WHERE `uid` = %d",
DBA::escape($theme),
intval(local_user())
);
Addon::callHooks('display_settings_post', $_POST);
Hook::callAll('display_settings_post', $_POST);
$a->internalRedirect('settings/display');
return; // NOTREACHED
}
@ -385,7 +385,7 @@ function settings_post(App $a)
$a->internalRedirect('settings');
}
Addon::callHooks('settings_post', $_POST);
Hook::callAll('settings_post', $_POST);
if (!empty($_POST['password']) || !empty($_POST['confirm'])) {
$newpass = $_POST['password'];
@ -474,18 +474,16 @@ function settings_post(App $a)
}
// Adjust the page flag if the account type doesn't fit to the page flag.
if (($account_type == Contact::ACCOUNT_TYPE_PERSON) && !in_array($page_flags, [Contact::PAGE_NORMAL, Contact::PAGE_SOAPBOX, Contact::PAGE_FREELOVE])) {
$page_flags = Contact::PAGE_NORMAL;
} elseif (($account_type == Contact::ACCOUNT_TYPE_ORGANISATION) && !in_array($page_flags, [Contact::PAGE_SOAPBOX])) {
$page_flags = Contact::PAGE_SOAPBOX;
} elseif (($account_type == Contact::ACCOUNT_TYPE_NEWS) && !in_array($page_flags, [Contact::PAGE_SOAPBOX])) {
$page_flags = Contact::PAGE_SOAPBOX;
} elseif (($account_type == Contact::ACCOUNT_TYPE_COMMUNITY) && !in_array($page_flags, [Contact::PAGE_COMMUNITY, Contact::PAGE_PRVGROUP])) {
$page_flags = Contact::PAGE_COMMUNITY;
if (($account_type == User::ACCOUNT_TYPE_PERSON) && !in_array($page_flags, [User::PAGE_FLAGS_NORMAL, User::PAGE_FLAGS_SOAPBOX, User::PAGE_FLAGS_FREELOVE])) {
$page_flags = User::PAGE_FLAGS_NORMAL;
} elseif (($account_type == User::ACCOUNT_TYPE_ORGANISATION) && !in_array($page_flags, [User::PAGE_FLAGS_SOAPBOX])) {
$page_flags = User::PAGE_FLAGS_SOAPBOX;
} elseif (($account_type == User::ACCOUNT_TYPE_NEWS) && !in_array($page_flags, [User::PAGE_FLAGS_SOAPBOX])) {
$page_flags = User::PAGE_FLAGS_SOAPBOX;
} elseif (($account_type == User::ACCOUNT_TYPE_COMMUNITY) && !in_array($page_flags, [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP])) {
$page_flags = User::PAGE_FLAGS_COMMUNITY;
}
$email_changed = false;
$err = '';
if ($username != $a->user['username']) {
@ -498,7 +496,6 @@ function settings_post(App $a)
}
if ($email != $a->user['email']) {
$email_changed = true;
// check for the correct password
if (!User::authenticate(intval(local_user()), $_POST['mpassword'])) {
$err .= L10n::t('Wrong Password') . EOL;
@ -558,7 +555,7 @@ function settings_post(App $a)
PConfig::set(local_user(), 'system', 'email_textonly', $email_textonly);
PConfig::set(local_user(), 'system', 'detailed_notif', $detailed_notif);
if ($page_flags == Contact::PAGE_PRVGROUP) {
if ($page_flags == User::PAGE_FLAGS_PRVGROUP) {
$hidewall = 1;
if (!$str_contact_allow && !$str_group_allow && !$str_contact_deny && !$str_group_deny) {
if ($def_gid) {
@ -611,7 +608,7 @@ function settings_post(App $a)
// clear session language
unset($_SESSION['language']);
$r = q("UPDATE `profile`
q("UPDATE `profile`
SET `publish` = %d,
`name` = '%s',
`net-publish` = %d,
@ -743,7 +740,7 @@ function settings_content(App $a)
$settings_addons = L10n::t('No Addon settings configured');
}
Addon::callHooks('addon_settings', $settings_addons);
Hook::callAll('addon_settings', $settings_addons);
$tpl = Renderer::getMarkupTemplate('settings/addons.tpl');
@ -790,7 +787,7 @@ function settings_content(App $a)
}
$settings_connectors = '';
Addon::callHooks('connector_settings', $settings_connectors);
Hook::callAll('connector_settings', $settings_connectors);
if (is_site_admin()) {
$diasp_enabled = L10n::t('Built-in support for %s connectivity is %s', L10n::t('Diaspora'), ((Config::get('system', 'diaspora_enabled')) ? L10n::t('enabled') : L10n::t('disabled')));
@ -863,7 +860,7 @@ function settings_content(App $a)
'$submit' => L10n::t('Save Settings'),
]);
Addon::callHooks('display_settings', $o);
Hook::callAll('display_settings', $o);
return $o;
}
@ -1017,9 +1014,9 @@ function settings_content(App $a)
// Set the account type to "Community" when the page is a community page but the account type doesn't fit
// This is only happening on the first visit after the update
if (in_array($a->user['page-flags'], [Contact::PAGE_COMMUNITY, Contact::PAGE_PRVGROUP]) &&
($a->user['account-type'] != Contact::ACCOUNT_TYPE_COMMUNITY))
$a->user['account-type'] = Contact::ACCOUNT_TYPE_COMMUNITY;
if (in_array($a->user['page-flags'], [User::PAGE_FLAGS_COMMUNITY, User::PAGE_FLAGS_PRVGROUP]) &&
($a->user['account-type'] != User::ACCOUNT_TYPE_COMMUNITY))
$a->user['account-type'] = User::ACCOUNT_TYPE_COMMUNITY;
$pageset_tpl = Renderer::getMarkupTemplate('settings/pagetypes.tpl');
@ -1028,46 +1025,46 @@ function settings_content(App $a)
'$user' => L10n::t("Personal Page Subtypes"),
'$community' => L10n::t("Community Forum Subtypes"),
'$account_type' => $a->user['account-type'],
'$type_person' => Contact::ACCOUNT_TYPE_PERSON,
'$type_organisation' => Contact::ACCOUNT_TYPE_ORGANISATION,
'$type_news' => Contact::ACCOUNT_TYPE_NEWS,
'$type_community' => Contact::ACCOUNT_TYPE_COMMUNITY,
'$type_person' => User::ACCOUNT_TYPE_PERSON,
'$type_organisation' => User::ACCOUNT_TYPE_ORGANISATION,
'$type_news' => User::ACCOUNT_TYPE_NEWS,
'$type_community' => User::ACCOUNT_TYPE_COMMUNITY,
'$account_person' => ['account-type', L10n::t('Personal Page'), Contact::ACCOUNT_TYPE_PERSON,
'$account_person' => ['account-type', L10n::t('Personal Page'), User::ACCOUNT_TYPE_PERSON,
L10n::t('Account for a personal profile.'),
($a->user['account-type'] == Contact::ACCOUNT_TYPE_PERSON)],
($a->user['account-type'] == User::ACCOUNT_TYPE_PERSON)],
'$account_organisation' => ['account-type', L10n::t('Organisation Page'), Contact::ACCOUNT_TYPE_ORGANISATION,
'$account_organisation' => ['account-type', L10n::t('Organisation Page'), User::ACCOUNT_TYPE_ORGANISATION,
L10n::t('Account for an organisation that automatically approves contact requests as "Followers".'),
($a->user['account-type'] == Contact::ACCOUNT_TYPE_ORGANISATION)],
($a->user['account-type'] == User::ACCOUNT_TYPE_ORGANISATION)],
'$account_news' => ['account-type', L10n::t('News Page'), Contact::ACCOUNT_TYPE_NEWS,
'$account_news' => ['account-type', L10n::t('News Page'), User::ACCOUNT_TYPE_NEWS,
L10n::t('Account for a news reflector that automatically approves contact requests as "Followers".'),
($a->user['account-type'] == Contact::ACCOUNT_TYPE_NEWS)],
($a->user['account-type'] == User::ACCOUNT_TYPE_NEWS)],
'$account_community' => ['account-type', L10n::t('Community Forum'), Contact::ACCOUNT_TYPE_COMMUNITY,
'$account_community' => ['account-type', L10n::t('Community Forum'), User::ACCOUNT_TYPE_COMMUNITY,
L10n::t('Account for community discussions.'),
($a->user['account-type'] == Contact::ACCOUNT_TYPE_COMMUNITY)],
($a->user['account-type'] == User::ACCOUNT_TYPE_COMMUNITY)],
'$page_normal' => ['page-flags', L10n::t('Normal Account Page'), Contact::PAGE_NORMAL,
'$page_normal' => ['page-flags', L10n::t('Normal Account Page'), User::PAGE_FLAGS_NORMAL,
L10n::t('Account for a regular personal profile that requires manual approval of "Friends" and "Followers".'),
($a->user['page-flags'] == Contact::PAGE_NORMAL)],
($a->user['page-flags'] == User::PAGE_FLAGS_NORMAL)],
'$page_soapbox' => ['page-flags', L10n::t('Soapbox Page'), Contact::PAGE_SOAPBOX,
'$page_soapbox' => ['page-flags', L10n::t('Soapbox Page'), User::PAGE_FLAGS_SOAPBOX,
L10n::t('Account for a public profile that automatically approves contact requests as "Followers".'),
($a->user['page-flags'] == Contact::PAGE_SOAPBOX)],
($a->user['page-flags'] == User::PAGE_FLAGS_SOAPBOX)],
'$page_community' => ['page-flags', L10n::t('Public Forum'), Contact::PAGE_COMMUNITY,
'$page_community' => ['page-flags', L10n::t('Public Forum'), User::PAGE_FLAGS_COMMUNITY,
L10n::t('Automatically approves all contact requests.'),
($a->user['page-flags'] == Contact::PAGE_COMMUNITY)],
($a->user['page-flags'] == User::PAGE_FLAGS_COMMUNITY)],
'$page_freelove' => ['page-flags', L10n::t('Automatic Friend Page'), Contact::PAGE_FREELOVE,
'$page_freelove' => ['page-flags', L10n::t('Automatic Friend Page'), User::PAGE_FLAGS_FREELOVE,
L10n::t('Account for a popular profile that automatically approves contact requests as "Friends".'),
($a->user['page-flags'] == Contact::PAGE_FREELOVE)],
($a->user['page-flags'] == User::PAGE_FLAGS_FREELOVE)],
'$page_prvgroup' => ['page-flags', L10n::t('Private Forum [Experimental]'), Contact::PAGE_PRVGROUP,
'$page_prvgroup' => ['page-flags', L10n::t('Private Forum [Experimental]'), User::PAGE_FLAGS_PRVGROUP,
L10n::t('Requires manual approval of contact requests.'),
($a->user['page-flags'] == Contact::PAGE_PRVGROUP)],
($a->user['page-flags'] == User::PAGE_FLAGS_PRVGROUP)],
]);
@ -1262,7 +1259,7 @@ function settings_content(App $a)
]);
Addon::callHooks('settings_form', $o);
Hook::callAll('settings_form', $o);
$o .= '</form>' . "\r\n";

View file

@ -8,7 +8,7 @@ function share_init(App $a) {
$post_id = (($a->argc > 1) ? intval($a->argv[1]) : 0);
if (!$post_id || !local_user()) {
killme();
exit();
}
$fields = ['private', 'body', 'author-name', 'author-link', 'author-avatar',
@ -16,7 +16,7 @@ function share_init(App $a) {
$item = Item::selectFirst($fields, ['id' => $post_id]);
if (!DBA::isResult($item) || $item['private'] == 1) {
killme();
exit();
}
if (strpos($item['body'], "[/share]") !== false) {
@ -26,7 +26,7 @@ function share_init(App $a) {
$o = share_header($item['author-name'], $item['author-link'], $item['author-avatar'], $item['guid'], $item['created'], $item['plink']);
if ($item['title']) {
$o .= '[b]'.$item['title'].'[/b]'."\n";
$o .= '[h3]'.$item['title'].'[/h3]'."\n";
}
$o .= $item['body'];
@ -34,7 +34,7 @@ function share_init(App $a) {
}
echo $o;
killme();
exit();
}
/// @TODO Rewrite to handle over whole record array

View file

@ -7,8 +7,9 @@ use Friendica\Content\Smilies;
use Friendica\Core\System;
/**
* @param object $a App
* @param App $a App
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
function smilies_content(App $a)
{

View file

@ -3,7 +3,6 @@
* @file mod/starred.php
*/
use Friendica\App;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Item;
@ -12,18 +11,18 @@ function starred_init(App $a) {
$message_id = null;
if (!local_user()) {
killme();
exit();
}
if ($a->argc > 1) {
$message_id = intval($a->argv[1]);
}
if (!$message_id) {
killme();
exit();
}
$item = Item::selectFirstForUser(local_user(), ['starred'], ['uid' => local_user(), 'id' => $message_id]);
if (!DBA::isResult($item)) {
killme();
exit();
}
if (!intval($item['starred'])) {
@ -48,5 +47,5 @@ function starred_init(App $a) {
// the json doesn't really matter, it will either be 0 or 1
echo json_encode($starred);
killme();
exit();
}

View file

@ -14,14 +14,17 @@ function statistics_json_init(App $a) {
if (!Config::get("system", "nodeinfo")) {
System::httpExit(404);
killme();
}
$registration_open =
intval(Config::get('config', 'register_policy')) !== \Friendica\Module\Register::CLOSED
&& ! Config::get('config', 'invitation_only');
$statistics = [
"name" => Config::get('config', 'sitename'),
"network" => FRIENDICA_PLATFORM,
"version" => FRIENDICA_VERSION . "-" . DB_UPDATE_VERSION,
"registrations_open" => intval(Config::get('config', 'register_policy')) !== REGISTER_CLOSED,
"registrations_open" => $registration_open,
"total_users" => Config::get('nodeinfo', 'total_users'),
"active_users_halfyear" => Config::get('nodeinfo', 'active_users_halfyear'),
"active_users_monthly" => Config::get('nodeinfo', 'active_users_monthly'),
@ -56,5 +59,5 @@ function statistics_json_init(App $a) {
header("Content-Type: application/json");
echo json_encode($statistics, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
Logger::log("statistics_init: printed " . print_r($statistics, true), Logger::DATA);
killme();
exit();
}

View file

@ -3,7 +3,7 @@
* @file mod/subthread.php
*/
use Friendica\App;
use Friendica\Core\Addon;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\System;
@ -149,8 +149,8 @@ EOT;
$arr['id'] = $post_id;
Addon::callHooks('post_local_end', $arr);
Hook::callAll('post_local_end', $arr);
killme();
exit();
}

View file

@ -77,6 +77,7 @@ function suggest_content(App $a)
}
$id = 0;
$entries = [];
foreach ($r as $rr) {

View file

@ -3,7 +3,7 @@
* @file mod/tagger.php
*/
use Friendica\App;
use Friendica\Core\Addon;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\System;
@ -199,11 +199,9 @@ EOT;
$arr['id'] = $post_id;
Addon::callHooks('post_local_end', $arr);
Hook::callAll('post_local_end', $arr);
Worker::add(PRIORITY_HIGH, "Notifier", "tag", $post_id);
killme();
return; // NOTREACHED
exit();
}

View file

@ -36,8 +36,10 @@ function tagrm_post(App $a)
/**
* Updates tags from an item
*
* @param $item_id
* @param $tags array
* @throws Exception
*/
function update_tags($item_id, $tags){
if (empty($item_id) || empty($tags)){

View file

@ -3,7 +3,7 @@
* @file mod/uexport.php
*/
use Friendica\App;
use Friendica\Core\Addon;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\System;
@ -11,7 +11,7 @@ use Friendica\Database\DBA;
function uexport_init(App $a) {
if (!local_user()) {
killme();
exit();
}
require_once("mod/settings.php");
@ -26,14 +26,14 @@ function uexport_content(App $a) {
switch ($a->argv[1]) {
case "backup":
uexport_all($a);
killme();
exit();
break;
case "account":
uexport_account($a);
killme();
exit();
break;
default:
killme();
exit();
}
}
@ -45,7 +45,7 @@ function uexport_content(App $a) {
['uexport/account', L10n::t('Export account'), L10n::t('Export your account info and contacts. Use this to make a backup of your account and/or to move it to another server.')],
['uexport/backup', L10n::t('Export all'), L10n::t("Export your accout info, contacts and all your items as json. Could be a very big file, and could take a lot of time. Use this to make a full backup of your account \x28photos are not exported\x29")],
];
Addon::callHooks('uexport_options', $options);
Hook::callAll('uexport_options', $options);
$tpl = Renderer::getMarkupTemplate("uexport.tpl");
return Renderer::replaceMacros($tpl, [
@ -130,12 +130,14 @@ function uexport_account($a) {
'group_member' => $group_member,
];
//echo "<pre>"; var_dump(json_encode($output)); killme();
echo json_encode($output, JSON_PARTIAL_OUTPUT_ON_ERROR);
}
/**
* echoes account data and items as separated json, one per line
*
* @param App $a
* @throws Exception
*/
function uexport_all(App $a) {
@ -152,7 +154,6 @@ function uexport_all(App $a) {
// chunk the output to avoid exhausting memory
for ($x = 0; $x < $total; $x += 500) {
$item = [];
$r = q("SELECT * FROM `item` WHERE `uid` = %d LIMIT %d, %d",
intval(local_user()),
intval($x),

View file

@ -13,7 +13,7 @@ use Friendica\Core\Renderer;
function uimport_post(App $a)
{
if ((Config::get('config', 'register_policy') != REGISTER_OPEN) && !is_site_admin()) {
if ((Config::get('config', 'register_policy') != \Friendica\Module\Register::OPEN) && !is_site_admin()) {
notice(L10n::t('Permission denied.') . EOL);
return;
}
@ -26,7 +26,7 @@ function uimport_post(App $a)
function uimport_content(App $a)
{
if ((Config::get('config', 'register_policy') != REGISTER_OPEN) && !is_site_admin()) {
if ((Config::get('config', 'register_policy') != \Friendica\Module\Register::OPEN) && !is_site_admin()) {
notice(L10n::t('User imports on closed servers can only be done by an administrator.') . EOL);
return;
}

View file

@ -34,5 +34,5 @@ function update_community_content(App $a) {
echo str_replace("\t", " ", $text);
echo "</section>";
echo "</body></html>\r\n";
killme();
exit();
}

View file

@ -14,7 +14,7 @@ function update_contact_content(App $a)
echo "<section>";
if ($_GET["force"] == 1) {
$text = Contact::content($a, true);
$text = Contact::content(true);
} else {
$text = '';
}
@ -34,5 +34,5 @@ function update_contact_content(App $a)
echo str_replace("\t", " ", $text);
echo "</section>";
echo "</body></html>\r\n";
killme();
exit();
}

View file

@ -35,5 +35,5 @@ function update_display_content(App $a)
echo str_replace("\t", " ", $text);
echo "</section>";
echo "</body></html>\r\n";
killme();
exit();
}

View file

@ -13,7 +13,7 @@ require_once "mod/network.php";
function update_network_content(App $a)
{
if (!isset($_GET['p']) || !isset($_GET['item'])) {
killme();
exit();
}
$profile_uid = intval($_GET['p']);
@ -44,5 +44,5 @@ function update_network_content(App $a)
echo str_replace("\t", " ", $text);
echo "</section>";
echo "</body></html>\r\n";
killme();
exit();
}

View file

@ -48,5 +48,5 @@ function update_notes_content(App $a) {
echo str_replace("\t", " ", $text);
echo "</section>";
echo "</body></html>\r\n";
killme();
exit();
}

View file

@ -8,8 +8,7 @@
use Friendica\App;
use Friendica\Core\L10n;
use Friendica\Core\PConfig;
require_once 'mod/profile.php';
use Friendica\Module\Profile;
function update_profile_content(App $a) {
@ -29,7 +28,7 @@ function update_profile_content(App $a) {
* on the client side and then swap the image back.
*/
$text = profile_content($a, $profile_uid);
$text = Profile::content($profile_uid);
if (PConfig::get(local_user(), "system", "bandwidth_saver")) {
$replace = "<br />".L10n::t("[Embedded content - reload page to view]")."<br />";
@ -47,5 +46,5 @@ function update_profile_content(App $a) {
echo str_replace("\t", " ", $text);
echo "</section>";
echo "</body></html>\r\n";
killme();
exit();
}

View file

@ -11,10 +11,12 @@ use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Attach;
use Friendica\Model\Contact;
use Friendica\Model\Group;
use Friendica\Model\Item;
use Friendica\Model\Profile;
use Friendica\Model\User;
use Friendica\Protocol\DFRN;
use Friendica\Util\Security;
@ -30,8 +32,6 @@ function videos_init(App $a)
Nav::setSelected('home');
$o = '';
if ($a->argc > 1) {
$nick = $a->argv[1];
$user = q("SELECT * FROM `user` WHERE `nickname` = '%s' AND `blocked` = 0 LIMIT 1",
@ -59,41 +59,6 @@ function videos_init(App $a)
'$pdesc' => defaults($profile, 'pdesc', ''),
]);
/// @TODO Old-lost code?
/*$sql_extra = Security::getPermissionsSQLByUserId($a->data['user']['uid']);
$albums = q("SELECT distinct(`album`) AS `album` FROM `photo` WHERE `uid` = %d $sql_extra order by created desc",
intval($a->data['user']['uid'])
);
if(count($albums)) {
$a->data['albums'] = $albums;
$albums_visible = ((intval($a->data['user']['hidewall']) && (!local_user()) && (!remote_user())) ? false : true);
if($albums_visible) {
$o .= '<div id="sidebar-photos-albums" class="widget">';
$o .= '<h3>' . '<a href="' . System::baseUrl() . '/photos/' . $a->data['user']['nickname'] . '">' . L10n::t('Photo Albums') . '</a></h3>';
$o .= '<ul>';
foreach($albums as $album) {
// don't show contact photos. We once translated this name, but then you could still access it under
// a different language setting. Now we store the name in English and check in English (and translated for legacy albums).
if((!strlen($album['album'])) || ($album['album'] === 'Contact Photos') || ($album['album'] === L10n::t('Contact Photos')))
continue;
$o .= '<li>' . '<a href="photos/' . $a->argv[1] . '/album/' . bin2hex($album['album']) . '" >' . $album['album'] . '</a></li>';
}
$o .= '</ul>';
}
if(local_user() && $a->data['user']['uid'] == local_user()) {
$o .= '<div id="photo-albums-upload-link"><a href="' . System::baseUrl() . '/photos/' . $a->data['user']['nickname'] . '/upload" >' .L10n::t('Upload New Photos') . '</a></div>';
}
$o .= '</div>';
}*/
// If not there, create 'aside' empty
if (!isset($a->page['aside'])) {
$a->page['aside'] = '';
@ -148,25 +113,15 @@ function videos_post(App $a)
$video_id = $_POST['id'];
$r = q("SELECT `id` FROM `attach` WHERE `uid` = %d AND `id` = '%s' LIMIT 1",
intval(local_user()),
DBA::escape($video_id)
);
if (Attach::exists(['id' => $video_id, 'uid' => local_user()])) {
// delete the attachment
Attach::delete(['id' => $video_id, 'uid' => local_user()]);
if (DBA::isResult($r)) {
q("DELETE FROM `attach` WHERE `uid` = %d AND `id` = '%s'",
intval(local_user()),
DBA::escape($video_id)
);
$i = q("SELECT `id` FROM `item` WHERE `attach` like '%%attach/%s%%' AND `uid` = %d LIMIT 1",
DBA::escape($video_id),
intval(local_user())
);
if (DBA::isResult($i)) {
Item::deleteForUser(['id' => $i[0]['id']], local_user());
}
// delete items where the attach is used
Item::deleteForUser(['`attach` LIKE ? AND `uid` = ?',
'%attach/' . $video_id . '%',
local_user()
], local_user());
}
$a->internalRedirect('videos/' . $a->data['user']['nickname']);
@ -207,19 +162,12 @@ function videos_content(App $a)
//
if ($a->argc > 3) {
$datatype = $a->argv[2];
$datum = $a->argv[3];
} elseif(($a->argc > 2) && ($a->argv[2] === 'upload')) {
$datatype = 'upload';
} else {
$datatype = 'summary';
}
if ($a->argc > 4) {
$cmd = $a->argv[4];
} else {
$cmd = 'view';
}
//
// Setup permissions structures
//
@ -231,7 +179,7 @@ function videos_content(App $a)
$owner_uid = $a->data['user']['uid'];
$community_page = (($a->data['user']['page-flags'] == Contact::PAGE_COMMUNITY) ? true : false);
$community_page = (($a->data['user']['page-flags'] == User::PAGE_FLAGS_COMMUNITY) ? true : false);
if ((local_user()) && (local_user() == $owner_uid)) {
$can_post = true;
@ -253,7 +201,6 @@ function videos_content(App $a)
if (DBA::isResult($r)) {
$can_post = true;
$contact = $r[0];
$remote_contact = true;
$visitor = $contact_id;
}
@ -283,17 +230,11 @@ function videos_content(App $a)
);
if (DBA::isResult($r)) {
$contact = $r[0];
$remote_contact = true;
}
}
}
if (!$remote_contact && local_user()) {
$contact_id = $_SESSION['cid'];
$contact = $a->contact;
}
if ($a->data['user']['hidewall'] && (local_user() != $owner_uid) && (!$remote_contact)) {
notice(L10n::t('Access to this item is restricted.') . EOL);
return;

View file

@ -1,17 +1,23 @@
<?php
use Friendica\App;
/**
* load view/theme/$current_theme/style.php with friendica contex
* load view/theme/$current_theme/style.php with friendica context
*
* @param App $a
*/
function view_init($a){
function view_init(App $a)
{
header("Content-Type: text/css");
if ($a->argc == 4){
$theme = $a->argv[2];
// set the path for later use in the theme styles
$THEMEPATH = "view/theme/$theme";
if(file_exists("view/theme/$theme/style.php"))
require_once("view/theme/$theme/style.php");
}
killme();
exit();
}

View file

@ -66,7 +66,7 @@ function viewcontacts_content(App $a)
'network' => [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA, Protocol::OSTATUS]
];
$total = DBA::count('count', $condition);
$total = DBA::count('contact', $condition);
$pager = new Pager($a->query_string);

View file

@ -28,7 +28,7 @@ function viewsrc_content(App $a)
if (DBA::isResult($item)) {
if ($a->isAjax()) {
echo str_replace("\n", '<br />', $item['body']);
killme();
exit();
} else {
$o .= str_replace("\n", '<br />', $item['body']);
}

View file

@ -6,11 +6,9 @@
use Friendica\App;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Mimetype;
use Friendica\Model\Attach;
use Friendica\Model\User;
use Friendica\Util\Strings;
function wall_attach_post(App $a) {
@ -26,26 +24,24 @@ function wall_attach_post(App $a) {
if (! DBA::isResult($r)) {
if ($r_json) {
echo json_encode(['error' => L10n::t('Invalid request.')]);
killme();
exit();
}
return;
}
} else {
if ($r_json) {
echo json_encode(['error' => L10n::t('Invalid request.')]);
killme();
exit();
}
return;
}
$can_post = false;
$visitor = 0;
$page_owner_uid = $r[0]['uid'];
$page_owner_cid = $r[0]['id'];
$page_owner_nick = $r[0]['nickname'];
$community_page = (($r[0]['page-flags'] == Contact::PAGE_COMMUNITY) ? true : false);
$community_page = (($r[0]['page-flags'] == User::PAGE_FLAGS_COMMUNITY) ? true : false);
if ((local_user()) && (local_user() == $page_owner_uid)) {
$can_post = true;
@ -70,7 +66,6 @@ function wall_attach_post(App $a) {
if (DBA::isResult($r)) {
$can_post = true;
$visitor = $contact_id;
}
}
}
@ -79,17 +74,17 @@ function wall_attach_post(App $a) {
if (! $can_post) {
if ($r_json) {
echo json_encode(['error' => L10n::t('Permission denied.')]);
killme();
exit();
}
notice(L10n::t('Permission denied.') . EOL );
killme();
exit();
}
if (empty($_FILES['userfile'])) {
if ($r_json) {
echo json_encode(['error' => L10n::t('Invalid request.')]);
}
killme();
exit();
}
$src = $_FILES['userfile']['tmp_name'];
@ -112,7 +107,7 @@ function wall_attach_post(App $a) {
notice($msg . EOL);
}
@unlink($src);
killme();
exit();
}
if ($maxfilesize && $filesize > $maxfilesize) {
@ -123,57 +118,32 @@ function wall_attach_post(App $a) {
echo $msg . EOL;
}
@unlink($src);
killme();
exit();
}
$filedata = @file_get_contents($src);
$mimetype = Mimetype::getContentType($filename);
$hash = System::createGUID(64);
$created = DateTimeFormat::utcNow();
$fields = ['uid' => $page_owner_uid, 'hash' => $hash, 'filename' => $filename, 'filetype' => $mimetype,
'filesize' => $filesize, 'data' => $filedata, 'created' => $created, 'edited' => $created,
'allow_cid' => '<' . $page_owner_cid . '>', 'allow_gid' => '','deny_cid' => '', 'deny_gid' => ''];
$r = DBA::insert('attach', $fields);
$newid = Attach::storeFile($src, $page_owner_uid, $filename, '<' . $page_owner_cid . '>');
@unlink($src);
if (! $r) {
if ($newid === false) {
$msg = L10n::t('File upload failed.');
if ($r_json) {
echo json_encode(['error' => $msg]);
} else {
echo $msg . EOL;
}
killme();
}
$r = q("SELECT `id` FROM `attach` WHERE `uid` = %d AND `created` = '%s' AND `hash` = '%s' LIMIT 1",
intval($page_owner_uid),
DBA::escape($created),
DBA::escape($hash)
);
if (! DBA::isResult($r)) {
$msg = L10n::t('File upload failed.');
if ($r_json) {
echo json_encode(['error' => $msg]);
} else {
echo $msg . EOL;
}
killme();
exit();
}
if ($r_json) {
echo json_encode(['ok' => true]);
killme();
echo json_encode(['ok' => true, 'id' => $newid]);
exit();
}
$lf = "\n";
echo $lf . $lf . '[attachment]' . $r[0]['id'] . '[/attachment]' . $lf;
echo $lf . $lf . '[attachment]' . $newid . '[/attachment]' . $lf;
killme();
exit();
// NOTREACHED
}

View file

@ -16,6 +16,7 @@ use Friendica\Core\Config;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Photo;
use Friendica\Model\User;
use Friendica\Object\Image;
use Friendica\Util\Strings;
@ -39,7 +40,7 @@ function wall_upload_post(App $a, $desktopmode = true)
if (!DBA::isResult($r)) {
if ($r_json) {
echo json_encode(['error' => L10n::t('Invalid request.')]);
killme();
exit();
}
return;
}
@ -55,7 +56,7 @@ function wall_upload_post(App $a, $desktopmode = true)
} else {
if ($r_json) {
echo json_encode(['error' => L10n::t('Invalid request.')]);
killme();
exit();
}
return;
}
@ -69,7 +70,7 @@ function wall_upload_post(App $a, $desktopmode = true)
$page_owner_uid = $r[0]['uid'];
$default_cid = $r[0]['id'];
$page_owner_nick = $r[0]['nickname'];
$community_page = (($r[0]['page-flags'] == Contact::PAGE_COMMUNITY) ? true : false);
$community_page = (($r[0]['page-flags'] == User::PAGE_FLAGS_COMMUNITY) ? true : false);
if ((local_user()) && (local_user() == $page_owner_uid)) {
$can_post = true;
@ -104,17 +105,17 @@ function wall_upload_post(App $a, $desktopmode = true)
if (!$can_post) {
if ($r_json) {
echo json_encode(['error' => L10n::t('Permission denied.')]);
killme();
exit();
}
notice(L10n::t('Permission denied.') . EOL);
killme();
exit();
}
if (empty($_FILES['userfile']) && empty($_FILES['media'])) {
if ($r_json) {
echo json_encode(['error' => L10n::t('Invalid request.')]);
}
killme();
exit();
}
$src = '';
@ -164,10 +165,10 @@ function wall_upload_post(App $a, $desktopmode = true)
if ($src == "") {
if ($r_json) {
echo json_encode(['error' => L10n::t('Invalid request.')]);
killme();
exit();
}
notice(L10n::t('Invalid request.').EOL);
killme();
exit();
}
// This is a special treatment for picture upload from Twidere
@ -201,7 +202,7 @@ function wall_upload_post(App $a, $desktopmode = true)
echo $msg. EOL;
}
@unlink($src);
killme();
exit();
}
$imagedata = @file_get_contents($src);
@ -215,7 +216,7 @@ function wall_upload_post(App $a, $desktopmode = true)
echo $msg. EOL;
}
@unlink($src);
killme();
exit();
}
$Image->orient($src);
@ -253,7 +254,7 @@ function wall_upload_post(App $a, $desktopmode = true)
} else {
echo $msg. EOL;
}
killme();
exit();
}
if ($width > 640 || $height > 640) {
@ -272,8 +273,6 @@ function wall_upload_post(App $a, $desktopmode = true)
}
}
$basename = basename($filename);
if (!$desktopmode) {
$r = q("SELECT `id`, `datasize`, `width`, `height`, `type` FROM `photo`
WHERE `resource-id` = '%s'
@ -283,7 +282,7 @@ function wall_upload_post(App $a, $desktopmode = true)
if (!$r) {
if ($r_json) {
echo json_encode(['error' => '']);
killme();
exit();
}
return false;
}
@ -300,7 +299,7 @@ function wall_upload_post(App $a, $desktopmode = true)
if ($r_json) {
echo json_encode(['picture' => $picture]);
killme();
exit();
}
Logger::log("upload done", Logger::DEBUG);
return $picture;
@ -310,10 +309,10 @@ function wall_upload_post(App $a, $desktopmode = true)
if ($r_json) {
echo json_encode(['ok' => true]);
killme();
exit();
}
echo "\n\n" . '[url=' . System::baseUrl() . '/photos/' . $page_owner_nick . '/image/' . $hash . '][img]' . System::baseUrl() . "/photo/{$hash}-{$smallest}.".$Image->getExt()."[/img][/url]\n\n";
killme();
exit();
// NOTREACHED
}

View file

@ -17,7 +17,7 @@ function webfinger_content(App $a)
"description" => L10n::t("Only logged in users are permitted to perform a probing.")
]
);
killme();
exit();
}
$o = '<div class="generic-page-wrapper">';

View file

@ -17,6 +17,9 @@ function worker_init()
return;
}
// Ensure that all "strtotime" operations do run timezone independent
date_default_timezone_set('UTC');
// We don't need the following lines if we can execute background jobs.
// So we just wake up the worker if it sleeps.
if (function_exists("proc_open")) {
@ -58,5 +61,5 @@ function worker_init()
Logger::log("Front end worker ended: ".getmypid());
killme();
exit();
}

View file

@ -4,7 +4,7 @@
*/
use Friendica\App;
use Friendica\Core\Addon;
use Friendica\Core\Hook;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
@ -63,13 +63,13 @@ function xrd_init(App $a)
}
if ($mode == 'xml') {
xrd_xml($a, $addr, $alias, $profile_url, $user);
xrd_xml($addr, $alias, $profile_url, $user);
} else {
xrd_json($a, $addr, $alias, $profile_url, $user);
xrd_json($addr, $alias, $profile_url, $user);
}
}
function xrd_json($a, $uri, $alias, $profile_url, $r)
function xrd_json($uri, $alias, $profile_url, $r)
{
$salmon_key = Salmon::salmonKey($r['spubkey']);
@ -97,10 +97,10 @@ function xrd_json($a, $uri, $alias, $profile_url, $r)
];
echo json_encode($json);
killme();
exit();
}
function xrd_xml($a, $uri, $alias, $profile_url, $r)
function xrd_xml($uri, $alias, $profile_url, $r)
{
$salmon_key = Salmon::salmonKey($r['spubkey']);
@ -127,8 +127,8 @@ function xrd_xml($a, $uri, $alias, $profile_url, $r)
);
$arr = ['user' => $r, 'xml' => $o];
Addon::callHooks('personal_xrd', $arr);
Hook::callAll('personal_xrd', $arr);
echo $arr['xml'];
killme();
exit();
}

View file

@ -12,7 +12,7 @@
</div>
<div id="c2" class="homeinfobox">
<h4>What other networks does it interact with?</h4>
<p>Every network that speaks either the DFRN2, OStatus or diaspora* protocol. Currently this list includes: diaspora*, friendica, ganggo, GNU social, Hubzilla, Mastodon, Pleroma, postActivi and Socialhome.</p>
<p>Every network that speaks either the DFRN2, ActivityPub, OStatus or diaspora* protocol. Currently this list includes: diaspora*, friendica, funkwhale, ganggo, GNU social, Hubzilla, Mastodon, NextClout social, pixelfed, Pleroma, postActivi, Osada, Socialhome and many more.</p>
<p><a href="http://fediverse.party/">Learn more at fediverse.party</a></p>
</div>
<div id="c3" class="homeinfobox">

View file

@ -31,7 +31,7 @@ return [
'config' => [
'admin_email' => 'admin@friendica.local',
'sitename' => 'Friendica Social Network',
'register_policy' => REGISTER_OPEN,
'register_policy' => \Friendica\Module\Register::OPEN,
'register_text' => '',
],
'system' => [

View file

@ -8,8 +8,15 @@ use Detection\MobileDetect;
use DOMDocument;
use DOMXPath;
use Exception;
use Friendica\Core\Config\Cache\ConfigCacheLoader;
use Friendica\Core\Config\Cache\IConfigCache;
use Friendica\Core\Config\Configuration;
use Friendica\Database\DBA;
use Friendica\Model\Profile;
use Friendica\Network\HTTPException\InternalServerErrorException;
use Friendica\Util\HTTPSignature;
use Friendica\Util\Profiler;
use Psr\Log\LoggerInterface;
/**
*
@ -29,7 +36,6 @@ class App
public $module_loaded = false;
public $module_class = null;
public $query_string = '';
public $config = [];
public $page = [];
public $profile;
public $profile_uid;
@ -50,8 +56,6 @@ class App
public $identities;
public $is_mobile = false;
public $is_tablet = false;
public $performance = [];
public $callstack = [];
public $theme_info = [];
public $category;
// Allow themes to control internal parameters
@ -106,6 +110,61 @@ class App
*/
public $mobileDetect;
/**
* @var Configuration The config
*/
private $config;
/**
* @var LoggerInterface The logger
*/
private $logger;
/**
* @var Profiler The profiler of this app
*/
private $profiler;
/**
* Returns the current config cache of this node
*
* @return IConfigCache
*/
public function getConfigCache()
{
return $this->config->getCache();
}
/**
* The basepath of this app
*
* @return string
*/
public function getBasePath()
{
return $this->basePath;
}
/**
* The Logger of this app
*
* @return LoggerInterface
*/
public function getLogger()
{
return $this->logger;
}
/**
* The profiler of this app
*
* @return Profiler
*/
public function getProfiler()
{
return $this->profiler;
}
/**
* Register a stylesheet file path to be included in the <head> tag of every page.
* Inclusion is done in App->initHead().
@ -114,10 +173,11 @@ class App
* @see initHead()
*
* @param string $path
* @throws InternalServerErrorException
*/
public function registerStylesheet($path)
{
$url = str_replace($this->getBasePath() . DIRECTORY_SEPARATOR, '', $path);
$url = str_replace($this->basePath . DIRECTORY_SEPARATOR, '', $path);
$this->stylesheets[] = trim($url, '/');
}
@ -130,15 +190,15 @@ class App
* @see initFooter()
*
* @param string $path
* @throws InternalServerErrorException
*/
public function registerFooterScript($path)
{
$url = str_replace($this->getBasePath() . DIRECTORY_SEPARATOR, '', $path);
$url = str_replace($this->basePath . DIRECTORY_SEPARATOR, '', $path);
$this->footerScripts[] = trim($url, '/');
}
public $process_id;
public $queue;
private $scheme;
private $hostname;
@ -146,45 +206,35 @@ class App
/**
* @brief App constructor.
*
* @param string $basePath Path to the app base folder
* @param bool $isBackend Whether it is used for backend or frontend (Default true=backend)
* @param string $basePath The basedir of the app
* @param Configuration $config The Configuration
* @param LoggerInterface $logger The current app logger
* @param Profiler $profiler The profiler of this application
* @param bool $isBackend Whether it is used for backend or frontend (Default true=backend)
*
* @throws Exception if the Basepath is not usable
*/
public function __construct($basePath, $isBackend = true)
public function __construct($basePath, Configuration $config, LoggerInterface $logger, Profiler $profiler, $isBackend = true)
{
if (!static::isDirectoryUsable($basePath, false)) {
throw new Exception('Basepath ' . $basePath . ' isn\'t usable.');
}
BaseObject::setApp($this);
$this->basePath = rtrim($basePath, DIRECTORY_SEPARATOR);
$this->logger = $logger;
$this->config = $config;
$this->profiler = $profiler;
$cfgBasePath = $this->config->get('system', 'basepath');
$this->basePath = !empty($cfgBasePath) ? $cfgBasePath : $basePath;
if (!Core\System::isDirectoryUsable($this->basePath, false)) {
throw new Exception('Basepath \'' . $this->basePath . '\' isn\'t usable.');
}
$this->basePath = rtrim($this->basePath, DIRECTORY_SEPARATOR);
$this->checkBackend($isBackend);
$this->checkFriendicaApp();
$this->performance['start'] = microtime(true);
$this->performance['database'] = 0;
$this->performance['database_write'] = 0;
$this->performance['cache'] = 0;
$this->performance['cache_write'] = 0;
$this->performance['network'] = 0;
$this->performance['file'] = 0;
$this->performance['rendering'] = 0;
$this->performance['parser'] = 0;
$this->performance['marktime'] = 0;
$this->performance['markstart'] = microtime(true);
$this->profiler->reset();
$this->callstack['database'] = [];
$this->callstack['database_write'] = [];
$this->callstack['cache'] = [];
$this->callstack['cache_write'] = [];
$this->callstack['network'] = [];
$this->callstack['file'] = [];
$this->callstack['rendering'] = [];
$this->callstack['parser'] = [];
$this->mode = new App\Mode($basePath);
$this->mode = new App\Mode($this->basePath);
$this->reload();
@ -215,9 +265,9 @@ class App
set_include_path(
get_include_path() . PATH_SEPARATOR
. $this->getBasePath() . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR
. $this->getBasePath() . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR
. $this->getBasePath());
. $this->basePath . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR
. $this->basePath . DIRECTORY_SEPARATOR . 'library' . PATH_SEPARATOR
. $this->basePath);
if (!empty($_SERVER['QUERY_STRING']) && strpos($_SERVER['QUERY_STRING'], 'pagename=') === 0) {
$this->query_string = substr($_SERVER['QUERY_STRING'], 9);
@ -306,180 +356,25 @@ class App
*/
public function reload()
{
// The order of the following calls is important to ensure proper initialization
$this->loadConfigFiles();
$this->loadDatabase();
$this->getMode()->determine($this->getBasePath());
$this->determineURLPath();
Core\Config::load();
$this->getMode()->determine($this->basePath);
if ($this->getMode()->has(App\Mode::DBAVAILABLE)) {
Core\Hook::loadHooks();
$loader = new ConfigCacheLoader($this->basePath);
$this->config->getCache()->load($loader->loadCoreConfig('addon'), true);
$this->loadAddonConfig();
$this->profiler->update(
$this->config->get('system', 'profiler', false),
$this->config->get('rendertime', 'callstack', false));
Core\Hook::loadHooks();
Core\Hook::callAll('load_config', $loader);
}
$this->loadDefaultTimezone();
Core\L10n::init();
$this->process_id = Core\System::processID('log');
}
/**
* Load the configuration files
*
* First loads the default value for all the configuration keys, then the legacy configuration files, then the
* expected local.config.php
*/
private function loadConfigFiles()
{
$this->loadConfigFile($this->getBasePath() . '/config/defaults.config.php');
$this->loadConfigFile($this->getBasePath() . '/config/settings.config.php');
// Legacy .htconfig.php support
if (file_exists($this->getBasePath() . '/.htpreconfig.php')) {
$a = $this;
include $this->getBasePath() . '/.htpreconfig.php';
}
// Legacy .htconfig.php support
if (file_exists($this->getBasePath() . '/.htconfig.php')) {
$a = $this;
include $this->getBasePath() . '/.htconfig.php';
$this->setConfigValue('database', 'hostname', $db_host);
$this->setConfigValue('database', 'username', $db_user);
$this->setConfigValue('database', 'password', $db_pass);
$this->setConfigValue('database', 'database', $db_data);
if (isset($a->config['system']['db_charset'])) {
$this->setConfigValue('database', 'charset', $a->config['system']['db_charset']);
}
unset($db_host, $db_user, $db_pass, $db_data);
if (isset($default_timezone)) {
$this->setConfigValue('system', 'default_timezone', $default_timezone);
unset($default_timezone);
}
if (isset($pidfile)) {
$this->setConfigValue('system', 'pidfile', $pidfile);
unset($pidfile);
}
if (isset($lang)) {
$this->setConfigValue('system', 'language', $lang);
unset($lang);
}
}
if (file_exists($this->getBasePath() . '/config/local.config.php')) {
$this->loadConfigFile($this->getBasePath() . '/config/local.config.php', true);
} elseif (file_exists($this->getBasePath() . '/config/local.ini.php')) {
$this->loadINIConfigFile($this->getBasePath() . '/config/local.ini.php', true);
}
}
/**
* Tries to load the specified legacy configuration file into the App->config array.
* Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config.
*
* @deprecated since version 2018.12
* @param string $filepath
* @param bool $overwrite Force value overwrite if the config key already exists
* @throws Exception
*/
public function loadINIConfigFile($filepath, $overwrite = false)
{
if (!file_exists($filepath)) {
throw new Exception('Error parsing non-existent INI config file ' . $filepath);
}
$contents = include($filepath);
$config = parse_ini_string($contents, true, INI_SCANNER_TYPED);
if ($config === false) {
throw new Exception('Error parsing INI config file ' . $filepath);
}
$this->loadConfigArray($config, $overwrite);
}
/**
* Tries to load the specified configuration file into the App->config array.
* Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config.
*
* The config format is PHP array and the template for configuration files is the following:
*
* <?php return [
* 'section' => [
* 'key' => 'value',
* ],
* ];
*
* @param string $filepath
* @param bool $overwrite Force value overwrite if the config key already exists
* @throws Exception
*/
public function loadConfigFile($filepath, $overwrite = false)
{
if (!file_exists($filepath)) {
throw new Exception('Error loading non-existent config file ' . $filepath);
}
$config = include($filepath);
if (!is_array($config)) {
throw new Exception('Error loading config file ' . $filepath);
}
$this->loadConfigArray($config, $overwrite);
}
/**
* Loads addons configuration files
*
* First loads all activated addons default configuration through the load_config hook, then load the local.config.php
* again to overwrite potential local addon configuration.
*/
private function loadAddonConfig()
{
// Loads addons default config
Core\Hook::callAll('load_config');
// Load the local addon config file to overwritten default addon config values
if (file_exists($this->getBasePath() . '/config/addon.config.php')) {
$this->loadConfigFile($this->getBasePath() . '/config/addon.config.php', true);
} elseif (file_exists($this->getBasePath() . '/config/addon.ini.php')) {
$this->loadINIConfigFile($this->getBasePath() . '/config/addon.ini.php', true);
}
}
/**
* Tries to load the specified configuration array into the App->config array.
* Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config.
*
* @param array $config
* @param bool $overwrite Force value overwrite if the config key already exists
*/
private function loadConfigArray(array $config, $overwrite = false)
{
foreach ($config as $category => $values) {
foreach ($values as $key => $value) {
if ($overwrite) {
$this->setConfigValue($category, $key, $value);
} else {
$this->setDefaultConfigValue($category, $key, $value);
}
}
}
}
/**
@ -491,8 +386,8 @@ class App
*/
private function loadDefaultTimezone()
{
if ($this->getConfigValue('system', 'default_timezone')) {
$this->timezone = $this->getConfigValue('system', 'default_timezone');
if ($this->config->get('system', 'default_timezone')) {
$this->timezone = $this->config->get('system', 'default_timezone');
} else {
global $default_timezone;
$this->timezone = !empty($default_timezone) ? $default_timezone : 'UTC';
@ -508,23 +403,33 @@ class App
*/
private function determineURLPath()
{
/*
* The automatic path detection in this function is currently deactivated,
* see issue https://github.com/friendica/friendica/issues/6679
*
* The problem is that the function seems to be confused with some url.
* These then confuses the detection which changes the url path.
*/
/* Relative script path to the web server root
* Not all of those $_SERVER properties can be present, so we do by inverse priority order
*/
/*
$relative_script_path = '';
$relative_script_path = defaults($_SERVER, 'REDIRECT_URL' , $relative_script_path);
$relative_script_path = defaults($_SERVER, 'REDIRECT_URI' , $relative_script_path);
$relative_script_path = defaults($_SERVER, 'REDIRECT_SCRIPT_URL', $relative_script_path);
$relative_script_path = defaults($_SERVER, 'SCRIPT_URL' , $relative_script_path);
$relative_script_path = defaults($_SERVER, 'REQUEST_URI' , $relative_script_path);
$this->urlPath = $this->getConfigValue('system', 'urlpath');
*/
$this->urlPath = $this->config->get('system', 'urlpath');
/* $relative_script_path gives /relative/path/to/friendica/module/parameter
* QUERY_STRING gives pagename=module/parameter
*
* To get /relative/path/to/friendica we perform dirname() for as many levels as there are slashes in the QUERY_STRING
*/
/*
if (!empty($relative_script_path)) {
// Module
if (!empty($_SERVER['QUERY_STRING'])) {
@ -538,97 +443,7 @@ class App
$this->urlPath = $path;
}
}
}
public function loadDatabase()
{
if (DBA::connected()) {
return;
}
$db_host = $this->getConfigValue('database', 'hostname');
$db_user = $this->getConfigValue('database', 'username');
$db_pass = $this->getConfigValue('database', 'password');
$db_data = $this->getConfigValue('database', 'database');
$charset = $this->getConfigValue('database', 'charset');
// Use environment variables for mysql if they are set beforehand
if (!empty(getenv('MYSQL_HOST'))
&& !empty(getenv('MYSQL_USERNAME') || !empty(getenv('MYSQL_USER')))
&& getenv('MYSQL_PASSWORD') !== false
&& !empty(getenv('MYSQL_DATABASE')))
{
$db_host = getenv('MYSQL_HOST');
if (!empty(getenv('MYSQL_PORT'))) {
$db_host .= ':' . getenv('MYSQL_PORT');
}
if (!empty(getenv('MYSQL_USERNAME'))) {
$db_user = getenv('MYSQL_USERNAME');
} else {
$db_user = getenv('MYSQL_USER');
}
$db_pass = (string) getenv('MYSQL_PASSWORD');
$db_data = getenv('MYSQL_DATABASE');
}
$stamp1 = microtime(true);
if (DBA::connect($db_host, $db_user, $db_pass, $db_data, $charset)) {
// Loads DB_UPDATE_VERSION constant
Database\DBStructure::definition(false);
}
unset($db_host, $db_user, $db_pass, $db_data, $charset);
$this->saveTimestamp($stamp1, 'network');
}
/**
* @brief Returns the base filesystem path of the App
*
* It first checks for the internal variable, then for DOCUMENT_ROOT and
* finally for PWD
*
* @return string
*/
public function getBasePath()
{
$basepath = $this->basePath;
if (!$basepath) {
$basepath = Core\Config::get('system', 'basepath');
}
if (!$basepath && !empty($_SERVER['DOCUMENT_ROOT'])) {
$basepath = $_SERVER['DOCUMENT_ROOT'];
}
if (!$basepath && !empty($_SERVER['PWD'])) {
$basepath = $_SERVER['PWD'];
}
return self::getRealPath($basepath);
}
/**
* @brief Returns a normalized file path
*
* This is a wrapper for the "realpath" function.
* That function cannot detect the real path when some folders aren't readable.
* Since this could happen with some hosters we need to handle this.
*
* @param string $path The path that is about to be normalized
* @return string normalized path - when possible
*/
public static function getRealPath($path)
{
$normalized = realpath($path);
if (!is_bool($normalized)) {
return $normalized;
} else {
return $path;
}
*/
}
public function getScheme()
@ -649,6 +464,7 @@ class App
*
* @param bool $ssl Whether to append http or https under SSL_POLICY_SELFSIGN
* @return string Friendica server base URL
* @throws InternalServerErrorException
*/
public function getBaseURL($ssl = false)
{
@ -673,7 +489,7 @@ class App
$this->hostname = Core\Config::get('config', 'hostname');
}
return $scheme . '://' . $this->hostname . !empty($this->getURLPath() ? '/' . $this->getURLPath() : '' );
return $scheme . '://' . $this->hostname . (!empty($this->getURLPath()) ? '/' . $this->getURLPath() : '' );
}
/**
@ -682,6 +498,7 @@ class App
* Clears the baseurl cache to prevent inconsistencies
*
* @param string $url
* @throws InternalServerErrorException
*/
public function setBaseURL($url)
{
@ -704,8 +521,8 @@ class App
$this->urlPath = trim($parsed['path'], '\\/');
}
if (file_exists($this->getBasePath() . '/.htpreconfig.php')) {
include $this->getBasePath() . '/.htpreconfig.php';
if (file_exists($this->basePath . '/.htpreconfig.php')) {
include $this->basePath . '/.htpreconfig.php';
}
if (Core\Config::get('config', 'hostname') != '') {
@ -755,14 +572,14 @@ class App
$interval = 40000;
}
// compose the page title from the sitename and the
// current module called
if (!$this->module == '') {
$this->page['title'] = $this->config['sitename'] . ' (' . $this->module . ')';
} else {
$this->page['title'] = $this->config['sitename'];
// Default title: current module called
if (empty($this->page['title']) && $this->module) {
$this->page['title'] = ucfirst($this->module);
}
// Prepend the sitename to the page title
$this->page['title'] = $this->config->get('config', 'sitename', '') . (!empty($this->page['title']) ? ' | ' . $this->page['title'] : '');
if (!empty(Core\Renderer::$theme['stylesheet'])) {
$stylesheet = Core\Renderer::$theme['stylesheet'];
} else {
@ -781,7 +598,7 @@ class App
$touch_icon = 'images/friendica-128.png';
}
Core\Addon::callHooks('head', $this->page['htmlhead']);
Core\Hook::callAll('head', $this->page['htmlhead']);
$tpl = Core\Renderer::getMarkupTemplate('head.tpl');
/* put the head template at the beginning of page['htmlhead']
@ -793,8 +610,6 @@ class App
'$local_user' => local_user(),
'$generator' => 'Friendica' . ' ' . FRIENDICA_VERSION,
'$delitem' => Core\L10n::t('Delete this item?'),
'$showmore' => Core\L10n::t('show more'),
'$showfewer' => Core\L10n::t('show fewer'),
'$update_interval' => $interval,
'$shortcut_icon' => $shortcut_icon,
'$touch_icon' => $touch_icon,
@ -840,7 +655,7 @@ class App
]);
}
Core\Addon::callHooks('footer', $this->page['footer']);
Core\Hook::callAll('footer', $this->page['footer']);
$tpl = Core\Renderer::getMarkupTemplate('footer.tpl');
$this->page['footer'] = Core\Renderer::replaceMacros($tpl, [
@ -855,6 +670,7 @@ class App
* @param string $origURL
*
* @return string The cleaned url
* @throws InternalServerErrorException
*/
public function removeBaseURL($origURL)
{
@ -871,43 +687,11 @@ class App
}
}
/**
* Saves a timestamp for a value - f.e. a call
* Necessary for profiling Friendica
*
* @param int $timestamp the Timestamp
* @param string $value A value to profile
*/
public function saveTimestamp($timestamp, $value)
{
if (!isset($this->config['system']['profiler']) || !$this->config['system']['profiler']) {
return;
}
$duration = (float) (microtime(true) - $timestamp);
if (!isset($this->performance[$value])) {
// Prevent ugly E_NOTICE
$this->performance[$value] = 0;
}
$this->performance[$value] += (float) $duration;
$this->performance['marktime'] += (float) $duration;
$callstack = Core\System::callstack();
if (!isset($this->callstack[$value][$callstack])) {
// Prevent ugly E_NOTICE
$this->callstack[$value][$callstack] = 0;
}
$this->callstack[$value][$callstack] += (float) $duration;
}
/**
* Returns the current UserAgent as a String
*
* @return string the UserAgent as a String
* @throws InternalServerErrorException
*/
public function getUserAgent()
{
@ -1031,6 +815,7 @@ class App
* @brief Checks if the minimal memory is reached
*
* @return bool Is the memory limit reached?
* @throws InternalServerErrorException
*/
public function isMinMemoryReached()
{
@ -1075,6 +860,7 @@ class App
* @brief Checks if the maximum load is reached
*
* @return bool Is the load reached?
* @throws InternalServerErrorException
*/
public function isMaxLoadReached()
{
@ -1107,6 +893,7 @@ class App
*
* @param string $command The command to execute
* @param array $args Arguments to pass to the command ( [ 'key' => value, 'key2' => value2, ... ]
* @throws InternalServerErrorException
*/
public function proc_run($command, $args)
{
@ -1114,7 +901,7 @@ class App
return;
}
$cmdline = $this->getConfigValue('config', 'php_path', 'php') . ' ' . escapeshellarg($command);
$cmdline = $this->config->get('config', 'php_path', 'php') . ' ' . escapeshellarg($command);
foreach ($args as $key => $value) {
if (!is_null($value) && is_bool($value) && !$value) {
@ -1132,9 +919,9 @@ class App
}
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$resource = proc_open('cmd /c start /b ' . $cmdline, [], $foo, $this->getBasePath());
$resource = proc_open('cmd /c start /b ' . $cmdline, [], $foo, $this->basePath);
} else {
$resource = proc_open($cmdline . ' &', [], $foo, $this->getBasePath());
$resource = proc_open($cmdline . ' &', [], $foo, $this->basePath);
}
if (!is_resource($resource)) {
Core\Logger::log('We got no resource for command ' . $cmdline, Core\Logger::DEBUG);
@ -1143,204 +930,11 @@ class App
proc_close($resource);
}
/**
* @brief Returns the system user that is executing the script
*
* This mostly returns something like "www-data".
*
* @return string system username
*/
private static function getSystemUser()
{
if (!function_exists('posix_getpwuid') || !function_exists('posix_geteuid')) {
return '';
}
$processUser = posix_getpwuid(posix_geteuid());
return $processUser['name'];
}
/**
* @brief Checks if a given directory is usable for the system
*
* @return boolean the directory is usable
*/
public static function isDirectoryUsable($directory, $check_writable = true)
{
if ($directory == '') {
Core\Logger::log('Directory is empty. This shouldn\'t happen.', Core\Logger::DEBUG);
return false;
}
if (!file_exists($directory)) {
Core\Logger::log('Path "' . $directory . '" does not exist for user ' . self::getSystemUser(), Core\Logger::DEBUG);
return false;
}
if (is_file($directory)) {
Core\Logger::log('Path "' . $directory . '" is a file for user ' . self::getSystemUser(), Core\Logger::DEBUG);
return false;
}
if (!is_dir($directory)) {
Core\Logger::log('Path "' . $directory . '" is not a directory for user ' . self::getSystemUser(), Core\Logger::DEBUG);
return false;
}
if ($check_writable && !is_writable($directory)) {
Core\Logger::log('Path "' . $directory . '" is not writable for user ' . self::getSystemUser(), Core\Logger::DEBUG);
return false;
}
return true;
}
/**
* @param string $cat Config category
* @param string $k Config key
* @param mixed $default Default value if it isn't set
*
* @return string Returns the value of the Config entry
*/
public function getConfigValue($cat, $k, $default = null)
{
$return = $default;
if ($cat === 'config') {
if (isset($this->config[$k])) {
$return = $this->config[$k];
}
} else {
if (isset($this->config[$cat][$k])) {
$return = $this->config[$cat][$k];
}
}
return $return;
}
/**
* Sets a default value in the config cache. Ignores already existing keys.
*
* @param string $cat Config category
* @param string $k Config key
* @param mixed $v Default value to set
*/
private function setDefaultConfigValue($cat, $k, $v)
{
if (!isset($this->config[$cat][$k])) {
$this->setConfigValue($cat, $k, $v);
}
}
/**
* Sets a value in the config cache. Accepts raw output from the config table
*
* @param string $cat Config category
* @param string $k Config key
* @param mixed $v Value to set
*/
public function setConfigValue($cat, $k, $v)
{
// Only arrays are serialized in database, so we have to unserialize sparingly
$value = is_string($v) && preg_match("|^a:[0-9]+:{.*}$|s", $v) ? unserialize($v) : $v;
if ($cat === 'config') {
$this->config[$k] = $value;
} else {
if (!isset($this->config[$cat])) {
$this->config[$cat] = [];
}
$this->config[$cat][$k] = $value;
}
}
/**
* Deletes a value from the config cache
*
* @param string $cat Config category
* @param string $k Config key
*/
public function deleteConfigValue($cat, $k)
{
if ($cat === 'config') {
if (isset($this->config[$k])) {
unset($this->config[$k]);
}
} else {
if (isset($this->config[$cat][$k])) {
unset($this->config[$cat][$k]);
}
}
}
/**
* Retrieves a value from the user config cache
*
* @param int $uid User Id
* @param string $cat Config category
* @param string $k Config key
* @param mixed $default Default value if key isn't set
*
* @return string The value of the config entry
*/
public function getPConfigValue($uid, $cat, $k, $default = null)
{
$return = $default;
if (isset($this->config[$uid][$cat][$k])) {
$return = $this->config[$uid][$cat][$k];
}
return $return;
}
/**
* Sets a value in the user config cache
*
* Accepts raw output from the pconfig table
*
* @param int $uid User Id
* @param string $cat Config category
* @param string $k Config key
* @param mixed $v Value to set
*/
public function setPConfigValue($uid, $cat, $k, $v)
{
// Only arrays are serialized in database, so we have to unserialize sparingly
$value = is_string($v) && preg_match("|^a:[0-9]+:{.*}$|s", $v) ? unserialize($v) : $v;
if (!isset($this->config[$uid]) || !is_array($this->config[$uid])) {
$this->config[$uid] = [];
}
if (!isset($this->config[$uid][$cat]) || !is_array($this->config[$uid][$cat])) {
$this->config[$uid][$cat] = [];
}
$this->config[$uid][$cat][$k] = $value;
}
/**
* Deletes a value from the user config cache
*
* @param int $uid User Id
* @param string $cat Config category
* @param string $k Config key
*/
public function deletePConfigValue($uid, $cat, $k)
{
if (isset($this->config[$uid][$cat][$k])) {
unset($this->config[$uid][$cat][$k]);
}
}
/**
* Generates the site's default sender email address
*
* @return string
* @throws InternalServerErrorException
*/
public function getSenderEmailAddress()
{
@ -1361,6 +955,7 @@ class App
* Returns the current theme name.
*
* @return string the name of the current theme
* @throws InternalServerErrorException
*/
public function getCurrentTheme()
{
@ -1442,6 +1037,7 @@ class App
* Provide a sane default if nothing is chosen or the specified theme does not exist.
*
* @return string
* @throws InternalServerErrorException
*/
public function getCurrentThemeStylesheetPath()
{
@ -1534,14 +1130,14 @@ class App
}
Core\Session::init();
Core\Addon::callHooks('init_1');
Core\Hook::callAll('init_1');
}
// Exclude the backend processes from the session management
if (!$this->isBackend()) {
$stamp1 = microtime(true);
session_start();
$this->saveTimestamp($stamp1, 'parser');
$this->profiler->saveTimestamp($stamp1, 'parser', Core\System::callstack());
Core\L10n::setSessionVariable();
Core\L10n::setLangFromSession();
} else {
@ -1549,6 +1145,13 @@ class App
Core\Worker::executeIfIdle();
}
if ($this->getMode()->isNormal()) {
$requester = HTTPSignature::getSigner('', $_SERVER);
if (!empty($requester)) {
Profile::addVisitorCookieForHandle($requester);
}
}
// ZRL
if (!empty($_GET['zrl']) && $this->getMode()->isNormal()) {
$this->query_string = Model\Profile::stripZrls($this->query_string);
@ -1601,7 +1204,7 @@ class App
$this->module = 'maintenance';
} else {
$this->checkURL();
Core\Update::check(false);
Core\Update::check($this->basePath, false);
Core\Addon::loadAddons();
Core\Hook::loadHooks();
}
@ -1725,7 +1328,7 @@ class App
$this->page['page_title'] = $this->module;
$placeholder = '';
Core\Addon::callHooks($this->module . '_mod_init', $placeholder);
Core\Hook::callAll($this->module . '_mod_init', $placeholder);
call_user_func([$this->module_class, 'init']);
@ -1749,28 +1352,28 @@ class App
if ($this->module_loaded) {
if (! $this->error && $_SERVER['REQUEST_METHOD'] === 'POST') {
Core\Addon::callHooks($this->module . '_mod_post', $_POST);
Core\Hook::callAll($this->module . '_mod_post', $_POST);
call_user_func([$this->module_class, 'post']);
}
if (! $this->error) {
Core\Addon::callHooks($this->module . '_mod_afterpost', $placeholder);
Core\Hook::callAll($this->module . '_mod_afterpost', $placeholder);
call_user_func([$this->module_class, 'afterpost']);
}
if (! $this->error) {
$arr = ['content' => $content];
Core\Addon::callHooks($this->module . '_mod_content', $arr);
Core\Hook::callAll($this->module . '_mod_content', $arr);
$content = $arr['content'];
$arr = ['content' => call_user_func([$this->module_class, 'content'])];
Core\Addon::callHooks($this->module . '_mod_aftercontent', $arr);
Core\Hook::callAll($this->module . '_mod_aftercontent', $arr);
$content .= $arr['content'];
}
}
// initialise content region
if ($this->getMode()->isNormal()) {
Core\Addon::callHooks('page_content_top', $this->page['content']);
Core\Hook::callAll('page_content_top', $this->page['content']);
}
$this->page['content'] .= $content;
@ -1797,7 +1400,7 @@ class App
}
// Report anything which needs to be communicated in the notification area (before the main body)
Core\Addon::callHooks('page_end', $this->page['content']);
Core\Hook::callAll('page_end', $this->page['content']);
// Add the navigation (menu) template
if ($this->module != 'install' && $this->module != 'maintenance') {
@ -1827,14 +1430,14 @@ class App
// And then append it to the target
$target->documentElement->appendChild($item);
}
}
if (isset($_GET["mode"]) && ($_GET["mode"] == "raw")) {
header("Content-type: text/html; charset=utf-8");
if ($_GET["mode"] == "raw") {
header("Content-type: text/html; charset=utf-8");
echo substr($target->saveHTML(), 6, -8);
echo substr($target->saveHTML(), 6, -8);
exit();
exit();
}
}
$page = $this->page;
@ -1903,7 +1506,7 @@ class App
* Should only be used if it isn't clear if the URL is either internal or external
*
* @param string $toUrl The target URL
*
* @throws InternalServerErrorException
*/
public function redirect($toUrl)
{

View file

@ -42,7 +42,7 @@ class Mode
* - App::MODE_NORMAL : Normal run with all features enabled
*
* @param string $basepath the Basepath of the Application
*
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function determine($basepath = null)
{

View file

@ -150,8 +150,8 @@ abstract class BaseModule extends BaseObject
$a = \get_app();
Logger::log('checkFormSecurityToken failed: user ' . $a->user['guid'] . ' - form element ' . $typename);
Logger::log('checkFormSecurityToken failed: _REQUEST data: ' . print_r($_REQUEST, true), Logger::DATA);
header('HTTP/1.1 403 Forbidden');
killme();
System::httpExit(403);
}
}
}

View file

@ -4,6 +4,10 @@
*/
namespace Friendica;
require_once __DIR__ . '/../boot.php';
use Friendica\Network\HTTPException\InternalServerErrorException;
/**
* Basic object
*
@ -19,11 +23,12 @@ class BaseObject
* Same as get_app from boot.php
*
* @return App
* @throws \Exception
*/
public static function getApp()
{
if (empty(self::$app)) {
self::$app = new App(dirname(__DIR__));
throw new InternalServerErrorException('App isn\'t initialized.');
}
return self::$app;

View file

@ -4,10 +4,9 @@
*/
namespace Friendica\Content;
use Friendica\Core\Addon;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Protocol;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Util\Network;
use Friendica\Util\Strings;
@ -20,6 +19,8 @@ class ContactSelector
/**
* @param string $current current
* @param string $foreign_net network
* @return string
* @throws \Exception
*/
public static function profileAssign($current, $foreign_net)
{
@ -74,6 +75,7 @@ class ContactSelector
* @param string $network network
* @param string $profile optional, default empty
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function networkToName($network, $profile = "")
{
@ -96,7 +98,7 @@ class ContactSelector
Protocol::PNUT => L10n::t('pnut'),
];
Addon::callHooks('network_to_name', $nets);
Hook::callAll('network_to_name', $nets);
$search = array_keys($nets);
$replace = array_values($nets);
@ -141,19 +143,37 @@ class ContactSelector
/**
* @param string $current optional, default empty
* @param string $suffix optionsl, default empty
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function gender($current = "", $suffix = "")
{
$o = '';
$select = ['', L10n::t('Male'), L10n::t('Female'), L10n::t('Currently Male'), L10n::t('Currently Female'), L10n::t('Mostly Male'), L10n::t('Mostly Female'), L10n::t('Transgender'), L10n::t('Intersex'), L10n::t('Transsexual'), L10n::t('Hermaphrodite'), L10n::t('Neuter'), L10n::t('Non-specific'), L10n::t('Other'), L10n::t('Undecided')];
$select = [
'' => L10n::t('No answer'),
'Male' => L10n::t('Male'),
'Female' => L10n::t('Female'),
'Currently Male' => L10n::t('Currently Male'),
'Currently Female' => L10n::t('Currently Female'),
'Mostly Male' => L10n::t('Mostly Male'),
'Mostly Female' => L10n::t('Mostly Female'),
'Transgender' => L10n::t('Transgender'),
'Intersex' => L10n::t('Intersex'),
'Transsexual' => L10n::t('Transsexual'),
'Hermaphrodite' => L10n::t('Hermaphrodite'),
'Neuter' => L10n::t('Neuter'),
'Non-specific' => L10n::t('Non-specific'),
'Other' => L10n::t('Other'),
'Undecided' => L10n::t('Undecided'),
];
Addon::callHooks('gender_selector', $select);
Hook::callAll('gender_selector', $select);
$o .= "<select name=\"gender$suffix\" id=\"gender-select$suffix\" size=\"1\" >";
foreach ($select as $selection) {
foreach ($select as $neutral => $selection) {
if ($selection !== 'NOTRANSLATION') {
$selected = (($selection == $current) ? ' selected="selected" ' : '');
$o .= "<option value=\"$selection\" $selected >$selection</option>";
$selected = (($neutral == $current) ? ' selected="selected" ' : '');
$o .= "<option value=\"$neutral\" $selected >$selection</option>";
}
}
$o .= '</select>';
@ -163,20 +183,36 @@ class ContactSelector
/**
* @param string $current optional, default empty
* @param string $suffix optionsl, default empty
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function sexualPreference($current = "", $suffix = "")
{
$o = '';
$select = ['', L10n::t('Males'), L10n::t('Females'), L10n::t('Gay'), L10n::t('Lesbian'), L10n::t('No Preference'), L10n::t('Bisexual'), L10n::t('Autosexual'), L10n::t('Abstinent'), L10n::t('Virgin'), L10n::t('Deviant'), L10n::t('Fetish'), L10n::t('Oodles'), L10n::t('Nonsexual')];
$select = [
'' => L10n::t('No answer'),
'Males' => L10n::t('Males'),
'Females' => L10n::t('Females'),
'Gay' => L10n::t('Gay'),
'Lesbian' => L10n::t('Lesbian'),
'No Preference' => L10n::t('No Preference'),
'Bisexual' => L10n::t('Bisexual'),
'Autosexual' => L10n::t('Autosexual'),
'Abstinent' => L10n::t('Abstinent'),
'Virgin' => L10n::t('Virgin'),
'Deviant' => L10n::t('Deviant'),
'Fetish' => L10n::t('Fetish'),
'Oodles' => L10n::t('Oodles'),
'Nonsexual' => L10n::t('Nonsexual'),
];
Addon::callHooks('sexpref_selector', $select);
Hook::callAll('sexpref_selector', $select);
$o .= "<select name=\"sexual$suffix\" id=\"sexual-select$suffix\" size=\"1\" >";
foreach ($select as $selection) {
foreach ($select as $neutral => $selection) {
if ($selection !== 'NOTRANSLATION') {
$selected = (($selection == $current) ? ' selected="selected" ' : '');
$o .= "<option value=\"$selection\" $selected >$selection</option>";
$selected = (($neutral == $current) ? ' selected="selected" ' : '');
$o .= "<option value=\"$neutral\" $selected >$selection</option>";
}
}
$o .= '</select>';
@ -185,19 +221,54 @@ class ContactSelector
/**
* @param string $current optional, default empty
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function maritalStatus($current = "")
{
$o = '';
$select = ['', L10n::t('Single'), L10n::t('Lonely'), L10n::t('Available'), L10n::t('Unavailable'), L10n::t('Has crush'), L10n::t('Infatuated'), L10n::t('Dating'), L10n::t('Unfaithful'), L10n::t('Sex Addict'), L10n::t('Friends'), L10n::t('Friends/Benefits'), L10n::t('Casual'), L10n::t('Engaged'), L10n::t('Married'), L10n::t('Imaginarily married'), L10n::t('Partners'), L10n::t('Cohabiting'), L10n::t('Common law'), L10n::t('Happy'), L10n::t('Not looking'), L10n::t('Swinger'), L10n::t('Betrayed'), L10n::t('Separated'), L10n::t('Unstable'), L10n::t('Divorced'), L10n::t('Imaginarily divorced'), L10n::t('Widowed'), L10n::t('Uncertain'), L10n::t('It\'s complicated'), L10n::t('Don\'t care'), L10n::t('Ask me')];
$select = [
'' => L10n::t('No answer'),
'Single' => L10n::t('Single'),
'Lonely' => L10n::t('Lonely'),
'Available' => L10n::t('Available'),
'Unavailable' => L10n::t('Unavailable'),
'Has crush' => L10n::t('Has crush'),
'Infatuated' => L10n::t('Infatuated'),
'Dating' => L10n::t('Dating'),
'Unfaithful' => L10n::t('Unfaithful'),
'Sex Addict' => L10n::t('Sex Addict'),
'Friends' => L10n::t('Friends'),
'Friends/Benefits' => L10n::t('Friends/Benefits'),
'Casual' => L10n::t('Casual'),
'Engaged' => L10n::t('Engaged'),
'Married' => L10n::t('Married'),
'Imaginarily married' => L10n::t('Imaginarily married'),
'Partners' => L10n::t('Partners'),
'Cohabiting' => L10n::t('Cohabiting'),
'Common law' => L10n::t('Common law'),
'Happy' => L10n::t('Happy'),
'Not looking' => L10n::t('Not looking'),
'Swinger' => L10n::t('Swinger'),
'Betrayed' => L10n::t('Betrayed'),
'Separated' => L10n::t('Separated'),
'Unstable' => L10n::t('Unstable'),
'Divorced' => L10n::t('Divorced'),
'Imaginarily divorced' => L10n::t('Imaginarily divorced'),
'Widowed' => L10n::t('Widowed'),
'Uncertain' => L10n::t('Uncertain'),
'It\'s complicated' => L10n::t('It\'s complicated'),
'Don\'t care' => L10n::t('Don\'t care'),
'Ask me' => L10n::t('Ask me'),
];
Addon::callHooks('marital_selector', $select);
Hook::callAll('marital_selector', $select);
$o .= '<select name="marital" id="marital-select" size="1" >';
foreach ($select as $selection) {
foreach ($select as $neutral => $selection) {
if ($selection !== 'NOTRANSLATION') {
$selected = (($selection == $current) ? ' selected="selected" ' : '');
$o .= "<option value=\"$selection\" $selected >$selection</option>";
$selected = (($neutral == $current) ? ' selected="selected" ' : '');
$o .= "<option value=\"$neutral\" $selected >$selection</option>";
}
}
$o .= '</select>';

View file

@ -5,8 +5,8 @@
*/
namespace Friendica\Content;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\PConfig;
@ -18,6 +18,7 @@ class Feature
* @param integer $uid user id
* @param string $feature feature
* @return boolean
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function isEnabled($uid, $feature)
{
@ -36,7 +37,7 @@ class Feature
}
$arr = ['uid' => $uid, 'feature' => $feature, 'enabled' => $x];
Addon::callHooks('isEnabled', $arr);
Hook::callAll('isEnabled', $arr);
return($arr['enabled']);
}
@ -45,6 +46,7 @@ class Feature
*
* @param string $feature feature
* @return boolean
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function getDefault($feature)
{
@ -69,6 +71,7 @@ class Feature
* @param bool $filtered True removes any locked features
*
* @return array
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function get($filtered = true)
{
@ -87,6 +90,7 @@ class Feature
'composition' => [
L10n::t('Post Composition Features'),
['aclautomention', L10n::t('Auto-mention Forums'), L10n::t('Add/remove mention when a forum page is selected/deselected in ACL window.'), false, Config::get('feature_lock', 'aclautomention', false)],
['explicit_mentions', L10n::t('Explicit Mentions'), L10n::t('Add explicit mentions to comment box for manual control over who gets mentioned in replies.'), false, Config::get('feature_lock', 'explicit_mentions', false)],
],
// Network sidebar widgets
@ -139,7 +143,7 @@ class Feature
}
}
Addon::callHooks('get', $arr);
Hook::callAll('get', $arr);
return $arr;
}
}

View file

@ -6,7 +6,6 @@
namespace Friendica\Content;
use Friendica\Core\Protocol;
use Friendica\Content\Feature;
use Friendica\Content\Text\HTML;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
@ -29,11 +28,12 @@ class ForumManager
* @param boolean $showprivate Show private groups
*
* @return array
* 'url' => forum url
* 'name' => forum name
* 'id' => number of the key from the array
* 'micro' => contact photo in format micro
* 'thumb' => contact photo in format thumb
* 'url' => forum url
* 'name' => forum name
* 'id' => number of the key from the array
* 'micro' => contact photo in format micro
* 'thumb' => contact photo in format thumb
* @throws \Exception
*/
public static function getList($uid, $lastitem, $showhidden = true, $showprivate = false)
{
@ -88,6 +88,8 @@ class ForumManager
* @param int $uid The ID of the User
* @param int $cid The contact id which is used to mark a forum as "selected"
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function widget($uid, $cid = 0)
{
@ -103,6 +105,8 @@ class ForumManager
if (DBA::isResult($contacts)) {
$id = 0;
$entries = [];
foreach ($contacts as $contact) {
$selected = (($cid == $contact['id']) ? ' forum-selected' : '');
@ -143,6 +147,8 @@ class ForumManager
*
* @param int $uid The ID of the User
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function profileAdvanced($uid)
{
@ -164,7 +170,7 @@ class ForumManager
$total_shown = 0;
$forumlist = '';
foreach ($contacts as $contact) {
$forumlist .= HTML::micropro($contact, false, 'forumlist-profile-advanced');
$forumlist .= HTML::micropro($contact, true, 'forumlist-profile-advanced');
$total_shown ++;
if ($total_shown == $show_total) {
break;
@ -183,9 +189,10 @@ class ForumManager
* Count unread items of connected forums and private groups
*
* @return array
* 'id' => contact id
* 'name' => contact/forum name
* 'count' => counted unseen forum items
* 'id' => contact id
* 'name' => contact/forum name
* 'count' => counted unseen forum items
* @throws \Exception
*/
public static function countUnseenItems()
{

View file

@ -5,15 +5,14 @@
namespace Friendica\Content;
use Friendica\App;
use Friendica\Content\Feature;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\Profile;
use Friendica\Model\User;
class Nav
{
@ -43,6 +42,8 @@ class Nav
/**
* Set a menu item in navbar as selected
*
* @param string $item
*/
public static function setSelected($item)
{
@ -51,6 +52,10 @@ class Nav
/**
* Build page header and site navigation bars
*
* @param App $a
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function build(App $a)
{
@ -74,7 +79,7 @@ class Nav
'$search_hint' => L10n::t('@name, !forum, #tags, content')
]);
Addon::callHooks('page_header', $nav);
Hook::callAll('page_header', $nav);
return $nav;
}
@ -105,7 +110,7 @@ class Nav
if (local_user() || !$privateapps) {
$arr = ['app_menu' => self::$app_menu];
Addon::callHooks('app_menu', $arr);
Hook::callAll('app_menu', $arr);
self::$app_menu = $arr['app_menu'];
}
@ -115,12 +120,13 @@ class Nav
* Prepares a list of navigation links
*
* @brief Prepares a list of navigation links
* @param App $a
* @param App $a
* @return array Navigation links
* string 'sitelocation' => The webbie (username@site.com)
* array 'nav' => Array of links used in the nav menu
* string 'banner' => Formatted html link with banner image
* array 'userinfo' => Array of user information (name, icon)
* string 'sitelocation' => The webbie (username@site.com)
* array 'nav' => Array of links used in the nav menu
* string 'banner' => Formatted html link with banner image
* array 'userinfo' => Array of user information (name, icon)
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function getInfo(App $a)
{
@ -174,7 +180,7 @@ class Nav
$nav['home'] = [$homelink, L10n::t('Home'), '', L10n::t('Home Page')];
}
if (intval(Config::get('config', 'register_policy')) === REGISTER_OPEN && !local_user() && !remote_user()) {
if (intval(Config::get('config', 'register_policy')) === \Friendica\Module\Register::OPEN && !local_user() && !remote_user()) {
$nav['register'] = ['register', L10n::t('Register'), '', L10n::t('Create an account')];
}
@ -236,7 +242,7 @@ class Nav
$nav['home'] = ['profile/' . $a->user['nickname'], L10n::t('Home'), '', L10n::t('Your posts and conversations')];
// Don't show notifications for public communities
if (defaults($_SESSION, 'page_flags', '') != Contact::PAGE_COMMUNITY) {
if (defaults($_SESSION, 'page_flags', '') != User::PAGE_FLAGS_COMMUNITY) {
$nav['introductions'] = ['notifications/intros', L10n::t('Introductions'), '', L10n::t('Friend Requests')];
$nav['notifications'] = ['notifications', L10n::t('Notifications'), '', L10n::t('Notifications')];
$nav['notifications']['all'] = ['notifications/system', L10n::t('See all notifications'), '', ''];
@ -276,7 +282,7 @@ class Nav
$banner = '<a href="https://friendi.ca"><img id="logo-img" src="images/friendica-32.png" alt="logo" /></a><span id="logo-text"><a href="https://friendi.ca">Friendica</a></span>';
}
Addon::callHooks('nav_info', $nav);
Hook::callAll('nav_info', $nav);
return [
'sitelocation' => $sitelocation,

View file

@ -10,9 +10,9 @@ use DOMNode;
use DOMText;
use DOMXPath;
use Exception;
use Friendica\Core\Addon;
use Friendica\Core\Cache;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Renderer;
use Friendica\Core\System;
@ -51,6 +51,7 @@ class OEmbed
* @param bool $no_rich_type If set to true rich type content won't be fetched.
*
* @return \Friendica\Object\OEmbed
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function fetchURL($embedurl, $no_rich_type = false)
{
@ -159,7 +160,7 @@ class OEmbed
}
}
Addon::callHooks('oembed_fetch_url', $embedurl, $oembed);
Hook::callAll('oembed_fetch_url', $embedurl, $oembed);
return $oembed;
}
@ -260,6 +261,9 @@ class OEmbed
/**
* Find <span class='oembed'>..<a href='url' rel='oembed'>..</a></span>
* and replace it with [embed]url[/embed]
*
* @param $text
* @return string
*/
public static function HTML2BBCode($text)
{
@ -298,6 +302,7 @@ class OEmbed
* @brief Determines if rich content OEmbed is allowed for the provided URL
* @param string $url
* @return boolean
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function isAllowedURL($url)
{
@ -353,19 +358,18 @@ class OEmbed
* Since the iframe is automatically resized on load, there are no need for ugly
* and impractical scrollbars.
*
* @todo This function is currently unused until someone™ adds support for a separate OEmbed domain
* @todo This function is currently unused until someone™ adds support for a separate OEmbed domain
*
* @param string $src Original remote URL to embed
* @param string $width
* @param string $height
* @return string formatted HTML
*
* @see oembed_format_object()
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @see oembed_format_object()
*/
private static function iframe($src, $width, $height)
{
$a = \get_app();
if (!$height || strstr($height, '%')) {
$height = '200';
}

View file

@ -65,7 +65,7 @@ class Pager
/**
* Returns the current page number
*
* @return type
* @return int
*/
public function getPage()
{
@ -140,6 +140,7 @@ class Pager
*
* @param integer $itemCount The number of displayed items on the page
* @return string HTML string of the pager
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function renderMinimal($itemCount)
{
@ -182,6 +183,7 @@ class Pager
*
* @param integer $itemCount The total number of items including those note displayed on the page
* @return string HTML string of the pager
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public function renderFull($itemCount)
{

View file

@ -14,9 +14,8 @@
*/
namespace Friendica\Content;
use Friendica\App;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\PConfig;
use Friendica\Core\System;
use Friendica\Util\Strings;
@ -56,10 +55,11 @@ class Smilies
* Get an array of all smilies, both internal and from addons.
*
* @return array
* 'texts' => smilie shortcut
* 'icons' => icon in html
* 'texts' => smilie shortcut
* 'icons' => icon in html
*
* @hook smilie ('texts' => smilies texts array, 'icons' => smilies html array)
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @hook smilie ('texts' => smilies texts array, 'icons' => smilies html array)
*/
public static function getList()
{
@ -141,7 +141,7 @@ class Smilies
];
$params = ['texts' => $texts, 'icons' => $icons];
Addon::callHooks('smilie', $params);
Hook::callAll('smilie', $params);
return $params;
}
@ -183,6 +183,7 @@ class Smilies
* @param boolean $no_images Only replace emoticons without images
*
* @return string HTML Output of the Smilie
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function replace($s, $no_images = false)
{
@ -202,6 +203,7 @@ class Smilies
* @param array $smilies An string replacement array with the following structure: ['texts' => [], 'icons' => []]
* @param bool $no_images Only replace shortcodes without image replacement (e.g. Unicode characters)
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function replaceFromArray($text, array $smilies, $no_images = false)
{
@ -249,6 +251,7 @@ class Smilies
* @param string $m string
*
* @return string base64 decoded string
* @throws \Exception
*/
private static function decode($m)
{
@ -263,7 +266,8 @@ class Smilies
*
* @return string HTML Output
*
* @todo: Rework because it doesn't work correctly
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @todo : Rework because it doesn't work correctly
*/
private static function pregHeart($x)
{

View file

@ -11,9 +11,9 @@ use Exception;
use Friendica\BaseObject;
use Friendica\Content\OEmbed;
use Friendica\Content\Smilies;
use Friendica\Core\Addon;
use Friendica\Core\Cache;
use Friendica\Core\Config;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\Protocol;
@ -37,13 +37,14 @@ class BBCode extends BaseObject
*
* @param string $body Message body
* @return array
* 'type' -> Message type ("link", "video", "photo")
* 'text' -> Text before the shared message
* 'after' -> Text after the shared message
* 'image' -> Preview image of the message
* 'url' -> Url to the attached message
* 'title' -> Title of the attachment
* 'description' -> Description of the attachment
* 'type' -> Message type ("link", "video", "photo")
* 'text' -> Text before the shared message
* 'after' -> Text after the shared message
* 'image' -> Preview image of the message
* 'url' -> Url to the attached message
* 'title' -> Title of the attachment
* 'description' -> Description of the attachment
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function getOldAttachmentData($body)
{
@ -66,6 +67,7 @@ class BBCode extends BaseObject
$post["after"] = trim(substr($body, $pos + strlen($data[0])));
} else {
$post["text"] = trim(str_replace($data[0], "", $body));
$post["after"] = '';
}
$attacheddata = $data[2];
@ -108,13 +110,14 @@ class BBCode extends BaseObject
*
* @param string $body Message body
* @return array
* 'type' -> Message type ("link", "video", "photo")
* 'text' -> Text before the shared message
* 'after' -> Text after the shared message
* 'image' -> Preview image of the message
* 'url' -> Url to the attached message
* 'title' -> Title of the attachment
* 'description' -> Description of the attachment
* 'type' -> Message type ("link", "video", "photo")
* 'text' -> Text before the shared message
* 'after' -> Text after the shared message
* 'image' -> Preview image of the message
* 'url' -> Url to the attached message
* 'title' -> Title of the attachment
* 'description' -> Description of the attachment
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function getAttachmentData($body)
{
@ -345,6 +348,7 @@ class BBCode extends BaseObject
/**
* @brief Converts a BBCode text into plaintext
*
* @param $text
* @param bool $keep_urls Whether to keep URLs in the resulting plaintext
*
* @return string
@ -446,6 +450,7 @@ class BBCode extends BaseObject
* @brief Truncates imported message body string length to max_import_size
* @param string $body
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function limitBodySize($body)
{
@ -532,10 +537,11 @@ class BBCode extends BaseObject
* Note: Can produce a [bookmark] tag in the returned string
*
* @brief Processes [attachment] tags
* @param string $return
* @param string $return
* @param bool|int $simplehtml
* @param bool $tryoembed
* @param bool $tryoembed
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function convertAttachment($return, $simplehtml = false, $tryoembed = true)
{
@ -777,10 +783,10 @@ class BBCode extends BaseObject
/**
* Performs a preg_replace within the boundaries of all named BBCode tags in a text
*
* @param type $pattern Preg pattern string
* @param type $replace Preg replace string
* @param type $name BBCode tag name
* @param type $text Text to search
* @param string $pattern Preg pattern string
* @param string $replace Preg replace string
* @param string $name BBCode tag name
* @param string $text Text to search
* @return string
*/
public static function pregReplaceInTag($pattern, $replace, $name, $text)
@ -930,6 +936,7 @@ class BBCode extends BaseObject
* @param boolean $is_quote_share Whether there is content before the [share] block
* @param integer $simplehtml Mysterious integer value depending on the target network/formatting style
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
private static function convertShareCallback(array $attributes, array $author_contact, $content, $is_quote_share, $simplehtml)
{
@ -943,15 +950,19 @@ class BBCode extends BaseObject
$text = ($is_quote_share? '<br />' : '') . '<p>' . html_entity_decode('&#x2672; ', ENT_QUOTES, 'UTF-8') . ' ' . $author_contact['addr'] . ': </p>' . "\n" . $content;
break;
case 3: // Diaspora
$headline = '<p><b>' . html_entity_decode('&#x2672; ', ENT_QUOTES, 'UTF-8') . $mention . ':</b></p>' . "\n";
if (stripos(Strings::normaliseLink($attributes['link']), 'http://twitter.com/') === 0) {
$text = ($is_quote_share? '<hr />' : '') . '<p><a href="' . $attributes['link'] . '">' . $attributes['link'] . '</a></p>' . "\n";
} else {
$headline = '<p><b>♲ <a href="' . $attributes['profile'] . '">' . $attributes['author'] . '</a>:</b></p>' . "\n";
if (!empty($attributes['posted']) && !empty($attributes['link'])) {
$headline = '<p><b>♲ <a href="' . $attributes['profile'] . '">' . $attributes['author'] . '</a></b> - <a href="' . $attributes['link'] . '">' . $attributes['posted'] . ' GMT</a></p>' . "\n";
}
$text = ($is_quote_share? '<hr />' : '') . $headline . '<blockquote>' . trim($content) . '</blockquote>' . "\n";
if ($attributes['link'] != '') {
$text .= '<p><a href="' . $attributes['link'] . '">[l]</a></p>' . "\n";
if (empty($attributes['posted']) && !empty($attributes['link'])) {
$text .= '<p><a href="' . $attributes['link'] . '">[Source]</a></p>' . "\n";
}
}
@ -1021,7 +1032,7 @@ class BBCode extends BaseObject
@curl_exec($ch);
$curl_info = @curl_getinfo($ch);
$a->saveTimestamp($stamp1, "network");
$a->getProfiler()->saveTimestamp($stamp1, "network", System::callstack());
if (substr($curl_info["content_type"], 0, 6) == "image/") {
$text = "[url=" . $match[1] . "]" . $match[1] . "[/url]";
@ -1080,7 +1091,7 @@ class BBCode extends BaseObject
@curl_exec($ch);
$curl_info = @curl_getinfo($ch);
$a->saveTimestamp($stamp1, "network");
$a->getProfiler()->saveTimestamp($stamp1, "network", System::callstack());
// if its a link to a picture then embed this picture
if (substr($curl_info["content_type"], 0, 6) == "image/") {
@ -1142,8 +1153,9 @@ class BBCode extends BaseObject
* @param int $simple_html
* @param bool $for_plaintext
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function convert($text, $try_oembed = true, $simple_html = false, $for_plaintext = false)
public static function convert($text, $try_oembed = true, $simple_html = 0, $for_plaintext = false)
{
$a = self::getApp();
@ -1168,17 +1180,18 @@ class BBCode extends BaseObject
return $return;
};
// Extracting multi-line code blocks before the whitespace processing
// Extracting code blocks before the whitespace processing and the autolinker
$codeblocks = [];
$text = preg_replace_callback("#\[code(?:=([^\]]*))?\](.*?)\[\/code\]#is",
$text = preg_replace_callback("#\[code(?:=([^\]]*))?\](.*?)\[\/code\]#ism",
function ($matches) use (&$codeblocks) {
$return = $matches[0];
$return = '#codeblock-' . count($codeblocks) . '#';
if (strpos($matches[2], "\n") !== false) {
$return = '#codeblock-' . count($codeblocks) . '#';
$codeblocks[] = '<pre><code class="language-' . trim($matches[1]) . '">' . trim($matches[2], "\n\r") . '</code></pre>';
$codeblocks[] = '<pre><code class="language-' . trim($matches[1]) . '">' . trim($matches[2], "\n\r") . '</code></pre>';
} else {
$codeblocks[] = '<code>' . $matches[2] . '</code>';
}
return $return;
},
$text
@ -1254,13 +1267,12 @@ class BBCode extends BaseObject
// Set up the parameters for a MAIL search string
$MAILSearchString = $URLSearchString;
// Handle attached links or videos
$text = self::convertAttachment($text, $simple_html, $try_oembed);
// if the HTML is used to generate plain text, then don't do this search, but replace all URL of that kind to text
if (!$for_plaintext) {
// Autolink feature (thanks to http://code.seebz.net/p/autolink-php/)
// Currently disabled, since the function is too greedy
// $autolink_regex = "`([^\]\=\"']|^)(https?\://[^\s<]+[^\s<\.\)])`ism";
$autolink_regex = "/([^\]\='".'"'."]|^)(https?\:\/\/[a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism";
$text = preg_replace($autolink_regex, '$1[url]$2[/url]', $text);
$text = preg_replace(Strings::autoLinkRegEx(), '[url]$1[/url]', $text);
if ($simple_html == 7) {
$text = preg_replace_callback("/\[url\]([$URLSearchString]*)\[\/url\]/ism", 'self::convertUrlForOStatusCallback', $text);
$text = preg_replace_callback("/\[url\=([$URLSearchString]*)\]([$URLSearchString]*)\[\/url\]/ism", 'self::convertUrlForOStatusCallback', $text);
@ -1270,10 +1282,6 @@ class BBCode extends BaseObject
$text = preg_replace_callback("&\[url=([^\[\]]*)\]\[img\](.*)\[\/img\]\[\/url\]&Usi", 'self::removePictureLinksCallback', $text);
}
// Handle attached links or videos
$text = self::convertAttachment($text, $simple_html, $try_oembed);
$text = str_replace(["\r","\n"], ['<br />', '<br />'], $text);
// Remove all hashtag addresses
@ -1286,7 +1294,7 @@ class BBCode extends BaseObject
$text);
} elseif ($simple_html == 7) {
$text = preg_replace("/([@!])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
'$1<span class="vcard"><a href="$2" class="url" title="$3"><span class="fn nickname mention">$3</span></a></span>',
'$1<span class="vcard"><a href="$2" class="url u-url mention" title="$3"><span class="fn nickname mention">$3</span></a></span>',
$text);
} elseif (!$simple_html) {
$text = preg_replace("/([@!])\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism",
@ -1354,6 +1362,12 @@ class BBCode extends BaseObject
. '</a>';
}, $text);
// We need no target="_blank" for local links
// convert links start with System::baseUrl() as local link without the target="_blank" attribute
$escapedBaseUrl = preg_quote(System::baseUrl(), '/');
$text = preg_replace("/\[url\](".$escapedBaseUrl."[$URLSearchString]*)\[\/url\]/ism", '<a href="$1">$1</a>', $text);
$text = preg_replace("/\[url\=(".$escapedBaseUrl."[$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1">$2</a>', $text);
$text = preg_replace("/\[url\]([$URLSearchString]*)\[\/url\]/ism", '<a href="$1" target="_blank">$1</a>', $text);
$text = preg_replace("/\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", '<a href="$1" target="_blank">$2</a>', $text);
@ -1489,12 +1503,6 @@ class BBCode extends BaseObject
// Check for font change text
$text = preg_replace("/\[font=(.*?)\](.*?)\[\/font\]/sm", "<span style=\"font-family: $1;\">$2</span>", $text);
// Declare the format for [code] layout
$CodeLayout = '<code>$1</code>';
// Check for [code] text
$text = preg_replace("/\[code\](.*?)\[\/code\]/ism", "$CodeLayout", $text);
// Declare the format for [spoiler] layout
$SpoilerLayout = '<blockquote class="spoiler">$1</blockquote>';
@ -1676,7 +1684,7 @@ class BBCode extends BaseObject
// Replace non graphical smilies for external posts
if ($simple_html) {
$text = Smilies::replace($text, false, true);
$text = Smilies::replace($text);
}
// Unhide all [noparse] contained bbtags unspacefying them
@ -1730,7 +1738,7 @@ class BBCode extends BaseObject
// Clean up the HTML by loading and saving the HTML with the DOM.
// Bad structured html can break a whole page.
// For performance reasons do it only with ativated item cache or at export.
// For performance reasons do it only with activated item cache or at export.
if (!$try_oembed || (get_itemcachepath() != "")) {
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
@ -1756,7 +1764,7 @@ class BBCode extends BaseObject
//$Text = str_replace('<br /><li>', '<li>', $Text);
//$Text = str_replace('<br /><ul', '<ul ', $Text);
Addon::callHooks('bbcode', $text);
Hook::callAll('bbcode', $text);
return trim($text);
}
@ -1813,6 +1821,8 @@ class BBCode extends BaseObject
* [2] = Name
* [3] = Address
* @return string Replaced mention
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
private static function bbCodeMention2DiasporaCallback($match)
{
@ -1839,6 +1849,7 @@ class BBCode extends BaseObject
* @param string $text
* @param bool $for_diaspora Diaspora requires more changes than Libertree
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function toMarkdown($text, $for_diaspora = true)
{
@ -1899,7 +1910,7 @@ class BBCode extends BaseObject
// unmask the special chars back to HTML
$text = str_replace(['&\_lt\_;', '&\_gt\_;', '&\_amp\_;'], ['&lt;', '&gt;', '&amp;'], $text);
$a->saveTimestamp($stamp1, "parser");
$a->getProfiler()->saveTimestamp($stamp1, "parser", System::callstack());
// Libertree has a problem with escaped hashtags.
$text = str_replace(['\#'], ['#'], $text);
@ -1917,7 +1928,7 @@ class BBCode extends BaseObject
);
}
Addon::callHooks('bb2diaspora', $text);
Hook::callAll('bb2diaspora', $text);
return $text;
}
@ -1943,7 +1954,7 @@ class BBCode extends BaseObject
$string = preg_replace('/#\[url\=([^\[\]]*)\](.*?)\[\/url\]/ism', '#$2', $string);
// ignore anything in a code block
$string = preg_replace('/\[code\](.*?)\[\/code\]/sm', '', $string);
$string = preg_replace('/\[code.*?\].*?\[\/code\]/sm', '', $string);
// Force line feeds at bbtags
$string = str_replace(['[', ']'], ["\n[", "]\n"], $string);

View file

@ -7,14 +7,11 @@ namespace Friendica\Content\Text;
use DOMDocument;
use DOMXPath;
use Friendica\Content\Feature;
use Friendica\Core\Addon;
use Friendica\Content\Widget\ContactBlock;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\Config;
use Friendica\Core\PConfig;
use Friendica\Core\Protocol;
use Friendica\Core\Renderer;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Util\Network;
use Friendica\Util\Proxy as ProxyUtils;
@ -118,12 +115,13 @@ class HTML
/**
* Made by: ike@piratenpartei.de
* Originally made for the syncom project: http://wiki.piratenpartei.de/Syncom
* https://github.com/annando/Syncom
* https://github.com/annando/Syncom
*
* @brief Converter for HTML to BBCode
* @param string $message
* @param string $basepath
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function toBBCode($message, $basepath = '')
{
@ -315,7 +313,7 @@ class HTML
$message = preg_replace('=\r *\r=i', "\n", $message);
$message = str_replace("\r", "\n", $message);
Addon::callHooks('html2bbcode', $message);
Hook::callAll('html2bbcode', $message);
$message = strip_tags($message);
@ -714,6 +712,7 @@ class HTML
* @brief Convert video HTML to BBCode tags
*
* @param string $s
* @return string
*/
public static function toBBCodeVideo($s)
{
@ -790,7 +789,9 @@ class HTML
/**
* Loader for infinite scrolling
*
* @return string html for loader
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function scrollLoader()
{
@ -804,109 +805,39 @@ class HTML
/**
* Get html for contact block.
*
* @template contact_block.tpl
* @hook contact_block_end (contacts=>array, output=>string)
* @deprecated since version 2019.03
* @see ContactBlock::getHTML()
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function contactBlock()
{
$o = '';
$a = \get_app();
$shown = PConfig::get($a->profile['uid'], 'system', 'display_friend_count', 24);
if ($shown == 0) {
return;
}
if (!is_array($a->profile) || $a->profile['hide-friends']) {
return $o;
}
$r = q("SELECT COUNT(*) AS `total` FROM `contact`
WHERE `uid` = %d AND NOT `self` AND NOT `blocked`
AND NOT `pending` AND NOT `hidden` AND NOT `archive`
AND `network` IN ('%s', '%s', '%s')",
intval($a->profile['uid']),
DBA::escape(Protocol::DFRN),
DBA::escape(Protocol::OSTATUS),
DBA::escape(Protocol::DIASPORA)
);
if (DBA::isResult($r)) {
$total = intval($r[0]['total']);
}
if (!$total) {
$contacts = L10n::t('No contacts');
$micropro = null;
} else {
// Splitting the query in two parts makes it much faster
$r = q("SELECT `id` FROM `contact`
WHERE `uid` = %d AND NOT `self` AND NOT `blocked`
AND NOT `pending` AND NOT `hidden` AND NOT `archive`
AND `network` IN ('%s', '%s', '%s')
ORDER BY RAND() LIMIT %d",
intval($a->profile['uid']),
DBA::escape(Protocol::DFRN),
DBA::escape(Protocol::OSTATUS),
DBA::escape(Protocol::DIASPORA),
intval($shown)
);
if (DBA::isResult($r)) {
$contacts = [];
foreach ($r as $contact) {
$contacts[] = $contact["id"];
}
$r = q("SELECT `id`, `uid`, `addr`, `url`, `name`, `thumb`, `network` FROM `contact` WHERE `id` IN (%s)",
DBA::escape(implode(",", $contacts))
);
if (DBA::isResult($r)) {
$contacts = L10n::tt('%d Contact', '%d Contacts', $total);
$micropro = [];
foreach ($r as $rr) {
$micropro[] = self::micropro($rr, true, 'mpfriend');
}
}
}
}
$tpl = Renderer::getMarkupTemplate('contact_block.tpl');
$o = Renderer::replaceMacros($tpl, [
'$contacts' => $contacts,
'$nickname' => $a->profile['nickname'],
'$viewcontacts' => L10n::t('View Contacts'),
'$micropro' => $micropro,
]);
$arr = ['contacts' => $r, 'output' => $o];
Addon::callHooks('contact_block_end', $arr);
return $o;
return ContactBlock::getHTML($a->profile);
}
/**
* @brief Format contacts as picture links or as text links
*
* @param array $contact Array with contacts which contains an array with
* int 'id' => The ID of the contact
* int 'uid' => The user ID of the user who owns this data
* string 'name' => The name of the contact
* string 'url' => The url to the profile page of the contact
* string 'addr' => The webbie of the contact (e.g.) username@friendica.com
* string 'network' => The network to which the contact belongs to
* string 'thumb' => The contact picture
* string 'click' => js code which is performed when clicking on the contact
* @param boolean $redirect If true try to use the redir url if it's possible
* @param string $class CSS class for the
* @param boolean $textmode If true display the contacts as text links
* if false display the contacts as picture links
* @return string Formatted html
*/
* @param array $contact Array with contacts which contains an array with
* int 'id' => The ID of the contact
* int 'uid' => The user ID of the user who owns this data
* string 'name' => The name of the contact
* string 'url' => The url to the profile page of the contact
* string 'addr' => The webbie of the contact (e.g.) username@friendica.com
* string 'network' => The network to which the contact belongs to
* string 'thumb' => The contact picture
* string 'click' => js code which is performed when clicking on the contact
* @param boolean $redirect If true try to use the redir url if it's possible
* @param string $class CSS class for the
* @param boolean $textmode If true display the contacts as text links
* if false display the contacts as picture links
* @return string Formatted html
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function micropro($contact, $redirect = false, $class = '', $textmode = false)
{
// Use the contact URL if no address is available
@ -948,10 +879,10 @@ class HTML
* @param string $s Search query.
* @param string $id HTML id
* @param string $url Search url.
* @param bool $save Show save search button.
* @param bool $aside Display the search widgit aside.
*
* @return string Formatted HTML.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function search($s, $id = 'search-box', $url = 'search', $aside = true)
{
@ -991,6 +922,7 @@ class HTML
* Replace naked text hyperlink with HTML formatted hyperlink
*
* @param string $s
* @return string
*/
public static function toLink($s)
{
@ -1007,6 +939,7 @@ class HTML
* @param string $html
* @param array $reasons
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function applyContentFilter($html, array $reasons)
{

View file

@ -7,9 +7,8 @@
namespace Friendica\Content\Text;
use Friendica\BaseObject;
use Friendica\Core\System;
use Friendica\Model\Contact;
use Michelf\MarkdownExtra;
use Friendica\Content\Text\HTML;
/**
* Friendica-specific usage of Markdown
@ -26,16 +25,25 @@ class Markdown extends BaseObject
* @param string $text
* @param bool $hardwrap
* @return string
* @throws \Exception
*/
public static function convert($text, $hardwrap = true) {
$stamp1 = microtime(true);
$MarkdownParser = new MarkdownExtra();
$MarkdownParser->hard_wrap = $hardwrap;
$MarkdownParser->code_class_prefix = 'language-';
$MarkdownParser = new MarkdownParser();
$MarkdownParser->code_class_prefix = 'language-';
$MarkdownParser->hard_wrap = $hardwrap;
$MarkdownParser->hashtag_protection = true;
$MarkdownParser->url_filter_func = function ($url) {
if (strpos($url, '#') === 0) {
$url = ltrim($_SERVER['REQUEST_URI'], '/') . $url;
}
return $url;
};
$html = $MarkdownParser->transform($text);
self::getApp()->saveTimestamp($stamp1, "parser");
self::getApp()->getProfiler()->saveTimestamp($stamp1, "parser", System::callstack());
return $html;
}
@ -48,6 +56,8 @@ class Markdown extends BaseObject
* [2] = name (optional)
* [3] = address
* @return string Replaced mention
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
private static function diasporaMention2BBCodeCallback($match)
{
@ -80,27 +90,17 @@ class Markdown extends BaseObject
{
$s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
// Handles single newlines
$s = str_replace("\r\n", "\n", $s);
$s = str_replace("\n", " \n", $s);
$s = str_replace("\r", " \n", $s);
// Replace lonely stars in lines not starting with it with literal stars
$s = preg_replace('/^([^\*]+)\*([^\*]*)$/im', '$1\*$2', $s);
// The parser cannot handle paragraphs correctly
$s = str_replace(['</p>', '<p>', '<p dir="ltr">'], ['<br>', '<br>', '<br>'], $s);
// Escaping the hash tags
$s = preg_replace('/\#([^\s\#])/', '&#35;$1', $s);
// Escaping hashtags that could be titles
$s = preg_replace('/^\#([^\s\#])/im', '\#$1', $s);
$s = self::convert($s);
$regexp = "/([@!])\{(?:([^\}]+?); ?)?([^\} ]+)\}/";
$s = preg_replace_callback($regexp, ['self', 'diasporaMention2BBCodeCallback'], $s);
$s = str_replace('&#35;', '#', $s);
$s = HTML::toBBCode($s);
// protect the recycle symbol from turning into a tag, but without unescaping angles and naked ampersands

View file

@ -0,0 +1,18 @@
<?php
namespace Friendica\Content\Text;
use Friendica\Util\Strings;
use Michelf\MarkdownExtra;
class MarkdownParser extends MarkdownExtra
{
protected function doAutoLinks($text)
{
$text = parent::doAutoLinks($text);
$text = preg_replace_callback(Strings::autoLinkRegEx(),
array($this, '_doAutoLinks_url_callback'), $text);
return $text;
}
}

View file

@ -9,9 +9,9 @@ class Plaintext
/**
* Shortens message
*
* @param type $msg
* @param type $limit
* @return type
* @param string $msg
* @param int $limit
* @return string
*
* @todo For Twitter URLs aren't shortened, but they have to be calculated as if.
*/

View file

@ -4,8 +4,6 @@
*/
namespace Friendica\Content;
use Friendica\Content\ContactSelector;
use Friendica\Content\Feature;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\L10n;
@ -28,6 +26,8 @@ class Widget
* Return the follow widget
*
* @param string $value optional, default empty
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function follow($value = "")
{
@ -125,6 +125,8 @@ class Widget
*
* @param string $baseurl baseurl
* @param string $selected optional, default empty
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function networks($baseurl, $selected = '')
{
@ -167,6 +169,8 @@ class Widget
*
* @param string $baseurl baseurl
* @param string $selected optional, default empty
* @return string|void
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function fileAs($baseurl, $selected = '')
{
@ -205,6 +209,8 @@ class Widget
*
* @param string $baseurl baseurl
* @param string $selected optional, default empty
* @return string|void
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function categories($baseurl, $selected = '')
{
@ -244,6 +250,8 @@ class Widget
* Return common friends visitor widget
*
* @param string $profile_uid uid
* @return string|void
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function commonFriendsVisitor($profile_uid)
{
@ -327,8 +335,10 @@ class Widget
* Insert a tag cloud widget for the present profile.
*
* @brief Insert a tag cloud widget for the present profile.
* @param int $limit Max number of displayed tags.
* @param int $limit Max number of displayed tags.
* @return string HTML formatted output.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
* @throws \ImagickException
*/
public static function tagCloud($limit = 50)
{

View file

@ -21,6 +21,7 @@ class CalendarExport
* @brief Get the events widget.
*
* @return string Formated HTML of the calendar widget.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function getHTML() {
$a = \get_app();

View file

@ -0,0 +1,119 @@
<?php
/*
* @file src/Content/Widget/ContactBlock.php
*/
namespace Friendica\Content\Widget;
use Friendica\Content\Text\HTML;
use Friendica\Core\Hook;
use Friendica\Core\L10n;
use Friendica\Core\PConfig;
use Friendica\Core\Protocol;
use Friendica\Core\Renderer;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\User;
/**
* ContactBlock widget
*
* @author Hypolite Petovan
*/
class ContactBlock
{
/**
* Get HTML for contact block
*
* @template contact_block.tpl
* @hook contact_block_end (contacts=>array, output=>string)
* @return string
*/
public static function getHTML(array $profile)
{
$o = '';
$shown = PConfig::get($profile['uid'], 'system', 'display_friend_count', 24);
if ($shown == 0) {
return $o;
}
if (!empty($profile['hide-friends'])) {
return $o;
}
$contacts = [];
$total = DBA::count('contact', [
'uid' => $profile['uid'],
'self' => false,
'blocked' => false,
'pending' => false,
'hidden' => false,
'archive' => false,
'network' => [Protocol::DFRN, Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA],
]);
$contacts_title = L10n::t('No contacts');
$micropro = [];
if ($total) {
// Only show followed for personal accounts, followers for pages
if (defaults($profile, 'account-type', User::ACCOUNT_TYPE_PERSON) == User::ACCOUNT_TYPE_PERSON) {
$rel = [Contact::SHARING, Contact::FRIEND];
} else {
$rel = [Contact::FOLLOWER, Contact::FRIEND];
}
$contact_ids_stmt = DBA::select('contact', ['id'], [
'uid' => $profile['uid'],
'self' => false,
'blocked' => false,
'pending' => false,
'hidden' => false,
'archive' => false,
'rel' => $rel,
'network' => [Protocol::DFRN, Protocol::ACTIVITYPUB, Protocol::OSTATUS, Protocol::DIASPORA],
], ['limit' => $shown]);
if (DBA::isResult($contact_ids_stmt)) {
$contact_ids = [];
while($contact = DBA::fetch($contact_ids_stmt)) {
$contact_ids[] = $contact["id"];
}
$contacts_stmt = DBA::select('contact', ['id', 'uid', 'addr', 'url', 'name', 'thumb', 'network'], ['id' => $contact_ids]);
if (DBA::isResult($contacts_stmt)) {
$contacts_title = L10n::tt('%d Contact', '%d Contacts', $total);
$micropro = [];
while ($contact = DBA::fetch($contacts_stmt)) {
$contacts[] = $contact;
$micropro[] = HTML::micropro($contact, true, 'mpfriend');
}
}
DBA::close($contacts_stmt);
}
DBA::close($contact_ids_stmt);
}
$tpl = Renderer::getMarkupTemplate('contact_block.tpl');
$o = Renderer::replaceMacros($tpl, [
'$contacts' => $contacts_title,
'$nickname' => $profile['nickname'],
'$viewcontacts' => L10n::t('View Contacts'),
'$micropro' => $micropro,
]);
$arr = ['contacts' => $contacts, 'output' => $o];
Hook::callAll('contact_block_end', $arr);
return $o;
}
}

View file

@ -11,7 +11,6 @@ use Friendica\Core\Renderer;
use Friendica\Core\System;
use Friendica\Database\DBA;
use Friendica\Model\Item;
use Friendica\Util\Security;
/**
* TagCloud widget
@ -24,13 +23,14 @@ class TagCloud
* Construct a tag/term cloud block for an user.
*
* @brief Construct a tag/term cloud block for an user.
* @param int $uid The user ID.
* @param int $count Max number of displayed tags/terms.
* @param int $owner_id The contact ID of the owner of the tagged items.
* @param string $flags Special item flags.
* @param int $type The tag/term type.
* @param int $uid The user ID.
* @param int $count Max number of displayed tags/terms.
* @param int $owner_id The contact ID of the owner of the tagged items.
* @param string $flags Special item flags.
* @param int $type The tag/term type.
*
* @return string HTML formatted output.
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function getHTML($uid, $count = 0, $owner_id = 0, $flags = '', $type = TERM_HASHTAG)
{
@ -40,6 +40,7 @@ class TagCloud
$contact = DBA::selectFirst('contact', ['url'], ['uid' => $uid, 'self' => true]);
$url = System::removedBaseUrl($contact['url']);
$tags = [];
foreach ($r as $rr) {
$tag['level'] = $rr[2];
$tag['url'] = $url . '?tag=' . urlencode($rr[0]);
@ -63,13 +64,14 @@ class TagCloud
*
* @brief Get alphabetical sorted array of used tags/terms of an user including
* a weighting by frequency of use.
* @param int $uid The user ID.
* @param int $count Max number of displayed tags/terms.
* @param int $owner_id The contact id of the owner of the tagged items.
* @param string $flags Special item flags.
* @param int $type The tag/term type.
* @param int $uid The user ID.
* @param int $count Max number of displayed tags/terms.
* @param int $owner_id The contact id of the owner of the tagged items.
* @param string $flags Special item flags.
* @param int $type The tag/term type.
*
* @return arr Alphabetical sorted array of used tags of an user.
* @return array Alphabetical sorted array of used tags of an user.
* @throws \Exception
*/
private static function tagadelic($uid, $count = 0, $owner_id = 0, $flags = '', $type = TERM_HASHTAG)
{
@ -87,7 +89,7 @@ class TagCloud
}
// Fetch tags
$r = DBA::p("SELECT `term`, COUNT(`term`) AS `total` FROM `term`
$tag_stmt = DBA::p("SELECT `term`, COUNT(`term`) AS `total` FROM `term`
LEFT JOIN `item` ON `term`.`oid` = `item`.`id`
WHERE `term`.`uid` = ? AND `term`.`type` = ?
AND `term`.`otype` = ?
@ -98,10 +100,12 @@ class TagCloud
$type,
TERM_OBJ_POST
);
if (!DBA::isResult($r)) {
if (!DBA::isResult($tag_stmt)) {
return [];
}
$r = DBA::toArray($tag_stmt);
return self::tagCalc($r);
}
@ -112,7 +116,7 @@ class TagCloud
* @param array $arr Array of tags/terms with tag/term name and total count of use.
* @return array Alphabetical sorted array of used tags/terms of an user.
*/
private static function tagCalc($arr)
private static function tagCalc(array $arr)
{
$tags = [];
$min = 1e9;
@ -146,8 +150,8 @@ class TagCloud
* Compare function to sort tags/terms alphabetically.
*
* @brief Compare function to sort tags/terms alphabetically.
* @param type $a
* @param type $b
* @param string $a
* @param string $b
*
* @return int
*/

View file

@ -8,8 +8,6 @@ namespace Friendica\Core;
use Friendica\BaseObject;
use Friendica\Content\Feature;
use Friendica\Core\Protocol;
use Friendica\Core\Renderer;
use Friendica\Database\DBA;
use Friendica\Model\Contact;
use Friendica\Model\GContact;
@ -25,15 +23,16 @@ class ACL extends BaseObject
/**
* Returns a select input tag with all the contact of the local user
*
* @param string $selname Name attribute of the select input tag
* @param string $selclass Class attribute of the select input tag
* @param array $options Available options:
* - size: length of the select box
* - mutual_friends: Only used for the hook
* - single: Only used for the hook
* - exclude: Only used for the hook
* @param array $preselected Contact ID that should be already selected
* @param string $selname Name attribute of the select input tag
* @param string $selclass Class attribute of the select input tag
* @param array $options Available options:
* - size: length of the select box
* - mutual_friends: Only used for the hook
* - single: Only used for the hook
* - exclude: Only used for the hook
* @param array $preselected Contact ID that should be already selected
* @return string
* @throws \Exception
*/
public static function getSuggestContactSelectHTML($selname, $selclass, array $options = [], array $preselected = [])
{
@ -69,7 +68,7 @@ class ACL extends BaseObject
$x = ['options' => $options, 'size' => $size, 'single' => $single, 'mutual' => $mutual, 'exclude' => $exclude, 'networks' => $networks];
Addon::callHooks('contact_select_options', $x);
Hook::callAll('contact_select_options', $x);
$o = '';
@ -111,7 +110,7 @@ class ACL extends BaseObject
$arr = ['contact' => $contacts, 'entry' => $o];
// e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'
Addon::callHooks($a->module . '_pre_' . $selname, $arr);
Hook::callAll($a->module . '_pre_' . $selname, $arr);
if (DBA::isResult($contacts)) {
foreach ($contacts as $contact) {
@ -129,7 +128,7 @@ class ACL extends BaseObject
$o .= '</select>' . PHP_EOL;
Addon::callHooks($a->module . '_post_' . $selname, $o);
Hook::callAll($a->module . '_post_' . $selname, $o);
return $o;
}
@ -143,6 +142,7 @@ class ACL extends BaseObject
* @param int $size Length of the select box
* @param int $tabindex Select input tag tabindex attribute
* @return string
* @throws \Exception
*/
public static function getMessageContactSelectHTML($selname, $selclass, array $preselected = [], $size = 4, $tabindex = null)
{
@ -176,7 +176,7 @@ class ACL extends BaseObject
$arr = ['contact' => $contacts, 'entry' => $o];
// e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'
Addon::callHooks($a->module . '_pre_' . $selname, $arr);
Hook::callAll($a->module . '_pre_' . $selname, $arr);
$receiverlist = [];
@ -202,7 +202,7 @@ class ACL extends BaseObject
$o .= implode(', ', $receiverlist);
}
Addon::callHooks($a->module . '_post_' . $selname, $o);
Hook::callAll($a->module . '_post_' . $selname, $o);
return $o;
}
@ -217,6 +217,7 @@ class ACL extends BaseObject
*
* @param array $user
* @return array Hash of contact id lists
* @throws \Exception
*/
public static function getDefaultUserPermissions(array $user = null)
{
@ -253,9 +254,10 @@ class ACL extends BaseObject
* Return the full jot ACL selector HTML
*
* @param array $user User array
* @param array $default_permissions Static defaults permission array: ['allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '']
* @param bool $show_jotnets
* @param array $default_permissions Static defaults permission array: ['allow_cid' => '', 'allow_gid' => '', 'deny_cid' => '', 'deny_gid' => '']
* @return string
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function getFullSelectorHTML(array $user, $show_jotnets = false, array $default_permissions = [])
{
@ -285,22 +287,22 @@ class ACL extends BaseObject
$jotnets .= '<div class="profile-jot-net"><input type="checkbox" name="pubmail_enable"' . $selected . ' value="1" /> ' . L10n::t("Post to Email") . '</div>';
}
Addon::callHooks('jot_networks', $jotnets);
Hook::callAll('jot_networks', $jotnets);
} else {
$jotnets .= L10n::t('Connectors disabled, since "%s" is enabled.',
L10n::t('Hide your profile details from unknown viewers?'));
}
}
$tpl = Renderer::getMarkupTemplate('acl_selector.tpl');
$o = Renderer::replaceMacros($tpl, [
'$showall' => L10n::t('Visible to everybody'),
'$show' => L10n::t('show'),
'$hide' => L10n::t('don\'t show'),
'$allowcid' => json_encode(defaults($default_permissions, 'allow_cid', '')),
'$allowgid' => json_encode(defaults($default_permissions, 'allow_gid', '')),
'$denycid' => json_encode(defaults($default_permissions, 'deny_cid', '')),
'$denygid' => json_encode(defaults($default_permissions, 'deny_gid', '')),
'$allowcid' => json_encode(defaults($default_permissions, 'allow_cid', [])), // we need arrays for Javascript since we call .remove() and .push() on this values
'$allowgid' => json_encode(defaults($default_permissions, 'allow_gid', [])),
'$denycid' => json_encode(defaults($default_permissions, 'deny_cid', [])),
'$denygid' => json_encode(defaults($default_permissions, 'deny_gid', [])),
'$networks' => $show_jotnets,
'$emailcc' => L10n::t('CC: email addresses'),
'$emtitle' => L10n::t('Example: bob@example.com, mary@example.com'),
@ -322,6 +324,7 @@ class ACL extends BaseObject
* @param string $search Name or part of a name or nick
* @param string $mode Search mode (e.g. "community")
* @return array with the search results
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function contactAutocomplete($search, $mode)
{

View file

@ -4,9 +4,7 @@
*/
namespace Friendica\Core;
use Friendica\App;
use Friendica\BaseObject;
use Friendica\Core\Logger;
use Friendica\Database\DBA;
/**
@ -14,6 +12,12 @@ use Friendica\Database\DBA;
*/
class Addon extends BaseObject
{
/**
* The addon sub-directory
* @var string
*/
const DIRECTORY = 'addon';
/**
* List of the names of enabled addons
*
@ -72,11 +76,12 @@ class Addon extends BaseObject
* @brief uninstalls an addon.
*
* @param string $addon name of the addon
* @return boolean
* @return void
* @throws \Exception
*/
public static function uninstall($addon)
{
Logger::log("Addons: uninstalling " . $addon);
Logger::notice("Addon {addon}: {action}", ['action' => 'uninstall', 'addon' => $addon]);
DBA::delete('addon', ['name' => $addon]);
@include_once('addon/' . $addon . '/' . $addon . '.php');
@ -93,6 +98,7 @@ class Addon extends BaseObject
*
* @param string $addon name of the addon
* @return bool
* @throws \Exception
*/
public static function install($addon)
{
@ -101,12 +107,12 @@ class Addon extends BaseObject
if (!file_exists('addon/' . $addon . '/' . $addon . '.php')) {
return false;
}
Logger::log("Addons: installing " . $addon);
Logger::notice("Addon {addon}: {action}", ['action' => 'install', 'addon' => $addon]);
$t = @filemtime('addon/' . $addon . '/' . $addon . '.php');
@include_once('addon/' . $addon . '/' . $addon . '.php');
if (function_exists($addon . '_install')) {
$func = $addon . '_install';
$func();
$func(self::getApp());
$addon_admin = (function_exists($addon . "_addon_admin") ? 1 : 0);
@ -126,7 +132,7 @@ class Addon extends BaseObject
}
return true;
} else {
Logger::log("Addons: FAILED installing " . $addon);
Logger::error("Addon {addon}: {action} failed", ['action' => 'uninstall', 'addon' => $addon]);
return false;
}
}
@ -156,16 +162,17 @@ class Addon extends BaseObject
$t = @filemtime($fname);
foreach ($installed as $i) {
if (($i['name'] == $addon) && ($i['timestamp'] != $t)) {
Logger::log('Reloading addon: ' . $i['name']);
Logger::notice("Addon {addon}: {action}", ['action' => 'reload', 'addon' => $i['name']]);
@include_once($fname);
if (function_exists($addon . '_uninstall')) {
$func = $addon . '_uninstall';
$func();
$func(self::getApp());
}
if (function_exists($addon . '_install')) {
$func = $addon . '_install';
$func();
$func(self::getApp());
}
DBA::update('addon', ['timestamp' => $t], ['id' => $i['id']]);
}
@ -191,6 +198,7 @@ class Addon extends BaseObject
* *\endcode
* @param string $addon the name of the addon
* @return array with the addon information
* @throws \Exception
*/
public static function getInfo($addon)
{
@ -211,7 +219,7 @@ class Addon extends BaseObject
$stamp1 = microtime(true);
$f = file_get_contents("addon/$addon/$addon.php");
$a->saveTimestamp($stamp1, "file");
$a->getProfiler()->saveTimestamp($stamp1, "file", System::callstack());
$r = preg_match("|/\*.*\*/|msU", $f, $m);
@ -270,6 +278,7 @@ class Addon extends BaseObject
* Saves the current enabled addon list in the system.addon config key
*
* @return boolean
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function saveEnabledList()
{
@ -280,6 +289,7 @@ class Addon extends BaseObject
* Returns the list of non-hidden enabled addon names
*
* @return array
* @throws \Exception
*/
public static function getVisibleList()
{
@ -297,13 +307,14 @@ class Addon extends BaseObject
/**
* Shim of Hook::register left for backward compatibility purpose.
*
* @see Hook::register
* @see Hook::register
* @deprecated since version 2018.12
* @param string $hook the name of the hook
* @param string $file the name of the file that hooks into
* @param string $function the name of the function that the hook will call
* @param int $priority A priority (defaults to 0)
* @return mixed|bool
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function registerHook($hook, $file, $function, $priority = 0)
{
@ -313,12 +324,13 @@ class Addon extends BaseObject
/**
* Shim of Hook::unregister left for backward compatibility purpose.
*
* @see Hook::unregister
* @see Hook::unregister
* @deprecated since version 2018.12
* @param string $hook the name of the hook
* @param string $file the name of the file that hooks into
* @param string $function the name of the function that the hook called
* @return boolean
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function unregisterHook($hook, $file, $function)
{
@ -328,10 +340,11 @@ class Addon extends BaseObject
/**
* Shim of Hook::callAll left for backward-compatibility purpose.
*
* @see Hook::callAll
* @see Hook::callAll
* @deprecated since version 2018.12
* @param string $name of the hook to call
* @param string $name of the hook to call
* @param string|array &$data to transmit to the callback handler
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function callHooks($name, &$data = null)
{

View file

@ -6,11 +6,6 @@
namespace Friendica\Core;
use Friendica\BaseObject;
use Friendica\Core\Addon;
use Friendica\Core\Config;
use Friendica\Core\L10n;
use Friendica\Core\Logger;
use Friendica\Core\PConfig;
use Friendica\Database\DBA;
use Friendica\Model\User;
use Friendica\Util\DateTimeFormat;
@ -26,6 +21,7 @@ class Authentication extends BaseObject
* @param array $user Record from "user" table
*
* @return string Hashed data
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function getCookieHashForUser($user)
{
@ -37,8 +33,9 @@ class Authentication extends BaseObject
/**
* @brief Set the "Friendica" cookie
*
* @param int $time
* @param int $time
* @param array $user Record from "user" table
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function setCookie($time, $user = [])
{
@ -60,12 +57,13 @@ class Authentication extends BaseObject
/**
* @brief Sets the provided user's authenticated session
*
* @todo Should be moved to Friendica\Core\Session once it's created
* @todo Should be moved to Friendica\Core\Session once it's created
*
* @param type $user_record
* @param type $login_initial
* @param type $interactive
* @param type $login_refresh
* @param array $user_record
* @param bool $login_initial
* @param bool $interactive
* @param bool $login_refresh
* @throws \Friendica\Network\HTTPException\InternalServerErrorException
*/
public static function setAuthenticatedSessionForUser($user_record, $login_initial = false, $interactive = false, $login_refresh = false)
{
@ -154,7 +152,7 @@ class Authentication extends BaseObject
}
if ($login_initial) {
Addon::callHooks('logged_in', $a->user);
Hook::callAll('logged_in', $a->user);
if (($a->module !== 'home') && isset($_SESSION['return_path'])) {
$a->internalRedirect($_SESSION['return_path']);

View file

@ -55,6 +55,7 @@ class Cache extends \Friendica\BaseObject
* @param string $prefix Prefix of the keys (optional)
*
* @return array Empty if the driver doesn't support this feature
* @throws \Exception
*/
public static function getAllKeys($prefix = null)
{
@ -62,7 +63,7 @@ class Cache extends \Friendica\BaseObject
$return = self::getDriver()->getAllKeys($prefix);
self::getApp()->saveTimestamp($time, 'cache');
self::getApp()->getProfiler()->saveTimestamp($time, 'cache', System::callstack());
return $return;
}
@ -73,6 +74,7 @@ class Cache extends \Friendica\BaseObject
* @param string $key The key to the cached data
*
* @return mixed Cached $value or "null" if not found
* @throws \Exception
*/
public static function get($key)
{
@ -80,7 +82,7 @@ class Cache extends \Friendica\BaseObject
$return = self::getDriver()->get($key);
self::getApp()->saveTimestamp($time, 'cache');
self::getApp()->getProfiler()->saveTimestamp($time, 'cache', System::callstack());
return $return;
}
@ -95,6 +97,7 @@ class Cache extends \Friendica\BaseObject
* @param integer $duration The cache lifespan
*
* @return bool
* @throws \Exception
*/
public static function set($key, $value, $duration = self::MONTH)
{
@ -102,7 +105,7 @@ class Cache extends \Friendica\BaseObject
$return = self::getDriver()->set($key, $value, $duration);
self::getApp()->saveTimestamp($time, 'cache_write');
self::getApp()->getProfiler()->saveTimestamp($time, 'cache_write', System::callstack());
return $return;
}
@ -113,6 +116,7 @@ class Cache extends \Friendica\BaseObject
* @param string $key The key to the cached data
*
* @return bool
* @throws \Exception
*/
public static function delete($key)
{
@ -120,7 +124,7 @@ class Cache extends \Friendica\BaseObject
$return = self::getDriver()->delete($key);
self::getApp()->saveTimestamp($time, 'cache_write');
self::getApp()->getProfiler()->saveTimestamp($time, 'cache_write', System::callstack());
return $return;
}
@ -130,7 +134,7 @@ class Cache extends \Friendica\BaseObject
*
* @param boolean $outdated just remove outdated values
*
* @return void
* @return bool
*/
public static function clear($outdated = true)
{

View file

@ -14,8 +14,9 @@ use Friendica\BaseObject;
abstract class AbstractCacheDriver extends BaseObject
{
/**
* @param string $key The original key
* @return string The cache key used for the cache
* @param string $key The original key
* @return string The cache key used for the cache
* @throws \Exception
*/
protected function getCacheKey($key)
{

View file

@ -6,7 +6,6 @@ use Friendica\Core\Cache;
use Friendica\Core\Logger;
use Exception;
use Friendica\Network\HTTPException\InternalServerErrorException;
use Memcached;
/**

View file

@ -2,9 +2,8 @@
namespace Friendica\Core\Cache;
use Friendica\Core\Cache;
use Exception;
use Friendica\Core\Cache;
use Redis;
/**
@ -152,7 +151,7 @@ class RedisCacheDriver extends AbstractCacheDriver implements IMemoryCacheDriver
->exec();
} else {
$result = $this->redis->multi()
->set($cachekey, $newValue)
->set($cachekey, $newCached)
->exec();
}
return $result !== false;

View file

@ -8,10 +8,6 @@
*/
namespace Friendica\Core;
use Friendica\App;
use Friendica\BaseObject;
use Friendica\Core\Config;
/**
* @brief Arbitrary system configuration storage
*
@ -19,134 +15,79 @@ use Friendica\Core\Config;
* If we ever would decide to return exactly the variable type as entered,
* we will have fun with the additional features. :-)
*/
class Config extends BaseObject
class Config
{
/**
* @var Friendica\Core\Config\IConfigAdapter
* @var Config\Configuration
*/
private static $adapter = null;
private static $config;
public static function init()
/**
* Initialize the config
*
* @param Config\Configuration $config
*/
public static function init(Config\Configuration $config)
{
// Database isn't ready or populated yet
if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return;
}
if (self::getApp()->getConfigValue('system', 'config_adapter') == 'preload') {
self::$adapter = new Config\PreloadConfigAdapter();
} else {
self::$adapter = new Config\JITConfigAdapter();
}
self::$config = $config;
}
/**
* @brief Loads all configuration values of family into a cached storage.
*
* All configuration values of the system are stored in global cache
* which is available under the global variable $a->config
*
* @param string $family The category of the configuration value
* @param string $cat The category of the configuration value
*
* @return void
*/
public static function load($family = "config")
public static function load($cat = "config")
{
// Database isn't ready or populated yet
if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return;
}
if (empty(self::$adapter)) {
self::init();
}
self::$adapter->load($family);
self::$config->load($cat);
}
/**
* @brief Get a particular user's config variable given the category name
* ($family) and a key.
*
* Get a particular config value from the given category ($family)
* and the $key from a cached storage in $a->config[$uid].
* $instore is only used by the set_config function
* to determine if the key already exists in the DB
* If a key is found in the DB but doesn't exist in
* local config cache, pull it into the cache so we don't have
* to hit the DB again for this item.
*
* @param string $family The category of the configuration value
* @param string $cat The category of the configuration value
* @param string $key The configuration key to query
* @param mixed $default_value optional, The value to return if key is not set (default: null)
* @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false)
*
* @return mixed Stored value or null if it does not exist
*/
public static function get($family, $key, $default_value = null, $refresh = false)
public static function get($cat, $key, $default_value = null, $refresh = false)
{
// Database isn't ready or populated yet, fallback to file config
if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return self::getApp()->getConfigValue($family, $key, $default_value);
}
if (empty(self::$adapter)) {
self::init();
}
return self::$adapter->get($family, $key, $default_value, $refresh);
return self::$config->get($cat, $key, $default_value, $refresh);
}
/**
* @brief Sets a configuration value for system config
*
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the user_id $uid.
* Stores a config value ($value) in the category ($cat) under the key ($key)
*
* Note: Please do not store booleans - convert to 0/1 integer values!
*
* @param string $family The category of the configuration value
* @param string $cat The category of the configuration value
* @param string $key The configuration key to set
* @param mixed $value The value to store
*
* @return bool Operation success
*/
public static function set($family, $key, $value)
public static function set($cat, $key, $value)
{
// Database isn't ready or populated yet
if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return false;
}
if (empty(self::$adapter)) {
self::init();
}
return self::$adapter->set($family, $key, $value);
return self::$config->set($cat, $key, $value);
}
/**
* @brief Deletes the given key from the system configuration.
*
* Removes the configured value from the stored cache in $a->config
* and removes it from the database.
*
* @param string $family The category of the configuration value
* @param string $cat The category of the configuration value
* @param string $key The configuration key to delete
*
* @return mixed
* @return bool
*/
public static function delete($family, $key)
public static function delete($cat, $key)
{
// Database isn't ready or populated yet
if (!self::getApp()->getMode()->has(App\Mode::DBCONFIGAVAILABLE)) {
return false;
}
if (empty(self::$adapter)) {
self::init();
}
return self::$adapter->delete($family, $key);
return self::$config->delete($cat, $key);
}
}

View file

@ -0,0 +1,83 @@
<?php
namespace Friendica\Core\Config\Adapter;
use Friendica\Database\DBA;
abstract class AbstractDbaConfigAdapter
{
/**
* The connection state of the adapter
*
* @var bool
*/
protected $connected = true;
public function __construct()
{
$this->connected = DBA::connected();
}
/**
* Checks if the adapter is currently connected
*
* @return bool
*/
public function isConnected()
{
return $this->connected;
}
/**
* Formats a DB value to a config value
* - null = The db-value isn't set
* - bool = The db-value is either '0' or '1'
* - array = The db-value is a serialized array
* - string = The db-value is a string
*
* Keep in mind that there aren't any numeric/integer config values in the database
*
* @param null|string $value
*
* @return null|array|string
*/
protected function toConfigValue($value)
{
if (!isset($value)) {
return null;
}
switch (true) {
// manage array value
case preg_match("|^a:[0-9]+:{.*}$|s", $value):
return unserialize($value);
default:
return $value;
}
}
/**
* Formats a config value to a DB value (string)
*
* @param mixed $value
*
* @return string
*/
protected function toDbValue($value)
{
// if not set, save an empty string
if (!isset($value)) {
return '';
}
switch (true) {
// manage arrays
case is_array($value):
return serialize($value);
default:
return (string)$value;
}
}
}

View file

@ -0,0 +1,73 @@
<?php
namespace Friendica\Core\Config\Adapter;
/**
*
* @author Hypolite Petovan <hypolite@mrpetovan.com>
*/
interface IConfigAdapter
{
/**
* Loads all configuration values and returns the loaded category as an array.
*
* @param string $cat The category of the configuration values to load
*
* @return array
*/
public function load($cat = "config");
/**
* Get a particular system-wide config variable given the category name
* ($family) and a key.
*
* Note: Boolean variables are defined as 0/1 in the database
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to query
*
* @return null|mixed Stored value or null if it does not exist
*/
public function get($cat, $key);
/**
* Stores a config value ($value) in the category ($family) under the key ($key).
*
* Note: Please do not store booleans - convert to 0/1 integer values!
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to set
* @param mixed $value The value to store
*
* @return bool Operation success
*/
public function set($cat, $key, $value);
/**
* Removes the configured value from the stored cache
* and removes it from the database.
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to delete
*
* @return bool Operation success
*/
public function delete($cat, $key);
/**
* Checks, if the current adapter is connected to the backend
*
* @return bool
*/
public function isConnected();
/**
* Checks, if a config key ($key) in the category ($cat) is already loaded.
*
* @param string $cat The configuration category
* @param string $key The configuration key
*
* @return bool
*/
public function isLoaded($cat, $key);
}

View file

@ -0,0 +1,85 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace Friendica\Core\Config\Adapter;
/**
*
* @author benlo
*/
interface IPConfigAdapter
{
/**
* Loads all configuration values of a user's config family and returns the loaded category as an array.
*
* @param string $uid The user_id
* @param string $cat The category of the configuration value
*
* @return array
*/
public function load($uid, $cat);
/**
* Get a particular user's config variable given the category name
* ($family) and a key.
*
* Note: Boolean variables are defined as 0/1 in the database
*
* @param string $uid The user_id
* @param string $cat The category of the configuration value
* @param string $key The configuration key to query
*
* @return null|mixed Stored value or null if it does not exist
*/
public function get($uid, $cat, $key);
/**
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the user_id $uid.
*
* @note Please do not store booleans - convert to 0/1 integer values!
*
* @param string $uid The user_id
* @param string $cat The category of the configuration value
* @param string $key The configuration key to set
* @param string $value The value to store
*
* @return bool Operation success
*/
public function set($uid, $cat, $key, $value);
/**
* Removes the configured value from the stored cache
* and removes it from the database.
*
* @param string $uid The user_id
* @param string $cat The category of the configuration value
* @param string $key The configuration key to delete
*
* @return bool Operation success
*/
public function delete($uid, $cat, $key);
/**
* Checks, if the current adapter is connected to the backend
*
* @return bool
*/
public function isConnected();
/**
* Checks, if a config key ($key) in the category ($cat) is already loaded for the user_id $uid.
*
* @param string $uid The user_id
* @param string $cat The configuration category
* @param string $key The configuration key
*
* @return bool
*/
public function isLoaded($uid, $cat, $key);
}

View file

@ -0,0 +1,145 @@
<?php
namespace Friendica\Core\Config\Adapter;
use Friendica\Database\DBA;
/**
* JustInTime Configuration Adapter
*
* Default Config Adapter. Provides the best performance for pages loading few configuration variables.
*
* @author Hypolite Petovan <hypolite@mrpetovan.com>
*/
class JITConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter
{
private $in_db;
/**
* {@inheritdoc}
*/
public function load($cat = "config")
{
$return = [];
if (!$this->isConnected()) {
return $return;
}
// We don't preload "system" anymore.
// This reduces the number of database reads a lot.
if ($cat === 'system') {
return $return;
}
$configs = DBA::select('config', ['v', 'k'], ['cat' => $cat]);
while ($config = DBA::fetch($configs)) {
$key = $config['k'];
$value = $this->toConfigValue($config['v']);
// The value was in the db, so don't check it again (unless you have to)
$this->in_db[$cat][$key] = true;
// just save it in case it is set
if (isset($value)) {
$return[$key] = $value;
}
}
DBA::close($configs);
return [$cat => $return];
}
/**
* {@inheritdoc}
*
* @param bool $mark if true, mark the selection of the current cat/key pair
*/
public function get($cat, $key, $mark = true)
{
if (!$this->isConnected()) {
return null;
}
// The value got checked, so mark it to avoid checking it over and over again
if ($mark) {
$this->in_db[$cat][$key] = true;
}
$config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]);
if (DBA::isResult($config)) {
$value = $this->toConfigValue($config['v']);
// just return it in case it is set
if (isset($value)) {
return $value;
}
}
return null;
}
/**
* {@inheritdoc}
*/
public function set($cat, $key, $value)
{
if (!$this->isConnected()) {
return false;
}
// We store our setting values in a string variable.
// So we have to do the conversion here so that the compare below works.
// The exception are array values.
$compare_value = (!is_array($value) ? (string)$value : $value);
$stored_value = $this->get($cat, $key, false);
if (!isset($this->in_db[$cat])) {
$this->in_db[$cat] = [];
}
if (!isset($this->in_db[$cat][$key])) {
$this->in_db[$cat][$key] = false;
}
if (isset($stored_value) && ($stored_value === $compare_value) && $this->in_db[$cat][$key]) {
return true;
}
$dbvalue = $this->toDbValue($value);
$result = DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true);
$this->in_db[$cat][$key] = $result;
return $result;
}
/**
* {@inheritdoc}
*/
public function delete($cat, $key)
{
if (!$this->isConnected()) {
return false;
}
if (isset($this->cache[$cat][$key])) {
unset($this->in_db[$cat][$key]);
}
$result = DBA::delete('config', ['cat' => $cat, 'k' => $key]);
return $result;
}
/**
* {@inheritdoc}
*/
public function isLoaded($cat, $key)
{
if (!$this->isConnected()) {
return false;
}
return (isset($this->in_db[$cat][$key])) && $this->in_db[$cat][$key];
}
}

View file

@ -0,0 +1,145 @@
<?php
namespace Friendica\Core\Config\Adapter;
use Friendica\Database\DBA;
/**
* JustInTime User Configuration Adapter
*
* Default PConfig Adapter. Provides the best performance for pages loading few configuration variables.
*
* @author Hypolite Petovan <hypolite@mrpetovan.com>
*/
class JITPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdapter
{
private $in_db;
/**
* {@inheritdoc}
*/
public function load($uid, $cat)
{
$return = [];
if (!$this->isConnected()) {
return $return;
}
$pconfigs = DBA::select('pconfig', ['v', 'k'], ['cat' => $cat, 'uid' => $uid]);
if (DBA::isResult($pconfigs)) {
while ($pconfig = DBA::fetch($pconfigs)) {
$key = $pconfig['k'];
$value = $this->toConfigValue($pconfig['v']);
// The value was in the db, so don't check it again (unless you have to)
$this->in_db[$uid][$cat][$key] = true;
if (isset($value)) {
$return[$key] = $value;
}
}
} else if ($cat != 'config') {
// Negative caching
$return = null;
}
DBA::close($pconfigs);
return [$cat => $return];
}
/**
* {@inheritdoc}
*
* @param bool $mark if true, mark the selection of the current cat/key pair
*/
public function get($uid, $cat, $key, $mark = true)
{
if (!$this->isConnected()) {
return null;
}
// The value was in the db, so don't check it again (unless you have to)
if ($mark) {
$this->in_db[$uid][$cat][$key] = true;
}
$pconfig = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
if (DBA::isResult($pconfig)) {
$value = $this->toConfigValue($pconfig['v']);
if (isset($value)) {
return $value;
}
}
$this->in_db[$uid][$cat][$key] = false;
return null;
}
/**
* {@inheritdoc}
*/
public function set($uid, $cat, $key, $value)
{
if (!$this->isConnected()) {
return false;
}
// We store our setting values in a string variable.
// So we have to do the conversion here so that the compare below works.
// The exception are array values.
$compare_value = (!is_array($value) ? (string)$value : $value);
$stored_value = $this->get($uid, $cat, $key, false);
if (!isset($this->in_db[$uid])) {
$this->in_db[$uid] = [];
}
if (!isset($this->in_db[$uid][$cat])) {
$this->in_db[$uid][$cat] = [];
}
if (!isset($this->in_db[$uid][$cat][$key])) {
$this->in_db[$uid][$cat][$key] = false;
}
if (isset($stored_value) && ($stored_value === $compare_value) && $this->in_db[$uid][$cat][$key]) {
return true;
}
// manage array value
$dbvalue = (is_array($value) ? serialize($value) : $value);
$result = DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true);
$this->in_db[$uid][$cat][$key] = $result;
return $result;
}
/**
* {@inheritdoc}
*/
public function delete($uid, $cat, $key)
{
if (!$this->isConnected()) {
return false;
}
if (isset($this->in_db[$uid][$cat][$key])) {
unset($this->in_db[$uid][$cat][$key]);
}
return DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
}
/**
* {@inheritdoc}
*/
public function isLoaded($uid, $cat, $key)
{
if (!$this->isConnected()) {
return false;
}
return (isset($this->in_db[$uid][$cat][$key])) && $this->in_db[$uid][$cat][$key];
}
}

View file

@ -0,0 +1,115 @@
<?php
namespace Friendica\Core\Config\Adapter;
use Friendica\Database\DBA;
/**
* Preload Configuration Adapter
*
* Minimizes the number of database queries to retrieve configuration values at the cost of memory.
*
* @author Hypolite Petovan <hypolite@mrpetovan.com>
*/
class PreloadConfigAdapter extends AbstractDbaConfigAdapter implements IConfigAdapter
{
private $config_loaded = false;
/**
* {@inheritdoc}
*/
public function load($cat = 'config')
{
$return = [];
if (!$this->isConnected()) {
return $return;
}
if ($this->config_loaded) {
return $return;
}
$configs = DBA::select('config', ['cat', 'v', 'k']);
while ($config = DBA::fetch($configs)) {
$value = $this->toConfigValue($config['v']);
if (isset($value)) {
$return[$config['cat']][$config['k']] = $value;
}
}
DBA::close($configs);
$this->config_loaded = true;
return $return;
}
/**
* {@inheritdoc}
*/
public function get($cat, $key)
{
if (!$this->isConnected()) {
return null;
}
$config = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]);
if (DBA::isResult($config)) {
$value = $this->toConfigValue($config['v']);
if (isset($value)) {
return $value;
}
}
return null;
}
/**
* {@inheritdoc}
*/
public function set($cat, $key, $value)
{
if (!$this->isConnected()) {
return false;
}
// We store our setting values as strings.
// So we have to do the conversion here so that the compare below works.
// The exception are array values.
$compare_value = !is_array($value) ? (string)$value : $value;
$stored_value = $this->get($cat, $key);
if (isset($stored_value) && $stored_value === $compare_value) {
return true;
}
$dbvalue = $this->toDbValue($value);
return DBA::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $key], true);
}
/**
* {@inheritdoc}
*/
public function delete($cat, $key)
{
if (!$this->isConnected()) {
return false;
}
return DBA::delete('config', ['cat' => $cat, 'k' => $key]);
}
/**
* {@inheritdoc}
*/
public function isLoaded($cat, $key)
{
if (!$this->isConnected()) {
return false;
}
return $this->config_loaded;
}
}

View file

@ -0,0 +1,142 @@
<?php
namespace Friendica\Core\Config\Adapter;
use Friendica\Database\DBA;
/**
* Preload User Configuration Adapter
*
* Minimizes the number of database queries to retrieve configuration values at the cost of memory.
*
* @author Hypolite Petovan <hypolite@mrpetovan.com>
*/
class PreloadPConfigAdapter extends AbstractDbaConfigAdapter implements IPConfigAdapter
{
/**
* @var array true if config for user is loaded
*/
private $config_loaded;
/**
* @param int $uid The UID of the current user
*/
public function __construct($uid = null)
{
parent::__construct();
$this->config_loaded = [];
if (isset($uid)) {
$this->load($uid, 'config');
}
}
/**
* {@inheritdoc}
*/
public function load($uid, $cat)
{
$return = [];
if (empty($uid)) {
return $return;
}
if (!$this->isLoaded($uid, $cat, null)) {
return $return;
}
$pconfigs = DBA::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]);
while ($pconfig = DBA::fetch($pconfigs)) {
$value = $this->toConfigValue($pconfig['v']);
if (isset($value)) {
$return[$pconfig['cat']][$pconfig['k']] = $value;
}
}
DBA::close($pconfigs);
$this->config_loaded[$uid] = true;
return $return;
}
/**
* {@inheritdoc}
*/
public function get($uid, $cat, $key)
{
if (!$this->isConnected()) {
return null;
}
if (!$this->isLoaded($uid, $cat, $key)) {
$this->load($uid, $cat);
}
$config = DBA::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
if (DBA::isResult($config)) {
$value = $this->toConfigValue($config['v']);
if (isset($value)) {
return $value;
}
}
return null;
}
/**
* {@inheritdoc}
*/
public function set($uid, $cat, $key, $value)
{
if (!$this->isConnected()) {
return false;
}
if (!$this->isLoaded($uid, $cat, $key)) {
$this->load($uid, $cat);
}
// We store our setting values as strings.
// So we have to do the conversion here so that the compare below works.
// The exception are array values.
$compare_value = !is_array($value) ? (string)$value : $value;
$stored_value = $this->get($uid, $cat, $key);
if (isset($stored_value) && $stored_value === $compare_value) {
return true;
}
$dbvalue = $this->toDbValue($value);
return DBA::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $key], true);
}
/**
* {@inheritdoc}
*/
public function delete($uid, $cat, $key)
{
if (!$this->isConnected()) {
return false;
}
if (!$this->isLoaded($uid, $cat, $key)) {
$this->load($uid, $cat);
}
return DBA::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $key]);
}
/**
* {@inheritdoc}
*/
public function isLoaded($uid, $cat, $key)
{
if (!$this->isConnected()) {
return false;
}
return isset($this->config_loaded[$uid]) && $this->config_loaded[$uid];
}
}

View file

@ -0,0 +1,191 @@
<?php
namespace Friendica\Core\Config\Cache;
/**
* The Friendica config cache for the application
* Initial, all *.config.php files are loaded into this cache with the
* ConfigCacheLoader ( @see ConfigCacheLoader )
*/
class ConfigCache implements IConfigCache, IPConfigCache
{
/**
* @var array
*/
private $config;
/**
* @param array $config A initial config array
*/
public function __construct(array $config = [])
{
$this->load($config);
}
/**
* {@inheritdoc}
*/
public function load(array $config, $overwrite = false)
{
$categories = array_keys($config);
foreach ($categories as $category) {
if (is_array($config[$category])) {
$keys = array_keys($config[$category]);
foreach ($keys as $key) {
$value = $config[$category][$key];
if (isset($value)) {
if ($overwrite) {
$this->set($category, $key, $value);
} else {
$this->setDefault($category, $key, $value);
}
}
}
}
}
}
/**
* {@inheritdoc}
*/
public function get($cat, $key = null)
{
if (isset($this->config[$cat][$key])) {
return $this->config[$cat][$key];
} elseif (!isset($key) && isset($this->config[$cat])) {
return $this->config[$cat];
} else {
return null;
}
}
/**
* Sets a default value in the config cache. Ignores already existing keys.
*
* @param string $cat Config category
* @param string $k Config key
* @param mixed $v Default value to set
*/
private function setDefault($cat, $k, $v)
{
if (!isset($this->config[$cat][$k])) {
$this->set($cat, $k, $v);
}
}
/**
* {@inheritdoc}
*/
public function set($cat, $key, $value)
{
if (!isset($this->config[$cat])) {
$this->config[$cat] = [];
}
$this->config[$cat][$key] = $value;
return true;
}
/**
* {@inheritdoc}
*/
public function delete($cat, $key)
{
if (isset($this->config[$cat][$key])) {
unset($this->config[$cat][$key]);
if (count($this->config[$cat]) == 0) {
unset($this->config[$cat]);
}
return true;
} else {
return false;
}
}
/**
* {@inheritdoc}
*/
public function loadP($uid, array $config)
{
$categories = array_keys($config);
foreach ($categories as $category) {
if (isset($config[$category]) && is_array($config[$category])) {
$keys = array_keys($config[$category]);
foreach ($keys as $key) {
$value = $config[$category][$key];
if (isset($value)) {
$this->setP($uid, $category, $key, $value);
}
}
}
}
}
/**
* {@inheritdoc}
*/
public function getP($uid, $cat, $key = null)
{
if (isset($this->config[$uid][$cat][$key])) {
return $this->config[$uid][$cat][$key];
} elseif (!isset($key) && isset($this->config[$uid][$cat])) {
return $this->config[$uid][$cat];
} else {
return null;
}
}
/**
* {@inheritdoc}
*/
public function setP($uid, $cat, $key, $value)
{
if (!isset($this->config[$uid]) || !is_array($this->config[$uid])) {
$this->config[$uid] = [];
}
if (!isset($this->config[$uid][$cat])) {
$this->config[$uid][$cat] = [];
}
$this->config[$uid][$cat][$key] = $value;
return true;
}
/**
* {@inheritdoc}
*/
public function deleteP($uid, $cat, $key)
{
if (isset($this->config[$uid][$cat][$key])) {
unset($this->config[$uid][$cat][$key]);
if (count($this->config[$uid][$cat]) == 0) {
unset($this->config[$uid][$cat]);
if (count($this->config[$uid]) == 0) {
unset($this->config[$uid]);
}
}
return true;
} else {
return false;
}
}
/**
* Returns the whole configuration
*
* @return array The configuration
*/
public function getAll()
{
return $this->config;
}
}

View file

@ -0,0 +1,214 @@
<?php
namespace Friendica\Core\Config\Cache;
use Friendica\Core\Addon;
/**
* The ConfigCacheLoader loads config-files and stores them in a ConfigCache ( @see ConfigCache )
*
* It is capable of loading the following config files:
* - *.config.php (current)
* - *.ini.php (deprecated)
* - *.htconfig.php (deprecated)
*/
class ConfigCacheLoader
{
/**
* The Sub directory of the config-files
* @var string
*/
const SUBDIRECTORY = 'config';
private $baseDir;
private $configDir;
public function __construct($baseDir)
{
$this->baseDir = $baseDir;
$this->configDir = $baseDir . DIRECTORY_SEPARATOR . self::SUBDIRECTORY;
}
/**
* Load the configuration files
*
* First loads the default value for all the configuration keys, then the legacy configuration files, then the
* expected local.config.php
*/
public function loadConfigFiles(ConfigCache $config)
{
$config->load($this->loadCoreConfig('defaults'));
$config->load($this->loadCoreConfig('settings'));
$config->load($this->loadLegacyConfig('htpreconfig'), true);
$config->load($this->loadLegacyConfig('htconfig'), true);
$config->load($this->loadCoreConfig('local'), true);
}
/**
* Tries to load the specified core-configuration and returns the config array.
*
* @param string $name The name of the configuration
*
* @return array The config array (empty if no config found)
*
* @throws \Exception if the configuration file isn't readable
*/
public function loadCoreConfig($name)
{
if (file_exists($this->configDir . DIRECTORY_SEPARATOR . $name . '.config.php')) {
return $this->loadConfigFile($this->configDir . DIRECTORY_SEPARATOR . $name . '.config.php');
} elseif (file_exists($this->configDir . DIRECTORY_SEPARATOR . $name . '.ini.php')) {
return $this->loadINIConfigFile($this->configDir . DIRECTORY_SEPARATOR . $name . '.ini.php');
} else {
return [];
}
}
/**
* Tries to load the specified addon-configuration and returns the config array.
*
* @param string $name The name of the configuration
*
* @return array The config array (empty if no config found)
*
* @throws \Exception if the configuration file isn't readable
*/
public function loadAddonConfig($name)
{
$filepath = $this->baseDir . DIRECTORY_SEPARATOR . // /var/www/html/
Addon::DIRECTORY . DIRECTORY_SEPARATOR . // addon/
$name . DIRECTORY_SEPARATOR . // openstreetmap/
self::SUBDIRECTORY . DIRECTORY_SEPARATOR . // config/
$name . ".config.php"; // openstreetmap.config.php
if (file_exists($filepath)) {
return $this->loadConfigFile($filepath);
} else {
return [];
}
}
/**
* Tries to load the legacy config files (.htconfig.php, .htpreconfig.php) and returns the config array.
*
* @param string $name The name of the config file
*
* @return array The configuration array (empty if no config found)
*
* @deprecated since version 2018.09
*/
private function loadLegacyConfig($name)
{
$filePath = $this->baseDir . DIRECTORY_SEPARATOR . '.' . $name . '.php';
$config = [];
if (file_exists($filePath)) {
$a = new \stdClass();
$a->config = [];
include $filePath;
$htConfigCategories = array_keys($a->config);
// map the legacy configuration structure to the current structure
foreach ($htConfigCategories as $htConfigCategory) {
if (is_array($a->config[$htConfigCategory])) {
$keys = array_keys($a->config[$htConfigCategory]);
foreach ($keys as $key) {
$config[$htConfigCategory][$key] = $a->config[$htConfigCategory][$key];
}
} else {
$config['config'][$htConfigCategory] = $a->config[$htConfigCategory];
}
}
unset($a);
if (isset($db_host)) {
$config['database']['hostname'] = $db_host;
unset($db_host);
}
if (isset($db_user)) {
$config['database']['username'] = $db_user;
unset($db_user);
}
if (isset($db_pass)) {
$config['database']['password'] = $db_pass;
unset($db_pass);
}
if (isset($db_data)) {
$config['database']['database'] = $db_data;
unset($db_data);
}
if (isset($config['system']['db_charset'])) {
$config['database']['charset'] = $config['system']['db_charset'];
}
if (isset($pidfile)) {
$config['system']['pidfile'] = $pidfile;
unset($pidfile);
}
if (isset($default_timezone)) {
$config['system']['default_timezone'] = $default_timezone;
unset($default_timezone);
}
if (isset($lang)) {
$config['system']['language'] = $lang;
unset($lang);
}
}
return $config;
}
/**
* Tries to load the specified legacy configuration file and returns the config array.
*
* @deprecated since version 2018.12
* @param string $filepath
*
* @return array The configuration array
* @throws \Exception
*/
private function loadINIConfigFile($filepath)
{
$contents = include($filepath);
$config = parse_ini_string($contents, true, INI_SCANNER_TYPED);
if ($config === false) {
throw new \Exception('Error parsing INI config file ' . $filepath);
}
return $config;
}
/**
* Tries to load the specified configuration file and returns the config array.
*
* The config format is PHP array and the template for configuration files is the following:
*
* <?php return [
* 'section' => [
* 'key' => 'value',
* ],
* ];
*
* @param string $filepath The filepath of the
* @return array The config array0
*
* @throws \Exception if the config cannot get loaded.
*/
private function loadConfigFile($filepath)
{
$config = include($filepath);
if (!is_array($config)) {
throw new \Exception('Error loading config file ' . $filepath);
}
return $config;
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace Friendica\Core\Config\Cache;
/**
* The interface for a system-wide ConfigCache
*/
interface IConfigCache
{
/**
* Tries to load the specified configuration array into the config array.
* Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config.
*
* @param array $config
* @param bool $overwrite Force value overwrite if the config key already exists
*/
function load(array $config, $overwrite = false);
/**
* Gets a value from the config cache.
*
* @param string $cat Config category
* @param string $key Config key
*
* @return null|mixed Returns the value of the Config entry or null if not set
*/
function get($cat, $key = null);
/**
* Sets a value in the config cache. Accepts raw output from the config table
*
* @param string $cat Config category
* @param string $key Config key
* @param mixed $value Value to set
*
* @return bool True, if the value is set
*/
function set($cat, $key, $value);
/**
* Deletes a value from the config cache.
*
* @param string $cat Config category
* @param string $key Config key
*
* @return bool true, if deleted
*/
function delete($cat, $key);
/**
* Returns the whole configuration cache
*
* @return array
*/
function getAll();
}

View file

@ -0,0 +1,59 @@
<?php
namespace Friendica\Core\Config\Cache;
/**
* The interface for a user-specific config cache
*/
interface IPConfigCache
{
/**
* Tries to load the specified configuration array into the user specific config array.
* Doesn't overwrite previously set values by default to prevent default config files to supersede DB Config.
*
* @param int $uid
* @param array $config
*/
function loadP($uid, array $config);
/**
* Retrieves a value from the user config cache
*
* @param int $uid User Id
* @param string $cat Config category
* @param string $key Config key
*
* @return null|string The value of the config entry or null if not set
*/
function getP($uid, $cat, $key = null);
/**
* Sets a value in the user config cache
*
* Accepts raw output from the pconfig table
*
* @param int $uid User Id
* @param string $cat Config category
* @param string $key Config key
* @param mixed $value Value to set
*/
function setP($uid, $cat, $key, $value);
/**
* Deletes a value from the user config cache
*
* @param int $uid User Id
* @param string $cat Config category
* @param string $key Config key
*
* @return bool true, if deleted
*/
function deleteP($uid, $cat, $key);
/**
* Returns the whole configuration cache
*
* @return array
*/
function getAll();
}

View file

@ -0,0 +1,152 @@
<?php
namespace Friendica\Core\Config;
/**
* This class is responsible for all system-wide configuration values in Friendica
* There are two types of storage
* - The Config-Files (loaded into the FileCache @see Cache\IConfigCache )
* - The Config-DB-Table (per Config-DB-adapter @see Adapter\IConfigAdapter )
*/
class Configuration
{
/**
* @var Cache\IConfigCache
*/
private $configCache;
/**
* @var Adapter\IConfigAdapter
*/
private $configAdapter;
/**
* @param Cache\IConfigCache $configCache The configuration cache (based on the config-files)
* @param Adapter\IConfigAdapter $configAdapter The configuration DB-backend
*/
public function __construct(Cache\IConfigCache $configCache, Adapter\IConfigAdapter $configAdapter)
{
$this->configCache = $configCache;
$this->configAdapter = $configAdapter;
$this->load();
}
/**
* Returns the Config Cache
*
* @return Cache\IConfigCache
*/
public function getCache()
{
return $this->configCache;
}
/**
* @brief Loads all configuration values of family into a cached storage.
*
* All configuration values of the system are stored in the cache ( @see IConfigCache )
*
* @param string $cat The category of the configuration value
*
* @return void
*/
public function load($cat = 'config')
{
// If not connected, do nothing
if (!$this->configAdapter->isConnected()) {
return;
}
// load the whole category out of the DB into the cache
$this->configCache->load($this->configAdapter->load($cat), true);
}
/**
* @brief Get a particular user's config variable given the category name
* ($cat) and a $key.
*
* Get a particular config value from the given category ($cat)
* and the $key from a cached storage either from the $this->configAdapter
* (@see IConfigAdapter ) or from the $this->configCache (@see IConfigCache ).
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to query
* @param mixed $default_value optional, The value to return if key is not set (default: null)
* @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false)
*
* @return mixed Stored value or null if it does not exist
*/
public function get($cat, $key, $default_value = null, $refresh = false)
{
// if the value isn't loaded or refresh is needed, load it to the cache
if ($this->configAdapter->isConnected() &&
(!$this->configAdapter->isLoaded($cat, $key) ||
$refresh)) {
$dbvalue = $this->configAdapter->get($cat, $key);
if (isset($dbvalue)) {
$this->configCache->set($cat, $key, $dbvalue);
return $dbvalue;
}
}
// use the config cache for return
$result = $this->configCache->get($cat, $key);
return (isset($result)) ? $result : $default_value;
}
/**
* @brief Sets a configuration value for system config
*
* Stores a config value ($value) in the category ($cat) under the key ($key)
*
* Note: Please do not store booleans - convert to 0/1 integer values!
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to set
* @param mixed $value The value to store
*
* @return bool Operation success
*/
public function set($cat, $key, $value)
{
// set the cache first
$cached = $this->configCache->set($cat, $key, $value);
// If there is no connected adapter, we're finished
if (!$this->configAdapter->isConnected()) {
return $cached;
}
$stored = $this->configAdapter->set($cat, $key, $value);
return $cached && $stored;
}
/**
* @brief Deletes the given key from the system configuration.
*
* Removes the configured value from the stored cache in $this->configCache
* (@see ConfigCache ) and removes it from the database (@see IConfigAdapter ).
*
* @param string $cat The category of the configuration value
* @param string $key The configuration key to delete
*
* @return bool
*/
public function delete($cat, $key)
{
$cacheRemoved = $this->configCache->delete($cat, $key);
if (!$this->configAdapter->isConnected()) {
return $cacheRemoved;
}
$storeRemoved = $this->configAdapter->delete($cat, $key);
return $cacheRemoved || $storeRemoved;
}
}

View file

@ -1,72 +0,0 @@
<?php
namespace Friendica\Core\Config;
/**
*
* @author Hypolite Petovan <hypolite@mrpetovan.com>
*/
interface IConfigAdapter
{
/**
* @brief Loads all configuration values into a cached storage.
*
* All configuration values of the system are stored in global cache
* which is available under the global variable $a->config
*
* @param string $cat The category of the configuration values to load
*
* @return void
*/
public function load($cat = "config");
/**
* @brief Get a particular user's config variable given the category name
* ($family) and a key.
*
* Get a particular config value from the given category ($family)
* and the $key from a cached storage in $a->config[$uid].
* $instore is only used by the set_config function
* to determine if the key already exists in the DB
* If a key is found in the DB but doesn't exist in
* local config cache, pull it into the cache so we don't have
* to hit the DB again for this item.
*
* @param string $cat The category of the configuration value
* @param string $k The configuration key to query
* @param mixed $default_value optional, The value to return if key is not set (default: null)
* @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false)
*
* @return mixed Stored value or null if it does not exist
*/
public function get($cat, $k, $default_value = null, $refresh = false);
/**
* @brief Sets a configuration value for system config
*
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the user_id $uid.
*
* Note: Please do not store booleans - convert to 0/1 integer values!
*
* @param string $family The category of the configuration value
* @param string $key The configuration key to set
* @param mixed $value The value to store
*
* @return bool Operation success
*/
public function set($cat, $k, $value);
/**
* @brief Deletes the given key from the system configuration.
*
* Removes the configured value from the stored cache in $a->config
* and removes it from the database.
*
* @param string $cat The category of the configuration value
* @param string $k The configuration key to delete
*
* @return mixed
*/
public function delete($cat, $k);
}

View file

@ -1,77 +0,0 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace Friendica\Core\Config;
/**
*
* @author benlo
*/
interface IPConfigAdapter
{
/**
* @brief Loads all configuration values of a user's config family into a cached storage.
*
* All configuration values of the given user are stored in global cache
* which is available under the global variable $a->config[$uid].
*
* @param string $uid The user_id
* @param string $cat The category of the configuration value
*
* @return void
*/
public function load($uid, $cat);
/**
* @brief Get a particular user's config variable given the category name
* ($family) and a key.
*
* Get a particular user's config value from the given category ($family)
* and the $key from a cached storage in $a->config[$uid].
*
* @param string $uid The user_id
* @param string $cat The category of the configuration value
* @param string $k The configuration key to query
* @param mixed $default_value optional, The value to return if key is not set (default: null)
* @param boolean $refresh optional, If true the config is loaded from the db and not from the cache (default: false)
*
* @return mixed Stored value or null if it does not exist
*/
public function get($uid, $cat, $k, $default_value = null, $refresh = false);
/**
* @brief Sets a configuration value for a user
*
* Stores a config value ($value) in the category ($family) under the key ($key)
* for the user_id $uid.
*
* @note Please do not store booleans - convert to 0/1 integer values!
*
* @param string $uid The user_id
* @param string $cat The category of the configuration value
* @param string $k The configuration key to set
* @param string $value The value to store
*
* @return bool Operation success
*/
public function set($uid, $cat, $k, $value);
/**
* @brief Deletes the given key from the users's configuration.
*
* Removes the configured value from the stored cache in $a->config[$uid]
* and removes it from the database.
*
* @param string $uid The user_id
* @param string $cat The category of the configuration value
* @param string $k The configuration key to delete
*
* @return mixed
*/
public function delete($uid, $cat, $k);
}

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