Merge remote-tracking branch 'upstream/develop' into update-self
This commit is contained in:
commit
a0451e1c62
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -53,7 +53,8 @@ nbproject
|
|||
venv/
|
||||
|
||||
#ignore Composer dependencies
|
||||
vendor
|
||||
/vendor
|
||||
/view/asset
|
||||
|
||||
#ignore config files from JetBrains
|
||||
/.idea
|
128
CHANGELOG
128
CHANGELOG
|
@ -1,3 +1,129 @@
|
|||
Version 3.6 (2018-03-23)
|
||||
Friendica Core:
|
||||
Updates to the translations (DE, EN_GB, EN_US, ES, FR, IT, ZH_CN) [translation teams]
|
||||
Updates for the Danish and French regions [Alkarex]
|
||||
Update for the documentation [andyhee, annando, rabuzarus, ratten, rudlof, silke, tobiasd]
|
||||
Updates to the themes [Andi-K, annando, fabrixxm, hoergen, rebeka-catalina, rabuzarus]
|
||||
Enhancements to the ARIA support in frio [rabuzarus]
|
||||
Enhancements to the DB handling and structure [annando]
|
||||
Enhancements to the API [annando, fabrixxm, MrPetovan, rudlof]
|
||||
Enhancements to the support of Open Graph with images [hoergen]
|
||||
Enhancements to the Diaspora federation (participation signal, relay of dislikes, basic forum support for D*, Birthdays) [annando]
|
||||
Enhancements to the OStatus federation [annando]
|
||||
Enhancements to the handling of feed contacts [MrPetovan]
|
||||
Enhancements to the display of threaded discussions (optional) [MrPetovan]
|
||||
Enhancements to the display of events [hoergen]
|
||||
Enhancements to the ACL dialog (selection of forums) [rabuzarus]
|
||||
Enhancements to the handling of new connections [annando]
|
||||
Enhancements to the vitality check of contacts [annando]
|
||||
Enhancements to the daemon script [annando]
|
||||
Enhancements to the federation stats [annando, tobiasd]
|
||||
Enhancements to the interaction with public posts [annando]
|
||||
Enhancements to the structure of the admin panel [tobiasd]
|
||||
Enhancements to the community page [annando]
|
||||
Enhancements to the delegation of accounts [annando, MrPetovan]
|
||||
Enhancements to the user import and server relocation functionality [annando]
|
||||
Enhancements to the menu layout in the admin panel [tobiasd]
|
||||
Enhancements to the extraction of strings to be translated [fabrixxm, MrPetovan]
|
||||
Enhancements to the installation wizard [annando, tobias]
|
||||
Enhancements to the events [annando, hoergen, MrPetovan, rabuzarus]
|
||||
Enhancements to the handling of email contacts [annando]
|
||||
Enhancements to the Vagrant configuration of the development VM [tobias]
|
||||
Enhancements to the probing of pump.io profiles [annando]
|
||||
Enhancements to the handling of BBCode tags [MrPetovan]
|
||||
Enhancements to the OEmbed handling [MrPetovan]
|
||||
Fixed a bug that triggered the display of activities on the cummunity page [annando]
|
||||
Fixed a bug with personal notes [annando]
|
||||
Fixed a display issue of long postings when using the showmore option [annando]
|
||||
Fixed a bug that caused Twidere to crash on reload [annando]
|
||||
Fixed a bug in the exported data to the-federation.info [annando]
|
||||
Fixed a bug in URL completion for feed fragments [annando]
|
||||
Fixed a bug in the notification system about new registrations [annando]
|
||||
Fixed the display of dislikes [annando]
|
||||
Fixed the display of orphans childs in threads [MrPetovan]
|
||||
Fixed some SQL problems [annando]
|
||||
Fixed the CLI config script [tobiasd]
|
||||
Fixed the forum selection on the network display [annando]
|
||||
Fixed a bug during the import of accounts [annando]
|
||||
Fixed a problem with UTF8 encoding during account export [annando]
|
||||
Fixed a problem with archiving "self" contacts [annando]
|
||||
Fixes to file permissions lintian reported [tobiasd]
|
||||
Fixed a session problem leading to double login problem [MrPetovan]
|
||||
Fixed a bug that caused code blocks on Diaspora being displayed wrongly [MrPetovan]
|
||||
Fixed a bug that suggested it was possible to use some bridges without an account on the other side [annando]
|
||||
Fixed the situation that an OStatus activity was triggered when publishing a image without sending out a posting for it [annando]
|
||||
Fixed some issues with the display of exported events on GNU social and diaspora [annando]
|
||||
Fixed the issue that Atom feeds of forums had no postings listed [annando]
|
||||
Fixed a problem with the expiration of accounts [annando]
|
||||
Added Atom feed for conversations [annando]
|
||||
Added the possibility to address forums with !forumname [annando]
|
||||
Added option to compare version against upstream version [tobiasd]
|
||||
Added an optional hint that a global community page is global [tobiasd]
|
||||
Added an option to always display the preview image in shared articles even if larger ones exist [annando]
|
||||
Added CLI script to silence accounts on the community page [tobiasd]
|
||||
Added CLI script to block postings to a node from accounts [tobiasd]
|
||||
Added account block interface to the admin panel [MrPetovan]
|
||||
Added browser bookmarklet code snippet [hoergen]
|
||||
Added an additional feature to display a tag cloud on the profile page [rabuzarus]
|
||||
Added retrieval of Mastodon server statistics [annando]
|
||||
Added Atom feed that only contains top level postings of a user [annando]
|
||||
Added tag following via saved search for #hashtag [annando]
|
||||
Added PHP version information to the admin panel [MrPetovan]
|
||||
Added the possibility to change relationships between Friendica contacts [annando]
|
||||
Added the membersince functionality from the addon to the core [rabuzarus]
|
||||
Added support of nodeinfo 2.0 [annando]
|
||||
Removed the long deprecated internal templating engine [annando]
|
||||
Removed the obsolete mysql support, you have to use MySQLI or PDO [annando]
|
||||
Removed the unused mood module [annando]
|
||||
Removed connect link from side panel when it should not be there [annando]
|
||||
Removed very old updating routines [annando]
|
||||
Dependencies are now (mostly) handled by composer [MrPetovan, zeroadam]
|
||||
General code refactoring and beautification work [annando, MrPetovan, tobiasd, zeroadam]
|
||||
ejabberd logs are now handled by syslog [annando]
|
||||
Moved the poller script to the "scripts" directory and renamed it to worker [annando]
|
||||
Threaded display of conversations is now always enabled [annando]
|
||||
Images send to public forums are now always public as well [annando]
|
||||
The DB cleanup option now includes the conversation table [annando]
|
||||
Hash tags now always search locally [annando]
|
||||
Consistent naming of addons (instead of plugins and addons) [zeroadam]
|
||||
Community page is split between local and global and always visible for local users [annando]
|
||||
Updated the credits to include new contributors [tobiasd]
|
||||
|
||||
Friendica Addons:
|
||||
Updates to the translations (DE, EN_GB, ES, FR, IT, NL, ZH_CN) [translation teams]
|
||||
all bridges don't relay postings anymore that are posted to a public forum [annando]
|
||||
DAV addon marked unsupported [tobiasd]
|
||||
Current Weather: fixing a problem with the weathermap link [zeroadam]
|
||||
NSFW added config examples, reworked the description, now ignores the CW from Mastodon [andyhee, annando, rebeka-catalina]
|
||||
Twitter support 280 chars limit [annando]
|
||||
OpenWeatherMap fix broken map link [zeroadam]
|
||||
CommunityHome added settings to admin panel, removed active users feature [annando, fabrixxm]
|
||||
General code refactoring and beautification work [annando, MrPetovan, tobiasd, zeroadam]
|
||||
Public Server reworked [annando]
|
||||
pageheader settings beautifications [tobiasd]
|
||||
mailstream settings beautifications [tobiasd]
|
||||
Membersince is now part of the core [rabuzarus]
|
||||
Forum posts are not transmitted over the connectors anymore [annando]
|
||||
|
||||
Friendica Dir:
|
||||
Fixed a problem with the maintenance cron [MrPetovan]
|
||||
Fixed a problem with the location widget [MrPetovan]
|
||||
Work on the UI [MrPetovan]
|
||||
|
||||
Closed Issues:
|
||||
929, 1050, 1056, 1125, 1215, 1251, 1289, 1312, 1429, 1488, 1540,
|
||||
1610, 1858, 2786, 2845, 3020, 3039, 3337, 3379, 3394, 3396, 3566,
|
||||
3583, 3661, 3671, 3680, 3801, 3822, 3824, 3828, 3839, 3855, 3857,
|
||||
3860, 3863, 3867, 3905, 3911, 3916, 3942, 3946, 3999, 4013, 4020,
|
||||
4023, 4041, 4042, 4061, 4069, 4070, 4071, 4075, 4078, 4082, 4094,
|
||||
4105, 4115, 4116, 4137, 4141, 4144, 4150, 4155, 4161, 4163, 4173,
|
||||
4184, 4199, 4200, 4207, 4227, 4228, 4236, 4251, 4272, 4273, 4278,
|
||||
4279, 4281, 4290, 4294, 4295, 4296, 4304, 4306, 4319, 4348, 4362,
|
||||
4368, 4369, 4377, 4390, 4395, 4396, 4409, 4412, 4426, 4431, 4445,
|
||||
4450, 4452, 4458, 4463, 4481, 4482, 4495, 4497, 4498, 4508, 4518,
|
||||
4520, 4522, 4535, 4543, 4550, 4555, 4556, 4571, 4575, 4610, 4611,
|
||||
4620
|
||||
|
||||
Version 3.5.4 (2017-10-16)
|
||||
Friendica Core:
|
||||
Updates to the translations (DE) [translation teams]
|
||||
|
@ -90,7 +216,7 @@ Version 3.5.2 (2017-06-06)
|
|||
Updates to the translations (DE, EN-GB, EN-US, ES, IT, PT-BR, RU) [translation teams]
|
||||
Updates to the documentation [annando, beardyunixer, rabuzarus, tobiasd]
|
||||
Updated the nginx example configuration [beardyunixer]
|
||||
Code revision and refactoring [annando, hypolite, Quix0r, rebeka-catalina]
|
||||
Code revision and refactoring [annando, MrPetovan, Quix0r, rebeka-catalina]
|
||||
Background process is now done by the new worker process [annando]
|
||||
Added support of Composer for dependencies [Hypolite]
|
||||
Added support of Web app manifests [Rudloff]
|
||||
|
|
10
INSTALL.txt
10
INSTALL.txt
|
@ -68,7 +68,7 @@ OR
|
|||
|
||||
git clone https://github.com/friendica/friendica [web server folder]
|
||||
cd [web server folder]
|
||||
php util/composer.phar install
|
||||
php bin/composer.phar install
|
||||
|
||||
3. Create an empty database and note the access details (hostname, username,
|
||||
password, database name).
|
||||
|
@ -115,14 +115,14 @@ tables, so that you can start fresh.
|
|||
8. Set up a cron job or scheduled task to run the worker once every 5-10
|
||||
minutes to pick up the recent "public" postings of your friends. Example:
|
||||
|
||||
cd /base/directory; /path/to/php scripts/worker.php
|
||||
cd /base/directory; /path/to/php bin/worker.php
|
||||
|
||||
Change "/base/directory", and "/path/to/php" as appropriate for your situation.
|
||||
|
||||
If you are using a Linux server, run "crontab -e" and add a line like the
|
||||
one shown, substituting for your unique paths and settings:
|
||||
|
||||
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php scripts/worker.php
|
||||
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/worker.php
|
||||
|
||||
You can generally find the location of PHP by executing "which php". If you
|
||||
have troubles with this section please contact your hosting provider for
|
||||
|
@ -287,14 +287,14 @@ cron by using something like
|
|||
|
||||
*/10 * * * * cd /var/www/friendica/friendica/ && sudo -u www-data /usr/bin/php
|
||||
-d suhosin.executor.func.blacklist=none -d suhosin.executor.eval.blacklist=none
|
||||
-f scripts/worker.php
|
||||
-f bin/worker.php
|
||||
|
||||
This worked well for simple test cases, but the friendica-cron still failed with
|
||||
a fatal error:
|
||||
suhosin[22962]: ALERT - function within blacklist called: proc_open() (attacker
|
||||
'REMOTE_ADDR not set', file '/var/www/friendica/friendica/boot.php', line 1341)
|
||||
|
||||
After a while I noticed, that scripts/worker.php calls further php script via
|
||||
After a while I noticed, that bin/worker.php calls further php script via
|
||||
proc_open. These scripts themselves also use proc_open and fail, because they
|
||||
are NOT called with -d suhosin.executor.func.blacklist=none.
|
||||
|
||||
|
|
|
@ -27,17 +27,17 @@ The location of the translated files in the source tree is
|
|||
/view/lang/LNG-CODE/
|
||||
where LNG-CODE is the language code used, e.g. de for German or fr for French.
|
||||
The translated strings come as a "message.po" file from transifex which needs to be translated into the PHP file friendica uses.
|
||||
To do so, place the file in the directory mentioned above and use the "po2php" utility from the util directory of your friendica installation.
|
||||
To do so, place the file in the directory mentioned above and use the "po2php" command from the console.
|
||||
|
||||
Assuming you want to convert the German localization which is placed in view/lang/de/message.po you would do the following.
|
||||
|
||||
1. Navigate at the command prompt to the base directory of your
|
||||
friendica installation
|
||||
|
||||
2. Execute the po2php script, which will place the translation
|
||||
2. Execute the po2php command, which will place the translation
|
||||
in the strings.php file that is used by friendica.
|
||||
|
||||
$> php util/po2php.php view/lang/de/messages.po
|
||||
$> php bin/console.php po2php view/lang/de/messages.po
|
||||
|
||||
The output of the script will be placed at view/lang/de/strings.php where
|
||||
friendica is expecting it, so you can test your translation immediately.
|
||||
|
@ -62,7 +62,7 @@ Otherwise your work might get lost, when the translation from Transifex is inclu
|
|||
Utilities
|
||||
---------
|
||||
|
||||
Additional to the po2php script there are some more utilities for translation in the "util" directory of the friendica source tree.
|
||||
Additional to the po2php command there are some more utilities for translation in the console.
|
||||
If you only want to translate friendica into another language you wont need any of these tools most likely but it gives you an idea how the translation process of friendica works.
|
||||
|
||||
For further information see the utils/README file.
|
||||
|
@ -90,9 +90,9 @@ To update the translation files after you have translated strings of e.g. Espera
|
|||
|
||||
$> tx pull -l eo
|
||||
|
||||
And then use the `po2php` utility described above to convert the `messages.po` file to the `strings.php` file Friendica is loading.
|
||||
And then use the `po2php` command described above to convert the `messages.po` file to the `strings.php` file Friendica is loading.
|
||||
|
||||
$> php util/po2php.php view/lang/eo/messages.po
|
||||
$> php bin/console.php po2php view/lang/eo/messages.po
|
||||
|
||||
Afterwards, just commit the two changed files to a feature branch of your Friendica repository, push the changes to github and open a pull request for your changes.
|
||||
|
||||
|
|
2
Vagrantfile
vendored
2
Vagrantfile
vendored
|
@ -17,7 +17,7 @@ Vagrant.configure(2) do |config|
|
|||
# Create a hostname, don't forget to put it to the `hosts` file
|
||||
# This will point to the server's default virtual host
|
||||
# TO DO: Make this work with virtualhost along-side xip.io URL
|
||||
config.vm.hostname = "friendica.dev"
|
||||
config.vm.hostname = "friendica.local"
|
||||
|
||||
# Create a static IP
|
||||
config.vm.network :private_network, ip: server_ip
|
||||
|
|
|
@ -13,14 +13,14 @@
|
|||
* Installation:
|
||||
*
|
||||
* - Change it's owner to whichever user is running the server, ie. ejabberd
|
||||
* $ chown ejabberd:ejabberd /path/to/friendica/scripts/auth_ejabberd.php
|
||||
* $ chown ejabberd:ejabberd /path/to/friendica/bin/auth_ejabberd.php
|
||||
*
|
||||
* - Change the access mode so it is readable only to the user ejabberd and has exec
|
||||
* $ chmod 700 /path/to/friendica/scripts/auth_ejabberd.php
|
||||
* $ chmod 700 /path/to/friendica/bin/auth_ejabberd.php
|
||||
*
|
||||
* - Edit your ejabberd.cfg file, comment out your auth_method and add:
|
||||
* {auth_method, external}.
|
||||
* {extauth_program, "/path/to/friendica/script/auth_ejabberd.php"}.
|
||||
* {extauth_program, "/path/to/friendica/bin/auth_ejabberd.php"}.
|
||||
*
|
||||
* - Restart your ejabberd service, you should be able to login with your friendica auth info
|
||||
*
|
||||
|
@ -33,6 +33,8 @@
|
|||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Util\ExAuth;
|
||||
|
||||
if (sizeof($_SERVER["argv"]) == 0) {
|
||||
|
@ -53,6 +55,7 @@ require_once "boot.php";
|
|||
require_once "include/dba.php";
|
||||
|
||||
$a = new App(dirname(__DIR__));
|
||||
BaseObject::setApp($a);
|
||||
|
||||
@include ".htconfig.php";
|
||||
dba::connect($db_host, $db_user, $db_pass, $db_data);
|
10
bin/console
Executable file
10
bin/console
Executable file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
dir=$(cd "${0%[/\\]*}" > /dev/null; pwd)
|
||||
|
||||
if [[ -d /proc/cygdrive && $(which php) == $(readlink -n /proc/cygdrive)/* ]]; then
|
||||
# We are in Cgywin using Windows php, so the path must be translated
|
||||
dir=$(cygpath -m "$dir");
|
||||
fi
|
||||
|
||||
php "${dir}/console.php" "$@"
|
4
bin/console.bat
Executable file
4
bin/console.bat
Executable file
|
@ -0,0 +1,4 @@
|
|||
@echo OFF
|
||||
:: in case DelayedExpansion is on and a path contains !
|
||||
setlocal DISABLEDELAYEDEXPANSION
|
||||
php "%~dp0console.php" %*
|
9
bin/console.php
Executable file
9
bin/console.php
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
include_once dirname(__DIR__) . '/boot.php';
|
||||
|
||||
$a = new Friendica\App(dirname(__DIR__));
|
||||
\Friendica\BaseObject::setApp($a);
|
||||
|
||||
(new Friendica\Core\Console())->execute();
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* @file scripts/daemon.php
|
||||
* @file bin/daemon.php
|
||||
* @brief Run the worker from a daemon.
|
||||
*
|
||||
* This script was taken from http://php.net/manual/en/function.pcntl-fork.php
|
||||
|
@ -104,7 +104,7 @@ while (true) {
|
|||
set_time_limit(0);
|
||||
|
||||
// Call the worker
|
||||
$cmdline = $php.' scripts/worker.php';
|
||||
$cmdline = $php.' bin/worker.php';
|
||||
|
||||
$executed = false;
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* @file scripts/worker.php
|
||||
* @file bin/worker.php
|
||||
* @brief Starts the background processing
|
||||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\Worker;
|
||||
|
@ -26,6 +27,7 @@ require_once "boot.php";
|
|||
require_once "include/dba.php";
|
||||
|
||||
$a = new App(dirname(__DIR__));
|
||||
BaseObject::setApp($a);
|
||||
|
||||
require_once ".htconfig.php";
|
||||
dba::connect($db_host, $db_user, $db_pass, $db_data);
|
29
boot.php
29
boot.php
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* @file_tag_unsave_file boot.php
|
||||
* @file boot.php
|
||||
* This file defines some global constants and includes the central App class.
|
||||
*/
|
||||
|
||||
|
@ -20,7 +20,9 @@
|
|||
require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php';
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Cache;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\PConfig;
|
||||
|
@ -36,10 +38,10 @@ use Friendica\Util\DateTimeFormat;
|
|||
require_once 'include/text.php';
|
||||
|
||||
define('FRIENDICA_PLATFORM', 'Friendica');
|
||||
define('FRIENDICA_CODENAME', 'Asparagus');
|
||||
define('FRIENDICA_VERSION', '3.6-rc');
|
||||
define('FRIENDICA_CODENAME', 'The Tazmans Flax-lily');
|
||||
define('FRIENDICA_VERSION', '2018-05-dev');
|
||||
define('DFRN_PROTOCOL_VERSION', '2.23');
|
||||
define('DB_UPDATE_VERSION', 1256);
|
||||
define('DB_UPDATE_VERSION', 1258);
|
||||
define('NEW_UPDATE_ROUTINE_VERSION', 1170);
|
||||
|
||||
/**
|
||||
|
@ -121,18 +123,20 @@ define('LOGGER_ALL', 4);
|
|||
|
||||
/**
|
||||
* @name Cache
|
||||
* @deprecated since version 3.6
|
||||
* @see Cache
|
||||
*
|
||||
* Cache levels
|
||||
* @{
|
||||
*/
|
||||
define('CACHE_MONTH', 0);
|
||||
define('CACHE_WEEK', 1);
|
||||
define('CACHE_DAY', 2);
|
||||
define('CACHE_HOUR', 3);
|
||||
define('CACHE_HALF_HOUR', 4);
|
||||
define('CACHE_QUARTER_HOUR', 5);
|
||||
define('CACHE_FIVE_MINUTES', 6);
|
||||
define('CACHE_MINUTE', 7);
|
||||
define('CACHE_MONTH', Cache::MONTH);
|
||||
define('CACHE_WEEK', Cache::WEEK);
|
||||
define('CACHE_DAY', Cache::DAY);
|
||||
define('CACHE_HOUR', Cache::HOUR);
|
||||
define('CACHE_HALF_HOUR', Cache::HALF_HOUR);
|
||||
define('CACHE_QUARTER_HOUR', Cache::QUARTER_HOUR);
|
||||
define('CACHE_FIVE_MINUTES', Cache::FIVE_MINUTES);
|
||||
define('CACHE_MINUTE', Cache::MINUTE);
|
||||
/* @}*/
|
||||
|
||||
/**
|
||||
|
@ -533,6 +537,7 @@ function get_app()
|
|||
|
||||
if (empty($a)) {
|
||||
$a = new App(dirname(__DIR__));
|
||||
BaseObject::setApp($a);
|
||||
}
|
||||
|
||||
return $a;
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
"require": {
|
||||
"php": ">5.6",
|
||||
"ext-xml": "*",
|
||||
"asika/simple-console": "^1.0",
|
||||
"divineomega/password_exposed": "^2.4",
|
||||
"ezyang/htmlpurifier": "~4.7.0",
|
||||
"league/html-to-markdown": "~4.4.1",
|
||||
"lightopenid/lightopenid": "dev-master",
|
||||
|
@ -54,8 +56,8 @@
|
|||
"preferred-install": "dist",
|
||||
"fxp-asset": {
|
||||
"installer-paths": {
|
||||
"npm-asset-library": "vendor/asset",
|
||||
"bower-asset-library": "vendor/asset"
|
||||
"npm-asset-library": "view/asset",
|
||||
"bower-asset-library": "view/asset"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
653
composer.lock
generated
653
composer.lock
generated
|
@ -4,8 +4,41 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "3ff4187b4f7167583a3b8caa5f7c2a8a",
|
||||
"content-hash": "0811acc361f70e08cce3ec09940cbf2d",
|
||||
"packages": [
|
||||
{
|
||||
"name": "asika/simple-console",
|
||||
"version": "1.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/asika32764/php-simple-console.git",
|
||||
"reference": "0b624c1a999849dc6481a47182e58d593bf65068"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/asika32764/php-simple-console/zipball/0b624c1a999849dc6481a47182e58d593bf65068",
|
||||
"reference": "0b624c1a999849dc6481a47182e58d593bf65068",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Asika\\SimpleConsole\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Simon Asika",
|
||||
"email": "asika32764@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "One file console framework to help you write build scripts.",
|
||||
"time": "2018-03-08T12:05:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "bower-asset/Chart-js",
|
||||
"version": "v2.7.1",
|
||||
|
@ -100,6 +133,54 @@
|
|||
"description": "Minimalistic but perfect custom scrollbar plugin",
|
||||
"time": "2017-01-10T01:04:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "divineomega/password_exposed",
|
||||
"version": "v2.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DivineOmega/password_exposed.git",
|
||||
"reference": "7e26898a280662529b3e5e472b16fcbda167ffce"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/DivineOmega/password_exposed/zipball/7e26898a280662529b3e5e472b16fcbda167ffce",
|
||||
"reference": "7e26898a280662529b3e5e472b16fcbda167ffce",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "^6.3",
|
||||
"paragonie/certainty": "^1",
|
||||
"php": ">=5.6",
|
||||
"rapidwebltd/rw-file-cache-psr-6": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"fzaninotto/faker": "^1.7",
|
||||
"phpunit/phpunit": "^5.7",
|
||||
"satooshi/php-coveralls": "^2.0",
|
||||
"vimeo/psalm": "^1"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"DivineOmega\\PasswordExposed\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/PasswordExposedFunction.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jordan Hall",
|
||||
"email": "jordan@hall05.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "This PHP package provides a `password_exposed` helper function, that uses the haveibeenpwned.com API to check if a password has been exposed in a data breach.",
|
||||
"time": "2018-03-14T09:17:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "ezyang/htmlpurifier",
|
||||
"version": "v4.7.0",
|
||||
|
@ -203,6 +284,187 @@
|
|||
],
|
||||
"time": "2017-10-20T06:53:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "6.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/guzzle.git",
|
||||
"reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699",
|
||||
"reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/promises": "^1.0",
|
||||
"guzzlehttp/psr7": "^1.4",
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-curl": "*",
|
||||
"phpunit/phpunit": "^4.0 || ^5.0",
|
||||
"psr/log": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"psr/log": "Required for using the Log middleware"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "6.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle is a PHP HTTP client library",
|
||||
"homepage": "http://guzzlephp.org/",
|
||||
"keywords": [
|
||||
"client",
|
||||
"curl",
|
||||
"framework",
|
||||
"http",
|
||||
"http client",
|
||||
"rest",
|
||||
"web service"
|
||||
],
|
||||
"time": "2017-06-22T18:50:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/promises",
|
||||
"version": "v1.3.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/promises.git",
|
||||
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
|
||||
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Promise\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
}
|
||||
],
|
||||
"description": "Guzzle promises library",
|
||||
"keywords": [
|
||||
"promise"
|
||||
],
|
||||
"time": "2016-12-20T10:07:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/psr7",
|
||||
"version": "1.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/guzzle/psr7.git",
|
||||
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
|
||||
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"psr/http-message": "~1.0"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-message-implementation": "1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"GuzzleHttp\\Psr7\\": "src/"
|
||||
},
|
||||
"files": [
|
||||
"src/functions_include.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Dowling",
|
||||
"email": "mtdowling@gmail.com",
|
||||
"homepage": "https://github.com/mtdowling"
|
||||
},
|
||||
{
|
||||
"name": "Tobias Schultze",
|
||||
"homepage": "https://github.com/Tobion"
|
||||
}
|
||||
],
|
||||
"description": "PSR-7 message implementation that also provides common utility methods",
|
||||
"keywords": [
|
||||
"http",
|
||||
"message",
|
||||
"request",
|
||||
"response",
|
||||
"stream",
|
||||
"uri",
|
||||
"url"
|
||||
],
|
||||
"time": "2017-03-20T17:10:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/html-to-markdown",
|
||||
"version": "4.4.1",
|
||||
|
@ -937,6 +1199,129 @@
|
|||
"homepage": "https://github.com/kartik-v/php-date-formatter",
|
||||
"time": "2016-02-18T15:15:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/certainty",
|
||||
"version": "v1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/certainty.git",
|
||||
"reference": "a2d14f5b0b85c58329dee248d77d34e7e1202a32"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/certainty/zipball/a2d14f5b0b85c58329dee248d77d34e7e1202a32",
|
||||
"reference": "a2d14f5b0b85c58329dee248d77d34e7e1202a32",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"guzzlehttp/guzzle": "^6",
|
||||
"paragonie/constant_time_encoding": "^1|^2",
|
||||
"paragonie/sodium_compat": "^1.6",
|
||||
"php": "^5.6|^7"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5|^6",
|
||||
"vimeo/psalm": "^1"
|
||||
},
|
||||
"bin": [
|
||||
"bin/certainty-cert-symlink"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ParagonIE\\Certainty\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"ISC"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
"email": "security@paragonie.com",
|
||||
"homepage": "https://paragonie.com"
|
||||
}
|
||||
],
|
||||
"description": "Up-to-date, verifiable repository for Certificate Authorities",
|
||||
"keywords": [
|
||||
"CA-Cert",
|
||||
"Ed25519",
|
||||
"Public-Key Infractructure",
|
||||
"ca",
|
||||
"ca-cert.pem",
|
||||
"cacert",
|
||||
"cacert.pem",
|
||||
"certificate authority",
|
||||
"pki",
|
||||
"ssl",
|
||||
"tls"
|
||||
],
|
||||
"time": "2018-03-12T18:34:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/constant_time_encoding",
|
||||
"version": "v1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/constant_time_encoding.git",
|
||||
"reference": "6111a38faf6fdebc14e36652d22036f379ba58d3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/6111a38faf6fdebc14e36652d22036f379ba58d3",
|
||||
"reference": "6111a38faf6fdebc14e36652d22036f379ba58d3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.3|^7"
|
||||
},
|
||||
"require-dev": {
|
||||
"paragonie/random_compat": "^1|^2",
|
||||
"phpunit/phpunit": "4.*|5.*",
|
||||
"vimeo/psalm": "^1"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ParagonIE\\ConstantTime\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
"email": "security@paragonie.com",
|
||||
"homepage": "https://paragonie.com",
|
||||
"role": "Maintainer"
|
||||
},
|
||||
{
|
||||
"name": "Steve 'Sc00bz' Thomas",
|
||||
"email": "steve@tobtu.com",
|
||||
"homepage": "https://www.tobtu.com",
|
||||
"role": "Original Developer"
|
||||
}
|
||||
],
|
||||
"description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
|
||||
"keywords": [
|
||||
"base16",
|
||||
"base32",
|
||||
"base32_decode",
|
||||
"base32_encode",
|
||||
"base64",
|
||||
"base64_decode",
|
||||
"base64_encode",
|
||||
"bin2hex",
|
||||
"encoding",
|
||||
"hex",
|
||||
"hex2bin",
|
||||
"rfc4648"
|
||||
],
|
||||
"time": "2018-03-10T19:46:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/random_compat",
|
||||
"version": "v2.0.11",
|
||||
|
@ -985,6 +1370,88 @@
|
|||
],
|
||||
"time": "2017-09-27T21:40:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "paragonie/sodium_compat",
|
||||
"version": "v1.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/paragonie/sodium_compat.git",
|
||||
"reference": "1f6e5682eff4a5a6a394b14331a1904f1740e432"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/1f6e5682eff4a5a6a394b14331a1904f1740e432",
|
||||
"reference": "1f6e5682eff4a5a6a394b14331a1904f1740e432",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"paragonie/random_compat": "^1|^2",
|
||||
"php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^3|^4|^5"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.",
|
||||
"ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security."
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"autoload.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"ISC"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paragon Initiative Enterprises",
|
||||
"email": "security@paragonie.com"
|
||||
},
|
||||
{
|
||||
"name": "Frank Denis",
|
||||
"email": "jedisct1@pureftpd.org"
|
||||
}
|
||||
],
|
||||
"description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists",
|
||||
"keywords": [
|
||||
"Authentication",
|
||||
"BLAKE2b",
|
||||
"ChaCha20",
|
||||
"ChaCha20-Poly1305",
|
||||
"Chapoly",
|
||||
"Curve25519",
|
||||
"Ed25519",
|
||||
"EdDSA",
|
||||
"Edwards-curve Digital Signature Algorithm",
|
||||
"Elliptic Curve Diffie-Hellman",
|
||||
"Poly1305",
|
||||
"Pure-PHP cryptography",
|
||||
"RFC 7748",
|
||||
"RFC 8032",
|
||||
"Salpoly",
|
||||
"Salsa20",
|
||||
"X25519",
|
||||
"XChaCha20-Poly1305",
|
||||
"XSalsa20-Poly1305",
|
||||
"Xchacha20",
|
||||
"Xsalsa20",
|
||||
"aead",
|
||||
"cryptography",
|
||||
"ecdh",
|
||||
"elliptic curve",
|
||||
"elliptic curve cryptography",
|
||||
"encryption",
|
||||
"libsodium",
|
||||
"php",
|
||||
"public-key cryptography",
|
||||
"secret-key cryptography",
|
||||
"side-channel resistant"
|
||||
],
|
||||
"time": "2018-02-15T05:50:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "pear/console_getopt",
|
||||
"version": "v1.4.1",
|
||||
|
@ -1227,6 +1694,190 @@
|
|||
"homepage": "http://pear.php.net/package/Text_LanguageDetect",
|
||||
"time": "2017-03-02T16:14:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/cache.git",
|
||||
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
|
||||
"reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Cache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for caching libraries",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"psr",
|
||||
"psr-6"
|
||||
],
|
||||
"time": "2016-08-06T20:24:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"time": "2016-08-06T14:39:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rapidwebltd/rw-file-cache",
|
||||
"version": "v1.2.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/rapidwebltd/RW-File-Cache.git",
|
||||
"reference": "4a1d5aaefa6ffafec8e2d60787f12bcd9890977e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/rapidwebltd/RW-File-Cache/zipball/4a1d5aaefa6ffafec8e2d60787f12bcd9890977e",
|
||||
"reference": "4a1d5aaefa6ffafec8e2d60787f12bcd9890977e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"rapidweb\\RWFileCache\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0-only"
|
||||
],
|
||||
"description": "RW File Cache is a PHP File-based Caching Library. Its syntax is designed to closely resemble the PHP memcache extension.",
|
||||
"homepage": "https://github.com/rapidwebltd/RW-File-Cache",
|
||||
"keywords": [
|
||||
"cache",
|
||||
"caching",
|
||||
"caching library",
|
||||
"file cache",
|
||||
"library",
|
||||
"php"
|
||||
],
|
||||
"time": "2018-01-23T17:20:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rapidwebltd/rw-file-cache-psr-6",
|
||||
"version": "v1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/rapidwebltd/RW-File-Cache-PSR-6.git",
|
||||
"reference": "b74ea201d4c964f0e6db0fb036d1ab28a570df66"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/rapidwebltd/RW-File-Cache-PSR-6/zipball/b74ea201d4c964f0e6db0fb036d1ab28a570df66",
|
||||
"reference": "b74ea201d4c964f0e6db0fb036d1ab28a570df66",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"psr/cache": "^1.0",
|
||||
"rapidwebltd/rw-file-cache": "^1.2.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"cache/integration-tests": "^0.16.0",
|
||||
"phpunit/phpunit": "^5.7"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"rapidweb\\RWFileCachePSR6\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jordan Hall",
|
||||
"email": "jordan.hall@rapidweb.biz"
|
||||
}
|
||||
],
|
||||
"description": "PSR-6 adapter for RW File Cache",
|
||||
"time": "2018-01-30T19:13:45+00:00"
|
||||
},
|
||||
{
|
||||
"name": "smarty/smarty",
|
||||
"version": "v3.1.31",
|
||||
|
|
21
database.sql
21
database.sql
|
@ -1,6 +1,6 @@
|
|||
-- ------------------------------------------
|
||||
-- Friendica 3.6-rc (Asparagus)
|
||||
-- DB_UPDATE_VERSION 1256
|
||||
-- Friendica 2018-05-dev (The Tazmans Flax-lily)
|
||||
-- DB_UPDATE_VERSION 1258
|
||||
-- ------------------------------------------
|
||||
|
||||
|
||||
|
@ -55,12 +55,12 @@ CREATE TABLE IF NOT EXISTS `auth_codes` (
|
|||
-- TABLE cache
|
||||
--
|
||||
CREATE TABLE IF NOT EXISTS `cache` (
|
||||
`k` varbinary(255) NOT NULL COMMENT '',
|
||||
`v` mediumtext COMMENT '',
|
||||
`expire_mode` tinyint unsigned NOT NULL DEFAULT 0 COMMENT '',
|
||||
`updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT '',
|
||||
`k` varbinary(255) NOT NULL COMMENT 'cache key',
|
||||
`v` mediumtext COMMENT 'cached serialized value',
|
||||
`expires` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'datetime of cache expiration',
|
||||
`updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' COMMENT 'datetime of cache insertion',
|
||||
PRIMARY KEY(`k`),
|
||||
INDEX `expire_mode_updated` (`expire_mode`,`updated`)
|
||||
INDEX `k_expires` (`k`,`expires`)
|
||||
) DEFAULT COLLATE utf8mb4_general_ci;
|
||||
|
||||
--
|
||||
|
@ -122,9 +122,9 @@ CREATE TABLE IF NOT EXISTS `contact` (
|
|||
`xmpp` varchar(255) NOT NULL DEFAULT '' COMMENT '',
|
||||
`attag` varchar(255) NOT NULL DEFAULT '' COMMENT '',
|
||||
`avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '',
|
||||
`photo` varchar(255) NOT NULL DEFAULT '' COMMENT '',
|
||||
`thumb` varchar(255) NOT NULL DEFAULT '' COMMENT '',
|
||||
`micro` varchar(255) NOT NULL DEFAULT '' COMMENT '',
|
||||
`photo` varchar(255) DEFAULT '' COMMENT '',
|
||||
`thumb` varchar(255) DEFAULT '' COMMENT '',
|
||||
`micro` varchar(255) DEFAULT '' COMMENT '',
|
||||
`site-pubkey` text COMMENT '',
|
||||
`issued-id` varchar(255) NOT NULL DEFAULT '' COMMENT '',
|
||||
`dfrn-id` varchar(255) NOT NULL DEFAULT '' COMMENT '',
|
||||
|
@ -1079,3 +1079,4 @@ CREATE TABLE IF NOT EXISTS `workerqueue` (
|
|||
INDEX `executed` (`executed`)
|
||||
) DEFAULT COLLATE utf8mb4_general_ci;
|
||||
|
||||
|
||||
|
|
|
@ -372,7 +372,7 @@ include/cronhooks.php: Addon::callHooks('cron', $d);
|
|||
|
||||
include/security.php: Addon::callHooks('logged_in', $a->user);
|
||||
|
||||
include/html2bbcode.php: Addon::callHooks('html2bbcode', $text);
|
||||
src/Content/Text/HTML.php: Addon::callHooks('html2bbcode', $text);
|
||||
|
||||
include/Contact.php: Addon::callHooks('remove_user',$r[0]);
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ It's a command-line tool that downloads required libraries into the `vendor` fol
|
|||
|
||||
## How to use Composer
|
||||
|
||||
If you don't have Composer installed on your system, Friendica ships with a copy of it at `util/composer.phar`.
|
||||
If you don't have Composer installed on your system, Friendica ships with a copy of it at `bin/composer.phar`.
|
||||
For the purpose of this help, all examples will use this path to run Composer commands, however feel free to replace them with your own way of calling Composer.
|
||||
Composer requires PHP CLI and the following examples assume it's available system-wide.
|
||||
|
||||
|
@ -30,7 +30,7 @@ Here are the typical commands you will have to run to do so:
|
|||
````
|
||||
~> git clone https://github.com/friendica/friendica.git friendica
|
||||
~/friendica> cd friendica
|
||||
~/friendica> util/composer.phar install
|
||||
~/friendica> bin/composer.phar install
|
||||
````
|
||||
|
||||
That's it! Composer will take care of fetching all the required libraries in the `vendor` folder and build the autoloader to make those libraries available to Friendica.
|
||||
|
@ -42,7 +42,7 @@ Updating Friendica to the current stable or the latest develop version is easy w
|
|||
````
|
||||
~> cd friendica
|
||||
~/friendica> git pull
|
||||
~/friendica> util/composer.phar install
|
||||
~/friendica> bin/composer.phar install
|
||||
````
|
||||
|
||||
And that's it. If any library used by Friendica has been upgraded, Composer will fetch the version currently used by Friendica and refresh the autoloader to ensure the best performances.
|
||||
|
@ -87,13 +87,13 @@ Or you can specify the exact version of the library if you code requires it, and
|
|||
|
||||
To add a library, just add its Packagist identifier to the `require` list and set a target version string.
|
||||
|
||||
Then you should run `util/composer.phar update` to add it to your local `vendor` folder and update the `composer.lock` file that specifies the current versions of the dependencies.
|
||||
Then you should run `bin/composer.phar update` to add it to your local `vendor` folder and update the `composer.lock` file that specifies the current versions of the dependencies.
|
||||
|
||||
#### Updating an existing dependency
|
||||
|
||||
If a package needs to be updated, whether to the next minor version or to the next major version provided you changed the adequate code in Friendica, simply edit `composer.json` to update the target version string of the relevant library.
|
||||
|
||||
Then you should run `util/composer.phar update` to update it in your local `vendor` folder and update the `composer.lock` file that specifies the current versions of the dependencies.
|
||||
Then you should run `bin/composer.phar update` to update it in your local `vendor` folder and update the `composer.lock` file that specifies the current versions of the dependencies.
|
||||
|
||||
Please note that you should commit both `composer.json` and `composer.lock` with your work every time you make a change to the former.
|
||||
|
||||
|
@ -111,7 +111,7 @@ This is because `sudo` doesn't always change the `HOME` environment variable, wh
|
|||
However, you can temporarily change environment variable for the execution of a single command.
|
||||
For Composer, this would be:
|
||||
````
|
||||
$> COMPOSER_HOME=/var/tmp/composer sudo -u [web user] util/composer.phar [mode]
|
||||
$> COMPOSER_HOME=/var/tmp/composer sudo -u [web user] bin/composer.phar [mode]
|
||||
````
|
||||
|
||||
## Related
|
||||
|
|
|
@ -94,7 +94,7 @@ Please remove all the `require_once` mentions of the former file, as they will p
|
|||
|
||||
## Miscellaneous tips
|
||||
|
||||
When you are done with moving the class, please run `php util/typo.php` from the Friendica base directory to check for obvious mistakes.
|
||||
When you are done with moving the class, please run `php bin/console.php typo` from the Friendica base directory to check for obvious mistakes.
|
||||
Howevever, this tool isn't bullet-proof, and a staging install of Friendica is recommended to test your class move without impairing your production server if you host one.
|
||||
|
||||
Most of Friendica processes are run in the background, so make sure to turn on your debug log to check for errors that wouldn't show up while simply browsing Friendica.
|
||||
|
|
|
@ -60,7 +60,7 @@ If you want to have git automatically update the dependencies with composer, you
|
|||
}
|
||||
# `composer install` if the `composer.lock` file gets changed
|
||||
# to update all the php dependencies
|
||||
check_run composer.lock "util/composer.phar install --no-dev"
|
||||
check_run composer.lock "bin/composer.phar install --no-dev"
|
||||
|
||||
just place it into `.git/hooks/post-merge` and make it executable.
|
||||
|
||||
|
|
|
@ -213,8 +213,8 @@ The listed emails need to be separated by a comma.
|
|||
Please have a look at the Admin panel under [DB updates](/admin/dbsync/) and follow the link to *check database structure*.
|
||||
This will start a background process to check if the structure is up to the current definition.
|
||||
|
||||
You can manually execute the structure update from the CLI in the base directory of your Friendica installation by running the following script:
|
||||
You can manually execute the structure update from the CLI in the base directory of your Friendica installation by running the following command:
|
||||
|
||||
scripts/dbstructure.php update
|
||||
bin/console dbstructure update
|
||||
|
||||
if there occur any errors, please contact the [support forum](https://forum.friendi.ca/profile/helpers).
|
||||
|
|
|
@ -13,7 +13,7 @@ Introduction to the workflow with our GitHub repository
|
|||
3. Fork the Friendica repository from [https://github.com/friendica/friendica.git](https://github.com/friendica/friendica.git).
|
||||
4. Clone your fork from your GitHub account to your machine.
|
||||
Follow the instructions provided here: [http://help.github.com/fork-a-repo/](http://help.github.com/fork-a-repo/) to create and use your own tracking fork on GitHub
|
||||
5. Run `util/composer.phar install` in Friendica's folder.
|
||||
5. Run `bin/composer.phar install` in Friendica's folder.
|
||||
6. Commit your changes to your fork.
|
||||
Then go to your GitHub page and create a "Pull request" to notify us to merge your work.
|
||||
|
||||
|
@ -68,7 +68,9 @@ If possible get an experienced Friendica developer to review the code.
|
|||
Don't hesitate to ask us in case of doubt.
|
||||
|
||||
3. Check your code for typos.
|
||||
There is a PHP script in the *util* directory called *typos.php* for this.
|
||||
There is a console command called *typo* for this.
|
||||
|
||||
$> php bin/console.php typo
|
||||
|
||||
Check out how to work with [our Vagrant](help/Vagrant) to save a lot of setup time!
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ The Linux commands to clone the repository into a directory "mywebsite" would be
|
|||
|
||||
git clone https://github.com/friendica/friendica.git mywebsite
|
||||
cd mywebsite
|
||||
util/composer.phar install
|
||||
bin/composer.phar install
|
||||
|
||||
Make sure the folder *view/smarty3* exists and is writable by the webserver user
|
||||
|
||||
|
@ -102,14 +102,14 @@ You might wish to move/rename .htconfig.php to another name and empty (called 'd
|
|||
Set up a cron job or scheduled task to run the worker once every 5-10 minutes in order to perform background processing.
|
||||
Example:
|
||||
|
||||
cd /base/directory; /path/to/php scripts/worker.php
|
||||
cd /base/directory; /path/to/php bin/worker.php
|
||||
|
||||
Change "/base/directory", and "/path/to/php" as appropriate for your situation.
|
||||
|
||||
If you are using a Linux server, run "crontab -e" and add a line like the
|
||||
one shown, substituting for your unique paths and settings:
|
||||
|
||||
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php scripts/worker.php
|
||||
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/worker.php
|
||||
|
||||
You can generally find the location of PHP by executing "which php".
|
||||
If you run into trouble with this section please contact your hosting provider for assistance.
|
||||
|
|
|
@ -21,7 +21,7 @@ You can get the latest changes at any time with
|
|||
|
||||
cd path/to/friendica
|
||||
git pull
|
||||
util/composer.phar install
|
||||
bin/composer.phar install
|
||||
|
||||
The addon tree has to be updated separately like so:
|
||||
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
Table cache
|
||||
===========
|
||||
|
||||
Stores temporary data
|
||||
|
||||
| Field | Description | Type | Null | Key | Default | Extra |
|
||||
| ------------ | ---------------------------------- | ------------ | ---- | --- | ------------------- | ----- |
|
||||
| k | horizontal width + url or resource | varchar(255) | NO | PRI | NULL | |
|
||||
| v | OEmbed response from site | text | NO | | NULL | |
|
||||
| k | cache key | varchar(255) | NO | PRI | NULL | |
|
||||
| v | cached serialized value | text | NO | | NULL | |
|
||||
| expires | datetime of cache expiration | datetime | NO | MUL | 0001-01-01 00:00:00 | |
|
||||
| updated | datetime of cache insertion | datetime | NO | MUL | 0001-01-01 00:00:00 | |
|
||||
| expire_mode | | int(11) | NO | | 0 | |
|
||||
|
||||
Return to [database documentation](help/database)
|
||||
|
|
|
@ -265,7 +265,7 @@ include/cronhooks.php: Addon::callHooks('cron', $d);
|
|||
|
||||
include/security.php: Addon::callHooks('logged_in', $a->user);
|
||||
|
||||
include/html2bbcode.php: Addon::callHooks('html2bbcode', $text);
|
||||
src/Content/Text/HTML.php: Addon::callHooks('html2bbcode', $text);
|
||||
|
||||
include/Contact.php: Addon::callHooks('remove_user',$r[0]);
|
||||
|
||||
|
|
|
@ -232,8 +232,8 @@ Rufe bitte im Admin Panel den Punkt [DB Updates](/admin/dbsync/) auf und folge d
|
|||
Damit wird ein Hintergrundprozess gestartet der die Struktur deiner Datenbank überprüft und gegebenenfalls aktualisiert.
|
||||
|
||||
Du kannst das Struktur Updatee auch manuell auf der Kommandoeingabe ausführen.
|
||||
Starte dazu bitte vom Grundverzeichnis deiner Friendica Instanz folgendes Skript:
|
||||
Starte dazu bitte vom Grundverzeichnis deiner Friendica Instanz folgendes Kommand:
|
||||
|
||||
scripts/dbstructure.php update
|
||||
bin/console dbstructure update
|
||||
|
||||
sollten bei der Ausführung Fehler auftreten, kontaktiere bitte das [Support Forum](https://forum.friendi.ca/profile/helpers).
|
||||
|
|
|
@ -50,7 +50,7 @@ Wir planen, diese Einschränkung in einer zukünftigen Version zu beheben.
|
|||
|
||||
`cd meinewebseite`
|
||||
`git pull`
|
||||
`util/composer.phar install`
|
||||
`bin/composer.phar install`
|
||||
|
||||
- Addons installieren
|
||||
- zunächst solltest du **in** deinem Webseitenordner sein
|
||||
|
@ -87,13 +87,13 @@ Wenn du irgendwelche **kritischen** Fehler zu diesen Zeitpunkt erhalten solltest
|
|||
|
||||
7. Erstelle einen Cron job oder einen regelmäßigen Task, um den Poller alle 5-10 Minuten im Hintergrund ablaufen zu lassen. Beispiel:
|
||||
|
||||
`cd /base/directory; /path/to/php scripts/worker.php`
|
||||
`cd /base/directory; /path/to/php bin/worker.php`
|
||||
|
||||
Ändere "/base/directory" und "/path/to/php" auf deine Systemvorgaben.
|
||||
|
||||
Wenn du einen Linux-Server nutzt, benutze den Befehl "crontab -e" und ergänze eine Zeile wie die Folgende; angepasst an dein System
|
||||
|
||||
`*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php scripts/worker.php`
|
||||
`*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/worker.php`
|
||||
|
||||
Du kannst den PHP-Pfad finden, indem du den Befehl „which php“ ausführst.
|
||||
Wenn du Schwierigkeiten mit diesem Schritt hast, kannst du deinen Hosting-Anbieter kontaktieren.
|
||||
|
|
|
@ -27,6 +27,7 @@ Example: To set the automatic database cleanup process add this line to your .ht
|
|||
* **always_show_preview** (Boolean) - Only show small preview picures. Default value is false.
|
||||
* **block_local_dir** (Boolean) - Blocks the access to the directory of the local users.
|
||||
* **auth_cookie_lifetime** (Integer) - Number of days that should pass without any activity before a user who chose "Remember me" when logging in is considered logged out. Defaults to 7.
|
||||
* **config_adapter** (jit|preload) - Allow to switch the configuration adapter to improve performances at the cost of memory consumption. Default value is "jit"
|
||||
* **curl_range_bytes** - Maximum number of bytes that should be fetched. Default is 0, which mean "no limit".
|
||||
* **db_log** - Name of a logfile to log slow database queries
|
||||
* **db_loglimit** - If a database call lasts longer than this value it is logged
|
||||
|
@ -40,6 +41,7 @@ Example: To set the automatic database cleanup process add this line to your .ht
|
|||
* **diaspora_test** (Boolean) - For development only. Disables the message transfer.
|
||||
* **disable_email_validation** (Boolean) - Disables the check if a mail address is in a valid format and can be resolved via DNS.
|
||||
* **disable_url_validation** (Boolean) - Disables the DNS lookup of an URL.
|
||||
* **disable_password_exposed** (Boolean) - Disable the exposition check against the remote haveibeenpwned API on password change. Default value is false.
|
||||
* **dlogfile - location of the developer log file
|
||||
* **dlogip - restricts develop log writes to requests originating from this IP address
|
||||
* **frontend_worker_timeout** - Value in minutes after we think that a frontend task was killed by the webserver. Default value is 10.
|
||||
|
@ -59,9 +61,11 @@ Example: To set the automatic database cleanup process add this line to your .ht
|
|||
* **max_processes_backend** - Maximum number of concurrent database processes for background tasks. Default value is 5.
|
||||
* **max_processes_frontend** - Maximum number of concurrent database processes for foreground tasks. Default value is 20.
|
||||
* **min_poll_interval** - minimal distance in minutes between two polls for a contact. Default is 1. Reasonable values are between 1 and 59.
|
||||
* **memcache** (Boolean) - Use memcache. To use memcache the PECL extension "memcache" has to be installed and activated.
|
||||
* **session_handler** (database|cache|native) - Whether to use Cache to store session data or to use PHP native session storage. Default value is `database`.
|
||||
* **cache_driver** (database|memcache|memcached) - Whether to use Memcache or Memcached to store temporary cache. Default value is `database`.
|
||||
* **memcache_host** - Host name of the memcache daemon. Default is '127.0.0.1'.
|
||||
* **memcache_port** - Port number of the memcache daemon. Default is 11211.
|
||||
* **memcached_hosts** - Array of Memcached servers info `[host, port(, weight)]`. Default value is `[['127.0.0.1', 11211]]`.
|
||||
* **no_count** (Boolean) - Don't do count calculations (currently only when showing albums)
|
||||
* **no_oembed** (Boolean) - Don't use OEmbed to fetch more information about a link.
|
||||
* **no_smilies** (Boolean) - Don't show smilies.
|
||||
|
|
|
@ -11,16 +11,16 @@ Installation
|
|||
|
||||
- Change it's owner to whichever user is running the server, ie. ejabberd
|
||||
|
||||
$ chown ejabberd:ejabberd /path/to/friendica/include/auth_ejabberd.php
|
||||
$ chown ejabberd:ejabberd /path/to/friendica/bin/auth_ejabberd.php
|
||||
|
||||
- Change the access mode so it is readable only to the user ejabberd and has exec
|
||||
|
||||
$ chmod 700 /path/to/friendica/include/auth_ejabberd.php
|
||||
$ chmod 700 /path/to/friendica/bin/auth_ejabberd.php
|
||||
|
||||
- Edit your ejabberd.cfg file, comment out your auth_method and add:
|
||||
|
||||
{auth_method, external}.
|
||||
{extauth_program, "/path/to/friendica/include/auth_ejabberd.php"}.
|
||||
{extauth_program, "/path/to/friendica/bin/auth_ejabberd.php"}.
|
||||
|
||||
- Disable the module "mod_register" and disable the registration:
|
||||
|
||||
|
|
|
@ -29,17 +29,17 @@ The location of the translated files in the source tree is
|
|||
/view/lang/LNG-CODE/
|
||||
where LNG-CODE is the language code used, e.g. de for German or fr for French.
|
||||
The translated strings come as a "message.po" file from transifex which needs to be translated into the PHP file friendica uses.
|
||||
To do so, place the file in the directory mentioned above and use the "po2php" utility from the util directory of your friendica installation.
|
||||
To do so, place the file in the directory mentioned above and use the "po2php" command from the Friendica Console.
|
||||
|
||||
Assuming you want to convert the German localization which is placed in view/lang/de/message.po you would do the following.
|
||||
|
||||
1. Navigate at the command prompt to the base directory of your
|
||||
friendica installation
|
||||
|
||||
2. Execute the po2php script, which will place the translation
|
||||
2. Execute the po2php command, which will place the translation
|
||||
in the strings.php file that is used by friendica.
|
||||
|
||||
$> php util/po2php.php view/lang/de/messages.po
|
||||
$> php bin/console.php po2php view/lang/de/messages.po
|
||||
|
||||
The output of the script will be placed at view/lang/de/strings.php where
|
||||
friendica is expecting it, so you can test your translation immediately.
|
||||
|
@ -64,7 +64,7 @@ Otherwise your work might get lost, when the translation from Transifex is inclu
|
|||
Utilities
|
||||
---------
|
||||
|
||||
Additional to the po2php script there are some more utilities for translation in the "util" directory of the friendica source tree.
|
||||
Additional to the po2php command there are some more utilities for translation in the console.
|
||||
If you only want to translate friendica into another language you wont need any of these tools most likely but it gives you an idea how the translation process of friendica works.
|
||||
|
||||
For further information see the utils/README file.
|
||||
|
@ -92,9 +92,9 @@ To update the translation files after you have translated strings of e.g. Espera
|
|||
|
||||
$> tx pull -l eo
|
||||
|
||||
And then use the `po2php` utility described above to convert the `messages.po` file to the `strings.php` file Friendica is loading.
|
||||
And then use the `po2php` command described above to convert the `messages.po` file to the `strings.php` file Friendica is loading.
|
||||
|
||||
$> php util/po2php.php view/lang/eo/messages.po
|
||||
$> php bin/console.php po2php view/lang/eo/messages.po
|
||||
|
||||
Afterwards, just commit the two changed files to a feature branch of your Friendica repository, push the changes to github and open a pull request for your changes.
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,755 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @file include/acl_selectors.php
|
||||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Content\Feature;
|
||||
use Friendica\Content\Widget;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\GContact;
|
||||
use Friendica\Util\Network;
|
||||
|
||||
require_once "mod/proxy.php";
|
||||
|
||||
/**
|
||||
* @package acl_selectors
|
||||
*/
|
||||
function group_select($selname,$selclass,$preselected = false,$size = 4) {
|
||||
|
||||
$a = get_app();
|
||||
|
||||
$o = '';
|
||||
|
||||
$o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"$size\" >\r\n";
|
||||
|
||||
$r = q("SELECT `id`, `name` FROM `group` WHERE NOT `deleted` AND `uid` = %d ORDER BY `name` ASC",
|
||||
intval(local_user())
|
||||
);
|
||||
|
||||
|
||||
$arr = ['group' => $r, 'entry' => $o];
|
||||
|
||||
// e.g. 'network_pre_group_deny', 'profile_pre_group_allow'
|
||||
|
||||
Addon::callHooks($a->module . '_pre_' . $selname, $arr);
|
||||
|
||||
if (DBM::is_result($r)) {
|
||||
foreach ($r as $rr) {
|
||||
if ((is_array($preselected)) && in_array($rr['id'], $preselected)) {
|
||||
$selected = " selected=\"selected\" ";
|
||||
} else {
|
||||
$selected = '';
|
||||
}
|
||||
|
||||
$trimmed = mb_substr($rr['name'],0,12);
|
||||
|
||||
$o .= "<option value=\"{$rr['id']}\" $selected title=\"{$rr['name']}\" >$trimmed</option>\r\n";
|
||||
}
|
||||
|
||||
}
|
||||
$o .= "</select>\r\n";
|
||||
|
||||
Addon::callHooks($a->module . '_post_' . $selname, $o);
|
||||
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
/// @TODO find proper type-hints
|
||||
function contact_selector($selname, $selclass, $options, $preselected = false)
|
||||
{
|
||||
$a = get_app();
|
||||
|
||||
$mutual = false;
|
||||
$networks = null;
|
||||
$single = false;
|
||||
$exclude = false;
|
||||
$size = 4;
|
||||
|
||||
if (is_array($options)) {
|
||||
if (x($options, 'size'))
|
||||
$size = $options['size'];
|
||||
|
||||
if (x($options, 'mutual_friends')) {
|
||||
$mutual = true;
|
||||
}
|
||||
if (x($options, 'single')) {
|
||||
$single = true;
|
||||
}
|
||||
if (x($options, 'multiple')) {
|
||||
$single = false;
|
||||
}
|
||||
if (x($options, 'exclude')) {
|
||||
$exclude = $options['exclude'];
|
||||
}
|
||||
|
||||
if (x($options, 'networks')) {
|
||||
switch ($options['networks']) {
|
||||
case 'DFRN_ONLY':
|
||||
$networks = [NETWORK_DFRN];
|
||||
break;
|
||||
case 'PRIVATE':
|
||||
if (is_array($a->user) && $a->user['prvnets']) {
|
||||
$networks = [NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA];
|
||||
} else {
|
||||
$networks = [NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA];
|
||||
}
|
||||
break;
|
||||
case 'TWO_WAY':
|
||||
if (is_array($a->user) && $a->user['prvnets']) {
|
||||
$networks = [NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA];
|
||||
} else {
|
||||
$networks = [NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA, NETWORK_OSTATUS];
|
||||
}
|
||||
break;
|
||||
default: /// @TODO Maybe log this call?
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$x = ['options' => $options, 'size' => $size, 'single' => $single, 'mutual' => $mutual, 'exclude' => $exclude, 'networks' => $networks];
|
||||
|
||||
Addon::callHooks('contact_select_options', $x);
|
||||
|
||||
$o = '';
|
||||
|
||||
$sql_extra = '';
|
||||
|
||||
if (x($x, 'mutual')) {
|
||||
$sql_extra .= sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND));
|
||||
}
|
||||
|
||||
if (x($x, 'exclude')) {
|
||||
$sql_extra .= sprintf(" AND `id` != %d ", intval($x['exclude']));
|
||||
}
|
||||
|
||||
if (is_array($x['networks']) && count($x['networks'])) {
|
||||
/// @TODO rewrite to foreach()
|
||||
for ($y = 0; $y < count($x['networks']) ; $y ++) {
|
||||
$x['networks'][$y] = "'" . dbesc($x['networks'][$y]) . "'";
|
||||
}
|
||||
$str_nets = implode(',', $x['networks']);
|
||||
$sql_extra .= " AND `network` IN ( $str_nets ) ";
|
||||
}
|
||||
|
||||
$tabindex = (x($options, 'tabindex') ? "tabindex=\"" . $options["tabindex"] . "\"" : "");
|
||||
|
||||
if ($x['single']) {
|
||||
$o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"" . $x['size'] . "\" $tabindex >\r\n";
|
||||
} else {
|
||||
$o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"" . $x['size'] . "$\" $tabindex >\r\n";
|
||||
}
|
||||
|
||||
$r = q("SELECT `id`, `name`, `url`, `network` FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
|
||||
$sql_extra
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user())
|
||||
);
|
||||
|
||||
|
||||
$arr = ['contact' => $r, 'entry' => $o];
|
||||
|
||||
// e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'
|
||||
|
||||
Addon::callHooks($a->module . '_pre_' . $selname, $arr);
|
||||
|
||||
if (DBM::is_result($r)) {
|
||||
foreach ($r as $rr) {
|
||||
if ((is_array($preselected)) && in_array($rr['id'], $preselected)) {
|
||||
$selected = " selected=\"selected\" ";
|
||||
} else {
|
||||
$selected = '';
|
||||
}
|
||||
|
||||
$trimmed = mb_substr($rr['name'],0,20);
|
||||
|
||||
$o .= "<option value=\"{$rr['id']}\" $selected title=\"{$rr['name']}|{$rr['url']}\" >$trimmed</option>\r\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$o .= "</select>\r\n";
|
||||
|
||||
Addon::callHooks($a->module . '_post_' . $selname, $o);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function contact_select($selname, $selclass, $preselected = false, $size = 4, $privmail = false, $celeb = false, $privatenet = false, $tabindex = null) {
|
||||
$a = get_app();
|
||||
|
||||
$o = '';
|
||||
|
||||
// When used for private messages, we limit correspondence to mutual DFRN/Friendica friends and the selector
|
||||
// to one recipient. By default our selector allows multiple selects amongst all contacts.
|
||||
|
||||
$sql_extra = '';
|
||||
|
||||
if ($privmail || $celeb) {
|
||||
$sql_extra .= sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND));
|
||||
}
|
||||
|
||||
if ($privmail) {
|
||||
$sql_extra .= sprintf(" AND `network` IN ('%s' , '%s') ",
|
||||
NETWORK_DFRN, NETWORK_DIASPORA);
|
||||
} elseif ($privatenet) {
|
||||
$sql_extra .= sprintf(" AND `network` IN ('%s' , '%s', '%s', '%s') ",
|
||||
NETWORK_DFRN, NETWORK_MAIL, NETWORK_FACEBOOK, NETWORK_DIASPORA);
|
||||
}
|
||||
|
||||
$tabindex = ($tabindex > 0 ? "tabindex=\"$tabindex\"" : "");
|
||||
|
||||
if ($privmail && $preselected) {
|
||||
$sql_extra .= " AND `id` IN (".implode(",", $preselected).")";
|
||||
$hidepreselected = ' style="display: none;"';
|
||||
} else {
|
||||
$hidepreselected = "";
|
||||
}
|
||||
|
||||
if ($privmail) {
|
||||
$o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"$size\" $tabindex $hidepreselected>\r\n";
|
||||
} else {
|
||||
$o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"$size\" $tabindex >\r\n";
|
||||
}
|
||||
|
||||
$r = q("SELECT `id`, `name`, `url`, `network` FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
|
||||
$sql_extra
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user())
|
||||
);
|
||||
|
||||
|
||||
$arr = ['contact' => $r, 'entry' => $o];
|
||||
|
||||
// e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'
|
||||
|
||||
Addon::callHooks($a->module . '_pre_' . $selname, $arr);
|
||||
|
||||
$receiverlist = [];
|
||||
|
||||
if (DBM::is_result($r)) {
|
||||
foreach ($r as $rr) {
|
||||
if ((is_array($preselected)) && in_array($rr['id'], $preselected)) {
|
||||
$selected = " selected=\"selected\" ";
|
||||
} else {
|
||||
$selected = '';
|
||||
}
|
||||
|
||||
if ($privmail) {
|
||||
$trimmed = Protocol::formatMention($rr['url'], $rr['name']);
|
||||
} else {
|
||||
$trimmed = mb_substr($rr['name'],0,20);
|
||||
}
|
||||
|
||||
$receiverlist[] = $trimmed;
|
||||
|
||||
$o .= "<option value=\"{$rr['id']}\" $selected title=\"{$rr['name']}|{$rr['url']}\" >$trimmed</option>\r\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$o .= "</select>\r\n";
|
||||
|
||||
if ($privmail && $preselected) {
|
||||
$o .= implode(", ", $receiverlist);
|
||||
}
|
||||
|
||||
Addon::callHooks($a->module . '_post_' . $selname, $o);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
function fixacl(&$item) {
|
||||
$item = intval(str_replace(['<', '>'], ['', ''], $item));
|
||||
}
|
||||
|
||||
function prune_deadguys($arr) {
|
||||
|
||||
if (! $arr) {
|
||||
return $arr;
|
||||
}
|
||||
|
||||
$str = dbesc(implode(',', $arr));
|
||||
|
||||
$r = q("SELECT `id` FROM `contact` WHERE `id` IN ( " . $str . ") AND `blocked` = 0 AND `pending` = 0 AND `archive` = 0 ");
|
||||
|
||||
if (DBM::is_result($r)) {
|
||||
$ret = [];
|
||||
foreach ($r as $rr) {
|
||||
$ret[] = intval($rr['id']);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
function get_acl_permissions($user = null) {
|
||||
$allow_cid = $allow_gid = $deny_cid = $deny_gid = false;
|
||||
|
||||
if (is_array($user)) {
|
||||
$allow_cid = ((strlen($user['allow_cid']))
|
||||
? explode('><', $user['allow_cid']) : [] );
|
||||
$allow_gid = ((strlen($user['allow_gid']))
|
||||
? explode('><', $user['allow_gid']) : [] );
|
||||
$deny_cid = ((strlen($user['deny_cid']))
|
||||
? explode('><', $user['deny_cid']) : [] );
|
||||
$deny_gid = ((strlen($user['deny_gid']))
|
||||
? explode('><', $user['deny_gid']) : [] );
|
||||
array_walk($allow_cid,'fixacl');
|
||||
array_walk($allow_gid,'fixacl');
|
||||
array_walk($deny_cid,'fixacl');
|
||||
array_walk($deny_gid,'fixacl');
|
||||
}
|
||||
|
||||
$allow_cid = prune_deadguys($allow_cid);
|
||||
|
||||
return [
|
||||
'allow_cid' => $allow_cid,
|
||||
'allow_gid' => $allow_gid,
|
||||
'deny_cid' => $deny_cid,
|
||||
'deny_gid' => $deny_gid,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
function populate_acl($user = null, $show_jotnets = false) {
|
||||
|
||||
$perms = get_acl_permissions($user);
|
||||
|
||||
$jotnets = '';
|
||||
if ($show_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 `pubmail` FROM `mailacct` WHERE `uid` = %d AND `server` != '' LIMIT 1",
|
||||
intval(local_user())
|
||||
);
|
||||
if (DBM::is_result($r)) {
|
||||
$mail_enabled = true;
|
||||
if (intval($r[0]['pubmail'])) {
|
||||
$pubmail_enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$user['hidewall']) {
|
||||
if ($mail_enabled) {
|
||||
$selected = (($pubmail_enabled) ? ' checked="checked" ' : '');
|
||||
$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);
|
||||
} else {
|
||||
$jotnets .= L10n::t('Connectors disabled, since "%s" is enabled.', L10n::t('Hide your profile details from unknown viewers?'));
|
||||
}
|
||||
}
|
||||
|
||||
$tpl = get_markup_template("acl_selector.tpl");
|
||||
$o = replace_macros($tpl, [
|
||||
'$showall'=> L10n::t("Visible to everybody"),
|
||||
'$show' => L10n::t("show"),
|
||||
'$hide' => L10n::t("don't show"),
|
||||
'$allowcid' => json_encode($perms['allow_cid']),
|
||||
'$allowgid' => json_encode($perms['allow_gid']),
|
||||
'$denycid' => json_encode($perms['deny_cid']),
|
||||
'$denygid' => json_encode($perms['deny_gid']),
|
||||
'$networks' => $show_jotnets,
|
||||
'$emailcc' => L10n::t('CC: email addresses'),
|
||||
'$emtitle' => L10n::t('Example: bob@example.com, mary@example.com'),
|
||||
'$jotnets' => $jotnets,
|
||||
'$aclModalTitle' => L10n::t('Permissions'),
|
||||
'$aclModalDismiss' => L10n::t('Close'),
|
||||
'$features' => [
|
||||
'aclautomention' => (Feature::isEnabled($user['uid'], "aclautomention") ? "true" : "false")
|
||||
],
|
||||
]);
|
||||
|
||||
|
||||
return $o;
|
||||
|
||||
}
|
||||
|
||||
function acl_lookup(App $a, $out_type = 'json')
|
||||
{
|
||||
if (!local_user()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$start = defaults($_REQUEST, 'start' , 0);
|
||||
$count = defaults($_REQUEST, 'count' , 100);
|
||||
$search = defaults($_REQUEST, 'search' , '');
|
||||
$type = defaults($_REQUEST, 'type' , '');
|
||||
$conv_id = defaults($_REQUEST, 'conversation', null);
|
||||
|
||||
// For use with jquery.textcomplete for private mail completion
|
||||
if (x($_REQUEST, 'query')) {
|
||||
if (! $type) {
|
||||
$type = 'm';
|
||||
}
|
||||
$search = $_REQUEST['query'];
|
||||
}
|
||||
|
||||
logger("Searching for ".$search." - type ".$type." conversation ".$conv_id, LOGGER_DEBUG);
|
||||
|
||||
if ($search != '') {
|
||||
$sql_extra = "AND `name` LIKE '%%".dbesc($search)."%%'";
|
||||
$sql_extra2 = "AND (`attag` LIKE '%%".dbesc($search)."%%' OR `name` LIKE '%%".dbesc($search)."%%' OR `nick` LIKE '%%".dbesc($search)."%%')";
|
||||
} else {
|
||||
/// @TODO Avoid these needless else blocks by putting variable-initialization atop of if()
|
||||
$sql_extra = $sql_extra2 = "";
|
||||
}
|
||||
|
||||
// count groups and contacts
|
||||
if ($type == '' || $type == 'g') {
|
||||
$r = q("SELECT COUNT(*) AS g FROM `group` WHERE `deleted` = 0 AND `uid` = %d $sql_extra",
|
||||
intval(local_user())
|
||||
);
|
||||
$group_count = (int)$r[0]['g'];
|
||||
} else {
|
||||
$group_count = 0;
|
||||
}
|
||||
|
||||
$sql_extra2 .= " ".Widget::unavailableNetworks();
|
||||
|
||||
if ($type == '' || $type == 'c') {
|
||||
// autocomplete for editor mentions
|
||||
$r = q("SELECT COUNT(*) AS c FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self`
|
||||
AND NOT `blocked` AND NOT `pending` AND NOT `archive`
|
||||
AND `success_update` >= `failure_update`
|
||||
AND `notify` != '' $sql_extra2" ,
|
||||
intval(local_user())
|
||||
);
|
||||
$contact_count = (int)$r[0]['c'];
|
||||
} elseif ($type == 'f') {
|
||||
// autocomplete for editor mentions of forums
|
||||
$r = q("SELECT COUNT(*) AS c FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self`
|
||||
AND NOT `blocked` AND NOT `pending` AND NOT `archive`
|
||||
AND (`forum` OR `prv`)
|
||||
AND `success_update` >= `failure_update`
|
||||
AND `notify` != '' $sql_extra2" ,
|
||||
intval(local_user())
|
||||
);
|
||||
$contact_count = (int)$r[0]['c'];
|
||||
} elseif ($type == 'm') {
|
||||
// autocomplete for Private Messages
|
||||
$r = q("SELECT COUNT(*) AS c FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self`
|
||||
AND NOT `blocked` AND NOT `pending` AND NOT `archive`
|
||||
AND `success_update` >= `failure_update`
|
||||
AND `network` IN ('%s', '%s') $sql_extra2" ,
|
||||
intval(local_user()),
|
||||
dbesc(NETWORK_DFRN),
|
||||
dbesc(NETWORK_DIASPORA)
|
||||
);
|
||||
$contact_count = (int)$r[0]['c'];
|
||||
|
||||
} elseif ($type == 'a') {
|
||||
// autocomplete for Contacts
|
||||
$r = q("SELECT COUNT(*) AS c FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self`
|
||||
AND NOT `pending` $sql_extra2" ,
|
||||
intval(local_user())
|
||||
);
|
||||
$contact_count = (int)$r[0]['c'];
|
||||
} else {
|
||||
$contact_count = 0;
|
||||
}
|
||||
|
||||
$tot = $group_count + $contact_count;
|
||||
|
||||
$groups = [];
|
||||
$contacts = [];
|
||||
|
||||
if ($type == '' || $type == 'g') {
|
||||
/// @todo We should cache this query.
|
||||
// This can be done when we can delete cache entries via wildcard
|
||||
$r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
|
||||
FROM `group`
|
||||
INNER JOIN `group_member` ON `group_member`.`gid`=`group`.`id`
|
||||
WHERE NOT `group`.`deleted` AND `group`.`uid` = %d
|
||||
$sql_extra
|
||||
GROUP BY `group`.`name`, `group`.`id`
|
||||
ORDER BY `group`.`name`
|
||||
LIMIT %d,%d",
|
||||
intval(local_user()),
|
||||
intval($start),
|
||||
intval($count)
|
||||
);
|
||||
|
||||
foreach ($r as $g) {
|
||||
$groups[] = [
|
||||
"type" => "g",
|
||||
"photo" => "images/twopeople.png",
|
||||
"name" => htmlentities($g['name']),
|
||||
"id" => intval($g['id']),
|
||||
"uids" => array_map("intval", explode(",",$g['uids'])),
|
||||
"link" => '',
|
||||
"forum" => '0'
|
||||
];
|
||||
}
|
||||
if ((count($groups) > 0) && ($search == "")) {
|
||||
$groups[] = ["separator" => true];
|
||||
}
|
||||
}
|
||||
|
||||
if ($type == '') {
|
||||
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv`, (`prv` OR `forum`) AS `frm` FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
|
||||
AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s', '%s'))
|
||||
$sql_extra2
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user()),
|
||||
dbesc(NETWORK_OSTATUS), dbesc(NETWORK_STATUSNET)
|
||||
);
|
||||
} elseif ($type == 'c') {
|
||||
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
|
||||
AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
|
||||
$sql_extra2
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user()),
|
||||
dbesc(NETWORK_STATUSNET)
|
||||
);
|
||||
} elseif ($type == 'f') {
|
||||
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
|
||||
AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
|
||||
AND (`forum` OR `prv`)
|
||||
$sql_extra2
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user()),
|
||||
dbesc(NETWORK_STATUSNET)
|
||||
);
|
||||
} elseif ($type == 'm') {
|
||||
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr` FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive`
|
||||
AND `success_update` >= `failure_update` AND `network` IN ('%s', '%s')
|
||||
$sql_extra2
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user()),
|
||||
dbesc(NETWORK_DFRN),
|
||||
dbesc(NETWORK_DIASPORA)
|
||||
);
|
||||
} elseif ($type == 'a') {
|
||||
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
|
||||
WHERE `uid` = %d AND `pending` = 0 AND `success_update` >= `failure_update`
|
||||
$sql_extra2
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user())
|
||||
);
|
||||
} elseif ($type == 'x') {
|
||||
// autocomplete for global contact search (e.g. navbar search)
|
||||
$r = navbar_complete($a);
|
||||
$contacts = [];
|
||||
if ($r) {
|
||||
foreach ($r as $g) {
|
||||
$contacts[] = [
|
||||
'photo' => proxy_url($g['photo'], false, PROXY_SIZE_MICRO),
|
||||
'name' => $g['name'],
|
||||
'nick' => (x($g['addr']) ? $g['addr'] : $g['url']),
|
||||
'network' => $g['network'],
|
||||
'link' => $g['url'],
|
||||
'forum' => (x($g['community']) ? 1 : 0),
|
||||
];
|
||||
}
|
||||
}
|
||||
$o = [
|
||||
'start' => $start,
|
||||
'count' => $count,
|
||||
'items' => $contacts,
|
||||
];
|
||||
echo json_encode($o);
|
||||
killme();
|
||||
} else {
|
||||
$r = [];
|
||||
}
|
||||
|
||||
if (DBM::is_result($r)) {
|
||||
$forums = [];
|
||||
foreach ($r as $g) {
|
||||
$entry = [
|
||||
'type' => 'c',
|
||||
'photo' => proxy_url($g['micro'], false, PROXY_SIZE_MICRO),
|
||||
'name' => htmlentities($g['name']),
|
||||
'id' => intval($g['id']),
|
||||
'network' => $g['network'],
|
||||
'link' => $g['url'],
|
||||
'nick' => htmlentities(($g['attag']) ? $g['attag'] : $g['nick']),
|
||||
'addr' => htmlentities(($g['addr']) ? $g['addr'] : $g['url']),
|
||||
'forum' => ((x($g, 'forum') || x($g, 'prv')) ? 1 : 0),
|
||||
];
|
||||
if ($entry['forum']) {
|
||||
$forums[] = $entry;
|
||||
} else {
|
||||
$contacts[] = $entry;
|
||||
}
|
||||
}
|
||||
if (count($forums) > 0) {
|
||||
if ($search == "") {
|
||||
$forums[] = ["separator" => true];
|
||||
}
|
||||
$contacts = array_merge($forums, $contacts);
|
||||
}
|
||||
}
|
||||
|
||||
$items = array_merge($groups, $contacts);
|
||||
|
||||
// At multi threaded posts the conv_id is not the parent of the whole thread
|
||||
if ($conv_id > 0) {
|
||||
$parent_item = dba::selectFirst('item', ['parent'], ['id' => $conv_id]);
|
||||
if (DBM::is_result($parent_item)) {
|
||||
$conv_id = $parent_item['parent'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($conv_id) {
|
||||
/*
|
||||
* if $conv_id is set, get unknown contacts in thread
|
||||
* but first get known contacts url to filter them out
|
||||
*/
|
||||
$known_contacts = array_map(
|
||||
function ($i) {
|
||||
return dbesc($i['link']);
|
||||
}
|
||||
, $contacts);
|
||||
|
||||
$unknown_contacts = [];
|
||||
$r = q("SELECT `author-link`
|
||||
FROM `item` WHERE `parent` = %d
|
||||
AND (`author-name` LIKE '%%%s%%' OR `author-link` LIKE '%%%s%%')
|
||||
AND `author-link` NOT IN ('%s')
|
||||
GROUP BY `author-link`, `author-avatar`, `author-name`
|
||||
ORDER BY `author-name` ASC
|
||||
",
|
||||
intval($conv_id),
|
||||
dbesc($search),
|
||||
dbesc($search),
|
||||
implode("', '", $known_contacts)
|
||||
);
|
||||
if (DBM::is_result($r)) {
|
||||
foreach ($r as $row) {
|
||||
$contact = Contact::getDetailsByURL($row['author-link']);
|
||||
|
||||
if (count($contact) > 0) {
|
||||
$unknown_contacts[] = [
|
||||
'type' => 'c',
|
||||
'photo' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO),
|
||||
'name' => htmlentities($contact['name']),
|
||||
'id' => intval($contact['cid']),
|
||||
'network' => $contact['network'],
|
||||
'link' => $contact['url'],
|
||||
'nick' => htmlentities($contact['nick'] ? : $contact['addr']),
|
||||
'addr' => htmlentities(($contact['addr']) ? $contact['addr'] : $contact['url']),
|
||||
'forum' => $contact['forum']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$items = array_merge($items, $unknown_contacts);
|
||||
$tot += count($unknown_contacts);
|
||||
}
|
||||
|
||||
$results = [
|
||||
'tot' => $tot,
|
||||
'start' => $start,
|
||||
'count' => $count,
|
||||
'groups' => $groups,
|
||||
'contacts' => $contacts,
|
||||
'items' => $items,
|
||||
'type' => $type,
|
||||
'search' => $search,
|
||||
];
|
||||
|
||||
Addon::callHooks('acl_lookup_end', $results);
|
||||
|
||||
if ($out_type === 'html') {
|
||||
$o = [
|
||||
'tot' => $results['tot'],
|
||||
'start' => $results['start'],
|
||||
'count' => $results['count'],
|
||||
'groups' => $results['groups'],
|
||||
'contacts' => $results['contacts'],
|
||||
];
|
||||
return $o;
|
||||
}
|
||||
|
||||
$o = [
|
||||
'tot' => $results['tot'],
|
||||
'start' => $results['start'],
|
||||
'count' => $results['count'],
|
||||
'items' => $results['items'],
|
||||
];
|
||||
|
||||
echo json_encode($o);
|
||||
|
||||
killme();
|
||||
}
|
||||
/**
|
||||
* @brief Searching for global contacts for autocompletion
|
||||
*
|
||||
* @param App $a
|
||||
* @return array with the search results
|
||||
*/
|
||||
function navbar_complete(App $a) {
|
||||
|
||||
// logger('navbar_complete');
|
||||
|
||||
if ((Config::get('system','block_public')) && (! local_user()) && (! remote_user())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if searching in the local global contact table is enabled
|
||||
$localsearch = Config::get('system','poco_local_search');
|
||||
|
||||
$search = notags(trim($_REQUEST['search']));
|
||||
$mode = $_REQUEST['smode'];
|
||||
|
||||
// don't search if search term has less than 2 characters
|
||||
if (! $search || mb_strlen($search) < 2) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (substr($search,0,1) === '@') {
|
||||
$search = substr($search,1);
|
||||
}
|
||||
|
||||
if ($localsearch) {
|
||||
$x = GContact::searchByName($search, $mode);
|
||||
return $x;
|
||||
}
|
||||
|
||||
if (! $localsearch) {
|
||||
$p = (($a->pager['page'] != 1) ? '&p=' . $a->pager['page'] : '');
|
||||
|
||||
$x = Network::curl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search));
|
||||
if ($x['success']) {
|
||||
$j = json_decode($x['body'],true);
|
||||
if ($j && isset($j['results'])) {
|
||||
return $j['results'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @TODO Not needed here?
|
||||
return;
|
||||
}
|
|
@ -10,6 +10,7 @@ use Friendica\App;
|
|||
use Friendica\Content\ContactSelector;
|
||||
use Friendica\Content\Feature;
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Content\Text\HTML;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\L10n;
|
||||
|
@ -41,11 +42,9 @@ use Friendica\Util\Network;
|
|||
use Friendica\Util\XML;
|
||||
|
||||
require_once 'include/conversation.php';
|
||||
require_once 'include/html2plain.php';
|
||||
require_once 'mod/share.php';
|
||||
require_once 'mod/item.php';
|
||||
require_once 'include/security.php';
|
||||
require_once 'include/html2bbcode.php';
|
||||
require_once 'mod/wall_upload.php';
|
||||
require_once 'mod/proxy.php';
|
||||
|
||||
|
@ -317,12 +316,16 @@ function api_call(App $a)
|
|||
/// @TODO round() really everywhere?
|
||||
logger(
|
||||
parse_url($a->query_string, PHP_URL_PATH) . ": " . sprintf(
|
||||
"Database: %s/%s, Network: %s, I/O: %s, Other: %s, Total: %s",
|
||||
"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["network"] + $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
|
||||
|
@ -344,6 +347,21 @@ function api_call(App $a)
|
|||
}
|
||||
}
|
||||
|
||||
$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);
|
||||
|
@ -1077,7 +1095,7 @@ function api_statuses_mediap($type)
|
|||
$purifier = new HTMLPurifier($config);
|
||||
$txt = $purifier->purify($txt);
|
||||
}
|
||||
$txt = html2bbcode($txt);
|
||||
$txt = HTML::toBBCode($txt);
|
||||
|
||||
$a->argv[1]=$user_info['screen_name']; //should be set to username?
|
||||
|
||||
|
@ -1128,7 +1146,7 @@ function api_statuses_update($type)
|
|||
$purifier = new HTMLPurifier($config);
|
||||
$txt = $purifier->purify($txt);
|
||||
|
||||
$_REQUEST['body'] = html2bbcode($txt);
|
||||
$_REQUEST['body'] = HTML::toBBCode($txt);
|
||||
}
|
||||
} else {
|
||||
$_REQUEST['body'] = requestdata('status');
|
||||
|
@ -2605,10 +2623,10 @@ function api_format_messages($item, $recipient, $sender)
|
|||
if ($_GET['getText'] == 'html') {
|
||||
$ret['text'] = BBCode::convert($item['body'], false);
|
||||
} elseif ($_GET['getText'] == 'plain') {
|
||||
$ret['text'] = trim(html2plain(BBCode::convert(api_clean_plain_items($item['body']), false, 2, true), 0));
|
||||
$ret['text'] = trim(HTML::toPlaintext(BBCode::convert(api_clean_plain_items($item['body']), false, 2, true), 0));
|
||||
}
|
||||
} else {
|
||||
$ret['text'] = $item['title'] . "\n" . html2plain(BBCode::convert(api_clean_plain_items($item['body']), false, 2, true), 0);
|
||||
$ret['text'] = $item['title'] . "\n" . HTML::toPlaintext(BBCode::convert(api_clean_plain_items($item['body']), false, 2, true), 0);
|
||||
}
|
||||
if (x($_GET, 'getUserObjects') && $_GET['getUserObjects'] == 'false') {
|
||||
unset($ret['sender']);
|
||||
|
@ -2631,7 +2649,7 @@ function api_convert_item($item)
|
|||
|
||||
// Workaround for ostatus messages where the title is identically to the body
|
||||
$html = BBCode::convert(api_clean_plain_items($body), false, 2, true);
|
||||
$statusbody = trim(html2plain($html, 0));
|
||||
$statusbody = trim(HTML::toPlaintext($html, 0));
|
||||
|
||||
// handle data: images
|
||||
$statusbody = api_format_items_embeded_images($item, $statusbody);
|
||||
|
|
|
@ -1,264 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Content\Text\Markdown;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Network\Probe;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use League\HTMLToMarkdown\HtmlConverter;
|
||||
|
||||
require_once 'include/event.php';
|
||||
require_once 'include/html2bbcode.php';
|
||||
|
||||
/**
|
||||
* @brief Callback function to replace a Diaspora style mention in a mention for Friendica
|
||||
*
|
||||
* @param array $match Matching values for the callback
|
||||
* @return string Replaced mention
|
||||
*/
|
||||
function diaspora_mention2bb($match) {
|
||||
if ($match[2] == '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = Contact::getDetailsByAddr($match[2]);
|
||||
|
||||
$name = $match[1];
|
||||
|
||||
if ($name == '') {
|
||||
$name = $data['name'];
|
||||
}
|
||||
|
||||
return '@[url=' . $data['url'] . ']' . $name . '[/url]';
|
||||
}
|
||||
|
||||
/*
|
||||
* we don't want to support a bbcode specific markdown interpreter
|
||||
* and the markdown library we have is pretty good, but provides HTML output.
|
||||
* So we'll use that to convert to HTML, then convert the HTML back to bbcode,
|
||||
* and then clean up a few Diaspora specific constructs.
|
||||
*/
|
||||
function diaspora2bb($s) {
|
||||
|
||||
$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\#])/', '#$1', $s);
|
||||
|
||||
$s = Markdown::convert($s);
|
||||
|
||||
$regexp = "/@\{(?:([^\}]+?); )?([^\} ]+)\}/";
|
||||
$s = preg_replace_callback($regexp, 'diaspora_mention2bb', $s);
|
||||
|
||||
$s = str_replace('#', '#', $s);
|
||||
|
||||
$s = html2bbcode($s);
|
||||
|
||||
// protect the recycle symbol from turning into a tag, but without unescaping angles and naked ampersands
|
||||
$s = str_replace('♲', html_entity_decode('♲', ENT_QUOTES, 'UTF-8'), $s);
|
||||
|
||||
// Convert everything that looks like a link to a link
|
||||
$s = preg_replace('/([^\]=]|^)(https?\:\/\/)([a-zA-Z0-9:\/\-?&;.=_~#%$!+,@]+(?<!,))/ism', '$1[url=$2$3]$2$3[/url]', $s);
|
||||
|
||||
//$s = preg_replace("/([^\]\=]|^)(https?\:\/\/)(vimeo|youtu|www\.youtube|soundcloud)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", '$1[url=$2$3$4]$2$3$4[/url]',$s);
|
||||
$s = BBCode::pregReplaceInTag('/\[url\=?(.*?)\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/url\]/ism', '[youtube]$2[/youtube]', 'url', $s);
|
||||
$s = BBCode::pregReplaceInTag('/\[url\=https?:\/\/www.youtube.com\/watch\?v\=(.*?)\].*?\[\/url\]/ism' , '[youtube]$1[/youtube]', 'url', $s);
|
||||
$s = BBCode::pregReplaceInTag('/\[url\=?(.*?)\]https?:\/\/vimeo.com\/([0-9]+)(.*?)\[\/url\]/ism' , '[vimeo]$2[/vimeo]' , 'url', $s);
|
||||
$s = BBCode::pregReplaceInTag('/\[url\=https?:\/\/vimeo.com\/([0-9]+)\](.*?)\[\/url\]/ism' , '[vimeo]$1[/vimeo]' , 'url', $s);
|
||||
|
||||
// remove duplicate adjacent code tags
|
||||
$s = preg_replace('/(\[code\])+(.*?)(\[\/code\])+/ism', '[code]$2[/code]', $s);
|
||||
|
||||
// Don't show link to full picture (until it is fixed)
|
||||
$s = BBCode::scaleExternalImages($s, false);
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function to replace a Friendica style mention in a mention for Diaspora
|
||||
*
|
||||
* @param array $match Matching values for the callback
|
||||
* @return string Replaced mention
|
||||
*/
|
||||
function diaspora_mentions($match) {
|
||||
|
||||
$contact = Contact::getDetailsByURL($match[3]);
|
||||
|
||||
if (!x($contact, 'addr')) {
|
||||
$contact = Probe::uri($match[3]);
|
||||
}
|
||||
|
||||
if (!x($contact, 'addr')) {
|
||||
return $match[0];
|
||||
}
|
||||
|
||||
$mention = '@{' . $match[2] . '; ' . $contact['addr'] . '}';
|
||||
return $mention;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a BBCode text into Markdown
|
||||
*
|
||||
* This function converts a BBCode item body to be sent to Markdown-enabled
|
||||
* systems like Diaspora and Libertree
|
||||
*
|
||||
* @param string $Text
|
||||
* @param bool $fordiaspora Diaspora requires more changes than Libertree
|
||||
* @return string
|
||||
*/
|
||||
function bb2diaspora($Text, $fordiaspora = true) {
|
||||
$a = get_app();
|
||||
|
||||
$OriginalText = $Text;
|
||||
|
||||
// Since Diaspora is creating a summary for links, this function removes them before posting
|
||||
if ($fordiaspora) {
|
||||
$Text = BBCode::removeShareInformation($Text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform #tags, strip off the [url] and replace spaces with underscore
|
||||
*/
|
||||
$URLSearchString = "^\[\]";
|
||||
$Text = preg_replace_callback("/#\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/i",
|
||||
function ($matches) {
|
||||
return '#' . str_replace(' ', '_', $matches[2]);
|
||||
}
|
||||
, $Text);
|
||||
|
||||
// Converting images with size parameters to simple images. Markdown doesn't know it.
|
||||
$Text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $Text);
|
||||
|
||||
// Extracting multi-line code blocks before the whitespace processing/code highlighter in BBCode::convert()
|
||||
$codeblocks = [];
|
||||
|
||||
$Text = preg_replace_callback("#\[code(?:=([^\]]*))?\](.*?)\[\/code\]#is",
|
||||
function ($matches) use (&$codeblocks) {
|
||||
$return = $matches[0];
|
||||
if (strpos($matches[2], "\n") !== false) {
|
||||
$return = '#codeblock-' . count($codeblocks) . '#';
|
||||
|
||||
$prefix = '````' . $matches[1] . PHP_EOL;
|
||||
$codeblocks[] = $prefix . trim($matches[2]) . PHP_EOL . '````';
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
, $Text);
|
||||
|
||||
// Convert it to HTML - don't try oembed
|
||||
if ($fordiaspora) {
|
||||
$Text = BBCode::convert($Text, false, 3);
|
||||
|
||||
// Add all tags that maybe were removed
|
||||
if (preg_match_all("/#\[url\=([$URLSearchString]*)\](.*?)\[\/url\]/ism", $OriginalText, $tags)) {
|
||||
$tagline = "";
|
||||
foreach ($tags[2] as $tag) {
|
||||
$tag = html_entity_decode($tag, ENT_QUOTES, 'UTF-8');
|
||||
if (!strpos(html_entity_decode($Text, ENT_QUOTES, 'UTF-8'), '#' . $tag)) {
|
||||
$tagline .= '#' . $tag . ' ';
|
||||
}
|
||||
}
|
||||
$Text = $Text." ".$tagline;
|
||||
}
|
||||
} else {
|
||||
$Text = BBCode::convert($Text, false, 4);
|
||||
}
|
||||
|
||||
// mask some special HTML chars from conversation to markdown
|
||||
$Text = str_replace(['<', '>', '&'], ['&_lt_;', '&_gt_;', '&_amp_;'], $Text);
|
||||
|
||||
// If a link is followed by a quote then there should be a newline before it
|
||||
// Maybe we should make this newline at every time before a quote.
|
||||
$Text = str_replace(["</a><blockquote>"], ["</a><br><blockquote>"], $Text);
|
||||
|
||||
$stamp1 = microtime(true);
|
||||
|
||||
// Now convert HTML to Markdown
|
||||
$converter = new HtmlConverter();
|
||||
$Text = $converter->convert($Text);
|
||||
|
||||
// unmask the special chars back to HTML
|
||||
$Text = str_replace(['&\_lt\_;', '&\_gt\_;', '&\_amp\_;'], ['<', '>', '&'], $Text);
|
||||
|
||||
$a->save_timestamp($stamp1, "parser");
|
||||
|
||||
// Libertree has a problem with escaped hashtags.
|
||||
$Text = str_replace(['\#'], ['#'], $Text);
|
||||
|
||||
// Remove any leading or trailing whitespace, as this will mess up
|
||||
// the Diaspora signature verification and cause the item to disappear
|
||||
$Text = trim($Text);
|
||||
|
||||
if ($fordiaspora) {
|
||||
$URLSearchString = "^\[\]";
|
||||
$Text = preg_replace_callback("/([@]\[(.*?)\])\(([$URLSearchString]*?)\)/ism", 'diaspora_mentions', $Text);
|
||||
}
|
||||
|
||||
// Restore code blocks
|
||||
$Text = preg_replace_callback('/#codeblock-([0-9]+)#/iU',
|
||||
function ($matches) use ($codeblocks) {
|
||||
$return = '';
|
||||
if (isset($codeblocks[intval($matches[1])])) {
|
||||
$return = $codeblocks[$matches[1]];
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
, $Text);
|
||||
|
||||
Addon::callHooks('bb2diaspora',$Text);
|
||||
|
||||
return $Text;
|
||||
}
|
||||
|
||||
function unescape_underscores_in_links($m) {
|
||||
$y = str_replace('\\_', '_', $m[2]);
|
||||
return('[' . $m[1] . '](' . $y . ')');
|
||||
}
|
||||
|
||||
function format_event_diaspora($ev) {
|
||||
if (! ((is_array($ev)) && count($ev))) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$bd_format = L10n::t('l F d, Y \@ g:i A') ; // Friday January 18, 2011 @ 8 AM
|
||||
|
||||
$o = 'Friendica event notification:' . "\n";
|
||||
|
||||
$o .= '**' . (($ev['summary']) ? bb2diaspora($ev['summary']) : bb2diaspora($ev['desc'])) . '**' . "\n";
|
||||
|
||||
// @todo What. Is. Going. On. With. This. Useless. Ternary. Operator? - mrpetovan
|
||||
$o .= L10n::t('Starts:') . ' ' . '[' . day_translate(
|
||||
$ev['adjust'] ? DateTimeFormat::utc($ev['start'], $bd_format) : DateTimeFormat::utc($ev['start'], $bd_format)
|
||||
)
|
||||
. '](' . System::baseUrl() . '/localtime/?f=&time=' . urlencode(DateTimeFormat::utc($ev['start'])) . ")\n";
|
||||
|
||||
if (! $ev['nofinish']) {
|
||||
$o .= L10n::t('Finishes:') . ' ' . '[' . day_translate(
|
||||
$ev['adjust'] ? DateTimeFormat::utc($ev['finish'], $bd_format) : DateTimeFormat::utc($ev['finish'], $bd_format)
|
||||
)
|
||||
. '](' . System::baseUrl() . '/localtime/?f=&time=' . urlencode(DateTimeFormat::utc($ev['finish'])) . ")\n";
|
||||
}
|
||||
|
||||
if (strlen($ev['location'])) {
|
||||
$o .= L10n::t('Location:') . bb2diaspora($ev['location'])
|
||||
. "\n";
|
||||
}
|
||||
|
||||
$o .= "\n";
|
||||
return $o;
|
||||
}
|
|
@ -21,8 +21,6 @@ use Friendica\Util\DateTimeFormat;
|
|||
use Friendica\Util\Temporal;
|
||||
use Friendica\Util\XML;
|
||||
|
||||
require_once "include/acl_selectors.php";
|
||||
|
||||
function item_extract_images($body) {
|
||||
|
||||
$saved_image = [];
|
||||
|
|
|
@ -13,7 +13,7 @@ use Friendica\Util\DateTimeFormat;
|
|||
*/
|
||||
|
||||
class dba {
|
||||
public static $connected = true;
|
||||
public static $connected = false;
|
||||
|
||||
private static $_server_info = '';
|
||||
private static $db;
|
||||
|
@ -48,8 +48,6 @@ class dba {
|
|||
$db = trim($db);
|
||||
|
||||
if (!(strlen($server) && strlen($user))) {
|
||||
self::$connected = false;
|
||||
self::$db = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -57,8 +55,6 @@ class dba {
|
|||
if (strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1')) {
|
||||
if (! dns_get_record($server, DNS_A + DNS_CNAME + DNS_PTR)) {
|
||||
self::$error = L10n::t('Cannot locate DNS info for database server \'%s\'', $server);
|
||||
self::$connected = false;
|
||||
self::$db = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +75,6 @@ class dba {
|
|||
self::$db = @new PDO($connect, $user, $pass);
|
||||
self::$connected = true;
|
||||
} catch (PDOException $e) {
|
||||
self::$connected = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,14 +93,10 @@ class dba {
|
|||
// No suitable SQL driver was found.
|
||||
if (!self::$connected) {
|
||||
self::$db = null;
|
||||
if (!$install) {
|
||||
System::unavailable();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
$a->save_timestamp($stamp1, "network");
|
||||
|
||||
return true;
|
||||
return self::$connected;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -146,7 +137,7 @@ class dba {
|
|||
*
|
||||
* @param string $query The database query that will be analyzed
|
||||
*/
|
||||
private static function log_index($query) {
|
||||
private static function logIndex($query) {
|
||||
$a = get_app();
|
||||
|
||||
if (empty($a->config["system"]["db_log_index"])) {
|
||||
|
@ -273,7 +264,7 @@ class dba {
|
|||
* @param array $args The parameters that are to replace the ? placeholders
|
||||
* @return string The replaced SQL query
|
||||
*/
|
||||
private static function replace_parameters($sql, $args) {
|
||||
private static function replaceParameters($sql, $args) {
|
||||
$offset = 0;
|
||||
foreach ($args AS $param => $value) {
|
||||
if (is_int($args[$param]) || is_float($args[$param])) {
|
||||
|
@ -414,7 +405,7 @@ class dba {
|
|||
|
||||
// The fallback routine is called as well when there are no arguments
|
||||
if (!$can_be_prepared || (count($args) == 0)) {
|
||||
$retval = self::$db->query(self::replace_parameters($sql, $args));
|
||||
$retval = self::$db->query(self::replaceParameters($sql, $args));
|
||||
if (self::$db->errno) {
|
||||
self::$error = self::$db->error;
|
||||
self::$errorno = self::$db->errno;
|
||||
|
@ -477,7 +468,7 @@ class dba {
|
|||
$errorno = self::$errorno;
|
||||
|
||||
logger('DB Error '.self::$errorno.': '.self::$error."\n".
|
||||
System::callstack(8)."\n".self::replace_parameters($sql, $params));
|
||||
System::callstack(8)."\n".self::replaceParameters($sql, $params));
|
||||
|
||||
self::$error = $error;
|
||||
self::$errorno = $errorno;
|
||||
|
@ -497,7 +488,7 @@ class dba {
|
|||
@file_put_contents($a->config["system"]["db_log"], DateTimeFormat::utcNow()."\t".$duration."\t".
|
||||
basename($backtrace[1]["file"])."\t".
|
||||
$backtrace[1]["line"]."\t".$backtrace[2]["function"]."\t".
|
||||
substr(self::replace_parameters($sql, $args), 0, 2000)."\n", FILE_APPEND);
|
||||
substr(self::replaceParameters($sql, $args), 0, 2000)."\n", FILE_APPEND);
|
||||
}
|
||||
}
|
||||
return $retval;
|
||||
|
@ -542,7 +533,7 @@ class dba {
|
|||
$errorno = self::$errorno;
|
||||
|
||||
logger('DB Error '.self::$errorno.': '.self::$error."\n".
|
||||
System::callstack(8)."\n".self::replace_parameters($sql, $params));
|
||||
System::callstack(8)."\n".self::replaceParameters($sql, $params));
|
||||
|
||||
self::$error = $error;
|
||||
self::$errorno = $errorno;
|
||||
|
@ -568,10 +559,10 @@ class dba {
|
|||
|
||||
$fields = [];
|
||||
|
||||
$array_element = each($condition);
|
||||
$array_key = $array_element['key'];
|
||||
if (!is_int($array_key)) {
|
||||
$fields = [$array_key];
|
||||
reset($condition);
|
||||
$first_key = key($condition);
|
||||
if (!is_int($first_key)) {
|
||||
$fields = [$first_key];
|
||||
}
|
||||
|
||||
$stmt = self::select($table, $fields, $condition, ['limit' => 1]);
|
||||
|
@ -847,7 +838,7 @@ class dba {
|
|||
*
|
||||
* This process must only be started once, since the value is cached.
|
||||
*/
|
||||
private static function build_relation_data() {
|
||||
private static function buildRelationData() {
|
||||
$definition = DBStructure::definition();
|
||||
|
||||
foreach ($definition AS $table => $structure) {
|
||||
|
@ -896,7 +887,7 @@ class dba {
|
|||
|
||||
// To speed up the whole process we cache the table relations
|
||||
if (count(self::$relation) == 0) {
|
||||
self::build_relation_data();
|
||||
self::buildRelationData();
|
||||
}
|
||||
|
||||
// Is there a relation entry for the table?
|
||||
|
@ -951,17 +942,14 @@ class dba {
|
|||
|
||||
foreach ($commands AS $command) {
|
||||
$conditions = $command['conditions'];
|
||||
$array_element = each($conditions);
|
||||
$array_key = $array_element['key'];
|
||||
if (is_int($array_key)) {
|
||||
$condition_string = " WHERE " . array_shift($conditions);
|
||||
} else {
|
||||
$condition_string = " WHERE `" . implode("` = ? AND `", array_keys($conditions)) . "` = ?";
|
||||
}
|
||||
reset($conditions);
|
||||
$first_key = key($conditions);
|
||||
|
||||
if ((count($command['conditions']) > 1) || is_int($array_key)) {
|
||||
$condition_string = self::buildCondition($conditions);
|
||||
|
||||
if ((count($command['conditions']) > 1) || is_int($first_key)) {
|
||||
$sql = "DELETE FROM `" . $command['table'] . "`" . $condition_string;
|
||||
logger(self::replace_parameters($sql, $conditions), LOGGER_DATA);
|
||||
logger(self::replaceParameters($sql, $conditions), LOGGER_DATA);
|
||||
|
||||
if (!self::e($sql, $conditions)) {
|
||||
if ($do_transaction) {
|
||||
|
@ -991,7 +979,7 @@ class dba {
|
|||
$sql = "DELETE FROM `" . $table . "` WHERE `" . $field . "` IN (" .
|
||||
substr(str_repeat("?, ", count($field_values)), 0, -2) . ");";
|
||||
|
||||
logger(self::replace_parameters($sql, $field_values), LOGGER_DATA);
|
||||
logger(self::replaceParameters($sql, $field_values), LOGGER_DATA);
|
||||
|
||||
if (!self::e($sql, $field_values)) {
|
||||
if ($do_transaction) {
|
||||
|
@ -1048,13 +1036,7 @@ class dba {
|
|||
|
||||
$table = self::escape($table);
|
||||
|
||||
$array_element = each($condition);
|
||||
$array_key = $array_element['key'];
|
||||
if (is_int($array_key)) {
|
||||
$condition_string = " WHERE ".array_shift($condition);
|
||||
} else {
|
||||
$condition_string = " WHERE `".implode("` = ? AND `", array_keys($condition))."` = ?";
|
||||
}
|
||||
$condition_string = self::buildCondition($condition);
|
||||
|
||||
if (is_bool($old_fields)) {
|
||||
$do_insert = $old_fields;
|
||||
|
@ -1149,6 +1131,8 @@ class dba {
|
|||
return false;
|
||||
}
|
||||
|
||||
$table = self::escape($table);
|
||||
|
||||
if (count($fields) > 0) {
|
||||
$select_fields = "`" . implode("`, `", array_values($fields)) . "`";
|
||||
} else {
|
||||
|
@ -1240,12 +1224,28 @@ class dba {
|
|||
{
|
||||
$condition_string = '';
|
||||
if (count($condition) > 0) {
|
||||
$array_element = each($condition);
|
||||
$array_key = $array_element['key'];
|
||||
if (is_int($array_key)) {
|
||||
reset($condition);
|
||||
$first_key = key($condition);
|
||||
if (is_int($first_key)) {
|
||||
$condition_string = " WHERE ".array_shift($condition);
|
||||
} else {
|
||||
$condition_string = " WHERE `".implode("` = ? AND `", array_keys($condition))."` = ?";
|
||||
$new_values = [];
|
||||
$condition_string = "";
|
||||
foreach ($condition as $field => $value) {
|
||||
if ($condition_string != "") {
|
||||
$condition_string .= " AND ";
|
||||
}
|
||||
if (is_array($value)) {
|
||||
$new_values = array_merge($new_values, array_values($value));
|
||||
$placeholders = substr(str_repeat("?, ", count($value)), 0, -2);
|
||||
$condition_string .= "`" . $field . "` IN (" . $placeholders . ")";
|
||||
} else {
|
||||
$new_values[$field] = $value;
|
||||
$condition_string .= "`" . $field . "` = ?";
|
||||
}
|
||||
}
|
||||
$condition_string = " WHERE " . $condition_string;
|
||||
$condition = $new_values;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ use Friendica\Database\DBM;
|
|||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Emailer;
|
||||
|
||||
require_once 'include/html2bbcode.php';
|
||||
|
||||
/**
|
||||
* @brief Creates a notification entry and possibly sends a mail
|
||||
*
|
||||
|
|
1065
include/event.php
1065
include/event.php
File diff suppressed because it is too large
Load diff
|
@ -1,403 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @file include/html2bbcode.php
|
||||
* @brief Converter for HTML to BBCode
|
||||
*
|
||||
* Made by: ike@piratenpartei.de
|
||||
* Originally made for the syncom project: http://wiki.piratenpartei.de/Syncom
|
||||
* https://github.com/annando/Syncom
|
||||
*/
|
||||
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Util\XML;
|
||||
|
||||
function node2bbcode(&$doc, $oldnode, $attributes, $startbb, $endbb)
|
||||
{
|
||||
do {
|
||||
$done = node2bbcodesub($doc, $oldnode, $attributes, $startbb, $endbb);
|
||||
} while ($done);
|
||||
}
|
||||
|
||||
function node2bbcodesub(&$doc, $oldnode, $attributes, $startbb, $endbb)
|
||||
{
|
||||
$savestart = str_replace('$', '\x01', $startbb);
|
||||
$replace = false;
|
||||
|
||||
$xpath = new DomXPath($doc);
|
||||
|
||||
$list = $xpath->query("//".$oldnode);
|
||||
foreach ($list as $oldNode) {
|
||||
$attr = [];
|
||||
if ($oldNode->attributes->length) {
|
||||
foreach ($oldNode->attributes as $attribute) {
|
||||
$attr[$attribute->name] = $attribute->value;
|
||||
}
|
||||
}
|
||||
|
||||
$replace = true;
|
||||
|
||||
$startbb = $savestart;
|
||||
|
||||
$i = 0;
|
||||
|
||||
foreach ($attributes as $attribute => $value) {
|
||||
$startbb = str_replace('\x01'.++$i, '$1', $startbb);
|
||||
if (strpos('*'.$startbb, '$1') > 0) {
|
||||
if ($replace && (@$attr[$attribute] != '')) {
|
||||
$startbb = preg_replace($value, $startbb, $attr[$attribute], -1, $count);
|
||||
|
||||
// If nothing could be changed
|
||||
if ($count == 0) {
|
||||
$replace = false;
|
||||
}
|
||||
} else {
|
||||
$replace = false;
|
||||
}
|
||||
} else {
|
||||
if (@$attr[$attribute] != $value) {
|
||||
$replace = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($replace) {
|
||||
$StartCode = $oldNode->ownerDocument->createTextNode($startbb);
|
||||
$EndCode = $oldNode->ownerDocument->createTextNode($endbb);
|
||||
|
||||
$oldNode->parentNode->insertBefore($StartCode, $oldNode);
|
||||
|
||||
if ($oldNode->hasChildNodes()) {
|
||||
foreach ($oldNode->childNodes as $child) {
|
||||
$newNode = $child->cloneNode(true);
|
||||
$oldNode->parentNode->insertBefore($newNode, $oldNode);
|
||||
}
|
||||
}
|
||||
|
||||
$oldNode->parentNode->insertBefore($EndCode, $oldNode);
|
||||
$oldNode->parentNode->removeChild($oldNode);
|
||||
}
|
||||
}
|
||||
return($replace);
|
||||
}
|
||||
|
||||
function html2bbcode($message, $basepath = '')
|
||||
{
|
||||
|
||||
$message = str_replace("\r", "", $message);
|
||||
|
||||
// Removing code blocks before the whitespace removal processing below
|
||||
$codeblocks = [];
|
||||
$message = preg_replace_callback(
|
||||
'#<pre><code(?: class="([^"]*)")?>(.*)</code></pre>#iUs',
|
||||
function ($matches) use (&$codeblocks) {
|
||||
$return = '[codeblock-' . count($codeblocks) . ']';
|
||||
|
||||
$prefix = '[code]';
|
||||
if ($matches[1] != '') {
|
||||
$prefix = '[code=' . $matches[1] . ']';
|
||||
}
|
||||
$codeblocks[] = $prefix . trim($matches[2]) . '[/code]';
|
||||
return $return;
|
||||
},
|
||||
$message
|
||||
);
|
||||
|
||||
$message = str_replace(
|
||||
[
|
||||
"<li><p>",
|
||||
"</p></li>",
|
||||
],
|
||||
[
|
||||
"<li>",
|
||||
"</li>",
|
||||
],
|
||||
$message
|
||||
);
|
||||
|
||||
// remove namespaces
|
||||
$message = preg_replace('=<(\w+):(.+?)>=', '<removeme>', $message);
|
||||
$message = preg_replace('=</(\w+):(.+?)>=', '</removeme>', $message);
|
||||
|
||||
$doc = new DOMDocument();
|
||||
$doc->preserveWhiteSpace = false;
|
||||
|
||||
$message = mb_convert_encoding($message, 'HTML-ENTITIES', "UTF-8");
|
||||
|
||||
@$doc->loadHTML($message);
|
||||
|
||||
XML::deleteNode($doc, 'style');
|
||||
XML::deleteNode($doc, 'head');
|
||||
XML::deleteNode($doc, 'title');
|
||||
XML::deleteNode($doc, 'meta');
|
||||
XML::deleteNode($doc, 'xml');
|
||||
XML::deleteNode($doc, 'removeme');
|
||||
|
||||
$xpath = new DomXPath($doc);
|
||||
$list = $xpath->query("//pre");
|
||||
foreach ($list as $node) {
|
||||
$node->nodeValue = str_replace("\n", "\r", $node->nodeValue);
|
||||
}
|
||||
|
||||
$message = $doc->saveHTML();
|
||||
$message = str_replace(["\n<", ">\n", "\r", "\n", "\xC3\x82\xC2\xA0"], ["<", ">", "<br />", " ", ""], $message);
|
||||
$message = preg_replace('= [\s]*=i', " ", $message);
|
||||
@$doc->loadHTML($message);
|
||||
|
||||
node2bbcode($doc, 'html', [], "", "");
|
||||
node2bbcode($doc, 'body', [], "", "");
|
||||
|
||||
// Outlook-Quote - Variant 1
|
||||
node2bbcode($doc, 'p', ['class'=>'MsoNormal', 'style'=>'margin-left:35.4pt'], '[quote]', '[/quote]');
|
||||
|
||||
// Outlook-Quote - Variant 2
|
||||
node2bbcode($doc, 'div', ['style'=>'border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt'], '[quote]', '[/quote]');
|
||||
|
||||
// MyBB-Stuff
|
||||
node2bbcode($doc, 'span', ['style'=>'text-decoration: underline;'], '[u]', '[/u]');
|
||||
node2bbcode($doc, 'span', ['style'=>'font-style: italic;'], '[i]', '[/i]');
|
||||
node2bbcode($doc, 'span', ['style'=>'font-weight: bold;'], '[b]', '[/b]');
|
||||
|
||||
/*node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/', 'size'=>'/(\d+)/', 'color'=>'/(.+)/'), '[font=$1][size=$2][color=$3]', '[/color][/size][/font]');
|
||||
node2bbcode($doc, 'font', array('size'=>'/(\d+)/', 'color'=>'/(.+)/'), '[size=$1][color=$2]', '[/color][/size]');
|
||||
node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/', 'size'=>'/(.+)/'), '[font=$1][size=$2]', '[/size][/font]');
|
||||
node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/', 'color'=>'/(.+)/'), '[font=$1][color=$3]', '[/color][/font]');
|
||||
node2bbcode($doc, 'font', array('face'=>'/([\w ]+)/'), '[font=$1]', '[/font]');
|
||||
node2bbcode($doc, 'font', array('size'=>'/(\d+)/'), '[size=$1]', '[/size]');
|
||||
node2bbcode($doc, 'font', array('color'=>'/(.+)/'), '[color=$1]', '[/color]');
|
||||
*/
|
||||
// Untested
|
||||
//node2bbcode($doc, 'span', array('style'=>'/.*font-size:\s*(.+?)[,;].*font-family:\s*(.+?)[,;].*color:\s*(.+?)[,;].*/'), '[size=$1][font=$2][color=$3]', '[/color][/font][/size]');
|
||||
//node2bbcode($doc, 'span', array('style'=>'/.*font-size:\s*(\d+)[,;].*/'), '[size=$1]', '[/size]');
|
||||
//node2bbcode($doc, 'span', array('style'=>'/.*font-size:\s*(.+?)[,;].*/'), '[size=$1]', '[/size]');
|
||||
|
||||
node2bbcode($doc, 'span', ['style'=>'/.*color:\s*(.+?)[,;].*/'], '[color="$1"]', '[/color]');
|
||||
|
||||
//node2bbcode($doc, 'span', array('style'=>'/.*font-family:\s*(.+?)[,;].*/'), '[font=$1]', '[/font]');
|
||||
|
||||
//node2bbcode($doc, 'div', array('style'=>'/.*font-family:\s*(.+?)[,;].*font-size:\s*(\d+?)pt.*/'), '[font=$1][size=$2]', '[/size][/font]');
|
||||
//node2bbcode($doc, 'div', array('style'=>'/.*font-family:\s*(.+?)[,;].*font-size:\s*(\d+?)px.*/'), '[font=$1][size=$2]', '[/size][/font]');
|
||||
//node2bbcode($doc, 'div', array('style'=>'/.*font-family:\s*(.+?)[,;].*/'), '[font=$1]', '[/font]');
|
||||
|
||||
// Importing the classes - interesting for importing of posts from third party networks that were exported from friendica
|
||||
// Test
|
||||
//node2bbcode($doc, 'span', array('class'=>'/([\w ]+)/'), '[class=$1]', '[/class]');
|
||||
node2bbcode($doc, 'span', ['class'=>'type-link'], '[class=type-link]', '[/class]');
|
||||
node2bbcode($doc, 'span', ['class'=>'type-video'], '[class=type-video]', '[/class]');
|
||||
|
||||
node2bbcode($doc, 'strong', [], '[b]', '[/b]');
|
||||
node2bbcode($doc, 'em', [], '[i]', '[/i]');
|
||||
node2bbcode($doc, 'b', [], '[b]', '[/b]');
|
||||
node2bbcode($doc, 'i', [], '[i]', '[/i]');
|
||||
node2bbcode($doc, 'u', [], '[u]', '[/u]');
|
||||
|
||||
node2bbcode($doc, 'big', [], "[size=large]", "[/size]");
|
||||
node2bbcode($doc, 'small', [], "[size=small]", "[/size]");
|
||||
|
||||
node2bbcode($doc, 'blockquote', [], '[quote]', '[/quote]');
|
||||
|
||||
node2bbcode($doc, 'br', [], "\n", '');
|
||||
|
||||
node2bbcode($doc, 'p', ['class'=>'MsoNormal'], "\n", "");
|
||||
node2bbcode($doc, 'div', ['class'=>'MsoNormal'], "\r", "");
|
||||
|
||||
node2bbcode($doc, 'span', [], "", "");
|
||||
|
||||
node2bbcode($doc, 'span', [], "", "");
|
||||
node2bbcode($doc, 'pre', [], "", "");
|
||||
|
||||
node2bbcode($doc, 'div', [], "\r", "\r");
|
||||
node2bbcode($doc, 'p', [], "\n", "\n");
|
||||
|
||||
node2bbcode($doc, 'ul', [], "[list]", "[/list]");
|
||||
node2bbcode($doc, 'ol', [], "[list=1]", "[/list]");
|
||||
node2bbcode($doc, 'li', [], "[*]", "");
|
||||
|
||||
node2bbcode($doc, 'hr', [], "[hr]", "");
|
||||
|
||||
node2bbcode($doc, 'table', [], "", "");
|
||||
node2bbcode($doc, 'tr', [], "\n", "");
|
||||
node2bbcode($doc, 'td', [], "\t", "");
|
||||
//node2bbcode($doc, 'table', array(), "[table]", "[/table]");
|
||||
//node2bbcode($doc, 'th', array(), "[th]", "[/th]");
|
||||
//node2bbcode($doc, 'tr', array(), "[tr]", "[/tr]");
|
||||
//node2bbcode($doc, 'td', array(), "[td]", "[/td]");
|
||||
|
||||
//node2bbcode($doc, 'h1', array(), "\n\n[size=xx-large][b]", "[/b][/size]\n");
|
||||
//node2bbcode($doc, 'h2', array(), "\n\n[size=x-large][b]", "[/b][/size]\n");
|
||||
//node2bbcode($doc, 'h3', array(), "\n\n[size=large][b]", "[/b][/size]\n");
|
||||
//node2bbcode($doc, 'h4', array(), "\n\n[size=medium][b]", "[/b][/size]\n");
|
||||
//node2bbcode($doc, 'h5', array(), "\n\n[size=small][b]", "[/b][/size]\n");
|
||||
//node2bbcode($doc, 'h6', array(), "\n\n[size=x-small][b]", "[/b][/size]\n");
|
||||
|
||||
node2bbcode($doc, 'h1', [], "\n\n[h1]", "[/h1]\n");
|
||||
node2bbcode($doc, 'h2', [], "\n\n[h2]", "[/h2]\n");
|
||||
node2bbcode($doc, 'h3', [], "\n\n[h3]", "[/h3]\n");
|
||||
node2bbcode($doc, 'h4', [], "\n\n[h4]", "[/h4]\n");
|
||||
node2bbcode($doc, 'h5', [], "\n\n[h5]", "[/h5]\n");
|
||||
node2bbcode($doc, 'h6', [], "\n\n[h6]", "[/h6]\n");
|
||||
|
||||
node2bbcode($doc, 'a', ['href'=>'/mailto:(.+)/'], '[mail=$1]', '[/mail]');
|
||||
node2bbcode($doc, 'a', ['href'=>'/(.+)/'], '[url=$1]', '[/url]');
|
||||
|
||||
node2bbcode($doc, 'img', ['src'=>'/(.+)/', 'width'=>'/(\d+)/', 'height'=>'/(\d+)/'], '[img=$2x$3]$1', '[/img]');
|
||||
node2bbcode($doc, 'img', ['src'=>'/(.+)/'], '[img]$1', '[/img]');
|
||||
|
||||
|
||||
node2bbcode($doc, 'video', ['src'=>'/(.+)/'], '[video]$1', '[/video]');
|
||||
node2bbcode($doc, 'audio', ['src'=>'/(.+)/'], '[audio]$1', '[/audio]');
|
||||
node2bbcode($doc, 'iframe', ['src'=>'/(.+)/'], '[iframe]$1', '[/iframe]');
|
||||
|
||||
node2bbcode($doc, 'key', [], '[code]', '[/code]');
|
||||
node2bbcode($doc, 'code', [], '[code]', '[/code]');
|
||||
|
||||
$message = $doc->saveHTML();
|
||||
|
||||
// I'm removing something really disturbing
|
||||
// Don't know exactly what it is
|
||||
$message = str_replace(chr(194).chr(160), ' ', $message);
|
||||
|
||||
$message = str_replace(" ", " ", $message);
|
||||
|
||||
// removing multiple DIVs
|
||||
$message = preg_replace('=\r *\r=i', "\n", $message);
|
||||
$message = str_replace("\r", "\n", $message);
|
||||
|
||||
Addon::callHooks('html2bbcode', $message);
|
||||
|
||||
$message = strip_tags($message);
|
||||
|
||||
$message = html_entity_decode($message, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
$message = str_replace(["<"], ["<"], $message);
|
||||
|
||||
// remove quotes if they don't make sense
|
||||
$message = preg_replace('=\[/quote\][\s]*\[quote\]=i', "\n", $message);
|
||||
|
||||
$message = preg_replace('=\[quote\]\s*=i', "[quote]", $message);
|
||||
$message = preg_replace('=\s*\[/quote\]=i', "[/quote]", $message);
|
||||
|
||||
do {
|
||||
$oldmessage = $message;
|
||||
$message = str_replace("\n \n", "\n\n", $message);
|
||||
} while ($oldmessage != $message);
|
||||
|
||||
do {
|
||||
$oldmessage = $message;
|
||||
$message = str_replace("\n\n\n", "\n\n", $message);
|
||||
} while ($oldmessage != $message);
|
||||
|
||||
do {
|
||||
$oldmessage = $message;
|
||||
$message = str_replace(
|
||||
[
|
||||
"[/size]\n\n",
|
||||
"\n[hr]",
|
||||
"[hr]\n",
|
||||
"\n[list",
|
||||
"[/list]\n",
|
||||
"\n[/",
|
||||
"[list]\n",
|
||||
"[list=1]\n",
|
||||
"\n[*]"],
|
||||
[
|
||||
"[/size]\n",
|
||||
"[hr]",
|
||||
"[hr]",
|
||||
"[list",
|
||||
"[/list]",
|
||||
"[/",
|
||||
"[list]",
|
||||
"[list=1]",
|
||||
"[*]"],
|
||||
$message
|
||||
);
|
||||
} while ($message != $oldmessage);
|
||||
|
||||
$message = str_replace(
|
||||
['[b][b]', '[/b][/b]', '[i][i]', '[/i][/i]'],
|
||||
['[b]', '[/b]', '[i]', '[/i]'],
|
||||
$message
|
||||
);
|
||||
|
||||
// Handling Yahoo style of mails
|
||||
$message = str_replace('[hr][b]From:[/b]', '[quote][b]From:[/b]', $message);
|
||||
|
||||
// Restore code blocks
|
||||
$message = preg_replace_callback(
|
||||
'#\[codeblock-([0-9]+)\]#iU',
|
||||
function ($matches) use ($codeblocks) {
|
||||
$return = '';
|
||||
if (isset($codeblocks[intval($matches[1])])) {
|
||||
$return = $codeblocks[$matches[1]];
|
||||
}
|
||||
return $return;
|
||||
},
|
||||
$message
|
||||
);
|
||||
|
||||
$message = trim($message);
|
||||
|
||||
if ($basepath != '') {
|
||||
$message = addHostname($message, $basepath);
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sub function to complete incomplete URL
|
||||
*
|
||||
* @param array $matches Result of preg_replace_callback
|
||||
* @param string $basepath Basepath that is used to complete the URL
|
||||
*
|
||||
* @return string The expanded URL
|
||||
*/
|
||||
function addHostnameSub($matches, $basepath)
|
||||
{
|
||||
$base = parse_url($basepath);
|
||||
unset($base['query']);
|
||||
unset($base['fragment']);
|
||||
|
||||
$link = $matches[0];
|
||||
$url = $matches[1];
|
||||
|
||||
$parts = array_merge($base, parse_url($url));
|
||||
$url2 = Network::unparseURL($parts);
|
||||
|
||||
return str_replace($url, $url2, $link);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Complete incomplete URLs in BBCode
|
||||
*
|
||||
* @param string $body Body with URLs
|
||||
* @param string $basepath Basepath that is used to complete the URL
|
||||
*
|
||||
* @return string Body with expanded URLs
|
||||
*/
|
||||
function addHostname($body, $basepath)
|
||||
{
|
||||
$URLSearchString = "^\[\]";
|
||||
|
||||
$matches = ["/\[url\=([$URLSearchString]*)\].*?\[\/url\]/ism",
|
||||
"/\[url\]([$URLSearchString]*)\[\/url\]/ism",
|
||||
"/\[img\=[0-9]*x[0-9]*\](.*?)\[\/img\]/ism",
|
||||
"/\[img\](.*?)\[\/img\]/ism",
|
||||
"/\[zmg\=[0-9]*x[0-9]*\](.*?)\[\/img\]/ism",
|
||||
"/\[zmg\](.*?)\[\/zmg\]/ism",
|
||||
"/\[video\](.*?)\[\/video\]/ism",
|
||||
"/\[audio\](.*?)\[\/audio\]/ism",
|
||||
];
|
||||
|
||||
foreach ($matches as $match) {
|
||||
$body = preg_replace_callback(
|
||||
$match,
|
||||
function ($match) use ($basepath) {
|
||||
return addHostnameSub($match, $basepath);
|
||||
},
|
||||
$body
|
||||
);
|
||||
}
|
||||
return $body;
|
||||
}
|
|
@ -1,246 +0,0 @@
|
|||
<?php
|
||||
|
||||
require_once 'include/html2bbcode.php';
|
||||
|
||||
function breaklines($line, $level, $wraplength = 75)
|
||||
{
|
||||
if ($wraplength == 0) {
|
||||
$wraplength = 2000000;
|
||||
}
|
||||
|
||||
$wraplen = $wraplength - $level;
|
||||
|
||||
$newlines = [];
|
||||
|
||||
do {
|
||||
$oldline = $line;
|
||||
|
||||
$subline = substr($line, 0, $wraplen);
|
||||
|
||||
$pos = strrpos($subline, ' ');
|
||||
|
||||
if ($pos == 0) {
|
||||
$pos = strpos($line, ' ');
|
||||
}
|
||||
|
||||
if (($pos > 0) && strlen($line) > $wraplen) {
|
||||
$newline = trim(substr($line, 0, $pos));
|
||||
if ($level > 0) {
|
||||
$newline = str_repeat(">", $level) . ' ' . $newline;
|
||||
}
|
||||
|
||||
$newlines[] = $newline . " ";
|
||||
$line = substr($line, $pos + 1);
|
||||
}
|
||||
} while ((strlen($line) > $wraplen) && !($oldline == $line));
|
||||
|
||||
if ($level > 0) {
|
||||
$line = str_repeat(">", $level) . ' ' . $line;
|
||||
}
|
||||
|
||||
$newlines[] = $line;
|
||||
|
||||
return implode($newlines, "\n");
|
||||
}
|
||||
|
||||
function quotelevel($message, $wraplength = 75)
|
||||
{
|
||||
$lines = explode("\n", $message);
|
||||
|
||||
$newlines = [];
|
||||
$level = 0;
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
$startquote = false;
|
||||
while (strpos("*" . $line, '[quote]') > 0) {
|
||||
$level++;
|
||||
$pos = strpos($line, '[quote]');
|
||||
$line = substr($line, 0, $pos) . substr($line, $pos + 7);
|
||||
$startquote = true;
|
||||
}
|
||||
|
||||
$currlevel = $level;
|
||||
|
||||
while (strpos("*" . $line, '[/quote]') > 0) {
|
||||
$level--;
|
||||
if ($level < 0) {
|
||||
$level = 0;
|
||||
}
|
||||
|
||||
$pos = strpos($line, '[/quote]');
|
||||
$line = substr($line, 0, $pos) . substr($line, $pos + 8);
|
||||
}
|
||||
|
||||
if (!$startquote || ($line != '')) {
|
||||
$newlines[] = breaklines($line, $currlevel, $wraplength);
|
||||
}
|
||||
}
|
||||
|
||||
return implode($newlines, "\n");
|
||||
}
|
||||
|
||||
function collecturls($message)
|
||||
{
|
||||
$pattern = '/<a.*?href="(.*?)".*?>(.*?)<\/a>/is';
|
||||
preg_match_all($pattern, $message, $result, PREG_SET_ORDER);
|
||||
|
||||
$urls = [];
|
||||
foreach ($result as $treffer) {
|
||||
$ignore = false;
|
||||
|
||||
// A list of some links that should be ignored
|
||||
$list = ["/user/", "/tag/", "/group/", "/profile/", "/search?search=", "/search?tag=", "mailto:", "/u/", "/node/",
|
||||
"//facebook.com/profile.php?id=", "//plus.google.com/", "//twitter.com/"];
|
||||
foreach ($list as $listitem) {
|
||||
if (strpos($treffer[1], $listitem) !== false) {
|
||||
$ignore = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((strpos($treffer[1], "//twitter.com/") !== false) && (strpos($treffer[1], "/status/") !== false)) {
|
||||
$ignore = false;
|
||||
}
|
||||
|
||||
if ((strpos($treffer[1], "//plus.google.com/") !== false) && (strpos($treffer[1], "/posts") !== false)) {
|
||||
$ignore = false;
|
||||
}
|
||||
|
||||
if ((strpos($treffer[1], "//plus.google.com/") !== false) && (strpos($treffer[1], "/photos") !== false)) {
|
||||
$ignore = false;
|
||||
}
|
||||
|
||||
if (!$ignore) {
|
||||
$urls[$treffer[1]] = $treffer[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $urls;
|
||||
}
|
||||
|
||||
function html2plain($html, $wraplength = 75, $compact = false)
|
||||
{
|
||||
global $lang;
|
||||
|
||||
$message = str_replace("\r", "", $html);
|
||||
|
||||
$doc = new DOMDocument();
|
||||
$doc->preserveWhiteSpace = false;
|
||||
|
||||
$message = mb_convert_encoding($message, 'HTML-ENTITIES', "UTF-8");
|
||||
|
||||
@$doc->loadHTML($message);
|
||||
|
||||
$xpath = new DomXPath($doc);
|
||||
$list = $xpath->query("//pre");
|
||||
foreach ($list as $node) {
|
||||
$node->nodeValue = str_replace("\n", "\r", $node->nodeValue);
|
||||
}
|
||||
|
||||
$message = $doc->saveHTML();
|
||||
$message = str_replace(["\n<", ">\n", "\r", "\n", "\xC3\x82\xC2\xA0"], ["<", ">", "<br>", " ", ""], $message);
|
||||
$message = preg_replace('= [\s]*=i', " ", $message);
|
||||
|
||||
// Collecting all links
|
||||
$urls = collecturls($message);
|
||||
|
||||
@$doc->loadHTML($message);
|
||||
|
||||
node2bbcode($doc, 'html', [], '', '');
|
||||
node2bbcode($doc, 'body', [], '', '');
|
||||
|
||||
// MyBB-Auszeichnungen
|
||||
/*
|
||||
node2bbcode($doc, 'span', array('style'=>'text-decoration: underline;'), '_', '_');
|
||||
node2bbcode($doc, 'span', array('style'=>'font-style: italic;'), '/', '/');
|
||||
node2bbcode($doc, 'span', array('style'=>'font-weight: bold;'), '*', '*');
|
||||
|
||||
node2bbcode($doc, 'strong', array(), '*', '*');
|
||||
node2bbcode($doc, 'b', array(), '*', '*');
|
||||
node2bbcode($doc, 'i', array(), '/', '/');
|
||||
node2bbcode($doc, 'u', array(), '_', '_');
|
||||
*/
|
||||
|
||||
if ($compact) {
|
||||
node2bbcode($doc, 'blockquote', [], "»", "«");
|
||||
} else {
|
||||
node2bbcode($doc, 'blockquote', [], '[quote]', "[/quote]\n");
|
||||
}
|
||||
|
||||
node2bbcode($doc, 'br', [], "\n", '');
|
||||
|
||||
node2bbcode($doc, 'span', [], "", "");
|
||||
node2bbcode($doc, 'pre', [], "", "");
|
||||
node2bbcode($doc, 'div', [], "\r", "\r");
|
||||
node2bbcode($doc, 'p', [], "\n", "\n");
|
||||
|
||||
//node2bbcode($doc, 'ul', array(), "\n[list]", "[/list]\n");
|
||||
//node2bbcode($doc, 'ol', array(), "\n[list=1]", "[/list]\n");
|
||||
node2bbcode($doc, 'li', [], "\n* ", "\n");
|
||||
|
||||
node2bbcode($doc, 'hr', [], "\n" . str_repeat("-", 70) . "\n", "");
|
||||
|
||||
node2bbcode($doc, 'tr', [], "\n", "");
|
||||
node2bbcode($doc, 'td', [], "\t", "");
|
||||
|
||||
node2bbcode($doc, 'h1', [], "\n\n*", "*\n");
|
||||
node2bbcode($doc, 'h2', [], "\n\n*", "*\n");
|
||||
node2bbcode($doc, 'h3', [], "\n\n*", "*\n");
|
||||
node2bbcode($doc, 'h4', [], "\n\n*", "*\n");
|
||||
node2bbcode($doc, 'h5', [], "\n\n*", "*\n");
|
||||
node2bbcode($doc, 'h6', [], "\n\n*", "*\n");
|
||||
|
||||
// Problem: there is no reliable way to detect if it is a link to a tag or profile
|
||||
//node2bbcode($doc, 'a', array('href'=>'/(.+)/'), ' $1 ', ' ', true);
|
||||
//node2bbcode($doc, 'a', array('href'=>'/(.+)/', 'rel'=>'oembed'), ' $1 ', '', true);
|
||||
//node2bbcode($doc, 'img', array('alt'=>'/(.+)/'), '$1', '');
|
||||
//node2bbcode($doc, 'img', array('title'=>'/(.+)/'), '$1', '');
|
||||
//node2bbcode($doc, 'img', array(), '', '');
|
||||
if (!$compact) {
|
||||
node2bbcode($doc, 'img', ['src' => '/(.+)/'], ' [img]$1', '[/img] ');
|
||||
} else {
|
||||
node2bbcode($doc, 'img', ['src' => '/(.+)/'], ' ', ' ');
|
||||
}
|
||||
|
||||
node2bbcode($doc, 'iframe', ['src' => '/(.+)/'], ' $1 ', '');
|
||||
|
||||
$message = $doc->saveHTML();
|
||||
|
||||
if (!$compact) {
|
||||
$message = str_replace("[img]", "", $message);
|
||||
$message = str_replace("[/img]", "", $message);
|
||||
}
|
||||
|
||||
// was ersetze ich da?
|
||||
// Irgendein stoerrisches UTF-Zeug
|
||||
$message = str_replace(chr(194) . chr(160), ' ', $message);
|
||||
|
||||
$message = str_replace(" ", " ", $message);
|
||||
|
||||
// Aufeinanderfolgende DIVs
|
||||
$message = preg_replace('=\r *\r=i', "\n", $message);
|
||||
$message = str_replace("\r", "\n", $message);
|
||||
|
||||
$message = strip_tags($message);
|
||||
|
||||
$message = html_entity_decode($message, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
if (!$compact && ($message != '')) {
|
||||
foreach ($urls as $id => $url) {
|
||||
if ($url != '' && strpos($message, $url) === false) {
|
||||
$message .= "\n" . $url . ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$message = str_replace("\n«", "«\n", $message);
|
||||
$message = str_replace("»\n", "\n»", $message);
|
||||
|
||||
do {
|
||||
$oldmessage = $message;
|
||||
$message = str_replace("\n\n\n", "\n\n", $message);
|
||||
} while ($oldmessage != $message);
|
||||
|
||||
$message = quotelevel(trim($message), $wraplength);
|
||||
|
||||
return trim($message);
|
||||
}
|
|
@ -14,6 +14,7 @@ use Friendica\Core\L10n;
|
|||
use Friendica\Core\PConfig;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Model\Event;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Profile;
|
||||
use Friendica\Render\FriendicaSmarty;
|
||||
|
@ -21,7 +22,6 @@ use Friendica\Util\DateTimeFormat;
|
|||
use Friendica\Util\Map;
|
||||
|
||||
require_once "mod/proxy.php";
|
||||
require_once "include/event.php";
|
||||
require_once "include/conversation.php";
|
||||
|
||||
/**
|
||||
|
@ -1235,7 +1235,7 @@ function prepare_body(&$item, $attach = false, $preview = false) {
|
|||
// In order to provide theme developers more possibilities, event items
|
||||
// are treated differently.
|
||||
if ($item['object-type'] === ACTIVITY_OBJ_EVENT && isset($item['event-id'])) {
|
||||
$ev = format_event_item($item);
|
||||
$ev = Event::getItemHTML($item);
|
||||
return $ev;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,9 +24,7 @@ use Friendica\Module\Login;
|
|||
|
||||
require_once 'boot.php';
|
||||
|
||||
if (empty($a)) {
|
||||
$a = new App(__DIR__);
|
||||
}
|
||||
BaseObject::setApp($a);
|
||||
|
||||
// We assume that the index.php is called by a frontend process
|
||||
|
@ -53,9 +51,13 @@ if (!$install) {
|
|||
require_once "include/dba.php";
|
||||
|
||||
if (!$install) {
|
||||
dba::connect($db_host, $db_user, $db_pass, $db_data, $install);
|
||||
$result = dba::connect($db_host, $db_user, $db_pass, $db_data);
|
||||
unset($db_host, $db_user, $db_pass, $db_data);
|
||||
|
||||
if (!$result) {
|
||||
System::unavailable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load configs from db. Overwrite configs from .htconfig.php
|
||||
*/
|
||||
|
@ -78,6 +80,7 @@ if (!$install) {
|
|||
exit();
|
||||
}
|
||||
|
||||
Config::init();
|
||||
Session::init();
|
||||
Addon::loadHooks();
|
||||
Addon::callHooks('init_1');
|
||||
|
|
309
mod/acl.php
309
mod/acl.php
|
@ -1,12 +1,315 @@
|
|||
<?php
|
||||
|
||||
/* ACL selector json backend */
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Content\Widget;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Model\Contact;
|
||||
|
||||
require_once 'include/acl_selectors.php';
|
||||
require_once 'include/dba.php';
|
||||
require_once 'mod/proxy.php';
|
||||
|
||||
function acl_init(App $a) {
|
||||
acl_lookup($a);
|
||||
function acl_content(App $a)
|
||||
{
|
||||
if (!local_user()) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$start = defaults($_REQUEST, 'start' , 0);
|
||||
$count = defaults($_REQUEST, 'count' , 100);
|
||||
$search = defaults($_REQUEST, 'search' , '');
|
||||
$type = defaults($_REQUEST, 'type' , '');
|
||||
$conv_id = defaults($_REQUEST, 'conversation', null);
|
||||
|
||||
// For use with jquery.textcomplete for private mail completion
|
||||
if (!empty($_REQUEST['query'])) {
|
||||
if (!$type) {
|
||||
$type = 'm';
|
||||
}
|
||||
$search = $_REQUEST['query'];
|
||||
}
|
||||
|
||||
logger("Searching for ".$search." - type ".$type." conversation ".$conv_id, LOGGER_DEBUG);
|
||||
|
||||
if ($search != '') {
|
||||
$sql_extra = "AND `name` LIKE '%%" . dbesc($search) . "%%'";
|
||||
$sql_extra2 = "AND (`attag` LIKE '%%" . dbesc($search) . "%%' OR `name` LIKE '%%" . dbesc($search) . "%%' OR `nick` LIKE '%%" . dbesc($search) . "%%')";
|
||||
} else {
|
||||
/// @TODO Avoid these needless else blocks by putting variable-initialization atop of if()
|
||||
$sql_extra = $sql_extra2 = '';
|
||||
}
|
||||
|
||||
// count groups and contacts
|
||||
$group_count = 0;
|
||||
if ($type == '' || $type == 'g') {
|
||||
$r = q("SELECT COUNT(*) AS g FROM `group` WHERE `deleted` = 0 AND `uid` = %d $sql_extra",
|
||||
intval(local_user())
|
||||
);
|
||||
$group_count = (int) $r[0]['g'];
|
||||
}
|
||||
|
||||
$sql_extra2 .= ' ' . Widget::unavailableNetworks();
|
||||
|
||||
$contact_count = 0;
|
||||
if ($type == '' || $type == 'c') {
|
||||
// autocomplete for editor mentions
|
||||
$r = q("SELECT COUNT(*) AS c FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self`
|
||||
AND NOT `blocked` AND NOT `pending` AND NOT `archive`
|
||||
AND `success_update` >= `failure_update`
|
||||
AND `notify` != '' $sql_extra2",
|
||||
intval(local_user())
|
||||
);
|
||||
$contact_count = (int) $r[0]['c'];
|
||||
} elseif ($type == 'f') {
|
||||
// autocomplete for editor mentions of forums
|
||||
$r = q("SELECT COUNT(*) AS c FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self`
|
||||
AND NOT `blocked` AND NOT `pending` AND NOT `archive`
|
||||
AND (`forum` OR `prv`)
|
||||
AND `success_update` >= `failure_update`
|
||||
AND `notify` != '' $sql_extra2",
|
||||
intval(local_user())
|
||||
);
|
||||
$contact_count = (int) $r[0]['c'];
|
||||
} elseif ($type == 'm') {
|
||||
// autocomplete for Private Messages
|
||||
$r = q("SELECT COUNT(*) AS c FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self`
|
||||
AND NOT `blocked` AND NOT `pending` AND NOT `archive`
|
||||
AND `success_update` >= `failure_update`
|
||||
AND `network` IN ('%s', '%s') $sql_extra2",
|
||||
intval(local_user()),
|
||||
dbesc(NETWORK_DFRN),
|
||||
dbesc(NETWORK_DIASPORA)
|
||||
);
|
||||
$contact_count = (int) $r[0]['c'];
|
||||
} elseif ($type == 'a') {
|
||||
// autocomplete for Contacts
|
||||
$r = q("SELECT COUNT(*) AS c FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self`
|
||||
AND NOT `pending` $sql_extra2",
|
||||
intval(local_user())
|
||||
);
|
||||
$contact_count = (int) $r[0]['c'];
|
||||
}
|
||||
|
||||
$tot = $group_count + $contact_count;
|
||||
|
||||
$groups = [];
|
||||
$contacts = [];
|
||||
|
||||
if ($type == '' || $type == 'g') {
|
||||
/// @todo We should cache this query.
|
||||
// This can be done when we can delete cache entries via wildcard
|
||||
$r = q("SELECT `group`.`id`, `group`.`name`, GROUP_CONCAT(DISTINCT `group_member`.`contact-id` SEPARATOR ',') AS uids
|
||||
FROM `group`
|
||||
INNER JOIN `group_member` ON `group_member`.`gid`=`group`.`id`
|
||||
WHERE NOT `group`.`deleted` AND `group`.`uid` = %d
|
||||
$sql_extra
|
||||
GROUP BY `group`.`name`, `group`.`id`
|
||||
ORDER BY `group`.`name`
|
||||
LIMIT %d,%d",
|
||||
intval(local_user()),
|
||||
intval($start),
|
||||
intval($count)
|
||||
);
|
||||
|
||||
foreach ($r as $g) {
|
||||
$groups[] = [
|
||||
'type' => 'g',
|
||||
'photo' => 'images/twopeople.png',
|
||||
'name' => htmlentities($g['name']),
|
||||
'id' => intval($g['id']),
|
||||
'uids' => array_map('intval', explode(',', $g['uids'])),
|
||||
'link' => '',
|
||||
'forum' => '0'
|
||||
];
|
||||
}
|
||||
if ((count($groups) > 0) && ($search == '')) {
|
||||
$groups[] = ['separator' => true];
|
||||
}
|
||||
}
|
||||
|
||||
$r = [];
|
||||
if ($type == '') {
|
||||
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv`, (`prv` OR `forum`) AS `frm` FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
|
||||
AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s', '%s'))
|
||||
$sql_extra2
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user()),
|
||||
dbesc(NETWORK_OSTATUS),
|
||||
dbesc(NETWORK_STATUSNET)
|
||||
);
|
||||
} elseif ($type == 'c') {
|
||||
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
|
||||
AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
|
||||
$sql_extra2
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user()),
|
||||
dbesc(NETWORK_STATUSNET)
|
||||
);
|
||||
} elseif ($type == 'f') {
|
||||
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
|
||||
AND `success_update` >= `failure_update` AND NOT (`network` IN ('%s'))
|
||||
AND (`forum` OR `prv`)
|
||||
$sql_extra2
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user()),
|
||||
dbesc(NETWORK_STATUSNET)
|
||||
);
|
||||
} elseif ($type == 'm') {
|
||||
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr` FROM `contact`
|
||||
WHERE `uid` = %d AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive`
|
||||
AND `success_update` >= `failure_update` AND `network` IN ('%s', '%s')
|
||||
$sql_extra2
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user()),
|
||||
dbesc(NETWORK_DFRN),
|
||||
dbesc(NETWORK_DIASPORA)
|
||||
);
|
||||
} elseif ($type == 'a') {
|
||||
$r = q("SELECT `id`, `name`, `nick`, `micro`, `network`, `url`, `attag`, `addr`, `forum`, `prv` FROM `contact`
|
||||
WHERE `uid` = %d AND `pending` = 0 AND `success_update` >= `failure_update`
|
||||
$sql_extra2
|
||||
ORDER BY `name` ASC ",
|
||||
intval(local_user())
|
||||
);
|
||||
} elseif ($type == 'x') {
|
||||
// autocomplete for global contact search (e.g. navbar search)
|
||||
$search = notags(trim($_REQUEST['search']));
|
||||
$mode = $_REQUEST['smode'];
|
||||
|
||||
$r = ACL::contactAutocomplete($search, $mode);
|
||||
|
||||
$contacts = [];
|
||||
foreach ($r as $g) {
|
||||
$contacts[] = [
|
||||
'photo' => proxy_url($g['photo'], false, PROXY_SIZE_MICRO),
|
||||
'name' => $g['name'],
|
||||
'nick' => defaults($g, 'addr', $g['url']),
|
||||
'network' => $g['network'],
|
||||
'link' => $g['url'],
|
||||
'forum' => !empty($g['community']) ? 1 : 0,
|
||||
];
|
||||
}
|
||||
$o = [
|
||||
'start' => $start,
|
||||
'count' => $count,
|
||||
'items' => $contacts,
|
||||
];
|
||||
echo json_encode($o);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (DBM::is_result($r)) {
|
||||
$forums = [];
|
||||
foreach ($r as $g) {
|
||||
$entry = [
|
||||
'type' => 'c',
|
||||
'photo' => proxy_url($g['micro'], false, PROXY_SIZE_MICRO),
|
||||
'name' => htmlentities($g['name']),
|
||||
'id' => intval($g['id']),
|
||||
'network' => $g['network'],
|
||||
'link' => $g['url'],
|
||||
'nick' => htmlentities(defaults($g, 'attag', $g['nick'])),
|
||||
'addr' => htmlentities(defaults($g, 'addr', $g['url'])),
|
||||
'forum' => !empty($g['forum']) || !empty($g['prv']) ? 1 : 0,
|
||||
];
|
||||
if ($entry['forum']) {
|
||||
$forums[] = $entry;
|
||||
} else {
|
||||
$contacts[] = $entry;
|
||||
}
|
||||
}
|
||||
if (count($forums) > 0) {
|
||||
if ($search == '') {
|
||||
$forums[] = ['separator' => true];
|
||||
}
|
||||
$contacts = array_merge($forums, $contacts);
|
||||
}
|
||||
}
|
||||
|
||||
$items = array_merge($groups, $contacts);
|
||||
|
||||
if ($conv_id) {
|
||||
// In multi threaded posts the conv_id is not the parent of the whole thread
|
||||
$parent_item = dba::selectFirst('item', ['parent'], ['id' => $conv_id]);
|
||||
if (DBM::is_result($parent_item)) {
|
||||
$conv_id = $parent_item['parent'];
|
||||
}
|
||||
|
||||
/*
|
||||
* if $conv_id is set, get unknown contacts in thread
|
||||
* but first get known contacts url to filter them out
|
||||
*/
|
||||
$known_contacts = array_map(function ($i) {
|
||||
return dbesc($i['link']);
|
||||
}, $contacts);
|
||||
|
||||
$unknown_contacts = [];
|
||||
$r = q("SELECT `author-link`
|
||||
FROM `item` WHERE `parent` = %d
|
||||
AND (`author-name` LIKE '%%%s%%' OR `author-link` LIKE '%%%s%%')
|
||||
AND `author-link` NOT IN ('%s')
|
||||
GROUP BY `author-link`, `author-avatar`, `author-name`
|
||||
ORDER BY `author-name` ASC
|
||||
",
|
||||
intval($conv_id),
|
||||
dbesc($search),
|
||||
dbesc($search),
|
||||
implode("', '", $known_contacts)
|
||||
);
|
||||
if (DBM::is_result($r)) {
|
||||
foreach ($r as $row) {
|
||||
$contact = Contact::getDetailsByURL($row['author-link']);
|
||||
|
||||
if (count($contact) > 0) {
|
||||
$unknown_contacts[] = [
|
||||
'type' => 'c',
|
||||
'photo' => proxy_url($contact['micro'], false, PROXY_SIZE_MICRO),
|
||||
'name' => htmlentities($contact['name']),
|
||||
'id' => intval($contact['cid']),
|
||||
'network' => $contact['network'],
|
||||
'link' => $contact['url'],
|
||||
'nick' => htmlentities(defaults($contact, 'nick', $contact['addr'])),
|
||||
'addr' => htmlentities(defaults($contact, 'addr', $contact['url'])),
|
||||
'forum' => $contact['forum']
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$items = array_merge($items, $unknown_contacts);
|
||||
$tot += count($unknown_contacts);
|
||||
}
|
||||
|
||||
$results = [
|
||||
'tot' => $tot,
|
||||
'start' => $start,
|
||||
'count' => $count,
|
||||
'groups' => $groups,
|
||||
'contacts' => $contacts,
|
||||
'items' => $items,
|
||||
'type' => $type,
|
||||
'search' => $search,
|
||||
];
|
||||
|
||||
Addon::callHooks('acl_lookup_end', $results);
|
||||
|
||||
$o = [
|
||||
'tot' => $results['tot'],
|
||||
'start' => $results['start'],
|
||||
'count' => $results['count'],
|
||||
'items' => $results['items'],
|
||||
];
|
||||
|
||||
echo json_encode($o);
|
||||
exit;
|
||||
}
|
||||
|
|
|
@ -718,7 +718,7 @@ function admin_page_summary(App $a)
|
|||
$warningtext = [];
|
||||
if (DBM::is_result($r)) {
|
||||
$showwarning = true;
|
||||
$warningtext[] = L10n::t('Your DB still runs with MyISAM tables. You should change the engine type to InnoDB. As Friendica will use InnoDB only features in the future, you should change this! See <a href="%s">here</a> for a guide that may be helpful converting the table engines. You may also use the command <tt>php scripts/dbstructure.php toinnodb</tt> of your Friendica installation for an automatic conversion.<br />', 'https://dev.mysql.com/doc/refman/5.7/en/converting-tables-to-innodb.html');
|
||||
$warningtext[] = L10n::t('Your DB still runs with MyISAM tables. You should change the engine type to InnoDB. As Friendica will use InnoDB only features in the future, you should change this! See <a href="%s">here</a> for a guide that may be helpful converting the table engines. You may also use the command <tt>php bin/console.php dbstructure toinnodb</tt> of your Friendica installation for an automatic conversion.<br />', 'https://dev.mysql.com/doc/refman/5.7/en/converting-tables-to-innodb.html');
|
||||
}
|
||||
// Check if github.com/friendica/master/VERSION is higher then
|
||||
// the local version of Friendica. Check is opt-in, source may be master or devel branch
|
||||
|
@ -735,7 +735,7 @@ function admin_page_summary(App $a)
|
|||
}
|
||||
if (Config::get('system', 'dbupdate') == DB_UPDATE_FAILED) {
|
||||
$showwarning = true;
|
||||
$warningtext[] = L10n::t('The database update failed. Please run "php scripts/dbstructure.php update" from the command line and have a look at the errors that might appear.');
|
||||
$warningtext[] = L10n::t('The database update failed. Please run "php bin/console.php dbstructure update" from the command line and have a look at the errors that might appear.');
|
||||
}
|
||||
|
||||
$last_worker_call = Config::get('system', 'last_poller_execution', false);
|
||||
|
|
136
mod/babel.php
136
mod/babel.php
|
@ -3,13 +3,9 @@
|
|||
* @file mod/babel.php
|
||||
*/
|
||||
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Content\Text\Markdown;
|
||||
use Friendica\Content\Text;
|
||||
use Friendica\Core\L10n;
|
||||
|
||||
require_once 'include/bb2diaspora.php';
|
||||
require_once 'include/html2bbcode.php';
|
||||
|
||||
function visible_lf($s)
|
||||
{
|
||||
return str_replace("\n", '<br />', $s);
|
||||
|
@ -17,64 +13,104 @@ function visible_lf($s)
|
|||
|
||||
function babel_content()
|
||||
{
|
||||
$o = '<h1>Babel Diagnostic</h1>';
|
||||
$results = [];
|
||||
if (!empty($_REQUEST['text'])) {
|
||||
switch (defaults($_REQUEST, 'type', 'bbcode')) {
|
||||
case 'bbcode':
|
||||
$bbcode = trim($_REQUEST['text']);
|
||||
$results[] = [
|
||||
'title' => L10n::t('Source input'),
|
||||
'content' => visible_lf($bbcode)
|
||||
];
|
||||
|
||||
$o .= '<form action="babel" method="post">';
|
||||
$o .= L10n::t("Source \x28bbcode\x29 text:") . EOL;
|
||||
$o .= '<textarea name="text" cols="80" rows="10">' . htmlspecialchars($_REQUEST['text']) . '</textarea>' . EOL;
|
||||
$o .= '<input type="submit" name="submit" value="Submit" /></form>';
|
||||
$html = Text\BBCode::convert($bbcode);
|
||||
$results[] = [
|
||||
'title' => L10n::t("BBCode::convert \x28raw HTML\x28"),
|
||||
'content' => htmlspecialchars($html)
|
||||
];
|
||||
|
||||
$o .= '<br /><br />';
|
||||
$results[] = [
|
||||
'title' => L10n::t('BBCode::convert'),
|
||||
'content' => $html
|
||||
];
|
||||
|
||||
$o .= '<form action="babel" method="post">';
|
||||
$o .= L10n::t("Source \x28Diaspora\x29 text to convert to BBcode:") . EOL;
|
||||
$o .= '<textarea name="d2bbtext" cols="80" rows="10">' . htmlspecialchars($_REQUEST['d2bbtext']) . '</textarea>' . EOL;
|
||||
$o .= '<input type="submit" name="submit" value="Submit" /></form>';
|
||||
$bbcode2 = Text\HTML::toBBCode($html);
|
||||
$results[] = [
|
||||
'title' => L10n::t('BBCode::convert => HTML::toBBCode'),
|
||||
'content' => visible_lf($bbcode2)
|
||||
];
|
||||
|
||||
$o .= '<br /><br />';
|
||||
$markdown = Text\BBCode::toMarkdown($bbcode);
|
||||
$results[] = [
|
||||
'title' => L10n::t('BBCode::toMarkdown'),
|
||||
'content' => visible_lf($markdown)
|
||||
];
|
||||
|
||||
if (x($_REQUEST, 'text')) {
|
||||
$text = trim($_REQUEST['text']);
|
||||
$o .= '<h2>' . L10n::t('Source input: ') . '</h2>' . EOL . EOL;
|
||||
$o .= visible_lf($text) . EOL . EOL;
|
||||
$html2 = Text\Markdown::convert($markdown);
|
||||
$results[] = [
|
||||
'title' => L10n::t('BBCode::toMarkdown => Markdown::convert'),
|
||||
'content' => $html2
|
||||
];
|
||||
|
||||
$html = BBCode::convert($text);
|
||||
$o .= '<h2>' . L10n::t("bbcode \x28raw HTML\x29: ") . '</h2>' . EOL . EOL;
|
||||
$o .= htmlspecialchars($html) . EOL . EOL;
|
||||
$bbcode3 = Text\Markdown::toBBCode($markdown);
|
||||
$results[] = [
|
||||
'title' => L10n::t('BBCode::toMarkdown => Markdown::toBBCode'),
|
||||
'content' => visible_lf($bbcode3)
|
||||
];
|
||||
|
||||
$o .= '<h2>' . L10n::t('bbcode: ') . '</h2>' . EOL . EOL;
|
||||
$o .= $html . EOL . EOL;
|
||||
$bbcode4 = Text\HTML::toBBCode($html2);
|
||||
$results[] = [
|
||||
'title' => L10n::t('BBCode::toMarkdown => Markdown::convert => HTML::toBBCode'),
|
||||
'content' => visible_lf($bbcode4)
|
||||
];
|
||||
break;
|
||||
case 'markdown':
|
||||
$markdown = trim($_REQUEST['text']);
|
||||
$results[] = [
|
||||
'title' => L10n::t('Source input \x28Diaspora format\x29'),
|
||||
'content' => '<pre>' . $markdown . '</pre>'
|
||||
];
|
||||
|
||||
$bbcode = html2bbcode($html);
|
||||
$o .= '<h2>' . L10n::t('bbcode => html2bbcode: ') . '</h2>' . EOL . EOL;
|
||||
$o .= visible_lf($bbcode) . EOL . EOL;
|
||||
$bbcode = Text\Markdown::toBBCode($markdown);
|
||||
$results[] = [
|
||||
'title' => L10n::t('Markdown::toBBCode'),
|
||||
'content' => '<pre>' . $bbcode . '</pre>'
|
||||
];
|
||||
break;
|
||||
case 'html' :
|
||||
$html = trim($_REQUEST['text']);
|
||||
$results[] = [
|
||||
'title' => L10n::t("Raw HTML input"),
|
||||
'content' => htmlspecialchars($html)
|
||||
];
|
||||
|
||||
$diaspora = bb2diaspora($text);
|
||||
$o .= '<h2>' . L10n::t('bb2diaspora: ') . '</h2>' . EOL . EOL;
|
||||
$o .= visible_lf($diaspora) . EOL . EOL;
|
||||
$results[] = [
|
||||
'title' => L10n::t('HTML Input'),
|
||||
'content' => $html
|
||||
];
|
||||
|
||||
$html = Markdown::convert($diaspora);
|
||||
$o .= '<h2>' . L10n::t('bb2diaspora => Markdown: ') . '</h2>' . EOL . EOL;
|
||||
$o .= $html . EOL . EOL;
|
||||
$bbcode = Text\HTML::toBBCode($html);
|
||||
$results[] = [
|
||||
'title' => L10n::t('HTML::toBBCode'),
|
||||
'content' => visible_lf($bbcode)
|
||||
];
|
||||
|
||||
$bbcode = diaspora2bb($diaspora);
|
||||
$o .= '<h2>' . L10n::t('bb2diaspora => diaspora2bb: ') . '</h2>' . EOL . EOL;
|
||||
$o .= visible_lf($bbcode) . EOL . EOL;
|
||||
|
||||
$bbcode = html2bbcode($html);
|
||||
$o .= '<h2>' . L10n::t('bbcode => html2bbcode: ') . '</h2>' . EOL . EOL;
|
||||
$o .= visible_lf($bbcode) . EOL . EOL;
|
||||
$text = Text\HTML::toPlaintext($html);
|
||||
$results[] = [
|
||||
'title' => L10n::t('HTML::toPlaintext'),
|
||||
'content' => '<pre>' . $text . '</pre>'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (x($_REQUEST, 'd2bbtext')) {
|
||||
$d2bbtext = trim($_REQUEST['d2bbtext']);
|
||||
$o .= '<h2>' . L10n::t("Source input \x28Diaspora format\x29: ") . '</h2>' . EOL . EOL;
|
||||
$o .= '<pre>' . $d2bbtext . '</pre>' . EOL . EOL;
|
||||
|
||||
$bb = diaspora2bb($d2bbtext);
|
||||
$o .= '<h2>' . L10n::t('diaspora2bb: ') . '</h2>' . EOL . EOL;
|
||||
$o .= '<pre>' . $bb . '</pre>' . EOL . EOL;
|
||||
}
|
||||
$tpl = get_markup_template('babel.tpl');
|
||||
$o = replace_macros($tpl, [
|
||||
'$text' => ['text', L10n::t('Source text'), defaults($_REQUEST, 'text', ''), ''],
|
||||
'$type_bbcode' => ['type', L10n::t('BBCode'), 'bbcode', '', defaults($_REQUEST, 'type', 'bbcode') == 'bbcode'],
|
||||
'$type_markdown' => ['type', L10n::t('Markdown'), 'markdown', '', defaults($_REQUEST, 'type', 'bbcode') == 'markdown'],
|
||||
'$type_html' => ['type', L10n::t('HTML'), 'html', '', defaults($_REQUEST, 'type', 'bbcode') == 'html'],
|
||||
'$results' => $results
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
/**
|
||||
* @file mod/bookmarklet.php
|
||||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Module\Login;
|
||||
|
@ -35,8 +37,8 @@ function bookmarklet_content(App $a)
|
|||
'default_location' => $a->user['default-location'],
|
||||
'nickname' => $a->user['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'),
|
||||
'default_perms' => get_acl_permissions($a->user),
|
||||
'acl' => populate_acl($a->user, true),
|
||||
'default_perms' => ACL::getDefaultUserPermissions($a->user),
|
||||
'acl' => ACL::getFullSelectorHTML($a->user, true),
|
||||
'bang' => '',
|
||||
'visitor' => 'block',
|
||||
'profile_uid' => local_user(),
|
||||
|
|
24
mod/cal.php
24
mod/cal.php
|
@ -9,19 +9,19 @@
|
|||
use Friendica\App;
|
||||
use Friendica\Content\Feature;
|
||||
use Friendica\Content\Nav;
|
||||
use Friendica\Content\Widget;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Event;
|
||||
use Friendica\Model\Group;
|
||||
use Friendica\Model\Profile;
|
||||
use Friendica\Protocol\DFRN;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Temporal;
|
||||
|
||||
require_once 'include/event.php';
|
||||
|
||||
function cal_init(App $a)
|
||||
{
|
||||
if ($a->argc > 1) {
|
||||
|
@ -64,7 +64,7 @@ function cal_init(App $a)
|
|||
'$pdesc' => (($profile['pdesc'] != "") ? $profile['pdesc'] : ""),
|
||||
]);
|
||||
|
||||
$cal_widget = widget_events();
|
||||
$cal_widget = Widget\CalendarExport::getHTML();
|
||||
|
||||
if (!x($a->page, 'aside')) {
|
||||
$a->page['aside'] = '';
|
||||
|
@ -82,7 +82,7 @@ function cal_content(App $a)
|
|||
Nav::setSelected('events');
|
||||
|
||||
// get the translation strings for the callendar
|
||||
$i18n = get_event_strings();
|
||||
$i18n = Event::getStrings();
|
||||
|
||||
$htpl = get_markup_template('event_head.tpl');
|
||||
$a->page['htmlhead'] .= replace_macros($htpl, [
|
||||
|
@ -212,25 +212,25 @@ function cal_content(App $a)
|
|||
|
||||
// put the event parametes in an array so we can better transmit them
|
||||
$event_params = [
|
||||
'event_id' => (x($_GET, 'id') ? $_GET["id"] : 0),
|
||||
'event_id' => intval(defaults($_GET, 'id', 0)),
|
||||
'start' => $start,
|
||||
'finish' => $finish,
|
||||
'adjust_start' => $adjust_start,
|
||||
'adjust_finish' => $adjust_finish,
|
||||
'ignored' => $ignored,
|
||||
'ignore' => $ignored,
|
||||
];
|
||||
|
||||
// get events by id or by date
|
||||
if (x($_GET, 'id')) {
|
||||
$r = event_by_id($owner_uid, $event_params, $sql_extra);
|
||||
if ($event_params['event_id']) {
|
||||
$r = Event::getListById($owner_uid, $event_params['event-id'], $sql_extra);
|
||||
} else {
|
||||
$r = events_by_date($owner_uid, $event_params, $sql_extra);
|
||||
$r = Event::getListByDate($owner_uid, $event_params, $sql_extra);
|
||||
}
|
||||
|
||||
$links = [];
|
||||
|
||||
if (DBM::is_result($r)) {
|
||||
$r = sort_by_date($r);
|
||||
$r = Event::sortByDate($r);
|
||||
foreach ($r as $rr) {
|
||||
$j = $rr['adjust'] ? DateTimeFormat::local($rr['start'], 'j') : DateTimeFormat::utc($rr['start'], 'j');
|
||||
if (!x($links, $j)) {
|
||||
|
@ -240,7 +240,7 @@ function cal_content(App $a)
|
|||
}
|
||||
|
||||
// transform the event in a usable array
|
||||
$events = process_events($r);
|
||||
$events = Event::prepareListForTemplate($r);
|
||||
|
||||
if ($a->argv[2] === 'json') {
|
||||
echo json_encode($events);
|
||||
|
@ -306,7 +306,7 @@ function cal_content(App $a)
|
|||
}
|
||||
|
||||
// Get the export data by uid
|
||||
$evexport = event_export($owner_uid, $format);
|
||||
$evexport = Event::exportListByUserId($owner_uid, $format);
|
||||
|
||||
if (!$evexport["success"]) {
|
||||
if ($evexport["content"]) {
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
/**
|
||||
* @file mod/community.php
|
||||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Content\Nav;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\PConfig;
|
||||
|
@ -104,7 +106,7 @@ function community_content(App $a, $update = 0)
|
|||
'default_location' => $a->user['default-location'],
|
||||
'nickname' => $a->user['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' => populate_acl($a->user, true),
|
||||
'acl' => ACL::getFullSelectorHTML($a->user, true),
|
||||
'bang' => '',
|
||||
'visitor' => 'block',
|
||||
'profile_uid' => local_user(),
|
||||
|
|
|
@ -14,7 +14,6 @@ use Friendica\Model\Contact;
|
|||
use Friendica\Protocol\DFRN;
|
||||
|
||||
require_once 'include/items.php';
|
||||
require_once 'include/event.php';
|
||||
|
||||
function dfrn_notify_post(App $a) {
|
||||
logger(__function__, LOGGER_TRACE);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
use Friendica\App;
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Content\Text\HTML;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Protocol;
|
||||
|
@ -204,7 +206,6 @@ function display_content(App $a, $update = false, $update_uid = 0) {
|
|||
|
||||
require_once 'include/security.php';
|
||||
require_once 'include/conversation.php';
|
||||
require_once 'include/acl_selectors.php';
|
||||
|
||||
$o = '';
|
||||
|
||||
|
@ -321,7 +322,7 @@ function display_content(App $a, $update = false, $update_uid = 0) {
|
|||
'default_location' => $a->user['default-location'],
|
||||
'nickname' => $a->user['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' => populate_acl($a->user, true),
|
||||
'acl' => ACL::getFullSelectorHTML($a->user, true),
|
||||
'bang' => '',
|
||||
'visitor' => 'block',
|
||||
'profile_uid' => local_user(),
|
||||
|
@ -371,10 +372,8 @@ function display_content(App $a, $update = false, $update_uid = 0) {
|
|||
$o .= conversation($a, $items, 'display', $update_uid);
|
||||
|
||||
// Preparing the meta header
|
||||
require_once 'include/html2plain.php';
|
||||
|
||||
$description = trim(html2plain(BBCode::convert($s[0]["body"], false), 0, true));
|
||||
$title = trim(html2plain(BBCode::convert($s[0]["title"], false), 0, true));
|
||||
$description = trim(HTML::toPlaintext(BBCode::convert($s[0]["body"], false), 0, true));
|
||||
$title = trim(HTML::toPlaintext(BBCode::convert($s[0]["title"], false), 0, true));
|
||||
$author_name = $s[0]["author-name"];
|
||||
|
||||
$image = $a->remove_baseurl($s[0]["author-thumb"]);
|
||||
|
|
|
@ -10,8 +10,6 @@ use Friendica\Core\L10n;
|
|||
use Friendica\Core\System;
|
||||
use Friendica\Database\DBM;
|
||||
|
||||
require_once 'include/acl_selectors.php';
|
||||
|
||||
function editpost_content(App $a) {
|
||||
|
||||
$o = '';
|
||||
|
|
|
@ -6,16 +6,18 @@
|
|||
|
||||
use Friendica\App;
|
||||
use Friendica\Content\Nav;
|
||||
use Friendica\Content\Widget\CalendarExport;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Core\Worker;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Model\Event;
|
||||
use Friendica\Model\Item;
|
||||
use Friendica\Model\Profile;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Temporal;
|
||||
|
||||
require_once 'include/event.php';
|
||||
require_once 'include/items.php';
|
||||
|
||||
function events_init(App $a) {
|
||||
|
@ -23,21 +25,21 @@ function events_init(App $a) {
|
|||
return;
|
||||
}
|
||||
|
||||
if ($a->argc > 1) {
|
||||
// If it's a json request abort here because we don't
|
||||
// need the widget data
|
||||
if ($a->argv[1] === 'json') {
|
||||
if ($a->argc > 1 && $a->argv[1] === 'json') {
|
||||
return;
|
||||
}
|
||||
|
||||
$cal_widget = widget_events();
|
||||
|
||||
if (! x($a->page,'aside')) {
|
||||
if (empty($a->page['aside'])) {
|
||||
$a->page['aside'] = '';
|
||||
}
|
||||
|
||||
$a->data['user'] = $_SESSION['user'];
|
||||
|
||||
$cal_widget = CalendarExport::getHTML();
|
||||
|
||||
$a->page['aside'] .= $cal_widget;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -154,7 +156,6 @@ function events_post(App $a) {
|
|||
|
||||
|
||||
$datarray = [];
|
||||
$datarray['guid'] = get_guid(32);
|
||||
$datarray['start'] = $start;
|
||||
$datarray['finish'] = $finish;
|
||||
$datarray['summary'] = $summary;
|
||||
|
@ -169,18 +170,16 @@ function events_post(App $a) {
|
|||
$datarray['allow_gid'] = $str_group_allow;
|
||||
$datarray['deny_cid'] = $str_contact_deny;
|
||||
$datarray['deny_gid'] = $str_group_deny;
|
||||
$datarray['private'] = (($private_event) ? 1 : 0);
|
||||
$datarray['private'] = $private_event;
|
||||
$datarray['id'] = $event_id;
|
||||
$datarray['created'] = $created;
|
||||
$datarray['edited'] = $edited;
|
||||
|
||||
if (intval($_REQUEST['preview'])) {
|
||||
$html = format_event_html($datarray);
|
||||
$html = Event::getHTML($datarray);
|
||||
echo $html;
|
||||
killme();
|
||||
}
|
||||
|
||||
$item_id = event_store($datarray);
|
||||
$item_id = Event::store($datarray);
|
||||
|
||||
if (! $cid) {
|
||||
Worker::add(PRIORITY_HIGH, "Notifier", "event", $item_id);
|
||||
|
@ -221,7 +220,7 @@ function events_content(App $a) {
|
|||
}
|
||||
|
||||
// get the translation strings for the callendar
|
||||
$i18n = get_event_strings();
|
||||
$i18n = Event::getStrings();
|
||||
|
||||
$htpl = get_markup_template('event_head.tpl');
|
||||
$a->page['htmlhead'] .= replace_macros($htpl, [
|
||||
|
@ -330,25 +329,25 @@ function events_content(App $a) {
|
|||
|
||||
// put the event parametes in an array so we can better transmit them
|
||||
$event_params = [
|
||||
'event_id' => (x($_GET, 'id') ? $_GET['id'] : 0),
|
||||
'event_id' => intval(defaults($_GET, 'id', 0)),
|
||||
'start' => $start,
|
||||
'finish' => $finish,
|
||||
'adjust_start' => $adjust_start,
|
||||
'adjust_finish' => $adjust_finish,
|
||||
'ignored' => $ignored,
|
||||
'ignore' => $ignored,
|
||||
];
|
||||
|
||||
// get events by id or by date
|
||||
if (x($_GET, 'id')) {
|
||||
$r = event_by_id(local_user(), $event_params);
|
||||
if ($event_params['event_id']) {
|
||||
$r = Event::getListById(local_user(), $event_params['event_id']);
|
||||
} else {
|
||||
$r = events_by_date(local_user(), $event_params);
|
||||
$r = Event::getListByDate(local_user(), $event_params);
|
||||
}
|
||||
|
||||
$links = [];
|
||||
|
||||
if (DBM::is_result($r)) {
|
||||
$r = sort_by_date($r);
|
||||
$r = Event::sortByDate($r);
|
||||
foreach ($r as $rr) {
|
||||
$j = $rr['adjust'] ? DateTimeFormat::local($rr['start'], 'j') : DateTimeFormat::utc($rr['start'], 'j');
|
||||
if (! x($links,$j)) {
|
||||
|
@ -361,8 +360,8 @@ function events_content(App $a) {
|
|||
|
||||
// transform the event in a usable array
|
||||
if (DBM::is_result($r)) {
|
||||
$r = sort_by_date($r);
|
||||
$events = process_events($r);
|
||||
$r = Event::sortByDate($r);
|
||||
$events = Event::prepareListForTemplate($r);
|
||||
}
|
||||
|
||||
if ($a->argc > 1 && $a->argv[1] === 'json'){
|
||||
|
@ -478,12 +477,10 @@ function events_content(App $a) {
|
|||
$fhour = ((x($orig_event)) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'H') : '00');
|
||||
$fminute = ((x($orig_event)) ? DateTimeFormat::convert($fdt, $tz, 'UTC', 'i') : '00');
|
||||
|
||||
require_once 'include/acl_selectors.php' ;
|
||||
|
||||
$perms = get_acl_permissions($orig_event);
|
||||
$perms = ACL::getDefaultUserPermissions($orig_event);
|
||||
|
||||
if ($mode === 'new' || $mode === 'copy') {
|
||||
$acl = (($cid) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $a->user)));
|
||||
$acl = (($cid) ? '' : ACL::getFullSelectorHTML(((x($orig_event)) ? $orig_event : $a->user)));
|
||||
}
|
||||
|
||||
// If we copy an old event, we need to remove the ID and URI
|
||||
|
@ -544,8 +541,7 @@ function events_content(App $a) {
|
|||
if ($mode === 'drop' && $event_id) {
|
||||
$del = 0;
|
||||
|
||||
$params = ['event_id' => ($event_id)];
|
||||
$ev = event_by_id(local_user(), $params);
|
||||
$ev = Event::getListById(local_user(), $event_id);
|
||||
|
||||
// Delete only real events (no birthdays)
|
||||
if (DBM::is_result($ev) && $ev[0]['type'] == 'event') {
|
||||
|
|
53
mod/feedtest.php
Normal file
53
mod/feedtest.php
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file_tag_list_to_file mod/feedtest.php
|
||||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Protocol\Feed;
|
||||
use Friendica\Util\Network;
|
||||
|
||||
require_once 'boot.php';
|
||||
require_once 'include/dba.php';
|
||||
require_once 'include/text.php';
|
||||
|
||||
function feedtest_content(App $a)
|
||||
{
|
||||
if (!local_user()) {
|
||||
info(L10n::t('You must be logged in to use this module'));
|
||||
return;
|
||||
};
|
||||
|
||||
$result = [];
|
||||
if (!empty($_REQUEST['url'])) {
|
||||
$url = $_REQUEST['url'];
|
||||
|
||||
$importer = dba::selectFirst('user', [], ['uid' => local_user()]);
|
||||
|
||||
$contact_id = Contact::getIdForURL($url, local_user(), true);
|
||||
|
||||
$contact = dba::selectFirst('contact', [], ['id' => $contact_id]);
|
||||
|
||||
$ret = Network::curl($contact['poll']);
|
||||
$xml = $ret['body'];
|
||||
|
||||
$dummy = null;
|
||||
$import_result = Feed::import($xml, $importer, $contact, $dummy, true);
|
||||
|
||||
$result = [
|
||||
'input' => text_highlight($xml, 'xml'),
|
||||
'output' => var_export($import_result, true),
|
||||
];
|
||||
}
|
||||
|
||||
$tpl = get_markup_template('feedtest.tpl');
|
||||
$o = replace_macros($tpl, [
|
||||
'$url' => ['url', L10n::t('Source URL'), defaults($_REQUEST, 'url', ''), ''],
|
||||
'$result' => $result
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Worker;
|
||||
use Friendica\Database\DBM;
|
||||
|
@ -75,8 +76,6 @@ function fsuggest_post(App $a)
|
|||
|
||||
function fsuggest_content(App $a)
|
||||
{
|
||||
require_once 'include/acl_selectors.php';
|
||||
|
||||
if (! local_user()) {
|
||||
notice(L10n::t('Permission denied.') . EOL);
|
||||
return;
|
||||
|
@ -105,11 +104,10 @@ function fsuggest_content(App $a)
|
|||
|
||||
$o .= '<form id="fsuggest-form" action="fsuggest/' . $contact_id . '" method="post" >';
|
||||
|
||||
$o .= contact_selector(
|
||||
$o .= ACL::getSuggestContactSelectHTML(
|
||||
'suggest',
|
||||
'suggest-select',
|
||||
['size' => 4, 'exclude' => $contact_id, 'networks' => 'DFRN_ONLY', 'single' => true],
|
||||
false
|
||||
['size' => 4, 'exclude' => $contact_id, 'networks' => 'DFRN_ONLY', 'single' => true]
|
||||
);
|
||||
|
||||
|
||||
|
|
|
@ -146,7 +146,6 @@ function group_content(App $a) {
|
|||
}
|
||||
|
||||
if (($a->argc > 1) && (intval($a->argv[1]))) {
|
||||
require_once 'include/acl_selectors.php';
|
||||
require_once 'mod/contacts.php';
|
||||
|
||||
$r = q("SELECT * FROM `group` WHERE `id` = %d AND `uid` = %d AND `deleted` = 0 LIMIT 1",
|
||||
|
|
|
@ -808,7 +808,6 @@ function item_post(App $a) {
|
|||
$link = '<a href="' . System::baseUrl() . '/profile/' . $a->user['nickname'] . '"><img src="' . $author['thumb'] . '" alt="' . $a->user['username'] . '" /></a><br /><br />';
|
||||
$html = prepare_body($datarray);
|
||||
$message = '<html><body>' . $link . $html . $disclaimer . '</body></html>';
|
||||
include_once 'include/html2plain.php';
|
||||
$params = [
|
||||
'fromName' => $a->user['username'],
|
||||
'fromEmail' => $a->user['email'],
|
||||
|
@ -816,7 +815,7 @@ function item_post(App $a) {
|
|||
'replyTo' => $a->user['email'],
|
||||
'messageSubject' => $subject,
|
||||
'htmlVersion' => $message,
|
||||
'textVersion' => html2plain($html.$disclaimer)
|
||||
'textVersion' => Friendica\Content\Text\HTML::toPlaintext($html.$disclaimer)
|
||||
];
|
||||
Emailer::send($params);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use Friendica\App;
|
|||
use Friendica\Content\Nav;
|
||||
use Friendica\Content\Smilies;
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Database\DBM;
|
||||
|
@ -15,7 +16,6 @@ use Friendica\Model\Mail;
|
|||
use Friendica\Util\DateTimeFormat;
|
||||
use Friendica\Util\Temporal;
|
||||
|
||||
require_once 'include/acl_selectors.php';
|
||||
require_once 'include/conversation.php';
|
||||
|
||||
function message_init(App $a)
|
||||
|
@ -207,7 +207,7 @@ function message_content(App $a)
|
|||
'$linkurl' => L10n::t('Please enter a link URL:')
|
||||
]);
|
||||
|
||||
$preselect = isset($a->argv[2]) ? [$a->argv[2]] : false;
|
||||
$preselect = isset($a->argv[2]) ? [$a->argv[2]] : [];
|
||||
|
||||
$prename = $preurl = $preid = '';
|
||||
|
||||
|
@ -236,14 +236,14 @@ function message_content(App $a)
|
|||
$preid = $r[0]['id'];
|
||||
$preselect = [$preid];
|
||||
} else {
|
||||
$preselect = false;
|
||||
$preselect = [];
|
||||
}
|
||||
}
|
||||
|
||||
$prefill = $preselect ? $prename : '';
|
||||
|
||||
// the ugly select box
|
||||
$select = contact_select('messageto', 'message-to-select', $preselect, 4, true, false, false, 10);
|
||||
$select = ACL::getMessageContactSelectHTML('messageto', 'message-to-select', $preselect, 4, 10);
|
||||
|
||||
$tpl = get_markup_template('prv_message.tpl');
|
||||
$o .= replace_macros($tpl, [
|
||||
|
|
|
@ -9,6 +9,7 @@ use Friendica\Content\Feature;
|
|||
use Friendica\Content\ForumManager;
|
||||
use Friendica\Content\Nav;
|
||||
use Friendica\Content\Widget;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\L10n;
|
||||
|
@ -24,7 +25,6 @@ use Friendica\Util\DateTimeFormat;
|
|||
|
||||
require_once 'include/conversation.php';
|
||||
require_once 'include/items.php';
|
||||
require_once 'include/acl_selectors.php';
|
||||
|
||||
function network_init(App $a)
|
||||
{
|
||||
|
@ -427,8 +427,8 @@ function networkFlatView(App $a, $update = 0)
|
|||
'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'),
|
||||
'default_perms' => get_acl_permissions($a->user),
|
||||
'acl' => populate_acl($a->user, true),
|
||||
'default_perms' => ACL::getDefaultUserPermissions($a->user),
|
||||
'acl' => ACL::getFullSelectorHTML($a->user, true),
|
||||
'bang' => '',
|
||||
'visitor' => 'block',
|
||||
'profile_uid' => local_user(),
|
||||
|
@ -576,8 +576,8 @@ function networkThreadedView(App $a, $update, $parent)
|
|||
'lockstate' => ((($gid) || ($cid) || ($nets) || (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'),
|
||||
'default_perms' => get_acl_permissions($a->user),
|
||||
'acl' => populate_acl((($gid || $cid || $nets) ? $def_acl : $a->user), true),
|
||||
'default_perms' => ACL::getDefaultUserPermissions($a->user),
|
||||
'acl' => ACL::getFullSelectorHTML((($gid || $cid || $nets) ? $def_acl : $a->user), true),
|
||||
'bang' => (($gid || $cid || $nets) ? '!' : ''),
|
||||
'visitor' => 'block',
|
||||
'profile_uid' => local_user(),
|
||||
|
|
|
@ -33,7 +33,6 @@ function notes_content(App $a, $update = false)
|
|||
|
||||
require_once 'include/security.php';
|
||||
require_once 'include/conversation.php';
|
||||
require_once 'include/acl_selectors.php';
|
||||
$groups = [];
|
||||
|
||||
|
||||
|
|
|
@ -46,13 +46,11 @@ function oexchange_content(App $a) {
|
|||
return;
|
||||
}
|
||||
|
||||
require_once('include/html2bbcode.php');
|
||||
|
||||
$post = [];
|
||||
|
||||
$post['profile_uid'] = local_user();
|
||||
$post['return'] = '/oexchange/done' ;
|
||||
$post['body'] = html2bbcode($s);
|
||||
$post['body'] = Friendica\Content\Text\HTML::toBBCode($s);
|
||||
$post['type'] = 'wall';
|
||||
|
||||
$_REQUEST = $post;
|
||||
|
|
|
@ -7,6 +7,7 @@ use Friendica\App;
|
|||
use Friendica\Content\Feature;
|
||||
use Friendica\Content\Nav;
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\L10n;
|
||||
|
@ -26,7 +27,6 @@ use Friendica\Util\Map;
|
|||
use Friendica\Util\Temporal;
|
||||
|
||||
require_once 'include/items.php';
|
||||
require_once 'include/acl_selectors.php';
|
||||
require_once 'include/security.php';
|
||||
|
||||
function photos_init(App $a) {
|
||||
|
@ -1084,7 +1084,7 @@ function photos_content(App $a)
|
|||
|
||||
$tpl = get_markup_template('photos_upload.tpl');
|
||||
|
||||
$aclselect_e = ($visitor ? '' : populate_acl($a->user));
|
||||
$aclselect_e = ($visitor ? '' : ACL::getFullSelectorHTML($a->user));
|
||||
|
||||
$o .= replace_macros($tpl,[
|
||||
'$pagename' => L10n::t('Upload Photos'),
|
||||
|
@ -1425,7 +1425,7 @@ function photos_content(App $a)
|
|||
|
||||
$album_e = $ph[0]['album'];
|
||||
$caption_e = $ph[0]['desc'];
|
||||
$aclselect_e = populate_acl($ph[0]);
|
||||
$aclselect_e = ACL::getFullSelectorHTML($ph[0]);
|
||||
|
||||
$edit = replace_macros($edit_tpl, [
|
||||
'$id' => $ph[0]['id'],
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
use Friendica\App;
|
||||
use Friendica\Content\Nav;
|
||||
use Friendica\Content\Widget;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\L10n;
|
||||
|
@ -118,7 +119,6 @@ function profile_content(App $a, $update = 0)
|
|||
|
||||
require_once 'include/security.php';
|
||||
require_once 'include/conversation.php';
|
||||
require_once 'include/acl_selectors.php';
|
||||
require_once 'include/items.php';
|
||||
|
||||
$groups = [];
|
||||
|
@ -213,7 +213,7 @@ function profile_content(App $a, $update = 0)
|
|||
|| strlen($a->user['deny_cid'])
|
||||
|| strlen($a->user['deny_gid'])
|
||||
) ? 'lock' : 'unlock',
|
||||
'acl' => $is_owner ? populate_acl($a->user, true) : '',
|
||||
'acl' => $is_owner ? ACL::getFullSelectorHTML($a->user, true) : '',
|
||||
'bang' => '',
|
||||
'visitor' => $is_owner || $commvisitor ? 'block' : 'none',
|
||||
'profile_uid' => $a->profile['profile_uid'],
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
use Friendica\App;
|
||||
use Friendica\Content\Feature;
|
||||
use Friendica\Content\Nav;
|
||||
use Friendica\Core\ACL;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\L10n;
|
||||
|
@ -389,6 +390,11 @@ function settings_post(App $a)
|
|||
$err = true;
|
||||
}
|
||||
|
||||
if (!Config::get('system', 'disable_password_exposed', false) && User::isPasswordExposed($newpass)) {
|
||||
notice(L10n::t('The new password has been exposed in a public data dump, please choose another.') . EOL);
|
||||
$err = true;
|
||||
}
|
||||
|
||||
// check if the old password was supplied correctly before changing it to the new value
|
||||
if (!User::authenticate(intval(local_user()), $_POST['opassword'])) {
|
||||
notice(L10n::t('Wrong password.') . EOL);
|
||||
|
@ -989,8 +995,6 @@ function settings_content(App $a)
|
|||
* ACCOUNT SETTINGS
|
||||
*/
|
||||
|
||||
require_once('include/acl_selectors.php');
|
||||
|
||||
$profile = dba::selectFirst('profile', [], ['is-default' => true, 'uid' => local_user()]);
|
||||
if (!DBM::is_result($profile)) {
|
||||
notice(L10n::t('Unable to find your profile. Please contact your admin.') . EOL);
|
||||
|
@ -1214,7 +1218,7 @@ function settings_content(App $a)
|
|||
'$permissions' => L10n::t('Default Post Permissions'),
|
||||
'$permdesc' => L10n::t("\x28click to open/close\x29"),
|
||||
'$visibility' => $profile['net-publish'],
|
||||
'$aclselect' => populate_acl($a->user),
|
||||
'$aclselect' => ACL::getFullSelectorHTML($a->user),
|
||||
'$suggestme' => $suggestme,
|
||||
'$blockwall'=> $blockwall, // array('blockwall', L10n::t('Allow friends to post to your profile page:'), !$blockwall, ''),
|
||||
'$blocktags'=> $blocktags, // array('blocktags', L10n::t('Allow friends to tag your posts:'), !$blocktags, ''),
|
||||
|
@ -1265,7 +1269,7 @@ function settings_content(App $a)
|
|||
|
||||
'$detailed_notif' => ['detailed_notif', L10n::t('Show detailled notifications'),
|
||||
PConfig::get(local_user(), 'system', 'detailed_notif'),
|
||||
L10n::t('Per default the notificiation are condensed to a single notification per item. When enabled, every notification is displayed.')],
|
||||
L10n::t('Per default, notifications are condensed to a single notification per item. When enabled every notification is displayed.')],
|
||||
|
||||
'$h_advn' => L10n::t('Advanced Account/Page Type Settings'),
|
||||
'$h_descadvn' => L10n::t('Change the behaviour of this account for special situations'),
|
||||
|
|
|
@ -19,7 +19,6 @@ use Friendica\Protocol\DFRN;
|
|||
use Friendica\Util\DateTimeFormat;
|
||||
|
||||
require_once 'include/items.php';
|
||||
require_once 'include/acl_selectors.php';
|
||||
require_once 'include/security.php';
|
||||
|
||||
function videos_init(App $a) {
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* @file scripts/dbstructure.php
|
||||
* @brief Does database updates from the command line
|
||||
*/
|
||||
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Database\DBStructure;
|
||||
|
||||
require_once "boot.php";
|
||||
require_once "include/dba.php";
|
||||
|
||||
$a = new App(dirname(__DIR__));
|
||||
|
||||
@include ".htconfig.php";
|
||||
dba::connect($db_host, $db_user, $db_pass, $db_data);
|
||||
unset($db_host, $db_user, $db_pass, $db_data);
|
||||
|
||||
if ($_SERVER["argc"] == 2) {
|
||||
switch ($_SERVER["argv"][1]) {
|
||||
case "dryrun":
|
||||
DBStructure::update(true, false);
|
||||
return;
|
||||
case "update":
|
||||
DBStructure::update(true, true);
|
||||
|
||||
$build = Config::get('system','build');
|
||||
if (!x($build)) {
|
||||
Config::set('system', 'build', DB_UPDATE_VERSION);
|
||||
$build = DB_UPDATE_VERSION;
|
||||
}
|
||||
|
||||
$stored = intval($build);
|
||||
$current = intval(DB_UPDATE_VERSION);
|
||||
|
||||
// run any left update_nnnn functions in update.php
|
||||
for ($x = $stored; $x < $current; $x ++) {
|
||||
$r = run_update_function($x);
|
||||
if (!$r) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Config::set('system','build',DB_UPDATE_VERSION);
|
||||
return;
|
||||
case "dumpsql":
|
||||
DBStructure::printStructure();
|
||||
return;
|
||||
case "toinnodb":
|
||||
DBStructure::convertToInnoDB();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// print help
|
||||
echo $_SERVER["argv"][0]." <command>\n";
|
||||
echo "\n";
|
||||
echo "Commands:\n";
|
||||
echo "dryrun show database update schema queries without running them\n";
|
||||
echo "update update database schema\n";
|
||||
echo "dumpsql dump database schema\n";
|
||||
echo "toinnodb convert all tables from MyISAM to InnoDB\n";
|
||||
killme();
|
||||
|
116
src/App.php
116
src/App.php
|
@ -148,6 +148,8 @@ class App
|
|||
$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;
|
||||
|
@ -157,6 +159,8 @@ class App
|
|||
|
||||
$this->callstack['database'] = [];
|
||||
$this->callstack['database_write'] = [];
|
||||
$this->callstack['cache'] = [];
|
||||
$this->callstack['cache_write'] = [];
|
||||
$this->callstack['network'] = [];
|
||||
$this->callstack['file'] = [];
|
||||
$this->callstack['rendering'] = [];
|
||||
|
@ -940,4 +944,116 @@ class App
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $cat Config category
|
||||
* @param string $k Config key
|
||||
* @param mixed $default Default value if it isn't set
|
||||
*/
|
||||
public function getConfigValue($cat, $k, $default = null)
|
||||
{
|
||||
$return = $default;
|
||||
|
||||
if ($cat === 'config') {
|
||||
if (isset($this->config[$k])) {
|
||||
$return = $this->config[$k];
|
||||
}
|
||||
} else {
|
||||
if (isset($this->config[$cat][$k])) {
|
||||
$return = $this->config[$cat][$k];
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in the config cache. Accepts raw output from the config table
|
||||
*
|
||||
* @param string $cat Config category
|
||||
* @param string $k Config key
|
||||
* @param mixed $v Value to set
|
||||
*/
|
||||
public function setConfigValue($cat, $k, $v)
|
||||
{
|
||||
// Only arrays are serialized in database, so we have to unserialize sparingly
|
||||
$value = is_string($v) && preg_match("|^a:[0-9]+:{.*}$|s", $v) ? unserialize($v) : $v;
|
||||
|
||||
if ($cat === 'config') {
|
||||
$this->config[$k] = $value;
|
||||
} else {
|
||||
$this->config[$cat][$k] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a value from the config cache
|
||||
*
|
||||
* @param string $cat Config category
|
||||
* @param string $k Config key
|
||||
*/
|
||||
public function deleteConfigValue($cat, $k)
|
||||
{
|
||||
if ($cat === 'config') {
|
||||
if (isset($this->config[$k])) {
|
||||
unset($this->config[$k]);
|
||||
}
|
||||
} else {
|
||||
if (isset($this->config[$cat][$k])) {
|
||||
unset($this->config[$cat][$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a value from the user config cache
|
||||
*
|
||||
* @param int $uid User Id
|
||||
* @param string $cat Config category
|
||||
* @param string $k Config key
|
||||
* @param mixed $default Default value if key isn't set
|
||||
*/
|
||||
public function getPConfigValue($uid, $cat, $k, $default = null)
|
||||
{
|
||||
$return = $default;
|
||||
|
||||
if (isset($this->config[$uid][$cat][$k])) {
|
||||
$return = $this->config[$uid][$cat][$k];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value in the user config cache
|
||||
*
|
||||
* Accepts raw output from the pconfig table
|
||||
*
|
||||
* @param int $uid User Id
|
||||
* @param string $cat Config category
|
||||
* @param string $k Config key
|
||||
* @param mixed $v Value to set
|
||||
*/
|
||||
public function setPConfigValue($uid, $cat, $k, $v)
|
||||
{
|
||||
// Only arrays are serialized in database, so we have to unserialize sparingly
|
||||
$value = is_string($v) && preg_match("|^a:[0-9]+:{.*}$|s", $v) ? unserialize($v) : $v;
|
||||
|
||||
$this->config[$uid][$cat][$k] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a value from the user config cache
|
||||
*
|
||||
* @param int $uid User Id
|
||||
* @param string $cat Config category
|
||||
* @param string $k Config key
|
||||
*/
|
||||
public function deletePConfigValue($uid, $cat, $k)
|
||||
{
|
||||
if (isset($this->config[$uid][$cat][$k])) {
|
||||
unset($this->config[$uid][$cat][$k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,36 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file src/Content/Text/BBCode.php
|
||||
*/
|
||||
|
||||
namespace Friendica\Content\Text;
|
||||
|
||||
use DOMDocument;
|
||||
use DomXPath;
|
||||
use DOMXPath;
|
||||
use Exception;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Content\OEmbed;
|
||||
use Friendica\Content\Smilies;
|
||||
use Friendica\Content\Text\Plaintext;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Cache;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\PConfig;
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\Event;
|
||||
use Friendica\Network\Probe;
|
||||
use Friendica\Object\Image;
|
||||
use Friendica\Util\Map;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Util\ParseUrl;
|
||||
use League\HTMLToMarkdown\HtmlConverter;
|
||||
|
||||
require_once "include/event.php";
|
||||
require_once "include/html2plain.php";
|
||||
require_once "include/html2bbcode.php";
|
||||
require_once "mod/proxy.php";
|
||||
|
||||
class BBCode
|
||||
class BBCode extends BaseObject
|
||||
{
|
||||
/**
|
||||
* @brief Fetches attachment data that were generated the old way
|
||||
|
@ -174,7 +176,7 @@ class BBCode
|
|||
}
|
||||
|
||||
if ($title != "") {
|
||||
$title = BBCode::convert(html_entity_decode($title, ENT_QUOTES, 'UTF-8'), false, true);
|
||||
$title = self::convert(html_entity_decode($title, ENT_QUOTES, 'UTF-8'), false, true);
|
||||
$title = html_entity_decode($title, ENT_QUOTES, 'UTF-8');
|
||||
$title = str_replace(["[", "]"], ["[", "]"], $title);
|
||||
$data["title"] = $title;
|
||||
|
@ -409,8 +411,8 @@ class BBCode
|
|||
}
|
||||
}
|
||||
|
||||
$html = BBCode::convert($post["text"].$post["after"], false, $htmlmode);
|
||||
$msg = html2plain($html, 0, true);
|
||||
$html = self::convert($post["text"].$post["after"], false, $htmlmode);
|
||||
$msg = HTML::toPlaintext($html, 0, true);
|
||||
$msg = trim(html_entity_decode($msg, ENT_QUOTES, 'UTF-8'));
|
||||
|
||||
$link = "";
|
||||
|
@ -707,7 +709,7 @@ class BBCode
|
|||
|
||||
if ($data["description"] != "" && $data["description"] != $data["title"]) {
|
||||
// Sanitize the HTML by converting it to BBCode
|
||||
$bbcode = html2bbcode($data["description"]);
|
||||
$bbcode = HTML::toBBCode($data["description"]);
|
||||
$return .= sprintf('<blockquote>%s</blockquote>', trim(self::convert($bbcode)));
|
||||
}
|
||||
if ($data["type"] == "link") {
|
||||
|
@ -762,27 +764,6 @@ class BBCode
|
|||
return $text . "\n" . $data["after"];
|
||||
}
|
||||
|
||||
private static function cleanCss($input)
|
||||
{
|
||||
$cleaned = "";
|
||||
|
||||
$input = strtolower($input);
|
||||
|
||||
for ($i = 0; $i < strlen($input); $i++) {
|
||||
$char = substr($input, $i, 1);
|
||||
|
||||
if (($char >= "a") && ($char <= "z")) {
|
||||
$cleaned .= $char;
|
||||
}
|
||||
|
||||
if (!(strpos(" #;:0123456789-_.%", $char) === false)) {
|
||||
$cleaned .= $char;
|
||||
}
|
||||
}
|
||||
|
||||
return $cleaned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts [url] BBCodes in a format that looks fine on Mastodon. (callback function)
|
||||
*
|
||||
|
@ -1197,7 +1178,7 @@ class BBCode
|
|||
$text = Cache::get($match[1]);
|
||||
|
||||
if (is_null($text)) {
|
||||
$a = get_app();
|
||||
$a = self::getApp();
|
||||
|
||||
$stamp1 = microtime(true);
|
||||
|
||||
|
@ -1220,7 +1201,7 @@ class BBCode
|
|||
|
||||
$doc = new DOMDocument();
|
||||
@$doc->loadHTML($body);
|
||||
$xpath = new DomXPath($doc);
|
||||
$xpath = new DOMXPath($doc);
|
||||
$list = $xpath->query("//meta[@name]");
|
||||
foreach ($list as $node) {
|
||||
$attr = [];
|
||||
|
@ -1256,7 +1237,7 @@ class BBCode
|
|||
$text = Cache::get($match[1]);
|
||||
|
||||
if (is_null($text)) {
|
||||
$a = get_app();
|
||||
$a = self::getApp();
|
||||
|
||||
$stamp1 = microtime(true);
|
||||
|
||||
|
@ -1280,7 +1261,7 @@ class BBCode
|
|||
|
||||
$doc = new DOMDocument();
|
||||
@$doc->loadHTML($body);
|
||||
$xpath = new DomXPath($doc);
|
||||
$xpath = new DOMXPath($doc);
|
||||
$list = $xpath->query("//meta[@name]");
|
||||
foreach ($list as $node) {
|
||||
$attr = [];
|
||||
|
@ -1343,7 +1324,7 @@ class BBCode
|
|||
*/
|
||||
public static function convert($text, $try_oembed = true, $simple_html = false, $for_plaintext = false)
|
||||
{
|
||||
$a = get_app();
|
||||
$a = self::getApp();
|
||||
|
||||
/*
|
||||
* preg_match_callback function to replace potential Oembed tags with Oembed content
|
||||
|
@ -1392,7 +1373,7 @@ class BBCode
|
|||
// After we're finished processing the bbcode we'll
|
||||
// replace all of the event code with a reformatted version.
|
||||
|
||||
$ev = bbtoevent($text);
|
||||
$ev = Event::fromBBCode($text);
|
||||
|
||||
// Replace any html brackets with HTML Entities to prevent executing HTML or script
|
||||
// Don't use strip_tags here because it breaks [url] search by replacing & with amp
|
||||
|
@ -1616,7 +1597,7 @@ class BBCode
|
|||
$text = preg_replace_callback(
|
||||
"(\[style=(.*?)\](.*?)\[\/style\])ism",
|
||||
function ($match) {
|
||||
return "<span style=\"" . self::cleanCss($match[1]) . ";\">" . $match[2] . "</span>";
|
||||
return "<span style=\"" . HTML::sanitizeCSS($match[1]) . ";\">" . $match[2] . "</span>";
|
||||
},
|
||||
$text
|
||||
);
|
||||
|
@ -1625,7 +1606,7 @@ class BBCode
|
|||
$text = preg_replace_callback(
|
||||
"(\[class=(.*?)\](.*?)\[\/class\])ism",
|
||||
function ($match) {
|
||||
return "<span class=\"" . self::cleanCss($match[1]) . "\">" . $match[2] . "</span>";
|
||||
return "<span class=\"" . HTML::sanitizeCSS($match[1]) . "\">" . $match[2] . "</span>";
|
||||
},
|
||||
$text
|
||||
);
|
||||
|
@ -1830,7 +1811,7 @@ class BBCode
|
|||
// start which is always required). Allow desc with a missing summary for compatibility.
|
||||
|
||||
if ((x($ev, 'desc') || x($ev, 'summary')) && x($ev, 'start')) {
|
||||
$sub = format_event_html($ev, $simple_html);
|
||||
$sub = Event::getHTML($ev, $simple_html);
|
||||
|
||||
$text = preg_replace("/\[event\-summary\](.*?)\[\/event\-summary\]/ism", '', $text);
|
||||
$text = preg_replace("/\[event\-description\](.*?)\[\/event\-description\]/ism", '', $text);
|
||||
|
@ -1969,4 +1950,148 @@ class BBCode
|
|||
|
||||
return $abstract;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function to replace a Friendica style mention in a mention for Diaspora
|
||||
*
|
||||
* @param array $match Matching values for the callback
|
||||
* @return string Replaced mention
|
||||
*/
|
||||
private static function bbCodeMention2DiasporaCallback($match)
|
||||
{
|
||||
$contact = Contact::getDetailsByURL($match[3]);
|
||||
|
||||
if (empty($contact['addr'])) {
|
||||
$contact = Probe::uri($match[3]);
|
||||
}
|
||||
|
||||
if (empty($contact['addr'])) {
|
||||
return $match[0];
|
||||
}
|
||||
|
||||
$mention = '@{' . $match[2] . '; ' . $contact['addr'] . '}';
|
||||
return $mention;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a BBCode text into Markdown
|
||||
*
|
||||
* This function converts a BBCode item body to be sent to Markdown-enabled
|
||||
* systems like Diaspora and Libertree
|
||||
*
|
||||
* @param string $text
|
||||
* @param bool $for_diaspora Diaspora requires more changes than Libertree
|
||||
* @return string
|
||||
*/
|
||||
public static function toMarkdown($text, $for_diaspora = true)
|
||||
{
|
||||
$a = self::getApp();
|
||||
|
||||
$original_text = $text;
|
||||
|
||||
// Since Diaspora is creating a summary for links, this function removes them before posting
|
||||
if ($for_diaspora) {
|
||||
$text = self::removeShareInformation($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform #tags, strip off the [url] and replace spaces with underscore
|
||||
*/
|
||||
$url_search_string = "^\[\]";
|
||||
$text = preg_replace_callback("/#\[url\=([$url_search_string]*)\](.*?)\[\/url\]/i",
|
||||
function ($matches) {
|
||||
return '#' . str_replace(' ', '_', $matches[2]);
|
||||
},
|
||||
$text
|
||||
);
|
||||
|
||||
// Converting images with size parameters to simple images. Markdown doesn't know it.
|
||||
$text = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $text);
|
||||
|
||||
// Extracting multi-line code blocks before the whitespace processing/code highlighter in self::convert()
|
||||
$codeblocks = [];
|
||||
|
||||
$text = preg_replace_callback("#\[code(?:=([^\]]*))?\](.*?)\[\/code\]#is",
|
||||
function ($matches) use (&$codeblocks) {
|
||||
$return = $matches[0];
|
||||
if (strpos($matches[2], "\n") !== false) {
|
||||
$return = '#codeblock-' . count($codeblocks) . '#';
|
||||
|
||||
$prefix = '````' . $matches[1] . PHP_EOL;
|
||||
$codeblocks[] = $prefix . trim($matches[2]) . PHP_EOL . '````';
|
||||
}
|
||||
return $return;
|
||||
},
|
||||
$text
|
||||
);
|
||||
|
||||
// Convert it to HTML - don't try oembed
|
||||
if ($for_diaspora) {
|
||||
$text = self::convert($text, false, 3);
|
||||
|
||||
// Add all tags that maybe were removed
|
||||
if (preg_match_all("/#\[url\=([$url_search_string]*)\](.*?)\[\/url\]/ism", $original_text, $tags)) {
|
||||
$tagline = "";
|
||||
foreach ($tags[2] as $tag) {
|
||||
$tag = html_entity_decode($tag, ENT_QUOTES, 'UTF-8');
|
||||
if (!strpos(html_entity_decode($text, ENT_QUOTES, 'UTF-8'), '#' . $tag)) {
|
||||
$tagline .= '#' . $tag . ' ';
|
||||
}
|
||||
}
|
||||
$text = $text . " " . $tagline;
|
||||
}
|
||||
} else {
|
||||
$text = self::convert($text, false, 4);
|
||||
}
|
||||
|
||||
// mask some special HTML chars from conversation to markdown
|
||||
$text = str_replace(['<', '>', '&'], ['&_lt_;', '&_gt_;', '&_amp_;'], $text);
|
||||
|
||||
// If a link is followed by a quote then there should be a newline before it
|
||||
// Maybe we should make this newline at every time before a quote.
|
||||
$text = str_replace(["</a><blockquote>"], ["</a><br><blockquote>"], $text);
|
||||
|
||||
$stamp1 = microtime(true);
|
||||
|
||||
// Now convert HTML to Markdown
|
||||
$converter = new HtmlConverter();
|
||||
$text = $converter->convert($text);
|
||||
|
||||
// unmask the special chars back to HTML
|
||||
$text = str_replace(['&\_lt\_;', '&\_gt\_;', '&\_amp\_;'], ['<', '>', '&'], $text);
|
||||
|
||||
$a->save_timestamp($stamp1, "parser");
|
||||
|
||||
// Libertree has a problem with escaped hashtags.
|
||||
$text = str_replace(['\#'], ['#'], $text);
|
||||
|
||||
// Remove any leading or trailing whitespace, as this will mess up
|
||||
// the Diaspora signature verification and cause the item to disappear
|
||||
$text = trim($text);
|
||||
|
||||
if ($for_diaspora) {
|
||||
$url_search_string = "^\[\]";
|
||||
$text = preg_replace_callback(
|
||||
"/([@]\[(.*?)\])\(([$url_search_string]*?)\)/ism",
|
||||
['self', 'bbCodeMention2DiasporaCallback'],
|
||||
$text
|
||||
);
|
||||
}
|
||||
|
||||
// Restore code blocks
|
||||
$text = preg_replace_callback('/#codeblock-([0-9]+)#/iU',
|
||||
function ($matches) use ($codeblocks) {
|
||||
$return = '';
|
||||
if (isset($codeblocks[intval($matches[1])])) {
|
||||
$return = $codeblocks[$matches[1]];
|
||||
}
|
||||
return $return;
|
||||
},
|
||||
$text
|
||||
);
|
||||
|
||||
Addon::callHooks('bb2diaspora', $text);
|
||||
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
|
|
674
src/Content/Text/HTML.php
Normal file
674
src/Content/Text/HTML.php
Normal file
|
@ -0,0 +1,674 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file src/Content/Text/HTML.php
|
||||
*/
|
||||
|
||||
namespace Friendica\Content\Text;
|
||||
|
||||
use DOMDocument;
|
||||
use DOMXPath;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Util\Network;
|
||||
use Friendica\Util\XML;
|
||||
|
||||
class HTML
|
||||
{
|
||||
public static function sanitizeCSS($input)
|
||||
{
|
||||
$cleaned = "";
|
||||
|
||||
$input = strtolower($input);
|
||||
|
||||
for ($i = 0; $i < strlen($input); $i++) {
|
||||
$char = substr($input, $i, 1);
|
||||
|
||||
if (($char >= "a") && ($char <= "z")) {
|
||||
$cleaned .= $char;
|
||||
}
|
||||
|
||||
if (!(strpos(" #;:0123456789-_.%", $char) === false)) {
|
||||
$cleaned .= $char;
|
||||
}
|
||||
}
|
||||
|
||||
return $cleaned;
|
||||
}
|
||||
|
||||
private static function tagToBBCode(DOMDocument $doc, $tag, $attributes, $startbb, $endbb)
|
||||
{
|
||||
do {
|
||||
$done = self::tagToBBCodeSub($doc, $tag, $attributes, $startbb, $endbb);
|
||||
} while ($done);
|
||||
}
|
||||
|
||||
private static function tagToBBCodeSub(DOMDocument $doc, $tag, $attributes, $startbb, $endbb)
|
||||
{
|
||||
$savestart = str_replace('$', '\x01', $startbb);
|
||||
$replace = false;
|
||||
|
||||
$xpath = new DOMXPath($doc);
|
||||
|
||||
$list = $xpath->query("//" . $tag);
|
||||
foreach ($list as $node) {
|
||||
$attr = [];
|
||||
if ($node->attributes->length) {
|
||||
foreach ($node->attributes as $attribute) {
|
||||
$attr[$attribute->name] = $attribute->value;
|
||||
}
|
||||
}
|
||||
|
||||
$replace = true;
|
||||
|
||||
$startbb = $savestart;
|
||||
|
||||
$i = 0;
|
||||
|
||||
foreach ($attributes as $attribute => $value) {
|
||||
$startbb = str_replace('\x01' . ++$i, '$1', $startbb);
|
||||
if (strpos('*' . $startbb, '$1') > 0) {
|
||||
if ($replace && (@$attr[$attribute] != '')) {
|
||||
$startbb = preg_replace($value, $startbb, $attr[$attribute], -1, $count);
|
||||
|
||||
// If nothing could be changed
|
||||
if ($count == 0) {
|
||||
$replace = false;
|
||||
}
|
||||
} else {
|
||||
$replace = false;
|
||||
}
|
||||
} else {
|
||||
if (@$attr[$attribute] != $value) {
|
||||
$replace = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($replace) {
|
||||
$StartCode = $doc->createTextNode($startbb);
|
||||
$EndCode = $doc->createTextNode($endbb);
|
||||
|
||||
$node->parentNode->insertBefore($StartCode, $node);
|
||||
|
||||
if ($node->hasChildNodes()) {
|
||||
foreach ($node->childNodes as $child) {
|
||||
$newNode = $child->cloneNode(true);
|
||||
$node->parentNode->insertBefore($newNode, $node);
|
||||
}
|
||||
}
|
||||
|
||||
$node->parentNode->insertBefore($EndCode, $node);
|
||||
$node->parentNode->removeChild($node);
|
||||
}
|
||||
}
|
||||
|
||||
return $replace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Made by: ike@piratenpartei.de
|
||||
* Originally made for the syncom project: http://wiki.piratenpartei.de/Syncom
|
||||
* https://github.com/annando/Syncom
|
||||
*
|
||||
* @brief Converter for HTML to BBCode
|
||||
* @param string $message
|
||||
* @param string $basepath
|
||||
* @return string
|
||||
*/
|
||||
public static function toBBCode($message, $basepath = '')
|
||||
{
|
||||
$message = str_replace("\r", "", $message);
|
||||
|
||||
// Removing code blocks before the whitespace removal processing below
|
||||
$codeblocks = [];
|
||||
$message = preg_replace_callback(
|
||||
'#<pre><code(?: class="([^"]*)")?>(.*)</code></pre>#iUs',
|
||||
function ($matches) use (&$codeblocks) {
|
||||
$return = '[codeblock-' . count($codeblocks) . ']';
|
||||
|
||||
$prefix = '[code]';
|
||||
if ($matches[1] != '') {
|
||||
$prefix = '[code=' . $matches[1] . ']';
|
||||
}
|
||||
|
||||
$codeblocks[] = $prefix . trim($matches[2]) . '[/code]';
|
||||
return $return;
|
||||
},
|
||||
$message
|
||||
);
|
||||
|
||||
$message = str_replace(
|
||||
[
|
||||
"<li><p>",
|
||||
"</p></li>",
|
||||
], [
|
||||
"<li>",
|
||||
"</li>",
|
||||
], $message
|
||||
);
|
||||
|
||||
// remove namespaces
|
||||
$message = preg_replace('=<(\w+):(.+?)>=', '<removeme>', $message);
|
||||
$message = preg_replace('=</(\w+):(.+?)>=', '</removeme>', $message);
|
||||
|
||||
$doc = new DOMDocument();
|
||||
$doc->preserveWhiteSpace = false;
|
||||
|
||||
$message = mb_convert_encoding($message, 'HTML-ENTITIES', "UTF-8");
|
||||
|
||||
@$doc->loadHTML($message);
|
||||
|
||||
XML::deleteNode($doc, 'style');
|
||||
XML::deleteNode($doc, 'head');
|
||||
XML::deleteNode($doc, 'title');
|
||||
XML::deleteNode($doc, 'meta');
|
||||
XML::deleteNode($doc, 'xml');
|
||||
XML::deleteNode($doc, 'removeme');
|
||||
|
||||
$xpath = new DomXPath($doc);
|
||||
$list = $xpath->query("//pre");
|
||||
foreach ($list as $node) {
|
||||
$node->nodeValue = str_replace("\n", "\r", $node->nodeValue);
|
||||
}
|
||||
|
||||
$message = $doc->saveHTML();
|
||||
$message = str_replace(["\n<", ">\n", "\r", "\n", "\xC3\x82\xC2\xA0"], ["<", ">", "<br />", " ", ""], $message);
|
||||
$message = preg_replace('= [\s]*=i', " ", $message);
|
||||
@$doc->loadHTML($message);
|
||||
|
||||
self::tagToBBCode($doc, 'html', [], "", "");
|
||||
self::tagToBBCode($doc, 'body', [], "", "");
|
||||
|
||||
// Outlook-Quote - Variant 1
|
||||
self::tagToBBCode($doc, 'p', ['class' => 'MsoNormal', 'style' => 'margin-left:35.4pt'], '[quote]', '[/quote]');
|
||||
|
||||
// Outlook-Quote - Variant 2
|
||||
self::tagToBBCode($doc, 'div', ['style' => 'border:none;border-left:solid blue 1.5pt;padding:0cm 0cm 0cm 4.0pt'],
|
||||
'[quote]', '[/quote]');
|
||||
|
||||
// MyBB-Stuff
|
||||
self::tagToBBCode($doc, 'span', ['style' => 'text-decoration: underline;'], '[u]', '[/u]');
|
||||
self::tagToBBCode($doc, 'span', ['style' => 'font-style: italic;'], '[i]', '[/i]');
|
||||
self::tagToBBCode($doc, 'span', ['style' => 'font-weight: bold;'], '[b]', '[/b]');
|
||||
|
||||
/* self::node2BBCode($doc, 'font', array('face'=>'/([\w ]+)/', 'size'=>'/(\d+)/', 'color'=>'/(.+)/'), '[font=$1][size=$2][color=$3]', '[/color][/size][/font]');
|
||||
self::node2BBCode($doc, 'font', array('size'=>'/(\d+)/', 'color'=>'/(.+)/'), '[size=$1][color=$2]', '[/color][/size]');
|
||||
self::node2BBCode($doc, 'font', array('face'=>'/([\w ]+)/', 'size'=>'/(.+)/'), '[font=$1][size=$2]', '[/size][/font]');
|
||||
self::node2BBCode($doc, 'font', array('face'=>'/([\w ]+)/', 'color'=>'/(.+)/'), '[font=$1][color=$3]', '[/color][/font]');
|
||||
self::node2BBCode($doc, 'font', array('face'=>'/([\w ]+)/'), '[font=$1]', '[/font]');
|
||||
self::node2BBCode($doc, 'font', array('size'=>'/(\d+)/'), '[size=$1]', '[/size]');
|
||||
self::node2BBCode($doc, 'font', array('color'=>'/(.+)/'), '[color=$1]', '[/color]');
|
||||
*/
|
||||
// Untested
|
||||
//self::node2BBCode($doc, 'span', array('style'=>'/.*font-size:\s*(.+?)[,;].*font-family:\s*(.+?)[,;].*color:\s*(.+?)[,;].*/'), '[size=$1][font=$2][color=$3]', '[/color][/font][/size]');
|
||||
//self::node2BBCode($doc, 'span', array('style'=>'/.*font-size:\s*(\d+)[,;].*/'), '[size=$1]', '[/size]');
|
||||
//self::node2BBCode($doc, 'span', array('style'=>'/.*font-size:\s*(.+?)[,;].*/'), '[size=$1]', '[/size]');
|
||||
|
||||
self::tagToBBCode($doc, 'span', ['style' => '/.*color:\s*(.+?)[,;].*/'], '[color="$1"]', '[/color]');
|
||||
|
||||
//self::node2BBCode($doc, 'span', array('style'=>'/.*font-family:\s*(.+?)[,;].*/'), '[font=$1]', '[/font]');
|
||||
//self::node2BBCode($doc, 'div', array('style'=>'/.*font-family:\s*(.+?)[,;].*font-size:\s*(\d+?)pt.*/'), '[font=$1][size=$2]', '[/size][/font]');
|
||||
//self::node2BBCode($doc, 'div', array('style'=>'/.*font-family:\s*(.+?)[,;].*font-size:\s*(\d+?)px.*/'), '[font=$1][size=$2]', '[/size][/font]');
|
||||
//self::node2BBCode($doc, 'div', array('style'=>'/.*font-family:\s*(.+?)[,;].*/'), '[font=$1]', '[/font]');
|
||||
// Importing the classes - interesting for importing of posts from third party networks that were exported from friendica
|
||||
// Test
|
||||
//self::node2BBCode($doc, 'span', array('class'=>'/([\w ]+)/'), '[class=$1]', '[/class]');
|
||||
self::tagToBBCode($doc, 'span', ['class' => 'type-link'], '[class=type-link]', '[/class]');
|
||||
self::tagToBBCode($doc, 'span', ['class' => 'type-video'], '[class=type-video]', '[/class]');
|
||||
|
||||
self::tagToBBCode($doc, 'strong', [], '[b]', '[/b]');
|
||||
self::tagToBBCode($doc, 'em', [], '[i]', '[/i]');
|
||||
self::tagToBBCode($doc, 'b', [], '[b]', '[/b]');
|
||||
self::tagToBBCode($doc, 'i', [], '[i]', '[/i]');
|
||||
self::tagToBBCode($doc, 'u', [], '[u]', '[/u]');
|
||||
|
||||
self::tagToBBCode($doc, 'big', [], "[size=large]", "[/size]");
|
||||
self::tagToBBCode($doc, 'small', [], "[size=small]", "[/size]");
|
||||
|
||||
self::tagToBBCode($doc, 'blockquote', [], '[quote]', '[/quote]');
|
||||
|
||||
self::tagToBBCode($doc, 'br', [], "\n", '');
|
||||
|
||||
self::tagToBBCode($doc, 'p', ['class' => 'MsoNormal'], "\n", "");
|
||||
self::tagToBBCode($doc, 'div', ['class' => 'MsoNormal'], "\r", "");
|
||||
|
||||
self::tagToBBCode($doc, 'span', [], "", "");
|
||||
|
||||
self::tagToBBCode($doc, 'span', [], "", "");
|
||||
self::tagToBBCode($doc, 'pre', [], "", "");
|
||||
|
||||
self::tagToBBCode($doc, 'div', [], "\r", "\r");
|
||||
self::tagToBBCode($doc, 'p', [], "\n", "\n");
|
||||
|
||||
self::tagToBBCode($doc, 'ul', [], "[list]", "[/list]");
|
||||
self::tagToBBCode($doc, 'ol', [], "[list=1]", "[/list]");
|
||||
self::tagToBBCode($doc, 'li', [], "[*]", "");
|
||||
|
||||
self::tagToBBCode($doc, 'hr', [], "[hr]", "");
|
||||
|
||||
self::tagToBBCode($doc, 'table', [], "", "");
|
||||
self::tagToBBCode($doc, 'tr', [], "\n", "");
|
||||
self::tagToBBCode($doc, 'td', [], "\t", "");
|
||||
//self::node2BBCode($doc, 'table', array(), "[table]", "[/table]");
|
||||
//self::node2BBCode($doc, 'th', array(), "[th]", "[/th]");
|
||||
//self::node2BBCode($doc, 'tr', array(), "[tr]", "[/tr]");
|
||||
//self::node2BBCode($doc, 'td', array(), "[td]", "[/td]");
|
||||
//self::node2BBCode($doc, 'h1', array(), "\n\n[size=xx-large][b]", "[/b][/size]\n");
|
||||
//self::node2BBCode($doc, 'h2', array(), "\n\n[size=x-large][b]", "[/b][/size]\n");
|
||||
//self::node2BBCode($doc, 'h3', array(), "\n\n[size=large][b]", "[/b][/size]\n");
|
||||
//self::node2BBCode($doc, 'h4', array(), "\n\n[size=medium][b]", "[/b][/size]\n");
|
||||
//self::node2BBCode($doc, 'h5', array(), "\n\n[size=small][b]", "[/b][/size]\n");
|
||||
//self::node2BBCode($doc, 'h6', array(), "\n\n[size=x-small][b]", "[/b][/size]\n");
|
||||
|
||||
self::tagToBBCode($doc, 'h1', [], "[h1]", "[/h1]");
|
||||
self::tagToBBCode($doc, 'h2', [], "[h2]", "[/h2]");
|
||||
self::tagToBBCode($doc, 'h3', [], "[h3]", "[/h3]");
|
||||
self::tagToBBCode($doc, 'h4', [], "[h4]", "[/h4]");
|
||||
self::tagToBBCode($doc, 'h5', [], "[h5]", "[/h5]");
|
||||
self::tagToBBCode($doc, 'h6', [], "[h6]", "[/h6]");
|
||||
|
||||
self::tagToBBCode($doc, 'a', ['href' => '/mailto:(.+)/'], '[mail=$1]', '[/mail]');
|
||||
self::tagToBBCode($doc, 'a', ['href' => '/(.+)/'], '[url=$1]', '[/url]');
|
||||
|
||||
self::tagToBBCode($doc, 'img', ['src' => '/(.+)/', 'width' => '/(\d+)/', 'height' => '/(\d+)/'], '[img=$2x$3]$1',
|
||||
'[/img]');
|
||||
self::tagToBBCode($doc, 'img', ['src' => '/(.+)/'], '[img]$1', '[/img]');
|
||||
|
||||
|
||||
self::tagToBBCode($doc, 'video', ['src' => '/(.+)/'], '[video]$1', '[/video]');
|
||||
self::tagToBBCode($doc, 'audio', ['src' => '/(.+)/'], '[audio]$1', '[/audio]');
|
||||
self::tagToBBCode($doc, 'iframe', ['src' => '/(.+)/'], '[iframe]$1', '[/iframe]');
|
||||
|
||||
self::tagToBBCode($doc, 'key', [], '[code]', '[/code]');
|
||||
self::tagToBBCode($doc, 'code', [], '[code]', '[/code]');
|
||||
|
||||
$message = $doc->saveHTML();
|
||||
|
||||
// I'm removing something really disturbing
|
||||
// Don't know exactly what it is
|
||||
$message = str_replace(chr(194) . chr(160), ' ', $message);
|
||||
|
||||
$message = str_replace(" ", " ", $message);
|
||||
|
||||
// removing multiple DIVs
|
||||
$message = preg_replace('=\r *\r=i', "\n", $message);
|
||||
$message = str_replace("\r", "\n", $message);
|
||||
|
||||
Addon::callHooks('html2bbcode', $message);
|
||||
|
||||
$message = strip_tags($message);
|
||||
|
||||
$message = html_entity_decode($message, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
$message = str_replace(["<"], ["<"], $message);
|
||||
|
||||
// remove quotes if they don't make sense
|
||||
$message = preg_replace('=\[/quote\][\s]*\[quote\]=i', "\n", $message);
|
||||
|
||||
$message = preg_replace('=\[quote\]\s*=i', "[quote]", $message);
|
||||
$message = preg_replace('=\s*\[/quote\]=i', "[/quote]", $message);
|
||||
|
||||
do {
|
||||
$oldmessage = $message;
|
||||
$message = str_replace("\n \n", "\n\n", $message);
|
||||
} while ($oldmessage != $message);
|
||||
|
||||
do {
|
||||
$oldmessage = $message;
|
||||
$message = str_replace("\n\n\n", "\n\n", $message);
|
||||
} while ($oldmessage != $message);
|
||||
|
||||
do {
|
||||
$oldmessage = $message;
|
||||
$message = str_replace(
|
||||
[
|
||||
"[/size]\n\n",
|
||||
"\n[hr]",
|
||||
"[hr]\n",
|
||||
"\n[list",
|
||||
"[/list]\n",
|
||||
"\n[/",
|
||||
"[list]\n",
|
||||
"[list=1]\n",
|
||||
"\n[*]"],
|
||||
[
|
||||
"[/size]\n",
|
||||
"[hr]",
|
||||
"[hr]",
|
||||
"[list",
|
||||
"[/list]",
|
||||
"[/",
|
||||
"[list]",
|
||||
"[list=1]",
|
||||
"[*]"], $message
|
||||
);
|
||||
} while ($message != $oldmessage);
|
||||
|
||||
$message = str_replace(
|
||||
['[b][b]', '[/b][/b]', '[i][i]', '[/i][/i]'], ['[b]', '[/b]', '[i]', '[/i]'], $message
|
||||
);
|
||||
|
||||
// Handling Yahoo style of mails
|
||||
$message = str_replace('[hr][b]From:[/b]', '[quote][b]From:[/b]', $message);
|
||||
|
||||
// Restore code blocks
|
||||
$message = preg_replace_callback(
|
||||
'#\[codeblock-([0-9]+)\]#iU',
|
||||
function ($matches) use ($codeblocks) {
|
||||
$return = '';
|
||||
if (isset($codeblocks[intval($matches[1])])) {
|
||||
$return = $codeblocks[$matches[1]];
|
||||
}
|
||||
return $return;
|
||||
},
|
||||
$message
|
||||
);
|
||||
|
||||
$message = trim($message);
|
||||
|
||||
if ($basepath != '') {
|
||||
$message = self::qualifyURLs($message, $basepath);
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sub function to complete incomplete URL
|
||||
*
|
||||
* @param array $matches Result of preg_replace_callback
|
||||
* @param string $basepath Basepath that is used to complete the URL
|
||||
*
|
||||
* @return string The expanded URL
|
||||
*/
|
||||
private static function qualifyURLsSub($matches, $basepath)
|
||||
{
|
||||
$base = parse_url($basepath);
|
||||
unset($base['query']);
|
||||
unset($base['fragment']);
|
||||
|
||||
$link = $matches[0];
|
||||
$url = $matches[1];
|
||||
|
||||
$parts = array_merge($base, parse_url($url));
|
||||
$url2 = Network::unparseURL($parts);
|
||||
|
||||
return str_replace($url, $url2, $link);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Complete incomplete URLs in BBCode
|
||||
*
|
||||
* @param string $body Body with URLs
|
||||
* @param string $basepath Base path that is used to complete the URL
|
||||
*
|
||||
* @return string Body with expanded URLs
|
||||
*/
|
||||
private static function qualifyURLs($body, $basepath)
|
||||
{
|
||||
$URLSearchString = "^\[\]";
|
||||
|
||||
$matches = ["/\[url\=([$URLSearchString]*)\].*?\[\/url\]/ism",
|
||||
"/\[url\]([$URLSearchString]*)\[\/url\]/ism",
|
||||
"/\[img\=[0-9]*x[0-9]*\](.*?)\[\/img\]/ism",
|
||||
"/\[img\](.*?)\[\/img\]/ism",
|
||||
"/\[zmg\=[0-9]*x[0-9]*\](.*?)\[\/img\]/ism",
|
||||
"/\[zmg\](.*?)\[\/zmg\]/ism",
|
||||
"/\[video\](.*?)\[\/video\]/ism",
|
||||
"/\[audio\](.*?)\[\/audio\]/ism",
|
||||
];
|
||||
|
||||
foreach ($matches as $match) {
|
||||
$body = preg_replace_callback(
|
||||
$match, function ($match) use ($basepath) {
|
||||
return self::qualifyURLsSub($match, $basepath);
|
||||
},
|
||||
$body
|
||||
);
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
private static function breakLines($line, $level, $wraplength = 75)
|
||||
{
|
||||
if ($wraplength == 0) {
|
||||
$wraplength = 2000000;
|
||||
}
|
||||
|
||||
$wraplen = $wraplength - $level;
|
||||
|
||||
$newlines = [];
|
||||
|
||||
do {
|
||||
$oldline = $line;
|
||||
|
||||
$subline = substr($line, 0, $wraplen);
|
||||
|
||||
$pos = strrpos($subline, ' ');
|
||||
|
||||
if ($pos == 0) {
|
||||
$pos = strpos($line, ' ');
|
||||
}
|
||||
|
||||
if (($pos > 0) && strlen($line) > $wraplen) {
|
||||
$newline = trim(substr($line, 0, $pos));
|
||||
if ($level > 0) {
|
||||
$newline = str_repeat(">", $level) . ' ' . $newline;
|
||||
}
|
||||
|
||||
$newlines[] = $newline . " ";
|
||||
$line = substr($line, $pos + 1);
|
||||
}
|
||||
} while ((strlen($line) > $wraplen) && !($oldline == $line));
|
||||
|
||||
if ($level > 0) {
|
||||
$line = str_repeat(">", $level) . ' ' . $line;
|
||||
}
|
||||
|
||||
$newlines[] = $line;
|
||||
|
||||
return implode($newlines, "\n");
|
||||
}
|
||||
|
||||
private static function quoteLevel($message, $wraplength = 75)
|
||||
{
|
||||
$lines = explode("\n", $message);
|
||||
|
||||
$newlines = [];
|
||||
$level = 0;
|
||||
foreach ($lines as $line) {
|
||||
$line = trim($line);
|
||||
$startquote = false;
|
||||
while (strpos("*" . $line, '[quote]') > 0) {
|
||||
$level++;
|
||||
$pos = strpos($line, '[quote]');
|
||||
$line = substr($line, 0, $pos) . substr($line, $pos + 7);
|
||||
$startquote = true;
|
||||
}
|
||||
|
||||
$currlevel = $level;
|
||||
|
||||
while (strpos("*" . $line, '[/quote]') > 0) {
|
||||
$level--;
|
||||
if ($level < 0) {
|
||||
$level = 0;
|
||||
}
|
||||
|
||||
$pos = strpos($line, '[/quote]');
|
||||
$line = substr($line, 0, $pos) . substr($line, $pos + 8);
|
||||
}
|
||||
|
||||
if (!$startquote || ($line != '')) {
|
||||
$newlines[] = self::breakLines($line, $currlevel, $wraplength);
|
||||
}
|
||||
}
|
||||
|
||||
return implode($newlines, "\n");
|
||||
}
|
||||
|
||||
private static function collectURLs($message)
|
||||
{
|
||||
$pattern = '/<a.*?href="(.*?)".*?>(.*?)<\/a>/is';
|
||||
preg_match_all($pattern, $message, $result, PREG_SET_ORDER);
|
||||
|
||||
$urls = [];
|
||||
foreach ($result as $treffer) {
|
||||
$ignore = false;
|
||||
|
||||
// A list of some links that should be ignored
|
||||
$list = ["/user/", "/tag/", "/group/", "/profile/", "/search?search=", "/search?tag=", "mailto:", "/u/", "/node/",
|
||||
"//facebook.com/profile.php?id=", "//plus.google.com/", "//twitter.com/"];
|
||||
foreach ($list as $listitem) {
|
||||
if (strpos($treffer[1], $listitem) !== false) {
|
||||
$ignore = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((strpos($treffer[1], "//twitter.com/") !== false) && (strpos($treffer[1], "/status/") !== false)) {
|
||||
$ignore = false;
|
||||
}
|
||||
|
||||
if ((strpos($treffer[1], "//plus.google.com/") !== false) && (strpos($treffer[1], "/posts") !== false)) {
|
||||
$ignore = false;
|
||||
}
|
||||
|
||||
if ((strpos($treffer[1], "//plus.google.com/") !== false) && (strpos($treffer[1], "/photos") !== false)) {
|
||||
$ignore = false;
|
||||
}
|
||||
|
||||
if (!$ignore) {
|
||||
$urls[$treffer[1]] = $treffer[1];
|
||||
}
|
||||
}
|
||||
|
||||
return $urls;
|
||||
}
|
||||
|
||||
public static function toPlaintext($html, $wraplength = 75, $compact = false)
|
||||
{
|
||||
global $lang;
|
||||
|
||||
$message = str_replace("\r", "", $html);
|
||||
|
||||
$doc = new DOMDocument();
|
||||
$doc->preserveWhiteSpace = false;
|
||||
|
||||
$message = mb_convert_encoding($message, 'HTML-ENTITIES', "UTF-8");
|
||||
|
||||
@$doc->loadHTML($message);
|
||||
|
||||
$xpath = new DOMXPath($doc);
|
||||
$list = $xpath->query("//pre");
|
||||
foreach ($list as $node) {
|
||||
$node->nodeValue = str_replace("\n", "\r", $node->nodeValue);
|
||||
}
|
||||
|
||||
$message = $doc->saveHTML();
|
||||
$message = str_replace(["\n<", ">\n", "\r", "\n", "\xC3\x82\xC2\xA0"], ["<", ">", "<br>", " ", ""], $message);
|
||||
$message = preg_replace('= [\s]*=i', " ", $message);
|
||||
|
||||
// Collecting all links
|
||||
$urls = self::collectURLs($message);
|
||||
|
||||
@$doc->loadHTML($message);
|
||||
|
||||
self::tagToBBCode($doc, 'html', [], '', '');
|
||||
self::tagToBBCode($doc, 'body', [], '', '');
|
||||
|
||||
// MyBB-Auszeichnungen
|
||||
/*
|
||||
self::node2BBCode($doc, 'span', array('style'=>'text-decoration: underline;'), '_', '_');
|
||||
self::node2BBCode($doc, 'span', array('style'=>'font-style: italic;'), '/', '/');
|
||||
self::node2BBCode($doc, 'span', array('style'=>'font-weight: bold;'), '*', '*');
|
||||
|
||||
self::node2BBCode($doc, 'strong', array(), '*', '*');
|
||||
self::node2BBCode($doc, 'b', array(), '*', '*');
|
||||
self::node2BBCode($doc, 'i', array(), '/', '/');
|
||||
self::node2BBCode($doc, 'u', array(), '_', '_');
|
||||
*/
|
||||
|
||||
if ($compact) {
|
||||
self::tagToBBCode($doc, 'blockquote', [], "»", "«");
|
||||
} else {
|
||||
self::tagToBBCode($doc, 'blockquote', [], '[quote]', "[/quote]\n");
|
||||
}
|
||||
|
||||
self::tagToBBCode($doc, 'br', [], "\n", '');
|
||||
|
||||
self::tagToBBCode($doc, 'span', [], "", "");
|
||||
self::tagToBBCode($doc, 'pre', [], "", "");
|
||||
self::tagToBBCode($doc, 'div', [], "\r", "\r");
|
||||
self::tagToBBCode($doc, 'p', [], "\n", "\n");
|
||||
|
||||
//self::node2BBCode($doc, 'ul', array(), "\n[list]", "[/list]\n");
|
||||
//self::node2BBCode($doc, 'ol', array(), "\n[list=1]", "[/list]\n");
|
||||
self::tagToBBCode($doc, 'li', [], "\n* ", "\n");
|
||||
|
||||
self::tagToBBCode($doc, 'hr', [], "\n" . str_repeat("-", 70) . "\n", "");
|
||||
|
||||
self::tagToBBCode($doc, 'tr', [], "\n", "");
|
||||
self::tagToBBCode($doc, 'td', [], "\t", "");
|
||||
|
||||
self::tagToBBCode($doc, 'h1', [], "\n\n*", "*\n");
|
||||
self::tagToBBCode($doc, 'h2', [], "\n\n*", "*\n");
|
||||
self::tagToBBCode($doc, 'h3', [], "\n\n*", "*\n");
|
||||
self::tagToBBCode($doc, 'h4', [], "\n\n*", "*\n");
|
||||
self::tagToBBCode($doc, 'h5', [], "\n\n*", "*\n");
|
||||
self::tagToBBCode($doc, 'h6', [], "\n\n*", "*\n");
|
||||
|
||||
// Problem: there is no reliable way to detect if it is a link to a tag or profile
|
||||
//self::node2BBCode($doc, 'a', array('href'=>'/(.+)/'), ' $1 ', ' ', true);
|
||||
//self::node2BBCode($doc, 'a', array('href'=>'/(.+)/', 'rel'=>'oembed'), ' $1 ', '', true);
|
||||
//self::node2BBCode($doc, 'img', array('alt'=>'/(.+)/'), '$1', '');
|
||||
//self::node2BBCode($doc, 'img', array('title'=>'/(.+)/'), '$1', '');
|
||||
//self::node2BBCode($doc, 'img', array(), '', '');
|
||||
if (!$compact) {
|
||||
self::tagToBBCode($doc, 'img', ['src' => '/(.+)/'], ' [img]$1', '[/img] ');
|
||||
} else {
|
||||
self::tagToBBCode($doc, 'img', ['src' => '/(.+)/'], ' ', ' ');
|
||||
}
|
||||
|
||||
self::tagToBBCode($doc, 'iframe', ['src' => '/(.+)/'], ' $1 ', '');
|
||||
|
||||
$message = $doc->saveHTML();
|
||||
|
||||
if (!$compact) {
|
||||
$message = str_replace("[img]", "", $message);
|
||||
$message = str_replace("[/img]", "", $message);
|
||||
}
|
||||
|
||||
// was ersetze ich da?
|
||||
// Irgendein stoerrisches UTF-Zeug
|
||||
$message = str_replace(chr(194) . chr(160), ' ', $message);
|
||||
|
||||
$message = str_replace(" ", " ", $message);
|
||||
|
||||
// Aufeinanderfolgende DIVs
|
||||
$message = preg_replace('=\r *\r=i', "\n", $message);
|
||||
$message = str_replace("\r", "\n", $message);
|
||||
|
||||
$message = strip_tags($message);
|
||||
|
||||
$message = html_entity_decode($message, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
if (!$compact && ($message != '')) {
|
||||
foreach ($urls as $id => $url) {
|
||||
if ($url != '' && strpos($message, $url) === false) {
|
||||
$message .= "\n" . $url . ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$message = str_replace("\n«", "«\n", $message);
|
||||
$message = str_replace("»\n", "\n»", $message);
|
||||
|
||||
do {
|
||||
$oldmessage = $message;
|
||||
$message = str_replace("\n\n\n", "\n\n", $message);
|
||||
} while ($oldmessage != $message);
|
||||
|
||||
$message = self::quoteLevel(trim($message), $wraplength);
|
||||
|
||||
return trim($message);
|
||||
}
|
||||
}
|
|
@ -7,7 +7,9 @@
|
|||
namespace Friendica\Content\Text;
|
||||
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Model\Contact;
|
||||
use Michelf\MarkdownExtra;
|
||||
use Friendica\Content\Text\HTML;
|
||||
|
||||
/**
|
||||
* Friendica-specific usage of Markdown
|
||||
|
@ -36,4 +38,81 @@ class Markdown extends BaseObject
|
|||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback function to replace a Diaspora style mention in a mention for Friendica
|
||||
*
|
||||
* @param array $match Matching values for the callback
|
||||
* @return string Replaced mention
|
||||
*/
|
||||
private static function diasporaMention2BBCodeCallback($match)
|
||||
{
|
||||
if ($match[2] == '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = Contact::getDetailsByAddr($match[2]);
|
||||
|
||||
$name = $match[1];
|
||||
|
||||
if ($name == '') {
|
||||
$name = $data['name'];
|
||||
}
|
||||
|
||||
return '@[url=' . $data['url'] . ']' . $name . '[/url]';
|
||||
}
|
||||
|
||||
/*
|
||||
* we don't want to support a bbcode specific markdown interpreter
|
||||
* and the markdown library we have is pretty good, but provides HTML output.
|
||||
* So we'll use that to convert to HTML, then convert the HTML back to bbcode,
|
||||
* and then clean up a few Diaspora specific constructs.
|
||||
*/
|
||||
public static function toBBCode($s)
|
||||
{
|
||||
$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\#])/', '#$1', $s);
|
||||
|
||||
$s = self::convert($s);
|
||||
|
||||
$regexp = "/@\{(?:([^\}]+?); )?([^\} ]+)\}/";
|
||||
$s = preg_replace_callback($regexp, ['self', 'diasporaMention2BBCodeCallback'], $s);
|
||||
|
||||
$s = str_replace('#', '#', $s);
|
||||
|
||||
$s = HTML::toBBCode($s);
|
||||
|
||||
// protect the recycle symbol from turning into a tag, but without unescaping angles and naked ampersands
|
||||
$s = str_replace('♲', html_entity_decode('♲', ENT_QUOTES, 'UTF-8'), $s);
|
||||
|
||||
// Convert everything that looks like a link to a link
|
||||
$s = preg_replace('/([^\]=]|^)(https?\:\/\/)([a-zA-Z0-9:\/\-?&;.=_~#%$!+,@]+(?<!,))/ism', '$1[url=$2$3]$2$3[/url]', $s);
|
||||
|
||||
//$s = preg_replace("/([^\]\=]|^)(https?\:\/\/)(vimeo|youtu|www\.youtube|soundcloud)([a-zA-Z0-9\:\/\-\?\&\;\.\=\_\~\#\%\$\!\+\,]+)/ism", '$1[url=$2$3$4]$2$3$4[/url]',$s);
|
||||
$s = BBCode::pregReplaceInTag('/\[url\=?(.*?)\]https?:\/\/www.youtube.com\/watch\?v\=(.*?)\[\/url\]/ism', '[youtube]$2[/youtube]', 'url', $s);
|
||||
$s = BBCode::pregReplaceInTag('/\[url\=https?:\/\/www.youtube.com\/watch\?v\=(.*?)\].*?\[\/url\]/ism' , '[youtube]$1[/youtube]', 'url', $s);
|
||||
$s = BBCode::pregReplaceInTag('/\[url\=?(.*?)\]https?:\/\/vimeo.com\/([0-9]+)(.*?)\[\/url\]/ism' , '[vimeo]$2[/vimeo]' , 'url', $s);
|
||||
$s = BBCode::pregReplaceInTag('/\[url\=https?:\/\/vimeo.com\/([0-9]+)\](.*?)\[\/url\]/ism' , '[vimeo]$1[/vimeo]' , 'url', $s);
|
||||
|
||||
// remove duplicate adjacent code tags
|
||||
$s = preg_replace('/(\[code\])+(.*?)(\[\/code\])+/ism', '[code]$2[/code]', $s);
|
||||
|
||||
// Don't show link to full picture (until it is fixed)
|
||||
$s = BBCode::scaleExternalImages($s, false);
|
||||
|
||||
return $s;
|
||||
}
|
||||
}
|
||||
|
|
69
src/Content/Widget/CalendarExport.php
Normal file
69
src/Content/Widget/CalendarExport.php
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* @file src/Content/Widget/CalendarExport.php
|
||||
*/
|
||||
|
||||
namespace Friendica\Content\Widget;
|
||||
|
||||
use Friendica\Content\Feature;
|
||||
use Friendica\Core\L10n;
|
||||
|
||||
require_once 'boot.php';
|
||||
require_once 'include/text.php';
|
||||
|
||||
/**
|
||||
* TagCloud widget
|
||||
*
|
||||
* @author Rabuzarus
|
||||
*/
|
||||
class CalendarExport
|
||||
{
|
||||
/**
|
||||
* @brief Get the events widget.
|
||||
*
|
||||
* @return string Formated HTML of the calendar widget.
|
||||
*/
|
||||
public static function getHTML() {
|
||||
$a = get_app();
|
||||
|
||||
$owner_uid = $a->data['user']['uid'];
|
||||
|
||||
// The permission testing is a little bit tricky because we have to respect many cases.
|
||||
|
||||
// It's not the private events page (we don't get the $owner_uid for /events).
|
||||
if (!local_user() && !$owner_uid) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it's a kind of profile page (intval($owner_uid)) return if the user not logged in and
|
||||
* export feature isn't enabled.
|
||||
*/
|
||||
/*
|
||||
* Cal logged in user (test permission at foreign profile page).
|
||||
* If the $owner uid is available we know it is part of one of the profile pages (like /cal).
|
||||
* So we have to test if if it's the own profile page of the logged in user
|
||||
* or a foreign one. For foreign profile pages we need to check if the feature
|
||||
* for exporting the cal is enabled (otherwise the widget would appear for logged in users
|
||||
* on foreigen profile pages even if the widget is disabled).
|
||||
*/
|
||||
if (local_user() != $owner_uid && !Feature::isEnabled($owner_uid, "export_calendar")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// $a->data is only available if the profile page is visited. If the visited page is not part
|
||||
// of the profile page it should be the personal /events page. So we can use $a->user.
|
||||
$user = defaults($a->data['user'], 'nickname', $a->user['nickname']);
|
||||
|
||||
$tpl = get_markup_template("events_aside.tpl");
|
||||
$return = replace_macros($tpl, [
|
||||
'$etitle' => L10n::t("Export"),
|
||||
'$export_ical' => L10n::t("Export calendar as ical"),
|
||||
'$export_csv' => L10n::t("Export calendar as csv"),
|
||||
'$user' => $user
|
||||
]);
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
369
src/Core/ACL.php
Normal file
369
src/Core/ACL.php
Normal file
|
@ -0,0 +1,369 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file src/Core/Acl.php
|
||||
*/
|
||||
|
||||
namespace Friendica\Core;
|
||||
|
||||
use dba;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Content\Feature;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Model\Contact;
|
||||
use Friendica\Model\GContact;
|
||||
use Friendica\Util\Network;
|
||||
use const CONTACT_IS_FRIEND;
|
||||
use const NETWORK_DFRN;
|
||||
use const NETWORK_DIASPORA;
|
||||
use const NETWORK_FACEBOOK;
|
||||
use const NETWORK_MAIL;
|
||||
use const NETWORK_OSTATUS;
|
||||
use const PHP_EOL;
|
||||
use function dbesc;
|
||||
use function defaults;
|
||||
use function get_markup_template;
|
||||
use function get_server;
|
||||
use function local_user;
|
||||
use function remote_user;
|
||||
use function replace_macros;
|
||||
|
||||
/**
|
||||
* Handle ACL management and display
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
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
|
||||
* @return string
|
||||
*/
|
||||
public static function getSuggestContactSelectHTML($selname, $selclass, array $options = [], array $preselected = [])
|
||||
{
|
||||
$a = self::getApp();
|
||||
|
||||
$networks = null;
|
||||
|
||||
$size = defaults($options, 'size', 4);
|
||||
$mutual = !empty($options['mutual_friends']);
|
||||
$single = !empty($options['single']) && empty($options['multiple']);
|
||||
$exclude = defaults($options, 'exclude', false);
|
||||
|
||||
switch (defaults($options, 'networks', Protocol::PHANTOM)) {
|
||||
case 'DFRN_ONLY':
|
||||
$networks = [NETWORK_DFRN];
|
||||
break;
|
||||
case 'PRIVATE':
|
||||
if (!empty($a->user['prvnets'])) {
|
||||
$networks = [NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA];
|
||||
} else {
|
||||
$networks = [NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA];
|
||||
}
|
||||
break;
|
||||
case 'TWO_WAY':
|
||||
if (!empty($a->user['prvnets'])) {
|
||||
$networks = [NETWORK_DFRN, NETWORK_MAIL, NETWORK_DIASPORA];
|
||||
} else {
|
||||
$networks = [NETWORK_DFRN, NETWORK_FACEBOOK, NETWORK_MAIL, NETWORK_DIASPORA, NETWORK_OSTATUS];
|
||||
}
|
||||
break;
|
||||
default: /// @TODO Maybe log this call?
|
||||
break;
|
||||
}
|
||||
|
||||
$x = ['options' => $options, 'size' => $size, 'single' => $single, 'mutual' => $mutual, 'exclude' => $exclude, 'networks' => $networks];
|
||||
|
||||
Addon::callHooks('contact_select_options', $x);
|
||||
|
||||
$o = '';
|
||||
|
||||
$sql_extra = '';
|
||||
|
||||
if (!empty($x['mutual'])) {
|
||||
$sql_extra .= sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND));
|
||||
}
|
||||
|
||||
if (!empty($x['exclude'])) {
|
||||
$sql_extra .= sprintf(" AND `id` != %d ", intval($x['exclude']));
|
||||
}
|
||||
|
||||
if (!empty($x['networks'])) {
|
||||
/// @TODO rewrite to foreach()
|
||||
array_walk($x['networks'], function (&$value) {
|
||||
$value = "'" . dbesc($value) . "'";
|
||||
});
|
||||
$str_nets = implode(',', $x['networks']);
|
||||
$sql_extra .= " AND `network` IN ( $str_nets ) ";
|
||||
}
|
||||
|
||||
$tabindex = (!empty($options['tabindex']) ? 'tabindex="' . $options["tabindex"] . '"' : '');
|
||||
|
||||
if (!empty($x['single'])) {
|
||||
$o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"" . $x['size'] . "\" $tabindex >\r\n";
|
||||
} else {
|
||||
$o .= "<select name=\"{$selname}[]\" id=\"$selclass\" class=\"$selclass\" multiple=\"multiple\" size=\"" . $x['size'] . "$\" $tabindex >\r\n";
|
||||
}
|
||||
|
||||
$stmt = dba::p("SELECT `id`, `name`, `url`, `network` FROM `contact`
|
||||
WHERE `uid` = ? AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
|
||||
$sql_extra
|
||||
ORDER BY `name` ASC ", intval(local_user())
|
||||
);
|
||||
|
||||
$contacts = dba::inArray($stmt);
|
||||
|
||||
$arr = ['contact' => $contacts, 'entry' => $o];
|
||||
|
||||
// e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'
|
||||
Addon::callHooks($a->module . '_pre_' . $selname, $arr);
|
||||
|
||||
if (DBM::is_result($contacts)) {
|
||||
foreach ($contacts as $contact) {
|
||||
if (in_array($contact['id'], $preselected)) {
|
||||
$selected = ' selected="selected" ';
|
||||
} else {
|
||||
$selected = '';
|
||||
}
|
||||
|
||||
$trimmed = mb_substr($contact['name'], 0, 20);
|
||||
|
||||
$o .= "<option value=\"{$contact['id']}\" $selected title=\"{$contact['name']}|{$contact['url']}\" >$trimmed</option>\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
$o .= '</select>' . PHP_EOL;
|
||||
|
||||
Addon::callHooks($a->module . '_post_' . $selname, $o);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 $preselected Contact IDs that should be already selected
|
||||
* @param int $size Length of the select box
|
||||
* @param int $tabindex Select input tag tabindex attribute
|
||||
* @return string
|
||||
*/
|
||||
public static function getMessageContactSelectHTML($selname, $selclass, array $preselected = [], $size = 4, $tabindex = null)
|
||||
{
|
||||
$a = self::getApp();
|
||||
|
||||
$o = '';
|
||||
|
||||
// When used for private messages, we limit correspondence to mutual DFRN/Friendica friends and the selector
|
||||
// to one recipient. By default our selector allows multiple selects amongst all contacts.
|
||||
$sql_extra = sprintf(" AND `rel` = %d ", intval(CONTACT_IS_FRIEND));
|
||||
$sql_extra .= sprintf(" AND `network` IN ('%s' , '%s') ", NETWORK_DFRN, NETWORK_DIASPORA);
|
||||
|
||||
$tabindex_attr = !empty($tabindex) ? ' tabindex="' . intval($tabindex) . '"' : '';
|
||||
|
||||
$hidepreselected = '';
|
||||
if ($preselected) {
|
||||
$sql_extra .= " AND `id` IN (" . implode(",", $preselected) . ")";
|
||||
$hidepreselected = ' style="display: none;"';
|
||||
}
|
||||
|
||||
$o .= "<select name=\"$selname\" id=\"$selclass\" class=\"$selclass\" size=\"$size\"$tabindex_attr$hidepreselected>\r\n";
|
||||
|
||||
$stmt = dba::p("SELECT `id`, `name`, `url`, `network` FROM `contact`
|
||||
WHERE `uid` = ? AND NOT `self` AND NOT `blocked` AND NOT `pending` AND NOT `archive` AND `notify` != ''
|
||||
$sql_extra
|
||||
ORDER BY `name` ASC ", intval(local_user())
|
||||
);
|
||||
|
||||
$contacts = dba::inArray($stmt);
|
||||
|
||||
$arr = ['contact' => $contacts, 'entry' => $o];
|
||||
|
||||
// e.g. 'network_pre_contact_deny', 'profile_pre_contact_allow'
|
||||
Addon::callHooks($a->module . '_pre_' . $selname, $arr);
|
||||
|
||||
$receiverlist = [];
|
||||
|
||||
if (DBM::is_result($contacts)) {
|
||||
foreach ($contacts as $contact) {
|
||||
if (in_array($contact['id'], $preselected)) {
|
||||
$selected = ' selected="selected"';
|
||||
} else {
|
||||
$selected = '';
|
||||
}
|
||||
|
||||
$trimmed = Protocol::formatMention($contact['url'], $contact['name']);
|
||||
|
||||
$receiverlist[] = $trimmed;
|
||||
|
||||
$o .= "<option value=\"{$contact['id']}\"$selected title=\"{$contact['name']}|{$contact['url']}\" >$trimmed</option>\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
$o .= '</select>' . PHP_EOL;
|
||||
|
||||
if ($preselected) {
|
||||
$o .= implode(', ', $receiverlist);
|
||||
}
|
||||
|
||||
Addon::callHooks($a->module . '_post_' . $selname, $o);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
private static function fixACL(&$item)
|
||||
{
|
||||
$item = intval(str_replace(['<', '>'], ['', ''], $item));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default permission of the provided user array
|
||||
*
|
||||
* @param array $user
|
||||
* @return array Hash of contact id lists
|
||||
*/
|
||||
public static function getDefaultUserPermissions(array $user = null)
|
||||
{
|
||||
$matches = [];
|
||||
|
||||
$acl_regex = '/<([0-9]+)>/i';
|
||||
|
||||
preg_match_all($acl_regex, defaults($user, 'allow_cid', ''), $matches);
|
||||
$allow_cid = $matches[1];
|
||||
preg_match_all($acl_regex, defaults($user, 'allow_gid', ''), $matches);
|
||||
$allow_gid = $matches[1];
|
||||
preg_match_all($acl_regex, defaults($user, 'deny_cid', ''), $matches);
|
||||
$deny_cid = $matches[1];
|
||||
preg_match_all($acl_regex, defaults($user, 'deny_gid', ''), $matches);
|
||||
$deny_gid = $matches[1];
|
||||
|
||||
// Reformats the ACL data so that it is accepted by the JS frontend
|
||||
array_walk($allow_cid, 'self::fixACL');
|
||||
array_walk($allow_gid, 'self::fixACL');
|
||||
array_walk($deny_cid, 'self::fixACL');
|
||||
array_walk($deny_gid, 'self::fixACL');
|
||||
|
||||
Contact::pruneUnavailable($allow_cid);
|
||||
|
||||
return [
|
||||
'allow_cid' => $allow_cid,
|
||||
'allow_gid' => $allow_gid,
|
||||
'deny_cid' => $deny_cid,
|
||||
'deny_gid' => $deny_gid,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full jot ACL selector HTML
|
||||
*
|
||||
* @param array $user
|
||||
* @param bool $show_jotnets
|
||||
* @return string
|
||||
*/
|
||||
public static function getFullSelectorHTML(array $user = null, $show_jotnets = false)
|
||||
{
|
||||
$perms = self::getDefaultUserPermissions($user);
|
||||
|
||||
$jotnets = '';
|
||||
if ($show_jotnets) {
|
||||
$imap_disabled = !function_exists('imap_open') || Config::get('system', 'imap_disabled');
|
||||
|
||||
$mail_enabled = false;
|
||||
$pubmail_enabled = false;
|
||||
|
||||
if (!$imap_disabled) {
|
||||
$mailacct = dba::selectFirst('mailacct', ['pubmail'], ['`uid` = ? AND `server` != ""', local_user()]);
|
||||
if (DBM::is_result($mailacct)) {
|
||||
$mail_enabled = true;
|
||||
$pubmail_enabled = !empty($mailacct['pubmail']);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($user['hidewall'])) {
|
||||
if ($mail_enabled) {
|
||||
$selected = $pubmail_enabled ? ' checked="checked"' : '';
|
||||
$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);
|
||||
} else {
|
||||
$jotnets .= L10n::t('Connectors disabled, since "%s" is enabled.',
|
||||
L10n::t('Hide your profile details from unknown viewers?'));
|
||||
}
|
||||
}
|
||||
|
||||
$tpl = get_markup_template('acl_selector.tpl');
|
||||
$o = replace_macros($tpl, [
|
||||
'$showall' => L10n::t('Visible to everybody'),
|
||||
'$show' => L10n::t('show'),
|
||||
'$hide' => L10n::t('don\'t show'),
|
||||
'$allowcid' => json_encode($perms['allow_cid']),
|
||||
'$allowgid' => json_encode($perms['allow_gid']),
|
||||
'$denycid' => json_encode($perms['deny_cid']),
|
||||
'$denygid' => json_encode($perms['deny_gid']),
|
||||
'$networks' => $show_jotnets,
|
||||
'$emailcc' => L10n::t('CC: email addresses'),
|
||||
'$emtitle' => L10n::t('Example: bob@example.com, mary@example.com'),
|
||||
'$jotnets' => $jotnets,
|
||||
'$aclModalTitle' => L10n::t('Permissions'),
|
||||
'$aclModalDismiss' => L10n::t('Close'),
|
||||
'$features' => [
|
||||
'aclautomention' => Feature::isEnabled($user['uid'], 'aclautomention') ? 'true' : 'false'
|
||||
],
|
||||
]);
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searching for global contacts for autocompletion
|
||||
*
|
||||
* @brief Searching for global contacts for autocompletion
|
||||
* @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
|
||||
*/
|
||||
public static function contactAutocomplete($search, $mode)
|
||||
{
|
||||
if ((Config::get('system', 'block_public')) && (!local_user()) && (!remote_user())) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// don't search if search term has less than 2 characters
|
||||
if (!$search || mb_strlen($search) < 2) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (substr($search, 0, 1) === '@') {
|
||||
$search = substr($search, 1);
|
||||
}
|
||||
|
||||
// check if searching in the local global contact table is enabled
|
||||
if (Config::get('system', 'poco_local_search')) {
|
||||
$return = GContact::searchByName($search, $mode);
|
||||
} else {
|
||||
$a = self::getApp();
|
||||
$p = $a->pager['page'] != 1 ? '&p=' . $a->pager['page'] : '';
|
||||
|
||||
$response = Network::curl(get_server() . '/lsearch?f=' . $p . '&search=' . urlencode($search));
|
||||
if ($response['success']) {
|
||||
$lsearch = json_decode($response['body'], true);
|
||||
if (!empty($lsearch['results'])) {
|
||||
$return = $lsearch['results'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return defaults($return, []);
|
||||
}
|
||||
}
|
|
@ -4,83 +4,59 @@
|
|||
*/
|
||||
namespace Friendica\Core;
|
||||
|
||||
use Friendica\Core\Cache;
|
||||
use Friendica\Core\Config;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
use dba;
|
||||
use Memcache;
|
||||
|
||||
require_once 'include/dba.php';
|
||||
|
||||
/**
|
||||
* @brief Class for storing data for a short time
|
||||
*/
|
||||
class Cache
|
||||
class Cache extends \Friendica\BaseObject
|
||||
{
|
||||
const MONTH = 2592000;
|
||||
const WEEK = 604800;
|
||||
const DAY = 86400;
|
||||
const HOUR = 3600;
|
||||
const HALF_HOUR = 1800;
|
||||
const QUARTER_HOUR = 900;
|
||||
const FIVE_MINUTES = 300;
|
||||
const MINUTE = 60;
|
||||
|
||||
/**
|
||||
* @brief Check for Memcache and open a connection if configured
|
||||
*
|
||||
* @return Memcache|boolean The Memcache object - or "false" if not successful
|
||||
* @var Cache\ICacheDriver
|
||||
*/
|
||||
public static function memcache()
|
||||
static $driver = null;
|
||||
|
||||
public static function init()
|
||||
{
|
||||
if (!class_exists('Memcache', false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Config::get('system', 'memcache')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(Config::get('system', 'cache_driver', 'database')) {
|
||||
case 'memcache':
|
||||
$memcache_host = Config::get('system', 'memcache_host', '127.0.0.1');
|
||||
$memcache_port = Config::get('system', 'memcache_port', 11211);
|
||||
|
||||
$memcache = new Memcache();
|
||||
self::$driver = new Cache\MemcacheCacheDriver($memcache_host, $memcache_port);
|
||||
break;
|
||||
case 'memcached':
|
||||
$memcached_hosts = Config::get('system', 'memcached_hosts', [['127.0.0.1', 11211]]);
|
||||
|
||||
if (!$memcache->connect($memcache_host, $memcache_port)) {
|
||||
return false;
|
||||
self::$driver = new Cache\MemcachedCacheDriver($memcached_hosts);
|
||||
break;
|
||||
default:
|
||||
self::$driver = new Cache\DatabaseCacheDriver();
|
||||
}
|
||||
|
||||
return $memcache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the duration for a given cache level
|
||||
* Returns the current cache driver
|
||||
*
|
||||
* @param integer $level Cache level
|
||||
*
|
||||
* @return integer The cache duration in seconds
|
||||
* @return Cache\ICacheDriver
|
||||
*/
|
||||
private static function duration($level)
|
||||
private static function getDriver()
|
||||
{
|
||||
switch ($level) {
|
||||
case CACHE_MONTH:
|
||||
$seconds = 2592000;
|
||||
break;
|
||||
case CACHE_WEEK:
|
||||
$seconds = 604800;
|
||||
break;
|
||||
case CACHE_DAY:
|
||||
$seconds = 86400;
|
||||
break;
|
||||
case CACHE_HOUR:
|
||||
$seconds = 3600;
|
||||
break;
|
||||
case CACHE_HALF_HOUR:
|
||||
$seconds = 1800;
|
||||
break;
|
||||
case CACHE_QUARTER_HOUR:
|
||||
$seconds = 900;
|
||||
break;
|
||||
case CACHE_FIVE_MINUTES:
|
||||
$seconds = 300;
|
||||
break;
|
||||
case CACHE_MINUTE:
|
||||
default:
|
||||
$seconds = 60;
|
||||
break;
|
||||
if (self::$driver === null) {
|
||||
self::init();
|
||||
}
|
||||
return $seconds;
|
||||
|
||||
return self::$driver;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,40 +68,13 @@ class Cache
|
|||
*/
|
||||
public static function get($key)
|
||||
{
|
||||
$memcache = self::memcache();
|
||||
if (is_object($memcache)) {
|
||||
// We fetch with the hostname as key to avoid problems with other applications
|
||||
$cached = $memcache->get(get_app()->get_hostname().":".$key);
|
||||
$value = @unserialize($cached);
|
||||
$time = microtime(true);
|
||||
|
||||
// Only return a value if the serialized value is valid.
|
||||
// We also check if the db entry is a serialized
|
||||
// boolean 'false' value (which we want to return).
|
||||
if ($cached === serialize(false) || $value !== false) {
|
||||
return $value;
|
||||
}
|
||||
$return = self::getDriver()->get($key);
|
||||
|
||||
return null;
|
||||
}
|
||||
self::getApp()->save_timestamp($time, 'cache');
|
||||
|
||||
// Frequently clear cache
|
||||
self::clear();
|
||||
|
||||
$cache = dba::selectFirst('cache', ['v'], ['k' => $key]);
|
||||
|
||||
if (DBM::is_result($cache)) {
|
||||
$cached = $cache['v'];
|
||||
$value = @unserialize($cached);
|
||||
|
||||
// Only return a value if the serialized value is valid.
|
||||
// We also check if the db entry is a serialized
|
||||
// boolean 'false' value (which we want to return).
|
||||
if ($cached === serialize(false) || $value !== false) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,20 +86,35 @@ class Cache
|
|||
* @param mixed $value The value that is about to be stored
|
||||
* @param integer $duration The cache lifespan
|
||||
*
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public static function set($key, $value, $duration = CACHE_MONTH)
|
||||
public static function set($key, $value, $duration = self::MONTH)
|
||||
{
|
||||
// Do we have an installed memcache? Use it instead.
|
||||
$memcache = self::memcache();
|
||||
if (is_object($memcache)) {
|
||||
// We store with the hostname as key to avoid problems with other applications
|
||||
$memcache->set(get_app()->get_hostname().":".$key, serialize($value), MEMCACHE_COMPRESSED, self::duration($duration));
|
||||
return;
|
||||
$time = microtime(true);
|
||||
|
||||
$return = self::getDriver()->set($key, $value, $duration);
|
||||
|
||||
self::getApp()->save_timestamp($time, 'cache_write');
|
||||
|
||||
return $return;
|
||||
}
|
||||
$fields = ['v' => serialize($value), 'expire_mode' => $duration, 'updated' => DateTimeFormat::utcNow()];
|
||||
$condition = ['k' => $key];
|
||||
dba::update('cache', $fields, $condition, true);
|
||||
|
||||
/**
|
||||
* @brief Delete a value from the cache
|
||||
*
|
||||
* @param string $key The key to the cached data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function delete($key)
|
||||
{
|
||||
$time = microtime(true);
|
||||
|
||||
$return = self::getDriver()->delete($key);
|
||||
|
||||
self::getApp()->save_timestamp($time, 'cache_write');
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -160,76 +124,8 @@ class Cache
|
|||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function clear($max_level = CACHE_MONTH)
|
||||
public static function clear()
|
||||
{
|
||||
// Clear long lasting cache entries only once a day
|
||||
if (Config::get("system", "cache_cleared_day") < time() - self::duration(CACHE_DAY)) {
|
||||
if ($max_level == CACHE_MONTH) {
|
||||
$condition = ["`updated` < ? AND `expire_mode` = ?",
|
||||
DateTimeFormat::utc("now - 30 days"),
|
||||
CACHE_MONTH];
|
||||
dba::delete('cache', $condition);
|
||||
}
|
||||
|
||||
if ($max_level <= CACHE_WEEK) {
|
||||
$condition = ["`updated` < ? AND `expire_mode` = ?",
|
||||
DateTimeFormat::utc("now - 7 days"),
|
||||
CACHE_WEEK];
|
||||
dba::delete('cache', $condition);
|
||||
}
|
||||
|
||||
if ($max_level <= CACHE_DAY) {
|
||||
$condition = ["`updated` < ? AND `expire_mode` = ?",
|
||||
DateTimeFormat::utc("now - 1 days"),
|
||||
CACHE_DAY];
|
||||
dba::delete('cache', $condition);
|
||||
}
|
||||
Config::set("system", "cache_cleared_day", time());
|
||||
}
|
||||
|
||||
if (($max_level <= CACHE_HOUR) && (Config::get("system", "cache_cleared_hour")) < time() - self::duration(CACHE_HOUR)) {
|
||||
$condition = ["`updated` < ? AND `expire_mode` = ?",
|
||||
DateTimeFormat::utc("now - 1 hours"),
|
||||
CACHE_HOUR];
|
||||
dba::delete('cache', $condition);
|
||||
|
||||
Config::set("system", "cache_cleared_hour", time());
|
||||
}
|
||||
|
||||
if (($max_level <= CACHE_HALF_HOUR) && (Config::get("system", "cache_cleared_half_hour")) < time() - self::duration(CACHE_HALF_HOUR)) {
|
||||
$condition = ["`updated` < ? AND `expire_mode` = ?",
|
||||
DateTimeFormat::utc("now - 30 minutes"),
|
||||
CACHE_HALF_HOUR];
|
||||
dba::delete('cache', $condition);
|
||||
|
||||
Config::set("system", "cache_cleared_half_hour", time());
|
||||
}
|
||||
|
||||
if (($max_level <= CACHE_QUARTER_HOUR) && (Config::get("system", "cache_cleared_quarter_hour")) < time() - self::duration(CACHE_QUARTER_HOUR)) {
|
||||
$condition = ["`updated` < ? AND `expire_mode` = ?",
|
||||
DateTimeFormat::utc("now - 15 minutes"),
|
||||
CACHE_QUARTER_HOUR];
|
||||
dba::delete('cache', $condition);
|
||||
|
||||
Config::set("system", "cache_cleared_quarter_hour", time());
|
||||
}
|
||||
|
||||
if (($max_level <= CACHE_FIVE_MINUTES) && (Config::get("system", "cache_cleared_five_minute")) < time() - self::duration(CACHE_FIVE_MINUTES)) {
|
||||
$condition = ["`updated` < ? AND `expire_mode` = ?",
|
||||
DateTimeFormat::utc("now - 5 minutes"),
|
||||
CACHE_FIVE_MINUTES];
|
||||
dba::delete('cache', $condition);
|
||||
|
||||
Config::set("system", "cache_cleared_five_minute", time());
|
||||
}
|
||||
|
||||
if (($max_level <= CACHE_MINUTE) && (Config::get("system", "cache_cleared_minute")) < time() - self::duration(CACHE_MINUTE)) {
|
||||
$condition = ["`updated` < ? AND `expire_mode` = ?",
|
||||
DateTimeFormat::utc("now - 1 minutes"),
|
||||
CACHE_MINUTE];
|
||||
dba::delete('cache', $condition);
|
||||
|
||||
Config::set("system", "cache_cleared_minute", time());
|
||||
}
|
||||
return self::getDriver()->clear();
|
||||
}
|
||||
}
|
||||
|
|
56
src/Core/Cache/DatabaseCacheDriver.php
Normal file
56
src/Core/Cache/DatabaseCacheDriver.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Cache;
|
||||
|
||||
use dba;
|
||||
use Friendica\Core\Cache;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Util\DateTimeFormat;
|
||||
|
||||
/**
|
||||
* Database Cache Driver
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class DatabaseCacheDriver implements ICacheDriver
|
||||
{
|
||||
public function get($key)
|
||||
{
|
||||
$cache = dba::selectFirst('cache', ['v'], ['`k` = ? AND `expires` >= ?', $key, DateTimeFormat::utcNow()]);
|
||||
|
||||
if (DBM::is_result($cache)) {
|
||||
$cached = $cache['v'];
|
||||
$value = @unserialize($cached);
|
||||
|
||||
// Only return a value if the serialized value is valid.
|
||||
// We also check if the db entry is a serialized
|
||||
// boolean 'false' value (which we want to return).
|
||||
if ($cached === serialize(false) || $value !== false) {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function set($key, $value, $duration = Cache::MONTH)
|
||||
{
|
||||
$fields = [
|
||||
'v' => serialize($value),
|
||||
'expires' => DateTimeFormat::utc('now + ' . $duration . ' seconds'),
|
||||
'updated' => DateTimeFormat::utcNow()
|
||||
];
|
||||
|
||||
return dba::update('cache', $fields, ['k' => $key], true);
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
return dba::delete('cache', ['k' => $key]);
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
return dba::delete('cache', ['`expires` < NOW()']);
|
||||
}
|
||||
}
|
50
src/Core/Cache/ICacheDriver.php
Normal file
50
src/Core/Cache/ICacheDriver.php
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Cache;
|
||||
|
||||
use Friendica\Core\Cache;
|
||||
|
||||
/**
|
||||
* Cache Driver Interface
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
interface ICacheDriver
|
||||
{
|
||||
/**
|
||||
* Fetches cached data according to the key
|
||||
*
|
||||
* @param string $key The key to the cached data
|
||||
*
|
||||
* @return mixed Cached $value or "null" if not found
|
||||
*/
|
||||
public function get($key);
|
||||
|
||||
/**
|
||||
* Stores data in the cache identified by the key. The input $value can have multiple formats.
|
||||
*
|
||||
* @param string $key The cache key
|
||||
* @param mixed $value The value to store
|
||||
* @param integer $duration The cache lifespan, must be one of the Cache constants
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function set($key, $value, $duration = Cache::MONTH);
|
||||
|
||||
|
||||
/**
|
||||
* Delete a key from the cache
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function delete($key);
|
||||
|
||||
/**
|
||||
* Remove outdated data from the cache
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function clear();
|
||||
}
|
77
src/Core/Cache/MemcacheCacheDriver.php
Normal file
77
src/Core/Cache/MemcacheCacheDriver.php
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Cache;
|
||||
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Core\Cache;
|
||||
|
||||
/**
|
||||
* Memcache Cache Driver
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class MemcacheCacheDriver extends BaseObject implements ICacheDriver
|
||||
{
|
||||
/**
|
||||
* @var Memcache
|
||||
*/
|
||||
private $memcache;
|
||||
|
||||
public function __construct($memcache_host, $memcache_port)
|
||||
{
|
||||
if (!class_exists('Memcache', false)) {
|
||||
throw new \Exception('Memcache class isn\'t available');
|
||||
}
|
||||
|
||||
$this->memcache = new \Memcache();
|
||||
|
||||
if (!$this->memcache->connect($memcache_host, $memcache_port)) {
|
||||
throw new \Exception('Expected Memcache server at ' . $memcache_host . ':' . $memcache_port . ' isn\'t available');
|
||||
}
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$return = null;
|
||||
|
||||
// We fetch with the hostname as key to avoid problems with other applications
|
||||
$cached = $this->memcache->get(self::getApp()->get_hostname() . ':' . $key);
|
||||
|
||||
// @see http://php.net/manual/en/memcache.get.php#84275
|
||||
if (is_bool($cached) || is_double($cached) || is_long($cached)) {
|
||||
return $return;
|
||||
}
|
||||
|
||||
$value = @unserialize($cached);
|
||||
|
||||
// Only return a value if the serialized value is valid.
|
||||
// We also check if the db entry is a serialized
|
||||
// boolean 'false' value (which we want to return).
|
||||
if ($cached === serialize(false) || $value !== false) {
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function set($key, $value, $duration = Cache::MONTH)
|
||||
{
|
||||
// We store with the hostname as key to avoid problems with other applications
|
||||
return $this->memcache->set(
|
||||
self::getApp()->get_hostname() . ":" . $key,
|
||||
serialize($value),
|
||||
MEMCACHE_COMPRESSED,
|
||||
time() + $duration
|
||||
);
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
return $this->memcache->delete($key);
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
68
src/Core/Cache/MemcachedCacheDriver.php
Normal file
68
src/Core/Cache/MemcachedCacheDriver.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Cache;
|
||||
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Core\Cache;
|
||||
|
||||
/**
|
||||
* Memcached Cache Driver
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class MemcachedCacheDriver extends BaseObject implements ICacheDriver
|
||||
{
|
||||
/**
|
||||
* @var Memcached
|
||||
*/
|
||||
private $memcached;
|
||||
|
||||
public function __construct(array $memcached_hosts)
|
||||
{
|
||||
if (!class_exists('Memcached', false)) {
|
||||
throw new \Exception('Memcached class isn\'t available');
|
||||
}
|
||||
|
||||
$this->memcached = new \Memcached();
|
||||
|
||||
$this->memcached->addServers($memcached_hosts);
|
||||
|
||||
if (count($this->memcached->getServerList()) == 0) {
|
||||
throw new \Exception('Expected Memcached servers aren\'t available, config:' . var_export($memcached_hosts, true));
|
||||
}
|
||||
}
|
||||
|
||||
public function get($key)
|
||||
{
|
||||
$return = null;
|
||||
|
||||
// We fetch with the hostname as key to avoid problems with other applications
|
||||
$value = $this->memcached->get(self::getApp()->get_hostname() . ':' . $key);
|
||||
|
||||
if ($this->memcached->getResultCode() === \Memcached::RES_SUCCESS) {
|
||||
$return = $value;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function set($key, $value, $duration = Cache::MONTH)
|
||||
{
|
||||
// We store with the hostname as key to avoid problems with other applications
|
||||
return $this->memcached->set(
|
||||
self::getApp()->get_hostname() . ":" . $key,
|
||||
$value,
|
||||
time() + $duration
|
||||
);
|
||||
}
|
||||
|
||||
public function delete($key)
|
||||
{
|
||||
return $this->memcached->delete($key);
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -8,26 +8,33 @@
|
|||
*/
|
||||
namespace Friendica\Core;
|
||||
|
||||
use Friendica\Database\DBM;
|
||||
use dba;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Core\Config;
|
||||
|
||||
require_once 'include/dba.php';
|
||||
|
||||
/**
|
||||
* @brief Arbitrary sytem configuration storage
|
||||
* @brief Arbitrary system configuration storage
|
||||
*
|
||||
* Note:
|
||||
* If we ever would decide to return exactly the variable type as entered,
|
||||
* we will have fun with the additional features. :-)
|
||||
*
|
||||
* The config class always returns strings but in the default features
|
||||
* we use a "false" to determine if the config value isn't set.
|
||||
*
|
||||
*/
|
||||
class Config
|
||||
class Config extends BaseObject
|
||||
{
|
||||
private static $cache;
|
||||
private static $in_db;
|
||||
/**
|
||||
* @var Friendica\Core\Config\IConfigAdapter
|
||||
*/
|
||||
private static $adapter = null;
|
||||
|
||||
public static function init()
|
||||
{
|
||||
if (self::getApp()->getConfigValue('system', 'config_adapter') == 'preload') {
|
||||
self::$adapter = new Config\PreloadConfigAdapter();
|
||||
} else {
|
||||
self::$adapter = new Config\JITConfigAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Loads all configuration values of family into a cached storage.
|
||||
|
@ -41,26 +48,11 @@ class Config
|
|||
*/
|
||||
public static function load($family = "config")
|
||||
{
|
||||
// We don't preload "system" anymore.
|
||||
// This reduces the number of database reads a lot.
|
||||
if ($family === 'system') {
|
||||
return;
|
||||
if (empty(self::$adapter)) {
|
||||
self::init();
|
||||
}
|
||||
|
||||
$a = get_app();
|
||||
|
||||
$r = dba::select('config', ['v', 'k'], ['cat' => $family]);
|
||||
while ($rr = dba::fetch($r)) {
|
||||
$k = $rr['k'];
|
||||
if ($family === 'config') {
|
||||
$a->config[$k] = $rr['v'];
|
||||
} else {
|
||||
$a->config[$family][$k] = $rr['v'];
|
||||
self::$cache[$family][$k] = $rr['v'];
|
||||
self::$in_db[$family][$k] = true;
|
||||
}
|
||||
}
|
||||
dba::close($r);
|
||||
self::$adapter->load($family);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,40 +76,11 @@ class Config
|
|||
*/
|
||||
public static function get($family, $key, $default_value = null, $refresh = false)
|
||||
{
|
||||
$a = get_app();
|
||||
|
||||
if (!$refresh) {
|
||||
// Do we have the cached value? Then return it
|
||||
if (isset(self::$cache[$family][$key])) {
|
||||
if (self::$cache[$family][$key] === '!<unset>!') {
|
||||
return $default_value;
|
||||
} else {
|
||||
return self::$cache[$family][$key];
|
||||
}
|
||||
}
|
||||
if (empty(self::$adapter)) {
|
||||
self::init();
|
||||
}
|
||||
|
||||
$config = dba::selectFirst('config', ['v'], ['cat' => $family, 'k' => $key]);
|
||||
if (DBM::is_result($config)) {
|
||||
// manage array value
|
||||
$val = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']);
|
||||
|
||||
// Assign the value from the database to the cache
|
||||
self::$cache[$family][$key] = $val;
|
||||
self::$in_db[$family][$key] = true;
|
||||
return $val;
|
||||
} elseif (isset($a->config[$family][$key])) {
|
||||
// Assign the value (mostly) from the .htconfig.php to the cache
|
||||
self::$cache[$family][$key] = $a->config[$family][$key];
|
||||
self::$in_db[$family][$key] = false;
|
||||
|
||||
return $a->config[$family][$key];
|
||||
}
|
||||
|
||||
self::$cache[$family][$key] = '!<unset>!';
|
||||
self::$in_db[$family][$key] = false;
|
||||
|
||||
return $default_value;
|
||||
return self::$adapter->get($family, $key, $default_value, $refresh);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,38 +99,11 @@ class Config
|
|||
*/
|
||||
public static function set($family, $key, $value)
|
||||
{
|
||||
$a = get_app();
|
||||
|
||||
// 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.
|
||||
$dbvalue = (!is_array($value) ? (string)$value : $value);
|
||||
|
||||
$stored = self::get($family, $key, null, true);
|
||||
|
||||
if (($stored === $dbvalue) && self::$in_db[$family][$key]) {
|
||||
return true;
|
||||
if (empty(self::$adapter)) {
|
||||
self::init();
|
||||
}
|
||||
|
||||
if ($family === 'config') {
|
||||
$a->config[$key] = $dbvalue;
|
||||
} elseif ($family != 'system') {
|
||||
$a->config[$family][$key] = $dbvalue;
|
||||
}
|
||||
|
||||
// Assign the just added value to the cache
|
||||
self::$cache[$family][$key] = $dbvalue;
|
||||
|
||||
// manage array value
|
||||
$dbvalue = (is_array($value) ? serialize($value) : $dbvalue);
|
||||
|
||||
$ret = dba::update('config', ['v' => $dbvalue], ['cat' => $family, 'k' => $key], true);
|
||||
|
||||
if ($ret) {
|
||||
self::$in_db[$family][$key] = true;
|
||||
return $value;
|
||||
}
|
||||
return $ret;
|
||||
return self::$adapter->set($family, $key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,13 +119,10 @@ class Config
|
|||
*/
|
||||
public static function delete($family, $key)
|
||||
{
|
||||
if (isset(self::$cache[$family][$key])) {
|
||||
unset(self::$cache[$family][$key]);
|
||||
unset(self::$in_db[$family][$key]);
|
||||
if (empty(self::$adapter)) {
|
||||
self::init();
|
||||
}
|
||||
|
||||
$ret = dba::delete('config', ['cat' => $family, 'k' => $key]);
|
||||
|
||||
return $ret;
|
||||
return self::$adapter->delete($family, $key);
|
||||
}
|
||||
}
|
||||
|
|
72
src/Core/Config/IConfigAdapter.php
Normal file
72
src/Core/Config/IConfigAdapter.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Config;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.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 mixed Stored $value or false if the database update failed
|
||||
*/
|
||||
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);
|
||||
}
|
77
src/Core/Config/IPConfigAdapter.php
Normal file
77
src/Core/Config/IPConfigAdapter.php
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?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 mixed Stored $value or false
|
||||
*/
|
||||
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);
|
||||
}
|
126
src/Core/Config/JITConfigAdapter.php
Normal file
126
src/Core/Config/JITConfigAdapter.php
Normal file
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
namespace Friendica\Core\Config;
|
||||
|
||||
use dba;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Database\DBM;
|
||||
|
||||
require_once 'include/dba.php';
|
||||
|
||||
/**
|
||||
* JustInTime Configuration Adapter
|
||||
*
|
||||
* Default Config Adapter. Provides the best performance for pages loading few configuration variables.
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class JITConfigAdapter extends BaseObject implements IConfigAdapter
|
||||
{
|
||||
private $cache;
|
||||
private $in_db;
|
||||
|
||||
public function load($cat = "config")
|
||||
{
|
||||
// We don't preload "system" anymore.
|
||||
// This reduces the number of database reads a lot.
|
||||
if ($cat === 'system') {
|
||||
return;
|
||||
}
|
||||
|
||||
$configs = dba::select('config', ['v', 'k'], ['cat' => $cat]);
|
||||
while ($config = dba::fetch($configs)) {
|
||||
$k = $config['k'];
|
||||
|
||||
self::getApp()->setConfigValue($cat, $k, $config['v']);
|
||||
|
||||
if ($cat !== 'config') {
|
||||
$this->cache[$cat][$k] = $config['v'];
|
||||
$this->in_db[$cat][$k] = true;
|
||||
}
|
||||
}
|
||||
dba::close($configs);
|
||||
}
|
||||
|
||||
public function get($cat, $k, $default_value = null, $refresh = false)
|
||||
{
|
||||
$a = self::getApp();
|
||||
|
||||
if (!$refresh) {
|
||||
// Do we have the cached value? Then return it
|
||||
if (isset($this->cache[$cat][$k])) {
|
||||
if ($this->cache[$cat][$k] === '!<unset>!') {
|
||||
return $default_value;
|
||||
} else {
|
||||
return $this->cache[$cat][$k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$config = dba::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $k]);
|
||||
if (DBM::is_result($config)) {
|
||||
// manage array value
|
||||
$value = (preg_match("|^a:[0-9]+:{.*}$|s", $config['v']) ? unserialize($config['v']) : $config['v']);
|
||||
|
||||
// Assign the value from the database to the cache
|
||||
$this->cache[$cat][$k] = $value;
|
||||
$this->in_db[$cat][$k] = true;
|
||||
return $value;
|
||||
} elseif (isset($a->config[$cat][$k])) {
|
||||
// Assign the value (mostly) from the .htconfig.php to the cache
|
||||
$this->cache[$cat][$k] = $a->config[$cat][$k];
|
||||
$this->in_db[$cat][$k] = false;
|
||||
|
||||
return $a->config[$cat][$k];
|
||||
}
|
||||
|
||||
$this->cache[$cat][$k] = '!<unset>!';
|
||||
$this->in_db[$cat][$k] = false;
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
|
||||
public function set($cat, $k, $value)
|
||||
{
|
||||
$a = self::getApp();
|
||||
|
||||
// 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.
|
||||
$dbvalue = (!is_array($value) ? (string)$value : $value);
|
||||
|
||||
$stored = $this->get($cat, $k, null, true);
|
||||
|
||||
if (($stored === $dbvalue) && $this->in_db[$cat][$k]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
self::getApp()->setConfigValue($cat, $k, $value);
|
||||
|
||||
// Assign the just added value to the cache
|
||||
$this->cache[$cat][$k] = $dbvalue;
|
||||
|
||||
// manage array value
|
||||
$dbvalue = (is_array($value) ? serialize($value) : $dbvalue);
|
||||
|
||||
$result = dba::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $k], true);
|
||||
|
||||
if ($result) {
|
||||
$this->in_db[$cat][$k] = true;
|
||||
return $value;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function delete($cat, $k)
|
||||
{
|
||||
if (isset($this->cache[$cat][$k])) {
|
||||
unset($this->cache[$cat][$k]);
|
||||
unset($this->in_db[$cat][$k]);
|
||||
}
|
||||
|
||||
$result = dba::delete('config', ['cat' => $cat, 'k' => $k]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
119
src/Core/Config/JITPConfigAdapter.php
Normal file
119
src/Core/Config/JITPConfigAdapter.php
Normal file
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
namespace Friendica\Core\Config;
|
||||
|
||||
use dba;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Database\DBM;
|
||||
|
||||
require_once 'include/dba.php';
|
||||
|
||||
/**
|
||||
* JustInTime User Configuration Adapter
|
||||
*
|
||||
* Default PConfig Adapter. Provides the best performance for pages loading few configuration variables.
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class JITPConfigAdapter extends BaseObject implements IPConfigAdapter
|
||||
{
|
||||
private $in_db;
|
||||
|
||||
public function load($uid, $cat)
|
||||
{
|
||||
$a = self::getApp();
|
||||
|
||||
$pconfigs = dba::select('pconfig', ['v', 'k'], ['cat' => $cat, 'uid' => $uid]);
|
||||
if (DBM::is_result($pconfigs)) {
|
||||
while ($pconfig = dba::fetch($pconfigs)) {
|
||||
$k = $pconfig['k'];
|
||||
|
||||
self::getApp()->setPConfigValue($uid, $cat, $k, $pconfig['v']);
|
||||
|
||||
$this->in_db[$uid][$cat][$k] = true;
|
||||
}
|
||||
} else if ($cat != 'config') {
|
||||
// Negative caching
|
||||
$a->config[$uid][$cat] = "!<unset>!";
|
||||
}
|
||||
dba::close($pconfigs);
|
||||
}
|
||||
|
||||
public function get($uid, $cat, $k, $default_value = null, $refresh = false)
|
||||
{
|
||||
$a = self::getApp();
|
||||
|
||||
if (!$refresh) {
|
||||
// Looking if the whole family isn't set
|
||||
if (isset($a->config[$uid][$cat])) {
|
||||
if ($a->config[$uid][$cat] === '!<unset>!') {
|
||||
return $default_value;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($a->config[$uid][$cat][$k])) {
|
||||
if ($a->config[$uid][$cat][$k] === '!<unset>!') {
|
||||
return $default_value;
|
||||
}
|
||||
return $a->config[$uid][$cat][$k];
|
||||
}
|
||||
}
|
||||
|
||||
$pconfig = dba::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]);
|
||||
if (DBM::is_result($pconfig)) {
|
||||
$val = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']);
|
||||
|
||||
self::getApp()->setPConfigValue($uid, $cat, $k, $val);
|
||||
|
||||
$this->in_db[$uid][$cat][$k] = true;
|
||||
|
||||
return $val;
|
||||
} else {
|
||||
self::getApp()->setPConfigValue($uid, $cat, $k, '!<unset>!');
|
||||
|
||||
$this->in_db[$uid][$cat][$k] = false;
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
}
|
||||
|
||||
public function set($uid, $cat, $k, $value)
|
||||
{
|
||||
// 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.
|
||||
$dbvalue = (!is_array($value) ? (string)$value : $value);
|
||||
|
||||
$stored = $this->get($uid, $cat, $k, null, true);
|
||||
|
||||
if (($stored === $dbvalue) && $this->in_db[$uid][$cat][$k]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
self::getApp()->setPConfigValue($uid, $cat, $k, $value);
|
||||
|
||||
// manage array value
|
||||
$dbvalue = (is_array($value) ? serialize($value) : $dbvalue);
|
||||
|
||||
$result = dba::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $k], true);
|
||||
|
||||
if ($result) {
|
||||
$this->in_db[$uid][$cat][$k] = true;
|
||||
return $value;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function delete($uid, $cat, $k)
|
||||
{
|
||||
self::getApp()->deletePConfigValue($uid, $cat, $k);
|
||||
|
||||
if (!empty($this->in_db[$uid][$cat][$k])) {
|
||||
unset($this->in_db[$uid][$cat][$k]);
|
||||
}
|
||||
|
||||
$result = dba::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
90
src/Core/Config/PreloadConfigAdapter.php
Normal file
90
src/Core/Config/PreloadConfigAdapter.php
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Config;
|
||||
|
||||
use dba;
|
||||
use Exception;
|
||||
use Friendica\App;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Database\DBM;
|
||||
|
||||
require_once 'include/dba.php';
|
||||
|
||||
/**
|
||||
* Preload Configuration Adapter
|
||||
*
|
||||
* Minimizes the number of database queries to retrieve configuration values at the cost of memory.
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class PreloadConfigAdapter extends BaseObject implements IConfigAdapter
|
||||
{
|
||||
private $config_loaded = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->load();
|
||||
}
|
||||
|
||||
public function load($family = 'config')
|
||||
{
|
||||
if ($this->config_loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
$configs = dba::select('config', ['cat', 'v', 'k']);
|
||||
while ($config = dba::fetch($configs)) {
|
||||
self::getApp()->setConfigValue($config['cat'], $config['k'], $config['v']);
|
||||
}
|
||||
dba::close($configs);
|
||||
|
||||
$this->config_loaded = true;
|
||||
}
|
||||
|
||||
public function get($cat, $k, $default_value = null, $refresh = false)
|
||||
{
|
||||
if ($refresh) {
|
||||
$config = dba::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $k]);
|
||||
if (DBM::is_result($config)) {
|
||||
self::getApp()->setConfigValue($cat, $k, $config['v']);
|
||||
}
|
||||
}
|
||||
|
||||
$return = self::getApp()->getConfigValue($cat, $k, $default_value);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function set($cat, $k, $value)
|
||||
{
|
||||
// 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;
|
||||
|
||||
if (self::getApp()->getConfigValue($cat, $k) === $compare_value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
self::getApp()->setConfigValue($cat, $k, $value);
|
||||
|
||||
// manage array value
|
||||
$dbvalue = is_array($value) ? serialize($value) : $value;
|
||||
|
||||
$result = dba::update('config', ['v' => $dbvalue], ['cat' => $cat, 'k' => $k], true);
|
||||
if (!$result) {
|
||||
throw new Exception('Unable to store config value in [' . $cat . '][' . $k . ']');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete($cat, $k)
|
||||
{
|
||||
self::getApp()->deleteConfigValue($cat, $k);
|
||||
|
||||
$result = dba::delete('config', ['cat' => $cat, 'k' => $k]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
92
src/Core/Config/PreloadPConfigAdapter.php
Normal file
92
src/Core/Config/PreloadPConfigAdapter.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Config;
|
||||
|
||||
use dba;
|
||||
use Exception;
|
||||
use Friendica\App;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Database\DBM;
|
||||
|
||||
require_once 'include/dba.php';
|
||||
|
||||
/**
|
||||
* Preload User Configuration Adapter
|
||||
*
|
||||
* Minimizes the number of database queries to retrieve configuration values at the cost of memory.
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class PreloadPConfigAdapter extends BaseObject implements IPConfigAdapter
|
||||
{
|
||||
private $config_loaded = false;
|
||||
|
||||
public function __construct($uid)
|
||||
{
|
||||
$this->load($uid, 'config');
|
||||
}
|
||||
|
||||
public function load($uid, $family)
|
||||
{
|
||||
if ($this->config_loaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pconfigs = dba::select('pconfig', ['cat', 'v', 'k'], ['uid' => $uid]);
|
||||
while ($pconfig = dba::fetch($pconfigs)) {
|
||||
self::getApp()->setPConfigValue($uid, $pconfig['cat'], $pconfig['k'], $pconfig['v']);
|
||||
}
|
||||
dba::close($pconfigs);
|
||||
|
||||
$this->config_loaded = true;
|
||||
}
|
||||
|
||||
public function get($uid, $cat, $k, $default_value = null, $refresh = false)
|
||||
{
|
||||
if ($refresh) {
|
||||
$config = dba::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $cat, 'k' => $k]);
|
||||
if (DBM::is_result($config)) {
|
||||
self::getApp()->setPConfigValue($uid, $cat, $k, $config['v']);
|
||||
} else {
|
||||
self::getApp()->deletePConfigValue($uid, $cat, $k);
|
||||
}
|
||||
}
|
||||
|
||||
$return = self::getApp()->getPConfigValue($uid, $cat, $k, $default_value);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
public function set($uid, $cat, $k, $value)
|
||||
{
|
||||
// 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;
|
||||
|
||||
if (self::getApp()->getPConfigValue($uid, $cat, $k) === $compare_value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
self::getApp()->setPConfigValue($uid, $cat, $k, $value);
|
||||
|
||||
// manage array value
|
||||
$dbvalue = is_array($value) ? serialize($value) : $value;
|
||||
|
||||
$result = dba::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $cat, 'k' => $k], true);
|
||||
if (!$result) {
|
||||
throw new Exception('Unable to store config value in [' . $uid . '][' . $cat . '][' . $k . ']');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function delete($uid, $cat, $k)
|
||||
{
|
||||
self::getApp()->deletePConfigValue($uid, $cat, $k);
|
||||
|
||||
$result = dba::delete('pconfig', ['uid' => $uid, 'cat' => $cat, 'k' => $k]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
123
src/Core/Console.php
Normal file
123
src/Core/Console.php
Normal file
|
@ -0,0 +1,123 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core;
|
||||
|
||||
/**
|
||||
* Description of Console
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class Console extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
// Disables the default help handling
|
||||
protected $helpOptions = [];
|
||||
protected $customHelpOptions = ['h', 'help', '?'];
|
||||
|
||||
protected $subConsoles = [
|
||||
'config' => __NAMESPACE__ . '\Console\Config',
|
||||
'createdoxygen' => __NAMESPACE__ . '\Console\CreateDoxygen',
|
||||
'docbloxerrorchecker' => __NAMESPACE__ . '\Console\DocBloxErrorChecker',
|
||||
'dbstructure' => __NAMESPACE__ . '\Console\DatabaseStructure',
|
||||
'extract' => __NAMESPACE__ . '\Console\Extract',
|
||||
'globalcommunityblock' => __NAMESPACE__ . '\Console\GlobalCommunityBlock',
|
||||
'globalcommunitysilence' => __NAMESPACE__ . '\Console\GlobalCommunitySilence',
|
||||
'maintenance' => __NAMESPACE__ . '\Console\Maintenance',
|
||||
'php2po' => __NAMESPACE__ . '\Console\PhpToPo',
|
||||
'po2php' => __NAMESPACE__ . '\Console\PoToPhp',
|
||||
'typo' => __NAMESPACE__ . '\Console\Typo',
|
||||
];
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
Usage: bin/console [--version] [-h|--help|-?] <command> [<args>] [-v]
|
||||
|
||||
Commands:
|
||||
config Edit site config
|
||||
createdoxygen Generate Doxygen headers
|
||||
dbstructure Do database updates
|
||||
docbloxerrorchecker Check the file tree for DocBlox errors
|
||||
extract Generate translation string file for the Friendica project (deprecated)
|
||||
globalcommunityblock Block remote profile from interacting with this node
|
||||
globalcommunitysilence Silence remote profile from global community page
|
||||
help Show help about a command, e.g (bin/console help config)
|
||||
maintenance Set maintenance mode for this node
|
||||
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
|
||||
|
||||
Options:
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Executable: ' . $this->executable);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
$showHelp = false;
|
||||
$subHelp = false;
|
||||
$command = null;
|
||||
|
||||
if ($this->getOption('version')) {
|
||||
$this->out('Friendica Console version ' . FRIENDICA_VERSION);
|
||||
|
||||
return 0;
|
||||
} elseif ((count($this->options) === 0 || $this->getOption($this->customHelpOptions) === true || $this->getOption($this->customHelpOptions) === 1) && count($this->args) === 0
|
||||
) {
|
||||
$showHelp = true;
|
||||
} elseif (count($this->args) >= 2 && $this->getArgument(0) == 'help') {
|
||||
$command = $this->getArgument(1);
|
||||
$subHelp = true;
|
||||
array_shift($this->args);
|
||||
array_shift($this->args);
|
||||
} elseif (count($this->args) >= 1) {
|
||||
$command = $this->getArgument(0);
|
||||
array_shift($this->args);
|
||||
}
|
||||
|
||||
if (is_null($command)) {
|
||||
$this->out($this->getHelp());
|
||||
return 0;
|
||||
}
|
||||
|
||||
$console = $this->getSubConsole($command);
|
||||
|
||||
if ($subHelp) {
|
||||
$console->setOption($this->customHelpOptions, true);
|
||||
}
|
||||
|
||||
return $console->execute();
|
||||
}
|
||||
|
||||
private function getSubConsole($command)
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Command: ' . $command);
|
||||
}
|
||||
|
||||
if (!isset($this->subConsoles[$command])) {
|
||||
throw new \Asika\SimpleConsole\CommandArgsException('Command ' . $command . ' doesn\'t exist');
|
||||
}
|
||||
|
||||
$subargs = $this->args;
|
||||
array_unshift($subargs, $this->executable);
|
||||
|
||||
$className = $this->subConsoles[$command];
|
||||
|
||||
$subconsole = new $className($subargs);
|
||||
|
||||
foreach ($this->options as $name => $value) {
|
||||
$subconsole->setOption($name, $value);
|
||||
}
|
||||
|
||||
return $subconsole;
|
||||
}
|
||||
|
||||
}
|
135
src/Core/Console/Config.php
Normal file
135
src/Core/Console/Config.php
Normal file
|
@ -0,0 +1,135 @@
|
|||
<?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\Console;
|
||||
|
||||
use Asika\SimpleConsole\CommandArgsException;
|
||||
use dba;
|
||||
use Friendica\Core;
|
||||
|
||||
require_once 'include/dba.php';
|
||||
require_once 'include/text.php';
|
||||
|
||||
/**
|
||||
* @brief tool to access the system config from the CLI
|
||||
*
|
||||
* With this script you can access the system configuration of your node from
|
||||
* the CLI. You can do both, reading current values stored in the database and
|
||||
* set new values to config variables.
|
||||
*
|
||||
* Usage:
|
||||
* If you specify no parameters at the CLI, the script will list all config
|
||||
* variables defined.
|
||||
*
|
||||
* If you specify one parameter, the script will list all config variables
|
||||
* defined in this section of the configuration (e.g. "system").
|
||||
*
|
||||
* If you specify two parameters, the script will show you the current value
|
||||
* of the named configuration setting. (e.g. "system loglevel")
|
||||
*
|
||||
* If you specify three parameters, the named configuration setting will be
|
||||
* set to the value of the last parameter. (e.g. "system loglevel 0" will
|
||||
* disable logging)
|
||||
*
|
||||
* @author Tobias Diekershoff
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class Config extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
console config - Manage site configuration
|
||||
Synopsis
|
||||
bin/console config [-h|--help|-?] [-v]
|
||||
bin/console config <category> [-h|--help|-?] [-v]
|
||||
bin/console config <category> <key> [-h|--help|-?] [-v]
|
||||
bin/console config <category> <key> <value> [-h|--help|-?] [-v]
|
||||
|
||||
Description
|
||||
bin/console config
|
||||
Lists all config values
|
||||
|
||||
bin/console config <category>
|
||||
Lists all config values in the provided category
|
||||
|
||||
bin/console config <category> <key>
|
||||
Shows the value of the provided key in the category
|
||||
|
||||
bin/console config <category> <key> <value>
|
||||
Sets the value of the provided key in the category
|
||||
|
||||
Notes:
|
||||
Setting config entries which are manually set in .htconfig.php may result in
|
||||
conflict between database settings and the manual startup settings.
|
||||
|
||||
Options
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Executable: ' . $this->executable);
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (count($this->args) > 3) {
|
||||
throw new CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
require_once '.htconfig.php';
|
||||
$result = dba::connect($db_host, $db_user, $db_pass, $db_data);
|
||||
unset($db_host, $db_user, $db_pass, $db_data);
|
||||
|
||||
if (!$result) {
|
||||
throw new \RuntimeException('Unable to connect to database');
|
||||
}
|
||||
|
||||
if (count($this->args) == 3) {
|
||||
Core\Config::set($this->getArgument(0), $this->getArgument(1), $this->getArgument(2));
|
||||
$this->out("config[{$this->getArgument(0)}][{$this->getArgument(1)}] = " . Core\Config::get($this->getArgument(0),
|
||||
$this->getArgument(1)));
|
||||
}
|
||||
|
||||
if (count($this->args) == 2) {
|
||||
$this->out("config[{$this->getArgument(0)}][{$this->getArgument(1)}] = " . Core\Config::get($this->getArgument(0),
|
||||
$this->getArgument(1)));
|
||||
}
|
||||
|
||||
if (count($this->args) == 1) {
|
||||
Core\Config::load($this->getArgument(0));
|
||||
|
||||
$a = get_app();
|
||||
if (!is_null($a->config[$this->getArgument(0)])) {
|
||||
foreach ($a->config[$this->getArgument(0)] as $k => $x) {
|
||||
$this->out("config[{$this->getArgument(0)}][{$k}] = " . $x);
|
||||
}
|
||||
} else {
|
||||
$this->out('Config section ' . $this->getArgument(0) . ' returned nothing');
|
||||
}
|
||||
}
|
||||
|
||||
if (count($this->args) == 0) {
|
||||
$configs = dba::select('config');
|
||||
foreach ($configs as $config) {
|
||||
$this->out("config[{$config['cat']}][{$config['k']}] = " . $config['v']);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
148
src/Core/Console/CreateDoxygen.php
Normal file
148
src/Core/Console/CreateDoxygen.php
Normal file
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Console;
|
||||
|
||||
/**
|
||||
* Description of CreateDoxygen
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class CreateDoxygen extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
console createdoxygen - Generate Doxygen headers
|
||||
Usage
|
||||
bin/console createdoxygen <file> [-h|--help|-?] [-v]
|
||||
|
||||
Description
|
||||
Outputs the provided file with added Doxygen headers to functions
|
||||
|
||||
Options
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (count($this->args) == 0) {
|
||||
$this->out($this->getHelp());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (count($this->args) > 1) {
|
||||
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
$file = $this->getArgument(0);
|
||||
if (!file_exists($file)) {
|
||||
throw new \RuntimeException('Unable to find specified file.');
|
||||
}
|
||||
|
||||
$data = file_get_contents($file);
|
||||
|
||||
$lines = explode("\n", $data);
|
||||
|
||||
$previous = "";
|
||||
|
||||
foreach ($lines AS $line) {
|
||||
$line = rtrim(trim($line, "\r"));
|
||||
|
||||
if (strstr(strtolower($line), "function")) {
|
||||
$detect = strtolower(trim($line));
|
||||
$detect = implode(" ", explode(" ", $detect));
|
||||
|
||||
$found = false;
|
||||
|
||||
if (substr($detect, 0, 9) == "function ") {
|
||||
$found = true;
|
||||
}
|
||||
|
||||
if (substr($detect, 0, 19) == "protected function ") {
|
||||
$found = true;
|
||||
}
|
||||
|
||||
if (substr($detect, 0, 17) == "private function ") {
|
||||
$found = true;
|
||||
}
|
||||
|
||||
if (substr($detect, 0, 23) == "public static function ") {
|
||||
$found = true;
|
||||
}
|
||||
|
||||
if (substr($detect, 0, 24) == "private static function ") {
|
||||
$found = true;
|
||||
}
|
||||
|
||||
if (substr($detect, 0, 10) == "function (") {
|
||||
$found = false;
|
||||
}
|
||||
|
||||
if ($found && ( trim($previous) == "*/")) {
|
||||
$found = false;
|
||||
}
|
||||
|
||||
if ($found) {
|
||||
$this->out($this->addDocumentation($line));
|
||||
}
|
||||
}
|
||||
$this->out($line);
|
||||
$previous = $line;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a doxygen header
|
||||
*
|
||||
* @param string $line The current line of the document
|
||||
*
|
||||
* @return string added doxygen header
|
||||
*/
|
||||
private function addDocumentation($line)
|
||||
{
|
||||
$trimmed = ltrim($line);
|
||||
$length = strlen($line) - strlen($trimmed);
|
||||
$space = substr($line, 0, $length);
|
||||
|
||||
$block = $space . "/**\n" .
|
||||
$space . " * @brief \n" .
|
||||
$space . " *\n"; /**/
|
||||
|
||||
|
||||
$left = strpos($line, "(");
|
||||
$line = substr($line, $left + 1);
|
||||
|
||||
$right = strpos($line, ")");
|
||||
$line = trim(substr($line, 0, $right));
|
||||
|
||||
if ($line != "") {
|
||||
$parameters = explode(",", $line);
|
||||
foreach ($parameters AS $parameter) {
|
||||
$parameter = trim($parameter);
|
||||
$splitted = explode("=", $parameter);
|
||||
|
||||
$block .= $space . " * @param " . trim($splitted[0], "& ") . "\n";
|
||||
}
|
||||
if (count($parameters) > 0) $block .= $space . " *\n";
|
||||
}
|
||||
|
||||
$block .= $space . " * @return \n" .
|
||||
$space . " */\n";
|
||||
|
||||
return $block;
|
||||
}
|
||||
|
||||
}
|
110
src/Core/Console/DatabaseStructure.php
Normal file
110
src/Core/Console/DatabaseStructure.php
Normal file
|
@ -0,0 +1,110 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Console;
|
||||
|
||||
use Friendica\Core;
|
||||
use Friendica\Database\DBStructure;
|
||||
|
||||
require_once 'boot.php';
|
||||
require_once 'include/dba.php';
|
||||
|
||||
/**
|
||||
* @brief Does database updates from the command line
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class DatabaseStructure extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
console dbstructure - Does database updates
|
||||
Usage
|
||||
bin/console dbstructure <command> [-h|--help|-?] [-v]
|
||||
|
||||
Commands
|
||||
dryrun Show database update schema queries without running them
|
||||
update Update database schema
|
||||
dumpsql Dump database schema
|
||||
toinnodb Convert all tables from MyISAM to InnoDB
|
||||
|
||||
Options
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (count($this->args) == 0) {
|
||||
$this->out($this->getHelp());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (count($this->args) > 1) {
|
||||
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
require_once '.htconfig.php';
|
||||
$result = \dba::connect($db_host, $db_user, $db_pass, $db_data);
|
||||
unset($db_host, $db_user, $db_pass, $db_data);
|
||||
|
||||
if (!$result) {
|
||||
throw new \RuntimeException('Unable to connect to database');
|
||||
}
|
||||
|
||||
Core\Config::load();
|
||||
|
||||
switch ($this->getArgument(0)) {
|
||||
case "dryrun":
|
||||
$output = DBStructure::update(true, false);
|
||||
break;
|
||||
case "update":
|
||||
$output = DBStructure::update(true, true);
|
||||
|
||||
$build = Core\Config::get('system', 'build');
|
||||
if (empty($build)) {
|
||||
Core\Config::set('system', 'build', DB_UPDATE_VERSION);
|
||||
$build = DB_UPDATE_VERSION;
|
||||
}
|
||||
|
||||
$stored = intval($build);
|
||||
$current = intval(DB_UPDATE_VERSION);
|
||||
|
||||
// run any left update_nnnn functions in update.php
|
||||
for ($x = $stored; $x < $current; $x ++) {
|
||||
$r = run_update_function($x);
|
||||
if (!$r) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Core\Config::set('system', 'build', DB_UPDATE_VERSION);
|
||||
break;
|
||||
case "dumpsql":
|
||||
ob_start();
|
||||
DBStructure::printStructure();
|
||||
$output = ob_get_clean();
|
||||
break;
|
||||
case "toinnodb":
|
||||
ob_start();
|
||||
DBStructure::convertToInnoDB();
|
||||
$output = ob_get_clean();
|
||||
break;
|
||||
}
|
||||
|
||||
$this->out($output);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
192
src/Core/Console/DocBloxErrorChecker.php
Normal file
192
src/Core/Console/DocBloxErrorChecker.php
Normal file
|
@ -0,0 +1,192 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Console;
|
||||
|
||||
/**
|
||||
* When I installed docblox, I had the experience that it does not generate any output at all.
|
||||
* This script may be used to find that kind of problems with the documentation build process.
|
||||
* If docblox generates output, use another approach for debugging.
|
||||
*
|
||||
* Basically, docblox takes a list of files to build documentation from. This script assumes there is a file or set of files
|
||||
* breaking the build when it is included in that list. It tries to calculate the smallest list containing these files.
|
||||
* Unfortunatly, the original problem is NP-complete, so what the script does is a best guess only.
|
||||
*
|
||||
* So it starts with a list of all files in the project.
|
||||
* If that list can't be build, it cuts it in two parts and tries both parts independently. If only one of them breaks,
|
||||
* it takes that one and tries the same independently. If both break, it assumes this is the smallest set. This assumption
|
||||
* is not necessarily true. Maybe the smallest set consists of two files and both of them were in different parts when
|
||||
* the list was divided, but by now it is my best guess. To make this assumption better, the list is shuffled after every step.
|
||||
*
|
||||
* After that, the script tries to remove a file from the list. It tests if the list breaks and if so, it
|
||||
* assumes that the file it removed belongs to the set of erroneous files.
|
||||
* This is done for all files, so, in the end removing one file leads to a working doc build.
|
||||
*
|
||||
* @author Alexander Kampmann
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class DocBloxErrorChecker extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
console docbloxerrorchecker - Checks the file tree for docblox errors
|
||||
Usage
|
||||
bin/console docbloxerrorchecker [-h|--help|-?] [-v]
|
||||
|
||||
Options
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (count($this->args) > 0) {
|
||||
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
if (!$this->commandExists('docblox')) {
|
||||
throw new \RuntimeException('DocBlox isn\'t available.');
|
||||
}
|
||||
|
||||
//return from util folder to frindica base dir
|
||||
$dir = get_app()->get_basepath();
|
||||
|
||||
//stack for dirs to search
|
||||
$dirstack = [];
|
||||
//list of source files
|
||||
$filelist = [];
|
||||
|
||||
//loop over all files in $dir
|
||||
while ($dh = opendir($dir)) {
|
||||
while ($file = readdir($dh)) {
|
||||
if (is_dir($dir . "/" . $file)) {
|
||||
//add to directory stack
|
||||
if (strpos($file, '.') !== 0) {
|
||||
array_push($dirstack, $dir . "/" . $file);
|
||||
$this->out('dir ' . $dir . '/' . $file);
|
||||
}
|
||||
} else {
|
||||
//test if it is a source file and add to filelist
|
||||
if (substr($file, strlen($file) - 4) == ".php") {
|
||||
array_push($filelist, $dir . "/" . $file);
|
||||
$this->out($dir . '/' . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
//look at the next dir
|
||||
$dir = array_pop($dirstack);
|
||||
}
|
||||
|
||||
//check the entire set
|
||||
if ($this->runs($filelist)) {
|
||||
throw new \RuntimeException("I can not detect a problem.");
|
||||
}
|
||||
|
||||
//check half of the set and discard if that half is okay
|
||||
$res = $filelist;
|
||||
$i = count($res);
|
||||
do {
|
||||
$this->out($i . '/' . count($filelist) . ' elements remaining.');
|
||||
$res = $this->reduce($res, count($res) / 2);
|
||||
shuffle($res);
|
||||
$i = count($res);
|
||||
} while (count($res) < $i);
|
||||
|
||||
//check one file after another
|
||||
$needed = [];
|
||||
|
||||
while (count($res) != 0) {
|
||||
$file = array_pop($res);
|
||||
|
||||
if ($this->runs(array_merge($res, $needed))) {
|
||||
$this->out('needs: ' . $file . ' and file count ' . count($needed));
|
||||
array_push($needed, $file);
|
||||
}
|
||||
}
|
||||
|
||||
$this->out('Smallest Set is: ' . $this->namesList($needed) . ' with ' . count($needed) . ' files. ');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function commandExists($command)
|
||||
{
|
||||
$prefix = strpos(strtolower(PHP_OS),'win') > -1 ? 'where' : 'which';
|
||||
exec("{$prefix} {$command}", $output, $returnVal);
|
||||
return $returnVal === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function generates a comma separated list of file names.
|
||||
*
|
||||
* @package util
|
||||
*
|
||||
* @param array $fileset Set of file names
|
||||
*
|
||||
* @return string comma-separated list of the file names
|
||||
*/
|
||||
private function namesList($fileset)
|
||||
{
|
||||
return implode(',', $fileset);
|
||||
}
|
||||
|
||||
/**
|
||||
* This functions runs phpdoc on the provided list of files
|
||||
* @package util
|
||||
*
|
||||
* @param array $fileset Set of filenames
|
||||
*
|
||||
* @return bool true, if that set can be built
|
||||
*/
|
||||
private function runs($fileset)
|
||||
{
|
||||
$fsParam = $this->namesList($fileset);
|
||||
$this->exec('docblox -t phpdoc_out -f ' . $fsParam);
|
||||
if (file_exists("phpdoc_out/index.html")) {
|
||||
$this->out('Subset ' . $fsParam . ' is okay.');
|
||||
$this->exec('rm -r phpdoc_out');
|
||||
return true;
|
||||
} else {
|
||||
$this->out('Subset ' . $fsParam . ' failed.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This functions cuts down a fileset by removing files until it finally works.
|
||||
* it was meant to be recursive, but php's maximum stack size is to small. So it just simulates recursion.
|
||||
*
|
||||
* In that version, it does not necessarily generate the smallest set, because it may not alter the elements order enough.
|
||||
*
|
||||
* @package util
|
||||
*
|
||||
* @param array $fileset set of filenames
|
||||
* @param int $ps number of files in subsets
|
||||
*
|
||||
* @return array a part of $fileset, that crashes
|
||||
*/
|
||||
private function reduce($fileset, $ps)
|
||||
{
|
||||
//split array...
|
||||
$parts = array_chunk($fileset, $ps);
|
||||
//filter working subsets...
|
||||
$parts = array_filter($parts, [$this, 'runs']);
|
||||
//melt remaining parts together
|
||||
if (is_array($parts)) {
|
||||
return array_reduce($parts, "array_merge", []);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
140
src/Core/Console/Extract.php
Normal file
140
src/Core/Console/Extract.php
Normal file
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Console;
|
||||
|
||||
/**
|
||||
* Extracts translation strings from the Friendica project's files to be exported
|
||||
* to Transifex for translation.
|
||||
*
|
||||
* Outputs a PHP file with language strings used by Friendica
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class Extract extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
console extract - Generate translation string file for the Friendica project (deprecated)
|
||||
Usage
|
||||
bin/console extract [-h|--help|-?] [-v]
|
||||
|
||||
Description
|
||||
This script was used to generate the translation string file to be exported to Transifex,
|
||||
please use bin/run_xgettext.sh instead
|
||||
|
||||
Options
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (count($this->args) > 0) {
|
||||
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
$s = '<?php' . PHP_EOL;
|
||||
$s .= '
|
||||
function string_plural_select($n){
|
||||
return ($n != 1);
|
||||
}
|
||||
|
||||
';
|
||||
|
||||
$arr = [];
|
||||
|
||||
$files = array_merge(
|
||||
['index.php', 'boot.php'],
|
||||
glob('mod/*'),
|
||||
glob('include/*'),
|
||||
glob('addon/*/*'),
|
||||
$this->globRecursive('src')
|
||||
);
|
||||
|
||||
foreach ($files as $file) {
|
||||
$str = file_get_contents($file);
|
||||
|
||||
$pat = '|L10n::t\(([^\)]*+)[\)]|';
|
||||
$patt = '|L10n::tt\(([^\)]*+)[\)]|';
|
||||
|
||||
$matches = [];
|
||||
$matchestt = [];
|
||||
|
||||
preg_match_all($pat, $str, $matches);
|
||||
preg_match_all($patt, $str, $matchestt);
|
||||
|
||||
if (count($matches) || count($matchestt)) {
|
||||
$s .= '// ' . $file . PHP_EOL;
|
||||
}
|
||||
|
||||
if (!empty($matches[1])) {
|
||||
foreach ($matches[1] as $long_match) {
|
||||
$match_arr = preg_split('/(?<=[\'"])\s*,/', $long_match);
|
||||
$match = $match_arr[0];
|
||||
if (!in_array($match, $arr)) {
|
||||
if (substr($match, 0, 1) == '$') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$arr[] = $match;
|
||||
|
||||
$s .= '$a->strings[' . $match . '] = ' . $match . ';' . "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($matchestt[1])) {
|
||||
foreach ($matchestt[1] as $match) {
|
||||
$matchtkns = preg_split("|[ \t\r\n]*,[ \t\r\n]*|", $match);
|
||||
if (count($matchtkns) == 3 && !in_array($matchtkns[0], $arr)) {
|
||||
if (substr($matchtkns[1], 0, 1) == '$') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$arr[] = $matchtkns[0];
|
||||
|
||||
$s .= '$a->strings[' . $matchtkns[0] . "] = array(\n";
|
||||
$s .= "\t0 => " . $matchtkns[0] . ",\n";
|
||||
$s .= "\t1 => " . $matchtkns[1] . ",\n";
|
||||
$s .= ");\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$s .= '// Timezones' . PHP_EOL;
|
||||
|
||||
$zones = timezone_identifiers_list();
|
||||
foreach ($zones as $zone) {
|
||||
$s .= '$a->strings[\'' . $zone . '\'] = \'' . $zone . '\';' . "\n";
|
||||
}
|
||||
|
||||
$this->out($s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function globRecursive($path) {
|
||||
$dir_iterator = new \RecursiveDirectoryIterator($path);
|
||||
$iterator = new \RecursiveIteratorIterator($dir_iterator, \RecursiveIteratorIterator::SELF_FIRST);
|
||||
|
||||
$return = [];
|
||||
foreach ($iterator as $file) {
|
||||
if ($file->getBasename() != '.' && $file->getBasename() != '..') {
|
||||
$return[] = $file->getPathname();
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
77
src/Core/Console/GlobalCommunityBlock.php
Normal file
77
src/Core/Console/GlobalCommunityBlock.php
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Console;
|
||||
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Model\Contact;
|
||||
|
||||
/**
|
||||
* @brief tool to block an account from the node
|
||||
*
|
||||
* With this tool, you can block an account in such a way, that no postings
|
||||
* or comments this account writes are accepted to the node.
|
||||
*
|
||||
* License: AGPLv3 or later, same as Friendica
|
||||
*
|
||||
* @author Tobias Diekershoff <mrpetovan@gmail.com>
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class GlobalCommunityBlock extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
console globalcommunityblock - Block remote profile from interacting with this node
|
||||
Usage
|
||||
bin/console globalcommunityblock <profile_url> [-h|--help|-?] [-v]
|
||||
|
||||
Description
|
||||
Blocks an account in such a way that no postings or comments this account writes are accepted to this node.
|
||||
|
||||
Options
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (count($this->args) == 0) {
|
||||
$this->out($this->getHelp());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (count($this->args) > 1) {
|
||||
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
require_once '.htconfig.php';
|
||||
$result = \dba::connect($db_host, $db_user, $db_pass, $db_data);
|
||||
unset($db_host, $db_user, $db_pass, $db_data);
|
||||
|
||||
if (!$result) {
|
||||
throw new \RuntimeException('Unable to connect to database');
|
||||
}
|
||||
|
||||
$contact_id = Contact::getIdForURL($this->getArgument(0));
|
||||
if (!$contact_id) {
|
||||
throw new \RuntimeException(L10n::t('Could not find any contact entry for this URL (%s)', $nurl));
|
||||
}
|
||||
if(Contact::block($contact_id)) {
|
||||
$this->out(L10n::t('The contact has been blocked from the node'));
|
||||
} else {
|
||||
throw new \RuntimeException('The contact block failed.');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
94
src/Core/Console/GlobalCommunitySilence.php
Normal file
94
src/Core/Console/GlobalCommunitySilence.php
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Console;
|
||||
|
||||
use Friendica\Core\Protocol;
|
||||
use Friendica\Database\DBM;
|
||||
use Friendica\Network\Probe;
|
||||
|
||||
require_once 'include/text.php';
|
||||
|
||||
/**
|
||||
* @brief tool to silence accounts on the global community page
|
||||
*
|
||||
* With this tool, you can silence an account on the global community page.
|
||||
* Postings from silenced accounts will not be displayed on the community
|
||||
* page. This silencing does only affect the display on the community page,
|
||||
* accounts following the silenced accounts will still get their postings.
|
||||
*
|
||||
* License: AGPLv3 or later, same as Friendica
|
||||
*
|
||||
* @author Tobias Diekershoff
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class GlobalCommunitySilence extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
console globalcommunitysilence - Silence remote profile from global community page
|
||||
Usage
|
||||
bin/console globalcommunitysilence <profile_url> [-h|--help|-?] [-v]
|
||||
|
||||
Description
|
||||
With this tool, you can silence an account on the global community page.
|
||||
Postings from silenced accounts will not be displayed on the community page.
|
||||
This silencing does only affect the display on the community page, accounts
|
||||
following the silenced accounts will still get their postings.
|
||||
|
||||
Options
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (count($this->args) == 0) {
|
||||
$this->out($this->getHelp());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (count($this->args) > 1) {
|
||||
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
require_once '.htconfig.php';
|
||||
$result = \dba::connect($db_host, $db_user, $db_pass, $db_data);
|
||||
unset($db_host, $db_user, $db_pass, $db_data);
|
||||
|
||||
if (!$result) {
|
||||
throw new \RuntimeException('Unable to connect to database');
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. make nurl from last parameter
|
||||
* 2. check DB (contact) if there is a contact with uid=0 and that nurl, get the ID
|
||||
* 3. set the flag hidden=1 for the contact entry with the found ID
|
||||
* */
|
||||
$net = Probe::uri($this->getArgument(0));
|
||||
if (in_array($net['network'], [Protocol::PHANTOM, Protocol::MAIL])) {
|
||||
throw new \RuntimeException('This account seems not to exist.');
|
||||
}
|
||||
|
||||
$nurl = normalise_link($net['url']);
|
||||
$contact = \dba::selectFirst("contact", ["id"], ["nurl" => $nurl, "uid" => 0]);
|
||||
if (DBM::is_result($contact)) {
|
||||
\dba::update("contact", ["hidden" => true], ["id" => $contact["id"]]);
|
||||
$this->out('NOTICE: The account should be silenced from the global community page');
|
||||
} else {
|
||||
throw new \RuntimeException('NOTICE: Could not find any entry for this URL (' . $nurl . ')');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
105
src/Core/Console/Maintenance.php
Normal file
105
src/Core/Console/Maintenance.php
Normal file
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Console;
|
||||
|
||||
use Friendica\Core;
|
||||
|
||||
require_once 'boot.php';
|
||||
require_once 'include/dba.php';
|
||||
|
||||
/**
|
||||
* @brief Sets maintenance mode for this node
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class Maintenance extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
console maintenance - Sets maintenance mode for this node
|
||||
Usage
|
||||
bin/console maintenance <enable> [<reason>] [-h|--help|-?] [-v]
|
||||
|
||||
Description
|
||||
<enable> cen be either 0 or 1 to disabled or enable the maintenance mode on this node.
|
||||
|
||||
<reason> is a quote-enclosed string with the optional reason for the maintenance mode.
|
||||
|
||||
Examples
|
||||
bin/console maintenance 1
|
||||
Enables the maintenance mode without setting a reason message
|
||||
|
||||
bin/console maintenance 1 "SSL certification update"
|
||||
Enables the maintenance mode with setting a reason message
|
||||
|
||||
bin/console maintenance 0
|
||||
Disables the maintenance mode
|
||||
|
||||
Options
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (count($this->args) == 0) {
|
||||
$this->out($this->getHelp());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (count($this->args) > 2) {
|
||||
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
require_once '.htconfig.php';
|
||||
$result = \dba::connect($db_host, $db_user, $db_pass, $db_data);
|
||||
unset($db_host, $db_user, $db_pass, $db_data);
|
||||
|
||||
if (!$result) {
|
||||
throw new \RuntimeException('Unable to connect to database');
|
||||
}
|
||||
|
||||
Core\Config::load();
|
||||
|
||||
$lang = Core\L10n::getBrowserLanguage();
|
||||
Core\L10n::loadTranslationTable($lang);
|
||||
|
||||
$enabled = intval($this->getArgument(0));
|
||||
|
||||
Core\Config::set('system', 'maintenance', $enabled);
|
||||
|
||||
$reason = $this->getArgument(1);
|
||||
|
||||
if ($enabled && $this->getArgument(1)) {
|
||||
Core\Config::set('system', 'maintenance_reason', $this->getArgument(1));
|
||||
} else {
|
||||
Core\Config::set('system', 'maintenance_reason', '');
|
||||
}
|
||||
|
||||
if ($enabled) {
|
||||
$mode_str = "maintenance mode";
|
||||
} else {
|
||||
$mode_str = "normal mode";
|
||||
}
|
||||
|
||||
$this->out('System set in ' . $mode_str);
|
||||
|
||||
if ($enabled && $reason != '') {
|
||||
$this->out('Maintenance reason: ' . $reason);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
234
src/Core/Console/PhpToPo.php
Normal file
234
src/Core/Console/PhpToPo.php
Normal file
|
@ -0,0 +1,234 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Console;
|
||||
|
||||
/**
|
||||
* Read a strings.php file and create messages.po in the same directory
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class PhpToPo extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
private $normBaseMsgIds = [];
|
||||
const NORM_REGEXP = "|[\\\]|";
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
console php2po - Generate a messages.po file from a strings.php file
|
||||
Usage
|
||||
bin/console php2po [-p <n>] [--base <file>] <path/to/strings.php> [-h|--help|-?] [-v]
|
||||
|
||||
Description
|
||||
Read a strings.php file and create the according messages.po in the same directory
|
||||
|
||||
Options
|
||||
-p <n> Number of plural forms. Default: 2
|
||||
--base <file> Path to base messages.po file. Default: util/messages.po
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (count($this->args) == 0) {
|
||||
$this->out($this->getHelp());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (count($this->args) > 1) {
|
||||
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
$a = get_app();
|
||||
|
||||
$phpfile = realpath($this->getArgument(0));
|
||||
|
||||
if (!file_exists($phpfile)) {
|
||||
throw new \RuntimeException('Supplied file path doesn\'t exist.');
|
||||
}
|
||||
|
||||
if (!is_writable(dirname($phpfile))) {
|
||||
throw new \RuntimeException('Supplied directory isn\'t writable.');
|
||||
}
|
||||
|
||||
$pofile = dirname($phpfile) . DIRECTORY_SEPARATOR . 'messages.po';
|
||||
|
||||
// start !
|
||||
include_once($phpfile);
|
||||
|
||||
$out = '';
|
||||
$out .= "# FRIENDICA Distributed Social Network\n";
|
||||
$out .= "# Copyright (C) 2010, 2011, 2012, 2013 the Friendica Project\n";
|
||||
$out .= "# This file is distributed under the same license as the Friendica package.\n";
|
||||
$out .= "# \n";
|
||||
$out .= 'msgid ""' . "\n";
|
||||
$out .= 'msgstr ""' . "\n";
|
||||
$out .= '"Project-Id-Version: friendica\n"' . "\n";
|
||||
$out .= '"Report-Msgid-Bugs-To: \n"' . "\n";
|
||||
$out .= '"POT-Creation-Date: ' . date("Y-m-d H:i:sO") . '\n"' . "\n";
|
||||
$out .= '"MIME-Version: 1.0\n"' . "\n";
|
||||
$out .= '"Content-Type: text/plain; charset=UTF-8\n"' . "\n";
|
||||
$out .= '"Content-Transfer-Encoding: 8bit\n"' . "\n";
|
||||
|
||||
// search for plural info
|
||||
$lang = "";
|
||||
$lang_logic = "";
|
||||
$lang_pnum = $this->getOption('p', 2);
|
||||
|
||||
$infile = file($phpfile);
|
||||
foreach ($infile as $l) {
|
||||
$l = trim($l);
|
||||
if ($this->startsWith($l, 'function string_plural_select_')) {
|
||||
$lang = str_replace('function string_plural_select_', '', str_replace('($n){', '', $l));
|
||||
}
|
||||
if ($this->startsWith($l, 'return')) {
|
||||
$lang_logic = str_replace('$', '', trim(str_replace('return ', '', $l), ';'));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->out('Language: ' . $lang);
|
||||
$this->out('Plural forms: ' . $lang_pnum);
|
||||
$this->out('Plural forms: ' . $lang_logic);
|
||||
|
||||
$out .= sprintf('"Language: %s\n"', $lang) . "\n";
|
||||
$out .= sprintf('"Plural-Forms: nplurals=%s; plural=%s;\n"', $lang_pnum, $lang_logic) . "\n";
|
||||
$out .= "\n";
|
||||
|
||||
$base_path = $this->getOption('base', 'util' . DIRECTORY_SEPARATOR . 'messages.po');
|
||||
|
||||
// load base messages.po and extract msgids
|
||||
$base_msgids = [];
|
||||
$base_f = file($base_path);
|
||||
if (!$base_f) {
|
||||
throw new \RuntimeException('The base ' . $base_path . ' file is missing or unavailable to read.');
|
||||
}
|
||||
|
||||
$this->out('Loading base file ' . $base_path . '...');
|
||||
|
||||
$_f = 0;
|
||||
$_mid = "";
|
||||
$_mids = [];
|
||||
foreach ($base_f as $l) {
|
||||
$l = trim($l);
|
||||
|
||||
if ($this->startsWith($l, 'msgstr')) {
|
||||
if ($_mid != '""') {
|
||||
$base_msgids[$_mid] = $_mids;
|
||||
$this->normBaseMsgIds[preg_replace(self::NORM_REGEXP, "", $_mid)] = $_mid;
|
||||
}
|
||||
|
||||
$_f = 0;
|
||||
$_mid = "";
|
||||
$_mids = [];
|
||||
}
|
||||
|
||||
if ($this->startsWith($l, '"') && $_f == 2) {
|
||||
$_mids[count($_mids) - 1] .= "\n" . $l;
|
||||
}
|
||||
if ($this->startsWith($l, 'msgid_plural ')) {
|
||||
$_f = 2;
|
||||
$_mids[] = str_replace('msgid_plural ', '', $l);
|
||||
}
|
||||
|
||||
if ($this->startsWith($l, '"') && $_f == 1) {
|
||||
$_mid .= "\n" . $l;
|
||||
$_mids[count($_mids) - 1] .= "\n" . $l;
|
||||
}
|
||||
if ($this->startsWith($l, 'msgid ')) {
|
||||
$_f = 1;
|
||||
$_mid = str_replace('msgid ', '', $l);
|
||||
$_mids = [$_mid];
|
||||
}
|
||||
}
|
||||
|
||||
$this->out('Creating ' . $pofile . '...');
|
||||
|
||||
// create msgid and msgstr
|
||||
$warnings = "";
|
||||
foreach ($a->strings as $key => $str) {
|
||||
$msgid = $this->massageString($key);
|
||||
|
||||
if (preg_match("|%[sd0-9](\$[sn])*|", $msgid)) {
|
||||
$out .= "#, php-format\n";
|
||||
}
|
||||
$msgid = $this->findOriginalMsgId($msgid);
|
||||
$out .= 'msgid ' . $msgid . "\n";
|
||||
|
||||
if (is_array($str)) {
|
||||
if (array_key_exists($msgid, $base_msgids) && isset($base_msgids[$msgid][1])) {
|
||||
$out .= 'msgid_plural ' . $base_msgids[$msgid][1] . "\n";
|
||||
} else {
|
||||
$out .= 'msgid_plural ' . $msgid . "\n";
|
||||
$warnings .= "[W] No source plural form for msgid:\n" . str_replace("\n", "\n\t", $msgid) . "\n\n";
|
||||
}
|
||||
foreach ($str as $n => $msgstr) {
|
||||
$out .= 'msgstr[' . $n . '] ' . $this->massageString($msgstr) . "\n";
|
||||
}
|
||||
} else {
|
||||
$out .= 'msgstr ' . $this->massageString($str) . "\n";
|
||||
}
|
||||
|
||||
$out .= "\n";
|
||||
}
|
||||
|
||||
if (!file_put_contents($pofile, $out)) {
|
||||
throw new \RuntimeException('Unable to write to ' . $pofile);
|
||||
}
|
||||
|
||||
if ($warnings != '') {
|
||||
$this->out($warnings);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function startsWith($haystack, $needle)
|
||||
{
|
||||
// search backwards starting from haystack length characters from the end
|
||||
return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a string and retun a message.po ready text
|
||||
* - replace " with \"
|
||||
* - replace tab char with \t
|
||||
* - manage multiline strings
|
||||
*/
|
||||
private function massageString($str)
|
||||
{
|
||||
$str = str_replace('\\', '\\\\', $str);
|
||||
$str = str_replace('"', '\"', $str);
|
||||
$str = str_replace("\t", '\t', $str);
|
||||
$str = str_replace("\n", '\n"' . "\n" . '"', $str);
|
||||
if (strpos($str, "\n") !== false && $str[0] !== '"') {
|
||||
$str = '"' . "\n" . $str;
|
||||
}
|
||||
|
||||
$str = preg_replace("|\n([^\"])|", "\n\"$1", $str);
|
||||
return sprintf('"%s"', $str);
|
||||
}
|
||||
|
||||
private function findOriginalMsgId($str)
|
||||
{
|
||||
$norm_str = preg_replace(self::NORM_REGEXP, "", $str);
|
||||
if (array_key_exists($norm_str, $this->normBaseMsgIds)) {
|
||||
return $this->normBaseMsgIds[$norm_str];
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
}
|
201
src/Core/Console/PoToPhp.php
Normal file
201
src/Core/Console/PoToPhp.php
Normal file
|
@ -0,0 +1,201 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Console;
|
||||
|
||||
/**
|
||||
* Read a messages.po file and create strings.php in the same directory
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class PoToPhp extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
const DQ_ESCAPE = "__DQ__";
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
console php2po - Generate a strings.php file from a messages.po file
|
||||
Usage
|
||||
bin/console php2po <path/to/messages.po> [-h|--help|-?] [-v]
|
||||
|
||||
Description
|
||||
Read a messages.po file and create the according strings.php in the same directory
|
||||
|
||||
Options
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (count($this->args) == 0) {
|
||||
$this->out($this->getHelp());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (count($this->args) > 1) {
|
||||
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
$a = get_app();
|
||||
|
||||
$pofile = realpath($this->getArgument(0));
|
||||
|
||||
if (!file_exists($pofile)) {
|
||||
throw new \RuntimeException('Supplied file path doesn\'t exist.');
|
||||
}
|
||||
|
||||
if (!is_writable(dirname($pofile))) {
|
||||
throw new \RuntimeException('Supplied directory isn\'t writable.');
|
||||
}
|
||||
|
||||
$outfile = dirname($pofile) . DIRECTORY_SEPARATOR . 'strings.php';
|
||||
|
||||
if (strstr($outfile, 'util')) {
|
||||
$lang = 'en';
|
||||
} else {
|
||||
$lang = str_replace('-', '_', basename(dirname($pofile)));
|
||||
}
|
||||
|
||||
$this->out('Out to ' . $outfile);
|
||||
|
||||
$out = "<?php\n\n";
|
||||
|
||||
$infile = file($pofile);
|
||||
$k = '';
|
||||
$v = '';
|
||||
$arr = false;
|
||||
$ink = false;
|
||||
$inv = false;
|
||||
$escape_s_exp = '|[^\\\\]\$[a-z]|';
|
||||
|
||||
foreach ($infile as $l) {
|
||||
$l = str_replace('\"', self::DQ_ESCAPE, $l);
|
||||
$len = strlen($l);
|
||||
if ($l[0] == "#") {
|
||||
$l = "";
|
||||
}
|
||||
|
||||
if (substr($l, 0, 15) == '"Plural-Forms: ') {
|
||||
$match = [];
|
||||
preg_match("|nplurals=([0-9]*); *plural=(.*)[;\\\\]|", $l, $match);
|
||||
$cond = str_replace('n', '$n', $match[2]);
|
||||
// define plural select function if not already defined
|
||||
$fnname = 'string_plural_select_' . $lang;
|
||||
$out .= 'if(! function_exists("' . $fnname . '")) {' . "\n";
|
||||
$out .= 'function ' . $fnname . '($n){' . "\n";
|
||||
$out .= ' return ' . $cond . ';' . "\n";
|
||||
$out .= '}}' . "\n";
|
||||
}
|
||||
|
||||
if ($k != '' && substr($l, 0, 7) == 'msgstr ') {
|
||||
if ($ink) {
|
||||
$ink = false;
|
||||
$out .= '$a->strings["' . $k . '"] = ';
|
||||
}
|
||||
|
||||
if ($inv) {
|
||||
$inv = false;
|
||||
$out .= '"' . $v . '"';
|
||||
}
|
||||
|
||||
$v = substr($l, 8, $len - 10);
|
||||
$v = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $v);
|
||||
|
||||
$inv = true;
|
||||
}
|
||||
|
||||
if ($k != "" && substr($l, 0, 7) == 'msgstr[') {
|
||||
if ($ink) {
|
||||
$ink = false;
|
||||
$out .= '$a->strings["' . $k . '"] = ';
|
||||
}
|
||||
if ($inv) {
|
||||
$inv = false;
|
||||
$out .= '"' . $v . '"';
|
||||
}
|
||||
|
||||
if (!$arr) {
|
||||
$arr = true;
|
||||
$out .= "[\n";
|
||||
}
|
||||
|
||||
$match = [];
|
||||
preg_match("|\[([0-9]*)\] (.*)|", $l, $match);
|
||||
$out .= "\t"
|
||||
. preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $match[1])
|
||||
. ' => '
|
||||
. preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $match[2])
|
||||
. ",\n";
|
||||
}
|
||||
|
||||
if (substr($l, 0, 6) == 'msgid_') {
|
||||
$ink = false;
|
||||
$out .= '$a->strings["' . $k . '"] = ';
|
||||
}
|
||||
|
||||
if ($ink) {
|
||||
$k .= trim($l, "\"\r\n");
|
||||
$k = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $k);
|
||||
}
|
||||
|
||||
if (substr($l, 0, 6) == 'msgid ') {
|
||||
if ($inv) {
|
||||
$inv = false;
|
||||
$out .= '"' . $v . '"';
|
||||
}
|
||||
|
||||
if ($k != "") {
|
||||
$out .= ($arr) ? "];\n" : ";\n";
|
||||
}
|
||||
|
||||
$arr = false;
|
||||
$k = str_replace("msgid ", "", $l);
|
||||
if ($k != '""') {
|
||||
$k = trim($k, "\"\r\n");
|
||||
} else {
|
||||
$k = '';
|
||||
}
|
||||
|
||||
$k = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $k);
|
||||
$ink = true;
|
||||
}
|
||||
|
||||
if ($inv && substr($l, 0, 6) != "msgstr") {
|
||||
$v .= trim($l, "\"\r\n");
|
||||
$v = preg_replace_callback($escape_s_exp, [$this, 'escapeDollar'], $v);
|
||||
}
|
||||
}
|
||||
|
||||
if ($inv) {
|
||||
$inv = false;
|
||||
$out .= '"' . $v . '"';
|
||||
}
|
||||
|
||||
if ($k != '') {
|
||||
$out .= ($arr ? "];\n" : ";\n");
|
||||
}
|
||||
|
||||
$out = str_replace(self::DQ_ESCAPE, '\"', $out);
|
||||
if (!file_put_contents($outfile, $out)) {
|
||||
throw new \RuntimeException('Unable to write to ' . $outfile);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function escapeDollar($match)
|
||||
{
|
||||
return str_replace('$', '\$', $match[0]);
|
||||
}
|
||||
}
|
119
src/Core/Console/Typo.php
Normal file
119
src/Core/Console/Typo.php
Normal file
|
@ -0,0 +1,119 @@
|
|||
<?php
|
||||
|
||||
namespace Friendica\Core\Console;
|
||||
|
||||
/**
|
||||
* Tired of chasing typos and finding them after a commit.
|
||||
* Run this and quickly see if we've got any parse errors in our application files.
|
||||
*
|
||||
* @author Hypolite Petovan <mrpetovan@gmail.com>
|
||||
*/
|
||||
class Typo extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
protected $helpOptions = ['h', 'help', '?'];
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
$help = <<<HELP
|
||||
console typo - Checks for parse errors in Friendica files
|
||||
Usage
|
||||
bin/console typo [-h|--help|-?] [-v]
|
||||
|
||||
Description
|
||||
Checks all PHP files in the Friendica file tree for parse errors
|
||||
|
||||
Options
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
HELP;
|
||||
return $help;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Class: ' . __CLASS__);
|
||||
$this->out('Arguments: ' . var_export($this->args, true));
|
||||
$this->out('Options: ' . var_export($this->options, true));
|
||||
}
|
||||
|
||||
if (count($this->args) > 0) {
|
||||
throw new \Asika\SimpleConsole\CommandArgsException('Too many arguments');
|
||||
}
|
||||
|
||||
$a = get_app();
|
||||
|
||||
$php_path = $a->getConfigValue('config', 'php_path', 'php');
|
||||
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Directory: src');
|
||||
}
|
||||
|
||||
$Iterator = new \RecursiveDirectoryIterator('src');
|
||||
|
||||
foreach (new \RecursiveIteratorIterator($Iterator) as $file) {
|
||||
if (substr($file, -4) === '.php') {
|
||||
$this->checkFile($php_path, $file);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Directory: mod');
|
||||
}
|
||||
|
||||
$files = glob('mod/*.php');
|
||||
$this->checkFiles($php_path, $files);
|
||||
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Directory: include');
|
||||
}
|
||||
|
||||
$files = glob('include/*.php');
|
||||
$this->checkFiles($php_path, $files);
|
||||
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Directory: addon');
|
||||
}
|
||||
|
||||
$dirs = glob('addon/*');
|
||||
foreach ($dirs as $dir) {
|
||||
$addon = basename($dir);
|
||||
$files = glob($dir . '/' . $addon . '.php');
|
||||
$this->checkFiles($php_path, $files);
|
||||
}
|
||||
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('String files');
|
||||
}
|
||||
|
||||
$this->checkFile($php_path, 'util/strings.php');
|
||||
|
||||
$files = glob('view/lang/*/strings.php');
|
||||
$this->checkFiles($php_path, $files);
|
||||
|
||||
$this->out('No errors.');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function checkFiles($php_path, array $files)
|
||||
{
|
||||
foreach ($files as $file) {
|
||||
$this->checkFile($php_path, $file);
|
||||
}
|
||||
}
|
||||
|
||||
private function checkFile($php_path, $file)
|
||||
{
|
||||
if ($this->getOption('v')) {
|
||||
$this->out('Checking ' . $file);
|
||||
}
|
||||
|
||||
$output = [];
|
||||
$ret = 0;
|
||||
exec("$php_path -l $file", $output, $ret);
|
||||
if ($ret !== 0) {
|
||||
throw new \RuntimeException('Parse error found in ' . $file . ', scan stopped.');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ namespace Friendica\Core;
|
|||
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Content\Text\BBCode;
|
||||
use Friendica\Content\Text\HTML;
|
||||
use Friendica\Core\L10n;
|
||||
use Friendica\Core\PConfig;
|
||||
use Friendica\Core\System;
|
||||
|
@ -19,7 +20,6 @@ use Friendica\Util\Temporal;
|
|||
use Friendica\Util\XML;
|
||||
|
||||
require_once 'include/dba.php';
|
||||
require_once 'include/html2plain.php';
|
||||
|
||||
/**
|
||||
* @brief Methods for read and write notifications from/to database
|
||||
|
@ -47,7 +47,7 @@ class NotificationsManager extends BaseObject
|
|||
$n['timestamp'] = strtotime($local_time);
|
||||
$n['date_rel'] = Temporal::getRelativeDate($n['date']);
|
||||
$n['msg_html'] = BBCode::convert($n['msg'], false);
|
||||
$n['msg_plain'] = explode("\n", trim(html2plain($n['msg_html'], 0)))[0];
|
||||
$n['msg_plain'] = explode("\n", trim(HTML::toPlaintext($n['msg_html'], 0)))[0];
|
||||
|
||||
$rets[] = $n;
|
||||
}
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
* @file src/Core/PConfig.php
|
||||
* User Configuration Class
|
||||
*
|
||||
* @file include/Core/PConfig.php
|
||||
*
|
||||
* @brief Contains the class with methods for user configuration
|
||||
*/
|
||||
namespace Friendica\Core;
|
||||
|
||||
use Friendica\Database\DBM;
|
||||
use dba;
|
||||
use Friendica\BaseObject;
|
||||
use Friendica\Core\Config;
|
||||
|
||||
require_once 'include/dba.php';
|
||||
|
||||
/**
|
||||
* @file include/Core/PConfig.php
|
||||
* @brief contains the class with methods for the management
|
||||
* of the user configuration
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Management of user configuration storage
|
||||
* Note:
|
||||
|
@ -22,9 +20,23 @@ require_once 'include/dba.php';
|
|||
* The PConfig::get() functions return boolean false for keys that are unset,
|
||||
* and this could lead to subtle bugs.
|
||||
*/
|
||||
class PConfig
|
||||
class PConfig extends BaseObject
|
||||
{
|
||||
private static $in_db;
|
||||
/**
|
||||
* @var Friendica\Core\Config\IPConfigAdapter
|
||||
*/
|
||||
private static $adapter = null;
|
||||
|
||||
public static function init($uid)
|
||||
{
|
||||
$a = self::getApp();
|
||||
|
||||
if (isset($a->config['system']['config_adapter']) && $a->config['system']['config_adapter'] == 'preload') {
|
||||
self::$adapter = new Config\PreloadPConfigAdapter($uid);
|
||||
} else {
|
||||
self::$adapter = new Config\JITPConfigAdapter($uid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Loads all configuration values of a user's config family into a cached storage.
|
||||
|
@ -39,20 +51,11 @@ class PConfig
|
|||
*/
|
||||
public static function load($uid, $family)
|
||||
{
|
||||
$a = get_app();
|
||||
if (empty(self::$adapter)) {
|
||||
self::init($uid);
|
||||
}
|
||||
|
||||
$r = dba::select('pconfig', ['v', 'k'], ['cat' => $family, 'uid' => $uid]);
|
||||
if (DBM::is_result($r)) {
|
||||
while ($rr = dba::fetch($r)) {
|
||||
$k = $rr['k'];
|
||||
$a->config[$uid][$family][$k] = $rr['v'];
|
||||
self::$in_db[$uid][$family][$k] = true;
|
||||
}
|
||||
} else if ($family != 'config') {
|
||||
// Negative caching
|
||||
$a->config[$uid][$family] = "!<unset>!";
|
||||
}
|
||||
dba::close($r);
|
||||
self::$adapter->load($uid, $family);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,37 +75,11 @@ class PConfig
|
|||
*/
|
||||
public static function get($uid, $family, $key, $default_value = null, $refresh = false)
|
||||
{
|
||||
$a = get_app();
|
||||
|
||||
if (!$refresh) {
|
||||
// Looking if the whole family isn't set
|
||||
if (isset($a->config[$uid][$family])) {
|
||||
if ($a->config[$uid][$family] === '!<unset>!') {
|
||||
return $default_value;
|
||||
}
|
||||
if (empty(self::$adapter)) {
|
||||
self::init($uid);
|
||||
}
|
||||
|
||||
if (isset($a->config[$uid][$family][$key])) {
|
||||
if ($a->config[$uid][$family][$key] === '!<unset>!') {
|
||||
return $default_value;
|
||||
}
|
||||
return $a->config[$uid][$family][$key];
|
||||
}
|
||||
}
|
||||
|
||||
$pconfig = dba::selectFirst('pconfig', ['v'], ['uid' => $uid, 'cat' => $family, 'k' => $key]);
|
||||
if (DBM::is_result($pconfig)) {
|
||||
$val = (preg_match("|^a:[0-9]+:{.*}$|s", $pconfig['v']) ? unserialize($pconfig['v']) : $pconfig['v']);
|
||||
$a->config[$uid][$family][$key] = $val;
|
||||
self::$in_db[$uid][$family][$key] = true;
|
||||
|
||||
return $val;
|
||||
} else {
|
||||
$a->config[$uid][$family][$key] = '!<unset>!';
|
||||
self::$in_db[$uid][$family][$key] = false;
|
||||
|
||||
return $default_value;
|
||||
}
|
||||
return self::$adapter->get($uid, $family, $key, $default_value, $refresh);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,31 +99,11 @@ class PConfig
|
|||
*/
|
||||
public static function set($uid, $family, $key, $value)
|
||||
{
|
||||
$a = get_app();
|
||||
|
||||
// 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.
|
||||
$dbvalue = (!is_array($value) ? (string)$value : $value);
|
||||
|
||||
$stored = self::get($uid, $family, $key, null, true);
|
||||
|
||||
if (($stored === $dbvalue) && self::$in_db[$uid][$family][$key]) {
|
||||
return true;
|
||||
if (empty(self::$adapter)) {
|
||||
self::init($uid);
|
||||
}
|
||||
|
||||
$a->config[$uid][$family][$key] = $dbvalue;
|
||||
|
||||
// manage array value
|
||||
$dbvalue = (is_array($value) ? serialize($value) : $dbvalue);
|
||||
|
||||
$ret = dba::update('pconfig', ['v' => $dbvalue], ['uid' => $uid, 'cat' => $family, 'k' => $key], true);
|
||||
|
||||
if ($ret) {
|
||||
self::$in_db[$uid][$family][$key] = true;
|
||||
return $value;
|
||||
}
|
||||
return $ret;
|
||||
return self::$adapter->set($uid, $family, $key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,15 +120,10 @@ class PConfig
|
|||
*/
|
||||
public static function delete($uid, $family, $key)
|
||||
{
|
||||
$a = get_app();
|
||||
|
||||
if (x($a->config[$uid][$family], $key)) {
|
||||
unset($a->config[$uid][$family][$key]);
|
||||
unset(self::$in_db[$uid][$family][$key]);
|
||||
if (empty(self::$adapter)) {
|
||||
self::init($uid);
|
||||
}
|
||||
|
||||
$ret = dba::delete('pconfig', ['uid' => $uid, 'cat' => $family, 'k' => $key]);
|
||||
|
||||
return $ret;
|
||||
return self::$adapter->delete($uid, $family, $key);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue